From 4f72bc4be91866c987b56b6ecbeab05f2d2beb34 Mon Sep 17 00:00:00 2001 From: Christoffer Lerno Date: Sun, 23 Feb 2025 13:53:04 +0100 Subject: [PATCH] Fixes to lib7, added parallel test structure. --- {lib2 => lib7}/std/ascii.c3 | 0 {lib2 => lib7}/std/atomic.c3 | 0 {lib2 => lib7}/std/atomic_nolibc.c3 | 0 {lib2 => lib7}/std/bits.c3 | 0 {lib2 => lib7}/std/collections/anylist.c3 | 0 {lib2 => lib7}/std/collections/bitset.c3 | 0 .../std/collections/elastic_array.c3 | 20 +- {lib2 => lib7}/std/collections/enummap.c3 | 0 {lib2 => lib7}/std/collections/enumset.c3 | 0 {lib2 => lib7}/std/collections/hashmap.c3 | 0 {lib2 => lib7}/std/collections/linkedlist.c3 | 0 {lib2 => lib7}/std/collections/list.c3 | 0 {lib2 => lib7}/std/collections/list_common.c3 | 0 {lib2 => lib7}/std/collections/maybe.c3 | 0 {lib2 => lib7}/std/collections/object.c3 | 0 .../std/collections/priorityqueue.c3 | 8 +- {lib2 => lib7}/std/collections/range.c3 | 0 {lib2 => lib7}/std/collections/ringbuffer.c3 | 0 {lib2 => lib7}/std/collections/tuple.c3 | 0 {lib2 => lib7}/std/compression/qoi.c3 | 0 .../std/core/allocators/arena_allocator.c3 | 0 .../std/core/allocators/dynamic_arena.c3 | 0 .../std/core/allocators/heap_allocator.c3 | 0 .../std/core/allocators/libc_allocator.c3 | 0 .../std/core/allocators/on_stack_allocator.c3 | 0 .../std/core/allocators/temp_allocator.c3 | 0 .../std/core/allocators/tracking_allocator.c3 | 0 {lib2 => lib7}/std/core/array.c3 | 0 {lib2 => lib7}/std/core/bitorder.c3 | 0 {lib2 => lib7}/std/core/builtin.c3 | 31 +- {lib2 => lib7}/std/core/builtin_comparison.c3 | 0 {lib2 => lib7}/std/core/cinterop.c3 | 0 {lib2 => lib7}/std/core/conv.c3 | 0 {lib2 => lib7}/std/core/dstring.c3 | 0 {lib2 => lib7}/std/core/env.c3 | 0 {lib2 => lib7}/std/core/mem.c3 | 0 {lib2 => lib7}/std/core/mem_allocator.c3 | 0 {lib2 => lib7}/std/core/os/wasm_memory.c3 | 0 {lib2 => lib7}/std/core/private/cpu_detect.c3 | 0 .../std/core/private/macho_runtime.c3 | 0 {lib2 => lib7}/std/core/private/main_stub.c3 | 0 {lib2 => lib7}/std/core/runtime.c3 | 0 {lib2 => lib7}/std/core/runtime_benchmark.c3 | 0 {lib2 => lib7}/std/core/runtime_test.c3 | 0 {lib2 => lib7}/std/core/sanitizer/asan.c3 | 0 .../std/core/sanitizer/sanitizer.c3 | 0 {lib2 => lib7}/std/core/sanitizer/tsan.c3 | 0 {lib2 => lib7}/std/core/string.c3 | 0 {lib2 => lib7}/std/core/string_iterator.c3 | 0 {lib2 => lib7}/std/core/string_to_real.c3 | 0 {lib2 => lib7}/std/core/test.c3 | 0 {lib2 => lib7}/std/core/types.c3 | 0 {lib2 => lib7}/std/core/values.c3 | 0 {lib2 => lib7}/std/crypto/crypto.c3 | 0 {lib2 => lib7}/std/crypto/dh.c3 | 0 {lib2 => lib7}/std/crypto/rc4.c3 | 0 {lib2 => lib7}/std/encoding/base32.c3 | 0 {lib2 => lib7}/std/encoding/base64.c3 | 0 {lib2 => lib7}/std/encoding/csv.c3 | 0 {lib2 => lib7}/std/encoding/encoding.c3 | 0 {lib2 => lib7}/std/encoding/hex.c3 | 0 {lib2 => lib7}/std/encoding/json.c3 | 0 .../std/experimental/FrameScheduler.c3 | 0 {lib2 => lib7}/std/hash/adler32.c3 | 0 {lib2 => lib7}/std/hash/crc32.c3 | 0 {lib2 => lib7}/std/hash/crc64.c3 | 0 {lib2 => lib7}/std/hash/fnv32a.c3 | 0 {lib2 => lib7}/std/hash/fnv64a.c3 | 0 {lib2 => lib7}/std/hash/hmac.c3 | 0 {lib2 => lib7}/std/hash/md5.c3 | 0 {lib2 => lib7}/std/hash/sha1.c3 | 0 {lib2 => lib7}/std/hash/sha256.c3 | 0 {lib2 => lib7}/std/io/bits.c3 | 0 {lib2 => lib7}/std/io/file.c3 | 0 {lib2 => lib7}/std/io/formatter.c3 | 0 {lib2 => lib7}/std/io/formatter_private.c3 | 0 {lib2 => lib7}/std/io/io.c3 | 0 {lib2 => lib7}/std/io/os/chdir.c3 | 0 {lib2 => lib7}/std/io/os/file_libc.c3 | 0 {lib2 => lib7}/std/io/os/file_nolibc.c3 | 0 {lib2 => lib7}/std/io/os/fileinfo.c3 | 0 {lib2 => lib7}/std/io/os/getcwd.c3 | 0 {lib2 => lib7}/std/io/os/ls.c3 | 2 +- {lib2 => lib7}/std/io/os/mkdir.c3 | 0 {lib2 => lib7}/std/io/os/rmdir.c3 | 0 {lib2 => lib7}/std/io/os/rmtree.c3 | 0 {lib2 => lib7}/std/io/os/temp_directory.c3 | 0 {lib2 => lib7}/std/io/path.c3 | 0 {lib2 => lib7}/std/io/stream.c3 | 0 {lib2 => lib7}/std/io/stream/buffer.c3 | 0 {lib2 => lib7}/std/io/stream/bytebuffer.c3 | 0 {lib2 => lib7}/std/io/stream/bytereader.c3 | 0 {lib2 => lib7}/std/io/stream/bytewriter.c3 | 0 {lib2 => lib7}/std/io/stream/limitreader.c3 | 0 {lib2 => lib7}/std/io/stream/multireader.c3 | 0 {lib2 => lib7}/std/io/stream/multiwriter.c3 | 0 {lib2 => lib7}/std/io/stream/scanner.c3 | 0 {lib2 => lib7}/std/io/stream/teereader.c3 | 0 {lib2 => lib7}/std/libc/libc.c3 | 0 {lib2 => lib7}/std/libc/libc_extra.c3 | 0 {lib2 => lib7}/std/libc/os/darwin.c3 | 0 {lib2 => lib7}/std/libc/os/errno.c3 | 0 {lib2 => lib7}/std/libc/os/freebsd.c3 | 0 {lib2 => lib7}/std/libc/os/linux.c3 | 0 {lib2 => lib7}/std/libc/os/posix.c3 | 0 {lib2 => lib7}/std/libc/os/win32.c3 | 0 {lib2 => lib7}/std/libc/termios.c3 | 0 {lib2 => lib7}/std/math/bigint.c3 | 0 {lib2 => lib7}/std/math/math.c3 | 0 {lib2 => lib7}/std/math/math_builtin.c3 | 0 {lib2 => lib7}/std/math/math_complex.c3 | 0 {lib2 => lib7}/std/math/math_easings.c3 | 0 {lib2 => lib7}/std/math/math_i128.c3 | 0 {lib2 => lib7}/std/math/math_libc.c3 | 0 {lib2 => lib7}/std/math/math_matrix.c3 | 0 {lib2 => lib7}/std/math/math_nolibc/__cos.c3 | 0 .../std/math/math_nolibc/__cosdf.c3 | 0 {lib2 => lib7}/std/math/math_nolibc/__fmod.c3 | 0 {lib2 => lib7}/std/math/math_nolibc/__sin.c3 | 0 .../std/math/math_nolibc/__sindf.c3 | 0 {lib2 => lib7}/std/math/math_nolibc/__tan.c3 | 0 .../std/math/math_nolibc/__tandf.c3 | 0 {lib2 => lib7}/std/math/math_nolibc/acos.c3 | 0 {lib2 => lib7}/std/math/math_nolibc/asin.c3 | 0 {lib2 => lib7}/std/math/math_nolibc/atan.c3 | 0 {lib2 => lib7}/std/math/math_nolibc/atanh.c3 | 0 {lib2 => lib7}/std/math/math_nolibc/ceil.c3 | 0 {lib2 => lib7}/std/math/math_nolibc/cos.c3 | 0 {lib2 => lib7}/std/math/math_nolibc/exp.c3 | 0 {lib2 => lib7}/std/math/math_nolibc/exp2.c3 | 0 {lib2 => lib7}/std/math/math_nolibc/fabs.c3 | 0 {lib2 => lib7}/std/math/math_nolibc/floor.c3 | 0 {lib2 => lib7}/std/math/math_nolibc/frexp.c3 | 0 {lib2 => lib7}/std/math/math_nolibc/ldexp.c3 | 0 {lib2 => lib7}/std/math/math_nolibc/log.c3 | 0 {lib2 => lib7}/std/math/math_nolibc/log1p.c3 | 0 .../std/math/math_nolibc/math_nolibc.c3 | 0 {lib2 => lib7}/std/math/math_nolibc/pow.c3 | 0 {lib2 => lib7}/std/math/math_nolibc/rempi.c3 | 0 {lib2 => lib7}/std/math/math_nolibc/round.c3 | 0 {lib2 => lib7}/std/math/math_nolibc/scalbn.c3 | 0 {lib2 => lib7}/std/math/math_nolibc/sin.c3 | 0 {lib2 => lib7}/std/math/math_nolibc/sincos.c3 | 0 {lib2 => lib7}/std/math/math_nolibc/tan.c3 | 0 {lib2 => lib7}/std/math/math_nolibc/trig.c3 | 0 {lib2 => lib7}/std/math/math_nolibc/trunc.c3 | 0 {lib2 => lib7}/std/math/math_quaternion.c3 | 0 {lib2 => lib7}/std/math/math_random.c3 | 0 {lib2 => lib7}/std/math/math_vector.c3 | 0 {lib2 => lib7}/std/math/random/math.lcg.c3 | 0 {lib2 => lib7}/std/math/random/math.mcg.c3 | 0 {lib2 => lib7}/std/math/random/math.msws.c3 | 0 {lib2 => lib7}/std/math/random/math.pcg.c3 | 0 {lib2 => lib7}/std/math/random/math.seeder.c3 | 0 {lib2 => lib7}/std/math/random/math.sfc.c3 | 0 .../std/math/random/math.simple_random.c3 | 0 {lib2 => lib7}/std/math/uuid.c3 | 0 {lib2 => lib7}/std/net/http.c3 | 0 {lib2 => lib7}/std/net/inetaddr.c3 | 0 {lib2 => lib7}/std/net/net.c3 | 0 {lib2 => lib7}/std/net/os/common.c3 | 0 {lib2 => lib7}/std/net/os/darwin.c3 | 0 {lib2 => lib7}/std/net/os/linux.c3 | 0 {lib2 => lib7}/std/net/os/posix.c3 | 0 {lib2 => lib7}/std/net/os/win32.c3 | 0 {lib2 => lib7}/std/net/socket.c3 | 0 {lib2 => lib7}/std/net/socket_private.c3 | 0 {lib2 => lib7}/std/net/tcp.c3 | 0 {lib2 => lib7}/std/net/udp.c3 | 0 {lib2 => lib7}/std/net/url.c3 | 0 {lib2 => lib7}/std/net/url_encoding.c3 | 0 {lib2 => lib7}/std/os/backtrace.c3 | 4 +- {lib2 => lib7}/std/os/cpu.c3 | 0 {lib2 => lib7}/std/os/env.c3 | 0 {lib2 => lib7}/std/os/linux/heap.c3 | 0 {lib2 => lib7}/std/os/linux/linux.c3 | 26 +- {lib2 => lib7}/std/os/macos/cf_allocator.c3 | 0 {lib2 => lib7}/std/os/macos/cf_array.c3 | 0 {lib2 => lib7}/std/os/macos/cocoa.c3 | 0 .../std/os/macos/core_foundation.c3 | 0 {lib2 => lib7}/std/os/macos/darwin.c3 | 0 {lib2 => lib7}/std/os/macos/heap.c3 | 0 {lib2 => lib7}/std/os/macos/objc.c3 | 0 {lib2 => lib7}/std/os/posix/files.c3 | 0 {lib2 => lib7}/std/os/posix/general.c3 | 0 {lib2 => lib7}/std/os/posix/heap.c3 | 0 {lib2 => lib7}/std/os/posix/process.c3 | 0 {lib2 => lib7}/std/os/posix/threads.c3 | 0 {lib2 => lib7}/std/os/subprocess.c3 | 0 {lib2 => lib7}/std/os/win32/files.c3 | 0 {lib2 => lib7}/std/os/win32/gdi.c3 | 0 {lib2 => lib7}/std/os/win32/general.c3 | 0 {lib2 => lib7}/std/os/win32/heap.c3 | 0 {lib2 => lib7}/std/os/win32/process.c3 | 12 +- {lib2 => lib7}/std/os/win32/types.c3 | 0 {lib2 => lib7}/std/os/win32/wincon.c3 | 0 {lib2 => lib7}/std/os/win32/windef.c3 | 0 {lib2 => lib7}/std/os/win32/winuser.c3 | 0 {lib2 => lib7}/std/os/win32/ws2def.c3 | 0 {lib2 => lib7}/std/os/win32/wsa.c3 | 0 {lib2 => lib7}/std/sort/binarysearch.c3 | 0 {lib2 => lib7}/std/sort/countingsort.c3 | 0 {lib2 => lib7}/std/sort/insertionsort.c3 | 0 {lib2 => lib7}/std/sort/quicksort.c3 | 0 {lib2 => lib7}/std/sort/sort.c3 | 0 {lib2 => lib7}/std/sort/sorted.c3 | 0 {lib2 => lib7}/std/text/i18n.c3 | 0 .../std/threads/buffered_channel.c3 | 0 .../std/threads/event/event_thread.c3 | 0 {lib2 => lib7}/std/threads/fixed_pool.c3 | 0 {lib2 => lib7}/std/threads/os/cpu.c3 | 0 {lib2 => lib7}/std/threads/os/thread_none.c3 | 0 {lib2 => lib7}/std/threads/os/thread_posix.c3 | 0 {lib2 => lib7}/std/threads/os/thread_win32.c3 | 0 {lib2 => lib7}/std/threads/pool.c3 | 0 {lib2 => lib7}/std/threads/thread.c3 | 0 .../std/threads/unbuffered_channel.c3 | 0 {lib2 => lib7}/std/time/clock.c3 | 0 {lib2 => lib7}/std/time/datetime.c3 | 0 {lib2 => lib7}/std/time/format.c3 | 0 {lib2 => lib7}/std/time/os/time_darwin.c3 | 0 {lib2 => lib7}/std/time/os/time_posix.c3 | 0 {lib2 => lib7}/std/time/os/time_win32.c3 | 0 {lib2 => lib7}/std/time/time.c3 | 0 src/build/build_options.c | 2 +- test/src/test_suite_runner.c3 | 39 +- test/test_suite7/abi/aarch64_args.c3t | 29 + test/test_suite7/abi/aarch64_hfa_args.c3t | 32 + .../abi/aarch_ret_small_struct.c3t | 45 + test/test_suite7/abi/avx512fp16-abi.c3t | 166 ++ test/test_suite7/abi/darwin64_avx.c3t | 264 ++ test/test_suite7/abi/darwin64_avx512.c3t | 133 + test/test_suite7/abi/darwin64_sret.c3t | 19 + test/test_suite7/abi/darwin64_sse.c3t | 56 + test/test_suite7/abi/darwin_arg.c3t | 25 + .../abi/darwin_return_boolarray.c3t | 18 + test/test_suite7/abi/darwinx64_1.c3t | 51 + test/test_suite7/abi/darwinx64_2.c3t | 180 ++ test/test_suite7/abi/linking_extern.c3t | 24 + test/test_suite7/abi/literal_load.c3t | 30 + test/test_suite7/abi/literal_load_aarch64.c3t | 34 + test/test_suite7/abi/literal_load_mingw.c3t | 31 + test/test_suite7/abi/macho_section.c3t | 15 + .../abi/macho_section_attributes.c3 | 8 + test/test_suite7/abi/pass_large_aarch.c3t | 32 + test/test_suite7/abi/riscv32-ilp32-abi.c3t | 94 + .../abi/riscv32-ilp32-ilp32f-abi-1.c3t | 91 + .../abi/riscv32-ilp32-ilp32f-abi-2.c3t | 57 + .../abi/riscv32-ilp32-ilp32f-ilp32d-abi-1.c3t | 526 ++++ .../abi/riscv32-ilp32-ilp32f-ilp32d-abi-2.c3t | 518 ++++ .../abi/riscv32-ilp32-ilp32f-ilp32d-abi-3.c3t | 527 ++++ test/test_suite7/abi/riscv32-ilp32d-abi.c3t | 505 ++++ test/test_suite7/abi/riscv32-ilp32f-abi.c3t | 89 + .../abi/riscv32-ilp32f-ilp32d-abi-1.c3t | 200 ++ .../abi/riscv32-ilp32f-ilp32d-abi-2.c3t | 430 ++++ test/test_suite7/abi/riscv64-lp64-abi.c3t | 45 + .../abi/riscv64-lp64-lp64f-abi-1.c3t | 51 + .../abi/riscv64-lp64-lp64f-abi-2.c3t | 52 + .../abi/riscv64-lp64-lp64f-lp64d-abi-1.c3t | 206 ++ .../abi/riscv64-lp64-lp64f-lp64d-abi-2.c3t | 207 ++ .../abi/riscv64-lp64-lp64f-lp64d-abi-3.c3t | 207 ++ test/test_suite7/abi/riscv64-lp64d-abi.c3t | 451 ++++ .../abi/riscv64-lp64f-lp64d-abi-1.c3t | 184 ++ .../abi/riscv64-lp64f-lp64d-abi-2.c3t | 415 +++ test/test_suite7/abi/small_struct_x64.c3t | 66 + test/test_suite7/abi/sysv_abi_avx.c3t | 42 + test/test_suite7/abi/sysv_abi_noavx.c3t | 41 + test/test_suite7/abi/sysv_direct_coerce.c3t | 34 + test/test_suite7/abi/test_sret.c3t | 32 + test/test_suite7/abi/union_x64.c3t | 35 + test/test_suite7/abi/vec2_aarch64.c3t | 95 + test/test_suite7/abi/vec2_wasm.c3t | 85 + test/test_suite7/abi/vec2_x64.c3t | 94 + test/test_suite7/abi/wasm_extern.c3t | 17 + test/test_suite7/abi/x64alignarray.c3t | 26 + test/test_suite7/any/any_in_any.c3t | 37 + .../test_suite7/any/casting_voidptr_to_any.c3 | 26 + test/test_suite7/any/generic_interface.c3 | 12 + test/test_suite7/any/interface_no_fn.c3 | 4 + .../any/interface_no_method_body_1536.c3 | 7 + test/test_suite7/any/interface_ptr.c3 | 8 + test/test_suite7/any/variant_assign.c3t | 406 +++ test/test_suite7/any/variant_switch.c3t | 165 ++ test/test_suite7/any/variant_test.c3t | 355 +++ .../test_suite7/arrays/array_bounds_check.c3t | 47 + test/test_suite7/arrays/array_casts.c3t | 31 + test/test_suite7/arrays/array_comparison.c3t | 248 ++ .../test_suite7/arrays/array_comparison_2.c3t | 86 + test/test_suite7/arrays/array_indexing.c3 | 11 + .../test_suite7/arrays/array_invalid_casts.c3 | 12 + test/test_suite7/arrays/array_literal.c3t | 28 + test/test_suite7/arrays/array_struct.c3t | 13 + .../arrays/complex_array_const.c3t | 22 + .../arrays/complex_inferred_array.c3t | 17 + .../arrays/global_array_non_const.c3 | 17 + test/test_suite7/arrays/global_init.c3t | 61 + .../arrays/global_init_array_out_of_range.c3 | 2 + test/test_suite7/arrays/index_from_back.c3t | 54 + test/test_suite7/arrays/index_into_global.c3t | 32 + test/test_suite7/arrays/inferred_array_err.c3 | 7 + .../test_suite7/arrays/inferred_array_err2.c3 | 5 + .../arrays/inferred_array_optional.c3t | 91 + test/test_suite7/arrays/inferred_subarray.c3 | 5 + test/test_suite7/arrays/negative_array.c3 | 5 + test/test_suite7/arrays/slice.c3 | 7 + test/test_suite7/arrays/slice_array.c3 | 6 + test/test_suite7/asm/asm_bit_rv.c3t | 20 + test/test_suite7/asm/asm_imm_err_rv.c3 | 58 + test/test_suite7/asm/asm_intr_rv.c3t | 21 + test/test_suite7/asm/asm_jump_rv.c3t | 30 + test/test_suite7/asm/asm_load_rv.c3t | 21 + test/test_suite7/asm/asm_load_rv64.c3t | 15 + test/test_suite7/asm/asm_math_rv.c3t | 19 + test/test_suite7/asm/asm_ops_x64_1.c3t | 44 + test/test_suite7/asm/asm_ops_x64_2.c3t | 30 + test/test_suite7/asm/asm_regression.c3t | 50 + test/test_suite7/asm/asm_set_rv.c3t | 18 + test/test_suite7/asm/asm_shift_rv.c3t | 19 + test/test_suite7/asm/asm_store_rv.c3t | 17 + test/test_suite7/asm/naked.c3t | 19 + test/test_suite7/asm/sideeffect.c3t | 21 + test/test_suite7/asm/syscall.c3t | 17 + test/test_suite7/assert/assert_variants.c3t | 62 + test/test_suite7/assert/assert_with_void.c3 | 42 + test/test_suite7/assert/assertf.c3t | 51 + .../global_static_assert_not_constant.c3 | 3 + .../local_static_assert_not_constant.c3 | 20 + test/test_suite7/assert/static_assert.c3 | 8 + test/test_suite7/assert/unreachable.c3t | 31 + .../assert/unreachable_in_macro.c3t | 99 + .../assignment/alignment_index.c3t | 24 + test/test_suite7/assignment/int_assign.c3t | 70 + test/test_suite7/assignment/var_variable.c3 | 39 + test/test_suite7/attributes/attr_link_err.c3 | 22 + .../attributes/attr_not_imported.c3 | 7 + .../attributes/attribute_params.c3 | 7 + test/test_suite7/attributes/attribute_path.c3 | 4 + .../attributes/attribute_visibility.c3t | 12 + .../attributes/attributes_repeat_param.c3t | 26 + .../attributes/call_attribute_error_eos.c3 | 5 + .../attributes/recursive_attributes.c3 | 17 + .../attributes/user_defined_attributes.c3t | 59 + test/test_suite7/attributes/wasm_import.c3t | 8 + test/test_suite7/attributes/wasm_module.c3 | 5 + .../bitstruct/address_of_bitstruct.c3 | 15 + .../bitstruct/anon_bitstruct_name_overlap.c3 | 24 + .../bitstruct/array_with_boolean.c3t | 69 + .../bitstruct/bistruct_cast_wrong_size.c3 | 14 + .../test_suite7/bitstruct/bitfield_access.c3t | 173 ++ .../bitstruct/bitstruct_access_signed.c3t | 88 + .../test_suite7/bitstruct/bitstruct_align.c3t | 40 + .../bitstruct/bitstruct_anon_in_struct_ok.c3t | 119 + .../bitstruct/bitstruct_arrays.c3t | 1069 ++++++++ .../bitstruct/bitstruct_arrays_be.c3t | 138 + test/test_suite7/bitstruct/bitstruct_be.c3t | 348 +++ test/test_suite7/bitstruct/bitstruct_bool.c3t | 67 + .../bitstruct/bitstruct_cast_and_back.c3 | 15 + .../bitstruct/bitstruct_cast_const_init.c3t | 20 + .../bitstruct/bitstruct_direct_in_struct.c3t | 52 + .../bitstruct/bitstruct_general.c3 | 46 + .../bitstruct/bitstruct_in_subarray.c3t | 26 + test/test_suite7/bitstruct/bitstruct_init.c3 | 104 + .../bitstruct/bitstruct_init_bool.c3t | 22 + .../bitstruct/bitstruct_initializer.c3t | 461 ++++ .../bitstruct/bitstruct_intcontainer.c3t | 105 + test/test_suite7/bitstruct/bitstruct_ops.c3t | 276 ++ .../bitstruct/bitstruct_overlap.c3 | 47 + .../test_suite7/bitstruct/bitstruct_simple.c3 | 18 + .../bitstruct/bitstruct_simple_err_decl.c3 | 11 + .../bitstruct/bitstruct_single_error.c3 | 19 + .../bitstruct/bitstruct_to_int.c3t | 108 + .../designated_initializer_with_bitstruct.c3t | 121 + .../bitstruct/embedded_bitstruct.c3t | 70 + .../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_suite7/bitstruct/param_bitstruct.c3t | 24 + .../builtins/builtin_vector_abs.c3t | 18 + .../builtins/builtin_vector_min_max.c3t | 24 + .../builtins/builtin_with_optional.c3 | 8 + test/test_suite7/builtins/exacts.c3t | 24 + test/test_suite7/builtins/mem.c3t | 23 + test/test_suite7/builtins/overflows.c3t | 66 + test/test_suite7/builtins/prefetch.c3t | 19 + .../builtins/reduce_arithmetics.c3t | 43 + test/test_suite7/builtins/reverse_builtin.c3t | 14 + .../builtins/rounding_builtins.c3t | 51 + test/test_suite7/builtins/sat_builtins.c3t | 38 + test/test_suite7/builtins/shufflevector.c3t | 90 + test/test_suite7/builtins/simple_builtins.c3t | 61 + test/test_suite7/builtins/trap.c3t | 12 + .../test_suite7/builtins/unaligned_access.c3t | 82 + .../builtins/unaligned_load_store.c3t | 54 + test/test_suite7/cast/cast_bitstruct_etc.c3t | 34 + test/test_suite7/cast/cast_from_ptr.c3t | 22 + test/test_suite7/cast/cast_narrow_alias.c3t | 26 + test/test_suite7/cast/cast_ok.c3 | 11 + test/test_suite7/cast/cast_parse_fails.c3 | 13 + test/test_suite7/cast/cast_parse_fails2.c3 | 8 + .../test_suite7/cast/cast_ptr_vec_to_bool.c3t | 25 + test/test_suite7/cast/cast_rcast.c3 | 19 + test/test_suite7/cast/cast_slice_implicit.c3 | 7 + .../cast/cast_string_to_infered_array.c3 | 6 + test/test_suite7/cast/cast_struct.c3 | 37 + test/test_suite7/cast/cast_struct_fails.c3 | 35 + test/test_suite7/cast/cast_subarray.c3t | 32 + test/test_suite7/cast/cast_to_failable.c3 | 14 + .../cast/cast_untyped_list_error.c3 | 6 + .../cast/implicit_array_ptr_conv.c3 | 12 + .../cast/implicit_infer_len_cast.c3t | 45 + .../cast/implicit_void_ptr_deep.c3 | 7 + test/test_suite7/cast/inner_type_cast.c3 | 21 + test/test_suite7/cast/top_down_cast_fails.c3 | 29 + test/test_suite7/cast/top_down_casts.c3t | 98 + test/test_suite7/clang/2002-01_02.c3t | 355 +++ test/test_suite7/clang/2002-03.c3t | 96 + test/test_suite7/clang/2002-04.c3t | 168 ++ test/test_suite7/clang/2002-07.c3t | 992 ++++++++ test/test_suite7/comments/simple_comments.c3 | 15 + .../compile_time/add_to_ct_undefined.c3 | 6 + .../compile_time_access_subscript.c3t | 92 + .../compile_time/compile_time_array.c3t | 28 + .../compile_time/compile_time_array_bug.c3t | 24 + .../compile_time/compile_time_array_ref.c3t | 18 + .../compile_time/compile_time_bitops.c3t | 18 + .../compile_time/compile_time_pointers.c3t | 33 + .../compile_time/compile_time_ptr_ref.c3t | 22 + .../compile_time/compile_time_utf32.c3 | 74 + .../compile_time/comptime_array_folding.c3t | 68 + .../compile_time/concat_append.c3t | 61 + .../concat_append_extended_and_edit.c3t | 2215 +++++++++++++++++ test/test_suite7/compile_time/concat_const.c3 | 22 + .../compile_time/concat_slice_array.c3 | 16 + .../compile_time/concat_slice_bytes.c3t | 18 + test/test_suite7/compile_time/concat_test.c3t | 506 ++++ .../compile_time/concat_test_cases.c3 | 25 + .../compile_time/concat_zero_slice.c3t | 6 + test/test_suite7/compile_time/ct_and_or.c3 | 6 + .../test_suite7/compile_time/ct_assert_bug.c3 | 25 + .../compile_time/ct_builtin_time_date.c3t | 318 +++ .../compile_time/ct_cast_example.c3t | 14 + .../compile_time/ct_declaration_in_if.c3t | 40 + test/test_suite7/compile_time/ct_else_else.c3 | 8 + .../compile_time/ct_enum_values.c3t | 30 + test/test_suite7/compile_time/ct_eval.c3t | 22 + test/test_suite7/compile_time/ct_eval_sym.c3 | 5 + .../test_suite7/compile_time/ct_eval_wrong.c3 | 10 + test/test_suite7/compile_time/ct_for.c3t | 32 + .../compile_time/ct_forach_with_defer.c3t | 258 ++ test/test_suite7/compile_time/ct_foreach.c3t | 55 + test/test_suite7/compile_time/ct_func.c3t | 29 + test/test_suite7/compile_time/ct_funcptr.c3t | 42 + test/test_suite7/compile_time/ct_if.c3t | 8 + .../compile_time/ct_if_folding.c3t | 32 + .../compile_time/ct_left_hand_assign.c3t | 23 + test/test_suite7/compile_time/ct_memberof.c3t | 854 +++++++ .../compile_time/ct_ordered_error.c3t | 4 + .../compile_time/ct_string_functions.c3t | 11 + .../compile_time/ct_subscript_inc.c3t | 71 + .../compile_time/ct_subscript_op.c3t | 27 + test/test_suite7/compile_time/ct_switch.c3t | 65 + .../compile_time/ct_switch_errors.c3 | 36 + .../compile_time/ct_switch_more_checks.c3 | 48 + .../compile_time/ct_switch_top_level.c3t | 52 + .../compile_time/ct_switch_type_check.c3t | 46 + .../compile_time/ct_switch_type_errors.c3 | 51 + .../compile_time/ct_through_constant.c3t | 23 + .../compile_time/ct_vaexpr_assign.c3t | 23 + .../compile_time/ct_value_from_access.c3t | 40 + .../compile_time/cttype_reassign.c3t | 15 + .../compile_time/deep_stringify.c3t | 22 + .../macro_compile_time_pseudo_evaluation.c3t | 35 + test/test_suite7/compile_time/mod_ct.c3t | 17 + .../compile_time/mod_in_other_scope.c3 | 23 + .../compile_time/more_untyped_conversions.c3t | 47 + test/test_suite7/compile_time/not_cost.c3 | 10 + .../compile_time/not_yet_initialized.c3 | 17 + test/test_suite7/compile_time/stringify.c3t | 109 + test/test_suite7/compile_time/stringify2.c3t | 20 + .../compile_time/ternary_folding.c3t | 25 + .../compile_time/typed_ct_vars.c3t | 28 + test/test_suite7/compile_time/typefrom.c3t | 15 + .../compile_time/typefrom_errors.c3t | 13 + .../compile_time/typeof_example.c3t | 52 + .../compile_time/typeof_from_literal.c3 | 14 + .../compile_time/untyped_conversions.c3t | 133 + .../compile_time/untyped_with_inferred.c3 | 6 + .../compile_time_introspection/alignof.c3t | 65 + .../compile_time_introspection/defined.c3t | 97 + .../compile_time_introspection/defined2.c3 | 15 + .../compile_time_introspection/defined_2.c3t | 40 + .../defined_builtin.c3t | 18 + .../compile_time_introspection/defined_err.c3 | 25 + .../defined_index.c3t | 29 + .../defined_subscript.c3 | 7 + .../compile_time_introspection/nameof.c3t | 68 + .../compile_time_introspection/nameof_err.c3 | 20 + .../compile_time_introspection/offsetof.c3t | 50 + .../compile_time_introspection/paramsof.c3t | 391 +++ .../compile_time_introspection/parentof.c3t | 50 + .../compile_time_introspection/qnameof.c3t | 60 + .../recursive_tag.c3 | 13 + .../compile_time_introspection/sizeof.c3t | 66 + .../sizeof_errors.c3 | 66 + .../compile_time_introspection/tag.c3t | 34 + .../compile_time_introspection/tag_1343.c3t | 17 + .../concurrency/atomic_load_store.c3t | 46 + .../concurrency/atomic_load_store_debug.c3t | 135 + test/test_suite7/constants/assign_to_const.c3 | 8 + .../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_suite7/constants/byte_literals.c3t | 13 + test/test_suite7/constants/char_literals.c3t | 24 + test/test_suite7/constants/const_var_copy.c3t | 30 + test/test_suite7/constants/constant_struct.c3 | 18 + test/test_suite7/constants/constants.c3t | 40 + .../constants/empty_byte_literal.c3 | 8 + test/test_suite7/constants/float_type.c3t | 11 + test/test_suite7/constants/init_order.c3t | 23 + test/test_suite7/contracts/constant_out.c3 | 36 + .../contracts/ct_eval_of_ensure.c3 | 16 + test/test_suite7/contracts/ensure_unsigned.c3 | 10 + test/test_suite7/contracts/in_array.c3 | 12 + test/test_suite7/contracts/in_out.c3 | 23 + test/test_suite7/contracts/inout_in.c3 | 21 + .../contracts/macro_ensure_static.c3 | 14 + test/test_suite7/contracts/out_subscript.c3 | 12 + test/test_suite7/contracts/pure.c3 | 22 + test/test_suite7/contracts/pure_calls.c3 | 24 + .../contracts/require_contract_loc.c3 | 6 + test/test_suite7/contracts/simple_test.c3t | 90 + test/test_suite7/debug_symbols/constants.c3t | 36 + .../debug_symbols/constants_mingw.c3t | 38 + test/test_suite7/debug_symbols/ct_foreach.c3t | 55 + .../test_suite7/debug_symbols/defer_macro.c3t | 811 ++++++ test/test_suite7/debug_symbols/foreach.c3t | 67 + .../defer/defer_and_expr_block.c3t | 39 + .../defer/defer_catch_direct_error.c3t | 29 + test/test_suite7/defer/defer_catch_err.c3t | 156 ++ test/test_suite7/defer/defer_catch_mix.c3t | 358 +++ test/test_suite7/defer/defer_catch_try.c3t | 148 ++ test/test_suite7/defer/defer_nextcase.c3t | 182 ++ test/test_suite7/defer/defer_single_stmt.c3 | 41 + test/test_suite7/defer/defer_static_var.c3t | 175 ++ test/test_suite7/defer/defer_try_catch.c3t | 10 + test/test_suite7/defer/defer_with_catch.c3t | 88 + test/test_suite7/defer/defer_with_rethrow.c3 | 15 + test/test_suite7/defer/defer_with_return.c3 | 11 + .../defer/defer_with_unwrapped.c3t | 53 + test/test_suite7/define/alias_typename.c3 | 2 + test/test_suite7/define/aliased_consts.c3t | 24 + test/test_suite7/define/common.c3 | 15 + test/test_suite7/define/common2.c3 | 10 + test/test_suite7/define/define_name_errors.c3 | 8 + test/test_suite7/define/forbidden_defines.c3 | 3 + test/test_suite7/define/test_at.c3 | 24 + test/test_suite7/define/test_at_alias.c3 | 16 + test/test_suite7/define/weak_alias_fails.c3 | 32 + test/test_suite7/define/weak_aliases.c3 | 32 + .../distinct/disntinct_add_fail.c3 | 12 + test/test_suite7/distinct/distinct_add.c3 | 7 + .../distinct/distinct_function.c3t | 33 + .../distinct/distinct_function_call.c3 | 16 + .../distinct/distinct_inline_access.c3 | 32 + test/test_suite7/distinct/distinct_invalid.c3 | 12 + test/test_suite7/distinct/distinct_max.c3t | 8 + test/test_suite7/distinct/distinct_shift.c3t | 47 + test/test_suite7/distinct/distinct_slicing.c3 | 10 + test/test_suite7/distinct/distinct_struct.c3 | 28 + .../distinct/distinct_struct_array.c3 | 19 + test/test_suite7/distinct/distinct_sub.c3t | 58 + test/test_suite7/distinct/distinct_union.c3 | 34 + test/test_suite7/distinct/test_errors.c3 | 11 + test/test_suite7/distinct/test_ops_on_int.c3 | 29 + .../distinct/test_ops_on_struct.c3 | 24 + test/test_suite7/dynamic/any_cast.c3 | 22 + .../dynamic/duplicate_definition.c3 | 12 + .../dynamic/dynamic_inherit_deep.c3t | 18 + test/test_suite7/dynamic/dynamic_mismatch.c3 | 25 + test/test_suite7/dynamic/dynamic_tracing.c3t | 66 + test/test_suite7/dynamic/inherit_linux.c3t | 197 ++ test/test_suite7/dynamic/inherit_macos.c3t | 176 ++ test/test_suite7/dynamic/inline_protocol.c3 | 35 + .../test_suite7/dynamic/null_and_protocol.c3t | 35 + .../dynamic/overlapping_function_linux.c3t | 190 ++ .../dynamic/overlapping_function_macos.c3t | 174 ++ test/test_suite7/dynamic/same_method_twice.c3 | 12 + test/test_suite7/embed/embed_basic.c3t | 34 + .../test_suite7/enumerations/compile_time.c3t | 17 + .../test_suite7/enumerations/enum_add_sub.c3t | 48 + .../enumerations/enum_associated_value.c3t | 61 + .../enum_associated_values_other.c3t | 37 + test/test_suite7/enumerations/enum_cast.c3t | 97 + .../enumerations/enum_cast_error.c3 | 24 + .../enumerations/enum_conversions.c3t | 155 ++ .../enumerations/enum_invalid_param.c3 | 14 + .../enumerations/enum_missing_comma.c3 | 5 + .../enumerations/enum_reflect_associated.c3t | 51 + .../enumerations/enum_same_param.c3 | 9 + .../enumerations/enum_signed_cast_swap.c3t | 27 + test/test_suite7/enumerations/enum_values.c3t | 35 + .../enum_with_associated_value_decl.c3 | 7 + .../enumerations/enum_with_const.c3t | 55 + test/test_suite7/enumerations/inc_assign.c3t | 35 + .../enumerations/inc_assign_fail.c3 | 20 + .../enumerations/inline_enum_size.c3 | 19 + .../test_suite7/enumerations/inline_enums.c3t | 38 + .../enumerations/introspection_data_error.c3t | 19 + test/test_suite7/enumerations/missing_type.c3 | 4 + .../enumerations/simple_inference.c3t | 23 + .../enumerations/too_many_associated.c3 | 9 + test/test_suite7/errors/anyfault_void.c3t | 108 + test/test_suite7/errors/bitshift_failable.c3 | 5 + test/test_suite7/errors/else_checks.c3t | 119 + test/test_suite7/errors/else_struct.c3t | 65 + test/test_suite7/errors/else_unreachable.c3t | 39 + .../errors/else_unreachable_in_block.c3 | 9 + test/test_suite7/errors/empty_fault.c3 | 4 + test/test_suite7/errors/error_decl_ok.c3 | 19 + test/test_suite7/errors/error_else.c3t | 22 + test/test_suite7/errors/error_introspect.c3t | 72 + .../test_suite7/errors/error_regression_2.c3t | 835 +++++++ .../errors/error_semantic_fails.c3 | 5 + test/test_suite7/errors/error_throw.c3 | 12 + test/test_suite7/errors/error_union.c3 | 11 + test/test_suite7/errors/failable_catch.c3t | 185 ++ test/test_suite7/errors/fault_conv.c3t | 123 + .../errors/general_error_regression.c3t | 324 +++ .../errors/illegal_use_of_optional.c3 | 14 + test/test_suite7/errors/invalid_cast_ct.c3 | 16 + test/test_suite7/errors/lone_try.c3 | 11 + test/test_suite7/errors/macro_err.c3t | 58 + test/test_suite7/errors/macro_err2.c3t | 60 + test/test_suite7/errors/macro_err3.c3t | 37 + .../test_suite7/errors/macro_recurse_twice.c3 | 13 + test/test_suite7/errors/missing_bang.c3 | 7 + test/test_suite7/errors/mixed_decl.c3 | 10 + .../errors/more_optional_discard.c3 | 15 + .../test_suite7/errors/more_optional_tests.c3 | 13 + test/test_suite7/errors/multiple_catch.c3t | 287 +++ test/test_suite7/errors/no_common.c3 | 13 + .../errors/optional_chained_init.c3t | 440 ++++ test/test_suite7/errors/optional_contracts.c3 | 35 + .../test_suite7/errors/optional_designated.c3 | 10 + .../errors/optional_discarded_func.c3 | 54 + .../errors/optional_discarded_macro.c3 | 54 + test/test_suite7/errors/optional_inits.c3t | 100 + test/test_suite7/errors/optional_sizeof.c3 | 43 + .../errors/optional_taddr_and_access.c3t | 118 + .../errors/optional_untyped_list.c3 | 30 + .../errors/optional_with_optional.c3t | 295 +++ test/test_suite7/errors/or_and_rethrow.c3t | 474 ++++ test/test_suite7/errors/or_err_bool.c3t | 35 + test/test_suite7/errors/or_err_infer.c3t | 96 + test/test_suite7/errors/precedence_err.c3 | 5 + test/test_suite7/errors/printing_errors.c3t | 59 + test/test_suite7/errors/rethrow.c3t | 34 + test/test_suite7/errors/rethrow_macro.c3 | 14 + test/test_suite7/errors/rethrow_mingw.c3t | 40 + test/test_suite7/errors/rethrow_no_err.c3 | 17 + .../errors/simple_static_failable.c3t | 24 + .../errors/switch_default_catch.c3 | 10 + .../test_suite7/errors/ternary_void_fault.c3t | 71 + test/test_suite7/errors/try_assign.c3t | 154 ++ test/test_suite7/errors/try_catch_if.c3t | 101 + .../errors/try_catch_unwrapping_while_if.c3 | 97 + test/test_suite7/errors/try_expr.c3t | 49 + .../errors/try_unwrap_using_assert.c3 | 11 + .../errors/try_with_assign_to_failable.c3 | 6 + .../errors/try_with_chained_unwrap.c3t | 59 + .../errors/try_with_chained_unwrap_errors.c3 | 91 + test/test_suite7/errors/try_with_unwrap.c3t | 86 + .../test_suite7/errors/try_with_unwrapper.c3t | 185 ++ .../errors/try_with_weird_stuff.c3 | 16 + .../errors/type_optional_declaration_order.c3 | 27 + test/test_suite7/examples/gameoflife.c3 | 90 + .../expr_block_labelled_break.c3 | 10 + .../expression_block/expr_block_no_assign.c3 | 7 + .../expression_block_break.c3 | 12 + .../expression_block_no_end_return.c3 | 9 + .../2002-02-13-ConditionalInCall.c3t | 16 + .../test_suite7/expressions/addr_compiles.c3t | 138 + test/test_suite7/expressions/addr_of_fails.c3 | 78 + test/test_suite7/expressions/arithmetics.c3 | 40 + .../expressions/arithmetics_sema_fail.c3 | 91 + test/test_suite7/expressions/assign.c3 | 5 + .../expressions/assign_deref_opt.c3 | 9 + .../expressions/assign_optional.c3t | 69 + .../expressions/assign_to_address.c3 | 7 + test/test_suite7/expressions/assignability.c3 | 39 + .../expressions/assignment_precedence.c3t | 23 + .../expressions/bit_op_on_bool.c3t | 14 + .../expressions/bool_conversions.c3t | 34 + .../test_suite7/expressions/call_arg_types.c3 | 19 + test/test_suite7/expressions/call_inline.c3t | 48 + .../expressions/casts/cast_const.c3 | 6 + .../casts/cast_enum_const_to_distinct.c3 | 9 + .../expressions/casts/cast_enum_to_various.c3 | 37 + .../expressions/casts/cast_expr.c3t | 28 + .../expressions/casts/cast_failable.c3 | 10 + .../expressions/casts/cast_func_to_various.c3 | 45 + .../casts/cast_implicit_inline_distinct.c3 | 9 + .../expressions/casts/cast_to_nonscalar.c3 | 9 + .../expressions/casts/cast_unknown.c3 | 21 + .../expressions/casts/cast_vector_fail.c3 | 17 + .../expressions/casts/enum_plus_minus.c3t | 72 + .../expressions/casts/explicit_cast.c3 | 16 + .../failed_distinct_float_conversions.c3 | 9 + .../expressions/casts/narrowing.c3 | 7 + .../casts/narrowing_through_casts.c3 | 9 + .../casts/struct_cast_and_distinct.c3 | 32 + .../expressions/casts/void_casting.c3t | 62 + .../expressions/chained_conditional.c3t | 70 + .../expressions/chained_ternary.c3t | 220 ++ ...eck_implict_conversion_signed_unsigned.c3t | 23 + .../expressions/deref_access_null.c3t | 37 + .../expressions/deref_const_string.c3t | 29 + test/test_suite7/expressions/elvis.c3t | 81 + test/test_suite7/expressions/enum_ct_sub.c3t | 20 + .../expressions/fail_index_usize.c3 | 5 + test/test_suite7/expressions/fmuladd.c3t | 82 + test/test_suite7/expressions/fmuladd_err.c3t | 71 + test/test_suite7/expressions/folding_ptr.c3t | 32 + test/test_suite7/expressions/incdec.c3t | 45 + .../expressions/incdec_overload.c3t | 179 ++ test/test_suite7/expressions/negate_int.c3 | 41 + .../test_suite7/expressions/negated_macro.c3t | 37 + .../expressions/no_valid_conversion_minus.c3 | 10 + .../expressions/not_in_wrong_position.c3 | 4 + test/test_suite7/expressions/opt_in_conv.c3 | 9 + .../expressions/optional_and_error.c3 | 13 + .../expressions/optional_ternary.c3t | 415 +++ .../expressions/parsed_numbers.c3t | 14 + test/test_suite7/expressions/plus_int.c3 | 27 + .../expressions/pointer_access.c3t | 98 + test/test_suite7/expressions/pointer_arith.c3 | 18 + .../expressions/pointer_conv_error.c3 | 18 + .../expressions/pointer_to_bool.c3 | 9 + test/test_suite7/expressions/rvalues.c3 | 16 + .../expressions/simple_float_sub_neg.c3t | 18 + test/test_suite7/expressions/strings.c3t | 11 + test/test_suite7/expressions/take_address.c3t | 30 + test/test_suite7/expressions/ternary_bool.c3t | 103 + .../test_suite7/expressions/ternary_infer.c3t | 23 + .../expressions/ternary_no_ident.c3 | 14 + test/test_suite7/expressions/ternary_void.c3t | 31 + .../expressions/test_ct_param_bug.c3 | 7 + test/test_suite7/expressions/type_support.c3t | 76 + .../expressions/underscore_errors.c3 | 15 + .../expressions/unsafe_comparisons.c3 | 51 + test/test_suite7/expressions/void_arg.c3 | 33 + test/test_suite7/floats/convert_float.c3t | 24 + .../explicit_float_truncation_needed.c3 | 4 + .../floats/float_exceeding_size.c3 | 5 + test/test_suite7/floats/inf_nan.c3t | 26 + test/test_suite7/floats/mod.c3t | 14 + test/test_suite7/from_docs/examples_defer.c3t | 253 ++ .../from_docs/examples_forswitch.c3t | 714 ++++++ .../from_docs/examples_functionpointer.c3t | 34 + .../from_docs/examples_if_catch.c3t | 163 ++ .../from_docs/examples_macro_function.c3t | 44 + test/test_suite7/from_docs/examples_struct.c3 | 46 + .../functions/accidental_method_1448.c3 | 11 + test/test_suite7/functions/after_vararg.c3 | 3 + test/test_suite7/functions/assorted_tests.c3t | 113 + .../functions/body_argument_fail.c3 | 5 + .../functions/c_vararg_expansion.c3t | 37 + .../test_suite7/functions/call_conv_fntype.c3 | 6 + .../test_suite7/functions/ct_named_params.c3t | 23 + .../functions/default_param_fail.c3 | 11 + .../functions/defered_default_arguments.c3t | 56 + .../functions/distinct_fn_ptr_and_lambda.c3t | 8 + test/test_suite7/functions/double_return.c3 | 8 + test/test_suite7/functions/failable_param.c3 | 3 + .../functions/func_ptr_conversion_alias.c3t | 21 + .../func_ptr_conversions_and_names.c3t | 135 + .../functions/func_ptr_null.check.c3t | 43 + .../functions/function_alias_llvm_check.c3t | 51 + .../functions/function_reserved_name.c3 | 7 + test/test_suite7/functions/invalid_param.c3 | 1 + test/test_suite7/functions/macro_arguments.c3 | 12 + test/test_suite7/functions/macro_expr_type.c3 | 7 + .../functions/missing_first_paren.c3 | 3 + test/test_suite7/functions/missing_fn.c3 | 1 + test/test_suite7/functions/missing_return.c3 | 3 + .../functions/missing_return_lambda.c3 | 9 + test/test_suite7/functions/multisplat.c3t | 112 + test/test_suite7/functions/naked_function.c3t | 15 + test/test_suite7/functions/named_arg_order.c3 | 10 + test/test_suite7/functions/param_doc_error.c3 | 13 + .../functions/param_with_comma_at_end.c3 | 6 + test/test_suite7/functions/pointer_escape.c3 | 24 + test/test_suite7/functions/raw_splat.c3t | 146 ++ test/test_suite7/functions/recursive_fn.c3 | 2 + .../functions/recursive_through_generic.c3 | 14 + test/test_suite7/functions/returning_void.c3t | 20 + test/test_suite7/functions/simple_test.c3t | 30 + test/test_suite7/functions/splat.c3t | 43 + test/test_suite7/functions/splat_aarch64.c3t | 57 + test/test_suite7/functions/splat_empty.c3t | 12 + test/test_suite7/functions/splat_init.c3t | 40 + test/test_suite7/functions/splat_mingw.c3t | 51 + .../functions/splat_post_order.c3t | 12 + test/test_suite7/functions/splat_raw.c3 | 8 + test/test_suite7/functions/splat_untyped.c3t | 39 + test/test_suite7/functions/static_vars.c3t | 23 + .../test_suite7/functions/test_regression.c3t | 582 +++++ .../functions/test_regression_mingw.c3t | 650 +++++ test/test_suite7/functions/too_many_params.c3 | 40 + .../functions/type_argument_live_1461.c3t | 9 + .../functions/typeless_varargs.c3t | 74 + test/test_suite7/functions/unsplat_named.c3 | 8 + test/test_suite7/functions/vaarg_raw.c3 | 8 + .../functions/vararg_and_named_tests.c3 | 53 + .../functions/vararg_argument_fails.c3 | 5 + test/test_suite7/functions/varargs.c3t | 42 + .../functions/varargs_followed_by_named.c3t | 94 + test/test_suite7/functions/void_params.c3 | 2 + .../generic/different_generic_def.c3 | 21 + .../generic/enum_in_other_module.c3t | 104 + test/test_suite7/generic/enum_set_test.c3t | 88 + test/test_suite7/generic/generic_builtin.c3t | 16 + test/test_suite7/generic/generic_copy.c3t | 12 + test/test_suite7/generic/generic_cyclic.c3 | 17 + test/test_suite7/generic/generic_idents.c3t | 71 + .../test_suite7/generic/generic_interface.c3t | 31 + .../generic/generic_lambda_complex.c3t | 249 ++ test/test_suite7/generic/generic_local.c3 | 23 + test/test_suite7/generic/generic_num.c3t | 35 + test/test_suite7/generic/generic_over_fn.c3t | 207 ++ test/test_suite7/generic/generic_parsing.c3 | 22 + .../test_suite7/generic/generic_recursion.c3t | 21 + .../generic/generic_resolution_1402.c3t | 33 + test/test_suite7/generic/generic_void.c3t | 29 + .../generic/generic_with_comment.c3t | 13 + .../test_suite7/generic/generic_with_enum.c3t | 36 + .../generic/generic_without_param.c3 | 9 + .../generic/implicit_import_of_generic.c3 | 18 + .../generic/incorrect_argument_type.c3 | 11 + test/test_suite7/generic/nested_typedef.c3t | 30 + .../test_suite7/generic/used_without_param.c3 | 8 + .../generic/used_without_param2.c3 | 9 + .../generic/used_without_param3.c3 | 7 + test/test_suite7/globals/ext_global_init.c3 | 1 + test/test_suite7/globals/extern_const.c3t | 17 + test/test_suite7/globals/external_global.c3t | 36 + test/test_suite7/globals/global_align.c3t | 22 + test/test_suite7/globals/global_extname.c3t | 8 + test/test_suite7/globals/global_init.c3 | 22 + test/test_suite7/globals/global_no_init.c3t | 33 + test/test_suite7/globals/init_with_err.c3t | 24 + test/test_suite7/globals/misplaced_const.c3 | 6 + test/test_suite7/globals/recursive_globals.c3 | 3 + test/test_suite7/globals/recursive_locals.c3 | 13 + .../globals/self_referencing_local.c3 | 5 + test/test_suite7/globals/static_global.c3 | 1 + .../import/access_other_module.c3t | 23 + test/test_suite7/import/autoimport.c3 | 36 + test/test_suite7/import/import_error.c3 | 6 + test/test_suite7/import/import_error_multi.c3 | 1 + .../test_suite7/import/import_error_string.c3 | 1 + test/test_suite7/import/import_implicit.c3 | 17 + test/test_suite7/import/import_nonrecurse.c3 | 5 + test/test_suite7/import/import_same.c3 | 10 + test/test_suite7/import/import_twice.c3 | 8 + test/test_suite7/import/import_works.c3t | 3 + .../initialize/init_non_resolved_type.c3 | 1 + .../initialize/initialize_bad_prio.c3 | 16 + .../initialize/initialize_finalize.c3t | 67 + .../test_suite7/initialize/initialize_jump.c3 | 9 + .../initialize/initialize_parse_error.c3 | 1 + .../test_suite7/initialize/initialize_prio.c3 | 3 + .../initialize/initializer_access.c3 | 10 + .../initialize/initializer_var.c3t | 7 + .../initializer_lists/disallowed_lists.c3 | 8 + test/test_suite7/initializer_lists/fasta.c3t | 340 +++ .../initializer_lists/general_tests.c3t | 72 + .../indexing_into_complist.c3 | 5 + .../initializer_lists/infer_with_init.c3t | 20 + .../initializer_lists/init_any_interface.c3 | 23 + .../initializers_to_macros.c3 | 11 + .../initializer_lists/ranges_to_dynamic.c3t | 63 + .../test_suite7/initializer_lists/statics.c3t | 72 + .../initializer_lists/subarrays.c3t | 256 ++ .../initializer_lists/zero_inferred_array.c3 | 4 + .../initializer_lists/zero_init.c3t | 56 + test/test_suite7/lambda/ct_lambda.c3t | 138 + test/test_suite7/lambda/ct_lambda2.c3t | 84 + test/test_suite7/lambda/lambda_checks.c3 | 14 + test/test_suite7/lambda/lambda_in_macro.c3t | 45 + test/test_suite7/lambda/lambda_ref.c3t | 35 + test/test_suite7/lambda/nested_lambda_def.c3t | 78 + test/test_suite7/lambda/simple_lambda.c3t | 33 + test/test_suite7/lambda/var_lambda.c3 | 8 + test/test_suite7/lexing/expected_directive.c3 | 4 + .../lexing/invalid_hex_in_hexarray.c3 | 1 + .../lexing/invalid_hex_in_hexarray2.c3 | 1 + test/test_suite7/lexing/no_builtin.c3 | 2 + test/test_suite7/literals/bad_bitwidth.c3 | 4 + test/test_suite7/literals/bin_literal.c3t | 77 + test/test_suite7/literals/bin_literal2.c3t | 30 + test/test_suite7/literals/literal_general.c3t | 22 + test/test_suite7/literals/multi_unicode.c3 | 1 + .../literals/radix_numbers_errors.c3 | 17 + test/test_suite7/literals/too_small.c3 | 2 + test/test_suite7/macro_methods/access.c3 | 35 + .../macro_method_different_args.c3t | 49 + .../macro_methods/macro_method_fails.c3 | 46 + .../macro_methods/macro_method_first_param.c3 | 4 + .../macro_methods_defined_twice.c3 | 32 + .../macro_methods/macro_methods_no_args.c3 | 17 + test/test_suite7/macros/hash_ident.c3 | 25 + test/test_suite7/macros/hash_ident_nested.c3t | 34 + test/test_suite7/macros/hash_initializer.c3t | 23 + .../test_suite7/macros/implicit_return_opt.c3 | 19 + test/test_suite7/macros/macro_always_const.c3 | 9 + .../test_suite7/macros/macro_body_as_value.c3 | 12 + test/test_suite7/macros/macro_body_defer.c3t | 87 + test/test_suite7/macros/macro_body_errors.c3 | 7 + .../macros/macro_body_missing_type.c3 | 17 + .../macro_body_ref_hash_constant_type.c3t | 167 ++ test/test_suite7/macros/macro_calls_prefix.c3 | 8 + .../macro_chained_return_void_optional.c3t | 9 + test/test_suite7/macros/macro_common.c3t | 31 + .../macros/macro_convert_literal.c3 | 12 + test/test_suite7/macros/macro_defer_exit.c3t | 77 + test/test_suite7/macros/macro_defer_scope.c3t | 42 + .../macros/macro_defer_with_body.c3t | 51 + .../macros/macro_failable_return_rethrow.c3t | 58 + .../macros/macro_import_res_private.c3t | 26 + .../macros/macro_import_resolution.c3 | 13 + .../macros/macro_nested_labels.c3t | 356 +++ .../test_suite7/macros/macro_ref_body_err1.c3 | 4 + .../test_suite7/macros/macro_ref_body_err2.c3 | 11 + test/test_suite7/macros/macro_resolution.c3 | 24 + test/test_suite7/macros/macro_rtype.c3 | 9 + test/test_suite7/macros/macro_tagof.c3t | 11 + .../macros/macro_typed_varargs.c3t | 128 + .../macros/macro_untyped_varargs.c3 | 25 + .../macros/macro_untyped_varargs_2.c3t | 190 ++ test/test_suite7/macros/macro_vasplat.c3t | 459 ++++ test/test_suite7/macros/macro_with_body.c3t | 100 + .../test_suite7/macros/macro_with_body_err.c3 | 33 + test/test_suite7/macros/modify_ct_param.c3 | 13 + test/test_suite7/macros/no_body.c3 | 50 + test/test_suite7/macros/ref_macro_method.c3 | 26 + test/test_suite7/macros/ref_vector.c3t | 53 + .../macros/short_trailing_body.c3t | 122 + .../macros/trailing_body_const.c3t | 31 + test/test_suite7/macros/trailing_body_type.c3 | 10 + test/test_suite7/macros/type_params.c3t | 42 + test/test_suite7/macros/typed_hash_access.c3 | 11 + .../macros/unifying_implicit_void.c3t | 115 + test/test_suite7/macros/userland_bitcast.c3t | 331 +++ .../macros/vasplat_function_call.c3 | 18 + test/test_suite7/methods/access.c3 | 37 + .../methods/access_private_method.c3 | 9 + .../methods/dynamic_method_fails.c3 | 6 + .../methods/enum_distinct_err_methods.c3t | 218 ++ .../methods/extending_with_visibility.c3 | 35 + .../methods/extending_with_visibility_fail.c3 | 37 + .../extending_with_visibility_fail_private.c3 | 37 + test/test_suite7/methods/extension_method.c3t | 40 + .../methods/extension_method_already_exist.c3 | 30 + .../methods/extension_method_check.c3 | 19 + .../methods/extension_method_generic.c3 | 31 + .../extension_method_in_other_modules.c3t | 42 + .../method_extension_in_conditional_module.c3 | 15 + test/test_suite7/methods/method_from_var.c3 | 9 + .../methods/method_name_collision.c3 | 7 + .../method_ref_for_extension_method.c3 | 19 + .../methods/methods_defined_twice.c3 | 31 + .../methods/methods_with_inferred_type.c3t | 83 + .../methods/operator_assign_mutate.c3t | 77 + .../methods/operator_defined_twice.c3 | 9 + test/test_suite7/methods/operator_inc.c3t | 52 + test/test_suite7/methods/operator_mismatch.c3 | 12 + .../test_suite7/methods/self_methods_null.c3t | 27 + .../methods/unsupported_operator.c3 | 3 + test/test_suite7/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_suite7/module/module_error_string.c3 | 1 + .../module/module_generic_mixing.c3 | 7 + .../module/module_section_export.c3t | 29 + .../module/module_start_bad_ident.c3 | 1 + .../module/module_start_invalid.c3 | 1 + .../module/module_start_keyword.c3 | 1 + test/test_suite7/module/private_module.c3 | 1 + test/test_suite7/module/unknown_modules.c3 | 4 + .../overloading/construct_op_zero_args.c3 | 5 + .../overloading/construct_operator.c3t | 353 +++ .../overloading/set_not_set_overload.c3t | 61 + test/test_suite7/overloading/set_overload.c3t | 24 + .../pointers/array_pointer_decay.c3t | 77 + test/test_suite7/pointers/const_pointer.c3t | 16 + test/test_suite7/pointers/const_ref.c3t | 25 + test/test_suite7/pointers/pointer_index.c3t | 77 + .../pointers/subarray_variant_to_ptr.c3t | 86 + .../test_suite7/precedence/required_parens.c3 | 13 + .../regression/crash_on_right_paren_macro.c3 | 6 + test/test_suite7/safe/deref.c3t | 60 + .../safe/detect_invalid_deref_return.c3 | 40 + test/test_suite7/slices/array_to_const_err.c3 | 8 + .../slices/array_to_const_slice.c3t | 19 + test/test_suite7/slices/slice_assign.c3t | 83 + test/test_suite7/slices/slice_assign2.c3t | 48 + test/test_suite7/slices/slice_checks.c3t | 128 + test/test_suite7/slices/slice_comparison.c3t | 232 ++ test/test_suite7/slices/slice_conv_byte.c3t | 51 + test/test_suite7/slices/slice_init.c3t | 37 + test/test_suite7/slices/slice_inline.c3t | 34 + test/test_suite7/slices/slice_len_error.c3 | 21 + test/test_suite7/slices/slice_negative_len.c3 | 87 + test/test_suite7/slices/slice_offset.c3t | 20 + .../slices/slice_offset_neg_end.c3t | 20 + .../slices/slice_offset_neg_start.c3t | 20 + test/test_suite7/slices/slice_optional.c3t | 41 + .../slices/slice_optional_index.c3t | 120 + test/test_suite7/slices/slice_start.c3t | 19 + test/test_suite7/slices/slice_syntax.c3 | 24 + .../slices/slice_to_slice_assign.c3t | 129 + .../slices/slice_to_slice_conv_err.c3t | 8 + .../slices/slice_to_slice_vector_assign.c3t | 130 + test/test_suite7/slices/sub_array_init.c3 | 7 + .../slices/subscript_check_1519.c3t | 37 + .../slices/various_const_slicing.c3t | 497 ++++ test/test_suite7/statements/binary_fail.c3 | 8 + .../statements/call_missing_paren.c3 | 7 + .../statements/comparison_widening.c3t | 43 + .../statements/conditional_return.c3 | 12 + .../statements/const_statements.c3t | 15 + .../statements/custom_foreach_with_ref.c3t | 406 +++ .../statements/dead_statements.c3t | 44 + test/test_suite7/statements/default_args.c3 | 4 + .../statements/default_macro_argc.c3t | 287 +++ test/test_suite7/statements/defer_break.c3t | 114 + .../statements/defer_break_simple.c3t | 58 + .../statements/defer_break_switch.c3t | 60 + .../statements/defer_continue_bug.c3t | 59 + .../test_suite7/statements/defer_do_while.c3t | 38 + test/test_suite7/statements/defer_hash.c3t | 45 + .../statements/defer_if_try_copy.c3t | 36 + .../test_suite7/statements/defer_in_block.c3t | 88 + .../test_suite7/statements/defer_in_defer.c3t | 38 + .../statements/defer_in_defer2.c3t | 120 + .../statements/defer_in_defer3.c3t | 46 + .../statements/defer_next_switch.c3t | 59 + test/test_suite7/statements/defer_return.c3t | 99 + test/test_suite7/statements/defer_test.c3 | 9 + .../statements/defer_with_loop.c3t | 108 + .../statements/do_without_compound.c3 | 5 + .../statements/exhaustive_switch.c3t | 39 + test/test_suite7/statements/fallthough_do.c3t | 80 + test/test_suite7/statements/for.c3 | 24 + test/test_suite7/statements/for_empty.c3 | 8 + test/test_suite7/statements/for_errors.c3 | 7 + .../statements/for_statement_placement.c3 | 13 + .../statements/for_with_extra_declarations.c3 | 17 + .../statements/for_with_optional.c3t | 128 + test/test_suite7/statements/foreach_break.c3t | 73 + .../test_suite7/statements/foreach_common.c3t | 359 +++ .../test_suite7/statements/foreach_custom.c3t | 85 + .../statements/foreach_custom_errors.c3 | 15 + .../statements/foreach_custom_macro.c3t | 91 + .../statements/foreach_distinct_iterable.c3t | 61 + .../foreach_distinct_pointer_1506.c3 | 14 + test/test_suite7/statements/foreach_errors.c3 | 54 + .../foreach_more_implementations.c3t | 126 + .../statements/foreach_parse_error.c3 | 5 + .../statements/foreach_r_break.c3t | 72 + .../statements/foreach_r_common.c3t | 359 +++ .../statements/foreach_r_custom.c3t | 88 + .../statements/foreach_r_custom_errors.c3 | 15 + .../statements/foreach_r_custom_macro.c3t | 77 + .../statements/foreach_r_errors.c3 | 54 + .../statements/foreach_r_parse_error.c3 | 5 + .../statements/foreach_r_with_error.c3 | 12 + .../statements/foreach_with_error.c3 | 12 + .../statements/foreach_wrong_index.c3 | 27 + test/test_suite7/statements/if_decl.c3 | 5 + test/test_suite7/statements/if_only_throw.c3t | 30 + test/test_suite7/statements/if_single.c3 | 29 + test/test_suite7/statements/if_tests.c3t | 71 + .../statements/if_while_do_error.c3 | 34 + .../statements/infinite_do_while.c3t | 40 + test/test_suite7/statements/label_errors.c3 | 24 + .../statements/labelled_continue_for.c3t | 71 + .../test_suite7/statements/nextcase_const.c3t | 52 + .../statements/nextcase_default.c3t | 121 + .../statements/nextcase_missing_case.c3 | 14 + .../statements/nextcase_no_switch.c3 | 11 + test/test_suite7/statements/ranged_switch.c3t | 229 ++ test/test_suite7/statements/return_stmt.c3 | 11 + test/test_suite7/statements/return_switch.c3t | 36 + .../statements/return_with_other_at_end.c3 | 7 + test/test_suite7/statements/simple_do.c3t | 112 + .../statements/switch_error_fallthrough.c3 | 11 + .../statements/switch_error_range.c3 | 12 + test/test_suite7/statements/switch_errors.c3 | 160 ++ .../statements/various_switching.c3t | 298 +++ .../statements/while_statement_placement.c3 | 11 + .../statements/while_statement_placement2.c3 | 34 + test/test_suite7/statements/while_switch.c3t | 90 + test/test_suite7/stdlib/ascii.c3 | 26 + test/test_suite7/stdlib/map_linux.c3t | 290 +++ test/test_suite7/stdlib/map_macos.c3t | 268 ++ test/test_suite7/stdlib/memcomp.c3t | 16 + test/test_suite7/stdlib/minmax.c3 | 9 + test/test_suite7/stdlib/print_env_defines.c3 | 15 + test/test_suite7/stdlib/priorityqueue.c3t | 31 + test/test_suite7/strings/literal_errors.c3 | 22 + test/test_suite7/strings/literal_hex_ok.c3 | 3 + .../strings/literal_to_subarray.c3t | 24 + .../test_suite7/strings/multiline_strings.c3t | 18 + test/test_suite7/strings/string_escape.c3t | 22 + test/test_suite7/strings/string_len.c3t | 7 + test/test_suite7/strings/string_to_array.c3t | 28 + test/test_suite7/struct/const_access_error.c3 | 6 + .../test_suite7/struct/const_slice_struct.c3t | 37 + .../struct/const_zero_init_1360.c3t | 27 + test/test_suite7/struct/duplicate_member.c3 | 72 + .../struct/flex_array_comparison.c3 | 15 + .../struct/flex_array_struct_err.c3 | 31 + .../struct/flexible_array_resolve.c3 | 16 + test/test_suite7/struct/func_return_struct.c3 | 12 + .../struct/init_cont_struct_array_locally.c3t | 206 ++ .../struct/initialize_inline_designated.c3t | 31 + .../struct/inline_array_access.c3t | 33 + test/test_suite7/struct/inner_struct_name.c3 | 5 + test/test_suite7/struct/member_access.c3 | 87 + test/test_suite7/struct/member_expr.c3 | 31 + .../struct/multi_member_attributes.c3t | 22 + .../test_suite7/struct/nested_struct_init.c3t | 71 + .../struct/nested_struct_union_init.c3t | 110 + test/test_suite7/struct/recursive_structs.c3 | 25 + test/test_suite7/struct/simple_struct.c3t | 14 + test/test_suite7/struct/sret.c3t | 26 + test/test_suite7/struct/struct_as_value.c3t | 46 + .../struct/struct_as_value_aarch64.c3t | 41 + test/test_suite7/struct/struct_bad_member.c3 | 19 + test/test_suite7/struct/struct_codegen.c3t | 27 + .../struct/struct_codegen_empty.c3t | 39 + .../test_suite7/struct/struct_codegen_fam.c3t | 30 + test/test_suite7/struct/struct_comma.c3 | 7 + .../struct/struct_const_construct_simple.c3t | 32 + .../struct/struct_nopadding_compact.c3t | 272 ++ .../struct/struct_pack_and_align.c3t | 101 + test/test_suite7/struct/struct_pack_error.c3t | 48 + test/test_suite7/struct/struct_params.c3 | 27 + test/test_suite7/struct/struct_reinit.c3t | 40 + .../struct/struct_union_inner_align.c3t | 43 + test/test_suite7/struct/zero_member.c3 | 7 + test/test_suite7/switch/bad_ranges.c3 | 22 + .../switch/enum_jump_switch_and_range.c3t | 503 ++++ test/test_suite7/switch/failable_switch.c3 | 14 + test/test_suite7/switch/jump_bug_nested.c3t | 139 ++ test/test_suite7/switch/jump_bugs.c3t | 70 + test/test_suite7/switch/jump_with_inc.c3t | 65 + test/test_suite7/switch/simple_jump.c3t | 283 +++ .../switch/switch_in_defer_macro.c3t | 838 +++++++ .../symbols/allow_local_shadowing.c3 | 10 + test/test_suite7/symbols/shadow_struct.c3 | 15 + test/test_suite7/symbols/various.c3 | 189 ++ test/test_suite7/types/enum_illegal_type.c3 | 9 + .../types/enum_implicit_overflow.c3 | 136 + test/test_suite7/types/enum_inference.c3 | 43 + test/test_suite7/types/enum_ok.c3 | 35 + test/test_suite7/types/enum_param.c3 | 12 + test/test_suite7/types/enum_parse_errors.c3 | 22 + .../types/illegal_array_size_constant.c3 | 12 + test/test_suite7/types/non_rec_fn.c3 | 11 + test/test_suite7/types/recursive_array.c3 | 4 + test/test_suite7/types/recursive_fn.c3 | 1 + test/test_suite7/types/recursive_typedef.c3 | 9 + test/test_suite7/types/redefinition.c3 | 2 + test/test_suite7/types/typedefs.c3 | 11 + test/test_suite7/types/various.c3 | 5 + test/test_suite7/unicode/commenting-out.c3 | 10 + .../union/designated_union_zeroing.c3t | 33 + .../test_suite7/union/flexible_array_union.c3 | 5 + .../test_suite7/union/inferred_size_vector.c3 | 4 + test/test_suite7/union/test_unions.c3 | 28 + .../test_suite7/union/union_codegen_const.c3t | 20 + .../test_suite7/union/union_codegen_empty.c3t | 45 + .../union/union_codegen_overwrite_call.c3t | 30 + test/test_suite7/union/union_in_struct.c3t | 45 + .../union/union_member_voidcast.c3 | 13 + test/test_suite7/union/union_zero.c3 | 3 + test/test_suite7/variables/const_in_func.c3t | 19 + test/test_suite7/variables/consts.c3 | 7 + .../test_suite7/variables/static_in_macro.c3t | 76 + test/test_suite7/variables/var_init.c3t | 26 + test/test_suite7/variables/var_init_multi.c3t | 28 + test/test_suite7/vector/gather_scatter.c3t | 30 + .../test_suite7/vector/swizzle_vector_ref.c3t | 27 + test/test_suite7/vector/swizzling.c3 | 22 + test/test_suite7/vector/vector_bit.c3t | 153 ++ test/test_suite7/vector/vector_consts.c3t | 43 + .../vector/vector_conversion_scalar.c3 | 15 + test/test_suite7/vector/vector_from_i1.c3t | 31 + test/test_suite7/vector/vector_incdec.c3t | 189 ++ test/test_suite7/vector/vector_init.c3t | 53 + .../vector/vector_init_regression.c3t | 414 +++ .../vector/vector_lowering_regression1.c3t | 12 + test/test_suite7/vector/vector_ops2.c3t | 55 + test/test_suite7/vector/vector_param.c3t | 34 + .../vector/vector_pointer_errors.c3 | 14 + test/test_suite7/vector/vector_shift.c3t | 43 + .../vector/vector_to_array_cast.c3t | 39 + .../vector/vector_to_array_fail.c3 | 13 + .../vector/vector_to_vector_const_fail.c3 | 5 + .../visibility/ambiguous_recursive.c3 | 33 + test/test_suite7/visibility/ambiguous_var.c3t | 27 + .../visibility/export_property.c3t | 39 + .../visibility/no_shared_imports.c3t | 22 + test/test_suite7/visibility/not_visible.c3t | 16 + test/test_suite7/visibility/private_import.c3 | 21 + .../test_suite7/visibility/private_import2.c3 | 27 + .../visibility/private_to_extern.c3t | 21 + test/test_suite7/visibility/shared_module.c3t | 12 + .../visibility/simple_visibility.c3t | 16 + test/unit/stdlib/collections/priorityqueue.c3 | 4 +- 1228 files changed, 63192 insertions(+), 56 deletions(-) rename {lib2 => lib7}/std/ascii.c3 (100%) rename {lib2 => lib7}/std/atomic.c3 (100%) rename {lib2 => lib7}/std/atomic_nolibc.c3 (100%) rename {lib2 => lib7}/std/bits.c3 (100%) rename {lib2 => lib7}/std/collections/anylist.c3 (100%) rename {lib2 => lib7}/std/collections/bitset.c3 (100%) rename {lib2 => lib7}/std/collections/elastic_array.c3 (94%) rename {lib2 => lib7}/std/collections/enummap.c3 (100%) rename {lib2 => lib7}/std/collections/enumset.c3 (100%) rename {lib2 => lib7}/std/collections/hashmap.c3 (100%) rename {lib2 => lib7}/std/collections/linkedlist.c3 (100%) rename {lib2 => lib7}/std/collections/list.c3 (100%) rename {lib2 => lib7}/std/collections/list_common.c3 (100%) rename {lib2 => lib7}/std/collections/maybe.c3 (100%) rename {lib2 => lib7}/std/collections/object.c3 (100%) rename {lib2 => lib7}/std/collections/priorityqueue.c3 (94%) rename {lib2 => lib7}/std/collections/range.c3 (100%) rename {lib2 => lib7}/std/collections/ringbuffer.c3 (100%) rename {lib2 => lib7}/std/collections/tuple.c3 (100%) rename {lib2 => lib7}/std/compression/qoi.c3 (100%) rename {lib2 => lib7}/std/core/allocators/arena_allocator.c3 (100%) rename {lib2 => lib7}/std/core/allocators/dynamic_arena.c3 (100%) rename {lib2 => lib7}/std/core/allocators/heap_allocator.c3 (100%) rename {lib2 => lib7}/std/core/allocators/libc_allocator.c3 (100%) rename {lib2 => lib7}/std/core/allocators/on_stack_allocator.c3 (100%) rename {lib2 => lib7}/std/core/allocators/temp_allocator.c3 (100%) rename {lib2 => lib7}/std/core/allocators/tracking_allocator.c3 (100%) rename {lib2 => lib7}/std/core/array.c3 (100%) rename {lib2 => lib7}/std/core/bitorder.c3 (100%) rename {lib2 => lib7}/std/core/builtin.c3 (96%) rename {lib2 => lib7}/std/core/builtin_comparison.c3 (100%) rename {lib2 => lib7}/std/core/cinterop.c3 (100%) rename {lib2 => lib7}/std/core/conv.c3 (100%) rename {lib2 => lib7}/std/core/dstring.c3 (100%) rename {lib2 => lib7}/std/core/env.c3 (100%) rename {lib2 => lib7}/std/core/mem.c3 (100%) rename {lib2 => lib7}/std/core/mem_allocator.c3 (100%) rename {lib2 => lib7}/std/core/os/wasm_memory.c3 (100%) rename {lib2 => lib7}/std/core/private/cpu_detect.c3 (100%) rename {lib2 => lib7}/std/core/private/macho_runtime.c3 (100%) rename {lib2 => lib7}/std/core/private/main_stub.c3 (100%) rename {lib2 => lib7}/std/core/runtime.c3 (100%) rename {lib2 => lib7}/std/core/runtime_benchmark.c3 (100%) rename {lib2 => lib7}/std/core/runtime_test.c3 (100%) rename {lib2 => lib7}/std/core/sanitizer/asan.c3 (100%) rename {lib2 => lib7}/std/core/sanitizer/sanitizer.c3 (100%) rename {lib2 => lib7}/std/core/sanitizer/tsan.c3 (100%) rename {lib2 => lib7}/std/core/string.c3 (100%) rename {lib2 => lib7}/std/core/string_iterator.c3 (100%) rename {lib2 => lib7}/std/core/string_to_real.c3 (100%) rename {lib2 => lib7}/std/core/test.c3 (100%) rename {lib2 => lib7}/std/core/types.c3 (100%) rename {lib2 => lib7}/std/core/values.c3 (100%) rename {lib2 => lib7}/std/crypto/crypto.c3 (100%) rename {lib2 => lib7}/std/crypto/dh.c3 (100%) rename {lib2 => lib7}/std/crypto/rc4.c3 (100%) rename {lib2 => lib7}/std/encoding/base32.c3 (100%) rename {lib2 => lib7}/std/encoding/base64.c3 (100%) rename {lib2 => lib7}/std/encoding/csv.c3 (100%) rename {lib2 => lib7}/std/encoding/encoding.c3 (100%) rename {lib2 => lib7}/std/encoding/hex.c3 (100%) rename {lib2 => lib7}/std/encoding/json.c3 (100%) rename {lib2 => lib7}/std/experimental/FrameScheduler.c3 (100%) rename {lib2 => lib7}/std/hash/adler32.c3 (100%) rename {lib2 => lib7}/std/hash/crc32.c3 (100%) rename {lib2 => lib7}/std/hash/crc64.c3 (100%) rename {lib2 => lib7}/std/hash/fnv32a.c3 (100%) rename {lib2 => lib7}/std/hash/fnv64a.c3 (100%) rename {lib2 => lib7}/std/hash/hmac.c3 (100%) rename {lib2 => lib7}/std/hash/md5.c3 (100%) rename {lib2 => lib7}/std/hash/sha1.c3 (100%) rename {lib2 => lib7}/std/hash/sha256.c3 (100%) rename {lib2 => lib7}/std/io/bits.c3 (100%) rename {lib2 => lib7}/std/io/file.c3 (100%) rename {lib2 => lib7}/std/io/formatter.c3 (100%) rename {lib2 => lib7}/std/io/formatter_private.c3 (100%) rename {lib2 => lib7}/std/io/io.c3 (100%) rename {lib2 => lib7}/std/io/os/chdir.c3 (100%) rename {lib2 => lib7}/std/io/os/file_libc.c3 (100%) rename {lib2 => lib7}/std/io/os/file_nolibc.c3 (100%) rename {lib2 => lib7}/std/io/os/fileinfo.c3 (100%) rename {lib2 => lib7}/std/io/os/getcwd.c3 (100%) rename {lib2 => lib7}/std/io/os/ls.c3 (97%) rename {lib2 => lib7}/std/io/os/mkdir.c3 (100%) rename {lib2 => lib7}/std/io/os/rmdir.c3 (100%) rename {lib2 => lib7}/std/io/os/rmtree.c3 (100%) rename {lib2 => lib7}/std/io/os/temp_directory.c3 (100%) rename {lib2 => lib7}/std/io/path.c3 (100%) rename {lib2 => lib7}/std/io/stream.c3 (100%) rename {lib2 => lib7}/std/io/stream/buffer.c3 (100%) rename {lib2 => lib7}/std/io/stream/bytebuffer.c3 (100%) rename {lib2 => lib7}/std/io/stream/bytereader.c3 (100%) rename {lib2 => lib7}/std/io/stream/bytewriter.c3 (100%) rename {lib2 => lib7}/std/io/stream/limitreader.c3 (100%) rename {lib2 => lib7}/std/io/stream/multireader.c3 (100%) rename {lib2 => lib7}/std/io/stream/multiwriter.c3 (100%) rename {lib2 => lib7}/std/io/stream/scanner.c3 (100%) rename {lib2 => lib7}/std/io/stream/teereader.c3 (100%) rename {lib2 => lib7}/std/libc/libc.c3 (100%) rename {lib2 => lib7}/std/libc/libc_extra.c3 (100%) rename {lib2 => lib7}/std/libc/os/darwin.c3 (100%) rename {lib2 => lib7}/std/libc/os/errno.c3 (100%) rename {lib2 => lib7}/std/libc/os/freebsd.c3 (100%) rename {lib2 => lib7}/std/libc/os/linux.c3 (100%) rename {lib2 => lib7}/std/libc/os/posix.c3 (100%) rename {lib2 => lib7}/std/libc/os/win32.c3 (100%) rename {lib2 => lib7}/std/libc/termios.c3 (100%) rename {lib2 => lib7}/std/math/bigint.c3 (100%) rename {lib2 => lib7}/std/math/math.c3 (100%) rename {lib2 => lib7}/std/math/math_builtin.c3 (100%) rename {lib2 => lib7}/std/math/math_complex.c3 (100%) rename {lib2 => lib7}/std/math/math_easings.c3 (100%) rename {lib2 => lib7}/std/math/math_i128.c3 (100%) rename {lib2 => lib7}/std/math/math_libc.c3 (100%) rename {lib2 => lib7}/std/math/math_matrix.c3 (100%) rename {lib2 => lib7}/std/math/math_nolibc/__cos.c3 (100%) rename {lib2 => lib7}/std/math/math_nolibc/__cosdf.c3 (100%) rename {lib2 => lib7}/std/math/math_nolibc/__fmod.c3 (100%) rename {lib2 => lib7}/std/math/math_nolibc/__sin.c3 (100%) rename {lib2 => lib7}/std/math/math_nolibc/__sindf.c3 (100%) rename {lib2 => lib7}/std/math/math_nolibc/__tan.c3 (100%) rename {lib2 => lib7}/std/math/math_nolibc/__tandf.c3 (100%) rename {lib2 => lib7}/std/math/math_nolibc/acos.c3 (100%) rename {lib2 => lib7}/std/math/math_nolibc/asin.c3 (100%) rename {lib2 => lib7}/std/math/math_nolibc/atan.c3 (100%) rename {lib2 => lib7}/std/math/math_nolibc/atanh.c3 (100%) rename {lib2 => lib7}/std/math/math_nolibc/ceil.c3 (100%) rename {lib2 => lib7}/std/math/math_nolibc/cos.c3 (100%) rename {lib2 => lib7}/std/math/math_nolibc/exp.c3 (100%) rename {lib2 => lib7}/std/math/math_nolibc/exp2.c3 (100%) rename {lib2 => lib7}/std/math/math_nolibc/fabs.c3 (100%) rename {lib2 => lib7}/std/math/math_nolibc/floor.c3 (100%) rename {lib2 => lib7}/std/math/math_nolibc/frexp.c3 (100%) rename {lib2 => lib7}/std/math/math_nolibc/ldexp.c3 (100%) rename {lib2 => lib7}/std/math/math_nolibc/log.c3 (100%) rename {lib2 => lib7}/std/math/math_nolibc/log1p.c3 (100%) rename {lib2 => lib7}/std/math/math_nolibc/math_nolibc.c3 (100%) rename {lib2 => lib7}/std/math/math_nolibc/pow.c3 (100%) rename {lib2 => lib7}/std/math/math_nolibc/rempi.c3 (100%) rename {lib2 => lib7}/std/math/math_nolibc/round.c3 (100%) rename {lib2 => lib7}/std/math/math_nolibc/scalbn.c3 (100%) rename {lib2 => lib7}/std/math/math_nolibc/sin.c3 (100%) rename {lib2 => lib7}/std/math/math_nolibc/sincos.c3 (100%) rename {lib2 => lib7}/std/math/math_nolibc/tan.c3 (100%) rename {lib2 => lib7}/std/math/math_nolibc/trig.c3 (100%) rename {lib2 => lib7}/std/math/math_nolibc/trunc.c3 (100%) rename {lib2 => lib7}/std/math/math_quaternion.c3 (100%) rename {lib2 => lib7}/std/math/math_random.c3 (100%) rename {lib2 => lib7}/std/math/math_vector.c3 (100%) rename {lib2 => lib7}/std/math/random/math.lcg.c3 (100%) rename {lib2 => lib7}/std/math/random/math.mcg.c3 (100%) rename {lib2 => lib7}/std/math/random/math.msws.c3 (100%) rename {lib2 => lib7}/std/math/random/math.pcg.c3 (100%) rename {lib2 => lib7}/std/math/random/math.seeder.c3 (100%) rename {lib2 => lib7}/std/math/random/math.sfc.c3 (100%) rename {lib2 => lib7}/std/math/random/math.simple_random.c3 (100%) rename {lib2 => lib7}/std/math/uuid.c3 (100%) rename {lib2 => lib7}/std/net/http.c3 (100%) rename {lib2 => lib7}/std/net/inetaddr.c3 (100%) rename {lib2 => lib7}/std/net/net.c3 (100%) rename {lib2 => lib7}/std/net/os/common.c3 (100%) rename {lib2 => lib7}/std/net/os/darwin.c3 (100%) rename {lib2 => lib7}/std/net/os/linux.c3 (100%) rename {lib2 => lib7}/std/net/os/posix.c3 (100%) rename {lib2 => lib7}/std/net/os/win32.c3 (100%) rename {lib2 => lib7}/std/net/socket.c3 (100%) rename {lib2 => lib7}/std/net/socket_private.c3 (100%) rename {lib2 => lib7}/std/net/tcp.c3 (100%) rename {lib2 => lib7}/std/net/udp.c3 (100%) rename {lib2 => lib7}/std/net/url.c3 (100%) rename {lib2 => lib7}/std/net/url_encoding.c3 (100%) rename {lib2 => lib7}/std/os/backtrace.c3 (90%) rename {lib2 => lib7}/std/os/cpu.c3 (100%) rename {lib2 => lib7}/std/os/env.c3 (100%) rename {lib2 => lib7}/std/os/linux/heap.c3 (100%) rename {lib2 => lib7}/std/os/linux/linux.c3 (82%) rename {lib2 => lib7}/std/os/macos/cf_allocator.c3 (100%) rename {lib2 => lib7}/std/os/macos/cf_array.c3 (100%) rename {lib2 => lib7}/std/os/macos/cocoa.c3 (100%) rename {lib2 => lib7}/std/os/macos/core_foundation.c3 (100%) rename {lib2 => lib7}/std/os/macos/darwin.c3 (100%) rename {lib2 => lib7}/std/os/macos/heap.c3 (100%) rename {lib2 => lib7}/std/os/macos/objc.c3 (100%) rename {lib2 => lib7}/std/os/posix/files.c3 (100%) rename {lib2 => lib7}/std/os/posix/general.c3 (100%) rename {lib2 => lib7}/std/os/posix/heap.c3 (100%) rename {lib2 => lib7}/std/os/posix/process.c3 (100%) rename {lib2 => lib7}/std/os/posix/threads.c3 (100%) rename {lib2 => lib7}/std/os/subprocess.c3 (100%) rename {lib2 => lib7}/std/os/win32/files.c3 (100%) rename {lib2 => lib7}/std/os/win32/gdi.c3 (100%) rename {lib2 => lib7}/std/os/win32/general.c3 (100%) rename {lib2 => lib7}/std/os/win32/heap.c3 (100%) rename {lib2 => lib7}/std/os/win32/process.c3 (96%) rename {lib2 => lib7}/std/os/win32/types.c3 (100%) rename {lib2 => lib7}/std/os/win32/wincon.c3 (100%) rename {lib2 => lib7}/std/os/win32/windef.c3 (100%) rename {lib2 => lib7}/std/os/win32/winuser.c3 (100%) rename {lib2 => lib7}/std/os/win32/ws2def.c3 (100%) rename {lib2 => lib7}/std/os/win32/wsa.c3 (100%) rename {lib2 => lib7}/std/sort/binarysearch.c3 (100%) rename {lib2 => lib7}/std/sort/countingsort.c3 (100%) rename {lib2 => lib7}/std/sort/insertionsort.c3 (100%) rename {lib2 => lib7}/std/sort/quicksort.c3 (100%) rename {lib2 => lib7}/std/sort/sort.c3 (100%) rename {lib2 => lib7}/std/sort/sorted.c3 (100%) rename {lib2 => lib7}/std/text/i18n.c3 (100%) rename {lib2 => lib7}/std/threads/buffered_channel.c3 (100%) rename {lib2 => lib7}/std/threads/event/event_thread.c3 (100%) rename {lib2 => lib7}/std/threads/fixed_pool.c3 (100%) rename {lib2 => lib7}/std/threads/os/cpu.c3 (100%) rename {lib2 => lib7}/std/threads/os/thread_none.c3 (100%) rename {lib2 => lib7}/std/threads/os/thread_posix.c3 (100%) rename {lib2 => lib7}/std/threads/os/thread_win32.c3 (100%) rename {lib2 => lib7}/std/threads/pool.c3 (100%) rename {lib2 => lib7}/std/threads/thread.c3 (100%) rename {lib2 => lib7}/std/threads/unbuffered_channel.c3 (100%) rename {lib2 => lib7}/std/time/clock.c3 (100%) rename {lib2 => lib7}/std/time/datetime.c3 (100%) rename {lib2 => lib7}/std/time/format.c3 (100%) rename {lib2 => lib7}/std/time/os/time_darwin.c3 (100%) rename {lib2 => lib7}/std/time/os/time_posix.c3 (100%) rename {lib2 => lib7}/std/time/os/time_win32.c3 (100%) rename {lib2 => lib7}/std/time/time.c3 (100%) create mode 100644 test/test_suite7/abi/aarch64_args.c3t create mode 100644 test/test_suite7/abi/aarch64_hfa_args.c3t create mode 100644 test/test_suite7/abi/aarch_ret_small_struct.c3t create mode 100644 test/test_suite7/abi/avx512fp16-abi.c3t create mode 100644 test/test_suite7/abi/darwin64_avx.c3t create mode 100644 test/test_suite7/abi/darwin64_avx512.c3t create mode 100644 test/test_suite7/abi/darwin64_sret.c3t create mode 100644 test/test_suite7/abi/darwin64_sse.c3t create mode 100644 test/test_suite7/abi/darwin_arg.c3t create mode 100644 test/test_suite7/abi/darwin_return_boolarray.c3t create mode 100644 test/test_suite7/abi/darwinx64_1.c3t create mode 100644 test/test_suite7/abi/darwinx64_2.c3t create mode 100644 test/test_suite7/abi/linking_extern.c3t create mode 100644 test/test_suite7/abi/literal_load.c3t create mode 100644 test/test_suite7/abi/literal_load_aarch64.c3t create mode 100644 test/test_suite7/abi/literal_load_mingw.c3t create mode 100644 test/test_suite7/abi/macho_section.c3t create mode 100644 test/test_suite7/abi/macho_section_attributes.c3 create mode 100644 test/test_suite7/abi/pass_large_aarch.c3t create mode 100644 test/test_suite7/abi/riscv32-ilp32-abi.c3t create mode 100644 test/test_suite7/abi/riscv32-ilp32-ilp32f-abi-1.c3t create mode 100644 test/test_suite7/abi/riscv32-ilp32-ilp32f-abi-2.c3t create mode 100644 test/test_suite7/abi/riscv32-ilp32-ilp32f-ilp32d-abi-1.c3t create mode 100644 test/test_suite7/abi/riscv32-ilp32-ilp32f-ilp32d-abi-2.c3t create mode 100644 test/test_suite7/abi/riscv32-ilp32-ilp32f-ilp32d-abi-3.c3t create mode 100644 test/test_suite7/abi/riscv32-ilp32d-abi.c3t create mode 100644 test/test_suite7/abi/riscv32-ilp32f-abi.c3t create mode 100644 test/test_suite7/abi/riscv32-ilp32f-ilp32d-abi-1.c3t create mode 100644 test/test_suite7/abi/riscv32-ilp32f-ilp32d-abi-2.c3t create mode 100644 test/test_suite7/abi/riscv64-lp64-abi.c3t create mode 100644 test/test_suite7/abi/riscv64-lp64-lp64f-abi-1.c3t create mode 100644 test/test_suite7/abi/riscv64-lp64-lp64f-abi-2.c3t create mode 100644 test/test_suite7/abi/riscv64-lp64-lp64f-lp64d-abi-1.c3t create mode 100644 test/test_suite7/abi/riscv64-lp64-lp64f-lp64d-abi-2.c3t create mode 100644 test/test_suite7/abi/riscv64-lp64-lp64f-lp64d-abi-3.c3t create mode 100644 test/test_suite7/abi/riscv64-lp64d-abi.c3t create mode 100644 test/test_suite7/abi/riscv64-lp64f-lp64d-abi-1.c3t create mode 100644 test/test_suite7/abi/riscv64-lp64f-lp64d-abi-2.c3t create mode 100644 test/test_suite7/abi/small_struct_x64.c3t create mode 100644 test/test_suite7/abi/sysv_abi_avx.c3t create mode 100644 test/test_suite7/abi/sysv_abi_noavx.c3t create mode 100644 test/test_suite7/abi/sysv_direct_coerce.c3t create mode 100644 test/test_suite7/abi/test_sret.c3t create mode 100644 test/test_suite7/abi/union_x64.c3t create mode 100644 test/test_suite7/abi/vec2_aarch64.c3t create mode 100644 test/test_suite7/abi/vec2_wasm.c3t create mode 100644 test/test_suite7/abi/vec2_x64.c3t create mode 100644 test/test_suite7/abi/wasm_extern.c3t create mode 100644 test/test_suite7/abi/x64alignarray.c3t create mode 100644 test/test_suite7/any/any_in_any.c3t create mode 100644 test/test_suite7/any/casting_voidptr_to_any.c3 create mode 100644 test/test_suite7/any/generic_interface.c3 create mode 100644 test/test_suite7/any/interface_no_fn.c3 create mode 100644 test/test_suite7/any/interface_no_method_body_1536.c3 create mode 100644 test/test_suite7/any/interface_ptr.c3 create mode 100644 test/test_suite7/any/variant_assign.c3t create mode 100644 test/test_suite7/any/variant_switch.c3t create mode 100644 test/test_suite7/any/variant_test.c3t create mode 100644 test/test_suite7/arrays/array_bounds_check.c3t create mode 100644 test/test_suite7/arrays/array_casts.c3t create mode 100644 test/test_suite7/arrays/array_comparison.c3t create mode 100644 test/test_suite7/arrays/array_comparison_2.c3t create mode 100644 test/test_suite7/arrays/array_indexing.c3 create mode 100644 test/test_suite7/arrays/array_invalid_casts.c3 create mode 100644 test/test_suite7/arrays/array_literal.c3t create mode 100644 test/test_suite7/arrays/array_struct.c3t create mode 100644 test/test_suite7/arrays/complex_array_const.c3t create mode 100644 test/test_suite7/arrays/complex_inferred_array.c3t create mode 100644 test/test_suite7/arrays/global_array_non_const.c3 create mode 100644 test/test_suite7/arrays/global_init.c3t create mode 100644 test/test_suite7/arrays/global_init_array_out_of_range.c3 create mode 100644 test/test_suite7/arrays/index_from_back.c3t create mode 100644 test/test_suite7/arrays/index_into_global.c3t create mode 100644 test/test_suite7/arrays/inferred_array_err.c3 create mode 100644 test/test_suite7/arrays/inferred_array_err2.c3 create mode 100644 test/test_suite7/arrays/inferred_array_optional.c3t create mode 100644 test/test_suite7/arrays/inferred_subarray.c3 create mode 100644 test/test_suite7/arrays/negative_array.c3 create mode 100644 test/test_suite7/arrays/slice.c3 create mode 100644 test/test_suite7/arrays/slice_array.c3 create mode 100644 test/test_suite7/asm/asm_bit_rv.c3t create mode 100644 test/test_suite7/asm/asm_imm_err_rv.c3 create mode 100644 test/test_suite7/asm/asm_intr_rv.c3t create mode 100644 test/test_suite7/asm/asm_jump_rv.c3t create mode 100644 test/test_suite7/asm/asm_load_rv.c3t create mode 100644 test/test_suite7/asm/asm_load_rv64.c3t create mode 100644 test/test_suite7/asm/asm_math_rv.c3t create mode 100644 test/test_suite7/asm/asm_ops_x64_1.c3t create mode 100644 test/test_suite7/asm/asm_ops_x64_2.c3t create mode 100644 test/test_suite7/asm/asm_regression.c3t create mode 100644 test/test_suite7/asm/asm_set_rv.c3t create mode 100644 test/test_suite7/asm/asm_shift_rv.c3t create mode 100644 test/test_suite7/asm/asm_store_rv.c3t create mode 100644 test/test_suite7/asm/naked.c3t create mode 100644 test/test_suite7/asm/sideeffect.c3t create mode 100644 test/test_suite7/asm/syscall.c3t create mode 100644 test/test_suite7/assert/assert_variants.c3t create mode 100644 test/test_suite7/assert/assert_with_void.c3 create mode 100644 test/test_suite7/assert/assertf.c3t create mode 100644 test/test_suite7/assert/global_static_assert_not_constant.c3 create mode 100644 test/test_suite7/assert/local_static_assert_not_constant.c3 create mode 100644 test/test_suite7/assert/static_assert.c3 create mode 100644 test/test_suite7/assert/unreachable.c3t create mode 100644 test/test_suite7/assert/unreachable_in_macro.c3t create mode 100644 test/test_suite7/assignment/alignment_index.c3t create mode 100644 test/test_suite7/assignment/int_assign.c3t create mode 100644 test/test_suite7/assignment/var_variable.c3 create mode 100644 test/test_suite7/attributes/attr_link_err.c3 create mode 100644 test/test_suite7/attributes/attr_not_imported.c3 create mode 100644 test/test_suite7/attributes/attribute_params.c3 create mode 100644 test/test_suite7/attributes/attribute_path.c3 create mode 100644 test/test_suite7/attributes/attribute_visibility.c3t create mode 100644 test/test_suite7/attributes/attributes_repeat_param.c3t create mode 100644 test/test_suite7/attributes/call_attribute_error_eos.c3 create mode 100644 test/test_suite7/attributes/recursive_attributes.c3 create mode 100644 test/test_suite7/attributes/user_defined_attributes.c3t create mode 100644 test/test_suite7/attributes/wasm_import.c3t create mode 100644 test/test_suite7/attributes/wasm_module.c3 create mode 100644 test/test_suite7/bitstruct/address_of_bitstruct.c3 create mode 100644 test/test_suite7/bitstruct/anon_bitstruct_name_overlap.c3 create mode 100644 test/test_suite7/bitstruct/array_with_boolean.c3t create mode 100644 test/test_suite7/bitstruct/bistruct_cast_wrong_size.c3 create mode 100644 test/test_suite7/bitstruct/bitfield_access.c3t create mode 100644 test/test_suite7/bitstruct/bitstruct_access_signed.c3t create mode 100644 test/test_suite7/bitstruct/bitstruct_align.c3t create mode 100644 test/test_suite7/bitstruct/bitstruct_anon_in_struct_ok.c3t create mode 100644 test/test_suite7/bitstruct/bitstruct_arrays.c3t create mode 100644 test/test_suite7/bitstruct/bitstruct_arrays_be.c3t create mode 100644 test/test_suite7/bitstruct/bitstruct_be.c3t create mode 100644 test/test_suite7/bitstruct/bitstruct_bool.c3t create mode 100644 test/test_suite7/bitstruct/bitstruct_cast_and_back.c3 create mode 100644 test/test_suite7/bitstruct/bitstruct_cast_const_init.c3t create mode 100644 test/test_suite7/bitstruct/bitstruct_direct_in_struct.c3t create mode 100644 test/test_suite7/bitstruct/bitstruct_general.c3 create mode 100644 test/test_suite7/bitstruct/bitstruct_in_subarray.c3t create mode 100644 test/test_suite7/bitstruct/bitstruct_init.c3 create mode 100644 test/test_suite7/bitstruct/bitstruct_init_bool.c3t create mode 100644 test/test_suite7/bitstruct/bitstruct_initializer.c3t create mode 100644 test/test_suite7/bitstruct/bitstruct_intcontainer.c3t create mode 100644 test/test_suite7/bitstruct/bitstruct_ops.c3t create mode 100644 test/test_suite7/bitstruct/bitstruct_overlap.c3 create mode 100644 test/test_suite7/bitstruct/bitstruct_simple.c3 create mode 100644 test/test_suite7/bitstruct/bitstruct_simple_err_decl.c3 create mode 100644 test/test_suite7/bitstruct/bitstruct_single_error.c3 create mode 100644 test/test_suite7/bitstruct/bitstruct_to_int.c3t create mode 100644 test/test_suite7/bitstruct/designated_initializer_with_bitstruct.c3t create mode 100644 test/test_suite7/bitstruct/embedded_bitstruct.c3t create mode 100644 test/test_suite7/bitstruct/invalid_bitstruct_member_types.c3 create mode 100644 test/test_suite7/bitstruct/invalid_bitstruct_name_other_ident.c3 create mode 100644 test/test_suite7/bitstruct/invalid_bitstruct_type.c3 create mode 100644 test/test_suite7/bitstruct/invalid_empty_struct_union.c3 create mode 100644 test/test_suite7/bitstruct/missing_bitstruct_type.c3 create mode 100644 test/test_suite7/bitstruct/param_bitstruct.c3t create mode 100644 test/test_suite7/builtins/builtin_vector_abs.c3t create mode 100644 test/test_suite7/builtins/builtin_vector_min_max.c3t create mode 100644 test/test_suite7/builtins/builtin_with_optional.c3 create mode 100644 test/test_suite7/builtins/exacts.c3t create mode 100644 test/test_suite7/builtins/mem.c3t create mode 100644 test/test_suite7/builtins/overflows.c3t create mode 100644 test/test_suite7/builtins/prefetch.c3t create mode 100644 test/test_suite7/builtins/reduce_arithmetics.c3t create mode 100644 test/test_suite7/builtins/reverse_builtin.c3t create mode 100644 test/test_suite7/builtins/rounding_builtins.c3t create mode 100644 test/test_suite7/builtins/sat_builtins.c3t create mode 100644 test/test_suite7/builtins/shufflevector.c3t create mode 100644 test/test_suite7/builtins/simple_builtins.c3t create mode 100644 test/test_suite7/builtins/trap.c3t create mode 100644 test/test_suite7/builtins/unaligned_access.c3t create mode 100644 test/test_suite7/builtins/unaligned_load_store.c3t create mode 100644 test/test_suite7/cast/cast_bitstruct_etc.c3t create mode 100644 test/test_suite7/cast/cast_from_ptr.c3t create mode 100644 test/test_suite7/cast/cast_narrow_alias.c3t create mode 100644 test/test_suite7/cast/cast_ok.c3 create mode 100644 test/test_suite7/cast/cast_parse_fails.c3 create mode 100644 test/test_suite7/cast/cast_parse_fails2.c3 create mode 100644 test/test_suite7/cast/cast_ptr_vec_to_bool.c3t create mode 100644 test/test_suite7/cast/cast_rcast.c3 create mode 100644 test/test_suite7/cast/cast_slice_implicit.c3 create mode 100644 test/test_suite7/cast/cast_string_to_infered_array.c3 create mode 100644 test/test_suite7/cast/cast_struct.c3 create mode 100644 test/test_suite7/cast/cast_struct_fails.c3 create mode 100644 test/test_suite7/cast/cast_subarray.c3t create mode 100644 test/test_suite7/cast/cast_to_failable.c3 create mode 100644 test/test_suite7/cast/cast_untyped_list_error.c3 create mode 100644 test/test_suite7/cast/implicit_array_ptr_conv.c3 create mode 100644 test/test_suite7/cast/implicit_infer_len_cast.c3t create mode 100644 test/test_suite7/cast/implicit_void_ptr_deep.c3 create mode 100644 test/test_suite7/cast/inner_type_cast.c3 create mode 100644 test/test_suite7/cast/top_down_cast_fails.c3 create mode 100644 test/test_suite7/cast/top_down_casts.c3t create mode 100644 test/test_suite7/clang/2002-01_02.c3t create mode 100644 test/test_suite7/clang/2002-03.c3t create mode 100644 test/test_suite7/clang/2002-04.c3t create mode 100644 test/test_suite7/clang/2002-07.c3t create mode 100644 test/test_suite7/comments/simple_comments.c3 create mode 100644 test/test_suite7/compile_time/add_to_ct_undefined.c3 create mode 100644 test/test_suite7/compile_time/compile_time_access_subscript.c3t create mode 100644 test/test_suite7/compile_time/compile_time_array.c3t create mode 100644 test/test_suite7/compile_time/compile_time_array_bug.c3t create mode 100644 test/test_suite7/compile_time/compile_time_array_ref.c3t create mode 100644 test/test_suite7/compile_time/compile_time_bitops.c3t create mode 100644 test/test_suite7/compile_time/compile_time_pointers.c3t create mode 100644 test/test_suite7/compile_time/compile_time_ptr_ref.c3t create mode 100644 test/test_suite7/compile_time/compile_time_utf32.c3 create mode 100644 test/test_suite7/compile_time/comptime_array_folding.c3t create mode 100644 test/test_suite7/compile_time/concat_append.c3t create mode 100644 test/test_suite7/compile_time/concat_append_extended_and_edit.c3t create mode 100644 test/test_suite7/compile_time/concat_const.c3 create mode 100644 test/test_suite7/compile_time/concat_slice_array.c3 create mode 100644 test/test_suite7/compile_time/concat_slice_bytes.c3t create mode 100644 test/test_suite7/compile_time/concat_test.c3t create mode 100644 test/test_suite7/compile_time/concat_test_cases.c3 create mode 100644 test/test_suite7/compile_time/concat_zero_slice.c3t create mode 100644 test/test_suite7/compile_time/ct_and_or.c3 create mode 100644 test/test_suite7/compile_time/ct_assert_bug.c3 create mode 100644 test/test_suite7/compile_time/ct_builtin_time_date.c3t create mode 100644 test/test_suite7/compile_time/ct_cast_example.c3t create mode 100644 test/test_suite7/compile_time/ct_declaration_in_if.c3t create mode 100644 test/test_suite7/compile_time/ct_else_else.c3 create mode 100644 test/test_suite7/compile_time/ct_enum_values.c3t create mode 100644 test/test_suite7/compile_time/ct_eval.c3t create mode 100644 test/test_suite7/compile_time/ct_eval_sym.c3 create mode 100644 test/test_suite7/compile_time/ct_eval_wrong.c3 create mode 100644 test/test_suite7/compile_time/ct_for.c3t create mode 100644 test/test_suite7/compile_time/ct_forach_with_defer.c3t create mode 100644 test/test_suite7/compile_time/ct_foreach.c3t create mode 100644 test/test_suite7/compile_time/ct_func.c3t create mode 100644 test/test_suite7/compile_time/ct_funcptr.c3t create mode 100644 test/test_suite7/compile_time/ct_if.c3t create mode 100644 test/test_suite7/compile_time/ct_if_folding.c3t create mode 100644 test/test_suite7/compile_time/ct_left_hand_assign.c3t create mode 100644 test/test_suite7/compile_time/ct_memberof.c3t create mode 100644 test/test_suite7/compile_time/ct_ordered_error.c3t create mode 100644 test/test_suite7/compile_time/ct_string_functions.c3t create mode 100644 test/test_suite7/compile_time/ct_subscript_inc.c3t create mode 100644 test/test_suite7/compile_time/ct_subscript_op.c3t create mode 100644 test/test_suite7/compile_time/ct_switch.c3t create mode 100644 test/test_suite7/compile_time/ct_switch_errors.c3 create mode 100644 test/test_suite7/compile_time/ct_switch_more_checks.c3 create mode 100644 test/test_suite7/compile_time/ct_switch_top_level.c3t create mode 100644 test/test_suite7/compile_time/ct_switch_type_check.c3t create mode 100644 test/test_suite7/compile_time/ct_switch_type_errors.c3 create mode 100644 test/test_suite7/compile_time/ct_through_constant.c3t create mode 100644 test/test_suite7/compile_time/ct_vaexpr_assign.c3t create mode 100644 test/test_suite7/compile_time/ct_value_from_access.c3t create mode 100644 test/test_suite7/compile_time/cttype_reassign.c3t create mode 100644 test/test_suite7/compile_time/deep_stringify.c3t create mode 100644 test/test_suite7/compile_time/macro_compile_time_pseudo_evaluation.c3t create mode 100644 test/test_suite7/compile_time/mod_ct.c3t create mode 100644 test/test_suite7/compile_time/mod_in_other_scope.c3 create mode 100644 test/test_suite7/compile_time/more_untyped_conversions.c3t create mode 100644 test/test_suite7/compile_time/not_cost.c3 create mode 100644 test/test_suite7/compile_time/not_yet_initialized.c3 create mode 100644 test/test_suite7/compile_time/stringify.c3t create mode 100644 test/test_suite7/compile_time/stringify2.c3t create mode 100644 test/test_suite7/compile_time/ternary_folding.c3t create mode 100644 test/test_suite7/compile_time/typed_ct_vars.c3t create mode 100644 test/test_suite7/compile_time/typefrom.c3t create mode 100644 test/test_suite7/compile_time/typefrom_errors.c3t create mode 100644 test/test_suite7/compile_time/typeof_example.c3t create mode 100644 test/test_suite7/compile_time/typeof_from_literal.c3 create mode 100644 test/test_suite7/compile_time/untyped_conversions.c3t create mode 100644 test/test_suite7/compile_time/untyped_with_inferred.c3 create mode 100644 test/test_suite7/compile_time_introspection/alignof.c3t create mode 100644 test/test_suite7/compile_time_introspection/defined.c3t create mode 100644 test/test_suite7/compile_time_introspection/defined2.c3 create mode 100644 test/test_suite7/compile_time_introspection/defined_2.c3t create mode 100644 test/test_suite7/compile_time_introspection/defined_builtin.c3t create mode 100644 test/test_suite7/compile_time_introspection/defined_err.c3 create mode 100644 test/test_suite7/compile_time_introspection/defined_index.c3t create mode 100644 test/test_suite7/compile_time_introspection/defined_subscript.c3 create mode 100644 test/test_suite7/compile_time_introspection/nameof.c3t create mode 100644 test/test_suite7/compile_time_introspection/nameof_err.c3 create mode 100644 test/test_suite7/compile_time_introspection/offsetof.c3t create mode 100644 test/test_suite7/compile_time_introspection/paramsof.c3t create mode 100644 test/test_suite7/compile_time_introspection/parentof.c3t create mode 100644 test/test_suite7/compile_time_introspection/qnameof.c3t create mode 100644 test/test_suite7/compile_time_introspection/recursive_tag.c3 create mode 100644 test/test_suite7/compile_time_introspection/sizeof.c3t create mode 100644 test/test_suite7/compile_time_introspection/sizeof_errors.c3 create mode 100644 test/test_suite7/compile_time_introspection/tag.c3t create mode 100644 test/test_suite7/compile_time_introspection/tag_1343.c3t create mode 100644 test/test_suite7/concurrency/atomic_load_store.c3t create mode 100644 test/test_suite7/concurrency/atomic_load_store_debug.c3t create mode 100644 test/test_suite7/constants/assign_to_const.c3 create mode 100644 test/test_suite7/constants/byte_literal_fail_base64.c3 create mode 100644 test/test_suite7/constants/byte_literal_fail_base64_2.c3 create mode 100644 test/test_suite7/constants/byte_literal_fail_base64_4.c3 create mode 100644 test/test_suite7/constants/byte_literal_fail_hex.c3 create mode 100644 test/test_suite7/constants/byte_literals.c3t create mode 100644 test/test_suite7/constants/char_literals.c3t create mode 100644 test/test_suite7/constants/const_var_copy.c3t create mode 100644 test/test_suite7/constants/constant_struct.c3 create mode 100644 test/test_suite7/constants/constants.c3t create mode 100644 test/test_suite7/constants/empty_byte_literal.c3 create mode 100644 test/test_suite7/constants/float_type.c3t create mode 100644 test/test_suite7/constants/init_order.c3t create mode 100644 test/test_suite7/contracts/constant_out.c3 create mode 100644 test/test_suite7/contracts/ct_eval_of_ensure.c3 create mode 100644 test/test_suite7/contracts/ensure_unsigned.c3 create mode 100644 test/test_suite7/contracts/in_array.c3 create mode 100644 test/test_suite7/contracts/in_out.c3 create mode 100644 test/test_suite7/contracts/inout_in.c3 create mode 100644 test/test_suite7/contracts/macro_ensure_static.c3 create mode 100644 test/test_suite7/contracts/out_subscript.c3 create mode 100644 test/test_suite7/contracts/pure.c3 create mode 100644 test/test_suite7/contracts/pure_calls.c3 create mode 100644 test/test_suite7/contracts/require_contract_loc.c3 create mode 100644 test/test_suite7/contracts/simple_test.c3t create mode 100644 test/test_suite7/debug_symbols/constants.c3t create mode 100644 test/test_suite7/debug_symbols/constants_mingw.c3t create mode 100644 test/test_suite7/debug_symbols/ct_foreach.c3t create mode 100644 test/test_suite7/debug_symbols/defer_macro.c3t create mode 100644 test/test_suite7/debug_symbols/foreach.c3t create mode 100644 test/test_suite7/defer/defer_and_expr_block.c3t create mode 100644 test/test_suite7/defer/defer_catch_direct_error.c3t create mode 100644 test/test_suite7/defer/defer_catch_err.c3t create mode 100644 test/test_suite7/defer/defer_catch_mix.c3t create mode 100644 test/test_suite7/defer/defer_catch_try.c3t create mode 100644 test/test_suite7/defer/defer_nextcase.c3t create mode 100644 test/test_suite7/defer/defer_single_stmt.c3 create mode 100644 test/test_suite7/defer/defer_static_var.c3t create mode 100644 test/test_suite7/defer/defer_try_catch.c3t create mode 100644 test/test_suite7/defer/defer_with_catch.c3t create mode 100644 test/test_suite7/defer/defer_with_rethrow.c3 create mode 100644 test/test_suite7/defer/defer_with_return.c3 create mode 100644 test/test_suite7/defer/defer_with_unwrapped.c3t create mode 100644 test/test_suite7/define/alias_typename.c3 create mode 100644 test/test_suite7/define/aliased_consts.c3t create mode 100644 test/test_suite7/define/common.c3 create mode 100644 test/test_suite7/define/common2.c3 create mode 100644 test/test_suite7/define/define_name_errors.c3 create mode 100644 test/test_suite7/define/forbidden_defines.c3 create mode 100644 test/test_suite7/define/test_at.c3 create mode 100644 test/test_suite7/define/test_at_alias.c3 create mode 100644 test/test_suite7/define/weak_alias_fails.c3 create mode 100644 test/test_suite7/define/weak_aliases.c3 create mode 100644 test/test_suite7/distinct/disntinct_add_fail.c3 create mode 100644 test/test_suite7/distinct/distinct_add.c3 create mode 100644 test/test_suite7/distinct/distinct_function.c3t create mode 100644 test/test_suite7/distinct/distinct_function_call.c3 create mode 100644 test/test_suite7/distinct/distinct_inline_access.c3 create mode 100644 test/test_suite7/distinct/distinct_invalid.c3 create mode 100644 test/test_suite7/distinct/distinct_max.c3t create mode 100644 test/test_suite7/distinct/distinct_shift.c3t create mode 100644 test/test_suite7/distinct/distinct_slicing.c3 create mode 100644 test/test_suite7/distinct/distinct_struct.c3 create mode 100644 test/test_suite7/distinct/distinct_struct_array.c3 create mode 100644 test/test_suite7/distinct/distinct_sub.c3t create mode 100644 test/test_suite7/distinct/distinct_union.c3 create mode 100644 test/test_suite7/distinct/test_errors.c3 create mode 100644 test/test_suite7/distinct/test_ops_on_int.c3 create mode 100644 test/test_suite7/distinct/test_ops_on_struct.c3 create mode 100644 test/test_suite7/dynamic/any_cast.c3 create mode 100644 test/test_suite7/dynamic/duplicate_definition.c3 create mode 100644 test/test_suite7/dynamic/dynamic_inherit_deep.c3t create mode 100644 test/test_suite7/dynamic/dynamic_mismatch.c3 create mode 100644 test/test_suite7/dynamic/dynamic_tracing.c3t create mode 100644 test/test_suite7/dynamic/inherit_linux.c3t create mode 100644 test/test_suite7/dynamic/inherit_macos.c3t create mode 100644 test/test_suite7/dynamic/inline_protocol.c3 create mode 100644 test/test_suite7/dynamic/null_and_protocol.c3t create mode 100644 test/test_suite7/dynamic/overlapping_function_linux.c3t create mode 100644 test/test_suite7/dynamic/overlapping_function_macos.c3t create mode 100644 test/test_suite7/dynamic/same_method_twice.c3 create mode 100644 test/test_suite7/embed/embed_basic.c3t create mode 100644 test/test_suite7/enumerations/compile_time.c3t create mode 100644 test/test_suite7/enumerations/enum_add_sub.c3t create mode 100644 test/test_suite7/enumerations/enum_associated_value.c3t create mode 100644 test/test_suite7/enumerations/enum_associated_values_other.c3t create mode 100644 test/test_suite7/enumerations/enum_cast.c3t create mode 100644 test/test_suite7/enumerations/enum_cast_error.c3 create mode 100644 test/test_suite7/enumerations/enum_conversions.c3t create mode 100644 test/test_suite7/enumerations/enum_invalid_param.c3 create mode 100644 test/test_suite7/enumerations/enum_missing_comma.c3 create mode 100644 test/test_suite7/enumerations/enum_reflect_associated.c3t create mode 100644 test/test_suite7/enumerations/enum_same_param.c3 create mode 100644 test/test_suite7/enumerations/enum_signed_cast_swap.c3t create mode 100644 test/test_suite7/enumerations/enum_values.c3t create mode 100644 test/test_suite7/enumerations/enum_with_associated_value_decl.c3 create mode 100644 test/test_suite7/enumerations/enum_with_const.c3t create mode 100644 test/test_suite7/enumerations/inc_assign.c3t create mode 100644 test/test_suite7/enumerations/inc_assign_fail.c3 create mode 100644 test/test_suite7/enumerations/inline_enum_size.c3 create mode 100644 test/test_suite7/enumerations/inline_enums.c3t create mode 100644 test/test_suite7/enumerations/introspection_data_error.c3t create mode 100644 test/test_suite7/enumerations/missing_type.c3 create mode 100644 test/test_suite7/enumerations/simple_inference.c3t create mode 100644 test/test_suite7/enumerations/too_many_associated.c3 create mode 100644 test/test_suite7/errors/anyfault_void.c3t create mode 100644 test/test_suite7/errors/bitshift_failable.c3 create mode 100644 test/test_suite7/errors/else_checks.c3t create mode 100644 test/test_suite7/errors/else_struct.c3t create mode 100644 test/test_suite7/errors/else_unreachable.c3t create mode 100644 test/test_suite7/errors/else_unreachable_in_block.c3 create mode 100644 test/test_suite7/errors/empty_fault.c3 create mode 100644 test/test_suite7/errors/error_decl_ok.c3 create mode 100644 test/test_suite7/errors/error_else.c3t create mode 100644 test/test_suite7/errors/error_introspect.c3t create mode 100644 test/test_suite7/errors/error_regression_2.c3t create mode 100644 test/test_suite7/errors/error_semantic_fails.c3 create mode 100644 test/test_suite7/errors/error_throw.c3 create mode 100644 test/test_suite7/errors/error_union.c3 create mode 100644 test/test_suite7/errors/failable_catch.c3t create mode 100644 test/test_suite7/errors/fault_conv.c3t create mode 100644 test/test_suite7/errors/general_error_regression.c3t create mode 100644 test/test_suite7/errors/illegal_use_of_optional.c3 create mode 100644 test/test_suite7/errors/invalid_cast_ct.c3 create mode 100644 test/test_suite7/errors/lone_try.c3 create mode 100644 test/test_suite7/errors/macro_err.c3t create mode 100644 test/test_suite7/errors/macro_err2.c3t create mode 100644 test/test_suite7/errors/macro_err3.c3t create mode 100644 test/test_suite7/errors/macro_recurse_twice.c3 create mode 100644 test/test_suite7/errors/missing_bang.c3 create mode 100644 test/test_suite7/errors/mixed_decl.c3 create mode 100644 test/test_suite7/errors/more_optional_discard.c3 create mode 100644 test/test_suite7/errors/more_optional_tests.c3 create mode 100644 test/test_suite7/errors/multiple_catch.c3t create mode 100644 test/test_suite7/errors/no_common.c3 create mode 100644 test/test_suite7/errors/optional_chained_init.c3t create mode 100644 test/test_suite7/errors/optional_contracts.c3 create mode 100644 test/test_suite7/errors/optional_designated.c3 create mode 100644 test/test_suite7/errors/optional_discarded_func.c3 create mode 100644 test/test_suite7/errors/optional_discarded_macro.c3 create mode 100644 test/test_suite7/errors/optional_inits.c3t create mode 100644 test/test_suite7/errors/optional_sizeof.c3 create mode 100644 test/test_suite7/errors/optional_taddr_and_access.c3t create mode 100644 test/test_suite7/errors/optional_untyped_list.c3 create mode 100644 test/test_suite7/errors/optional_with_optional.c3t create mode 100644 test/test_suite7/errors/or_and_rethrow.c3t create mode 100644 test/test_suite7/errors/or_err_bool.c3t create mode 100644 test/test_suite7/errors/or_err_infer.c3t create mode 100644 test/test_suite7/errors/precedence_err.c3 create mode 100644 test/test_suite7/errors/printing_errors.c3t create mode 100644 test/test_suite7/errors/rethrow.c3t create mode 100644 test/test_suite7/errors/rethrow_macro.c3 create mode 100644 test/test_suite7/errors/rethrow_mingw.c3t create mode 100644 test/test_suite7/errors/rethrow_no_err.c3 create mode 100644 test/test_suite7/errors/simple_static_failable.c3t create mode 100644 test/test_suite7/errors/switch_default_catch.c3 create mode 100644 test/test_suite7/errors/ternary_void_fault.c3t create mode 100644 test/test_suite7/errors/try_assign.c3t create mode 100644 test/test_suite7/errors/try_catch_if.c3t create mode 100644 test/test_suite7/errors/try_catch_unwrapping_while_if.c3 create mode 100644 test/test_suite7/errors/try_expr.c3t create mode 100644 test/test_suite7/errors/try_unwrap_using_assert.c3 create mode 100644 test/test_suite7/errors/try_with_assign_to_failable.c3 create mode 100644 test/test_suite7/errors/try_with_chained_unwrap.c3t create mode 100644 test/test_suite7/errors/try_with_chained_unwrap_errors.c3 create mode 100644 test/test_suite7/errors/try_with_unwrap.c3t create mode 100644 test/test_suite7/errors/try_with_unwrapper.c3t create mode 100644 test/test_suite7/errors/try_with_weird_stuff.c3 create mode 100644 test/test_suite7/errors/type_optional_declaration_order.c3 create mode 100644 test/test_suite7/examples/gameoflife.c3 create mode 100644 test/test_suite7/expression_block/expr_block_labelled_break.c3 create mode 100644 test/test_suite7/expression_block/expr_block_no_assign.c3 create mode 100644 test/test_suite7/expression_block/expression_block_break.c3 create mode 100644 test/test_suite7/expression_block/expression_block_no_end_return.c3 create mode 100644 test/test_suite7/expressions/2002-02-13-ConditionalInCall.c3t create mode 100644 test/test_suite7/expressions/addr_compiles.c3t create mode 100644 test/test_suite7/expressions/addr_of_fails.c3 create mode 100644 test/test_suite7/expressions/arithmetics.c3 create mode 100644 test/test_suite7/expressions/arithmetics_sema_fail.c3 create mode 100644 test/test_suite7/expressions/assign.c3 create mode 100644 test/test_suite7/expressions/assign_deref_opt.c3 create mode 100644 test/test_suite7/expressions/assign_optional.c3t create mode 100644 test/test_suite7/expressions/assign_to_address.c3 create mode 100644 test/test_suite7/expressions/assignability.c3 create mode 100644 test/test_suite7/expressions/assignment_precedence.c3t create mode 100644 test/test_suite7/expressions/bit_op_on_bool.c3t create mode 100644 test/test_suite7/expressions/bool_conversions.c3t create mode 100644 test/test_suite7/expressions/call_arg_types.c3 create mode 100644 test/test_suite7/expressions/call_inline.c3t create mode 100644 test/test_suite7/expressions/casts/cast_const.c3 create mode 100644 test/test_suite7/expressions/casts/cast_enum_const_to_distinct.c3 create mode 100644 test/test_suite7/expressions/casts/cast_enum_to_various.c3 create mode 100644 test/test_suite7/expressions/casts/cast_expr.c3t create mode 100644 test/test_suite7/expressions/casts/cast_failable.c3 create mode 100644 test/test_suite7/expressions/casts/cast_func_to_various.c3 create mode 100644 test/test_suite7/expressions/casts/cast_implicit_inline_distinct.c3 create mode 100644 test/test_suite7/expressions/casts/cast_to_nonscalar.c3 create mode 100644 test/test_suite7/expressions/casts/cast_unknown.c3 create mode 100644 test/test_suite7/expressions/casts/cast_vector_fail.c3 create mode 100644 test/test_suite7/expressions/casts/enum_plus_minus.c3t create mode 100644 test/test_suite7/expressions/casts/explicit_cast.c3 create mode 100644 test/test_suite7/expressions/casts/failed_distinct_float_conversions.c3 create mode 100644 test/test_suite7/expressions/casts/narrowing.c3 create mode 100644 test/test_suite7/expressions/casts/narrowing_through_casts.c3 create mode 100644 test/test_suite7/expressions/casts/struct_cast_and_distinct.c3 create mode 100644 test/test_suite7/expressions/casts/void_casting.c3t create mode 100644 test/test_suite7/expressions/chained_conditional.c3t create mode 100644 test/test_suite7/expressions/chained_ternary.c3t create mode 100644 test/test_suite7/expressions/check_implict_conversion_signed_unsigned.c3t create mode 100644 test/test_suite7/expressions/deref_access_null.c3t create mode 100644 test/test_suite7/expressions/deref_const_string.c3t create mode 100644 test/test_suite7/expressions/elvis.c3t create mode 100644 test/test_suite7/expressions/enum_ct_sub.c3t create mode 100644 test/test_suite7/expressions/fail_index_usize.c3 create mode 100644 test/test_suite7/expressions/fmuladd.c3t create mode 100644 test/test_suite7/expressions/fmuladd_err.c3t create mode 100644 test/test_suite7/expressions/folding_ptr.c3t create mode 100644 test/test_suite7/expressions/incdec.c3t create mode 100644 test/test_suite7/expressions/incdec_overload.c3t create mode 100644 test/test_suite7/expressions/negate_int.c3 create mode 100644 test/test_suite7/expressions/negated_macro.c3t create mode 100644 test/test_suite7/expressions/no_valid_conversion_minus.c3 create mode 100644 test/test_suite7/expressions/not_in_wrong_position.c3 create mode 100644 test/test_suite7/expressions/opt_in_conv.c3 create mode 100644 test/test_suite7/expressions/optional_and_error.c3 create mode 100644 test/test_suite7/expressions/optional_ternary.c3t create mode 100644 test/test_suite7/expressions/parsed_numbers.c3t create mode 100644 test/test_suite7/expressions/plus_int.c3 create mode 100644 test/test_suite7/expressions/pointer_access.c3t create mode 100644 test/test_suite7/expressions/pointer_arith.c3 create mode 100644 test/test_suite7/expressions/pointer_conv_error.c3 create mode 100644 test/test_suite7/expressions/pointer_to_bool.c3 create mode 100644 test/test_suite7/expressions/rvalues.c3 create mode 100644 test/test_suite7/expressions/simple_float_sub_neg.c3t create mode 100644 test/test_suite7/expressions/strings.c3t create mode 100644 test/test_suite7/expressions/take_address.c3t create mode 100644 test/test_suite7/expressions/ternary_bool.c3t create mode 100644 test/test_suite7/expressions/ternary_infer.c3t create mode 100644 test/test_suite7/expressions/ternary_no_ident.c3 create mode 100644 test/test_suite7/expressions/ternary_void.c3t create mode 100644 test/test_suite7/expressions/test_ct_param_bug.c3 create mode 100644 test/test_suite7/expressions/type_support.c3t create mode 100644 test/test_suite7/expressions/underscore_errors.c3 create mode 100644 test/test_suite7/expressions/unsafe_comparisons.c3 create mode 100644 test/test_suite7/expressions/void_arg.c3 create mode 100644 test/test_suite7/floats/convert_float.c3t create mode 100644 test/test_suite7/floats/explicit_float_truncation_needed.c3 create mode 100644 test/test_suite7/floats/float_exceeding_size.c3 create mode 100644 test/test_suite7/floats/inf_nan.c3t create mode 100644 test/test_suite7/floats/mod.c3t create mode 100644 test/test_suite7/from_docs/examples_defer.c3t create mode 100644 test/test_suite7/from_docs/examples_forswitch.c3t create mode 100644 test/test_suite7/from_docs/examples_functionpointer.c3t create mode 100644 test/test_suite7/from_docs/examples_if_catch.c3t create mode 100644 test/test_suite7/from_docs/examples_macro_function.c3t create mode 100644 test/test_suite7/from_docs/examples_struct.c3 create mode 100644 test/test_suite7/functions/accidental_method_1448.c3 create mode 100644 test/test_suite7/functions/after_vararg.c3 create mode 100644 test/test_suite7/functions/assorted_tests.c3t create mode 100644 test/test_suite7/functions/body_argument_fail.c3 create mode 100644 test/test_suite7/functions/c_vararg_expansion.c3t create mode 100644 test/test_suite7/functions/call_conv_fntype.c3 create mode 100644 test/test_suite7/functions/ct_named_params.c3t create mode 100644 test/test_suite7/functions/default_param_fail.c3 create mode 100644 test/test_suite7/functions/defered_default_arguments.c3t create mode 100644 test/test_suite7/functions/distinct_fn_ptr_and_lambda.c3t create mode 100644 test/test_suite7/functions/double_return.c3 create mode 100644 test/test_suite7/functions/failable_param.c3 create mode 100644 test/test_suite7/functions/func_ptr_conversion_alias.c3t create mode 100644 test/test_suite7/functions/func_ptr_conversions_and_names.c3t create mode 100644 test/test_suite7/functions/func_ptr_null.check.c3t create mode 100644 test/test_suite7/functions/function_alias_llvm_check.c3t create mode 100644 test/test_suite7/functions/function_reserved_name.c3 create mode 100644 test/test_suite7/functions/invalid_param.c3 create mode 100644 test/test_suite7/functions/macro_arguments.c3 create mode 100644 test/test_suite7/functions/macro_expr_type.c3 create mode 100644 test/test_suite7/functions/missing_first_paren.c3 create mode 100644 test/test_suite7/functions/missing_fn.c3 create mode 100644 test/test_suite7/functions/missing_return.c3 create mode 100644 test/test_suite7/functions/missing_return_lambda.c3 create mode 100644 test/test_suite7/functions/multisplat.c3t create mode 100644 test/test_suite7/functions/naked_function.c3t create mode 100644 test/test_suite7/functions/named_arg_order.c3 create mode 100644 test/test_suite7/functions/param_doc_error.c3 create mode 100644 test/test_suite7/functions/param_with_comma_at_end.c3 create mode 100644 test/test_suite7/functions/pointer_escape.c3 create mode 100644 test/test_suite7/functions/raw_splat.c3t create mode 100644 test/test_suite7/functions/recursive_fn.c3 create mode 100644 test/test_suite7/functions/recursive_through_generic.c3 create mode 100644 test/test_suite7/functions/returning_void.c3t create mode 100644 test/test_suite7/functions/simple_test.c3t create mode 100644 test/test_suite7/functions/splat.c3t create mode 100644 test/test_suite7/functions/splat_aarch64.c3t create mode 100644 test/test_suite7/functions/splat_empty.c3t create mode 100644 test/test_suite7/functions/splat_init.c3t create mode 100644 test/test_suite7/functions/splat_mingw.c3t create mode 100644 test/test_suite7/functions/splat_post_order.c3t create mode 100644 test/test_suite7/functions/splat_raw.c3 create mode 100644 test/test_suite7/functions/splat_untyped.c3t create mode 100644 test/test_suite7/functions/static_vars.c3t create mode 100644 test/test_suite7/functions/test_regression.c3t create mode 100644 test/test_suite7/functions/test_regression_mingw.c3t create mode 100644 test/test_suite7/functions/too_many_params.c3 create mode 100644 test/test_suite7/functions/type_argument_live_1461.c3t create mode 100644 test/test_suite7/functions/typeless_varargs.c3t create mode 100644 test/test_suite7/functions/unsplat_named.c3 create mode 100644 test/test_suite7/functions/vaarg_raw.c3 create mode 100644 test/test_suite7/functions/vararg_and_named_tests.c3 create mode 100644 test/test_suite7/functions/vararg_argument_fails.c3 create mode 100644 test/test_suite7/functions/varargs.c3t create mode 100644 test/test_suite7/functions/varargs_followed_by_named.c3t create mode 100644 test/test_suite7/functions/void_params.c3 create mode 100644 test/test_suite7/generic/different_generic_def.c3 create mode 100644 test/test_suite7/generic/enum_in_other_module.c3t create mode 100644 test/test_suite7/generic/enum_set_test.c3t create mode 100644 test/test_suite7/generic/generic_builtin.c3t create mode 100644 test/test_suite7/generic/generic_copy.c3t create mode 100644 test/test_suite7/generic/generic_cyclic.c3 create mode 100644 test/test_suite7/generic/generic_idents.c3t create mode 100644 test/test_suite7/generic/generic_interface.c3t create mode 100644 test/test_suite7/generic/generic_lambda_complex.c3t create mode 100644 test/test_suite7/generic/generic_local.c3 create mode 100644 test/test_suite7/generic/generic_num.c3t create mode 100644 test/test_suite7/generic/generic_over_fn.c3t create mode 100644 test/test_suite7/generic/generic_parsing.c3 create mode 100644 test/test_suite7/generic/generic_recursion.c3t create mode 100644 test/test_suite7/generic/generic_resolution_1402.c3t create mode 100644 test/test_suite7/generic/generic_void.c3t create mode 100644 test/test_suite7/generic/generic_with_comment.c3t create mode 100644 test/test_suite7/generic/generic_with_enum.c3t create mode 100644 test/test_suite7/generic/generic_without_param.c3 create mode 100644 test/test_suite7/generic/implicit_import_of_generic.c3 create mode 100644 test/test_suite7/generic/incorrect_argument_type.c3 create mode 100644 test/test_suite7/generic/nested_typedef.c3t create mode 100644 test/test_suite7/generic/used_without_param.c3 create mode 100644 test/test_suite7/generic/used_without_param2.c3 create mode 100644 test/test_suite7/generic/used_without_param3.c3 create mode 100644 test/test_suite7/globals/ext_global_init.c3 create mode 100644 test/test_suite7/globals/extern_const.c3t create mode 100644 test/test_suite7/globals/external_global.c3t create mode 100644 test/test_suite7/globals/global_align.c3t create mode 100644 test/test_suite7/globals/global_extname.c3t create mode 100644 test/test_suite7/globals/global_init.c3 create mode 100644 test/test_suite7/globals/global_no_init.c3t create mode 100644 test/test_suite7/globals/init_with_err.c3t create mode 100644 test/test_suite7/globals/misplaced_const.c3 create mode 100644 test/test_suite7/globals/recursive_globals.c3 create mode 100644 test/test_suite7/globals/recursive_locals.c3 create mode 100644 test/test_suite7/globals/self_referencing_local.c3 create mode 100644 test/test_suite7/globals/static_global.c3 create mode 100644 test/test_suite7/import/access_other_module.c3t create mode 100644 test/test_suite7/import/autoimport.c3 create mode 100644 test/test_suite7/import/import_error.c3 create mode 100644 test/test_suite7/import/import_error_multi.c3 create mode 100644 test/test_suite7/import/import_error_string.c3 create mode 100644 test/test_suite7/import/import_implicit.c3 create mode 100644 test/test_suite7/import/import_nonrecurse.c3 create mode 100644 test/test_suite7/import/import_same.c3 create mode 100644 test/test_suite7/import/import_twice.c3 create mode 100644 test/test_suite7/import/import_works.c3t create mode 100644 test/test_suite7/initialize/init_non_resolved_type.c3 create mode 100644 test/test_suite7/initialize/initialize_bad_prio.c3 create mode 100644 test/test_suite7/initialize/initialize_finalize.c3t create mode 100644 test/test_suite7/initialize/initialize_jump.c3 create mode 100644 test/test_suite7/initialize/initialize_parse_error.c3 create mode 100644 test/test_suite7/initialize/initialize_prio.c3 create mode 100644 test/test_suite7/initialize/initializer_access.c3 create mode 100644 test/test_suite7/initialize/initializer_var.c3t create mode 100644 test/test_suite7/initializer_lists/disallowed_lists.c3 create mode 100644 test/test_suite7/initializer_lists/fasta.c3t create mode 100644 test/test_suite7/initializer_lists/general_tests.c3t create mode 100644 test/test_suite7/initializer_lists/indexing_into_complist.c3 create mode 100644 test/test_suite7/initializer_lists/infer_with_init.c3t create mode 100644 test/test_suite7/initializer_lists/init_any_interface.c3 create mode 100644 test/test_suite7/initializer_lists/initializers_to_macros.c3 create mode 100644 test/test_suite7/initializer_lists/ranges_to_dynamic.c3t create mode 100644 test/test_suite7/initializer_lists/statics.c3t create mode 100644 test/test_suite7/initializer_lists/subarrays.c3t create mode 100644 test/test_suite7/initializer_lists/zero_inferred_array.c3 create mode 100644 test/test_suite7/initializer_lists/zero_init.c3t create mode 100644 test/test_suite7/lambda/ct_lambda.c3t create mode 100644 test/test_suite7/lambda/ct_lambda2.c3t create mode 100644 test/test_suite7/lambda/lambda_checks.c3 create mode 100644 test/test_suite7/lambda/lambda_in_macro.c3t create mode 100644 test/test_suite7/lambda/lambda_ref.c3t create mode 100644 test/test_suite7/lambda/nested_lambda_def.c3t create mode 100644 test/test_suite7/lambda/simple_lambda.c3t create mode 100644 test/test_suite7/lambda/var_lambda.c3 create mode 100644 test/test_suite7/lexing/expected_directive.c3 create mode 100644 test/test_suite7/lexing/invalid_hex_in_hexarray.c3 create mode 100644 test/test_suite7/lexing/invalid_hex_in_hexarray2.c3 create mode 100644 test/test_suite7/lexing/no_builtin.c3 create mode 100644 test/test_suite7/literals/bad_bitwidth.c3 create mode 100644 test/test_suite7/literals/bin_literal.c3t create mode 100644 test/test_suite7/literals/bin_literal2.c3t create mode 100644 test/test_suite7/literals/literal_general.c3t create mode 100644 test/test_suite7/literals/multi_unicode.c3 create mode 100644 test/test_suite7/literals/radix_numbers_errors.c3 create mode 100644 test/test_suite7/literals/too_small.c3 create mode 100644 test/test_suite7/macro_methods/access.c3 create mode 100644 test/test_suite7/macro_methods/macro_method_different_args.c3t create mode 100644 test/test_suite7/macro_methods/macro_method_fails.c3 create mode 100644 test/test_suite7/macro_methods/macro_method_first_param.c3 create mode 100644 test/test_suite7/macro_methods/macro_methods_defined_twice.c3 create mode 100644 test/test_suite7/macro_methods/macro_methods_no_args.c3 create mode 100644 test/test_suite7/macros/hash_ident.c3 create mode 100644 test/test_suite7/macros/hash_ident_nested.c3t create mode 100644 test/test_suite7/macros/hash_initializer.c3t create mode 100644 test/test_suite7/macros/implicit_return_opt.c3 create mode 100644 test/test_suite7/macros/macro_always_const.c3 create mode 100644 test/test_suite7/macros/macro_body_as_value.c3 create mode 100644 test/test_suite7/macros/macro_body_defer.c3t create mode 100644 test/test_suite7/macros/macro_body_errors.c3 create mode 100644 test/test_suite7/macros/macro_body_missing_type.c3 create mode 100644 test/test_suite7/macros/macro_body_ref_hash_constant_type.c3t create mode 100644 test/test_suite7/macros/macro_calls_prefix.c3 create mode 100644 test/test_suite7/macros/macro_chained_return_void_optional.c3t create mode 100644 test/test_suite7/macros/macro_common.c3t create mode 100644 test/test_suite7/macros/macro_convert_literal.c3 create mode 100644 test/test_suite7/macros/macro_defer_exit.c3t create mode 100644 test/test_suite7/macros/macro_defer_scope.c3t create mode 100644 test/test_suite7/macros/macro_defer_with_body.c3t create mode 100644 test/test_suite7/macros/macro_failable_return_rethrow.c3t create mode 100644 test/test_suite7/macros/macro_import_res_private.c3t create mode 100644 test/test_suite7/macros/macro_import_resolution.c3 create mode 100644 test/test_suite7/macros/macro_nested_labels.c3t create mode 100644 test/test_suite7/macros/macro_ref_body_err1.c3 create mode 100644 test/test_suite7/macros/macro_ref_body_err2.c3 create mode 100644 test/test_suite7/macros/macro_resolution.c3 create mode 100644 test/test_suite7/macros/macro_rtype.c3 create mode 100644 test/test_suite7/macros/macro_tagof.c3t create mode 100644 test/test_suite7/macros/macro_typed_varargs.c3t create mode 100644 test/test_suite7/macros/macro_untyped_varargs.c3 create mode 100644 test/test_suite7/macros/macro_untyped_varargs_2.c3t create mode 100644 test/test_suite7/macros/macro_vasplat.c3t create mode 100644 test/test_suite7/macros/macro_with_body.c3t create mode 100644 test/test_suite7/macros/macro_with_body_err.c3 create mode 100644 test/test_suite7/macros/modify_ct_param.c3 create mode 100644 test/test_suite7/macros/no_body.c3 create mode 100644 test/test_suite7/macros/ref_macro_method.c3 create mode 100644 test/test_suite7/macros/ref_vector.c3t create mode 100644 test/test_suite7/macros/short_trailing_body.c3t create mode 100644 test/test_suite7/macros/trailing_body_const.c3t create mode 100644 test/test_suite7/macros/trailing_body_type.c3 create mode 100644 test/test_suite7/macros/type_params.c3t create mode 100644 test/test_suite7/macros/typed_hash_access.c3 create mode 100644 test/test_suite7/macros/unifying_implicit_void.c3t create mode 100644 test/test_suite7/macros/userland_bitcast.c3t create mode 100644 test/test_suite7/macros/vasplat_function_call.c3 create mode 100644 test/test_suite7/methods/access.c3 create mode 100644 test/test_suite7/methods/access_private_method.c3 create mode 100644 test/test_suite7/methods/dynamic_method_fails.c3 create mode 100644 test/test_suite7/methods/enum_distinct_err_methods.c3t create mode 100644 test/test_suite7/methods/extending_with_visibility.c3 create mode 100644 test/test_suite7/methods/extending_with_visibility_fail.c3 create mode 100644 test/test_suite7/methods/extending_with_visibility_fail_private.c3 create mode 100644 test/test_suite7/methods/extension_method.c3t create mode 100644 test/test_suite7/methods/extension_method_already_exist.c3 create mode 100644 test/test_suite7/methods/extension_method_check.c3 create mode 100644 test/test_suite7/methods/extension_method_generic.c3 create mode 100644 test/test_suite7/methods/extension_method_in_other_modules.c3t create mode 100644 test/test_suite7/methods/method_extension_in_conditional_module.c3 create mode 100644 test/test_suite7/methods/method_from_var.c3 create mode 100644 test/test_suite7/methods/method_name_collision.c3 create mode 100644 test/test_suite7/methods/method_ref_for_extension_method.c3 create mode 100644 test/test_suite7/methods/methods_defined_twice.c3 create mode 100644 test/test_suite7/methods/methods_with_inferred_type.c3t create mode 100644 test/test_suite7/methods/operator_assign_mutate.c3t create mode 100644 test/test_suite7/methods/operator_defined_twice.c3 create mode 100644 test/test_suite7/methods/operator_inc.c3t create mode 100644 test/test_suite7/methods/operator_mismatch.c3 create mode 100644 test/test_suite7/methods/self_methods_null.c3t create mode 100755 test/test_suite7/methods/unsupported_operator.c3 create mode 100644 test/test_suite7/module/missing_semi.c3 create mode 100644 test/test_suite7/module/module_bad_path_ident.c3 create mode 100644 test/test_suite7/module/module_bad_path_invalid.c3 create mode 100644 test/test_suite7/module/module_bad_path_keyword.c3 create mode 100644 test/test_suite7/module/module_error_string.c3 create mode 100644 test/test_suite7/module/module_generic_mixing.c3 create mode 100644 test/test_suite7/module/module_section_export.c3t create mode 100644 test/test_suite7/module/module_start_bad_ident.c3 create mode 100644 test/test_suite7/module/module_start_invalid.c3 create mode 100644 test/test_suite7/module/module_start_keyword.c3 create mode 100644 test/test_suite7/module/private_module.c3 create mode 100644 test/test_suite7/module/unknown_modules.c3 create mode 100644 test/test_suite7/overloading/construct_op_zero_args.c3 create mode 100644 test/test_suite7/overloading/construct_operator.c3t create mode 100644 test/test_suite7/overloading/set_not_set_overload.c3t create mode 100644 test/test_suite7/overloading/set_overload.c3t create mode 100644 test/test_suite7/pointers/array_pointer_decay.c3t create mode 100644 test/test_suite7/pointers/const_pointer.c3t create mode 100644 test/test_suite7/pointers/const_ref.c3t create mode 100644 test/test_suite7/pointers/pointer_index.c3t create mode 100644 test/test_suite7/pointers/subarray_variant_to_ptr.c3t create mode 100644 test/test_suite7/precedence/required_parens.c3 create mode 100644 test/test_suite7/regression/crash_on_right_paren_macro.c3 create mode 100644 test/test_suite7/safe/deref.c3t create mode 100644 test/test_suite7/safe/detect_invalid_deref_return.c3 create mode 100644 test/test_suite7/slices/array_to_const_err.c3 create mode 100644 test/test_suite7/slices/array_to_const_slice.c3t create mode 100644 test/test_suite7/slices/slice_assign.c3t create mode 100644 test/test_suite7/slices/slice_assign2.c3t create mode 100644 test/test_suite7/slices/slice_checks.c3t create mode 100644 test/test_suite7/slices/slice_comparison.c3t create mode 100644 test/test_suite7/slices/slice_conv_byte.c3t create mode 100644 test/test_suite7/slices/slice_init.c3t create mode 100644 test/test_suite7/slices/slice_inline.c3t create mode 100644 test/test_suite7/slices/slice_len_error.c3 create mode 100644 test/test_suite7/slices/slice_negative_len.c3 create mode 100644 test/test_suite7/slices/slice_offset.c3t create mode 100644 test/test_suite7/slices/slice_offset_neg_end.c3t create mode 100644 test/test_suite7/slices/slice_offset_neg_start.c3t create mode 100644 test/test_suite7/slices/slice_optional.c3t create mode 100644 test/test_suite7/slices/slice_optional_index.c3t create mode 100644 test/test_suite7/slices/slice_start.c3t create mode 100644 test/test_suite7/slices/slice_syntax.c3 create mode 100644 test/test_suite7/slices/slice_to_slice_assign.c3t create mode 100644 test/test_suite7/slices/slice_to_slice_conv_err.c3t create mode 100644 test/test_suite7/slices/slice_to_slice_vector_assign.c3t create mode 100644 test/test_suite7/slices/sub_array_init.c3 create mode 100644 test/test_suite7/slices/subscript_check_1519.c3t create mode 100644 test/test_suite7/slices/various_const_slicing.c3t create mode 100644 test/test_suite7/statements/binary_fail.c3 create mode 100644 test/test_suite7/statements/call_missing_paren.c3 create mode 100644 test/test_suite7/statements/comparison_widening.c3t create mode 100644 test/test_suite7/statements/conditional_return.c3 create mode 100644 test/test_suite7/statements/const_statements.c3t create mode 100644 test/test_suite7/statements/custom_foreach_with_ref.c3t create mode 100644 test/test_suite7/statements/dead_statements.c3t create mode 100644 test/test_suite7/statements/default_args.c3 create mode 100644 test/test_suite7/statements/default_macro_argc.c3t create mode 100644 test/test_suite7/statements/defer_break.c3t create mode 100644 test/test_suite7/statements/defer_break_simple.c3t create mode 100644 test/test_suite7/statements/defer_break_switch.c3t create mode 100644 test/test_suite7/statements/defer_continue_bug.c3t create mode 100644 test/test_suite7/statements/defer_do_while.c3t create mode 100644 test/test_suite7/statements/defer_hash.c3t create mode 100644 test/test_suite7/statements/defer_if_try_copy.c3t create mode 100644 test/test_suite7/statements/defer_in_block.c3t create mode 100644 test/test_suite7/statements/defer_in_defer.c3t create mode 100644 test/test_suite7/statements/defer_in_defer2.c3t create mode 100644 test/test_suite7/statements/defer_in_defer3.c3t create mode 100644 test/test_suite7/statements/defer_next_switch.c3t create mode 100644 test/test_suite7/statements/defer_return.c3t create mode 100644 test/test_suite7/statements/defer_test.c3 create mode 100644 test/test_suite7/statements/defer_with_loop.c3t create mode 100644 test/test_suite7/statements/do_without_compound.c3 create mode 100644 test/test_suite7/statements/exhaustive_switch.c3t create mode 100644 test/test_suite7/statements/fallthough_do.c3t create mode 100644 test/test_suite7/statements/for.c3 create mode 100644 test/test_suite7/statements/for_empty.c3 create mode 100644 test/test_suite7/statements/for_errors.c3 create mode 100644 test/test_suite7/statements/for_statement_placement.c3 create mode 100644 test/test_suite7/statements/for_with_extra_declarations.c3 create mode 100644 test/test_suite7/statements/for_with_optional.c3t create mode 100644 test/test_suite7/statements/foreach_break.c3t create mode 100644 test/test_suite7/statements/foreach_common.c3t create mode 100644 test/test_suite7/statements/foreach_custom.c3t create mode 100644 test/test_suite7/statements/foreach_custom_errors.c3 create mode 100644 test/test_suite7/statements/foreach_custom_macro.c3t create mode 100644 test/test_suite7/statements/foreach_distinct_iterable.c3t create mode 100644 test/test_suite7/statements/foreach_distinct_pointer_1506.c3 create mode 100644 test/test_suite7/statements/foreach_errors.c3 create mode 100644 test/test_suite7/statements/foreach_more_implementations.c3t create mode 100644 test/test_suite7/statements/foreach_parse_error.c3 create mode 100644 test/test_suite7/statements/foreach_r_break.c3t create mode 100644 test/test_suite7/statements/foreach_r_common.c3t create mode 100644 test/test_suite7/statements/foreach_r_custom.c3t create mode 100644 test/test_suite7/statements/foreach_r_custom_errors.c3 create mode 100644 test/test_suite7/statements/foreach_r_custom_macro.c3t create mode 100644 test/test_suite7/statements/foreach_r_errors.c3 create mode 100644 test/test_suite7/statements/foreach_r_parse_error.c3 create mode 100644 test/test_suite7/statements/foreach_r_with_error.c3 create mode 100644 test/test_suite7/statements/foreach_with_error.c3 create mode 100644 test/test_suite7/statements/foreach_wrong_index.c3 create mode 100644 test/test_suite7/statements/if_decl.c3 create mode 100644 test/test_suite7/statements/if_only_throw.c3t create mode 100644 test/test_suite7/statements/if_single.c3 create mode 100644 test/test_suite7/statements/if_tests.c3t create mode 100644 test/test_suite7/statements/if_while_do_error.c3 create mode 100644 test/test_suite7/statements/infinite_do_while.c3t create mode 100644 test/test_suite7/statements/label_errors.c3 create mode 100644 test/test_suite7/statements/labelled_continue_for.c3t create mode 100644 test/test_suite7/statements/nextcase_const.c3t create mode 100644 test/test_suite7/statements/nextcase_default.c3t create mode 100644 test/test_suite7/statements/nextcase_missing_case.c3 create mode 100644 test/test_suite7/statements/nextcase_no_switch.c3 create mode 100644 test/test_suite7/statements/ranged_switch.c3t create mode 100644 test/test_suite7/statements/return_stmt.c3 create mode 100644 test/test_suite7/statements/return_switch.c3t create mode 100644 test/test_suite7/statements/return_with_other_at_end.c3 create mode 100644 test/test_suite7/statements/simple_do.c3t create mode 100644 test/test_suite7/statements/switch_error_fallthrough.c3 create mode 100644 test/test_suite7/statements/switch_error_range.c3 create mode 100644 test/test_suite7/statements/switch_errors.c3 create mode 100644 test/test_suite7/statements/various_switching.c3t create mode 100644 test/test_suite7/statements/while_statement_placement.c3 create mode 100644 test/test_suite7/statements/while_statement_placement2.c3 create mode 100644 test/test_suite7/statements/while_switch.c3t create mode 100644 test/test_suite7/stdlib/ascii.c3 create mode 100644 test/test_suite7/stdlib/map_linux.c3t create mode 100644 test/test_suite7/stdlib/map_macos.c3t create mode 100644 test/test_suite7/stdlib/memcomp.c3t create mode 100644 test/test_suite7/stdlib/minmax.c3 create mode 100644 test/test_suite7/stdlib/print_env_defines.c3 create mode 100644 test/test_suite7/stdlib/priorityqueue.c3t create mode 100644 test/test_suite7/strings/literal_errors.c3 create mode 100644 test/test_suite7/strings/literal_hex_ok.c3 create mode 100644 test/test_suite7/strings/literal_to_subarray.c3t create mode 100644 test/test_suite7/strings/multiline_strings.c3t create mode 100644 test/test_suite7/strings/string_escape.c3t create mode 100644 test/test_suite7/strings/string_len.c3t create mode 100644 test/test_suite7/strings/string_to_array.c3t create mode 100644 test/test_suite7/struct/const_access_error.c3 create mode 100644 test/test_suite7/struct/const_slice_struct.c3t create mode 100644 test/test_suite7/struct/const_zero_init_1360.c3t create mode 100644 test/test_suite7/struct/duplicate_member.c3 create mode 100644 test/test_suite7/struct/flex_array_comparison.c3 create mode 100644 test/test_suite7/struct/flex_array_struct_err.c3 create mode 100644 test/test_suite7/struct/flexible_array_resolve.c3 create mode 100644 test/test_suite7/struct/func_return_struct.c3 create mode 100644 test/test_suite7/struct/init_cont_struct_array_locally.c3t create mode 100644 test/test_suite7/struct/initialize_inline_designated.c3t create mode 100644 test/test_suite7/struct/inline_array_access.c3t create mode 100644 test/test_suite7/struct/inner_struct_name.c3 create mode 100644 test/test_suite7/struct/member_access.c3 create mode 100644 test/test_suite7/struct/member_expr.c3 create mode 100644 test/test_suite7/struct/multi_member_attributes.c3t create mode 100644 test/test_suite7/struct/nested_struct_init.c3t create mode 100644 test/test_suite7/struct/nested_struct_union_init.c3t create mode 100644 test/test_suite7/struct/recursive_structs.c3 create mode 100644 test/test_suite7/struct/simple_struct.c3t create mode 100644 test/test_suite7/struct/sret.c3t create mode 100644 test/test_suite7/struct/struct_as_value.c3t create mode 100644 test/test_suite7/struct/struct_as_value_aarch64.c3t create mode 100644 test/test_suite7/struct/struct_bad_member.c3 create mode 100644 test/test_suite7/struct/struct_codegen.c3t create mode 100644 test/test_suite7/struct/struct_codegen_empty.c3t create mode 100644 test/test_suite7/struct/struct_codegen_fam.c3t create mode 100644 test/test_suite7/struct/struct_comma.c3 create mode 100644 test/test_suite7/struct/struct_const_construct_simple.c3t create mode 100644 test/test_suite7/struct/struct_nopadding_compact.c3t create mode 100644 test/test_suite7/struct/struct_pack_and_align.c3t create mode 100644 test/test_suite7/struct/struct_pack_error.c3t create mode 100644 test/test_suite7/struct/struct_params.c3 create mode 100644 test/test_suite7/struct/struct_reinit.c3t create mode 100644 test/test_suite7/struct/struct_union_inner_align.c3t create mode 100644 test/test_suite7/struct/zero_member.c3 create mode 100644 test/test_suite7/switch/bad_ranges.c3 create mode 100644 test/test_suite7/switch/enum_jump_switch_and_range.c3t create mode 100644 test/test_suite7/switch/failable_switch.c3 create mode 100644 test/test_suite7/switch/jump_bug_nested.c3t create mode 100644 test/test_suite7/switch/jump_bugs.c3t create mode 100644 test/test_suite7/switch/jump_with_inc.c3t create mode 100644 test/test_suite7/switch/simple_jump.c3t create mode 100644 test/test_suite7/switch/switch_in_defer_macro.c3t create mode 100644 test/test_suite7/symbols/allow_local_shadowing.c3 create mode 100644 test/test_suite7/symbols/shadow_struct.c3 create mode 100644 test/test_suite7/symbols/various.c3 create mode 100644 test/test_suite7/types/enum_illegal_type.c3 create mode 100644 test/test_suite7/types/enum_implicit_overflow.c3 create mode 100644 test/test_suite7/types/enum_inference.c3 create mode 100644 test/test_suite7/types/enum_ok.c3 create mode 100644 test/test_suite7/types/enum_param.c3 create mode 100644 test/test_suite7/types/enum_parse_errors.c3 create mode 100644 test/test_suite7/types/illegal_array_size_constant.c3 create mode 100644 test/test_suite7/types/non_rec_fn.c3 create mode 100644 test/test_suite7/types/recursive_array.c3 create mode 100644 test/test_suite7/types/recursive_fn.c3 create mode 100644 test/test_suite7/types/recursive_typedef.c3 create mode 100644 test/test_suite7/types/redefinition.c3 create mode 100644 test/test_suite7/types/typedefs.c3 create mode 100644 test/test_suite7/types/various.c3 create mode 100644 test/test_suite7/unicode/commenting-out.c3 create mode 100644 test/test_suite7/union/designated_union_zeroing.c3t create mode 100644 test/test_suite7/union/flexible_array_union.c3 create mode 100644 test/test_suite7/union/inferred_size_vector.c3 create mode 100644 test/test_suite7/union/test_unions.c3 create mode 100644 test/test_suite7/union/union_codegen_const.c3t create mode 100644 test/test_suite7/union/union_codegen_empty.c3t create mode 100644 test/test_suite7/union/union_codegen_overwrite_call.c3t create mode 100644 test/test_suite7/union/union_in_struct.c3t create mode 100644 test/test_suite7/union/union_member_voidcast.c3 create mode 100644 test/test_suite7/union/union_zero.c3 create mode 100644 test/test_suite7/variables/const_in_func.c3t create mode 100644 test/test_suite7/variables/consts.c3 create mode 100644 test/test_suite7/variables/static_in_macro.c3t create mode 100644 test/test_suite7/variables/var_init.c3t create mode 100644 test/test_suite7/variables/var_init_multi.c3t create mode 100644 test/test_suite7/vector/gather_scatter.c3t create mode 100644 test/test_suite7/vector/swizzle_vector_ref.c3t create mode 100644 test/test_suite7/vector/swizzling.c3 create mode 100644 test/test_suite7/vector/vector_bit.c3t create mode 100644 test/test_suite7/vector/vector_consts.c3t create mode 100644 test/test_suite7/vector/vector_conversion_scalar.c3 create mode 100644 test/test_suite7/vector/vector_from_i1.c3t create mode 100644 test/test_suite7/vector/vector_incdec.c3t create mode 100644 test/test_suite7/vector/vector_init.c3t create mode 100644 test/test_suite7/vector/vector_init_regression.c3t create mode 100644 test/test_suite7/vector/vector_lowering_regression1.c3t create mode 100644 test/test_suite7/vector/vector_ops2.c3t create mode 100644 test/test_suite7/vector/vector_param.c3t create mode 100644 test/test_suite7/vector/vector_pointer_errors.c3 create mode 100644 test/test_suite7/vector/vector_shift.c3t create mode 100644 test/test_suite7/vector/vector_to_array_cast.c3t create mode 100644 test/test_suite7/vector/vector_to_array_fail.c3 create mode 100644 test/test_suite7/vector/vector_to_vector_const_fail.c3 create mode 100644 test/test_suite7/visibility/ambiguous_recursive.c3 create mode 100644 test/test_suite7/visibility/ambiguous_var.c3t create mode 100644 test/test_suite7/visibility/export_property.c3t create mode 100644 test/test_suite7/visibility/no_shared_imports.c3t create mode 100644 test/test_suite7/visibility/not_visible.c3t create mode 100644 test/test_suite7/visibility/private_import.c3 create mode 100644 test/test_suite7/visibility/private_import2.c3 create mode 100644 test/test_suite7/visibility/private_to_extern.c3t create mode 100644 test/test_suite7/visibility/shared_module.c3t create mode 100644 test/test_suite7/visibility/simple_visibility.c3t diff --git a/lib2/std/ascii.c3 b/lib7/std/ascii.c3 similarity index 100% rename from lib2/std/ascii.c3 rename to lib7/std/ascii.c3 diff --git a/lib2/std/atomic.c3 b/lib7/std/atomic.c3 similarity index 100% rename from lib2/std/atomic.c3 rename to lib7/std/atomic.c3 diff --git a/lib2/std/atomic_nolibc.c3 b/lib7/std/atomic_nolibc.c3 similarity index 100% rename from lib2/std/atomic_nolibc.c3 rename to lib7/std/atomic_nolibc.c3 diff --git a/lib2/std/bits.c3 b/lib7/std/bits.c3 similarity index 100% rename from lib2/std/bits.c3 rename to lib7/std/bits.c3 diff --git a/lib2/std/collections/anylist.c3 b/lib7/std/collections/anylist.c3 similarity index 100% rename from lib2/std/collections/anylist.c3 rename to lib7/std/collections/anylist.c3 diff --git a/lib2/std/collections/bitset.c3 b/lib7/std/collections/bitset.c3 similarity index 100% rename from lib2/std/collections/bitset.c3 rename to lib7/std/collections/bitset.c3 diff --git a/lib2/std/collections/elastic_array.c3 b/lib7/std/collections/elastic_array.c3 similarity index 94% rename from lib2/std/collections/elastic_array.c3 rename to lib7/std/collections/elastic_array.c3 index a835aa68c..e2c89e6b9 100644 --- a/lib2/std/collections/elastic_array.c3 +++ b/lib7/std/collections/elastic_array.c3 @@ -160,28 +160,12 @@ fn void ElasticArray.add_array(&self, Type[] array) -<* - IMPORTANT The returned array must be freed using free_aligned. -*> -fn Type[] ElasticArray.to_new_aligned_array(&self) -{ - return list_common::list_to_new_aligned_array(Type, self, allocator::heap()); -} - <* IMPORTANT The returned array must be freed using free_aligned. *> fn Type[] ElasticArray.to_aligned_array(&self, Allocator allocator) { - return list_common::list_to_new_aligned_array(Type, self, allocator); -} - -<* - @require !type_is_overaligned() : "This function is not available on overaligned types" -*> -macro Type[] ElasticArray.to_new_array(&self) -{ - return list_common::list_to_array(Type, self, allocator::heap()); + return list_common::list_to_aligned_array(Type, self, allocator); } <* @@ -189,7 +173,7 @@ macro Type[] ElasticArray.to_new_array(&self) *> macro Type[] ElasticArray.to_array(&self, Allocator allocator) { - return list_common::list_to_new_array(Type, self, allocator); + return list_common::list_to_array(Type, self, allocator); } fn Type[] ElasticArray.to_tarray(&self) diff --git a/lib2/std/collections/enummap.c3 b/lib7/std/collections/enummap.c3 similarity index 100% rename from lib2/std/collections/enummap.c3 rename to lib7/std/collections/enummap.c3 diff --git a/lib2/std/collections/enumset.c3 b/lib7/std/collections/enumset.c3 similarity index 100% rename from lib2/std/collections/enumset.c3 rename to lib7/std/collections/enumset.c3 diff --git a/lib2/std/collections/hashmap.c3 b/lib7/std/collections/hashmap.c3 similarity index 100% rename from lib2/std/collections/hashmap.c3 rename to lib7/std/collections/hashmap.c3 diff --git a/lib2/std/collections/linkedlist.c3 b/lib7/std/collections/linkedlist.c3 similarity index 100% rename from lib2/std/collections/linkedlist.c3 rename to lib7/std/collections/linkedlist.c3 diff --git a/lib2/std/collections/list.c3 b/lib7/std/collections/list.c3 similarity index 100% rename from lib2/std/collections/list.c3 rename to lib7/std/collections/list.c3 diff --git a/lib2/std/collections/list_common.c3 b/lib7/std/collections/list_common.c3 similarity index 100% rename from lib2/std/collections/list_common.c3 rename to lib7/std/collections/list_common.c3 diff --git a/lib2/std/collections/maybe.c3 b/lib7/std/collections/maybe.c3 similarity index 100% rename from lib2/std/collections/maybe.c3 rename to lib7/std/collections/maybe.c3 diff --git a/lib2/std/collections/object.c3 b/lib7/std/collections/object.c3 similarity index 100% rename from lib2/std/collections/object.c3 rename to lib7/std/collections/object.c3 diff --git a/lib2/std/collections/priorityqueue.c3 b/lib7/std/collections/priorityqueue.c3 similarity index 94% rename from lib2/std/collections/priorityqueue.c3 rename to lib7/std/collections/priorityqueue.c3 index 599abd3d1..4a244292f 100644 --- a/lib2/std/collections/priorityqueue.c3 +++ b/lib7/std/collections/priorityqueue.c3 @@ -23,8 +23,8 @@ module std::collections::priorityqueue{Type}; import std::collections::priorityqueue::private; -distinct PriorityQueue = inline List{Type}; -distinct PriorityQueueMax = inline List{Type}; +distinct PriorityQueue = inline PrivatePriorityQueue{Type, false}; +distinct PriorityQueueMax = inline PrivatePriorityQueue{Type, true}; module std::collections::priorityqueue::private{Type, MAX}; import std::collections::list, std::io; @@ -68,13 +68,13 @@ fn void PrivatePriorityQueue.push(&self, Type element) } <* - @require index < self.len : "Index out of range" + @require index < self.len() : "Index out of range" *> fn void PrivatePriorityQueue.remove_at(&self, usz index) { if (index == 0) { - self.heap.remove_last(); + self.pop()!!; return; } self.heap.remove_at(index); diff --git a/lib2/std/collections/range.c3 b/lib7/std/collections/range.c3 similarity index 100% rename from lib2/std/collections/range.c3 rename to lib7/std/collections/range.c3 diff --git a/lib2/std/collections/ringbuffer.c3 b/lib7/std/collections/ringbuffer.c3 similarity index 100% rename from lib2/std/collections/ringbuffer.c3 rename to lib7/std/collections/ringbuffer.c3 diff --git a/lib2/std/collections/tuple.c3 b/lib7/std/collections/tuple.c3 similarity index 100% rename from lib2/std/collections/tuple.c3 rename to lib7/std/collections/tuple.c3 diff --git a/lib2/std/compression/qoi.c3 b/lib7/std/compression/qoi.c3 similarity index 100% rename from lib2/std/compression/qoi.c3 rename to lib7/std/compression/qoi.c3 diff --git a/lib2/std/core/allocators/arena_allocator.c3 b/lib7/std/core/allocators/arena_allocator.c3 similarity index 100% rename from lib2/std/core/allocators/arena_allocator.c3 rename to lib7/std/core/allocators/arena_allocator.c3 diff --git a/lib2/std/core/allocators/dynamic_arena.c3 b/lib7/std/core/allocators/dynamic_arena.c3 similarity index 100% rename from lib2/std/core/allocators/dynamic_arena.c3 rename to lib7/std/core/allocators/dynamic_arena.c3 diff --git a/lib2/std/core/allocators/heap_allocator.c3 b/lib7/std/core/allocators/heap_allocator.c3 similarity index 100% rename from lib2/std/core/allocators/heap_allocator.c3 rename to lib7/std/core/allocators/heap_allocator.c3 diff --git a/lib2/std/core/allocators/libc_allocator.c3 b/lib7/std/core/allocators/libc_allocator.c3 similarity index 100% rename from lib2/std/core/allocators/libc_allocator.c3 rename to lib7/std/core/allocators/libc_allocator.c3 diff --git a/lib2/std/core/allocators/on_stack_allocator.c3 b/lib7/std/core/allocators/on_stack_allocator.c3 similarity index 100% rename from lib2/std/core/allocators/on_stack_allocator.c3 rename to lib7/std/core/allocators/on_stack_allocator.c3 diff --git a/lib2/std/core/allocators/temp_allocator.c3 b/lib7/std/core/allocators/temp_allocator.c3 similarity index 100% rename from lib2/std/core/allocators/temp_allocator.c3 rename to lib7/std/core/allocators/temp_allocator.c3 diff --git a/lib2/std/core/allocators/tracking_allocator.c3 b/lib7/std/core/allocators/tracking_allocator.c3 similarity index 100% rename from lib2/std/core/allocators/tracking_allocator.c3 rename to lib7/std/core/allocators/tracking_allocator.c3 diff --git a/lib2/std/core/array.c3 b/lib7/std/core/array.c3 similarity index 100% rename from lib2/std/core/array.c3 rename to lib7/std/core/array.c3 diff --git a/lib2/std/core/bitorder.c3 b/lib7/std/core/bitorder.c3 similarity index 100% rename from lib2/std/core/bitorder.c3 rename to lib7/std/core/bitorder.c3 diff --git a/lib2/std/core/builtin.c3 b/lib7/std/core/builtin.c3 similarity index 96% rename from lib2/std/core/builtin.c3 rename to lib7/std/core/builtin.c3 index f9b3c2406..ca73f36b8 100644 --- a/lib2/std/core/builtin.c3 +++ b/lib7/std/core/builtin.c3 @@ -4,6 +4,31 @@ module std::core::builtin; import libc, std::hash, std::io, std::os::backtrace; +<* + EMPTY_MACRO_SLOT is a value used for implementing optional arguments for macros in an efficient + way. It relies on the fact that distinct types are not implicitly convertable. + + You can use `@is_empty_macro_slot()` and `@is_valid_macro_slot()` to figure out whether + the argument has been used or not. + + An example: + +```c3 +macro foo(a, #b = EMPTY_MACRO_SLOT) +{ + $if @is_valid_macro_slot(#b): + return invoke_foo2(a, #b); + $else + return invoke_foo1(a); + $endif +} +*> +const EmptySlot EMPTY_MACRO_SLOT @builtin = null; + +distinct EmptySlot = void*; +macro @is_empty_macro_slot(#arg) @const @builtin => @typeis(#arg, EmptySlot); +macro @is_valid_macro_slot(#arg) @const @builtin => !@typeis(#arg, EmptySlot); + /* Use `IteratorResult` when reading the end of an iterator, or accessing a result out of bounds. */ @@ -67,7 +92,7 @@ fn bool print_backtrace(String message, int backtraces_to_ignore) @if(env::NATIV void*[256] buffer; void*[] backtraces = backtrace::capture_current(&buffer); backtraces_to_ignore++; - BacktraceList! backtrace = backtrace::symbolize_backtrace(allocator::temp(), backtraces); + BacktraceList! backtrace = backtrace::symbolize_backtrace(tmem(), backtraces); if (catch backtrace) return false; if (backtrace.len() <= backtraces_to_ignore) return false; io::eprint("\nERROR: '"); @@ -413,10 +438,6 @@ macro uint String.hash(String c) => (uint)fnv32a::encode(c); macro uint char[].hash(char[] c) => (uint)fnv32a::encode(c); macro uint void*.hash(void* ptr) => @generic_hash(((ulong)(uptr)ptr)); -distinct EmptySlot = void*; -const EmptySlot EMPTY_MACRO_SLOT @builtin = null; -macro @is_empty_macro_slot(#arg) @builtin => @typeis(#arg, EmptySlot); -macro @is_valid_macro_slot(#arg) @builtin => !@typeis(#arg, EmptySlot); const MAX_FRAMEADDRESS = 128; <* diff --git a/lib2/std/core/builtin_comparison.c3 b/lib7/std/core/builtin_comparison.c3 similarity index 100% rename from lib2/std/core/builtin_comparison.c3 rename to lib7/std/core/builtin_comparison.c3 diff --git a/lib2/std/core/cinterop.c3 b/lib7/std/core/cinterop.c3 similarity index 100% rename from lib2/std/core/cinterop.c3 rename to lib7/std/core/cinterop.c3 diff --git a/lib2/std/core/conv.c3 b/lib7/std/core/conv.c3 similarity index 100% rename from lib2/std/core/conv.c3 rename to lib7/std/core/conv.c3 diff --git a/lib2/std/core/dstring.c3 b/lib7/std/core/dstring.c3 similarity index 100% rename from lib2/std/core/dstring.c3 rename to lib7/std/core/dstring.c3 diff --git a/lib2/std/core/env.c3 b/lib7/std/core/env.c3 similarity index 100% rename from lib2/std/core/env.c3 rename to lib7/std/core/env.c3 diff --git a/lib2/std/core/mem.c3 b/lib7/std/core/mem.c3 similarity index 100% rename from lib2/std/core/mem.c3 rename to lib7/std/core/mem.c3 diff --git a/lib2/std/core/mem_allocator.c3 b/lib7/std/core/mem_allocator.c3 similarity index 100% rename from lib2/std/core/mem_allocator.c3 rename to lib7/std/core/mem_allocator.c3 diff --git a/lib2/std/core/os/wasm_memory.c3 b/lib7/std/core/os/wasm_memory.c3 similarity index 100% rename from lib2/std/core/os/wasm_memory.c3 rename to lib7/std/core/os/wasm_memory.c3 diff --git a/lib2/std/core/private/cpu_detect.c3 b/lib7/std/core/private/cpu_detect.c3 similarity index 100% rename from lib2/std/core/private/cpu_detect.c3 rename to lib7/std/core/private/cpu_detect.c3 diff --git a/lib2/std/core/private/macho_runtime.c3 b/lib7/std/core/private/macho_runtime.c3 similarity index 100% rename from lib2/std/core/private/macho_runtime.c3 rename to lib7/std/core/private/macho_runtime.c3 diff --git a/lib2/std/core/private/main_stub.c3 b/lib7/std/core/private/main_stub.c3 similarity index 100% rename from lib2/std/core/private/main_stub.c3 rename to lib7/std/core/private/main_stub.c3 diff --git a/lib2/std/core/runtime.c3 b/lib7/std/core/runtime.c3 similarity index 100% rename from lib2/std/core/runtime.c3 rename to lib7/std/core/runtime.c3 diff --git a/lib2/std/core/runtime_benchmark.c3 b/lib7/std/core/runtime_benchmark.c3 similarity index 100% rename from lib2/std/core/runtime_benchmark.c3 rename to lib7/std/core/runtime_benchmark.c3 diff --git a/lib2/std/core/runtime_test.c3 b/lib7/std/core/runtime_test.c3 similarity index 100% rename from lib2/std/core/runtime_test.c3 rename to lib7/std/core/runtime_test.c3 diff --git a/lib2/std/core/sanitizer/asan.c3 b/lib7/std/core/sanitizer/asan.c3 similarity index 100% rename from lib2/std/core/sanitizer/asan.c3 rename to lib7/std/core/sanitizer/asan.c3 diff --git a/lib2/std/core/sanitizer/sanitizer.c3 b/lib7/std/core/sanitizer/sanitizer.c3 similarity index 100% rename from lib2/std/core/sanitizer/sanitizer.c3 rename to lib7/std/core/sanitizer/sanitizer.c3 diff --git a/lib2/std/core/sanitizer/tsan.c3 b/lib7/std/core/sanitizer/tsan.c3 similarity index 100% rename from lib2/std/core/sanitizer/tsan.c3 rename to lib7/std/core/sanitizer/tsan.c3 diff --git a/lib2/std/core/string.c3 b/lib7/std/core/string.c3 similarity index 100% rename from lib2/std/core/string.c3 rename to lib7/std/core/string.c3 diff --git a/lib2/std/core/string_iterator.c3 b/lib7/std/core/string_iterator.c3 similarity index 100% rename from lib2/std/core/string_iterator.c3 rename to lib7/std/core/string_iterator.c3 diff --git a/lib2/std/core/string_to_real.c3 b/lib7/std/core/string_to_real.c3 similarity index 100% rename from lib2/std/core/string_to_real.c3 rename to lib7/std/core/string_to_real.c3 diff --git a/lib2/std/core/test.c3 b/lib7/std/core/test.c3 similarity index 100% rename from lib2/std/core/test.c3 rename to lib7/std/core/test.c3 diff --git a/lib2/std/core/types.c3 b/lib7/std/core/types.c3 similarity index 100% rename from lib2/std/core/types.c3 rename to lib7/std/core/types.c3 diff --git a/lib2/std/core/values.c3 b/lib7/std/core/values.c3 similarity index 100% rename from lib2/std/core/values.c3 rename to lib7/std/core/values.c3 diff --git a/lib2/std/crypto/crypto.c3 b/lib7/std/crypto/crypto.c3 similarity index 100% rename from lib2/std/crypto/crypto.c3 rename to lib7/std/crypto/crypto.c3 diff --git a/lib2/std/crypto/dh.c3 b/lib7/std/crypto/dh.c3 similarity index 100% rename from lib2/std/crypto/dh.c3 rename to lib7/std/crypto/dh.c3 diff --git a/lib2/std/crypto/rc4.c3 b/lib7/std/crypto/rc4.c3 similarity index 100% rename from lib2/std/crypto/rc4.c3 rename to lib7/std/crypto/rc4.c3 diff --git a/lib2/std/encoding/base32.c3 b/lib7/std/encoding/base32.c3 similarity index 100% rename from lib2/std/encoding/base32.c3 rename to lib7/std/encoding/base32.c3 diff --git a/lib2/std/encoding/base64.c3 b/lib7/std/encoding/base64.c3 similarity index 100% rename from lib2/std/encoding/base64.c3 rename to lib7/std/encoding/base64.c3 diff --git a/lib2/std/encoding/csv.c3 b/lib7/std/encoding/csv.c3 similarity index 100% rename from lib2/std/encoding/csv.c3 rename to lib7/std/encoding/csv.c3 diff --git a/lib2/std/encoding/encoding.c3 b/lib7/std/encoding/encoding.c3 similarity index 100% rename from lib2/std/encoding/encoding.c3 rename to lib7/std/encoding/encoding.c3 diff --git a/lib2/std/encoding/hex.c3 b/lib7/std/encoding/hex.c3 similarity index 100% rename from lib2/std/encoding/hex.c3 rename to lib7/std/encoding/hex.c3 diff --git a/lib2/std/encoding/json.c3 b/lib7/std/encoding/json.c3 similarity index 100% rename from lib2/std/encoding/json.c3 rename to lib7/std/encoding/json.c3 diff --git a/lib2/std/experimental/FrameScheduler.c3 b/lib7/std/experimental/FrameScheduler.c3 similarity index 100% rename from lib2/std/experimental/FrameScheduler.c3 rename to lib7/std/experimental/FrameScheduler.c3 diff --git a/lib2/std/hash/adler32.c3 b/lib7/std/hash/adler32.c3 similarity index 100% rename from lib2/std/hash/adler32.c3 rename to lib7/std/hash/adler32.c3 diff --git a/lib2/std/hash/crc32.c3 b/lib7/std/hash/crc32.c3 similarity index 100% rename from lib2/std/hash/crc32.c3 rename to lib7/std/hash/crc32.c3 diff --git a/lib2/std/hash/crc64.c3 b/lib7/std/hash/crc64.c3 similarity index 100% rename from lib2/std/hash/crc64.c3 rename to lib7/std/hash/crc64.c3 diff --git a/lib2/std/hash/fnv32a.c3 b/lib7/std/hash/fnv32a.c3 similarity index 100% rename from lib2/std/hash/fnv32a.c3 rename to lib7/std/hash/fnv32a.c3 diff --git a/lib2/std/hash/fnv64a.c3 b/lib7/std/hash/fnv64a.c3 similarity index 100% rename from lib2/std/hash/fnv64a.c3 rename to lib7/std/hash/fnv64a.c3 diff --git a/lib2/std/hash/hmac.c3 b/lib7/std/hash/hmac.c3 similarity index 100% rename from lib2/std/hash/hmac.c3 rename to lib7/std/hash/hmac.c3 diff --git a/lib2/std/hash/md5.c3 b/lib7/std/hash/md5.c3 similarity index 100% rename from lib2/std/hash/md5.c3 rename to lib7/std/hash/md5.c3 diff --git a/lib2/std/hash/sha1.c3 b/lib7/std/hash/sha1.c3 similarity index 100% rename from lib2/std/hash/sha1.c3 rename to lib7/std/hash/sha1.c3 diff --git a/lib2/std/hash/sha256.c3 b/lib7/std/hash/sha256.c3 similarity index 100% rename from lib2/std/hash/sha256.c3 rename to lib7/std/hash/sha256.c3 diff --git a/lib2/std/io/bits.c3 b/lib7/std/io/bits.c3 similarity index 100% rename from lib2/std/io/bits.c3 rename to lib7/std/io/bits.c3 diff --git a/lib2/std/io/file.c3 b/lib7/std/io/file.c3 similarity index 100% rename from lib2/std/io/file.c3 rename to lib7/std/io/file.c3 diff --git a/lib2/std/io/formatter.c3 b/lib7/std/io/formatter.c3 similarity index 100% rename from lib2/std/io/formatter.c3 rename to lib7/std/io/formatter.c3 diff --git a/lib2/std/io/formatter_private.c3 b/lib7/std/io/formatter_private.c3 similarity index 100% rename from lib2/std/io/formatter_private.c3 rename to lib7/std/io/formatter_private.c3 diff --git a/lib2/std/io/io.c3 b/lib7/std/io/io.c3 similarity index 100% rename from lib2/std/io/io.c3 rename to lib7/std/io/io.c3 diff --git a/lib2/std/io/os/chdir.c3 b/lib7/std/io/os/chdir.c3 similarity index 100% rename from lib2/std/io/os/chdir.c3 rename to lib7/std/io/os/chdir.c3 diff --git a/lib2/std/io/os/file_libc.c3 b/lib7/std/io/os/file_libc.c3 similarity index 100% rename from lib2/std/io/os/file_libc.c3 rename to lib7/std/io/os/file_libc.c3 diff --git a/lib2/std/io/os/file_nolibc.c3 b/lib7/std/io/os/file_nolibc.c3 similarity index 100% rename from lib2/std/io/os/file_nolibc.c3 rename to lib7/std/io/os/file_nolibc.c3 diff --git a/lib2/std/io/os/fileinfo.c3 b/lib7/std/io/os/fileinfo.c3 similarity index 100% rename from lib2/std/io/os/fileinfo.c3 rename to lib7/std/io/os/fileinfo.c3 diff --git a/lib2/std/io/os/getcwd.c3 b/lib7/std/io/os/getcwd.c3 similarity index 100% rename from lib2/std/io/os/getcwd.c3 rename to lib7/std/io/os/getcwd.c3 diff --git a/lib2/std/io/os/ls.c3 b/lib7/std/io/os/ls.c3 similarity index 97% rename from lib2/std/io/os/ls.c3 rename to lib7/std/io/os/ls.c3 index c9c9edd0a..7a51865e8 100644 --- a/lib2/std/io/os/ls.c3 +++ b/lib7/std/io/os/ls.c3 @@ -27,7 +27,7 @@ import std::time, std::os, std::io; fn PathList! native_ls(Path dir, bool no_dirs, bool no_symlinks, String mask, Allocator allocator) { PathList list; - list.new_init(allocator: allocator); + list.init(allocator); @pool(allocator) { diff --git a/lib2/std/io/os/mkdir.c3 b/lib7/std/io/os/mkdir.c3 similarity index 100% rename from lib2/std/io/os/mkdir.c3 rename to lib7/std/io/os/mkdir.c3 diff --git a/lib2/std/io/os/rmdir.c3 b/lib7/std/io/os/rmdir.c3 similarity index 100% rename from lib2/std/io/os/rmdir.c3 rename to lib7/std/io/os/rmdir.c3 diff --git a/lib2/std/io/os/rmtree.c3 b/lib7/std/io/os/rmtree.c3 similarity index 100% rename from lib2/std/io/os/rmtree.c3 rename to lib7/std/io/os/rmtree.c3 diff --git a/lib2/std/io/os/temp_directory.c3 b/lib7/std/io/os/temp_directory.c3 similarity index 100% rename from lib2/std/io/os/temp_directory.c3 rename to lib7/std/io/os/temp_directory.c3 diff --git a/lib2/std/io/path.c3 b/lib7/std/io/path.c3 similarity index 100% rename from lib2/std/io/path.c3 rename to lib7/std/io/path.c3 diff --git a/lib2/std/io/stream.c3 b/lib7/std/io/stream.c3 similarity index 100% rename from lib2/std/io/stream.c3 rename to lib7/std/io/stream.c3 diff --git a/lib2/std/io/stream/buffer.c3 b/lib7/std/io/stream/buffer.c3 similarity index 100% rename from lib2/std/io/stream/buffer.c3 rename to lib7/std/io/stream/buffer.c3 diff --git a/lib2/std/io/stream/bytebuffer.c3 b/lib7/std/io/stream/bytebuffer.c3 similarity index 100% rename from lib2/std/io/stream/bytebuffer.c3 rename to lib7/std/io/stream/bytebuffer.c3 diff --git a/lib2/std/io/stream/bytereader.c3 b/lib7/std/io/stream/bytereader.c3 similarity index 100% rename from lib2/std/io/stream/bytereader.c3 rename to lib7/std/io/stream/bytereader.c3 diff --git a/lib2/std/io/stream/bytewriter.c3 b/lib7/std/io/stream/bytewriter.c3 similarity index 100% rename from lib2/std/io/stream/bytewriter.c3 rename to lib7/std/io/stream/bytewriter.c3 diff --git a/lib2/std/io/stream/limitreader.c3 b/lib7/std/io/stream/limitreader.c3 similarity index 100% rename from lib2/std/io/stream/limitreader.c3 rename to lib7/std/io/stream/limitreader.c3 diff --git a/lib2/std/io/stream/multireader.c3 b/lib7/std/io/stream/multireader.c3 similarity index 100% rename from lib2/std/io/stream/multireader.c3 rename to lib7/std/io/stream/multireader.c3 diff --git a/lib2/std/io/stream/multiwriter.c3 b/lib7/std/io/stream/multiwriter.c3 similarity index 100% rename from lib2/std/io/stream/multiwriter.c3 rename to lib7/std/io/stream/multiwriter.c3 diff --git a/lib2/std/io/stream/scanner.c3 b/lib7/std/io/stream/scanner.c3 similarity index 100% rename from lib2/std/io/stream/scanner.c3 rename to lib7/std/io/stream/scanner.c3 diff --git a/lib2/std/io/stream/teereader.c3 b/lib7/std/io/stream/teereader.c3 similarity index 100% rename from lib2/std/io/stream/teereader.c3 rename to lib7/std/io/stream/teereader.c3 diff --git a/lib2/std/libc/libc.c3 b/lib7/std/libc/libc.c3 similarity index 100% rename from lib2/std/libc/libc.c3 rename to lib7/std/libc/libc.c3 diff --git a/lib2/std/libc/libc_extra.c3 b/lib7/std/libc/libc_extra.c3 similarity index 100% rename from lib2/std/libc/libc_extra.c3 rename to lib7/std/libc/libc_extra.c3 diff --git a/lib2/std/libc/os/darwin.c3 b/lib7/std/libc/os/darwin.c3 similarity index 100% rename from lib2/std/libc/os/darwin.c3 rename to lib7/std/libc/os/darwin.c3 diff --git a/lib2/std/libc/os/errno.c3 b/lib7/std/libc/os/errno.c3 similarity index 100% rename from lib2/std/libc/os/errno.c3 rename to lib7/std/libc/os/errno.c3 diff --git a/lib2/std/libc/os/freebsd.c3 b/lib7/std/libc/os/freebsd.c3 similarity index 100% rename from lib2/std/libc/os/freebsd.c3 rename to lib7/std/libc/os/freebsd.c3 diff --git a/lib2/std/libc/os/linux.c3 b/lib7/std/libc/os/linux.c3 similarity index 100% rename from lib2/std/libc/os/linux.c3 rename to lib7/std/libc/os/linux.c3 diff --git a/lib2/std/libc/os/posix.c3 b/lib7/std/libc/os/posix.c3 similarity index 100% rename from lib2/std/libc/os/posix.c3 rename to lib7/std/libc/os/posix.c3 diff --git a/lib2/std/libc/os/win32.c3 b/lib7/std/libc/os/win32.c3 similarity index 100% rename from lib2/std/libc/os/win32.c3 rename to lib7/std/libc/os/win32.c3 diff --git a/lib2/std/libc/termios.c3 b/lib7/std/libc/termios.c3 similarity index 100% rename from lib2/std/libc/termios.c3 rename to lib7/std/libc/termios.c3 diff --git a/lib2/std/math/bigint.c3 b/lib7/std/math/bigint.c3 similarity index 100% rename from lib2/std/math/bigint.c3 rename to lib7/std/math/bigint.c3 diff --git a/lib2/std/math/math.c3 b/lib7/std/math/math.c3 similarity index 100% rename from lib2/std/math/math.c3 rename to lib7/std/math/math.c3 diff --git a/lib2/std/math/math_builtin.c3 b/lib7/std/math/math_builtin.c3 similarity index 100% rename from lib2/std/math/math_builtin.c3 rename to lib7/std/math/math_builtin.c3 diff --git a/lib2/std/math/math_complex.c3 b/lib7/std/math/math_complex.c3 similarity index 100% rename from lib2/std/math/math_complex.c3 rename to lib7/std/math/math_complex.c3 diff --git a/lib2/std/math/math_easings.c3 b/lib7/std/math/math_easings.c3 similarity index 100% rename from lib2/std/math/math_easings.c3 rename to lib7/std/math/math_easings.c3 diff --git a/lib2/std/math/math_i128.c3 b/lib7/std/math/math_i128.c3 similarity index 100% rename from lib2/std/math/math_i128.c3 rename to lib7/std/math/math_i128.c3 diff --git a/lib2/std/math/math_libc.c3 b/lib7/std/math/math_libc.c3 similarity index 100% rename from lib2/std/math/math_libc.c3 rename to lib7/std/math/math_libc.c3 diff --git a/lib2/std/math/math_matrix.c3 b/lib7/std/math/math_matrix.c3 similarity index 100% rename from lib2/std/math/math_matrix.c3 rename to lib7/std/math/math_matrix.c3 diff --git a/lib2/std/math/math_nolibc/__cos.c3 b/lib7/std/math/math_nolibc/__cos.c3 similarity index 100% rename from lib2/std/math/math_nolibc/__cos.c3 rename to lib7/std/math/math_nolibc/__cos.c3 diff --git a/lib2/std/math/math_nolibc/__cosdf.c3 b/lib7/std/math/math_nolibc/__cosdf.c3 similarity index 100% rename from lib2/std/math/math_nolibc/__cosdf.c3 rename to lib7/std/math/math_nolibc/__cosdf.c3 diff --git a/lib2/std/math/math_nolibc/__fmod.c3 b/lib7/std/math/math_nolibc/__fmod.c3 similarity index 100% rename from lib2/std/math/math_nolibc/__fmod.c3 rename to lib7/std/math/math_nolibc/__fmod.c3 diff --git a/lib2/std/math/math_nolibc/__sin.c3 b/lib7/std/math/math_nolibc/__sin.c3 similarity index 100% rename from lib2/std/math/math_nolibc/__sin.c3 rename to lib7/std/math/math_nolibc/__sin.c3 diff --git a/lib2/std/math/math_nolibc/__sindf.c3 b/lib7/std/math/math_nolibc/__sindf.c3 similarity index 100% rename from lib2/std/math/math_nolibc/__sindf.c3 rename to lib7/std/math/math_nolibc/__sindf.c3 diff --git a/lib2/std/math/math_nolibc/__tan.c3 b/lib7/std/math/math_nolibc/__tan.c3 similarity index 100% rename from lib2/std/math/math_nolibc/__tan.c3 rename to lib7/std/math/math_nolibc/__tan.c3 diff --git a/lib2/std/math/math_nolibc/__tandf.c3 b/lib7/std/math/math_nolibc/__tandf.c3 similarity index 100% rename from lib2/std/math/math_nolibc/__tandf.c3 rename to lib7/std/math/math_nolibc/__tandf.c3 diff --git a/lib2/std/math/math_nolibc/acos.c3 b/lib7/std/math/math_nolibc/acos.c3 similarity index 100% rename from lib2/std/math/math_nolibc/acos.c3 rename to lib7/std/math/math_nolibc/acos.c3 diff --git a/lib2/std/math/math_nolibc/asin.c3 b/lib7/std/math/math_nolibc/asin.c3 similarity index 100% rename from lib2/std/math/math_nolibc/asin.c3 rename to lib7/std/math/math_nolibc/asin.c3 diff --git a/lib2/std/math/math_nolibc/atan.c3 b/lib7/std/math/math_nolibc/atan.c3 similarity index 100% rename from lib2/std/math/math_nolibc/atan.c3 rename to lib7/std/math/math_nolibc/atan.c3 diff --git a/lib2/std/math/math_nolibc/atanh.c3 b/lib7/std/math/math_nolibc/atanh.c3 similarity index 100% rename from lib2/std/math/math_nolibc/atanh.c3 rename to lib7/std/math/math_nolibc/atanh.c3 diff --git a/lib2/std/math/math_nolibc/ceil.c3 b/lib7/std/math/math_nolibc/ceil.c3 similarity index 100% rename from lib2/std/math/math_nolibc/ceil.c3 rename to lib7/std/math/math_nolibc/ceil.c3 diff --git a/lib2/std/math/math_nolibc/cos.c3 b/lib7/std/math/math_nolibc/cos.c3 similarity index 100% rename from lib2/std/math/math_nolibc/cos.c3 rename to lib7/std/math/math_nolibc/cos.c3 diff --git a/lib2/std/math/math_nolibc/exp.c3 b/lib7/std/math/math_nolibc/exp.c3 similarity index 100% rename from lib2/std/math/math_nolibc/exp.c3 rename to lib7/std/math/math_nolibc/exp.c3 diff --git a/lib2/std/math/math_nolibc/exp2.c3 b/lib7/std/math/math_nolibc/exp2.c3 similarity index 100% rename from lib2/std/math/math_nolibc/exp2.c3 rename to lib7/std/math/math_nolibc/exp2.c3 diff --git a/lib2/std/math/math_nolibc/fabs.c3 b/lib7/std/math/math_nolibc/fabs.c3 similarity index 100% rename from lib2/std/math/math_nolibc/fabs.c3 rename to lib7/std/math/math_nolibc/fabs.c3 diff --git a/lib2/std/math/math_nolibc/floor.c3 b/lib7/std/math/math_nolibc/floor.c3 similarity index 100% rename from lib2/std/math/math_nolibc/floor.c3 rename to lib7/std/math/math_nolibc/floor.c3 diff --git a/lib2/std/math/math_nolibc/frexp.c3 b/lib7/std/math/math_nolibc/frexp.c3 similarity index 100% rename from lib2/std/math/math_nolibc/frexp.c3 rename to lib7/std/math/math_nolibc/frexp.c3 diff --git a/lib2/std/math/math_nolibc/ldexp.c3 b/lib7/std/math/math_nolibc/ldexp.c3 similarity index 100% rename from lib2/std/math/math_nolibc/ldexp.c3 rename to lib7/std/math/math_nolibc/ldexp.c3 diff --git a/lib2/std/math/math_nolibc/log.c3 b/lib7/std/math/math_nolibc/log.c3 similarity index 100% rename from lib2/std/math/math_nolibc/log.c3 rename to lib7/std/math/math_nolibc/log.c3 diff --git a/lib2/std/math/math_nolibc/log1p.c3 b/lib7/std/math/math_nolibc/log1p.c3 similarity index 100% rename from lib2/std/math/math_nolibc/log1p.c3 rename to lib7/std/math/math_nolibc/log1p.c3 diff --git a/lib2/std/math/math_nolibc/math_nolibc.c3 b/lib7/std/math/math_nolibc/math_nolibc.c3 similarity index 100% rename from lib2/std/math/math_nolibc/math_nolibc.c3 rename to lib7/std/math/math_nolibc/math_nolibc.c3 diff --git a/lib2/std/math/math_nolibc/pow.c3 b/lib7/std/math/math_nolibc/pow.c3 similarity index 100% rename from lib2/std/math/math_nolibc/pow.c3 rename to lib7/std/math/math_nolibc/pow.c3 diff --git a/lib2/std/math/math_nolibc/rempi.c3 b/lib7/std/math/math_nolibc/rempi.c3 similarity index 100% rename from lib2/std/math/math_nolibc/rempi.c3 rename to lib7/std/math/math_nolibc/rempi.c3 diff --git a/lib2/std/math/math_nolibc/round.c3 b/lib7/std/math/math_nolibc/round.c3 similarity index 100% rename from lib2/std/math/math_nolibc/round.c3 rename to lib7/std/math/math_nolibc/round.c3 diff --git a/lib2/std/math/math_nolibc/scalbn.c3 b/lib7/std/math/math_nolibc/scalbn.c3 similarity index 100% rename from lib2/std/math/math_nolibc/scalbn.c3 rename to lib7/std/math/math_nolibc/scalbn.c3 diff --git a/lib2/std/math/math_nolibc/sin.c3 b/lib7/std/math/math_nolibc/sin.c3 similarity index 100% rename from lib2/std/math/math_nolibc/sin.c3 rename to lib7/std/math/math_nolibc/sin.c3 diff --git a/lib2/std/math/math_nolibc/sincos.c3 b/lib7/std/math/math_nolibc/sincos.c3 similarity index 100% rename from lib2/std/math/math_nolibc/sincos.c3 rename to lib7/std/math/math_nolibc/sincos.c3 diff --git a/lib2/std/math/math_nolibc/tan.c3 b/lib7/std/math/math_nolibc/tan.c3 similarity index 100% rename from lib2/std/math/math_nolibc/tan.c3 rename to lib7/std/math/math_nolibc/tan.c3 diff --git a/lib2/std/math/math_nolibc/trig.c3 b/lib7/std/math/math_nolibc/trig.c3 similarity index 100% rename from lib2/std/math/math_nolibc/trig.c3 rename to lib7/std/math/math_nolibc/trig.c3 diff --git a/lib2/std/math/math_nolibc/trunc.c3 b/lib7/std/math/math_nolibc/trunc.c3 similarity index 100% rename from lib2/std/math/math_nolibc/trunc.c3 rename to lib7/std/math/math_nolibc/trunc.c3 diff --git a/lib2/std/math/math_quaternion.c3 b/lib7/std/math/math_quaternion.c3 similarity index 100% rename from lib2/std/math/math_quaternion.c3 rename to lib7/std/math/math_quaternion.c3 diff --git a/lib2/std/math/math_random.c3 b/lib7/std/math/math_random.c3 similarity index 100% rename from lib2/std/math/math_random.c3 rename to lib7/std/math/math_random.c3 diff --git a/lib2/std/math/math_vector.c3 b/lib7/std/math/math_vector.c3 similarity index 100% rename from lib2/std/math/math_vector.c3 rename to lib7/std/math/math_vector.c3 diff --git a/lib2/std/math/random/math.lcg.c3 b/lib7/std/math/random/math.lcg.c3 similarity index 100% rename from lib2/std/math/random/math.lcg.c3 rename to lib7/std/math/random/math.lcg.c3 diff --git a/lib2/std/math/random/math.mcg.c3 b/lib7/std/math/random/math.mcg.c3 similarity index 100% rename from lib2/std/math/random/math.mcg.c3 rename to lib7/std/math/random/math.mcg.c3 diff --git a/lib2/std/math/random/math.msws.c3 b/lib7/std/math/random/math.msws.c3 similarity index 100% rename from lib2/std/math/random/math.msws.c3 rename to lib7/std/math/random/math.msws.c3 diff --git a/lib2/std/math/random/math.pcg.c3 b/lib7/std/math/random/math.pcg.c3 similarity index 100% rename from lib2/std/math/random/math.pcg.c3 rename to lib7/std/math/random/math.pcg.c3 diff --git a/lib2/std/math/random/math.seeder.c3 b/lib7/std/math/random/math.seeder.c3 similarity index 100% rename from lib2/std/math/random/math.seeder.c3 rename to lib7/std/math/random/math.seeder.c3 diff --git a/lib2/std/math/random/math.sfc.c3 b/lib7/std/math/random/math.sfc.c3 similarity index 100% rename from lib2/std/math/random/math.sfc.c3 rename to lib7/std/math/random/math.sfc.c3 diff --git a/lib2/std/math/random/math.simple_random.c3 b/lib7/std/math/random/math.simple_random.c3 similarity index 100% rename from lib2/std/math/random/math.simple_random.c3 rename to lib7/std/math/random/math.simple_random.c3 diff --git a/lib2/std/math/uuid.c3 b/lib7/std/math/uuid.c3 similarity index 100% rename from lib2/std/math/uuid.c3 rename to lib7/std/math/uuid.c3 diff --git a/lib2/std/net/http.c3 b/lib7/std/net/http.c3 similarity index 100% rename from lib2/std/net/http.c3 rename to lib7/std/net/http.c3 diff --git a/lib2/std/net/inetaddr.c3 b/lib7/std/net/inetaddr.c3 similarity index 100% rename from lib2/std/net/inetaddr.c3 rename to lib7/std/net/inetaddr.c3 diff --git a/lib2/std/net/net.c3 b/lib7/std/net/net.c3 similarity index 100% rename from lib2/std/net/net.c3 rename to lib7/std/net/net.c3 diff --git a/lib2/std/net/os/common.c3 b/lib7/std/net/os/common.c3 similarity index 100% rename from lib2/std/net/os/common.c3 rename to lib7/std/net/os/common.c3 diff --git a/lib2/std/net/os/darwin.c3 b/lib7/std/net/os/darwin.c3 similarity index 100% rename from lib2/std/net/os/darwin.c3 rename to lib7/std/net/os/darwin.c3 diff --git a/lib2/std/net/os/linux.c3 b/lib7/std/net/os/linux.c3 similarity index 100% rename from lib2/std/net/os/linux.c3 rename to lib7/std/net/os/linux.c3 diff --git a/lib2/std/net/os/posix.c3 b/lib7/std/net/os/posix.c3 similarity index 100% rename from lib2/std/net/os/posix.c3 rename to lib7/std/net/os/posix.c3 diff --git a/lib2/std/net/os/win32.c3 b/lib7/std/net/os/win32.c3 similarity index 100% rename from lib2/std/net/os/win32.c3 rename to lib7/std/net/os/win32.c3 diff --git a/lib2/std/net/socket.c3 b/lib7/std/net/socket.c3 similarity index 100% rename from lib2/std/net/socket.c3 rename to lib7/std/net/socket.c3 diff --git a/lib2/std/net/socket_private.c3 b/lib7/std/net/socket_private.c3 similarity index 100% rename from lib2/std/net/socket_private.c3 rename to lib7/std/net/socket_private.c3 diff --git a/lib2/std/net/tcp.c3 b/lib7/std/net/tcp.c3 similarity index 100% rename from lib2/std/net/tcp.c3 rename to lib7/std/net/tcp.c3 diff --git a/lib2/std/net/udp.c3 b/lib7/std/net/udp.c3 similarity index 100% rename from lib2/std/net/udp.c3 rename to lib7/std/net/udp.c3 diff --git a/lib2/std/net/url.c3 b/lib7/std/net/url.c3 similarity index 100% rename from lib2/std/net/url.c3 rename to lib7/std/net/url.c3 diff --git a/lib2/std/net/url_encoding.c3 b/lib7/std/net/url_encoding.c3 similarity index 100% rename from lib2/std/net/url_encoding.c3 rename to lib7/std/net/url_encoding.c3 diff --git a/lib2/std/os/backtrace.c3 b/lib7/std/os/backtrace.c3 similarity index 90% rename from lib2/std/os/backtrace.c3 rename to lib7/std/os/backtrace.c3 index f7c6f0bf1..c2e7dd9b9 100644 --- a/lib2/std/os/backtrace.c3 +++ b/lib7/std/os/backtrace.c3 @@ -55,7 +55,7 @@ fn void Backtrace.free(&self) allocator::free(self.allocator, self.file); } -fn Backtrace* Backtrace.init(&self, uptr offset, String function, String object_file, String file = "", uint line = 0, Allocator allocator) +fn Backtrace* Backtrace.init(&self, Allocator allocator, uptr offset, String function, String object_file, String file = "", uint line = 0) { if (!allocator) { @@ -97,7 +97,7 @@ def symbolize_backtrace = linux::symbolize_backtrace @if(env::LINUX); def symbolize_backtrace = win32::symbolize_backtrace @if(env::WIN32); def symbolize_backtrace = darwin::symbolize_backtrace @if(env::DARWIN); -fn BacktraceList! symbolize_backtrace(void*[] backtrace, Allocator allocator) @if(!env::NATIVE_STACKTRACE) +fn BacktraceList! symbolize_backtrace(Allocator allocator, void*[] backtrace) @if(!env::NATIVE_STACKTRACE) { return {}; } \ No newline at end of file diff --git a/lib2/std/os/cpu.c3 b/lib7/std/os/cpu.c3 similarity index 100% rename from lib2/std/os/cpu.c3 rename to lib7/std/os/cpu.c3 diff --git a/lib2/std/os/env.c3 b/lib7/std/os/env.c3 similarity index 100% rename from lib2/std/os/env.c3 rename to lib7/std/os/env.c3 diff --git a/lib2/std/os/linux/heap.c3 b/lib7/std/os/linux/heap.c3 similarity index 100% rename from lib2/std/os/linux/heap.c3 rename to lib7/std/os/linux/heap.c3 diff --git a/lib2/std/os/linux/linux.c3 b/lib7/std/os/linux/linux.c3 similarity index 82% rename from lib2/std/os/linux/linux.c3 rename to lib7/std/os/linux/linux.c3 index 305db433e..50bf56107 100644 --- a/lib2/std/os/linux/linux.c3 +++ b/lib7/std/os/linux/linux.c3 @@ -128,17 +128,17 @@ fn ulong! elf_module_image_base(String path) @local return 0; } -fn void! backtrace_add_from_exec(BacktraceList* list, void* addr, Allocator allocator) @local +fn void! backtrace_add_from_exec(Allocator allocator, BacktraceList* list, void* addr) @local { char[] buf = mem::temp_alloc_array(char, 1024); String exec_path = process::execute_stdout_to_buffer(buf, {"realpath", "-e", string::tformat("/proc/%d/exe", posix::getpid())})!; String obj_name = exec_path.copy(allocator); String addr2line = process::execute_stdout_to_buffer(buf, {"addr2line", "-p", "-i", "-C", "-f", "-e", exec_path, string::tformat("0x%x", addr)})!; - return backtrace_add_addr2line(list, addr, addr2line, obj_name, "???", allocator); + return backtrace_add_addr2line(allocator, list, addr, addr2line, obj_name, "???"); } -fn void! backtrace_add_from_dlinfo(BacktraceList* list, void* addr, Linux_Dl_info* info, Allocator allocator) @local +fn void! backtrace_add_from_dlinfo(Allocator allocator, BacktraceList* list, void* addr, Linux_Dl_info* info) @local { char[] buf = mem::temp_alloc_array(char, 1024); @@ -146,10 +146,10 @@ fn void! backtrace_add_from_dlinfo(BacktraceList* list, void* addr, Linux_Dl_inf ZString obj_path = info.dli_fname; String sname = info.dli_sname ? info.dli_sname.str_view() : "???"; String addr2line = process::execute_stdout_to_buffer(buf, {"addr2line", "-p", "-i", "-C", "-f", "-e", obj_path.str_view(), string::tformat("0x%x", obj_addr - 1)})!; - return backtrace_add_addr2line(list, addr, addr2line, info.dli_fname.str_view(), sname, allocator); + return backtrace_add_addr2line(allocator, list, addr, addr2line, info.dli_fname.str_view(), sname); } -fn Backtrace! backtrace_line_parse(String string, String obj_name, String func_name, bool is_inlined, Allocator allocator) +fn Backtrace! backtrace_line_parse(Allocator allocator, String string, String obj_name, String func_name, bool is_inlined) { String[] parts = string.trim().tsplit(" at "); if (parts.len != 2) return SearchResult.MISSING?; @@ -171,14 +171,14 @@ fn Backtrace! backtrace_line_parse(String string, String obj_name, String func_n .is_inline = is_inlined }; } -fn void! backtrace_add_addr2line(BacktraceList* list, void* addr, String addr2line, String obj_name, String func_name, Allocator allocator) @local +fn void! backtrace_add_addr2line(Allocator allocator, BacktraceList* list, void* addr, String addr2line, String obj_name, String func_name) @local { String[] inline_parts = addr2line.tsplit("(inlined by)"); usz last = inline_parts.len - 1; foreach (i, part : inline_parts) { bool is_inline = i != last; - Backtrace! trace = backtrace_line_parse(part, obj_name, func_name, is_inline, allocator); + Backtrace! trace = backtrace_line_parse(allocator, part, obj_name, func_name, is_inline); if (catch trace) { list.push({ @@ -196,7 +196,7 @@ fn void! backtrace_add_addr2line(BacktraceList* list, void* addr, String addr2li } } -fn void! backtrace_add_element(BacktraceList *list, void* addr, Allocator allocator = allocator::heap()) @local +fn void! backtrace_add_element(Allocator allocator, BacktraceList *list, void* addr) @local { if (!addr) { @@ -209,16 +209,16 @@ fn void! backtrace_add_element(BacktraceList *list, void* addr, Allocator alloca Linux_Dl_info info; if (dladdr(addr, &info) == 0) { - return backtrace_add_from_exec(list, addr, allocator); + return backtrace_add_from_exec(allocator, list, addr); } - return backtrace_add_from_dlinfo(list, addr, &info, allocator); + return backtrace_add_from_dlinfo(allocator, list, addr, &info); }; } -fn BacktraceList! symbolize_backtrace(void*[] backtrace, Allocator allocator) +fn BacktraceList! symbolize_backtrace(Allocator allocator, void*[] backtrace) { BacktraceList list; - list.new_init(backtrace.len, allocator); + list.init(allocator, backtrace.len); defer catch { foreach (trace : list) @@ -231,7 +231,7 @@ fn BacktraceList! symbolize_backtrace(void*[] backtrace, Allocator allocator) { foreach (addr : backtrace) { - backtrace_add_element(&list, addr, allocator)!; + backtrace_add_element(allocator, &list, addr)!; } }; return list; diff --git a/lib2/std/os/macos/cf_allocator.c3 b/lib7/std/os/macos/cf_allocator.c3 similarity index 100% rename from lib2/std/os/macos/cf_allocator.c3 rename to lib7/std/os/macos/cf_allocator.c3 diff --git a/lib2/std/os/macos/cf_array.c3 b/lib7/std/os/macos/cf_array.c3 similarity index 100% rename from lib2/std/os/macos/cf_array.c3 rename to lib7/std/os/macos/cf_array.c3 diff --git a/lib2/std/os/macos/cocoa.c3 b/lib7/std/os/macos/cocoa.c3 similarity index 100% rename from lib2/std/os/macos/cocoa.c3 rename to lib7/std/os/macos/cocoa.c3 diff --git a/lib2/std/os/macos/core_foundation.c3 b/lib7/std/os/macos/core_foundation.c3 similarity index 100% rename from lib2/std/os/macos/core_foundation.c3 rename to lib7/std/os/macos/core_foundation.c3 diff --git a/lib2/std/os/macos/darwin.c3 b/lib7/std/os/macos/darwin.c3 similarity index 100% rename from lib2/std/os/macos/darwin.c3 rename to lib7/std/os/macos/darwin.c3 diff --git a/lib2/std/os/macos/heap.c3 b/lib7/std/os/macos/heap.c3 similarity index 100% rename from lib2/std/os/macos/heap.c3 rename to lib7/std/os/macos/heap.c3 diff --git a/lib2/std/os/macos/objc.c3 b/lib7/std/os/macos/objc.c3 similarity index 100% rename from lib2/std/os/macos/objc.c3 rename to lib7/std/os/macos/objc.c3 diff --git a/lib2/std/os/posix/files.c3 b/lib7/std/os/posix/files.c3 similarity index 100% rename from lib2/std/os/posix/files.c3 rename to lib7/std/os/posix/files.c3 diff --git a/lib2/std/os/posix/general.c3 b/lib7/std/os/posix/general.c3 similarity index 100% rename from lib2/std/os/posix/general.c3 rename to lib7/std/os/posix/general.c3 diff --git a/lib2/std/os/posix/heap.c3 b/lib7/std/os/posix/heap.c3 similarity index 100% rename from lib2/std/os/posix/heap.c3 rename to lib7/std/os/posix/heap.c3 diff --git a/lib2/std/os/posix/process.c3 b/lib7/std/os/posix/process.c3 similarity index 100% rename from lib2/std/os/posix/process.c3 rename to lib7/std/os/posix/process.c3 diff --git a/lib2/std/os/posix/threads.c3 b/lib7/std/os/posix/threads.c3 similarity index 100% rename from lib2/std/os/posix/threads.c3 rename to lib7/std/os/posix/threads.c3 diff --git a/lib2/std/os/subprocess.c3 b/lib7/std/os/subprocess.c3 similarity index 100% rename from lib2/std/os/subprocess.c3 rename to lib7/std/os/subprocess.c3 diff --git a/lib2/std/os/win32/files.c3 b/lib7/std/os/win32/files.c3 similarity index 100% rename from lib2/std/os/win32/files.c3 rename to lib7/std/os/win32/files.c3 diff --git a/lib2/std/os/win32/gdi.c3 b/lib7/std/os/win32/gdi.c3 similarity index 100% rename from lib2/std/os/win32/gdi.c3 rename to lib7/std/os/win32/gdi.c3 diff --git a/lib2/std/os/win32/general.c3 b/lib7/std/os/win32/general.c3 similarity index 100% rename from lib2/std/os/win32/general.c3 rename to lib7/std/os/win32/general.c3 diff --git a/lib2/std/os/win32/heap.c3 b/lib7/std/os/win32/heap.c3 similarity index 100% rename from lib2/std/os/win32/heap.c3 rename to lib7/std/os/win32/heap.c3 diff --git a/lib2/std/os/win32/process.c3 b/lib7/std/os/win32/process.c3 similarity index 96% rename from lib2/std/os/win32/process.c3 rename to lib7/std/os/win32/process.c3 index 7986388b2..05fe742ea 100644 --- a/lib2/std/os/win32/process.c3 +++ b/lib7/std/os/win32/process.c3 @@ -154,21 +154,21 @@ struct Symbol Win32_DWORD64 displacement; -fn BacktraceList! symbolize_backtrace(void*[] backtrace, Allocator allocator) +fn BacktraceList! symbolize_backtrace(Allocator allocator, void*[] backtrace) { BacktraceList list; - list.new_init(backtrace.len, allocator); + list.init(allocator, backtrace.len); Win32_HANDLE process = getCurrentProcess(); symInitialize(process, null, 1); defer symCleanup(process); foreach (addr : backtrace) { - list.push(resolve_backtrace(addr, process, allocator) ?? backtrace::BACKTRACE_UNKNOWN); + list.push(resolve_backtrace(allocator, addr, process) ?? backtrace::BACKTRACE_UNKNOWN); } return list; } -fn Backtrace! resolve_backtrace(void* addr, Win32_HANDLE process, Allocator allocator) +fn Backtrace! resolve_backtrace(Allocator allocator, void* addr, Win32_HANDLE process) { Symbol symbol; //Win32_DWORD image_type = load_modules()!; @@ -193,10 +193,10 @@ fn Backtrace! resolve_backtrace(void* addr, Win32_HANDLE process, Allocator allo ZString zname = (ZString)&name; if (!symGetLineFromAddr64(process, (Win32_ULONG64)addr - 1, &offset, &line)) { - backtrace.init((uptr)addr, zname.str_view(), module_name.str_view(), allocator: allocator); + backtrace.init(allocator, (uptr)addr, zname.str_view(), module_name.str_view()); return backtrace; } String filename = ((ZString)line.fileName).str_view(); - backtrace.init((uptr)addr, zname.str_view(), module_name.str_view(), file: filename, line: line.lineNumber, allocator: allocator); + backtrace.init(allocator, (uptr)addr, zname.str_view(), module_name.str_view(), file: filename, line: line.lineNumber); return backtrace; } diff --git a/lib2/std/os/win32/types.c3 b/lib7/std/os/win32/types.c3 similarity index 100% rename from lib2/std/os/win32/types.c3 rename to lib7/std/os/win32/types.c3 diff --git a/lib2/std/os/win32/wincon.c3 b/lib7/std/os/win32/wincon.c3 similarity index 100% rename from lib2/std/os/win32/wincon.c3 rename to lib7/std/os/win32/wincon.c3 diff --git a/lib2/std/os/win32/windef.c3 b/lib7/std/os/win32/windef.c3 similarity index 100% rename from lib2/std/os/win32/windef.c3 rename to lib7/std/os/win32/windef.c3 diff --git a/lib2/std/os/win32/winuser.c3 b/lib7/std/os/win32/winuser.c3 similarity index 100% rename from lib2/std/os/win32/winuser.c3 rename to lib7/std/os/win32/winuser.c3 diff --git a/lib2/std/os/win32/ws2def.c3 b/lib7/std/os/win32/ws2def.c3 similarity index 100% rename from lib2/std/os/win32/ws2def.c3 rename to lib7/std/os/win32/ws2def.c3 diff --git a/lib2/std/os/win32/wsa.c3 b/lib7/std/os/win32/wsa.c3 similarity index 100% rename from lib2/std/os/win32/wsa.c3 rename to lib7/std/os/win32/wsa.c3 diff --git a/lib2/std/sort/binarysearch.c3 b/lib7/std/sort/binarysearch.c3 similarity index 100% rename from lib2/std/sort/binarysearch.c3 rename to lib7/std/sort/binarysearch.c3 diff --git a/lib2/std/sort/countingsort.c3 b/lib7/std/sort/countingsort.c3 similarity index 100% rename from lib2/std/sort/countingsort.c3 rename to lib7/std/sort/countingsort.c3 diff --git a/lib2/std/sort/insertionsort.c3 b/lib7/std/sort/insertionsort.c3 similarity index 100% rename from lib2/std/sort/insertionsort.c3 rename to lib7/std/sort/insertionsort.c3 diff --git a/lib2/std/sort/quicksort.c3 b/lib7/std/sort/quicksort.c3 similarity index 100% rename from lib2/std/sort/quicksort.c3 rename to lib7/std/sort/quicksort.c3 diff --git a/lib2/std/sort/sort.c3 b/lib7/std/sort/sort.c3 similarity index 100% rename from lib2/std/sort/sort.c3 rename to lib7/std/sort/sort.c3 diff --git a/lib2/std/sort/sorted.c3 b/lib7/std/sort/sorted.c3 similarity index 100% rename from lib2/std/sort/sorted.c3 rename to lib7/std/sort/sorted.c3 diff --git a/lib2/std/text/i18n.c3 b/lib7/std/text/i18n.c3 similarity index 100% rename from lib2/std/text/i18n.c3 rename to lib7/std/text/i18n.c3 diff --git a/lib2/std/threads/buffered_channel.c3 b/lib7/std/threads/buffered_channel.c3 similarity index 100% rename from lib2/std/threads/buffered_channel.c3 rename to lib7/std/threads/buffered_channel.c3 diff --git a/lib2/std/threads/event/event_thread.c3 b/lib7/std/threads/event/event_thread.c3 similarity index 100% rename from lib2/std/threads/event/event_thread.c3 rename to lib7/std/threads/event/event_thread.c3 diff --git a/lib2/std/threads/fixed_pool.c3 b/lib7/std/threads/fixed_pool.c3 similarity index 100% rename from lib2/std/threads/fixed_pool.c3 rename to lib7/std/threads/fixed_pool.c3 diff --git a/lib2/std/threads/os/cpu.c3 b/lib7/std/threads/os/cpu.c3 similarity index 100% rename from lib2/std/threads/os/cpu.c3 rename to lib7/std/threads/os/cpu.c3 diff --git a/lib2/std/threads/os/thread_none.c3 b/lib7/std/threads/os/thread_none.c3 similarity index 100% rename from lib2/std/threads/os/thread_none.c3 rename to lib7/std/threads/os/thread_none.c3 diff --git a/lib2/std/threads/os/thread_posix.c3 b/lib7/std/threads/os/thread_posix.c3 similarity index 100% rename from lib2/std/threads/os/thread_posix.c3 rename to lib7/std/threads/os/thread_posix.c3 diff --git a/lib2/std/threads/os/thread_win32.c3 b/lib7/std/threads/os/thread_win32.c3 similarity index 100% rename from lib2/std/threads/os/thread_win32.c3 rename to lib7/std/threads/os/thread_win32.c3 diff --git a/lib2/std/threads/pool.c3 b/lib7/std/threads/pool.c3 similarity index 100% rename from lib2/std/threads/pool.c3 rename to lib7/std/threads/pool.c3 diff --git a/lib2/std/threads/thread.c3 b/lib7/std/threads/thread.c3 similarity index 100% rename from lib2/std/threads/thread.c3 rename to lib7/std/threads/thread.c3 diff --git a/lib2/std/threads/unbuffered_channel.c3 b/lib7/std/threads/unbuffered_channel.c3 similarity index 100% rename from lib2/std/threads/unbuffered_channel.c3 rename to lib7/std/threads/unbuffered_channel.c3 diff --git a/lib2/std/time/clock.c3 b/lib7/std/time/clock.c3 similarity index 100% rename from lib2/std/time/clock.c3 rename to lib7/std/time/clock.c3 diff --git a/lib2/std/time/datetime.c3 b/lib7/std/time/datetime.c3 similarity index 100% rename from lib2/std/time/datetime.c3 rename to lib7/std/time/datetime.c3 diff --git a/lib2/std/time/format.c3 b/lib7/std/time/format.c3 similarity index 100% rename from lib2/std/time/format.c3 rename to lib7/std/time/format.c3 diff --git a/lib2/std/time/os/time_darwin.c3 b/lib7/std/time/os/time_darwin.c3 similarity index 100% rename from lib2/std/time/os/time_darwin.c3 rename to lib7/std/time/os/time_darwin.c3 diff --git a/lib2/std/time/os/time_posix.c3 b/lib7/std/time/os/time_posix.c3 similarity index 100% rename from lib2/std/time/os/time_posix.c3 rename to lib7/std/time/os/time_posix.c3 diff --git a/lib2/std/time/os/time_win32.c3 b/lib7/std/time/os/time_win32.c3 similarity index 100% rename from lib2/std/time/os/time_win32.c3 rename to lib7/std/time/os/time_win32.c3 diff --git a/lib2/std/time/time.c3 b/lib7/std/time/time.c3 similarity index 100% rename from lib2/std/time/time.c3 rename to lib7/std/time/time.c3 diff --git a/src/build/build_options.c b/src/build/build_options.c index 857e00a1d..d66090630 100644 --- a/src/build/build_options.c +++ b/src/build/build_options.c @@ -1372,7 +1372,7 @@ static const char *check_dir(const char *path) { char original_path[PATH_MAX + 1]; if (!getcwd(original_path, PATH_MAX)) error_exit("Failed to store path."); - if (!dir_change(path)) error_exit("The path \"%s\" does not point to a valid directory.", path); + if (!dir_change(path)) error_exit("The path \"%s\" does not point to a valid directory from '%s'.", path, original_path); if (!dir_change(original_path)) FAIL_WITH_ERR("Failed to change path to %s.", original_path); return path; } diff --git a/test/src/test_suite_runner.c3 b/test/src/test_suite_runner.c3 index 00454be8d..39e795167 100644 --- a/test/src/test_suite_runner.c3 +++ b/test/src/test_suite_runner.c3 @@ -9,12 +9,13 @@ int success_count; Path start_cwd; Path test_dir; bool print_to_file; +String stdlib; fn void main(String[] args) { // Grab the name for `usage` String appname = args[0]; - if (args.len < 3 || args.len > 4) usage(appname); + if (args.len < 3) usage(appname); // Do we want the print to file variant print_to_file = !io::stdout().isatty(); @@ -37,8 +38,31 @@ fn void main(String[] args) // Ok we're done. compiler_path = path; - // Do we only run skipped? [Not implemented yet!] - bool only_skipped = args.len == 4; + bool only_skipped = false; + for (int i = 3; i < args.len; i++) + { + String arg = args[i]; + switch (arg) + { + case "-s": + case "--skipped": + only_skipped = true; + case "--stdlib": + if (i == args.len - 1 || args[i + 1].starts_with("-")) + { + arg_error_exit(appname, "Expected --stdlib to be followed by the path to the alternative standard library."); + } + stdlib = args[i + 1]; + i++; + if (!os::native_is_dir(stdlib)) + { + error_exit(appname, "Stdlib directory '%s' cannot be found.", stdlib); + } + stdlib = start_cwd.temp_append(stdlib).str_view()!!; + default: + arg_error_exit(appname, "Unknown option '%s'.", args[i]); + } + } if (only_skipped && args[3] != "-s" && args[3] != "--skipped") usage(appname); // Get the directory or file to test @@ -393,6 +417,12 @@ fn void test_file(Path file_path) cmdline.push(compiler_path.str_view()); cmdline.push("compile-only"); cmdline.push("--test"); + if (stdlib) + { + cmdline.push("--stdlib"); + cmdline.push(stdlib); + cmdline.push("--enable-new-generics"); + } cmdline.push("--llvm-out"); cmdline.push("."); foreach (file : settings.input_files) @@ -498,10 +528,11 @@ fn void! test_path(Path file_path) fn void usage(String appname) @noreturn { - io::printfn("Usage: %s [-s]", appname); + io::printfn("Usage: %s [options]", appname); io::printn(); io::printn("Options:"); io::printn(" -s, --skipped only run skipped tests"); + io::printn(" --stdlib override the path to stdlib"); libc::exit(0); } diff --git a/test/test_suite7/abi/aarch64_args.c3t b/test/test_suite7/abi/aarch64_args.c3t new file mode 100644 index 000000000..2de1b44db --- /dev/null +++ b/test/test_suite7/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_suite7/abi/aarch64_hfa_args.c3t b/test/test_suite7/abi/aarch64_hfa_args.c3t new file mode 100644 index 000000000..cc9311c92 --- /dev/null +++ b/test/test_suite7/abi/aarch64_hfa_args.c3t @@ -0,0 +1,32 @@ +// #target: macos-aarch64 +module test; +def Int8x16 = ichar[<16>]; +def 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_suite7/abi/aarch_ret_small_struct.c3t b/test/test_suite7/abi/aarch_ret_small_struct.c3t new file mode 100644 index 000000000..cf6ce3cad --- /dev/null +++ b/test/test_suite7/abi/aarch_ret_small_struct.c3t @@ -0,0 +1,45 @@ +// #target: macos-aarch64 +module test; +import std; + +extern fn Features query_features() @extern("sg_query_features"); +extern fn void set_features(Features); + +struct Features +{ + bool origin_top_left; + bool image_clamp_to_border; + bool mrt_independent_blend_state; + bool mrt_independent_write_mask; + bool storage_buffer; +} + +fn void main() +{ + Features fs = query_features(); + fs.storage_buffer = false; + set_features(fs); +} +/* #expect: test.ll + +declare i40 @sg_query_features() #0 + +declare void @set_features(i64) #0 + +define void @test.main() #0 { +entry: + %fs = alloca %Features, align 1 + %result = alloca %Features, align 1 + %tempcoerce = alloca i40, align 8 + %tempcoerce1 = alloca i64, align 8 + %0 = call i40 @sg_query_features() + store i40 %0, ptr %tempcoerce, align 8 + call void @llvm.memcpy.p0.p0.i32(ptr align 1 %result, ptr align 8 %tempcoerce, i32 5, i1 false) + call void @llvm.memcpy.p0.p0.i32(ptr align 1 %fs, ptr align 1 %result, i32 5, i1 false) + %ptradd = getelementptr inbounds i8, ptr %fs, i64 4 + store i8 0, ptr %ptradd, align 1 + call void @llvm.memcpy.p0.p0.i32(ptr align 8 %tempcoerce1, ptr align 1 %fs, i32 5, i1 false) + %1 = load i64, ptr %tempcoerce1, align 8 + call void @set_features(i64 %1) + ret void +} diff --git a/test/test_suite7/abi/avx512fp16-abi.c3t b/test/test_suite7/abi/avx512fp16-abi.c3t new file mode 100644 index 000000000..50a76a70e --- /dev/null +++ b/test/test_suite7/abi/avx512fp16-abi.c3t @@ -0,0 +1,166 @@ +// #target: macos-x64 +// #opt: --x86cpu=avx512 +module abi; + +struct Half1 { + float16 a; +} + +fn Half1 h1(float16 a) { + Half1 x; + x.a = a; + return x; +} + +struct Half2 { + float16 a; + float16 b; +} + +fn Half2 h2(float16 a, float16 b) { + Half2 x; + x.a = a; + x.b = b; + return x; +} + +struct Half3 { + float16 a; + float16 b; + float16 c; +} + +fn Half3 h3(float16 a, float16 b, float16 c) { + // CHECK: define{{.*}}<4 x half> @ + Half3 x; + x.a = a; + x.b = b; + x.c = c; + return x; +} + +struct Half4 { + float16 a; + float16 b; + float16 c; + float16 d; +} + +fn Half4 h4(float16 a, float16 b, float16 c, float16 d) { + Half4 x; + x.a = a; + x.b = b; + x.c = c; + x.d = d; + return x; +} + +struct Floathalf { + float a; + float16 b; +} + +fn Floathalf fh(float a, float16 b) { + Floathalf x; + x.a = a; + x.b = b; + return x; +} + +struct Floathalf2 { + float a; + float16 b; + float16 c; +} + +fn Floathalf2 fh2(float a, float16 b, float16 c) { + Floathalf2 x; + x.a = a; + x.b = b; + x.c = c; + return x; +} + +struct Halffloat { + float16 a; + float b; +} + +fn Halffloat hf(float16 a, float b) { + Halffloat x; + x.a = a; + x.b = b; + return x; +} + +struct Half2float { + float16 a; + float16 b; + float c; +} + +fn Half2float h2f(float16 a, float16 b, float c) { + Half2float x; + x.a = a; + x.b = b; + x.c = c; + return x; +} + +struct Floathalf3 { + float a; + float16 b; + float16 c; + float16 d; +} + +fn Floathalf3 fh3(float a, float16 b, float16 c, float16 d) { + Floathalf3 x; + x.a = a; + x.b = b; + x.c = c; + x.d = d; + return x; +} + +struct Half5 { + float16 a; + float16 b; + float16 c; + float16 d; + float16 e; +} + +fn Half5 h5(float16 a, float16 b, float16 c, float16 d, float16 e) { + Half5 x; + x.a = a; + x.b = b; + x.c = c; + x.d = d; + x.e = e; + return x; +} + +/* #expect: abi.ll + +%Half1 = type { half } +%Half2 = type { half, half } +%Half3 = type { half, half, half } +%Half4 = type { half, half, half, half } +%Floathalf = type { float, half } +%Floathalf2 = type { float, half, half } +%Halffloat = type { half, float } +%Half2float = type { half, half, float } +%Floathalf3 = type { float, half, half, half } +%Half5 = type { half, half, half, half, half } + +define half @abi.h1(half %0) +define <2 x half> @abi.h2(half %0, half %1) +define <4 x half> @abi.h3(half %0, half %1, half %2) +define <4 x half> @abi.h4(half %0, half %1, half %2, half %3) +define <4 x half> @abi.fh(float %0, half %1) +define <4 x half> @abi.fh2(float %0, half %1, half %2) +define <4 x half> @abi.hf(half %0, float %1) +define <4 x half> @abi.h2f(half %0, half %1, float %2) #0 { +define { <4 x half>, half } @abi.fh3(float %0, half %1, half %2, half %3) #0 { +define { <4 x half>, half } @abi.h5(half %0, half %1, half %2, half %3, half %4) #0 { diff --git a/test/test_suite7/abi/darwin64_avx.c3t b/test/test_suite7/abi/darwin64_avx.c3t new file mode 100644 index 000000000..66f0e7d09 --- /dev/null +++ b/test/test_suite7/abi/darwin64_avx.c3t @@ -0,0 +1,264 @@ +// #target: macos-x64 +// #opt: --x86cpu=avx1 +module test; + +def 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) + +def 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); +} + + +def 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); } + +extern 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 }); +} + +def 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>) #0 + +; Function Attrs: +declare void @f37(<8 x float>) #0 + +; Function Attrs: +define void @test.f39() #0 { +entry: + %0 = load <8 x float>, ptr @test.x38, align 32 + call void @f38(<8 x float> %0) + %1 = load <8 x float>, ptr @test.x37, align 32 + call void @f37(<8 x float> %1) + ret void +} + +; Function Attrs: +declare void @func40(ptr byval(%Two128) align 16) #0 + +; Function Attrs: +define void @test.func41(ptr byval(%Two128) align 16 %0) #0 { +entry: + call void @func40(ptr byval(%Two128) align 16 %0) + ret void +} + +; Function Attrs: +declare void @func42(ptr byval(%Sa) align 16) #0 + +; Function Attrs: +define void @test.func43(ptr byval(%Sa) align 16 %0) #0 { +entry: + call void @func42(ptr byval(%Sa) align 16 %0) + ret void +} + +; Function Attrs: +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 + +; Function Attrs: +define void @test.test46() #0 { +entry: + %x = alloca <2 x float>, align 8 + store <2 x float> , ptr %x, align 8 + %0 = load double, ptr %x, align 8 + %1 = load double, ptr %x, align 8 + %2 = load double, ptr %x, align 8 + %3 = load double, ptr %x, align 8 + %4 = load double, ptr %x, align 8 + %5 = load double, ptr %x, align 8 + %6 = load double, ptr %x, align 8 + %7 = load double, ptr %x, align 8 + call void @f46(double %0, double %1, double %2, double %3, double %4, double %5, double %6, double %7, ptr byval(<2 x float>) align 8 %x, ptr byval(<2 x float>) align 8 %x) + ret void +} + +; Function Attrs: +declare void @f47(i32, i32, i32, i32, i32, i32, i32) #0 + +; Function Attrs: +define void @test.test47(i32 %0, i32 %1) #0 { +entry: + %b = alloca %Vec47, align 4 + store i32 %1, ptr %b, align 4 + %2 = load i32, ptr %b, align 4 + call void @f47(i32 %0, i32 %0, i32 %0, i32 %0, i32 %0, i32 %0, i32 %2) + ret void +} + +; Function Attrs: +declare void @test49_helper(double, ...) #0 + +; Function Attrs: +define void @test.test49(double %0, double %1) #0 { +entry: + call void (double, ...) @test49_helper(double %0, double %1) + ret void +} + +; Function Attrs: +declare void @test52_helper(i32, ...) #0 + +; Function Attrs: +define void @test.test52() #0 { +entry: + %literal = alloca %Complex, align 8 + call void @llvm.memcpy.p0.p0.i32(ptr align 8 %literal, ptr align 8 @.__const, i32 16, i1 false) + %0 = load <8 x float>, ptr @test.x52, align 32 + %lo = load double, ptr %literal, align 8 + %ptradd = getelementptr inbounds i8, ptr %literal, i64 8 + %hi = load double, ptr %ptradd, align 8 + 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) + ret void +} + +; Function Attrs: +declare void @test54_helper(<8 x float>, ...) #0 + +; Function Attrs: +define void @test.test54() #0 { +entry: + %literal = alloca %Complex, align 8 + %literal1 = alloca %Complex, align 8 + call void @llvm.memcpy.p0.p0.i32(ptr align 8 %literal, ptr align 8 @.__const.6, i32 16, i1 false) + %0 = load <8 x float>, ptr @test.x54, align 32 + %1 = load <8 x float>, ptr @test.x54, align 32 + %lo = load double, ptr %literal, align 8 + %ptradd = getelementptr inbounds i8, ptr %literal, i64 8 + %hi = load double, ptr %ptradd, align 8 + 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 @llvm.memcpy.p0.p0.i32(ptr align 8 %literal1, ptr align 8 @.__const.7, i32 16, i1 false) + %2 = load <8 x float>, ptr @test.x54, align 32 + %3 = load <8 x float>, ptr @test.x54, align 32 + call void (<8 x float>, ...) @test54_helper(<8 x float> %2, <8 x float> %3, 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 %literal1) + ret void +} + +; Function Attrs: +declare void @f55(ptr byval(%St512) align 64) #0 + +; Function Attrs: +declare void @f56(ptr byval(<16 x float>) align 64) #0 + +; Function Attrs: +define void @test.f57() #0 { +entry: + call void @f55(ptr byval(%St512) align 64 @test.x55) + call void @f56(ptr byval(<16 x float>) align 64 @test.x56) + ret void +} + +; Function Attrs: +declare void @f58(ptr byval(%Two256) align 32) #0 + +; Function Attrs: +define void @test.f59(ptr byval(%Two256) align 32 %0) #0 { +entry: + call void @f58(ptr byval(%Two256) align 32 %0) + ret void +} + +; Function Attrs: +declare void @f60(ptr byval(%SAtwo256) align 32) #0 + +; Function Attrs: +define void @test.f61(ptr byval(%SAtwo256) align 32 %0) #0 { +entry: + call void @f60(ptr byval(%SAtwo256) align 32 %0) + ret void +} \ No newline at end of file diff --git a/test/test_suite7/abi/darwin64_avx512.c3t b/test/test_suite7/abi/darwin64_avx512.c3t new file mode 100644 index 000000000..367c4bbd9 --- /dev/null +++ b/test/test_suite7/abi/darwin64_avx512.c3t @@ -0,0 +1,133 @@ +// #target: macos-x64 +// #opt: --x86cpu=avx512 +module test; + +def Mm256 = float[<8>]; +def 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]+}}) +extern 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 }); +} + +extern 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 + +; Function Attrs: +declare void @f56(<16 x float>) #0 + +; Function Attrs: +define void @test.f57() #0 { +entry: + %0 = load <16 x float>, ptr @test.x55, align 64 + call void @f55(<16 x float> %0) + %1 = load <16 x float>, ptr @test.x56, align 64 + call void @f56(<16 x float> %1) + ret void +} + +; Function Attrs: +declare void @f58(ptr byval(%Two256) align 32) #0 + +; Function Attrs: +define void @test.f59(ptr byval(%Two256) align 32 %0) #0 { +entry: + call void @f58(ptr byval(%Two256) align 32 %0) + ret void +} + +; Function Attrs: +declare void @f60(ptr byval(%SAtwo256) align 32) #0 + +; Function Attrs: +define void @test.f61(ptr byval(%SAtwo256) align 32 %0) #0 { +entry: + call void @f60(ptr byval(%SAtwo256) align 32 %0) + ret void +} + +; Function Attrs: +declare void @f62_helper(i32, ...) #0 + +; Function Attrs: +define void @test.f62() #0 { +entry: + %literal = alloca %Complex, align 8 + call void @llvm.memcpy.p0.p0.i32(ptr align 8 %literal, ptr align 8 @.__const, i32 16, i1 false) + %0 = load <16 x float>, ptr @test.x62, align 64 + %lo = load double, ptr %literal, align 8 + %ptradd = getelementptr inbounds i8, ptr %literal, i64 8 + %hi = load double, ptr %ptradd, align 8 + call void (i32, ...) @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) + ret void +} + +; Function Attrs: +declare void @f64_helper(<16 x float>, ...) #0 + +; Function Attrs: +define void @test.f64() #0 { +entry: + %literal = alloca %Complex, align 8 + %literal1 = alloca %Complex, align 8 + call void @llvm.memcpy.p0.p0.i32(ptr align 8 %literal, ptr align 8 @.__const.4, i32 16, i1 false) + %0 = load <16 x float>, ptr @test.x64, align 64 + %1 = load <16 x float>, ptr @test.x64, align 64 + %lo = load double, ptr %literal, align 8 + %ptradd = getelementptr inbounds i8, ptr %literal, i64 8 + %hi = load double, ptr %ptradd, align 8 + call void (<16 x float>, ...) @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 @llvm.memcpy.p0.p0.i32(ptr align 8 %literal1, ptr align 8 @.__const.5, i32 16, i1 false) + %2 = load <16 x float>, ptr @test.x64, align 64 + %3 = load <16 x float>, ptr @test.x64, align 64 + call void (<16 x float>, ...) @f64_helper(<16 x float> %2, <16 x float> %3, 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 %literal1) + ret void +} diff --git a/test/test_suite7/abi/darwin64_sret.c3t b/test/test_suite7/abi/darwin64_sret.c3t new file mode 100644 index 000000000..29bd6d7a6 --- /dev/null +++ b/test/test_suite7/abi/darwin64_sret.c3t @@ -0,0 +1,19 @@ +// #target: macos-x64 +module foo; + +struct SimdDouble4x4 +{ + double[<4>][4] columns; +} + +fn SimdDouble4x4 ident(SimdDouble4x4 x) { + return x; +} + +/* #expect: foo.ll + +define void @foo.ident(ptr noalias sret(%SimdDouble4x4) align 32 %0, ptr byval(%SimdDouble4x4) align 32 %1) #0 { +entry: + call void @llvm.memcpy.p0.p0.i32(ptr align 32 %0, ptr align 32 %1, i32 128, i1 false) + ret void +} \ No newline at end of file diff --git a/test/test_suite7/abi/darwin64_sse.c3t b/test/test_suite7/abi/darwin64_sse.c3t new file mode 100644 index 000000000..67d9f7b43 --- /dev/null +++ b/test/test_suite7/abi/darwin64_sse.c3t @@ -0,0 +1,56 @@ +// #target: macos-x64 +// #opt: --x86cpu=sse4 +module test; + +def 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) + +def 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_suite7/abi/darwin_arg.c3t b/test/test_suite7/abi/darwin_arg.c3t new file mode 100644 index 000000000..6f71ab845 --- /dev/null +++ b/test/test_suite7/abi/darwin_arg.c3t @@ -0,0 +1,25 @@ +// #target: macos-x64 +module test; +struct Str +{ + union + { + float128 a; + long c; + } +} + +extern fn void d(Str s); +Str ss; +fn void f9122143() +{ + d(ss); +} + +/* #expect: test.ll + +declare void @d(i64, double) #0 + + %lo = load i64, ptr @test.ss, align 16 + %hi = load double, ptr getelementptr inbounds (i8, ptr @test.ss, i64 8), align 8 + call void @d(i64 %lo, double %hi) diff --git a/test/test_suite7/abi/darwin_return_boolarray.c3t b/test/test_suite7/abi/darwin_return_boolarray.c3t new file mode 100644 index 000000000..dbf7ace3c --- /dev/null +++ b/test/test_suite7/abi/darwin_return_boolarray.c3t @@ -0,0 +1,18 @@ +// #target: macos-x64 +module test; + +fn bool[2] get() { return { false, false }; } + +/* #expect: test.ll + +source_filename = "test" +target datalayout = "e-m:o-p270:32:32-p271:32 +target triple = "x86_64-apple +@.__const = private unnamed_addr constant [2 x i8] zeroinitializer, align 1 +define i16 @test.get() #0 { +entry: + %literal = alloca [2 x i8], align 1 + call void @llvm.memcpy.p0.p0.i32(ptr align 1 %literal, ptr align 1 @.__const, i32 2, i1 false) + %0 = load i16, ptr %literal, align 1 + ret i16 %0 +} diff --git a/test/test_suite7/abi/darwinx64_1.c3t b/test/test_suite7/abi/darwinx64_1.c3t new file mode 100644 index 000000000..7b75cffed --- /dev/null +++ b/test/test_suite7/abi/darwinx64_1.c3t @@ -0,0 +1,51 @@ +// #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 (0) {} 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_suite7/abi/darwinx64_2.c3t b/test/test_suite7/abi/darwinx64_2.c3t new file mode 100644 index 000000000..efc2d5f5a --- /dev/null +++ b/test/test_suite7/abi/darwinx64_2.c3t @@ -0,0 +1,180 @@ +// #target: macos-x64 +module test; +import std; + +struct St12 +{ + int a @align(16); +} +fn St12 f12_0() { while (1) {} } +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) {} } + +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. + +def 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; +} + +def V1i64 = ulong[<1>]; + +fn V1i64 f34(V1i64 arg) { return arg; } + + +def V1i64_2 = uint[<2>]; +fn V1i64_2 f35(V1i64_2 arg) { return arg+arg; } + +def 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(i32 %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_suite7/abi/linking_extern.c3t b/test/test_suite7/abi/linking_extern.c3t new file mode 100644 index 000000000..231fdae30 --- /dev/null +++ b/test/test_suite7/abi/linking_extern.c3t @@ -0,0 +1,24 @@ +// #target: macos-x64 +module abc; +extern fn void puts(char*); +macro void test() +{ + puts("b"); +} +module test; +import abc; +extern fn void puts(char*); +fn void main() +{ + puts("a"); + abc::test(); +} + +/* #expect: test.ll + +define void @test.main() #0 { +entry: + call void @puts(ptr @.str) + call void @puts(ptr @.str.1) + ret void +} diff --git a/test/test_suite7/abi/literal_load.c3t b/test/test_suite7/abi/literal_load.c3t new file mode 100644 index 000000000..66a71f63b --- /dev/null +++ b/test/test_suite7/abi/literal_load.c3t @@ -0,0 +1,30 @@ +// #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 = load i32, ptr %literal, align 4 + call void @blorg(i32 %0) + store i32 0, ptr %literal1, align 4 + %1 = load i32, ptr %literal1, align 4 + ret i32 %1 +} \ No newline at end of file diff --git a/test/test_suite7/abi/literal_load_aarch64.c3t b/test/test_suite7/abi/literal_load_aarch64.c3t new file mode 100644 index 000000000..d2ca84e40 --- /dev/null +++ b/test/test_suite7/abi/literal_load_aarch64.c3t @@ -0,0 +1,34 @@ +// #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 = load i32, ptr %literal, align 4 + %1 = zext i32 %0 to i64 + call void @blorg(i64 %1) + store i32 0, ptr %literal1, align 4 + %2 = load i32, ptr %literal1, align 4 + ret i32 %2 +} \ No newline at end of file diff --git a/test/test_suite7/abi/literal_load_mingw.c3t b/test/test_suite7/abi/literal_load_mingw.c3t new file mode 100644 index 000000000..291540b49 --- /dev/null +++ b/test/test_suite7/abi/literal_load_mingw.c3t @@ -0,0 +1,31 @@ +// #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 = load i32, ptr %literal, align 4 + call void @blorg(i32 %0) + store i32 0, ptr %literal1, align 4 + %1 = load i32, ptr %literal1, align 4 + ret i32 %1 +} diff --git a/test/test_suite7/abi/macho_section.c3t b/test/test_suite7/abi/macho_section.c3t new file mode 100644 index 000000000..49c5e75d4 --- /dev/null +++ b/test/test_suite7/abi/macho_section.c3t @@ -0,0 +1,15 @@ +// #target: macos-x64 +module test; + +int z @section("__TEXT,__custoection"); +int w @section("__TEXT,__custoection"); + +fn void main() +{ + int a = z + w; +} + +/* #expect: test.ll + +@test.z = local_unnamed_addr global i32 0, section "__TEXT,__custoection", align 4 +@test.w = local_unnamed_addr global i32 0, section "__TEXT,__custoection", align 4 diff --git a/test/test_suite7/abi/macho_section_attributes.c3 b/test/test_suite7/abi/macho_section_attributes.c3 new file mode 100644 index 000000000..b6e1f7707 --- /dev/null +++ b/test/test_suite7/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 defg @section("foo,b,c,d"); + diff --git a/test/test_suite7/abi/pass_large_aarch.c3t b/test/test_suite7/abi/pass_large_aarch.c3t new file mode 100644 index 000000000..52e15789a --- /dev/null +++ b/test/test_suite7/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_suite7/abi/riscv32-ilp32-abi.c3t b/test/test_suite7/abi/riscv32-ilp32-abi.c3t new file mode 100644 index 000000000..5fc8442d2 --- /dev/null +++ b/test/test_suite7/abi/riscv32-ilp32-abi.c3t @@ -0,0 +1,94 @@ +// #target: linux-riscv32 +module test; + +struct Tiny { + char a, b, c, d; +} + +struct Small { + int a; + int* b; +} + +struct Small_aligned +{ + long a; +} + +struct Large { + int a, b, c, d; +} + +// Scalars passed on the stack should not have signext/zeroext attributes +// (they are anyext). + +fn int f_scalar_stack_1(int a, long b, float c, double d, float128 e, + char f, ichar g, char h) { + return g + h; +} + +// Ensure that scalars passed on the stack are still determined correctly in +// the presence of large return values that consume a register due to the need +// to pass a pointer. + +fn Large f_scalar_stack_2(float a, long b, double c, float128 d, + char e, ichar f, char g) { + return {(int)a, e, f, g}; +} + +// Aggregates and >=XLen scalars passed on the stack should be lowered just as +// they would be if passed via registers. + +fn void f_scalar_stack_3(double a, long b, double c, long d, int e, + long f, float g, double h, float128 i) {} + +fn void f_agg_stack(double a, long b, double c, long d, Tiny e, + Small f, Small_aligned g, Large h) {} + +/* #expect: test.ll + + +define i32 @test.f_scalar_stack_1(i32 %0, i64 %1, float %2, double %3, fp128 %4, i8 zeroext %5, i8 %6, i8 %7) #0 { +entry: + %sext = sext i8 %6 to i32 + %zext = zext i8 %7 to i32 + %add = add i32 %sext, %zext + ret i32 %add +} + +; Function Attrs: +define void @test.f_scalar_stack_2(ptr noalias sret(%Large) align 4 %0, float %1, i64 %2, double %3, fp128 %4, i8 zeroext %5, i8 %6, i8 %7) #0 { +entry: + %literal = alloca %Large, align 4 + %fpsi = fptosi float %1 to i32 + store i32 %fpsi, ptr %literal, align 4 + %ptradd = getelementptr inbounds i8, ptr %literal, i32 4 + %zext = zext i8 %5 to i32 + store i32 %zext, ptr %ptradd, align 4 + %ptradd1 = getelementptr inbounds i8, ptr %literal, i32 8 + %sext = sext i8 %6 to i32 + store i32 %sext, ptr %ptradd1, align 4 + %ptradd2 = getelementptr inbounds i8, ptr %literal, i32 12 + %zext3 = zext i8 %7 to i32 + store i32 %zext3, ptr %ptradd2, align 4 + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %0, ptr align 4 %literal, i32 16, i1 false) + ret void +} + +; Function Attrs: +define void @test.f_scalar_stack_3(double %0, i64 %1, double %2, i64 %3, i32 %4, i64 %5, float %6, double %7, fp128 %8) #0 { +entry: + ret void +} + +; Function Attrs: +define void @test.f_agg_stack(double %0, i64 %1, double %2, i64 %3, i32 %4, [2 x i32] %5, i64 %6, ptr align 4 %7) #0 { +entry: + %e = alloca %Tiny, align 1 + %f = alloca %Small, align 4 + %g = alloca %Small_aligned, align 8 + store i32 %4, ptr %e, align 1 + store [2 x i32] %5, ptr %f, align 4 + store i64 %6, ptr %g, align 8 + ret void +} diff --git a/test/test_suite7/abi/riscv32-ilp32-ilp32f-abi-1.c3t b/test/test_suite7/abi/riscv32-ilp32-ilp32f-abi-1.c3t new file mode 100644 index 000000000..dedad0285 --- /dev/null +++ b/test/test_suite7/abi/riscv32-ilp32-ilp32f-abi-1.c3t @@ -0,0 +1,91 @@ +// #target: linux-riscv32 +module test; +struct Tiny { + char a, b, c, d; +} + +struct Small { + int a; + int* b; +} + +struct Small_aligned { + long a; +} + +struct Large { + int a, b, c, d; +} + +// Scalars passed on the stack should not have signext/zeroext attributes +// (they are anyext). + +fn int f_scalar_stack_1(int a, long b, int c, double d, float128 e, + char f, ichar g, char h) { + return g + h; +} + +// Ensure that scalars passed on the stack are still determined correctly in +// the presence of large return values that consume a register due to the need +// to pass a pointer. + +fn Large f_scalar_stack_2(int a, long b, double c, float128 d, + char e, ichar f, char g) { + return {a, e, f, g}; +} + +// Aggregates and >=XLen scalars passed on the stack should be lowered just as +// they would be if passed via registers. + +fn void f_scalar_stack_3(double a, long b, double c, long d, int e, + long f, int g, double h, float128 i) {} + +fn void f_agg_stack(double a, long b, double c, long d, Tiny e, + Small f, Small_aligned g, Large h) {} + +/* #expect: test.ll + +define i32 @test.f_scalar_stack_1(i32 %0, i64 %1, i32 %2, double %3, fp128 %4, i8 zeroext %5, i8 %6, i8 %7) #0 { +entry: + %sext = sext i8 %6 to i32 + %zext = zext i8 %7 to i32 + %add = add i32 %sext, %zext + ret i32 %add +} + +; Function Attrs: +define void @test.f_scalar_stack_2(ptr noalias sret(%Large) align 4 %0, i32 %1, i64 %2, double %3, fp128 %4, i8 zeroext %5, i8 %6, i8 %7) #0 { +entry: + %literal = alloca %Large, align 4 + store i32 %1, ptr %literal, align 4 + %ptradd = getelementptr inbounds i8, ptr %literal, i32 4 + %zext = zext i8 %5 to i32 + store i32 %zext, ptr %ptradd, align 4 + %ptradd1 = getelementptr inbounds i8, ptr %literal, i32 8 + %sext = sext i8 %6 to i32 + store i32 %sext, ptr %ptradd1, align 4 + %ptradd2 = getelementptr inbounds i8, ptr %literal, i32 12 + %zext3 = zext i8 %7 to i32 + store i32 %zext3, ptr %ptradd2, align 4 + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %0, ptr align 4 %literal, i32 16, i1 false) + ret void +} + +; Function Attrs: +define void @test.f_scalar_stack_3(double %0, i64 %1, double %2, i64 %3, i32 %4, i64 %5, i32 %6, double %7, fp128 %8) #0 { +entry: + ret void +} + +; Function Attrs: +define void @test.f_agg_stack(double %0, i64 %1, double %2, i64 %3, i32 %4, [2 x i32] %5, i64 %6, ptr align 4 %7) #0 { +entry: + %e = alloca %Tiny, align 1 + %f = alloca %Small, align 4 + %g = alloca %Small_aligned, align 8 + store i32 %4, ptr %e, align 1 + store [2 x i32] %5, ptr %f, align 4 + store i64 %6, ptr %g, align 8 + ret void +} + diff --git a/test/test_suite7/abi/riscv32-ilp32-ilp32f-abi-2.c3t b/test/test_suite7/abi/riscv32-ilp32-ilp32f-abi-2.c3t new file mode 100644 index 000000000..69cae96e6 --- /dev/null +++ b/test/test_suite7/abi/riscv32-ilp32-ilp32f-abi-2.c3t @@ -0,0 +1,57 @@ +// #target: linux-riscv32 +// #opt: --riscvfloat=float +module test; +struct Tiny { + char a, b, c, d; +} + +struct Small { + int a; + int* b; +} + +struct Small_aligned { + long a; +} + +struct Large { + int a, b, c, d; +} + +// Scalars passed on the stack should not have signext/zeroext attributes +// (they are anyext). + +fn int f_scalar_stack_1(int a, long b, int c, double d, float128 e, + char f, ichar g, char h) { + return g + h; +} + +// Ensure that scalars passed on the stack are still determined correctly in +// the presence of large return values that consume a register due to the need +// to pass a pointer. + +fn Large f_scalar_stack_2(int a, long b, double c, float128 d, + char e, ichar f, char g) { + return {a, e, f, g}; +} + +// Aggregates and >=XLen scalars passed on the stack should be lowered just as +// they would be if passed via registers. + +fn void f_scalar_stack_3(double a, long b, double c, long d, int e, + long f, int g, double h, float128 i) {} + +fn void f_agg_stack(double a, long b, double c, long d, Tiny e, + Small f, Small_aligned g, Large h) {} + +/* #expect: test.ll + +define i32 @test.f_scalar_stack_1(i32 %0, i64 %1, i32 %2, double %3, fp128 %4, i8 zeroext %5, i8 %6, i8 %7) + +define void @test.f_scalar_stack_2(ptr noalias sret(%Large) align 4 %0, i32 %1, i64 %2, double %3, fp128 %4, i8 zeroext %5, i8 %6, i8 %7) + +define void @test.f_scalar_stack_3(double %0, i64 %1, double %2, i64 %3, i32 %4, i64 %5, i32 %6, double %7, fp128 %8) + +define void @test.f_agg_stack(double %0, i64 %1, double %2, i64 %3, i32 %4, [2 x i32] %5, i64 %6, ptr align 4 %7) + + diff --git a/test/test_suite7/abi/riscv32-ilp32-ilp32f-ilp32d-abi-1.c3t b/test/test_suite7/abi/riscv32-ilp32-ilp32f-ilp32d-abi-1.c3t new file mode 100644 index 000000000..6bdf8968d --- /dev/null +++ b/test/test_suite7/abi/riscv32-ilp32-ilp32f-ilp32d-abi-1.c3t @@ -0,0 +1,526 @@ +// #target: linux-riscv32 +module test; + + +fn void f_void() {} + +// Scalar arguments and return values smaller than the word size are extended +// according to the sign of their type, up to 32 bits + +fn bool f_scalar_0(bool x) { return x; } + +fn ichar f_scalar_1(ichar x) { return x; } + +fn char f_scalar_2(char x) { return x; } + +fn int f_scalar_3(int x) { return x; } + +fn long f_scalar_4(long x) { return x; } + +fn int128 f_scalar_5(int128 x) { return x; } + +fn float f_fp_scalar_1(float x) { return x; } + +fn double f_fp_scalar_2(double x) { return x; } + +// Scalars larger than 2*xlen are passed/returned indirect. However, the +// RISC-V LLVM backend can handle this fine, so the function doesn't need to +// be modified. + +fn float128 f_fp_scalar_3(float128 x) { return x; } + +// Aggregates <= 2*xlen may be passed in registers, so will be coerced to +// integer arguments. The rules for return are the same. + +struct Tiny { + char a, b, c, d; +} + +fn void f_agg_tiny(Tiny x) { + x.a += x.b; + x.c += x.d; +} + +fn Tiny f_agg_tiny_ret() { + return {1, 2, 3, 4}; +} + +fn void f_vec_tiny_v4i8(char[<4>] x) { + x[0] = x[1]; + x[2] = x[3]; +} + +fn char[<4>] f_vec_tiny_v4i8_ret() { + return {1, 2, 3, 4}; +} + +fn void f_vec_tiny_v1i32(int[<1>] x) { + x[0] = 114; +} + +fn int[<1>] f_vec_tiny_v1i32_ret() { + return {1}; +} + +struct Small { + int a; + int* b; +} + +fn void f_agg_small(Small x) { + x.a += *x.b; + x.b = &x.a; +} + +fn Small f_agg_small_ret() { + return {1, null}; +} + + +fn void f_vec_small_v8i8(char[<8>] x) { + x[0] = x[7]; +} + +fn char[<8>] f_vec_small_v8i8_ret() { + return {1, 2, 3, 4, 5, 6, 7, 8}; +} + +fn void f_vec_small_v1i64(long[<1>] x) { + x[0] = 114; +} + +fn long[<1>] f_vec_small_v1i64_ret() { + return {1}; +} + +// Aggregates of 2*xlen size and 2*xlen alignment should be coerced to a +// single 2*xlen-sized argument, to ensure that alignment can be maintained if +// passed on the stack. + +struct Small_aligned { + long a; +} + +fn void f_agg_small_aligned(Small_aligned x) { + x.a += x.a; +} + +fn Small_aligned f_agg_small_aligned_ret(Small_aligned x) { + return {10}; +} + +// Aggregates greater > 2*xlen will be passed and returned indirectly +struct Large { + int a, b, c, d; +} + +fn void f_agg_large(Large x) { + x.a = x.b + x.c + x.d; +} + +// The address where the struct should be written to will be the first +// argument +fn Large f_agg_large_ret(int i, ichar j) { + return {1, 2, 3, 4}; +} + +fn void f_vec_large_v16i8(char[<16>] x) { + x[0] = x[7]; +} + +fn char[<16>] f_vec_large_v16i8_ret() { + return {1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8}; +} + +// Scalars passed on the stack should not have signext/zeroext attributes +// (they are anyext). + +fn int f_scalar_stack_1(Tiny a, Small b, Small_aligned c, + Large d, char e, ichar f, char g, ichar h) { + return g + h; +} + +// Ensure that scalars passed on the stack are still determined correctly in +// the presence of large return values that consume a register due to the need +// to pass a pointer. + +fn Large f_scalar_stack_2(int a, long b, long c, float128 d, + char e, ichar f, char g) +{ + return {a, e, f, g}; +} + +fn float128 f_scalar_stack_4(int a, long b, long c, float128 d, + char e, ichar f, char g) { + return d; +} + +// Aggregates and >=XLen scalars passed on the stack should be lowered just as +// they would be if passed via registers. + +fn void f_scalar_stack_5(double a, long b, double c, long d, int e, + long f, float g, double h, float128 i) {} + +fn void f_agg_stack(double a, long b, double c, long d, Tiny e, + Small f, Small_aligned g, Large h) {} + +// Ensure that ABI lowering happens as expected for vararg calls. For RV32 +// with the base integer calling convention there will be no observable +// differences in the lowered IR for a call with varargs vs without. + +extern fn int f_va_callee(int, ...); + +fn void f_va_caller() { + f_va_callee(1, 2, 3, 4.0, 5.0, (Tiny){6, 7, 8, 9}, + (Small){10, null}, (Small_aligned){11}, + (Large){12, 13, 14, 15}); +} + + +/* #expect: test.ll + +define void @test.f_void() #0 { +entry: + ret void +} + +; Function Attrs: +define zeroext i8 @test.f_scalar_0(i8 zeroext %0) #0 { +entry: + ret i8 %0 +} + +; Function Attrs: +define signext i8 @test.f_scalar_1(i8 signext %0) #0 { +entry: + ret i8 %0 +} + +; Function Attrs: +define zeroext i8 @test.f_scalar_2(i8 zeroext %0) #0 { +entry: + ret i8 %0 +} + +; Function Attrs: +define i32 @test.f_scalar_3(i32 %0) #0 { +entry: + ret i32 %0 +} + +; Function Attrs: +define i64 @test.f_scalar_4(i64 %0) #0 { +entry: + ret i64 %0 +} + +; Function Attrs: +define i128 @test.f_scalar_5(i128 %0) #0 { +entry: + ret i128 %0 +} + +; Function Attrs: +define float @test.f_fp_scalar_1(float %0) #0 { +entry: + ret float %0 +} + +; Function Attrs: +define double @test.f_fp_scalar_2(double %0) #0 { +entry: + ret double %0 +} + +; Function Attrs: +define fp128 @test.f_fp_scalar_3(fp128 %0) #0 { +entry: + ret fp128 %0 +} + +; Function Attrs: +define void @test.f_agg_tiny(i32 %0) #0 { +entry: + %x = alloca %Tiny, align 1 + store i32 %0, ptr %x, align 1 + %1 = load i8, ptr %x, align 1 + %ptradd = getelementptr inbounds i8, ptr %x, i32 1 + %2 = load i8, ptr %ptradd, align 1 + %add = add i8 %1, %2 + store i8 %add, ptr %x, align 1 + %ptradd1 = getelementptr inbounds i8, ptr %x, i32 2 + %3 = load i8, ptr %ptradd1, align 1 + %ptradd2 = getelementptr inbounds i8, ptr %x, i32 3 + %4 = load i8, ptr %ptradd2, align 1 + %add3 = add i8 %3, %4 + store i8 %add3, ptr %ptradd1, align 1 + ret void +} + +; Function Attrs: +define i32 @test.f_agg_tiny_ret() #0 { +entry: + %literal = alloca %Tiny, align 1 + call void @llvm.memcpy.p0.p0.i32(ptr align 1 %literal, ptr align 1 @.__const, i32 4, i1 false) + %0 = load i32, ptr %literal, align 1 + ret i32 %0 +} + +; Function Attrs: +define void @test.f_vec_tiny_v4i8(i32 %0) #0 { +entry: + %x = alloca <4 x i8>, align 4 + store i32 %0, ptr %x, align 4 + %1 = load <4 x i8>, ptr %x, align 4 + %2 = load <4 x i8>, ptr %x, align 4 + %3 = extractelement <4 x i8> %2, i32 1 + %elemset = insertelement <4 x i8> %1, i8 %3, i32 0 + store <4 x i8> %elemset, ptr %x, align 4 + %4 = load <4 x i8>, ptr %x, align 4 + %5 = load <4 x i8>, ptr %x, align 4 + %6 = extractelement <4 x i8> %5, i32 3 + %elemset1 = insertelement <4 x i8> %4, i8 %6, i32 2 + store <4 x i8> %elemset1, ptr %x, align 4 + ret void +} + +; Function Attrs: +define i32 @test.f_vec_tiny_v4i8_ret() #0 { +entry: + %taddr = alloca <4 x i8>, align 4 + store <4 x i8> , ptr %taddr, align 4 + %0 = load i32, ptr %taddr, align 4 + ret i32 %0 +} + +; Function Attrs: +define void @test.f_vec_tiny_v1i32(i32 %0) #0 { +entry: + %x = alloca <1 x i32>, align 4 + store i32 %0, ptr %x, align 4 + %1 = load <1 x i32>, ptr %x, align 4 + %elemset = insertelement <1 x i32> %1, i32 114, i32 0 + store <1 x i32> %elemset, ptr %x, align 4 + ret void +} + +; Function Attrs: +define i32 @test.f_vec_tiny_v1i32_ret() #0 { +entry: + %taddr = alloca <1 x i32>, align 4 + store <1 x i32> + %0 = load i32, ptr %taddr, align 4 + ret i32 %0 +} + +; Function Attrs: +define void @test.f_agg_small([2 x i32] %0) #0 { +entry: + %x = alloca %Small, align 4 + store [2 x i32] %0, ptr %x, align 4 + %1 = load i32, ptr %x, align 4 + %ptradd = getelementptr inbounds i8, ptr %x, i32 4 + %2 = load ptr, ptr %ptradd, align 4 + %3 = load i32, ptr %2, align 4 + %add = add i32 %1, %3 + store i32 %add, ptr %x, align 4 + %ptradd1 = getelementptr inbounds i8, ptr %x, i32 4 + store ptr %x, ptr %ptradd1, align 4 + ret void +} + +; Function Attrs: +define [2 x i32] @test.f_agg_small_ret() #0 { +entry: + %literal = alloca %Small, align 4 + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %literal, ptr align 4 @.__const.1, i32 8, i1 false) + %0 = load [2 x i32], ptr %literal, align 4 + ret [2 x i32] %0 +} + +; Function Attrs: +define void @test.f_vec_small_v8i8(i64 %0) #0 { +entry: + %x = alloca <8 x i8>, align 8 + store i64 %0, ptr %x, align 8 + %1 = load <8 x i8>, ptr %x, align 8 + %2 = load <8 x i8>, ptr %x, align 8 + %3 = extractelement <8 x i8> %2, i32 7 + %elemset = insertelement <8 x i8> %1, i8 %3, i32 0 + store <8 x i8> %elemset, ptr %x, align 8 + ret void +} + +; Function Attrs: +define i64 @test.f_vec_small_v8i8_ret() #0 { +entry: + %taddr = alloca <8 x i8>, align 8 + store <8 x i8> , ptr %taddr, align 8 + %0 = load i64, ptr %taddr, align 8 + ret i64 %0 +} + +; Function Attrs: +define void @test.f_vec_small_v1i64(i64 %0) #0 { +entry: + %x = alloca <1 x i64>, align 8 + store i64 %0, ptr %x, align 8 + %1 = load <1 x i64>, ptr %x, align 8 + %elemset = insertelement <1 x i64> %1, i64 114, i32 0 + store <1 x i64> %elemset, ptr %x, align 8 + ret void +} + +; Function Attrs: +define i64 @test.f_vec_small_v1i64_ret() #0 { +entry: + %taddr = alloca <1 x i64>, align 8 + store <1 x i64> + %0 = load i64, ptr %taddr, align 8 + ret i64 %0 +} + +; Function Attrs: +define void @test.f_agg_small_aligned(i64 %0) #0 { +entry: + %x = alloca %Small_aligned, align 8 + store i64 %0, ptr %x, align 8 + %1 = load i64, ptr %x, align 8 + %2 = load i64, ptr %x, align 8 + %add = add i64 %1, %2 + store i64 %add, ptr %x, align 8 + ret void +} + +; Function Attrs: +define i64 @test.f_agg_small_aligned_ret(i64 %0) #0 { +entry: + %x = alloca %Small_aligned, align 8 + %literal = alloca %Small_aligned, align 8 + store i64 %0, ptr %x, align 8 + call void @llvm.memcpy.p0.p0.i32(ptr align 8 %literal, ptr align 8 @.__const.2, i32 8, i1 false) + %1 = load i64, ptr %literal, align 8 + ret i64 %1 +} + +; Function Attrs: +define void @test.f_agg_large(ptr align 4 %0) #0 { +entry: + %ptradd = getelementptr inbounds i8, ptr %0, i32 4 + %1 = load i32, ptr %ptradd, align 4 + %ptradd1 = getelementptr inbounds i8, ptr %0, i32 8 + %2 = load i32, ptr %ptradd1, align 4 + %add = add i32 %1, %2 + %ptradd2 = getelementptr inbounds i8, ptr %0, i32 12 + %3 = load i32, ptr %ptradd2, align 4 + %add3 = add i32 %add, %3 + store i32 %add3, ptr %0, align 4 + ret void +} + +; Function Attrs: +define void @test.f_agg_large_ret(ptr noalias sret(%Large) align 4 %0, i32 %1, i8 signext %2) #0 { +entry: + %literal = alloca %Large, align 4 + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %literal, ptr align 4 @.__const.3, i32 16, i1 false) + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %0, ptr align 4 %literal, i32 16, i1 false) + ret void +} + +; Function Attrs: +define void @test.f_vec_large_v16i8(ptr align 16 %0) #0 { +entry: + %1 = load <16 x i8>, ptr %0, align 16 + %2 = load <16 x i8>, ptr %0, align 16 + %3 = extractelement <16 x i8> %2, i32 7 + %elemset = insertelement <16 x i8> %1, i8 %3, i32 0 + store <16 x i8> %elemset, ptr %0, align 16 + ret void +} + +; Function Attrs: +define void @test.f_vec_large_v16i8_ret(ptr noalias sret(<16 x i8>) align 16 %0) #0 { +entry: + store <16 x i8> , ptr %0, align 16 + ret void +} + +; Function Attrs: +define i32 @test.f_scalar_stack_1(i32 %0, [2 x i32] %1, i64 %2, ptr align 4 %3, i8 zeroext %4, i8 signext %5, i8 %6, i8 %7) #0 { +entry: + %a = alloca %Tiny, align 1 + %b = alloca %Small, align 4 + %c = alloca %Small_aligned, align 8 + store i32 %0, ptr %a, align 1 + store [2 x i32] %1, ptr %b, align 4 + store i64 %2, ptr %c, align 8 + %zext = zext i8 %6 to i32 + %sext = sext i8 %7 to i32 + %add = add i32 %zext, %sext + ret i32 %add +} + +; Function Attrs: +define void @test.f_scalar_stack_2(ptr noalias sret(%Large) align 4 %0, i32 %1, i64 %2, i64 %3, fp128 %4, i8 zeroext %5, i8 %6, i8 %7) #0 { +entry: + %literal = alloca %Large, align 4 + store i32 %1, ptr %literal, align 4 + %ptradd = getelementptr inbounds i8, ptr %literal, i32 4 + %zext = zext i8 %5 to i32 + store i32 %zext, ptr %ptradd, align 4 + %ptradd1 = getelementptr inbounds i8, ptr %literal, i32 8 + %sext = sext i8 %6 to i32 + store i32 %sext, ptr %ptradd1, align 4 + %ptradd2 = getelementptr inbounds i8, ptr %literal, i32 12 + %zext3 = zext i8 %7 to i32 + store i32 %zext3, ptr %ptradd2, align 4 + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %0, ptr align 4 %literal, i32 16, i1 false) + ret void +} + +; Function Attrs: +define fp128 @test.f_scalar_stack_4(i32 %0, i64 %1, i64 %2, fp128 %3, i8 zeroext %4, i8 %5, i8 %6) #0 { +entry: + ret fp128 %3 +} + +; Function Attrs: +define void @test.f_scalar_stack_5(double %0, i64 %1, double %2, i64 %3, i32 %4, i64 %5, float %6, double %7, fp128 %8) #0 { +entry: + ret void +} + +; Function Attrs: +define void @test.f_agg_stack(double %0, i64 %1, double %2, i64 %3, i32 %4, [2 x i32] %5, i64 %6, ptr align 4 %7) #0 { +entry: + %e = alloca %Tiny, align 1 + %f = alloca %Small, align 4 + %g = alloca %Small_aligned, align 8 + store i32 %4, ptr %e, align 1 + store [2 x i32] %5, ptr %f, align 4 + store i64 %6, ptr %g, align 8 + ret void +} + +; Function Attrs: +declare i32 @f_va_callee(i32, ...) #0 + +; Function Attrs: +define void @test.f_va_caller() #0 { +entry: + %literal = alloca %Tiny, align 1 + %literal1 = alloca %Small, align 4 + %literal2 = alloca %Small_aligned, align 8 + %literal3 = alloca %Large, align 4 + %indirectarg = alloca %Large, align 4 + call void @llvm.memcpy.p0.p0.i32(ptr align 1 %literal, ptr align 1 @.__const.4, i32 4, i1 false) + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %literal1, ptr align 4 @.__const.5, i32 8, i1 false) + call void @llvm.memcpy.p0.p0.i32(ptr align 8 %literal2, ptr align 8 @.__const.6, i32 8, i1 false) + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %literal3, ptr align 4 @.__const.7, i32 16, i1 false) + %0 = load i32, ptr %literal, align 1 + %1 = load [2 x i32], ptr %literal1, align 4 + %2 = load i64, ptr %literal2, align 8 + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %indirectarg, ptr align 4 %literal3, i32 16, i1 false) + %3 = call i32 (i32, ...) @f_va_callee(i32 1, i32 2, i32 3, double 4.000000e+00, double 5.000000e+00, i32 %0, [2 x i32] %1, i64 %2, ptr align 4 %indirectarg) + ret void +} \ No newline at end of file diff --git a/test/test_suite7/abi/riscv32-ilp32-ilp32f-ilp32d-abi-2.c3t b/test/test_suite7/abi/riscv32-ilp32-ilp32f-ilp32d-abi-2.c3t new file mode 100644 index 000000000..bfec66560 --- /dev/null +++ b/test/test_suite7/abi/riscv32-ilp32-ilp32f-ilp32d-abi-2.c3t @@ -0,0 +1,518 @@ +// #target: linux-riscv32 +// #opt: --riscvfloat=float +module test; + + +fn void f_void() {} + +// Scalar arguments and return values smaller than the word size are extended +// according to the sign of their type, up to 32 bits + +fn bool f_scalar_0(bool x) { return x; } + +fn ichar f_scalar_1(ichar x) { return x; } + +fn char f_scalar_2(char x) { return x; } + +fn int f_scalar_3(int x) { return x; } + +fn long f_scalar_4(long x) { return x; } + +fn int128 f_scalar_5(int128 x) { return x; } + +fn float f_fp_scalar_1(float x) { return x; } + +fn double f_fp_scalar_2(double x) { return x; } + +// Scalars larger than 2*xlen are passed/returned indirect. However, the +// RISC-V LLVM backend can handle this fine, so the function doesn't need to +// be modified. + +fn float128 f_fp_scalar_3(float128 x) { return x; } + +// Aggregates <= 2*xlen may be passed in registers, so will be coerced to +// integer arguments. The rules for return are the same. + +struct Tiny { + char a, b, c, d; +} + +fn void f_agg_tiny(Tiny x) { + x.a += x.b; + x.c += x.d; +} + +fn Tiny f_agg_tiny_ret() { + return {1, 2, 3, 4}; +} + +fn void f_vec_tiny_v4i8(char[<4>] x) { + x[0] = x[1]; + x[2] = x[3]; +} + +fn char[<4>] f_vec_tiny_v4i8_ret() { + return {1, 2, 3, 4}; +} + +fn void f_vec_tiny_v1i32(int[<1>] x) { + x[0] = 114; +} + +fn int[<1>] f_vec_tiny_v1i32_ret() { + return {1}; +} + +struct Small { + int a; + int* b; +} + +fn void f_agg_small(Small x) { + x.a += *x.b; + x.b = &x.a; +} + +fn Small f_agg_small_ret() { + return {1, null}; +} + + +fn void f_vec_small_v8i8(char[<8>] x) { + x[0] = x[7]; +} + +fn char[<8>] f_vec_small_v8i8_ret() { + return {1, 2, 3, 4, 5, 6, 7, 8}; +} + +fn void f_vec_small_v1i64(long[<1>] x) { + x[0] = 114; +} + +fn long[<1>] f_vec_small_v1i64_ret() { + return {1}; +} + +// Aggregates of 2*xlen size and 2*xlen alignment should be coerced to a +// single 2*xlen-sized argument, to ensure that alignment can be maintained if +// passed on the stack. + +struct Small_aligned { + long a; +} + +fn void f_agg_small_aligned(Small_aligned x) { + x.a += x.a; +} + +fn Small_aligned f_agg_small_aligned_ret(Small_aligned x) { + return {10}; +} + +// Aggregates greater > 2*xlen will be passed and returned indirectly +struct Large { + int a, b, c, d; +} + +fn void f_agg_large(Large x) { + x.a = x.b + x.c + x.d; +} + +// The address where the struct should be written to will be the first +// argument +fn Large f_agg_large_ret(int i, ichar j) { + return {1, 2, 3, 4}; +} + +fn void f_vec_large_v16i8(char[<16>] x) { + x[0] = x[7]; +} + +fn char[<16>] f_vec_large_v16i8_ret() { + return {1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8}; +} + +// Scalars passed on the stack should not have signext/zeroext attributes +// (they are anyext). + +fn int f_scalar_stack_1(Tiny a, Small b, Small_aligned c, + Large d, char e, ichar f, char g, ichar h) { + return g + h; +} + +// Ensure that scalars passed on the stack are still determined correctly in +// the presence of large return values that consume a register due to the need +// to pass a pointer. + +fn Large f_scalar_stack_2(int a, long b, long c, float128 d, + char e, ichar f, char g) +{ + return {a, e, f, g}; +} + +fn float128 f_scalar_stack_4(int a, long b, long c, float128 d, + char e, ichar f, char g) { + return d; +} + +// Aggregates and >=XLen scalars passed on the stack should be lowered just as +// they would be if passed via registers. + +fn void f_scalar_stack_5(double a, long b, double c, long d, int e, + long f, float g, double h, float128 i) {} + +fn void f_agg_stack(double a, long b, double c, long d, Tiny e, + Small f, Small_aligned g, Large h) {} + +// Ensure that ABI lowering happens as expected for vararg calls. For RV32 +// with the base integer calling convention there will be no observable +// differences in the lowered IR for a call with varargs vs without. + +extern fn int f_va_callee(int, ...); + +fn void f_va_caller() { + f_va_callee(1, 2, 3, 4.0, 5.0, (Tiny){6, 7, 8, 9}, + (Small){10, null}, (Small_aligned){11}, + (Large){12, 13, 14, 15}); +} + + +/* #expect: test.ll + +define void @test.f_void() + + +define signext i8 @test.f_scalar_1(i8 signext %0) #0 { +entry: + ret i8 %0 +} + +; Function Attrs: +define zeroext i8 @test.f_scalar_2(i8 zeroext %0) #0 { +entry: + ret i8 %0 +} + +; Function Attrs: +define i32 @test.f_scalar_3(i32 %0) #0 { +entry: + ret i32 %0 +} + +; Function Attrs: +define i64 @test.f_scalar_4(i64 %0) #0 { +entry: + ret i64 %0 +} + +; Function Attrs: +define i128 @test.f_scalar_5(i128 %0) #0 { +entry: + ret i128 %0 +} + +; Function Attrs: +define float @test.f_fp_scalar_1(float %0) #0 { +entry: + ret float %0 +} + +; Function Attrs: +define double @test.f_fp_scalar_2(double %0) #0 { +entry: + ret double %0 +} + +; Function Attrs: +define fp128 @test.f_fp_scalar_3(fp128 %0) #0 { +entry: + ret fp128 %0 +} + +; Function Attrs: +define void @test.f_agg_tiny(i32 %0) #0 { +entry: + %x = alloca %Tiny, align 1 + store i32 %0, ptr %x, align 1 + %1 = load i8, ptr %x, align 1 + %ptradd = getelementptr inbounds i8, ptr %x, i32 1 + %2 = load i8, ptr %ptradd, align 1 + %add = add i8 %1, %2 + store i8 %add, ptr %x, align 1 + %ptradd1 = getelementptr inbounds i8, ptr %x, i32 2 + %3 = load i8, ptr %ptradd1, align 1 + %ptradd2 = getelementptr inbounds i8, ptr %x, i32 3 + %4 = load i8, ptr %ptradd2, align 1 + %add3 = add i8 %3, %4 + store i8 %add3, ptr %ptradd1, align 1 + ret void +} + +; Function Attrs: +define i32 @test.f_agg_tiny_ret() #0 { +entry: + %literal = alloca %Tiny, align 1 + call void @llvm.memcpy.p0.p0.i32(ptr align 1 %literal, ptr align 1 @.__const, i32 4, i1 false) + %0 = load i32, ptr %literal, align 1 + ret i32 %0 +} + +; Function Attrs: +define void @test.f_vec_tiny_v4i8(i32 %0) #0 { +entry: + %x = alloca <4 x i8>, align 4 + store i32 %0, ptr %x, align 4 + %1 = load <4 x i8>, ptr %x, align 4 + %2 = load <4 x i8>, ptr %x, align 4 + %3 = extractelement <4 x i8> %2, i32 1 + %elemset = insertelement <4 x i8> %1, i8 %3, i32 0 + store <4 x i8> %elemset, ptr %x, align 4 + %4 = load <4 x i8>, ptr %x, align 4 + %5 = load <4 x i8>, ptr %x, align 4 + %6 = extractelement <4 x i8> %5, i32 3 + %elemset1 = insertelement <4 x i8> %4, i8 %6, i32 2 + store <4 x i8> %elemset1, ptr %x, align 4 + ret void +} + +; Function Attrs: +define i32 @test.f_vec_tiny_v4i8_ret() #0 { +entry: + %taddr = alloca <4 x i8>, align 4 + store <4 x i8> , ptr %taddr, align 4 + %0 = load i32, ptr %taddr, align 4 + ret i32 %0 +} + +; Function Attrs: +define void @test.f_vec_tiny_v1i32(i32 %0) #0 { +entry: + %x = alloca <1 x i32>, align 4 + store i32 %0, ptr %x, align 4 + %1 = load <1 x i32>, ptr %x, align 4 + %elemset = insertelement <1 x i32> %1, i32 114, i32 0 + store <1 x i32> %elemset, ptr %x, align 4 + ret void +} + +; Function Attrs: +define i32 @test.f_vec_tiny_v1i32_ret() #0 { +entry: + %taddr = alloca <1 x i32>, align 4 + store <1 x i32> + %0 = load i32, ptr %taddr, align 4 + ret i32 %0 +} + +; Function Attrs: +define void @test.f_agg_small([2 x i32] %0) #0 { +entry: + %x = alloca %Small, align 4 + store [2 x i32] %0, ptr %x, align 4 + %1 = load i32, ptr %x, align 4 + %ptradd = getelementptr inbounds i8, ptr %x, i32 4 + %2 = load ptr, ptr %ptradd, align 4 + %3 = load i32, ptr %2, align 4 + %add = add i32 %1, %3 + store i32 %add, ptr %x, align 4 + %ptradd1 = getelementptr inbounds i8, ptr %x, i32 4 + store ptr %x, ptr %ptradd1, align 4 + ret void +} + +; Function Attrs: +define [2 x i32] @test.f_agg_small_ret() #0 { +entry: + %literal = alloca %Small, align 4 + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %literal, ptr align 4 @.__const.1, i32 8, i1 false) + %0 = load [2 x i32], ptr %literal, align 4 + ret [2 x i32] %0 +} + +; Function Attrs: +define void @test.f_vec_small_v8i8(i64 %0) #0 { +entry: + %x = alloca <8 x i8>, align 8 + store i64 %0, ptr %x, align 8 + %1 = load <8 x i8>, ptr %x, align 8 + %2 = load <8 x i8>, ptr %x, align 8 + %3 = extractelement <8 x i8> %2, i32 7 + %elemset = insertelement <8 x i8> %1, i8 %3, i32 0 + store <8 x i8> %elemset, ptr %x, align 8 + ret void +} + +; Function Attrs: +define i64 @test.f_vec_small_v8i8_ret() #0 { +entry: + %taddr = alloca <8 x i8>, align 8 + store <8 x i8> , ptr %taddr, align 8 + %0 = load i64, ptr %taddr, align 8 + ret i64 %0 +} + +; Function Attrs: +define void @test.f_vec_small_v1i64(i64 %0) #0 { +entry: + %x = alloca <1 x i64>, align 8 + store i64 %0, ptr %x, align 8 + %1 = load <1 x i64>, ptr %x, align 8 + %elemset = insertelement <1 x i64> %1, i64 114, i32 0 + store <1 x i64> %elemset, ptr %x, align 8 + ret void +} + +; Function Attrs: +define i64 @test.f_vec_small_v1i64_ret() #0 { +entry: + %taddr = alloca <1 x i64>, align 8 + store <1 x i64> + %0 = load i64, ptr %taddr, align 8 + ret i64 %0 +} + +; Function Attrs: +define void @test.f_agg_small_aligned(i64 %0) #0 { +entry: + %x = alloca %Small_aligned, align 8 + store i64 %0, ptr %x, align 8 + %1 = load i64, ptr %x, align 8 + %2 = load i64, ptr %x, align 8 + %add = add i64 %1, %2 + store i64 %add, ptr %x, align 8 + ret void +} + +; Function Attrs: +define i64 @test.f_agg_small_aligned_ret(i64 %0) #0 { +entry: + %x = alloca %Small_aligned, align 8 + %literal = alloca %Small_aligned, align 8 + store i64 %0, ptr %x, align 8 + call void @llvm.memcpy.p0.p0.i32(ptr align 8 %literal, ptr align 8 @.__const.2, i32 8, i1 false) + %1 = load i64, ptr %literal, align 8 + ret i64 %1 +} + +; Function Attrs: +define void @test.f_agg_large(ptr align 4 %0) #0 { +entry: + %ptradd = getelementptr inbounds i8, ptr %0, i32 4 + %1 = load i32, ptr %ptradd, align 4 + %ptradd1 = getelementptr inbounds i8, ptr %0, i32 8 + %2 = load i32, ptr %ptradd1, align 4 + %add = add i32 %1, %2 + %ptradd2 = getelementptr inbounds i8, ptr %0, i32 12 + %3 = load i32, ptr %ptradd2, align 4 + %add3 = add i32 %add, %3 + store i32 %add3, ptr %0, align 4 + ret void +} + +; Function Attrs: +define void @test.f_agg_large_ret(ptr noalias sret(%Large) align 4 %0, i32 %1, i8 signext %2) #0 { +entry: + %literal = alloca %Large, align 4 + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %literal, ptr align 4 @.__const.3, i32 16, i1 false) + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %0, ptr align 4 %literal, i32 16, i1 false) + ret void +} + +; Function Attrs: +define void @test.f_vec_large_v16i8(ptr align 16 %0) #0 { +entry: + %1 = load <16 x i8>, ptr %0, align 16 + %2 = load <16 x i8>, ptr %0, align 16 + %3 = extractelement <16 x i8> %2, i32 7 + %elemset = insertelement <16 x i8> %1, i8 %3, i32 0 + store <16 x i8> %elemset, ptr %0, align 16 + ret void +} + +; Function Attrs: +define void @test.f_vec_large_v16i8_ret(ptr noalias sret(<16 x i8>) align 16 %0) #0 { +entry: + store <16 x i8> , ptr %0, align 16 + ret void +} + +; Function Attrs: +define i32 @test.f_scalar_stack_1(i32 %0, [2 x i32] %1, i64 %2, ptr align 4 %3, i8 zeroext %4, i8 signext %5, i8 %6, i8 %7) #0 { +entry: + %a = alloca %Tiny, align 1 + %b = alloca %Small, align 4 + %c = alloca %Small_aligned, align 8 + store i32 %0, ptr %a, align 1 + store [2 x i32] %1, ptr %b, align 4 + store i64 %2, ptr %c, align 8 + %zext = zext i8 %6 to i32 + %sext = sext i8 %7 to i32 + %add = add i32 %zext, %sext + ret i32 %add +} + +; Function Attrs: +define void @test.f_scalar_stack_2(ptr noalias sret(%Large) align 4 %0, i32 %1, i64 %2, i64 %3, fp128 %4, i8 zeroext %5, i8 %6, i8 %7) #0 { +entry: + %literal = alloca %Large, align 4 + store i32 %1, ptr %literal, align 4 + %ptradd = getelementptr inbounds i8, ptr %literal, i32 4 + %zext = zext i8 %5 to i32 + store i32 %zext, ptr %ptradd, align 4 + %ptradd1 = getelementptr inbounds i8, ptr %literal, i32 8 + %sext = sext i8 %6 to i32 + store i32 %sext, ptr %ptradd1, align 4 + %ptradd2 = getelementptr inbounds i8, ptr %literal, i32 12 + %zext3 = zext i8 %7 to i32 + store i32 %zext3, ptr %ptradd2, align 4 + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %0, ptr align 4 %literal, i32 16, i1 false) + ret void +} + +; Function Attrs: +define fp128 @test.f_scalar_stack_4(i32 %0, i64 %1, i64 %2, fp128 %3, i8 zeroext %4, i8 %5, i8 %6) #0 { +entry: + ret fp128 %3 +} + +; Function Attrs: +define void @test.f_scalar_stack_5(double %0, i64 %1, double %2, i64 %3, i32 %4, i64 %5, float %6, double %7, fp128 %8) #0 { +entry: + ret void +} + +; Function Attrs: +define void @test.f_agg_stack(double %0, i64 %1, double %2, i64 %3, i32 %4, [2 x i32] %5, i64 %6, ptr align 4 %7) #0 { +entry: + %e = alloca %Tiny, align 1 + %f = alloca %Small, align 4 + %g = alloca %Small_aligned, align 8 + store i32 %4, ptr %e, align 1 + store [2 x i32] %5, ptr %f, align 4 + store i64 %6, ptr %g, align 8 + ret void +} + +; Function Attrs: +declare i32 @f_va_callee(i32, ...) #0 + +; Function Attrs: +define void @test.f_va_caller() #0 { +entry: + %literal = alloca %Tiny, align 1 + %literal1 = alloca %Small, align 4 + %literal2 = alloca %Small_aligned, align 8 + %literal3 = alloca %Large, align 4 + %indirectarg = alloca %Large, align 4 + call void @llvm.memcpy.p0.p0.i32(ptr align 1 %literal, ptr align 1 @.__const.4, i32 4, i1 false) + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %literal1, ptr align 4 @.__const.5, i32 8, i1 false) + call void @llvm.memcpy.p0.p0.i32(ptr align 8 %literal2, ptr align 8 @.__const.6, i32 8, i1 false) + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %literal3, ptr align 4 @.__const.7, i32 16, i1 false) + %0 = load i32, ptr %literal, align 1 + %1 = load [2 x i32], ptr %literal1, align 4 + %2 = load i64, ptr %literal2, align 8 + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %indirectarg, ptr align 4 %literal3, i32 16, i1 false) + %3 = call i32 (i32, ...) @f_va_callee(i32 1, i32 2, i32 3, double 4.000000e+00, double 5.000000e+00, i32 %0, [2 x i32] %1, i64 %2, ptr align 4 %indirectarg) + ret void +} diff --git a/test/test_suite7/abi/riscv32-ilp32-ilp32f-ilp32d-abi-3.c3t b/test/test_suite7/abi/riscv32-ilp32-ilp32f-ilp32d-abi-3.c3t new file mode 100644 index 000000000..8bb9b31a8 --- /dev/null +++ b/test/test_suite7/abi/riscv32-ilp32-ilp32f-ilp32d-abi-3.c3t @@ -0,0 +1,527 @@ +// #target: linux-riscv32 +// #opt: --riscvfloat=double +module test; + + +fn void f_void() {} + +// Scalar arguments and return values smaller than the word size are extended +// according to the sign of their type, up to 32 bits + +fn bool f_scalar_0(bool x) { return x; } + +fn ichar f_scalar_1(ichar x) { return x; } + +fn char f_scalar_2(char x) { return x; } + +fn int f_scalar_3(int x) { return x; } + +fn long f_scalar_4(long x) { return x; } + +fn int128 f_scalar_5(int128 x) { return x; } + +fn float f_fp_scalar_1(float x) { return x; } + +fn double f_fp_scalar_2(double x) { return x; } + +// Scalars larger than 2*xlen are passed/returned indirect. However, the +// RISC-V LLVM backend can handle this fine, so the function doesn't need to +// be modified. + +fn float128 f_fp_scalar_3(float128 x) { return x; } + +// Aggregates <= 2*xlen may be passed in registers, so will be coerced to +// integer arguments. The rules for return are the same. + +struct Tiny { + char a, b, c, d; +} + +fn void f_agg_tiny(Tiny x) { + x.a += x.b; + x.c += x.d; +} + +fn Tiny f_agg_tiny_ret() { + return {1, 2, 3, 4}; +} + +fn void f_vec_tiny_v4i8(char[<4>] x) { + x[0] = x[1]; + x[2] = x[3]; +} + +fn char[<4>] f_vec_tiny_v4i8_ret() { + return {1, 2, 3, 4}; +} + +fn void f_vec_tiny_v1i32(int[<1>] x) { + x[0] = 114; +} + +fn int[<1>] f_vec_tiny_v1i32_ret() { + return {1}; +} + +struct Small { + int a; + int* b; +} + +fn void f_agg_small(Small x) { + x.a += *x.b; + x.b = &x.a; +} + +fn Small f_agg_small_ret() { + return {1, null}; +} + + +fn void f_vec_small_v8i8(char[<8>] x) { + x[0] = x[7]; +} + +fn char[<8>] f_vec_small_v8i8_ret() { + return {1, 2, 3, 4, 5, 6, 7, 8}; +} + +fn void f_vec_small_v1i64(long[<1>] x) { + x[0] = 114; +} + +fn long[<1>] f_vec_small_v1i64_ret() { + return {1}; +} + +// Aggregates of 2*xlen size and 2*xlen alignment should be coerced to a +// single 2*xlen-sized argument, to ensure that alignment can be maintained if +// passed on the stack. + +struct Small_aligned { + long a; +} + +fn void f_agg_small_aligned(Small_aligned x) { + x.a += x.a; +} + +fn Small_aligned f_agg_small_aligned_ret(Small_aligned x) { + return {10}; +} + +// Aggregates greater > 2*xlen will be passed and returned indirectly +struct Large { + int a, b, c, d; +} + +fn void f_agg_large(Large x) { + x.a = x.b + x.c + x.d; +} + +// The address where the struct should be written to will be the first +// argument +fn Large f_agg_large_ret(int i, ichar j) { + return {1, 2, 3, 4}; +} + +fn void f_vec_large_v16i8(char[<16>] x) { + x[0] = x[7]; +} + +fn char[<16>] f_vec_large_v16i8_ret() { + return {1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8}; +} + +// Scalars passed on the stack should not have signext/zeroext attributes +// (they are anyext). + +fn int f_scalar_stack_1(Tiny a, Small b, Small_aligned c, + Large d, char e, ichar f, char g, ichar h) { + return g + h; +} + +// Ensure that scalars passed on the stack are still determined correctly in +// the presence of large return values that consume a register due to the need +// to pass a pointer. + +fn Large f_scalar_stack_2(int a, long b, long c, float128 d, + char e, ichar f, char g) +{ + return {a, e, f, g}; +} + +fn float128 f_scalar_stack_4(int a, long b, long c, float128 d, + char e, ichar f, char g) { + return d; +} + +// Aggregates and >=XLen scalars passed on the stack should be lowered just as +// they would be if passed via registers. + +fn void f_scalar_stack_5(double a, long b, double c, long d, int e, + long f, float g, double h, float128 i) {} + +fn void f_agg_stack(double a, long b, double c, long d, Tiny e, + Small f, Small_aligned g, Large h) {} + +// Ensure that ABI lowering happens as expected for vararg calls. For RV32 +// with the base integer calling convention there will be no observable +// differences in the lowered IR for a call with varargs vs without. + +extern fn int f_va_callee(int, ...); + +fn void f_va_caller() { + f_va_callee(1, 2, 3, 4.0, 5.0, (Tiny){6, 7, 8, 9}, + (Small){10, null}, (Small_aligned){11}, + (Large){12, 13, 14, 15}); +} + + +/* #expect: test.ll + +define void @test.f_void() #0 { +entry: + ret void +} + +; Function Attrs: +define zeroext i8 @test.f_scalar_0(i8 zeroext %0) #0 { +entry: + ret i8 %0 +} + +; Function Attrs: +define signext i8 @test.f_scalar_1(i8 signext %0) #0 { +entry: + ret i8 %0 +} + +; Function Attrs: +define zeroext i8 @test.f_scalar_2(i8 zeroext %0) #0 { +entry: + ret i8 %0 +} + +; Function Attrs: +define i32 @test.f_scalar_3(i32 %0) #0 { +entry: + ret i32 %0 +} + +; Function Attrs: +define i64 @test.f_scalar_4(i64 %0) #0 { +entry: + ret i64 %0 +} + +; Function Attrs: +define i128 @test.f_scalar_5(i128 %0) #0 { +entry: + ret i128 %0 +} + +; Function Attrs: +define float @test.f_fp_scalar_1(float %0) #0 { +entry: + ret float %0 +} + +; Function Attrs: +define double @test.f_fp_scalar_2(double %0) #0 { +entry: + ret double %0 +} + +; Function Attrs: +define fp128 @test.f_fp_scalar_3(fp128 %0) #0 { +entry: + ret fp128 %0 +} + +; Function Attrs: +define void @test.f_agg_tiny(i32 %0) #0 { +entry: + %x = alloca %Tiny, align 1 + store i32 %0, ptr %x, align 1 + %1 = load i8, ptr %x, align 1 + %ptradd = getelementptr inbounds i8, ptr %x, i32 1 + %2 = load i8, ptr %ptradd, align 1 + %add = add i8 %1, %2 + store i8 %add, ptr %x, align 1 + %ptradd1 = getelementptr inbounds i8, ptr %x, i32 2 + %3 = load i8, ptr %ptradd1, align 1 + %ptradd2 = getelementptr inbounds i8, ptr %x, i32 3 + %4 = load i8, ptr %ptradd2, align 1 + %add3 = add i8 %3, %4 + store i8 %add3, ptr %ptradd1, align 1 + ret void +} + +; Function Attrs: +define i32 @test.f_agg_tiny_ret() #0 { +entry: + %literal = alloca %Tiny, align 1 + call void @llvm.memcpy.p0.p0.i32(ptr align 1 %literal, ptr align 1 @.__const, i32 4, i1 false) + %0 = load i32, ptr %literal, align 1 + ret i32 %0 +} + +; Function Attrs: +define void @test.f_vec_tiny_v4i8(i32 %0) #0 { +entry: + %x = alloca <4 x i8>, align 4 + store i32 %0, ptr %x, align 4 + %1 = load <4 x i8>, ptr %x, align 4 + %2 = load <4 x i8>, ptr %x, align 4 + %3 = extractelement <4 x i8> %2, i32 1 + %elemset = insertelement <4 x i8> %1, i8 %3, i32 0 + store <4 x i8> %elemset, ptr %x, align 4 + %4 = load <4 x i8>, ptr %x, align 4 + %5 = load <4 x i8>, ptr %x, align 4 + %6 = extractelement <4 x i8> %5, i32 3 + %elemset1 = insertelement <4 x i8> %4, i8 %6, i32 2 + store <4 x i8> %elemset1, ptr %x, align 4 + ret void +} + +; Function Attrs: +define i32 @test.f_vec_tiny_v4i8_ret() #0 { +entry: + %taddr = alloca <4 x i8>, align 4 + store <4 x i8> , ptr %taddr, align 4 + %0 = load i32, ptr %taddr, align 4 + ret i32 %0 +} + +; Function Attrs: +define void @test.f_vec_tiny_v1i32(i32 %0) #0 { +entry: + %x = alloca <1 x i32>, align 4 + store i32 %0, ptr %x, align 4 + %1 = load <1 x i32>, ptr %x, align 4 + %elemset = insertelement <1 x i32> %1, i32 114, i32 0 + store <1 x i32> %elemset, ptr %x, align 4 + ret void +} + +; Function Attrs: +define i32 @test.f_vec_tiny_v1i32_ret() #0 { +entry: + %taddr = alloca <1 x i32>, align 4 + store <1 x i32> + %0 = load i32, ptr %taddr, align 4 + ret i32 %0 +} + +; Function Attrs: +define void @test.f_agg_small([2 x i32] %0) #0 { +entry: + %x = alloca %Small, align 4 + store [2 x i32] %0, ptr %x, align 4 + %1 = load i32, ptr %x, align 4 + %ptradd = getelementptr inbounds i8, ptr %x, i32 4 + %2 = load ptr, ptr %ptradd, align 4 + %3 = load i32, ptr %2, align 4 + %add = add i32 %1, %3 + store i32 %add, ptr %x, align 4 + %ptradd1 = getelementptr inbounds i8, ptr %x, i32 4 + store ptr %x, ptr %ptradd1, align 4 + ret void +} + +; Function Attrs: +define [2 x i32] @test.f_agg_small_ret() #0 { +entry: + %literal = alloca %Small, align 4 + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %literal, ptr align 4 @.__const.1, i32 8, i1 false) + %0 = load [2 x i32], ptr %literal, align 4 + ret [2 x i32] %0 +} + +; Function Attrs: +define void @test.f_vec_small_v8i8(i64 %0) #0 { +entry: + %x = alloca <8 x i8>, align 8 + store i64 %0, ptr %x, align 8 + %1 = load <8 x i8>, ptr %x, align 8 + %2 = load <8 x i8>, ptr %x, align 8 + %3 = extractelement <8 x i8> %2, i32 7 + %elemset = insertelement <8 x i8> %1, i8 %3, i32 0 + store <8 x i8> %elemset, ptr %x, align 8 + ret void +} + +; Function Attrs: +define i64 @test.f_vec_small_v8i8_ret() #0 { +entry: + %taddr = alloca <8 x i8>, align 8 + store <8 x i8> , ptr %taddr, align 8 + %0 = load i64, ptr %taddr, align 8 + ret i64 %0 +} + +; Function Attrs: +define void @test.f_vec_small_v1i64(i64 %0) #0 { +entry: + %x = alloca <1 x i64>, align 8 + store i64 %0, ptr %x, align 8 + %1 = load <1 x i64>, ptr %x, align 8 + %elemset = insertelement <1 x i64> %1, i64 114, i32 0 + store <1 x i64> %elemset, ptr %x, align 8 + ret void +} + +; Function Attrs: +define i64 @test.f_vec_small_v1i64_ret() #0 { +entry: + %taddr = alloca <1 x i64>, align 8 + store <1 x i64> + %0 = load i64, ptr %taddr, align 8 + ret i64 %0 +} + +; Function Attrs: +define void @test.f_agg_small_aligned(i64 %0) #0 { +entry: + %x = alloca %Small_aligned, align 8 + store i64 %0, ptr %x, align 8 + %1 = load i64, ptr %x, align 8 + %2 = load i64, ptr %x, align 8 + %add = add i64 %1, %2 + store i64 %add, ptr %x, align 8 + ret void +} + +; Function Attrs: +define i64 @test.f_agg_small_aligned_ret(i64 %0) #0 { +entry: + %x = alloca %Small_aligned, align 8 + %literal = alloca %Small_aligned, align 8 + store i64 %0, ptr %x, align 8 + call void @llvm.memcpy.p0.p0.i32(ptr align 8 %literal, ptr align 8 @.__const.2, i32 8, i1 false) + %1 = load i64, ptr %literal, align 8 + ret i64 %1 +} + +; Function Attrs: +define void @test.f_agg_large(ptr align 4 %0) #0 { +entry: + %ptradd = getelementptr inbounds i8, ptr %0, i32 4 + %1 = load i32, ptr %ptradd, align 4 + %ptradd1 = getelementptr inbounds i8, ptr %0, i32 8 + %2 = load i32, ptr %ptradd1, align 4 + %add = add i32 %1, %2 + %ptradd2 = getelementptr inbounds i8, ptr %0, i32 12 + %3 = load i32, ptr %ptradd2, align 4 + %add3 = add i32 %add, %3 + store i32 %add3, ptr %0, align 4 + ret void +} + +; Function Attrs: +define void @test.f_agg_large_ret(ptr noalias sret(%Large) align 4 %0, i32 %1, i8 signext %2) #0 { +entry: + %literal = alloca %Large, align 4 + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %literal, ptr align 4 @.__const.3, i32 16, i1 false) + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %0, ptr align 4 %literal, i32 16, i1 false) + ret void +} + +; Function Attrs: +define void @test.f_vec_large_v16i8(ptr align 16 %0) #0 { +entry: + %1 = load <16 x i8>, ptr %0, align 16 + %2 = load <16 x i8>, ptr %0, align 16 + %3 = extractelement <16 x i8> %2, i32 7 + %elemset = insertelement <16 x i8> %1, i8 %3, i32 0 + store <16 x i8> %elemset, ptr %0, align 16 + ret void +} + +; Function Attrs: +define void @test.f_vec_large_v16i8_ret(ptr noalias sret(<16 x i8>) align 16 %0) #0 { +entry: + store <16 x i8> , ptr %0, align 16 + ret void +} + +; Function Attrs: +define i32 @test.f_scalar_stack_1(i32 %0, [2 x i32] %1, i64 %2, ptr align 4 %3, i8 zeroext %4, i8 signext %5, i8 %6, i8 %7) #0 { +entry: + %a = alloca %Tiny, align 1 + %b = alloca %Small, align 4 + %c = alloca %Small_aligned, align 8 + store i32 %0, ptr %a, align 1 + store [2 x i32] %1, ptr %b, align 4 + store i64 %2, ptr %c, align 8 + %zext = zext i8 %6 to i32 + %sext = sext i8 %7 to i32 + %add = add i32 %zext, %sext + ret i32 %add +} + +; Function Attrs: +define void @test.f_scalar_stack_2(ptr noalias sret(%Large) align 4 %0, i32 %1, i64 %2, i64 %3, fp128 %4, i8 zeroext %5, i8 %6, i8 %7) #0 { +entry: + %literal = alloca %Large, align 4 + store i32 %1, ptr %literal, align 4 + %ptradd = getelementptr inbounds i8, ptr %literal, i32 4 + %zext = zext i8 %5 to i32 + store i32 %zext, ptr %ptradd, align 4 + %ptradd1 = getelementptr inbounds i8, ptr %literal, i32 8 + %sext = sext i8 %6 to i32 + store i32 %sext, ptr %ptradd1, align 4 + %ptradd2 = getelementptr inbounds i8, ptr %literal, i32 12 + %zext3 = zext i8 %7 to i32 + store i32 %zext3, ptr %ptradd2, align 4 + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %0, ptr align 4 %literal, i32 16, i1 false) + ret void +} + +; Function Attrs: +define fp128 @test.f_scalar_stack_4(i32 %0, i64 %1, i64 %2, fp128 %3, i8 zeroext %4, i8 %5, i8 %6) #0 { +entry: + ret fp128 %3 +} + +; Function Attrs: +define void @test.f_scalar_stack_5(double %0, i64 %1, double %2, i64 %3, i32 %4, i64 %5, float %6, double %7, fp128 %8) #0 { +entry: + ret void +} + +; Function Attrs: +define void @test.f_agg_stack(double %0, i64 %1, double %2, i64 %3, i32 %4, [2 x i32] %5, i64 %6, ptr align 4 %7) #0 { +entry: + %e = alloca %Tiny, align 1 + %f = alloca %Small, align 4 + %g = alloca %Small_aligned, align 8 + store i32 %4, ptr %e, align 1 + store [2 x i32] %5, ptr %f, align 4 + store i64 %6, ptr %g, align 8 + ret void +} + +; Function Attrs: +declare i32 @f_va_callee(i32, ...) #0 + +; Function Attrs: +define void @test.f_va_caller() #0 { +entry: + %literal = alloca %Tiny, align 1 + %literal1 = alloca %Small, align 4 + %literal2 = alloca %Small_aligned, align 8 + %literal3 = alloca %Large, align 4 + %indirectarg = alloca %Large, align 4 + call void @llvm.memcpy.p0.p0.i32(ptr align 1 %literal, ptr align 1 @.__const.4, i32 4, i1 false) + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %literal1, ptr align 4 @.__const.5, i32 8, i1 false) + call void @llvm.memcpy.p0.p0.i32(ptr align 8 %literal2, ptr align 8 @.__const.6, i32 8, i1 false) + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %literal3, ptr align 4 @.__const.7, i32 16, i1 false) + %0 = load i32, ptr %literal, align 1 + %1 = load [2 x i32], ptr %literal1, align 4 + %2 = load i64, ptr %literal2, align 8 + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %indirectarg, ptr align 4 %literal3, i32 16, i1 false) + %3 = call i32 (i32, ...) @f_va_callee(i32 1, i32 2, i32 3, double 4.000000e+00, double 5.000000e+00, i32 %0, [2 x i32] %1, i64 %2, ptr align 4 %indirectarg) + ret void +} diff --git a/test/test_suite7/abi/riscv32-ilp32d-abi.c3t b/test/test_suite7/abi/riscv32-ilp32d-abi.c3t new file mode 100644 index 000000000..e696a4994 --- /dev/null +++ b/test/test_suite7/abi/riscv32-ilp32d-abi.c3t @@ -0,0 +1,505 @@ +// #target: linux-riscv32 +// #opt: --riscvfloat=double +module test; +// Verify that the tracking of used GPRs and FPRs works correctly by checking +// that small integers are sign/zero extended when passed in registers. + +// Doubles are passed in FPRs, so argument 'i' will be passed zero-extended +// because it will be passed in a GPR. + +fn void f_fpr_tracking(double a, double b, double c, double d, double e, double f, + double g, double h, char i) {} + +// Check that fp, fp+fp, and int+fp structs are lowered correctly. These will +// be passed in FPR, FPR+FPR, or GPR+FPR regs if sufficient registers are +// available the widths are <= XLEN and FLEN, and should be expanded to +// separate arguments in IR. They are passed by the same rules for returns, +// but will be lowered to simple two-element structs if necessary (as LLVM IR +// functions cannot return multiple values). + +// A struct containing just one floating-point real is passed as though it +// were a standalone floating-point real. + +struct Double_s { double f; } + +fn void f_double_s_arg(Double_s a) {} + +fn Double_s f_ret_double_s() { + return {1.0}; +} + +// Check that structs containing two floating point values (FLEN <= width) are +// expanded provided sufficient FPRs are available. + +struct Double_double_s { double f; double g; } +struct Double_float_s { double f; float g; } + +fn void f_double_double_s_arg(Double_double_s a) {} + +fn Double_double_s f_ret_double_double_s() { + return {1.0, 2.0}; +} + +fn void f_double_float_s_arg(Double_float_s a) {} + +fn Double_float_s f_ret_double_float_s() { + return {1.0, 2.0}; +} + +fn void f_double_double_s_arg_insufficient_fprs(float a, double b, double c, double d, + double e, double f, double g, Double_double_s h) {} + +// Check that structs containing int+double values are expanded, provided +// sufficient FPRs and GPRs are available. The integer components are neither +// sign or zero-extended. + +struct Double_int8_s { double f; ichar i; } +struct Double_uint8_s { double f; char i; } +struct Double_int32_s { double f; int i; } +struct Double_int64_s { double f; long i; } + +fn void f_double_int8_s_arg(Double_int8_s a) {} + +fn Double_int8_s f_ret_double_int8_s() { + return {1.0, 2}; +} + +fn void f_double_uint8_s_arg(Double_uint8_s a) {} + +fn Double_uint8_s f_ret_double_uint8_s() { + return {1.0, 2}; +} + +fn void f_double_int32_s_arg(Double_int32_s a) {} + +fn Double_int32_s f_ret_double_int32_s() { + return {1.0, 2}; +} + +fn void f_double_int64_s_arg(Double_int64_s a) {} + +fn Double_int64_s f_ret_double_int64_s() { + return {1.0, 2}; +} + + + +fn void f_double_int8_s_arg_insufficient_gprs(int a, int b, int c, int d, int e, + int f, int g, int h, Double_int8_s i) {} + +fn void f_struct_double_int8_insufficient_fprs(float a, double b, double c, double d, + double e, double f, double g, double h, Double_int8_s i) {} + +// Test single or two-element structs that need flattening. e.g. those +// containing nested structs, doubles in small arrays, zero-length structs etc. + +struct Doublearr1_s { double[1] a; } + +fn void f_doublearr1_s_arg(Doublearr1_s a) {} + +fn Doublearr1_s f_ret_doublearr1_s() { + return {{1.0}}; +} + +struct Doublearr2_s { double[2] a; } + +fn void f_doublearr2_s_arg(Doublearr2_s a) {} + +fn Doublearr2_s f_ret_doublearr2_s() { + return {{1.0, 2.0}}; +} + +struct Inner { double[1] f; } +struct Doublearr2_tricky1_s { Inner[2] g; } + +fn void f_doublearr2_tricky1_s_arg(Doublearr2_tricky1_s a) {} + +fn Doublearr2_tricky1_s f_ret_doublearr2_tricky1_s() { + return {{{{1.0}}, {{2.0}}}}; +} + +// Test structs that should be passed according to the normal integer calling +// convention. + +struct Int_double_int_s { int a; double b; int c; } + +fn void f_int_double_int_s_arg(Int_double_int_s a) {} + +fn Int_double_int_s f_ret_int_double_int_s() { + return {1, 2.0, 3}; +} + +struct Int64_double_s { long a; double b; } + +fn void f_int64_double_s_arg(Int64_double_s a) {} + +fn Int64_double_s f_ret_int64_double_s() { + return {1, 2.0}; +} + +struct Char_char_double_s { ichar a; ichar b; double c; } + +fn void f_char_char_double_s_arg(Char_char_double_s a) {} + +fn Char_char_double_s f_ret_char_char_double_s() { + return {1, 2, 3.0}; +} + +// Unions are always passed according to the integer calling convention, even +// if they can only contain a double. + +union Double_u { double a; } + +fn void f_double_u_arg(Double_u a) {} + +fn Double_u f_ret_double_u() { + return {1.0}; +} + +// Test that we don't incorrectly think double+int/double+double structs will +// be returned indirectly and thus have an off-by-one error for the number of +// GPRs available (this is an edge case when structs > 2*XLEN are still +// returned in registers). This includes complex doubles, which are treated as +// double+double structs by the ABI. + +fn Double_int32_s f_ret_double_int32_s_double_int32_s_just_sufficient_gprs( + int a, int b, int c, int d, int e, int f, int g, Double_int32_s h) { + return {1.0, 2}; +} + +fn Double_double_s f_ret_double_double_s_double_int32_s_just_sufficient_gprs( + int a, int b, int c, int d, int e, int f, int g, Double_int32_s h) { + return {1.0, 2.0}; +} + + +/* #expect: test.ll + +define void @test.f_fpr_tracking(double %0, double %1, double %2, double %3, double %4, double %5, double %6, double %7, i8 zeroext %8) #0 { +entry: + ret void +} + + +define void @test.f_double_s_arg(double %0) #0 { +entry: + %a = alloca %Double_s, align 8 + store double %0, ptr %a, align 8 + ret void +} + + +define double @test.f_ret_double_s() #0 { +entry: + %literal = alloca %Double_s, align 8 + call void @llvm.memcpy.p0.p0.i32(ptr align 8 %literal, ptr align 8 @.__const, i32 8, i1 false) + %0 = load double, ptr %literal, align 8 + ret double %0 +} + + +define void @test.f_double_double_s_arg(double %0, double %1) #0 { +entry: + %a = alloca %Double_double_s, align 8 + store double %0, ptr %a, align 8 + %ptradd = getelementptr inbounds i8, ptr %a, i32 8 + store double %1, ptr %a, align 8 + ret void +} + + +define { double, double } @test.f_ret_double_double_s() #0 { +entry: + %literal = alloca %Double_double_s, align 8 + call void @llvm.memcpy.p0.p0.i32(ptr align 8 %literal, ptr align 8 @.__const.1, i32 16, i1 false) + %0 = load double, ptr %literal, align 8 + %ptradd = getelementptr inbounds i8, ptr %literal, i32 8 + %1 = load double, ptr %literal, align 8 + %2 = insertvalue { double, double } undef, double %0, 0 + %3 = insertvalue { double, double } %2, double %1, 1 + ret { double, double } %3 +} + + +define void @test.f_double_float_s_arg(double %0, float %1) #0 { +entry: + %a = alloca %Double_float_s, align 8 + store double %0, ptr %a, align 8 + %ptradd = getelementptr inbounds i8, ptr %a, i32 8 + store float %1, ptr %a, align 8 + ret void +} + + +define { double, float } @test.f_ret_double_float_s() #0 { +entry: + %literal = alloca %Double_float_s, align 8 + call void @llvm.memcpy.p0.p0.i32(ptr align 8 %literal, ptr align 8 @.__const.2, i32 16, i1 false) + %0 = load double, ptr %literal, align 8 + %ptradd = getelementptr inbounds i8, ptr %literal, i32 8 + %1 = load float, ptr %literal, align 8 + %2 = insertvalue { double, float } undef, double %0, 0 + %3 = insertvalue { double, float } %2, float %1, 1 + ret { double, float } %3 +} + + +define void @test.f_double_double_s_arg_insufficient_fprs(float %0, double %1, double %2, double %3, double %4, double %5, double %6, ptr align 8 %7) #0 { +entry: + ret void +} + + +define void @test.f_double_int8_s_arg(double %0, i8 %1) #0 { +entry: + %a = alloca %Double_int8_s, align 8 + store double %0, ptr %a, align 8 + %ptradd = getelementptr inbounds i8, ptr %a, i32 8 + store i8 %1, ptr %a, align 8 + ret void +} + + +define { double, i8 } @test.f_ret_double_int8_s() #0 { +entry: + %literal = alloca %Double_int8_s, align 8 + call void @llvm.memcpy.p0.p0.i32(ptr align 8 %literal, ptr align 8 @.__const.3, i32 16, i1 false) + %0 = load double, ptr %literal, align 8 + %ptradd = getelementptr inbounds i8, ptr %literal, i32 8 + %1 = load i8, ptr %literal, align 8 + %2 = insertvalue { double, i8 } undef, double %0, 0 + %3 = insertvalue { double, i8 } %2, i8 %1, 1 + ret { double, i8 } %3 +} + + +define void @test.f_double_uint8_s_arg(double %0, i8 %1) #0 { +entry: + %a = alloca %Double_uint8_s, align 8 + store double %0, ptr %a, align 8 + %ptradd = getelementptr inbounds i8, ptr %a, i32 8 + store i8 %1, ptr %a, align 8 + ret void +} + + +define { double, i8 } @test.f_ret_double_uint8_s() #0 { +entry: + %literal = alloca %Double_uint8_s, align 8 + call void @llvm.memcpy.p0.p0.i32(ptr align 8 %literal, ptr align 8 @.__const.4, i32 16, i1 false) + %0 = load double, ptr %literal, align 8 + %ptradd = getelementptr inbounds i8, ptr %literal, i32 8 + %1 = load i8, ptr %literal, align 8 + %2 = insertvalue { double, i8 } undef, double %0, 0 + %3 = insertvalue { double, i8 } %2, i8 %1, 1 + ret { double, i8 } %3 +} + + +define void @test.f_double_int32_s_arg(double %0, i32 %1) #0 { +entry: + %a = alloca %Double_int32_s, align 8 + store double %0, ptr %a, align 8 + %ptradd = getelementptr inbounds i8, ptr %a, i32 8 + store i32 %1, ptr %a, align 8 + ret void +} + + +define { double, i32 } @test.f_ret_double_int32_s() #0 { +entry: + %literal = alloca %Double_int32_s, align 8 + call void @llvm.memcpy.p0.p0.i32(ptr align 8 %literal, ptr align 8 @.__const.5, i32 16, i1 false) + %0 = load double, ptr %literal, align 8 + %ptradd = getelementptr inbounds i8, ptr %literal, i32 8 + %1 = load i32, ptr %literal, align 8 + %2 = insertvalue { double, i32 } undef, double %0, 0 + %3 = insertvalue { double, i32 } %2, i32 %1, 1 + ret { double, i32 } %3 +} + + +define void @test.f_double_int64_s_arg(ptr align 8 %0) #0 { +entry: + ret void +} + + +define void @test.f_ret_double_int64_s(ptr noalias sret(%Double_int64_s) align 8 %0) #0 { +entry: + %literal = alloca %Double_int64_s, align 8 + call void @llvm.memcpy.p0.p0.i32(ptr align 8 %literal, ptr align 8 @.__const.6, i32 16, i1 false) + call void @llvm.memcpy.p0.p0.i32(ptr align 8 %0, ptr align 8 %literal, i32 16, i1 false) + ret void +} + + +define void @test.f_double_int8_s_arg_insufficient_gprs(i32 %0, i32 %1, i32 %2, i32 %3, i32 %4, i32 %5, i32 %6, i32 %7, ptr align 8 %8) #0 { +entry: + ret void +} + + +define void @test.f_struct_double_int8_insufficient_fprs(float %0, double %1, double %2, double %3, double %4, double %5, double %6, double %7, ptr align 8 %8) #0 { +entry: + ret void +} + + +define void @test.f_doublearr1_s_arg(double %0) #0 { +entry: + %a = alloca %Doublearr1_s, align 8 + store double %0, ptr %a, align 8 + ret void +} + + +define double @test.f_ret_doublearr1_s() #0 { +entry: + %literal = alloca %Doublearr1_s, align 8 + call void @llvm.memcpy.p0.p0.i32(ptr align 8 %literal, ptr align 8 @.__const.7, i32 8, i1 false) + %0 = load double, ptr %literal, align 8 + ret double %0 +} + + +define void @test.f_doublearr2_s_arg(double %0, double %1) #0 { +entry: + %a = alloca %Doublearr2_s, align 8 + store double %0, ptr %a, align 8 + %ptradd = getelementptr inbounds i8, ptr %a, i32 8 + store double %1, ptr %a, align 8 + ret void +} + + +define { double, double } @test.f_ret_doublearr2_s() #0 { +entry: + %literal = alloca %Doublearr2_s, align 8 + call void @llvm.memcpy.p0.p0.i32(ptr align 8 %literal, ptr align 8 @.__const.8, i32 16, i1 false) + %0 = load double, ptr %literal, align 8 + %ptradd = getelementptr inbounds i8, ptr %literal, i32 8 + %1 = load double, ptr %literal, align 8 + %2 = insertvalue { double, double } undef, double %0, 0 + %3 = insertvalue { double, double } %2, double %1, 1 + ret { double, double } %3 +} + + +define void @test.f_doublearr2_tricky1_s_arg(double %0, double %1) #0 { +entry: + %a = alloca %Doublearr2_tricky1_s, align 8 + store double %0, ptr %a, align 8 + %ptradd = getelementptr inbounds i8, ptr %a, i32 8 + store double %1, ptr %a, align 8 + ret void +} + + +define { double, double } @test.f_ret_doublearr2_tricky1_s() #0 { +entry: + %literal = alloca %Doublearr2_tricky1_s, align 8 + call void @llvm.memcpy.p0.p0.i32(ptr align 8 %literal, ptr align 8 @.__const.9, i32 16, i1 false) + %0 = load double, ptr %literal, align 8 + %ptradd = getelementptr inbounds i8, ptr %literal, i32 8 + %1 = load double, ptr %literal, align 8 + %2 = insertvalue { double, double } undef, double %0, 0 + %3 = insertvalue { double, double } %2, double %1, 1 + ret { double, double } %3 +} + + +define void @test.f_int_double_int_s_arg(ptr align 8 %0) #0 { +entry: + ret void +} + + +define void @test.f_ret_int_double_int_s(ptr noalias sret(%Int_double_int_s) align 8 %0) #0 { +entry: + %literal = alloca %Int_double_int_s, align 8 + call void @llvm.memcpy.p0.p0.i32(ptr align 8 %literal, ptr align 8 @.__const.10, i32 24, i1 false) + call void @llvm.memcpy.p0.p0.i32(ptr align 8 %0, ptr align 8 %literal, i32 24, i1 false) + ret void +} + + +define void @test.f_int64_double_s_arg(ptr align 8 %0) #0 { +entry: + ret void +} + + +define void @test.f_ret_int64_double_s(ptr noalias sret(%Int64_double_s) align 8 %0) #0 { +entry: + %literal = alloca %Int64_double_s, align 8 + call void @llvm.memcpy.p0.p0.i32(ptr align 8 %literal, ptr align 8 @.__const.11, i32 16, i1 false) + call void @llvm.memcpy.p0.p0.i32(ptr align 8 %0, ptr align 8 %literal, i32 16, i1 false) + ret void +} + + +define void @test.f_char_char_double_s_arg(ptr align 8 %0) #0 { +entry: + ret void +} + + +define void @test.f_ret_char_char_double_s(ptr noalias sret(%Char_char_double_s) align 8 %0) #0 { +entry: + %literal = alloca %Char_char_double_s, align 8 + call void @llvm.memcpy.p0.p0.i32(ptr align 8 %literal, ptr align 8 @.__const.12, i32 16, i1 false) + call void @llvm.memcpy.p0.p0.i32(ptr align 8 %0, ptr align 8 %literal, i32 16, i1 false) + ret void +} + + +define void @test.f_double_u_arg(i64 %0) #0 { +entry: + %a = alloca %Double_u, align 8 + store i64 %0, ptr %a, align 8 + ret void +} + + +define i64 @test.f_ret_double_u() #0 { +entry: + %literal = alloca %Double_u, align 8 + call void @llvm.memcpy.p0.p0.i32(ptr align 8 %literal, ptr align 8 @.__const.13, i32 8, i1 false) + %0 = load i64, ptr %literal, align 8 + ret i64 %0 +} + + +define { double, i32 } @test.f_ret_double_int32_s_double_int32_s_just_sufficient_gprs(i32 %0, i32 %1, i32 %2, i32 %3, i32 %4, i32 %5, i32 %6, double %7, i32 %8) #0 { +entry: + %h = alloca %Double_int32_s, align 8 + %literal = alloca %Double_int32_s, align 8 + store double %7, ptr %h, align 8 + %ptradd = getelementptr inbounds i8, ptr %h, i32 8 + store i32 %8, ptr %h, align 8 + call void @llvm.memcpy.p0.p0.i32(ptr align 8 %literal, ptr align 8 @.__const.14, i32 16, i1 false) + %9 = load double, ptr %literal, align 8 + %ptradd1 = getelementptr inbounds i8, ptr %literal, i32 8 + %10 = load i32, ptr %literal, align 8 + %11 = insertvalue { double, i32 } undef, double %9, 0 + %12 = insertvalue { double, i32 } %11, i32 %10, 1 + ret { double, i32 } %12 +} + + +define { double, double } @test.f_ret_double_double_s_double_int32_s_just_sufficient_gprs(i32 %0, i32 %1, i32 %2, i32 %3, i32 %4, i32 %5, i32 %6, double %7, i32 %8) #0 { +entry: + %h = alloca %Double_int32_s, align 8 + %literal = alloca %Double_double_s, align 8 + store double %7, ptr %h, align 8 + %ptradd = getelementptr inbounds i8, ptr %h, i32 8 + store i32 %8, ptr %h, align 8 + call void @llvm.memcpy.p0.p0.i32(ptr align 8 %literal, ptr align 8 @.__const.15, i32 16, i1 false) + %9 = load double, ptr %literal, align 8 + %ptradd1 = getelementptr inbounds i8, ptr %literal, i32 8 + %10 = load double, ptr %literal, align 8 + %11 = insertvalue { double, double } undef, double %9, 0 + %12 = insertvalue { double, double } %11, double %10, 1 + ret { double, double } %12 +} diff --git a/test/test_suite7/abi/riscv32-ilp32f-abi.c3t b/test/test_suite7/abi/riscv32-ilp32f-abi.c3t new file mode 100644 index 000000000..8da477614 --- /dev/null +++ b/test/test_suite7/abi/riscv32-ilp32f-abi.c3t @@ -0,0 +1,89 @@ +// #target: linux-riscv32 +// #opt: --riscvfloat=float +module test; +// Doubles are still passed in GPRs, so the 'e' argument will be anyext as +// GPRs are exhausted. +fn void f_fpr_tracking(double a, double b, double c, double d, ichar e) {} + +// Lowering for doubles is unnmodified, as 64 > FLEN. +struct Double_s { double d; } + +fn void f_double_s_arg(Double_s a) {} + +fn Double_s f_ret_double_s() { + return {1.0}; +} + +struct Double_double_s { double d; double e; } + +fn void f_double_double_s_arg(Double_double_s a) {} + +fn Double_double_s f_ret_double_double_s() { + return {1.0, 2.0}; +} + +struct Double_int8_s { double d; long i; } + +struct Int_double_s { int a; double b; } + +fn void f_int_double_s_arg(Int_double_s a) {} + +fn Int_double_s f_ret_int_double_s() { + return {1, 2.0}; +} + +/* #expect: test.ll + + +define void @test.f_fpr_tracking(double %0, double %1, double %2, double %3, i8 %4) #0 { +entry: + ret void +} + + +define void @test.f_double_s_arg(i64 %0) #0 { +entry: + %a = alloca %Double_s, align 8 + store i64 %0, ptr %a, align 8 + ret void +} + + +define i64 @test.f_ret_double_s() #0 { +entry: + %literal = alloca %Double_s, align 8 + call void @llvm.memcpy.p0.p0.i32(ptr align 8 %literal, ptr align 8 @.__const, i32 8, i1 false) + %0 = load i64, ptr %literal, align 8 + ret i64 %0 +} + + +define void @test.f_double_double_s_arg(ptr align 8 %0) #0 { +entry: + ret void +} + + +define void @test.f_ret_double_double_s(ptr noalias sret(%Double_double_s) align 8 %0) #0 { +entry: + %literal = alloca %Double_double_s, align 8 + call void @llvm.memcpy.p0.p0.i32(ptr align 8 %literal, ptr align 8 @.__const.1, i32 16, i1 false) + call void @llvm.memcpy.p0.p0.i32(ptr align 8 %0, ptr align 8 %literal, i32 16, i1 false) + ret void +} + + +define void @test.f_int_double_s_arg(ptr align 8 %0) #0 { +entry: + ret void +} + + +define void @test.f_ret_int_double_s(ptr noalias sret(%Int_double_s) align 8 %0) #0 { +entry: + %literal = alloca %Int_double_s, align 8 + call void @llvm.memcpy.p0.p0.i32(ptr align 8 %literal, ptr align 8 @.__const.2, i32 16, i1 false) + call void @llvm.memcpy.p0.p0.i32(ptr align 8 %0, ptr align 8 %literal, i32 16, i1 false) + ret void +} + diff --git a/test/test_suite7/abi/riscv32-ilp32f-ilp32d-abi-1.c3t b/test/test_suite7/abi/riscv32-ilp32f-ilp32d-abi-1.c3t new file mode 100644 index 000000000..cf407ed12 --- /dev/null +++ b/test/test_suite7/abi/riscv32-ilp32f-ilp32d-abi-1.c3t @@ -0,0 +1,200 @@ +// #target: linux-riscv32 +// #opt: --riscvfloat=float +module test; + +// Verify that the tracking of used GPRs and FPRs works correctly by checking +// that small integers are sign/zero extended when passed in registers. + +// Floats are passed in FPRs, so argument 'i' will be passed zero-extended +// because it will be passed in a GPR. + +fn void f_fpr_tracking(float a, float b, float c, float d, float e, float f, + float g, float h, char i) {} + +// Check that fp, fp+fp, and int+fp structs are lowered correctly. These will +// be passed in FPR, FPR+FPR, or GPR+FPR regs if sufficient registers are +// available the widths are <= XLEN and FLEN, and should be expanded to +// separate arguments in IR. They are passed by the same rules for returns, +// but will be lowered to simple two-element structs if necessary (as LLVM IR +// functions cannot return multiple values). + +// A struct containing just one floating-point real is passed as though it +// were a standalone floating-point real. + +struct Float_s { float f; } + +fn void f_float_s_arg(Float_s a) {} + +fn Float_s f_ret_float_s() { + return {1.0}; +} + + +// Check that structs containing two float values (FLEN <= width) are expanded +// provided sufficient FPRs are available. + +struct Float_float_s { float f; float g; } + +fn void f_float_float_s_arg(Float_float_s a) {} + +fn Float_float_s f_ret_float_float_s() { + return {1.0, 2.0}; +} + +fn void f_float_float_s_arg_insufficient_fprs(float a, float b, float c, float d, + float e, float f, float g, Float_float_s h) {} + +// Check that structs containing int+float values are expanded, provided +// sufficient FPRs and GPRs are available. The integer components are neither +// sign or zero-extended. + +struct Float_int8_s { float f; ichar i; } +struct Float_uint8_s { float f; char i; } +struct Float_int32_s { float f; int i; } +struct Float_int64_s { float f; long i; } + +fn void f_float_int8_s_arg(Float_int8_s a) {} + +fn Float_int8_s f_ret_float_int8_s() { + return {1.0, 2}; +} + +fn void f_float_uint8_s_arg(Float_uint8_s a) {} + +fn Float_uint8_s f_ret_float_uint8_s() { + return {1.0, 2}; +} + +fn void f_float_int32_s_arg(Float_int32_s a) {} + +fn Float_int32_s f_ret_float_int32_s() { + return {1.0, 2}; +} + +fn void f_float_int64_s_arg(Float_int64_s a) {} + +fn Float_int64_s f_ret_float_int64_s() { + return {1.0, 2}; +} + + +fn void f_float_int8_s_arg_insufficient_gprs(int a, int b, int c, int d, int e, + int f, int g, int h, Float_int8_s i) {} + +fn void f_struct_float_int8_insufficient_fprs(float a, float b, float c, float d, + float e, float f, float g, float h, Float_int8_s i) {} + +// Test single or two-element structs that need flattening. e.g. those +// containing nested structs, floats in small arrays, zero-length structs etc. + +struct Floatarr1_s { float[1] a; } + +fn void f_floatarr1_s_arg(Floatarr1_s a) {} + +fn Floatarr1_s f_ret_floatarr1_s() { + return {{1.0}}; +} + +struct Floatarr2_s { float[2] a; } + +fn void f_floatarr2_s_arg(Floatarr2_s a) {} + +fn Floatarr2_s f_ret_floatarr2_s() { + return {{1.0, 2.0}}; +} + +struct Inner { float[1] f; } +struct Floatarr2_tricky1_s { Inner[2] g; } + +fn void f_floatarr2_tricky1_s_arg(Floatarr2_tricky1_s a) {} + +fn Floatarr2_tricky1_s f_ret_floatarr2_tricky1_s() { + return {{{{1.0}}, {{2.0}}}}; +} + +// Test structs that should be passed according to the normal integer calling +// convention. + +struct Int_float_int_s { int a; float b; int c; } + +fn void f_int_float_int_s_arg(Int_float_int_s a) {} + +fn Int_float_int_s f_ret_int_float_int_s() { + return {1, 2.0, 3}; +} + +struct Int64_float_s { long a; float b; } + +fn void f_int64_float_s_arg(Int64_float_s a) {} + +fn Int64_float_s f_ret_int64_float_s() { + return {1, 2.0}; +} + +struct Char_char_float_s { char a; char b; float c; } + +fn void f_char_char_float_s_arg(Char_char_float_s a) {} + +fn Char_char_float_s f_ret_char_char_float_s() { + return {1, 2, 3.0}; +} + +// Unions are always passed according to the integer calling convention, even +// if they can only contain a float. + +union Float_u { float a; } + +fn void f_float_u_arg(Float_u a) {} + +fn Float_u f_ret_float_u() { + return {1.0}; +} + + +/* #expect: test.ll + +define void @test.f_fpr_tracking(float %0, float %1, float %2, float %3, float %4, float %5, float %6, float %7, i8 zeroext %8) + +define void @test.f_float_s_arg(float %0) +define float @test.f_ret_float_s() + +define void @test.f_float_float_s_arg(float %0, float %1) +define { float, float } @test.f_ret_float_float_s() + +define void @test.f_float_float_s_arg_insufficient_fprs(float %0, float %1, float %2, float %3, float %4, float %5, float %6, [2 x i32] %7) #0 { + +define void @test.f_float_int8_s_arg(float %0, i8 %1) +define { float, i8 } @test.f_ret_float_int8_s() + +define void @test.f_float_uint8_s_arg(float %0, i8 %1) +define { float, i8 } @test.f_ret_float_uint8_s() + +define void @test.f_float_int32_s_arg(float %0, i32 %1) +define { float, i32 } @test.f_ret_float_int32_s() + +define void @test.f_float_int64_s_arg(ptr align 8 %0) +define void @test.f_ret_float_int64_s(ptr noalias sret(%Float_int64_s) align 8 %0) + +define void @test.f_float_int8_s_arg_insufficient_gprs(i32 %0, i32 %1, i32 %2, i32 %3, i32 %4, i32 %5, i32 %6, i32 %7, [2 x i32] %8) +define void @test.f_struct_float_int8_insufficient_fprs(float %0, float %1, float %2, float %3, float %4, float %5, float %6, float %7, [2 x i32] %8) + +define void @test.f_floatarr1_s_arg(float %0) +define float @test.f_ret_floatarr1_s() + +define void @test.f_floatarr2_s_arg(float %0, float %1) +define { float, float } @test.f_ret_floatarr2_s() + +define void @test.f_floatarr2_tricky1_s_arg(float %0, float %1) +define { float, float } @test.f_ret_floatarr2_tricky1_s() + +define void @test.f_int_float_int_s_arg(ptr align 4 %0) +define void @test.f_ret_int_float_int_s(ptr noalias sret(%Int_float_int_s) align 4 %0) + +define void @test.f_int64_float_s_arg(ptr align 8 %0) +define void @test.f_ret_int64_float_s(ptr noalias sret(%Int64_float_s) align 8 %0) + +define void @test.f_char_char_float_s_arg([2 x i32] %0) +define [2 x i32] @test.f_ret_char_char_float_s() + +define void @test.f_float_u_arg(i32 %0) +define i32 @test.f_ret_float_u() \ No newline at end of file diff --git a/test/test_suite7/abi/riscv32-ilp32f-ilp32d-abi-2.c3t b/test/test_suite7/abi/riscv32-ilp32f-ilp32d-abi-2.c3t new file mode 100644 index 000000000..29668b915 --- /dev/null +++ b/test/test_suite7/abi/riscv32-ilp32f-ilp32d-abi-2.c3t @@ -0,0 +1,430 @@ +// #target: linux-riscv32 +// #opt: --riscvfloat=double +module test; + +// Verify that the tracking of used GPRs and FPRs works correctly by checking +// that small integers are sign/zero extended when passed in registers. + +// Floats are passed in FPRs, so argument 'i' will be passed zero-extended +// because it will be passed in a GPR. + +fn void f_fpr_tracking(float a, float b, float c, float d, float e, float f, + float g, float h, char i) {} + +// Check that fp, fp+fp, and int+fp structs are lowered correctly. These will +// be passed in FPR, FPR+FPR, or GPR+FPR regs if sufficient registers are +// available the widths are <= XLEN and FLEN, and should be expanded to +// separate arguments in IR. They are passed by the same rules for returns, +// but will be lowered to simple two-element structs if necessary (as LLVM IR +// functions cannot return multiple values). + +// A struct containing just one floating-point real is passed as though it +// were a standalone floating-point real. + +struct Float_s { float f; } + +fn void f_float_s_arg(Float_s a) {} + +fn Float_s f_ret_float_s() { + return {1.0}; +} + + +// Check that structs containing two float values (FLEN <= width) are expanded +// provided sufficient FPRs are available. + +struct Float_float_s { float f; float g; } + +fn void f_float_float_s_arg(Float_float_s a) {} + +fn Float_float_s f_ret_float_float_s() { + return {1.0, 2.0}; +} + +fn void f_float_float_s_arg_insufficient_fprs(float a, float b, float c, float d, + float e, float f, float g, Float_float_s h) {} + +// Check that structs containing int+float values are expanded, provided +// sufficient FPRs and GPRs are available. The integer components are neither +// sign or zero-extended. + +struct Float_int8_s { float f; ichar i; } +struct Float_uint8_s { float f; char i; } +struct Float_int32_s { float f; int i; } +struct Float_int64_s { float f; long i; } + +fn void f_float_int8_s_arg(Float_int8_s a) {} + +fn Float_int8_s f_ret_float_int8_s() { + return {1.0, 2}; +} + +fn void f_float_uint8_s_arg(Float_uint8_s a) {} + +fn Float_uint8_s f_ret_float_uint8_s() { + return {1.0, 2}; +} + +fn void f_float_int32_s_arg(Float_int32_s a) {} + +fn Float_int32_s f_ret_float_int32_s() { + return {1.0, 2}; +} + +fn void f_float_int64_s_arg(Float_int64_s a) {} + +fn Float_int64_s f_ret_float_int64_s() { + return {1.0, 2}; +} + + +fn void f_float_int8_s_arg_insufficient_gprs(int a, int b, int c, int d, int e, + int f, int g, int h, Float_int8_s i) {} + +fn void f_struct_float_int8_insufficient_fprs(float a, float b, float c, float d, + float e, float f, float g, float h, Float_int8_s i) {} + +// Test single or two-element structs that need flattening. e.g. those +// containing nested structs, floats in small arrays, zero-length structs etc. + +struct Floatarr1_s { float[1] a; } + +fn void f_floatarr1_s_arg(Floatarr1_s a) {} + +fn Floatarr1_s f_ret_floatarr1_s() { + return {{1.0}}; +} + +struct Floatarr2_s { float[2] a; } + +fn void f_floatarr2_s_arg(Floatarr2_s a) {} + +fn Floatarr2_s f_ret_floatarr2_s() { + return {{1.0, 2.0}}; +} + +struct Inner { float[1] f; } +struct Floatarr2_tricky1_s { Inner[2] g; } + +fn void f_floatarr2_tricky1_s_arg(Floatarr2_tricky1_s a) {} + +fn Floatarr2_tricky1_s f_ret_floatarr2_tricky1_s() { + return {{{{1.0}}, {{2.0}}}}; +} + +// Test structs that should be passed according to the normal integer calling +// convention. + +struct Int_float_int_s { int a; float b; int c; } + +fn void f_int_float_int_s_arg(Int_float_int_s a) {} + +fn Int_float_int_s f_ret_int_float_int_s() { + return {1, 2.0, 3}; +} + +struct Int64_float_s { long a; float b; } + +fn void f_int64_float_s_arg(Int64_float_s a) {} + +fn Int64_float_s f_ret_int64_float_s() { + return {1, 2.0}; +} + +struct Char_char_float_s { char a; char b; float c; } + +fn void f_char_char_float_s_arg(Char_char_float_s a) {} + +fn Char_char_float_s f_ret_char_char_float_s() { + return {1, 2, 3.0}; +} + +// Unions are always passed according to the integer calling convention, even +// if they can only contain a float. + +union Float_u { float a; } + +fn void f_float_u_arg(Float_u a) {} + +fn Float_u f_ret_float_u() { + return {1.0}; +} + + +/* #expect: test.ll + +define void @test.f_fpr_tracking(float %0, float %1, float %2, float %3, float %4, float %5, float %6, float %7, i8 zeroext %8) #0 { +entry: + ret void +} + +define void @test.f_float_s_arg(float %0) #0 { +entry: + %a = alloca %Float_s, align 4 + store float %0, ptr %a, align 4 + ret void +} + +define float @test.f_ret_float_s() #0 { +entry: + %literal = alloca %Float_s, align 4 + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %literal, ptr align 4 @.__const, i32 4, i1 false) + %0 = load float, ptr %literal, align 4 + ret float %0 +} + +define void @test.f_float_float_s_arg(float %0, float %1) #0 { +entry: + %a = alloca %Float_float_s, align 4 + store float %0, ptr %a, align 4 + %ptradd = getelementptr inbounds i8, ptr %a, i32 4 + store float %1, ptr %a, align 4 + ret void +} + +define { float, float } @test.f_ret_float_float_s() #0 { +entry: + %literal = alloca %Float_float_s, align 4 + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %literal, ptr align 4 @.__const.1, i32 8, i1 false) + %0 = load float, ptr %literal, align 4 + %ptradd = getelementptr inbounds i8, ptr %literal, i32 4 + %1 = load float, ptr %literal, align 4 + %2 = insertvalue { float, float } undef, float %0, 0 + %3 = insertvalue { float, float } %2, float %1, 1 + ret { float, float } %3 +} + + +define void @test.f_float_float_s_arg_insufficient_fprs(float %0, float %1, float %2, float %3, float %4, float %5, float %6, [2 x i32] %7) #0 { +entry: + %h = alloca %Float_float_s, align 4 + store [2 x i32] %7, ptr %h, align 4 + ret void +} + + +define void @test.f_float_int8_s_arg(float %0, i8 %1) #0 { +entry: + %a = alloca %Float_int8_s, align 4 + store float %0, ptr %a, align 4 + %ptradd = getelementptr inbounds i8, ptr %a, i32 4 + store i8 %1, ptr %a, align 4 + ret void +} + + +define { float, i8 } @test.f_ret_float_int8_s() #0 { +entry: + %literal = alloca %Float_int8_s, align 4 + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %literal, ptr align 4 @.__const.2, i32 8, i1 false) + %0 = load float, ptr %literal, align 4 + %ptradd = getelementptr inbounds i8, ptr %literal, i32 4 + %1 = load i8, ptr %literal, align 4 + %2 = insertvalue { float, i8 } undef, float %0, 0 + %3 = insertvalue { float, i8 } %2, i8 %1, 1 + ret { float, i8 } %3 +} + + +define void @test.f_float_uint8_s_arg(float %0, i8 %1) #0 { +entry: + %a = alloca %Float_uint8_s, align 4 + store float %0, ptr %a, align 4 + %ptradd = getelementptr inbounds i8, ptr %a, i32 4 + store i8 %1, ptr %a, align 4 + ret void +} + + +define { float, i8 } @test.f_ret_float_uint8_s() #0 { +entry: + %literal = alloca %Float_uint8_s, align 4 + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %literal, ptr align 4 @.__const.3, i32 8, i1 false) + %0 = load float, ptr %literal, align 4 + %ptradd = getelementptr inbounds i8, ptr %literal, i32 4 + %1 = load i8, ptr %literal, align 4 + %2 = insertvalue { float, i8 } undef, float %0, 0 + %3 = insertvalue { float, i8 } %2, i8 %1, 1 + ret { float, i8 } %3 +} + + +define void @test.f_float_int32_s_arg(float %0, i32 %1) #0 { +entry: + %a = alloca %Float_int32_s, align 4 + store float %0, ptr %a, align 4 + %ptradd = getelementptr inbounds i8, ptr %a, i32 4 + store i32 %1, ptr %a, align 4 + ret void +} + + +define { float, i32 } @test.f_ret_float_int32_s() #0 { +entry: + %literal = alloca %Float_int32_s, align 4 + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %literal, ptr align 4 @.__const.4, i32 8, i1 false) + %0 = load float, ptr %literal, align 4 + %ptradd = getelementptr inbounds i8, ptr %literal, i32 4 + %1 = load i32, ptr %literal, align 4 + %2 = insertvalue { float, i32 } undef, float %0, 0 + %3 = insertvalue { float, i32 } %2, i32 %1, 1 + ret { float, i32 } %3 +} + + +define void @test.f_float_int64_s_arg(ptr align 8 %0) #0 { +entry: + ret void +} + + +define void @test.f_ret_float_int64_s(ptr noalias sret(%Float_int64_s) align 8 %0) #0 { +entry: + %literal = alloca %Float_int64_s, align 8 + call void @llvm.memcpy.p0.p0.i32(ptr align 8 %literal, ptr align 8 @.__const.5, i32 16, i1 false) + call void @llvm.memcpy.p0.p0.i32(ptr align 8 %0, ptr align 8 %literal, i32 16, i1 false) + ret void +} + + +define void @test.f_float_int8_s_arg_insufficient_gprs(i32 %0, i32 %1, i32 %2, i32 %3, i32 %4, i32 %5, i32 %6, i32 %7, [2 x i32] %8) #0 { +entry: + %i = alloca %Float_int8_s, align 4 + store [2 x i32] %8, ptr %i, align 4 + ret void +} + + +define void @test.f_struct_float_int8_insufficient_fprs(float %0, float %1, float %2, float %3, float %4, float %5, float %6, float %7, [2 x i32] %8) #0 { +entry: + %i = alloca %Float_int8_s, align 4 + store [2 x i32] %8, ptr %i, align 4 + ret void +} + + +define void @test.f_floatarr1_s_arg(float %0) #0 { +entry: + %a = alloca %Floatarr1_s, align 4 + store float %0, ptr %a, align 4 + ret void +} + + +define float @test.f_ret_floatarr1_s() #0 { +entry: + %literal = alloca %Floatarr1_s, align 4 + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %literal, ptr align 4 @.__const.6, i32 4, i1 false) + %0 = load float, ptr %literal, align 4 + ret float %0 +} + + +define void @test.f_floatarr2_s_arg(float %0, float %1) #0 { +entry: + %a = alloca %Floatarr2_s, align 4 + store float %0, ptr %a, align 4 + %ptradd = getelementptr inbounds i8, ptr %a, i32 4 + store float %1, ptr %a, align 4 + ret void +} + + +define { float, float } @test.f_ret_floatarr2_s() #0 { +entry: + %literal = alloca %Floatarr2_s, align 4 + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %literal, ptr align 4 @.__const.7, i32 8, i1 false) + %0 = load float, ptr %literal, align 4 + %ptradd = getelementptr inbounds i8, ptr %literal, i32 4 + %1 = load float, ptr %literal, align 4 + %2 = insertvalue { float, float } undef, float %0, 0 + %3 = insertvalue { float, float } %2, float %1, 1 + ret { float, float } %3 +} + + +define void @test.f_floatarr2_tricky1_s_arg(float %0, float %1) #0 { +entry: + %a = alloca %Floatarr2_tricky1_s, align 4 + store float %0, ptr %a, align 4 + %ptradd = getelementptr inbounds i8, ptr %a, i32 4 + store float %1, ptr %a, align 4 + ret void +} + + +define { float, float } @test.f_ret_floatarr2_tricky1_s() #0 { +entry: + %literal = alloca %Floatarr2_tricky1_s, align 4 + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %literal, ptr align 4 @.__const.8, i32 8, i1 false) + %0 = load float, ptr %literal, align 4 + %ptradd = getelementptr inbounds i8, ptr %literal, i32 4 + %1 = load float, ptr %literal, align 4 + %2 = insertvalue { float, float } undef, float %0, 0 + %3 = insertvalue { float, float } %2, float %1, 1 + ret { float, float } %3 +} + + +define void @test.f_int_float_int_s_arg(ptr align 4 %0) #0 { +entry: + ret void +} + + +define void @test.f_ret_int_float_int_s(ptr noalias sret(%Int_float_int_s) align 4 %0) #0 { +entry: + %literal = alloca %Int_float_int_s, align 4 + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %literal, ptr align 4 @.__const.9, i32 12, i1 false) + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %0, ptr align 4 %literal, i32 12, i1 false) + ret void +} + + +define void @test.f_int64_float_s_arg(ptr align 8 %0) #0 { +entry: + ret void +} + + +define void @test.f_ret_int64_float_s(ptr noalias sret(%Int64_float_s) align 8 %0) #0 { +entry: + %literal = alloca %Int64_float_s, align 8 + call void @llvm.memcpy.p0.p0.i32(ptr align 8 %literal, ptr align 8 @.__const.10, i32 16, i1 false) + call void @llvm.memcpy.p0.p0.i32(ptr align 8 %0, ptr align 8 %literal, i32 16, i1 false) + ret void +} + + +define void @test.f_char_char_float_s_arg([2 x i32] %0) #0 { +entry: + %a = alloca %Char_char_float_s, align 4 + store [2 x i32] %0, ptr %a, align 4 + ret void +} + + +define [2 x i32] @test.f_ret_char_char_float_s() #0 { +entry: + %literal = alloca %Char_char_float_s, align 4 + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %literal, ptr align 4 @.__const.11, i32 8, i1 false) + %0 = load [2 x i32], ptr %literal, align 4 + ret [2 x i32] %0 +} + + +define void @test.f_float_u_arg(i32 %0) #0 { +entry: + %a = alloca %Float_u, align 4 + store i32 %0, ptr %a, align 4 + ret void +} + + +define i32 @test.f_ret_float_u() #0 { +entry: + %literal = alloca %Float_u, align 4 + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %literal, ptr align 4 @.__const.12, i32 4, i1 false) + %0 = load i32, ptr %literal, align 4 + ret i32 %0 +} diff --git a/test/test_suite7/abi/riscv64-lp64-abi.c3t b/test/test_suite7/abi/riscv64-lp64-abi.c3t new file mode 100644 index 000000000..32afce841 --- /dev/null +++ b/test/test_suite7/abi/riscv64-lp64-abi.c3t @@ -0,0 +1,45 @@ +// #target: linux-riscv64 +module test; + +struct Large { + long a, b, c, d; +} + +def 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) +entry: + %zext = zext i8 %6 to i32 + %zext1 = zext i8 %7 to i32 + %add = add i32 %zext, %zext1 + ret i32 %add + +; Function Attrs: +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: + %literal = alloca %Large, align 8 + %fpsi = fptosi double %1 to i64 + store i64 %fpsi, ptr %literal, align 8 + %ptradd = getelementptr inbounds i8, ptr %literal, i64 8 + %zext = zext i8 %5 to i64 + store i64 %zext, ptr %ptradd, align 8 + %ptradd1 = getelementptr inbounds i8, ptr %literal, i64 16 + %sext = sext i8 %6 to i64 + store i64 %sext, ptr %ptradd1, align 8 + %ptradd2 = getelementptr inbounds i8, ptr %literal, i64 24 + %zext3 = zext i8 %7 to i64 + store i64 %zext3, ptr %ptradd2, 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_suite7/abi/riscv64-lp64-lp64f-abi-1.c3t b/test/test_suite7/abi/riscv64-lp64-lp64f-abi-1.c3t new file mode 100644 index 000000000..bd0ea226d --- /dev/null +++ b/test/test_suite7/abi/riscv64-lp64-lp64f-abi-1.c3t @@ -0,0 +1,51 @@ +// #target: linux-riscv64 +module test; + +struct Large { + long a, b, c, d; +} +// Scalars passed on the stack should not have signext/zeroext attributes +// (they are anyext). + +fn int f_scalar_stack_1(int a, int128 b, double c, float128 d, char[<32>] e, + char f, ichar g, char h) { + return g + h; +} + +// Ensure that scalars passed on the stack are still determined correctly in +// the presence of large return values that consume a register due to the need +// to pass a pointer. + +fn Large f_scalar_stack_2(double a, int128 b, float128 c, char[<32>] d, + char e, ichar f, char g) { + return {(long)a, e, f, g}; +} + +/* #expect: test.ll + +define signext i32 @test.f_scalar_stack_1(i32 signext %0, i128 %1, double %2, fp128 %3, ptr align 32 %4, i8 zeroext %5, i8 %6, i8 %7) #0 { +entry: + %sext = sext i8 %6 to i32 + %zext = zext i8 %7 to i32 + %add = add i32 %sext, %zext + ret i32 %add +} + +; Function Attrs: +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: + %literal = alloca %Large, align 8 + %fpsi = fptosi double %1 to i64 + store i64 %fpsi, ptr %literal, align 8 + %ptradd = getelementptr inbounds i8, ptr %literal, i64 8 + %zext = zext i8 %5 to i64 + store i64 %zext, ptr %ptradd, align 8 + %ptradd1 = getelementptr inbounds i8, ptr %literal, i64 16 + %sext = sext i8 %6 to i64 + store i64 %sext, ptr %ptradd1, align 8 + %ptradd2 = getelementptr inbounds i8, ptr %literal, i64 24 + %zext3 = zext i8 %7 to i64 + store i64 %zext3, ptr %ptradd2, align 8 + call void @llvm.memcpy.p0.p0.i32(ptr align 8 %0, ptr align 8 %literal, i32 32, i1 false) + ret void +} \ No newline at end of file diff --git a/test/test_suite7/abi/riscv64-lp64-lp64f-abi-2.c3t b/test/test_suite7/abi/riscv64-lp64-lp64f-abi-2.c3t new file mode 100644 index 000000000..d77e6f5bd --- /dev/null +++ b/test/test_suite7/abi/riscv64-lp64-lp64f-abi-2.c3t @@ -0,0 +1,52 @@ +// #target: linux-riscv64 +// #opt: --riscvfloat=float +module test; + +struct Large { + long a, b, c, d; +} +// Scalars passed on the stack should not have signext/zeroext attributes +// (they are anyext). + +fn int f_scalar_stack_1(int a, int128 b, double c, float128 d, char[<32>] e, + char f, ichar g, char h) { + return g + h; +} + +// Ensure that scalars passed on the stack are still determined correctly in +// the presence of large return values that consume a register due to the need +// to pass a pointer. + +fn Large f_scalar_stack_2(double a, int128 b, float128 c, char[<32>] d, + char e, ichar f, char g) { + return {(long)a, e, f, g}; +} + +/* #expect: test.ll + +define signext i32 @test.f_scalar_stack_1(i32 signext %0, i128 %1, double %2, fp128 %3, ptr align 32 %4, i8 zeroext %5, i8 %6, i8 %7) #0 { +entry: + %sext = sext i8 %6 to i32 + %zext = zext i8 %7 to i32 + %add = add i32 %sext, %zext + ret i32 %add +} + +; Function Attrs: +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: + %literal = alloca %Large, align 8 + %fpsi = fptosi double %1 to i64 + store i64 %fpsi, ptr %literal, align 8 + %ptradd = getelementptr inbounds i8, ptr %literal, i64 8 + %zext = zext i8 %5 to i64 + store i64 %zext, ptr %ptradd, align 8 + %ptradd1 = getelementptr inbounds i8, ptr %literal, i64 16 + %sext = sext i8 %6 to i64 + store i64 %sext, ptr %ptradd1, align 8 + %ptradd2 = getelementptr inbounds i8, ptr %literal, i64 24 + %zext3 = zext i8 %7 to i64 + store i64 %zext3, ptr %ptradd2, align 8 + call void @llvm.memcpy.p0.p0.i32(ptr align 8 %0, ptr align 8 %literal, i32 32, i1 false) + ret void +} \ No newline at end of file diff --git a/test/test_suite7/abi/riscv64-lp64-lp64f-lp64d-abi-1.c3t b/test/test_suite7/abi/riscv64-lp64-lp64f-lp64d-abi-1.c3t new file mode 100644 index 000000000..1c1b89eb4 --- /dev/null +++ b/test/test_suite7/abi/riscv64-lp64-lp64f-lp64d-abi-1.c3t @@ -0,0 +1,206 @@ +// #target: linux-riscv64 +module test; + +fn void f_void() {} + +fn bool f_scalar_0(bool x) { return x; } +fn int f_scalar_1(ichar x) { return x; } +fn char f_scalar_2(char x) { return x; } +fn uint f_scalar_3(int x) { return x; } +fn long f_scalar_4(long x) { return x; } +fn float f_fp_scalar_1(float x) { return x; } +fn double f_fp_scalar_2(double x) { return x; } +fn float128 f_fp_scalar_3(float128 x) { return x; } + +// Aggregates <= 2*xlen may be passed in registers, so will be coerced to +// integer arguments. The rules for return are the same. + +struct Tiny { + ushort a, b, c, d; +} + +fn void f_agg_tiny(Tiny x) { + x.a += x.b; + x.c += x.d; +} + +fn Tiny f_agg_tiny_ret() { + return {1, 2, 3, 4}; +} + +fn void f_vec_tiny_v4i16(short[<4>] x) { + x[0] = x[1]; + x[2] = x[3]; +} + +fn short[<4>] f_vec_tiny_v4i16_ret() { + return {1, 2, 3, 4}; +} + +fn void f_vec_tiny_v1i64(long[<1>] x) { + x[0] = 114; +} + +fn long[<1>] f_vec_tiny_v1i64_ret() { + return {1}; +} + +struct Small { + long a; + long *b; +} + +fn void f_agg_small(Small x) { + x.a += *x.b; + x.b = &x.a; +} + +fn Small f_agg_small_ret() { + return {1, null}; +} + +fn void f_vec_small_v8i16(short[<8>] x) { + x[0] = x[7]; +} + +fn short[<8>] f_vec_small_v8i16_ret() { + return {1, 2, 3, 4, 5, 6, 7, 8}; +} + +fn void f_vec_small_v1i128(int128[<1>] x) { + x[0] = 114; +} + +fn int128[<1>] f_vec_small_v1i128_ret() { + return {1}; +} + +// Aggregates of 2*xlen size and 2*xlen alignment should be coerced to a +// single 2*xlen-sized argument, to ensure that alignment can be maintained if +// passed on the stack. + +struct Small_aligned { + int128 a; +} + +fn void f_agg_small_aligned(Small_aligned x) { + x.a += x.a; +} + +fn Small_aligned f_agg_small_aligned_ret(Small_aligned x) { + return {10}; +} + +// Aggregates greater > 2*xlen will be passed and returned indirectly +struct Large { + long a, b, c, d; +} + +fn void f_agg_large(Large x) { + x.a = x.b + x.c + x.d; +} + +// The address where the struct should be written to will be the first +// argument +fn Large f_agg_large_ret(int i, ichar j) { + return {1, 2, 3, 4}; +} + +fn void f_vec_large_v32i8(char[<32>] x) { + x[0] = x[7]; +} + +fn char[<32>] f_vec_large_v32i8_ret() { + return { [1] = 1, [31] = 31 }; +} + +// Scalars passed on the stack should not have signext/zeroext attributes +// (they are anyext). + +fn int f_scalar_stack_1(Tiny a, Small b, Small_aligned c, + Large d, char e, ichar f, char g, ichar h) { + return g + h; +} + +fn int f_scalar_stack_2(int a, int128 b, long c, float128 d, char[<32>] e, + char f, ichar g, char h) { + return g + h; +} + +// Ensure that scalars passed on the stack are still determined correctly in +// the presence of large return values that consume a register due to the need +// to pass a pointer. + +fn Large f_scalar_stack_3(uint a, int128 b, float128 c, char[<32>] d, + char e, ichar f, char g) { + return {a, e, f, g}; +} + +// Ensure that ABI lowering happens as expected for vararg calls. +// Specifically, ensure that signext is emitted for varargs that will be +// passed in registers but not on the stack. Ensure this takes into account +// the use of "aligned" register pairs for varargs with 2*xlen alignment. + +extern fn int f_va_callee(int, ...); + +fn void f_va_caller() { + float128 fq; + f_va_callee(1, 2, 3i64, 4.0f, 5.0, (Tiny){6, 7, 8, 9}, + (Small){10, null}, (Small_aligned){11}, + (Large){12, 13, 14, 15}); + f_va_callee(1, 2, 3, 4, fq, 6, 7, 8, 9); + f_va_callee(1, 2, 3, 4, (Small_aligned){5}, 6, 7, 8, 9); + f_va_callee(1, 2, 3, 4, (Small){5,null}, 6, 7, 8, 9); + f_va_callee(1, 2, 3, 4, 5, fq, 7, 8, 9); + f_va_callee(1, 2, 3, 4, 5, (Small_aligned){6}, 7, 8, 9); + f_va_callee(1, 2, 3, 4, 5, (Small){6, null}, 7, 8, 9); + f_va_callee(1, 2, 3, 4, 5, 6, fq, 8, 9); + f_va_callee(1, 2, 3, 4, 5, 6, (Small_aligned){7}, 8, 9); + f_va_callee(1, 2, 3, 4, 5, 6, (Small){7, null}, 8, 9); +} + + +/* #expect: test.ll + +define void @test.f_void() +define zeroext i8 @test.f_scalar_0(i8 zeroext %0) +define signext i32 @test.f_scalar_1(i8 signext %0) +define zeroext i8 @test.f_scalar_2(i8 zeroext %0) +define signext i32 @test.f_scalar_3(i32 signext %0) +define i64 @test.f_scalar_4(i64 %0) +define float @test.f_fp_scalar_1(float %0) +define double @test.f_fp_scalar_2(double %0) +define fp128 @test.f_fp_scalar_3(fp128 %0) +define void @test.f_agg_tiny(i64 %0) +define i64 @test.f_agg_tiny_ret() +define void @test.f_vec_tiny_v4i16(i64 %0) +define i64 @test.f_vec_tiny_v4i16_ret() +define void @test.f_vec_tiny_v1i64(i64 %0) +define i64 @test.f_vec_tiny_v1i64_ret() +define void @test.f_agg_small([2 x i64] %0) +define [2 x i64] @test.f_agg_small_ret() +define void @test.f_vec_small_v8i16(i128 %0) +define i128 @test.f_vec_small_v8i16_ret() +define void @test.f_vec_small_v1i128(i128 %0) +define i128 @test.f_vec_small_v1i128_ret() +define void @test.f_agg_small_aligned(i128 %0) +define i128 @test.f_agg_small_aligned_ret(i128 %0) +define void @test.f_agg_large(ptr align 8 %0) +define void @test.f_agg_large_ret(ptr noalias sret(%Large) align 8 %0, i32 signext %1, i8 signext %2) +define void @test.f_vec_large_v32i8(ptr align 32 %0) +define void @test.f_vec_large_v32i8_ret(ptr noalias sret(<32 x i8>) align 32 %0) +define signext i32 @test.f_scalar_stack_1(i64 %0, [2 x i64] %1, i128 %2, ptr align 8 %3, i8 zeroext %4, i8 signext %5, i8 %6, i8 %7) +define signext i32 @test.f_scalar_stack_2(i32 signext %0, i128 %1, i64 %2, fp128 %3, ptr align 32 %4, i8 zeroext %5, i8 %6, i8 %7) +define void @test.f_scalar_stack_3(ptr noalias sret(%Large) align 8 %0, i32 signext %1, i128 %2, fp128 %3, ptr align 32 %4, i8 zeroext %5, i8 %6, i8 %7) +declare signext i32 @f_va_callee(i32 signext, ...) + call void @llvm.memcpy.p0.p0.i32(ptr align 8 %indirectarg, ptr align 8 %literal3, i32 32, i1 false) + %3 = call i32 (i32, ...) @f_va_callee(i32 signext 1, i32 signext 2, i64 3, double 4.000000e+00, double 5.000000e+00, i64 %0, [2 x i64] %1, i128 %2, ptr align 8 %indirectarg) + %5 = call i32 (i32, ...) @f_va_callee(i32 signext 1, i32 signext 2, i32 signext 3, i32 signext 4, fp128 %4, i32 signext 6, i32 signext 7, i32 8, i32 9) + %7 = call i32 (i32, ...) @f_va_callee(i32 signext 1, i32 signext 2, i32 signext 3, i32 signext 4, i128 %6, i32 signext 6, i32 signext 7, i32 8, i32 9) + %9 = call i32 (i32, ...) @f_va_callee(i32 signext 1, i32 signext 2, i32 signext 3, i32 signext 4, [2 x i64] %8, i32 signext 6, i32 signext 7, i32 8, i32 9) + %11 = call i32 (i32, ...) @f_va_callee(i32 signext 1, i32 signext 2, i32 signext 3, i32 signext 4, i32 signext 5, fp128 %10, i32 7, i32 8, i32 9) + %13 = call i32 (i32, ...) @f_va_callee(i32 signext 1, i32 signext 2, i32 signext 3, i32 signext 4, i32 signext 5, i128 %12, i32 7, i32 8, i32 9) + %15 = call i32 (i32, ...) @f_va_callee(i32 signext 1, i32 signext 2, i32 signext 3, i32 signext 4, i32 signext 5, [2 x i64] %14, i32 signext 7, i32 8, i32 9) + %17 = call i32 (i32, ...) @f_va_callee(i32 signext 1, i32 signext 2, i32 signext 3, i32 signext 4, i32 signext 5, i32 signext 6, fp128 %16, i32 8, i32 9) + %19 = call i32 (i32, ...) @f_va_callee(i32 signext 1, i32 signext 2, i32 signext 3, i32 signext 4, i32 signext 5, i32 signext 6, i128 %18, i32 8, i32 9) + %21 = call i32 (i32, ...) @f_va_callee(i32 signext 1, i32 signext 2, i32 signext 3, i32 signext 4, i32 signext 5, i32 signext 6, [2 x i64] %20, i32 8, i32 9) \ No newline at end of file diff --git a/test/test_suite7/abi/riscv64-lp64-lp64f-lp64d-abi-2.c3t b/test/test_suite7/abi/riscv64-lp64-lp64f-lp64d-abi-2.c3t new file mode 100644 index 000000000..23a674e8f --- /dev/null +++ b/test/test_suite7/abi/riscv64-lp64-lp64f-lp64d-abi-2.c3t @@ -0,0 +1,207 @@ +// #target: linux-riscv64 +// #opt: --riscvfloat=float +module test; + +fn void f_void() {} + +fn bool f_scalar_0(bool x) { return x; } +fn int f_scalar_1(ichar x) { return x; } +fn char f_scalar_2(char x) { return x; } +fn uint f_scalar_3(int x) { return x; } +fn long f_scalar_4(long x) { return x; } +fn float f_fp_scalar_1(float x) { return x; } +fn double f_fp_scalar_2(double x) { return x; } +fn float128 f_fp_scalar_3(float128 x) { return x; } + +// Aggregates <= 2*xlen may be passed in registers, so will be coerced to +// integer arguments. The rules for return are the same. + +struct Tiny { + ushort a, b, c, d; +} + +fn void f_agg_tiny(Tiny x) { + x.a += x.b; + x.c += x.d; +} + +fn Tiny f_agg_tiny_ret() { + return {1, 2, 3, 4}; +} + +fn void f_vec_tiny_v4i16(short[<4>] x) { + x[0] = x[1]; + x[2] = x[3]; +} + +fn short[<4>] f_vec_tiny_v4i16_ret() { + return {1, 2, 3, 4}; +} + +fn void f_vec_tiny_v1i64(long[<1>] x) { + x[0] = 114; +} + +fn long[<1>] f_vec_tiny_v1i64_ret() { + return {1}; +} + +struct Small { + long a; + long *b; +} + +fn void f_agg_small(Small x) { + x.a += *x.b; + x.b = &x.a; +} + +fn Small f_agg_small_ret() { + return {1, null}; +} + +fn void f_vec_small_v8i16(short[<8>] x) { + x[0] = x[7]; +} + +fn short[<8>] f_vec_small_v8i16_ret() { + return {1, 2, 3, 4, 5, 6, 7, 8}; +} + +fn void f_vec_small_v1i128(int128[<1>] x) { + x[0] = 114; +} + +fn int128[<1>] f_vec_small_v1i128_ret() { + return {1}; +} + +// Aggregates of 2*xlen size and 2*xlen alignment should be coerced to a +// single 2*xlen-sized argument, to ensure that alignment can be maintained if +// passed on the stack. + +struct Small_aligned { + int128 a; +} + +fn void f_agg_small_aligned(Small_aligned x) { + x.a += x.a; +} + +fn Small_aligned f_agg_small_aligned_ret(Small_aligned x) { + return {10}; +} + +// Aggregates greater > 2*xlen will be passed and returned indirectly +struct Large { + long a, b, c, d; +} + +fn void f_agg_large(Large x) { + x.a = x.b + x.c + x.d; +} + +// The address where the struct should be written to will be the first +// argument +fn Large f_agg_large_ret(int i, ichar j) { + return {1, 2, 3, 4}; +} + +fn void f_vec_large_v32i8(char[<32>] x) { + x[0] = x[7]; +} + +fn char[<32>] f_vec_large_v32i8_ret() { + return { [1] = 1, [31] = 31 }; +} + +// Scalars passed on the stack should not have signext/zeroext attributes +// (they are anyext). + +fn int f_scalar_stack_1(Tiny a, Small b, Small_aligned c, + Large d, char e, ichar f, char g, ichar h) { + return g + h; +} + +fn int f_scalar_stack_2(int a, int128 b, long c, float128 d, char[<32>] e, + char f, ichar g, char h) { + return g + h; +} + +// Ensure that scalars passed on the stack are still determined correctly in +// the presence of large return values that consume a register due to the need +// to pass a pointer. + +fn Large f_scalar_stack_3(uint a, int128 b, float128 c, char[<32>] d, + char e, ichar f, char g) { + return {a, e, f, g}; +} + +// Ensure that ABI lowering happens as expected for vararg calls. +// Specifically, ensure that signext is emitted for varargs that will be +// passed in registers but not on the stack. Ensure this takes into account +// the use of "aligned" register pairs for varargs with 2*xlen alignment. + +extern fn int f_va_callee(int, ...); + +fn void f_va_caller() { + float128 fq; + f_va_callee(1, 2, 3i64, 4.0f, 5.0, (Tiny){6, 7, 8, 9}, + (Small){10, null}, (Small_aligned){11}, + (Large){12, 13, 14, 15}); + f_va_callee(1, 2, 3, 4, fq, 6, 7, 8, 9); + f_va_callee(1, 2, 3, 4, (Small_aligned){5}, 6, 7, 8, 9); + f_va_callee(1, 2, 3, 4, (Small){5,null}, 6, 7, 8, 9); + f_va_callee(1, 2, 3, 4, 5, fq, 7, 8, 9); + f_va_callee(1, 2, 3, 4, 5, (Small_aligned){6}, 7, 8, 9); + f_va_callee(1, 2, 3, 4, 5, (Small){6, null}, 7, 8, 9); + f_va_callee(1, 2, 3, 4, 5, 6, fq, 8, 9); + f_va_callee(1, 2, 3, 4, 5, 6, (Small_aligned){7}, 8, 9); + f_va_callee(1, 2, 3, 4, 5, 6, (Small){7, null}, 8, 9); +} + + +/* #expect: test.ll + +define void @test.f_void() +define zeroext i8 @test.f_scalar_0(i8 zeroext %0) +define signext i32 @test.f_scalar_1(i8 signext %0) +define zeroext i8 @test.f_scalar_2(i8 zeroext %0) +define signext i32 @test.f_scalar_3(i32 signext %0) +define i64 @test.f_scalar_4(i64 %0) +define float @test.f_fp_scalar_1(float %0) +define double @test.f_fp_scalar_2(double %0) +define fp128 @test.f_fp_scalar_3(fp128 %0) +define void @test.f_agg_tiny(i64 %0) +define i64 @test.f_agg_tiny_ret() +define void @test.f_vec_tiny_v4i16(i64 %0) +define i64 @test.f_vec_tiny_v4i16_ret() +define void @test.f_vec_tiny_v1i64(i64 %0) +define i64 @test.f_vec_tiny_v1i64_ret() +define void @test.f_agg_small([2 x i64] %0) +define [2 x i64] @test.f_agg_small_ret() +define void @test.f_vec_small_v8i16(i128 %0) +define i128 @test.f_vec_small_v8i16_ret() +define void @test.f_vec_small_v1i128(i128 %0) +define i128 @test.f_vec_small_v1i128_ret() +define void @test.f_agg_small_aligned(i128 %0) +define i128 @test.f_agg_small_aligned_ret(i128 %0) +define void @test.f_agg_large(ptr align 8 %0) +define void @test.f_agg_large_ret(ptr noalias sret(%Large) align 8 %0, i32 signext %1, i8 signext %2) +define void @test.f_vec_large_v32i8(ptr align 32 %0) +define void @test.f_vec_large_v32i8_ret(ptr noalias sret(<32 x i8>) align 32 %0) +define signext i32 @test.f_scalar_stack_1(i64 %0, [2 x i64] %1, i128 %2, ptr align 8 %3, i8 zeroext %4, i8 signext %5, i8 %6, i8 %7) +define signext i32 @test.f_scalar_stack_2(i32 signext %0, i128 %1, i64 %2, fp128 %3, ptr align 32 %4, i8 zeroext %5, i8 %6, i8 %7) +define void @test.f_scalar_stack_3(ptr noalias sret(%Large) align 8 %0, i32 signext %1, i128 %2, fp128 %3, ptr align 32 %4, i8 zeroext %5, i8 %6, i8 %7) +declare signext i32 @f_va_callee(i32 signext, ...) + call void @llvm.memcpy.p0.p0.i32(ptr align 8 %indirectarg, ptr align 8 %literal3, i32 32, i1 false) + %3 = call i32 (i32, ...) @f_va_callee(i32 signext 1, i32 signext 2, i64 3, double 4.000000e+00, double 5.000000e+00, i64 %0, [2 x i64] %1, i128 %2, ptr align 8 %indirectarg) + %5 = call i32 (i32, ...) @f_va_callee(i32 signext 1, i32 signext 2, i32 signext 3, i32 signext 4, fp128 %4, i32 signext 6, i32 signext 7, i32 8, i32 9) + %7 = call i32 (i32, ...) @f_va_callee(i32 signext 1, i32 signext 2, i32 signext 3, i32 signext 4, i128 %6, i32 signext 6, i32 signext 7, i32 8, i32 9) + %9 = call i32 (i32, ...) @f_va_callee(i32 signext 1, i32 signext 2, i32 signext 3, i32 signext 4, [2 x i64] %8, i32 signext 6, i32 signext 7, i32 8, i32 9) + %11 = call i32 (i32, ...) @f_va_callee(i32 signext 1, i32 signext 2, i32 signext 3, i32 signext 4, i32 signext 5, fp128 %10, i32 7, i32 8, i32 9) + %13 = call i32 (i32, ...) @f_va_callee(i32 signext 1, i32 signext 2, i32 signext 3, i32 signext 4, i32 signext 5, i128 %12, i32 7, i32 8, i32 9) + %15 = call i32 (i32, ...) @f_va_callee(i32 signext 1, i32 signext 2, i32 signext 3, i32 signext 4, i32 signext 5, [2 x i64] %14, i32 signext 7, i32 8, i32 9) + %17 = call i32 (i32, ...) @f_va_callee(i32 signext 1, i32 signext 2, i32 signext 3, i32 signext 4, i32 signext 5, i32 signext 6, fp128 %16, i32 8, i32 9) + %19 = call i32 (i32, ...) @f_va_callee(i32 signext 1, i32 signext 2, i32 signext 3, i32 signext 4, i32 signext 5, i32 signext 6, i128 %18, i32 8, i32 9) + %21 = call i32 (i32, ...) @f_va_callee(i32 signext 1, i32 signext 2, i32 signext 3, i32 signext 4, i32 signext 5, i32 signext 6, [2 x i64] %20, i32 8, i32 9) diff --git a/test/test_suite7/abi/riscv64-lp64-lp64f-lp64d-abi-3.c3t b/test/test_suite7/abi/riscv64-lp64-lp64f-lp64d-abi-3.c3t new file mode 100644 index 000000000..b9b9a2531 --- /dev/null +++ b/test/test_suite7/abi/riscv64-lp64-lp64f-lp64d-abi-3.c3t @@ -0,0 +1,207 @@ +// #target: linux-riscv64 +// #opt: --riscvfloat=double +module test; + +fn void f_void() {} + +fn bool f_scalar_0(bool x) { return x; } +fn int f_scalar_1(ichar x) { return x; } +fn char f_scalar_2(char x) { return x; } +fn uint f_scalar_3(int x) { return x; } +fn long f_scalar_4(long x) { return x; } +fn float f_fp_scalar_1(float x) { return x; } +fn double f_fp_scalar_2(double x) { return x; } +fn float128 f_fp_scalar_3(float128 x) { return x; } + +// Aggregates <= 2*xlen may be passed in registers, so will be coerced to +// integer arguments. The rules for return are the same. + +struct Tiny { + ushort a, b, c, d; +} + +fn void f_agg_tiny(Tiny x) { + x.a += x.b; + x.c += x.d; +} + +fn Tiny f_agg_tiny_ret() { + return {1, 2, 3, 4}; +} + +fn void f_vec_tiny_v4i16(short[<4>] x) { + x[0] = x[1]; + x[2] = x[3]; +} + +fn short[<4>] f_vec_tiny_v4i16_ret() { + return {1, 2, 3, 4}; +} + +fn void f_vec_tiny_v1i64(long[<1>] x) { + x[0] = 114; +} + +fn long[<1>] f_vec_tiny_v1i64_ret() { + return {1}; +} + +struct Small { + long a; + long *b; +} + +fn void f_agg_small(Small x) { + x.a += *x.b; + x.b = &x.a; +} + +fn Small f_agg_small_ret() { + return {1, null}; +} + +fn void f_vec_small_v8i16(short[<8>] x) { + x[0] = x[7]; +} + +fn short[<8>] f_vec_small_v8i16_ret() { + return {1, 2, 3, 4, 5, 6, 7, 8}; +} + +fn void f_vec_small_v1i128(int128[<1>] x) { + x[0] = 114; +} + +fn int128[<1>] f_vec_small_v1i128_ret() { + return {1}; +} + +// Aggregates of 2*xlen size and 2*xlen alignment should be coerced to a +// single 2*xlen-sized argument, to ensure that alignment can be maintained if +// passed on the stack. + +struct Small_aligned { + int128 a; +} + +fn void f_agg_small_aligned(Small_aligned x) { + x.a += x.a; +} + +fn Small_aligned f_agg_small_aligned_ret(Small_aligned x) { + return {10}; +} + +// Aggregates greater > 2*xlen will be passed and returned indirectly +struct Large { + long a, b, c, d; +} + +fn void f_agg_large(Large x) { + x.a = x.b + x.c + x.d; +} + +// The address where the struct should be written to will be the first +// argument +fn Large f_agg_large_ret(int i, ichar j) { + return {1, 2, 3, 4}; +} + +fn void f_vec_large_v32i8(char[<32>] x) { + x[0] = x[7]; +} + +fn char[<32>] f_vec_large_v32i8_ret() { + return { [1] = 1, [31] = 31 }; +} + +// Scalars passed on the stack should not have signext/zeroext attributes +// (they are anyext). + +fn int f_scalar_stack_1(Tiny a, Small b, Small_aligned c, + Large d, char e, ichar f, char g, ichar h) { + return g + h; +} + +fn int f_scalar_stack_2(int a, int128 b, long c, float128 d, char[<32>] e, + char f, ichar g, char h) { + return g + h; +} + +// Ensure that scalars passed on the stack are still determined correctly in +// the presence of large return values that consume a register due to the need +// to pass a pointer. + +fn Large f_scalar_stack_3(uint a, int128 b, float128 c, char[<32>] d, + char e, ichar f, char g) { + return {a, e, f, g}; +} + +// Ensure that ABI lowering happens as expected for vararg calls. +// Specifically, ensure that signext is emitted for varargs that will be +// passed in registers but not on the stack. Ensure this takes into account +// the use of "aligned" register pairs for varargs with 2*xlen alignment. + +extern fn int f_va_callee(int, ...); + +fn void f_va_caller() { + float128 fq; + f_va_callee(1, 2, 3i64, 4.0f, 5.0, (Tiny){6, 7, 8, 9}, + (Small){10, null}, (Small_aligned){11}, + (Large){12, 13, 14, 15}); + f_va_callee(1, 2, 3, 4, fq, 6, 7, 8, 9); + f_va_callee(1, 2, 3, 4, (Small_aligned){5}, 6, 7, 8, 9); + f_va_callee(1, 2, 3, 4, (Small){5,null}, 6, 7, 8, 9); + f_va_callee(1, 2, 3, 4, 5, fq, 7, 8, 9); + f_va_callee(1, 2, 3, 4, 5, (Small_aligned){6}, 7, 8, 9); + f_va_callee(1, 2, 3, 4, 5, (Small){6, null}, 7, 8, 9); + f_va_callee(1, 2, 3, 4, 5, 6, fq, 8, 9); + f_va_callee(1, 2, 3, 4, 5, 6, (Small_aligned){7}, 8, 9); + f_va_callee(1, 2, 3, 4, 5, 6, (Small){7, null}, 8, 9); +} + + +/* #expect: test.ll + +define void @test.f_void() +define zeroext i8 @test.f_scalar_0(i8 zeroext %0) +define signext i32 @test.f_scalar_1(i8 signext %0) +define zeroext i8 @test.f_scalar_2(i8 zeroext %0) +define signext i32 @test.f_scalar_3(i32 signext %0) +define i64 @test.f_scalar_4(i64 %0) +define float @test.f_fp_scalar_1(float %0) +define double @test.f_fp_scalar_2(double %0) +define fp128 @test.f_fp_scalar_3(fp128 %0) +define void @test.f_agg_tiny(i64 %0) +define i64 @test.f_agg_tiny_ret() +define void @test.f_vec_tiny_v4i16(i64 %0) +define i64 @test.f_vec_tiny_v4i16_ret() +define void @test.f_vec_tiny_v1i64(i64 %0) +define i64 @test.f_vec_tiny_v1i64_ret() +define void @test.f_agg_small([2 x i64] %0) +define [2 x i64] @test.f_agg_small_ret() +define void @test.f_vec_small_v8i16(i128 %0) +define i128 @test.f_vec_small_v8i16_ret() +define void @test.f_vec_small_v1i128(i128 %0) +define i128 @test.f_vec_small_v1i128_ret() +define void @test.f_agg_small_aligned(i128 %0) +define i128 @test.f_agg_small_aligned_ret(i128 %0) +define void @test.f_agg_large(ptr align 8 %0) +define void @test.f_agg_large_ret(ptr noalias sret(%Large) align 8 %0, i32 signext %1, i8 signext %2) +define void @test.f_vec_large_v32i8(ptr align 32 %0) +define void @test.f_vec_large_v32i8_ret(ptr noalias sret(<32 x i8>) align 32 %0) +define signext i32 @test.f_scalar_stack_1(i64 %0, [2 x i64] %1, i128 %2, ptr align 8 %3, i8 zeroext %4, i8 signext %5, i8 %6, i8 %7) +define signext i32 @test.f_scalar_stack_2(i32 signext %0, i128 %1, i64 %2, fp128 %3, ptr align 32 %4, i8 zeroext %5, i8 %6, i8 %7) +define void @test.f_scalar_stack_3(ptr noalias sret(%Large) align 8 %0, i32 signext %1, i128 %2, fp128 %3, ptr align 32 %4, i8 zeroext %5, i8 %6, i8 %7) +declare signext i32 @f_va_callee(i32 signext, ...) + call void @llvm.memcpy.p0.p0.i32(ptr align 8 %indirectarg, ptr align 8 %literal3, i32 32, i1 false) + %3 = call i32 (i32, ...) @f_va_callee(i32 signext 1, i32 signext 2, i64 3, double 4.000000e+00, double 5.000000e+00, i64 %0, [2 x i64] %1, i128 %2, ptr align 8 %indirectarg) + %5 = call i32 (i32, ...) @f_va_callee(i32 signext 1, i32 signext 2, i32 signext 3, i32 signext 4, fp128 %4, i32 signext 6, i32 signext 7, i32 8, i32 9) + %7 = call i32 (i32, ...) @f_va_callee(i32 signext 1, i32 signext 2, i32 signext 3, i32 signext 4, i128 %6, i32 signext 6, i32 signext 7, i32 8, i32 9) + %9 = call i32 (i32, ...) @f_va_callee(i32 signext 1, i32 signext 2, i32 signext 3, i32 signext 4, [2 x i64] %8, i32 signext 6, i32 signext 7, i32 8, i32 9) + %11 = call i32 (i32, ...) @f_va_callee(i32 signext 1, i32 signext 2, i32 signext 3, i32 signext 4, i32 signext 5, fp128 %10, i32 7, i32 8, i32 9) + %13 = call i32 (i32, ...) @f_va_callee(i32 signext 1, i32 signext 2, i32 signext 3, i32 signext 4, i32 signext 5, i128 %12, i32 7, i32 8, i32 9) + %15 = call i32 (i32, ...) @f_va_callee(i32 signext 1, i32 signext 2, i32 signext 3, i32 signext 4, i32 signext 5, [2 x i64] %14, i32 signext 7, i32 8, i32 9) + %17 = call i32 (i32, ...) @f_va_callee(i32 signext 1, i32 signext 2, i32 signext 3, i32 signext 4, i32 signext 5, i32 signext 6, fp128 %16, i32 8, i32 9) + %19 = call i32 (i32, ...) @f_va_callee(i32 signext 1, i32 signext 2, i32 signext 3, i32 signext 4, i32 signext 5, i32 signext 6, i128 %18, i32 8, i32 9) + %21 = call i32 (i32, ...) @f_va_callee(i32 signext 1, i32 signext 2, i32 signext 3, i32 signext 4, i32 signext 5, i32 signext 6, [2 x i64] %20, i32 8, i32 9) \ No newline at end of file diff --git a/test/test_suite7/abi/riscv64-lp64d-abi.c3t b/test/test_suite7/abi/riscv64-lp64d-abi.c3t new file mode 100644 index 000000000..fdbb448bd --- /dev/null +++ b/test/test_suite7/abi/riscv64-lp64d-abi.c3t @@ -0,0 +1,451 @@ +// #target: linux-riscv64 +// #opt: --riscvfloat=double +module test; + +// Verify that the tracking of used GPRs and FPRs works correctly by checking +// that small integers are sign/zero extended when passed in registers. + +// Doubles are passed in FPRs, so argument 'i' will be passed zero-extended +// because it will be passed in a GPR. + +fn void f_fpr_tracking(double a, double b, double c, double d, double e, double f, + double g, double h, char i) {} + +// Check that fp, fp+fp, and int+fp structs are lowered correctly. These will +// be passed in FPR, FPR+FPR, or GPR+FPR regs if sufficient registers are +// available the widths are <= XLEN and FLEN, and should be expanded to +// separate arguments in IR. They are passed by the same rules for returns, +// but will be lowered to simple two-element structs if necessary (as LLVM IR +// functions cannot return multiple values). + +// A struct containing just one floating-point real is passed as though it +// were a standalone floating-point real. + +struct Double_s { double f; } + +fn void f_double_s_arg(Double_s a) {} + +fn Double_s f_ret_double_s() { + return {1.0}; +} + +// A struct containing a double and any number of zero-width bitfields is +// passed as though it were a standalone floating-point real. + +// Check that structs containing two floating point values (FLEN <= width) are +// expanded provided sufficient FPRs are available. + +struct Double_double_s { double f; double g; } +struct Double_float_s { double f; float g; } + +fn void f_double_double_s_arg(Double_double_s a) {} + +fn Double_double_s f_ret_double_double_s() { + return {1.0, 2.0}; +} + +fn void f_double_float_s_arg(Double_float_s a) {} +fn Double_float_s f_ret_double_float_s() { + return {1.0, 2.0}; +} + +fn void f_double_double_s_arg_insufficient_fprs(float a, double b, double c, double d, + double e, double f, double g, Double_double_s h) {} + +// Check that structs containing int+double values are expanded, provided +// sufficient FPRs and GPRs are available. The integer components are neither +// sign or zero-extended. + +struct Double_int8_s { double f; ichar i; } +struct Double_uint8_s { double f; char i; } +struct Double_int32_s { double f; int i; } +struct Double_int64_s { double f; long i; } + +fn void f_double_int8_s_arg(Double_int8_s a) {} + +fn Double_int8_s f_ret_double_int8_s() { + return {1.0, 2}; +} + +fn void f_double_uint8_s_arg(Double_uint8_s a) {} + +fn Double_uint8_s f_ret_double_uint8_s() { + return {1.0, 2}; +} + +fn void f_double_int32_s_arg(Double_int32_s a) {} + +fn Double_int32_s f_ret_double_int32_s() { + return {1.0, 2}; +} + +fn void f_double_int64_s_arg(Double_int64_s a) {} + +fn Double_int64_s f_ret_double_int64_s() { + return {1.0, 2}; +} + + +fn void f_double_int8_s_arg_insufficient_gprs(int a, int b, int c, int d, int e, + int f, int g, int h, Double_int8_s i) {} + +fn void f_struct_double_int8_insufficient_fprs(float a, double b, double c, double d, + double e, double f, double g, double h, Double_int8_s i) {} + + +// Test single or two-element structs that need flattening. e.g. those +// containing nested structs, doubles in small arrays, zero-length structs etc. + +struct Doublearr1_s { double[1] a; } + +fn void f_doublearr1_s_arg(Doublearr1_s a) {} + +fn Doublearr1_s f_ret_doublearr1_s() { + return {{1.0}}; +} + +struct Doublearr2_s { double[2] a; } + +fn void f_doublearr2_s_arg(Doublearr2_s a) {} + +fn Doublearr2_s f_ret_doublearr2_s() { + return {{1.0, 2.0}}; +} + +struct Inner { double[1] f; } +struct Doublearr2_tricky1_s { Inner[2] g; } + +fn void f_doublearr2_tricky1_s_arg(Doublearr2_tricky1_s a) {} + +fn Doublearr2_tricky1_s f_ret_doublearr2_tricky1_s() { + return {{{{1.0}}, {{2.0}}}}; +} + +// Test structs that should be passed according to the normal integer calling +// convention. + +struct Int_double_int_s { int a; double b; int c; } + +fn void f_int_double_int_s_arg(Int_double_int_s a) {} + +fn Int_double_int_s f_ret_int_double_int_s() { + return {1, 2.0, 3}; +} + +struct Char_char_double_s { char a; char b; double c; } + +fn void f_char_char_double_s_arg(Char_char_double_s a) {} + +fn Char_char_double_s f_ret_char_char_double_s() { + return {1, 2, 3.0}; +} + +// Unions are always passed according to the integer calling convention, even +// if they can only contain a double. + +union Double_u { double a; } + +fn void f_double_u_arg(Double_u a) {} + +fn Double_u f_ret_double_u() { + return {1.0}; +} + +/* #expect: test.ll + +define void @test.f_fpr_tracking(double %0, double %1, double %2, double %3, double %4, double %5, double %6, double %7, i8 zeroext %8) #0 { +entry: + ret void +} + + +define void @test.f_double_s_arg(double %0) #0 { +entry: + %a = alloca %Double_s, align 8 + store double %0, ptr %a, align 8 + ret void +} + + +define double @test.f_ret_double_s() #0 { +entry: + %literal = alloca %Double_s, align 8 + call void @llvm.memcpy.p0.p0.i32(ptr align 8 %literal, ptr align 8 @.__const, i32 8, i1 false) + %0 = load double, ptr %literal, align 8 + ret double %0 +} + + +define void @test.f_double_double_s_arg(double %0, double %1) #0 { +entry: + %a = alloca %Double_double_s, align 8 + store double %0, ptr %a, align 8 + %ptradd = getelementptr inbounds i8, ptr %a, i64 8 + store double %1, ptr %a, align 8 + ret void +} + + +define { double, double } @test.f_ret_double_double_s() #0 { +entry: + %literal = alloca %Double_double_s, align 8 + call void @llvm.memcpy.p0.p0.i32(ptr align 8 %literal, ptr align 8 @.__const.1, i32 16, i1 false) + %0 = load double, ptr %literal, align 8 + %ptradd = getelementptr inbounds i8, ptr %literal, i64 8 + %1 = load double, ptr %literal, align 8 + %2 = insertvalue { double, double } undef, double %0, 0 + %3 = insertvalue { double, double } %2, double %1, 1 + ret { double, double } %3 +} + + +define void @test.f_double_float_s_arg(double %0, float %1) #0 { +entry: + %a = alloca %Double_float_s, align 8 + store double %0, ptr %a, align 8 + %ptradd = getelementptr inbounds i8, ptr %a, i64 8 + store float %1, ptr %a, align 8 + ret void +} + + +define { double, float } @test.f_ret_double_float_s() #0 { +entry: + %literal = alloca %Double_float_s, align 8 + call void @llvm.memcpy.p0.p0.i32(ptr align 8 %literal, ptr align 8 @.__const.2, i32 16, i1 false) + %0 = load double, ptr %literal, align 8 + %ptradd = getelementptr inbounds i8, ptr %literal, i64 8 + %1 = load float, ptr %literal, align 8 + %2 = insertvalue { double, float } undef, double %0, 0 + %3 = insertvalue { double, float } %2, float %1, 1 + ret { double, float } %3 +} + + +define void @test.f_double_double_s_arg_insufficient_fprs(float %0, double %1, double %2, double %3, double %4, double %5, double %6, [2 x i64] %7) #0 { +entry: + %h = alloca %Double_double_s, align 8 + store [2 x i64] %7, ptr %h, align 8 + ret void +} + + +define void @test.f_double_int8_s_arg(double %0, i8 %1) #0 { +entry: + %a = alloca %Double_int8_s, align 8 + store double %0, ptr %a, align 8 + %ptradd = getelementptr inbounds i8, ptr %a, i64 8 + store i8 %1, ptr %a, align 8 + ret void +} + + +define { double, i8 } @test.f_ret_double_int8_s() #0 { +entry: + %literal = alloca %Double_int8_s, align 8 + call void @llvm.memcpy.p0.p0.i32(ptr align 8 %literal, ptr align 8 @.__const.3, i32 16, i1 false) + %0 = load double, ptr %literal, align 8 + %ptradd = getelementptr inbounds i8, ptr %literal, i64 8 + %1 = load i8, ptr %literal, align 8 + %2 = insertvalue { double, i8 } undef, double %0, 0 + %3 = insertvalue { double, i8 } %2, i8 %1, 1 + ret { double, i8 } %3 +} + + +define void @test.f_double_uint8_s_arg(double %0, i8 %1) #0 { +entry: + %a = alloca %Double_uint8_s, align 8 + store double %0, ptr %a, align 8 + %ptradd = getelementptr inbounds i8, ptr %a, i64 8 + store i8 %1, ptr %a, align 8 + ret void +} + + +define { double, i8 } @test.f_ret_double_uint8_s() #0 { +entry: + %literal = alloca %Double_uint8_s, align 8 + call void @llvm.memcpy.p0.p0.i32(ptr align 8 %literal, ptr align 8 @.__const.4, i32 16, i1 false) + %0 = load double, ptr %literal, align 8 + %ptradd = getelementptr inbounds i8, ptr %literal, i64 8 + %1 = load i8, ptr %literal, align 8 + %2 = insertvalue { double, i8 } undef, double %0, 0 + %3 = insertvalue { double, i8 } %2, i8 %1, 1 + ret { double, i8 } %3 +} + + +define void @test.f_double_int32_s_arg(double %0, i32 %1) #0 { +entry: + %a = alloca %Double_int32_s, align 8 + store double %0, ptr %a, align 8 + %ptradd = getelementptr inbounds i8, ptr %a, i64 8 + store i32 %1, ptr %a, align 8 + ret void +} + + +define { double, i32 } @test.f_ret_double_int32_s() #0 { +entry: + %literal = alloca %Double_int32_s, align 8 + call void @llvm.memcpy.p0.p0.i32(ptr align 8 %literal, ptr align 8 @.__const.5, i32 16, i1 false) + %0 = load double, ptr %literal, align 8 + %ptradd = getelementptr inbounds i8, ptr %literal, i64 8 + %1 = load i32, ptr %literal, align 8 + %2 = insertvalue { double, i32 } undef, double %0, 0 + %3 = insertvalue { double, i32 } %2, i32 %1, 1 + ret { double, i32 } %3 +} + + +define void @test.f_double_int64_s_arg(double %0, i64 %1) #0 { +entry: + %a = alloca %Double_int64_s, align 8 + store double %0, ptr %a, align 8 + %ptradd = getelementptr inbounds i8, ptr %a, i64 8 + store i64 %1, ptr %a, align 8 + ret void +} + + +define { double, i64 } @test.f_ret_double_int64_s() #0 { +entry: + %literal = alloca %Double_int64_s, align 8 + call void @llvm.memcpy.p0.p0.i32(ptr align 8 %literal, ptr align 8 @.__const.6, i32 16, i1 false) + %0 = load double, ptr %literal, align 8 + %ptradd = getelementptr inbounds i8, ptr %literal, i64 8 + %1 = load i64, ptr %literal, align 8 + %2 = insertvalue { double, i64 } undef, double %0, 0 + %3 = insertvalue { double, i64 } %2, i64 %1, 1 + ret { double, i64 } %3 +} + + +define void @test.f_double_int8_s_arg_insufficient_gprs(i32 signext %0, i32 signext %1, i32 signext %2, i32 signext %3, i32 signext %4, i32 signext %5, i32 signext %6, i32 signext %7, [2 x i64] %8) #0 { +entry: + %i = alloca %Double_int8_s, align 8 + store [2 x i64] %8, ptr %i, align 8 + ret void +} + + +define void @test.f_struct_double_int8_insufficient_fprs(float %0, double %1, double %2, double %3, double %4, double %5, double %6, double %7, [2 x i64] %8) #0 { +entry: + %i = alloca %Double_int8_s, align 8 + store [2 x i64] %8, ptr %i, align 8 + ret void +} + + +define void @test.f_doublearr1_s_arg(double %0) #0 { +entry: + %a = alloca %Doublearr1_s, align 8 + store double %0, ptr %a, align 8 + ret void +} + + +define double @test.f_ret_doublearr1_s() #0 { +entry: + %literal = alloca %Doublearr1_s, align 8 + call void @llvm.memcpy.p0.p0.i32(ptr align 8 %literal, ptr align 8 @.__const.7, i32 8, i1 false) + %0 = load double, ptr %literal, align 8 + ret double %0 +} + + +define void @test.f_doublearr2_s_arg(double %0, double %1) #0 { +entry: + %a = alloca %Doublearr2_s, align 8 + store double %0, ptr %a, align 8 + %ptradd = getelementptr inbounds i8, ptr %a, i64 8 + store double %1, ptr %a, align 8 + ret void +} + + +define { double, double } @test.f_ret_doublearr2_s() #0 { +entry: + %literal = alloca %Doublearr2_s, align 8 + call void @llvm.memcpy.p0.p0.i32(ptr align 8 %literal, ptr align 8 @.__const.8, i32 16, i1 false) + %0 = load double, ptr %literal, align 8 + %ptradd = getelementptr inbounds i8, ptr %literal, i64 8 + %1 = load double, ptr %literal, align 8 + %2 = insertvalue { double, double } undef, double %0, 0 + %3 = insertvalue { double, double } %2, double %1, 1 + ret { double, double } %3 +} + + +define void @test.f_doublearr2_tricky1_s_arg(double %0, double %1) #0 { +entry: + %a = alloca %Doublearr2_tricky1_s, align 8 + store double %0, ptr %a, align 8 + %ptradd = getelementptr inbounds i8, ptr %a, i64 8 + store double %1, ptr %a, align 8 + ret void +} + + +define { double, double } @test.f_ret_doublearr2_tricky1_s() #0 { +entry: + %literal = alloca %Doublearr2_tricky1_s, align 8 + call void @llvm.memcpy.p0.p0.i32(ptr align 8 %literal, ptr align 8 @.__const.9, i32 16, i1 false) + %0 = load double, ptr %literal, align 8 + %ptradd = getelementptr inbounds i8, ptr %literal, i64 8 + %1 = load double, ptr %literal, align 8 + %2 = insertvalue { double, double } undef, double %0, 0 + %3 = insertvalue { double, double } %2, double %1, 1 + ret { double, double } %3 +} + + +define void @test.f_int_double_int_s_arg(ptr align 8 %0) #0 { +entry: + ret void +} + + +define void @test.f_ret_int_double_int_s(ptr noalias sret(%Int_double_int_s) align 8 %0) #0 { +entry: + %literal = alloca %Int_double_int_s, align 8 + call void @llvm.memcpy.p0.p0.i32(ptr align 8 %literal, ptr align 8 @.__const.10, i32 24, i1 false) + call void @llvm.memcpy.p0.p0.i32(ptr align 8 %0, ptr align 8 %literal, i32 24, i1 false) + ret void +} + + +define void @test.f_char_char_double_s_arg([2 x i64] %0) #0 { +entry: + %a = alloca %Char_char_double_s, align 8 + store [2 x i64] %0, ptr %a, align 8 + ret void +} + + +define [2 x i64] @test.f_ret_char_char_double_s() #0 { +entry: + %literal = alloca %Char_char_double_s, align 8 + call void @llvm.memcpy.p0.p0.i32(ptr align 8 %literal, ptr align 8 @.__const.11, i32 16, i1 false) + %0 = load [2 x i64], ptr %literal, align 8 + ret [2 x i64] %0 +} + + +define void @test.f_double_u_arg(i64 %0) #0 { +entry: + %a = alloca %Double_u, align 8 + store i64 %0, ptr %a, align 8 + ret void +} + + +define i64 @test.f_ret_double_u() #0 { +entry: + %literal = alloca %Double_u, align 8 + call void @llvm.memcpy.p0.p0.i32(ptr align 8 %literal, ptr align 8 @.__const.12, i32 8, i1 false) + %0 = load i64, ptr %literal, align 8 + ret i64 %0 +} + diff --git a/test/test_suite7/abi/riscv64-lp64f-lp64d-abi-1.c3t b/test/test_suite7/abi/riscv64-lp64f-lp64d-abi-1.c3t new file mode 100644 index 000000000..2ffa8a903 --- /dev/null +++ b/test/test_suite7/abi/riscv64-lp64f-lp64d-abi-1.c3t @@ -0,0 +1,184 @@ +// #target: linux-riscv64 +// #opt: --riscvfloat=float +module test; + +// Verify that the tracking of used GPRs and FPRs works correctly by checking +// that small integers are sign/zero extended when passed in registers. + +// Floats are passed in FPRs, so argument 'i' will be passed zero-extended +// because it will be passed in a GPR. + +fn void f_fpr_tracking(float a, float b, float c, float d, float e, float f, + float g, float h, char i) {} + +// Check that fp, fp+fp, and int+fp structs are lowered correctly. These will +// be passed in FPR, FPR+FPR, or GPR+FPR regs if sufficient registers are +// available the widths are <= XLEN and FLEN, and should be expanded to +// separate arguments in IR. They are passed by the same rules for returns, +// but will be lowered to simple two-element structs if necessary (as LLVM IR +// functions cannot return multiple values). + +// A struct containing just one floating-point real is passed as though it +// were a standalone floating-point real. + +struct Float_s { float f; } + +fn void f_float_s_arg(Float_s a) {} +fn Float_s f_ret_float_s() { + return {1.0}; +} + + +// Check that structs containing two float values (FLEN <= width) are expanded +// provided sufficient FPRs are available. + +struct Float_float_s { float f; float g; } + +fn void f_float_float_s_arg(Float_float_s a) {} + +fn Float_float_s f_ret_float_float_s() { + return {1.0, 2.0}; +} + +fn void f_float_float_s_arg_insufficient_fprs(float a, float b, float c, float d, + float e, float f, float g, Float_float_s h) {} + +// Check that structs containing int+float values are expanded, provided +// sufficient FPRs and GPRs are available. The integer components are neither +// sign or zero-extended. + +struct Float_int8_s { float f; ichar i; } +struct Float_uint8_s { float f; char i; } +struct Float_int32_s { float f; int i; } +struct Float_int64_s { float f; long i; } + +fn void f_float_int8_s_arg(Float_int8_s a) {} +fn Float_int8_s f_ret_float_int8_s() { + return {1.0, 2}; +} + +fn void f_float_uint8_s_arg(Float_uint8_s a) {} +fn Float_uint8_s f_ret_float_uint8_s() { + return {1.0, 2}; +} + +fn void f_float_int32_s_arg(Float_int32_s a) {} +fn Float_int32_s f_ret_float_int32_s() { + return {1.0, 2}; +} + +fn void f_float_int64_s_arg(Float_int64_s a) {} +fn Float_int64_s f_ret_float_int64_s() { + return {1.0, 2}; +} + + +fn void f_float_int8_s_arg_insufficient_gprs(int a, int b, int c, int d, int e, + int f, int g, int h, Float_int8_s i) {} + +fn void f_struct_float_int8_insufficient_fprs(float a, float b, float c, float d, + float e, float f, float g, float h, Float_int8_s i) {} + +// Test single or two-element structs that need flattening. e.g. those +// containing nested structs, floats in small arrays, zero-length structs etc. + +struct Floatarr1_s { float[1] a; } + +fn void f_floatarr1_s_arg(Floatarr1_s a) {} +fn Floatarr1_s f_ret_floatarr1_s() { + return {{1.0}}; +} + +struct Floatarr2_s { float[2] a; } +fn void f_floatarr2_s_arg(Floatarr2_s a) {} + +fn Floatarr2_s f_ret_floatarr2_s() { + return {{1.0, 2.0}}; +} + +struct Inner { float[1] f; } +struct Floatarr2_tricky1_s { Inner[2] g; } + +fn void f_floatarr2_tricky1_s_arg(Floatarr2_tricky1_s a) {} +fn Floatarr2_tricky1_s f_ret_floatarr2_tricky1_s() { + return {{{{1.0}}, {{2.0}}}}; +} + + +// Test structs that should be passed according to the normal integer calling +// convention. + +struct Int_float_int_s { int a; float b; int c; } + +fn void f_int_float_int_s_arg(Int_float_int_s a) {} + +fn Int_float_int_s f_ret_int_float_int_s() { + return {1, 2.0, 3}; +} + +struct Char_char_float_s { char a; char b; float c; } + +fn void f_char_char_float_s_arg(Char_char_float_s a) {} +fn Char_char_float_s f_ret_char_char_float_s() { + return {1, 2, 3.0}; +} + +// Unions are always passed according to the integer calling convention, even +// if they can only contain a float. + +union Float_u { float a; } + +fn void f_float_u_arg(Float_u a) {} +fn Float_u f_ret_float_u() { + return {1.0}; +} + +/* #expect: test.ll + +define void @test.f_fpr_tracking(float %0, float %1, float %2, float %3, float %4, float %5, float %6, float %7, i8 zeroext %8) #0 { + +define void @test.f_float_s_arg(float %0) #0 { +define float @test.f_ret_float_s() #0 { + +define void @test.f_float_float_s_arg(float %0, float %1) #0 { +define { float, float } @test.f_ret_float_float_s() #0 { +define void @test.f_float_float_s_arg_insufficient_fprs(float %0, float %1, float %2, float %3, float %4, float %5, float %6, i64 %7) #0 { +define void @test.f_float_int8_s_arg(float %0, i8 %1) #0 { +define { float, i8 } @test.f_ret_float_int8_s() #0 { + +define void @test.f_float_uint8_s_arg(float %0, i8 %1) #0 { + +define { float, i8 } @test.f_ret_float_uint8_s() #0 { + +define void @test.f_float_int32_s_arg(float %0, i32 %1) #0 { + +define { float, i32 } @test.f_ret_float_int32_s() #0 { +define void @test.f_float_int64_s_arg(float %0, i64 %1) #0 { + +define { float, i64 } @test.f_ret_float_int64_s() #0 { + +define void @test.f_float_int8_s_arg_insufficient_gprs(i32 signext %0, i32 signext %1, i32 signext %2, i32 signext %3, i32 signext %4, i32 signext %5, i32 signext %6, i32 signext %7, i64 %8) #0 { + +define void @test.f_struct_float_int8_insufficient_fprs(float %0, float %1, float %2, float %3, float %4, float %5, float %6, float %7, i64 %8) #0 { + +define void @test.f_floatarr1_s_arg(float %0) #0 { + +define float @test.f_ret_floatarr1_s() #0 { + +define void @test.f_floatarr2_s_arg(float %0, float %1) #0 { + +define { float, float } @test.f_ret_floatarr2_s() #0 { + +define void @test.f_floatarr2_tricky1_s_arg(float %0, float %1) #0 { + +define { float, float } @test.f_ret_floatarr2_tricky1_s() #0 { + +define void @test.f_int_float_int_s_arg([2 x i64] %0) #0 { + +define [2 x i64] @test.f_ret_int_float_int_s() #0 { + +define void @test.f_char_char_float_s_arg(i64 %0) #0 { +define i64 @test.f_ret_char_char_float_s() #0 { + +define void @test.f_float_u_arg(i64 %0) #0 { +define i64 @test.f_ret_float_u() #0 { diff --git a/test/test_suite7/abi/riscv64-lp64f-lp64d-abi-2.c3t b/test/test_suite7/abi/riscv64-lp64f-lp64d-abi-2.c3t new file mode 100644 index 000000000..be6f8280e --- /dev/null +++ b/test/test_suite7/abi/riscv64-lp64f-lp64d-abi-2.c3t @@ -0,0 +1,415 @@ +// #target: linux-riscv64 +// #opt: --riscvfloat=double +module test; + +// Verify that the tracking of used GPRs and FPRs works correctly by checking +// that small integers are sign/zero extended when passed in registers. + +// Floats are passed in FPRs, so argument 'i' will be passed zero-extended +// because it will be passed in a GPR. + +fn void f_fpr_tracking(float a, float b, float c, float d, float e, float f, + float g, float h, char i) {} + +// Check that fp, fp+fp, and int+fp structs are lowered correctly. These will +// be passed in FPR, FPR+FPR, or GPR+FPR regs if sufficient registers are +// available the widths are <= XLEN and FLEN, and should be expanded to +// separate arguments in IR. They are passed by the same rules for returns, +// but will be lowered to simple two-element structs if necessary (as LLVM IR +// functions cannot return multiple values). + +// A struct containing just one floating-point real is passed as though it +// were a standalone floating-point real. + +struct Float_s { float f; } + +fn void f_float_s_arg(Float_s a) {} +fn Float_s f_ret_float_s() { + return {1.0}; +} + + +// Check that structs containing two float values (FLEN <= width) are expanded +// provided sufficient FPRs are available. + +struct Float_float_s { float f; float g; } + +fn void f_float_float_s_arg(Float_float_s a) {} + +fn Float_float_s f_ret_float_float_s() { + return {1.0, 2.0}; +} + +fn void f_float_float_s_arg_insufficient_fprs(float a, float b, float c, float d, + float e, float f, float g, Float_float_s h) {} + +// Check that structs containing int+float values are expanded, provided +// sufficient FPRs and GPRs are available. The integer components are neither +// sign or zero-extended. + +struct Float_int8_s { float f; ichar i; } +struct Float_uint8_s { float f; char i; } +struct Float_int32_s { float f; int i; } +struct Float_int64_s { float f; long i; } + +fn void f_float_int8_s_arg(Float_int8_s a) {} +fn Float_int8_s f_ret_float_int8_s() { + return {1.0, 2}; +} + +fn void f_float_uint8_s_arg(Float_uint8_s a) {} +fn Float_uint8_s f_ret_float_uint8_s() { + return {1.0, 2}; +} + +fn void f_float_int32_s_arg(Float_int32_s a) {} +fn Float_int32_s f_ret_float_int32_s() { + return {1.0, 2}; +} + +fn void f_float_int64_s_arg(Float_int64_s a) {} +fn Float_int64_s f_ret_float_int64_s() { + return {1.0, 2}; +} + + +fn void f_float_int8_s_arg_insufficient_gprs(int a, int b, int c, int d, int e, + int f, int g, int h, Float_int8_s i) {} + +fn void f_struct_float_int8_insufficient_fprs(float a, float b, float c, float d, + float e, float f, float g, float h, Float_int8_s i) {} + +// Test single or two-element structs that need flattening. e.g. those +// containing nested structs, floats in small arrays, zero-length structs etc. + +struct Floatarr1_s { float[1] a; } + +fn void f_floatarr1_s_arg(Floatarr1_s a) {} +fn Floatarr1_s f_ret_floatarr1_s() { + return {{1.0}}; +} + +struct Floatarr2_s { float[2] a; } +fn void f_floatarr2_s_arg(Floatarr2_s a) {} + +fn Floatarr2_s f_ret_floatarr2_s() { + return {{1.0, 2.0}}; +} + +struct Inner { float[1] f; } +struct Floatarr2_tricky1_s { Inner[2] g; } + +fn void f_floatarr2_tricky1_s_arg(Floatarr2_tricky1_s a) {} +fn Floatarr2_tricky1_s f_ret_floatarr2_tricky1_s() { + return {{{{1.0}}, {{2.0}}}}; +} + + +// Test structs that should be passed according to the normal integer calling +// convention. + +struct Int_float_int_s { int a; float b; int c; } + +fn void f_int_float_int_s_arg(Int_float_int_s a) {} + +fn Int_float_int_s f_ret_int_float_int_s() { + return {1, 2.0, 3}; +} + +struct Char_char_float_s { char a; char b; float c; } + +fn void f_char_char_float_s_arg(Char_char_float_s a) {} +fn Char_char_float_s f_ret_char_char_float_s() { + return {1, 2, 3.0}; +} + +// Unions are always passed according to the integer calling convention, even +// if they can only contain a float. + +union Float_u { float a; } + +fn void f_float_u_arg(Float_u a) {} +fn Float_u f_ret_float_u() { + return {1.0}; +} + +/* #expect: test.ll + +define void @test.f_fpr_tracking(float %0, float %1, float %2, float %3, float %4, float %5, float %6, float %7, i8 zeroext %8) #0 { + +define void @test.f_float_s_arg(float %0) #0 { +entry: + %a = alloca %Float_s, align 4 + store float %0, ptr %a, align 4 + ret void +} + + +define float @test.f_ret_float_s() #0 { +entry: + %literal = alloca %Float_s, align 4 + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %literal, ptr align 4 @.__const, i32 4, i1 false) + %0 = load float, ptr %literal, align 4 + ret float %0 +} + + +define void @test.f_float_float_s_arg(float %0, float %1) #0 { +entry: + %a = alloca %Float_float_s, align 4 + store float %0, ptr %a, align 4 + %ptradd = getelementptr inbounds i8, ptr %a, i64 4 + store float %1, ptr %a, align 4 + ret void +} + + +define { float, float } @test.f_ret_float_float_s() #0 { +entry: + %literal = alloca %Float_float_s, align 4 + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %literal, ptr align 4 @.__const.1, i32 8, i1 false) + %0 = load float, ptr %literal, align 4 + %ptradd = getelementptr inbounds i8, ptr %literal, i64 4 + %1 = load float, ptr %literal, align 4 + %2 = insertvalue { float, float } undef, float %0, 0 + %3 = insertvalue { float, float } %2, float %1, 1 + ret { float, float } %3 +} + + +define void @test.f_float_float_s_arg_insufficient_fprs(float %0, float %1, float %2, float %3, float %4, float %5, float %6, i64 %7) #0 { +entry: + %h = alloca %Float_float_s, align 4 + store i64 %7, ptr %h, align 4 + ret void +} + + +define void @test.f_float_int8_s_arg(float %0, i8 %1) #0 { +entry: + %a = alloca %Float_int8_s, align 4 + store float %0, ptr %a, align 4 + %ptradd = getelementptr inbounds i8, ptr %a, i64 4 + store i8 %1, ptr %a, align 4 + ret void +} + + +define { float, i8 } @test.f_ret_float_int8_s() #0 { +entry: + %literal = alloca %Float_int8_s, align 4 + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %literal, ptr align 4 @.__const.2, i32 8, i1 false) + %0 = load float, ptr %literal, align 4 + %ptradd = getelementptr inbounds i8, ptr %literal, i64 4 + %1 = load i8, ptr %literal, align 4 + %2 = insertvalue { float, i8 } undef, float %0, 0 + %3 = insertvalue { float, i8 } %2, i8 %1, 1 + ret { float, i8 } %3 +} + + +define void @test.f_float_uint8_s_arg(float %0, i8 %1) #0 { +entry: + %a = alloca %Float_uint8_s, align 4 + store float %0, ptr %a, align 4 + %ptradd = getelementptr inbounds i8, ptr %a, i64 4 + store i8 %1, ptr %a, align 4 + ret void +} + + +define { float, i8 } @test.f_ret_float_uint8_s() #0 { +entry: + %literal = alloca %Float_uint8_s, align 4 + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %literal, ptr align 4 @.__const.3, i32 8, i1 false) + %0 = load float, ptr %literal, align 4 + %ptradd = getelementptr inbounds i8, ptr %literal, i64 4 + %1 = load i8, ptr %literal, align 4 + %2 = insertvalue { float, i8 } undef, float %0, 0 + %3 = insertvalue { float, i8 } %2, i8 %1, 1 + ret { float, i8 } %3 +} + + +define void @test.f_float_int32_s_arg(float %0, i32 %1) #0 { +entry: + %a = alloca %Float_int32_s, align 4 + store float %0, ptr %a, align 4 + %ptradd = getelementptr inbounds i8, ptr %a, i64 4 + store i32 %1, ptr %a, align 4 + ret void +} + + +define { float, i32 } @test.f_ret_float_int32_s() #0 { +entry: + %literal = alloca %Float_int32_s, align 4 + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %literal, ptr align 4 @.__const.4, i32 8, i1 false) + %0 = load float, ptr %literal, align 4 + %ptradd = getelementptr inbounds i8, ptr %literal, i64 4 + %1 = load i32, ptr %literal, align 4 + %2 = insertvalue { float, i32 } undef, float %0, 0 + %3 = insertvalue { float, i32 } %2, i32 %1, 1 + ret { float, i32 } %3 +} + + +define void @test.f_float_int64_s_arg(float %0, i64 %1) #0 { +entry: + %a = alloca %Float_int64_s, align 8 + store float %0, ptr %a, align 8 + %ptradd = getelementptr inbounds i8, ptr %a, i64 8 + store i64 %1, ptr %a, align 8 + ret void +} + + +define { float, i64 } @test.f_ret_float_int64_s() #0 { +entry: + %literal = alloca %Float_int64_s, align 8 + call void @llvm.memcpy.p0.p0.i32(ptr align 8 %literal, ptr align 8 @.__const.5, i32 16, i1 false) + %0 = load float, ptr %literal, align 8 + %ptradd = getelementptr inbounds i8, ptr %literal, i64 8 + %1 = load i64, ptr %literal, align 8 + %2 = insertvalue { float, i64 } undef, float %0, 0 + %3 = insertvalue { float, i64 } %2, i64 %1, 1 + ret { float, i64 } %3 +} + + +define void @test.f_float_int8_s_arg_insufficient_gprs(i32 signext %0, i32 signext %1, i32 signext %2, i32 signext %3, i32 signext %4, i32 signext %5, i32 signext %6, i32 signext %7, i64 %8) #0 { +entry: + %i = alloca %Float_int8_s, align 4 + store i64 %8, ptr %i, align 4 + ret void +} + + +define void @test.f_struct_float_int8_insufficient_fprs(float %0, float %1, float %2, float %3, float %4, float %5, float %6, float %7, i64 %8) #0 { +entry: + %i = alloca %Float_int8_s, align 4 + store i64 %8, ptr %i, align 4 + ret void +} + + +define void @test.f_floatarr1_s_arg(float %0) #0 { +entry: + %a = alloca %Floatarr1_s, align 4 + store float %0, ptr %a, align 4 + ret void +} + + +define float @test.f_ret_floatarr1_s() #0 { +entry: + %literal = alloca %Floatarr1_s, align 4 + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %literal, ptr align 4 @.__const.6, i32 4, i1 false) + %0 = load float, ptr %literal, align 4 + ret float %0 +} + + +define void @test.f_floatarr2_s_arg(float %0, float %1) #0 { +entry: + %a = alloca %Floatarr2_s, align 4 + store float %0, ptr %a, align 4 + %ptradd = getelementptr inbounds i8, ptr %a, i64 4 + store float %1, ptr %a, align 4 + ret void +} + + +define { float, float } @test.f_ret_floatarr2_s() #0 { +entry: + %literal = alloca %Floatarr2_s, align 4 + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %literal, ptr align 4 @.__const.7, i32 8, i1 false) + %0 = load float, ptr %literal, align 4 + %ptradd = getelementptr inbounds i8, ptr %literal, i64 4 + %1 = load float, ptr %literal, align 4 + %2 = insertvalue { float, float } undef, float %0, 0 + %3 = insertvalue { float, float } %2, float %1, 1 + ret { float, float } %3 +} + + +define void @test.f_floatarr2_tricky1_s_arg(float %0, float %1) #0 { +entry: + %a = alloca %Floatarr2_tricky1_s, align 4 + store float %0, ptr %a, align 4 + %ptradd = getelementptr inbounds i8, ptr %a, i64 4 + store float %1, ptr %a, align 4 + ret void +} + + +define { float, float } @test.f_ret_floatarr2_tricky1_s() #0 { +entry: + %literal = alloca %Floatarr2_tricky1_s, align 4 + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %literal, ptr align 4 @.__const.8, i32 8, i1 false) + %0 = load float, ptr %literal, align 4 + %ptradd = getelementptr inbounds i8, ptr %literal, i64 4 + %1 = load float, ptr %literal, align 4 + %2 = insertvalue { float, float } undef, float %0, 0 + %3 = insertvalue { float, float } %2, float %1, 1 + ret { float, float } %3 +} + + +define void @test.f_int_float_int_s_arg([2 x i64] %0) #0 { +entry: + %a = alloca %Int_float_int_s, align 4 + %tempcoerce = alloca [2 x i64], align 8 + store [2 x i64] %0, ptr %tempcoerce, align 8 + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %a, ptr align 8 %tempcoerce, i32 12, i1 false) + ret void +} + + +define [2 x i64] @test.f_ret_int_float_int_s() #0 { +entry: + %literal = alloca %Int_float_int_s, align 4 + %tempcoerce = alloca [2 x i64], align 8 + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %literal, ptr align 4 @.__const.9, i32 12, i1 false) + call void @llvm.memcpy.p0.p0.i32(ptr align 8 %tempcoerce, ptr align 4 %literal, i32 12, i1 false) + %0 = load [2 x i64], ptr %tempcoerce, align 8 + ret [2 x i64] %0 +} + + +define void @test.f_char_char_float_s_arg(i64 %0) #0 { +entry: + %a = alloca %Char_char_float_s, align 4 + store i64 %0, ptr %a, align 4 + ret void +} + + +define i64 @test.f_ret_char_char_float_s() #0 { +entry: + %literal = alloca %Char_char_float_s, align 4 + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %literal, ptr align 4 @.__const.10, i32 8, i1 false) + %0 = load i64, ptr %literal, align 4 + ret i64 %0 +} + + +define void @test.f_float_u_arg(i64 %0) #0 { +entry: + %a = alloca %Float_u, align 4 + %tempcoerce = alloca i64, align 8 + store i64 %0, ptr %tempcoerce, align 8 + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %a, ptr align 8 %tempcoerce, i32 4, i1 false) + ret void +} + + +define i64 @test.f_ret_float_u() #0 { +entry: + %literal = alloca %Float_u, align 4 + %tempcoerce = alloca i64, align 8 + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %literal, ptr align 4 @.__const.11, i32 4, i1 false) + call void @llvm.memcpy.p0.p0.i32(ptr align 8 %tempcoerce, ptr align 4 %literal, i32 4, i1 false) + %0 = load i64, ptr %tempcoerce, align 8 + ret i64 %0 +} diff --git a/test/test_suite7/abi/small_struct_x64.c3t b/test/test_suite7/abi/small_struct_x64.c3t new file mode 100644 index 000000000..8bf57d9fe --- /dev/null +++ b/test/test_suite7/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 + +%.introspect = type { i8, i64, ptr, i64, i64, i64, [0 x i64] } +%Foo = type { i8, i8, i8 } + +@"$ct.test.Foo" = linkonce global %.introspect { i8 10, i64 0, ptr null, i64 3, i64 0, i64 3, [0 x i64] zeroinitializer }, align 8 + +; Function Attrs: +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 + %tempcoerce1 = alloca i24, align 4 + call void @llvm.memcpy.p0.p0.i32(ptr align 1 %literal, ptr align 1 @.__const, i32 3, i1 false) + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %tempcoerce, ptr align 1 %literal, i32 3, i1 false) + %0 = load i24, ptr %tempcoerce, align 4 + %1 = call i24 @test.getFoo(i24 %0) + store i24 %1, ptr %tempcoerce1, align 4 + call void @llvm.memcpy.p0.p0.i32(ptr align 1 %result, ptr align 4 %tempcoerce1, i32 3, i1 false) + call void @llvm.memcpy.p0.p0.i32(ptr align 1 %y, ptr align 1 %result, i32 3, i1 false) + %2 = load i8, ptr %y, align 1 + %zext = zext i8 %2 to i32 + %ptradd = getelementptr inbounds i8, ptr %y, i64 2 + %3 = load i8, ptr %ptradd, align 1 + %zext2 = zext i8 %3 to i32 + %add = add i32 %zext, %zext2 + ret i32 %add +} + +; Function Attrs: +define i24 @test.getFoo(i24 %0) #0 { +entry: + %f = alloca %Foo, align 1 + %tempcoerce = alloca i24, align 4 + %literal = alloca %Foo, align 1 + %tempcoerce1 = alloca i24, align 4 + store i24 %0, ptr %tempcoerce, align 4 + call void @llvm.memcpy.p0.p0.i32(ptr align 1 %f, ptr align 4 %tempcoerce, i32 3, i1 false) + call void @llvm.memcpy.p0.p0.i32(ptr align 1 %literal, ptr align 1 @.__const.1, i32 3, i1 false) + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %tempcoerce1, ptr align 1 %literal, i32 3, i1 false) + %1 = load i24, ptr %tempcoerce1, align 4 + ret i24 %1 +} + diff --git a/test/test_suite7/abi/sysv_abi_avx.c3t b/test/test_suite7/abi/sysv_abi_avx.c3t new file mode 100644 index 000000000..95f579afb --- /dev/null +++ b/test/test_suite7/abi/sysv_abi_avx.c3t @@ -0,0 +1,42 @@ +// #target: linux-x64 +// #opt: --x86cpu=avx512 +module foo; + +struct StringRef +{ + char* str; + usz size; +} + +char gc; +extern fn void take_stringref(StringRef s); +fn void callit() +{ + StringRef s = { "asdf" , 4}; + take_stringref(s); +} + +extern fn float[<8>] get_m256(); +extern fn void take_m256(float[<8>] x); +extern fn float[<16>] get_m512(); +extern fn void take_m512(float[<16>] x); + +fn void use_vectors() +{ + float[<8>] v1 = get_m256(); + take_m256(v1); + float[<16>] v2 = get_m512(); + take_m512(v2); +} + +/* #expect: foo.ll + +declare void @take_stringref(ptr, i64) #0 +call void @take_stringref(ptr %lo, i64 %hi) + +define void @foo.use_vectors() #0 { +entry: + %0 = call <8 x float> @get_m256() + call void @take_m256(<8 x float> %1) + %2 = call <16 x float> @get_m512() + call void @take_m512(<16 x float> %3) diff --git a/test/test_suite7/abi/sysv_abi_noavx.c3t b/test/test_suite7/abi/sysv_abi_noavx.c3t new file mode 100644 index 000000000..a32ded346 --- /dev/null +++ b/test/test_suite7/abi/sysv_abi_noavx.c3t @@ -0,0 +1,41 @@ +// #target: linux-x64 +// #opt: --x86vec=none +module foo; + +struct StringRef +{ + char* str; + usz size; +} + +char gc; +extern fn void take_stringref(StringRef s); +fn void callit() +{ + StringRef s = { "asdf" , 4}; + take_stringref(s); +} + +extern fn float[<8>] get_m256(); +extern fn void take_m256(float[<8>] x); +extern fn float[<16>] get_m512(); +extern fn void take_m512(float[<16>] x); + +fn void use_vectors() +{ + float[<8>] v1 = get_m256(); + take_m256(v1); + float[<16>] v2 = get_m512(); + take_m512(v2); +} + +/* #expect: foo.ll + +declare void @take_stringref(ptr, i64) #0 + call void @take_stringref(ptr %lo, i64 %hi) + +define void @foo.use_vectors() #0 { + %0 = call <8 x float> @get_m256() + call void @take_m256(ptr byval(<8 x float>) align 32 %v1) + %1 = call <16 x float> @get_m512() + call void @take_m512(ptr byval(<16 x float>) align 64 %v2) \ No newline at end of file diff --git a/test/test_suite7/abi/sysv_direct_coerce.c3t b/test/test_suite7/abi/sysv_direct_coerce.c3t new file mode 100644 index 000000000..f33ade62b --- /dev/null +++ b/test/test_suite7/abi/sysv_direct_coerce.c3t @@ -0,0 +1,34 @@ +// #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 8 + %literal = alloca %Rectangle, align 4 + %coerce = alloca %Rectangle, align 8 + store <2 x float> %0, ptr %r, align 8 + %ptradd = getelementptr inbounds i8, ptr %r, i64 8 + store <2 x float> %1, ptr %ptradd, align 8 + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %literal, ptr align 4 @.__const, i32 16, i1 false) + call void @llvm.memcpy.p0.p0.i32(ptr align 8 %coerce, ptr align 4 %literal, i32 16, i1 false) + %lo = load <2 x float>, ptr %coerce, align 8 + %ptradd1 = getelementptr inbounds i8, ptr %coerce, i64 8 + %hi = load <2 x float>, ptr %ptradd1, 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_suite7/abi/test_sret.c3t b/test/test_suite7/abi/test_sret.c3t new file mode 100644 index 000000000..3ec4addaf --- /dev/null +++ b/test/test_suite7/abi/test_sret.c3t @@ -0,0 +1,32 @@ +// #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(); +} + +/* #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 + %dummy2 = alloca %Abc, align 8 + call void @foo1(ptr sret(%Abc) align 8 %dummy1) + call void @foo2(ptr sret(%Abc) align 8 %dummy2) + ret void +} diff --git a/test/test_suite7/abi/union_x64.c3t b/test/test_suite7/abi/union_x64.c3t new file mode 100644 index 000000000..b598969f4 --- /dev/null +++ b/test/test_suite7/abi/union_x64.c3t @@ -0,0 +1,35 @@ +// #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 + +; Function Attrs: +define void @unionx64.hello(i64 %0, i64 %1) #0 { +entry: + %f = alloca %Foo, align 8 + store i64 %0, ptr %f, align 8 + %ptradd = getelementptr inbounds i8, ptr %f, i64 8 + store i64 %1, ptr %ptradd, align 8 + %lo = load i64, ptr %f, align 8 + %ptradd1 = getelementptr inbounds i8, ptr %f, i64 8 + %hi = load i64, ptr %ptradd1, align 8 + call void @hello2(i64 %lo, i64 %hi) + ret void +} diff --git a/test/test_suite7/abi/vec2_aarch64.c3t b/test/test_suite7/abi/vec2_aarch64.c3t new file mode 100644 index 000000000..20e8e5295 --- /dev/null +++ b/test/test_suite7/abi/vec2_aarch64.c3t @@ -0,0 +1,95 @@ +// #target: linux-aarch64 +module abi; + +struct Vector2 { + float x; + float y; +} +fn Vector2 vector2_zero() @extern("vector2_zero") { return {}; } +fn Vector2 vector2_one() @extern("vector2_one") { return {}; } +fn Vector2 vector2_add(Vector2 v1, Vector2 v2) @extern("vector2_add") { return {}; } +fn Vector2 vector2_add_value(Vector2 v, float add) @extern("vector2_add_value") { return {}; } +fn Vector2 vector2_subtract(Vector2 v1, Vector2 v2) @extern("vector2_subtract") { return {}; } +fn Vector2 vector2_subtract_value(Vector2 v, float sub) @extern("vector2_subtract_value") { return {}; } + + +/* #expect: abi.ll + +%Vector2 = type { float, float } + +define %Vector2 @vector2_zero() #0 { +entry: + %literal = alloca %Vector2, align 4 + store float 0.000000e+00, ptr %literal, align 4 + %ptradd = getelementptr inbounds i8, ptr %literal, i64 4 + store float 0.000000e+00, ptr %ptradd, align 4 + %0 = load %Vector2, ptr %literal, align 4 + ret %Vector2 %0 +} + +; Function Attrs: +define %Vector2 @vector2_one() #0 { +entry: + %literal = alloca %Vector2, align 4 + store float 0.000000e+00, ptr %literal, align 4 + %ptradd = getelementptr inbounds i8, ptr %literal, i64 4 + store float 0.000000e+00, ptr %ptradd, align 4 + %0 = load %Vector2, ptr %literal, align 4 + ret %Vector2 %0 +} + +; Function Attrs: +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 + store float 0.000000e+00, ptr %literal, align 4 + %ptradd = getelementptr inbounds i8, ptr %literal, i64 4 + store float 0.000000e+00, ptr %ptradd, align 4 + %2 = load %Vector2, ptr %literal, align 4 + ret %Vector2 %2 +} + +; Function Attrs: +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 + store float 0.000000e+00, ptr %literal, align 4 + %ptradd = getelementptr inbounds i8, ptr %literal, i64 4 + store float 0.000000e+00, ptr %ptradd, align 4 + %2 = load %Vector2, ptr %literal, align 4 + ret %Vector2 %2 +} + +; Function Attrs: +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 + store float 0.000000e+00, ptr %literal, align 4 + %ptradd = getelementptr inbounds i8, ptr %literal, i64 4 + store float 0.000000e+00, ptr %ptradd, align 4 + %2 = load %Vector2, ptr %literal, align 4 + ret %Vector2 %2 +} + +; Function Attrs: +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 + store float 0.000000e+00, ptr %literal, align 4 + %ptradd = getelementptr inbounds i8, ptr %literal, i64 4 + store float 0.000000e+00, ptr %ptradd, align 4 + %2 = load %Vector2, ptr %literal, align 4 + ret %Vector2 %2 +} diff --git a/test/test_suite7/abi/vec2_wasm.c3t b/test/test_suite7/abi/vec2_wasm.c3t new file mode 100644 index 000000000..0a07e9ce4 --- /dev/null +++ b/test/test_suite7/abi/vec2_wasm.c3t @@ -0,0 +1,85 @@ +// #target: wasm32 +module abi; + +struct Vector2 { + float x; + float y; +} +fn Vector2 vector2_zero() @extern("vector2_zero") { return {}; } +fn Vector2 vector2_one() @extern("vector2_one") { return {}; } +fn Vector2 vector2_add(Vector2 v1, Vector2 v2) @extern("vector2_add") { return {}; } +fn Vector2 vector2_add_value(Vector2 v, float add) @extern("vector2_add_value") { return {}; } +fn Vector2 vector2_subtract(Vector2 v1, Vector2 v2) @extern("vector2_subtract") { return {}; } +fn Vector2 vector2_subtract_value(Vector2 v, float sub) @extern("vector2_subtract_value") { return {}; } + +/* #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 + store float 0.000000e+00, ptr %literal, align 4 + %ptradd = getelementptr inbounds i8, ptr %literal, i32 4 + store float 0.000000e+00, ptr %ptradd, align 4 + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %0, ptr align 4 %literal, i32 8, i1 false) + ret void +} + +; Function Attrs: +define void @vector2_one(ptr noalias sret(%Vector2) align 4 %0) #0 { +entry: + %literal = alloca %Vector2, align 4 + store float 0.000000e+00, ptr %literal, align 4 + %ptradd = getelementptr inbounds i8, ptr %literal, i32 4 + store float 0.000000e+00, ptr %ptradd, align 4 + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %0, ptr align 4 %literal, i32 8, i1 false) + ret void +} + +; Function Attrs: +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: + %literal = alloca %Vector2, align 4 + store float 0.000000e+00, ptr %literal, align 4 + %ptradd = getelementptr inbounds i8, ptr %literal, i32 4 + store float 0.000000e+00, ptr %ptradd, align 4 + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %0, ptr align 4 %literal, i32 8, i1 false) + ret void +} + +; Function Attrs: +define void @vector2_add_value(ptr noalias sret(%Vector2) align 4 %0, ptr byval(%Vector2) align 4 %1, float %2) #0 { +entry: + %literal = alloca %Vector2, align 4 + store float 0.000000e+00, ptr %literal, align 4 + %ptradd = getelementptr inbounds i8, ptr %literal, i32 4 + store float 0.000000e+00, ptr %ptradd, align 4 + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %0, ptr align 4 %literal, i32 8, i1 false) + ret void +} + +; Function Attrs: +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: + %literal = alloca %Vector2, align 4 + store float 0.000000e+00, ptr %literal, align 4 + %ptradd = getelementptr inbounds i8, ptr %literal, i32 4 + store float 0.000000e+00, ptr %ptradd, align 4 + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %0, ptr align 4 %literal, i32 8, i1 false) + ret void +} + +; Function Attrs: +define void @vector2_subtract_value(ptr noalias sret(%Vector2) align 4 %0, ptr byval(%Vector2) align 4 %1, float %2) #0 { +entry: + %literal = alloca %Vector2, align 4 + store float 0.000000e+00, ptr %literal, align 4 + %ptradd = getelementptr inbounds i8, ptr %literal, i32 4 + store float 0.000000e+00, ptr %ptradd, 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_suite7/abi/vec2_x64.c3t b/test/test_suite7/abi/vec2_x64.c3t new file mode 100644 index 000000000..2ac743251 --- /dev/null +++ b/test/test_suite7/abi/vec2_x64.c3t @@ -0,0 +1,94 @@ +// #target: macos-x64 +module abi; + +struct Vector2 { + float x; + float y; +} +fn Vector2 vector2_zero() @extern("vector2_zero") { return {}; } +fn Vector2 vector2_one() @extern("vector2_one") { return {}; } +fn Vector2 vector2_add(Vector2 v1, Vector2 v2) @extern("vector2_add") { return {}; } +fn Vector2 vector2_add_value(Vector2 v, float add) @extern("vector2_add_value") { return {}; } +fn Vector2 vector2_subtract(Vector2 v1, Vector2 v2) @extern("vector2_subtract") { return {}; } +fn Vector2 vector2_subtract_value(Vector2 v, float sub) @extern("vector2_subtract_value") { return {}; } + +/* #expect: abi.ll + +%Vector2 = type { float, float } + +define <2 x float> @vector2_zero() #0 { +entry: + %literal = alloca %Vector2, align 4 + store float 0.000000e+00, ptr %literal, align 4 + %ptradd = getelementptr inbounds i8, ptr %literal, i64 4 + store float 0.000000e+00, ptr %ptradd, align 4 + %0 = load <2 x float>, ptr %literal, align 4 + ret <2 x float> %0 +} + +; Function Attrs: +define <2 x float> @vector2_one() #0 { +entry: + %literal = alloca %Vector2, align 4 + store float 0.000000e+00, ptr %literal, align 4 + %ptradd = getelementptr inbounds i8, ptr %literal, i64 4 + store float 0.000000e+00, ptr %ptradd, align 4 + %0 = load <2 x float>, ptr %literal, align 4 + ret <2 x float> %0 +} + +; Function Attrs: +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 + store <2 x float> %0, ptr %v1, align 4 + store <2 x float> %1, ptr %v2, align 4 + store float 0.000000e+00, ptr %literal, align 4 + %ptradd = getelementptr inbounds i8, ptr %literal, i64 4 + store float 0.000000e+00, ptr %ptradd, align 4 + %2 = load <2 x float>, ptr %literal, align 4 + ret <2 x float> %2 +} + +; Function Attrs: +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 + store <2 x float> %0, ptr %v, align 4 + store float 0.000000e+00, ptr %literal, align 4 + %ptradd = getelementptr inbounds i8, ptr %literal, i64 4 + store float 0.000000e+00, ptr %ptradd, align 4 + %2 = load <2 x float>, ptr %literal, align 4 + ret <2 x float> %2 +} + +; Function Attrs: +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 + store <2 x float> %0, ptr %v1, align 4 + store <2 x float> %1, ptr %v2, align 4 + store float 0.000000e+00, ptr %literal, align 4 + %ptradd = getelementptr inbounds i8, ptr %literal, i64 4 + store float 0.000000e+00, ptr %ptradd, align 4 + %2 = load <2 x float>, ptr %literal, align 4 + ret <2 x float> %2 +} + +; Function Attrs: +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 + store <2 x float> %0, ptr %v, align 4 + store float 0.000000e+00, ptr %literal, align 4 + %ptradd = getelementptr inbounds i8, ptr %literal, i64 4 + store float 0.000000e+00, ptr %ptradd, align 4 + %2 = load <2 x float>, ptr %literal, align 4 + ret <2 x float> %2 +} diff --git a/test/test_suite7/abi/wasm_extern.c3t b/test/test_suite7/abi/wasm_extern.c3t new file mode 100644 index 000000000..9d269cdca --- /dev/null +++ b/test/test_suite7/abi/wasm_extern.c3t @@ -0,0 +1,17 @@ +// #target: wasm32 +module test; +extern fn int get_abc(); +fn int hello() @export("fgh") +{ + return 1; +} + +/* #expect: test.ll + +target triple = "wasm32-unknown-unknown" + +declare i32 @get_abc() #0 +define i32 @fgh() #1 + +attributes #0 = { nounwind uwtable "no-trapping-math"="true" "stack-protector-buffer-size"="8" "wasm-import-name"="get_abc" } +attributes #1 = { nounwind uwtable "no-trapping-math"="true" "stack-protector-buffer-size"="8" "wasm-export-name"="fgh" } diff --git a/test/test_suite7/abi/x64alignarray.c3t b/test/test_suite7/abi/x64alignarray.c3t new file mode 100644 index 000000000..31f5d990b --- /dev/null +++ b/test/test_suite7/abi/x64alignarray.c3t @@ -0,0 +1,26 @@ +// #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 + store float 0.000000e+00, ptr %x, align 4 + %ptradd = getelementptr inbounds i8, ptr %x, i64 4 + store float 0.000000e+00, ptr %ptradd, align 4 + %ptradd1 = getelementptr inbounds i8, ptr %x, i64 8 + store float 0.000000e+00, ptr %ptradd1, align 4 + %ptradd2 = getelementptr inbounds i8, ptr %x, i64 12 + store float 0.000000e+00, ptr %ptradd2, align 4 + call void @test1_f(ptr %x) + ret void +} diff --git a/test/test_suite7/any/any_in_any.c3t b/test/test_suite7/any/any_in_any.c3t new file mode 100644 index 000000000..56e828ea1 --- /dev/null +++ b/test/test_suite7/any/any_in_any.c3t @@ -0,0 +1,37 @@ +// #target: macos-x64 +module foo; +fn void main() +{ + any x; + x = &x; + x = &&(&x); + x = &&(&&(&x)); +} +/* #expect: foo.ll + +%any = type { ptr, i64 } +@"$ct.any$" = linkonce global %.introspect { i8 7, i64 0, ptr null, i64 16, i64 0, i64 0, [0 x i64] zeroinitializer }, align 8 +@"$ct.p$any$" = linkonce global %.introspect { i8 19, i64 0, ptr null, i64 8, i64 ptrtoint (ptr @"$ct.any$" to i64), i64 0, [0 x i64] zeroinitializer }, align 8 +@"$ct.p$p$any$" = linkonce global %.introspect { i8 19, i64 0, ptr null, i64 8, i64 ptrtoint (ptr @"$ct.p$any$" to i64), i64 0, [0 x i64] zeroinitializer }, align 8 + +define void @foo.main() #0 { +entry: + %x = alloca %any, align 8 + %taddr = alloca ptr, align 8 + %taddr1 = alloca ptr, align 8 + %taddr2 = alloca ptr, align 8 + store %any zeroinitializer, ptr %x, align 8 + %0 = insertvalue %any undef, ptr %x, 0 + %1 = insertvalue %any %0, i64 ptrtoint (ptr @"$ct.any$" to i64), 1 + store %any %1, ptr %x, align 8 + store ptr %x, ptr %taddr, align 8 + %2 = insertvalue %any undef, ptr %taddr, 0 + %3 = insertvalue %any %2, i64 ptrtoint (ptr @"$ct.p$any$" to i64), 1 + store %any %3, ptr %x, align 8 + store ptr %x, ptr %taddr1, align 8 + store ptr %taddr1, ptr %taddr2, align 8 + %4 = insertvalue %any undef, ptr %taddr2, 0 + %5 = insertvalue %any %4, i64 ptrtoint (ptr @"$ct.p$p$any$" to i64), 1 + store %any %5, ptr %x, align 8 + ret void +} diff --git a/test/test_suite7/any/casting_voidptr_to_any.c3 b/test/test_suite7/any/casting_voidptr_to_any.c3 new file mode 100644 index 000000000..e4999e63a --- /dev/null +++ b/test/test_suite7/any/casting_voidptr_to_any.c3 @@ -0,0 +1,26 @@ +module mylib::ifaces; +interface IOp { + fn void op(); +} +module mylib(); +import std::io; +import mylib::ifaces; +struct Op (IOp){ + Type data; +} +fn void Op.op(&self) @dynamic => io::printn("op"); +module myapp; +import mylib; +fn void test(void* tptr){ + // this work + IOp iop = (Op()*)tptr; + iop.op(); + + // this don't work + iop = tptr; // #error: Casting a 'void*' to 'IOp' is not permitted + iop.op(); +} +fn void main(String[] args) { + Op()* t = mem::new(Op(), {.data = 1}); + test(&t); +} diff --git a/test/test_suite7/any/generic_interface.c3 b/test/test_suite7/any/generic_interface.c3 new file mode 100644 index 000000000..6bd257af5 --- /dev/null +++ b/test/test_suite7/any/generic_interface.c3 @@ -0,0 +1,12 @@ +module foo(); + +interface Baz +{} + +module test; +import foo; + +fn void main() +{ + Baz() x; +} diff --git a/test/test_suite7/any/interface_no_fn.c3 b/test/test_suite7/any/interface_no_fn.c3 new file mode 100644 index 000000000..62f323bc1 --- /dev/null +++ b/test/test_suite7/any/interface_no_fn.c3 @@ -0,0 +1,4 @@ +interface IOp { + int val; // #error: Interfaces can only have function + int my_fn(); // missing fn +} \ No newline at end of file diff --git a/test/test_suite7/any/interface_no_method_body_1536.c3 b/test/test_suite7/any/interface_no_method_body_1536.c3 new file mode 100644 index 000000000..8774ec6d1 --- /dev/null +++ b/test/test_suite7/any/interface_no_method_body_1536.c3 @@ -0,0 +1,7 @@ +interface Foo +{ + fn int bar() + { // #error: An interface method + return 0; + } +} \ No newline at end of file diff --git a/test/test_suite7/any/interface_ptr.c3 b/test/test_suite7/any/interface_ptr.c3 new file mode 100644 index 000000000..ae66baa06 --- /dev/null +++ b/test/test_suite7/any/interface_ptr.c3 @@ -0,0 +1,8 @@ +interface Abc {} + +fn void main() +{ + Abc y; + typeid z = y.type; + void* x = y.ptr; +} diff --git a/test/test_suite7/any/variant_assign.c3t b/test/test_suite7/any/variant_assign.c3t new file mode 100644 index 000000000..6e1aab1fa --- /dev/null +++ b/test/test_suite7/any/variant_assign.c3t @@ -0,0 +1,406 @@ +// #target: macos-x64 +module foo; + +extern fn void printf(char*, ...); + +fn void test(any 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(any 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(any 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 + +@"$ct.int" = linkonce global %.introspect { i8 2, i64 0, ptr null, i64 4, i64 0, i64 0, [0 x i64] zeroinitializer }, align 8 +@"$ct.double" = linkonce global %.introspect { i8 4, i64 0, ptr null, i64 8, i64 0, i64 0, [0 x i64] zeroinitializer }, align 8 +@"$ct.bool" = linkonce global %.introspect { i8 1, i64 0, ptr null, i64 1, i64 0, i64 0, [0 x i64] zeroinitializer }, align 8 + +define void @foo.test(i64 %0, ptr %1) #0 { +entry: + %z = alloca %any, align 8 + %switch = alloca i64, align 8 + %z3 = alloca ptr, align 8 + %z11 = alloca ptr, align 8 + store i64 %0, ptr %z, align 8 + %ptradd = getelementptr inbounds i8, ptr %z, i64 8 + store ptr %1, ptr %ptradd, align 8 + %ptradd1 = getelementptr inbounds i8, ptr %z, i64 8 + %2 = load i64, ptr %ptradd1, align 8 + store i64 %2, ptr %switch, align 8 + br label %switch.entry + +switch.entry: ; preds = %entry + %3 = load i64, ptr %switch, align 8 + br label %check_subtype + +check_subtype: ; preds = %parent_type_block, %switch.entry + %4 = phi i64 [ %3, %switch.entry ], [ %typeid.parent, %parent_type_block ] + %eq = icmp eq i64 ptrtoint (ptr @"$ct.int" to i64), %4 + br i1 %eq, label %result_block, label %parent_type_block + +parent_type_block: ; preds = %check_subtype + %5 = inttoptr i64 %4 to ptr + %ptradd2 = getelementptr inbounds i8, ptr %5, i64 8 + %typeid.parent = load i64, ptr %ptradd2, align 8 + %6 = icmp eq i64 %typeid.parent, 0 + br i1 %6, label %result_block, label %check_subtype + +result_block: ; preds = %parent_type_block, %check_subtype + %7 = phi i1 [ false, %parent_type_block ], [ true, %check_subtype ] + br i1 %7, label %switch.case, label %next_if + +switch.case: ; preds = %result_block + %8 = load ptr, ptr %z, align 8 + store ptr %8, ptr %z3, align 8 + %9 = load ptr, ptr %z3, align 8 + %10 = load i32, ptr %9, align 4 + call void (ptr, ...) @printf(ptr @.str, i32 %10) + br label %switch.exit + +next_if: ; preds = %result_block + br label %check_subtype4 + +check_subtype4: ; preds = %parent_type_block6, %next_if + %11 = phi i64 [ %3, %next_if ], [ %typeid.parent8, %parent_type_block6 ] + %eq5 = icmp eq i64 ptrtoint (ptr @"$ct.double" to i64), %11 + br i1 %eq5, label %result_block9, label %parent_type_block6 + +parent_type_block6: ; preds = %check_subtype4 + %12 = inttoptr i64 %11 to ptr + %ptradd7 = getelementptr inbounds i8, ptr %12, i64 8 + %typeid.parent8 = load i64, ptr %ptradd7, align 8 + %13 = icmp eq i64 %typeid.parent8, 0 + br i1 %13, label %result_block9, label %check_subtype4 + +result_block9: ; preds = %parent_type_block6, %check_subtype4 + %14 = phi i1 [ false, %parent_type_block6 ], [ true, %check_subtype4 ] + br i1 %14, label %switch.case10, label %next_if12 + +switch.case10: ; preds = %result_block9 + %15 = load ptr, ptr %z, align 8 + store ptr %15, ptr %z11, align 8 + %16 = load ptr, ptr %z11, align 8 + %17 = load double, ptr %16, align 8 + call void (ptr, ...) @printf(ptr @.str.1, double %17) + br label %switch.exit + +next_if12: ; preds = %result_block9 + br label %switch.default + +switch.default: ; preds = %next_if12 + call void (ptr, ...) @printf(ptr @.str.2) + br label %switch.exit + +switch.exit: ; preds = %switch.default, %switch.case10, %switch.case + ret void +} + +; Function Attrs: +define void @foo.test2(i64 %0, ptr %1) #0 { +entry: + %y = alloca %any, align 8 + %switch = alloca i64, align 8 + %z = alloca ptr, align 8 + %taddr = alloca i32, align 4 + %z9 = alloca ptr, align 8 + store i64 %0, ptr %y, align 8 + %ptradd = getelementptr inbounds i8, ptr %y, i64 8 + store ptr %1, ptr %ptradd, align 8 + %2 = load %any, ptr %y, align 8 + %3 = extractvalue %any %2, 1 + store i64 %3, ptr %switch, align 8 + br label %switch.entry + +switch.entry: ; preds = %entry + %4 = load i64, ptr %switch, align 8 + br label %check_subtype + +check_subtype: ; preds = %parent_type_block, %switch.entry + %5 = phi i64 [ %4, %switch.entry ], [ %typeid.parent, %parent_type_block ] + %eq = icmp eq i64 ptrtoint (ptr @"$ct.int" to i64), %5 + br i1 %eq, label %result_block, label %parent_type_block + +parent_type_block: ; preds = %check_subtype + %6 = inttoptr i64 %5 to ptr + %ptradd1 = getelementptr inbounds i8, ptr %6, i64 8 + %typeid.parent = load i64, ptr %ptradd1, align 8 + %7 = icmp eq i64 %typeid.parent, 0 + br i1 %7, label %result_block, label %check_subtype + +result_block: ; preds = %parent_type_block, %check_subtype + %8 = phi i1 [ false, %parent_type_block ], [ true, %check_subtype ] + br i1 %8, label %switch.case, label %next_if + +switch.case: ; preds = %result_block + %9 = extractvalue %any %2, 0 + store ptr %9, ptr %z, align 8 + store i32 12, ptr %taddr, align 4 + %10 = insertvalue %any undef, ptr %taddr, 0 + %11 = insertvalue %any %10, i64 ptrtoint (ptr @"$ct.int" to i64), 1 + store %any %11, ptr %y, align 8 + %12 = load ptr, ptr %z, align 8 + %13 = load i32, ptr %12, align 4 + call void (ptr, ...) @printf(ptr @.str.3, i32 %13) + br label %switch.exit + +next_if: ; preds = %result_block + br label %check_subtype2 + +check_subtype2: ; preds = %parent_type_block4, %next_if + %14 = phi i64 [ %4, %next_if ], [ %typeid.parent6, %parent_type_block4 ] + %eq3 = icmp eq i64 ptrtoint (ptr @"$ct.double" to i64), %14 + br i1 %eq3, label %result_block7, label %parent_type_block4 + +parent_type_block4: ; preds = %check_subtype2 + %15 = inttoptr i64 %14 to ptr + %ptradd5 = getelementptr inbounds i8, ptr %15, i64 8 + %typeid.parent6 = load i64, ptr %ptradd5, align 8 + %16 = icmp eq i64 %typeid.parent6, 0 + br i1 %16, label %result_block7, label %check_subtype2 + +result_block7: ; preds = %parent_type_block4, %check_subtype2 + %17 = phi i1 [ false, %parent_type_block4 ], [ true, %check_subtype2 ] + br i1 %17, label %switch.case8, label %next_if10 + +switch.case8: ; preds = %result_block7 + %18 = extractvalue %any %2, 0 + store ptr %18, ptr %z9, align 8 + %19 = load ptr, ptr %z9, align 8 + %20 = load double, ptr %19, align 8 + call void (ptr, ...) @printf(ptr @.str.4, double %20) + br label %switch.exit + +next_if10: ; preds = %result_block7 + br label %switch.default + +switch.default: ; preds = %next_if10 + call void (ptr, ...) @printf(ptr @.str.5) + br label %switch.exit + +switch.exit: ; preds = %switch.default, %switch.case8, %switch.case + ret void +} + +; Function Attrs: +define void @foo.test3(i64 %0, ptr %1) #0 { +entry: + %y = alloca %any, align 8 + %switch = alloca i64, align 8 + %z = alloca i32, align 4 + %z9 = alloca double, align 8 + store i64 %0, ptr %y, align 8 + %ptradd = getelementptr inbounds i8, ptr %y, i64 8 + store ptr %1, ptr %ptradd, align 8 + %2 = load %any, ptr %y, align 8 + %3 = extractvalue %any %2, 1 + store i64 %3, ptr %switch, align 8 + br label %switch.entry + +switch.entry: ; preds = %entry + %4 = load i64, ptr %switch, align 8 + br label %check_subtype + +check_subtype: ; preds = %parent_type_block, %switch.entry + %5 = phi i64 [ %4, %switch.entry ], [ %typeid.parent, %parent_type_block ] + %eq = icmp eq i64 ptrtoint (ptr @"$ct.int" to i64), %5 + br i1 %eq, label %result_block, label %parent_type_block + +parent_type_block: ; preds = %check_subtype + %6 = inttoptr i64 %5 to ptr + %ptradd1 = getelementptr inbounds i8, ptr %6, i64 8 + %typeid.parent = load i64, ptr %ptradd1, align 8 + %7 = icmp eq i64 %typeid.parent, 0 + br i1 %7, label %result_block, label %check_subtype + +result_block: ; preds = %parent_type_block, %check_subtype + %8 = phi i1 [ false, %parent_type_block ], [ true, %check_subtype ] + br i1 %8, label %switch.case, label %next_if + +switch.case: ; preds = %result_block + %9 = extractvalue %any %2, 0 + %10 = load i32, ptr %9, align 4 + store i32 %10, ptr %z, align 4 + %11 = load i32, ptr %z, align 4 + call void (ptr, ...) @printf(ptr @.str.6, i32 %11) + br label %switch.exit + +next_if: ; preds = %result_block + br label %check_subtype2 + +check_subtype2: ; preds = %parent_type_block4, %next_if + %12 = phi i64 [ %4, %next_if ], [ %typeid.parent6, %parent_type_block4 ] + %eq3 = icmp eq i64 ptrtoint (ptr @"$ct.double" to i64), %12 + br i1 %eq3, label %result_block7, label %parent_type_block4 + +parent_type_block4: ; preds = %check_subtype2 + %13 = inttoptr i64 %12 to ptr + %ptradd5 = getelementptr inbounds i8, ptr %13, i64 8 + %typeid.parent6 = load i64, ptr %ptradd5, align 8 + %14 = icmp eq i64 %typeid.parent6, 0 + br i1 %14, label %result_block7, label %check_subtype2 + +result_block7: ; preds = %parent_type_block4, %check_subtype2 + %15 = phi i1 [ false, %parent_type_block4 ], [ true, %check_subtype2 ] + br i1 %15, label %switch.case8, label %next_if10 + +switch.case8: ; preds = %result_block7 + %16 = extractvalue %any %2, 0 + %17 = load double, ptr %16, align 8 + store double %17, ptr %z9, align 8 + %18 = load double, ptr %z9, align 8 + call void (ptr, ...) @printf(ptr @.str.7, double %18) + br label %switch.exit + +next_if10: ; preds = %result_block7 + br label %switch.default + +switch.default: ; preds = %next_if10 + call void (ptr, ...) @printf(ptr @.str.8) + br label %switch.exit + +switch.exit: ; preds = %switch.default, %switch.case8, %switch.case + ret void +} + +; Function Attrs: +define i32 @main() #0 { +entry: + %taddr = alloca double, align 8 + %taddr1 = alloca %any, align 8 + %taddr2 = alloca i32, align 4 + %taddr3 = alloca %any, align 8 + %taddr7 = alloca i8, align 1 + %taddr8 = alloca %any, align 8 + %taddr12 = alloca double, align 8 + %taddr13 = alloca %any, align 8 + %taddr17 = alloca i32, align 4 + %taddr18 = alloca %any, align 8 + %taddr22 = alloca i8, align 1 + %taddr23 = alloca %any, align 8 + %taddr27 = alloca double, align 8 + %taddr28 = alloca %any, align 8 + %taddr32 = alloca i32, align 4 + %taddr33 = alloca %any, align 8 + %taddr37 = alloca i8, align 1 + %taddr38 = alloca %any, align 8 + store double 1.230000e+02, ptr %taddr, align 8 + %0 = insertvalue %any undef, ptr %taddr, 0 + %1 = insertvalue %any %0, i64 ptrtoint (ptr @"$ct.double" to i64), 1 + store %any %1, ptr %taddr1, align 8 + %lo = load i64, ptr %taddr1, align 8 + %ptradd = getelementptr inbounds i8, ptr %taddr1, i64 8 + %hi = load ptr, ptr %ptradd, align 8 + call void @foo.test(i64 %lo, ptr %hi) + store i32 1, ptr %taddr2, align 4 + %2 = insertvalue %any undef, ptr %taddr2, 0 + %3 = insertvalue %any %2, i64 ptrtoint (ptr @"$ct.int" to i64), 1 + store %any %3, ptr %taddr3, align 8 + %lo4 = load i64, ptr %taddr3, align 8 + %ptradd5 = getelementptr inbounds i8, ptr %taddr3, i64 8 + %hi6 = load ptr, ptr %ptradd5, align 8 + call void @foo.test(i64 %lo4, ptr %hi6) + store i8 1, ptr %taddr7, align 1 + %4 = insertvalue %any undef, ptr %taddr7, 0 + %5 = insertvalue %any %4, i64 ptrtoint (ptr @"$ct.bool" to i64), 1 + store %any %5, ptr %taddr8, align 8 + %lo9 = load i64, ptr %taddr8, align 8 + %ptradd10 = getelementptr inbounds i8, ptr %taddr8, i64 8 + %hi11 = load ptr, ptr %ptradd10, align 8 + call void @foo.test(i64 %lo9, ptr %hi11) + store double 1.235000e+02, ptr %taddr12, align 8 + %6 = insertvalue %any undef, ptr %taddr12, 0 + %7 = insertvalue %any %6, i64 ptrtoint (ptr @"$ct.double" to i64), 1 + store %any %7, ptr %taddr13, align 8 + %lo14 = load i64, ptr %taddr13, align 8 + %ptradd15 = getelementptr inbounds i8, ptr %taddr13, i64 8 + %hi16 = load ptr, ptr %ptradd15, align 8 + call void @foo.test2(i64 %lo14, ptr %hi16) + store i32 1, ptr %taddr17, align 4 + %8 = insertvalue %any undef, ptr %taddr17, 0 + %9 = insertvalue %any %8, i64 ptrtoint (ptr @"$ct.int" to i64), 1 + store %any %9, ptr %taddr18, align 8 + %lo19 = load i64, ptr %taddr18, align 8 + %ptradd20 = getelementptr inbounds i8, ptr %taddr18, i64 8 + %hi21 = load ptr, ptr %ptradd20, align 8 + call void @foo.test2(i64 %lo19, ptr %hi21) + store i8 1, ptr %taddr22, align 1 + %10 = insertvalue %any undef, ptr %taddr22, 0 + %11 = insertvalue %any %10, i64 ptrtoint (ptr @"$ct.bool" to i64), 1 + store %any %11, ptr %taddr23, align 8 + %lo24 = load i64, ptr %taddr23, align 8 + %ptradd25 = getelementptr inbounds i8, ptr %taddr23, i64 8 + %hi26 = load ptr, ptr %ptradd25, align 8 + call void @foo.test2(i64 %lo24, ptr %hi26) + store double 1.240000e+02, ptr %taddr27, align 8 + %12 = insertvalue %any undef, ptr %taddr27, 0 + %13 = insertvalue %any %12, i64 ptrtoint (ptr @"$ct.double" to i64), 1 + store %any %13, ptr %taddr28, align 8 + %lo29 = load i64, ptr %taddr28, align 8 + %ptradd30 = getelementptr inbounds i8, ptr %taddr28, i64 8 + %hi31 = load ptr, ptr %ptradd30, align 8 + call void @foo.test3(i64 %lo29, ptr %hi31) + store i32 2, ptr %taddr32, align 4 + %14 = insertvalue %any undef, ptr %taddr32, 0 + %15 = insertvalue %any %14, i64 ptrtoint (ptr @"$ct.int" to i64), 1 + store %any %15, ptr %taddr33, align 8 + %lo34 = load i64, ptr %taddr33, align 8 + %ptradd35 = getelementptr inbounds i8, ptr %taddr33, i64 8 + %hi36 = load ptr, ptr %ptradd35, align 8 + call void @foo.test3(i64 %lo34, ptr %hi36) + store i8 1, ptr %taddr37, align 1 + %16 = insertvalue %any undef, ptr %taddr37, 0 + %17 = insertvalue %any %16, i64 ptrtoint (ptr @"$ct.bool" to i64), 1 + store %any %17, ptr %taddr38, align 8 + %lo39 = load i64, ptr %taddr38, align 8 + %ptradd40 = getelementptr inbounds i8, ptr %taddr38, i64 8 + %hi41 = load ptr, ptr %ptradd40, align 8 + call void @foo.test3(i64 %lo39, ptr %hi41) + ret i32 0 +} diff --git a/test/test_suite7/any/variant_switch.c3t b/test/test_suite7/any/variant_switch.c3t new file mode 100644 index 000000000..7496d4d2d --- /dev/null +++ b/test/test_suite7/any/variant_switch.c3t @@ -0,0 +1,165 @@ +// #target: macos-x64 +module foo; + +extern fn void printf(char*, ...); + +fn void test(any 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 + +@"$ct.int" = linkonce global %.introspect { i8 2, i64 0, ptr null, i64 4, i64 0, i64 0, [0 x i64] zeroinitializer }, align 8 +@"$ct.double" = linkonce global %.introspect { i8 4, i64 0, ptr null, i64 8, i64 0, i64 0, [0 x i64] zeroinitializer }, align 8 +@"$ct.bool" = linkonce global %.introspect { i8 1, i64 0, ptr null, i64 1, i64 0, i64 0, [0 x i64] zeroinitializer }, align 8 + +define void @foo.test(i64 %0, ptr %1) #0 { +entry: + %z = alloca %any, align 8 + %switch = alloca i64, align 8 + %z3 = alloca ptr, align 8 + %z11 = alloca ptr, align 8 + store i64 %0, ptr %z, align 8 + %ptradd = getelementptr inbounds i8, ptr %z, i64 8 + store ptr %1, ptr %ptradd, align 8 + %ptradd1 = getelementptr inbounds i8, ptr %z, i64 8 + %2 = load i64, ptr %ptradd1, align 8 + store i64 %2, ptr %switch, align 8 + br label %switch.entry + +switch.entry: ; preds = %entry + %3 = load i64, ptr %switch, align 8 + br label %check_subtype + +check_subtype: ; preds = %parent_type_block, %switch.entry + %4 = phi i64 [ %3, %switch.entry ], [ %typeid.parent, %parent_type_block ] + %eq = icmp eq i64 ptrtoint (ptr @"$ct.int" to i64), %4 + br i1 %eq, label %result_block, label %parent_type_block + +parent_type_block: ; preds = %check_subtype + %5 = inttoptr i64 %4 to ptr + %ptradd2 = getelementptr inbounds i8, ptr %5, i64 8 + %typeid.parent = load i64, ptr %ptradd2, align 8 + %6 = icmp eq i64 %typeid.parent, 0 + br i1 %6, label %result_block, label %check_subtype + +result_block: ; preds = %parent_type_block, %check_subtype + %7 = phi i1 [ false, %parent_type_block ], [ true, %check_subtype ] + br i1 %7, label %switch.case, label %next_if + +switch.case: ; preds = %result_block + %8 = load ptr, ptr %z, align 8 + store ptr %8, ptr %z3, align 8 + %9 = load ptr, ptr %z3, align 8 + %10 = load i32, ptr %9, align 4 + call void (ptr, ...) @printf(ptr @.str, i32 %10) + %11 = load ptr, ptr %z3, align 8 + store i32 3, ptr %11, align 4 + br label %switch.exit + +next_if: ; preds = %result_block + br label %check_subtype4 + +check_subtype4: ; preds = %parent_type_block6, %next_if + %12 = phi i64 [ %3, %next_if ], [ %typeid.parent8, %parent_type_block6 ] + %eq5 = icmp eq i64 ptrtoint (ptr @"$ct.double" to i64), %12 + br i1 %eq5, label %result_block9, label %parent_type_block6 + +parent_type_block6: ; preds = %check_subtype4 + %13 = inttoptr i64 %12 to ptr + %ptradd7 = getelementptr inbounds i8, ptr %13, i64 8 + %typeid.parent8 = load i64, ptr %ptradd7, align 8 + %14 = icmp eq i64 %typeid.parent8, 0 + br i1 %14, label %result_block9, label %check_subtype4 + +result_block9: ; preds = %parent_type_block6, %check_subtype4 + %15 = phi i1 [ false, %parent_type_block6 ], [ true, %check_subtype4 ] + br i1 %15, label %switch.case10, label %next_if12 + +switch.case10: ; preds = %result_block9 + %16 = load ptr, ptr %z, align 8 + store ptr %16, ptr %z11, align 8 + %17 = load ptr, ptr %z11, align 8 + %18 = load double, ptr %17, align 8 + call void (ptr, ...) @printf(ptr @.str.1, double %18) + br label %switch.exit + +next_if12: ; preds = %result_block9 + br label %switch.default + +switch.default: ; preds = %next_if12 + call void (ptr, ...) @printf(ptr @.str.2) + br label %switch.exit + +switch.exit: ; preds = %switch.default, %switch.case10, %switch.case + %ptradd13 = getelementptr inbounds i8, ptr %z, i64 8 + %19 = load i64, ptr %ptradd13, align 8 + %eq14 = icmp eq i64 %19, ptrtoint (ptr @"$ct.int" to i64) + br i1 %eq14, label %if.then, label %if.exit + +if.then: ; preds = %switch.exit + %20 = load ptr, ptr %z, align 8 + %21 = load i32, ptr %20, align 4 + call void (ptr, ...) @printf(ptr @.str.3, i32 %21) + br label %if.exit + +if.exit: ; preds = %if.then, %switch.exit + ret void +} + +; Function Attrs: +define i32 @main() #0 { +entry: + %taddr = alloca double, align 8 + %taddr1 = alloca %any, align 8 + %taddr2 = alloca i32, align 4 + %taddr3 = alloca %any, align 8 + %taddr7 = alloca i8, align 1 + %taddr8 = alloca %any, align 8 + store double 1.230000e+02, ptr %taddr, align 8 + %0 = insertvalue %any undef, ptr %taddr, 0 + %1 = insertvalue %any %0, i64 ptrtoint (ptr @"$ct.double" to i64), 1 + store %any %1, ptr %taddr1, align 8 + %lo = load i64, ptr %taddr1, align 8 + %ptradd = getelementptr inbounds i8, ptr %taddr1, i64 8 + %hi = load ptr, ptr %ptradd, align 8 + call void @foo.test(i64 %lo, ptr %hi) + store i32 1, ptr %taddr2, align 4 + %2 = insertvalue %any undef, ptr %taddr2, 0 + %3 = insertvalue %any %2, i64 ptrtoint (ptr @"$ct.int" to i64), 1 + store %any %3, ptr %taddr3, align 8 + %lo4 = load i64, ptr %taddr3, align 8 + %ptradd5 = getelementptr inbounds i8, ptr %taddr3, i64 8 + %hi6 = load ptr, ptr %ptradd5, align 8 + call void @foo.test(i64 %lo4, ptr %hi6) + store i8 1, ptr %taddr7, align 1 + %4 = insertvalue %any undef, ptr %taddr7, 0 + %5 = insertvalue %any %4, i64 ptrtoint (ptr @"$ct.bool" to i64), 1 + store %any %5, ptr %taddr8, align 8 + %lo9 = load i64, ptr %taddr8, align 8 + %ptradd10 = getelementptr inbounds i8, ptr %taddr8, i64 8 + %hi11 = load ptr, ptr %ptradd10, align 8 + call void @foo.test(i64 %lo9, ptr %hi11) + ret i32 0 +} diff --git a/test/test_suite7/any/variant_test.c3t b/test/test_suite7/any/variant_test.c3t new file mode 100644 index 000000000..cbb329af0 --- /dev/null +++ b/test/test_suite7/any/variant_test.c3t @@ -0,0 +1,355 @@ +// #target: macos-x64 +module foo; +extern fn void printf(char*, ...); + +fn void test(any x) +{ + switch (x.type) + { + case int: + printf("Was int\n"); + case double: + printf("Was double\n"); + case any: + printf("Was variant\n"); + case int*: + printf("Was int*\n"); + default: + printf("Unknown type\n"); + } +} + +fn void test_all(any... y) +{ + foreach (element : y) + { + test(element); + } +} + +fn void main() +{ + any x = &&1; + int z; + any 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 + +%any = type { ptr, i64 } +%"any[]" = type { ptr, i64 } +@"$ct.int" = linkonce global %.introspect { i8 2, i64 0, ptr null, i64 4, i64 0, i64 0, [0 x i64] zeroinitializer }, align 8 +@"$ct.double" = linkonce global %.introspect { i8 4, i64 0, ptr null, i64 8, i64 0, i64 0, [0 x i64] zeroinitializer }, align 8 +@"$ct.any$" = linkonce global %.introspect { i8 7, i64 0, ptr null, i64 16, i64 0, i64 0, [0 x i64] zeroinitializer }, align 8 +@"$ct.p$int" = linkonce global %.introspect { i8 19, i64 0, ptr null, i64 8, i64 ptrtoint (ptr @"$ct.int" to i64), i64 0, [0 x i64] zeroinitializer }, align 8 +@"$ct.bool" = linkonce global %.introspect { i8 1, i64 0, ptr null, i64 1, i64 0, i64 0, [0 x i64] zeroinitializer }, align 8 + +define void @foo.test(i64 %0, ptr %1) #0 { +entry: + %x = alloca %any, align 8 + %switch = alloca i64, align 8 + store i64 %0, ptr %x, align 8 + %ptradd = getelementptr inbounds i8, ptr %x, i64 8 + store ptr %1, ptr %ptradd, align 8 + %ptradd1 = getelementptr inbounds i8, ptr %x, i64 8 + %2 = load i64, ptr %ptradd1, align 8 + store i64 %2, ptr %switch, align 8 + br label %switch.entry + +switch.entry: ; preds = %entry + %3 = load i64, ptr %switch, align 8 + br label %check_subtype + +check_subtype: ; preds = %parent_type_block, %switch.entry + %4 = phi i64 [ %3, %switch.entry ], [ %typeid.parent, %parent_type_block ] + %eq = icmp eq i64 ptrtoint (ptr @"$ct.int" to i64), %4 + br i1 %eq, label %result_block, label %parent_type_block + +parent_type_block: ; preds = %check_subtype + %5 = inttoptr i64 %4 to ptr + %ptradd2 = getelementptr inbounds i8, ptr %5, i64 8 + %typeid.parent = load i64, ptr %ptradd2, align 8 + %6 = icmp eq i64 %typeid.parent, 0 + br i1 %6, label %result_block, label %check_subtype + +result_block: ; preds = %parent_type_block, %check_subtype + %7 = phi i1 [ false, %parent_type_block ], [ true, %check_subtype ] + br i1 %7, label %switch.case, label %next_if + +switch.case: ; preds = %result_block + call void (ptr, ...) @printf(ptr @.str) + br label %switch.exit + +next_if: ; preds = %result_block + br label %check_subtype3 + +check_subtype3: ; preds = %parent_type_block5, %next_if + %8 = phi i64 [ %3, %next_if ], [ %typeid.parent7, %parent_type_block5 ] + %eq4 = icmp eq i64 ptrtoint (ptr @"$ct.double" to i64), %8 + br i1 %eq4, label %result_block8, label %parent_type_block5 + +parent_type_block5: ; preds = %check_subtype3 + %9 = inttoptr i64 %8 to ptr + %ptradd6 = getelementptr inbounds i8, ptr %9, i64 8 + %typeid.parent7 = load i64, ptr %ptradd6, align 8 + %10 = icmp eq i64 %typeid.parent7, 0 + br i1 %10, label %result_block8, label %check_subtype3 + +result_block8: ; preds = %parent_type_block5, %check_subtype3 + %11 = phi i1 [ false, %parent_type_block5 ], [ true, %check_subtype3 ] + br i1 %11, label %switch.case9, label %next_if10 + +switch.case9: ; preds = %result_block8 + call void (ptr, ...) @printf(ptr @.str.1) + br label %switch.exit + +next_if10: ; preds = %result_block8 + br label %check_subtype11 + +check_subtype11: ; preds = %parent_type_block13, %next_if10 + %12 = phi i64 [ %3, %next_if10 ], [ %typeid.parent15, %parent_type_block13 ] + %eq12 = icmp eq i64 ptrtoint (ptr @"$ct.any$" to i64), %12 + br i1 %eq12, label %result_block16, label %parent_type_block13 + +parent_type_block13: ; preds = %check_subtype11 + %13 = inttoptr i64 %12 to ptr + %ptradd14 = getelementptr inbounds i8, ptr %13, i64 8 + %typeid.parent15 = load i64, ptr %ptradd14, align 8 + %14 = icmp eq i64 %typeid.parent15, 0 + br i1 %14, label %result_block16, label %check_subtype11 + +result_block16: ; preds = %parent_type_block13, %check_subtype11 + %15 = phi i1 [ false, %parent_type_block13 ], [ true, %check_subtype11 ] + br i1 %15, label %switch.case17, label %next_if18 + +switch.case17: ; preds = %result_block16 + call void (ptr, ...) @printf(ptr @.str.2) + br label %switch.exit + +next_if18: ; preds = %result_block16 + br label %check_subtype19 + +check_subtype19: ; preds = %parent_type_block21, %next_if18 + %16 = phi i64 [ %3, %next_if18 ], [ %typeid.parent23, %parent_type_block21 ] + %eq20 = icmp eq i64 ptrtoint (ptr @"$ct.p$int" to i64), %16 + br i1 %eq20, label %result_block24, label %parent_type_block21 + +parent_type_block21: ; preds = %check_subtype19 + %17 = inttoptr i64 %16 to ptr + %ptradd22 = getelementptr inbounds i8, ptr %17, i64 8 + %typeid.parent23 = load i64, ptr %ptradd22, align 8 + %18 = icmp eq i64 %typeid.parent23, 0 + br i1 %18, label %result_block24, label %check_subtype19 + +result_block24: ; preds = %parent_type_block21, %check_subtype19 + %19 = phi i1 [ false, %parent_type_block21 ], [ true, %check_subtype19 ] + br i1 %19, label %switch.case25, label %next_if26 + +switch.case25: ; preds = %result_block24 + call void (ptr, ...) @printf(ptr @.str.3) + br label %switch.exit + +next_if26: ; preds = %result_block24 + br label %switch.default + +switch.default: ; preds = %next_if26 + call void (ptr, ...) @printf(ptr @.str.4) + br label %switch.exit + +switch.exit: ; preds = %switch.default, %switch.case25, %switch.case17, %switch.case9, %switch.case + ret void +} + +; Function Attrs: +define void @foo.test_all(ptr %0, i64 %1) #0 { +entry: + %y = alloca %"any[]", align 8 + %.anon = alloca i64, align 8 + %element = alloca %any, align 8 + store ptr %0, ptr %y, align 8 + %ptradd = getelementptr inbounds i8, ptr %y, i64 8 + store i64 %1, ptr %ptradd, align 8 + %ptradd1 = getelementptr inbounds i8, ptr %y, i64 8 + %2 = load i64, ptr %ptradd1, align 8 + store i64 0, ptr %.anon, align 8 + br label %loop.cond + +loop.cond: ; preds = %loop.body, %entry + %3 = load i64, ptr %.anon, align 8 + %lt = icmp ult i64 %3, %2 + br i1 %lt, label %loop.body, label %loop.exit + +loop.body: ; preds = %loop.cond + %4 = load ptr, ptr %y, align 8 + %5 = load i64, ptr %.anon, align 8 + %ptroffset = getelementptr inbounds [16 x i8], ptr %4, i64 %5 + call void @llvm.memcpy.p0.p0.i32(ptr align 8 %element, ptr align 8 %ptroffset, i32 16, i1 false) + %lo = load i64, ptr %element, align 8 + %ptradd2 = getelementptr inbounds i8, ptr %element, i64 8 + %hi = load ptr, ptr %ptradd2, align 8 + call void @foo.test(i64 %lo, ptr %hi) + %6 = load i64, ptr %.anon, align 8 + %addnuw = add nuw i64 %6, 1 + store i64 %addnuw, ptr %.anon, align 8 + br label %loop.cond + +loop.exit: ; preds = %loop.cond + ret void +} + +; Function Attrs: +define void @foo.main() #0 { +entry: + %x = alloca %any, align 8 + %taddr = alloca i32, align 4 + %z = alloca i32, align 4 + %y = alloca %any, align 8 + %g = alloca i64, align 8 + %h = alloca i64, align 8 + %taddr7 = alloca double, align 8 + %taddr17 = alloca double, align 8 + %taddr18 = alloca %any, align 8 + %taddr22 = alloca i32, align 4 + %taddr23 = alloca %any, align 8 + %taddr27 = alloca i8, align 1 + %taddr28 = alloca %any, align 8 + %df = alloca ptr, align 8 + %varargslots = alloca [5 x %any], align 16 + %taddr33 = alloca double, align 8 + store i32 1, ptr %taddr, align 4 + %0 = insertvalue %any undef, ptr %taddr, 0 + %1 = insertvalue %any %0, i64 ptrtoint (ptr @"$ct.int" to i64), 1 + store %any %1, ptr %x, align 8 + store i32 0, ptr %z, align 4 + %2 = insertvalue %any undef, ptr %z, 0 + %3 = insertvalue %any %2, i64 ptrtoint (ptr @"$ct.int" to i64), 1 + store %any %3, ptr %y, align 8 + %ptradd = getelementptr inbounds i8, ptr %y, i64 8 + %4 = load i64, ptr %ptradd, align 8 + store i64 %4, ptr %g, align 8 + %ptradd1 = getelementptr inbounds i8, ptr %x, i64 8 + %5 = load i64, ptr %ptradd1, align 8 + store i64 %5, ptr %h, align 8 + %ptradd2 = getelementptr inbounds i8, ptr %y, i64 8 + %6 = load i64, ptr %ptradd2, align 8 + %eq = icmp eq i64 %6, ptrtoint (ptr @"$ct.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 + %ptradd3 = getelementptr inbounds i8, ptr %x, i64 8 + %7 = load i64, ptr %ptradd3, align 8 + %eq4 = icmp eq i64 %7, ptrtoint (ptr @"$ct.int" to i64) + br i1 %eq4, label %if.then5, label %if.exit6 + +if.then5: ; preds = %if.exit + call void (ptr, ...) @printf(ptr @.str.6) + br label %if.exit6 + +if.exit6: ; preds = %if.then5, %if.exit + store double 1.000000e+00, ptr %taddr7, align 8 + %8 = insertvalue %any undef, ptr %taddr7, 0 + %9 = insertvalue %any %8, i64 ptrtoint (ptr @"$ct.double" to i64), 1 + store %any %9, ptr %y, align 8 + %10 = insertvalue %any undef, ptr %x, 0 + %11 = insertvalue %any %10, i64 ptrtoint (ptr @"$ct.any$" to i64), 1 + store %any %11, ptr %x, align 8 + %ptradd8 = getelementptr inbounds i8, ptr %y, i64 8 + %12 = load i64, ptr %ptradd8, align 8 + %eq9 = icmp eq i64 %12, ptrtoint (ptr @"$ct.int" to i64) + br i1 %eq9, label %if.then10, label %if.exit11 + +if.then10: ; preds = %if.exit6 + call void (ptr, ...) @printf(ptr @.str.7) + br label %if.exit11 + +if.exit11: ; preds = %if.then10, %if.exit6 + %ptradd12 = getelementptr inbounds i8, ptr %x, i64 8 + %13 = load i64, ptr %ptradd12, align 8 + %eq13 = icmp eq i64 %13, ptrtoint (ptr @"$ct.int" to i64) + br i1 %eq13, label %if.then14, label %if.exit15 + +if.then14: ; preds = %if.exit11 + call void (ptr, ...) @printf(ptr @.str.8) + br label %if.exit15 + +if.exit15: ; preds = %if.then14, %if.exit11 + %lo = load i64, ptr %x, align 8 + %ptradd16 = getelementptr inbounds i8, ptr %x, i64 8 + %hi = load ptr, ptr %ptradd16, align 8 + call void @foo.test(i64 %lo, ptr %hi) + store double 1.000000e+00, ptr %taddr17, align 8 + %14 = insertvalue %any undef, ptr %taddr17, 0 + %15 = insertvalue %any %14, i64 ptrtoint (ptr @"$ct.double" to i64), 1 + store %any %15, ptr %taddr18, align 8 + %lo19 = load i64, ptr %taddr18, align 8 + %ptradd20 = getelementptr inbounds i8, ptr %taddr18, i64 8 + %hi21 = load ptr, ptr %ptradd20, align 8 + call void @foo.test(i64 %lo19, ptr %hi21) + store i32 1, ptr %taddr22, align 4 + %16 = insertvalue %any undef, ptr %taddr22, 0 + %17 = insertvalue %any %16, i64 ptrtoint (ptr @"$ct.int" to i64), 1 + store %any %17, ptr %taddr23, align 8 + %lo24 = load i64, ptr %taddr23, align 8 + %ptradd25 = getelementptr inbounds i8, ptr %taddr23, i64 8 + %hi26 = load ptr, ptr %ptradd25, align 8 + call void @foo.test(i64 %lo24, ptr %hi26) + store i8 1, ptr %taddr27, align 1 + %18 = insertvalue %any undef, ptr %taddr27, 0 + %19 = insertvalue %any %18, i64 ptrtoint (ptr @"$ct.bool" to i64), 1 + store %any %19, ptr %taddr28, align 8 + %lo29 = load i64, ptr %taddr28, align 8 + %ptradd30 = getelementptr inbounds i8, ptr %taddr28, i64 8 + %hi31 = load ptr, ptr %ptradd30, align 8 + call void @foo.test(i64 %lo29, ptr %hi31) + call void (ptr, ...) @printf(ptr @.str.9) + store ptr null, ptr %df, align 8 + call void @llvm.memcpy.p0.p0.i32(ptr align 16 %varargslots, ptr align 8 %x, i32 16, i1 false) + %ptradd32 = getelementptr inbounds i8, ptr %varargslots, i64 16 + call void @llvm.memcpy.p0.p0.i32(ptr align 16 %ptradd32, ptr align 8 %x, i32 16, i1 false) + store double 1.000000e+00, ptr %taddr33, align 8 + %20 = insertvalue %any undef, ptr %taddr33, 0 + %21 = insertvalue %any %20, i64 ptrtoint (ptr @"$ct.double" to i64), 1 + %ptradd34 = getelementptr inbounds i8, ptr %varargslots, i64 32 + store %any %21, ptr %ptradd34, align 16 + %22 = insertvalue %any undef, ptr %x, 0 + %23 = insertvalue %any %22, i64 ptrtoint (ptr @"$ct.any$" to i64), 1 + %ptradd35 = getelementptr inbounds i8, ptr %varargslots, i64 48 + store %any %23, ptr %ptradd35, align 16 + %24 = insertvalue %any undef, ptr %df, 0 + %25 = insertvalue %any %24, i64 ptrtoint (ptr @"$ct.p$int" to i64), 1 + %ptradd36 = getelementptr inbounds i8, ptr %varargslots, i64 64 + store %any %25, ptr %ptradd36, align 16 + call void @foo.test_all(ptr %varargslots, i64 5) + ret void +} diff --git a/test/test_suite7/arrays/array_bounds_check.c3t b/test/test_suite7/arrays/array_bounds_check.c3t new file mode 100644 index 000000000..af971dfdb --- /dev/null +++ b/test/test_suite7/arrays/array_bounds_check.c3t @@ -0,0 +1,47 @@ +// #target: macos-x64 +// #safe: yes +module testing; +import std::io; + +const FOO = (Foo[2]){ {11}, {22} }; + +struct Foo +{ + int x; +} + +fn void main() +{ + for (usz i = 0; i < 20; i++) + { + int x = FOO[i].x; + } +} + +/* #expect: testing.ll + +loop.cond: ; preds = %checkok, %entry + %0 = load i64, ptr %i, align 8 + %gt = icmp ugt i64 20, %0 + br i1 %gt, label %loop.body, label %loop.exit + +loop.body: ; preds = %loop.cond + %1 = load i64, ptr %i, align 8 + %ge = icmp uge i64 %1, 2 + %2 = call i1 @llvm.expect.i1(i1 %ge, i1 false) + br i1 %2, label %panic, label %checkok + +checkok: ; preds = %loop.body + %ptroffset = getelementptr inbounds [4 x i8], ptr @testing.FOO, i64 %1 + %3 = load i32, ptr %ptroffset, align 4 + store i32 %3, ptr %x, align 4 + %4 = load i64, ptr %i, align 8 + %add = add i64 %4, 1 + store i64 %add, ptr %i, align 8 + br label %loop.cond + +loop.exit: ; preds = %loop.cond + ret void + +panic: ; preds = %loop.body + store i64 2, ptr %taddr, align 8 diff --git a/test/test_suite7/arrays/array_casts.c3t b/test/test_suite7/arrays/array_casts.c3t new file mode 100644 index 000000000..f769e4678 --- /dev/null +++ b/test/test_suite7/arrays/array_casts.c3t @@ -0,0 +1,31 @@ +// #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 + store i32 0, ptr %x, align 4 + %ptradd = getelementptr inbounds i8, ptr %x, i64 4 + store i32 0, ptr %ptradd, align 4 + %ptradd1 = getelementptr inbounds i8, ptr %x, i64 8 + store i32 0, ptr %ptradd1, align 4 + store ptr %x, ptr %y, align 8 + %0 = insertvalue %"int[]" undef, ptr %x, 0 + %1 = insertvalue %"int[]" %0, i64 3, 1 + store %"int[]" %1, ptr %z, align 8 + ret void +} \ No newline at end of file diff --git a/test/test_suite7/arrays/array_comparison.c3t b/test/test_suite7/arrays/array_comparison.c3t new file mode 100644 index 000000000..ef0f26e47 --- /dev/null +++ b/test/test_suite7/arrays/array_comparison.c3t @@ -0,0 +1,248 @@ +// #target: macos-x64 +module test; + +extern fn void get(double[2]*); +extern fn void get2(int[2]*); +extern fn void get3(bool[2]*); + +fn void test() +{ + double[2] a @noinit; + double[2] b @noinit; + get(&a); + get(&b); + bool x = a == b; + bool y = a != b; + + int[2] a2 @noinit; + int[2] b2 @noinit; + get2(&a2); + get2(&b2); + bool x2 = a2 == b2; + bool y2 = a2 != b2; + + bool[2] a3 @noinit; + bool[2] b3 @noinit; + get3(&a3); + get3(&b3); + + bool x3 = a3 == b3; + bool y3 = a3 != b3; + +} + +extern fn void aget(double[200]*); +extern fn void aget2(int[200]*); +extern fn void aget3(bool[200]*); + +fn void test2() +{ + double[200] a @noinit; + double[200] b @noinit; + aget(&a); + aget(&b); + bool x = a == b; + bool y = a != b; + + int[200] a2 @noinit; + int[200] b2 @noinit; + aget2(&a2); + aget2(&b2); + bool x2 = a2 == b2; + bool y2 = a2 != b2; + + bool[200] a3 @noinit; + bool[200] b3 @noinit; + aget3(&a3); + aget3(&b3); + bool x3 = a3 == b3; + bool y3 = a3 != b3; + +} + +/* #expect: test.ll + +define void @test.test() #0 { +entry: + %a = alloca [2 x double], align 16 + %b = alloca [2 x double], align 16 + %x = alloca i8, align 1 + %y = alloca i8, align 1 + %a2 = alloca [2 x i32], align 4 + %b2 = alloca [2 x i32], align 4 + %x2 = alloca i8, align 1 + %y2 = alloca i8, align 1 + %a3 = alloca [2 x i8], align 1 + %b3 = alloca [2 x i8], align 1 + %x3 = alloca i8, align 1 + %y3 = alloca i8, align 1 + call void @get(ptr %a) + call void @get(ptr %b) + %lhs = load <2 x double>, ptr %a, align 16 + %rhs = load <2 x double>, ptr %b, align 16 + %cmp = fcmp oeq <2 x double> %lhs, %rhs + %0 = call i1 @llvm.vector.reduce.and.v2i1(<2 x i1> %cmp) + %1 = zext i1 %0 to i8 + store i8 %1, ptr %x, align 1 + %lhs1 = load <2 x double>, ptr %a, align 16 + %rhs2 = load <2 x double>, ptr %b, align 16 + %cmp3 = fcmp one <2 x double> %lhs1, %rhs2 + %2 = call i1 @llvm.vector.reduce.or.v2i1(<2 x i1> %cmp3) + %3 = zext i1 %2 to i8 + store i8 %3, ptr %y, align 1 + call void @get2(ptr %a2) + call void @get2(ptr %b2) + %cmp4 = call i32 @memcmp(ptr %a2, ptr %b2, i64 8) + %eq = icmp eq i32 %cmp4, 0 + %4 = zext i1 %eq to i8 + store i8 %4, ptr %x2, align 1 + %cmp5 = call i32 @memcmp(ptr %a2, ptr %b2, i64 8) + %neq = icmp ne i32 %cmp5, 0 + %5 = zext i1 %neq to i8 + store i8 %5, ptr %y2, align 1 + call void @get3(ptr %a3) + call void @get3(ptr %b3) + %lhs6 = load <2 x i8>, ptr %a3, align 1 + %rhs7 = load <2 x i8>, ptr %b3, align 1 + %6 = trunc <2 x i8> %lhs6 to <2 x i1> + %7 = trunc <2 x i8> %rhs7 to <2 x i1> + %cmp8 = icmp eq <2 x i1> %6, %7 + %8 = call i1 @llvm.vector.reduce.and.v2i1(<2 x i1> %cmp8) + %9 = zext i1 %8 to i8 + store i8 %9, ptr %x3, align 1 + %lhs9 = load <2 x i8>, ptr %a3, align 1 + %rhs10 = load <2 x i8>, ptr %b3, align 1 + %10 = trunc <2 x i8> %lhs9 to <2 x i1> + %11 = trunc <2 x i8> %rhs10 to <2 x i1> + %cmp11 = icmp ne <2 x i1> %10, %11 + %12 = call i1 @llvm.vector.reduce.or.v2i1(<2 x i1> %cmp11) + %13 = zext i1 %12 to i8 + store i8 %13, ptr %y3, align 1 + ret void +} +define void @test.test2() #0 { +entry: + %a = alloca [200 x double], align 16 + %b = alloca [200 x double], align 16 + %x = alloca i8, align 1 + %cmp.idx = alloca i64, align 8 + %y = alloca i8, align 1 + %cmp.idx2 = alloca i64, align 8 + %a2 = alloca [200 x i32], align 16 + %b2 = alloca [200 x i32], align 16 + %x2 = alloca i8, align 1 + %y2 = alloca i8, align 1 + %a3 = alloca [200 x i8], align 16 + %b3 = alloca [200 x i8], align 16 + %x3 = alloca i8, align 1 + %cmp.idx14 = alloca i64, align 8 + %y3 = alloca i8, align 1 + %cmp.idx23 = alloca i64, align 8 + call void @aget(ptr %a) + call void @aget(ptr %b) + store i64 0, ptr %cmp.idx, align 8 + br label %array_loop_start + +array_loop_start: ; preds = %array_loop_comparison, %entry + %0 = load i64, ptr %cmp.idx, align 8 + %ptroffset = getelementptr inbounds [8 x i8], ptr %a, i64 %0 + %ptroffset1 = getelementptr inbounds [8 x i8], ptr %b, i64 %0 + %1 = load double, ptr %ptroffset, align 8 + %2 = load double, ptr %ptroffset1, align 8 + %eq = fcmp oeq double %1, %2 + br i1 %eq, label %array_loop_comparison, label %array_cmp_exit + +array_loop_comparison: ; preds = %array_loop_start + %inc = add i64 %0, 1 + store i64 %inc, ptr %cmp.idx, align 8 + %lt = icmp ult i64 %inc, 200 + br i1 %lt, label %array_loop_start, label %array_cmp_exit + +array_cmp_exit: ; preds = %array_loop_comparison, %array_loop_start + %array_cmp_phi = phi i1 [ true, %array_loop_comparison ], [ false, %array_loop_start ] + %3 = zext i1 %array_cmp_phi to i8 + store i8 %3, ptr %x, align 1 + store i64 0, ptr %cmp.idx2, align 8 + br label %array_loop_start3 + +array_loop_start3: ; preds = %array_loop_comparison7, %array_cmp_exit + %4 = load i64, ptr %cmp.idx2, align 8 + %ptroffset4 = getelementptr inbounds [8 x i8], ptr %a, i64 %4 + %ptroffset5 = getelementptr inbounds [8 x i8], ptr %b, i64 %4 + %5 = load double, ptr %ptroffset4, align 8 + %6 = load double, ptr %ptroffset5, align 8 + %eq6 = fcmp oeq double %5, %6 + br i1 %eq6, label %array_loop_comparison7, label %array_cmp_exit10 + +array_loop_comparison7: ; preds = %array_loop_start3 + %inc8 = add i64 %4, 1 + store i64 %inc8, ptr %cmp.idx2, align 8 + %lt9 = icmp ult i64 %inc8, 200 + br i1 %lt9, label %array_loop_start3, label %array_cmp_exit10 + +array_cmp_exit10: ; preds = %array_loop_comparison7, %array_loop_start3 + %array_cmp_phi11 = phi i1 [ false, %array_loop_comparison7 ], [ true, %array_loop_start3 ] + %7 = zext i1 %array_cmp_phi11 to i8 + store i8 %7, ptr %y, align 1 + call void @aget2(ptr %a2) + call void @aget2(ptr %b2) + %cmp = call i32 @memcmp(ptr %a2, ptr %b2, i64 800) + %eq12 = icmp eq i32 %cmp, 0 + %8 = zext i1 %eq12 to i8 + store i8 %8, ptr %x2, align 1 + %cmp13 = call i32 @memcmp(ptr %a2, ptr %b2, i64 800) + %neq = icmp ne i32 %cmp13, 0 + %9 = zext i1 %neq to i8 + store i8 %9, ptr %y2, align 1 + call void @aget3(ptr %a3) + call void @aget3(ptr %b3) + store i64 0, ptr %cmp.idx14, align 8 + br label %array_loop_start15 + +array_loop_start15: ; preds = %array_loop_comparison18, %array_cmp_exit10 + %10 = load i64, ptr %cmp.idx14, align 8 + %ptradd = getelementptr inbounds i8, ptr %a3, i64 %10 + %ptradd16 = getelementptr inbounds i8, ptr %b3, i64 %10 + %11 = load i8, ptr %ptradd, align 1 + %12 = trunc i8 %11 to i1 + %13 = load i8, ptr %ptradd16, align 1 + %14 = trunc i8 %13 to i1 + %eq17 = icmp eq i1 %12, %14 + br i1 %eq17, label %array_loop_comparison18, label %array_cmp_exit21 + +array_loop_comparison18: ; preds = %array_loop_start15 + %inc19 = add i64 %10, 1 + store i64 %inc19, ptr %cmp.idx14, align 8 + %lt20 = icmp ult i64 %inc19, 200 + br i1 %lt20, label %array_loop_start15, label %array_cmp_exit21 + +array_cmp_exit21: ; preds = %array_loop_comparison18, %array_loop_start15 + %array_cmp_phi22 = phi i1 [ true, %array_loop_comparison18 ], [ false, %array_loop_start15 ] + %15 = zext i1 %array_cmp_phi22 to i8 + store i8 %15, ptr %x3, align 1 + store i64 0, ptr %cmp.idx23, align 8 + br label %array_loop_start24 + +array_loop_start24: ; preds = %array_loop_comparison28, %array_cmp_exit21 + %16 = load i64, ptr %cmp.idx23, align 8 + %ptradd25 = getelementptr inbounds i8, ptr %a3, i64 %16 + %ptradd26 = getelementptr inbounds i8, ptr %b3, i64 %16 + %17 = load i8, ptr %ptradd25, align 1 + %18 = trunc i8 %17 to i1 + %19 = load i8, ptr %ptradd26, align 1 + %20 = trunc i8 %19 to i1 + %eq27 = icmp eq i1 %18, %20 + br i1 %eq27, label %array_loop_comparison28, label %array_cmp_exit31 + +array_loop_comparison28: ; preds = %array_loop_start24 + %inc29 = add i64 %16, 1 + store i64 %inc29, ptr %cmp.idx23, align 8 + %lt30 = icmp ult i64 %inc29, 200 + br i1 %lt30, label %array_loop_start24, label %array_cmp_exit31 + +array_cmp_exit31: ; preds = %array_loop_comparison28, %array_loop_start24 + %array_cmp_phi32 = phi i1 [ false, %array_loop_comparison28 ], [ true, %array_loop_start24 ] + %21 = zext i1 %array_cmp_phi32 to i8 + store i8 %21, ptr %y3, align 1 + ret void +} diff --git a/test/test_suite7/arrays/array_comparison_2.c3t b/test/test_suite7/arrays/array_comparison_2.c3t new file mode 100644 index 000000000..23370b44a --- /dev/null +++ b/test/test_suite7/arrays/array_comparison_2.c3t @@ -0,0 +1,86 @@ +// #target: macos-x64 +module test; + +fn void main() +{ + int[2][2] x; + int[2][2] y; + bool match = x == y; + int[2][2][8] z; + int[2][2][8] w; + match = z == w; +} + +/* #expect: test.ll + +define void @test.main() #0 { +entry: + %x = alloca [2 x [2 x i32]], align 16 + %y = alloca [2 x [2 x i32]], align 16 + %match = alloca i8, align 1 + %z = alloca [8 x [2 x [2 x i32]]], align 16 + %w = alloca [8 x [2 x [2 x i32]]], align 16 + %cmp.idx = alloca i64, align 8 + store i32 0, ptr %x, align 4 + %ptradd = getelementptr inbounds i8, ptr %x, i64 4 + store i32 0, ptr %ptradd, align 4 + %ptradd1 = getelementptr inbounds i8, ptr %x, i64 8 + store i32 0, ptr %ptradd1, align 4 + %ptradd2 = getelementptr inbounds i8, ptr %ptradd1, i64 4 + store i32 0, ptr %ptradd2, align 4 + store i32 0, ptr %y, align 4 + %ptradd3 = getelementptr inbounds i8, ptr %y, i64 4 + store i32 0, ptr %ptradd3, align 4 + %ptradd4 = getelementptr inbounds i8, ptr %y, i64 8 + store i32 0, ptr %ptradd4, align 4 + %ptradd5 = getelementptr inbounds i8, ptr %ptradd4, i64 4 + store i32 0, ptr %ptradd5, align 4 + %cmp = call i32 @memcmp(ptr %x, ptr %y, i64 8) + %eq = icmp eq i32 %cmp, 0 + br i1 %eq, label %next_check, label %exit +next_check: ; preds = %entry + %ptradd6 = getelementptr inbounds i8, ptr %x, i64 8 + %ptradd7 = getelementptr inbounds i8, ptr %y, i64 8 + %cmp8 = call i32 @memcmp(ptr %ptradd6, ptr %ptradd7, i64 8) + %eq9 = icmp eq i32 %cmp8, 0 + br i1 %eq9, label %match10, label %exit +match10: ; preds = %next_check + br label %exit +exit: ; preds = %match10, %next_check, %entry + %array_cmp_phi = phi i1 [ false, %entry ], [ false, %next_check ], [ true, %match10 ] + %0 = zext i1 %array_cmp_phi to i8 + store i8 %0, ptr %match, align 1 + call void @llvm.memset.p0.i64(ptr align 16 %z, i8 0, i64 128, i1 false) + call void @llvm.memset.p0.i64(ptr align 16 %w, i8 0, i64 128, i1 false) + store i64 0, ptr %cmp.idx, align 8 + br label %array_loop_start +array_loop_start: ; preds = %array_loop_comparison, %exit + %1 = load i64, ptr %cmp.idx, align 8 + %ptroffset = getelementptr inbounds [16 x i8], ptr %z, i64 %1 + %ptroffset11 = getelementptr inbounds [16 x i8], ptr %w, i64 %1 + %cmp12 = call i32 @memcmp(ptr %ptroffset, ptr %ptroffset11, i64 8) + %eq13 = icmp eq i32 %cmp12, 0 + br i1 %eq13, label %next_check14, label %exit20 +next_check14: ; preds = %array_loop_start + %ptradd15 = getelementptr inbounds i8, ptr %ptroffset, i64 8 + %ptradd16 = getelementptr inbounds i8, ptr %ptroffset11, i64 8 + %cmp17 = call i32 @memcmp(ptr %ptradd15, ptr %ptradd16, i64 8) + %eq18 = icmp eq i32 %cmp17, 0 + br i1 %eq18, label %match19, label %exit20 +match19: ; preds = %next_check14 + br label %exit20 +exit20: ; preds = %match19, %next_check14, %array_loop_start + %array_cmp_phi21 = phi i1 [ false, %array_loop_start ], [ false, %next_check14 ], [ true, %match19 ] + br i1 %array_cmp_phi21, label %array_loop_comparison, label %array_cmp_exit +array_loop_comparison: ; preds = %exit20 + %inc = add i64 %1, 1 + store i64 %inc, ptr %cmp.idx, align 8 + %lt = icmp ult i64 %inc, 8 + br i1 %lt, label %array_loop_start, label %array_cmp_exit +array_cmp_exit: ; preds = %array_loop_comparison, %exit20 + %array_cmp_phi22 = phi i1 [ true, %array_loop_comparison ], [ false, %exit20 ] + %2 = zext i1 %array_cmp_phi22 to i8 + store i8 %2, ptr %match, align 1 + ret void +} + diff --git a/test/test_suite7/arrays/array_indexing.c3 b/test/test_suite7/arrays/array_indexing.c3 new file mode 100644 index 000000000..3d5be2a87 --- /dev/null +++ b/test/test_suite7/arrays/array_indexing.c3 @@ -0,0 +1,11 @@ +enum Foo : int +{ + TEST +} + +int[100] a = { [Foo.TEST.ordinal] = 123 }; + +fn void test() +{ + a[Foo.TEST.ordinal] = 33; +} \ No newline at end of file diff --git a/test/test_suite7/arrays/array_invalid_casts.c3 b/test/test_suite7/arrays/array_invalid_casts.c3 new file mode 100644 index 000000000..869499795 --- /dev/null +++ b/test/test_suite7/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]*' to 'double[]' +} \ No newline at end of file diff --git a/test/test_suite7/arrays/array_literal.c3t b/test/test_suite7/arrays/array_literal.c3t new file mode 100644 index 000000000..9e2bad3db --- /dev/null +++ b/test/test_suite7/arrays/array_literal.c3t @@ -0,0 +1,28 @@ +// #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 + +; Function Attrs: +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) + %zext = zext i32 %0 to i64 + %ptroffset = getelementptr inbounds [8 x i8], ptr %student_t, i64 %zext + %1 = load double, ptr %ptroffset, align 8 + ret double %1 +} diff --git a/test/test_suite7/arrays/array_struct.c3t b/test/test_suite7/arrays/array_struct.c3t new file mode 100644 index 000000000..d73e0e4d1 --- /dev/null +++ b/test/test_suite7/arrays/array_struct.c3t @@ -0,0 +1,13 @@ +// #target: macos-x64 +module test; + +struct Foo +{ + int x, y; +} + +Foo[10] array @private; + +/* #expect: test.ll + +@test.array = internal unnamed_addr global [10 x %Foo] zeroinitializer, align 16 \ No newline at end of file diff --git a/test/test_suite7/arrays/complex_array_const.c3t b/test/test_suite7/arrays/complex_array_const.c3t new file mode 100644 index 000000000..fcd12f014 --- /dev/null +++ b/test/test_suite7/arrays/complex_array_const.c3t @@ -0,0 +1,22 @@ +// #target: macos-x64 +module test; + +struct Connection +{ + long to; + char* type; + long length; +} + +Connection[3] link @private += { {1, "link1", 10}, + {2, "link2", 20}, + {3, "link3", 30} }; + +/* #expect: test.ll + +@"$ct.test.Connection" = linkonce global %.introspect { i8 10, i64 0, ptr null, i64 24, i64 0, i64 3, [0 x i64] zeroinitializer }, 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 = internal 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_suite7/arrays/complex_inferred_array.c3t b/test/test_suite7/arrays/complex_inferred_array.c3t new file mode 100644 index 000000000..da584132b --- /dev/null +++ b/test/test_suite7/arrays/complex_inferred_array.c3t @@ -0,0 +1,17 @@ +// #target: macos-x64 +module test; + +fn void main() +{ + int[?][?][2][?]! y = { {{{1}, {2}}, { {3}, {4}}}}; + int[?][?][2][?] x = { {{{1}, {2}}, { {3}, {4}}}}; +} + +/* #expect: test.ll + + +@.__const = private unnamed_addr constant [1 x [2 x [2 x [1 x i32]]]] [[2 x [2 x [1 x i32]]] [[2 x [1 x i32]] [[1 x i32] [i32 1], [1 x i32] [i32 2]], [2 x [1 x i32]] [[1 x i32] [i32 3], [1 x i32] [i32 4]]]], align 16 +@.__const.1 = private unnamed_addr constant [1 x [2 x [2 x [1 x i32]]]] [[2 x [2 x [1 x i32]]] [[2 x [1 x i32]] [[1 x i32] [i32 1], [1 x i32] [i32 2]], [2 x [1 x i32]] [[1 x i32] [i32 3], [1 x i32] [i32 4]]]], align 16 + + %y = alloca [1 x [2 x [2 x [1 x i32]]]], align 16 + %x = alloca [1 x [2 x [2 x [1 x i32]]]], align 16 diff --git a/test/test_suite7/arrays/global_array_non_const.c3 b/test/test_suite7/arrays/global_array_non_const.c3 new file mode 100644 index 000000000..18fb162b3 --- /dev/null +++ b/test/test_suite7/arrays/global_array_non_const.c3 @@ -0,0 +1,17 @@ + +const int CONSTANT = 1; +int[CONSTANT] a2; +int[3] a3 = { [CONSTANT] = 1 }; +const bool B = true; +int[B] c2; // #error: be implicitly converted + +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_suite7/arrays/global_init.c3t b/test/test_suite7/arrays/global_init.c3t new file mode 100644 index 000000000..3c84d724c --- /dev/null +++ b/test/test_suite7/arrays/global_init.c3t @@ -0,0 +1,61 @@ +// #target: macos-x64 +module test; + +int* foo = &&3; + +int a; +int c; +int d; +int[3] abc; +int *b = (&((&a + 1)[2]) + 1 - 2) + 5; +int *bf = &abc[2] + 2; +int *bf2 = &abc[2]; +int *bf3 = &abc[2] + 2; + +fn void main() { + int *bf34 = (&abc[2] + 2) + 3; + static any[3] x = { &&42, &&'c', &&"for" }; + any[3] y = { &&42, &&'c', &&"for" }; +} + +/* #expect: test.ll + +@.taddr = private unnamed_addr global i32 3, align 4 +@test.foo = local_unnamed_addr global ptr @.taddr, align 8 +@test.a = global i32 0, align 4 +@test.c = local_unnamed_addr global i32 0, align 4 +@test.d = local_unnamed_addr global i32 0, align 4 +@test.abc = local_unnamed_addr global [3 x i32] zeroinitializer, align 4 +@test.b = local_unnamed_addr global ptr getelementptr (i8, ptr +@test.bf = local_unnamed_addr global ptr getelementptr (i8, ptr +@test.bf2 = local_unnamed_addr global ptr getelementptr inbounds (i8, ptr @test.abc, i64 8), align 8 +@test.bf3 = local_unnamed_addr global ptr getelementptr (i8, ptr +@.taddr.9 = private unnamed_addr global i32 42, align 4 +@.taddr.10 = private unnamed_addr global i8 99, align 1 +@.taddr.11 = private unnamed_addr global %"char[]" { ptr @.str, i64 3 }, align 8 +@main.x = internal unnamed_addr global [3 x %any] [%any { ptr @.taddr.9, i64 ptrtoint (ptr @"$ct.int" to i64) }, %any { ptr @.taddr.10, i64 ptrtoint (ptr @"$ct.char" to i64) }, %any { ptr @.taddr.11, i64 ptrtoint (ptr @"$ct.String" to i64) }], align 16 + +define void @test.main() #0 { +entry: + %bf34 = alloca ptr, align 8 + %y = alloca [3 x %any], align 16 + %taddr = alloca i32, align 4 + %taddr1 = alloca i8, align 1 + %taddr3 = alloca %"char[]", align 8 + store ptr getelementptr (i8, ptr + store i32 42, ptr %taddr, align 4 + %0 = insertvalue %any undef, ptr %taddr, 0 + %1 = insertvalue %any %0, i64 ptrtoint (ptr @"$ct.int" to i64), 1 + store %any %1, ptr %y, align 16 + %ptradd = getelementptr inbounds i8, ptr %y, i64 16 + store i8 99, ptr %taddr1, align 1 + %2 = insertvalue %any undef, ptr %taddr1, 0 + %3 = insertvalue %any %2, i64 ptrtoint (ptr @"$ct.char" to i64), 1 + store %any %3, ptr %ptradd, align 16 + %ptradd2 = getelementptr inbounds i8, ptr %y, i64 32 + store %"char[]" { ptr @.str.12, i64 3 }, ptr %taddr3, align 8 + %4 = insertvalue %any undef, ptr %taddr3, 0 + %5 = insertvalue %any %4, i64 ptrtoint (ptr @"$ct.String" to i64), 1 + store %any %5, ptr %ptradd2, align 16 + ret void +} diff --git a/test/test_suite7/arrays/global_init_array_out_of_range.c3 b/test/test_suite7/arrays/global_init_array_out_of_range.c3 new file mode 100644 index 000000000..7471b4927 --- /dev/null +++ b/test/test_suite7/arrays/global_init_array_out_of_range.c3 @@ -0,0 +1,2 @@ +int[3] abc; +int *bf3 = (&abc[4]) + 2; // #error: An index of '4' is out of range, a value between 0 and 2 was expected \ No newline at end of file diff --git a/test/test_suite7/arrays/index_from_back.c3t b/test/test_suite7/arrays/index_from_back.c3t new file mode 100644 index 000000000..8b83536e4 --- /dev/null +++ b/test/test_suite7/arrays/index_from_back.c3t @@ -0,0 +1,54 @@ +// #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 + +; Function Attrs: +define void @test.test(ptr byval([10 x i32]) align 8 %0, ptr byval(<10 x i32>) align 64 %1) #0 { +entry: + %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 + %ptradd = getelementptr inbounds i8, ptr %0, i64 16 + %2 = load i32, ptr %ptradd, align 4 + store i32 %2, ptr %a, align 4 + %ptradd1 = getelementptr inbounds i8, ptr %0, i64 32 + %3 = load i32, ptr %ptradd1, align 4 + store i32 %3, ptr %b, align 4 + %4 = load <10 x i32>, ptr %1, align 64 + %5 = extractelement <10 x i32> %4, i64 4 + store i32 %5, ptr %c, align 4 + %6 = load <10 x i32>, ptr %1, align 64 + %7 = extractelement <10 x i32> %6, i64 8 + store i32 %7, ptr %d, align 4 + store i32 3, ptr %j, align 4 + %8 = load <10 x i32>, ptr %1, align 64 + %9 = load i32, ptr %j, align 4 + %sext = sext i32 %9 to i64 + %10 = sub nuw i64 10, %sext + %11 = extractelement <10 x i32> %8, i64 %10 + store i32 %11, ptr %e, align 4 + %12 = load i32, ptr %j, align 4 + %sext2 = sext i32 %12 to i64 + %13 = sub nuw i64 10, %sext2 + %ptroffset = getelementptr inbounds [4 x i8], ptr %0, i64 %13 + %14 = load i32, ptr %ptroffset, align 4 + store i32 %14, ptr %f, align 4 + ret void +} \ No newline at end of file diff --git a/test/test_suite7/arrays/index_into_global.c3t b/test/test_suite7/arrays/index_into_global.c3t new file mode 100644 index 000000000..13ef5c884 --- /dev/null +++ b/test/test_suite7/arrays/index_into_global.c3t @@ -0,0 +1,32 @@ +// #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: + %sext = sext i32 %0 to i64 + %ptroffset = getelementptr inbounds [4 x i8], ptr @foo.bar, i64 %sext + store i32 0, ptr %ptroffset, align 4 + store i32 %0, ptr @foo.bar, align 4 + ret void +} diff --git a/test/test_suite7/arrays/inferred_array_err.c3 b/test/test_suite7/arrays/inferred_array_err.c3 new file mode 100644 index 000000000..6562be53d --- /dev/null +++ b/test/test_suite7/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_suite7/arrays/inferred_array_err2.c3 b/test/test_suite7/arrays/inferred_array_err2.c3 new file mode 100644 index 000000000..d85269e4d --- /dev/null +++ b/test/test_suite7/arrays/inferred_array_err2.c3 @@ -0,0 +1,5 @@ +fn void test() +{ + int[3] z; + (int[?])(z); +} \ No newline at end of file diff --git a/test/test_suite7/arrays/inferred_array_optional.c3t b/test/test_suite7/arrays/inferred_array_optional.c3t new file mode 100644 index 000000000..0ad8a5f62 --- /dev/null +++ b/test/test_suite7/arrays/inferred_array_optional.c3t @@ -0,0 +1,91 @@ +// #target: macos-x64 +module test; + +fn int! foo() => 1; + +fn int main() +{ + int[?]! x = { 1, 2 }; + int[?]! y = { foo(), foo() }; + int[]! x2 = { 1, 2 }; + int[]! y2 = { foo(), foo() }; + return 1; +} + +/* #expect: test.ll + + +define i32 @main() #0 { +entry: + %x = alloca [2 x i32], align 4 + %x.f = alloca i64, align 8 + %y = alloca [2 x i32], align 4 + %y.f = alloca i64, align 8 + %retparam = alloca i32, align 4 + %retparam1 = alloca i32, align 4 + %x2 = alloca <2 x i32>, align 8 + %x2.f = alloca i64, align 8 + %y2 = alloca <2 x i32>, align 8 + %y2.f = alloca i64, align 8 + %retparam5 = alloca i32, align 4 + %retparam9 = alloca i32, align 4 + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %x, ptr align 4 @.__const, i32 8, i1 false) + store i64 0, ptr %x.f, align 8 + %0 = call i64 @test.foo(ptr %retparam) + %not_err = icmp eq i64 %0, 0 + %1 = call i1 @llvm.expect.i1(i1 %not_err, i1 true) + br i1 %1, label %after_check, label %assign_optional + +assign_optional: ; preds = %entry + store i64 %0, ptr %y.f, align 8 + br label %after_assign + +after_check: ; preds = %entry + %2 = load i32, ptr %retparam, align 4 + store i32 %2, ptr %y, align 4 + %ptradd = getelementptr inbounds i8, ptr %y, i64 4 + %3 = call i64 @test.foo(ptr %retparam1) + %not_err2 = icmp eq i64 %3, 0 + %4 = call i1 @llvm.expect.i1(i1 %not_err2, i1 true) + br i1 %4, label %after_check4, label %assign_optional3 + +assign_optional3: ; preds = %after_check + store i64 %3, ptr %y.f, align 8 + br label %after_assign + +after_check4: ; preds = %after_check + %5 = load i32, ptr %retparam1, align 4 + store i32 %5, ptr %ptradd, align 4 + store i64 0, ptr %y.f, align 8 + br label %after_assign + +after_assign: ; preds = %after_check4, %assign_optional3, %assign_optional + store <2 x i32> , ptr %x2, align 8 + store i64 0, ptr %x2.f, align 8 + %6 = call i64 @test.foo(ptr %retparam5) + %not_err6 = icmp eq i64 %6, 0 + %7 = call i1 @llvm.expect.i1(i1 %not_err6, i1 true) + br i1 %7, label %after_check8, label %assign_optional7 + +assign_optional7: ; preds = %after_assign + store i64 %6, ptr %y2.f, align 8 + br label %after_assign13 + +after_check8: ; preds = %after_assign + %8 = load i32, ptr %retparam5, align 4 + %9 = insertelement <2 x i32> undef, i32 %8, i64 0 + %10 = call i64 @test.foo(ptr %retparam9) + %not_err10 = icmp eq i64 %10, 0 + %11 = call i1 @llvm.expect.i1(i1 %not_err10, i1 true) + br i1 %11, label %after_check12, label %assign_optional11 + +assign_optional11: ; preds = %after_check8 + store i64 %10, ptr %y2.f, align 8 + br label %after_assign13 + +after_check12: ; preds = %after_check8 + %12 = load i32, ptr %retparam9, align 4 + %13 = insertelement <2 x i32> %9, i32 %12, i64 1 + store <2 x i32> %13, ptr %y2, align 8 + store i64 0, ptr %y2.f, align 8 + br label %after_assign13 diff --git a/test/test_suite7/arrays/inferred_subarray.c3 b/test/test_suite7/arrays/inferred_subarray.c3 new file mode 100644 index 000000000..c8258fa30 --- /dev/null +++ b/test/test_suite7/arrays/inferred_subarray.c3 @@ -0,0 +1,5 @@ +fn void main() +{ + int[?][?][] x = (int[2][1][]) { { { 1, 2 } } }; + int[?][?][?] y = (int[2][1][]) { { { 1, 2 } } }; +} diff --git a/test/test_suite7/arrays/negative_array.c3 b/test/test_suite7/arrays/negative_array.c3 new file mode 100644 index 000000000..15e33a942 --- /dev/null +++ b/test/test_suite7/arrays/negative_array.c3 @@ -0,0 +1,5 @@ + +int[-1] a; // #error: An array may not have a negative +int[10-20] b; // #error: An array may not have a negative +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_suite7/arrays/slice.c3 b/test/test_suite7/arrays/slice.c3 new file mode 100644 index 000000000..6d12e07c3 --- /dev/null +++ b/test/test_suite7/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_suite7/arrays/slice_array.c3 b/test/test_suite7/arrays/slice_array.c3 new file mode 100644 index 000000000..ac5ddd612 --- /dev/null +++ b/test/test_suite7/arrays/slice_array.c3 @@ -0,0 +1,6 @@ +distinct Bar = inline void; + +struct Foo +{ + Bar[] bars; // #error: You cannot form a slice with elements +} \ No newline at end of file diff --git a/test/test_suite7/asm/asm_bit_rv.c3t b/test/test_suite7/asm/asm_bit_rv.c3t new file mode 100644 index 000000000..56ba45552 --- /dev/null +++ b/test/test_suite7/asm/asm_bit_rv.c3t @@ -0,0 +1,20 @@ +// #target: elf-riscv32 +module test; + +fn void main(String[] args) +{ + asm + { + and $t0, $t1, $t2; + or $a0, $a1, $a2; + xor $s7, $s6, $s5; + andi $s1, $s2, -2048; + ori $s3, $s4, 2047; + xori $t3, $t4, 1; + not $t3, $t4; + } +} + +/* #expect: test.ll + +"and t0, t1, t2\0Aor a0, a1, a2\0Axor s7, s6, s5\0Aandi s1, s2, -2048\0Aori s3, s4, 2047\0Axori t3, t4, 1\0Anot t3, t4\0A", "~{x5},~{x9},~{x10},~{x19},~{x23},~{x28}"() \ No newline at end of file diff --git a/test/test_suite7/asm/asm_imm_err_rv.c3 b/test/test_suite7/asm/asm_imm_err_rv.c3 new file mode 100644 index 000000000..78728d56d --- /dev/null +++ b/test/test_suite7/asm/asm_imm_err_rv.c3 @@ -0,0 +1,58 @@ +// #target: elf-riscv32 +module test; + +fn void test1() +{ + asm + { + andi $s1, $s2, -2049; // #error: 'andi' expected 'short' limited to 12 bits. + } +} + +fn void test2() +{ + asm + { + ori $t0, $t1, 2048; // #error: 'ori' expected 'short' limited to 12 bits. + } +} + +fn void test3() +{ + asm + { + slli $a0, $a1, 32u; // #error: 'slli' expected 'char' limited to 5 bits. + } +} + +fn void test4() +{ + asm + { + lui $a0, 0xFFFFFF; // #error: 'lui' expected 'uint' limited to 20 bits. + } +} + +fn void test5() +{ + asm + { + lui $a0, -1; // #error: 'lui' expected 'uint' limited to 20 bits. + } +} + +fn void test6() +{ + asm + { + auipc $a0, -1; // #error: 'auipc' expected 'uint' limited to 20 bits. + } +} + +fn void test7() +{ + asm + { + slli $a0, 1, 31u; // #error: 'slli' does not support a direct integer constant here. + } +} diff --git a/test/test_suite7/asm/asm_intr_rv.c3t b/test/test_suite7/asm/asm_intr_rv.c3t new file mode 100644 index 000000000..0f4928505 --- /dev/null +++ b/test/test_suite7/asm/asm_intr_rv.c3t @@ -0,0 +1,21 @@ +// #target: elf-riscv32 +module test; + +fn void main(String[] args) +{ + int x = 0; + void* fp; + asm + { + csrw $mstatus, $a0; + csrrsi $zero, $mstatus, 8u; + csrrci $zero, $mstatus, 31u; + csrrw $zero, $mtvec, fp; + mret; + wfi; + } +} + +/* #expect: test.ll + +"csrw mstatus, a0\0Acsrrsi zero, mstatus, 8\0Acsrrci zero, mstatus, 31\0Acsrrw zero, mtvec, $0\0Amret \0Awfi \0A", "r,~{x0},~{mstatus},~{mtvec}"(ptr %1) \ No newline at end of file diff --git a/test/test_suite7/asm/asm_jump_rv.c3t b/test/test_suite7/asm/asm_jump_rv.c3t new file mode 100644 index 000000000..ed0539fd5 --- /dev/null +++ b/test/test_suite7/asm/asm_jump_rv.c3t @@ -0,0 +1,30 @@ +// #target: elf-riscv32 +module test; + +def Sum = fn int(int a, int b); + +fn int sum(int a, int b) +{ + return a + b; +} + +fn void main(String[] args) +{ + int a = 1; + int b = 2; + int result = 0; + Sum sum_ptr = ∑ + + asm + { + mv $a0, a; + mv $a1, b; + jalr $ra, sum_ptr, 0; + mv result, $a0; + } +} + + +/* #expect: test.ll + +"mv a0, $1\0Amv a1, $2\0Ajalr ra, $3, 0\0Amv $0, a0\0A", "=r,r,r,r,~{x1},~{x10},~{x11}"(i32 %1, i32 %2, ptr %3) \ No newline at end of file diff --git a/test/test_suite7/asm/asm_load_rv.c3t b/test/test_suite7/asm/asm_load_rv.c3t new file mode 100644 index 000000000..18aad2202 --- /dev/null +++ b/test/test_suite7/asm/asm_load_rv.c3t @@ -0,0 +1,21 @@ +// #target: elf-riscv32 +module test; + +fn void main(String[] args) +{ + int x = 2; + asm + { + li $s1, -2147483648; + lui $t0, 123456u; + auipc $x15, 123456u; + auipc $a0, 1; + mv $a0, $a1; + lw $a4, [&x]; + lb $a5, [$a7 - 4]; + } +} + +/* #expect: test.ll + +"li s1, -2147483648\0Alui t0, 123456\0Aauipc x15, 123456\0Aauipc a0, 1\0Amv a0, a1\0Alw a4, $0\0Alb a5, -4(a7)\0A", "*m,~{x5},~{x9},~{x10},~{x14},~{x15}"(ptr elementtype(i32) %x) \ No newline at end of file diff --git a/test/test_suite7/asm/asm_load_rv64.c3t b/test/test_suite7/asm/asm_load_rv64.c3t new file mode 100644 index 000000000..27dcd217f --- /dev/null +++ b/test/test_suite7/asm/asm_load_rv64.c3t @@ -0,0 +1,15 @@ +// #target: elf-riscv64 +module test; + +fn void main(String[] args) +{ + int x = 2; + asm + { + li $s1, -9223372036854775808; + } +} + +/* #expect: test.ll + +"li s1, -9223372036854775808\0A", "~{x9}"() \ No newline at end of file diff --git a/test/test_suite7/asm/asm_math_rv.c3t b/test/test_suite7/asm/asm_math_rv.c3t new file mode 100644 index 000000000..ac6da66e1 --- /dev/null +++ b/test/test_suite7/asm/asm_math_rv.c3t @@ -0,0 +1,19 @@ +// #target: elf-riscv32 +module test; + +fn void main(String[] args) +{ + int x = 0; + asm + { + add $t0, $t1, $t2; + add x, $t1, $t2; + sub $a0, $a1, $a2; + addi $s1, $s2, -2048; + neg $t3, $t4; + } +} + +/* #expect: test.ll + +"add t0, t1, t2\0Aadd $0, t1, t2\0Asub a0, a1, a2\0Aaddi s1, s2, -2048\0Aneg t3, t4\0A", "=r,~{x5},~{x9},~{x10},~{x28}"() \ No newline at end of file diff --git a/test/test_suite7/asm/asm_ops_x64_1.c3t b/test/test_suite7/asm/asm_ops_x64_1.c3t new file mode 100644 index 000000000..2e094bdf2 --- /dev/null +++ b/test/test_suite7/asm/asm_ops_x64_1.c3t @@ -0,0 +1,44 @@ +// #target: macos-x64 +module test; + +fn void main(String[] args) +{ + int x; + if (args.len < 10) return; + asm + { + in $eax, 3; + in $ax, $dx; + incb $al; + incw $bx; + incl $eax; + incq $rax; + incl [&x]; + insb; + insw; + insl; + int 0x08; + int3; + // int1; Broken in LLVM + invd; + invlpg [&x]; + invpcid $rax, [&x]; + invlpga $ecx, $rax; + iret; + iretl; + iretw; + iretq; + push 1; + pushw 2; + pushw $ax; + pushw [&x]; + pushq $rax; + pushq [&x]; + popw $ax; + popq $rax; + } +} + +/* #expect: test.ll + +"in $$3, %eax\0Ain %dx, %ax\0Aincb %al\0Aincw %bx\0Aincl %eax\0Aincq %rax\0Aincl $0\0Ainsb \0Ainsw \0Ainsl \0Aint $$8\0Aint3 \0Ainvd \0Ainvlpg $0\0Ainvpcid $1, %rax\0Ainvlpga %rax, %ecx\0Airet \0Airetl \0Airetw \0Airetq \0Apush $$1\0Apushw $$2\0Apushw %ax\0Apushw $1\0Apushq %rax\0Apushq $1\0Apopw %ax\0Apopq %rax\0A", "=*&m,*m,~{cc},~{rax},~{rbx},~{flags},~{dirflag},~{fspr}" diff --git a/test/test_suite7/asm/asm_ops_x64_2.c3t b/test/test_suite7/asm/asm_ops_x64_2.c3t new file mode 100644 index 000000000..4090068d8 --- /dev/null +++ b/test/test_suite7/asm/asm_ops_x64_2.c3t @@ -0,0 +1,30 @@ +// #target: macos-x64 +module test; + +fn void main(String[] args) +{ + int foo; + asm + { + adcxl $eax, $ecx; + adcxq $rax, $rcx; + addpd $xmm1, $xmm2; + addps $xmm1, $xmm2; + addsd $xmm1, $xmm2; + addss $xmm1, $xmm2; + vaddpd $xmm1, $xmm2, $xmm3; + vaddpd $ymm1, $ymm2, $ymm3; + vaddpd $xmm1, $xmm2, [&foo]; + vaddps $xmm1, $xmm2, $xmm3; + vaddps $ymm1, $ymm2, $ymm3; + vaddps $xmm1, $xmm2, [&foo]; + vaddsd $xmm1, $xmm2, $xmm3; + vaddsd $xmm1, $xmm2, [&foo]; + vaddss $xmm1, $xmm2, $xmm3; + vaddss $xmm1, $xmm2, [&foo]; + } +} + +/* #expect: test.ll + +"adcxl %ecx, %eax\0Aadcxq %rcx, %rax\0Aaddpd %xmm2, %xmm1\0Aaddps %xmm2, %xmm1\0Aaddsd %xmm2, %xmm1\0Aaddss %xmm2, %xmm1\0Avaddpd %xmm3, %xmm2, %xmm1\0Avaddpd %ymm3, %ymm2, %ymm1\0Avaddpd $0, %xmm2, %xmm1\0Avaddps %xmm3, %xmm2, %xmm1\0Avaddps %ymm3, %ymm2, %ymm1\0Avaddps $0, %xmm2, %xmm1\0Avaddsd %xmm3, %xmm2, %xmm1\0Avaddsd $0, %xmm2, %xmm1\0Avaddss %xmm3, %xmm2, %xmm1\0Avaddss $0, %xmm2, %xmm1\0A", "*m,~{cc},~{rcx},~{xmm1},~{flags},~{dirflag},~{fspr}" diff --git a/test/test_suite7/asm/asm_regression.c3t b/test/test_suite7/asm/asm_regression.c3t new file mode 100644 index 000000000..924d4b615 --- /dev/null +++ b/test/test_suite7/asm/asm_regression.c3t @@ -0,0 +1,50 @@ +// #target: macos-x64 + +module test; +import std::io; +fn void main() +{ + int x = 222; + int y = 223; + long z = 0; + z = (long)x + y; + z *= x; + int g = 0; + int* gp = &g; + int[4] a = { 3, 4, 5, 6 }; + int* xa = &a; + usz asf = 1; + int aa = 3; + asm + { + + movl x, 4; + movl [gp], x; + movl x, 1; + movl [xa + asf * 4 + 4], x; + movl $eax, (23 + x); + movl x, $eax; + movq [&z], 33; + addl aa, 22; + } + io::printfn("aa: %d", aa); + io::printfn("Z: %d", z); + io::printfn("x: %d", x); + io::printfn("G was: %d", g); + foreach(int abc : a) io::printfn("%d", abc); + +} + +/* #expect: test.ll + + %4 = load ptr, ptr %gp, align 8 + %5 = load ptr, ptr %xa, align 8 + %6 = load i64, ptr %asf, align 8 + %7 = load i32, ptr %x, align 4 + %add3 = add i32 23, %7 + %8 = load i32, ptr %aa, align 4 + %9 = call { i32, i32 } asm sideeffect alignstack "movl $$4, $0\0Amovl $0, ($3)\0Amovl $$1, $0\0Amovl $0, 4($4,$5,4)\0Amovl $6, %eax\0Amovl %eax, $0\0Amovq $$33, $1\0Aaddl $$22, $2\0A", "=&r,=*&m,=r,r,r,r,r,2,~{cc},~{rax},~{flags},~{dirflag},~{fspr}"(ptr elementtype(i64) %z, ptr %4, ptr %5, i64 %6, i32 %add3, i32 %8) + %10 = extractvalue { i32, i32 } %9, 0 + store i32 %10, ptr %x, align 4 + %11 = extractvalue { i32, i32 } %9, 1 + store i32 %11, ptr %aa, align 4 diff --git a/test/test_suite7/asm/asm_set_rv.c3t b/test/test_suite7/asm/asm_set_rv.c3t new file mode 100644 index 000000000..89295b1e2 --- /dev/null +++ b/test/test_suite7/asm/asm_set_rv.c3t @@ -0,0 +1,18 @@ +// #target: elf-riscv32 +module test; + +fn void main(String[] args) +{ + int x = 2; + asm + { + slt $t0, $t1, x; + slti $a0, $a1, -2048; + sltiu $a0, $a1, 4095u; + seqz $s0, $zero; + } +} + +/* #expect: test.ll + +"slt t0, t1, $0\0Aslti a0, a1, -2048\0Asltiu a0, a1, 4095\0Aseqz s0, zero\0A", "r,~{x5},~{x8},~{x10}"(i32 %1) \ No newline at end of file diff --git a/test/test_suite7/asm/asm_shift_rv.c3t b/test/test_suite7/asm/asm_shift_rv.c3t new file mode 100644 index 000000000..21253b356 --- /dev/null +++ b/test/test_suite7/asm/asm_shift_rv.c3t @@ -0,0 +1,19 @@ +// #target: elf-riscv32 +module test; + +fn void main(String[] args) +{ + asm + { + sll $t0, $t1, $t2; + slli $s1, $s2, 31u; + srl $a0, $a1, $a2; + srli $x10, $x11, 0u; + sra $t0, $t1, $t2; + srai $s1, $s2, 1u; + } +} + +/* #expect: test.ll + +"sll t0, t1, t2\0Aslli s1, s2, 31\0Asrl a0, a1, a2\0Asrli x10, x11, 0\0Asra t0, t1, t2\0Asrai s1, s2, 1\0A", "~{x5},~{x9},~{x10}"() \ No newline at end of file diff --git a/test/test_suite7/asm/asm_store_rv.c3t b/test/test_suite7/asm/asm_store_rv.c3t new file mode 100644 index 000000000..abff59560 --- /dev/null +++ b/test/test_suite7/asm/asm_store_rv.c3t @@ -0,0 +1,17 @@ +// #target: elf-riscv32 +module test; + +fn void main(String[] args) +{ + int x = 2; + int y = 0; + asm + { + lw $a4, [&x]; + sw $a4, [&y]; + } +} + +/* #expect: test.ll + +"lw a4, $1\0Asw a4, $0\0A", "=*m,*m,~{x14}"(ptr elementtype(i32) %y, ptr elementtype(i32) %x) \ No newline at end of file diff --git a/test/test_suite7/asm/naked.c3t b/test/test_suite7/asm/naked.c3t new file mode 100644 index 000000000..a820f7f17 --- /dev/null +++ b/test/test_suite7/asm/naked.c3t @@ -0,0 +1,19 @@ +// #target: macos-x64 +module testing; + +fn void start() @export("_start") @naked @nostrip { + asm { + movq $rax, 0x3c; + movq $rdi, 42; + syscall; + } +} + +/* #expect: testing.ll + +define void @_start() #0 { +entry: + call void asm sideeffect alignstack "movq $$60, %rax\0Amovq $$42, %rdi\0Asyscall \0A", "~{cc},~{rax},~{rcx},~{r8},~{r11},~{flags},~{dirflag},~{fspr}"() + ret void +} + diff --git a/test/test_suite7/asm/sideeffect.c3t b/test/test_suite7/asm/sideeffect.c3t new file mode 100644 index 000000000..3613ba606 --- /dev/null +++ b/test/test_suite7/asm/sideeffect.c3t @@ -0,0 +1,21 @@ +// #target: macos-x64 +module test; + +fn void test() +{ + asm { nop; } + asm @pure { nop; } + asm("nop"); + asm("nop") @pure; +} + +/* #expect: test.ll + +define void @test.test() #0 { +entry: + call void asm sideeffect alignstack "nop \0A", "~{flags},~{dirflag},~{fspr}"() + call void asm alignstack "nop \0A", "~{flags},~{dirflag},~{fspr}"() + call void asm sideeffect alignstack "nop", "~{dirflag},~{fpsr},~{flags}"() + call void asm alignstack "nop", "~{dirflag},~{fpsr},~{flags}"() + ret void +} \ No newline at end of file diff --git a/test/test_suite7/asm/syscall.c3t b/test/test_suite7/asm/syscall.c3t new file mode 100644 index 000000000..bc2cabd9e --- /dev/null +++ b/test/test_suite7/asm/syscall.c3t @@ -0,0 +1,17 @@ +// #target: macos-x64 +module testing; + +fn void start() @export("_start") @naked @nostrip { + asm { + syscall; + } +} + +/* #expect: testing.ll + +define void @_start() #0 { +entry: + call void asm sideeffect alignstack "syscall \0A", "~{cc},~{rax},~{rcx},~{r11},~{flags},~{dirflag},~{fspr}"() + ret void +} + diff --git a/test/test_suite7/assert/assert_variants.c3t b/test/test_suite7/assert/assert_variants.c3t new file mode 100644 index 000000000..52b0288c5 --- /dev/null +++ b/test/test_suite7/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_suite7/assert/assert_with_void.c3 b/test/test_suite7/assert/assert_with_void.c3 new file mode 100644 index 000000000..1725e0bd2 --- /dev/null +++ b/test/test_suite7/assert/assert_with_void.c3 @@ -0,0 +1,42 @@ +module testing; +import std::io; + +fn void main() +{ + String[] s1; + String[] s2; + assert(false, "%s / %s", deep_print(s1), deep_print(s2)); // #error: This expression is of type +} + +macro deep_print(a) +{ + var $Type = $typeof(a); + $switch ($Type.kindof) + $case ARRAY: + $case SLICE: + io::print("["); + foreach (i, x : a) + { + if (i > 0) io::print(", "); + deep_print(x); + } + io::print("]"); + $case STRUCT: + io::print("{"); + $foreach ($i, $m : $typeof(a).membersof) + if ($i > 0) io::print(", "); + deep_print($m.get(a)); + $endforeach + io::print("}"); + $default: + $switch ($Type.nameof) + $case "String": + $case "DString": + $case "WString": + $case "ZString": + io::printf(`"%s"`, a); + $default: + io::printf("%s", a); + $endswitch + $endswitch +} \ No newline at end of file diff --git a/test/test_suite7/assert/assertf.c3t b/test/test_suite7/assert/assertf.c3t new file mode 100644 index 000000000..4920c5979 --- /dev/null +++ b/test/test_suite7/assert/assertf.c3t @@ -0,0 +1,51 @@ +// #target: macos-x64 +// #safe: yes +module main; + +fn void main() +{ + for (usz i = 0; i < 100000000; i++) + { + assert(i != 2, "Test %s %s", i, i * 2); + } +} + +/* #expect: main.ll + + %i = alloca i64, align 8 + %taddr = alloca i64, align 8 + %varargslots = alloca [2 x %any], align 16 + %indirectarg = alloca %"any[]", align 8 + store i64 0, ptr %i, align 8 + br label %loop.cond +loop.cond: ; preds = %assert_ok, %entry + %0 = load i64, ptr %i, align 8 + %gt = icmp ugt i64 100000000, %0 + br i1 %gt, label %loop.body, label %loop.exit +loop.body: ; preds = %loop.cond + %1 = load i64, ptr %i, align 8 + %neq = icmp ne i64 2, %1 + br i1 %neq, label %assert_ok, label %assert_fail +assert_fail: ; preds = %loop.body + %2 = insertvalue %any undef, ptr %i, 0 + %3 = insertvalue %any %2, i64 ptrtoint (ptr @"$ct.ulong" to i64), 1 + %4 = load i64, ptr %i, align 8 + %mul = mul i64 %4, 2 + store i64 %mul, ptr %taddr, align 8 + %5 = insertvalue %any undef, ptr %taddr, 0 + %6 = insertvalue %any %5, i64 ptrtoint (ptr @"$ct.long" to i64), 1 + store %any %3, ptr %varargslots, align 16 + %ptradd = getelementptr inbounds i8, ptr %varargslots, i64 16 + store %any %6, ptr %ptradd, align 16 + %7 = insertvalue %"any[]" undef, ptr %varargslots, 0 + %"$$temp" = insertvalue %"any[]" %7, i64 2, 1 + store %"any[]" %"$$temp", ptr %indirectarg, align 8 + call void @std.core.builtin.panicf(ptr @.panic_msg, i64 10, ptr @.file, i64 10, ptr @.func, i64 4, i32 7, ptr byval(%"any[]") align 8 %indirectarg) + unreachable +assert_ok: ; preds = %loop.body + %8 = load i64, ptr %i, align 8 + %add = add i64 %8, 1 + store i64 %add, ptr %i, align 8 + br label %loop.cond +loop.exit: ; preds = %loop.cond + diff --git a/test/test_suite7/assert/global_static_assert_not_constant.c3 b/test/test_suite7/assert/global_static_assert_not_constant.c3 new file mode 100644 index 000000000..a26c52b89 --- /dev/null +++ b/test/test_suite7/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_suite7/assert/local_static_assert_not_constant.c3 b/test/test_suite7/assert/local_static_assert_not_constant.c3 new file mode 100644 index 000000000..c40f7826d --- /dev/null +++ b/test/test_suite7/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. +} + +extern 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_suite7/assert/static_assert.c3 b/test/test_suite7/assert/static_assert.c3 new file mode 100644 index 000000000..75a060f06 --- /dev/null +++ b/test/test_suite7/assert/static_assert.c3 @@ -0,0 +1,8 @@ + +const int FOO = 2; + +fn void test() +{ + $assert FOO == 2 : "Bad"; + $assert FOO == 0 : "Good"; // #error: Good +} \ No newline at end of file diff --git a/test/test_suite7/assert/unreachable.c3t b/test/test_suite7/assert/unreachable.c3t new file mode 100644 index 000000000..c93c7d572 --- /dev/null +++ b/test/test_suite7/assert/unreachable.c3t @@ -0,0 +1,31 @@ +// #target: macos-x64 +fn int foo() +{ + return 1; +} + +fn void test() +{ + int x = foo(); + if (x > 0) return; + unreachable(); +} + + +/* #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 + unreachable +} \ No newline at end of file diff --git a/test/test_suite7/assert/unreachable_in_macro.c3t b/test/test_suite7/assert/unreachable_in_macro.c3t new file mode 100644 index 000000000..d4025c7bf --- /dev/null +++ b/test/test_suite7/assert/unreachable_in_macro.c3t @@ -0,0 +1,99 @@ +// #target: windows-x64 +module test; +import std; +fn int main() +{ + if (catch test()) + { + io::printn("Hello"); + } + (void)test(); + return 0; +} + +fault Bob +{ + ABC +} + +macro test() +{ + if (false) return; + return Bob.ABC?; + unreachable(); +} + +/* #expect: test.ll + +define i32 @main() #0 { +entry: + %temp_err = alloca i64, align 8 + %len = alloca i64, align 8 + %error_var = alloca i64, align 8 + %retparam = alloca i64, align 8 + %indirectarg = alloca %"char[]", align 8 + %error_var2 = alloca i64, align 8 + %error_var8 = alloca i64, align 8 + br label %testblock +testblock: ; preds = %entry + br label %if.exit +if.exit: ; preds = %testblock + store i64 ptrtoint (ptr @"test.Bob$ABC" to i64), ptr %temp_err, align 8 + br label %end_block +end_block: ; preds = %if.exit + %0 = load i64, ptr %temp_err, align 8 + %i2b = icmp ne i64 %0, 0 + br i1 %i2b, label %if.then, label %if.exit14 +if.then: ; preds = %end_block + %1 = call ptr @std.io.stdout() + store %"char[]" { ptr @.str, i64 5 }, ptr %indirectarg, align 8 + %2 = call i64 @std.io.File.write(ptr %retparam, ptr %1, ptr align 8 %indirectarg) + %not_err = icmp eq i64 %2, 0 + %3 = call i1 @llvm.expect.i1(i1 %not_err, i1 true) + br i1 %3, label %after_check, label %assign_optional +assign_optional: ; preds = %if.then + store i64 %2, ptr %error_var, align 8 + br label %guard_block +after_check: ; preds = %if.then + br label %noerr_block +guard_block: ; preds = %assign_optional + br label %voiderr +noerr_block: ; preds = %after_check + %4 = load i64, ptr %retparam, align 8 + store i64 %4, ptr %len, align 8 + %5 = call i64 @std.io.File.write_byte(ptr %1, i8 10) + %not_err3 = icmp eq i64 %5, 0 + %6 = call i1 @llvm.expect.i1(i1 %not_err3, i1 true) + br i1 %6, label %after_check5, label %assign_optional4 +assign_optional4: ; preds = %noerr_block + store i64 %5, ptr %error_var2, align 8 + br label %guard_block6 +after_check5: ; preds = %noerr_block + br label %noerr_block7 +guard_block6: ; preds = %assign_optional4 + br label %voiderr +noerr_block7: ; preds = %after_check5 + %7 = call i64 @std.io.File.flush(ptr %1) + %not_err9 = icmp eq i64 %7, 0 + %8 = call i1 @llvm.expect.i1(i1 %not_err9, i1 true) + br i1 %8, label %after_check11, label %assign_optional10 +assign_optional10: ; preds = %noerr_block7 + store i64 %7, ptr %error_var8, align 8 + br label %guard_block12 +after_check11: ; preds = %noerr_block7 + br label %noerr_block13 +guard_block12: ; preds = %assign_optional10 + br label %voiderr +noerr_block13: ; preds = %after_check11 + %9 = load i64, ptr %len, align 8 + %add = add i64 %9, 1 + br label %voiderr +voiderr: ; preds = %noerr_block13, %guard_block12, %guard_block6, %guard_block + br label %if.exit14 +if.exit14: ; preds = %voiderr, %end_block + br label %if.exit15 +if.exit15: ; preds = %if.exit14 + br label %after_macro +after_macro: ; preds = %if.exit15 + ret i32 0 +} diff --git a/test/test_suite7/assignment/alignment_index.c3t b/test/test_suite7/assignment/alignment_index.c3t new file mode 100644 index 000000000..5674c7b96 --- /dev/null +++ b/test/test_suite7/assignment/alignment_index.c3t @@ -0,0 +1,24 @@ +// #target: windows-x64 +module test; +int[<2>] foo @align(1); + +fn void main() +{ + foo[1] = 2; + foo.y = 4; +} + +/* #expect: test.ll + +@test.foo = local_unnamed_addr global <2 x i32> zeroinitializer, align 1 + +define void @test.main() #0 { +entry: + %0 = load <2 x i32>, ptr @test.foo, align 1 + %elemset = insertelement <2 x i32> %0, i32 2, i64 1 + store <2 x i32> %elemset, ptr @test.foo, align 1 + %1 = load <2 x i32>, ptr @test.foo, align 1 + %elemset1 = insertelement <2 x i32> %1, i32 4, i64 1 + store <2 x i32> %elemset1, ptr @test.foo, align 1 + ret void +} \ No newline at end of file diff --git a/test/test_suite7/assignment/int_assign.c3t b/test/test_suite7/assignment/int_assign.c3t new file mode 100644 index 000000000..a905dece6 --- /dev/null +++ b/test/test_suite7/assignment/int_assign.c3t @@ -0,0 +1,70 @@ +// #target: windows-x64 +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_suite7/assignment/var_variable.c3 b/test/test_suite7/assignment/var_variable.c3 new file mode 100644 index 000000000..89772ea69 --- /dev/null +++ b/test/test_suite7/assignment/var_variable.c3 @@ -0,0 +1,39 @@ +module test; +import std::io; + +macro @foo(;@body) +{ + var i = 1.0; + @body(); +} + +fn void main() +{ + @foo() { int j = 1; }; + @foo() { var j = 1.0; }; // #error: is only allowed inside +} + +fn void test() +{ + var g = 1; // #error: is only allowed inside +} + +macro void test2m() +{ + var h = { 1, 2 }; // #error: cannot be inferred +} + +fn void test2() +{ + test2m(); +} +struct Foo { int a; } +macro void test3m() +{ + var $foo = Foo.membersof; + var h = $foo[0]; // #error: compile time type +} +fn void test3() +{ + test3m(); +} \ No newline at end of file diff --git a/test/test_suite7/attributes/attr_link_err.c3 b/test/test_suite7/attributes/attr_link_err.c3 new file mode 100644 index 000000000..4f56a61b2 --- /dev/null +++ b/test/test_suite7/attributes/attr_link_err.c3 @@ -0,0 +1,22 @@ +fn void test(int x) @link(true, "abc", "cde") +{ +} + +fn void testc(int x) @link("abc", "cde") +{ +} + +fn void test2(int x) @link(true) // #error: Expected a constant string here +{ +} +fn void test3(int x) @link(true, 2) // #error: Expected a constant string here +{ +} + +fn void test4(int x) @link("a", 2) // #error: Expected a constant string here +{ +} + +fn void test5(int x) @link(true, "a", 5, 5) // #error: Expected a constant string here +{ +} diff --git a/test/test_suite7/attributes/attr_not_imported.c3 b/test/test_suite7/attributes/attr_not_imported.c3 new file mode 100644 index 000000000..d8aba13d9 --- /dev/null +++ b/test/test_suite7/attributes/attr_not_imported.c3 @@ -0,0 +1,7 @@ +module abc; + +def @Foo = { @inline }; + +module bar; + +fn void test() abc::@Foo {} // #error: Did you mean the attribute diff --git a/test/test_suite7/attributes/attribute_params.c3 b/test/test_suite7/attributes/attribute_params.c3 new file mode 100644 index 000000000..dbad2720e --- /dev/null +++ b/test/test_suite7/attributes/attribute_params.c3 @@ -0,0 +1,7 @@ +def @Foo() = { @inline }; // #error: At least one parameter was expected +def @Bar = { @inline }; + +fn void test1() @Foo { } +fn void test2() @Foo() { } // #error: An expression was +fn void test3() @Bar { } +fn void test4() @Bar() { } // #error: An expression was \ No newline at end of file diff --git a/test/test_suite7/attributes/attribute_path.c3 b/test/test_suite7/attributes/attribute_path.c3 new file mode 100644 index 000000000..17783fb31 --- /dev/null +++ b/test/test_suite7/attributes/attribute_path.c3 @@ -0,0 +1,4 @@ +fn void test() abc::@inline // #error: Only user-defined attribute names +{ + +} \ No newline at end of file diff --git a/test/test_suite7/attributes/attribute_visibility.c3t b/test/test_suite7/attributes/attribute_visibility.c3t new file mode 100644 index 000000000..14e9ee109 --- /dev/null +++ b/test/test_suite7/attributes/attribute_visibility.c3t @@ -0,0 +1,12 @@ +// #target: macos-x64 +module test; +const int FOO @private = 4; +def @Align(x) = { @align(x * FOO) }; + +module test2; +import test; +int black @Align(16) = 123; + +/* #expect: test2.ll + +@test2.black = local_unnamed_addr global i32 123, align 64 \ No newline at end of file diff --git a/test/test_suite7/attributes/attributes_repeat_param.c3t b/test/test_suite7/attributes/attributes_repeat_param.c3t new file mode 100644 index 000000000..9c3ea7915 --- /dev/null +++ b/test/test_suite7/attributes/attributes_repeat_param.c3t @@ -0,0 +1,26 @@ +// #target: macos-aarch64 +module test; + +def @Test(x) = { @extern("Foo" +++ x) }; + +fn void hello_world() @Test("Megaman") +{} + +fn void ello_world() @Test("Pegasus") +{} + +fn int main() +{ + hello_world(); + ello_world(); + return 0; +} + +/* #expect: test.ll + +define i32 @main() #0 { +entry: + call void @FooMegaman() + call void @FooPegasus() + ret i32 0 +} diff --git a/test/test_suite7/attributes/call_attribute_error_eos.c3 b/test/test_suite7/attributes/call_attribute_error_eos.c3 new file mode 100644 index 000000000..4f610fde6 --- /dev/null +++ b/test/test_suite7/attributes/call_attribute_error_eos.c3 @@ -0,0 +1,5 @@ +fn void main() +{ + call() // #error: ';' + rl::bar(); +} \ No newline at end of file diff --git a/test/test_suite7/attributes/recursive_attributes.c3 b/test/test_suite7/attributes/recursive_attributes.c3 new file mode 100644 index 000000000..bba90fcf1 --- /dev/null +++ b/test/test_suite7/attributes/recursive_attributes.c3 @@ -0,0 +1,17 @@ +module test; + +def @Align(y) = { @Align16(y / 2) }; +def @Align16(x) = { @align(4) @Align(8 * x) }; // #error: Recursive declaration of attribute +def @Test = { @noinline }; +struct Foo +{ + int z; + int xy @Align16(8); +} + +Foo f; + +fn void testme() @Test +{ + int x; +} diff --git a/test/test_suite7/attributes/user_defined_attributes.c3t b/test/test_suite7/attributes/user_defined_attributes.c3t new file mode 100644 index 000000000..e69aa7ae1 --- /dev/null +++ b/test/test_suite7/attributes/user_defined_attributes.c3t @@ -0,0 +1,59 @@ +// #target: macos-x64 + +module test; + +def @Foo = { @noreturn @weak }; + +def @Align(y) = { @align(y) }; +def @Align16(x) = { @Align(8 * x) @align(1024) } @private; +def @Test = { @noinline }; +def @TestZero = { }; +struct Foo +{ + int z; + int xy @Align16(8); +} + +Foo f; + +fn void testme2() @Foo +{} + +fn void testme() @Test +{ + int x; +} + +fn void main() @TestZero +{ + testme(); +} + +/* #expect: test.ll + +%Foo = type { i32, [1020 x i8], i32, [1020 x i8] } + +@"$ct.test.Foo" = linkonce global %.introspect { i8 10, i64 0, ptr null, i64 2048, i64 0, i64 2, [0 x i64] zeroinitializer }, align 8 +@test.f = local_unnamed_addr global %Foo zeroinitializer, align 1024 + +define weak void @test.testme2() #0 { +entry: + ret void +} + +define void @test.testme() #1 { +entry: + %x = alloca i32, align 4 + store i32 0, ptr %x, align 4 + ret void +} + +define void @test.main() #2 { +entry: + call void @test.testme() + ret void +} + +attributes #0 = { noreturn nounwind uwtable "no-trapping-math"="true" "stack-protector-buffer-size"="8" } +attributes #1 = { noinline nounwind uwtable "no-trapping-math"="true" "stack-protector-buffer-size"="8" } +attributes #2 = { nounwind uwtable "no-trapping-math"="true" "stack-protector-buffer-size"="8" } diff --git a/test/test_suite7/attributes/wasm_import.c3t b/test/test_suite7/attributes/wasm_import.c3t new file mode 100644 index 000000000..7c96caa95 --- /dev/null +++ b/test/test_suite7/attributes/wasm_import.c3t @@ -0,0 +1,8 @@ +// #target: wasm32 +module test; +extern fn void test() @wasm("hello", "world"); + +/* #expect: test.ll + +declare void @world() #0 +attributes #0 = { nounwind uwtable "no-trapping-math"="true" "stack-protector-buffer-size"="8" "wasm-export-name"="world" "wasm-import-module"="hello" "wasm-import-name"="world" } \ No newline at end of file diff --git a/test/test_suite7/attributes/wasm_module.c3 b/test/test_suite7/attributes/wasm_module.c3 new file mode 100644 index 000000000..d7307f047 --- /dev/null +++ b/test/test_suite7/attributes/wasm_module.c3 @@ -0,0 +1,5 @@ + +fn void test() @wasm("hello", "world") { } // #error: Specifying a wasm import module +extern fn void test2() @wasm("a", "b", "c"); // #error: Too many arguments to +extern fn void test3() @extern("hello") @wasm("a"); // #error: An external name +extern fn void test4() @extern("hello") @wasm("a", "b"); // #error: An external name \ No newline at end of file diff --git a/test/test_suite7/bitstruct/address_of_bitstruct.c3 b/test/test_suite7/bitstruct/address_of_bitstruct.c3 new file mode 100644 index 000000000..7fe1d41ba --- /dev/null +++ b/test/test_suite7/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_suite7/bitstruct/anon_bitstruct_name_overlap.c3 b/test/test_suite7/bitstruct/anon_bitstruct_name_overlap.c3 new file mode 100644 index 000000000..6390fb585 --- /dev/null +++ b/test/test_suite7/bitstruct/anon_bitstruct_name_overlap.c3 @@ -0,0 +1,24 @@ +import std::io; + +struct Test { +ushort a; + bitstruct : ushort @overlap { + ushort ab : 0..15; + char a : 8..15; // #error: Duplicate member name 'a' + char b : 0..7; + bool c : 7; + bool d : 6; + bool e : 5; + bool f : 4; + } +} + +fn void main() { + io::printfn("Weird structs :P"); + + Test test; + test.ab = 0xAFBA; + + io::printfn("%02x %02x -> %04x\n", test.a, test.b, test.ab); + io::printfn("%x %x %x %x\n", test.c, test.d, test.e, test.f); +} \ No newline at end of file diff --git a/test/test_suite7/bitstruct/array_with_boolean.c3t b/test/test_suite7/bitstruct/array_with_boolean.c3t new file mode 100644 index 000000000..8119b806f --- /dev/null +++ b/test/test_suite7/bitstruct/array_with_boolean.c3t @@ -0,0 +1,69 @@ +// #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 = load i8, ptr %xx, align 1 + %zext = zext i8 %0 to i32 + %shl = shl i32 %zext, 29 + %ashr = ashr i32 %shl, 29 + %1 = load i8, ptr %xx, align 1 + %zext1 = zext i8 %1 to i32 + %lshrl = lshr i32 %zext1, 3 + %ptradd = getelementptr inbounds i8, ptr %xx, i64 1 + %2 = load i8, ptr %ptradd, align 1 + %zext2 = zext i8 %2 to i32 + %shl3 = shl i32 %zext2, 5 + %3 = or i32 %shl3, %lshrl + %shl4 = shl i32 %3, 26 + %ashr5 = ashr i32 %shl4, 26 + %ptradd6 = getelementptr inbounds i8, ptr %xx, i64 1 + %4 = load i8, ptr %ptradd6, align 1 + %zext7 = zext i8 %4 to i32 + %lshrl8 = lshr i32 %zext7, 1 + %ptradd9 = getelementptr inbounds i8, ptr %xx, i64 2 + %5 = load i8, ptr %ptradd9, align 1 + %zext10 = zext i8 %5 to i32 + %shl11 = shl i32 %zext10, 7 + %6 = or i32 %shl11, %lshrl8 + %shl12 = shl i32 %6, 22 + %ashr13 = ashr i32 %shl12, 22 + %ptradd14 = getelementptr inbounds i8, ptr %xx, i64 2 + %7 = load i8, ptr %ptradd14, align 1 + %lshrl15 = lshr i8 %7, 3 + %8 = trunc i8 %lshrl15 to i1 + %zext16 = zext i1 %8 to i32 + %ptradd17 = getelementptr inbounds i8, ptr %xx, i64 2 + %9 = load i8, ptr %ptradd17, align 1 + %lshrl18 = lshr i8 %9, 4 + %10 = trunc i8 %lshrl18 to i1 + %zext19 = zext i1 %10 to i32 + call void (ptr, ...) @printf(ptr @.str, i32 %ashr, i32 %ashr5, i32 %ashr13, i32 %zext16, i32 %zext19) + ret void +} \ No newline at end of file diff --git a/test/test_suite7/bitstruct/bistruct_cast_wrong_size.c3 b/test/test_suite7/bitstruct/bistruct_cast_wrong_size.c3 new file mode 100644 index 000000000..27b1e34c7 --- /dev/null +++ b/test/test_suite7/bitstruct/bistruct_cast_wrong_size.c3 @@ -0,0 +1,14 @@ +module bug_repro; + +bitstruct Edge_Flags : char { + bool left; + bool top; + bool right; + bool bottom; +} + +fn int main() { + Edge_Flags edges; + Edge_Flags a = edges & (Edge_Flags)(1 << 0); // #error: 'int' + return 0; +} \ No newline at end of file diff --git a/test/test_suite7/bitstruct/bitfield_access.c3t b/test/test_suite7/bitstruct/bitfield_access.c3t new file mode 100644 index 000000000..22962cf06 --- /dev/null +++ b/test/test_suite7/bitstruct/bitfield_access.c3t @@ -0,0 +1,173 @@ +// #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 = load i8, ptr %e1, align 1 + %zext = zext i8 %0 to i32 + %shl = shl i32 %zext, 29 + %ashr = ashr i32 %shl, 29 + call void (ptr, ...) @printf(ptr @.str, i32 %ashr) + %1 = load i8, ptr %e2, align 1 + %zext1 = zext i8 %1 to i32 + %shl2 = shl i32 %zext1, 29 + %ashr3 = ashr i32 %shl2, 29 + call void (ptr, ...) @printf(ptr @.str.1, i32 %ashr3) + %2 = load i8, ptr %e3, align 1 + %zext4 = zext i8 %2 to i32 + %shl5 = shl i32 %zext4, 29 + %ashr6 = ashr i32 %shl5, 29 + call void (ptr, ...) @printf(ptr @.str.2, i32 %ashr6) + 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 + %3 = load i8, ptr %z1, align 1 + %zext7 = zext i8 %3 to i32 + %4 = and i32 7, %zext7 + call void (ptr, ...) @printf(ptr @.str.3, i32 %4) + %5 = load i8, ptr %z2, align 1 + %zext8 = zext i8 %5 to i32 + %6 = and i32 7, %zext8 + call void (ptr, ...) @printf(ptr @.str.4, i32 %6) + %7 = load i8, ptr %z3, align 1 + %zext9 = zext i8 %7 to i32 + %8 = and i32 7, %zext9 + call void (ptr, ...) @printf(ptr @.str.5, i32 %8) + store [5 x i8] c"\00G\02\00\00", ptr %xx, align 1 + %9 = load i8, ptr %xx, align 1 + %zext10 = zext i8 %9 to i32 + %lshrl = lshr i32 %zext10, 5 + %ptradd = getelementptr inbounds i8, ptr %xx, i64 1 + %10 = load i8, ptr %ptradd, align 1 + %zext11 = zext i8 %10 to i32 + %shl12 = shl i32 %zext11, 3 + %11 = or i32 %shl12, %lshrl + %ptradd13 = getelementptr inbounds i8, ptr %xx, i64 2 + %12 = load i8, ptr %ptradd13, align 1 + %zext14 = zext i8 %12 to i32 + %shl15 = shl i32 %zext14, 11 + %13 = or i32 %shl15, %11 + %14 = and i32 262143, %13 + call void (ptr, ...) @printf(ptr @.str.6, i32 %14) + ret void +} \ No newline at end of file diff --git a/test/test_suite7/bitstruct/bitstruct_access_signed.c3t b/test/test_suite7/bitstruct/bitstruct_access_signed.c3t new file mode 100644 index 000000000..5c3423e09 --- /dev/null +++ b/test/test_suite7/bitstruct/bitstruct_access_signed.c3t @@ -0,0 +1,88 @@ +// #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 = load i8, ptr %xx, align 1 + %zext = zext i8 %0 to i32 + %lshrl = lshr i32 %zext, 5 + %ptradd = getelementptr inbounds i8, ptr %xx, i64 1 + %1 = load i8, ptr %ptradd, align 1 + %zext1 = zext i8 %1 to i32 + %shl = shl i32 %zext1, 3 + %2 = or i32 %shl, %lshrl + %ptradd2 = getelementptr inbounds i8, ptr %xx, i64 2 + %3 = load i8, ptr %ptradd2, align 1 + %zext3 = zext i8 %3 to i32 + %shl4 = shl i32 %zext3, 11 + %4 = or i32 %shl4, %2 + %shl5 = shl i32 %4, 14 + %ashr = ashr i32 %shl5, 14 + call void (ptr, ...) @printf(ptr @.str, i32 %ashr) + store [3 x i8] c"\FF\FD\FF", ptr %xx, align 1 + %5 = load i8, ptr %xx, align 1 + %zext6 = zext i8 %5 to i32 + %lshrl7 = lshr i32 %zext6, 5 + %ptradd8 = getelementptr inbounds i8, ptr %xx, i64 1 + %6 = load i8, ptr %ptradd8, align 1 + %zext9 = zext i8 %6 to i32 + %shl10 = shl i32 %zext9, 3 + %7 = or i32 %shl10, %lshrl7 + %ptradd11 = getelementptr inbounds i8, ptr %xx, i64 2 + %8 = load i8, ptr %ptradd11, align 1 + %zext12 = zext i8 %8 to i32 + %shl13 = shl i32 %zext12, 11 + %9 = or i32 %shl13, %7 + %shl14 = shl i32 %9, 14 + %ashr15 = ashr i32 %shl14, 14 + call void (ptr, ...) @printf(ptr @.str.1, i32 %ashr15) + store [3 x i8] c"\1F\CF\AA", ptr %xxu, align 1 + %10 = load i8, ptr %xxu, align 1 + %zext16 = zext i8 %10 to i32 + %lshrl17 = lshr i32 %zext16, 5 + %ptradd18 = getelementptr inbounds i8, ptr %xxu, i64 1 + %11 = load i8, ptr %ptradd18, align 1 + %zext19 = zext i8 %11 to i32 + %shl20 = shl i32 %zext19, 3 + %12 = or i32 %shl20, %lshrl17 + %ptradd21 = getelementptr inbounds i8, ptr %xxu, i64 2 + %13 = load i8, ptr %ptradd21, align 1 + %zext22 = zext i8 %13 to i32 + %shl23 = shl i32 %zext22, 11 + %14 = or i32 %shl23, %12 + %15 = and i32 262143, %14 + call void (ptr, ...) @printf(ptr @.str.2, i32 %15) + ret void +} diff --git a/test/test_suite7/bitstruct/bitstruct_align.c3t b/test/test_suite7/bitstruct/bitstruct_align.c3t new file mode 100644 index 000000000..67e353273 --- /dev/null +++ b/test/test_suite7/bitstruct/bitstruct_align.c3t @@ -0,0 +1,40 @@ +// #target: macos-x64 +module test; +import std::io; + +Foo y; +bitstruct Foo : ushort @align(1) +{ + int a : 0..10; +} +fn int main(String[] args) +{ + Foo z = y; + Foo* y = &z; + y.a = 123; + return 0; +} + +/* #expect: test.ll + +@test.y = local_unnamed_addr global i16 0, align 1 + +define i32 @test.main(ptr %0, i64 %1) #0 { +entry: + %args = alloca %"char[][]", align 8 + %z = alloca i16, align 1 + %y = alloca ptr, align 8 + store ptr %0, ptr %args, align 8 + %ptradd = getelementptr inbounds i8, ptr %args, i64 8 + store i64 %1, ptr %ptradd, align 8 + %2 = load i16, ptr @test.y, align 1 + store i16 %2, ptr %z, align 1 + store ptr %z, ptr %y, align 8 + %3 = load ptr, ptr %y, align 8 + %4 = load i16, ptr %3, align 1 + %5 = and i16 %4, -2048 + %6 = or i16 %5, 123 + store i16 %6, ptr %3, align 1 + ret i32 0 +} + diff --git a/test/test_suite7/bitstruct/bitstruct_anon_in_struct_ok.c3t b/test/test_suite7/bitstruct/bitstruct_anon_in_struct_ok.c3t new file mode 100644 index 000000000..cf79b500c --- /dev/null +++ b/test/test_suite7/bitstruct/bitstruct_anon_in_struct_ok.c3t @@ -0,0 +1,119 @@ +// #target: macos-x64 +module foo; +import std::io; + +struct Test { +ushort afff; + bitstruct : ushort @overlap { + ushort ab : 0..15; + char a : 8..15; + char b : 0..7; + bool c : 7; + bool d : 6; + bool e : 5; + bool f : 4; + } +} + +fn void main() { + + + Test test; + test.ab = 0xAFBA; + + io::printfn("%02x %02x -> %04x\n", test.a, test.b, test.ab); + io::printfn("%x %x %x %x\n", test.c, test.d, test.e, test.f); +} + +/* #expect: foo.ll + + +define void @foo.main() #0 { +entry: + %test = alloca %Test, align 2 + %varargslots = alloca [3 x %any], align 16 + %taddr = alloca i8, align 1 + %taddr5 = alloca i8, align 1 + %taddr8 = alloca i16, align 2 + %retparam = alloca i64, align 8 + %varargslots10 = alloca [4 x %any], align 16 + %taddr14 = alloca i8, align 1 + %taddr18 = alloca i8, align 1 + %taddr23 = alloca i8, align 1 + %taddr28 = alloca i8, align 1 + %retparam30 = alloca i64, align 8 + store i16 0, ptr %test, align 2 + %ptradd = getelementptr inbounds i8, ptr %test, i64 2 + store i16 0, ptr %ptradd, align 2 + %ptradd1 = getelementptr inbounds i8, ptr %test, i64 2 + %0 = load i16, ptr %ptradd1, align 2 + store i16 -20550, ptr %ptradd1, align 2 + %ptradd2 = getelementptr inbounds i8, ptr %test, i64 2 + %1 = load i16, ptr %ptradd2, align 2 + %lshrl = lshr i16 %1, 8 + %2 = and i16 255, %lshrl + %trunc = trunc i16 %2 to i8 + store i8 %trunc, ptr %taddr, align 1 + %3 = insertvalue %any undef, ptr %taddr, 0 + %4 = insertvalue %any %3, i64 ptrtoint (ptr @"$ct.char" to i64), 1 + store %any %4, ptr %varargslots, align 16 + %ptradd3 = getelementptr inbounds i8, ptr %test, i64 2 + %5 = load i16, ptr %ptradd3, align 2 + %6 = and i16 255, %5 + %trunc4 = trunc i16 %6 to i8 + store i8 %trunc4, ptr %taddr5, align 1 + %7 = insertvalue %any undef, ptr %taddr5, 0 + %8 = insertvalue %any %7, i64 ptrtoint (ptr @"$ct.char" to i64), 1 + %ptradd6 = getelementptr inbounds i8, ptr %varargslots, i64 16 + store %any %8, ptr %ptradd6, align 16 + %ptradd7 = getelementptr inbounds i8, ptr %test, i64 2 + %9 = load i16, ptr %ptradd7, align 2 + store i16 %9, ptr %taddr8, align 2 + %10 = insertvalue %any undef, ptr %taddr8, 0 + %11 = insertvalue %any %10, i64 ptrtoint (ptr @"$ct.ushort" to i64), 1 + %ptradd9 = getelementptr inbounds i8, ptr %varargslots, i64 32 + store %any %11, ptr %ptradd9, align 16 + %12 = call i64 @std.io.printfn(ptr %retparam, ptr @.str, i64 18, ptr %varargslots, i64 3) + %ptradd11 = getelementptr inbounds i8, ptr %test, i64 2 + %13 = load i16, ptr %ptradd11, align 2 + %lshrl12 = lshr i16 %13, 7 + %14 = and i16 1, %lshrl12 + %trunc13 = trunc i16 %14 to i8 + store i8 %trunc13, ptr %taddr14, align 1 + %15 = insertvalue %any undef, ptr %taddr14, 0 + %16 = insertvalue %any %15, i64 ptrtoint (ptr @"$ct.bool" to i64), 1 + store %any %16, ptr %varargslots10, align 16 + %ptradd15 = getelementptr inbounds i8, ptr %test, i64 2 + %17 = load i16, ptr %ptradd15, align 2 + %lshrl16 = lshr i16 %17, 6 + %18 = and i16 1, %lshrl16 + %trunc17 = trunc i16 %18 to i8 + store i8 %trunc17, ptr %taddr18, align 1 + %19 = insertvalue %any undef, ptr %taddr18, 0 + %20 = insertvalue %any %19, i64 ptrtoint (ptr @"$ct.bool" to i64), 1 + %ptradd19 = getelementptr inbounds i8, ptr %varargslots10, i64 16 + store %any %20, ptr %ptradd19, align 16 + %ptradd20 = getelementptr inbounds i8, ptr %test, i64 2 + %21 = load i16, ptr %ptradd20, align 2 + %lshrl21 = lshr i16 %21, 5 + %22 = and i16 1, %lshrl21 + %trunc22 = trunc i16 %22 to i8 + store i8 %trunc22, ptr %taddr23, align 1 + %23 = insertvalue %any undef, ptr %taddr23, 0 + %24 = insertvalue %any %23, i64 ptrtoint (ptr @"$ct.bool" to i64), 1 + %ptradd24 = getelementptr inbounds i8, ptr %varargslots10, i64 32 + store %any %24, ptr %ptradd24, align 16 + %ptradd25 = getelementptr inbounds i8, ptr %test, i64 2 + %25 = load i16, ptr %ptradd25, align 2 + %lshrl26 = lshr i16 %25, 4 + %26 = and i16 1, %lshrl26 + %trunc27 = trunc i16 %26 to i8 + store i8 %trunc27, ptr %taddr28, align 1 + %27 = insertvalue %any undef, ptr %taddr28, 0 + %28 = insertvalue %any %27, i64 ptrtoint (ptr @"$ct.bool" to i64), 1 + %ptradd29 = getelementptr inbounds i8, ptr %varargslots10, i64 48 + store %any %28, ptr %ptradd29, align 16 + %29 = call i64 @std.io.printfn(ptr %retparam30, ptr @.str.1, i64 12, ptr %varargslots10, i64 4) + ret void +} + diff --git a/test/test_suite7/bitstruct/bitstruct_arrays.c3t b/test/test_suite7/bitstruct/bitstruct_arrays.c3t new file mode 100644 index 000000000..afc4f346b --- /dev/null +++ b/test/test_suite7/bitstruct/bitstruct_arrays.c3t @@ -0,0 +1,1069 @@ +// #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.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 + %shl = shl i64 %3, 61 + %ashr = ashr i64 %shl, 61 + %trunc = trunc i64 %ashr to i32 + %4 = load i64, ptr %xx, align 8 + %shl1 = shl i64 %4, 55 + %ashr2 = ashr i64 %shl1, 58 + %trunc3 = trunc i64 %ashr2 to i32 + call void (ptr, ...) @printf(ptr @.str, i32 %trunc, i32 %trunc3) + %5 = load i64, ptr %xx, align 8 + %shl4 = shl i64 %5, 61 + %ashr5 = ashr i64 %shl4, 61 + %trunc6 = trunc i64 %ashr5 to i32 + %sub = sub i32 %trunc6, 1 + %6 = load i64, ptr %xx, align 8 + %zext = zext i32 %sub to i64 + %7 = and i64 %zext, 7 + %8 = and i64 %6, -8 + %9 = or i64 %8, %7 + store i64 %9, ptr %xx, align 8 + %10 = load i64, ptr %xx, align 8 + %shl7 = shl i64 %10, 61 + %ashr8 = ashr i64 %shl7, 61 + %trunc9 = trunc i64 %ashr8 to i32 + %11 = load i64, ptr %xx, align 8 + %shl10 = shl i64 %11, 55 + %ashr11 = ashr i64 %shl10, 58 + %trunc12 = trunc i64 %ashr11 to i32 + call void (ptr, ...) @printf(ptr @.str.1, i32 %trunc9, i32 %trunc12) + %12 = load i64, ptr %xx, align 8 + %shl13 = shl i64 %12, 55 + %ashr14 = ashr i64 %shl13, 58 + %trunc15 = trunc i64 %ashr14 to i32 + %mul = mul i32 %trunc15, 2 + %13 = load i64, ptr %xx, align 8 + %zext16 = zext i32 %mul to i64 + %shl17 = shl i64 %zext16, 3 + %14 = and i64 %shl17, 504 + %15 = and i64 %13, -505 + %16 = or i64 %15, %14 + store i64 %16, ptr %xx, align 8 + %17 = load i64, ptr %xx, align 8 + %shl18 = shl i64 %17, 61 + %ashr19 = ashr i64 %shl18, 61 + %trunc20 = trunc i64 %ashr19 to i32 + %18 = load i64, ptr %xx, align 8 + %shl21 = shl i64 %18, 55 + %ashr22 = ashr i64 %shl21, 58 + %trunc23 = trunc i64 %ashr22 to i32 + call void (ptr, ...) @printf(ptr @.str.2, i32 %trunc20, i32 %trunc23) + %19 = load i64, ptr %xx, align 8 + %shl24 = shl i64 %19, 55 + %ashr25 = ashr i64 %shl24, 58 + %trunc26 = trunc i64 %ashr25 to i32 + %xor = xor i32 %trunc26, 4 + %20 = load i64, ptr %xx, align 8 + %zext27 = zext i32 %xor to i64 + %shl28 = shl i64 %zext27, 3 + %21 = and i64 %shl28, 504 + %22 = and i64 %20, -505 + %23 = or i64 %22, %21 + store i64 %23, ptr %xx, align 8 + %24 = load i64, ptr %xx, align 8 + %shl29 = shl i64 %24, 61 + %ashr30 = ashr i64 %shl29, 61 + %trunc31 = trunc i64 %ashr30 to i32 + %25 = load i64, ptr %xx, align 8 + %shl32 = shl i64 %25, 55 + %ashr33 = ashr i64 %shl32, 58 + %trunc34 = trunc i64 %ashr33 to i32 + call void (ptr, ...) @printf(ptr @.str.3, i32 %trunc31, i32 %trunc34) + %26 = load i64, ptr %xx, align 8 + %shl35 = shl i64 %26, 55 + %ashr36 = ashr i64 %shl35, 58 + %trunc37 = trunc i64 %ashr36 to i32 + %or = or i32 %trunc37, 4 + %27 = load i64, ptr %xx, align 8 + %zext38 = zext i32 %or to i64 + %shl39 = shl i64 %zext38, 3 + %28 = and i64 %shl39, 504 + %29 = and i64 %27, -505 + %30 = or i64 %29, %28 + store i64 %30, ptr %xx, align 8 + %31 = load i64, ptr %xx, align 8 + %shl40 = shl i64 %31, 61 + %ashr41 = ashr i64 %shl40, 61 + %trunc42 = trunc i64 %ashr41 to i32 + %32 = load i64, ptr %xx, align 8 + %shl43 = shl i64 %32, 55 + %ashr44 = ashr i64 %shl43, 58 + %trunc45 = trunc i64 %ashr44 to i32 + call void (ptr, ...) @printf(ptr @.str.4, i32 %trunc42, i32 %trunc45) + %33 = load i64, ptr %xx, align 8 + %shl46 = shl i64 %33, 55 + %ashr47 = ashr i64 %shl46, 58 + %trunc48 = trunc i64 %ashr47 to i32 + %shl49 = shl i32 %trunc48, 1 + %34 = freeze i32 %shl49 + %35 = load i64, ptr %xx, align 8 + %zext50 = zext i32 %34 to i64 + %shl51 = shl i64 %zext50, 3 + %36 = and i64 %shl51, 504 + %37 = and i64 %35, -505 + %38 = or i64 %37, %36 + store i64 %38, ptr %xx, align 8 + %39 = load i64, ptr %xx, align 8 + %shl52 = shl i64 %39, 61 + %ashr53 = ashr i64 %shl52, 61 + %trunc54 = trunc i64 %ashr53 to i32 + %40 = load i64, ptr %xx, align 8 + %shl55 = shl i64 %40, 55 + %ashr56 = ashr i64 %shl55, 58 + %trunc57 = trunc i64 %ashr56 to i32 + call void (ptr, ...) @printf(ptr @.str.5, i32 %trunc54, i32 %trunc57) + %41 = load i64, ptr %xx, align 8 + %shl58 = shl i64 %41, 55 + %ashr59 = ashr i64 %shl58, 58 + %trunc60 = trunc i64 %ashr59 to i32 + %ashr61 = ashr i32 %trunc60, 1 + %42 = freeze i32 %ashr61 + %43 = load i64, ptr %xx, align 8 + %zext62 = zext i32 %42 to i64 + %shl63 = shl i64 %zext62, 3 + %44 = and i64 %shl63, 504 + %45 = and i64 %43, -505 + %46 = or i64 %45, %44 + store i64 %46, ptr %xx, align 8 + %47 = load i64, ptr %xx, align 8 + %shl64 = shl i64 %47, 61 + %ashr65 = ashr i64 %shl64, 61 + %trunc66 = trunc i64 %ashr65 to i32 + %48 = load i64, ptr %xx, align 8 + %shl67 = shl i64 %48, 55 + %ashr68 = ashr i64 %shl67, 58 + %trunc69 = trunc i64 %ashr68 to i32 + call void (ptr, ...) @printf(ptr @.str.6, i32 %trunc66, i32 %trunc69) + %49 = load i64, ptr %xx, align 8 + %shl70 = shl i64 %49, 55 + %ashr71 = ashr i64 %shl70, 58 + %trunc72 = trunc i64 %ashr71 to i32 + %sdiv = sdiv i32 %trunc72, 2 + %50 = load i64, ptr %xx, align 8 + %zext73 = zext i32 %sdiv to i64 + %shl74 = shl i64 %zext73, 3 + %51 = and i64 %shl74, 504 + %52 = and i64 %50, -505 + %53 = or i64 %52, %51 + store i64 %53, ptr %xx, align 8 + %54 = load i64, ptr %xx, align 8 + %shl75 = shl i64 %54, 61 + %ashr76 = ashr i64 %shl75, 61 + %trunc77 = trunc i64 %ashr76 to i32 + %55 = load i64, ptr %xx, align 8 + %shl78 = shl i64 %55, 55 + %ashr79 = ashr i64 %shl78, 58 + %trunc80 = trunc i64 %ashr79 to i32 + call void (ptr, ...) @printf(ptr @.str.7, i32 %trunc77, i32 %trunc80) + %56 = load i64, ptr %xx, align 8 + %shl81 = shl i64 %56, 55 + %ashr82 = ashr i64 %shl81, 58 + %trunc83 = trunc i64 %ashr82 to i32 + %smod = srem i32 %trunc83, 2 + %57 = load i64, ptr %xx, align 8 + %zext84 = zext i32 %smod to i64 + %shl85 = shl i64 %zext84, 3 + %58 = and i64 %shl85, 504 + %59 = and i64 %57, -505 + %60 = or i64 %59, %58 + store i64 %60, ptr %xx, align 8 + %61 = load i64, ptr %xx, align 8 + %shl86 = shl i64 %61, 61 + %ashr87 = ashr i64 %shl86, 61 + %trunc88 = trunc i64 %ashr87 to i32 + %62 = load i64, ptr %xx, align 8 + %shl89 = shl i64 %62, 55 + %ashr90 = ashr i64 %shl89, 58 + %trunc91 = trunc i64 %ashr90 to i32 + call void (ptr, ...) @printf(ptr @.str.8, i32 %trunc88, i32 %trunc91) + %63 = load i64, ptr %xx, align 8 + %64 = and i64 %63, -1048577 + %65 = or i64 %64, 1048576 + store i64 %65, ptr %xx, align 8 + %66 = load i64, ptr %xx, align 8 + %lshrl = lshr i64 %66, 20 + %67 = and i64 1, %lshrl + %trunc92 = trunc i64 %67 to i8 + %68 = trunc i8 %trunc92 to i1 + %zext93 = zext i1 %68 to i32 + call void (ptr, ...) @printf(ptr @.str.9, i32 %zext93) + %69 = load i64, ptr %xx, align 8 + %70 = and i64 %69, -1048577 + store i64 %70, ptr %xx, align 8 + %71 = load i64, ptr %xx, align 8 + %lshrl94 = lshr i64 %71, 20 + %72 = and i64 1, %lshrl94 + %trunc95 = trunc i64 %72 to i8 + %73 = trunc i8 %trunc95 to i1 + %zext96 = zext i1 %73 to i32 + call void (ptr, ...) @printf(ptr @.str.10, i32 %zext96) + ret void +} + +; Function Attrs: +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 = load i8, ptr %xx, align 1 + %1 = and i8 %0, -8 + %2 = or i8 %1, 3 + store i8 %1, ptr %xx, align 1 + %3 = load i8, ptr %xx, align 1 + %zext = zext i8 %3 to i32 + %shl = shl i32 %zext, 29 + %ashr = ashr i32 %shl, 29 + %4 = load i8, ptr %xx, align 1 + %zext1 = zext i8 %4 to i32 + %lshrl = lshr i32 %zext1, 3 + %ptradd = getelementptr inbounds i8, ptr %xx, i64 1 + %5 = load i8, ptr %ptradd, align 1 + %zext2 = zext i8 %5 to i32 + %shl3 = shl i32 %zext2, 5 + %6 = or i32 %shl3, %lshrl + %shl4 = shl i32 %6, 26 + %ashr5 = ashr i32 %shl4, 26 + call void (ptr, ...) @printf(ptr @.str.11, i32 %ashr, i32 %ashr5) + %7 = load i8, ptr %xx, align 1 + %zext6 = zext i8 %7 to i32 + %shl7 = shl i32 %zext6, 29 + %ashr8 = ashr i32 %shl7, 29 + %sub = sub i32 %ashr8, 1 + %trunc = trunc i32 %sub to i8 + %8 = and i8 %trunc, 7 + %9 = load i8, ptr %xx, align 1 + %10 = and i8 %9, -8 + %11 = or i8 %10, %8 + store i8 %10, ptr %xx, align 1 + %12 = load i8, ptr %xx, align 1 + %zext9 = zext i8 %12 to i32 + %shl10 = shl i32 %zext9, 29 + %ashr11 = ashr i32 %shl10, 29 + %13 = load i8, ptr %xx, align 1 + %zext12 = zext i8 %13 to i32 + %lshrl13 = lshr i32 %zext12, 3 + %ptradd14 = getelementptr inbounds i8, ptr %xx, i64 1 + %14 = load i8, ptr %ptradd14, align 1 + %zext15 = zext i8 %14 to i32 + %shl16 = shl i32 %zext15, 5 + %15 = or i32 %shl16, %lshrl13 + %shl17 = shl i32 %15, 26 + %ashr18 = ashr i32 %shl17, 26 + call void (ptr, ...) @printf(ptr @.str.12, i32 %ashr11, i32 %ashr18) + %16 = load i8, ptr %xx, align 1 + %zext19 = zext i8 %16 to i32 + %lshrl20 = lshr i32 %zext19, 3 + %ptradd21 = getelementptr inbounds i8, ptr %xx, i64 1 + %17 = load i8, ptr %ptradd21, align 1 + %zext22 = zext i8 %17 to i32 + %shl23 = shl i32 %zext22, 5 + %18 = or i32 %shl23, %lshrl20 + %shl24 = shl i32 %18, 26 + %ashr25 = ashr i32 %shl24, 26 + %mul = mul i32 %ashr25, 2 + %shl26 = shl i32 %mul, 3 + %trunc27 = trunc i32 %shl26 to i8 + %19 = load i8, ptr %xx, align 1 + %20 = and i8 %19, 7 + %21 = or i8 %20, %trunc27 + store i8 %21, ptr %xx, align 1 + %lshrl28 = lshr i32 %mul, 5 + %ptradd29 = getelementptr inbounds i8, ptr %xx, i64 1 + %trunc30 = trunc i32 %lshrl28 to i8 + %22 = and i8 %trunc30, 1 + %23 = load i8, ptr %ptradd29, align 1 + %24 = and i8 %23, -2 + %25 = or i8 %24, %22 + store i8 %24, ptr %ptradd29, align 1 + %26 = load i8, ptr %xx, align 1 + %zext31 = zext i8 %26 to i32 + %shl32 = shl i32 %zext31, 29 + %ashr33 = ashr i32 %shl32, 29 + %27 = load i8, ptr %xx, align 1 + %zext34 = zext i8 %27 to i32 + %lshrl35 = lshr i32 %zext34, 3 + %ptradd36 = getelementptr inbounds i8, ptr %xx, i64 1 + %28 = load i8, ptr %ptradd36, align 1 + %zext37 = zext i8 %28 to i32 + %shl38 = shl i32 %zext37, 5 + %29 = or i32 %shl38, %lshrl35 + %shl39 = shl i32 %29, 26 + %ashr40 = ashr i32 %shl39, 26 + call void (ptr, ...) @printf(ptr @.str.13, i32 %ashr33, i32 %ashr40) + %30 = load i8, ptr %xx, align 1 + %zext41 = zext i8 %30 to i32 + %lshrl42 = lshr i32 %zext41, 3 + %ptradd43 = getelementptr inbounds i8, ptr %xx, i64 1 + %31 = load i8, ptr %ptradd43, align 1 + %zext44 = zext i8 %31 to i32 + %shl45 = shl i32 %zext44, 5 + %32 = or i32 %shl45, %lshrl42 + %shl46 = shl i32 %32, 26 + %ashr47 = ashr i32 %shl46, 26 + %xor = xor i32 %ashr47, 4 + %shl48 = shl i32 %xor, 3 + %trunc49 = trunc i32 %shl48 to i8 + %33 = load i8, ptr %xx, align 1 + %34 = and i8 %33, 7 + %35 = or i8 %34, %trunc49 + store i8 %35, ptr %xx, align 1 + %lshrl50 = lshr i32 %xor, 5 + %ptradd51 = getelementptr inbounds i8, ptr %xx, i64 1 + %trunc52 = trunc i32 %lshrl50 to i8 + %36 = and i8 %trunc52, 1 + %37 = load i8, ptr %ptradd51, align 1 + %38 = and i8 %37, -2 + %39 = or i8 %38, %36 + store i8 %38, ptr %ptradd51, align 1 + %40 = load i8, ptr %xx, align 1 + %zext53 = zext i8 %40 to i32 + %shl54 = shl i32 %zext53, 29 + %ashr55 = ashr i32 %shl54, 29 + %41 = load i8, ptr %xx, align 1 + %zext56 = zext i8 %41 to i32 + %lshrl57 = lshr i32 %zext56, 3 + %ptradd58 = getelementptr inbounds i8, ptr %xx, i64 1 + %42 = load i8, ptr %ptradd58, align 1 + %zext59 = zext i8 %42 to i32 + %shl60 = shl i32 %zext59, 5 + %43 = or i32 %shl60, %lshrl57 + %shl61 = shl i32 %43, 26 + %ashr62 = ashr i32 %shl61, 26 + call void (ptr, ...) @printf(ptr @.str.14, i32 %ashr55, i32 %ashr62) + %44 = load i8, ptr %xx, align 1 + %zext63 = zext i8 %44 to i32 + %lshrl64 = lshr i32 %zext63, 3 + %ptradd65 = getelementptr inbounds i8, ptr %xx, i64 1 + %45 = load i8, ptr %ptradd65, align 1 + %zext66 = zext i8 %45 to i32 + %shl67 = shl i32 %zext66, 5 + %46 = or i32 %shl67, %lshrl64 + %shl68 = shl i32 %46, 26 + %ashr69 = ashr i32 %shl68, 26 + %or = or i32 %ashr69, 4 + %shl70 = shl i32 %or, 3 + %trunc71 = trunc i32 %shl70 to i8 + %47 = load i8, ptr %xx, align 1 + %48 = and i8 %47, 7 + %49 = or i8 %48, %trunc71 + store i8 %49, ptr %xx, align 1 + %lshrl72 = lshr i32 %or, 5 + %ptradd73 = getelementptr inbounds i8, ptr %xx, i64 1 + %trunc74 = trunc i32 %lshrl72 to i8 + %50 = and i8 %trunc74, 1 + %51 = load i8, ptr %ptradd73, align 1 + %52 = and i8 %51, -2 + %53 = or i8 %52, %50 + store i8 %52, ptr %ptradd73, align 1 + %54 = load i8, ptr %xx, align 1 + %zext75 = zext i8 %54 to i32 + %shl76 = shl i32 %zext75, 29 + %ashr77 = ashr i32 %shl76, 29 + %55 = load i8, ptr %xx, align 1 + %zext78 = zext i8 %55 to i32 + %lshrl79 = lshr i32 %zext78, 3 + %ptradd80 = getelementptr inbounds i8, ptr %xx, i64 1 + %56 = load i8, ptr %ptradd80, align 1 + %zext81 = zext i8 %56 to i32 + %shl82 = shl i32 %zext81, 5 + %57 = or i32 %shl82, %lshrl79 + %shl83 = shl i32 %57, 26 + %ashr84 = ashr i32 %shl83, 26 + call void (ptr, ...) @printf(ptr @.str.15, i32 %ashr77, i32 %ashr84) + %58 = load i8, ptr %xx, align 1 + %zext85 = zext i8 %58 to i32 + %lshrl86 = lshr i32 %zext85, 3 + %ptradd87 = getelementptr inbounds i8, ptr %xx, i64 1 + %59 = load i8, ptr %ptradd87, align 1 + %zext88 = zext i8 %59 to i32 + %shl89 = shl i32 %zext88, 5 + %60 = or i32 %shl89, %lshrl86 + %shl90 = shl i32 %60, 26 + %ashr91 = ashr i32 %shl90, 26 + %shl92 = shl i32 %ashr91, 1 + %61 = freeze i32 %shl92 + %shl93 = shl i32 %61, 3 + %trunc94 = trunc i32 %shl93 to i8 + %62 = load i8, ptr %xx, align 1 + %63 = and i8 %62, 7 + %64 = or i8 %63, %trunc94 + store i8 %64, ptr %xx, align 1 + %lshrl95 = lshr i32 %61, 5 + %ptradd96 = getelementptr inbounds i8, ptr %xx, i64 1 + %trunc97 = trunc i32 %lshrl95 to i8 + %65 = and i8 %trunc97, 1 + %66 = load i8, ptr %ptradd96, align 1 + %67 = and i8 %66, -2 + %68 = or i8 %67, %65 + store i8 %67, ptr %ptradd96, align 1 + %69 = load i8, ptr %xx, align 1 + %zext98 = zext i8 %69 to i32 + %shl99 = shl i32 %zext98, 29 + %ashr100 = ashr i32 %shl99, 29 + %70 = load i8, ptr %xx, align 1 + %zext101 = zext i8 %70 to i32 + %lshrl102 = lshr i32 %zext101, 3 + %ptradd103 = getelementptr inbounds i8, ptr %xx, i64 1 + %71 = load i8, ptr %ptradd103, align 1 + %zext104 = zext i8 %71 to i32 + %shl105 = shl i32 %zext104, 5 + %72 = or i32 %shl105, %lshrl102 + %shl106 = shl i32 %72, 26 + %ashr107 = ashr i32 %shl106, 26 + call void (ptr, ...) @printf(ptr @.str.16, i32 %ashr100, i32 %ashr107) + %73 = load i8, ptr %xx, align 1 + %zext108 = zext i8 %73 to i32 + %lshrl109 = lshr i32 %zext108, 3 + %ptradd110 = getelementptr inbounds i8, ptr %xx, i64 1 + %74 = load i8, ptr %ptradd110, align 1 + %zext111 = zext i8 %74 to i32 + %shl112 = shl i32 %zext111, 5 + %75 = or i32 %shl112, %lshrl109 + %shl113 = shl i32 %75, 26 + %ashr114 = ashr i32 %shl113, 26 + %ashr115 = ashr i32 %ashr114, 1 + %76 = freeze i32 %ashr115 + %shl116 = shl i32 %76, 3 + %trunc117 = trunc i32 %shl116 to i8 + %77 = load i8, ptr %xx, align 1 + %78 = and i8 %77, 7 + %79 = or i8 %78, %trunc117 + store i8 %79, ptr %xx, align 1 + %lshrl118 = lshr i32 %76, 5 + %ptradd119 = getelementptr inbounds i8, ptr %xx, i64 1 + %trunc120 = trunc i32 %lshrl118 to i8 + %80 = and i8 %trunc120, 1 + %81 = load i8, ptr %ptradd119, align 1 + %82 = and i8 %81, -2 + %83 = or i8 %82, %80 + store i8 %82, ptr %ptradd119, align 1 + %84 = load i8, ptr %xx, align 1 + %zext121 = zext i8 %84 to i32 + %shl122 = shl i32 %zext121, 29 + %ashr123 = ashr i32 %shl122, 29 + %85 = load i8, ptr %xx, align 1 + %zext124 = zext i8 %85 to i32 + %lshrl125 = lshr i32 %zext124, 3 + %ptradd126 = getelementptr inbounds i8, ptr %xx, i64 1 + %86 = load i8, ptr %ptradd126, align 1 + %zext127 = zext i8 %86 to i32 + %shl128 = shl i32 %zext127, 5 + %87 = or i32 %shl128, %lshrl125 + %shl129 = shl i32 %87, 26 + %ashr130 = ashr i32 %shl129, 26 + call void (ptr, ...) @printf(ptr @.str.17, i32 %ashr123, i32 %ashr130) + %88 = load i8, ptr %xx, align 1 + %zext131 = zext i8 %88 to i32 + %lshrl132 = lshr i32 %zext131, 3 + %ptradd133 = getelementptr inbounds i8, ptr %xx, i64 1 + %89 = load i8, ptr %ptradd133, align 1 + %zext134 = zext i8 %89 to i32 + %shl135 = shl i32 %zext134, 5 + %90 = or i32 %shl135, %lshrl132 + %shl136 = shl i32 %90, 26 + %ashr137 = ashr i32 %shl136, 26 + %sdiv = sdiv i32 %ashr137, 2 + %shl138 = shl i32 %sdiv, 3 + %trunc139 = trunc i32 %shl138 to i8 + %91 = load i8, ptr %xx, align 1 + %92 = and i8 %91, 7 + %93 = or i8 %92, %trunc139 + store i8 %93, ptr %xx, align 1 + %lshrl140 = lshr i32 %sdiv, 5 + %ptradd141 = getelementptr inbounds i8, ptr %xx, i64 1 + %trunc142 = trunc i32 %lshrl140 to i8 + %94 = and i8 %trunc142, 1 + %95 = load i8, ptr %ptradd141, align 1 + %96 = and i8 %95, -2 + %97 = or i8 %96, %94 + store i8 %96, ptr %ptradd141, align 1 + %98 = load i8, ptr %xx, align 1 + %zext143 = zext i8 %98 to i32 + %shl144 = shl i32 %zext143, 29 + %ashr145 = ashr i32 %shl144, 29 + %99 = load i8, ptr %xx, align 1 + %zext146 = zext i8 %99 to i32 + %lshrl147 = lshr i32 %zext146, 3 + %ptradd148 = getelementptr inbounds i8, ptr %xx, i64 1 + %100 = load i8, ptr %ptradd148, align 1 + %zext149 = zext i8 %100 to i32 + %shl150 = shl i32 %zext149, 5 + %101 = or i32 %shl150, %lshrl147 + %shl151 = shl i32 %101, 26 + %ashr152 = ashr i32 %shl151, 26 + call void (ptr, ...) @printf(ptr @.str.18, i32 %ashr145, i32 %ashr152) + %102 = load i8, ptr %xx, align 1 + %zext153 = zext i8 %102 to i32 + %lshrl154 = lshr i32 %zext153, 3 + %ptradd155 = getelementptr inbounds i8, ptr %xx, i64 1 + %103 = load i8, ptr %ptradd155, align 1 + %zext156 = zext i8 %103 to i32 + %shl157 = shl i32 %zext156, 5 + %104 = or i32 %shl157, %lshrl154 + %shl158 = shl i32 %104, 26 + %ashr159 = ashr i32 %shl158, 26 + %smod = srem i32 %ashr159, 2 + %shl160 = shl i32 %smod, 3 + %trunc161 = trunc i32 %shl160 to i8 + %105 = load i8, ptr %xx, align 1 + %106 = and i8 %105, 7 + %107 = or i8 %106, %trunc161 + store i8 %107, ptr %xx, align 1 + %lshrl162 = lshr i32 %smod, 5 + %ptradd163 = getelementptr inbounds i8, ptr %xx, i64 1 + %trunc164 = trunc i32 %lshrl162 to i8 + %108 = and i8 %trunc164, 1 + %109 = load i8, ptr %ptradd163, align 1 + %110 = and i8 %109, -2 + %111 = or i8 %110, %108 + store i8 %110, ptr %ptradd163, align 1 + %112 = load i8, ptr %xx, align 1 + %zext165 = zext i8 %112 to i32 + %shl166 = shl i32 %zext165, 29 + %ashr167 = ashr i32 %shl166, 29 + %113 = load i8, ptr %xx, align 1 + %zext168 = zext i8 %113 to i32 + %lshrl169 = lshr i32 %zext168, 3 + %ptradd170 = getelementptr inbounds i8, ptr %xx, i64 1 + %114 = load i8, ptr %ptradd170, align 1 + %zext171 = zext i8 %114 to i32 + %shl172 = shl i32 %zext171, 5 + %115 = or i32 %shl172, %lshrl169 + %shl173 = shl i32 %115, 26 + %ashr174 = ashr i32 %shl173, 26 + call void (ptr, ...) @printf(ptr @.str.19, i32 %ashr167, i32 %ashr174) + %ptradd175 = getelementptr inbounds i8, ptr %xx, i64 2 + %116 = load i8, ptr %ptradd175, align 1 + %lshrl176 = lshr i8 %116, 4 + %117 = trunc i8 %lshrl176 to i1 + %zext177 = zext i1 %117 to i32 + call void (ptr, ...) @printf(ptr @.str.20, i32 %zext177) + %ptradd178 = getelementptr inbounds i8, ptr %xx, i64 2 + %118 = load i8, ptr %ptradd178, align 1 + %119 = and i8 %118, -17 + %120 = or i8 %119, 16 + store i8 %120, ptr %ptradd178, align 1 + %ptradd179 = getelementptr inbounds i8, ptr %xx, i64 2 + %121 = load i8, ptr %ptradd179, align 1 + %lshrl180 = lshr i8 %121, 4 + %122 = trunc i8 %lshrl180 to i1 + %zext181 = zext i1 %122 to i32 + call void (ptr, ...) @printf(ptr @.str.21, i32 %zext181) + %ptradd182 = getelementptr inbounds i8, ptr %xx, i64 2 + %123 = load i8, ptr %ptradd182, align 1 + %124 = and i8 %123, -17 + store i8 %124, ptr %ptradd182, align 1 + %ptradd183 = getelementptr inbounds i8, ptr %xx, i64 2 + %125 = load i8, ptr %ptradd183, align 1 + %lshrl184 = lshr i8 %125, 4 + %126 = trunc i8 %lshrl184 to i1 + %zext185 = zext i1 %126 to i32 + call void (ptr, ...) @printf(ptr @.str.22, i32 %zext185) + ret void +} + +; Function Attrs: +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 = load i8, ptr %xx, align 1 + %1 = and i8 %0, -15 + %2 = or i8 %1, 6 + store i8 %2, ptr %xx, align 1 + %3 = load i8, ptr %xx, align 1 + %zext = zext i8 %3 to i32 + %lshrl = lshr i32 %zext, 1 + %shl = shl i32 %lshrl, 29 + %ashr = ashr i32 %shl, 29 + %4 = load i8, ptr %xx, align 1 + %zext1 = zext i8 %4 to i32 + %lshrl2 = lshr i32 %zext1, 4 + %ptradd = getelementptr inbounds i8, ptr %xx, i64 1 + %5 = load i8, ptr %ptradd, align 1 + %zext3 = zext i8 %5 to i32 + %shl4 = shl i32 %zext3, 4 + %6 = or i32 %shl4, %lshrl2 + %shl5 = shl i32 %6, 26 + %ashr6 = ashr i32 %shl5, 26 + call void (ptr, ...) @printf(ptr @.str.23, i32 %ashr, i32 %ashr6) + %7 = load i8, ptr %xx, align 1 + %zext7 = zext i8 %7 to i32 + %lshrl8 = lshr i32 %zext7, 1 + %shl9 = shl i32 %lshrl8, 29 + %ashr10 = ashr i32 %shl9, 29 + %sub = sub i32 %ashr10, 1 + %shl11 = shl i32 %sub, 1 + %trunc = trunc i32 %shl11 to i8 + %8 = and i8 %trunc, 15 + %9 = load i8, ptr %xx, align 1 + %10 = and i8 %9, -15 + %11 = or i8 %10, %8 + store i8 %11, ptr %xx, align 1 + %lshrl12 = lshr i32 %sub, 7 + %12 = load i8, ptr %xx, align 1 + %zext13 = zext i8 %12 to i32 + %lshrl14 = lshr i32 %zext13, 1 + %shl15 = shl i32 %lshrl14, 29 + %ashr16 = ashr i32 %shl15, 29 + %13 = load i8, ptr %xx, align 1 + %zext17 = zext i8 %13 to i32 + %lshrl18 = lshr i32 %zext17, 4 + %ptradd19 = getelementptr inbounds i8, ptr %xx, i64 1 + %14 = load i8, ptr %ptradd19, align 1 + %zext20 = zext i8 %14 to i32 + %shl21 = shl i32 %zext20, 4 + %15 = or i32 %shl21, %lshrl18 + %shl22 = shl i32 %15, 26 + %ashr23 = ashr i32 %shl22, 26 + call void (ptr, ...) @printf(ptr @.str.24, i32 %ashr16, i32 %ashr23) + %16 = load i8, ptr %xx, align 1 + %zext24 = zext i8 %16 to i32 + %lshrl25 = lshr i32 %zext24, 4 + %ptradd26 = getelementptr inbounds i8, ptr %xx, i64 1 + %17 = load i8, ptr %ptradd26, align 1 + %zext27 = zext i8 %17 to i32 + %shl28 = shl i32 %zext27, 4 + %18 = or i32 %shl28, %lshrl25 + %shl29 = shl i32 %18, 26 + %ashr30 = ashr i32 %shl29, 26 + %mul = mul i32 %ashr30, 2 + %shl31 = shl i32 %mul, 4 + %trunc32 = trunc i32 %shl31 to i8 + %19 = load i8, ptr %xx, align 1 + %20 = and i8 %19, 15 + %21 = or i8 %20, %trunc32 + store i8 %21, ptr %xx, align 1 + %lshrl33 = lshr i32 %mul, 4 + %ptradd34 = getelementptr inbounds i8, ptr %xx, i64 1 + %trunc35 = trunc i32 %lshrl33 to i8 + %22 = and i8 %trunc35, 3 + %23 = load i8, ptr %ptradd34, align 1 + %24 = and i8 %23, -4 + %25 = or i8 %24, %22 + store i8 %24, ptr %ptradd34, align 1 + %26 = load i8, ptr %xx, align 1 + %zext36 = zext i8 %26 to i32 + %lshrl37 = lshr i32 %zext36, 1 + %shl38 = shl i32 %lshrl37, 29 + %ashr39 = ashr i32 %shl38, 29 + %27 = load i8, ptr %xx, align 1 + %zext40 = zext i8 %27 to i32 + %lshrl41 = lshr i32 %zext40, 4 + %ptradd42 = getelementptr inbounds i8, ptr %xx, i64 1 + %28 = load i8, ptr %ptradd42, align 1 + %zext43 = zext i8 %28 to i32 + %shl44 = shl i32 %zext43, 4 + %29 = or i32 %shl44, %lshrl41 + %shl45 = shl i32 %29, 26 + %ashr46 = ashr i32 %shl45, 26 + call void (ptr, ...) @printf(ptr @.str.25, i32 %ashr39, i32 %ashr46) + %30 = load i8, ptr %xx, align 1 + %zext47 = zext i8 %30 to i32 + %lshrl48 = lshr i32 %zext47, 4 + %ptradd49 = getelementptr inbounds i8, ptr %xx, i64 1 + %31 = load i8, ptr %ptradd49, align 1 + %zext50 = zext i8 %31 to i32 + %shl51 = shl i32 %zext50, 4 + %32 = or i32 %shl51, %lshrl48 + %shl52 = shl i32 %32, 26 + %ashr53 = ashr i32 %shl52, 26 + %xor = xor i32 %ashr53, 4 + %shl54 = shl i32 %xor, 4 + %trunc55 = trunc i32 %shl54 to i8 + %33 = load i8, ptr %xx, align 1 + %34 = and i8 %33, 15 + %35 = or i8 %34, %trunc55 + store i8 %35, ptr %xx, align 1 + %lshrl56 = lshr i32 %xor, 4 + %ptradd57 = getelementptr inbounds i8, ptr %xx, i64 1 + %trunc58 = trunc i32 %lshrl56 to i8 + %36 = and i8 %trunc58, 3 + %37 = load i8, ptr %ptradd57, align 1 + %38 = and i8 %37, -4 + %39 = or i8 %38, %36 + store i8 %38, ptr %ptradd57, align 1 + %40 = load i8, ptr %xx, align 1 + %zext59 = zext i8 %40 to i32 + %lshrl60 = lshr i32 %zext59, 1 + %shl61 = shl i32 %lshrl60, 29 + %ashr62 = ashr i32 %shl61, 29 + %41 = load i8, ptr %xx, align 1 + %zext63 = zext i8 %41 to i32 + %lshrl64 = lshr i32 %zext63, 4 + %ptradd65 = getelementptr inbounds i8, ptr %xx, i64 1 + %42 = load i8, ptr %ptradd65, align 1 + %zext66 = zext i8 %42 to i32 + %shl67 = shl i32 %zext66, 4 + %43 = or i32 %shl67, %lshrl64 + %shl68 = shl i32 %43, 26 + %ashr69 = ashr i32 %shl68, 26 + call void (ptr, ...) @printf(ptr @.str.26, i32 %ashr62, i32 %ashr69) + %44 = load i8, ptr %xx, align 1 + %zext70 = zext i8 %44 to i32 + %lshrl71 = lshr i32 %zext70, 4 + %ptradd72 = getelementptr inbounds i8, ptr %xx, i64 1 + %45 = load i8, ptr %ptradd72, align 1 + %zext73 = zext i8 %45 to i32 + %shl74 = shl i32 %zext73, 4 + %46 = or i32 %shl74, %lshrl71 + %shl75 = shl i32 %46, 26 + %ashr76 = ashr i32 %shl75, 26 + %or = or i32 %ashr76, 4 + %shl77 = shl i32 %or, 4 + %trunc78 = trunc i32 %shl77 to i8 + %47 = load i8, ptr %xx, align 1 + %48 = and i8 %47, 15 + %49 = or i8 %48, %trunc78 + store i8 %49, ptr %xx, align 1 + %lshrl79 = lshr i32 %or, 4 + %ptradd80 = getelementptr inbounds i8, ptr %xx, i64 1 + %trunc81 = trunc i32 %lshrl79 to i8 + %50 = and i8 %trunc81, 3 + %51 = load i8, ptr %ptradd80, align 1 + %52 = and i8 %51, -4 + %53 = or i8 %52, %50 + store i8 %52, ptr %ptradd80, align 1 + %54 = load i8, ptr %xx, align 1 + %zext82 = zext i8 %54 to i32 + %lshrl83 = lshr i32 %zext82, 1 + %shl84 = shl i32 %lshrl83, 29 + %ashr85 = ashr i32 %shl84, 29 + %55 = load i8, ptr %xx, align 1 + %zext86 = zext i8 %55 to i32 + %lshrl87 = lshr i32 %zext86, 4 + %ptradd88 = getelementptr inbounds i8, ptr %xx, i64 1 + %56 = load i8, ptr %ptradd88, align 1 + %zext89 = zext i8 %56 to i32 + %shl90 = shl i32 %zext89, 4 + %57 = or i32 %shl90, %lshrl87 + %shl91 = shl i32 %57, 26 + %ashr92 = ashr i32 %shl91, 26 + call void (ptr, ...) @printf(ptr @.str.27, i32 %ashr85, i32 %ashr92) + %58 = load i8, ptr %xx, align 1 + %zext93 = zext i8 %58 to i32 + %lshrl94 = lshr i32 %zext93, 4 + %ptradd95 = getelementptr inbounds i8, ptr %xx, i64 1 + %59 = load i8, ptr %ptradd95, align 1 + %zext96 = zext i8 %59 to i32 + %shl97 = shl i32 %zext96, 4 + %60 = or i32 %shl97, %lshrl94 + %shl98 = shl i32 %60, 26 + %ashr99 = ashr i32 %shl98, 26 + %shl100 = shl i32 %ashr99, 1 + %61 = freeze i32 %shl100 + %shl101 = shl i32 %61, 4 + %trunc102 = trunc i32 %shl101 to i8 + %62 = load i8, ptr %xx, align 1 + %63 = and i8 %62, 15 + %64 = or i8 %63, %trunc102 + store i8 %64, ptr %xx, align 1 + %lshrl103 = lshr i32 %61, 4 + %ptradd104 = getelementptr inbounds i8, ptr %xx, i64 1 + %trunc105 = trunc i32 %lshrl103 to i8 + %65 = and i8 %trunc105, 3 + %66 = load i8, ptr %ptradd104, align 1 + %67 = and i8 %66, -4 + %68 = or i8 %67, %65 + store i8 %67, ptr %ptradd104, align 1 + %69 = load i8, ptr %xx, align 1 + %zext106 = zext i8 %69 to i32 + %lshrl107 = lshr i32 %zext106, 1 + %shl108 = shl i32 %lshrl107, 29 + %ashr109 = ashr i32 %shl108, 29 + %70 = load i8, ptr %xx, align 1 + %zext110 = zext i8 %70 to i32 + %lshrl111 = lshr i32 %zext110, 4 + %ptradd112 = getelementptr inbounds i8, ptr %xx, i64 1 + %71 = load i8, ptr %ptradd112, align 1 + %zext113 = zext i8 %71 to i32 + %shl114 = shl i32 %zext113, 4 + %72 = or i32 %shl114, %lshrl111 + %shl115 = shl i32 %72, 26 + %ashr116 = ashr i32 %shl115, 26 + call void (ptr, ...) @printf(ptr @.str.28, i32 %ashr109, i32 %ashr116) + %73 = load i8, ptr %xx, align 1 + %zext117 = zext i8 %73 to i32 + %lshrl118 = lshr i32 %zext117, 4 + %ptradd119 = getelementptr inbounds i8, ptr %xx, i64 1 + %74 = load i8, ptr %ptradd119, align 1 + %zext120 = zext i8 %74 to i32 + %shl121 = shl i32 %zext120, 4 + %75 = or i32 %shl121, %lshrl118 + %shl122 = shl i32 %75, 26 + %ashr123 = ashr i32 %shl122, 26 + %ashr124 = ashr i32 %ashr123, 1 + %76 = freeze i32 %ashr124 + %shl125 = shl i32 %76, 4 + %trunc126 = trunc i32 %shl125 to i8 + %77 = load i8, ptr %xx, align 1 + %78 = and i8 %77, 15 + %79 = or i8 %78, %trunc126 + store i8 %79, ptr %xx, align 1 + %lshrl127 = lshr i32 %76, 4 + %ptradd128 = getelementptr inbounds i8, ptr %xx, i64 1 + %trunc129 = trunc i32 %lshrl127 to i8 + %80 = and i8 %trunc129, 3 + %81 = load i8, ptr %ptradd128, align 1 + %82 = and i8 %81, -4 + %83 = or i8 %82, %80 + store i8 %82, ptr %ptradd128, align 1 + %84 = load i8, ptr %xx, align 1 + %zext130 = zext i8 %84 to i32 + %lshrl131 = lshr i32 %zext130, 1 + %shl132 = shl i32 %lshrl131, 29 + %ashr133 = ashr i32 %shl132, 29 + %85 = load i8, ptr %xx, align 1 + %zext134 = zext i8 %85 to i32 + %lshrl135 = lshr i32 %zext134, 4 + %ptradd136 = getelementptr inbounds i8, ptr %xx, i64 1 + %86 = load i8, ptr %ptradd136, align 1 + %zext137 = zext i8 %86 to i32 + %shl138 = shl i32 %zext137, 4 + %87 = or i32 %shl138, %lshrl135 + %shl139 = shl i32 %87, 26 + %ashr140 = ashr i32 %shl139, 26 + call void (ptr, ...) @printf(ptr @.str.29, i32 %ashr133, i32 %ashr140) + %88 = load i8, ptr %xx, align 1 + %zext141 = zext i8 %88 to i32 + %lshrl142 = lshr i32 %zext141, 4 + %ptradd143 = getelementptr inbounds i8, ptr %xx, i64 1 + %89 = load i8, ptr %ptradd143, align 1 + %zext144 = zext i8 %89 to i32 + %shl145 = shl i32 %zext144, 4 + %90 = or i32 %shl145, %lshrl142 + %shl146 = shl i32 %90, 26 + %ashr147 = ashr i32 %shl146, 26 + %sdiv = sdiv i32 %ashr147, 2 + %shl148 = shl i32 %sdiv, 4 + %trunc149 = trunc i32 %shl148 to i8 + %91 = load i8, ptr %xx, align 1 + %92 = and i8 %91, 15 + %93 = or i8 %92, %trunc149 + store i8 %93, ptr %xx, align 1 + %lshrl150 = lshr i32 %sdiv, 4 + %ptradd151 = getelementptr inbounds i8, ptr %xx, i64 1 + %trunc152 = trunc i32 %lshrl150 to i8 + %94 = and i8 %trunc152, 3 + %95 = load i8, ptr %ptradd151, align 1 + %96 = and i8 %95, -4 + %97 = or i8 %96, %94 + store i8 %96, ptr %ptradd151, align 1 + %98 = load i8, ptr %xx, align 1 + %zext153 = zext i8 %98 to i32 + %lshrl154 = lshr i32 %zext153, 1 + %shl155 = shl i32 %lshrl154, 29 + %ashr156 = ashr i32 %shl155, 29 + %99 = load i8, ptr %xx, align 1 + %zext157 = zext i8 %99 to i32 + %lshrl158 = lshr i32 %zext157, 4 + %ptradd159 = getelementptr inbounds i8, ptr %xx, i64 1 + %100 = load i8, ptr %ptradd159, align 1 + %zext160 = zext i8 %100 to i32 + %shl161 = shl i32 %zext160, 4 + %101 = or i32 %shl161, %lshrl158 + %shl162 = shl i32 %101, 26 + %ashr163 = ashr i32 %shl162, 26 + call void (ptr, ...) @printf(ptr @.str.30, i32 %ashr156, i32 %ashr163) + %102 = load i8, ptr %xx, align 1 + %zext164 = zext i8 %102 to i32 + %lshrl165 = lshr i32 %zext164, 4 + %ptradd166 = getelementptr inbounds i8, ptr %xx, i64 1 + %103 = load i8, ptr %ptradd166, align 1 + %zext167 = zext i8 %103 to i32 + %shl168 = shl i32 %zext167, 4 + %104 = or i32 %shl168, %lshrl165 + %shl169 = shl i32 %104, 26 + %ashr170 = ashr i32 %shl169, 26 + %smod = srem i32 %ashr170, 2 + %shl171 = shl i32 %smod, 4 + %trunc172 = trunc i32 %shl171 to i8 + %105 = load i8, ptr %xx, align 1 + %106 = and i8 %105, 15 + %107 = or i8 %106, %trunc172 + store i8 %107, ptr %xx, align 1 + %lshrl173 = lshr i32 %smod, 4 + %ptradd174 = getelementptr inbounds i8, ptr %xx, i64 1 + %trunc175 = trunc i32 %lshrl173 to i8 + %108 = and i8 %trunc175, 3 + %109 = load i8, ptr %ptradd174, align 1 + %110 = and i8 %109, -4 + %111 = or i8 %110, %108 + store i8 %110, ptr %ptradd174, align 1 + %112 = load i8, ptr %xx, align 1 + %zext176 = zext i8 %112 to i32 + %lshrl177 = lshr i32 %zext176, 1 + %shl178 = shl i32 %lshrl177, 29 + %ashr179 = ashr i32 %shl178, 29 + %113 = load i8, ptr %xx, align 1 + %zext180 = zext i8 %113 to i32 + %lshrl181 = lshr i32 %zext180, 4 + %ptradd182 = getelementptr inbounds i8, ptr %xx, i64 1 + %114 = load i8, ptr %ptradd182, align 1 + %zext183 = zext i8 %114 to i32 + %shl184 = shl i32 %zext183, 4 + %115 = or i32 %shl184, %lshrl181 + %shl185 = shl i32 %115, 26 + %ashr186 = ashr i32 %shl185, 26 + call void (ptr, ...) @printf(ptr @.str.31, i32 %ashr179, i32 %ashr186) + %ptradd187 = getelementptr inbounds i8, ptr %xx, i64 2 + %116 = load i8, ptr %ptradd187, align 1 + %lshrl188 = lshr i8 %116, 5 + %117 = trunc i8 %lshrl188 to i1 + %zext189 = zext i1 %117 to i32 + call void (ptr, ...) @printf(ptr @.str.32, i32 %zext189) + %ptradd190 = getelementptr inbounds i8, ptr %xx, i64 2 + %118 = load i8, ptr %ptradd190, align 1 + %119 = and i8 %118, -33 + %120 = or i8 %119, 32 + store i8 %120, ptr %ptradd190, align 1 + %ptradd191 = getelementptr inbounds i8, ptr %xx, i64 2 + %121 = load i8, ptr %ptradd191, align 1 + %lshrl192 = lshr i8 %121, 5 + %122 = trunc i8 %lshrl192 to i1 + %zext193 = zext i1 %122 to i32 + call void (ptr, ...) @printf(ptr @.str.33, i32 %zext193) + %ptradd194 = getelementptr inbounds i8, ptr %xx, i64 2 + %123 = load i8, ptr %ptradd194, align 1 + %124 = and i8 %123, -33 + store i8 %124, ptr %ptradd194, align 1 + %ptradd195 = getelementptr inbounds i8, ptr %xx, i64 2 + %125 = load i8, ptr %ptradd195, align 1 + %lshrl196 = lshr i8 %125, 5 + %126 = trunc i8 %lshrl196 to i1 + %zext197 = zext i1 %126 to i32 + call void (ptr, ...) @printf(ptr @.str.34, i32 %zext197) + ret void +} diff --git a/test/test_suite7/bitstruct/bitstruct_arrays_be.c3t b/test/test_suite7/bitstruct/bitstruct_arrays_be.c3t new file mode 100644 index 000000000..5d86abd7c --- /dev/null +++ b/test/test_suite7/bitstruct/bitstruct_arrays_be.c3t @@ -0,0 +1,138 @@ +// #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 = load i8, ptr %xx, align 1 + %zext = zext i8 %0 to i32 + %lshrl = lshr i32 %zext, 4 + %ptradd = getelementptr inbounds i8, ptr %xx, i64 1 + %1 = load i8, ptr %ptradd, align 1 + %zext1 = zext i8 %1 to i32 + %shl = shl i32 %zext1, 4 + %2 = or i32 %shl, %lshrl + %ptradd2 = getelementptr inbounds i8, ptr %xx, i64 2 + %3 = load i8, ptr %ptradd2, align 1 + %zext3 = zext i8 %3 to i32 + %shl4 = shl i32 %zext3, 12 + %4 = or i32 %shl4, %2 + %shl5 = shl i32 %4, 16 + %5 = call i32 @llvm.bswap.i32(i32 %shl5) + %6 = and i32 65535, %5 + call void (ptr, ...) @printf(ptr @.str, i32 %6) + store [4 x i8] c"\F0\EA\0B\00", ptr %xy, align 1 + store ptr %xy, ptr %abc, align 8 + %7 = load ptr, ptr %abc, align 8 + store ptr %7, ptr %z, align 8 + %8 = load i8, ptr %xy, align 1 + %zext6 = zext i8 %8 to i32 + %lshrl7 = lshr i32 %zext6, 4 + %ptradd8 = getelementptr inbounds i8, ptr %xy, i64 1 + %9 = load i8, ptr %ptradd8, align 1 + %zext9 = zext i8 %9 to i32 + %shl10 = shl i32 %zext9, 4 + %10 = or i32 %shl10, %lshrl7 + %ptradd11 = getelementptr inbounds i8, ptr %xy, i64 2 + %11 = load i8, ptr %ptradd11, align 1 + %zext12 = zext i8 %11 to i32 + %shl13 = shl i32 %zext12, 12 + %12 = or i32 %shl13, %10 + %13 = and i32 65535, %12 + call void (ptr, ...) @printf(ptr @.str.1, i32 %13) + %14 = load i8, ptr %xy, align 1 + %15 = and i8 %14, 15 + %16 = or i8 %15, -16 + store i8 %16, ptr %xy, align 1 + %ptradd14 = getelementptr inbounds i8, ptr %xy, i64 1 + store i8 -18, ptr %ptradd14, align 1 + %ptradd15 = getelementptr inbounds i8, ptr %xy, i64 2 + %17 = load i8, ptr %ptradd15, align 1 + %18 = and i8 %17, -16 + %19 = or i8 %18, 11 + store i8 %18, ptr %ptradd15, align 1 + %20 = load i8, ptr %xy, align 1 + %zext16 = zext i8 %20 to i32 + %lshrl17 = lshr i32 %zext16, 4 + %ptradd18 = getelementptr inbounds i8, ptr %xy, i64 1 + %21 = load i8, ptr %ptradd18, align 1 + %zext19 = zext i8 %21 to i32 + %shl20 = shl i32 %zext19, 4 + %22 = or i32 %shl20, %lshrl17 + %ptradd21 = getelementptr inbounds i8, ptr %xy, i64 2 + %23 = load i8, ptr %ptradd21, align 1 + %zext22 = zext i8 %23 to i32 + %shl23 = shl i32 %zext22, 12 + %24 = or i32 %shl23, %22 + %25 = and i32 65535, %24 + call void (ptr, ...) @printf(ptr @.str.2, i32 %25) + %26 = load i8, ptr %xx, align 1 + %27 = and i8 %26, 15 + %28 = or i8 %27, -32 + store i8 %28, ptr %xx, align 1 + %ptradd24 = getelementptr inbounds i8, ptr %xx, i64 1 + store i8 -5, ptr %ptradd24, align 1 + %ptradd25 = getelementptr inbounds i8, ptr %xx, i64 2 + %29 = load i8, ptr %ptradd25, align 1 + %30 = and i8 %29, -16 + %31 = or i8 %30, 14 + store i8 %30, ptr %ptradd25, align 1 + %32 = load i8, ptr %xx, align 1 + %zext26 = zext i8 %32 to i32 + %lshrl27 = lshr i32 %zext26, 4 + %ptradd28 = getelementptr inbounds i8, ptr %xx, i64 1 + %33 = load i8, ptr %ptradd28, align 1 + %zext29 = zext i8 %33 to i32 + %shl30 = shl i32 %zext29, 4 + %34 = or i32 %shl30, %lshrl27 + %ptradd31 = getelementptr inbounds i8, ptr %xx, i64 2 + %35 = load i8, ptr %ptradd31, align 1 + %zext32 = zext i8 %35 to i32 + %shl33 = shl i32 %zext32, 12 + %36 = or i32 %shl33, %34 + %shl34 = shl i32 %36, 16 + %37 = call i32 @llvm.bswap.i32(i32 %shl34) + %38 = and i32 65535, %37 + call void (ptr, ...) @printf(ptr @.str.3, i32 %38) + ret void +} \ No newline at end of file diff --git a/test/test_suite7/bitstruct/bitstruct_be.c3t b/test/test_suite7/bitstruct/bitstruct_be.c3t new file mode 100644 index 000000000..5e20ec6eb --- /dev/null +++ b/test/test_suite7/bitstruct/bitstruct_be.c3t @@ -0,0 +1,348 @@ +// #target: macos-x64 +module test; +import std::io; + +bitstruct Test : int @bigendian +{ + ushort a : 0..15; + ushort b : 16..31; +} + +bitstruct Test2 : char[4] @bigendian +{ + ushort a : 0..15; + ushort b : 16..31; +} + +fn void main() +{ + IntBE x; + x.val = 123; + + io::printf("BE 123 => %d (%d)\n", (int)x, x.val); + Test abc = { .a = 0x1234, .b = 0x5678 }; + Test2 abc2 = { .a = 0x1234, .b = 0x5678 }; + char[4]* z = (char[4]*)&abc; + char[4]* z2 = (char[4]*)&abc2; + foreach (d : z2) io::printf(" %x", d); + io::printn(""); + foreach (d : z) io::printf(" %x", d); + io::printn(""); + io::printfn("abc.a = %x", abc.a); + abc.a = 0x1234; + abc.b = 0x5678; + io::printfn("->abc.a = %x", abc.a); + foreach (d : z) io::printf(" %x", d); + io::printn(""); + + IntLE y; + y.val = 123; + io::printf("LE 123 => %d (%d)\n", (int)y, y.val); + +} + +/* #expect: test.ll + + %0 = load i32, ptr %x, align 4 + %1 = call i32 @llvm.bswap.i32(i32 %0) + store i32 2063597568, ptr %x, align 4 + %2 = insertvalue %any undef, ptr %x, 0 + %3 = insertvalue %any %2, i64 ptrtoint (ptr @"$ct.int" to i64), 1 + store %any %3, ptr %varargslots, align 16 + %4 = load i32, ptr %x, align 4 + %5 = call i32 @llvm.bswap.i32(i32 %4) + store i32 %5, ptr %taddr, align 4 + %6 = insertvalue %any undef, ptr %taddr, 0 + %7 = insertvalue %any %6, i64 ptrtoint (ptr @"$ct.int" to i64), 1 + %ptradd = getelementptr inbounds i8, ptr %varargslots, i64 16 + store %any %7, ptr %ptradd, align 16 + %8 = call i64 @std.io.printf(ptr %retparam, ptr @.str, i64 18, ptr %varargslots, i64 2) + store i32 873625686, ptr %abc, align 4 + store [4 x i8] c"\124Vx", ptr %abc2, align 1 + store ptr %abc, ptr %z, align 8 + store ptr %abc2, ptr %z2, align 8 + %9 = load ptr, ptr %z2, align 8 + store i64 0, ptr %.anon, align 8 + br label %loop.cond + +loop.cond: ; preds = %loop.body, %entry + %10 = load i64, ptr %.anon, align 8 + %gt = icmp ugt i64 4, %10 + br i1 %gt, label %loop.body, label %loop.exit + +loop.body: ; preds = %loop.cond + %11 = load i64, ptr %.anon, align 8 + %ptradd1 = getelementptr inbounds i8, ptr %9, i64 %11 + %12 = load i8, ptr %ptradd1, align 1 + store i8 %12, ptr %d, align 1 + %13 = insertvalue %any undef, ptr %d, 0 + %14 = insertvalue %any %13, i64 ptrtoint (ptr @"$ct.char" to i64), 1 + store %any %14, ptr %varargslots2, align 16 + %15 = call i64 @std.io.printf(ptr %retparam3, ptr @.str.1, i64 3, ptr %varargslots2, i64 1) + %16 = load i64, ptr %.anon, align 8 + %addnuw = add nuw i64 %16, 1 + store i64 %addnuw, ptr %.anon, align 8 + br label %loop.cond + +loop.exit: ; preds = %loop.cond + %17 = call ptr @std.io.stdout() + %18 = call i64 @std.io.File.write(ptr %retparam5, ptr %17, ptr null, i64 0) + %not_err = icmp eq i64 %18, 0 + %19 = call i1 @llvm.expect.i1(i1 %not_err, i1 true) + br i1 %19, label %after_check, label %assign_optional + +assign_optional: ; preds = %loop.exit + store i64 %18, ptr %error_var, align 8 + br label %guard_block + +after_check: ; preds = %loop.exit + br label %noerr_block + +guard_block: ; preds = %assign_optional + br label %voiderr + +noerr_block: ; preds = %after_check + %20 = load i64, ptr %retparam5, align 8 + store i64 %20, ptr %len, align 8 + %21 = call i64 @std.io.File.write_byte(ptr %17, i8 zeroext 10) + %not_err7 = icmp eq i64 %21, 0 + %22 = call i1 @llvm.expect.i1(i1 %not_err7, i1 true) + br i1 %22, label %after_check9, label %assign_optional8 + +assign_optional8: ; preds = %noerr_block + store i64 %21, ptr %error_var6, align 8 + br label %guard_block10 + +after_check9: ; preds = %noerr_block + br label %noerr_block11 + +guard_block10: ; preds = %assign_optional8 + br label %voiderr + +noerr_block11: ; preds = %after_check9 + %23 = call i64 @std.io.File.flush(ptr %17) + %not_err13 = icmp eq i64 %23, 0 + %24 = call i1 @llvm.expect.i1(i1 %not_err13, i1 true) + br i1 %24, label %after_check15, label %assign_optional14 + +assign_optional14: ; preds = %noerr_block11 + store i64 %23, ptr %error_var12, align 8 + br label %guard_block16 + +after_check15: ; preds = %noerr_block11 + br label %noerr_block17 + +guard_block16: ; preds = %assign_optional14 + br label %voiderr + +noerr_block17: ; preds = %after_check15 + %25 = load i64, ptr %len, align 8 + %add = add i64 %25, 1 + br label %voiderr + +voiderr: ; preds = %noerr_block17, %guard_block16, %guard_block10, %guard_block + %26 = load ptr, ptr %z, align 8 + store i64 0, ptr %.anon18, align 8 + br label %loop.cond19 + +loop.cond19: ; preds = %loop.body21, %voiderr + %27 = load i64, ptr %.anon18, align 8 + %gt20 = icmp ugt i64 4, %27 + br i1 %gt20, label %loop.body21, label %loop.exit29 + +loop.body21: ; preds = %loop.cond19 + %28 = load i64, ptr %.anon18, align 8 + %ptradd23 = getelementptr inbounds i8, ptr %26, i64 %28 + %29 = load i8, ptr %ptradd23, align 1 + store i8 %29, ptr %d22, align 1 + %30 = insertvalue %any undef, ptr %d22, 0 + %31 = insertvalue %any %30, i64 ptrtoint (ptr @"$ct.char" to i64), 1 + store %any %31, ptr %varargslots24, align 16 + %32 = call i64 @std.io.printf(ptr %retparam25, ptr @.str.2, i64 3, ptr %varargslots24, i64 1) + %33 = load i64, ptr %.anon18, align 8 + %addnuw28 = add nuw i64 %33, 1 + store i64 %addnuw28, ptr %.anon18, align 8 + br label %loop.cond19 + +loop.exit29: ; preds = %loop.cond19 + %34 = call ptr @std.io.stdout() + %35 = call i64 @std.io.File.write(ptr %retparam33, ptr %34, ptr null, i64 0) + %not_err34 = icmp eq i64 %35, 0 + %36 = call i1 @llvm.expect.i1(i1 %not_err34, i1 true) + br i1 %36, label %after_check36, label %assign_optional35 + +assign_optional35: ; preds = %loop.exit29 + store i64 %35, ptr %error_var31, align 8 + br label %guard_block37 + +after_check36: ; preds = %loop.exit29 + br label %noerr_block38 + +guard_block37: ; preds = %assign_optional35 + br label %voiderr52 + +noerr_block38: ; preds = %after_check36 + %37 = load i64, ptr %retparam33, align 8 + store i64 %37, ptr %len30, align 8 + %38 = call i64 @std.io.File.write_byte(ptr %34, i8 zeroext 10) + %not_err40 = icmp eq i64 %38, 0 + %39 = call i1 @llvm.expect.i1(i1 %not_err40, i1 true) + br i1 %39, label %after_check42, label %assign_optional41 + +assign_optional41: ; preds = %noerr_block38 + store i64 %38, ptr %error_var39, align 8 + br label %guard_block43 + +after_check42: ; preds = %noerr_block38 + br label %noerr_block44 + +guard_block43: ; preds = %assign_optional41 + br label %voiderr52 + +noerr_block44: ; preds = %after_check42 + %40 = call i64 @std.io.File.flush(ptr %34) + %not_err46 = icmp eq i64 %40, 0 + %41 = call i1 @llvm.expect.i1(i1 %not_err46, i1 true) + br i1 %41, label %after_check48, label %assign_optional47 + +assign_optional47: ; preds = %noerr_block44 + store i64 %40, ptr %error_var45, align 8 + br label %guard_block49 + +after_check48: ; preds = %noerr_block44 + br label %noerr_block50 + +guard_block49: ; preds = %assign_optional47 + br label %voiderr52 + +noerr_block50: ; preds = %after_check48 + %42 = load i64, ptr %len30, align 8 + %add51 = add i64 %42, 1 + br label %voiderr52 + +voiderr52: ; preds = %noerr_block50, %guard_block49, %guard_block43, %guard_block37 + %43 = load i32, ptr %abc, align 4 + %44 = call i32 @llvm.bswap.i32(i32 %43) + %45 = and i32 65535, %44 + %trunc = trunc i32 %45 to i16 + store i16 %trunc, ptr %taddr54, align 2 + %46 = insertvalue %any undef, ptr %taddr54, 0 + %47 = insertvalue %any %46, i64 ptrtoint (ptr @"$ct.ushort" to i64), 1 + store %any %47, ptr %varargslots53, align 16 + %48 = call i64 @std.io.printfn(ptr %retparam55, ptr @.str.3, i64 10, ptr %varargslots53, i64 1) + %49 = load i32, ptr %abc, align 4 + %50 = call i32 @llvm.bswap.i32(i32 %49) + %51 = and i32 %50, -65536 + %52 = or i32 %51, 4660 + %53 = call i32 @llvm.bswap.i32(i32 %52) + store i32 %53, ptr %abc, align 4 + %54 = load i32, ptr %abc, align 4 + %55 = call i32 @llvm.bswap.i32(i32 %54) + %56 = and i32 %55, 65535 + %57 = or i32 %56, 1450704896 + %58 = call i32 @llvm.bswap.i32(i32 %57) + store i32 %58, ptr %abc, align 4 + %59 = load i32, ptr %abc, align 4 + %60 = call i32 @llvm.bswap.i32(i32 %59) + %61 = and i32 65535, %60 + %trunc59 = trunc i32 %61 to i16 + store i16 %trunc59, ptr %taddr60, align 2 + %62 = insertvalue %any undef, ptr %taddr60, 0 + %63 = insertvalue %any %62, i64 ptrtoint (ptr @"$ct.ushort" to i64), 1 + store %any %63, ptr %varargslots58, align 16 + %64 = call i64 @std.io.printfn(ptr %retparam61, ptr @.str.4, i64 12, ptr %varargslots58, i64 1) + %65 = load ptr, ptr %z, align 8 + store i64 0, ptr %.anon64, align 8 + br label %loop.cond65 + +loop.cond65: ; preds = %loop.body67, %voiderr52 + %66 = load i64, ptr %.anon64, align 8 + %gt66 = icmp ugt i64 4, %66 + br i1 %gt66, label %loop.body67, label %loop.exit75 + +loop.body67: ; preds = %loop.cond65 + %67 = load i64, ptr %.anon64, align 8 + %ptradd69 = getelementptr inbounds i8, ptr %65, i64 %67 + %68 = load i8, ptr %ptradd69, align 1 + store i8 %68, ptr %d68, align 1 + %69 = insertvalue %any undef, ptr %d68, 0 + %70 = insertvalue %any %69, i64 ptrtoint (ptr @"$ct.char" to i64), 1 + store %any %70, ptr %varargslots70, align 16 + %71 = call i64 @std.io.printf(ptr %retparam71, ptr @.str.5, i64 3, ptr %varargslots70, i64 1) + %72 = load i64, ptr %.anon64, align 8 + %addnuw74 = add nuw i64 %72, 1 + store i64 %addnuw74, ptr %.anon64, align 8 + br label %loop.cond65 + +loop.exit75: ; preds = %loop.cond65 + %73 = call ptr @std.io.stdout() + %74 = call i64 @std.io.File.write(ptr %retparam79, ptr %73, ptr null, i64 0) + %not_err80 = icmp eq i64 %74, 0 + %75 = call i1 @llvm.expect.i1(i1 %not_err80, i1 true) + br i1 %75, label %after_check82, label %assign_optional81 + +assign_optional81: ; preds = %loop.exit75 + store i64 %74, ptr %error_var77, align 8 + br label %guard_block83 + +after_check82: ; preds = %loop.exit75 + br label %noerr_block84 + +guard_block83: ; preds = %assign_optional81 + br label %voiderr98 + +noerr_block84: ; preds = %after_check82 + %76 = load i64, ptr %retparam79, align 8 + store i64 %76, ptr %len76, align 8 + %77 = call i64 @std.io.File.write_byte(ptr %73, i8 zeroext 10) + %not_err86 = icmp eq i64 %77, 0 + %78 = call i1 @llvm.expect.i1(i1 %not_err86, i1 true) + br i1 %78, label %after_check88, label %assign_optional87 + +assign_optional87: ; preds = %noerr_block84 + store i64 %77, ptr %error_var85, align 8 + br label %guard_block89 + +after_check88: ; preds = %noerr_block84 + br label %noerr_block90 + +guard_block89: ; preds = %assign_optional87 + br label %voiderr98 + +noerr_block90: ; preds = %after_check88 + %79 = call i64 @std.io.File.flush(ptr %73) + %not_err92 = icmp eq i64 %79, 0 + %80 = call i1 @llvm.expect.i1(i1 %not_err92, i1 true) + br i1 %80, label %after_check94, label %assign_optional93 + +assign_optional93: ; preds = %noerr_block90 + store i64 %79, ptr %error_var91, align 8 + br label %guard_block95 + +after_check94: ; preds = %noerr_block90 + br label %noerr_block96 + +guard_block95: ; preds = %assign_optional93 + br label %voiderr98 + +noerr_block96: ; preds = %after_check94 + %81 = load i64, ptr %len76, align 8 + %add97 = add i64 %81, 1 + br label %voiderr98 + +voiderr98: ; preds = %noerr_block96, %guard_block95, %guard_block89, %guard_block83 + store i32 0, ptr %y, align 4 + %82 = load i32, ptr %y, align 4 + store i32 123, ptr %y, align 4 + %83 = insertvalue %any undef, ptr %y, 0 + %84 = insertvalue %any %83, i64 ptrtoint (ptr @"$ct.int" to i64), 1 + store %any %84, ptr %varargslots99, align 16 + %85 = load i32, ptr %y, align 4 + store i32 %85, ptr %taddr100, align 4 + %86 = insertvalue %any undef, ptr %taddr100, 0 + %87 = insertvalue %any %86, i64 ptrtoint (ptr @"$ct.int" to i64), 1 + %ptradd101 = getelementptr inbounds i8, ptr %varargslots99, i64 16 + store %any %87, ptr %ptradd101, align 16 + %88 = call i64 @std.io.printf(ptr %retparam102, ptr @.str.6, i64 18, ptr %varargslots99, i64 2) + ret void +} \ No newline at end of file diff --git a/test/test_suite7/bitstruct/bitstruct_bool.c3t b/test/test_suite7/bitstruct/bitstruct_bool.c3t new file mode 100644 index 000000000..bbece73f1 --- /dev/null +++ b/test/test_suite7/bitstruct/bitstruct_bool.c3t @@ -0,0 +1,67 @@ +// #target: macos-x64 +module test; +bitstruct Foo : int +{ + bool enable_help; + bool enable_version; +} + +bitstruct Foo2 : char[2] +{ + bool enable_help; + bool enable_version; +} + +fn void main() +{ + Foo a = { .enable_help }; + Foo b = { .enable_version }; + Foo $a = { .enable_help }; + Foo $b = { .enable_version }; + $assert(!($a & $b)); + if (a & b) return; + Foo2 a2 = { .enable_help }; + Foo2 b2 = { .enable_version, .enable_help }; + if (!(a2 & b2)) return; +} + +/* #expect: test.ll + + %a = alloca i32, align 4 + %b = alloca i32, align 4 + %a2 = alloca [2 x i8], align 1 + %b2 = alloca [2 x i8], align 1 + %0 = alloca i16, align 1 + store i32 1, ptr %a, align 4 + store i32 2, ptr %b, align 4 + %1 = load i32, ptr %a, align 4 + %2 = load i32, ptr %b, align 4 + %and = and i32 %1, %2 + %i2b = icmp ne i32 %and, 0 + br i1 %i2b, label %if.then, label %if.exit + +if.then: ; preds = %entry + ret void + +if.exit: ; preds = %entry + store [2 x i8] c"\01\00", ptr %a2, align 1 + store [2 x i8] c"\03\00", ptr %b2, align 1 + %3 = load i16, ptr %a2, align 1 + %4 = load i16, ptr %b2, align 1 + %and1 = and i16 %3, %4 + store i16 %and1, ptr %0, align 1 + %5 = load i8, ptr %0, align 1 + %zext = zext i8 %5 to i32 + %ptradd = getelementptr inbounds i8, ptr %0, i64 1 + %6 = load i8, ptr %ptradd, align 1 + %zext2 = zext i8 %6 to i32 + %7 = add i32 %zext, %zext2 + %8 = icmp eq i32 %7, 0 + br i1 %8, label %if.then3, label %if.exit4 + +if.then3: ; preds = %if.exit + ret void + +if.exit4: ; preds = %if.exit + ret void +} \ No newline at end of file diff --git a/test/test_suite7/bitstruct/bitstruct_cast_and_back.c3 b/test/test_suite7/bitstruct/bitstruct_cast_and_back.c3 new file mode 100644 index 000000000..7956f3f52 --- /dev/null +++ b/test/test_suite7/bitstruct/bitstruct_cast_and_back.c3 @@ -0,0 +1,15 @@ +// See issue #1159 + +bitstruct Foo : int { + bool a; +} + +bitstruct Bar : int { + bool a; + bool b; +} + +fn void bitstruct_cast() { + Bar bar; + Foo foo = (Foo)(int)bar; +} diff --git a/test/test_suite7/bitstruct/bitstruct_cast_const_init.c3t b/test/test_suite7/bitstruct/bitstruct_cast_const_init.c3t new file mode 100644 index 000000000..d1503ab39 --- /dev/null +++ b/test/test_suite7/bitstruct/bitstruct_cast_const_init.c3t @@ -0,0 +1,20 @@ +// #target: macos-x64 +module test; +bitstruct Foo : int +{ + int abc : 0..4; + int defg : 23..26; +} + +fn void main() +{ + Foo f; + int z = (int) (Foo) { .abc = 2, .defg = 1 }; +} + +/* #expect: test.ll + + %f = alloca i32, align 4 + %z = alloca i32, align 4 + store i32 0, ptr %f, align 4 + store i32 8388610, ptr %z, align 4 \ No newline at end of file diff --git a/test/test_suite7/bitstruct/bitstruct_direct_in_struct.c3t b/test/test_suite7/bitstruct/bitstruct_direct_in_struct.c3t new file mode 100644 index 000000000..644ca323b --- /dev/null +++ b/test/test_suite7/bitstruct/bitstruct_direct_in_struct.c3t @@ -0,0 +1,52 @@ +// #target: macos-x64 +module test; +bitstruct Flags : int { + bool flag1; +} + +struct Foo { + long x; + Flags flags; +} + +fn int main(String[] args) { + long x; + Foo foo = { + .x = x, + .flags.flag1 = true, + }; + Flags flags; + Foo bar = { + .x = x, + .flags = flags, + }; + return 0; +} + + +/* #expect: test.ll + + store ptr %0, ptr %args, align 8 + %ptradd = getelementptr inbounds i8, ptr %args, i64 8 + store i64 %1, ptr %ptradd, align 8 + store i64 0, ptr %x, align 8 + store i64 0, ptr %foo, align 8 + %ptradd1 = getelementptr inbounds i8, ptr %foo, i64 8 + store i32 0, ptr %ptradd1, align 8 + %2 = load i64, ptr %x, align 8 + store i64 %2, ptr %foo, align 8 + %ptradd2 = getelementptr inbounds i8, ptr %foo, i64 8 + %3 = load i32, ptr %ptradd2, align 8 + %4 = and i32 %3, -2 + %5 = or i32 %4, 1 + store i32 %5, ptr %ptradd2, align 8 + store i32 0, ptr %flags, align 4 + store i64 0, ptr %bar, align 8 + %ptradd3 = getelementptr inbounds i8, ptr %bar, i64 8 + store i32 0, ptr %ptradd3, align 8 + %6 = load i64, ptr %x, align 8 + store i64 %6, ptr %bar, align 8 + %ptradd4 = getelementptr inbounds i8, ptr %bar, i64 8 + %7 = load i32, ptr %flags, align 4 + store i32 %7, ptr %ptradd4, align 8 + ret i32 0 diff --git a/test/test_suite7/bitstruct/bitstruct_general.c3 b/test/test_suite7/bitstruct/bitstruct_general.c3 new file mode 100644 index 000000000..62580160b --- /dev/null +++ b/test/test_suite7/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_suite7/bitstruct/bitstruct_in_subarray.c3t b/test/test_suite7/bitstruct/bitstruct_in_subarray.c3t new file mode 100644 index 000000000..0e5396d88 --- /dev/null +++ b/test/test_suite7/bitstruct/bitstruct_in_subarray.c3t @@ -0,0 +1,26 @@ +// #target: macos-x64 +module test; +bitstruct StructFieldKind : char +{ + bool is_inline : 0; + bool is_union : 1; +} + +fn void main() +{ + StructFieldKind[] xx = { { .is_union = true } }; +} + +/* #expect: test.ll + + +define void @test.main() #0 { +entry: + %xx = alloca %"char[]", align 8 + %literal = alloca [1 x i8], align 1 + store i8 2, ptr %literal, align 1 + %0 = insertvalue %"char[]" undef, ptr %literal, 0 + %1 = insertvalue %"char[]" %0, i64 1, 1 + store %"char[]" %1, ptr %xx, align 8 + ret void +} \ No newline at end of file diff --git a/test/test_suite7/bitstruct/bitstruct_init.c3 b/test/test_suite7/bitstruct/bitstruct_init.c3 new file mode 100644 index 000000000..b7ba43915 --- /dev/null +++ b/test/test_suite7/bitstruct/bitstruct_init.c3 @@ -0,0 +1,104 @@ +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 +} + +bitstruct Flags1 : int +{ + bool a; + bool b; + bool c; +} + +distinct Bool = bool; + +bitstruct Flags2 : int +{ + bool a : 0; + Bool b : 1; + int c : 2..3; + bool d : 6; +} + +struct Flags2_Struct +{ + bool a; + bool b; + int c; + bool d; +} + +fn void test4() +{ + Flags1 flags1 = {.a, .b, .c}; + flags1 = {.a}; + flags1 = {.a = true, .b = true, .c = false}; + flags1 = {.a, .b = true, .c = true}; // #error: Mixing the omission + Foo foo = { .x = 0, .z }; // #error: needs a value + + Flags2 flags2 = {.b, .d}; + flags2 = {.b, .c, .d}; // #error: needs a value + flags2 = {.a, .c = 1, .d}; // #error: Mixing the omission + + Flags2_Struct flags2s; + flags2s = {.b, .c, .d}; // #error: needs a value + flags2s = {.a, .c = 1, .d}; // #error: needs a value +} diff --git a/test/test_suite7/bitstruct/bitstruct_init_bool.c3t b/test/test_suite7/bitstruct/bitstruct_init_bool.c3t new file mode 100644 index 000000000..e91b63457 --- /dev/null +++ b/test/test_suite7/bitstruct/bitstruct_init_bool.c3t @@ -0,0 +1,22 @@ +module foo; + +bitstruct Foo : int +{ + bool a : 1; + bool b : 2; + bool c : 3; +} + +fn void test() +{ + Foo f = { .a = true, .b = false }; +} + +/* #expect: foo.ll + +define void @foo.test() #0 { +entry: + %f = alloca i32, align 4 + store i32 2, ptr %f, align 4 + ret void +} \ No newline at end of file diff --git a/test/test_suite7/bitstruct/bitstruct_initializer.c3t b/test/test_suite7/bitstruct/bitstruct_initializer.c3t new file mode 100644 index 000000000..b20b1106a --- /dev/null +++ b/test/test_suite7/bitstruct/bitstruct_initializer.c3t @@ -0,0 +1,461 @@ +// #target: macos-x64 +module test; +import std::io; + +bitstruct Foo : ulong +{ + uint x : 0..31; + uint y : 32..62; + bool w : 63; +} + +bitstruct Bar : char[8] +{ + uint x : 0..31; + uint y : 32..62; + bool w : 63; +} +struct Abc +{ + int x; + Foo b; +} + +fn void hello(int z) +{ + Foo x; + x = { .x = z, .w = z < 100 }; + Abc y = { .b.x = 32, .b.y = 10 }; + Abc d = { .b = { 23, 11, true } }; + Bar b; + b = { .x = z, .w = z < 100 }; + io::printfn("%s %s %s", x.x, x.y, x.w); + io::printfn("%s %s %s", y.b.x, y.b.y, y.b.w); + io::printfn("%s %s %s", b.x, b.y, b.w); + x = { z + 1, 1, z > 100 }; + y.b = { 33, 11, true }; + b = { z + 1, 1, z > 100 }; + io::printfn("%s %s %s", x.x, x.y, x.w); + io::printfn("%s %s %s", y.b.x, y.b.y, y.b.w); + io::printfn("%s %s %s", b.x, b.y, b.w); + +} + +fn void main() +{ + hello(12); +} + +/* #expect: test.ll + +define void @test.hello(i32 %0) #0 { +entry: + %x = alloca i64, align 8 + %.assign_list = alloca i64, align 8 + %y = alloca %Abc, align 8 + %d = alloca %Abc, align 8 + %b = alloca [8 x i8], align 1 + %.assign_list10 = alloca [8 x i8], align 1 + %varargslots = alloca [3 x %any], align 16 + %taddr = alloca i32, align 4 + %taddr33 = alloca i32, align 4 + %taddr37 = alloca i8, align 1 + %retparam = alloca i64, align 8 + %varargslots39 = alloca [3 x %any], align 16 + %taddr42 = alloca i32, align 4 + %taddr46 = alloca i32, align 4 + %taddr51 = alloca i8, align 1 + %retparam53 = alloca i64, align 8 + %varargslots54 = alloca [3 x %any], align 16 + %taddr65 = alloca i32, align 4 + %taddr77 = alloca i32, align 4 + %taddr81 = alloca i8, align 1 + %retparam83 = alloca i64, align 8 + %.assign_list84 = alloca i64, align 8 + %.assign_list89 = alloca [8 x i8], align 1 + %varargslots116 = alloca [3 x %any], align 16 + %taddr118 = alloca i32, align 4 + %taddr121 = alloca i32, align 4 + %taddr125 = alloca i8, align 1 + %retparam127 = alloca i64, align 8 + %varargslots128 = alloca [3 x %any], align 16 + %taddr131 = alloca i32, align 4 + %taddr135 = alloca i32, align 4 + %taddr140 = alloca i8, align 1 + %retparam142 = alloca i64, align 8 + %varargslots143 = alloca [3 x %any], align 16 + %taddr154 = alloca i32, align 4 + %taddr166 = alloca i32, align 4 + %taddr170 = alloca i8, align 1 + %retparam172 = alloca i64, align 8 + store i64 0, ptr %x, align 8 + %zext = zext i32 %0 to i64 + %1 = and i64 %zext, 4294967295 + %lt = icmp slt i32 %0, 100 + %2 = zext i1 %lt to i8 + %zext1 = zext i8 %2 to i64 + %shl = shl i64 %zext1, 63 + %3 = and i64 %shl, -9223372036854775808 + %4 = and i64 %1, 9223372036854775807 + %5 = or i64 %4, %3 + store i64 %5, ptr %.assign_list, align 8 + %6 = load i64, ptr %.assign_list, align 8 + store i64 %6, ptr %x, align 8 + store i32 0, ptr %y, align 8 + %ptradd = getelementptr inbounds i8, ptr %y, i64 8 + store i64 42949672992, ptr %ptradd, align 8 + store i32 0, ptr %d, align 8 + %ptradd2 = getelementptr inbounds i8, ptr %d, i64 8 + store i64 -9223371989610135529, ptr %ptradd2, align 8 + store i8 0, ptr %b, align 1 + %ptradd3 = getelementptr inbounds i8, ptr %b, i64 1 + store i8 0, ptr %ptradd3, align 1 + %ptradd4 = getelementptr inbounds i8, ptr %b, i64 2 + store i8 0, ptr %ptradd4, align 1 + %ptradd5 = getelementptr inbounds i8, ptr %b, i64 3 + store i8 0, ptr %ptradd5, align 1 + %ptradd6 = getelementptr inbounds i8, ptr %b, i64 4 + store i8 0, ptr %ptradd6, align 1 + %ptradd7 = getelementptr inbounds i8, ptr %b, i64 5 + store i8 0, ptr %ptradd7, align 1 + %ptradd8 = getelementptr inbounds i8, ptr %b, i64 6 + store i8 0, ptr %ptradd8, align 1 + %ptradd9 = getelementptr inbounds i8, ptr %b, i64 7 + store i8 0, ptr %ptradd9, align 1 + store i8 0, ptr %.assign_list10, align 1 + %ptradd11 = getelementptr inbounds i8, ptr %.assign_list10, i64 1 + store i8 0, ptr %ptradd11, align 1 + %ptradd12 = getelementptr inbounds i8, ptr %.assign_list10, i64 2 + store i8 0, ptr %ptradd12, align 1 + %ptradd13 = getelementptr inbounds i8, ptr %.assign_list10, i64 3 + store i8 0, ptr %ptradd13, align 1 + %ptradd14 = getelementptr inbounds i8, ptr %.assign_list10, i64 4 + store i8 0, ptr %ptradd14, align 1 + %ptradd15 = getelementptr inbounds i8, ptr %.assign_list10, i64 5 + store i8 0, ptr %ptradd15, align 1 + %ptradd16 = getelementptr inbounds i8, ptr %.assign_list10, i64 6 + store i8 0, ptr %ptradd16, align 1 + %ptradd17 = getelementptr inbounds i8, ptr %.assign_list10, i64 7 + store i8 0, ptr %ptradd17, align 1 + %trunc = trunc i32 %0 to i8 + store i8 %trunc, ptr %.assign_list10, align 1 + %lshrl = lshr i32 %0, 8 + %ptradd18 = getelementptr inbounds i8, ptr %.assign_list10, i64 1 + %trunc19 = trunc i32 %lshrl to i8 + store i8 %trunc19, ptr %ptradd18, align 1 + %lshrl20 = lshr i32 %lshrl, 8 + %ptradd21 = getelementptr inbounds i8, ptr %.assign_list10, i64 2 + %trunc22 = trunc i32 %lshrl20 to i8 + store i8 %trunc22, ptr %ptradd21, align 1 + %lshrl23 = lshr i32 %lshrl20, 8 + %ptradd24 = getelementptr inbounds i8, ptr %.assign_list10, i64 3 + %trunc25 = trunc i32 %lshrl23 to i8 + store i8 %trunc25, ptr %ptradd24, align 1 + %lshrl26 = lshr i32 %lshrl23, 8 + %lt27 = icmp slt i32 %0, 100 + %7 = zext i1 %lt27 to i8 + %shl28 = shl i8 %7, 7 + %ptradd29 = getelementptr inbounds i8, ptr %.assign_list10, i64 7 + %8 = load i8, ptr %ptradd29, align 1 + %9 = and i8 %8, 127 + %10 = or i8 %9, %shl28 + store i8 %10, ptr %ptradd29, align 1 + call void @llvm.memcpy.p0.p0.i32(ptr align 1 %b, ptr align 1 %.assign_list10, i32 8, i1 false) + %11 = load i64, ptr %x, align 8 + %12 = and i64 4294967295, %11 + %trunc30 = trunc i64 %12 to i32 + store i32 %trunc30, ptr %taddr, align 4 + %13 = insertvalue %any undef, ptr %taddr, 0 + %14 = insertvalue %any %13, i64 ptrtoint (ptr @"$ct.uint" to i64), 1 + store %any %14, ptr %varargslots, align 16 + %15 = load i64, ptr %x, align 8 + %lshrl31 = lshr i64 %15, 32 + %16 = and i64 2147483647, %lshrl31 + %trunc32 = trunc i64 %16 to i32 + store i32 %trunc32, ptr %taddr33, align 4 + %17 = insertvalue %any undef, ptr %taddr33, 0 + %18 = insertvalue %any %17, i64 ptrtoint (ptr @"$ct.uint" to i64), 1 + %ptradd34 = getelementptr inbounds i8, ptr %varargslots, i64 16 + store %any %18, ptr %ptradd34, align 16 + %19 = load i64, ptr %x, align 8 + %lshrl35 = lshr i64 %19, 63 + %20 = and i64 1, %lshrl35 + %trunc36 = trunc i64 %20 to i8 + store i8 %trunc36, ptr %taddr37, align 1 + %21 = insertvalue %any undef, ptr %taddr37, 0 + %22 = insertvalue %any %21, i64 ptrtoint (ptr @"$ct.bool" to i64), 1 + %ptradd38 = getelementptr inbounds i8, ptr %varargslots, i64 32 + store %any %22, ptr %ptradd38, align 16 + %23 = call i64 @std.io.printfn(ptr %retparam, ptr @.str, i64 8, ptr %varargslots, i64 3) + %ptradd40 = getelementptr inbounds i8, ptr %y, i64 8 + %24 = load i64, ptr %ptradd40, align 8 + %25 = and i64 4294967295, %24 + %trunc41 = trunc i64 %25 to i32 + store i32 %trunc41, ptr %taddr42, align 4 + %26 = insertvalue %any undef, ptr %taddr42, 0 + %27 = insertvalue %any %26, i64 ptrtoint (ptr @"$ct.uint" to i64), 1 + store %any %27, ptr %varargslots39, align 16 + %ptradd43 = getelementptr inbounds i8, ptr %y, i64 8 + %28 = load i64, ptr %ptradd43, align 8 + %lshrl44 = lshr i64 %28, 32 + %29 = and i64 2147483647, %lshrl44 + %trunc45 = trunc i64 %29 to i32 + store i32 %trunc45, ptr %taddr46, align 4 + %30 = insertvalue %any undef, ptr %taddr46, 0 + %31 = insertvalue %any %30, i64 ptrtoint (ptr @"$ct.uint" to i64), 1 + %ptradd47 = getelementptr inbounds i8, ptr %varargslots39, i64 16 + store %any %31, ptr %ptradd47, align 16 + %ptradd48 = getelementptr inbounds i8, ptr %y, i64 8 + %32 = load i64, ptr %ptradd48, align 8 + %lshrl49 = lshr i64 %32, 63 + %33 = and i64 1, %lshrl49 + %trunc50 = trunc i64 %33 to i8 + store i8 %trunc50, ptr %taddr51, align 1 + %34 = insertvalue %any undef, ptr %taddr51, 0 + %35 = insertvalue %any %34, i64 ptrtoint (ptr @"$ct.bool" to i64), 1 + %ptradd52 = getelementptr inbounds i8, ptr %varargslots39, i64 32 + store %any %35, ptr %ptradd52, align 16 + %36 = call i64 @std.io.printfn(ptr %retparam53, ptr @.str.1, i64 8, ptr %varargslots39, i64 3) + %37 = load i8, ptr %b, align 1 + %zext55 = zext i8 %37 to i32 + %ptradd56 = getelementptr inbounds i8, ptr %b, i64 1 + %38 = load i8, ptr %ptradd56, align 1 + %zext57 = zext i8 %38 to i32 + %shl58 = shl i32 %zext57, 8 + %39 = or i32 %shl58, %zext55 + %ptradd59 = getelementptr inbounds i8, ptr %b, i64 2 + %40 = load i8, ptr %ptradd59, align 1 + %zext60 = zext i8 %40 to i32 + %shl61 = shl i32 %zext60, 16 + %41 = or i32 %shl61, %39 + %ptradd62 = getelementptr inbounds i8, ptr %b, i64 3 + %42 = load i8, ptr %ptradd62, align 1 + %zext63 = zext i8 %42 to i32 + %shl64 = shl i32 %zext63, 24 + %43 = or i32 %shl64, %41 + store i32 %43, ptr %taddr65, align 4 + %44 = insertvalue %any undef, ptr %taddr65, 0 + %45 = insertvalue %any %44, i64 ptrtoint (ptr @"$ct.uint" to i64), 1 + store %any %45, ptr %varargslots54, align 16 + %ptradd66 = getelementptr inbounds i8, ptr %b, i64 4 + %46 = load i8, ptr %ptradd66, align 1 + %zext67 = zext i8 %46 to i32 + %ptradd68 = getelementptr inbounds i8, ptr %b, i64 5 + %47 = load i8, ptr %ptradd68, align 1 + %zext69 = zext i8 %47 to i32 + %shl70 = shl i32 %zext69, 8 + %48 = or i32 %shl70, %zext67 + %ptradd71 = getelementptr inbounds i8, ptr %b, i64 6 + %49 = load i8, ptr %ptradd71, align 1 + %zext72 = zext i8 %49 to i32 + %shl73 = shl i32 %zext72, 16 + %50 = or i32 %shl73, %48 + %ptradd74 = getelementptr inbounds i8, ptr %b, i64 7 + %51 = load i8, ptr %ptradd74, align 1 + %zext75 = zext i8 %51 to i32 + %shl76 = shl i32 %zext75, 24 + %52 = or i32 %shl76, %50 + %53 = and i32 2147483647, %52 + store i32 %53, ptr %taddr77, align 4 + %54 = insertvalue %any undef, ptr %taddr77, 0 + %55 = insertvalue %any %54, i64 ptrtoint (ptr @"$ct.uint" to i64), 1 + %ptradd78 = getelementptr inbounds i8, ptr %varargslots54, i64 16 + store %any %55, ptr %ptradd78, align 16 + %ptradd79 = getelementptr inbounds i8, ptr %b, i64 7 + %56 = load i8, ptr %ptradd79, align 1 + %lshrl80 = lshr i8 %56, 7 + %57 = trunc i8 %lshrl80 to i1 + %58 = zext i1 %57 to i8 + store i8 %58, ptr %taddr81, align 1 + %59 = insertvalue %any undef, ptr %taddr81, 0 + %60 = insertvalue %any %59, i64 ptrtoint (ptr @"$ct.bool" to i64), 1 + %ptradd82 = getelementptr inbounds i8, ptr %varargslots54, i64 32 + store %any %60, ptr %ptradd82, align 16 + %61 = call i64 @std.io.printfn(ptr %retparam83, ptr @.str.2, i64 8, ptr %varargslots54, i64 3) + %add = add i32 %0, 1 + %zext85 = zext i32 %add to i64 + %62 = and i64 %zext85, 4294967295 + %63 = and i64 %62, -9223372032559808513 + %64 = or i64 %63, 4294967296 + %gt = icmp sgt i32 %0, 100 + %65 = zext i1 %gt to i8 + %zext86 = zext i8 %65 to i64 + %shl87 = shl i64 %zext86, 63 + %66 = and i64 %shl87, -9223372036854775808 + %67 = and i64 %64, 9223372036854775807 + %68 = or i64 %67, %66 + store i64 %68, ptr %.assign_list84, align 8 + %69 = load i64, ptr %.assign_list84, align 8 + store i64 %69, ptr %x, align 8 + %ptradd88 = getelementptr inbounds i8, ptr %y, i64 8 + store i64 -9223371989610135519, ptr %ptradd88, align 8 + store i8 0, ptr %.assign_list89, align 1 + %ptradd90 = getelementptr inbounds i8, ptr %.assign_list89, i64 1 + store i8 0, ptr %ptradd90, align 1 + %ptradd91 = getelementptr inbounds i8, ptr %.assign_list89, i64 2 + store i8 0, ptr %ptradd91, align 1 + %ptradd92 = getelementptr inbounds i8, ptr %.assign_list89, i64 3 + store i8 0, ptr %ptradd92, align 1 + %ptradd93 = getelementptr inbounds i8, ptr %.assign_list89, i64 4 + store i8 0, ptr %ptradd93, align 1 + %ptradd94 = getelementptr inbounds i8, ptr %.assign_list89, i64 5 + store i8 0, ptr %ptradd94, align 1 + %ptradd95 = getelementptr inbounds i8, ptr %.assign_list89, i64 6 + store i8 0, ptr %ptradd95, align 1 + %ptradd96 = getelementptr inbounds i8, ptr %.assign_list89, i64 7 + store i8 0, ptr %ptradd96, align 1 + %add97 = add i32 %0, 1 + %trunc98 = trunc i32 %add97 to i8 + store i8 %trunc98, ptr %.assign_list89, align 1 + %lshrl99 = lshr i32 %add97, 8 + %ptradd100 = getelementptr inbounds i8, ptr %.assign_list89, i64 1 + %trunc101 = trunc i32 %lshrl99 to i8 + store i8 %trunc101, ptr %ptradd100, align 1 + %lshrl102 = lshr i32 %lshrl99, 8 + %ptradd103 = getelementptr inbounds i8, ptr %.assign_list89, i64 2 + %trunc104 = trunc i32 %lshrl102 to i8 + store i8 %trunc104, ptr %ptradd103, align 1 + %lshrl105 = lshr i32 %lshrl102, 8 + %ptradd106 = getelementptr inbounds i8, ptr %.assign_list89, i64 3 + %trunc107 = trunc i32 %lshrl105 to i8 + store i8 %trunc107, ptr %ptradd106, align 1 + %lshrl108 = lshr i32 %lshrl105, 8 + %ptradd109 = getelementptr inbounds i8, ptr %.assign_list89, i64 4 + store i8 1, ptr %ptradd109, align 1 + %ptradd110 = getelementptr inbounds i8, ptr %.assign_list89, i64 5 + store i8 0, ptr %ptradd110, align 1 + %ptradd111 = getelementptr inbounds i8, ptr %.assign_list89, i64 6 + store i8 0, ptr %ptradd111, align 1 + %ptradd112 = getelementptr inbounds i8, ptr %.assign_list89, i64 7 + %70 = load i8, ptr %ptradd112, align 1 + %71 = and i8 %70, -128 + store i8 %71, ptr %ptradd112, align 1 + %gt113 = icmp sgt i32 %0, 100 + %72 = zext i1 %gt113 to i8 + %shl114 = shl i8 %72, 7 + %ptradd115 = getelementptr inbounds i8, ptr %.assign_list89, i64 7 + %73 = load i8, ptr %ptradd115, align 1 + %74 = and i8 %73, 127 + %75 = or i8 %74, %shl114 + store i8 %75, ptr %ptradd115, align 1 + call void @llvm.memcpy.p0.p0.i32(ptr align 1 %b, ptr align 1 %.assign_list89, i32 8, i1 false) + %76 = load i64, ptr %x, align 8 + %77 = and i64 4294967295, %76 + %trunc117 = trunc i64 %77 to i32 + store i32 %trunc117, ptr %taddr118, align 4 + %78 = insertvalue %any undef, ptr %taddr118, 0 + %79 = insertvalue %any %78, i64 ptrtoint (ptr @"$ct.uint" to i64), 1 + store %any %79, ptr %varargslots116, align 16 + %80 = load i64, ptr %x, align 8 + %lshrl119 = lshr i64 %80, 32 + %81 = and i64 2147483647, %lshrl119 + %trunc120 = trunc i64 %81 to i32 + store i32 %trunc120, ptr %taddr121, align 4 + %82 = insertvalue %any undef, ptr %taddr121, 0 + %83 = insertvalue %any %82, i64 ptrtoint (ptr @"$ct.uint" to i64), 1 + %ptradd122 = getelementptr inbounds i8, ptr %varargslots116, i64 16 + store %any %83, ptr %ptradd122, align 16 + %84 = load i64, ptr %x, align 8 + %lshrl123 = lshr i64 %84, 63 + %85 = and i64 1, %lshrl123 + %trunc124 = trunc i64 %85 to i8 + store i8 %trunc124, ptr %taddr125, align 1 + %86 = insertvalue %any undef, ptr %taddr125, 0 + %87 = insertvalue %any %86, i64 ptrtoint (ptr @"$ct.bool" to i64), 1 + %ptradd126 = getelementptr inbounds i8, ptr %varargslots116, i64 32 + store %any %87, ptr %ptradd126, align 16 + %88 = call i64 @std.io.printfn(ptr %retparam127, ptr @.str.3, i64 8, ptr %varargslots116, i64 3) + %ptradd129 = getelementptr inbounds i8, ptr %y, i64 8 + %89 = load i64, ptr %ptradd129, align 8 + %90 = and i64 4294967295, %89 + %trunc130 = trunc i64 %90 to i32 + store i32 %trunc130, ptr %taddr131, align 4 + %91 = insertvalue %any undef, ptr %taddr131, 0 + %92 = insertvalue %any %91, i64 ptrtoint (ptr @"$ct.uint" to i64), 1 + store %any %92, ptr %varargslots128, align 16 + %ptradd132 = getelementptr inbounds i8, ptr %y, i64 8 + %93 = load i64, ptr %ptradd132, align 8 + %lshrl133 = lshr i64 %93, 32 + %94 = and i64 2147483647, %lshrl133 + %trunc134 = trunc i64 %94 to i32 + store i32 %trunc134, ptr %taddr135, align 4 + %95 = insertvalue %any undef, ptr %taddr135, 0 + %96 = insertvalue %any %95, i64 ptrtoint (ptr @"$ct.uint" to i64), 1 + %ptradd136 = getelementptr inbounds i8, ptr %varargslots128, i64 16 + store %any %96, ptr %ptradd136, align 16 + %ptradd137 = getelementptr inbounds i8, ptr %y, i64 8 + %97 = load i64, ptr %ptradd137, align 8 + %lshrl138 = lshr i64 %97, 63 + %98 = and i64 1, %lshrl138 + %trunc139 = trunc i64 %98 to i8 + store i8 %trunc139, ptr %taddr140, align 1 + %99 = insertvalue %any undef, ptr %taddr140, 0 + %100 = insertvalue %any %99, i64 ptrtoint (ptr @"$ct.bool" to i64), 1 + %ptradd141 = getelementptr inbounds i8, ptr %varargslots128, i64 32 + store %any %100, ptr %ptradd141, align 16 + %101 = call i64 @std.io.printfn(ptr %retparam142, ptr @.str.4, i64 8, ptr %varargslots128, i64 3) + %102 = load i8, ptr %b, align 1 + %zext144 = zext i8 %102 to i32 + %ptradd145 = getelementptr inbounds i8, ptr %b, i64 1 + %103 = load i8, ptr %ptradd145, align 1 + %zext146 = zext i8 %103 to i32 + %shl147 = shl i32 %zext146, 8 + %104 = or i32 %shl147, %zext144 + %ptradd148 = getelementptr inbounds i8, ptr %b, i64 2 + %105 = load i8, ptr %ptradd148, align 1 + %zext149 = zext i8 %105 to i32 + %shl150 = shl i32 %zext149, 16 + %106 = or i32 %shl150, %104 + %ptradd151 = getelementptr inbounds i8, ptr %b, i64 3 + %107 = load i8, ptr %ptradd151, align 1 + %zext152 = zext i8 %107 to i32 + %shl153 = shl i32 %zext152, 24 + %108 = or i32 %shl153, %106 + store i32 %108, ptr %taddr154, align 4 + %109 = insertvalue %any undef, ptr %taddr154, 0 + %110 = insertvalue %any %109, i64 ptrtoint (ptr @"$ct.uint" to i64), 1 + store %any %110, ptr %varargslots143, align 16 + %ptradd155 = getelementptr inbounds i8, ptr %b, i64 4 + %111 = load i8, ptr %ptradd155, align 1 + %zext156 = zext i8 %111 to i32 + %ptradd157 = getelementptr inbounds i8, ptr %b, i64 5 + %112 = load i8, ptr %ptradd157, align 1 + %zext158 = zext i8 %112 to i32 + %shl159 = shl i32 %zext158, 8 + %113 = or i32 %shl159, %zext156 + %ptradd160 = getelementptr inbounds i8, ptr %b, i64 6 + %114 = load i8, ptr %ptradd160, align 1 + %zext161 = zext i8 %114 to i32 + %shl162 = shl i32 %zext161, 16 + %115 = or i32 %shl162, %113 + %ptradd163 = getelementptr inbounds i8, ptr %b, i64 7 + %116 = load i8, ptr %ptradd163, align 1 + %zext164 = zext i8 %116 to i32 + %shl165 = shl i32 %zext164, 24 + %117 = or i32 %shl165, %115 + %118 = and i32 2147483647, %117 + store i32 %118, ptr %taddr166, align 4 + %119 = insertvalue %any undef, ptr %taddr166, 0 + %120 = insertvalue %any %119, i64 ptrtoint (ptr @"$ct.uint" to i64), 1 + %ptradd167 = getelementptr inbounds i8, ptr %varargslots143, i64 16 + store %any %120, ptr %ptradd167, align 16 + %ptradd168 = getelementptr inbounds i8, ptr %b, i64 7 + %121 = load i8, ptr %ptradd168, align 1 + %lshrl169 = lshr i8 %121, 7 + %122 = trunc i8 %lshrl169 to i1 + %123 = zext i1 %122 to i8 + store i8 %123, ptr %taddr170, align 1 + %124 = insertvalue %any undef, ptr %taddr170, 0 + %125 = insertvalue %any %124, i64 ptrtoint (ptr @"$ct.bool" to i64), 1 + %ptradd171 = getelementptr inbounds i8, ptr %varargslots143, i64 32 + store %any %125, ptr %ptradd171, align 16 + %126 = call i64 @std.io.printfn(ptr %retparam172, ptr @.str.5, i64 8, ptr %varargslots143, i64 3) + ret void +} + +; Function Attrs: nounwind uwtable +define void @test.main() #0 { +entry: + call void @test.hello(i32 12) + ret void +} diff --git a/test/test_suite7/bitstruct/bitstruct_intcontainer.c3t b/test/test_suite7/bitstruct/bitstruct_intcontainer.c3t new file mode 100644 index 000000000..ce26f7058 --- /dev/null +++ b/test/test_suite7/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 + %shl = shl i32 %0, 9 + %ashr = ashr i32 %shl, 14 + call void (ptr, ...) @printf(ptr @.str, i32 %ashr) + store i32 1073741375, ptr %xx, align 4 + %1 = load i32, ptr %xx, align 4 + %shl1 = shl i32 %1, 9 + %ashr2 = ashr i32 %shl1, 14 + call void (ptr, ...) @printf(ptr @.str.1, i32 %ashr2) + store i32 -3485921, ptr %xxu, align 4 + %2 = load i32, ptr %xxu, align 4 + %lshrl = lshr i32 %2, 5 + %3 = and i32 262143, %lshrl + call void (ptr, ...) @printf(ptr @.str.2, i32 %3) + store i64 1525363991714123551, ptr %xxy, align 8 + %4 = load i64, ptr %xxy, align 8 + %lshrl3 = lshr i64 %4, 5 + %5 = and i64 262143, %lshrl3 + %trunc = trunc i64 %5 to i32 + %6 = load i64, ptr %xxy, align 8 + %lshrl4 = lshr i64 %6, 23 + %7 = and i64 262143, %lshrl4 + %trunc5 = trunc i64 %7 to i32 + %8 = load i64, ptr %xxy, align 8 + %lshrl6 = lshr i64 %8, 41 + %9 = and i64 2097151, %lshrl6 + %trunc7 = trunc i64 %9 to i32 + call void (ptr, ...) @printf(ptr @.str.3, i32 %trunc, i32 %trunc5, i32 %trunc7) + store i64 2292133196431502101, ptr %xxybe, align 8 + %10 = load i64, ptr %xxybe, align 8 + %11 = call i64 @llvm.bswap.i64(i64 %10) + %lshrl8 = lshr i64 %11, 5 + %12 = and i64 262143, %lshrl8 + %trunc9 = trunc i64 %12 to i32 + %13 = load i64, ptr %xxybe, align 8 + %14 = call i64 @llvm.bswap.i64(i64 %13) + %lshrl10 = lshr i64 %14, 23 + %15 = and i64 262143, %lshrl10 + %trunc11 = trunc i64 %15 to i32 + %16 = load i64, ptr %xxybe, align 8 + %17 = call i64 @llvm.bswap.i64(i64 %16) + %lshrl12 = lshr i64 %17, 41 + %18 = and i64 2097151, %lshrl12 + %trunc13 = trunc i64 %18 to i32 + call void (ptr, ...) @printf(ptr @.str.4, i32 %trunc9, i32 %trunc11, i32 %trunc13) + ret void +} \ No newline at end of file diff --git a/test/test_suite7/bitstruct/bitstruct_ops.c3t b/test/test_suite7/bitstruct/bitstruct_ops.c3t new file mode 100644 index 000000000..f6439f669 --- /dev/null +++ b/test/test_suite7/bitstruct/bitstruct_ops.c3t @@ -0,0 +1,276 @@ +// #target: macos-x64 +module test; +import std::io; + +bitstruct Foo : int +{ + bool a : 0; + bool b : 1; +} + +bitstruct Bar : char[13] +{ + bool z : 0; + bool w : 1; + bool gh : 25; +} +fn void main() +{ + Foo f1 = { true, true }; + Foo f2 = { true, false }; + + Foo f3 = f1 & f2; + io::printfn("%s %s", f3.a, f3.b); + Foo f4 = (f1 | ~f2) ^ f3; + io::printfn("%s %s", f4.a, f4.b); + Foo f5 = (Foo) { true, false } | (Foo) { false, true }; + io::printfn("%s %s", f5.a, f5.b); + + f5 &= f2; + io::printfn("%s %s", f5.a, f5.b); + + Bar b1 = { true, true, true }; + Bar b2 = { true, false, false }; + + Bar b3 = b1 & b2; + io::printfn("%s %s %s", b3.z, b3.w, b3.gh); + b3 = ~b3; + io::printfn("%s %s %s", b3.z, b3.w, b3.gh); + b3 ^= (Bar) { true, true, false }; + io::printfn("%s %s %s", b3.z, b3.w, b3.gh); +} + +/* #expect: test.ll + +define void @test.main() #0 { +entry: + %f1 = alloca i32, align 4 + %f2 = alloca i32, align 4 + %f3 = alloca i32, align 4 + %varargslots = alloca [2 x %any], align 16 + %taddr = alloca i8, align 1 + %taddr2 = alloca i8, align 1 + %retparam = alloca i64, align 8 + %f4 = alloca i32, align 4 + %varargslots3 = alloca [2 x %any], align 16 + %taddr5 = alloca i8, align 1 + %taddr8 = alloca i8, align 1 + %retparam10 = alloca i64, align 8 + %f5 = alloca i32, align 4 + %varargslots11 = alloca [2 x %any], align 16 + %taddr13 = alloca i8, align 1 + %taddr16 = alloca i8, align 1 + %retparam18 = alloca i64, align 8 + %varargslots20 = alloca [2 x %any], align 16 + %taddr22 = alloca i8, align 1 + %taddr25 = alloca i8, align 1 + %retparam27 = alloca i64, align 8 + %b1 = alloca [13 x i8], align 1 + %b2 = alloca [13 x i8], align 1 + %b3 = alloca [13 x i8], align 1 + %0 = alloca i104, align 1 + %varargslots29 = alloca [3 x %any], align 16 + %taddr30 = alloca i8, align 1 + %taddr32 = alloca i8, align 1 + %taddr36 = alloca i8, align 1 + %retparam38 = alloca i64, align 8 + %1 = alloca i104, align 1 + %varargslots40 = alloca [3 x %any], align 16 + %taddr41 = alloca i8, align 1 + %taddr43 = alloca i8, align 1 + %taddr47 = alloca i8, align 1 + %retparam49 = alloca i64, align 8 + %taddr50 = alloca [13 x i8], align 1 + %2 = alloca i104, align 1 + %varargslots52 = alloca [3 x %any], align 16 + %taddr53 = alloca i8, align 1 + %taddr55 = alloca i8, align 1 + %taddr59 = alloca i8, align 1 + %retparam61 = alloca i64, align 8 + store i32 3, ptr %f1, align 4 + store i32 1, ptr %f2, align 4 + %3 = load i32, ptr %f1, align 4 + %4 = load i32, ptr %f2, align 4 + %and = and i32 %3, %4 + store i32 %and, ptr %f3, align 4 + %5 = load i32, ptr %f3, align 4 + %6 = and i32 1, %5 + %trunc = trunc i32 %6 to i8 + store i8 %trunc, ptr %taddr, align 1 + %7 = insertvalue %any undef, ptr %taddr, 0 + %8 = insertvalue %any %7, i64 ptrtoint (ptr @"$ct.bool" to i64), 1 + store %any %8, ptr %varargslots, align 16 + %9 = load i32, ptr %f3, align 4 + %lshrl = lshr i32 %9, 1 + %10 = and i32 1, %lshrl + %trunc1 = trunc i32 %10 to i8 + store i8 %trunc1, ptr %taddr2, align 1 + %11 = insertvalue %any undef, ptr %taddr2, 0 + %12 = insertvalue %any %11, i64 ptrtoint (ptr @"$ct.bool" to i64), 1 + %ptradd = getelementptr inbounds i8, ptr %varargslots, i64 16 + store %any %12, ptr %ptradd, align 16 + %13 = call i64 @std.io.printfn(ptr %retparam, ptr @.str, i64 5, ptr %varargslots, i64 2) + %14 = load i32, ptr %f1, align 4 + %15 = load i32, ptr %f2, align 4 + %bnot = xor i32 %15, -1 + %or = or i32 %14, %bnot + %16 = load i32, ptr %f3, align 4 + %xor = xor i32 %or, %16 + store i32 %xor, ptr %f4, align 4 + %17 = load i32, ptr %f4, align 4 + %18 = and i32 1, %17 + %trunc4 = trunc i32 %18 to i8 + store i8 %trunc4, ptr %taddr5, align 1 + %19 = insertvalue %any undef, ptr %taddr5, 0 + %20 = insertvalue %any %19, i64 ptrtoint (ptr @"$ct.bool" to i64), 1 + store %any %20, ptr %varargslots3, align 16 + %21 = load i32, ptr %f4, align 4 + %lshrl6 = lshr i32 %21, 1 + %22 = and i32 1, %lshrl6 + %trunc7 = trunc i32 %22 to i8 + store i8 %trunc7, ptr %taddr8, align 1 + %23 = insertvalue %any undef, ptr %taddr8, 0 + %24 = insertvalue %any %23, i64 ptrtoint (ptr @"$ct.bool" to i64), 1 + %ptradd9 = getelementptr inbounds i8, ptr %varargslots3, i64 16 + store %any %24, ptr %ptradd9, align 16 + %25 = call i64 @std.io.printfn(ptr %retparam10, ptr @.str.1, i64 5, ptr %varargslots3, i64 2) + store i32 3, ptr %f5, align 4 + %26 = load i32, ptr %f5, align 4 + %27 = and i32 1, %26 + %trunc12 = trunc i32 %27 to i8 + store i8 %trunc12, ptr %taddr13, align 1 + %28 = insertvalue %any undef, ptr %taddr13, 0 + %29 = insertvalue %any %28, i64 ptrtoint (ptr @"$ct.bool" to i64), 1 + store %any %29, ptr %varargslots11, align 16 + %30 = load i32, ptr %f5, align 4 + %lshrl14 = lshr i32 %30, 1 + %31 = and i32 1, %lshrl14 + %trunc15 = trunc i32 %31 to i8 + store i8 %trunc15, ptr %taddr16, align 1 + %32 = insertvalue %any undef, ptr %taddr16, 0 + %33 = insertvalue %any %32, i64 ptrtoint (ptr @"$ct.bool" to i64), 1 + %ptradd17 = getelementptr inbounds i8, ptr %varargslots11, i64 16 + store %any %33, ptr %ptradd17, align 16 + %34 = call i64 @std.io.printfn(ptr %retparam18, ptr @.str.2, i64 5, ptr %varargslots11, i64 2) + %35 = load i32, ptr %f5, align 4 + %36 = load i32, ptr %f2, align 4 + %and19 = and i32 %35, %36 + store i32 %and19, ptr %f5, align 4 + %37 = load i32, ptr %f5, align 4 + %38 = and i32 1, %37 + %trunc21 = trunc i32 %38 to i8 + store i8 %trunc21, ptr %taddr22, align 1 + %39 = insertvalue %any undef, ptr %taddr22, 0 + %40 = insertvalue %any %39, i64 ptrtoint (ptr @"$ct.bool" to i64), 1 + store %any %40, ptr %varargslots20, align 16 + %41 = load i32, ptr %f5, align 4 + %lshrl23 = lshr i32 %41, 1 + %42 = and i32 1, %lshrl23 + %trunc24 = trunc i32 %42 to i8 + store i8 %trunc24, ptr %taddr25, align 1 + %43 = insertvalue %any undef, ptr %taddr25, 0 + %44 = insertvalue %any %43, i64 ptrtoint (ptr @"$ct.bool" to i64), 1 + %ptradd26 = getelementptr inbounds i8, ptr %varargslots20, i64 16 + store %any %44, ptr %ptradd26, align 16 + %45 = call i64 @std.io.printfn(ptr %retparam27, ptr @.str.3, i64 5, ptr %varargslots20, i64 2) + store [13 x i8] c"\03\00\00\02\00\00\00\00\00\00\00\00\00", ptr %b1, align 1 + store [13 x i8] c"\01\00\00\00\00\00\00\00\00\00\00\00\00", ptr %b2, align 1 + %46 = load i104, ptr %b1, align 1 + %47 = load i104, ptr %b2, align 1 + %and28 = and i104 %46, %47 + store i104 %and28, ptr %0, align 1 + call void @llvm.memcpy.p0.p0.i32(ptr align 1 %b3, ptr align 1 %0, i32 13, i1 false) + %48 = load i8, ptr %b3, align 1 + %49 = trunc i8 %48 to i1 + %50 = zext i1 %49 to i8 + store i8 %50, ptr %taddr30, align 1 + %51 = insertvalue %any undef, ptr %taddr30, 0 + %52 = insertvalue %any %51, i64 ptrtoint (ptr @"$ct.bool" to i64), 1 + store %any %52, ptr %varargslots29, align 16 + %53 = load i8, ptr %b3, align 1 + %lshrl31 = lshr i8 %53, 1 + %54 = trunc i8 %lshrl31 to i1 + %55 = zext i1 %54 to i8 + store i8 %55, ptr %taddr32, align 1 + %56 = insertvalue %any undef, ptr %taddr32, 0 + %57 = insertvalue %any %56, i64 ptrtoint (ptr @"$ct.bool" to i64), 1 + %ptradd33 = getelementptr inbounds i8, ptr %varargslots29, i64 16 + store %any %57, ptr %ptradd33, align 16 + %ptradd34 = getelementptr inbounds i8, ptr %b3, i64 3 + %58 = load i8, ptr %ptradd34, align 1 + %lshrl35 = lshr i8 %58, 1 + %59 = trunc i8 %lshrl35 to i1 + %60 = zext i1 %59 to i8 + store i8 %60, ptr %taddr36, align 1 + %61 = insertvalue %any undef, ptr %taddr36, 0 + %62 = insertvalue %any %61, i64 ptrtoint (ptr @"$ct.bool" to i64), 1 + %ptradd37 = getelementptr inbounds i8, ptr %varargslots29, i64 32 + store %any %62, ptr %ptradd37, align 16 + %63 = call i64 @std.io.printfn(ptr %retparam38, ptr @.str.4, i64 8, ptr %varargslots29, i64 3) + %64 = load i104, ptr %b3, align 1 + %bnot39 = xor i104 %64, -1 + store i104 %bnot39, ptr %1, align 1 + call void @llvm.memcpy.p0.p0.i32(ptr align 1 %b3, ptr align 1 %1, i32 13, i1 false) + %65 = load i8, ptr %b3, align 1 + %66 = trunc i8 %65 to i1 + %67 = zext i1 %66 to i8 + store i8 %67, ptr %taddr41, align 1 + %68 = insertvalue %any undef, ptr %taddr41, 0 + %69 = insertvalue %any %68, i64 ptrtoint (ptr @"$ct.bool" to i64), 1 + store %any %69, ptr %varargslots40, align 16 + %70 = load i8, ptr %b3, align 1 + %lshrl42 = lshr i8 %70, 1 + %71 = trunc i8 %lshrl42 to i1 + %72 = zext i1 %71 to i8 + store i8 %72, ptr %taddr43, align 1 + %73 = insertvalue %any undef, ptr %taddr43, 0 + %74 = insertvalue %any %73, i64 ptrtoint (ptr @"$ct.bool" to i64), 1 + %ptradd44 = getelementptr inbounds i8, ptr %varargslots40, i64 16 + store %any %74, ptr %ptradd44, align 16 + %ptradd45 = getelementptr inbounds i8, ptr %b3, i64 3 + %75 = load i8, ptr %ptradd45, align 1 + %lshrl46 = lshr i8 %75, 1 + %76 = trunc i8 %lshrl46 to i1 + %77 = zext i1 %76 to i8 + store i8 %77, ptr %taddr47, align 1 + %78 = insertvalue %any undef, ptr %taddr47, 0 + %79 = insertvalue %any %78, i64 ptrtoint (ptr @"$ct.bool" to i64), 1 + %ptradd48 = getelementptr inbounds i8, ptr %varargslots40, i64 32 + store %any %79, ptr %ptradd48, align 16 + %80 = call i64 @std.io.printfn(ptr %retparam49, ptr @.str.5, i64 8, ptr %varargslots40, i64 3) + store [13 x i8] c"\03\00\00\00\00\00\00\00\00\00\00\00\00", ptr %taddr50, align 1 + %81 = load i104, ptr %b3, align 1 + %82 = load i104, ptr %taddr50, align 1 + %xor51 = xor i104 %81, %82 + store i104 %xor51, ptr %2, align 1 + call void @llvm.memcpy.p0.p0.i32(ptr align 1 %b3, ptr align 1 %2, i32 13, i1 false) + %83 = load i8, ptr %b3, align 1 + %84 = trunc i8 %83 to i1 + %85 = zext i1 %84 to i8 + store i8 %85, ptr %taddr53, align 1 + %86 = insertvalue %any undef, ptr %taddr53, 0 + %87 = insertvalue %any %86, i64 ptrtoint (ptr @"$ct.bool" to i64), 1 + store %any %87, ptr %varargslots52, align 16 + %88 = load i8, ptr %b3, align 1 + %lshrl54 = lshr i8 %88, 1 + %89 = trunc i8 %lshrl54 to i1 + %90 = zext i1 %89 to i8 + store i8 %90, ptr %taddr55, align 1 + %91 = insertvalue %any undef, ptr %taddr55, 0 + %92 = insertvalue %any %91, i64 ptrtoint (ptr @"$ct.bool" to i64), 1 + %ptradd56 = getelementptr inbounds i8, ptr %varargslots52, i64 16 + store %any %92, ptr %ptradd56, align 16 + %ptradd57 = getelementptr inbounds i8, ptr %b3, i64 3 + %93 = load i8, ptr %ptradd57, align 1 + %lshrl58 = lshr i8 %93, 1 + %94 = trunc i8 %lshrl58 to i1 + %95 = zext i1 %94 to i8 + store i8 %95, ptr %taddr59, align 1 + %96 = insertvalue %any undef, ptr %taddr59, 0 + %97 = insertvalue %any %96, i64 ptrtoint (ptr @"$ct.bool" to i64), 1 + %ptradd60 = getelementptr inbounds i8, ptr %varargslots52, i64 32 + store %any %97, ptr %ptradd60, align 16 + %98 = call i64 @std.io.printfn(ptr %retparam61, ptr @.str.6, i64 8, ptr %varargslots52, i64 3) + ret void +} + diff --git a/test/test_suite7/bitstruct/bitstruct_overlap.c3 b/test/test_suite7/bitstruct/bitstruct_overlap.c3 new file mode 100644 index 000000000..bbee3b194 --- /dev/null +++ b/test/test_suite7/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_suite7/bitstruct/bitstruct_simple.c3 b/test/test_suite7/bitstruct/bitstruct_simple.c3 new file mode 100644 index 000000000..e9be8ab1c --- /dev/null +++ b/test/test_suite7/bitstruct/bitstruct_simple.c3 @@ -0,0 +1,18 @@ +bitstruct Foo : char +{ + bool a; + int b; // #error: For bitstructs without bit ranges, the types must all be 'bool' +} + +bitstruct Foo2 : char +{ + bool a0; + bool a1; + bool a2; + bool a3; + bool a4; + bool a5; + bool a6; + bool a7; + bool a8; // #error: overflow +} \ No newline at end of file diff --git a/test/test_suite7/bitstruct/bitstruct_simple_err_decl.c3 b/test/test_suite7/bitstruct/bitstruct_simple_err_decl.c3 new file mode 100644 index 000000000..f4909c0ac --- /dev/null +++ b/test/test_suite7/bitstruct/bitstruct_simple_err_decl.c3 @@ -0,0 +1,11 @@ +bitstruct Foo : char +{ + bool a : 1; + bool b; // #error: remove ranges from the other member +} + +bitstruct Foo2 : char +{ + bool a; + bool b : 1; // #error: ranges to all other members +} \ No newline at end of file diff --git a/test/test_suite7/bitstruct/bitstruct_single_error.c3 b/test/test_suite7/bitstruct/bitstruct_single_error.c3 new file mode 100644 index 000000000..663cf196c --- /dev/null +++ b/test/test_suite7/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_suite7/bitstruct/bitstruct_to_int.c3t b/test/test_suite7/bitstruct/bitstruct_to_int.c3t new file mode 100644 index 000000000..5cb104e55 --- /dev/null +++ b/test/test_suite7/bitstruct/bitstruct_to_int.c3t @@ -0,0 +1,108 @@ +// #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 = bitcast(b, char[4]); + 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 = bitcast(b, int); + 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 + %expr = alloca i32, align 4 + %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 i32, ptr %b, align 4 + store i32 %1, ptr %expr, align 4 + call void @llvm.memcpy.p0.p0.i32(ptr align 1 %y, ptr align 1 %expr, i32 4, i1 false) + store ptr %b, ptr %c, align 8 + %2 = load ptr, ptr %c, align 8 + %3 = load i32, ptr %2, align 4 + %shl = shl i32 %3, 28 + %ashr = ashr i32 %shl, 29 + %4 = load ptr, ptr %c, align 8 + store ptr %4, ptr %x2, align 8 + %5 = load ptr, ptr %c, align 8 + store ptr %5, ptr %y2, align 8 + ret void +} + +; Function Attrs: +define void @foo.test2() #0 { +entry: + %b = alloca [4 x i8], align 1 + %x = alloca i32, align 4 + %expr = alloca [4 x i8], align 1 + %x1 = 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 + call void @llvm.memcpy.p0.p0.i32(ptr align 1 %expr, ptr align 1 %b, i32 4, i1 false) + call void @llvm.memcpy.p0.p0.i64(ptr align 4 %x1, ptr align 1 %expr, i64 4, i1 false) + %0 = load i32, ptr %x1, align 4 + 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 = load i8, ptr %1, align 1 + %zext = zext i8 %2 to i32 + %lshrl = lshr i32 %zext, 1 + %shl = shl i32 %lshrl, 29 + %ashr = ashr i32 %shl, 29 + call void (ptr, ...) @printf(ptr @.str, i32 %ashr) + %3 = load ptr, ptr %c, align 8 + store ptr %3, ptr %x2, align 8 + %4 = load ptr, ptr %c, align 8 + store ptr %4, ptr %y2, align 8 + ret void +} \ No newline at end of file diff --git a/test/test_suite7/bitstruct/designated_initializer_with_bitstruct.c3t b/test/test_suite7/bitstruct/designated_initializer_with_bitstruct.c3t new file mode 100644 index 000000000..672bc81b0 --- /dev/null +++ b/test/test_suite7/bitstruct/designated_initializer_with_bitstruct.c3t @@ -0,0 +1,121 @@ +// #target: macos-x64 +module testing; +import std::io; +struct Foo +{ + bitstruct : ushort { + short expand : 0..7; + } + void* widget; +} + +struct Foo2 +{ + bitstruct : char[2] { + short expand : 0..7; + } + void* widget; +} + +struct Foo3 +{ + bitstruct : char[2] { + bool a : 0; + short expand : 1..7; + bool b : 8; + } + void* widget; +} +struct Foo4 +{ + bitstruct : short { + bool a : 0; + short expand : 1..7; + bool b : 8; + } + void* widget; +} + +fn void main() +{ + void* foo; + Foo *f = &&(Foo) { .expand = 2, .widget = &f }; + Foo2 *f2 = &&(Foo2) { .expand = 2, .widget = &f }; + Foo3 *f3 = &&(Foo3) { .expand = 2, .a = true, .b = true, .widget = &f }; + Foo4 *f4 = &&(Foo4) { .expand = 2, .a = true, .b = true, .widget = &f }; +} + +/* #expect: testing.ll + +define void @testing.main() #0 { +entry: + %foo = alloca ptr, align 8 + %f = alloca ptr, align 8 + %literal = alloca %Foo, align 8 + %f2 = alloca ptr, align 8 + %literal2 = alloca %Foo2, align 8 + %f3 = alloca ptr, align 8 + %literal6 = alloca %Foo3, align 8 + %f4 = alloca ptr, align 8 + %literal11 = alloca %Foo4, align 8 + store ptr null, ptr %foo, align 8 + store i16 0, ptr %literal, align 8 + %ptradd = getelementptr inbounds i8, ptr %literal, i64 8 + store ptr null, ptr %ptradd, align 8 + %0 = load i16, ptr %literal, align 8 + %1 = and i16 %0, -256 + %2 = or i16 %1, 2 + store i16 %2, ptr %literal, align 8 + %ptradd1 = getelementptr inbounds i8, ptr %literal, i64 8 + store ptr %f, ptr %ptradd1, align 8 + store ptr %literal, ptr %f, align 8 + store i8 0, ptr %literal2, align 1 + %ptradd3 = getelementptr inbounds i8, ptr %literal2, i64 1 + store i8 0, ptr %ptradd3, align 1 + %ptradd4 = getelementptr inbounds i8, ptr %literal2, i64 8 + store ptr null, ptr %ptradd4, align 8 + store i8 2, ptr %literal2, align 1 + %ptradd5 = getelementptr inbounds i8, ptr %literal2, i64 8 + store ptr %f, ptr %ptradd5, align 8 + store ptr %literal2, ptr %f2, align 8 + store i8 0, ptr %literal6, align 1 + %ptradd7 = getelementptr inbounds i8, ptr %literal6, i64 1 + store i8 0, ptr %ptradd7, align 1 + %ptradd8 = getelementptr inbounds i8, ptr %literal6, i64 8 + store ptr null, ptr %ptradd8, align 8 + %3 = load i8, ptr %literal6, align 1 + %4 = and i8 %3, 1 + %5 = or i8 %4, 4 + store i8 %5, ptr %literal6, align 1 + %6 = load i8, ptr %literal6, align 1 + %7 = and i8 %6, -2 + %8 = or i8 %7, 1 + store i8 %8, ptr %literal6, align 1 + %ptradd9 = getelementptr inbounds i8, ptr %literal6, i64 1 + %9 = load i8, ptr %ptradd9, align 1 + %10 = and i8 %9, -2 + %11 = or i8 %10, 1 + store i8 %11, ptr %ptradd9, align 1 + %ptradd10 = getelementptr inbounds i8, ptr %literal6, i64 8 + store ptr %f, ptr %ptradd10, align 8 + store ptr %literal6, ptr %f3, align 8 + store i16 0, ptr %literal11, align 8 + %ptradd12 = getelementptr inbounds i8, ptr %literal11, i64 8 + store ptr null, ptr %ptradd12, align 8 + %12 = load i16, ptr %literal11, align 8 + %13 = and i16 %12, -255 + %14 = or i16 %13, 4 + store i16 %14, ptr %literal11, align 8 + %15 = load i16, ptr %literal11, align 8 + %16 = and i16 %15, -2 + %17 = or i16 %16, 1 + store i16 %17, ptr %literal11, align 8 + %18 = load i16, ptr %literal11, align 8 + %19 = and i16 %18, -257 + %20 = or i16 %19, 256 + store i16 %20, ptr %literal11, align 8 + %ptradd13 = getelementptr inbounds i8, ptr %literal11, i64 8 + store ptr %f, ptr %ptradd13, align 8 + store ptr %literal11, ptr %f4, align 8 + ret void +} diff --git a/test/test_suite7/bitstruct/embedded_bitstruct.c3t b/test/test_suite7/bitstruct/embedded_bitstruct.c3t new file mode 100644 index 000000000..6ddc713f9 --- /dev/null +++ b/test/test_suite7/bitstruct/embedded_bitstruct.c3t @@ -0,0 +1,70 @@ +// #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) + %ptradd = getelementptr inbounds i8, ptr %b, i64 4 + %ptradd1 = getelementptr inbounds i8, ptr %b, i64 8 + %0 = load i32, ptr %ptradd1, align 4 + %shl = shl i32 %0, 21 + %ashr = ashr i32 %shl, 23 + %1 = load i32, ptr %ptradd, align 4 + call void (ptr, ...) @printf(ptr @.str, i32 %1, i32 %ashr) + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %f, ptr align 4 @.__const.10, i32 16, i1 false) + %ptradd2 = getelementptr inbounds i8, ptr %f, i64 4 + %ptradd3 = getelementptr inbounds i8, ptr %f, i64 8 + %ptradd4 = getelementptr inbounds i8, ptr %f, i64 12 + %2 = load i32, ptr %f, align 4 + %3 = load i32, ptr %ptradd2, align 4 + %4 = load i32, ptr %ptradd3, align 4 + %5 = load i32, ptr %ptradd4, align 4 + call void (ptr, ...) @printf(ptr @.str.11, i32 %2, i32 %3, i32 %4, i32 %5) + ret void +} diff --git a/test/test_suite7/bitstruct/invalid_bitstruct_member_types.c3 b/test/test_suite7/bitstruct/invalid_bitstruct_member_types.c3 new file mode 100644 index 000000000..95c33992d --- /dev/null +++ b/test/test_suite7/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. +} + +distinct Baz = float; +distinct Foo = 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_suite7/bitstruct/invalid_bitstruct_name_other_ident.c3 b/test/test_suite7/bitstruct/invalid_bitstruct_name_other_ident.c3 new file mode 100644 index 000000000..dda1db4e6 --- /dev/null +++ b/test/test_suite7/bitstruct/invalid_bitstruct_name_other_ident.c3 @@ -0,0 +1,20 @@ +bitstruct test : int // #error: Names of bitstructs must start with an uppercase 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 uppercase letter. +{ + int a : 1..3; + int b : 5..10; + uint c : 20..20; +} \ No newline at end of file diff --git a/test/test_suite7/bitstruct/invalid_bitstruct_type.c3 b/test/test_suite7/bitstruct/invalid_bitstruct_type.c3 new file mode 100644 index 000000000..d4d616ec0 --- /dev/null +++ b/test/test_suite7/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_suite7/bitstruct/invalid_empty_struct_union.c3 b/test/test_suite7/bitstruct/invalid_empty_struct_union.c3 new file mode 100644 index 000000000..d51661a07 --- /dev/null +++ b/test/test_suite7/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_suite7/bitstruct/missing_bitstruct_type.c3 b/test/test_suite7/bitstruct/missing_bitstruct_type.c3 new file mode 100644 index 000000000..1b82e0c70 --- /dev/null +++ b/test/test_suite7/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_suite7/bitstruct/param_bitstruct.c3t b/test/test_suite7/bitstruct/param_bitstruct.c3t new file mode 100644 index 000000000..61a580136 --- /dev/null +++ b/test/test_suite7/bitstruct/param_bitstruct.c3t @@ -0,0 +1,24 @@ +// #target: macos-x64 +module foo; + +bitstruct Abc : uint +{ + bool x : 0; +} + +fn void test(Abc x) +{ + x.x = false; +} + +/* #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 + %2 = and i32 %1, -2 + store i32 %2, ptr %x, align 4 + ret void +} \ No newline at end of file diff --git a/test/test_suite7/builtins/builtin_vector_abs.c3t b/test/test_suite7/builtins/builtin_vector_abs.c3t new file mode 100644 index 000000000..2bfaff266 --- /dev/null +++ b/test/test_suite7/builtins/builtin_vector_abs.c3t @@ -0,0 +1,18 @@ +// #target: macos-x64 +module test; +fn void main() +{ + { + float[<2>] vf1 = { 1, -1 }; + float[<2>] absf = $$abs(vf1); + } + { + int[<2>] v1 = { 1, -1 }; + int[<2>] absi = $$abs(v1); + } +} + +/* #expect: test.ll + + %1 = call <2 x float> @llvm.fabs.v2f32(<2 x float> %0) + %3 = call <2 x i32> @llvm.abs.v2i32(<2 x i32> %2, i1 false) diff --git a/test/test_suite7/builtins/builtin_vector_min_max.c3t b/test/test_suite7/builtins/builtin_vector_min_max.c3t new file mode 100644 index 000000000..ff05001aa --- /dev/null +++ b/test/test_suite7/builtins/builtin_vector_min_max.c3t @@ -0,0 +1,24 @@ +// #target: macos-x64 +module test; +fn void main() +{ + { + float[<2>] vf1 = { 1, -1 }; + float[<2>] vf2 = { 1, 1 }; + float[<2>] max = $$max(vf1, vf2); + float[<2>] min = $$min(vf1, vf2); + } + { + int[<2>] v1 = { 1, -1 }; + int[<2>] v2 = { 1, 1 }; + int[<2>] max = $$max(v1, v2); + int[<2>] min = $$min(v1, v2); + } +} + +/* #expect: test.ll + + %2 = call <2 x float> @llvm.maxnum.v2f32(<2 x float> %0, <2 x float> %1) + %5 = call <2 x float> @llvm.minnum.v2f32(<2 x float> %3, <2 x float> %4) + %8 = call <2 x i32> @llvm.smax.v2i32(<2 x i32> %6, <2 x i32> %7) + %11 = call <2 x i32> @llvm.smin.v2i32(<2 x i32> %9, <2 x i32> %10) diff --git a/test/test_suite7/builtins/builtin_with_optional.c3 b/test/test_suite7/builtins/builtin_with_optional.c3 new file mode 100644 index 000000000..037fa3b5a --- /dev/null +++ b/test/test_suite7/builtins/builtin_with_optional.c3 @@ -0,0 +1,8 @@ +fn void main() +{ + float x; + x = $$fma(x, x, x); + float! y; + y = $$fma(x, x, y); + x = $$fma(x, x, y); // #error: 'float!' +} \ No newline at end of file diff --git a/test/test_suite7/builtins/exacts.c3t b/test/test_suite7/builtins/exacts.c3t new file mode 100644 index 000000000..9012d5d91 --- /dev/null +++ b/test/test_suite7/builtins/exacts.c3t @@ -0,0 +1,24 @@ +// #target: macos-x64 +module test; +import std::io; +fn void main() +{ + ichar x = 23; + ichar y = 121; + int z1 = $$mul(x, y); + ichar z2 = $$div(y, x); + ichar z3 = $$mod(y, x); + int z4 = $$add(x, y); + int z5 = $$sub(x, y); + int z6 = $$neg(x); + io::printfn("%s %s %s %s %s %s", z1, z2, z3, z4, z5, z6); +} + +/* #expect: test.ll + + %emul = mul i8 %0, %1 + %esdiv = sdiv i8 %2, %3 + %eumod = srem i8 %4, %5 + %eadd = add i8 %6, %7 + %esub = sub i8 %8, %9 + %eneg = sub i8 0, %10 \ No newline at end of file diff --git a/test/test_suite7/builtins/mem.c3t b/test/test_suite7/builtins/mem.c3t new file mode 100644 index 000000000..08c1ea6e1 --- /dev/null +++ b/test/test_suite7/builtins/mem.c3t @@ -0,0 +1,23 @@ +// #target: macos-x64 +module test; + +fn void main() +{ + ushort src = 1; + ushort dst = 2; + + $$memcpy(&dst, &src, ushort.sizeof, false, $alignof(dst), $alignof(src)); + $$memmove(&dst, &src, ushort.sizeof, false, $alignof(dst), $alignof(src)); + $$memset(&dst, 0u8, ushort.sizeof, false, $alignof(dst)); + + $$memcpy_inline(&dst, &src, ushort.sizeof, false, $alignof(dst), $alignof(src)); + $$memset_inline(&dst, 0u8, ushort.sizeof, false, $alignof(dst)); +} + +/* #expect: test.ll + + call void @llvm.memcpy.p0.p0.i64(ptr align 2 %dst, ptr align 2 %src, i64 2, i1 false) + call void @llvm.memmove.p0.p0.i64(ptr align 2 %dst, ptr align 2 %src, i64 2, i1 false) + call void @llvm.memset.p0.i64(ptr align 2 %dst, i8 0, i64 2, i1 false) + call void @llvm.memcpy.inline.p0.p0.i64(ptr align 2 %dst, ptr align 2 %src, i64 2, i1 false) + call void @llvm.memset.inline.p0.i64(ptr align 2 %dst, i8 0, i64 2, i1 false) diff --git a/test/test_suite7/builtins/overflows.c3t b/test/test_suite7/builtins/overflows.c3t new file mode 100644 index 000000000..ac6267f04 --- /dev/null +++ b/test/test_suite7/builtins/overflows.c3t @@ -0,0 +1,66 @@ +module test; +import std::io; +fn void main() +{ + ichar x = 23; + ichar y = 121; + ichar z1; + ichar z2; + ichar z3; + ichar z4; + ichar z5; + bool success1 = $$overflow_mul(x, y, &z1); + bool success2 = $$overflow_add(x, y, &z2); + bool success3 = $$overflow_add(x, x, &z3); + bool success4 = $$overflow_sub($$neg(y), y, &z4); + bool success5 = $$overflow_sub(x, y, &z5); + io::printfn("%s %s", success1, z1); + io::printfn("%s %s", success2, z2); + io::printfn("%s %s", success3, z3); + io::printfn("%s %s", success4, z4); + io::printfn("%s %s", success5, z5); +} + +/* #expect: test.ll + + %0 = load i8, ptr %x, align 1 + %1 = load i8, ptr %y, align 1 + %2 = call { i8, i1 } @llvm.smul.with.overflow.i8(i8 %0, i8 %1) + %3 = extractvalue { i8, i1 } %2, 1 + %4 = extractvalue { i8, i1 } %2, 0 + store i8 %4, ptr %z1, align 1 + %5 = zext i1 %3 to i8 + store i8 %5, ptr %success1, align 1 + %6 = load i8, ptr %x, align 1 + %7 = load i8, ptr %y, align 1 + %8 = call { i8, i1 } @llvm.sadd.with.overflow.i8(i8 %6, i8 %7) + %9 = extractvalue { i8, i1 } %8, 1 + %10 = extractvalue { i8, i1 } %8, 0 + store i8 %10, ptr %z2, align 1 + %11 = zext i1 %9 to i8 + store i8 %11, ptr %success2, align 1 + %12 = load i8, ptr %x, align 1 + %13 = load i8, ptr %x, align 1 + %14 = call { i8, i1 } @llvm.sadd.with.overflow.i8(i8 %12, i8 %13) + %15 = extractvalue { i8, i1 } %14, 1 + %16 = extractvalue { i8, i1 } %14, 0 + store i8 %16, ptr %z3, align 1 + %17 = zext i1 %15 to i8 + store i8 %17, ptr %success3, align 1 + %18 = load i8, ptr %y, align 1 + %eneg = sub i8 0, %18 + %19 = load i8, ptr %y, align 1 + %20 = call { i8, i1 } @llvm.ssub.with.overflow.i8(i8 %eneg, i8 %19) + %21 = extractvalue { i8, i1 } %20, 1 + %22 = extractvalue { i8, i1 } %20, 0 + store i8 %22, ptr %z4, align 1 + %23 = zext i1 %21 to i8 + store i8 %23, ptr %success4, align 1 + %24 = load i8, ptr %x, align 1 + %25 = load i8, ptr %y, align 1 + %26 = call { i8, i1 } @llvm.ssub.with.overflow.i8(i8 %24, i8 %25) + %27 = extractvalue { i8, i1 } %26, 1 + %28 = extractvalue { i8, i1 } %26, 0 + store i8 %28, ptr %z5, align 1 + %29 = zext i1 %27 to i8 + store i8 %29, ptr %success5, align 1 diff --git a/test/test_suite7/builtins/prefetch.c3t b/test/test_suite7/builtins/prefetch.c3t new file mode 100644 index 000000000..4bb042e60 --- /dev/null +++ b/test/test_suite7/builtins/prefetch.c3t @@ -0,0 +1,19 @@ +// #target: macos-x64 +module test; +import std::io; + +fn void main() +{ + int a; + $$prefetch(&a, 1, 3); + $$prefetch(&a, 0, 1); + @prefetch(&a); +} + +/* #expect: test.ll + + %a = alloca i32, align 4 + store i32 0, ptr %a, align 4 + call void @llvm.prefetch.p0(ptr %a, i32 1, i32 3, i32 1) + call void @llvm.prefetch.p0(ptr %a, i32 0, i32 1, i32 1) + call void @llvm.prefetch.p0(ptr %a, i32 0, i32 3, i32 1) diff --git a/test/test_suite7/builtins/reduce_arithmetics.c3t b/test/test_suite7/builtins/reduce_arithmetics.c3t new file mode 100644 index 000000000..5a27bceff --- /dev/null +++ b/test/test_suite7/builtins/reduce_arithmetics.c3t @@ -0,0 +1,43 @@ +// #target: macos-x64 +module test; +import std::io; + +fn void main() +{ + int a; + io::printfn("%s", $$pow_int((double[<2>]) { 23.3, 2.1 }, 3)); + io::printfn("%s", $$reduce_add((int[<2>]) { 3, 10 })); + io::printfn("%s", $$reduce_fadd((double[<2>]) { 3, 10 }, -0.0)); + io::printfn("%s", $$reduce_fadd((double[<2>]) { 3, 10 }, 3.2)); + io::printfn("%s", $$reduce_mul((int[<2>]) { 3, 10 })); + io::printfn("%s", $$reduce_fmul((double[<2>]) { 3, 10 }, 3.4)); + io::printfn("%s", $$reduce_and((int[<2>]) { 3, 11 })); + io::printfn("%s", $$reduce_or((int[<2>]) { 3, 10 })); + io::printfn("%s", $$reduce_xor((int[<2>]) { 3, 10 })); + io::printfn("%s", $$reduce_max((double[<2>]) { 23.2, 23.3 })); + io::printfn("%s", $$reduce_max((int[<2>]) { -23, 32 })); + io::printfn("%s", $$reduce_max((char[<2>]) { 4, 253 })); + io::printfn("%s", $$reduce_min((double[<2>]) { 23.2, 23.3 })); + io::printfn("%s", $$reduce_min((int[<2>]) { -23, 32 })); + io::printfn("%s", $$reduce_min((char[<2>]) { 4, 253 })); + +} + +/* #expect: test.ll + + + call <2 x double> @llvm.powi.v2f64.i32(<2 x double> , i32 3) + call i32 @llvm.vector.reduce.add.v2i32(<2 x i32> ) + call double @llvm.vector.reduce.fadd.v2f64(double -0.000000e+00, <2 x double> ) + call double @llvm.vector.reduce.fadd.v2f64(double 3.200000e+00, <2 x double> ) + call i32 @llvm.vector.reduce.mul.v2i32(<2 x i32> ) + call double @llvm.vector.reduce.fmul.v2f64(double 3.400000e+00, <2 x double> ) + call i32 @llvm.vector.reduce.and.v2i32(<2 x i32> ) + call i32 @llvm.vector.reduce.or.v2i32(<2 x i32> ) + call i32 @llvm.vector.reduce.xor.v2i32(<2 x i32> ) + call double @llvm.vector.reduce.fmax.v2f64(<2 x double> ) + call i32 @llvm.vector.reduce.smax.v2i32(<2 x i32> ) + call i8 @llvm.vector.reduce.umax.v2i8(<2 x i8> ) + call double @llvm.vector.reduce.fmin.v2f64(<2 x double> ) + call i32 @llvm.vector.reduce.smin.v2i32(<2 x i32> ) + call i8 @llvm.vector.reduce.umin.v2i8(<2 x i8> ) diff --git a/test/test_suite7/builtins/reverse_builtin.c3t b/test/test_suite7/builtins/reverse_builtin.c3t new file mode 100644 index 000000000..effef43d0 --- /dev/null +++ b/test/test_suite7/builtins/reverse_builtin.c3t @@ -0,0 +1,14 @@ +// #target: macos-x64 + +module test; +import std::io; + +fn void main() +{ + int[<4>] a = { 1, -3, 5, -7 }; + io::printfn("%s", $$reverse(a)); +} + +/* #expect: test.ll + + %reverse = shufflevector <4 x i32> %0, <4 x i32> poison, <4 x i32> \ No newline at end of file diff --git a/test/test_suite7/builtins/rounding_builtins.c3t b/test/test_suite7/builtins/rounding_builtins.c3t new file mode 100644 index 000000000..d8a3b3e27 --- /dev/null +++ b/test/test_suite7/builtins/rounding_builtins.c3t @@ -0,0 +1,51 @@ +// #target: macos-x64 +module test; + +fn void main() +{ + double d = 1.2345; + + double d1 = $$ceil(d); + double d2 = $$floor(d); +// double d3 = $$llrint(d); +// double d4 = $$llround(d); +// double d5 = $$lrint(d); +// double d6 = $$lround(d); + double d7 = $$nearbyint(d); + double d8 = $$rint(d); + double d9 = $$round(d); + double d10 = $$roundeven(d); + + double[<2>] vd = { 1.2345, 0.6789 }; + + double[<2>] vd1 = $$ceil(vd); + double[<2>] vd2 = $$floor(vd); +// double[<2>] vd3 = $$llrint(vd); +// double[<2>] vd4 = $$llround(vd); +// double[<2>] vd5 = $$lrint(vd); +// double[<2>] vd6 = $$lround(vd); + double[<2>] vd7 = $$nearbyint(vd); + double[<2>] vd8 = $$rint(vd); + double[<2>] vd9 = $$round(vd); + double[<2>] vd10 = $$roundeven(vd); + + $$set_rounding_mode(0); + + return; +} + +/* #expect: test.ll + + %1 = call double @llvm.ceil.f64(double %0) + %3 = call double @llvm.floor.f64(double %2) + %5 = call double @llvm.nearbyint.f64(double %4) + %7 = call double @llvm.rint.f64(double %6) + %9 = call double @llvm.round.f64(double %8) + %11 = call double @llvm.roundeven.f64(double %10) + %13 = call <2 x double> @llvm.ceil.v2f64(<2 x double> %12) + %15 = call <2 x double> @llvm.floor.v2f64(<2 x double> %14) + %17 = call <2 x double> @llvm.nearbyint.v2f64(<2 x double> %16) + %19 = call <2 x double> @llvm.rint.v2f64(<2 x double> %18) + %21 = call <2 x double> @llvm.round.v2f64(<2 x double> %20) + %23 = call <2 x double> @llvm.roundeven.v2f64(<2 x double> %22) + call void @llvm.set.rounding(i32 0) diff --git a/test/test_suite7/builtins/sat_builtins.c3t b/test/test_suite7/builtins/sat_builtins.c3t new file mode 100644 index 000000000..4b41a6215 --- /dev/null +++ b/test/test_suite7/builtins/sat_builtins.c3t @@ -0,0 +1,38 @@ +// #target: macos-x64 + +module test; +import std::io; + +fn void main() +{ + char a = 123; + char b = 222; + io::printfn("%s %s", $$sat_add(a, b), $$sat_add((ichar)a, (ichar)30)); + io::printfn("%s %s", $$sat_sub(a, b), $$sat_sub((ichar)-120, (ichar)10)); + b = 3; + io::printfn("%s %s", $$sat_shl(a, b), $$sat_shl((ichar)a, (ichar)1)); + b = 222; + char[<2>] x = { 123, 222 }; + char[<2>] y = { 143, 50 }; + ichar[<2>] z = { 120, -120 }; + ichar[<2>] w = { -44, 30 }; + io::printfn("%s %s", $$sat_add(x, y), $$sat_add(z, z)); + io::printfn("%s %s", $$sat_sub(x, y), $$sat_sub(w, z)); + io::printfn("%s %s", $$sat_shl(x, (char[<2>]) { 1, 1 }), $$sat_shl(z, (ichar[<2>]) { 1, 1 })); +} + +/* #expect: test.ll + + + call i8 @llvm.uadd.sat.i8 + call i8 @llvm.sadd.sat.i8 + call i8 @llvm.usub.sat.i8 + call i8 @llvm.ssub.sat.i8 + call i8 @llvm.ushl.sat.i8 + call i8 @llvm.sshl.sat.i8 + call <2 x i8> @llvm.uadd.sat.v2i8 + call <2 x i8> @llvm.sadd.sat.v2i8 + call <2 x i8> @llvm.usub.sat.v2i8 + call <2 x i8> @llvm.ssub.sat.v2i8 + call <2 x i8> @llvm.ushl.sat.v2i8 + call <2 x i8> @llvm.sshl.sat.v2i8 diff --git a/test/test_suite7/builtins/shufflevector.c3t b/test/test_suite7/builtins/shufflevector.c3t new file mode 100644 index 000000000..4faa45d87 --- /dev/null +++ b/test/test_suite7/builtins/shufflevector.c3t @@ -0,0 +1,90 @@ +// #target: macos-x64 + +module test; +import std::io; + +struct Matrix2x2 +{ + union + { + struct + { + float m00, m01; + float m10, m11; + } + struct + { + float[<2>] m0; + float[<2>] m1; + } + float[<4>] m; + } +} + +fn float[<2>] apply1(Matrix2x2* mat, float[<2>] vec) +{ + return (float[<2>]) { + mat.m00 * vec[0] + mat.m01 * vec[1], + mat.m10 * vec[0] + mat.m11 * vec[1], + }; +} + +fn float[<2>] apply2(Matrix2x2* mat, float[<2>] vec) +{ + return (float[<2>]) { + mat.m0[0] * vec[0] + mat.m0[1] * vec[1], + mat.m1[0] * vec[0] + mat.m1[1] * vec[1], + }; +} + +fn float[<2>] apply3(Matrix2x2* mat, float[<2>] vec) +{ + float[<2>] a = $$swizzle2(mat.m0, mat.m1, 0, 3); + float[<2>] b = $$swizzle2(mat.m0, mat.m1, 1, 2); + float[<2>] flip = $$swizzle(vec, 1, 0); + return a * vec + b * flip; +} + + +fn void main() +{ + Matrix2x2 a = { 1, -3, 5, -7 }; + io::printfn("1: %s", apply1(&a, (float[<2>]) { 11, 13 })); + io::printfn("2: %s", apply2(&a, (float[<2>]) { 11, 13 })); + io::printfn("3: %s", apply3(&a, (float[<2>]) { 11, 13 })); +} + +/* #expect: test.ll + +define double @test.apply3(ptr %0, double %1) #0 { +entry: + %vec = alloca <2 x float>, align 8 + %a = alloca <2 x float>, align 8 + %b = alloca <2 x float>, align 8 + %flip = alloca <2 x float>, align 8 + %taddr = alloca <2 x float>, align 8 + store double %1, ptr %vec, align 8 + %2 = load <2 x float>, ptr %0, align 16 + %ptradd = getelementptr inbounds i8, ptr %0, i64 8 + %3 = load <2 x float>, ptr %ptradd, align 8 + %shuffle = shufflevector <2 x float> %2, <2 x float> %3, <2 x i32> + store <2 x float> %shuffle, ptr %a, align 8 + %4 = load <2 x float>, ptr %0, align 16 + %ptradd1 = getelementptr inbounds i8, ptr %0, i64 8 + %5 = load <2 x float>, ptr %ptradd1, align 8 + %shuffle2 = shufflevector <2 x float> %4, <2 x float> %5, <2 x i32> + store <2 x float> %shuffle2, ptr %b, align 8 + %6 = load <2 x float>, ptr %vec, align 8 + %shuffle3 = shufflevector <2 x float> %6, <2 x float> poison, <2 x i32> + store <2 x float> %shuffle3, ptr %flip, align 8 + %7 = load <2 x float>, ptr %a, align 8 + %8 = load <2 x float>, ptr %vec, align 8 + %fmul = fmul <2 x float> %7, %8 + %9 = load <2 x float>, ptr %b, align 8 + %10 = load <2 x float>, ptr %flip, align 8 + %fmul4 = fmul <2 x float> %9, %10 + %fadd = fadd <2 x float> %fmul, %fmul4 + store <2 x float> %fadd, ptr %taddr, align 8 + %11 = load double, ptr %taddr, align 8 + ret double %11 +} \ No newline at end of file diff --git a/test/test_suite7/builtins/simple_builtins.c3t b/test/test_suite7/builtins/simple_builtins.c3t new file mode 100644 index 000000000..b0e59e0f3 --- /dev/null +++ b/test/test_suite7/builtins/simple_builtins.c3t @@ -0,0 +1,61 @@ +// #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); + double m = $$fmuladd(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 + %m = 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 + %6 = load double, ptr %d, align 8 + %7 = call double @llvm.fmuladd.f64(double %6, double 2.000000e+00, double 3.000000e+00) + store double %7, ptr %m, align 8 + store i32 13, ptr %xeb, align 4 + store i32 0, ptr %abcd, align 4 + %ptradd = getelementptr inbounds i8, ptr %abcd, i64 4 + store i32 0, ptr %ptradd, align 4 + %ptradd1 = getelementptr inbounds i8, ptr %abcd, i64 8 + store i32 0, ptr %ptradd1, align 4 + %8 = load volatile i32, ptr %xeb, align 4 + store i32 %8, ptr %sy, align 4 + %9 = load i32, ptr %sy, align 4 + %add = add i32 %9, 1 + store volatile i32 %add, ptr %xeb, align 4 + %ptradd2 = getelementptr inbounds i8, ptr %abcd, i64 8 + %10 = load i32, ptr %sy, align 4 + %add3 = add i32 %10, 2 + store volatile i32 %add3, ptr %ptradd2, align 4 + %ptradd4 = getelementptr inbounds i8, ptr %abcd, i64 8 + %11 = load volatile i32, ptr %ptradd4, align 4 + store i32 %11, ptr %sy, align 4 + ret i32 1 +} diff --git a/test/test_suite7/builtins/trap.c3t b/test/test_suite7/builtins/trap.c3t new file mode 100644 index 000000000..c2eb5bd07 --- /dev/null +++ b/test/test_suite7/builtins/trap.c3t @@ -0,0 +1,12 @@ +module test; + +fn void main() +{ + $$breakpoint(); + $$trap(); +} + +/* #expect: test.ll + + call void @llvm.debugtrap() + call void @llvm.trap() diff --git a/test/test_suite7/builtins/unaligned_access.c3t b/test/test_suite7/builtins/unaligned_access.c3t new file mode 100644 index 000000000..4963b6fcf --- /dev/null +++ b/test/test_suite7/builtins/unaligned_access.c3t @@ -0,0 +1,82 @@ +// #target: macos-x64 +// #safe: yes +module test; +import std::io; + +fn int main() +{ + char[10] buf; + + int* i = (int*)(&buf[1]); + int z = *i; + int z2 = @unaligned_load(*i, 1); + *i = 5; + @unaligned_store(*i, 6, 1); + int y = *i; + + return 0; +} + +/* #expect: test.ll + + store ptr %ptradd9, ptr %i, align 8 + %0 = load ptr, ptr %i, align 8 + %checknull = icmp eq ptr %0, null + %1 = call i1 @llvm.expect.i1(i1 %checknull, i1 false) + br i1 %1, label %panic, label %checkok + +checkok: ; preds = %entry + %2 = ptrtoint ptr %0 to i64 + %3 = urem i64 %2, 4 + %4 = icmp ne i64 %3, 0 + %5 = call i1 @llvm.expect.i1(i1 %4, i1 false) + br i1 %5, label %panic10, label %checkok13 + +checkok13: ; preds = %checkok + %6 = load i32, ptr %0, align 4 + store i32 %6, ptr %z, align 4 + %7 = load ptr, ptr %i, align 8 + %checknull14 = icmp eq ptr %7, null + %8 = call i1 @llvm.expect.i1(i1 %checknull14, i1 false) + br i1 %8, label %panic15, label %checkok16 + +checkok16: ; preds = %checkok13 + %9 = load i32, ptr %7, align 1 + store i32 %9, ptr %z2, align 4 + %10 = load ptr, ptr %i, align 8 + %checknull17 = icmp eq ptr %10, null + %11 = call i1 @llvm.expect.i1(i1 %checknull17, i1 false) + br i1 %11, label %panic18, label %checkok19 + +checkok19: ; preds = %checkok16 + %12 = ptrtoint ptr %10 to i64 + %13 = urem i64 %12, 4 + %14 = icmp ne i64 %13, 0 + %15 = call i1 @llvm.expect.i1(i1 %14, i1 false) + br i1 %15, label %panic20, label %checkok27 + +checkok27: ; preds = %checkok19 + store i32 5, ptr %10, align 4 + %16 = load ptr, ptr %i, align 8 + %checknull28 = icmp eq ptr %16, null + %17 = call i1 @llvm.expect.i1(i1 %checknull28, i1 false) + br i1 %17, label %panic29, label %checkok30 + +checkok30: ; preds = %checkok27 + store i32 6, ptr %16, align 1 + %18 = load ptr, ptr %i, align 8 + %checknull31 = icmp eq ptr %18, null + %19 = call i1 @llvm.expect.i1(i1 %checknull31, i1 false) + br i1 %19, label %panic32, label %checkok33 + +checkok33: ; preds = %checkok30 + %20 = ptrtoint ptr %18 to i64 + %21 = urem i64 %20, 4 + %22 = icmp ne i64 %21, 0 + %23 = call i1 @llvm.expect.i1(i1 %22, i1 false) + br i1 %23, label %panic34, label %checkok41 + +checkok41: ; preds = %checkok33 + %24 = load i32, ptr %18, align 4 + store i32 %24, ptr %y, align 4 + ret i32 0 diff --git a/test/test_suite7/builtins/unaligned_load_store.c3t b/test/test_suite7/builtins/unaligned_load_store.c3t new file mode 100644 index 000000000..c4aa12992 --- /dev/null +++ b/test/test_suite7/builtins/unaligned_load_store.c3t @@ -0,0 +1,54 @@ +module test; + +struct Foo +{ + float[4] a; +} + +fn void main() +{ + Foo* foo; + float[<4>] a @align(1) @noinit; + float[<4>] b @align(1) @noinit; + + a = *(float[<4>]*)&foo.a; + *(float[<4>]*)&foo.a = a; + + a = $$unaligned_load((float[<4>]*)&foo.a, 1); + $$unaligned_store((float[<4>]*)&foo.a, a, 1); + + b = @unaligned_load(*(float[<4>]*)&foo.a, 1); + @unaligned_store(*(float[<4>]*)&foo.a, b, 1); +} + +/* #expect: test.ll + +define void @test.main() #0 { +entry: + %foo = alloca ptr, align 8 + %a = alloca <4 x float>, align 1 + %b = alloca <4 x float>, align 1 + %value = alloca <4 x float>, align 16 + store ptr null, ptr %foo, align 8 + %0 = load ptr, ptr %foo, align 8 + %1 = load <4 x float>, ptr %0, align 16 + store <4 x float> %1, ptr %a, align 1 + %2 = load ptr, ptr %foo, align 8 + %3 = load <4 x float>, ptr %a, align 1 + store <4 x float> %3, ptr %2, align 16 + %4 = load ptr, ptr %foo, align 8 + %5 = load <4 x float>, ptr %4, align 1 + store <4 x float> %5, ptr %a, align 1 + %6 = load ptr, ptr %foo, align 8 + %7 = load <4 x float>, ptr %a, align 1 + store <4 x float> %7, ptr %6, align 1 + %8 = load ptr, ptr %foo, align 8 + %9 = load <4 x float>, ptr %8, align 1 + store <4 x float> %9, ptr %b, align 1 + %10 = load <4 x float>, ptr %b, align 1 + store <4 x float> %10, ptr %value, align 16 + %11 = load ptr, ptr %foo, align 8 + %12 = load <4 x float>, ptr %value, align 16 + store <4 x float> %12, ptr %11, align 1 + ret void +} \ No newline at end of file diff --git a/test/test_suite7/cast/cast_bitstruct_etc.c3t b/test/test_suite7/cast/cast_bitstruct_etc.c3t new file mode 100644 index 000000000..c99822a61 --- /dev/null +++ b/test/test_suite7/cast/cast_bitstruct_etc.c3t @@ -0,0 +1,34 @@ +// #target: macos-x64 +module test; + +fn void main() +{ + Enum e = ENUM1; + ushort x = (ushort)(Foo){ .x = e }; + Foo z = (Foo)(ushort)(Foo) { .x = e }; +} + +enum Enum : char +{ + ENUM1, +} + +bitstruct Foo : ushort +{ + Enum x : 0..7; +} + +/* #expect: test.ll + + %e = alloca i8, align 1 + %x = alloca i16, align 2 + %z = alloca i16, align 2 + store i8 0, ptr %e, align 1 + %0 = load i8, ptr %e, align 1 + %zext = zext i8 %0 to i16 + %1 = and i16 %zext, 255 + store i16 %1, ptr %x, align 2 + %2 = load i8, ptr %e, align 1 + %zext1 = zext i8 %2 to i16 + %3 = and i16 %zext1, 255 + store i16 %3, ptr %z, align 2 diff --git a/test/test_suite7/cast/cast_from_ptr.c3t b/test/test_suite7/cast/cast_from_ptr.c3t new file mode 100644 index 000000000..9c692b6ba --- /dev/null +++ b/test/test_suite7/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 + %sext = sext i16 %ptrxi1 to i64 + store i64 %sext, ptr %z, align 8 diff --git a/test/test_suite7/cast/cast_narrow_alias.c3t b/test/test_suite7/cast/cast_narrow_alias.c3t new file mode 100644 index 000000000..c20d40af7 --- /dev/null +++ b/test/test_suite7/cast/cast_narrow_alias.c3t @@ -0,0 +1,26 @@ +// #target: macos-x64 +module abc; +def UInt8 = char; +fn void main() +{ + UInt8 x = 17; + UInt8 y = 5; + UInt8 z = (x >> y) & 0x1; +} +/* #expect: abc.ll + +entry: + %x = alloca i8, align 1 + %y = alloca i8, align 1 + %z = alloca i8, align 1 + store i8 17, ptr %x, align 1 + store i8 5, ptr %y, align 1 + %0 = load i8, ptr %x, align 1 + %zext = zext i8 %0 to i32 + %1 = load i8, ptr %y, align 1 + %zext1 = zext i8 %1 to i32 + %lshr = lshr i32 %zext, %zext1 + %2 = freeze i32 %lshr + %and = and i32 %2, 1 + %trunc = trunc i32 %and to i8 + store i8 %trunc, ptr %z, align 1 diff --git a/test/test_suite7/cast/cast_ok.c3 b/test/test_suite7/cast/cast_ok.c3 new file mode 100644 index 000000000..8c2b57223 --- /dev/null +++ b/test/test_suite7/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_suite7/cast/cast_parse_fails.c3 b/test/test_suite7/cast/cast_parse_fails.c3 new file mode 100644 index 000000000..8a6c90a47 --- /dev/null +++ b/test/test_suite7/cast/cast_parse_fails.c3 @@ -0,0 +1,13 @@ +struct Foo { int a; } + +fn void test2() +{ + int x = (int){ 32 }; // #error: 'int' with a non-empty initializer list +} + +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_suite7/cast/cast_parse_fails2.c3 b/test/test_suite7/cast/cast_parse_fails2.c3 new file mode 100644 index 000000000..883deaee8 --- /dev/null +++ b/test/test_suite7/cast/cast_parse_fails2.c3 @@ -0,0 +1,8 @@ + +struct Foo { int a; } + +fn void test1() +{ + (Foo)({ 32 }); + Foo({ 32 }); // #error: A type cannot be followed by (), if you intended a cast, use '(type) expression' +} \ No newline at end of file diff --git a/test/test_suite7/cast/cast_ptr_vec_to_bool.c3t b/test/test_suite7/cast/cast_ptr_vec_to_bool.c3t new file mode 100644 index 000000000..2865abb8a --- /dev/null +++ b/test/test_suite7/cast/cast_ptr_vec_to_bool.c3t @@ -0,0 +1,25 @@ +// #target: macos-x64 +module test; +fn void main() +{ + int xd; + void*[<2>] x = { &xd, null }; + bool[<2>] y = (bool[<2>])x; +} + +/* #expect: test.ll + +entry: + %xd = alloca i32, align 4 + %x = alloca <2 x ptr>, align 16 + %y = alloca <2 x i8>, align 2 + store i32 0, ptr %xd, align 4 + %0 = insertelement <2 x ptr> undef, ptr %xd, i64 0 + %1 = insertelement <2 x ptr> %0, ptr null, i64 1 + store <2 x ptr> %1, ptr %x, align 16 + %2 = load <2 x ptr>, ptr %x, align 16 + %i2b = icmp ne <2 x ptr> %2, zeroinitializer + %3 = sext <2 x i1> %i2b to <2 x i8> + store <2 x i8> %3, ptr %y, align 2 + ret void +} diff --git a/test/test_suite7/cast/cast_rcast.c3 b/test/test_suite7/cast/cast_rcast.c3 new file mode 100644 index 000000000..92484c037 --- /dev/null +++ b/test/test_suite7/cast/cast_rcast.c3 @@ -0,0 +1,19 @@ +module test; +// Issue #1811 +bitstruct Image_Tag : uint +{ + char x1 : 24..31; + char x2 : 16..23; + char x3 : 8..15; + char x4 : 0..7; +} + +distinct Glyph_Format = CInt; +const Glyph_Format GLYPH_FORMAT_BITMAP = (Glyph_Format)(Image_Tag) {'b', 'i', 't', 's'}; + +fn void main() { + // Error: Implicitly casting 'Image_Tag' to 'Glyph_Format' is not permitted + Glyph_Format format = GLYPH_FORMAT_BITMAP; + // Error: 'Glyph_Format' and 'Image_Tag' are different types and cannot be compared. + assert(format == GLYPH_FORMAT_BITMAP); +} \ No newline at end of file diff --git a/test/test_suite7/cast/cast_slice_implicit.c3 b/test/test_suite7/cast/cast_slice_implicit.c3 new file mode 100644 index 000000000..f07f1a10f --- /dev/null +++ b/test/test_suite7/cast/cast_slice_implicit.c3 @@ -0,0 +1,7 @@ +fn void foo() +{ + int[] array; + int* ptr = array; + void* ptr2 = &array; + int* ptr3 = &array; // #error: is not permitted +} \ No newline at end of file diff --git a/test/test_suite7/cast/cast_string_to_infered_array.c3 b/test/test_suite7/cast/cast_string_to_infered_array.c3 new file mode 100644 index 000000000..3a89fdcc8 --- /dev/null +++ b/test/test_suite7/cast/cast_string_to_infered_array.c3 @@ -0,0 +1,6 @@ +import std; +fn void main() +{ + char[?]* x = "abc"; // #error: You cannot cast 'String' to 'char[?]*' + io::printn($typeof(x).nameof); +} \ No newline at end of file diff --git a/test/test_suite7/cast/cast_struct.c3 b/test/test_suite7/cast/cast_struct.c3 new file mode 100644 index 000000000..210ae5045 --- /dev/null +++ b/test/test_suite7/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); // #error: 'Foo' to 'Bar' + + Baz z; + int[2] w = (int[2])(z); // #error: 'Baz' to 'int[2]' + z = (Baz)(w); + BazTwo v = (BazTwo)(z); // #error: 'Baz' to 'BazTwo' + v = (BazTwo)(w); + z = (Baz)(v); + w = (int[2])(v); +} diff --git a/test/test_suite7/cast/cast_struct_fails.c3 b/test/test_suite7/cast/cast_struct_fails.c3 new file mode 100644 index 000000000..85e4a08b4 --- /dev/null +++ b/test/test_suite7/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: 'Foo' to 'Baz' +} +fn void test2() +{ + Baz x; + BazTwo z = (BazTwo)(x); // #error: 'Baz' to 'BazTwo' +} + diff --git a/test/test_suite7/cast/cast_subarray.c3t b/test/test_suite7/cast/cast_subarray.c3t new file mode 100644 index 000000000..3ed733ca8 --- /dev/null +++ b/test/test_suite7/cast/cast_subarray.c3t @@ -0,0 +1,32 @@ +// #target: macos-x64 +module test; + +distinct Foo = int; +fn void main() +{ + int*[] abc = { }; + void*[] bcd = (void*[]) abc; + int[] cde = {}; + Foo[] xyz = (Foo[])cde; + Foo[] xyz2 = (Foo[])(int[]) { 1, 2 }; +} + +/* #expect: test.ll + +entry: + %abc = alloca %"int*[]", align 8 + %bcd = alloca %"void*[]", align 8 + %cde = alloca %"int[]", align 8 + %xyz = alloca %"int[]", align 8 + %xyz2 = alloca %"int[]", align 8 + %literal = alloca [2 x i32], align 4 + store %"int*[]" zeroinitializer, ptr %abc, align 8 + call void @llvm.memcpy.p0.p0.i32(ptr align 8 %bcd, ptr align 8 %abc, i32 16, i1 false) + store %"int[]" zeroinitializer, ptr %cde, align 8 + call void @llvm.memcpy.p0.p0.i32(ptr align 8 %xyz, ptr align 8 %cde, i32 16, i1 false) + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %literal, ptr align 4 @.__const, i32 8, i1 false) + %0 = insertvalue %"int[]" undef, ptr %literal, 0 + %1 = insertvalue %"int[]" %0, i64 2, 1 + store %"int[]" %1, ptr %xyz2, align 8 + ret void +} diff --git a/test/test_suite7/cast/cast_to_failable.c3 b/test/test_suite7/cast/cast_to_failable.c3 new file mode 100644 index 000000000..0625d48c4 --- /dev/null +++ b/test/test_suite7/cast/cast_to_failable.c3 @@ -0,0 +1,14 @@ +fault MyErr +{ + FOO +} + +fn void test() +{ + int! x; + double! y; + int! d = ($typeof(MyErr.FOO?))(x); // #error: Casting to an optional + int! df = ($typeof(y))(x); // #error: Casting to an optional type is not allowed + double! df2 = ($typeof(y!!))(x); +} + diff --git a/test/test_suite7/cast/cast_untyped_list_error.c3 b/test/test_suite7/cast/cast_untyped_list_error.c3 new file mode 100644 index 000000000..76cfc73e6 --- /dev/null +++ b/test/test_suite7/cast/cast_untyped_list_error.c3 @@ -0,0 +1,6 @@ +module testing; + +fn void main() +{ + (void){}; // #error: You cannot use 'void' with an initializer list +} \ No newline at end of file diff --git a/test/test_suite7/cast/implicit_array_ptr_conv.c3 b/test/test_suite7/cast/implicit_array_ptr_conv.c3 new file mode 100644 index 000000000..311caa1bd --- /dev/null +++ b/test/test_suite7/cast/implicit_array_ptr_conv.c3 @@ -0,0 +1,12 @@ +module test; + +fn void test(int[5]* x) {} +fn void test2(int* x) {} + +fn int main() +{ + int[5][5] y; + test(&y); + test2(&y); + return 0; +} \ No newline at end of file diff --git a/test/test_suite7/cast/implicit_infer_len_cast.c3t b/test/test_suite7/cast/implicit_infer_len_cast.c3t new file mode 100644 index 000000000..69ea02de2 --- /dev/null +++ b/test/test_suite7/cast/implicit_infer_len_cast.c3t @@ -0,0 +1,45 @@ +// #target: macos-x64 +module test; + +macro int test(int[?][?]* y) +{ + $typeof(*y) z = *y; + return z[1][1]; +} +fn void main() +{ + int[2][?] x = { { 2, 3}, { 5, 6 }}; + int[<2>][?] y = { { 1, 3 }}; + int[][?] z = y; + int[<2>][1] w = z; + int[<2>][] aa = { { 1, 3 }}; + int[][?] bb = { { 1, 3 } }; + test(&x); +} +/* #expect: test.ll + + %x = alloca [2 x [2 x i32]], align 16 + %y = alloca [1 x <2 x i32>], align 8 + %z = alloca [1 x <2 x i32>], align 8 + %w = alloca [1 x <2 x i32>], align 8 + %aa = alloca %"int[<2>][]", align 8 + %literal = alloca [1 x <2 x i32>], align 8 + %bb = alloca [1 x %"int[]"], align 16 + %literal1 = alloca [2 x i32], align 4 + %z2 = alloca [2 x [2 x i32]], align 16 + call void @llvm.memcpy.p0.p0.i32(ptr align 16 %x, ptr align 16 @.__const, i32 16, i1 false) + call void @llvm.memcpy.p0.p0.i32(ptr align 8 %y, ptr align 8 @.__const.1, i32 8, i1 false) + call void @llvm.memcpy.p0.p0.i32(ptr align 8 %z, ptr align 8 %y, i32 8, i1 false) + call void @llvm.memcpy.p0.p0.i32(ptr align 8 %w, ptr align 8 %z, i32 8, i1 false) + call void @llvm.memcpy.p0.p0.i32(ptr align 8 %literal, ptr align 8 @.__const.2, i32 8, i1 false) + %0 = insertvalue %"int[<2>][]" undef, ptr %literal, 0 + %1 = insertvalue %"int[<2>][]" %0, i64 1, 1 + store %"int[<2>][]" %1, ptr %aa, align 8 + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %literal1, ptr align 4 @.__const.3, i32 8, i1 false) + %2 = insertvalue %"int[]" undef, ptr %literal1, 0 + %3 = insertvalue %"int[]" %2, i64 2, 1 + store %"int[]" %3, ptr %bb, align 16 + call void @llvm.memcpy.p0.p0.i32(ptr align 16 %z2, ptr align 4 %x, i32 16, i1 false) + %ptradd = getelementptr inbounds i8, ptr %z2, i64 8 + %ptradd3 = getelementptr inbounds i8, ptr %ptradd, i64 4 + ret void diff --git a/test/test_suite7/cast/implicit_void_ptr_deep.c3 b/test/test_suite7/cast/implicit_void_ptr_deep.c3 new file mode 100644 index 000000000..46b829c1f --- /dev/null +++ b/test/test_suite7/cast/implicit_void_ptr_deep.c3 @@ -0,0 +1,7 @@ +fn void main() +{ + int** y; + int* z; + void** x = y; + void** z2 = z; // #error: Implicitly casting +} \ No newline at end of file diff --git a/test/test_suite7/cast/inner_type_cast.c3 b/test/test_suite7/cast/inner_type_cast.c3 new file mode 100644 index 000000000..ec015cad4 --- /dev/null +++ b/test/test_suite7/cast/inner_type_cast.c3 @@ -0,0 +1,21 @@ +module test; + +struct Foo +{ + bitstruct abc : int + { + bool a; + } +} + +fn void test1() +{ + Foo x; + x.abc = "abc"; // #error: to the inner type 'Foo.abc' +} + +fn void test2() +{ + Foo x; + x.abc = 2; // #error: type 'Foo.abc' is not permitted, but you may do an explicit +} \ No newline at end of file diff --git a/test/test_suite7/cast/top_down_cast_fails.c3 b/test/test_suite7/cast/top_down_cast_fails.c3 new file mode 100644 index 000000000..c2c2bea63 --- /dev/null +++ b/test/test_suite7/cast/top_down_cast_fails.c3 @@ -0,0 +1,29 @@ +fn void test() +{ + int x; + int y; + long z = x * (long)y; + z = x * y + z; // #error: 'long' + z = x * y + x; // #error: 'long' + z = x / y; + z = (long)x + y; + z = (long)x - y; + z = x % y; + z = x / y + z; + z = x + y + z; // #error: 'long' + z = x - y + z; // #error: 'long' + z = x % y + z; + z = x / y + x; // #error: 'long' + z = x + y + x; // #error: 'long' + z = x - y + x; // #error: 'long' + z = x % y + x; // #error: 'long' + + z = x << y + x; // #error: 'long' + z = x >> y + x; // #error: 'long' + z = x << y + z; // #error: 'long' + z = x >> y + z; // #error: 'long' + z = ~x + x; // #error: 'long' + z = ~x + z; // #error: 'long' + z = -x + z; // #error: 'long' + z = x + z; +} \ No newline at end of file diff --git a/test/test_suite7/cast/top_down_casts.c3t b/test/test_suite7/cast/top_down_casts.c3t new file mode 100644 index 000000000..80bbf9ce4 --- /dev/null +++ b/test/test_suite7/cast/top_down_casts.c3t @@ -0,0 +1,98 @@ +fn void test() +{ + int x; + int y; + long z = (long)x * y; + z = x / y; + z = (long)x + y; + z = (long)x - y; + z = x % y; + z = (long)x << y; + z = (long)x >> y; + z = (long)~x; + z = (long)-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 + %sext = sext i32 %0 to i64 + %1 = load i32, ptr %y, align 4 + %sext1 = sext i32 %1 to i64 + %mul = mul i64 %sext, %sext1 + store i64 %mul, ptr %z, align 8 + %2 = load i32, ptr %x, align 4 + %3 = load i32, ptr %y, align 4 + %sdiv = sdiv i32 %2, %3 + %sext2 = sext i32 %sdiv to i64 + store i64 %sext2, ptr %z, align 8 + %4 = load i32, ptr %x, align 4 + %sext3 = sext i32 %4 to i64 + %5 = load i32, ptr %y, align 4 + %sext4 = sext i32 %5 to i64 + %add = add i64 %sext3, %sext4 + store i64 %add, ptr %z, align 8 + %6 = load i32, ptr %x, align 4 + %sext5 = sext i32 %6 to i64 + %7 = load i32, ptr %y, align 4 + %sext6 = sext i32 %7 to i64 + %sub = sub i64 %sext5, %sext6 + store i64 %sub, ptr %z, align 8 + %8 = load i32, ptr %x, align 4 + %9 = load i32, ptr %y, align 4 + %smod = srem i32 %8, %9 + %sext7 = sext i32 %smod to i64 + store i64 %sext7, ptr %z, align 8 + %10 = load i32, ptr %x, align 4 + %sext8 = sext i32 %10 to i64 + %11 = load i32, ptr %y, align 4 + %zext = zext i32 %11 to i64 + %shl = shl i64 %sext8, %zext + %12 = freeze i64 %shl + store i64 %12, ptr %z, align 8 + %13 = load i32, ptr %x, align 4 + %sext9 = sext i32 %13 to i64 + %14 = load i32, ptr %y, align 4 + %zext10 = zext i32 %14 to i64 + %ashr = ashr i64 %sext9, %zext10 + %15 = freeze i64 %ashr + store i64 %15, ptr %z, align 8 + %16 = load i32, ptr %x, align 4 + %bnot = xor i32 %16, -1 + %sext11 = sext i32 %bnot to i64 + store i64 %sext11, ptr %z, align 8 + %17 = load i32, ptr %x, align 4 + %neg = sub i32 0, %17 + %sext12 = sext i32 %neg to i64 + store i64 %sext12, ptr %z, align 8 + store i64 0, ptr %w.f, align 8 + store i32 0, ptr %w, align 4 + %optval = load i64, ptr %w.f, align 8 + %not_err = icmp eq i64 %optval, 0 + %18 = call i1 @llvm.expect.i1(i1 %not_err, i1 true) + br i1 %18, label %after_check, label %else_block + +after_check: ; preds = %entry + %19 = load i32, ptr %w, align 4 + %sext13 = sext i32 %19 to i64 + br label %phi_block + +else_block: ; preds = %entry + br label %phi_block + +phi_block: ; preds = %else_block, %after_check + %val = phi i64 [ %sext13, %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_suite7/clang/2002-01_02.c3t b/test/test_suite7/clang/2002-01_02.c3t new file mode 100644 index 000000000..50d88fe44 --- /dev/null +++ b/test/test_suite7/clang/2002-01_02.c3t @@ -0,0 +1,355 @@ +// #target: macos-x64 +module test; + +struct Foo { int x, y; } +Foo[10] array; + +fn void foo() {} + +extern 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; +} + +def 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)); + } + } +} + +fn int test(int x) { + return x; +} + +extern fn void abc(int *x); +fn int deff(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 } +%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 + +; Function Attrs: +define void @test.foo() #0 { +entry: + ret void +} + +; Function Attrs: +declare ptr @dlclose(ptr) #0 + +; Function Attrs: +define void @test.ap_os_dso_unload(ptr %0) #0 { +entry: + %1 = call ptr @dlclose(ptr %0) + ret void +} + +; Function Attrs: +declare void @foo2(i32, double, float) #0 + +; Function Attrs: +define void @test.bar(i32 %0) #0 { +entry: + %i2b = icmp ne i32 %0, 0 + %ternary = select i1 %i2b, double 1.000000e+00, double 1.250000e+01 + call void @foo2(i32 %0, double %ternary, float 1.000000e+00) + ret void +} + +; Function Attrs: +declare i32 @tolower(i32) #0 + +; Function Attrs: +define ptr @test.rangematch(ptr %0, i32 %1, i32 %2) #0 { +entry: + %le = icmp sle i32 %2, %1 + %3 = call i32 @tolower(i32 %2) + %trunc = trunc i32 %1 to i8 + %zext = zext i8 %trunc to i32 + %4 = call i32 @tolower(i32 %zext) + %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 +} + +; Function Attrs: +declare i32 @foo3(i16) #0 + +; Function Attrs: +define void @test.teste2() #0 { +entry: + %xqic = alloca %Foostruct, align 2 + store i16 0, ptr %xqic, align 2 + %0 = load i16, ptr %xqic, align 2 + %1 = call i32 @foo3(i16 %0) + ret void +} + +; Function Attrs: +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 + %i2nb = icmp eq i32 %2, 0 + br i1 %i2nb, label %if.then, label %if.exit + +if.then: ; preds = %loop.body + %3 = load ptr, ptr %basel, align 8 + %ptradd = getelementptr inbounds i8, ptr %3, i64 8 + %4 = load ptr, ptr %ptradd, align 8 + %ptrxi = ptrtoint ptr %4 to i32 + ret i32 %ptrxi + +if.exit: ; preds = %loop.body + br label %loop.body +} + +; Function Attrs: +define i32 @test.test(i32 %0) #0 { +entry: + ret i32 %0 +} + +; Function Attrs: +declare void @abc(ptr) #0 + +; Function Attrs: +define i32 @test.deff(i32 %0, i32 %1) #0 { +entry: + %z = alloca i32, align 4 + store i32 %1, ptr %z, align 4 + call void @abc(ptr %z) + ret i32 %0 +} + +; Function Attrs: +define i32 @test.testing(ptr %0) #0 { +entry: + %ptradd = getelementptr inbounds i8, ptr %0, i64 2 + %1 = load i16, ptr %ptradd, align 2 + %sext = sext i16 %1 to i32 + %ptradd1 = getelementptr inbounds i8, ptr %0, i64 4 + %2 = load i32, ptr %ptradd1, align 4 + %add = add i32 %sext, %2 + ret i32 %add +} + +; Function Attrs: +define i32 @test.test2(i32 %0, i64 %1, i32 %2, i32 %3) #0 { +entry: + %a = alloca %Test, align 8 + store i64 %1, ptr %a, align 8 + %ptradd = getelementptr inbounds i8, ptr %a, i64 8 + store i32 %2, ptr %ptradd, align 8 + %add = add i32 %0, %3 + %ptradd1 = getelementptr inbounds i8, ptr %a, i64 2 + %4 = load i16, ptr %ptradd1, align 2 + %sext = sext i16 %4 to i32 + %add2 = add i32 %add, %sext + %ptradd3 = getelementptr inbounds i8, ptr %a, i64 4 + %5 = load i32, ptr %ptradd3, align 4 + %add4 = add i32 %add2, %5 + ret i32 %add4 +} + +; Function Attrs: +define i32 @test.test3(i64 %0, i32 %1, i64 %2, i32 %3) #0 { +entry: + %a = alloca %Test, align 8 + %b = alloca %Test, align 8 + store i64 %0, ptr %a, align 8 + %ptradd = getelementptr inbounds i8, ptr %a, i64 8 + store i32 %1, ptr %ptradd, align 8 + store i64 %2, ptr %b, align 8 + %ptradd1 = getelementptr inbounds i8, ptr %b, i64 8 + store i32 %3, ptr %ptradd1, align 8 + %ptradd2 = getelementptr inbounds i8, ptr %a, i64 2 + %4 = load i16, ptr %ptradd2, align 2 + %sext = sext i16 %4 to i32 + %ptradd3 = getelementptr inbounds i8, ptr %a, i64 4 + %5 = load i32, ptr %ptradd3, align 4 + %add = add i32 %sext, %5 + %ptradd4 = getelementptr inbounds i8, ptr %b, i64 4 + %6 = load i32, ptr %ptradd4, align 4 + %add5 = add i32 %add, %6 + %ptradd6 = getelementptr inbounds i8, ptr %b, i64 8 + %7 = load i32, ptr %ptradd6, align 8 + %add7 = add i32 %add5, %7 + ret i32 %add7 +} + +; Function Attrs: +define { i64, i32 } @test.test4(i64 %0, i32 %1) #0 { +entry: + %a = alloca %Test, align 8 + %tempcoerce = alloca { i64, i32 }, align 8 + store i64 %0, ptr %a, align 8 + %ptradd = getelementptr inbounds i8, ptr %a, i64 8 + store i32 %1, ptr %ptradd, align 8 + call void @llvm.memcpy.p0.p0.i32(ptr align 8 %tempcoerce, ptr align 8 %a, i32 12, i1 false) + %2 = load { i64, i32 }, ptr %tempcoerce, align 8 + ret { i64, i32 } %2 +} + +; Function Attrs: +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) + %ptradd = getelementptr inbounds i8, ptr %b, i64 16 + %0 = load i32, ptr %ptradd, align 4 + ret i32 %0 +} + +; Function Attrs: +define void @test.test7(ptr noalias sret(%STest2) align 8 %0, ptr byval(%STest2) align 8 %1) #0 { +entry: + call void @llvm.memcpy.p0.p0.i32(ptr align 8 %0, ptr align 8 %1, i32 24, i1 false) + ret void +} + +; Function Attrs: +declare i32 @printf(ptr, ...) #0 + +; Function Attrs: +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_suite7/clang/2002-03.c3t b/test/test_suite7/clang/2002-03.c3t new file mode 100644 index 000000000..ab572335a --- /dev/null +++ b/test/test_suite7/clang/2002-03.c3t @@ -0,0 +1,96 @@ +// #target: macos-x64 +module test; +extern 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], [4 x i32], { i32, i32, [2 x i32] }, [4 x i32] } { [4 x i32] [i32 1, i32 2, i32 3, i32 4], [4 x 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 @strcmp(ptr, ptr) #0 + +define i32 @test.test(ptr %0) #0 { +entry: + %1 = call i32 @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 + %i2b = icmp ne i32 %1, 0 + br i1 %i2b, 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_suite7/clang/2002-04.c3t b/test/test_suite7/clang/2002-04.c3t new file mode 100644 index 000000000..864a3264d --- /dev/null +++ b/test/test_suite7/clang/2002-04.c3t @@ -0,0 +1,168 @@ +// #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() { + 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() + %i2b = icmp ne i32 %0, 0 + br i1 %i2b, 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 +} + +; Function Attrs: +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) + %zext = zext i32 %0 to i64 + %ptroffset = getelementptr inbounds [8 x i8], ptr %student_t, i64 %zext + %1 = load double, ptr %ptroffset, align 8 + ret double %1 +} + +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 +} + +; Function Attrs: +declare i32 @testF(ptr byval(%FooSt) align 8, float) #0 + +; Function Attrs: +declare i32 @testE(i8 zeroext, i16 signext, i8 zeroext, i32, i32, float) #0 + +; Function Attrs: +define void @test.test3(ptr %0) #0 { +entry: + %ptradd = getelementptr inbounds i8, ptr %0, i64 2 + store i16 1, ptr %ptradd, align 2 + ret void +} + +; Function Attrs: +define void @test.test2(ptr byval(%FooSt) align 8 %0) #0 { +entry: + %indirectarg = alloca %FooSt, align 8 + %indirectarg4 = alloca %FooSt, align 8 + %ptradd = getelementptr inbounds i8, ptr %0, i64 2 + %ptradd1 = getelementptr inbounds i8, ptr %0, i64 4 + %ptradd2 = getelementptr inbounds i8, ptr %0, i64 8 + %ptradd3 = getelementptr inbounds i8, ptr %0, i64 12 + %1 = load i16, ptr %ptradd3, align 4 + %sext = sext i16 %1 to i32 + %2 = load i8, ptr %0, align 4 + %3 = load i16, ptr %ptradd, align 2 + %4 = load i8, ptr %ptradd1, align 4 + %5 = load i32, ptr %ptradd2, align 4 + %6 = call i32 @testE(i8 zeroext %2, i16 signext %3, i8 zeroext %4, i32 %5, i32 %sext, float 0x3FB99999A0000000) + call void @llvm.memcpy.p0.p0.i32(ptr align 8 %indirectarg, ptr align 4 %0, i32 20, i1 false) + %7 = call i32 @testF(ptr byval(%FooSt) align 8 %indirectarg, float 0x3FB99999A0000000) + call void @llvm.memcpy.p0.p0.i32(ptr align 8 %indirectarg4, ptr align 4 %0, i32 20, i1 false) + call void @test.test2(ptr byval(%FooSt) align 8 %indirectarg4) + call void @test.test3(ptr %0) + ret void +} diff --git a/test/test_suite7/clang/2002-07.c3t b/test/test_suite7/clang/2002-07.c3t new file mode 100644 index 000000000..abb40af09 --- /dev/null +++ b/test/test_suite7/clang/2002-07.c3t @@ -0,0 +1,992 @@ +// #target: macos-x64 +module foo; + +extern fn void* malloc(uint); + +struct List +{ + int data; + List* next; +} + +fn List* passThroughList(List* l) { + return l; +} + +// Recursive data structure tests... + +List* data; + +fn void foo() +{ + static int foo = 0; // Test static local variable + foo += 1; // Increment static variable + + data = (List*)malloc(12); // This is not a proper list allocation +} + +List listNode3 = { 4, null }; +List listNode2 = { 3, &listNode3 }; +List listNode0 = { 1, &listNode1 }; +List listNode1 = { 2, &listNode2 }; + + +List[10] listArray; + +// Iterative insert fn +fn void insertIntoListTail(List **l, int data) { + while (*l) l = &(*l).next; + *l = (List*)malloc(List.sizeof); + (*l).data = data; + (*l).next = null; +} + +// Recursive list search fn +fn List *findData(List *l, int data) { + if (!l) return null; + if (l.data == data) return l; + return findData(l.next, data); +} + +extern fn void foundIt(); + +// Driver fn... +fn void doListStuff() { + List* myList = null; + insertIntoListTail(&myList, 100); + insertIntoListTail(&myList, 12); + insertIntoListTail(&myList, 42); + insertIntoListTail(&myList, 1123); + insertIntoListTail(&myList, 1213); + + if (findData(myList, 75)) foundIt(); + if (findData(myList, 42)) foundIt(); + if (findData(myList, 700)) foundIt(); +} + + +fn int floatcomptest(double *x, double *y, float *x1, float *y1) { + return (int)(*x < *y || *x1 < *y1); +} + +// Exposed a bug +fn void* memset_impl(void* dstpp, int c, uint len) +{ + iptr dstp = (iptr)dstpp; + + while (dstp % 4 != 0) + { + ((char*)dstp)[0] = (char)c; + dstp += 1; + len -= 1; + } + return dstpp; +} + +// TEST problem with signed/unsigned versions of the same constants being shared +// incorrectly! +char* temp @private; +int remaining @private; +fn char* localmalloc(int size) @private { + char* blah; + + if (size>remaining) + { + temp = (char*) malloc(32768); + remaining = 32768; + return temp; + } + return null; +} + + +struct PBVTest { double x; double y; int z; } + +fn PBVTest testRetStruct(float x, double y, int z) { + PBVTest t = { x, y, z }; + return t; +} +extern fn PBVTest testRetStruct2(); // external func no inlining + + +fn double callRetStruct(float x, double y, int z) { + PBVTest t = testRetStruct2(); + return t.x+x+y+z; +} + +extern fn int fp(int, char*); +char *ext; +fn void __bb_exit_func() +{ + fp(12, ext ? ext : ""); +} + +extern fn int puts(char* s); + +struct FunStructTest +{ + int test1; + char* pointer; + int[12] array; +} + +struct SubStruct { + short x, y; +} + +struct Quad { + int w; + SubStruct ss; + SubStruct *ssp; + char c; + int y; +} + +Quad globalQuad = { 4, {1, 2}, null, 3, 156 }; + +def FuncPtr = fn int(int); + +fn uint ptrFunc(FuncPtr func, int x) { + return func(x); +} + +fn char ptrFunc2(FuncPtr[30] funcTab, int num) { + return (char)funcTab[num]('b'); +} + +extern fn char smallArgs2(char w, char x, long zrrk, char y, char z); +extern fn int someFuncA(); +fn char smallArgs(char w, char x, char y, char z) { + someFuncA(); + return smallArgs2(w-1, x+1, y, z, w); +} + +fn int f0(Quad q, int i) @private { /* Pass Q by value */ + Quad r @noinit; + if (i) r.ss = q.ss; + q.ssp = &r.ss; + q.w = q.y = q.c = 1; + return q.ss.y + i + r.y - q.c; +} + +fn int f1(Quad *q, int i) { /* Pass Q by address */ + Quad r @noinit; + if (i) r = *q; + q.w = q.y = q.c = 1; + return q.ss.y+i+r.y-q.c; +} + + +fn int badFunc(float val) { + int result @noinit; + if (val > 12.345) result = 4; + return result; /* Test use of undefined value */ +} + +extern fn int ef1(int *, char *, int *); + +fn int func(int param, long param2) { + int result = param; + + {{{{ + char c @noinit; int x @noinit; + ef1(&result, &c, &x); + }}} + + { // c & X are duplicate names! + char c; int x; + ef1(&result, &c, &x); + } + + } + return result; +} + + +fn short funFunc(long x, char z) { + return (short)(x+z); +} + +fn uint castTest(int x) { return x; } + +fn double testAdd(double x, float y) { + return x+y+0.5; +} + +fn int funcZ(int i, int j) { + while (i != 20) i += 2; + + j += funcZ(2, i); + return (i * 3 + j*2)*j; +} + +fn int sumArray(int* array, int num) { + int i @noinit; + int result = 0; + for (i = 0; i < num; ++i) result += array[i]; + return result; +} + +fn int arrayParam(int* values) { + return ef1((int*)(iptr)values[50], (char*)1, &values[50]); +} + +fn int arrayToSum() { + int[100] a @noinit; + int i; + for (i = 0; i < 100; ++i) a[i] = i*4; + + return a[a[0]]; //SumArray(A, 100); +} + + +extern fn int externFunc(long, uint*, short, char); + +fn int main(int argc, char **argv) +{ + uint i @noinit; + puts("Hello world!\n"); + + externFunc(-1, null, (short)argc, 2); + //func(argc, argc); + + for (i = 0; i < 10; i++) puts(argv[3]); + return 0; +} + +fn double mathFunc(double x, double y, double z, + double aa, double bb, double cc, double dd, + double ee, double ff, double gg, double hh, + double aaa, double abb, double acc, double add, + double aee, double aff) { + return x + y + z + aa + bb + cc + dd + ee + ff + gg + hh + + aaa + abb + acc + add + aee + aff; +} + + + +fn void strcpy(char *s1, char *s2) { + while (*s1++ = *s2++); +} + +fn void strcat(char *s1, char *s2) { + while (*s1++); + s1--; + while (*s1++ = *s2++); +} + +fn int strcmp(char *s1, char *s2) { + while (*s1++ == *s2++); + if (*s1 == 0) { + if (*s2 == 0) { + return 0; + } else { + return -1; + } + } else { + if (*s2 == 0) { + return 1; + } else { + return (*(--s1) - *(--s2)); + } + } +} + +/* #expect: foo.ll + +%.introspect = type { i8, i64, ptr, i64, i64, i64, [0 x i64] } +%List = type { i32, ptr } +%Quad = type { i32, %SubStruct, ptr, i8, i32 } +%SubStruct = type { i16, i16 } +%PBVTest = type { double, double, i32 } +@"$ct.foo.List" = linkonce global %.introspect { i8 10, i64 0, ptr null, i64 16, i64 0, i64 2, [0 x i64] zeroinitializer }, align 8 +@"$ct.foo.PBVTest" = linkonce global %.introspect { i8 10, i64 0, ptr null, i64 24, i64 0, i64 3, [0 x i64] zeroinitializer }, align 8 +@"$ct.foo.FunStructTest" = linkonce global %.introspect { i8 10, i64 0, ptr null, i64 64, i64 0, i64 3, [0 x i64] zeroinitializer }, align 8 +@"$ct.foo.SubStruct" = linkonce global %.introspect { i8 10, i64 0, ptr null, i64 4, i64 0, i64 2, [0 x i64] zeroinitializer }, align 8 +@"$ct.foo.Quad" = linkonce global %.introspect { i8 10, i64 0, ptr null, i64 24, i64 0, i64 5, [0 x i64] zeroinitializer }, align 8 +@foo.data = local_unnamed_addr global ptr null, align 8 +@foo.listNode3 = global %List { i32 4, ptr null }, align 8 +@foo.listNode2 = global %List { i32 3, ptr @foo.listNode3 }, align 8 +@foo.listNode0 = local_unnamed_addr global %List { i32 1, ptr @foo.listNode1 }, align 8 +@foo.listNode1 = global %List { i32 2, ptr @foo.listNode2 }, align 8 +@foo.listArray = local_unnamed_addr global [10 x %List] zeroinitializer, align 16 +@foo.temp = internal unnamed_addr global ptr null, align 8 +@foo.remaining = internal unnamed_addr global i32 0, align 4 +@foo.ext = local_unnamed_addr global ptr null, align 8 +@foo.globalQuad = local_unnamed_addr global %Quad { i32 4, %SubStruct { i16 1, i16 2 }, ptr null, i8 3, i32 156 }, align 8 +@foo.foo.10 = internal unnamed_addr global i32 0, align 4 +@.str = private unnamed_addr constant [7 x i8] c"\00", align 1 +@.str.11 = private unnamed_addr constant [14 x i8] c"Hello world!\0A\00", align 1 + +; Function Attrs: +declare ptr @malloc(i32) #0 + +; Function Attrs: +define ptr @foo.passThroughList(ptr %0) #0 { +entry: + ret ptr %0 +} + +; Function Attrs: +define void @foo.foo() #0 { +entry: + %0 = load i32, ptr @foo.foo.10, align 4 + %add = add i32 %0, 1 + store i32 %add, ptr @foo.foo.10, align 4 + %1 = call ptr @malloc(i32 12) + store ptr %1, ptr @foo.data, align 8 + ret void +} + +; Function Attrs: +define void @foo.insertIntoListTail(ptr %0, i32 %1) #0 { +entry: + %l = alloca ptr, align 8 + store ptr %0, ptr %l, align 8 + br label %loop.cond +loop.cond: ; preds = %loop.body, %entry + %2 = load ptr, ptr %l, align 8 + %3 = load ptr, ptr %2, align 8 + %i2b = icmp ne ptr %3, null + br i1 %i2b, label %loop.body, label %loop.exit +loop.body: ; preds = %loop.cond + %4 = load ptr, ptr %l, align 8 + %5 = load ptr, ptr %4, align 8 + %ptradd = getelementptr inbounds i8, ptr %5, i64 8 + store ptr %ptradd, ptr %l, align 8 + br label %loop.cond +loop.exit: ; preds = %loop.cond + %6 = load ptr, ptr %l, align 8 + %7 = call ptr @malloc(i32 16) + store ptr %7, ptr %6, align 8 + %8 = load ptr, ptr %l, align 8 + %9 = load ptr, ptr %8, align 8 + store i32 %1, ptr %9, align 8 + %10 = load ptr, ptr %l, align 8 + %11 = load ptr, ptr %10, align 8 + %ptradd1 = getelementptr inbounds i8, ptr %11, i64 8 + store ptr null, ptr %ptradd1, align 8 + ret void +} + +; Function Attrs: +define ptr @foo.findData(ptr %0, i32 %1) #0 { +entry: + %i2nb = icmp eq ptr %0, null + br i1 %i2nb, label %if.then, label %if.exit +if.then: ; preds = %entry + ret ptr null +if.exit: ; preds = %entry + %2 = load i32, ptr %0, align 8 + %eq = icmp eq i32 %2, %1 + br i1 %eq, label %if.then1, label %if.exit2 +if.then1: ; preds = %if.exit + ret ptr %0 +if.exit2: ; preds = %if.exit + %ptradd = getelementptr inbounds i8, ptr %0, i64 8 + %3 = load ptr, ptr %ptradd, align 8 + %4 = call ptr @foo.findData(ptr %3, i32 %1) + ret ptr %4 +} + +; Function Attrs: +declare void @foundIt() #0 + +; Function Attrs: +define void @foo.doListStuff() #0 { +entry: + %myList = alloca ptr, align 8 + store ptr null, ptr %myList, align 8 + call void @foo.insertIntoListTail(ptr %myList, i32 100) + call void @foo.insertIntoListTail(ptr %myList, i32 12) + call void @foo.insertIntoListTail(ptr %myList, i32 42) + call void @foo.insertIntoListTail(ptr %myList, i32 1123) + call void @foo.insertIntoListTail(ptr %myList, i32 1213) + %0 = load ptr, ptr %myList, align 8 + %1 = call ptr @foo.findData(ptr %0, i32 75) + %i2b = icmp ne ptr %1, null + br i1 %i2b, label %if.then, label %if.exit +if.then: ; preds = %entry + call void @foundIt() + br label %if.exit +if.exit: ; preds = %if.then, %entry + %2 = load ptr, ptr %myList, align 8 + %3 = call ptr @foo.findData(ptr %2, i32 42) + %i2b1 = icmp ne ptr %3, null + br i1 %i2b1, label %if.then2, label %if.exit3 +if.then2: ; preds = %if.exit + call void @foundIt() + br label %if.exit3 +if.exit3: ; preds = %if.then2, %if.exit + %4 = load ptr, ptr %myList, align 8 + %5 = call ptr @foo.findData(ptr %4, i32 700) + %i2b4 = icmp ne ptr %5, null + br i1 %i2b4, label %if.then5, label %if.exit6 +if.then5: ; preds = %if.exit3 + call void @foundIt() + br label %if.exit6 +if.exit6: ; preds = %if.then5, %if.exit3 + ret void +} + +; Function Attrs: +define i32 @foo.floatcomptest(ptr %0, ptr %1, ptr %2, ptr %3) #0 { +entry: + %4 = load double, ptr %0, align 8 + %5 = load double, ptr %1, align 8 + %lt = fcmp olt double %4, %5 + br i1 %lt, label %or.phi, label %or.rhs +or.rhs: ; preds = %entry + %6 = load float, ptr %2, align 4 + %7 = load float, ptr %3, align 4 + %lt1 = fcmp olt float %6, %7 + br label %or.phi +or.phi: ; preds = %or.rhs, %entry + %val = phi i1 [ true, %entry ], [ %lt1, %or.rhs ] + %zext = zext i1 %val to i32 + ret i32 %zext +} + +; Function Attrs: +define ptr @foo.memset_impl(ptr %0, i32 %1, i32 %2) #0 { +entry: + %len = alloca i32, align 4 + %dstp = alloca i64, align 8 + store i32 %2, ptr %len, align 4 + %ptrxi = ptrtoint ptr %0 to i64 + store i64 %ptrxi, ptr %dstp, align 8 + br label %loop.cond +loop.cond: ; preds = %loop.body, %entry + %3 = load i64, ptr %dstp, align 8 + %smod = srem i64 %3, 4 + %neq = icmp ne i64 %smod, 0 + br i1 %neq, label %loop.body, label %loop.exit +loop.body: ; preds = %loop.cond + %4 = load i64, ptr %dstp, align 8 + %intptr = inttoptr i64 %4 to ptr + %trunc = trunc i32 %1 to i8 + store i8 %trunc, ptr %intptr, align 1 + %5 = load i64, ptr %dstp, align 8 + %add = add i64 %5, 1 + store i64 %add, ptr %dstp, align 8 + %6 = load i32, ptr %len, align 4 + %sub = sub i32 %6, 1 + store i32 %sub, ptr %len, align 4 + br label %loop.cond +loop.exit: ; preds = %loop.cond + ret ptr %0 +} + +; Function Attrs: +define internal ptr @foo.localmalloc(i32 %0) #0 { +entry: + %blah = alloca ptr, align 8 + store ptr null, ptr %blah, align 8 + %1 = load i32, ptr @foo.remaining, align 4 + %gt = icmp sgt i32 %0, %1 + br i1 %gt, label %if.then, label %if.exit +if.then: ; preds = %entry + %2 = call ptr @malloc(i32 32768) + store ptr %2, ptr @foo.temp, align 8 + store i32 32768, ptr @foo.remaining, align 4 + %3 = load ptr, ptr @foo.temp, align 8 + ret ptr %3 +if.exit: ; preds = %entry + ret ptr null +} + +; Function Attrs: +define void @foo.testRetStruct(ptr noalias sret(%PBVTest) align 8 %0, float %1, double %2, i32 %3) #0 { +entry: + %t = alloca %PBVTest, align 8 + %fpfpext = fpext float %1 to double + store double %fpfpext, ptr %t, align 8 + %ptradd = getelementptr inbounds i8, ptr %t, i64 8 + store double %2, ptr %ptradd, align 8 + %ptradd1 = getelementptr inbounds i8, ptr %t, i64 16 + store i32 %3, ptr %ptradd1, align 8 + call void @llvm.memcpy.p0.p0.i32(ptr align 8 %0, ptr align 8 %t, i32 24, i1 false) + ret void +} + +; Function Attrs: +declare void @testRetStruct2(ptr noalias sret(%PBVTest) align 8) #0 + +; Function Attrs: +define double @foo.callRetStruct(float %0, double %1, i32 %2) #0 { +entry: + %t = alloca %PBVTest, align 8 + call void @testRetStruct2(ptr sret(%PBVTest) align 8 %t) + %3 = load double, ptr %t, align 8 + %fpfpext = fpext float %0 to double + %fadd = fadd double %3, %fpfpext + %fadd1 = fadd double %fadd, %1 + %sifp = sitofp i32 %2 to double + %fadd2 = fadd double %fadd1, %sifp + ret double %fadd2 +} + +; Function Attrs: +declare i32 @fp(i32, ptr) #0 + +; Function Attrs: +define void @foo.__bb_exit_func() #0 { +entry: + %0 = load ptr, ptr @foo.ext, align 8 + %i2b = icmp ne ptr %0, null + br i1 %i2b, label %cond.lhs, label %cond.rhs +cond.lhs: ; preds = %entry + %1 = load ptr, ptr @foo.ext, align 8 + br label %cond.phi +cond.rhs: ; preds = %entry + br label %cond.phi +cond.phi: ; preds = %cond.rhs, %cond.lhs + %val = phi ptr [ %1, %cond.lhs ], [ @.str, %cond.rhs ] + %2 = call i32 @fp(i32 12, ptr %val) + ret void +} + +; Function Attrs: +declare i32 @puts(ptr) #0 + +; Function Attrs: +define i32 @foo.ptrFunc(ptr %0, i32 %1) #0 { +entry: + %2 = call i32 %0(i32 %1) + ret i32 %2 +} + +; Function Attrs: +define zeroext i8 @foo.ptrFunc2(ptr byval([30 x ptr]) align 8 %0, i32 %1) #0 { +entry: + %sext = sext i32 %1 to i64 + %ptroffset = getelementptr inbounds [8 x i8], ptr %0, i64 %sext + %2 = load ptr, ptr %ptroffset, align 8 + %3 = call i32 %2(i32 98) + %trunc = trunc i32 %3 to i8 + ret i8 %trunc +} + +; Function Attrs: +declare zeroext i8 @smallArgs2(i8 zeroext, i8 zeroext, i64, i8 zeroext, i8 zeroext) #0 + +; Function Attrs: +declare i32 @someFuncA() #0 + +; Function Attrs: +define zeroext i8 @foo.smallArgs(i8 zeroext %0, i8 zeroext %1, i8 zeroext %2, i8 zeroext %3) #0 { +entry: + %4 = call i32 @someFuncA() + %zext = zext i8 %0 to i32 + %sub = sub i32 %zext, 1 + %trunc = trunc i32 %sub to i8 + %zext1 = zext i8 %1 to i32 + %add = add i32 %zext1, 1 + %trunc2 = trunc i32 %add to i8 + %zext3 = zext i8 %2 to i64 + %5 = call i8 @smallArgs2(i8 zeroext %trunc, i8 zeroext %trunc2, i64 %zext3, i8 zeroext %3, i8 zeroext %0) + ret i8 %5 +} + +; Function Attrs: +define internal i32 @foo.f0(ptr byval(%Quad) align 8 %0, i32 %1) #0 { +entry: + %r = alloca %Quad, align 8 + %i2b = icmp ne i32 %1, 0 + br i1 %i2b, label %if.then, label %if.exit +if.then: ; preds = %entry + %ptradd = getelementptr inbounds i8, ptr %r, i64 4 + %ptradd1 = getelementptr inbounds i8, ptr %0, i64 4 + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %ptradd, ptr align 4 %ptradd1, i32 4, i1 false) + br label %if.exit +if.exit: ; preds = %if.then, %entry + %ptradd2 = getelementptr inbounds i8, ptr %0, i64 8 + %ptradd3 = getelementptr inbounds i8, ptr %r, i64 4 + store ptr %ptradd3, ptr %ptradd2, align 8 + %ptradd4 = getelementptr inbounds i8, ptr %0, i64 20 + %ptradd5 = getelementptr inbounds i8, ptr %0, i64 16 + store i8 1, ptr %ptradd5, align 8 + store i32 1, ptr %ptradd4, align 4 + store i32 1, ptr %0, align 8 + %ptradd6 = getelementptr inbounds i8, ptr %0, i64 4 + %ptradd7 = getelementptr inbounds i8, ptr %ptradd6, i64 2 + %2 = load i16, ptr %ptradd7, align 2 + %sext = sext i16 %2 to i32 + %add = add i32 %sext, %1 + %ptradd8 = getelementptr inbounds i8, ptr %r, i64 20 + %3 = load i32, ptr %ptradd8, align 4 + %add9 = add i32 %add, %3 + %ptradd10 = getelementptr inbounds i8, ptr %0, i64 16 + %4 = load i8, ptr %ptradd10, align 8 + %zext = zext i8 %4 to i32 + %sub = sub i32 %add9, %zext + ret i32 %sub +} + +; Function Attrs: +define i32 @foo.f1(ptr %0, i32 %1) #0 { +entry: + %r = alloca %Quad, align 8 + %i2b = icmp ne i32 %1, 0 + br i1 %i2b, label %if.then, label %if.exit +if.then: ; preds = %entry + call void @llvm.memcpy.p0.p0.i32(ptr align 8 %r, ptr align 8 %0, i32 24, i1 false) + br label %if.exit +if.exit: ; preds = %if.then, %entry + %ptradd = getelementptr inbounds i8, ptr %0, i64 20 + %ptradd1 = getelementptr inbounds i8, ptr %0, i64 16 + store i8 1, ptr %ptradd1, align 8 + store i32 1, ptr %ptradd, align 4 + store i32 1, ptr %0, align 8 + %ptradd2 = getelementptr inbounds i8, ptr %0, i64 4 + %ptradd3 = getelementptr inbounds i8, ptr %ptradd2, i64 2 + %2 = load i16, ptr %ptradd3, align 2 + %sext = sext i16 %2 to i32 + %add = add i32 %sext, %1 + %ptradd4 = getelementptr inbounds i8, ptr %r, i64 20 + %3 = load i32, ptr %ptradd4, align 4 + %add5 = add i32 %add, %3 + %ptradd6 = getelementptr inbounds i8, ptr %0, i64 16 + %4 = load i8, ptr %ptradd6, align 8 + %zext = zext i8 %4 to i32 + %sub = sub i32 %add5, %zext + ret i32 %sub +} + +; Function Attrs: +define i32 @foo.badFunc(float %0) #0 { +entry: + %result = alloca i32, align 4 + %fpfpext = fpext float %0 to double + %gt = fcmp ogt double %fpfpext, 1.234500e+01 + br i1 %gt, label %if.then, label %if.exit +if.then: ; preds = %entry + store i32 4, ptr %result, align 4 + br label %if.exit +if.exit: ; preds = %if.then, %entry + %1 = load i32, ptr %result, align 4 + ret i32 %1 +} + +; Function Attrs: +declare i32 @ef1(ptr, ptr, ptr) #0 + +; Function Attrs: +define i32 @foo.func(i32 %0, i64 %1) #0 { +entry: + %result = alloca i32, align 4 + %c = alloca i8, align 1 + %x = alloca i32, align 4 + %c1 = alloca i8, align 1 + %x2 = alloca i32, align 4 + store i32 %0, ptr %result, align 4 + %2 = call i32 @ef1(ptr %result, ptr %c, ptr %x) + store i8 0, ptr %c1, align 1 + store i32 0, ptr %x2, align 4 + %3 = call i32 @ef1(ptr %result, ptr %c1, ptr %x2) + %4 = load i32, ptr %result, align 4 + ret i32 %4 +} + +; Function Attrs: +define signext i16 @foo.funFunc(i64 %0, i8 zeroext %1) #0 { +entry: + %zext = zext i8 %1 to i64 + %add = add i64 %0, %zext + %trunc = trunc i64 %add to i16 + ret i16 %trunc +} + +; Function Attrs: +define i32 @foo.castTest(i32 %0) #0 { +entry: + ret i32 %0 +} + +; Function Attrs: +define double @foo.testAdd(double %0, float %1) #0 { +entry: + %fpfpext = fpext float %1 to double + %fadd = fadd double %0, %fpfpext + %fadd1 = fadd double %fadd, 5.000000e-01 + ret double %fadd1 +} + +; Function Attrs: +define i32 @foo.funcZ(i32 %0, i32 %1) #0 { +entry: + %i = alloca i32, align 4 + %j = alloca i32, align 4 + store i32 %0, ptr %i, align 4 + store i32 %1, ptr %j, align 4 + br label %loop.cond +loop.cond: ; preds = %loop.body, %entry + %2 = load i32, ptr %i, align 4 + %neq = icmp ne i32 %2, 20 + br i1 %neq, label %loop.body, label %loop.exit +loop.body: ; preds = %loop.cond + %3 = load i32, ptr %i, align 4 + %add = add i32 %3, 2 + store i32 %add, ptr %i, align 4 + br label %loop.cond +loop.exit: ; preds = %loop.cond + %4 = load i32, ptr %j, align 4 + %5 = load i32, ptr %i, align 4 + %6 = call i32 @foo.funcZ(i32 2, i32 %5) + %add1 = add i32 %4, %6 + store i32 %add1, ptr %j, align 4 + %7 = load i32, ptr %i, align 4 + %mul = mul i32 %7, 3 + %8 = load i32, ptr %j, align 4 + %mul2 = mul i32 %8, 2 + %add3 = add i32 %mul, %mul2 + %9 = load i32, ptr %j, align 4 + %mul4 = mul i32 %add3, %9 + ret i32 %mul4 +} + +; Function Attrs: +define i32 @foo.sumArray(ptr %0, i32 %1) #0 { +entry: + %i = alloca i32, align 4 + %result = alloca i32, align 4 + store i32 0, ptr %result, align 4 + store i32 0, ptr %i, align 4 + br label %loop.cond +loop.cond: ; preds = %loop.body, %entry + %2 = load i32, ptr %i, align 4 + %lt = icmp slt i32 %2, %1 + br i1 %lt, label %loop.body, label %loop.exit +loop.body: ; preds = %loop.cond + %3 = load i32, ptr %result, align 4 + %4 = load i32, ptr %i, align 4 + %sext = sext i32 %4 to i64 + %ptroffset = getelementptr inbounds [4 x i8], ptr %0, i64 %sext + %5 = load i32, ptr %ptroffset, align 4 + %add = add i32 %3, %5 + store i32 %add, ptr %result, align 4 + %6 = load i32, ptr %i, align 4 + %add1 = add i32 %6, 1 + store i32 %add1, ptr %i, align 4 + br label %loop.cond +loop.exit: ; preds = %loop.cond + %7 = load i32, ptr %result, align 4 + ret i32 %7 +} + +; Function Attrs: +define i32 @foo.arrayParam(ptr %0) #0 { +entry: + %ptradd = getelementptr inbounds i8, ptr %0, i64 200 + %1 = load i32, ptr %ptradd, align 4 + %sext = sext i32 %1 to i64 + %intptr = inttoptr i64 %sext to ptr + %ptradd1 = getelementptr inbounds i8, ptr %0, i64 200 + %2 = call i32 @ef1(ptr %intptr, ptr inttoptr (i64 1 to ptr), ptr %ptradd1) + ret i32 %2 +} + +; Function Attrs: +define i32 @foo.arrayToSum() #0 { +entry: + %a = alloca [100 x i32], align 16 + %i = alloca i32, align 4 + store i32 0, ptr %i, 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, 100 + br i1 %lt, label %loop.body, label %loop.exit +loop.body: ; preds = %loop.cond + %1 = load i32, ptr %i, align 4 + %sext = sext i32 %1 to i64 + %ptroffset = getelementptr inbounds [4 x i8], ptr %a, i64 %sext + %2 = load i32, ptr %i, align 4 + %mul = mul i32 %2, 4 + store i32 %mul, ptr %ptroffset, align 4 + %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 + %4 = load i32, ptr %a, align 4 + %sext1 = sext i32 %4 to i64 + %ptroffset2 = getelementptr inbounds [4 x i8], ptr %a, i64 %sext1 + %5 = load i32, ptr %ptroffset2, align 4 + ret i32 %5 +} + +; Function Attrs: +declare i32 @externFunc(i64, ptr, i16 signext, i8 zeroext) #0 + +; Function Attrs: +define i32 @main(i32 %0, ptr %1) #0 { +entry: + %i = alloca i32, align 4 + %2 = call i32 @puts(ptr @.str.11) + %trunc = trunc i32 %0 to i16 + %3 = call i32 @externFunc(i64 -1, ptr null, i16 signext %trunc, i8 zeroext 2) + store i32 0, ptr %i, align 4 + br label %loop.cond +loop.cond: ; preds = %loop.body, %entry + %4 = load i32, ptr %i, align 4 + %gt = icmp ugt i32 10, %4 + br i1 %gt, label %loop.body, label %loop.exit +loop.body: ; preds = %loop.cond + %ptradd = getelementptr inbounds i8, ptr %1, i64 24 + %5 = load ptr, ptr %ptradd, align 8 + %6 = call i32 @puts(ptr %5) + %7 = load i32, ptr %i, align 4 + %add = add i32 %7, 1 + store i32 %add, ptr %i, align 4 + br label %loop.cond +loop.exit: ; preds = %loop.cond + ret i32 0 +} + +; Function Attrs: +define double @foo.mathFunc(double %0, double %1, double %2, double %3, double %4, double %5, double %6, double %7, double %8, double %9, double %10, double %11, double %12, double %13, double %14, double %15, double %16) #0 { +entry: + %fadd = fadd double %0, %1 + %fadd1 = fadd double %fadd, %2 + %fadd2 = fadd double %fadd1, %3 + %fadd3 = fadd double %fadd2, %4 + %fadd4 = fadd double %fadd3, %5 + %fadd5 = fadd double %fadd4, %6 + %fadd6 = fadd double %fadd5, %7 + %fadd7 = fadd double %fadd6, %8 + %fadd8 = fadd double %fadd7, %9 + %fadd9 = fadd double %fadd8, %10 + %fadd10 = fadd double %fadd9, %11 + %fadd11 = fadd double %fadd10, %12 + %fadd12 = fadd double %fadd11, %13 + %fadd13 = fadd double %fadd12, %14 + %fadd14 = fadd double %fadd13, %15 + %fadd15 = fadd double %fadd14, %16 + ret double %fadd15 +} + +; Function Attrs: +define void @foo.strcpy(ptr %0, ptr %1) #0 { +entry: + %s1 = alloca ptr, align 8 + %s2 = alloca ptr, align 8 + store ptr %0, ptr %s1, align 8 + store ptr %1, ptr %s2, align 8 + br label %loop.cond +loop.cond: ; preds = %loop.body, %entry + %2 = load ptr, ptr %s1, align 8 + %ptradd_any = getelementptr i8, ptr %2, i8 1 + store ptr %ptradd_any, ptr %s1, align 8 + %3 = load ptr, ptr %s2, align 8 + %ptradd_any1 = getelementptr i8, ptr %3, i8 1 + store ptr %ptradd_any1, ptr %s2, align 8 + %4 = load i8, ptr %3, align 1 + store i8 %4, ptr %2, align 1 + %i2b = icmp ne i8 %4, 0 + br i1 %i2b, label %loop.body, label %loop.exit +loop.body: ; preds = %loop.cond + br label %loop.cond +loop.exit: ; preds = %loop.cond + ret void +} + +; Function Attrs: +define void @foo.strcat(ptr %0, ptr %1) #0 { +entry: + %s1 = alloca ptr, align 8 + %s2 = alloca ptr, align 8 + store ptr %0, ptr %s1, align 8 + store ptr %1, ptr %s2, align 8 + br label %loop.cond +loop.cond: ; preds = %loop.body, %entry + %2 = load ptr, ptr %s1, align 8 + %ptradd_any = getelementptr i8, ptr %2, i8 1 + store ptr %ptradd_any, ptr %s1, align 8 + %3 = load i8, ptr %2, align 1 + %i2b = icmp ne i8 %3, 0 + br i1 %i2b, label %loop.body, label %loop.exit +loop.body: ; preds = %loop.cond + br label %loop.cond +loop.exit: ; preds = %loop.cond + %4 = load ptr, ptr %s1, align 8 + %ptradd_any1 = getelementptr i8, ptr %4, i8 -1 + store ptr %ptradd_any1, ptr %s1, align 8 + br label %loop.cond2 +loop.cond2: ; preds = %loop.body6, %loop.exit + %5 = load ptr, ptr %s1, align 8 + %ptradd_any3 = getelementptr i8, ptr %5, i8 1 + store ptr %ptradd_any3, ptr %s1, align 8 + %6 = load ptr, ptr %s2, align 8 + %ptradd_any4 = getelementptr i8, ptr %6, i8 1 + store ptr %ptradd_any4, ptr %s2, align 8 + %7 = load i8, ptr %6, align 1 + store i8 %7, ptr %5, align 1 + %i2b5 = icmp ne i8 %7, 0 + br i1 %i2b5, label %loop.body6, label %loop.exit7 +loop.body6: ; preds = %loop.cond2 + br label %loop.cond2 +loop.exit7: ; preds = %loop.cond2 + ret void +} + +; Function Attrs: +define i32 @foo.strcmp(ptr %0, ptr %1) #0 { +entry: + %s1 = alloca ptr, align 8 + %s2 = alloca ptr, align 8 + store ptr %0, ptr %s1, align 8 + store ptr %1, ptr %s2, align 8 + br label %loop.cond +loop.cond: ; preds = %loop.body, %entry + %2 = load ptr, ptr %s1, align 8 + %ptradd_any = getelementptr i8, ptr %2, i8 1 + store ptr %ptradd_any, ptr %s1, align 8 + %3 = load i8, ptr %2, align 1 + %4 = load ptr, ptr %s2, align 8 + %ptradd_any1 = getelementptr i8, ptr %4, i8 1 + store ptr %ptradd_any1, ptr %s2, align 8 + %5 = load i8, ptr %4, align 1 + %eq = icmp eq i8 %3, %5 + br i1 %eq, label %loop.body, label %loop.exit +loop.body: ; preds = %loop.cond + br label %loop.cond +loop.exit: ; preds = %loop.cond + %6 = load ptr, ptr %s1, align 8 + %7 = load i8, ptr %6, align 1 + %zext = zext i8 %7 to i32 + %eq2 = icmp eq i32 0, %zext + br i1 %eq2, label %if.then, label %if.else6 +if.then: ; preds = %loop.exit + %8 = load ptr, ptr %s2, align 8 + %9 = load i8, ptr %8, align 1 + %zext3 = zext i8 %9 to i32 + %eq4 = icmp eq i32 0, %zext3 + br i1 %eq4, label %if.then5, label %if.else +if.then5: ; preds = %if.then + ret i32 0 +if.else: ; preds = %if.then + ret i32 -1 +if.else6: ; preds = %loop.exit + %10 = load ptr, ptr %s2, align 8 + %11 = load i8, ptr %10, align 1 + %zext7 = zext i8 %11 to i32 + %eq8 = icmp eq i32 0, %zext7 + br i1 %eq8, label %if.then9, label %if.else10 +if.then9: ; preds = %if.else6 + ret i32 1 +if.else10: ; preds = %if.else6 + %12 = load ptr, ptr %s1, align 8 + %ptradd_any11 = getelementptr i8, ptr %12, i8 -1 + store ptr %ptradd_any11, ptr %s1, align 8 + %13 = load i8, ptr %ptradd_any11, align 1 + %zext12 = zext i8 %13 to i32 + %14 = load ptr, ptr %s2, align 8 + %ptradd_any13 = getelementptr i8, ptr %14, i8 -1 + store ptr %ptradd_any13, ptr %s2, align 8 + %15 = load i8, ptr %ptradd_any13, align 1 + %zext14 = zext i8 %15 to i32 + %sub = sub i32 %zext12, %zext14 + ret i32 %sub +} diff --git a/test/test_suite7/comments/simple_comments.c3 b/test/test_suite7/comments/simple_comments.c3 new file mode 100644 index 000000000..ded9afc18 --- /dev/null +++ b/test/test_suite7/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_suite7/compile_time/add_to_ct_undefined.c3 b/test/test_suite7/compile_time/add_to_ct_undefined.c3 new file mode 100644 index 000000000..e9fd8f5cc --- /dev/null +++ b/test/test_suite7/compile_time/add_to_ct_undefined.c3 @@ -0,0 +1,6 @@ +fn int main() +{ + var $a; + $a += 1; // #error: not yet initialized + return 0; +} \ No newline at end of file diff --git a/test/test_suite7/compile_time/compile_time_access_subscript.c3t b/test/test_suite7/compile_time/compile_time_access_subscript.c3t new file mode 100644 index 000000000..f797b254e --- /dev/null +++ b/test/test_suite7/compile_time/compile_time_access_subscript.c3t @@ -0,0 +1,92 @@ +// #target: macos-x64 +module test; +import std::io; +struct Abc +{ + float m00, m01, m10, m11; +} + +Abc a = flip((Abc) { 1, 2, 3, 4 }); + +macro flip($init) +{ + return (Abc) { $init.m01, $init.m10, $init.m11, $init.m00 }; +} + +macro check_type($Type) +{ + var $b = ($Type[4][4]) {}; + $Type z = $b[2][2]; + return z; +} + +enum Blurb { FOO } + +distinct Bdd = Abc; +fn void main() +{ + var $i = (int[4]) { 1, 2, 3, 4 }; + var $b = (Abc[2]) { (Abc) {}, (Abc) { 11, 22, 33, 44 }}; + var $c = (any[4]) {}; + check_type(int); + check_type(Abc); + check_type(anyfault); + check_type(Blurb); + check_type(int*); + check_type(bool); + check_type(typeid); + check_type(int[<3>]); + check_type(Bdd); + check_type(int[2]); + check_type(int[]); + io::printfn("%d", $b[0].m11); +} + +/* #expect: test.ll + + %z = alloca i32, align 4 + %z1 = alloca %Abc, align 4 + %z4 = alloca i64, align 8 + %z5 = alloca i32, align 4 + %z6 = alloca ptr, align 8 + %z7 = alloca i8, align 1 + %z8 = alloca i64, align 8 + %z9 = alloca <3 x i32>, align 16 + %z10 = alloca %Abc, align 4 + %z14 = alloca [2 x i32], align 4 + %z16 = alloca %"int[]", align 8 + %varargslots = alloca [1 x %any], align 16 + %taddr = alloca float, align 4 + %retparam = alloca i64, align 8 + store i32 0, ptr %z, align 4 + store float 0.000000e+00, ptr %z1, align 4 + %ptradd = getelementptr inbounds i8, ptr %z1, i64 4 + store float 0.000000e+00, ptr %ptradd, align 4 + %ptradd2 = getelementptr inbounds i8, ptr %z1, i64 8 + store float 0.000000e+00, ptr %ptradd2, align 4 + %ptradd3 = getelementptr inbounds i8, ptr %z1, i64 12 + store float 0.000000e+00, ptr %ptradd3, align 4 + store i64 0, ptr %z4, align 8 + store i32 0, ptr %z5, align 4 + store ptr null, ptr %z6, align 8 + store i8 0, ptr %z7, align 1 + store i64 0, ptr %z8, align 8 + store <3 x i32> zeroinitializer, ptr %z9, align 16 + store float 0.000000e+00, ptr %z10, align 4 + %ptradd11 = getelementptr inbounds i8, ptr %z10, i64 4 + store float 0.000000e+00, ptr %ptradd11, align 4 + %ptradd12 = getelementptr inbounds i8, ptr %z10, i64 8 + store float 0.000000e+00, ptr %ptradd12, align 4 + %ptradd13 = getelementptr inbounds i8, ptr %z10, i64 12 + store float 0.000000e+00, ptr %ptradd13, align 4 + store i32 0, ptr %z14, align 4 + %ptradd15 = getelementptr inbounds i8, ptr %z14, i64 4 + store i32 0, ptr %ptradd15, align 4 + store %"int[]" zeroinitializer, ptr %z16, align 8 + store float 0.000000e+00, ptr %taddr, align 4 + %0 = insertvalue %any undef, ptr %taddr, 0 + %1 = insertvalue %any %0, i64 ptrtoint (ptr @"$ct.float" to i64), 1 + store %any %1, ptr %varargslots, align 16 + %2 = call i64 @std.io.printfn(ptr %retparam, ptr @.str, i64 2, ptr %varargslots, i64 1) + ret void +} diff --git a/test/test_suite7/compile_time/compile_time_array.c3t b/test/test_suite7/compile_time/compile_time_array.c3t new file mode 100644 index 000000000..621e3f50e --- /dev/null +++ b/test/test_suite7/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 + + +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_suite7/compile_time/compile_time_array_bug.c3t b/test/test_suite7/compile_time/compile_time_array_bug.c3t new file mode 100644 index 000000000..c27082d04 --- /dev/null +++ b/test/test_suite7/compile_time/compile_time_array_bug.c3t @@ -0,0 +1,24 @@ +// #target: macos-x64 +module test; +enum TokenType: char (char token) { + ERROR = 0, + INCP = '>', + DECP = '>', + LOOPS = '[', +} + +macro populate_token_table() { + TokenType[256] $tmp = {}; + + $foreach ($tokenType: TokenType.values) + $tmp[$tokenType.token] = $tokenType; + $endforeach + + return $tmp; +} + +const TokenType[256] TOKEN_TABLE = populate_token_table(); + +/* #expect: test.ll + +@test.TOKEN_TABLE = local_unnamed_addr constant { i8, [61 x i8], i8, [28 x i8], i8, [164 x i8] } { i8 0, [61 x i8] zeroinitializer, i8 2, [28 x i8] zeroinitializer, i8 3, [164 x i8] zeroinitializer }, align 16 diff --git a/test/test_suite7/compile_time/compile_time_array_ref.c3t b/test/test_suite7/compile_time/compile_time_array_ref.c3t new file mode 100644 index 000000000..69638b35e --- /dev/null +++ b/test/test_suite7/compile_time/compile_time_array_ref.c3t @@ -0,0 +1,18 @@ +// #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 (i8, ptr @test.y, i64 1), align 8 \ No newline at end of file diff --git a/test/test_suite7/compile_time/compile_time_bitops.c3t b/test/test_suite7/compile_time/compile_time_bitops.c3t new file mode 100644 index 000000000..573a5aac9 --- /dev/null +++ b/test/test_suite7/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_suite7/compile_time/compile_time_pointers.c3t b/test/test_suite7/compile_time/compile_time_pointers.c3t new file mode 100644 index 000000000..fa552fcbc --- /dev/null +++ b/test/test_suite7/compile_time/compile_time_pointers.c3t @@ -0,0 +1,33 @@ +// #target: macos-x64 +module test; + +const uptr ABC = 0x213; +const void* BAC = (void*)144 - 1; +const void* EXX = (void*)155; +const isz KEX = BAC - EXX; +const void* CAB = BAC; +const uptr ZAB = (uptr)CAB; +const int* BOB = (int*)16 - 1; +const int* BAB = (int*)16 + 1; +const isz AO = BAB - BOB; + +int abc @if(ZAB > 100) = 123; + +fn void test() +{ + abc++; + uptr foo = (uptr)BAC; +} + +/* #expect: test.ll + +@test.ABC = local_unnamed_addr constant i64 531, align 8 +@test.BAC = local_unnamed_addr constant ptr inttoptr (i64 143 to ptr), align 8 +@test.EXX = local_unnamed_addr constant ptr inttoptr (i64 155 to ptr), align 8 +@test.KEX = local_unnamed_addr constant i64 -12, align 8 +@test.CAB = local_unnamed_addr constant ptr inttoptr (i64 143 to ptr), align 8 +@test.ZAB = local_unnamed_addr constant i64 143, align 8 +@test.BOB = local_unnamed_addr constant ptr inttoptr (i64 12 to ptr), align 8 +@test.BAB = local_unnamed_addr constant ptr inttoptr (i64 20 to ptr), align 8 +@test.AO = local_unnamed_addr constant i64 2, align 8 +@test.abc = local_unnamed_addr global i32 123, align 4 \ No newline at end of file diff --git a/test/test_suite7/compile_time/compile_time_ptr_ref.c3t b/test/test_suite7/compile_time/compile_time_ptr_ref.c3t new file mode 100644 index 000000000..32449c8c1 --- /dev/null +++ b/test/test_suite7/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 } + +@.__const_slice = private unnamed_addr global [5 x ptr] [ptr @test.ptr, ptr @test.ptr, ptr getelementptr (i8, ptr @test.ptr, i64 4), ptr getelementptr (i8, ptr @test.ptr, i64 -4), ptr getelementptr (i8, ptr @test.ptr, i64 -4)], align 16 +@test.blurp = local_unnamed_addr global %"int*[]" { ptr @.__const_slice, 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_suite7/compile_time/compile_time_utf32.c3 b/test/test_suite7/compile_time/compile_time_utf32.c3 new file mode 100644 index 000000000..0d5ea9501 --- /dev/null +++ b/test/test_suite7/compile_time/compile_time_utf32.c3 @@ -0,0 +1,74 @@ +macro int get_utf32_codepoint_length(char $c) @const +{ + int $len; + $switch + $case !($c & 0x80): $len = 1; + $case ($c & 0xE0) == 0xC0: $len = 2; + $case ($c & 0xF0) == 0xE0: $len = 3; + $case ($c & 0xF8) == 0xF0: $len = 4; + $default: $len = -1; + $endswitch + return $len; +} + +macro usz get_utf32_len_from_utf8(String $source) @const +{ + usz $len = 0; + $for (var $i=0; $i < $source.len;) + var $curlen = get_utf32_codepoint_length ($source[$i]); + $i += $curlen; + $len++; + $endfor + return $len; +} + +macro Char32[] conv_utf8_to_char32($source) @const +{ + Char32 $codepoint; + var $max = $source.len; + + var $char32len = get_utf32_len_from_utf8 ($source); + Char32[] $chars = {}; + var $char_index = 0; + + $for (var $inx = 0; $inx < $max; ) + var $c = $source[$inx]; + var $len = get_utf32_codepoint_length($c); + $switch ($len) + $case 1: $codepoint = $c; + $case 2: $codepoint = $c & 0x1F; + $case 3: $codepoint = $c & 0x0F; + $case 4: $codepoint = $c & 0x07; + $default: + $error("Error, invalid utf8 character in string"); + return; + $endswitch + + $for (var $x = 1; $x < $len; ++$x) + $c = $source[$inx + $x]; + $if ( ($c & 0xC0) != 0x80): + $error("Error, invalid utf8 character in string"); + return; + $endif + $codepoint = ($codepoint << 6) | ($c & 0x3F); + $endfor + + $chars = $chars +++ $codepoint; + $inx += $len; + $endfor + return $chars; +} +import std; +fn void main(String[] args) +{ + Char32[] $chars = conv_utf8_to_char32("🐉 eats 🌎"); + $foreach($v : $chars) + io::printn($v); + $endforeach + Char32[] chars = conv_utf8_to_char32 ("🐉 eats 🌎"); + io::printn(chars); + foreach (c : chars) + { + io::printfn ("char32 :%x", c ); + } +} \ No newline at end of file diff --git a/test/test_suite7/compile_time/comptime_array_folding.c3t b/test/test_suite7/compile_time/comptime_array_folding.c3t new file mode 100644 index 000000000..1a7198140 --- /dev/null +++ b/test/test_suite7/compile_time/comptime_array_folding.c3t @@ -0,0 +1,68 @@ +// #target: macos-x64 +module test; +import std; + +def @TaggedAttr(value) = { + @tag("foo", (ValueHere[?]){ value }) +}; + +const FOO_STR = "foo"; + +union TestUnion +{ + int a; +} +struct ValueHere +{ + int value; + String thing; +} + +const ValueHere VALUE_STRUCT = { 32, "lol" }; + +struct ThisOtherStruct @TaggedAttr(VALUE_STRUCT) +{ + int something; +} + +enum Example : int (String str) @TaggedAttr(VALUE_STRUCT) +{ + FOO = FOO_STR, +} + +const int[2][1] BAR = { { 1, 2} }; +const int[2] BAZ = BAR[0]; +const int BAZ2 = BAZ[1]; +const TestUnion[1] ABC = { { .a = 112 } }; +const TestUnion BCD = ABC[0]; + +macro int get_tag_value($Type) +{ + $if $Type.has_tagof("foo"): + return $Type.tagof("foo")[0].value; + $else + return -1; + $endif +} + +const MY_VALUE_1 = get_tag_value(Example); +const MY_VALUE_2 = get_tag_value(ThisOtherStruct); + +fn void main() +{ + io::printn(MY_VALUE_2); + io::printn(BAZ); +} + +/* #expect: test.ll + +@.enum.FOO = internal constant [4 x i8] c"FOO\00", align 1 +@test.FOO_STR = local_unnamed_addr constant %"char[]" { ptr @.str.9, i64 3 }, align 8 +@test.VALUE_STRUCT = local_unnamed_addr constant %ValueHere { i32 32, %"char[]" { ptr @.str.10, i64 3 } }, align 8 +@test.BAR = local_unnamed_addr constant [1 x [2 x i32]] [[2 x i32] [i32 1, i32 2]], align 4 +@test.BAZ = local_unnamed_addr constant [2 x i32] [i32 1, i32 2], align 4 +@test.BAZ2 = local_unnamed_addr constant i32 2, align 4 +@test.ABC = local_unnamed_addr constant [1 x %TestUnion] [%TestUnion { i32 112 }], align 4 +@test.BCD = local_unnamed_addr constant %TestUnion { i32 112 }, align 4 +@test.MY_VALUE_1 = local_unnamed_addr constant i32 32, align 4 +@test.MY_VALUE_2 = local_unnamed_addr constant i32 32, align 4 diff --git a/test/test_suite7/compile_time/concat_append.c3t b/test/test_suite7/compile_time/concat_append.c3t new file mode 100644 index 000000000..2b2b92d3f --- /dev/null +++ b/test/test_suite7/compile_time/concat_append.c3t @@ -0,0 +1,61 @@ +// #target: macos-x64 +module test; +macro foo() +{ + var c = "hello" +++ " world"; + String[?] a = (String[1]) { "hello" } +++ (String[1]) { " world" }; + int[2] $a = { 1, 2 }; + $a = $a +++ 100; + int z = $typeof($a).len; + var b = $a; + var d = (int[]){} +++ 1 +++ 2 +++ 3; + var e = (String[1]) { "hello... " } +++ " there!"; + var f = "" +++ ""; + var g = "bye"; + var h = $$str_hash("helloworld"); +} +fn int main() +{ + foo(); + return 0; +} + +/* #expect: test.ll + +@.str = private unnamed_addr constant [12 x i8] c"hello world\00", align 1 +@.str.1 = private unnamed_addr constant [6 x i8] c"hello\00", align 1 +@.str.2 = private unnamed_addr constant [7 x i8] c" world\00", align 1 +@.__const = private unnamed_addr constant [2 x %"char[]"] [%"char[]" { ptr @.str.1, i64 5 }, %"char[]" { ptr @.str.2, i64 6 }], align 16 +@.__const.3 = private unnamed_addr constant [3 x i32] [i32 1, i32 2, i32 100], align 4 +@.__const.4 = private unnamed_addr constant [3 x i32] [i32 1, i32 2, i32 3], align 4 +@.str.5 = private unnamed_addr constant [10 x i8] c"hello... \00", align 1 +@.str.6 = private unnamed_addr constant [8 x i8] c" there!\00", align 1 +@.__const.7 = private unnamed_addr constant [2 x %"char[]"] [%"char[]" { ptr @.str.5, i64 9 }, %"char[]" { ptr @.str.6, i64 7 }], align 16 +@.str.8 = private unnamed_addr constant [4 x i8] c"bye\00", align 1 + +define i32 @main() #0 { +entry: + %c = alloca %"char[]", align 8 + %a = alloca [2 x %"char[]"], align 16 + %z = alloca i32, align 4 + %b = alloca [3 x i32], align 4 + %d = alloca %"int[]", align 8 + %literal = alloca [3 x i32], align 4 + %e = alloca [2 x %"char[]"], align 16 + %f = alloca %"char[]", align 8 + %g = alloca %"char[]", align 8 + %h = alloca i32, align 4 + store %"char[]" { ptr @.str, i64 11 }, ptr %c, align 8 + call void @llvm.memcpy.p0.p0.i32(ptr align 16 %a, ptr align 16 @.__const, i32 32, i1 false) + store i32 3, ptr %z, align 4 + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %b, ptr align 4 @.__const.3, i32 12, i1 false) + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %literal, ptr align 4 @.__const.4, i32 12, i1 false) + %0 = insertvalue %"int[]" undef, ptr %literal, 0 + %1 = insertvalue %"int[]" %0, i64 3, 1 + store %"int[]" %1, ptr %d, align 8 + call void @llvm.memcpy.p0.p0.i32(ptr align 16 %e, ptr align 16 @.__const.7, i32 32, i1 false) + store %"char[]" zeroinitializer, ptr %f, align 8 + store %"char[]" { ptr @.str.8, i64 3 }, ptr %g, align 8 + store i32 1000299617, ptr %h, align 4 + ret i32 0 +} diff --git a/test/test_suite7/compile_time/concat_append_extended_and_edit.c3t b/test/test_suite7/compile_time/concat_append_extended_and_edit.c3t new file mode 100644 index 000000000..c2ded4d53 --- /dev/null +++ b/test/test_suite7/compile_time/concat_append_extended_and_edit.c3t @@ -0,0 +1,2215 @@ +// #target: macos-x64 +module test; +import std; + +struct Abc (Printable) +{ + int a; +} +fn usz! Abc.to_format(&self, Formatter* f) @dynamic => f.printf("{%s}", self.a); + +fn void main2() +{ + char[3] $y = "abc"; + $y[2] = '8'; + io::printn((String)$y[..]); + $y[1] = 'E'; + io::printn((String)$y[..]); + var $x = {5, 5}; + var $z = $x[0] = 1000; + $x = $x +++ 333; + io::printn((int[3])$x); + $x[1] = 4; + io::printn((int[3])$x); + io::printn($z); + int[5] $w = { }; + $w[3] = 100; + io::printn($w); +} + +fn int main() +{ + int[3] $x = { }; + int[5] $y = { }; + io::printn($x +++ $y); + int[2] $z = { 1, 2 }; + io::printn($x +++ $z); + int[5] $w = { [0] = 99, [3] = 1 }; + io::printn($w); + io::printn($x +++ $w); + io::printn($z +++ $x); + io::printn($z +++ $z); + io::printn($z +++ $w); + io::printn($w +++ $x); + io::printn($w +++ $z); + io::printn($w +++ $w); + var $untyped = { 98, 91 }; + io::printn((int[4])($z +++ $untyped)); + io::printn((int[4])($untyped +++ $z)); + + io::printn((int[5])($x +++ $untyped)); + io::printn((int[5])($untyped +++ $x)); + + io::printn((int[7])($untyped +++ $w)); + io::printn((int[7])($w +++ $untyped)); + + int[3][3] $zz = { [2][1] = 5 }; + var $untyped2 = { }; + io::printn((int[3][3])($untyped2 +++ $zz)); + Abc[3] $zzz = { [1].a = 11 }; + io::printn((Abc[3])($untyped2 +++ $zzz)); + var $untyped3 = { "hello", "world" }; + $untyped3 = $untyped3 +++ $zzz; + Abc y = $untyped3[3]; + io::printn(y); + return 0; +} +/* #expect: test.ll + +define void @test.main2() #0 { +entry: + %len = alloca i64, align 8 + %error_var = alloca i64, align 8 + %retparam = alloca i64, align 8 + %error_var2 = alloca i64, align 8 + %error_var8 = alloca i64, align 8 + %len14 = alloca i64, align 8 + %error_var15 = alloca i64, align 8 + %retparam17 = alloca i64, align 8 + %error_var23 = alloca i64, align 8 + %error_var29 = alloca i64, align 8 + %literal = alloca [3 x i32], align 4 + %x = alloca [3 x i32], align 4 + %x37 = alloca [3 x i32], align 4 + %len38 = alloca i64, align 8 + %error_var39 = alloca i64, align 8 + %x40 = alloca [3 x i32], align 4 + %varargslots = alloca [1 x %any], align 16 + %retparam42 = alloca i64, align 8 + %taddr = alloca %any, align 8 + %indirectarg = alloca %"any[]", align 8 + %error_var48 = alloca i64, align 8 + %error_var54 = alloca i64, align 8 + %literal62 = alloca [3 x i32], align 4 + %x63 = alloca [3 x i32], align 4 + %x64 = alloca [3 x i32], align 4 + %len65 = alloca i64, align 8 + %error_var66 = alloca i64, align 8 + %x67 = alloca [3 x i32], align 4 + %varargslots69 = alloca [1 x %any], align 16 + %retparam71 = alloca i64, align 8 + %taddr72 = alloca %any, align 8 + %indirectarg76 = alloca %"any[]", align 8 + %error_var82 = alloca i64, align 8 + %error_var88 = alloca i64, align 8 + %len96 = alloca i64, align 8 + %error_var97 = alloca i64, align 8 + %varargslots99 = alloca [1 x %any], align 16 + %taddr100 = alloca i32, align 4 + %retparam102 = alloca i64, align 8 + %taddr103 = alloca %any, align 8 + %indirectarg107 = alloca %"any[]", align 8 + %error_var113 = alloca i64, align 8 + %error_var119 = alloca i64, align 8 + %literal127 = alloca [5 x i32], align 16 + %x128 = alloca [5 x i32], align 16 + %x129 = alloca [5 x i32], align 16 + %len130 = alloca i64, align 8 + %error_var131 = alloca i64, align 8 + %x132 = alloca [5 x i32], align 16 + %varargslots134 = alloca [1 x %any], align 16 + %retparam136 = alloca i64, align 8 + %taddr137 = alloca %any, align 8 + %indirectarg141 = alloca %"any[]", align 8 + %error_var147 = alloca i64, align 8 + %error_var153 = alloca i64, align 8 + %0 = call ptr @std.io.stdout() + %1 = call i64 @std.io.File.write(ptr %retparam, ptr %0, ptr @.str, i64 3) + %not_err = icmp eq i64 %1, 0 + %2 = call i1 @llvm.expect.i1(i1 %not_err, i1 true) + br i1 %2, label %after_check, label %assign_optional + +assign_optional: ; preds = %entry + store i64 %1, ptr %error_var, align 8 + br label %guard_block + +after_check: ; preds = %entry + br label %noerr_block + +guard_block: ; preds = %assign_optional + br label %voiderr + +noerr_block: ; preds = %after_check + %3 = load i64, ptr %retparam, align 8 + store i64 %3, ptr %len, align 8 + %4 = call i64 @std.io.File.write_byte(ptr %0, i8 zeroext 10) + %not_err3 = icmp eq i64 %4, 0 + %5 = call i1 @llvm.expect.i1(i1 %not_err3, i1 true) + br i1 %5, label %after_check5, label %assign_optional4 + +assign_optional4: ; preds = %noerr_block + store i64 %4, ptr %error_var2, align 8 + br label %guard_block6 + +after_check5: ; preds = %noerr_block + br label %noerr_block7 + +guard_block6: ; preds = %assign_optional4 + br label %voiderr + +noerr_block7: ; preds = %after_check5 + %6 = call i64 @std.io.File.flush(ptr %0) + %not_err9 = icmp eq i64 %6, 0 + %7 = call i1 @llvm.expect.i1(i1 %not_err9, i1 true) + br i1 %7, label %after_check11, label %assign_optional10 + +assign_optional10: ; preds = %noerr_block7 + store i64 %6, ptr %error_var8, align 8 + br label %guard_block12 + +after_check11: ; preds = %noerr_block7 + br label %noerr_block13 + +guard_block12: ; preds = %assign_optional10 + br label %voiderr + +noerr_block13: ; preds = %after_check11 + %8 = load i64, ptr %len, align 8 + %add = add i64 %8, 1 + br label %voiderr + +voiderr: ; preds = %noerr_block13, %guard_block12, %guard_block6, %guard_block + %9 = call ptr @std.io.stdout() + %10 = call i64 @std.io.File.write(ptr %retparam17, ptr %9, ptr @.str.1, i64 3) + %not_err18 = icmp eq i64 %10, 0 + %11 = call i1 @llvm.expect.i1(i1 %not_err18, i1 true) + br i1 %11, label %after_check20, label %assign_optional19 + +assign_optional19: ; preds = %voiderr + store i64 %10, ptr %error_var15, align 8 + br label %guard_block21 + +after_check20: ; preds = %voiderr + br label %noerr_block22 + +guard_block21: ; preds = %assign_optional19 + br label %voiderr36 + +noerr_block22: ; preds = %after_check20 + %12 = load i64, ptr %retparam17, align 8 + store i64 %12, ptr %len14, align 8 + %13 = call i64 @std.io.File.write_byte(ptr %9, i8 zeroext 10) + %not_err24 = icmp eq i64 %13, 0 + %14 = call i1 @llvm.expect.i1(i1 %not_err24, i1 true) + br i1 %14, label %after_check26, label %assign_optional25 + +assign_optional25: ; preds = %noerr_block22 + store i64 %13, ptr %error_var23, align 8 + br label %guard_block27 + +after_check26: ; preds = %noerr_block22 + br label %noerr_block28 + +guard_block27: ; preds = %assign_optional25 + br label %voiderr36 + +noerr_block28: ; preds = %after_check26 + %15 = call i64 @std.io.File.flush(ptr %9) + %not_err30 = icmp eq i64 %15, 0 + %16 = call i1 @llvm.expect.i1(i1 %not_err30, i1 true) + br i1 %16, label %after_check32, label %assign_optional31 + +assign_optional31: ; preds = %noerr_block28 + store i64 %15, ptr %error_var29, align 8 + br label %guard_block33 + +after_check32: ; preds = %noerr_block28 + br label %noerr_block34 + +guard_block33: ; preds = %assign_optional31 + br label %voiderr36 + +noerr_block34: ; preds = %after_check32 + %17 = load i64, ptr %len14, align 8 + %add35 = add i64 %17, 1 + br label %voiderr36 + +voiderr36: ; preds = %noerr_block34, %guard_block33, %guard_block27, %guard_block21 + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %literal, ptr align 4 @.__const, i32 12, i1 false) + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %x, ptr align 4 %literal, i32 12, i1 false) + %18 = call ptr @std.io.stdout() + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %x37, ptr align 4 %x, i32 12, i1 false) + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %x40, ptr align 4 %x37, i32 12, i1 false) + %19 = insertvalue %any undef, ptr %18, 0 + %20 = insertvalue %any %19, i64 ptrtoint (ptr @"$ct.std.io.File" to i64), 1 + %21 = insertvalue %any undef, ptr %x40, 0 + %22 = insertvalue %any %21, i64 ptrtoint (ptr @"$ct.a3$int" to i64), 1 + store %any %22, ptr %varargslots, align 16 + %23 = insertvalue %"any[]" undef, ptr %varargslots, 0 + %"$$temp" = insertvalue %"any[]" %23, i64 1, 1 + store %any %20, ptr %taddr, align 8 + %lo = load i64, ptr %taddr, align 8 + %ptradd = getelementptr inbounds i8, ptr %taddr, i64 8 + %hi = load ptr, ptr %ptradd, align 8 + store %"any[]" %"$$temp", ptr %indirectarg, align 8 + %24 = call i64 @std.io.fprintf(ptr %retparam42, i64 %lo, ptr %hi, ptr @.str.2, i64 2, ptr byval(%"any[]") align 8 %indirectarg) + %not_err43 = icmp eq i64 %24, 0 + %25 = call i1 @llvm.expect.i1(i1 %not_err43, i1 true) + br i1 %25, label %after_check45, label %assign_optional44 + +assign_optional44: ; preds = %voiderr36 + store i64 %24, ptr %error_var39, align 8 + br label %guard_block46 + +after_check45: ; preds = %voiderr36 + br label %noerr_block47 + +guard_block46: ; preds = %assign_optional44 + br label %voiderr61 + +noerr_block47: ; preds = %after_check45 + %26 = load i64, ptr %retparam42, align 8 + store i64 %26, ptr %len38, align 8 + %27 = call i64 @std.io.File.write_byte(ptr %18, i8 zeroext 10) + %not_err49 = icmp eq i64 %27, 0 + %28 = call i1 @llvm.expect.i1(i1 %not_err49, i1 true) + br i1 %28, label %after_check51, label %assign_optional50 + +assign_optional50: ; preds = %noerr_block47 + store i64 %27, ptr %error_var48, align 8 + br label %guard_block52 + +after_check51: ; preds = %noerr_block47 + br label %noerr_block53 + +guard_block52: ; preds = %assign_optional50 + br label %voiderr61 + +noerr_block53: ; preds = %after_check51 + %29 = call i64 @std.io.File.flush(ptr %18) + %not_err55 = icmp eq i64 %29, 0 + %30 = call i1 @llvm.expect.i1(i1 %not_err55, i1 true) + br i1 %30, label %after_check57, label %assign_optional56 + +assign_optional56: ; preds = %noerr_block53 + store i64 %29, ptr %error_var54, align 8 + br label %guard_block58 + +after_check57: ; preds = %noerr_block53 + br label %noerr_block59 + +guard_block58: ; preds = %assign_optional56 + br label %voiderr61 + +noerr_block59: ; preds = %after_check57 + %31 = load i64, ptr %len38, align 8 + %add60 = add i64 %31, 1 + br label %voiderr61 + +voiderr61: ; preds = %noerr_block59, %guard_block58, %guard_block52, %guard_block46 + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %literal62, ptr align 4 @.__const.3, i32 12, i1 false) + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %x63, ptr align 4 %literal62, i32 12, i1 false) + %32 = call ptr @std.io.stdout() + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %x64, ptr align 4 %x63, i32 12, i1 false) + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %x67, ptr align 4 %x64, i32 12, i1 false) + %33 = insertvalue %any undef, ptr %32, 0 + %34 = insertvalue %any %33, i64 ptrtoint (ptr @"$ct.std.io.File" to i64), 1 + %35 = insertvalue %any undef, ptr %x67, 0 + %36 = insertvalue %any %35, i64 ptrtoint (ptr @"$ct.a3$int" to i64), 1 + store %any %36, ptr %varargslots69, align 16 + %37 = insertvalue %"any[]" undef, ptr %varargslots69, 0 + %"$$temp70" = insertvalue %"any[]" %37, i64 1, 1 + store %any %34, ptr %taddr72, align 8 + %lo73 = load i64, ptr %taddr72, align 8 + %ptradd74 = getelementptr inbounds i8, ptr %taddr72, i64 8 + %hi75 = load ptr, ptr %ptradd74, align 8 + store %"any[]" %"$$temp70", ptr %indirectarg76, align 8 + %38 = call i64 @std.io.fprintf(ptr %retparam71, i64 %lo73, ptr %hi75, ptr @.str.4, i64 2, ptr byval(%"any[]") align 8 %indirectarg76) + %not_err77 = icmp eq i64 %38, 0 + %39 = call i1 @llvm.expect.i1(i1 %not_err77, i1 true) + br i1 %39, label %after_check79, label %assign_optional78 + +assign_optional78: ; preds = %voiderr61 + store i64 %38, ptr %error_var66, align 8 + br label %guard_block80 + +after_check79: ; preds = %voiderr61 + br label %noerr_block81 + +guard_block80: ; preds = %assign_optional78 + br label %voiderr95 + +noerr_block81: ; preds = %after_check79 + %40 = load i64, ptr %retparam71, align 8 + store i64 %40, ptr %len65, align 8 + %41 = call i64 @std.io.File.write_byte(ptr %32, i8 zeroext 10) + %not_err83 = icmp eq i64 %41, 0 + %42 = call i1 @llvm.expect.i1(i1 %not_err83, i1 true) + br i1 %42, label %after_check85, label %assign_optional84 + +assign_optional84: ; preds = %noerr_block81 + store i64 %41, ptr %error_var82, align 8 + br label %guard_block86 + +after_check85: ; preds = %noerr_block81 + br label %noerr_block87 + +guard_block86: ; preds = %assign_optional84 + br label %voiderr95 + +noerr_block87: ; preds = %after_check85 + %43 = call i64 @std.io.File.flush(ptr %32) + %not_err89 = icmp eq i64 %43, 0 + %44 = call i1 @llvm.expect.i1(i1 %not_err89, i1 true) + br i1 %44, label %after_check91, label %assign_optional90 + +assign_optional90: ; preds = %noerr_block87 + store i64 %43, ptr %error_var88, align 8 + br label %guard_block92 + +after_check91: ; preds = %noerr_block87 + br label %noerr_block93 + +guard_block92: ; preds = %assign_optional90 + br label %voiderr95 + +noerr_block93: ; preds = %after_check91 + %45 = load i64, ptr %len65, align 8 + %add94 = add i64 %45, 1 + br label %voiderr95 + +voiderr95: ; preds = %noerr_block93, %guard_block92, %guard_block86, %guard_block80 + %46 = call ptr @std.io.stdout() + %47 = insertvalue %any undef, ptr %46, 0 + %48 = insertvalue %any %47, i64 ptrtoint (ptr @"$ct.std.io.File" to i64), 1 + store i32 1000, ptr %taddr100, align 4 + %49 = insertvalue %any undef, ptr %taddr100, 0 + %50 = insertvalue %any %49, i64 ptrtoint (ptr @"$ct.int" to i64), 1 + store %any %50, ptr %varargslots99, align 16 + %51 = insertvalue %"any[]" undef, ptr %varargslots99, 0 + %"$$temp101" = insertvalue %"any[]" %51, i64 1, 1 + store %any %48, ptr %taddr103, align 8 + %lo104 = load i64, ptr %taddr103, align 8 + %ptradd105 = getelementptr inbounds i8, ptr %taddr103, i64 8 + %hi106 = load ptr, ptr %ptradd105, align 8 + store %"any[]" %"$$temp101", ptr %indirectarg107, align 8 + %52 = call i64 @std.io.fprintf(ptr %retparam102, i64 %lo104, ptr %hi106, ptr @.str.5, i64 2, ptr byval(%"any[]") align 8 %indirectarg107) + %not_err108 = icmp eq i64 %52, 0 + %53 = call i1 @llvm.expect.i1(i1 %not_err108, i1 true) + br i1 %53, label %after_check110, label %assign_optional109 + +assign_optional109: ; preds = %voiderr95 + store i64 %52, ptr %error_var97, align 8 + br label %guard_block111 + +after_check110: ; preds = %voiderr95 + br label %noerr_block112 + +guard_block111: ; preds = %assign_optional109 + br label %voiderr126 + +noerr_block112: ; preds = %after_check110 + %54 = load i64, ptr %retparam102, align 8 + store i64 %54, ptr %len96, align 8 + %55 = call i64 @std.io.File.write_byte(ptr %46, i8 zeroext 10) + %not_err114 = icmp eq i64 %55, 0 + %56 = call i1 @llvm.expect.i1(i1 %not_err114, i1 true) + br i1 %56, label %after_check116, label %assign_optional115 + +assign_optional115: ; preds = %noerr_block112 + store i64 %55, ptr %error_var113, align 8 + br label %guard_block117 + +after_check116: ; preds = %noerr_block112 + br label %noerr_block118 + +guard_block117: ; preds = %assign_optional115 + br label %voiderr126 + +noerr_block118: ; preds = %after_check116 + %57 = call i64 @std.io.File.flush(ptr %46) + %not_err120 = icmp eq i64 %57, 0 + %58 = call i1 @llvm.expect.i1(i1 %not_err120, i1 true) + br i1 %58, label %after_check122, label %assign_optional121 + +assign_optional121: ; preds = %noerr_block118 + store i64 %57, ptr %error_var119, align 8 + br label %guard_block123 + +after_check122: ; preds = %noerr_block118 + br label %noerr_block124 + +guard_block123: ; preds = %assign_optional121 + br label %voiderr126 + +noerr_block124: ; preds = %after_check122 + %59 = load i64, ptr %len96, align 8 + %add125 = add i64 %59, 1 + br label %voiderr126 + +voiderr126: ; preds = %noerr_block124, %guard_block123, %guard_block117, %guard_block111 + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %literal127, ptr align 16 @.__const.6, i32 20, i1 false) + call void @llvm.memcpy.p0.p0.i32(ptr align 16 %x128, ptr align 4 %literal127, i32 20, i1 false) + %60 = call ptr @std.io.stdout() + call void @llvm.memcpy.p0.p0.i32(ptr align 16 %x129, ptr align 16 %x128, i32 20, i1 false) + call void @llvm.memcpy.p0.p0.i32(ptr align 16 %x132, ptr align 16 %x129, i32 20, i1 false) + %61 = insertvalue %any undef, ptr %60, 0 + %62 = insertvalue %any %61, i64 ptrtoint (ptr @"$ct.std.io.File" to i64), 1 + %63 = insertvalue %any undef, ptr %x132, 0 + %64 = insertvalue %any %63, i64 ptrtoint (ptr @"$ct.a5$int" to i64), 1 + store %any %64, ptr %varargslots134, align 16 + %65 = insertvalue %"any[]" undef, ptr %varargslots134, 0 + %"$$temp135" = insertvalue %"any[]" %65, i64 1, 1 + store %any %62, ptr %taddr137, align 8 + %lo138 = load i64, ptr %taddr137, align 8 + %ptradd139 = getelementptr inbounds i8, ptr %taddr137, i64 8 + %hi140 = load ptr, ptr %ptradd139, align 8 + store %"any[]" %"$$temp135", ptr %indirectarg141, align 8 + %66 = call i64 @std.io.fprintf(ptr %retparam136, i64 %lo138, ptr %hi140, ptr @.str.7, i64 2, ptr byval(%"any[]") align 8 %indirectarg141) + %not_err142 = icmp eq i64 %66, 0 + %67 = call i1 @llvm.expect.i1(i1 %not_err142, i1 true) + br i1 %67, label %after_check144, label %assign_optional143 + +assign_optional143: ; preds = %voiderr126 + store i64 %66, ptr %error_var131, align 8 + br label %guard_block145 + +after_check144: ; preds = %voiderr126 + br label %noerr_block146 + +guard_block145: ; preds = %assign_optional143 + br label %voiderr160 + +noerr_block146: ; preds = %after_check144 + %68 = load i64, ptr %retparam136, align 8 + store i64 %68, ptr %len130, align 8 + %69 = call i64 @std.io.File.write_byte(ptr %60, i8 zeroext 10) + %not_err148 = icmp eq i64 %69, 0 + %70 = call i1 @llvm.expect.i1(i1 %not_err148, i1 true) + br i1 %70, label %after_check150, label %assign_optional149 + +assign_optional149: ; preds = %noerr_block146 + store i64 %69, ptr %error_var147, align 8 + br label %guard_block151 + +after_check150: ; preds = %noerr_block146 + br label %noerr_block152 + +guard_block151: ; preds = %assign_optional149 + br label %voiderr160 + +noerr_block152: ; preds = %after_check150 + %71 = call i64 @std.io.File.flush(ptr %60) + %not_err154 = icmp eq i64 %71, 0 + %72 = call i1 @llvm.expect.i1(i1 %not_err154, i1 true) + br i1 %72, label %after_check156, label %assign_optional155 + +assign_optional155: ; preds = %noerr_block152 + store i64 %71, ptr %error_var153, align 8 + br label %guard_block157 + +after_check156: ; preds = %noerr_block152 + br label %noerr_block158 + +guard_block157: ; preds = %assign_optional155 + br label %voiderr160 + +noerr_block158: ; preds = %after_check156 + %73 = load i64, ptr %len130, align 8 + %add159 = add i64 %73, 1 + br label %voiderr160 + +voiderr160: ; preds = %noerr_block158, %guard_block157, %guard_block151, %guard_block145 + ret void +} + +; Function Attrs: nounwind uwtable +define i32 @main() #0 { +entry: + %literal = alloca [8 x i32], align 16 + %x = alloca [8 x i32], align 16 + %x1 = alloca [8 x i32], align 16 + %len = alloca i64, align 8 + %error_var = alloca i64, align 8 + %x2 = alloca [8 x i32], align 16 + %varargslots = alloca [1 x %any], align 16 + %retparam = alloca i64, align 8 + %taddr = alloca %any, align 8 + %indirectarg = alloca %"any[]", align 8 + %error_var4 = alloca i64, align 8 + %error_var10 = alloca i64, align 8 + %literal16 = alloca [5 x i32], align 16 + %x21 = alloca [5 x i32], align 16 + %x22 = alloca [5 x i32], align 16 + %len23 = alloca i64, align 8 + %error_var24 = alloca i64, align 8 + %x25 = alloca [5 x i32], align 16 + %varargslots27 = alloca [1 x %any], align 16 + %retparam29 = alloca i64, align 8 + %taddr30 = alloca %any, align 8 + %indirectarg34 = alloca %"any[]", align 8 + %error_var40 = alloca i64, align 8 + %error_var46 = alloca i64, align 8 + %literal54 = alloca [5 x i32], align 16 + %x55 = alloca [5 x i32], align 16 + %x56 = alloca [5 x i32], align 16 + %len57 = alloca i64, align 8 + %error_var58 = alloca i64, align 8 + %x59 = alloca [5 x i32], align 16 + %varargslots61 = alloca [1 x %any], align 16 + %retparam63 = alloca i64, align 8 + %taddr64 = alloca %any, align 8 + %indirectarg68 = alloca %"any[]", align 8 + %error_var74 = alloca i64, align 8 + %error_var80 = alloca i64, align 8 + %literal88 = alloca [8 x i32], align 16 + %x89 = alloca [8 x i32], align 16 + %x90 = alloca [8 x i32], align 16 + %len91 = alloca i64, align 8 + %error_var92 = alloca i64, align 8 + %x93 = alloca [8 x i32], align 16 + %varargslots95 = alloca [1 x %any], align 16 + %retparam97 = alloca i64, align 8 + %taddr98 = alloca %any, align 8 + %indirectarg102 = alloca %"any[]", align 8 + %error_var108 = alloca i64, align 8 + %error_var114 = alloca i64, align 8 + %literal122 = alloca [5 x i32], align 16 + %x127 = alloca [5 x i32], align 16 + %x128 = alloca [5 x i32], align 16 + %len129 = alloca i64, align 8 + %error_var130 = alloca i64, align 8 + %x131 = alloca [5 x i32], align 16 + %varargslots133 = alloca [1 x %any], align 16 + %retparam135 = alloca i64, align 8 + %taddr136 = alloca %any, align 8 + %indirectarg140 = alloca %"any[]", align 8 + %error_var146 = alloca i64, align 8 + %error_var152 = alloca i64, align 8 + %literal160 = alloca [4 x i32], align 16 + %x161 = alloca [4 x i32], align 16 + %x162 = alloca [4 x i32], align 16 + %len163 = alloca i64, align 8 + %error_var164 = alloca i64, align 8 + %x165 = alloca [4 x i32], align 16 + %varargslots167 = alloca [1 x %any], align 16 + %retparam169 = alloca i64, align 8 + %taddr170 = alloca %any, align 8 + %indirectarg174 = alloca %"any[]", align 8 + %error_var180 = alloca i64, align 8 + %error_var186 = alloca i64, align 8 + %literal194 = alloca [7 x i32], align 16 + %x201 = alloca [7 x i32], align 16 + %x202 = alloca [7 x i32], align 16 + %len203 = alloca i64, align 8 + %error_var204 = alloca i64, align 8 + %x205 = alloca [7 x i32], align 16 + %varargslots207 = alloca [1 x %any], align 16 + %retparam209 = alloca i64, align 8 + %taddr210 = alloca %any, align 8 + %indirectarg214 = alloca %"any[]", align 8 + %error_var220 = alloca i64, align 8 + %error_var226 = alloca i64, align 8 + %literal234 = alloca [8 x i32], align 16 + %x235 = alloca [8 x i32], align 16 + %x236 = alloca [8 x i32], align 16 + %len237 = alloca i64, align 8 + %error_var238 = alloca i64, align 8 + %x239 = alloca [8 x i32], align 16 + %varargslots241 = alloca [1 x %any], align 16 + %retparam243 = alloca i64, align 8 + %taddr244 = alloca %any, align 8 + %indirectarg248 = alloca %"any[]", align 8 + %error_var254 = alloca i64, align 8 + %error_var260 = alloca i64, align 8 + %literal268 = alloca [7 x i32], align 16 + %x275 = alloca [7 x i32], align 16 + %x276 = alloca [7 x i32], align 16 + %len277 = alloca i64, align 8 + %error_var278 = alloca i64, align 8 + %x279 = alloca [7 x i32], align 16 + %varargslots281 = alloca [1 x %any], align 16 + %retparam283 = alloca i64, align 8 + %taddr284 = alloca %any, align 8 + %indirectarg288 = alloca %"any[]", align 8 + %error_var294 = alloca i64, align 8 + %error_var300 = alloca i64, align 8 + %literal308 = alloca [10 x i32], align 16 + %x312 = alloca [10 x i32], align 16 + %x313 = alloca [10 x i32], align 16 + %len314 = alloca i64, align 8 + %error_var315 = alloca i64, align 8 + %x316 = alloca [10 x i32], align 16 + %varargslots318 = alloca [1 x %any], align 16 + %retparam320 = alloca i64, align 8 + %taddr321 = alloca %any, align 8 + %indirectarg325 = alloca %"any[]", align 8 + %error_var331 = alloca i64, align 8 + %error_var337 = alloca i64, align 8 + %literal345 = alloca [4 x i32], align 16 + %x346 = alloca [4 x i32], align 16 + %x347 = alloca [4 x i32], align 16 + %len348 = alloca i64, align 8 + %error_var349 = alloca i64, align 8 + %x350 = alloca [4 x i32], align 16 + %varargslots352 = alloca [1 x %any], align 16 + %retparam354 = alloca i64, align 8 + %taddr355 = alloca %any, align 8 + %indirectarg359 = alloca %"any[]", align 8 + %error_var365 = alloca i64, align 8 + %error_var371 = alloca i64, align 8 + %literal379 = alloca [4 x i32], align 16 + %x380 = alloca [4 x i32], align 16 + %x381 = alloca [4 x i32], align 16 + %len382 = alloca i64, align 8 + %error_var383 = alloca i64, align 8 + %x384 = alloca [4 x i32], align 16 + %varargslots386 = alloca [1 x %any], align 16 + %retparam388 = alloca i64, align 8 + %taddr389 = alloca %any, align 8 + %indirectarg393 = alloca %"any[]", align 8 + %error_var399 = alloca i64, align 8 + %error_var405 = alloca i64, align 8 + %literal413 = alloca [5 x i32], align 16 + %x418 = alloca [5 x i32], align 16 + %x419 = alloca [5 x i32], align 16 + %len420 = alloca i64, align 8 + %error_var421 = alloca i64, align 8 + %x422 = alloca [5 x i32], align 16 + %varargslots424 = alloca [1 x %any], align 16 + %retparam426 = alloca i64, align 8 + %taddr427 = alloca %any, align 8 + %indirectarg431 = alloca %"any[]", align 8 + %error_var437 = alloca i64, align 8 + %error_var443 = alloca i64, align 8 + %literal451 = alloca [5 x i32], align 16 + %x452 = alloca [5 x i32], align 16 + %x453 = alloca [5 x i32], align 16 + %len454 = alloca i64, align 8 + %error_var455 = alloca i64, align 8 + %x456 = alloca [5 x i32], align 16 + %varargslots458 = alloca [1 x %any], align 16 + %retparam460 = alloca i64, align 8 + %taddr461 = alloca %any, align 8 + %indirectarg465 = alloca %"any[]", align 8 + %error_var471 = alloca i64, align 8 + %error_var477 = alloca i64, align 8 + %literal485 = alloca [7 x i32], align 16 + %x486 = alloca [7 x i32], align 16 + %x487 = alloca [7 x i32], align 16 + %len488 = alloca i64, align 8 + %error_var489 = alloca i64, align 8 + %x490 = alloca [7 x i32], align 16 + %varargslots492 = alloca [1 x %any], align 16 + %retparam494 = alloca i64, align 8 + %taddr495 = alloca %any, align 8 + %indirectarg499 = alloca %"any[]", align 8 + %error_var505 = alloca i64, align 8 + %error_var511 = alloca i64, align 8 + %literal519 = alloca [7 x i32], align 16 + %x526 = alloca [7 x i32], align 16 + %x527 = alloca [7 x i32], align 16 + %len528 = alloca i64, align 8 + %error_var529 = alloca i64, align 8 + %x530 = alloca [7 x i32], align 16 + %varargslots532 = alloca [1 x %any], align 16 + %retparam534 = alloca i64, align 8 + %taddr535 = alloca %any, align 8 + %indirectarg539 = alloca %"any[]", align 8 + %error_var545 = alloca i64, align 8 + %error_var551 = alloca i64, align 8 + %literal559 = alloca [3 x [3 x i32]], align 16 + %x569 = alloca [3 x [3 x i32]], align 16 + %x570 = alloca [3 x [3 x i32]], align 16 + %len571 = alloca i64, align 8 + %error_var572 = alloca i64, align 8 + %x573 = alloca [3 x [3 x i32]], align 16 + %varargslots575 = alloca [1 x %any], align 16 + %retparam577 = alloca i64, align 8 + %taddr578 = alloca %any, align 8 + %indirectarg582 = alloca %"any[]", align 8 + %error_var588 = alloca i64, align 8 + %error_var594 = alloca i64, align 8 + %literal602 = alloca [3 x %Abc], align 4 + %x605 = alloca [3 x %Abc], align 4 + %x606 = alloca [3 x %Abc], align 4 + %len607 = alloca i64, align 8 + %error_var608 = alloca i64, align 8 + %x609 = alloca [3 x %Abc], align 4 + %varargslots611 = alloca [1 x %any], align 16 + %retparam613 = alloca i64, align 8 + %taddr614 = alloca %any, align 8 + %indirectarg618 = alloca %"any[]", align 8 + %error_var624 = alloca i64, align 8 + %error_var630 = alloca i64, align 8 + %y = alloca %Abc, align 4 + %x638 = alloca %Abc, align 4 + %x639 = alloca %Abc, align 4 + %len640 = alloca i64, align 8 + %error_var641 = alloca i64, align 8 + %x642 = alloca %Abc, align 4 + %varargslots644 = alloca [1 x %any], align 16 + %retparam646 = alloca i64, align 8 + %taddr647 = alloca %any, align 8 + %indirectarg651 = alloca %"any[]", align 8 + %error_var657 = alloca i64, align 8 + %error_var663 = alloca i64, align 8 + call void @llvm.memset.p0.i64(ptr align 4 %literal, i8 0, i64 32, i1 false) + call void @llvm.memcpy.p0.p0.i32(ptr align 16 %x, ptr align 4 %literal, i32 32, i1 false) + %0 = call ptr @std.io.stdout() + call void @llvm.memcpy.p0.p0.i32(ptr align 16 %x1, ptr align 16 %x, i32 32, i1 false) + call void @llvm.memcpy.p0.p0.i32(ptr align 16 %x2, ptr align 16 %x1, i32 32, i1 false) + %1 = insertvalue %any undef, ptr %0, 0 + %2 = insertvalue %any %1, i64 ptrtoint (ptr @"$ct.std.io.File" to i64), 1 + %3 = insertvalue %any undef, ptr %x2, 0 + %4 = insertvalue %any %3, i64 ptrtoint (ptr @"$ct.a8$int" to i64), 1 + store %any %4, ptr %varargslots, align 16 + %5 = insertvalue %"any[]" undef, ptr %varargslots, 0 + %"$$temp" = insertvalue %"any[]" %5, i64 1, 1 + store %any %2, ptr %taddr, align 8 + %lo = load i64, ptr %taddr, align 8 + %ptradd = getelementptr inbounds i8, ptr %taddr, i64 8 + %hi = load ptr, ptr %ptradd, align 8 + store %"any[]" %"$$temp", ptr %indirectarg, align 8 + %6 = call i64 @std.io.fprintf(ptr %retparam, i64 %lo, ptr %hi, ptr @.str.8, i64 2, ptr byval(%"any[]") align 8 %indirectarg) + %not_err = icmp eq i64 %6, 0 + %7 = call i1 @llvm.expect.i1(i1 %not_err, i1 true) + br i1 %7, label %after_check, label %assign_optional + +assign_optional: ; preds = %entry + store i64 %6, ptr %error_var, align 8 + br label %guard_block + +after_check: ; preds = %entry + br label %noerr_block + +guard_block: ; preds = %assign_optional + br label %voiderr + +noerr_block: ; preds = %after_check + %8 = load i64, ptr %retparam, align 8 + store i64 %8, ptr %len, align 8 + %9 = call i64 @std.io.File.write_byte(ptr %0, i8 zeroext 10) + %not_err5 = icmp eq i64 %9, 0 + %10 = call i1 @llvm.expect.i1(i1 %not_err5, i1 true) + br i1 %10, label %after_check7, label %assign_optional6 + +assign_optional6: ; preds = %noerr_block + store i64 %9, ptr %error_var4, align 8 + br label %guard_block8 + +after_check7: ; preds = %noerr_block + br label %noerr_block9 + +guard_block8: ; preds = %assign_optional6 + br label %voiderr + +noerr_block9: ; preds = %after_check7 + %11 = call i64 @std.io.File.flush(ptr %0) + %not_err11 = icmp eq i64 %11, 0 + %12 = call i1 @llvm.expect.i1(i1 %not_err11, i1 true) + br i1 %12, label %after_check13, label %assign_optional12 + +assign_optional12: ; preds = %noerr_block9 + store i64 %11, ptr %error_var10, align 8 + br label %guard_block14 + +after_check13: ; preds = %noerr_block9 + br label %noerr_block15 + +guard_block14: ; preds = %assign_optional12 + br label %voiderr + +noerr_block15: ; preds = %after_check13 + %13 = load i64, ptr %len, align 8 + %add = add i64 %13, 1 + br label %voiderr + +voiderr: ; preds = %noerr_block15, %guard_block14, %guard_block8, %guard_block + store i32 0, ptr %literal16, align 4 + %ptradd17 = getelementptr inbounds i8, ptr %literal16, i64 4 + store i32 0, ptr %ptradd17, align 4 + %ptradd18 = getelementptr inbounds i8, ptr %literal16, i64 8 + store i32 0, ptr %ptradd18, align 4 + %ptradd19 = getelementptr inbounds i8, ptr %literal16, i64 12 + store i32 1, ptr %ptradd19, align 4 + %ptradd20 = getelementptr inbounds i8, ptr %literal16, i64 16 + store i32 2, ptr %ptradd20, align 4 + call void @llvm.memcpy.p0.p0.i32(ptr align 16 %x21, ptr align 4 %literal16, i32 20, i1 false) + %14 = call ptr @std.io.stdout() + call void @llvm.memcpy.p0.p0.i32(ptr align 16 %x22, ptr align 16 %x21, i32 20, i1 false) + call void @llvm.memcpy.p0.p0.i32(ptr align 16 %x25, ptr align 16 %x22, i32 20, i1 false) + %15 = insertvalue %any undef, ptr %14, 0 + %16 = insertvalue %any %15, i64 ptrtoint (ptr @"$ct.std.io.File" to i64), 1 + %17 = insertvalue %any undef, ptr %x25, 0 + %18 = insertvalue %any %17, i64 ptrtoint (ptr @"$ct.a5$int" to i64), 1 + store %any %18, ptr %varargslots27, align 16 + %19 = insertvalue %"any[]" undef, ptr %varargslots27, 0 + %"$$temp28" = insertvalue %"any[]" %19, i64 1, 1 + store %any %16, ptr %taddr30, align 8 + %lo31 = load i64, ptr %taddr30, align 8 + %ptradd32 = getelementptr inbounds i8, ptr %taddr30, i64 8 + %hi33 = load ptr, ptr %ptradd32, align 8 + store %"any[]" %"$$temp28", ptr %indirectarg34, align 8 + %20 = call i64 @std.io.fprintf(ptr %retparam29, i64 %lo31, ptr %hi33, ptr @.str.9, i64 2, ptr byval(%"any[]") align 8 %indirectarg34) + %not_err35 = icmp eq i64 %20, 0 + %21 = call i1 @llvm.expect.i1(i1 %not_err35, i1 true) + br i1 %21, label %after_check37, label %assign_optional36 + +assign_optional36: ; preds = %voiderr + store i64 %20, ptr %error_var24, align 8 + br label %guard_block38 + +after_check37: ; preds = %voiderr + br label %noerr_block39 + +guard_block38: ; preds = %assign_optional36 + br label %voiderr53 + +noerr_block39: ; preds = %after_check37 + %22 = load i64, ptr %retparam29, align 8 + store i64 %22, ptr %len23, align 8 + %23 = call i64 @std.io.File.write_byte(ptr %14, i8 zeroext 10) + %not_err41 = icmp eq i64 %23, 0 + %24 = call i1 @llvm.expect.i1(i1 %not_err41, i1 true) + br i1 %24, label %after_check43, label %assign_optional42 + +assign_optional42: ; preds = %noerr_block39 + store i64 %23, ptr %error_var40, align 8 + br label %guard_block44 + +after_check43: ; preds = %noerr_block39 + br label %noerr_block45 + +guard_block44: ; preds = %assign_optional42 + br label %voiderr53 + +noerr_block45: ; preds = %after_check43 + %25 = call i64 @std.io.File.flush(ptr %14) + %not_err47 = icmp eq i64 %25, 0 + %26 = call i1 @llvm.expect.i1(i1 %not_err47, i1 true) + br i1 %26, label %after_check49, label %assign_optional48 + +assign_optional48: ; preds = %noerr_block45 + store i64 %25, ptr %error_var46, align 8 + br label %guard_block50 + +after_check49: ; preds = %noerr_block45 + br label %noerr_block51 + +guard_block50: ; preds = %assign_optional48 + br label %voiderr53 + +noerr_block51: ; preds = %after_check49 + %27 = load i64, ptr %len23, align 8 + %add52 = add i64 %27, 1 + br label %voiderr53 + +voiderr53: ; preds = %noerr_block51, %guard_block50, %guard_block44, %guard_block38 + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %literal54, ptr align 16 @.__const.10, i32 20, i1 false) + call void @llvm.memcpy.p0.p0.i32(ptr align 16 %x55, ptr align 4 %literal54, i32 20, i1 false) + %28 = call ptr @std.io.stdout() + call void @llvm.memcpy.p0.p0.i32(ptr align 16 %x56, ptr align 16 %x55, i32 20, i1 false) + call void @llvm.memcpy.p0.p0.i32(ptr align 16 %x59, ptr align 16 %x56, i32 20, i1 false) + %29 = insertvalue %any undef, ptr %28, 0 + %30 = insertvalue %any %29, i64 ptrtoint (ptr @"$ct.std.io.File" to i64), 1 + %31 = insertvalue %any undef, ptr %x59, 0 + %32 = insertvalue %any %31, i64 ptrtoint (ptr @"$ct.a5$int" to i64), 1 + store %any %32, ptr %varargslots61, align 16 + %33 = insertvalue %"any[]" undef, ptr %varargslots61, 0 + %"$$temp62" = insertvalue %"any[]" %33, i64 1, 1 + store %any %30, ptr %taddr64, align 8 + %lo65 = load i64, ptr %taddr64, align 8 + %ptradd66 = getelementptr inbounds i8, ptr %taddr64, i64 8 + %hi67 = load ptr, ptr %ptradd66, align 8 + store %"any[]" %"$$temp62", ptr %indirectarg68, align 8 + %34 = call i64 @std.io.fprintf(ptr %retparam63, i64 %lo65, ptr %hi67, ptr @.str.11, i64 2, ptr byval(%"any[]") align 8 %indirectarg68) + %not_err69 = icmp eq i64 %34, 0 + %35 = call i1 @llvm.expect.i1(i1 %not_err69, i1 true) + br i1 %35, label %after_check71, label %assign_optional70 + +assign_optional70: ; preds = %voiderr53 + store i64 %34, ptr %error_var58, align 8 + br label %guard_block72 + +after_check71: ; preds = %voiderr53 + br label %noerr_block73 + +guard_block72: ; preds = %assign_optional70 + br label %voiderr87 + +noerr_block73: ; preds = %after_check71 + %36 = load i64, ptr %retparam63, align 8 + store i64 %36, ptr %len57, align 8 + %37 = call i64 @std.io.File.write_byte(ptr %28, i8 zeroext 10) + %not_err75 = icmp eq i64 %37, 0 + %38 = call i1 @llvm.expect.i1(i1 %not_err75, i1 true) + br i1 %38, label %after_check77, label %assign_optional76 + +assign_optional76: ; preds = %noerr_block73 + store i64 %37, ptr %error_var74, align 8 + br label %guard_block78 + +after_check77: ; preds = %noerr_block73 + br label %noerr_block79 + +guard_block78: ; preds = %assign_optional76 + br label %voiderr87 + +noerr_block79: ; preds = %after_check77 + %39 = call i64 @std.io.File.flush(ptr %28) + %not_err81 = icmp eq i64 %39, 0 + %40 = call i1 @llvm.expect.i1(i1 %not_err81, i1 true) + br i1 %40, label %after_check83, label %assign_optional82 + +assign_optional82: ; preds = %noerr_block79 + store i64 %39, ptr %error_var80, align 8 + br label %guard_block84 + +after_check83: ; preds = %noerr_block79 + br label %noerr_block85 + +guard_block84: ; preds = %assign_optional82 + br label %voiderr87 + +noerr_block85: ; preds = %after_check83 + %41 = load i64, ptr %len57, align 8 + %add86 = add i64 %41, 1 + br label %voiderr87 + +voiderr87: ; preds = %noerr_block85, %guard_block84, %guard_block78, %guard_block72 + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %literal88, ptr align 16 @.__const.12, i32 32, i1 false) + call void @llvm.memcpy.p0.p0.i32(ptr align 16 %x89, ptr align 4 %literal88, i32 32, i1 false) + %42 = call ptr @std.io.stdout() + call void @llvm.memcpy.p0.p0.i32(ptr align 16 %x90, ptr align 16 %x89, i32 32, i1 false) + call void @llvm.memcpy.p0.p0.i32(ptr align 16 %x93, ptr align 16 %x90, i32 32, i1 false) + %43 = insertvalue %any undef, ptr %42, 0 + %44 = insertvalue %any %43, i64 ptrtoint (ptr @"$ct.std.io.File" to i64), 1 + %45 = insertvalue %any undef, ptr %x93, 0 + %46 = insertvalue %any %45, i64 ptrtoint (ptr @"$ct.a8$int" to i64), 1 + store %any %46, ptr %varargslots95, align 16 + %47 = insertvalue %"any[]" undef, ptr %varargslots95, 0 + %"$$temp96" = insertvalue %"any[]" %47, i64 1, 1 + store %any %44, ptr %taddr98, align 8 + %lo99 = load i64, ptr %taddr98, align 8 + %ptradd100 = getelementptr inbounds i8, ptr %taddr98, i64 8 + %hi101 = load ptr, ptr %ptradd100, align 8 + store %"any[]" %"$$temp96", ptr %indirectarg102, align 8 + %48 = call i64 @std.io.fprintf(ptr %retparam97, i64 %lo99, ptr %hi101, ptr @.str.13, i64 2, ptr byval(%"any[]") align 8 %indirectarg102) + %not_err103 = icmp eq i64 %48, 0 + %49 = call i1 @llvm.expect.i1(i1 %not_err103, i1 true) + br i1 %49, label %after_check105, label %assign_optional104 + +assign_optional104: ; preds = %voiderr87 + store i64 %48, ptr %error_var92, align 8 + br label %guard_block106 + +after_check105: ; preds = %voiderr87 + br label %noerr_block107 + +guard_block106: ; preds = %assign_optional104 + br label %voiderr121 + +noerr_block107: ; preds = %after_check105 + %50 = load i64, ptr %retparam97, align 8 + store i64 %50, ptr %len91, align 8 + %51 = call i64 @std.io.File.write_byte(ptr %42, i8 zeroext 10) + %not_err109 = icmp eq i64 %51, 0 + %52 = call i1 @llvm.expect.i1(i1 %not_err109, i1 true) + br i1 %52, label %after_check111, label %assign_optional110 + +assign_optional110: ; preds = %noerr_block107 + store i64 %51, ptr %error_var108, align 8 + br label %guard_block112 + +after_check111: ; preds = %noerr_block107 + br label %noerr_block113 + +guard_block112: ; preds = %assign_optional110 + br label %voiderr121 + +noerr_block113: ; preds = %after_check111 + %53 = call i64 @std.io.File.flush(ptr %42) + %not_err115 = icmp eq i64 %53, 0 + %54 = call i1 @llvm.expect.i1(i1 %not_err115, i1 true) + br i1 %54, label %after_check117, label %assign_optional116 + +assign_optional116: ; preds = %noerr_block113 + store i64 %53, ptr %error_var114, align 8 + br label %guard_block118 + +after_check117: ; preds = %noerr_block113 + br label %noerr_block119 + +guard_block118: ; preds = %assign_optional116 + br label %voiderr121 + +noerr_block119: ; preds = %after_check117 + %55 = load i64, ptr %len91, align 8 + %add120 = add i64 %55, 1 + br label %voiderr121 + +voiderr121: ; preds = %noerr_block119, %guard_block118, %guard_block112, %guard_block106 + store i32 1, ptr %literal122, align 4 + %ptradd123 = getelementptr inbounds i8, ptr %literal122, i64 4 + store i32 2, ptr %ptradd123, align 4 + %ptradd124 = getelementptr inbounds i8, ptr %literal122, i64 8 + store i32 0, ptr %ptradd124, align 4 + %ptradd125 = getelementptr inbounds i8, ptr %literal122, i64 12 + store i32 0, ptr %ptradd125, align 4 + %ptradd126 = getelementptr inbounds i8, ptr %literal122, i64 16 + store i32 0, ptr %ptradd126, align 4 + call void @llvm.memcpy.p0.p0.i32(ptr align 16 %x127, ptr align 4 %literal122, i32 20, i1 false) + %56 = call ptr @std.io.stdout() + call void @llvm.memcpy.p0.p0.i32(ptr align 16 %x128, ptr align 16 %x127, i32 20, i1 false) + call void @llvm.memcpy.p0.p0.i32(ptr align 16 %x131, ptr align 16 %x128, i32 20, i1 false) + %57 = insertvalue %any undef, ptr %56, 0 + %58 = insertvalue %any %57, i64 ptrtoint (ptr @"$ct.std.io.File" to i64), 1 + %59 = insertvalue %any undef, ptr %x131, 0 + %60 = insertvalue %any %59, i64 ptrtoint (ptr @"$ct.a5$int" to i64), 1 + store %any %60, ptr %varargslots133, align 16 + %61 = insertvalue %"any[]" undef, ptr %varargslots133, 0 + %"$$temp134" = insertvalue %"any[]" %61, i64 1, 1 + store %any %58, ptr %taddr136, align 8 + %lo137 = load i64, ptr %taddr136, align 8 + %ptradd138 = getelementptr inbounds i8, ptr %taddr136, i64 8 + %hi139 = load ptr, ptr %ptradd138, align 8 + store %"any[]" %"$$temp134", ptr %indirectarg140, align 8 + %62 = call i64 @std.io.fprintf(ptr %retparam135, i64 %lo137, ptr %hi139, ptr @.str.14, i64 2, ptr byval(%"any[]") align 8 %indirectarg140) + %not_err141 = icmp eq i64 %62, 0 + %63 = call i1 @llvm.expect.i1(i1 %not_err141, i1 true) + br i1 %63, label %after_check143, label %assign_optional142 + +assign_optional142: ; preds = %voiderr121 + store i64 %62, ptr %error_var130, align 8 + br label %guard_block144 + +after_check143: ; preds = %voiderr121 + br label %noerr_block145 + +guard_block144: ; preds = %assign_optional142 + br label %voiderr159 + +noerr_block145: ; preds = %after_check143 + %64 = load i64, ptr %retparam135, align 8 + store i64 %64, ptr %len129, align 8 + %65 = call i64 @std.io.File.write_byte(ptr %56, i8 zeroext 10) + %not_err147 = icmp eq i64 %65, 0 + %66 = call i1 @llvm.expect.i1(i1 %not_err147, i1 true) + br i1 %66, label %after_check149, label %assign_optional148 + +assign_optional148: ; preds = %noerr_block145 + store i64 %65, ptr %error_var146, align 8 + br label %guard_block150 + +after_check149: ; preds = %noerr_block145 + br label %noerr_block151 + +guard_block150: ; preds = %assign_optional148 + br label %voiderr159 + +noerr_block151: ; preds = %after_check149 + %67 = call i64 @std.io.File.flush(ptr %56) + %not_err153 = icmp eq i64 %67, 0 + %68 = call i1 @llvm.expect.i1(i1 %not_err153, i1 true) + br i1 %68, label %after_check155, label %assign_optional154 + +assign_optional154: ; preds = %noerr_block151 + store i64 %67, ptr %error_var152, align 8 + br label %guard_block156 + +after_check155: ; preds = %noerr_block151 + br label %noerr_block157 + +guard_block156: ; preds = %assign_optional154 + br label %voiderr159 + +noerr_block157: ; preds = %after_check155 + %69 = load i64, ptr %len129, align 8 + %add158 = add i64 %69, 1 + br label %voiderr159 + +voiderr159: ; preds = %noerr_block157, %guard_block156, %guard_block150, %guard_block144 + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %literal160, ptr align 16 @.__const.15, i32 16, i1 false) + call void @llvm.memcpy.p0.p0.i32(ptr align 16 %x161, ptr align 4 %literal160, i32 16, i1 false) + %70 = call ptr @std.io.stdout() + call void @llvm.memcpy.p0.p0.i32(ptr align 16 %x162, ptr align 16 %x161, i32 16, i1 false) + call void @llvm.memcpy.p0.p0.i32(ptr align 16 %x165, ptr align 16 %x162, i32 16, i1 false) + %71 = insertvalue %any undef, ptr %70, 0 + %72 = insertvalue %any %71, i64 ptrtoint (ptr @"$ct.std.io.File" to i64), 1 + %73 = insertvalue %any undef, ptr %x165, 0 + %74 = insertvalue %any %73, i64 ptrtoint (ptr @"$ct.a4$int" to i64), 1 + store %any %74, ptr %varargslots167, align 16 + %75 = insertvalue %"any[]" undef, ptr %varargslots167, 0 + %"$$temp168" = insertvalue %"any[]" %75, i64 1, 1 + store %any %72, ptr %taddr170, align 8 + %lo171 = load i64, ptr %taddr170, align 8 + %ptradd172 = getelementptr inbounds i8, ptr %taddr170, i64 8 + %hi173 = load ptr, ptr %ptradd172, align 8 + store %"any[]" %"$$temp168", ptr %indirectarg174, align 8 + %76 = call i64 @std.io.fprintf(ptr %retparam169, i64 %lo171, ptr %hi173, ptr @.str.16, i64 2, ptr byval(%"any[]") align 8 %indirectarg174) + %not_err175 = icmp eq i64 %76, 0 + %77 = call i1 @llvm.expect.i1(i1 %not_err175, i1 true) + br i1 %77, label %after_check177, label %assign_optional176 + +assign_optional176: ; preds = %voiderr159 + store i64 %76, ptr %error_var164, align 8 + br label %guard_block178 + +after_check177: ; preds = %voiderr159 + br label %noerr_block179 + +guard_block178: ; preds = %assign_optional176 + br label %voiderr193 + +noerr_block179: ; preds = %after_check177 + %78 = load i64, ptr %retparam169, align 8 + store i64 %78, ptr %len163, align 8 + %79 = call i64 @std.io.File.write_byte(ptr %70, i8 zeroext 10) + %not_err181 = icmp eq i64 %79, 0 + %80 = call i1 @llvm.expect.i1(i1 %not_err181, i1 true) + br i1 %80, label %after_check183, label %assign_optional182 + +assign_optional182: ; preds = %noerr_block179 + store i64 %79, ptr %error_var180, align 8 + br label %guard_block184 + +after_check183: ; preds = %noerr_block179 + br label %noerr_block185 + +guard_block184: ; preds = %assign_optional182 + br label %voiderr193 + +noerr_block185: ; preds = %after_check183 + %81 = call i64 @std.io.File.flush(ptr %70) + %not_err187 = icmp eq i64 %81, 0 + %82 = call i1 @llvm.expect.i1(i1 %not_err187, i1 true) + br i1 %82, label %after_check189, label %assign_optional188 + +assign_optional188: ; preds = %noerr_block185 + store i64 %81, ptr %error_var186, align 8 + br label %guard_block190 + +after_check189: ; preds = %noerr_block185 + br label %noerr_block191 + +guard_block190: ; preds = %assign_optional188 + br label %voiderr193 + +noerr_block191: ; preds = %after_check189 + %83 = load i64, ptr %len163, align 8 + %add192 = add i64 %83, 1 + br label %voiderr193 + +voiderr193: ; preds = %noerr_block191, %guard_block190, %guard_block184, %guard_block178 + store i32 1, ptr %literal194, align 4 + %ptradd195 = getelementptr inbounds i8, ptr %literal194, i64 4 + store i32 2, ptr %ptradd195, align 4 + %ptradd196 = getelementptr inbounds i8, ptr %literal194, i64 8 + store i32 99, ptr %ptradd196, align 4 + %ptradd197 = getelementptr inbounds i8, ptr %literal194, i64 12 + store i32 0, ptr %ptradd197, align 4 + %ptradd198 = getelementptr inbounds i8, ptr %literal194, i64 16 + store i32 0, ptr %ptradd198, align 4 + %ptradd199 = getelementptr inbounds i8, ptr %literal194, i64 20 + store i32 1, ptr %ptradd199, align 4 + %ptradd200 = getelementptr inbounds i8, ptr %literal194, i64 24 + store i32 0, ptr %ptradd200, align 4 + call void @llvm.memcpy.p0.p0.i32(ptr align 16 %x201, ptr align 4 %literal194, i32 28, i1 false) + %84 = call ptr @std.io.stdout() + call void @llvm.memcpy.p0.p0.i32(ptr align 16 %x202, ptr align 16 %x201, i32 28, i1 false) + call void @llvm.memcpy.p0.p0.i32(ptr align 16 %x205, ptr align 16 %x202, i32 28, i1 false) + %85 = insertvalue %any undef, ptr %84, 0 + %86 = insertvalue %any %85, i64 ptrtoint (ptr @"$ct.std.io.File" to i64), 1 + %87 = insertvalue %any undef, ptr %x205, 0 + %88 = insertvalue %any %87, i64 ptrtoint (ptr @"$ct.a7$int" to i64), 1 + store %any %88, ptr %varargslots207, align 16 + %89 = insertvalue %"any[]" undef, ptr %varargslots207, 0 + %"$$temp208" = insertvalue %"any[]" %89, i64 1, 1 + store %any %86, ptr %taddr210, align 8 + %lo211 = load i64, ptr %taddr210, align 8 + %ptradd212 = getelementptr inbounds i8, ptr %taddr210, i64 8 + %hi213 = load ptr, ptr %ptradd212, align 8 + store %"any[]" %"$$temp208", ptr %indirectarg214, align 8 + %90 = call i64 @std.io.fprintf(ptr %retparam209, i64 %lo211, ptr %hi213, ptr @.str.17, i64 2, ptr byval(%"any[]") align 8 %indirectarg214) + %not_err215 = icmp eq i64 %90, 0 + %91 = call i1 @llvm.expect.i1(i1 %not_err215, i1 true) + br i1 %91, label %after_check217, label %assign_optional216 + +assign_optional216: ; preds = %voiderr193 + store i64 %90, ptr %error_var204, align 8 + br label %guard_block218 + +after_check217: ; preds = %voiderr193 + br label %noerr_block219 + +guard_block218: ; preds = %assign_optional216 + br label %voiderr233 + +noerr_block219: ; preds = %after_check217 + %92 = load i64, ptr %retparam209, align 8 + store i64 %92, ptr %len203, align 8 + %93 = call i64 @std.io.File.write_byte(ptr %84, i8 zeroext 10) + %not_err221 = icmp eq i64 %93, 0 + %94 = call i1 @llvm.expect.i1(i1 %not_err221, i1 true) + br i1 %94, label %after_check223, label %assign_optional222 + +assign_optional222: ; preds = %noerr_block219 + store i64 %93, ptr %error_var220, align 8 + br label %guard_block224 + +after_check223: ; preds = %noerr_block219 + br label %noerr_block225 + +guard_block224: ; preds = %assign_optional222 + br label %voiderr233 + +noerr_block225: ; preds = %after_check223 + %95 = call i64 @std.io.File.flush(ptr %84) + %not_err227 = icmp eq i64 %95, 0 + %96 = call i1 @llvm.expect.i1(i1 %not_err227, i1 true) + br i1 %96, label %after_check229, label %assign_optional228 + +assign_optional228: ; preds = %noerr_block225 + store i64 %95, ptr %error_var226, align 8 + br label %guard_block230 + +after_check229: ; preds = %noerr_block225 + br label %noerr_block231 + +guard_block230: ; preds = %assign_optional228 + br label %voiderr233 + +noerr_block231: ; preds = %after_check229 + %97 = load i64, ptr %len203, align 8 + %add232 = add i64 %97, 1 + br label %voiderr233 + +voiderr233: ; preds = %noerr_block231, %guard_block230, %guard_block224, %guard_block218 + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %literal234, ptr align 16 @.__const.18, i32 32, i1 false) + call void @llvm.memcpy.p0.p0.i32(ptr align 16 %x235, ptr align 4 %literal234, i32 32, i1 false) + %98 = call ptr @std.io.stdout() + call void @llvm.memcpy.p0.p0.i32(ptr align 16 %x236, ptr align 16 %x235, i32 32, i1 false) + call void @llvm.memcpy.p0.p0.i32(ptr align 16 %x239, ptr align 16 %x236, i32 32, i1 false) + %99 = insertvalue %any undef, ptr %98, 0 + %100 = insertvalue %any %99, i64 ptrtoint (ptr @"$ct.std.io.File" to i64), 1 + %101 = insertvalue %any undef, ptr %x239, 0 + %102 = insertvalue %any %101, i64 ptrtoint (ptr @"$ct.a8$int" to i64), 1 + store %any %102, ptr %varargslots241, align 16 + %103 = insertvalue %"any[]" undef, ptr %varargslots241, 0 + %"$$temp242" = insertvalue %"any[]" %103, i64 1, 1 + store %any %100, ptr %taddr244, align 8 + %lo245 = load i64, ptr %taddr244, align 8 + %ptradd246 = getelementptr inbounds i8, ptr %taddr244, i64 8 + %hi247 = load ptr, ptr %ptradd246, align 8 + store %"any[]" %"$$temp242", ptr %indirectarg248, align 8 + %104 = call i64 @std.io.fprintf(ptr %retparam243, i64 %lo245, ptr %hi247, ptr @.str.19, i64 2, ptr byval(%"any[]") align 8 %indirectarg248) + %not_err249 = icmp eq i64 %104, 0 + %105 = call i1 @llvm.expect.i1(i1 %not_err249, i1 true) + br i1 %105, label %after_check251, label %assign_optional250 + +assign_optional250: ; preds = %voiderr233 + store i64 %104, ptr %error_var238, align 8 + br label %guard_block252 + +after_check251: ; preds = %voiderr233 + br label %noerr_block253 + +guard_block252: ; preds = %assign_optional250 + br label %voiderr267 + +noerr_block253: ; preds = %after_check251 + %106 = load i64, ptr %retparam243, align 8 + store i64 %106, ptr %len237, align 8 + %107 = call i64 @std.io.File.write_byte(ptr %98, i8 zeroext 10) + %not_err255 = icmp eq i64 %107, 0 + %108 = call i1 @llvm.expect.i1(i1 %not_err255, i1 true) + br i1 %108, label %after_check257, label %assign_optional256 + +assign_optional256: ; preds = %noerr_block253 + store i64 %107, ptr %error_var254, align 8 + br label %guard_block258 + +after_check257: ; preds = %noerr_block253 + br label %noerr_block259 + +guard_block258: ; preds = %assign_optional256 + br label %voiderr267 + +noerr_block259: ; preds = %after_check257 + %109 = call i64 @std.io.File.flush(ptr %98) + %not_err261 = icmp eq i64 %109, 0 + %110 = call i1 @llvm.expect.i1(i1 %not_err261, i1 true) + br i1 %110, label %after_check263, label %assign_optional262 + +assign_optional262: ; preds = %noerr_block259 + store i64 %109, ptr %error_var260, align 8 + br label %guard_block264 + +after_check263: ; preds = %noerr_block259 + br label %noerr_block265 + +guard_block264: ; preds = %assign_optional262 + br label %voiderr267 + +noerr_block265: ; preds = %after_check263 + %111 = load i64, ptr %len237, align 8 + %add266 = add i64 %111, 1 + br label %voiderr267 + +voiderr267: ; preds = %noerr_block265, %guard_block264, %guard_block258, %guard_block252 + store i32 99, ptr %literal268, align 4 + %ptradd269 = getelementptr inbounds i8, ptr %literal268, i64 4 + store i32 0, ptr %ptradd269, align 4 + %ptradd270 = getelementptr inbounds i8, ptr %literal268, i64 8 + store i32 0, ptr %ptradd270, align 4 + %ptradd271 = getelementptr inbounds i8, ptr %literal268, i64 12 + store i32 1, ptr %ptradd271, align 4 + %ptradd272 = getelementptr inbounds i8, ptr %literal268, i64 16 + store i32 0, ptr %ptradd272, align 4 + %ptradd273 = getelementptr inbounds i8, ptr %literal268, i64 20 + store i32 1, ptr %ptradd273, align 4 + %ptradd274 = getelementptr inbounds i8, ptr %literal268, i64 24 + store i32 2, ptr %ptradd274, align 4 + call void @llvm.memcpy.p0.p0.i32(ptr align 16 %x275, ptr align 4 %literal268, i32 28, i1 false) + %112 = call ptr @std.io.stdout() + call void @llvm.memcpy.p0.p0.i32(ptr align 16 %x276, ptr align 16 %x275, i32 28, i1 false) + call void @llvm.memcpy.p0.p0.i32(ptr align 16 %x279, ptr align 16 %x276, i32 28, i1 false) + %113 = insertvalue %any undef, ptr %112, 0 + %114 = insertvalue %any %113, i64 ptrtoint (ptr @"$ct.std.io.File" to i64), 1 + %115 = insertvalue %any undef, ptr %x279, 0 + %116 = insertvalue %any %115, i64 ptrtoint (ptr @"$ct.a7$int" to i64), 1 + store %any %116, ptr %varargslots281, align 16 + %117 = insertvalue %"any[]" undef, ptr %varargslots281, 0 + %"$$temp282" = insertvalue %"any[]" %117, i64 1, 1 + store %any %114, ptr %taddr284, align 8 + %lo285 = load i64, ptr %taddr284, align 8 + %ptradd286 = getelementptr inbounds i8, ptr %taddr284, i64 8 + %hi287 = load ptr, ptr %ptradd286, align 8 + store %"any[]" %"$$temp282", ptr %indirectarg288, align 8 + %118 = call i64 @std.io.fprintf(ptr %retparam283, i64 %lo285, ptr %hi287, ptr @.str.20, i64 2, ptr byval(%"any[]") align 8 %indirectarg288) + %not_err289 = icmp eq i64 %118, 0 + %119 = call i1 @llvm.expect.i1(i1 %not_err289, i1 true) + br i1 %119, label %after_check291, label %assign_optional290 + +assign_optional290: ; preds = %voiderr267 + store i64 %118, ptr %error_var278, align 8 + br label %guard_block292 + +after_check291: ; preds = %voiderr267 + br label %noerr_block293 + +guard_block292: ; preds = %assign_optional290 + br label %voiderr307 + +noerr_block293: ; preds = %after_check291 + %120 = load i64, ptr %retparam283, align 8 + store i64 %120, ptr %len277, align 8 + %121 = call i64 @std.io.File.write_byte(ptr %112, i8 zeroext 10) + %not_err295 = icmp eq i64 %121, 0 + %122 = call i1 @llvm.expect.i1(i1 %not_err295, i1 true) + br i1 %122, label %after_check297, label %assign_optional296 + +assign_optional296: ; preds = %noerr_block293 + store i64 %121, ptr %error_var294, align 8 + br label %guard_block298 + +after_check297: ; preds = %noerr_block293 + br label %noerr_block299 + +guard_block298: ; preds = %assign_optional296 + br label %voiderr307 + +noerr_block299: ; preds = %after_check297 + %123 = call i64 @std.io.File.flush(ptr %112) + %not_err301 = icmp eq i64 %123, 0 + %124 = call i1 @llvm.expect.i1(i1 %not_err301, i1 true) + br i1 %124, label %after_check303, label %assign_optional302 + +assign_optional302: ; preds = %noerr_block299 + store i64 %123, ptr %error_var300, align 8 + br label %guard_block304 + +after_check303: ; preds = %noerr_block299 + br label %noerr_block305 + +guard_block304: ; preds = %assign_optional302 + br label %voiderr307 + +noerr_block305: ; preds = %after_check303 + %125 = load i64, ptr %len277, align 8 + %add306 = add i64 %125, 1 + br label %voiderr307 + +voiderr307: ; preds = %noerr_block305, %guard_block304, %guard_block298, %guard_block292 + call void @llvm.memset.p0.i64(ptr align 4 %literal308, i8 0, i64 40, i1 false) + store i32 99, ptr %literal308, align 4 + %ptradd309 = getelementptr inbounds i8, ptr %literal308, i64 12 + store i32 1, ptr %ptradd309, align 4 + %ptradd310 = getelementptr inbounds i8, ptr %literal308, i64 20 + store i32 99, ptr %ptradd310, align 4 + %ptradd311 = getelementptr inbounds i8, ptr %literal308, i64 32 + store i32 1, ptr %ptradd311, align 4 + call void @llvm.memcpy.p0.p0.i32(ptr align 16 %x312, ptr align 4 %literal308, i32 40, i1 false) + %126 = call ptr @std.io.stdout() + call void @llvm.memcpy.p0.p0.i32(ptr align 16 %x313, ptr align 16 %x312, i32 40, i1 false) + call void @llvm.memcpy.p0.p0.i32(ptr align 16 %x316, ptr align 16 %x313, i32 40, i1 false) + %127 = insertvalue %any undef, ptr %126, 0 + %128 = insertvalue %any %127, i64 ptrtoint (ptr @"$ct.std.io.File" to i64), 1 + %129 = insertvalue %any undef, ptr %x316, 0 + %130 = insertvalue %any %129, i64 ptrtoint (ptr @"$ct.a10$int" to i64), 1 + store %any %130, ptr %varargslots318, align 16 + %131 = insertvalue %"any[]" undef, ptr %varargslots318, 0 + %"$$temp319" = insertvalue %"any[]" %131, i64 1, 1 + store %any %128, ptr %taddr321, align 8 + %lo322 = load i64, ptr %taddr321, align 8 + %ptradd323 = getelementptr inbounds i8, ptr %taddr321, i64 8 + %hi324 = load ptr, ptr %ptradd323, align 8 + store %"any[]" %"$$temp319", ptr %indirectarg325, align 8 + %132 = call i64 @std.io.fprintf(ptr %retparam320, i64 %lo322, ptr %hi324, ptr @.str.21, i64 2, ptr byval(%"any[]") align 8 %indirectarg325) + %not_err326 = icmp eq i64 %132, 0 + %133 = call i1 @llvm.expect.i1(i1 %not_err326, i1 true) + br i1 %133, label %after_check328, label %assign_optional327 + +assign_optional327: ; preds = %voiderr307 + store i64 %132, ptr %error_var315, align 8 + br label %guard_block329 + +after_check328: ; preds = %voiderr307 + br label %noerr_block330 + +guard_block329: ; preds = %assign_optional327 + br label %voiderr344 + +noerr_block330: ; preds = %after_check328 + %134 = load i64, ptr %retparam320, align 8 + store i64 %134, ptr %len314, align 8 + %135 = call i64 @std.io.File.write_byte(ptr %126, i8 zeroext 10) + %not_err332 = icmp eq i64 %135, 0 + %136 = call i1 @llvm.expect.i1(i1 %not_err332, i1 true) + br i1 %136, label %after_check334, label %assign_optional333 + +assign_optional333: ; preds = %noerr_block330 + store i64 %135, ptr %error_var331, align 8 + br label %guard_block335 + +after_check334: ; preds = %noerr_block330 + br label %noerr_block336 + +guard_block335: ; preds = %assign_optional333 + br label %voiderr344 + +noerr_block336: ; preds = %after_check334 + %137 = call i64 @std.io.File.flush(ptr %126) + %not_err338 = icmp eq i64 %137, 0 + %138 = call i1 @llvm.expect.i1(i1 %not_err338, i1 true) + br i1 %138, label %after_check340, label %assign_optional339 + +assign_optional339: ; preds = %noerr_block336 + store i64 %137, ptr %error_var337, align 8 + br label %guard_block341 + +after_check340: ; preds = %noerr_block336 + br label %noerr_block342 + +guard_block341: ; preds = %assign_optional339 + br label %voiderr344 + +noerr_block342: ; preds = %after_check340 + %139 = load i64, ptr %len314, align 8 + %add343 = add i64 %139, 1 + br label %voiderr344 + +voiderr344: ; preds = %noerr_block342, %guard_block341, %guard_block335, %guard_block329 + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %literal345, ptr align 16 @.__const.22, i32 16, i1 false) + call void @llvm.memcpy.p0.p0.i32(ptr align 16 %x346, ptr align 4 %literal345, i32 16, i1 false) + %140 = call ptr @std.io.stdout() + call void @llvm.memcpy.p0.p0.i32(ptr align 16 %x347, ptr align 16 %x346, i32 16, i1 false) + call void @llvm.memcpy.p0.p0.i32(ptr align 16 %x350, ptr align 16 %x347, i32 16, i1 false) + %141 = insertvalue %any undef, ptr %140, 0 + %142 = insertvalue %any %141, i64 ptrtoint (ptr @"$ct.std.io.File" to i64), 1 + %143 = insertvalue %any undef, ptr %x350, 0 + %144 = insertvalue %any %143, i64 ptrtoint (ptr @"$ct.a4$int" to i64), 1 + store %any %144, ptr %varargslots352, align 16 + %145 = insertvalue %"any[]" undef, ptr %varargslots352, 0 + %"$$temp353" = insertvalue %"any[]" %145, i64 1, 1 + store %any %142, ptr %taddr355, align 8 + %lo356 = load i64, ptr %taddr355, align 8 + %ptradd357 = getelementptr inbounds i8, ptr %taddr355, i64 8 + %hi358 = load ptr, ptr %ptradd357, align 8 + store %"any[]" %"$$temp353", ptr %indirectarg359, align 8 + %146 = call i64 @std.io.fprintf(ptr %retparam354, i64 %lo356, ptr %hi358, ptr @.str.23, i64 2, ptr byval(%"any[]") align 8 %indirectarg359) + %not_err360 = icmp eq i64 %146, 0 + %147 = call i1 @llvm.expect.i1(i1 %not_err360, i1 true) + br i1 %147, label %after_check362, label %assign_optional361 + +assign_optional361: ; preds = %voiderr344 + store i64 %146, ptr %error_var349, align 8 + br label %guard_block363 + +after_check362: ; preds = %voiderr344 + br label %noerr_block364 + +guard_block363: ; preds = %assign_optional361 + br label %voiderr378 + +noerr_block364: ; preds = %after_check362 + %148 = load i64, ptr %retparam354, align 8 + store i64 %148, ptr %len348, align 8 + %149 = call i64 @std.io.File.write_byte(ptr %140, i8 zeroext 10) + %not_err366 = icmp eq i64 %149, 0 + %150 = call i1 @llvm.expect.i1(i1 %not_err366, i1 true) + br i1 %150, label %after_check368, label %assign_optional367 + +assign_optional367: ; preds = %noerr_block364 + store i64 %149, ptr %error_var365, align 8 + br label %guard_block369 + +after_check368: ; preds = %noerr_block364 + br label %noerr_block370 + +guard_block369: ; preds = %assign_optional367 + br label %voiderr378 + +noerr_block370: ; preds = %after_check368 + %151 = call i64 @std.io.File.flush(ptr %140) + %not_err372 = icmp eq i64 %151, 0 + %152 = call i1 @llvm.expect.i1(i1 %not_err372, i1 true) + br i1 %152, label %after_check374, label %assign_optional373 + +assign_optional373: ; preds = %noerr_block370 + store i64 %151, ptr %error_var371, align 8 + br label %guard_block375 + +after_check374: ; preds = %noerr_block370 + br label %noerr_block376 + +guard_block375: ; preds = %assign_optional373 + br label %voiderr378 + +noerr_block376: ; preds = %after_check374 + %153 = load i64, ptr %len348, align 8 + %add377 = add i64 %153, 1 + br label %voiderr378 + +voiderr378: ; preds = %noerr_block376, %guard_block375, %guard_block369, %guard_block363 + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %literal379, ptr align 16 @.__const.24, i32 16, i1 false) + call void @llvm.memcpy.p0.p0.i32(ptr align 16 %x380, ptr align 4 %literal379, i32 16, i1 false) + %154 = call ptr @std.io.stdout() + call void @llvm.memcpy.p0.p0.i32(ptr align 16 %x381, ptr align 16 %x380, i32 16, i1 false) + call void @llvm.memcpy.p0.p0.i32(ptr align 16 %x384, ptr align 16 %x381, i32 16, i1 false) + %155 = insertvalue %any undef, ptr %154, 0 + %156 = insertvalue %any %155, i64 ptrtoint (ptr @"$ct.std.io.File" to i64), 1 + %157 = insertvalue %any undef, ptr %x384, 0 + %158 = insertvalue %any %157, i64 ptrtoint (ptr @"$ct.a4$int" to i64), 1 + store %any %158, ptr %varargslots386, align 16 + %159 = insertvalue %"any[]" undef, ptr %varargslots386, 0 + %"$$temp387" = insertvalue %"any[]" %159, i64 1, 1 + store %any %156, ptr %taddr389, align 8 + %lo390 = load i64, ptr %taddr389, align 8 + %ptradd391 = getelementptr inbounds i8, ptr %taddr389, i64 8 + %hi392 = load ptr, ptr %ptradd391, align 8 + store %"any[]" %"$$temp387", ptr %indirectarg393, align 8 + %160 = call i64 @std.io.fprintf(ptr %retparam388, i64 %lo390, ptr %hi392, ptr @.str.25, i64 2, ptr byval(%"any[]") align 8 %indirectarg393) + %not_err394 = icmp eq i64 %160, 0 + %161 = call i1 @llvm.expect.i1(i1 %not_err394, i1 true) + br i1 %161, label %after_check396, label %assign_optional395 + +assign_optional395: ; preds = %voiderr378 + store i64 %160, ptr %error_var383, align 8 + br label %guard_block397 + +after_check396: ; preds = %voiderr378 + br label %noerr_block398 + +guard_block397: ; preds = %assign_optional395 + br label %voiderr412 + +noerr_block398: ; preds = %after_check396 + %162 = load i64, ptr %retparam388, align 8 + store i64 %162, ptr %len382, align 8 + %163 = call i64 @std.io.File.write_byte(ptr %154, i8 zeroext 10) + %not_err400 = icmp eq i64 %163, 0 + %164 = call i1 @llvm.expect.i1(i1 %not_err400, i1 true) + br i1 %164, label %after_check402, label %assign_optional401 + +assign_optional401: ; preds = %noerr_block398 + store i64 %163, ptr %error_var399, align 8 + br label %guard_block403 + +after_check402: ; preds = %noerr_block398 + br label %noerr_block404 + +guard_block403: ; preds = %assign_optional401 + br label %voiderr412 + +noerr_block404: ; preds = %after_check402 + %165 = call i64 @std.io.File.flush(ptr %154) + %not_err406 = icmp eq i64 %165, 0 + %166 = call i1 @llvm.expect.i1(i1 %not_err406, i1 true) + br i1 %166, label %after_check408, label %assign_optional407 + +assign_optional407: ; preds = %noerr_block404 + store i64 %165, ptr %error_var405, align 8 + br label %guard_block409 + +after_check408: ; preds = %noerr_block404 + br label %noerr_block410 + +guard_block409: ; preds = %assign_optional407 + br label %voiderr412 + +noerr_block410: ; preds = %after_check408 + %167 = load i64, ptr %len382, align 8 + %add411 = add i64 %167, 1 + br label %voiderr412 + +voiderr412: ; preds = %noerr_block410, %guard_block409, %guard_block403, %guard_block397 + store i32 0, ptr %literal413, align 4 + %ptradd414 = getelementptr inbounds i8, ptr %literal413, i64 4 + store i32 0, ptr %ptradd414, align 4 + %ptradd415 = getelementptr inbounds i8, ptr %literal413, i64 8 + store i32 0, ptr %ptradd415, align 4 + %ptradd416 = getelementptr inbounds i8, ptr %literal413, i64 12 + store i32 98, ptr %ptradd416, align 4 + %ptradd417 = getelementptr inbounds i8, ptr %literal413, i64 16 + store i32 91, ptr %ptradd417, align 4 + call void @llvm.memcpy.p0.p0.i32(ptr align 16 %x418, ptr align 4 %literal413, i32 20, i1 false) + %168 = call ptr @std.io.stdout() + call void @llvm.memcpy.p0.p0.i32(ptr align 16 %x419, ptr align 16 %x418, i32 20, i1 false) + call void @llvm.memcpy.p0.p0.i32(ptr align 16 %x422, ptr align 16 %x419, i32 20, i1 false) + %169 = insertvalue %any undef, ptr %168, 0 + %170 = insertvalue %any %169, i64 ptrtoint (ptr @"$ct.std.io.File" to i64), 1 + %171 = insertvalue %any undef, ptr %x422, 0 + %172 = insertvalue %any %171, i64 ptrtoint (ptr @"$ct.a5$int" to i64), 1 + store %any %172, ptr %varargslots424, align 16 + %173 = insertvalue %"any[]" undef, ptr %varargslots424, 0 + %"$$temp425" = insertvalue %"any[]" %173, i64 1, 1 + store %any %170, ptr %taddr427, align 8 + %lo428 = load i64, ptr %taddr427, align 8 + %ptradd429 = getelementptr inbounds i8, ptr %taddr427, i64 8 + %hi430 = load ptr, ptr %ptradd429, align 8 + store %"any[]" %"$$temp425", ptr %indirectarg431, align 8 + %174 = call i64 @std.io.fprintf(ptr %retparam426, i64 %lo428, ptr %hi430, ptr @.str.26, i64 2, ptr byval(%"any[]") align 8 %indirectarg431) + %not_err432 = icmp eq i64 %174, 0 + %175 = call i1 @llvm.expect.i1(i1 %not_err432, i1 true) + br i1 %175, label %after_check434, label %assign_optional433 + +assign_optional433: ; preds = %voiderr412 + store i64 %174, ptr %error_var421, align 8 + br label %guard_block435 + +after_check434: ; preds = %voiderr412 + br label %noerr_block436 + +guard_block435: ; preds = %assign_optional433 + br label %voiderr450 + +noerr_block436: ; preds = %after_check434 + %176 = load i64, ptr %retparam426, align 8 + store i64 %176, ptr %len420, align 8 + %177 = call i64 @std.io.File.write_byte(ptr %168, i8 zeroext 10) + %not_err438 = icmp eq i64 %177, 0 + %178 = call i1 @llvm.expect.i1(i1 %not_err438, i1 true) + br i1 %178, label %after_check440, label %assign_optional439 + +assign_optional439: ; preds = %noerr_block436 + store i64 %177, ptr %error_var437, align 8 + br label %guard_block441 + +after_check440: ; preds = %noerr_block436 + br label %noerr_block442 + +guard_block441: ; preds = %assign_optional439 + br label %voiderr450 + +noerr_block442: ; preds = %after_check440 + %179 = call i64 @std.io.File.flush(ptr %168) + %not_err444 = icmp eq i64 %179, 0 + %180 = call i1 @llvm.expect.i1(i1 %not_err444, i1 true) + br i1 %180, label %after_check446, label %assign_optional445 + +assign_optional445: ; preds = %noerr_block442 + store i64 %179, ptr %error_var443, align 8 + br label %guard_block447 + +after_check446: ; preds = %noerr_block442 + br label %noerr_block448 + +guard_block447: ; preds = %assign_optional445 + br label %voiderr450 + +noerr_block448: ; preds = %after_check446 + %181 = load i64, ptr %len420, align 8 + %add449 = add i64 %181, 1 + br label %voiderr450 + +voiderr450: ; preds = %noerr_block448, %guard_block447, %guard_block441, %guard_block435 + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %literal451, ptr align 16 @.__const.27, i32 20, i1 false) + call void @llvm.memcpy.p0.p0.i32(ptr align 16 %x452, ptr align 4 %literal451, i32 20, i1 false) + %182 = call ptr @std.io.stdout() + call void @llvm.memcpy.p0.p0.i32(ptr align 16 %x453, ptr align 16 %x452, i32 20, i1 false) + call void @llvm.memcpy.p0.p0.i32(ptr align 16 %x456, ptr align 16 %x453, i32 20, i1 false) + %183 = insertvalue %any undef, ptr %182, 0 + %184 = insertvalue %any %183, i64 ptrtoint (ptr @"$ct.std.io.File" to i64), 1 + %185 = insertvalue %any undef, ptr %x456, 0 + %186 = insertvalue %any %185, i64 ptrtoint (ptr @"$ct.a5$int" to i64), 1 + store %any %186, ptr %varargslots458, align 16 + %187 = insertvalue %"any[]" undef, ptr %varargslots458, 0 + %"$$temp459" = insertvalue %"any[]" %187, i64 1, 1 + store %any %184, ptr %taddr461, align 8 + %lo462 = load i64, ptr %taddr461, align 8 + %ptradd463 = getelementptr inbounds i8, ptr %taddr461, i64 8 + %hi464 = load ptr, ptr %ptradd463, align 8 + store %"any[]" %"$$temp459", ptr %indirectarg465, align 8 + %188 = call i64 @std.io.fprintf(ptr %retparam460, i64 %lo462, ptr %hi464, ptr @.str.28, i64 2, ptr byval(%"any[]") align 8 %indirectarg465) + %not_err466 = icmp eq i64 %188, 0 + %189 = call i1 @llvm.expect.i1(i1 %not_err466, i1 true) + br i1 %189, label %after_check468, label %assign_optional467 + +assign_optional467: ; preds = %voiderr450 + store i64 %188, ptr %error_var455, align 8 + br label %guard_block469 + +after_check468: ; preds = %voiderr450 + br label %noerr_block470 + +guard_block469: ; preds = %assign_optional467 + br label %voiderr484 + +noerr_block470: ; preds = %after_check468 + %190 = load i64, ptr %retparam460, align 8 + store i64 %190, ptr %len454, align 8 + %191 = call i64 @std.io.File.write_byte(ptr %182, i8 zeroext 10) + %not_err472 = icmp eq i64 %191, 0 + %192 = call i1 @llvm.expect.i1(i1 %not_err472, i1 true) + br i1 %192, label %after_check474, label %assign_optional473 + +assign_optional473: ; preds = %noerr_block470 + store i64 %191, ptr %error_var471, align 8 + br label %guard_block475 + +after_check474: ; preds = %noerr_block470 + br label %noerr_block476 + +guard_block475: ; preds = %assign_optional473 + br label %voiderr484 + +noerr_block476: ; preds = %after_check474 + %193 = call i64 @std.io.File.flush(ptr %182) + %not_err478 = icmp eq i64 %193, 0 + %194 = call i1 @llvm.expect.i1(i1 %not_err478, i1 true) + br i1 %194, label %after_check480, label %assign_optional479 + +assign_optional479: ; preds = %noerr_block476 + store i64 %193, ptr %error_var477, align 8 + br label %guard_block481 + +after_check480: ; preds = %noerr_block476 + br label %noerr_block482 + +guard_block481: ; preds = %assign_optional479 + br label %voiderr484 + +noerr_block482: ; preds = %after_check480 + %195 = load i64, ptr %len454, align 8 + %add483 = add i64 %195, 1 + br label %voiderr484 + +voiderr484: ; preds = %noerr_block482, %guard_block481, %guard_block475, %guard_block469 + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %literal485, ptr align 16 @.__const.29, i32 28, i1 false) + call void @llvm.memcpy.p0.p0.i32(ptr align 16 %x486, ptr align 4 %literal485, i32 28, i1 false) + %196 = call ptr @std.io.stdout() + call void @llvm.memcpy.p0.p0.i32(ptr align 16 %x487, ptr align 16 %x486, i32 28, i1 false) + call void @llvm.memcpy.p0.p0.i32(ptr align 16 %x490, ptr align 16 %x487, i32 28, i1 false) + %197 = insertvalue %any undef, ptr %196, 0 + %198 = insertvalue %any %197, i64 ptrtoint (ptr @"$ct.std.io.File" to i64), 1 + %199 = insertvalue %any undef, ptr %x490, 0 + %200 = insertvalue %any %199, i64 ptrtoint (ptr @"$ct.a7$int" to i64), 1 + store %any %200, ptr %varargslots492, align 16 + %201 = insertvalue %"any[]" undef, ptr %varargslots492, 0 + %"$$temp493" = insertvalue %"any[]" %201, i64 1, 1 + store %any %198, ptr %taddr495, align 8 + %lo496 = load i64, ptr %taddr495, align 8 + %ptradd497 = getelementptr inbounds i8, ptr %taddr495, i64 8 + %hi498 = load ptr, ptr %ptradd497, align 8 + store %"any[]" %"$$temp493", ptr %indirectarg499, align 8 + %202 = call i64 @std.io.fprintf(ptr %retparam494, i64 %lo496, ptr %hi498, ptr @.str.30, i64 2, ptr byval(%"any[]") align 8 %indirectarg499) + %not_err500 = icmp eq i64 %202, 0 + %203 = call i1 @llvm.expect.i1(i1 %not_err500, i1 true) + br i1 %203, label %after_check502, label %assign_optional501 + +assign_optional501: ; preds = %voiderr484 + store i64 %202, ptr %error_var489, align 8 + br label %guard_block503 + +after_check502: ; preds = %voiderr484 + br label %noerr_block504 + +guard_block503: ; preds = %assign_optional501 + br label %voiderr518 + +noerr_block504: ; preds = %after_check502 + %204 = load i64, ptr %retparam494, align 8 + store i64 %204, ptr %len488, align 8 + %205 = call i64 @std.io.File.write_byte(ptr %196, i8 zeroext 10) + %not_err506 = icmp eq i64 %205, 0 + %206 = call i1 @llvm.expect.i1(i1 %not_err506, i1 true) + br i1 %206, label %after_check508, label %assign_optional507 + +assign_optional507: ; preds = %noerr_block504 + store i64 %205, ptr %error_var505, align 8 + br label %guard_block509 + +after_check508: ; preds = %noerr_block504 + br label %noerr_block510 + +guard_block509: ; preds = %assign_optional507 + br label %voiderr518 + +noerr_block510: ; preds = %after_check508 + %207 = call i64 @std.io.File.flush(ptr %196) + %not_err512 = icmp eq i64 %207, 0 + %208 = call i1 @llvm.expect.i1(i1 %not_err512, i1 true) + br i1 %208, label %after_check514, label %assign_optional513 + +assign_optional513: ; preds = %noerr_block510 + store i64 %207, ptr %error_var511, align 8 + br label %guard_block515 + +after_check514: ; preds = %noerr_block510 + br label %noerr_block516 + +guard_block515: ; preds = %assign_optional513 + br label %voiderr518 + +noerr_block516: ; preds = %after_check514 + %209 = load i64, ptr %len488, align 8 + %add517 = add i64 %209, 1 + br label %voiderr518 + +voiderr518: ; preds = %noerr_block516, %guard_block515, %guard_block509, %guard_block503 + store i32 99, ptr %literal519, align 4 + %ptradd520 = getelementptr inbounds i8, ptr %literal519, i64 4 + store i32 0, ptr %ptradd520, align 4 + %ptradd521 = getelementptr inbounds i8, ptr %literal519, i64 8 + store i32 0, ptr %ptradd521, align 4 + %ptradd522 = getelementptr inbounds i8, ptr %literal519, i64 12 + store i32 1, ptr %ptradd522, align 4 + %ptradd523 = getelementptr inbounds i8, ptr %literal519, i64 16 + store i32 0, ptr %ptradd523, align 4 + %ptradd524 = getelementptr inbounds i8, ptr %literal519, i64 20 + store i32 98, ptr %ptradd524, align 4 + %ptradd525 = getelementptr inbounds i8, ptr %literal519, i64 24 + store i32 91, ptr %ptradd525, align 4 + call void @llvm.memcpy.p0.p0.i32(ptr align 16 %x526, ptr align 4 %literal519, i32 28, i1 false) + %210 = call ptr @std.io.stdout() + call void @llvm.memcpy.p0.p0.i32(ptr align 16 %x527, ptr align 16 %x526, i32 28, i1 false) + call void @llvm.memcpy.p0.p0.i32(ptr align 16 %x530, ptr align 16 %x527, i32 28, i1 false) + %211 = insertvalue %any undef, ptr %210, 0 + %212 = insertvalue %any %211, i64 ptrtoint (ptr @"$ct.std.io.File" to i64), 1 + %213 = insertvalue %any undef, ptr %x530, 0 + %214 = insertvalue %any %213, i64 ptrtoint (ptr @"$ct.a7$int" to i64), 1 + store %any %214, ptr %varargslots532, align 16 + %215 = insertvalue %"any[]" undef, ptr %varargslots532, 0 + %"$$temp533" = insertvalue %"any[]" %215, i64 1, 1 + store %any %212, ptr %taddr535, align 8 + %lo536 = load i64, ptr %taddr535, align 8 + %ptradd537 = getelementptr inbounds i8, ptr %taddr535, i64 8 + %hi538 = load ptr, ptr %ptradd537, align 8 + store %"any[]" %"$$temp533", ptr %indirectarg539, align 8 + %216 = call i64 @std.io.fprintf(ptr %retparam534, i64 %lo536, ptr %hi538, ptr @.str.31, i64 2, ptr byval(%"any[]") align 8 %indirectarg539) + %not_err540 = icmp eq i64 %216, 0 + %217 = call i1 @llvm.expect.i1(i1 %not_err540, i1 true) + br i1 %217, label %after_check542, label %assign_optional541 + +assign_optional541: ; preds = %voiderr518 + store i64 %216, ptr %error_var529, align 8 + br label %guard_block543 + +after_check542: ; preds = %voiderr518 + br label %noerr_block544 + +guard_block543: ; preds = %assign_optional541 + br label %voiderr558 + +noerr_block544: ; preds = %after_check542 + %218 = load i64, ptr %retparam534, align 8 + store i64 %218, ptr %len528, align 8 + %219 = call i64 @std.io.File.write_byte(ptr %210, i8 zeroext 10) + %not_err546 = icmp eq i64 %219, 0 + %220 = call i1 @llvm.expect.i1(i1 %not_err546, i1 true) + br i1 %220, label %after_check548, label %assign_optional547 + +assign_optional547: ; preds = %noerr_block544 + store i64 %219, ptr %error_var545, align 8 + br label %guard_block549 + +after_check548: ; preds = %noerr_block544 + br label %noerr_block550 + +guard_block549: ; preds = %assign_optional547 + br label %voiderr558 + +noerr_block550: ; preds = %after_check548 + %221 = call i64 @std.io.File.flush(ptr %210) + %not_err552 = icmp eq i64 %221, 0 + %222 = call i1 @llvm.expect.i1(i1 %not_err552, i1 true) + br i1 %222, label %after_check554, label %assign_optional553 + +assign_optional553: ; preds = %noerr_block550 + store i64 %221, ptr %error_var551, align 8 + br label %guard_block555 + +after_check554: ; preds = %noerr_block550 + br label %noerr_block556 + +guard_block555: ; preds = %assign_optional553 + br label %voiderr558 + +noerr_block556: ; preds = %after_check554 + %223 = load i64, ptr %len528, align 8 + %add557 = add i64 %223, 1 + br label %voiderr558 + +voiderr558: ; preds = %noerr_block556, %guard_block555, %guard_block549, %guard_block543 + store i32 0, ptr %literal559, align 4 + %ptradd560 = getelementptr inbounds i8, ptr %literal559, i64 4 + store i32 0, ptr %ptradd560, align 4 + %ptradd561 = getelementptr inbounds i8, ptr %literal559, i64 8 + store i32 0, ptr %ptradd561, align 4 + %ptradd562 = getelementptr inbounds i8, ptr %literal559, i64 12 + store i32 0, ptr %ptradd562, align 4 + %ptradd563 = getelementptr inbounds i8, ptr %ptradd562, i64 4 + store i32 0, ptr %ptradd563, align 4 + %ptradd564 = getelementptr inbounds i8, ptr %ptradd562, i64 8 + store i32 0, ptr %ptradd564, align 4 + %ptradd565 = getelementptr inbounds i8, ptr %literal559, i64 24 + store i32 0, ptr %ptradd565, align 4 + %ptradd566 = getelementptr inbounds i8, ptr %ptradd565, i64 4 + store i32 0, ptr %ptradd566, align 4 + %ptradd567 = getelementptr inbounds i8, ptr %ptradd565, i64 8 + store i32 0, ptr %ptradd567, align 4 + %ptradd568 = getelementptr inbounds i8, ptr %ptradd565, i64 4 + store i32 5, ptr %ptradd568, align 4 + call void @llvm.memcpy.p0.p0.i32(ptr align 16 %x569, ptr align 4 %literal559, i32 36, i1 false) + %224 = call ptr @std.io.stdout() + call void @llvm.memcpy.p0.p0.i32(ptr align 16 %x570, ptr align 16 %x569, i32 36, i1 false) + call void @llvm.memcpy.p0.p0.i32(ptr align 16 %x573, ptr align 16 %x570, i32 36, i1 false) + %225 = insertvalue %any undef, ptr %224, 0 + %226 = insertvalue %any %225, i64 ptrtoint (ptr @"$ct.std.io.File" to i64), 1 + %227 = insertvalue %any undef, ptr %x573, 0 + %228 = insertvalue %any %227, i64 ptrtoint (ptr @"$ct.a3$a3$int" to i64), 1 + store %any %228, ptr %varargslots575, align 16 + %229 = insertvalue %"any[]" undef, ptr %varargslots575, 0 + %"$$temp576" = insertvalue %"any[]" %229, i64 1, 1 + store %any %226, ptr %taddr578, align 8 + %lo579 = load i64, ptr %taddr578, align 8 + %ptradd580 = getelementptr inbounds i8, ptr %taddr578, i64 8 + %hi581 = load ptr, ptr %ptradd580, align 8 + store %"any[]" %"$$temp576", ptr %indirectarg582, align 8 + %230 = call i64 @std.io.fprintf(ptr %retparam577, i64 %lo579, ptr %hi581, ptr @.str.32, i64 2, ptr byval(%"any[]") align 8 %indirectarg582) + %not_err583 = icmp eq i64 %230, 0 + %231 = call i1 @llvm.expect.i1(i1 %not_err583, i1 true) + br i1 %231, label %after_check585, label %assign_optional584 + +assign_optional584: ; preds = %voiderr558 + store i64 %230, ptr %error_var572, align 8 + br label %guard_block586 + +after_check585: ; preds = %voiderr558 + br label %noerr_block587 + +guard_block586: ; preds = %assign_optional584 + br label %voiderr601 + +noerr_block587: ; preds = %after_check585 + %232 = load i64, ptr %retparam577, align 8 + store i64 %232, ptr %len571, align 8 + %233 = call i64 @std.io.File.write_byte(ptr %224, i8 zeroext 10) + %not_err589 = icmp eq i64 %233, 0 + %234 = call i1 @llvm.expect.i1(i1 %not_err589, i1 true) + br i1 %234, label %after_check591, label %assign_optional590 + +assign_optional590: ; preds = %noerr_block587 + store i64 %233, ptr %error_var588, align 8 + br label %guard_block592 + +after_check591: ; preds = %noerr_block587 + br label %noerr_block593 + +guard_block592: ; preds = %assign_optional590 + br label %voiderr601 + +noerr_block593: ; preds = %after_check591 + %235 = call i64 @std.io.File.flush(ptr %224) + %not_err595 = icmp eq i64 %235, 0 + %236 = call i1 @llvm.expect.i1(i1 %not_err595, i1 true) + br i1 %236, label %after_check597, label %assign_optional596 + +assign_optional596: ; preds = %noerr_block593 + store i64 %235, ptr %error_var594, align 8 + br label %guard_block598 + +after_check597: ; preds = %noerr_block593 + br label %noerr_block599 + +guard_block598: ; preds = %assign_optional596 + br label %voiderr601 + +noerr_block599: ; preds = %after_check597 + %237 = load i64, ptr %len571, align 8 + %add600 = add i64 %237, 1 + br label %voiderr601 + +voiderr601: ; preds = %noerr_block599, %guard_block598, %guard_block592, %guard_block586 + store i32 0, ptr %literal602, align 4 + %ptradd603 = getelementptr inbounds i8, ptr %literal602, i64 4 + store i32 11, ptr %ptradd603, align 4 + %ptradd604 = getelementptr inbounds i8, ptr %literal602, i64 8 + store i32 0, ptr %ptradd604, align 4 + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %x605, ptr align 4 %literal602, i32 12, i1 false) + %238 = call ptr @std.io.stdout() + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %x606, ptr align 4 %x605, i32 12, i1 false) + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %x609, ptr align 4 %x606, i32 12, i1 false) + %239 = insertvalue %any undef, ptr %238, 0 + %240 = insertvalue %any %239, i64 ptrtoint (ptr @"$ct.std.io.File" to i64), 1 + %241 = insertvalue %any undef, ptr %x609, 0 + %242 = insertvalue %any %241, i64 ptrtoint (ptr @"$ct.a3$test.Abc" to i64), 1 + store %any %242, ptr %varargslots611, align 16 + %243 = insertvalue %"any[]" undef, ptr %varargslots611, 0 + %"$$temp612" = insertvalue %"any[]" %243, i64 1, 1 + store %any %240, ptr %taddr614, align 8 + %lo615 = load i64, ptr %taddr614, align 8 + %ptradd616 = getelementptr inbounds i8, ptr %taddr614, i64 8 + %hi617 = load ptr, ptr %ptradd616, align 8 + store %"any[]" %"$$temp612", ptr %indirectarg618, align 8 + %244 = call i64 @std.io.fprintf(ptr %retparam613, i64 %lo615, ptr %hi617, ptr @.str.33, i64 2, ptr byval(%"any[]") align 8 %indirectarg618) + %not_err619 = icmp eq i64 %244, 0 + %245 = call i1 @llvm.expect.i1(i1 %not_err619, i1 true) + br i1 %245, label %after_check621, label %assign_optional620 + +assign_optional620: ; preds = %voiderr601 + store i64 %244, ptr %error_var608, align 8 + br label %guard_block622 + +after_check621: ; preds = %voiderr601 + br label %noerr_block623 + +guard_block622: ; preds = %assign_optional620 + br label %voiderr637 + +noerr_block623: ; preds = %after_check621 + %246 = load i64, ptr %retparam613, align 8 + store i64 %246, ptr %len607, align 8 + %247 = call i64 @std.io.File.write_byte(ptr %238, i8 zeroext 10) + %not_err625 = icmp eq i64 %247, 0 + %248 = call i1 @llvm.expect.i1(i1 %not_err625, i1 true) + br i1 %248, label %after_check627, label %assign_optional626 + +assign_optional626: ; preds = %noerr_block623 + store i64 %247, ptr %error_var624, align 8 + br label %guard_block628 + +after_check627: ; preds = %noerr_block623 + br label %noerr_block629 + +guard_block628: ; preds = %assign_optional626 + br label %voiderr637 + +noerr_block629: ; preds = %after_check627 + %249 = call i64 @std.io.File.flush(ptr %238) + %not_err631 = icmp eq i64 %249, 0 + %250 = call i1 @llvm.expect.i1(i1 %not_err631, i1 true) + br i1 %250, label %after_check633, label %assign_optional632 + +assign_optional632: ; preds = %noerr_block629 + store i64 %249, ptr %error_var630, align 8 + br label %guard_block634 + +after_check633: ; preds = %noerr_block629 + br label %noerr_block635 + +guard_block634: ; preds = %assign_optional632 + br label %voiderr637 + +noerr_block635: ; preds = %after_check633 + %251 = load i64, ptr %len607, align 8 + %add636 = add i64 %251, 1 + br label %voiderr637 + +voiderr637: ; preds = %noerr_block635, %guard_block634, %guard_block628, %guard_block622 + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %y, ptr align 4 @.__const.34, i32 4, i1 false) + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %x638, ptr align 4 %y, i32 4, i1 false) + %252 = call ptr @std.io.stdout() + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %x639, ptr align 4 %x638, i32 4, i1 false) + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %x642, ptr align 4 %x639, i32 4, i1 false) + %253 = insertvalue %any undef, ptr %252, 0 + %254 = insertvalue %any %253, i64 ptrtoint (ptr @"$ct.std.io.File" to i64), 1 + %255 = insertvalue %any undef, ptr %x642, 0 + %256 = insertvalue %any %255, i64 ptrtoint (ptr @"$ct.test.Abc" to i64), 1 + store %any %256, ptr %varargslots644, align 16 + %257 = insertvalue %"any[]" undef, ptr %varargslots644, 0 + %"$$temp645" = insertvalue %"any[]" %257, i64 1, 1 + store %any %254, ptr %taddr647, align 8 + %lo648 = load i64, ptr %taddr647, align 8 + %ptradd649 = getelementptr inbounds i8, ptr %taddr647, i64 8 + %hi650 = load ptr, ptr %ptradd649, align 8 + store %"any[]" %"$$temp645", ptr %indirectarg651, align 8 + %258 = call i64 @std.io.fprintf(ptr %retparam646, i64 %lo648, ptr %hi650, ptr @.str.35, i64 2, ptr byval(%"any[]") align 8 %indirectarg651) + %not_err652 = icmp eq i64 %258, 0 + %259 = call i1 @llvm.expect.i1(i1 %not_err652, i1 true) + br i1 %259, label %after_check654, label %assign_optional653 + +assign_optional653: ; preds = %voiderr637 + store i64 %258, ptr %error_var641, align 8 + br label %guard_block655 + +after_check654: ; preds = %voiderr637 + br label %noerr_block656 + +guard_block655: ; preds = %assign_optional653 + br label %voiderr670 + +noerr_block656: ; preds = %after_check654 + %260 = load i64, ptr %retparam646, align 8 + store i64 %260, ptr %len640, align 8 + %261 = call i64 @std.io.File.write_byte(ptr %252, i8 zeroext 10) + %not_err658 = icmp eq i64 %261, 0 + %262 = call i1 @llvm.expect.i1(i1 %not_err658, i1 true) + br i1 %262, label %after_check660, label %assign_optional659 + +assign_optional659: ; preds = %noerr_block656 + store i64 %261, ptr %error_var657, align 8 + br label %guard_block661 + +after_check660: ; preds = %noerr_block656 + br label %noerr_block662 + +guard_block661: ; preds = %assign_optional659 + br label %voiderr670 + +noerr_block662: ; preds = %after_check660 + %263 = call i64 @std.io.File.flush(ptr %252) + %not_err664 = icmp eq i64 %263, 0 + %264 = call i1 @llvm.expect.i1(i1 %not_err664, i1 true) + br i1 %264, label %after_check666, label %assign_optional665 + +assign_optional665: ; preds = %noerr_block662 + store i64 %263, ptr %error_var663, align 8 + br label %guard_block667 + +after_check666: ; preds = %noerr_block662 + br label %noerr_block668 + +guard_block667: ; preds = %assign_optional665 + br label %voiderr670 + +noerr_block668: ; preds = %after_check666 + %265 = load i64, ptr %len640, align 8 + %add669 = add i64 %265, 1 + br label %voiderr670 + +voiderr670: ; preds = %noerr_block668, %guard_block667, %guard_block661, %guard_block655 + ret i32 0 +} diff --git a/test/test_suite7/compile_time/concat_const.c3 b/test/test_suite7/compile_time/concat_const.c3 new file mode 100644 index 000000000..88766eeb0 --- /dev/null +++ b/test/test_suite7/compile_time/concat_const.c3 @@ -0,0 +1,22 @@ +module wi3enrich; +import std::io; +import std::os::env; + +macro String to_string(uint $num) @const +{ + char[] $res; + int $i = 0; + $for (;$num != 0;) + $res = $res +++ (char) ('0' + $num % 10); + $num = $num / 10; + $i++; + $endfor + $res = $res +++ '\0'; + return (String) $res; +} + +fn int main(String[] args) +{ + io::printn(to_string(4)); + return 0; +} diff --git a/test/test_suite7/compile_time/concat_slice_array.c3 b/test/test_suite7/compile_time/concat_slice_array.c3 new file mode 100644 index 000000000..07037864e --- /dev/null +++ b/test/test_suite7/compile_time/concat_slice_array.c3 @@ -0,0 +1,16 @@ +module test; + +const BITS = 8; +fn int main() +{ + String $chars = "Abcd"; + char $from = 2; + char[10] $bitmap = {}; +$foreach ( $c : $chars) + int $offset = ($c - $from) / BITS; + int $rem = ($c - $from) % BITS; + uint128 $value = $bitmap[$offset]; // #error: is out of range + $value |= 1u128 << $rem; + $bitmap = $bitmap[:$offset] +++ $value +++ $bitmap[$offset+1..]; // #error: End index out of bounds +$endforeach +} \ No newline at end of file diff --git a/test/test_suite7/compile_time/concat_slice_bytes.c3t b/test/test_suite7/compile_time/concat_slice_bytes.c3t new file mode 100644 index 000000000..1885c53f7 --- /dev/null +++ b/test/test_suite7/compile_time/concat_slice_bytes.c3t @@ -0,0 +1,18 @@ +module test; +import std; + +fn void main() +{ + String $a = "hello"; + char[] $b = { 'a', 'b' }; + var $c = $a +++ $b; + String y = $c; + char[3] $bytes = x'0103ff'; + var $d = $bytes +++ $b; + char[5] z = $d; +} + +/* #expect: test.ll + +@.str = private unnamed_addr constant [8 x i8] c"helloab\00", align 1 +@.bytes = private unnamed_addr constant [6 x i8] c"\01\03\FFab\00", align 1 \ No newline at end of file diff --git a/test/test_suite7/compile_time/concat_test.c3t b/test/test_suite7/compile_time/concat_test.c3t new file mode 100644 index 000000000..97aa5439a --- /dev/null +++ b/test/test_suite7/compile_time/concat_test.c3t @@ -0,0 +1,506 @@ +// #target: macos-x64 +module test; +import std; + +fn void test1() +{ + int[] $x = { 1, 2, 3, 4 }; + var $y = $x +++ 5; + io::printn($y); +} + +fn void test2() +{ + int[] $x = { }; + var $y = $x +++ 5; + io::printn($y); + $y = $y +++ 1; + io::printn($y); +} + +fn void test3() +{ + int[] $x = { [5] = 2 }; + var $y = $x +++ 5; + io::printn($y); +} + +fn void test4() +{ + int[4] $x = { [1] = 2 }; + var $y = $x +++ 5; + io::printn($y); +} + +fn void test5() +{ + int[4] $x = { }; + var $y = $x +++ 5; + io::printn($y); +} + +fn int main() +{ + test1(); + test2(); + test3(); + test4(); + test5(); + return 0; +} + +/* #expect: test.ll + +@.__const = private unnamed_addr constant [5 x i32] [i32 1, i32 2, i32 3, i32 4, i32 5], align 16 +@.__const.1 = private unnamed_addr constant [1 x i32] [i32 5], align 4 +@.__const.3 = private unnamed_addr constant [2 x i32] [i32 5, i32 1], align 4 +@.__const.5 = private unnamed_addr constant { [5 x i32], i32, i32 } { [5 x i32] zeroinitializer, i32 2, i32 5 }, align 16 +@.__const.7 = private unnamed_addr constant { i32, i32, [2 x i32], i32 } { i32 0, i32 2, [2 x i32] zeroinitializer, i32 5 }, align 16 +@.__const.9 = private unnamed_addr constant { [4 x i32], i32 } { [4 x i32] zeroinitializer, i32 5 }, align 16 + +define void @test.test1() #0 { +entry: + %literal = alloca [5 x i32], align 16 + %len = alloca i64, align 8 + %error_var = alloca i64, align 8 + %varargslots = alloca [1 x %any], align 16 + %taddr = alloca %"int[]", align 8 + %retparam = alloca i64, align 8 + %taddr2 = alloca %any, align 8 + %indirectarg = alloca %"any[]", align 8 + %error_var3 = alloca i64, align 8 + %error_var9 = alloca i64, align 8 + +define void @test.test2() #0 { +entry: + %literal = alloca [1 x i32], align 4 + %len = alloca i64, align 8 + %error_var = alloca i64, align 8 + %varargslots = alloca [1 x %any], align 16 + %taddr = alloca %"int[]", align 8 + %retparam = alloca i64, align 8 + %taddr2 = alloca %any, align 8 + %indirectarg = alloca %"any[]", align 8 + %error_var3 = alloca i64, align 8 + %error_var9 = alloca i64, align 8 + %literal15 = alloca [2 x i32], align 4 + %len16 = alloca i64, align 8 + %error_var17 = alloca i64, align 8 + %varargslots19 = alloca [1 x %any], align 16 + %taddr20 = alloca %"int[]", align 8 + %retparam22 = alloca i64, align 8 + %taddr23 = alloca %any, align 8 + %indirectarg27 = alloca %"any[]", align 8 + %error_var33 = alloca i64, align 8 + %error_var39 = alloca i64, align 8 + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %literal, ptr align 4 @.__const.1, i32 4, i1 false) + %0 = insertvalue %"int[]" undef, ptr %literal, 0 + %1 = insertvalue %"int[]" %0, i64 1, 1 + %2 = call ptr @std.io.stdout() + %3 = insertvalue %any undef, ptr %2, 0 + %4 = insertvalue %any %3, i64 ptrtoint (ptr @"$ct.std.io.File" to i64), 1 + store %"int[]" %1, ptr %taddr, align 8 + %5 = insertvalue %any undef, ptr %taddr, 0 + %6 = insertvalue %any %5, i64 ptrtoint (ptr @"$ct.sa$int" to i64), 1 + store %any %6, ptr %varargslots, align 16 + %7 = insertvalue %"any[]" undef, ptr %varargslots, 0 + %"$$temp" = insertvalue %"any[]" %7, i64 1, 1 + store %any %4, ptr %taddr2, align 8 + %lo = load i64, ptr %taddr2, align 8 + %ptradd = getelementptr inbounds i8, ptr %taddr2, i64 8 + %hi = load ptr, ptr %ptradd, align 8 + store %"any[]" %"$$temp", ptr %indirectarg, align 8 + %8 = call i64 @std.io.fprintf(ptr %retparam, i64 %lo, ptr %hi, ptr @.str.2, i64 2, ptr byval(%"any[]") align 8 %indirectarg) + %not_err = icmp eq i64 %8, 0 + %9 = call i1 @llvm.expect.i1(i1 %not_err, i1 true) + br i1 %9, label %after_check, label %assign_optional + +assign_optional: ; preds = %entry + store i64 %8, ptr %error_var, align 8 + br label %guard_block + +after_check: ; preds = %entry + br label %noerr_block + +guard_block: ; preds = %assign_optional + br label %voiderr + +noerr_block: ; preds = %after_check + %10 = load i64, ptr %retparam, align 8 + store i64 %10, ptr %len, align 8 + %11 = call i64 @std.io.File.write_byte(ptr %2, i8 zeroext 10) + %not_err4 = icmp eq i64 %11, 0 + %12 = call i1 @llvm.expect.i1(i1 %not_err4, i1 true) + br i1 %12, label %after_check6, label %assign_optional5 + +assign_optional5: ; preds = %noerr_block + store i64 %11, ptr %error_var3, align 8 + br label %guard_block7 + +after_check6: ; preds = %noerr_block + br label %noerr_block8 + +guard_block7: ; preds = %assign_optional5 + br label %voiderr + +noerr_block8: ; preds = %after_check6 + %13 = call i64 @std.io.File.flush(ptr %2) + %not_err10 = icmp eq i64 %13, 0 + %14 = call i1 @llvm.expect.i1(i1 %not_err10, i1 true) + br i1 %14, label %after_check12, label %assign_optional11 + +assign_optional11: ; preds = %noerr_block8 + store i64 %13, ptr %error_var9, align 8 + br label %guard_block13 + +after_check12: ; preds = %noerr_block8 + br label %noerr_block14 + +guard_block13: ; preds = %assign_optional11 + br label %voiderr + +noerr_block14: ; preds = %after_check12 + %15 = load i64, ptr %len, align 8 + %add = add i64 %15, 1 + br label %voiderr + +voiderr: ; preds = %noerr_block14, %guard_block13, %guard_block7, %guard_block + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %literal15, ptr align 4 @.__const.3, i32 8, i1 false) + %16 = insertvalue %"int[]" undef, ptr %literal15, 0 + %17 = insertvalue %"int[]" %16, i64 2, 1 + %18 = call ptr @std.io.stdout() + %19 = insertvalue %any undef, ptr %18, 0 + %20 = insertvalue %any %19, i64 ptrtoint (ptr @"$ct.std.io.File" to i64), 1 + store %"int[]" %17, ptr %taddr20, align 8 + %21 = insertvalue %any undef, ptr %taddr20, 0 + %22 = insertvalue %any %21, i64 ptrtoint (ptr @"$ct.sa$int" to i64), 1 + store %any %22, ptr %varargslots19, align 16 + %23 = insertvalue %"any[]" undef, ptr %varargslots19, 0 + %"$$temp21" = insertvalue %"any[]" %23, i64 1, 1 + store %any %20, ptr %taddr23, align 8 + %lo24 = load i64, ptr %taddr23, align 8 + %ptradd25 = getelementptr inbounds i8, ptr %taddr23, i64 8 + %hi26 = load ptr, ptr %ptradd25, align 8 + store %"any[]" %"$$temp21", ptr %indirectarg27, align 8 + %24 = call i64 @std.io.fprintf(ptr %retparam22, i64 %lo24, ptr %hi26, ptr @.str.4, i64 2, ptr byval(%"any[]") align 8 %indirectarg27) + %not_err28 = icmp eq i64 %24, 0 + %25 = call i1 @llvm.expect.i1(i1 %not_err28, i1 true) + br i1 %25, label %after_check30, label %assign_optional29 + +assign_optional29: ; preds = %voiderr + store i64 %24, ptr %error_var17, align 8 + br label %guard_block31 + +after_check30: ; preds = %voiderr + br label %noerr_block32 + +guard_block31: ; preds = %assign_optional29 + br label %voiderr46 + +noerr_block32: ; preds = %after_check30 + %26 = load i64, ptr %retparam22, align 8 + store i64 %26, ptr %len16, align 8 + %27 = call i64 @std.io.File.write_byte(ptr %18, i8 zeroext 10) + %not_err34 = icmp eq i64 %27, 0 + %28 = call i1 @llvm.expect.i1(i1 %not_err34, i1 true) + br i1 %28, label %after_check36, label %assign_optional35 + +assign_optional35: ; preds = %noerr_block32 + store i64 %27, ptr %error_var33, align 8 + br label %guard_block37 + +after_check36: ; preds = %noerr_block32 + br label %noerr_block38 + +guard_block37: ; preds = %assign_optional35 + br label %voiderr46 + +noerr_block38: ; preds = %after_check36 + %29 = call i64 @std.io.File.flush(ptr %18) + %not_err40 = icmp eq i64 %29, 0 + %30 = call i1 @llvm.expect.i1(i1 %not_err40, i1 true) + br i1 %30, label %after_check42, label %assign_optional41 + +assign_optional41: ; preds = %noerr_block38 + store i64 %29, ptr %error_var39, align 8 + br label %guard_block43 + +after_check42: ; preds = %noerr_block38 + br label %noerr_block44 + +guard_block43: ; preds = %assign_optional41 + br label %voiderr46 + +noerr_block44: ; preds = %after_check42 + %31 = load i64, ptr %len16, align 8 + %add45 = add i64 %31, 1 + br label %voiderr46 + +voiderr46: ; preds = %noerr_block44, %guard_block43, %guard_block37, %guard_block31 + ret void +} + +define void @test.test3() #0 { +entry: + %literal = alloca [7 x i32], align 16 + %len = alloca i64, align 8 + %error_var = alloca i64, align 8 + %varargslots = alloca [1 x %any], align 16 + %taddr = alloca %"int[]", align 8 + %retparam = alloca i64, align 8 + %taddr2 = alloca %any, align 8 + %indirectarg = alloca %"any[]", align 8 + %error_var3 = alloca i64, align 8 + %error_var9 = alloca i64, align 8 + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %literal, ptr align 16 @.__const.5, i32 28, i1 false) + %0 = insertvalue %"int[]" undef, ptr %literal, 0 + %1 = insertvalue %"int[]" %0, i64 7, 1 + %2 = call ptr @std.io.stdout() + %3 = insertvalue %any undef, ptr %2, 0 + %4 = insertvalue %any %3, i64 ptrtoint (ptr @"$ct.std.io.File" to i64), 1 + store %"int[]" %1, ptr %taddr, align 8 + %5 = insertvalue %any undef, ptr %taddr, 0 + %6 = insertvalue %any %5, i64 ptrtoint (ptr @"$ct.sa$int" to i64), 1 + store %any %6, ptr %varargslots, align 16 + %7 = insertvalue %"any[]" undef, ptr %varargslots, 0 + %"$$temp" = insertvalue %"any[]" %7, i64 1, 1 + store %any %4, ptr %taddr2, align 8 + %lo = load i64, ptr %taddr2, align 8 + %ptradd = getelementptr inbounds i8, ptr %taddr2, i64 8 + %hi = load ptr, ptr %ptradd, align 8 + store %"any[]" %"$$temp", ptr %indirectarg, align 8 + %8 = call i64 @std.io.fprintf(ptr %retparam, i64 %lo, ptr %hi, ptr @.str.6, i64 2, ptr byval(%"any[]") align 8 %indirectarg) + %not_err = icmp eq i64 %8, 0 + %9 = call i1 @llvm.expect.i1(i1 %not_err, i1 true) + br i1 %9, label %after_check, label %assign_optional + +assign_optional: ; preds = %entry + store i64 %8, ptr %error_var, align 8 + br label %guard_block + +after_check: ; preds = %entry + br label %noerr_block + +guard_block: ; preds = %assign_optional + br label %voiderr + +noerr_block: ; preds = %after_check + %10 = load i64, ptr %retparam, align 8 + store i64 %10, ptr %len, align 8 + %11 = call i64 @std.io.File.write_byte(ptr %2, i8 zeroext 10) + %not_err4 = icmp eq i64 %11, 0 + %12 = call i1 @llvm.expect.i1(i1 %not_err4, i1 true) + br i1 %12, label %after_check6, label %assign_optional5 + +assign_optional5: ; preds = %noerr_block + store i64 %11, ptr %error_var3, align 8 + br label %guard_block7 + +after_check6: ; preds = %noerr_block + br label %noerr_block8 + +guard_block7: ; preds = %assign_optional5 + br label %voiderr + +noerr_block8: ; preds = %after_check6 + %13 = call i64 @std.io.File.flush(ptr %2) + %not_err10 = icmp eq i64 %13, 0 + %14 = call i1 @llvm.expect.i1(i1 %not_err10, i1 true) + br i1 %14, label %after_check12, label %assign_optional11 + +assign_optional11: ; preds = %noerr_block8 + store i64 %13, ptr %error_var9, align 8 + br label %guard_block13 + +after_check12: ; preds = %noerr_block8 + br label %noerr_block14 + +guard_block13: ; preds = %assign_optional11 + br label %voiderr + +noerr_block14: ; preds = %after_check12 + %15 = load i64, ptr %len, align 8 + %add = add i64 %15, 1 + br label %voiderr + +voiderr: ; preds = %noerr_block14, %guard_block13, %guard_block7, %guard_block + ret void +} + +define void @test.test4() #0 { +entry: + %literal = alloca [5 x i32], align 16 + %x = alloca [5 x i32], align 16 + %x1 = alloca [5 x i32], align 16 + %len = alloca i64, align 8 + %error_var = alloca i64, align 8 + %x2 = alloca [5 x i32], align 16 + %varargslots = alloca [1 x %any], align 16 + %retparam = alloca i64, align 8 + %taddr = alloca %any, align 8 + %indirectarg = alloca %"any[]", align 8 + %error_var4 = alloca i64, align 8 + %error_var10 = alloca i64, align 8 + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %literal, ptr align 16 @.__const.7, i32 20, i1 false) + call void @llvm.memcpy.p0.p0.i32(ptr align 16 %x, ptr align 4 %literal, i32 20, i1 false) + %0 = call ptr @std.io.stdout() + call void @llvm.memcpy.p0.p0.i32(ptr align 16 %x1, ptr align 16 %x, i32 20, i1 false) + call void @llvm.memcpy.p0.p0.i32(ptr align 16 %x2, ptr align 16 %x1, i32 20, i1 false) + %1 = insertvalue %any undef, ptr %0, 0 + %2 = insertvalue %any %1, i64 ptrtoint (ptr @"$ct.std.io.File" to i64), 1 + %3 = insertvalue %any undef, ptr %x2, 0 + %4 = insertvalue %any %3, i64 ptrtoint (ptr @"$ct.a5$int" to i64), 1 + store %any %4, ptr %varargslots, align 16 + %5 = insertvalue %"any[]" undef, ptr %varargslots, 0 + %"$$temp" = insertvalue %"any[]" %5, i64 1, 1 + store %any %2, ptr %taddr, align 8 + %lo = load i64, ptr %taddr, align 8 + %ptradd = getelementptr inbounds i8, ptr %taddr, i64 8 + %hi = load ptr, ptr %ptradd, align 8 + store %"any[]" %"$$temp", ptr %indirectarg, align 8 + %6 = call i64 @std.io.fprintf(ptr %retparam, i64 %lo, ptr %hi, ptr @.str.8, i64 2, ptr byval(%"any[]") align 8 %indirectarg) + %not_err = icmp eq i64 %6, 0 + %7 = call i1 @llvm.expect.i1(i1 %not_err, i1 true) + br i1 %7, label %after_check, label %assign_optional + +assign_optional: ; preds = %entry + store i64 %6, ptr %error_var, align 8 + br label %guard_block + +after_check: ; preds = %entry + br label %noerr_block + +guard_block: ; preds = %assign_optional + br label %voiderr + +noerr_block: ; preds = %after_check + %8 = load i64, ptr %retparam, align 8 + store i64 %8, ptr %len, align 8 + %9 = call i64 @std.io.File.write_byte(ptr %0, i8 zeroext 10) + %not_err5 = icmp eq i64 %9, 0 + %10 = call i1 @llvm.expect.i1(i1 %not_err5, i1 true) + br i1 %10, label %after_check7, label %assign_optional6 + +assign_optional6: ; preds = %noerr_block + store i64 %9, ptr %error_var4, align 8 + br label %guard_block8 + +after_check7: ; preds = %noerr_block + br label %noerr_block9 + +guard_block8: ; preds = %assign_optional6 + br label %voiderr + +noerr_block9: ; preds = %after_check7 + %11 = call i64 @std.io.File.flush(ptr %0) + %not_err11 = icmp eq i64 %11, 0 + %12 = call i1 @llvm.expect.i1(i1 %not_err11, i1 true) + br i1 %12, label %after_check13, label %assign_optional12 + +assign_optional12: ; preds = %noerr_block9 + store i64 %11, ptr %error_var10, align 8 + br label %guard_block14 + +after_check13: ; preds = %noerr_block9 + br label %noerr_block15 + +guard_block14: ; preds = %assign_optional12 + br label %voiderr + +noerr_block15: ; preds = %after_check13 + %13 = load i64, ptr %len, align 8 + %add = add i64 %13, 1 + br label %voiderr + +voiderr: ; preds = %noerr_block15, %guard_block14, %guard_block8, %guard_block + ret void +} + +define void @test.test5() #0 { +entry: + %literal = alloca [5 x i32], align 16 + %x = alloca [5 x i32], align 16 + %x1 = alloca [5 x i32], align 16 + %len = alloca i64, align 8 + %error_var = alloca i64, align 8 + %x2 = alloca [5 x i32], align 16 + %varargslots = alloca [1 x %any], align 16 + %retparam = alloca i64, align 8 + %taddr = alloca %any, align 8 + %indirectarg = alloca %"any[]", align 8 + %error_var4 = alloca i64, align 8 + %error_var10 = alloca i64, align 8 + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %literal, ptr align 16 @.__const.9, i32 20, i1 false) + call void @llvm.memcpy.p0.p0.i32(ptr align 16 %x, ptr align 4 %literal, i32 20, i1 false) + %0 = call ptr @std.io.stdout() + call void @llvm.memcpy.p0.p0.i32(ptr align 16 %x1, ptr align 16 %x, i32 20, i1 false) + call void @llvm.memcpy.p0.p0.i32(ptr align 16 %x2, ptr align 16 %x1, i32 20, i1 false) + %1 = insertvalue %any undef, ptr %0, 0 + %2 = insertvalue %any %1, i64 ptrtoint (ptr @"$ct.std.io.File" to i64), 1 + %3 = insertvalue %any undef, ptr %x2, 0 + %4 = insertvalue %any %3, i64 ptrtoint (ptr @"$ct.a5$int" to i64), 1 + store %any %4, ptr %varargslots, align 16 + %5 = insertvalue %"any[]" undef, ptr %varargslots, 0 + %"$$temp" = insertvalue %"any[]" %5, i64 1, 1 + store %any %2, ptr %taddr, align 8 + %lo = load i64, ptr %taddr, align 8 + %ptradd = getelementptr inbounds i8, ptr %taddr, i64 8 + %hi = load ptr, ptr %ptradd, align 8 + store %"any[]" %"$$temp", ptr %indirectarg, align 8 + %6 = call i64 @std.io.fprintf(ptr %retparam, i64 %lo, ptr %hi, ptr @.str.10, i64 2, ptr byval(%"any[]") align 8 %indirectarg) + %not_err = icmp eq i64 %6, 0 + %7 = call i1 @llvm.expect.i1(i1 %not_err, i1 true) + br i1 %7, label %after_check, label %assign_optional + +assign_optional: ; preds = %entry + store i64 %6, ptr %error_var, align 8 + br label %guard_block + +after_check: ; preds = %entry + br label %noerr_block + +guard_block: ; preds = %assign_optional + br label %voiderr + +noerr_block: ; preds = %after_check + %8 = load i64, ptr %retparam, align 8 + store i64 %8, ptr %len, align 8 + %9 = call i64 @std.io.File.write_byte(ptr %0, i8 zeroext 10) + %not_err5 = icmp eq i64 %9, 0 + %10 = call i1 @llvm.expect.i1(i1 %not_err5, i1 true) + br i1 %10, label %after_check7, label %assign_optional6 + +assign_optional6: ; preds = %noerr_block + store i64 %9, ptr %error_var4, align 8 + br label %guard_block8 + +after_check7: ; preds = %noerr_block + br label %noerr_block9 + +guard_block8: ; preds = %assign_optional6 + br label %voiderr + +noerr_block9: ; preds = %after_check7 + %11 = call i64 @std.io.File.flush(ptr %0) + %not_err11 = icmp eq i64 %11, 0 + %12 = call i1 @llvm.expect.i1(i1 %not_err11, i1 true) + br i1 %12, label %after_check13, label %assign_optional12 + +assign_optional12: ; preds = %noerr_block9 + store i64 %11, ptr %error_var10, align 8 + br label %guard_block14 + +after_check13: ; preds = %noerr_block9 + br label %noerr_block15 + +guard_block14: ; preds = %assign_optional12 + br label %voiderr + +noerr_block15: ; preds = %after_check13 + %13 = load i64, ptr %len, align 8 + %add = add i64 %13, 1 + br label %voiderr + +voiderr: ; preds = %noerr_block15, %guard_block14, %guard_block8, %guard_block + ret void +} diff --git a/test/test_suite7/compile_time/concat_test_cases.c3 b/test/test_suite7/compile_time/concat_test_cases.c3 new file mode 100644 index 000000000..21c291d0f --- /dev/null +++ b/test/test_suite7/compile_time/concat_test_cases.c3 @@ -0,0 +1,25 @@ +fn void main(String[] args) +{ + var $x = (int[2]){ 1, 2 } +++ (int[2]){ 4, 5 }; + var $v = "foo" +++ "baz" +++ '!' +++ '?'; + var $b = x'403322' +++ "baz"; + var $b2 = x'40334a' +++ 55 +++ 55; + var $b3 = x'403322' +++ (char[2]) { 1, 2 }; + var $b4 = x'403322' +++ (char[2]) { 1, 2 }; + var $b5 = "foo" +++ { 55, 57 }; + var $b6 = ((ichar[3])x'403322') +++ (ichar[2]) { 1, 2 }; + var $b7 = (char[2]) { 1, 2 } +++ "foo"; + assert($b7 == { 1, 2, 102, 111, 111}); + assert($b5 == "foo79"); + assert($b3 == $b4); + assert($b6 == { 0x40, 0x33, 0x22, 1, 2 }); + int[4] $x2 = (int[2]){ 1, 2 }+++ (int[2]){ 4, 5 }; + int[4] $y = { 1, 2 } +++ { 4, 5 }; + assert($x == {1, 2, 4, 5}); + assert($x2 == {1, 2, 4, 5}); + assert($y == {1, 2, 4, 5}); + assert($v == "foobaz!?"); + assert($b == {64, 51, 34, 98, 97, 122}); + assert($b2 == {64, 51, 74, 55, 55}); + assert($b3 == {64, 51, 34, 1, 2}); +} \ No newline at end of file diff --git a/test/test_suite7/compile_time/concat_zero_slice.c3t b/test/test_suite7/compile_time/concat_zero_slice.c3t new file mode 100644 index 000000000..aed583c0a --- /dev/null +++ b/test/test_suite7/compile_time/concat_zero_slice.c3t @@ -0,0 +1,6 @@ +fn int main() +{ + char[] $res; + $res = { '0' } +++ $res; + return 0; +} \ No newline at end of file diff --git a/test/test_suite7/compile_time/ct_and_or.c3 b/test/test_suite7/compile_time/ct_and_or.c3 new file mode 100644 index 000000000..bd2dc0a12 --- /dev/null +++ b/test/test_suite7/compile_time/ct_and_or.c3 @@ -0,0 +1,6 @@ +fn void test() +{ + $assert false ||| false ||| true ||| hello(""); + $assert !(false &&& hello("")); + $assert !(true &&& true &&& false &&& hello("")); +} \ No newline at end of file diff --git a/test/test_suite7/compile_time/ct_assert_bug.c3 b/test/test_suite7/compile_time/ct_assert_bug.c3 new file mode 100644 index 000000000..5b6582bbc --- /dev/null +++ b/test/test_suite7/compile_time/ct_assert_bug.c3 @@ -0,0 +1,25 @@ +// #target: macos-x64 +module testing; +import std::io; + +fn void main() +{ + String[] s1; + String[] s2; + deep_equal(s1, s2); +} + +macro bool deep_equal(a, b) +{ + $switch ($typeof(a).kindof) + $case SLICE: + if (a.len != b.len) return false; + foreach (i, x : a) + { + if (!deep_equal(x, b[i])) return false; + } + return true; + $default: + $assert(false); // #error: Compile time assert failed + $endswitch +} \ No newline at end of file diff --git a/test/test_suite7/compile_time/ct_builtin_time_date.c3t b/test/test_suite7/compile_time/ct_builtin_time_date.c3t new file mode 100644 index 000000000..c00b36607 --- /dev/null +++ b/test/test_suite7/compile_time/ct_builtin_time_date.c3t @@ -0,0 +1,318 @@ +// #target: macos-x64 +module test; +import std::io; + +macro printline() +{ + io::printfn("%d", $$LINE); io::printfn("%d", $$LINE_RAW); +} +fn void test(int x) +{ + io::printfn("%d", x); + if (x > 0) $$FUNCTION(x - 1); + io::printn($$TIME); + io::printn($$DATE); + printline(); + io::printn($$FILE); + io::printn($$MODULE); +} + +bool is_def = $defined($$FUNCTION); +fn void main() +{ + bool is_def2 = $defined($$FUNCTION); + test(10); +} + +/* #expect: test.ll + +define void @test.test(i32 %0) #0 { +entry: + %varargslots = alloca [1 x %any], align 16 + %taddr = alloca i32, align 4 + %retparam = alloca i64, align 8 + %len = alloca i64, align 8 + %error_var = alloca i64, align 8 + %retparam2 = alloca i64, align 8 + %error_var3 = alloca i64, align 8 + %error_var9 = alloca i64, align 8 + %len15 = alloca i64, align 8 + %error_var16 = alloca i64, align 8 + %retparam18 = alloca i64, align 8 + %error_var24 = alloca i64, align 8 + %error_var30 = alloca i64, align 8 + %varargslots38 = alloca [1 x %any], align 16 + %taddr39 = alloca i64, align 8 + %retparam40 = alloca i64, align 8 + %varargslots43 = alloca [1 x %any], align 16 + %taddr44 = alloca i64, align 8 + %retparam45 = alloca i64, align 8 + %len48 = alloca i64, align 8 + %error_var49 = alloca i64, align 8 + %retparam51 = alloca i64, align 8 + %error_var57 = alloca i64, align 8 + %error_var63 = alloca i64, align 8 + %len71 = alloca i64, align 8 + %error_var72 = alloca i64, align 8 + %retparam74 = alloca i64, align 8 + %error_var80 = alloca i64, align 8 + %error_var86 = alloca i64, align 8 + store i32 %0, ptr %taddr, align 4 + %1 = insertvalue %any undef, ptr %taddr, 0 + %2 = insertvalue %any %1, i64 ptrtoint (ptr @"$ct.int" to i64), 1 + store %any %2, ptr %varargslots, align 16 + %3 = call i64 @std.io.printfn(ptr %retparam, ptr @.str, i64 2, ptr %varargslots, i64 1) + %gt = icmp sgt i32 %0, 0 + br i1 %gt, label %if.then, label %if.exit + +if.then: ; preds = %entry + %sub = sub i32 %0, 1 + call void @test.test(i32 %sub) + br label %if.exit + +if.exit: ; preds = %if.then, %entry + %4 = call ptr @std.io.stdout() + %5 = call i64 @std.io.File.write(ptr %retparam2, ptr %4, ptr @.str.1, i64 8) + %not_err = icmp eq i64 %5, 0 + %6 = call i1 @llvm.expect.i1(i1 %not_err, i1 true) + br i1 %6, label %after_check, label %assign_optional + +assign_optional: ; preds = %if.exit + store i64 %5, ptr %error_var, align 8 + br label %guard_block + +after_check: ; preds = %if.exit + br label %noerr_block + +guard_block: ; preds = %assign_optional + br label %voiderr + +noerr_block: ; preds = %after_check + %7 = load i64, ptr %retparam2, align 8 + store i64 %7, ptr %len, align 8 + %8 = call i64 @std.io.File.write_byte(ptr %4, i8 zeroext 10) + %not_err4 = icmp eq i64 %8, 0 + %9 = call i1 @llvm.expect.i1(i1 %not_err4, i1 true) + br i1 %9, label %after_check6, label %assign_optional5 + +assign_optional5: ; preds = %noerr_block + store i64 %8, ptr %error_var3, align 8 + br label %guard_block7 + +after_check6: ; preds = %noerr_block + br label %noerr_block8 + +guard_block7: ; preds = %assign_optional5 + br label %voiderr + +noerr_block8: ; preds = %after_check6 + %10 = call i64 @std.io.File.flush(ptr %4) + %not_err10 = icmp eq i64 %10, 0 + %11 = call i1 @llvm.expect.i1(i1 %not_err10, i1 true) + br i1 %11, label %after_check12, label %assign_optional11 + +assign_optional11: ; preds = %noerr_block8 + store i64 %10, ptr %error_var9, align 8 + br label %guard_block13 + +after_check12: ; preds = %noerr_block8 + br label %noerr_block14 + +guard_block13: ; preds = %assign_optional11 + br label %voiderr + +noerr_block14: ; preds = %after_check12 + %12 = load i64, ptr %len, align 8 + %add = add i64 %12, 1 + br label %voiderr + +voiderr: ; preds = %noerr_block14, %guard_block13, %guard_block7, %guard_block + %13 = call ptr @std.io.stdout() + %14 = call i64 @std.io.File.write(ptr %retparam18, ptr %13, ptr @.str.2, i64 10) + %not_err19 = icmp eq i64 %14, 0 + %15 = call i1 @llvm.expect.i1(i1 %not_err19, i1 true) + br i1 %15, label %after_check21, label %assign_optional20 + +assign_optional20: ; preds = %voiderr + store i64 %14, ptr %error_var16, align 8 + br label %guard_block22 + +after_check21: ; preds = %voiderr + br label %noerr_block23 + +guard_block22: ; preds = %assign_optional20 + br label %voiderr37 + +noerr_block23: ; preds = %after_check21 + %16 = load i64, ptr %retparam18, align 8 + store i64 %16, ptr %len15, align 8 + %17 = call i64 @std.io.File.write_byte(ptr %13, i8 zeroext 10) + %not_err25 = icmp eq i64 %17, 0 + %18 = call i1 @llvm.expect.i1(i1 %not_err25, i1 true) + br i1 %18, label %after_check27, label %assign_optional26 + +assign_optional26: ; preds = %noerr_block23 + store i64 %17, ptr %error_var24, align 8 + br label %guard_block28 + +after_check27: ; preds = %noerr_block23 + br label %noerr_block29 + +guard_block28: ; preds = %assign_optional26 + br label %voiderr37 + +noerr_block29: ; preds = %after_check27 + %19 = call i64 @std.io.File.flush(ptr %13) + %not_err31 = icmp eq i64 %19, 0 + %20 = call i1 @llvm.expect.i1(i1 %not_err31, i1 true) + br i1 %20, label %after_check33, label %assign_optional32 + +assign_optional32: ; preds = %noerr_block29 + store i64 %19, ptr %error_var30, align 8 + br label %guard_block34 + +after_check33: ; preds = %noerr_block29 + br label %noerr_block35 + +guard_block34: ; preds = %assign_optional32 + br label %voiderr37 + +noerr_block35: ; preds = %after_check33 + %21 = load i64, ptr %len15, align 8 + %add36 = add i64 %21, 1 + br label %voiderr37 + +voiderr37: ; preds = %noerr_block35, %guard_block34, %guard_block28, %guard_block22 + store i64 14, ptr %taddr39, align 8 + %22 = insertvalue %any undef, ptr %taddr39, 0 + %23 = insertvalue %any %22, i64 ptrtoint (ptr @"$ct.long" to i64), 1 + store %any %23, ptr %varargslots38, align 16 + %24 = call i64 @std.io.printfn(ptr %retparam40, ptr @.str.3, i64 2, ptr %varargslots38, i64 1) + store i64 6, ptr %taddr44, align 8 + %25 = insertvalue %any undef, ptr %taddr44, 0 + %26 = insertvalue %any %25, i64 ptrtoint (ptr @"$ct.long" to i64), 1 + store %any %26, ptr %varargslots43, align 16 + %27 = call i64 @std.io.printfn(ptr %retparam45, ptr @.str.4, i64 2, ptr %varargslots43, i64 1) + %28 = call ptr @std.io.stdout() + %29 = call i64 @std.io.File.write(ptr %retparam51, ptr %28, ptr @.str.5, i64 23) + %not_err52 = icmp eq i64 %29, 0 + %30 = call i1 @llvm.expect.i1(i1 %not_err52, i1 true) + br i1 %30, label %after_check54, label %assign_optional53 + +assign_optional53: ; preds = %voiderr37 + store i64 %29, ptr %error_var49, align 8 + br label %guard_block55 + +after_check54: ; preds = %voiderr37 + br label %noerr_block56 + +guard_block55: ; preds = %assign_optional53 + br label %voiderr70 + +noerr_block56: ; preds = %after_check54 + %31 = load i64, ptr %retparam51, align 8 + store i64 %31, ptr %len48, align 8 + %32 = call i64 @std.io.File.write_byte(ptr %28, i8 zeroext 10) + %not_err58 = icmp eq i64 %32, 0 + %33 = call i1 @llvm.expect.i1(i1 %not_err58, i1 true) + br i1 %33, label %after_check60, label %assign_optional59 + +assign_optional59: ; preds = %noerr_block56 + store i64 %32, ptr %error_var57, align 8 + br label %guard_block61 + +after_check60: ; preds = %noerr_block56 + br label %noerr_block62 + +guard_block61: ; preds = %assign_optional59 + br label %voiderr70 + +noerr_block62: ; preds = %after_check60 + %34 = call i64 @std.io.File.flush(ptr %28) + %not_err64 = icmp eq i64 %34, 0 + %35 = call i1 @llvm.expect.i1(i1 %not_err64, i1 true) + br i1 %35, label %after_check66, label %assign_optional65 + +assign_optional65: ; preds = %noerr_block62 + store i64 %34, ptr %error_var63, align 8 + br label %guard_block67 + +after_check66: ; preds = %noerr_block62 + br label %noerr_block68 + +guard_block67: ; preds = %assign_optional65 + br label %voiderr70 + +noerr_block68: ; preds = %after_check66 + %36 = load i64, ptr %len48, align 8 + %add69 = add i64 %36, 1 + br label %voiderr70 + +voiderr70: ; preds = %noerr_block68, %guard_block67, %guard_block61, %guard_block55 + %37 = call ptr @std.io.stdout() + %38 = call i64 @std.io.File.write(ptr %retparam74, ptr %37, ptr @.str.6, i64 4) + %not_err75 = icmp eq i64 %38, 0 + %39 = call i1 @llvm.expect.i1(i1 %not_err75, i1 true) + br i1 %39, label %after_check77, label %assign_optional76 + +assign_optional76: ; preds = %voiderr70 + store i64 %38, ptr %error_var72, align 8 + br label %guard_block78 + +after_check77: ; preds = %voiderr70 + br label %noerr_block79 + +guard_block78: ; preds = %assign_optional76 + br label %voiderr93 + +noerr_block79: ; preds = %after_check77 + %40 = load i64, ptr %retparam74, align 8 + store i64 %40, ptr %len71, align 8 + %41 = call i64 @std.io.File.write_byte(ptr %37, i8 zeroext 10) + %not_err81 = icmp eq i64 %41, 0 + %42 = call i1 @llvm.expect.i1(i1 %not_err81, i1 true) + br i1 %42, label %after_check83, label %assign_optional82 + +assign_optional82: ; preds = %noerr_block79 + store i64 %41, ptr %error_var80, align 8 + br label %guard_block84 + +after_check83: ; preds = %noerr_block79 + br label %noerr_block85 + +guard_block84: ; preds = %assign_optional82 + br label %voiderr93 + +noerr_block85: ; preds = %after_check83 + %43 = call i64 @std.io.File.flush(ptr %37) + %not_err87 = icmp eq i64 %43, 0 + %44 = call i1 @llvm.expect.i1(i1 %not_err87, i1 true) + br i1 %44, label %after_check89, label %assign_optional88 + +assign_optional88: ; preds = %noerr_block85 + store i64 %43, ptr %error_var86, align 8 + br label %guard_block90 + +after_check89: ; preds = %noerr_block85 + br label %noerr_block91 + +guard_block90: ; preds = %assign_optional88 + br label %voiderr93 + +noerr_block91: ; preds = %after_check89 + %45 = load i64, ptr %len71, align 8 + %add92 = add i64 %45, 1 + br label %voiderr93 + +voiderr93: ; preds = %noerr_block91, %guard_block90, %guard_block84, %guard_block78 + ret void +} + +; Function Attrs: +define void @test.main() #0 { +entry: + %is_def2 = alloca i8, align 1 + store i8 1, ptr %is_def2, align 1 + call void @test.test(i32 10) + ret void +} \ No newline at end of file diff --git a/test/test_suite7/compile_time/ct_cast_example.c3t b/test/test_suite7/compile_time/ct_cast_example.c3t new file mode 100644 index 000000000..6d346fefc --- /dev/null +++ b/test/test_suite7/compile_time/ct_cast_example.c3t @@ -0,0 +1,14 @@ +// #target: macos-x64 +module test; +import std; + +fn void main() +{ + var $x = { 1, 2 }; + $x = $x +++ 333; + io::printn((int[?])$x); +} + +/* #expect: test.ll + +@.__const = private unnamed_addr constant [3 x i32] [i32 1, i32 2, i32 333], align 4 diff --git a/test/test_suite7/compile_time/ct_declaration_in_if.c3t b/test/test_suite7/compile_time/ct_declaration_in_if.c3t new file mode 100644 index 000000000..e1b4671cf --- /dev/null +++ b/test/test_suite7/compile_time/ct_declaration_in_if.c3t @@ -0,0 +1,40 @@ +// #target: macos-x64 +module test; +import std; + +struct Vector3 +{ + float x, y, z; +} + +macro @printVecs(Vector3... vectors) +{ + for (int $i = 0; $i < vectors.len; ++$i) + { + // do something + } +} + +fn void main() +{ + @printVecs({10, 5, 3}, {9, 6, 4}, {5, 4, 3}); +} + +/* #expect: test.ll + +define void @test.main() #0 { +entry: + %literal = alloca [3 x %Vector3], align 16 + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %literal, ptr align 16 @.__const, i32 36, i1 false) + %0 = insertvalue %"Vector3[]" undef, ptr %literal, 0 + %1 = insertvalue %"Vector3[]" %0, i64 3, 1 + br label %loop.cond +loop.cond: ; preds = %loop.inc, %entry + %2 = extractvalue %"Vector3[]" %1, 1 + %lt = icmp ult i64 0, %2 + br i1 %lt, label %loop.inc, label %loop.exit +loop.inc: ; preds = %loop.cond + br label %loop.cond +loop.exit: ; preds = %loop.cond + ret void +} diff --git a/test/test_suite7/compile_time/ct_else_else.c3 b/test/test_suite7/compile_time/ct_else_else.c3 new file mode 100644 index 000000000..d6dcd7e23 --- /dev/null +++ b/test/test_suite7/compile_time/ct_else_else.c3 @@ -0,0 +1,8 @@ +// Issue #1824 +fn void main() +{ + $if true: + $else + $else // #error: Expected '$endif' + $endif +} \ No newline at end of file diff --git a/test/test_suite7/compile_time/ct_enum_values.c3t b/test/test_suite7/compile_time/ct_enum_values.c3t new file mode 100644 index 000000000..c17c69701 --- /dev/null +++ b/test/test_suite7/compile_time/ct_enum_values.c3t @@ -0,0 +1,30 @@ +// #target: macos-x64 +module test; +enum Vehicles +{ + CAR, + PLANE +} + +macro elements($Type) +{ + int x; + $foreach ($x : $Type.values) + x = $x.ordinal; + $endforeach; +} + +fn void main() +{ + elements(Vehicles); +} + +/* #expect: test.ll + +entry: + %x = alloca i32, align 4 + store i32 0, ptr %x, align 4 + store i32 0, ptr %x, align 4 + store i32 1, ptr %x, align 4 + ret void +} diff --git a/test/test_suite7/compile_time/ct_eval.c3t b/test/test_suite7/compile_time/ct_eval.c3t new file mode 100644 index 000000000..e9fea6cb2 --- /dev/null +++ b/test/test_suite7/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_suite7/compile_time/ct_eval_sym.c3 b/test/test_suite7/compile_time/ct_eval_sym.c3 new file mode 100644 index 000000000..d351c8d95 --- /dev/null +++ b/test/test_suite7/compile_time/ct_eval_sym.c3 @@ -0,0 +1,5 @@ +fn int test() +{ + void* x = (void*)&$eval($$FUNC); + return 1; +} \ No newline at end of file diff --git a/test/test_suite7/compile_time/ct_eval_wrong.c3 b/test/test_suite7/compile_time/ct_eval_wrong.c3 new file mode 100644 index 000000000..e6a11fdb5 --- /dev/null +++ b/test/test_suite7/compile_time/ct_eval_wrong.c3 @@ -0,0 +1,10 @@ +import std::io; + +fn void main() +{ + $eval("foo()"); // #error: with $eval +} +fn void foo() +{ + io::printfn("foo"); +} \ No newline at end of file diff --git a/test/test_suite7/compile_time/ct_for.c3t b/test/test_suite7/compile_time/ct_for.c3t new file mode 100644 index 000000000..8d58ca058 --- /dev/null +++ b/test/test_suite7/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 ($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_suite7/compile_time/ct_forach_with_defer.c3t b/test/test_suite7/compile_time/ct_forach_with_defer.c3t new file mode 100644 index 000000000..a1176febe --- /dev/null +++ b/test/test_suite7/compile_time/ct_forach_with_defer.c3t @@ -0,0 +1,258 @@ +// #target: macos-x64 +module test; +import std; +// Issue #1912 +fn void test() +{ + defer io::printn("World!"); + const HELLO = "Hello"; + $for (var $i = 0; $i < 5; $i++) + io::printf("%c", HELLO[$i]); + $endfor +} + +fn void main() +{ + defer io::printn("World!"); + + $foreach ($c : "Hello") + io::printf("%c", $c); + $endforeach + io::printn(); +} + +/* #expect: test.ll + +define void @test.test() #0 { +entry: + %varargslots = alloca [1 x %any], align 16 + %taddr = alloca i8, align 1 + %retparam = alloca i64, align 8 + %varargslots1 = alloca [1 x %any], align 16 + %taddr2 = alloca i8, align 1 + %retparam3 = alloca i64, align 8 + %varargslots4 = alloca [1 x %any], align 16 + %taddr5 = alloca i8, align 1 + %retparam6 = alloca i64, align 8 + %varargslots7 = alloca [1 x %any], align 16 + %taddr8 = alloca i8, align 1 + %retparam9 = alloca i64, align 8 + %varargslots10 = alloca [1 x %any], align 16 + %taddr11 = alloca i8, align 1 + %retparam12 = alloca i64, align 8 + %len = alloca i64, align 8 + %error_var = alloca i64, align 8 + %retparam14 = alloca i64, align 8 + %error_var15 = alloca i64, align 8 + %error_var21 = alloca i64, align 8 + store i8 72, ptr %taddr, align 1 + %0 = insertvalue %any undef, ptr %taddr, 0 + %1 = insertvalue %any %0, i64 ptrtoint (ptr @"$ct.char" to i64), 1 + store %any %1, ptr %varargslots, align 16 + %2 = call i64 @std.io.printf(ptr %retparam, ptr @.str.1, i64 2, ptr %varargslots, i64 1) + store i8 101, ptr %taddr2, align 1 + %3 = insertvalue %any undef, ptr %taddr2, 0 + %4 = insertvalue %any %3, i64 ptrtoint (ptr @"$ct.char" to i64), 1 + store %any %4, ptr %varargslots1, align 16 + %5 = call i64 @std.io.printf(ptr %retparam3, ptr @.str.2, i64 2, ptr %varargslots1, i64 1) + store i8 108, ptr %taddr5, align 1 + %6 = insertvalue %any undef, ptr %taddr5, 0 + %7 = insertvalue %any %6, i64 ptrtoint (ptr @"$ct.char" to i64), 1 + store %any %7, ptr %varargslots4, align 16 + %8 = call i64 @std.io.printf(ptr %retparam6, ptr @.str.3, i64 2, ptr %varargslots4, i64 1) + store i8 108, ptr %taddr8, align 1 + %9 = insertvalue %any undef, ptr %taddr8, 0 + %10 = insertvalue %any %9, i64 ptrtoint (ptr @"$ct.char" to i64), 1 + store %any %10, ptr %varargslots7, align 16 + %11 = call i64 @std.io.printf(ptr %retparam9, ptr @.str.4, i64 2, ptr %varargslots7, i64 1) + store i8 111, ptr %taddr11, align 1 + %12 = insertvalue %any undef, ptr %taddr11, 0 + %13 = insertvalue %any %12, i64 ptrtoint (ptr @"$ct.char" to i64), 1 + store %any %13, ptr %varargslots10, align 16 + %14 = call i64 @std.io.printf(ptr %retparam12, ptr @.str.5, i64 2, ptr %varargslots10, i64 1) + %15 = call ptr @std.io.stdout() + %16 = call i64 @std.io.File.write(ptr %retparam14, ptr %15, ptr @.str.6, i64 6) + %not_err = icmp eq i64 %16, 0 + %17 = call i1 @llvm.expect.i1(i1 %not_err, i1 true) + br i1 %17, label %after_check, label %assign_optional +assign_optional: ; preds = %entry + store i64 %16, ptr %error_var, align 8 + br label %guard_block +after_check: ; preds = %entry + br label %noerr_block +guard_block: ; preds = %assign_optional + br label %voiderr +noerr_block: ; preds = %after_check + %18 = load i64, ptr %retparam14, align 8 + store i64 %18, ptr %len, align 8 + %19 = call i64 @std.io.File.write_byte(ptr %15, i8 zeroext 10) + %not_err16 = icmp eq i64 %19, 0 + %20 = call i1 @llvm.expect.i1(i1 %not_err16, i1 true) + br i1 %20, label %after_check18, label %assign_optional17 +assign_optional17: ; preds = %noerr_block + store i64 %19, ptr %error_var15, align 8 + br label %guard_block19 +after_check18: ; preds = %noerr_block + br label %noerr_block20 +guard_block19: ; preds = %assign_optional17 + br label %voiderr +noerr_block20: ; preds = %after_check18 + %21 = call i64 @std.io.File.flush(ptr %15) + %not_err22 = icmp eq i64 %21, 0 + %22 = call i1 @llvm.expect.i1(i1 %not_err22, i1 true) + br i1 %22, label %after_check24, label %assign_optional23 +assign_optional23: ; preds = %noerr_block20 + store i64 %21, ptr %error_var21, align 8 + br label %guard_block25 +after_check24: ; preds = %noerr_block20 + br label %noerr_block26 +guard_block25: ; preds = %assign_optional23 + br label %voiderr +noerr_block26: ; preds = %after_check24 + %23 = load i64, ptr %len, align 8 + %add = add i64 %23, 1 + br label %voiderr +voiderr: ; preds = %noerr_block26, %guard_block25, %guard_block19, %guard_block + ret void +} + +define void @test.main() #0 { +entry: + %varargslots = alloca [1 x %any], align 16 + %taddr = alloca i8, align 1 + %retparam = alloca i64, align 8 + %varargslots1 = alloca [1 x %any], align 16 + %taddr2 = alloca i8, align 1 + %retparam3 = alloca i64, align 8 + %varargslots4 = alloca [1 x %any], align 16 + %taddr5 = alloca i8, align 1 + %retparam6 = alloca i64, align 8 + %varargslots7 = alloca [1 x %any], align 16 + %taddr8 = alloca i8, align 1 + %retparam9 = alloca i64, align 8 + %varargslots10 = alloca [1 x %any], align 16 + %taddr11 = alloca i8, align 1 + %retparam12 = alloca i64, align 8 + %len = alloca i64, align 8 + %error_var = alloca i64, align 8 + %retparam14 = alloca i64, align 8 + %error_var15 = alloca i64, align 8 + %error_var21 = alloca i64, align 8 + %len27 = alloca i64, align 8 + %error_var28 = alloca i64, align 8 + %retparam30 = alloca i64, align 8 + %error_var36 = alloca i64, align 8 + %error_var42 = alloca i64, align 8 + store i8 72, ptr %taddr, align 1 + %0 = insertvalue %any undef, ptr %taddr, 0 + %1 = insertvalue %any %0, i64 ptrtoint (ptr @"$ct.char" to i64), 1 + store %any %1, ptr %varargslots, align 16 + %2 = call i64 @std.io.printf(ptr %retparam, ptr @.str.7, i64 2, ptr %varargslots, i64 1) + store i8 101, ptr %taddr2, align 1 + %3 = insertvalue %any undef, ptr %taddr2, 0 + %4 = insertvalue %any %3, i64 ptrtoint (ptr @"$ct.char" to i64), 1 + store %any %4, ptr %varargslots1, align 16 + %5 = call i64 @std.io.printf(ptr %retparam3, ptr @.str.8, i64 2, ptr %varargslots1, i64 1) + store i8 108, ptr %taddr5, align 1 + %6 = insertvalue %any undef, ptr %taddr5, 0 + %7 = insertvalue %any %6, i64 ptrtoint (ptr @"$ct.char" to i64), 1 + store %any %7, ptr %varargslots4, align 16 + %8 = call i64 @std.io.printf(ptr %retparam6, ptr @.str.9, i64 2, ptr %varargslots4, i64 1) + store i8 108, ptr %taddr8, align 1 + %9 = insertvalue %any undef, ptr %taddr8, 0 + %10 = insertvalue %any %9, i64 ptrtoint (ptr @"$ct.char" to i64), 1 + store %any %10, ptr %varargslots7, align 16 + %11 = call i64 @std.io.printf(ptr %retparam9, ptr @.str.10, i64 2, ptr %varargslots7, i64 1) + store i8 111, ptr %taddr11, align 1 + %12 = insertvalue %any undef, ptr %taddr11, 0 + %13 = insertvalue %any %12, i64 ptrtoint (ptr @"$ct.char" to i64), 1 + store %any %13, ptr %varargslots10, align 16 + %14 = call i64 @std.io.printf(ptr %retparam12, ptr @.str.11, i64 2, ptr %varargslots10, i64 1) + %15 = call ptr @std.io.stdout() + %16 = call i64 @std.io.File.write(ptr %retparam14, ptr %15, ptr null, i64 0) + %not_err = icmp eq i64 %16, 0 + %17 = call i1 @llvm.expect.i1(i1 %not_err, i1 true) + br i1 %17, label %after_check, label %assign_optional +assign_optional: ; preds = %entry + store i64 %16, ptr %error_var, align 8 + br label %guard_block +after_check: ; preds = %entry + br label %noerr_block +guard_block: ; preds = %assign_optional + br label %voiderr +noerr_block: ; preds = %after_check + %18 = load i64, ptr %retparam14, align 8 + store i64 %18, ptr %len, align 8 + %19 = call i64 @std.io.File.write_byte(ptr %15, i8 zeroext 10) + %not_err16 = icmp eq i64 %19, 0 + %20 = call i1 @llvm.expect.i1(i1 %not_err16, i1 true) + br i1 %20, label %after_check18, label %assign_optional17 +assign_optional17: ; preds = %noerr_block + store i64 %19, ptr %error_var15, align 8 + br label %guard_block19 +after_check18: ; preds = %noerr_block + br label %noerr_block20 +guard_block19: ; preds = %assign_optional17 + br label %voiderr +noerr_block20: ; preds = %after_check18 + %21 = call i64 @std.io.File.flush(ptr %15) + %not_err22 = icmp eq i64 %21, 0 + %22 = call i1 @llvm.expect.i1(i1 %not_err22, i1 true) + br i1 %22, label %after_check24, label %assign_optional23 +assign_optional23: ; preds = %noerr_block20 + store i64 %21, ptr %error_var21, align 8 + br label %guard_block25 +after_check24: ; preds = %noerr_block20 + br label %noerr_block26 +guard_block25: ; preds = %assign_optional23 + br label %voiderr +noerr_block26: ; preds = %after_check24 + %23 = load i64, ptr %len, align 8 + %add = add i64 %23, 1 + br label %voiderr +voiderr: ; preds = %noerr_block26, %guard_block25, %guard_block19, %guard_block + %24 = call ptr @std.io.stdout() + %25 = call i64 @std.io.File.write(ptr %retparam30, ptr %24, ptr @.str.12, i64 6) + %not_err31 = icmp eq i64 %25, 0 + %26 = call i1 @llvm.expect.i1(i1 %not_err31, i1 true) + br i1 %26, label %after_check33, label %assign_optional32 +assign_optional32: ; preds = %voiderr + store i64 %25, ptr %error_var28, align 8 + br label %guard_block34 +after_check33: ; preds = %voiderr + br label %noerr_block35 +guard_block34: ; preds = %assign_optional32 + br label %voiderr49 +noerr_block35: ; preds = %after_check33 + %27 = load i64, ptr %retparam30, align 8 + store i64 %27, ptr %len27, align 8 + %28 = call i64 @std.io.File.write_byte(ptr %24, i8 zeroext 10) + %not_err37 = icmp eq i64 %28, 0 + %29 = call i1 @llvm.expect.i1(i1 %not_err37, i1 true) + br i1 %29, label %after_check39, label %assign_optional38 +assign_optional38: ; preds = %noerr_block35 + store i64 %28, ptr %error_var36, align 8 + br label %guard_block40 +after_check39: ; preds = %noerr_block35 + br label %noerr_block41 +guard_block40: ; preds = %assign_optional38 + br label %voiderr49 +noerr_block41: ; preds = %after_check39 + %30 = call i64 @std.io.File.flush(ptr %24) + %not_err43 = icmp eq i64 %30, 0 + %31 = call i1 @llvm.expect.i1(i1 %not_err43, i1 true) + br i1 %31, label %after_check45, label %assign_optional44 +assign_optional44: ; preds = %noerr_block41 + store i64 %30, ptr %error_var42, align 8 + br label %guard_block46 +after_check45: ; preds = %noerr_block41 + br label %noerr_block47 +guard_block46: ; preds = %assign_optional44 + br label %voiderr49 +noerr_block47: ; preds = %after_check45 + %32 = load i64, ptr %len27, align 8 + %add48 = add i64 %32, 1 + br label %voiderr49 +voiderr49: ; preds = %noerr_block47, %guard_block46, %guard_block40, %guard_block34 + ret void +} diff --git a/test/test_suite7/compile_time/ct_foreach.c3t b/test/test_suite7/compile_time/ct_foreach.c3t new file mode 100644 index 000000000..7298b737a --- /dev/null +++ b/test/test_suite7/compile_time/ct_foreach.c3t @@ -0,0 +1,55 @@ +// #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 %"char[]", align 8 + %z2 = alloca i32, align 4 + %z3 = alloca %"char[]", 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 %"char[]" { ptr @.str.7, i64 3 }, 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 %"char[]" { ptr @.str.11, i64 5 }, ptr %z3, align 8 + call void (ptr, ...) @printf(ptr @.str.12, ptr @.str.13) + ret void +} \ No newline at end of file diff --git a/test/test_suite7/compile_time/ct_func.c3t b/test/test_suite7/compile_time/ct_func.c3t new file mode 100644 index 000000000..31c5a82d4 --- /dev/null +++ b/test/test_suite7/compile_time/ct_func.c3t @@ -0,0 +1,29 @@ +// #target: macos-x64 +module test; +import std::io; + +fn int test() +{ + io::printn($$FUNC); + return 1; +} + +struct Foo +{ int x; } + +fn void Foo.tester(Foo* f) +{ + io::printn($$FUNC); +} + +fn void main() +{ + Foo f; + f.tester(); + test(); +} + +/* #expect: test.ll + +@.str = private unnamed_addr constant [5 x i8] c"test\00", align 1 +@.str.1 = private unnamed_addr constant [11 x i8] c"Foo.tester\00", align 1 diff --git a/test/test_suite7/compile_time/ct_funcptr.c3t b/test/test_suite7/compile_time/ct_funcptr.c3t new file mode 100644 index 000000000..f7203a80b --- /dev/null +++ b/test/test_suite7/compile_time/ct_funcptr.c3t @@ -0,0 +1,42 @@ +// #target: macos-x64 +module test; +import std::io; + +fn void test(int x) +{ + $typeof(&$$FUNCTION) ptr = &$$FUNCTION; + io::printfn("%d", x); + if (x > 0) ptr(x - 1); +} + +fn void main() +{ + test(10); +} + +/* #expect: test.ll + +define void @test.test(i32 %0) #0 { +entry: + %ptr = alloca ptr, align 8 + %varargslots = alloca [1 x %any], align 16 + %taddr = alloca i32, align 4 + %retparam = alloca i64, align 8 + store ptr @test.test, ptr %ptr, align 8 + store i32 %0, ptr %taddr, align 4 + %1 = insertvalue %any undef, ptr %taddr, 0 + %2 = insertvalue %any %1, i64 ptrtoint (ptr @"$ct.int" to i64), 1 + store %any %2, ptr %varargslots, align 16 + %3 = call i64 @std.io.printfn(ptr %retparam, ptr @.str, i64 2, ptr %varargslots, i64 1) + %gt = icmp sgt i32 %0, 0 + br i1 %gt, label %if.then, label %if.exit + +if.then: ; preds = %entry + %4 = load ptr, ptr %ptr, align 8 + %sub = sub i32 %0, 1 + call void %4(i32 %sub) + br label %if.exit + +if.exit: ; preds = %if.then, %entry + ret void +} \ No newline at end of file diff --git a/test/test_suite7/compile_time/ct_if.c3t b/test/test_suite7/compile_time/ct_if.c3t new file mode 100644 index 000000000..fe7b39df6 --- /dev/null +++ b/test/test_suite7/compile_time/ct_if.c3t @@ -0,0 +1,8 @@ +// #target: macos-x64 +int x @if(false) = 1; + +int d @if(true) = 5; + +/* #expect: ct_if.ll + +@ct_if.d = local_unnamed_addr global i32 5, align 4 diff --git a/test/test_suite7/compile_time/ct_if_folding.c3t b/test/test_suite7/compile_time/ct_if_folding.c3t new file mode 100644 index 000000000..97126d475 --- /dev/null +++ b/test/test_suite7/compile_time/ct_if_folding.c3t @@ -0,0 +1,32 @@ +// #target: macos-x64 +module test; + +macro void @test(bool $skip = false) +{ + $if $skip: + + $else + int a; + int b; + defer + { + a = b; + } + $endif +} + +fn int main() { + @test(); + return 0; +} +/* #expect: test.ll + +entry: + %a = alloca i32, align 4 + %b = alloca i32, align 4 + store i32 0, ptr %a, align 4 + store i32 0, ptr %b, align 4 + %0 = load i32, ptr %b, align 4 + store i32 %0, ptr %a, align 4 + ret i32 0 +} diff --git a/test/test_suite7/compile_time/ct_left_hand_assign.c3t b/test/test_suite7/compile_time/ct_left_hand_assign.c3t new file mode 100644 index 000000000..6203a92c7 --- /dev/null +++ b/test/test_suite7/compile_time/ct_left_hand_assign.c3t @@ -0,0 +1,23 @@ +// #target: macos-x64 +module foo; +import std; + +macro @foo(#arg) +{ + #arg++; +} + +module bar; +import foo; + +fn void main() +{ + int $c = 0; + foo::@foo($c); +} + +/* #expect: bar.ll + +entry: + ret void +} \ No newline at end of file diff --git a/test/test_suite7/compile_time/ct_memberof.c3t b/test/test_suite7/compile_time/ct_memberof.c3t new file mode 100644 index 000000000..d60e6e732 --- /dev/null +++ b/test/test_suite7/compile_time/ct_memberof.c3t @@ -0,0 +1,854 @@ +// #target: macos-x64 +module test; +import std::io; + +fn int hell() { return 1; } + +macro print_args($Type) +{ + var $params = $Type.params; + $foreach ($param : $params) + io::printn($param.nameof); + $endforeach; +} + +bitstruct Bark : ulong +{ + int x : 1..4; + short y : 6..10; +} + +struct Foo +{ + int x; + union test { + int y; + double z; + } + struct { + int abc; + int bcd; + } + double q; +} +macro print_fields($Type) +{ + io::printfn("Type: %s", $Type.nameof); + var $params = $Type.membersof; + $foreach ($param : $params) + io::printfn("%s: %s", $param.nameof, $param.typeid.nameof); + $endforeach; +} + +fn void hello(int a, double b, int[4] d, args...) {} +fn void test(int x) +{ + print_args($typeof(&test)); + print_args($typeof(&hell)); + print_args($typeof(&hello)); + io::printn($typeof(&test).returns.nameof); + io::printn($typeof(&hell).returns.nameof); + print_fields(Foo); + print_fields(Bar); + print_fields(Bark); +} + +struct BarInner +{ + char a; + char b; +} + +struct Bar +{ + char a; + short b; + struct + { + union + { + BarInner y; + char z; + struct { + char z1; + char z2; + } + } + } + struct baz + { + int foo; + } +} +fn void main() +{ + var $x = Bar.a; + + io::printfn("len: %d", Bar.membersof.len); + io::printfn("len: %d", Bar.baz.membersof.len); + io::printfn("a: %d %d", Bar.a.offsetof, Bar.a.alignof); + io::printfn("b: %d %d", Bar.b.offsetof, Bar.b.alignof); + io::printfn("y: %d %d", Bar.y.offsetof, Bar.y.alignof); + io::printfn("z: %d %d", Bar.z.offsetof, Bar.z.alignof); + io::printfn("z1: %d %d", Bar.z1.offsetof, Bar.z1.alignof); + io::printfn("z2: %d %d", Bar.z2.offsetof, Bar.z2.alignof); + io::printfn("baz: %d %d", Bar.baz.offsetof, Bar.baz.alignof); + io::printfn("Bar: %d", $x.alignof); + io::printfn("foo: %d %d", Bar.baz.foo.offsetof, Bar.baz.foo.alignof); + + test(10); +} + +/* #expect: test.ll + +define void @test.hello(i32 %0, double %1, i64 %2, i64 %3, ptr %4, i64 %5) #0 { +entry: + %d = alloca [4 x i32], align 8 + %args = alloca %"any[]", align 8 + store i64 %2, ptr %d, align 8 + %ptradd = getelementptr inbounds i8, ptr %d, i64 8 + store i64 %3, ptr %ptradd, align 8 + store ptr %4, ptr %args, align 8 + %ptradd1 = getelementptr inbounds i8, ptr %args, i64 8 + store i64 %5, ptr %ptradd1, align 8 + ret void +} + +; Function Attrs: +define void @test.test(i32 %0) #0 { +entry: + %len = alloca i64, align 8 + %error_var = alloca i64, align 8 + %retparam = alloca i64, align 8 + %error_var2 = alloca i64, align 8 + %error_var8 = alloca i64, align 8 + %len14 = alloca i64, align 8 + %error_var15 = alloca i64, align 8 + %retparam17 = alloca i64, align 8 + %error_var23 = alloca i64, align 8 + %error_var29 = alloca i64, align 8 + %len37 = alloca i64, align 8 + %error_var38 = alloca i64, align 8 + %retparam40 = alloca i64, align 8 + %error_var46 = alloca i64, align 8 + %error_var52 = alloca i64, align 8 + %len60 = alloca i64, align 8 + %error_var61 = alloca i64, align 8 + %retparam63 = alloca i64, align 8 + %error_var69 = alloca i64, align 8 + %error_var75 = alloca i64, align 8 + %len83 = alloca i64, align 8 + %error_var84 = alloca i64, align 8 + %retparam86 = alloca i64, align 8 + %error_var92 = alloca i64, align 8 + %error_var98 = alloca i64, align 8 + %len106 = alloca i64, align 8 + %error_var107 = alloca i64, align 8 + %retparam109 = alloca i64, align 8 + %error_var115 = alloca i64, align 8 + %error_var121 = alloca i64, align 8 + %len129 = alloca i64, align 8 + %error_var130 = alloca i64, align 8 + %retparam132 = alloca i64, align 8 + %error_var138 = alloca i64, align 8 + %error_var144 = alloca i64, align 8 + %varargslots = alloca [1 x %any], align 16 + %taddr = alloca %"char[]", align 8 + %retparam152 = alloca i64, align 8 + %varargslots155 = alloca [2 x %any], align 16 + %taddr156 = alloca %"char[]", align 8 + %taddr157 = alloca %"char[]", align 8 + %retparam158 = alloca i64, align 8 + %varargslots161 = alloca [2 x %any], align 16 + %taddr162 = alloca %"char[]", align 8 + %taddr163 = alloca %"char[]", align 8 + %retparam165 = alloca i64, align 8 + %varargslots168 = alloca [2 x %any], align 16 + %taddr169 = alloca %"char[]", align 8 + %taddr170 = alloca %"char[]", align 8 + %retparam172 = alloca i64, align 8 + %varargslots175 = alloca [2 x %any], align 16 + %taddr176 = alloca %"char[]", align 8 + %taddr177 = alloca %"char[]", align 8 + %retparam179 = alloca i64, align 8 + %varargslots182 = alloca [1 x %any], align 16 + %taddr183 = alloca %"char[]", align 8 + %retparam184 = alloca i64, align 8 + %varargslots187 = alloca [2 x %any], align 16 + %taddr188 = alloca %"char[]", align 8 + %taddr189 = alloca %"char[]", align 8 + %retparam191 = alloca i64, align 8 + %varargslots194 = alloca [2 x %any], align 16 + %taddr195 = alloca %"char[]", align 8 + %taddr196 = alloca %"char[]", align 8 + %retparam198 = alloca i64, align 8 + %varargslots201 = alloca [2 x %any], align 16 + %taddr202 = alloca %"char[]", align 8 + %taddr203 = alloca %"char[]", align 8 + %retparam205 = alloca i64, align 8 + %varargslots208 = alloca [2 x %any], align 16 + %taddr209 = alloca %"char[]", align 8 + %taddr210 = alloca %"char[]", align 8 + %retparam212 = alloca i64, align 8 + %varargslots215 = alloca [1 x %any], align 16 + %taddr216 = alloca %"char[]", align 8 + %retparam217 = alloca i64, align 8 + %varargslots220 = alloca [2 x %any], align 16 + %taddr221 = alloca %"char[]", align 8 + %taddr222 = alloca %"char[]", align 8 + %retparam224 = alloca i64, align 8 + %varargslots227 = alloca [2 x %any], align 16 + %taddr228 = alloca %"char[]", align 8 + %taddr229 = alloca %"char[]", align 8 + %retparam231 = alloca i64, align 8 + %1 = call ptr @std.io.stdout() + %2 = call i64 @std.io.File.write(ptr %retparam, ptr %1, ptr @.str, i64 3) + %not_err = icmp eq i64 %2, 0 + %3 = call i1 @llvm.expect.i1(i1 %not_err, i1 true) + br i1 %3, label %after_check, label %assign_optional +assign_optional: ; preds = %entry + store i64 %2, ptr %error_var, align 8 + br label %guard_block +after_check: ; preds = %entry + br label %noerr_block +guard_block: ; preds = %assign_optional + br label %voiderr +noerr_block: ; preds = %after_check + %4 = load i64, ptr %retparam, align 8 + store i64 %4, ptr %len, align 8 + %5 = call i64 @std.io.File.write_byte(ptr %1, i8 zeroext 10) + %not_err3 = icmp eq i64 %5, 0 + %6 = call i1 @llvm.expect.i1(i1 %not_err3, i1 true) + br i1 %6, label %after_check5, label %assign_optional4 +assign_optional4: ; preds = %noerr_block + store i64 %5, ptr %error_var2, align 8 + br label %guard_block6 +after_check5: ; preds = %noerr_block + br label %noerr_block7 +guard_block6: ; preds = %assign_optional4 + br label %voiderr +noerr_block7: ; preds = %after_check5 + %7 = call i64 @std.io.File.flush(ptr %1) + %not_err9 = icmp eq i64 %7, 0 + %8 = call i1 @llvm.expect.i1(i1 %not_err9, i1 true) + br i1 %8, label %after_check11, label %assign_optional10 +assign_optional10: ; preds = %noerr_block7 + store i64 %7, ptr %error_var8, align 8 + br label %guard_block12 +after_check11: ; preds = %noerr_block7 + br label %noerr_block13 +guard_block12: ; preds = %assign_optional10 + br label %voiderr +noerr_block13: ; preds = %after_check11 + %9 = load i64, ptr %len, align 8 + %add = add i64 %9, 1 + br label %voiderr +voiderr: ; preds = %noerr_block13, %guard_block12, %guard_block6, %guard_block + %10 = call ptr @std.io.stdout() + %11 = call i64 @std.io.File.write(ptr %retparam17, ptr %10, ptr @.str.10, i64 3) + %not_err18 = icmp eq i64 %11, 0 + %12 = call i1 @llvm.expect.i1(i1 %not_err18, i1 true) + br i1 %12, label %after_check20, label %assign_optional19 +assign_optional19: ; preds = %voiderr + store i64 %11, ptr %error_var15, align 8 + br label %guard_block21 +after_check20: ; preds = %voiderr + br label %noerr_block22 +guard_block21: ; preds = %assign_optional19 + br label %voiderr36 +noerr_block22: ; preds = %after_check20 + %13 = load i64, ptr %retparam17, align 8 + store i64 %13, ptr %len14, align 8 + %14 = call i64 @std.io.File.write_byte(ptr %10, i8 zeroext 10) + %not_err24 = icmp eq i64 %14, 0 + %15 = call i1 @llvm.expect.i1(i1 %not_err24, i1 true) + br i1 %15, label %after_check26, label %assign_optional25 +assign_optional25: ; preds = %noerr_block22 + store i64 %14, ptr %error_var23, align 8 + br label %guard_block27 + +after_check26: ; preds = %noerr_block22 + br label %noerr_block28 + +guard_block27: ; preds = %assign_optional25 + br label %voiderr36 + +noerr_block28: ; preds = %after_check26 + %16 = call i64 @std.io.File.flush(ptr %10) + %not_err30 = icmp eq i64 %16, 0 + %17 = call i1 @llvm.expect.i1(i1 %not_err30, i1 true) + br i1 %17, label %after_check32, label %assign_optional31 + +assign_optional31: ; preds = %noerr_block28 + store i64 %16, ptr %error_var29, align 8 + br label %guard_block33 + +after_check32: ; preds = %noerr_block28 + br label %noerr_block34 + +guard_block33: ; preds = %assign_optional31 + br label %voiderr36 + +noerr_block34: ; preds = %after_check32 + %18 = load i64, ptr %len14, align 8 + %add35 = add i64 %18, 1 + br label %voiderr36 + +voiderr36: ; preds = %noerr_block34, %guard_block33, %guard_block27, %guard_block21 + %19 = call ptr @std.io.stdout() + %20 = call i64 @std.io.File.write(ptr %retparam40, ptr %19, ptr @.str.11, i64 6) + %not_err41 = icmp eq i64 %20, 0 + %21 = call i1 @llvm.expect.i1(i1 %not_err41, i1 true) + br i1 %21, label %after_check43, label %assign_optional42 + +assign_optional42: ; preds = %voiderr36 + store i64 %20, ptr %error_var38, align 8 + br label %guard_block44 + +after_check43: ; preds = %voiderr36 + br label %noerr_block45 + +guard_block44: ; preds = %assign_optional42 + br label %voiderr59 + +noerr_block45: ; preds = %after_check43 + %22 = load i64, ptr %retparam40, align 8 + store i64 %22, ptr %len37, align 8 + %23 = call i64 @std.io.File.write_byte(ptr %19, i8 zeroext 10) + %not_err47 = icmp eq i64 %23, 0 + %24 = call i1 @llvm.expect.i1(i1 %not_err47, i1 true) + br i1 %24, label %after_check49, label %assign_optional48 + +assign_optional48: ; preds = %noerr_block45 + store i64 %23, ptr %error_var46, align 8 + br label %guard_block50 + +after_check49: ; preds = %noerr_block45 + br label %noerr_block51 + +guard_block50: ; preds = %assign_optional48 + br label %voiderr59 + +noerr_block51: ; preds = %after_check49 + %25 = call i64 @std.io.File.flush(ptr %19) + %not_err53 = icmp eq i64 %25, 0 + %26 = call i1 @llvm.expect.i1(i1 %not_err53, i1 true) + br i1 %26, label %after_check55, label %assign_optional54 + +assign_optional54: ; preds = %noerr_block51 + store i64 %25, ptr %error_var52, align 8 + br label %guard_block56 + +after_check55: ; preds = %noerr_block51 + br label %noerr_block57 + +guard_block56: ; preds = %assign_optional54 + br label %voiderr59 + +noerr_block57: ; preds = %after_check55 + %27 = load i64, ptr %len37, align 8 + %add58 = add i64 %27, 1 + br label %voiderr59 + +voiderr59: ; preds = %noerr_block57, %guard_block56, %guard_block50, %guard_block44 + %28 = call ptr @std.io.stdout() + %29 = call i64 @std.io.File.write(ptr %retparam63, ptr %28, ptr @.str.12, i64 6) + %not_err64 = icmp eq i64 %29, 0 + %30 = call i1 @llvm.expect.i1(i1 %not_err64, i1 true) + br i1 %30, label %after_check66, label %assign_optional65 + +assign_optional65: ; preds = %voiderr59 + store i64 %29, ptr %error_var61, align 8 + br label %guard_block67 + +after_check66: ; preds = %voiderr59 + br label %noerr_block68 + +guard_block67: ; preds = %assign_optional65 + br label %voiderr82 + +noerr_block68: ; preds = %after_check66 + %31 = load i64, ptr %retparam63, align 8 + store i64 %31, ptr %len60, align 8 + %32 = call i64 @std.io.File.write_byte(ptr %28, i8 zeroext 10) + %not_err70 = icmp eq i64 %32, 0 + %33 = call i1 @llvm.expect.i1(i1 %not_err70, i1 true) + br i1 %33, label %after_check72, label %assign_optional71 + +assign_optional71: ; preds = %noerr_block68 + store i64 %32, ptr %error_var69, align 8 + br label %guard_block73 + +after_check72: ; preds = %noerr_block68 + br label %noerr_block74 + +guard_block73: ; preds = %assign_optional71 + br label %voiderr82 + +noerr_block74: ; preds = %after_check72 + %34 = call i64 @std.io.File.flush(ptr %28) + %not_err76 = icmp eq i64 %34, 0 + %35 = call i1 @llvm.expect.i1(i1 %not_err76, i1 true) + br i1 %35, label %after_check78, label %assign_optional77 + +assign_optional77: ; preds = %noerr_block74 + store i64 %34, ptr %error_var75, align 8 + br label %guard_block79 + +after_check78: ; preds = %noerr_block74 + br label %noerr_block80 + +guard_block79: ; preds = %assign_optional77 + br label %voiderr82 + +noerr_block80: ; preds = %after_check78 + %36 = load i64, ptr %len60, align 8 + %add81 = add i64 %36, 1 + br label %voiderr82 + +voiderr82: ; preds = %noerr_block80, %guard_block79, %guard_block73, %guard_block67 + %37 = call ptr @std.io.stdout() + %38 = call i64 @std.io.File.write(ptr %retparam86, ptr %37, ptr @.str.13, i64 5) + %not_err87 = icmp eq i64 %38, 0 + %39 = call i1 @llvm.expect.i1(i1 %not_err87, i1 true) + br i1 %39, label %after_check89, label %assign_optional88 + +assign_optional88: ; preds = %voiderr82 + store i64 %38, ptr %error_var84, align 8 + br label %guard_block90 + +after_check89: ; preds = %voiderr82 + br label %noerr_block91 + +guard_block90: ; preds = %assign_optional88 + br label %voiderr105 + +noerr_block91: ; preds = %after_check89 + %40 = load i64, ptr %retparam86, align 8 + store i64 %40, ptr %len83, align 8 + %41 = call i64 @std.io.File.write_byte(ptr %37, i8 zeroext 10) + %not_err93 = icmp eq i64 %41, 0 + %42 = call i1 @llvm.expect.i1(i1 %not_err93, i1 true) + br i1 %42, label %after_check95, label %assign_optional94 + +assign_optional94: ; preds = %noerr_block91 + store i64 %41, ptr %error_var92, align 8 + br label %guard_block96 + +after_check95: ; preds = %noerr_block91 + br label %noerr_block97 + +guard_block96: ; preds = %assign_optional94 + br label %voiderr105 + +noerr_block97: ; preds = %after_check95 + %43 = call i64 @std.io.File.flush(ptr %37) + %not_err99 = icmp eq i64 %43, 0 + %44 = call i1 @llvm.expect.i1(i1 %not_err99, i1 true) + br i1 %44, label %after_check101, label %assign_optional100 + +assign_optional100: ; preds = %noerr_block97 + store i64 %43, ptr %error_var98, align 8 + br label %guard_block102 + +after_check101: ; preds = %noerr_block97 + br label %noerr_block103 + +guard_block102: ; preds = %assign_optional100 + br label %voiderr105 + +noerr_block103: ; preds = %after_check101 + %45 = load i64, ptr %len83, align 8 + %add104 = add i64 %45, 1 + br label %voiderr105 + +voiderr105: ; preds = %noerr_block103, %guard_block102, %guard_block96, %guard_block90 + %46 = call ptr @std.io.stdout() + %47 = call i64 @std.io.File.write(ptr %retparam109, ptr %46, ptr @.str.14, i64 4) + %not_err110 = icmp eq i64 %47, 0 + %48 = call i1 @llvm.expect.i1(i1 %not_err110, i1 true) + br i1 %48, label %after_check112, label %assign_optional111 + +assign_optional111: ; preds = %voiderr105 + store i64 %47, ptr %error_var107, align 8 + br label %guard_block113 + +after_check112: ; preds = %voiderr105 + br label %noerr_block114 + +guard_block113: ; preds = %assign_optional111 + br label %voiderr128 + +noerr_block114: ; preds = %after_check112 + %49 = load i64, ptr %retparam109, align 8 + store i64 %49, ptr %len106, align 8 + %50 = call i64 @std.io.File.write_byte(ptr %46, i8 zeroext 10) + %not_err116 = icmp eq i64 %50, 0 + %51 = call i1 @llvm.expect.i1(i1 %not_err116, i1 true) + br i1 %51, label %after_check118, label %assign_optional117 + +assign_optional117: ; preds = %noerr_block114 + store i64 %50, ptr %error_var115, align 8 + br label %guard_block119 + +after_check118: ; preds = %noerr_block114 + br label %noerr_block120 + +guard_block119: ; preds = %assign_optional117 + br label %voiderr128 + +noerr_block120: ; preds = %after_check118 + %52 = call i64 @std.io.File.flush(ptr %46) + %not_err122 = icmp eq i64 %52, 0 + %53 = call i1 @llvm.expect.i1(i1 %not_err122, i1 true) + br i1 %53, label %after_check124, label %assign_optional123 + +assign_optional123: ; preds = %noerr_block120 + store i64 %52, ptr %error_var121, align 8 + br label %guard_block125 + +after_check124: ; preds = %noerr_block120 + br label %noerr_block126 + +guard_block125: ; preds = %assign_optional123 + br label %voiderr128 + +noerr_block126: ; preds = %after_check124 + %54 = load i64, ptr %len106, align 8 + %add127 = add i64 %54, 1 + br label %voiderr128 + +voiderr128: ; preds = %noerr_block126, %guard_block125, %guard_block119, %guard_block113 + %55 = call ptr @std.io.stdout() + %56 = call i64 @std.io.File.write(ptr %retparam132, ptr %55, ptr @.str.15, i64 3) + %not_err133 = icmp eq i64 %56, 0 + %57 = call i1 @llvm.expect.i1(i1 %not_err133, i1 true) + br i1 %57, label %after_check135, label %assign_optional134 + +assign_optional134: ; preds = %voiderr128 + store i64 %56, ptr %error_var130, align 8 + br label %guard_block136 + +after_check135: ; preds = %voiderr128 + br label %noerr_block137 + +guard_block136: ; preds = %assign_optional134 + br label %voiderr151 + +noerr_block137: ; preds = %after_check135 + %58 = load i64, ptr %retparam132, align 8 + store i64 %58, ptr %len129, align 8 + %59 = call i64 @std.io.File.write_byte(ptr %55, i8 zeroext 10) + %not_err139 = icmp eq i64 %59, 0 + %60 = call i1 @llvm.expect.i1(i1 %not_err139, i1 true) + br i1 %60, label %after_check141, label %assign_optional140 + +assign_optional140: ; preds = %noerr_block137 + store i64 %59, ptr %error_var138, align 8 + br label %guard_block142 + +after_check141: ; preds = %noerr_block137 + br label %noerr_block143 + +guard_block142: ; preds = %assign_optional140 + br label %voiderr151 + +noerr_block143: ; preds = %after_check141 + %61 = call i64 @std.io.File.flush(ptr %55) + %not_err145 = icmp eq i64 %61, 0 + %62 = call i1 @llvm.expect.i1(i1 %not_err145, i1 true) + br i1 %62, label %after_check147, label %assign_optional146 + +assign_optional146: ; preds = %noerr_block143 + store i64 %61, ptr %error_var144, align 8 + br label %guard_block148 + +after_check147: ; preds = %noerr_block143 + br label %noerr_block149 + +guard_block148: ; preds = %assign_optional146 + br label %voiderr151 + +noerr_block149: ; preds = %after_check147 + %63 = load i64, ptr %len129, align 8 + %add150 = add i64 %63, 1 + br label %voiderr151 + +voiderr151: ; preds = %noerr_block149, %guard_block148, %guard_block142, %guard_block136 + store %"char[]" { ptr @.str.17, i64 3 }, ptr %taddr, align 8 + %64 = insertvalue %any undef, ptr %taddr, 0 + %65 = insertvalue %any %64, i64 ptrtoint (ptr @"$ct.String" to i64), 1 + store %any %65, ptr %varargslots, align 16 + %66 = call i64 @std.io.printfn(ptr %retparam152, ptr @.str.16, i64 8, ptr %varargslots, i64 1) + store %"char[]" { ptr @.str.19, i64 1 }, ptr %taddr156, align 8 + %67 = insertvalue %any undef, ptr %taddr156, 0 + %68 = insertvalue %any %67, i64 ptrtoint (ptr @"$ct.String" to i64), 1 + store %any %68, ptr %varargslots155, align 16 + store %"char[]" { ptr @.str.20, i64 3 }, ptr %taddr157, align 8 + %69 = insertvalue %any undef, ptr %taddr157, 0 + %70 = insertvalue %any %69, i64 ptrtoint (ptr @"$ct.String" to i64), 1 + %ptradd = getelementptr inbounds i8, ptr %varargslots155, i64 16 + store %any %70, ptr %ptradd, align 16 + %71 = call i64 @std.io.printfn(ptr %retparam158, ptr @.str.18, i64 6, ptr %varargslots155, i64 2) + store %"char[]" { ptr @.str.22, i64 4 }, ptr %taddr162, align 8 + %72 = insertvalue %any undef, ptr %taddr162, 0 + %73 = insertvalue %any %72, i64 ptrtoint (ptr @"$ct.String" to i64), 1 + store %any %73, ptr %varargslots161, align 16 + store %"char[]" { ptr @.str.23, i64 4 }, ptr %taddr163, align 8 + %74 = insertvalue %any undef, ptr %taddr163, 0 + %75 = insertvalue %any %74, i64 ptrtoint (ptr @"$ct.String" to i64), 1 + %ptradd164 = getelementptr inbounds i8, ptr %varargslots161, i64 16 + store %any %75, ptr %ptradd164, align 16 + %76 = call i64 @std.io.printfn(ptr %retparam165, ptr @.str.21, i64 6, ptr %varargslots161, i64 2) + store %"char[]" zeroinitializer, ptr %taddr169, align 8 + %77 = insertvalue %any undef, ptr %taddr169, 0 + %78 = insertvalue %any %77, i64 ptrtoint (ptr @"$ct.String" to i64), 1 + store %any %78, ptr %varargslots168, align 16 + store %"char[]" { ptr @.str.25, i64 5 }, ptr %taddr170, align 8 + %79 = insertvalue %any undef, ptr %taddr170, 0 + %80 = insertvalue %any %79, i64 ptrtoint (ptr @"$ct.String" to i64), 1 + %ptradd171 = getelementptr inbounds i8, ptr %varargslots168, i64 16 + store %any %80, ptr %ptradd171, align 16 + %81 = call i64 @std.io.printfn(ptr %retparam172, ptr @.str.24, i64 6, ptr %varargslots168, i64 2) + store %"char[]" { ptr @.str.27, i64 1 }, ptr %taddr176, align 8 + %82 = insertvalue %any undef, ptr %taddr176, 0 + %83 = insertvalue %any %82, i64 ptrtoint (ptr @"$ct.String" to i64), 1 + store %any %83, ptr %varargslots175, align 16 + store %"char[]" { ptr @.str.28, i64 6 }, ptr %taddr177, align 8 + %84 = insertvalue %any undef, ptr %taddr177, 0 + %85 = insertvalue %any %84, i64 ptrtoint (ptr @"$ct.String" to i64), 1 + %ptradd178 = getelementptr inbounds i8, ptr %varargslots175, i64 16 + store %any %85, ptr %ptradd178, align 16 + %86 = call i64 @std.io.printfn(ptr %retparam179, ptr @.str.26, i64 6, ptr %varargslots175, i64 2) + store %"char[]" { ptr @.str.30, i64 3 }, ptr %taddr183, align 8 + %87 = insertvalue %any undef, ptr %taddr183, 0 + %88 = insertvalue %any %87, i64 ptrtoint (ptr @"$ct.String" to i64), 1 + store %any %88, ptr %varargslots182, align 16 + %89 = call i64 @std.io.printfn(ptr %retparam184, ptr @.str.29, i64 8, ptr %varargslots182, i64 1) + store %"char[]" { ptr @.str.32, i64 1 }, ptr %taddr188, align 8 + %90 = insertvalue %any undef, ptr %taddr188, 0 + %91 = insertvalue %any %90, i64 ptrtoint (ptr @"$ct.String" to i64), 1 + store %any %91, ptr %varargslots187, align 16 + store %"char[]" { ptr @.str.33, i64 4 }, ptr %taddr189, align 8 + %92 = insertvalue %any undef, ptr %taddr189, 0 + %93 = insertvalue %any %92, i64 ptrtoint (ptr @"$ct.String" to i64), 1 + %ptradd190 = getelementptr inbounds i8, ptr %varargslots187, i64 16 + store %any %93, ptr %ptradd190, align 16 + %94 = call i64 @std.io.printfn(ptr %retparam191, ptr @.str.31, i64 6, ptr %varargslots187, i64 2) + store %"char[]" { ptr @.str.35, i64 1 }, ptr %taddr195, align 8 + %95 = insertvalue %any undef, ptr %taddr195, 0 + %96 = insertvalue %any %95, i64 ptrtoint (ptr @"$ct.String" to i64), 1 + store %any %96, ptr %varargslots194, align 16 + store %"char[]" { ptr @.str.36, i64 5 }, ptr %taddr196, align 8 + %97 = insertvalue %any undef, ptr %taddr196, 0 + %98 = insertvalue %any %97, i64 ptrtoint (ptr @"$ct.String" to i64), 1 + %ptradd197 = getelementptr inbounds i8, ptr %varargslots194, i64 16 + store %any %98, ptr %ptradd197, align 16 + %99 = call i64 @std.io.printfn(ptr %retparam198, ptr @.str.34, i64 6, ptr %varargslots194, i64 2) + store %"char[]" zeroinitializer, ptr %taddr202, align 8 + %100 = insertvalue %any undef, ptr %taddr202, 0 + %101 = insertvalue %any %100, i64 ptrtoint (ptr @"$ct.String" to i64), 1 + store %any %101, ptr %varargslots201, align 16 + store %"char[]" { ptr @.str.38, i64 5 }, ptr %taddr203, align 8 + %102 = insertvalue %any undef, ptr %taddr203, 0 + %103 = insertvalue %any %102, i64 ptrtoint (ptr @"$ct.String" to i64), 1 + %ptradd204 = getelementptr inbounds i8, ptr %varargslots201, i64 16 + store %any %103, ptr %ptradd204, align 16 + %104 = call i64 @std.io.printfn(ptr %retparam205, ptr @.str.37, i64 6, ptr %varargslots201, i64 2) + store %"char[]" { ptr @.str.40, i64 3 }, ptr %taddr209, align 8 + %105 = insertvalue %any undef, ptr %taddr209, 0 + %106 = insertvalue %any %105, i64 ptrtoint (ptr @"$ct.String" to i64), 1 + store %any %106, ptr %varargslots208, align 16 + store %"char[]" { ptr @.str.41, i64 3 }, ptr %taddr210, align 8 + %107 = insertvalue %any undef, ptr %taddr210, 0 + %108 = insertvalue %any %107, i64 ptrtoint (ptr @"$ct.String" to i64), 1 + %ptradd211 = getelementptr inbounds i8, ptr %varargslots208, i64 16 + store %any %108, ptr %ptradd211, align 16 + %109 = call i64 @std.io.printfn(ptr %retparam212, ptr @.str.39, i64 6, ptr %varargslots208, i64 2) + store %"char[]" { ptr @.str.43, i64 4 }, ptr %taddr216, align 8 + %110 = insertvalue %any undef, ptr %taddr216, 0 + %111 = insertvalue %any %110, i64 ptrtoint (ptr @"$ct.String" to i64), 1 + store %any %111, ptr %varargslots215, align 16 + %112 = call i64 @std.io.printfn(ptr %retparam217, ptr @.str.42, i64 8, ptr %varargslots215, i64 1) + store %"char[]" { ptr @.str.45, i64 1 }, ptr %taddr221, align 8 + %113 = insertvalue %any undef, ptr %taddr221, 0 + %114 = insertvalue %any %113, i64 ptrtoint (ptr @"$ct.String" to i64), 1 + store %any %114, ptr %varargslots220, align 16 + store %"char[]" { ptr @.str.46, i64 3 }, ptr %taddr222, align 8 + %115 = insertvalue %any undef, ptr %taddr222, 0 + %116 = insertvalue %any %115, i64 ptrtoint (ptr @"$ct.String" to i64), 1 + %ptradd223 = getelementptr inbounds i8, ptr %varargslots220, i64 16 + store %any %116, ptr %ptradd223, align 16 + %117 = call i64 @std.io.printfn(ptr %retparam224, ptr @.str.44, i64 6, ptr %varargslots220, i64 2) + store %"char[]" { ptr @.str.48, i64 1 }, ptr %taddr228, align 8 + %118 = insertvalue %any undef, ptr %taddr228, 0 + %119 = insertvalue %any %118, i64 ptrtoint (ptr @"$ct.String" to i64), 1 + store %any %119, ptr %varargslots227, align 16 + store %"char[]" { ptr @.str.49, i64 5 }, ptr %taddr229, align 8 + %120 = insertvalue %any undef, ptr %taddr229, 0 + %121 = insertvalue %any %120, i64 ptrtoint (ptr @"$ct.String" to i64), 1 + %ptradd230 = getelementptr inbounds i8, ptr %varargslots227, i64 16 + store %any %121, ptr %ptradd230, align 16 + %122 = call i64 @std.io.printfn(ptr %retparam231, ptr @.str.47, i64 6, ptr %varargslots227, i64 2) + ret void +} + +; Function Attrs: nounwind uwtable +define void @test.main() #0 { +entry: + %varargslots = alloca [1 x %any], align 16 + %taddr = alloca i64, align 8 + %retparam = alloca i64, align 8 + %varargslots1 = alloca [1 x %any], align 16 + %taddr2 = alloca i64, align 8 + %retparam3 = alloca i64, align 8 + %varargslots4 = alloca [2 x %any], align 16 + %taddr5 = alloca i64, align 8 + %taddr6 = alloca i64, align 8 + %retparam7 = alloca i64, align 8 + %varargslots8 = alloca [2 x %any], align 16 + %taddr9 = alloca i64, align 8 + %taddr10 = alloca i64, align 8 + %retparam12 = alloca i64, align 8 + %varargslots13 = alloca [2 x %any], align 16 + %taddr14 = alloca i64, align 8 + %taddr15 = alloca i64, align 8 + %retparam17 = alloca i64, align 8 + %varargslots18 = alloca [2 x %any], align 16 + %taddr19 = alloca i64, align 8 + %taddr20 = alloca i64, align 8 + %retparam22 = alloca i64, align 8 + %varargslots23 = alloca [2 x %any], align 16 + %taddr24 = alloca i64, align 8 + %taddr25 = alloca i64, align 8 + %retparam27 = alloca i64, align 8 + %varargslots28 = alloca [2 x %any], align 16 + %taddr29 = alloca i64, align 8 + %taddr30 = alloca i64, align 8 + %retparam32 = alloca i64, align 8 + %varargslots33 = alloca [2 x %any], align 16 + %taddr34 = alloca i64, align 8 + %taddr35 = alloca i64, align 8 + %retparam37 = alloca i64, align 8 + %varargslots38 = alloca [1 x %any], align 16 + %taddr39 = alloca i64, align 8 + %retparam40 = alloca i64, align 8 + %varargslots41 = alloca [2 x %any], align 16 + %taddr42 = alloca i64, align 8 + %taddr43 = alloca i64, align 8 + %retparam45 = alloca i64, align 8 + store i64 4, ptr %taddr, align 8 + %0 = insertvalue %any undef, ptr %taddr, 0 + %1 = insertvalue %any %0, i64 ptrtoint (ptr @"$ct.long" to i64), 1 + store %any %1, ptr %varargslots, align 16 + %2 = call i64 @std.io.printfn(ptr %retparam, ptr @.str.50, i64 7, ptr %varargslots, i64 1) + store i64 1, ptr %taddr2, align 8 + %3 = insertvalue %any undef, ptr %taddr2, 0 + %4 = insertvalue %any %3, i64 ptrtoint (ptr @"$ct.long" to i64), 1 + store %any %4, ptr %varargslots1, align 16 + %5 = call i64 @std.io.printfn(ptr %retparam3, ptr @.str.51, i64 7, ptr %varargslots1, i64 1) + store i64 0, ptr %taddr5, align 8 + %6 = insertvalue %any undef, ptr %taddr5, 0 + %7 = insertvalue %any %6, i64 ptrtoint (ptr @"$ct.ulong" to i64), 1 + store %any %7, ptr %varargslots4, align 16 + store i64 4, ptr %taddr6, align 8 + %8 = insertvalue %any undef, ptr %taddr6, 0 + %9 = insertvalue %any %8, i64 ptrtoint (ptr @"$ct.ulong" to i64), 1 + %ptradd = getelementptr inbounds i8, ptr %varargslots4, i64 16 + store %any %9, ptr %ptradd, align 16 + %10 = call i64 @std.io.printfn(ptr %retparam7, ptr @.str.52, i64 8, ptr %varargslots4, i64 2) + store i64 2, ptr %taddr9, align 8 + %11 = insertvalue %any undef, ptr %taddr9, 0 + %12 = insertvalue %any %11, i64 ptrtoint (ptr @"$ct.ulong" to i64), 1 + store %any %12, ptr %varargslots8, align 16 + store i64 2, ptr %taddr10, align 8 + %13 = insertvalue %any undef, ptr %taddr10, 0 + %14 = insertvalue %any %13, i64 ptrtoint (ptr @"$ct.ulong" to i64), 1 + %ptradd11 = getelementptr inbounds i8, ptr %varargslots8, i64 16 + store %any %14, ptr %ptradd11, align 16 + %15 = call i64 @std.io.printfn(ptr %retparam12, ptr @.str.53, i64 8, ptr %varargslots8, i64 2) + store i64 4, ptr %taddr14, align 8 + %16 = insertvalue %any undef, ptr %taddr14, 0 + %17 = insertvalue %any %16, i64 ptrtoint (ptr @"$ct.ulong" to i64), 1 + store %any %17, ptr %varargslots13, align 16 + store i64 4, ptr %taddr15, align 8 + %18 = insertvalue %any undef, ptr %taddr15, 0 + %19 = insertvalue %any %18, i64 ptrtoint (ptr @"$ct.ulong" to i64), 1 + %ptradd16 = getelementptr inbounds i8, ptr %varargslots13, i64 16 + store %any %19, ptr %ptradd16, align 16 + %20 = call i64 @std.io.printfn(ptr %retparam17, ptr @.str.54, i64 8, ptr %varargslots13, i64 2) + store i64 4, ptr %taddr19, align 8 + %21 = insertvalue %any undef, ptr %taddr19, 0 + %22 = insertvalue %any %21, i64 ptrtoint (ptr @"$ct.ulong" to i64), 1 + store %any %22, ptr %varargslots18, align 16 + store i64 4, ptr %taddr20, align 8 + %23 = insertvalue %any undef, ptr %taddr20, 0 + %24 = insertvalue %any %23, i64 ptrtoint (ptr @"$ct.ulong" to i64), 1 + %ptradd21 = getelementptr inbounds i8, ptr %varargslots18, i64 16 + store %any %24, ptr %ptradd21, align 16 + %25 = call i64 @std.io.printfn(ptr %retparam22, ptr @.str.55, i64 8, ptr %varargslots18, i64 2) + store i64 4, ptr %taddr24, align 8 + %26 = insertvalue %any undef, ptr %taddr24, 0 + %27 = insertvalue %any %26, i64 ptrtoint (ptr @"$ct.ulong" to i64), 1 + store %any %27, ptr %varargslots23, align 16 + store i64 4, ptr %taddr25, align 8 + %28 = insertvalue %any undef, ptr %taddr25, 0 + %29 = insertvalue %any %28, i64 ptrtoint (ptr @"$ct.ulong" to i64), 1 + %ptradd26 = getelementptr inbounds i8, ptr %varargslots23, i64 16 + store %any %29, ptr %ptradd26, align 16 + %30 = call i64 @std.io.printfn(ptr %retparam27, ptr @.str.56, i64 9, ptr %varargslots23, i64 2) + store i64 5, ptr %taddr29, align 8 + %31 = insertvalue %any undef, ptr %taddr29, 0 + %32 = insertvalue %any %31, i64 ptrtoint (ptr @"$ct.ulong" to i64), 1 + store %any %32, ptr %varargslots28, align 16 + store i64 1, ptr %taddr30, align 8 + %33 = insertvalue %any undef, ptr %taddr30, 0 + %34 = insertvalue %any %33, i64 ptrtoint (ptr @"$ct.ulong" to i64), 1 + %ptradd31 = getelementptr inbounds i8, ptr %varargslots28, i64 16 + store %any %34, ptr %ptradd31, align 16 + %35 = call i64 @std.io.printfn(ptr %retparam32, ptr @.str.57, i64 9, ptr %varargslots28, i64 2) + store i64 8, ptr %taddr34, align 8 + %36 = insertvalue %any undef, ptr %taddr34, 0 + %37 = insertvalue %any %36, i64 ptrtoint (ptr @"$ct.ulong" to i64), 1 + store %any %37, ptr %varargslots33, align 16 + store i64 4, ptr %taddr35, align 8 + %38 = insertvalue %any undef, ptr %taddr35, 0 + %39 = insertvalue %any %38, i64 ptrtoint (ptr @"$ct.ulong" to i64), 1 + %ptradd36 = getelementptr inbounds i8, ptr %varargslots33, i64 16 + store %any %39, ptr %ptradd36, align 16 + %40 = call i64 @std.io.printfn(ptr %retparam37, ptr @.str.58, i64 10, ptr %varargslots33, i64 2) + store i64 4, ptr %taddr39, align 8 + %41 = insertvalue %any undef, ptr %taddr39, 0 + %42 = insertvalue %any %41, i64 ptrtoint (ptr @"$ct.ulong" to i64), 1 + store %any %42, ptr %varargslots38, align 16 + %43 = call i64 @std.io.printfn(ptr %retparam40, ptr @.str.59, i64 7, ptr %varargslots38, i64 1) + store i64 8, ptr %taddr42, align 8 + %44 = insertvalue %any undef, ptr %taddr42, 0 + %45 = insertvalue %any %44, i64 ptrtoint (ptr @"$ct.ulong" to i64), 1 + store %any %45, ptr %varargslots41, align 16 + store i64 4, ptr %taddr43, align 8 + %46 = insertvalue %any undef, ptr %taddr43, 0 + %47 = insertvalue %any %46, i64 ptrtoint (ptr @"$ct.ulong" to i64), 1 + %ptradd44 = getelementptr inbounds i8, ptr %varargslots41, i64 16 + store %any %47, ptr %ptradd44, align 16 + %48 = call i64 @std.io.printfn(ptr %retparam45, ptr @.str.60, i64 10, ptr %varargslots41, i64 2) + call void @test.test(i32 10) + ret void +} + +; Function Attrs: nounwind uwtable +define i32 @main(i32 %0, ptr %1) #0 { +entry: + call void @test.main() + ret i32 0 +} + +declare extern_weak ptr @std.io.stdout() #0 + +declare extern_weak i64 @std.io.File.write(ptr, ptr, ptr, i64) #0 + +declare extern_weak i64 @std.io.File.write_byte(ptr, i8 zeroext) #0 + +declare extern_weak i64 @std.io.File.flush(ptr) #0 + +declare extern_weak i64 @std.io.printfn(ptr, ptr, i64, ptr, i64) #0 diff --git a/test/test_suite7/compile_time/ct_ordered_error.c3t b/test/test_suite7/compile_time/ct_ordered_error.c3t new file mode 100644 index 000000000..202dc37ab --- /dev/null +++ b/test/test_suite7/compile_time/ct_ordered_error.c3t @@ -0,0 +1,4 @@ +module test; +const ABC = 1; +const A @if(ABC == 1) = 100 ; +int b @if(A == 100); // #error: This @if expression is dependent on \ No newline at end of file diff --git a/test/test_suite7/compile_time/ct_string_functions.c3t b/test/test_suite7/compile_time/ct_string_functions.c3t new file mode 100644 index 000000000..45f9ebb1e --- /dev/null +++ b/test/test_suite7/compile_time/ct_string_functions.c3t @@ -0,0 +1,11 @@ +import std; + +fn int main() +{ + $assert(@str_upper("Hello World") == "HELLO WORLD"); + $assert(@str_lower("Hello World") == "hello world"); + $assert(@str_find("Hello World", "o") == 4); + $assert(@str_find("Hello World", "w") == -1); + $assert(@str_hash("Hello C3") == 487972447); + return 0; +} \ No newline at end of file diff --git a/test/test_suite7/compile_time/ct_subscript_inc.c3t b/test/test_suite7/compile_time/ct_subscript_inc.c3t new file mode 100644 index 000000000..df8114c2f --- /dev/null +++ b/test/test_suite7/compile_time/ct_subscript_inc.c3t @@ -0,0 +1,71 @@ +// #target: macos-x64 +module test; +import std; + +fn void main() +{ + String $c = "Abcd"; + io::printn($c); + io::printfn("%c", $c[1]++); + io::printfn("%c", $c[2]++); + io::printfn("%c", $c[3]--); + io::printn($c); + + String $d = "Abcd"; + io::printn($d); + io::printfn("%c", ++$d[1]); + io::printfn("%c", ++$d[2]); + io::printfn("%c", --$d[3]); + io::printn($d); + + var $e = { 1, 2, 3 }; + io::printn((int[?])$e); + io::printn($e[1]++); + io::printn((int[?])$e); + + int[?] $f = { 1, 2, 3 }; + io::printn($f); + io::printn($f[1]++); + io::printn($f); + + int[?] $g = { 1, 2, 3 }; + io::printn($g); + io::printn(--$g[1]); + io::printn(--$g[0]); + io::printn($g); + +} + +/* #expect: test.ll + + +@.str = private unnamed_addr constant [5 x i8] c"Abcd\00", align 1 +@.str.1 = private unnamed_addr constant [3 x i8] c"%c\00", align 1 +@"$ct.char" = linkonce global %.introspect { i8 3, i64 0, ptr null, i64 1, i64 0, i64 0, [0 x i64] zeroinitializer }, align 8 +@.str.2 = private unnamed_addr constant [3 x i8] c"%c\00", align 1 +@.str.3 = private unnamed_addr constant [3 x i8] c"%c\00", align 1 +@.str.4 = private unnamed_addr constant [5 x i8] c"Acdc\00", align 1 +@.str.5 = private unnamed_addr constant [5 x i8] c"Abcd\00", align 1 +@.str.6 = private unnamed_addr constant [3 x i8] c"%c\00", align 1 +@.str.7 = private unnamed_addr constant [3 x i8] c"%c\00", align 1 +@.str.8 = private unnamed_addr constant [3 x i8] c"%c\00", align 1 +@.str.9 = private unnamed_addr constant [5 x i8] c"Acdc\00", align 1 +@.__const = private unnamed_addr constant [3 x i32] [i32 1, i32 2, i32 3], align 4 +@"$ct.std.io.File" = linkonce global %.introspect { i8 10, i64 0, ptr null, i64 8, i64 0, i64 1, [0 x i64] zeroinitializer }, align 8 +@.str.10 = private unnamed_addr constant [3 x i8] c"%s\00", align 1 +@"$ct.a3$int" = linkonce global %.introspect { i8 15, i64 0, ptr null, i64 12, i64 ptrtoint (ptr @"$ct.int" to i64), i64 3, [0 x i64] zeroinitializer }, align 8 +@"$ct.int" = linkonce global %.introspect { i8 2, i64 0, ptr null, i64 4, i64 0, i64 0, [0 x i64] zeroinitializer }, align 8 +@.str.11 = private unnamed_addr constant [3 x i8] c"%s\00", align 1 +@.__const.12 = private unnamed_addr constant [3 x i32] [i32 1, i32 3, i32 3], align 4 +@.str.13 = private unnamed_addr constant [3 x i8] c"%s\00", align 1 +@.__const.14 = private unnamed_addr constant [3 x i32] [i32 1, i32 2, i32 3], align 4 +@.str.15 = private unnamed_addr constant [3 x i8] c"%s\00", align 1 +@.str.16 = private unnamed_addr constant [3 x i8] c"%s\00", align 1 +@.__const.17 = private unnamed_addr constant [3 x i32] [i32 1, i32 3, i32 3], align 4 +@.str.18 = private unnamed_addr constant [3 x i8] c"%s\00", align 1 +@.__const.19 = private unnamed_addr constant [3 x i32] [i32 1, i32 2, i32 3], align 4 +@.str.20 = private unnamed_addr constant [3 x i8] c"%s\00", align 1 +@.str.21 = private unnamed_addr constant [3 x i8] c"%s\00", align 1 +@.str.22 = private unnamed_addr constant [3 x i8] c"%s\00", align 1 +@.__const.23 = private unnamed_addr constant [3 x i32] [i32 0, i32 1, i32 3], align 4 +@.str.24 = private unnamed_addr constant [3 x i8] c"%s\00", align 1 diff --git a/test/test_suite7/compile_time/ct_subscript_op.c3t b/test/test_suite7/compile_time/ct_subscript_op.c3t new file mode 100644 index 000000000..f636a6e11 --- /dev/null +++ b/test/test_suite7/compile_time/ct_subscript_op.c3t @@ -0,0 +1,27 @@ +// #target: macos-x64 +module test; +fn void main() +{ + var $x2 = { 1, 2, 4 }; + int y = $x2[2] += 1; + int[3] gh = $x2; + $x2[1] <<= 4; + int[3] kl = $x2; +} + +/* #expect: test.ll + +@.__const = private unnamed_addr constant [3 x i32] [i32 1, i32 2, i32 5], align 4 +@.__const.1 = private unnamed_addr constant [3 x i32] [i32 1, i32 32, i32 5], align 4 + +; Function Attrs: nounwind uwtable +define void @test.main() #0 { +entry: + %y = alloca i32, align 4 + %gh = alloca [3 x i32], align 4 + %kl = alloca [3 x i32], align 4 + store i32 5, ptr %y, align 4 + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %gh, ptr align 4 @.__const, i32 12, i1 false) + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %kl, ptr align 4 @.__const.1, i32 12, i1 false) + ret void +} diff --git a/test/test_suite7/compile_time/ct_switch.c3t b/test/test_suite7/compile_time/ct_switch.c3t new file mode 100644 index 000000000..7a625ffa5 --- /dev/null +++ b/test/test_suite7/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 + + +declare void @printf(ptr, ...) #0 + + +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_suite7/compile_time/ct_switch_errors.c3 b/test/test_suite7/compile_time/ct_switch_errors.c3 new file mode 100644 index 000000000..bbb85a1a7 --- /dev/null +++ b/test/test_suite7/compile_time/ct_switch_errors.c3 @@ -0,0 +1,36 @@ + +fn void test() +{ + $switch (3) + $case 2: + return; + $default: // #error: $default must be last in a $switch + $default: + 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: 'int' + return; + $default: + return; + $endswitch +} \ No newline at end of file diff --git a/test/test_suite7/compile_time/ct_switch_more_checks.c3 b/test/test_suite7/compile_time/ct_switch_more_checks.c3 new file mode 100644 index 000000000..34eb21b95 --- /dev/null +++ b/test/test_suite7/compile_time/ct_switch_more_checks.c3 @@ -0,0 +1,48 @@ +module test; +import std::io; + +fn void foo() +{ + int a; + $switch ($typeof(a)) + $case int..float: // #error: $case ranges are only allowed for integers + io::printn("Hello"); + $default: + io::printn("World"); + $endswitch +} + +fn void foo2() +{ + int a; + $switch ($typeof(a)) + $case true..false: // #error: $case ranges are only allowed + io::printn("Hello"); + $default: + io::printn("World"); + $endswitch +} + +fn void foo3() +{ + int a; + $switch ({ 1, 3 }) // #error: Only types, strings, enums, integers, floats and booleans + $case 1: + io::printn("Hello"); + $default: + io::printn("World"); + $endswitch +} + +fn void main() +{ + int a; + $switch ("abc") + $case "cde": + io::printn("!!!"); + $case "abc": + io::printn("Hello"); + $default: + io::printn("World"); + $endswitch +} diff --git a/test/test_suite7/compile_time/ct_switch_top_level.c3t b/test/test_suite7/compile_time/ct_switch_top_level.c3t new file mode 100644 index 000000000..922d83d5d --- /dev/null +++ b/test/test_suite7/compile_time/ct_switch_top_level.c3t @@ -0,0 +1,52 @@ +// #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 + +} + +const BOOL_TYPEID = bool.typeid; +int oefke @if(BOOL_TYPEID == int.typeid) = 23; +int oeoekgokege @if(BOOL_TYPEID != int.typeid) = 343432; + +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 +target triple = "x86_64-apple + +@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.2 = 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.2) + store i32 0, ptr %z1, align 4 + store i32 1, ptr %i, align 4 + ret i32 1 +} diff --git a/test/test_suite7/compile_time/ct_switch_type_check.c3t b/test/test_suite7/compile_time/ct_switch_type_check.c3t new file mode 100644 index 000000000..4fe4bf14c --- /dev/null +++ b/test/test_suite7/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 + + +declare void @printf(ptr, ...) #0 + + +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_suite7/compile_time/ct_switch_type_errors.c3 b/test/test_suite7/compile_time/ct_switch_type_errors.c3 new file mode 100644 index 000000000..27a3df32d --- /dev/null +++ b/test/test_suite7/compile_time/ct_switch_type_errors.c3 @@ -0,0 +1,51 @@ + +fn void test() +{ + $switch (int.typeid) + $case int: + return; + $default: // #error: must be last in a $switch + $default: + return; + $endswitch +} + +fn void test1() +{ + $switch (int.typeid) + $case int: + return; + $case int: // #error: 'int' appears more than once + return; + $default: + return; + $endswitch +} + +def Foo = int; +def Bar = double; +fn void test2() +{ + $switch (int.typeid) + $case Foo: + return; + $case Bar: + return; + $case int: // #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_suite7/compile_time/ct_through_constant.c3t b/test/test_suite7/compile_time/ct_through_constant.c3t new file mode 100644 index 000000000..52bce83ea --- /dev/null +++ b/test/test_suite7/compile_time/ct_through_constant.c3t @@ -0,0 +1,23 @@ +// #target: macos-x64 +module test; + +const FOO = "123"; +int[FOO.len] x; + +fn void main() +{ + int z = x[0]; +} + +/* #expect: test.ll + +@test.FOO = local_unnamed_addr constant %"char[]" { ptr @.str, i64 3 }, align 8 +@test.x = local_unnamed_addr global [3 x i32] zeroinitializer, align 4 + +define void @test.main() #0 { +entry: + %z = alloca i32, align 4 + %0 = load i32, ptr @test.x, align 4 + store i32 %0, ptr %z, align 4 + ret void +} diff --git a/test/test_suite7/compile_time/ct_vaexpr_assign.c3t b/test/test_suite7/compile_time/ct_vaexpr_assign.c3t new file mode 100644 index 000000000..670c9d109 --- /dev/null +++ b/test/test_suite7/compile_time/ct_vaexpr_assign.c3t @@ -0,0 +1,23 @@ +// #target: macos-x64 +module test; +import std; +macro foo(...) +{ + $vaexpr[0] = 2; +} + +fn void main() +{ + int $x; + foo($x); + int y = $x; +} + +/* #expect: test.ll + +define void @test.main() #0 { +entry: + %y = alloca i32, align 4 + store i32 2, ptr %y, align 4 + ret void +} diff --git a/test/test_suite7/compile_time/ct_value_from_access.c3t b/test/test_suite7/compile_time/ct_value_from_access.c3t new file mode 100644 index 000000000..390363623 --- /dev/null +++ b/test/test_suite7/compile_time/ct_value_from_access.c3t @@ -0,0 +1,40 @@ +// #target: macos-x64 +module test; +struct Abc +{ + int a; + int b; +} + +const Abc X = { 2, 3 }; + +const int Y = X.b; +const int* Z = &X.b; + +fn void main() +{ + Abc x = X; + int y = Y; + int* yy = &Y; + int* z = Z; +} + +/* #expect: test.ll + +@test.X = constant %Abc { i32 2, i32 3 }, align 4 +@test.Y = constant i32 3, align 4 +@test.Z = local_unnamed_addr constant ptr getelementptr inbounds (i8, ptr @test.X, i64 4), align 8 + +define void @test.main() #0 { +entry: + %x = alloca %Abc, align 4 + %y = alloca i32, align 4 + %yy = alloca ptr, align 8 + %z = alloca ptr, align 8 + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %x, ptr align 4 @test.X, i32 8, i1 false) + store i32 3, ptr %y, align 4 + store ptr @test.Y, ptr %yy, align 8 + store ptr getelementptr inbounds (i8, ptr @test.X, i64 4), ptr %z, align 8 + ret void +} + diff --git a/test/test_suite7/compile_time/cttype_reassign.c3t b/test/test_suite7/compile_time/cttype_reassign.c3t new file mode 100644 index 000000000..b6819292d --- /dev/null +++ b/test/test_suite7/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_suite7/compile_time/deep_stringify.c3t b/test/test_suite7/compile_time/deep_stringify.c3t new file mode 100644 index 000000000..7cbefe811 --- /dev/null +++ b/test/test_suite7/compile_time/deep_stringify.c3t @@ -0,0 +1,22 @@ +// #target: macos-x64 +module test; +macro @foo(#foo) => @bar(#foo); +macro @bar(#bar) +{ + return "#bar contains " +++ $stringify(#bar); +} + +fn void main() +{ + String a = @foo(something); +} + +/* #expect: test.ll + +@.str = private unnamed_addr constant [24 x i8] c"#bar contains something\00", align 1 + +entry: + %a = alloca %"char[]", align 8 + store %"char[]" { ptr @.str, i64 23 }, ptr %a, align 8 + ret void +} diff --git a/test/test_suite7/compile_time/macro_compile_time_pseudo_evaluation.c3t b/test/test_suite7/compile_time/macro_compile_time_pseudo_evaluation.c3t new file mode 100644 index 000000000..718507204 --- /dev/null +++ b/test/test_suite7/compile_time/macro_compile_time_pseudo_evaluation.c3t @@ -0,0 +1,35 @@ +// #target: macos-x64 +module test; +import std; +macro foo(int a) +{ + int h = a; + return a; +} + +$typeof(baz(2)) y; +const ABC = $sizeof(baz(2)); + +macro baz(int x) => foo(x); + +fn void main() +{ + int x = ABC; + int a = baz(3); +} + +/* #expect: test.ll + + +@test.y = local_unnamed_addr global i32 0, align 4 +@test.ABC = local_unnamed_addr constant i64 4, align 8 + +entry: + %x = alloca i32, align 4 + %a = alloca i32, align 4 + %h = alloca i32, align 4 + store i32 4, ptr %x, align 4 + store i32 3, ptr %h, align 4 + store i32 3, ptr %a, align 4 + ret void +} diff --git a/test/test_suite7/compile_time/mod_ct.c3t b/test/test_suite7/compile_time/mod_ct.c3t new file mode 100644 index 000000000..3e7212419 --- /dev/null +++ b/test/test_suite7/compile_time/mod_ct.c3t @@ -0,0 +1,17 @@ +// #target: macos-x64 +module test; +fn int main() +{ + double a = 4.5 % 5; + double b = -4.5 % 5; + int ai = 4 % 5; + int bi = -4 % 5; + return 0; +} + +/* #expect: test.ll + +store double 4.500000e+00, ptr %a, align 8 +store double -4.500000e+00, ptr %b, align 8 +store i32 4, ptr %ai, align 4 +store i32 -4, ptr %bi, align 4 \ No newline at end of file diff --git a/test/test_suite7/compile_time/mod_in_other_scope.c3 b/test/test_suite7/compile_time/mod_in_other_scope.c3 new file mode 100644 index 000000000..a029de6b2 --- /dev/null +++ b/test/test_suite7/compile_time/mod_in_other_scope.c3 @@ -0,0 +1,23 @@ +module test; + +macro void @foo(#a) +{ + #a; +} + +macro void @bar(#a) +{ + $typeof(#a) x; +} +fn int main() +{ + int $i; + var $Type; + @foo($Type = int); // #error: only be modified + @foo($i = 2); // #error: only be modified + @foo($i += 1); // #error: only be modified + @bar($Type = int); // #error: only be modified + @bar($i = 2); // #error: only be modified + @bar($i += 1); // #error: only be modified + return 0; +} \ No newline at end of file diff --git a/test/test_suite7/compile_time/more_untyped_conversions.c3t b/test/test_suite7/compile_time/more_untyped_conversions.c3t new file mode 100644 index 000000000..41c4cf772 --- /dev/null +++ b/test/test_suite7/compile_time/more_untyped_conversions.c3t @@ -0,0 +1,47 @@ +// #target: macos-x64 +module test; + +struct Foo { int a; struct { int b; int c; }} +fn int main() +{ + var $z = { { 1, 2 }, { }}; + int[2][] z = $z; + int[2][2] z_slice = $z; + var $c = { 1, { 3, 4 }}; + var $d = { 1, 2 }; + Foo f = $c; + int[?] y = $d; + return 0; +} + +/* #expect: test.ll + +@.__const = private unnamed_addr constant %Foo { i32 1, %.anon { i32 3, i32 4 } }, align 4 +@.__const.2 = private unnamed_addr constant [2 x i32] [i32 1, i32 2], align 4 + +entry: + %z = alloca %"int[2][]", align 8 + %literal = alloca [2 x [2 x i32]], align 16 + %z_slice = alloca [2 x [2 x i32]], align 16 + %f = alloca %Foo, align 4 + %y = alloca [2 x i32], align 4 + store i32 1, ptr %literal, align 4 + %ptradd = getelementptr inbounds i8, ptr %literal, i64 4 + store i32 2, ptr %ptradd, align 4 + %ptradd1 = getelementptr inbounds i8, ptr %literal, i64 8 + store i32 0, ptr %ptradd1, align 4 + %ptradd2 = getelementptr inbounds i8, ptr %ptradd1, i64 4 + store i32 0, ptr %ptradd2, align 4 + %0 = insertvalue %"int[2][]" undef, ptr %literal, 0 + %1 = insertvalue %"int[2][]" %0, i64 2, 1 + store %"int[2][]" %1, ptr %z, align 8 + store i32 1, ptr %z_slice, align 4 + %ptradd3 = getelementptr inbounds i8, ptr %z_slice, i64 4 + store i32 2, ptr %ptradd3, align 4 + %ptradd4 = getelementptr inbounds i8, ptr %z_slice, i64 8 + store i32 0, ptr %ptradd4, align 4 + %ptradd5 = getelementptr inbounds i8, ptr %ptradd4, i64 4 + store i32 0, ptr %ptradd5, align 4 + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %f, ptr align 4 @.__const, i32 12, i1 false) + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %y, ptr align 4 @.__const.2, i32 8, i1 false) + ret i32 0 \ No newline at end of file diff --git a/test/test_suite7/compile_time/not_cost.c3 b/test/test_suite7/compile_time/not_cost.c3 new file mode 100644 index 000000000..8b6c5c192 --- /dev/null +++ b/test/test_suite7/compile_time/not_cost.c3 @@ -0,0 +1,10 @@ +macro foo($a) @const +{ + int a = $a; + return $a; +} + +fn void test() +{ + foo(123); // #error: failed to fold to a constant value +} \ No newline at end of file diff --git a/test/test_suite7/compile_time/not_yet_initialized.c3 b/test/test_suite7/compile_time/not_yet_initialized.c3 new file mode 100644 index 000000000..2fbe0b136 --- /dev/null +++ b/test/test_suite7/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: You need to assign a type to +} + +fn void test2() +{ + var $Bar; + $Bar z; // #error: You need to assign a type to +} diff --git a/test/test_suite7/compile_time/stringify.c3t b/test/test_suite7/compile_time/stringify.c3t new file mode 100644 index 000000000..12432da13 --- /dev/null +++ b/test/test_suite7/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_suite7/compile_time/stringify2.c3t b/test/test_suite7/compile_time/stringify2.c3t new file mode 100644 index 000000000..f4d2db3ab --- /dev/null +++ b/test/test_suite7/compile_time/stringify2.c3t @@ -0,0 +1,20 @@ +// #target: macos-x64 +module test; +import std::io; + +fn void main() +{ + var $s1 = $stringify(1 + 2); + char[?] s2 = $stringify($s1); + char[] s3 = $s1; + + io::printfn("$s1 == %s", $s1); + io::printfn("s2 == %s", &s2); + io::printfn("s3 == %s", s3); +} + +/* #expect: test.ll + +c"$s1\00", align 1 +c"1 + 2\00", align 1 +c"1 + 2\00", align 1 \ No newline at end of file diff --git a/test/test_suite7/compile_time/ternary_folding.c3t b/test/test_suite7/compile_time/ternary_folding.c3t new file mode 100644 index 000000000..b53487ddb --- /dev/null +++ b/test/test_suite7/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_suite7/compile_time/typed_ct_vars.c3t b/test/test_suite7/compile_time/typed_ct_vars.c3t new file mode 100644 index 000000000..dcfb36bac --- /dev/null +++ b/test/test_suite7/compile_time/typed_ct_vars.c3t @@ -0,0 +1,28 @@ +// #target: macos-x64 +module test; + +struct Foo +{ + int x, y; +} + +fn void test() +{ + Foo $z = { 1, 2 }; + Foo $y; + Foo y = $z; + Foo z = $y; +} + +/* #expect: test.ll + +define void @test.test() #0 { +entry: + %y = alloca %Foo, align 4 + %z = alloca %Foo, align 4 + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %y, ptr align 4 @.__const, i32 8, i1 false) + store i32 0, ptr %z, align 4 + %ptradd = getelementptr inbounds i8, ptr %z, i64 4 + store i32 0, ptr %ptradd, align 4 + ret void +} \ No newline at end of file diff --git a/test/test_suite7/compile_time/typefrom.c3t b/test/test_suite7/compile_time/typefrom.c3t new file mode 100644 index 000000000..8955f105e --- /dev/null +++ b/test/test_suite7/compile_time/typefrom.c3t @@ -0,0 +1,15 @@ +// #target: macos-x64 + +module test; + + +fn int main() +{ + var $foo = double.typeid; + $typefrom($foo) a = 123.0; + return (int)a; +} + +/* #expect: test.ll + + %a = alloca double, align 8 \ No newline at end of file diff --git a/test/test_suite7/compile_time/typefrom_errors.c3t b/test/test_suite7/compile_time/typefrom_errors.c3t new file mode 100644 index 000000000..37cb68d96 --- /dev/null +++ b/test/test_suite7/compile_time/typefrom_errors.c3t @@ -0,0 +1,13 @@ + +fn void test() +{ + typeid x; + $typefrom(2 > 1 ? int.typeid : double.typeid) xf; + $typefrom(x) a; // #error: Expected a constant +} + +fn void test2() +{ + var $x = 1; + $typefrom($x) a; // #error: Expected a constant +} \ No newline at end of file diff --git a/test/test_suite7/compile_time/typeof_example.c3t b/test/test_suite7/compile_time/typeof_example.c3t new file mode 100644 index 000000000..83a555113 --- /dev/null +++ b/test/test_suite7/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 4 + 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 4 + store float %7, ptr %f2, align 4 + %8 = load float, ptr %f, align 4 + %fpfpext = fpext float %8 to double + %9 = load float, ptr %f2, align 4 + %fpfpext4 = fpext float %9 to double + %10 = load i32, ptr %i, align 4 + call void (ptr, ...) @printf(ptr @.str, double %fpfpext, i32 %10, double %fpfpext4) + ret void \ No newline at end of file diff --git a/test/test_suite7/compile_time/typeof_from_literal.c3 b/test/test_suite7/compile_time/typeof_from_literal.c3 new file mode 100644 index 000000000..e5deaa514 --- /dev/null +++ b/test/test_suite7/compile_time/typeof_from_literal.c3 @@ -0,0 +1,14 @@ +module foo; + +fn void a() +{ + $typeof(9146744073709551615i64) ef; + int fffx = ef; // #error: 'long' +} + +fn void b() +{ + $typeof(9223372036854775809u64) ef; + int fffx = ef; // #error: 'ulong' +} + diff --git a/test/test_suite7/compile_time/untyped_conversions.c3t b/test/test_suite7/compile_time/untyped_conversions.c3t new file mode 100644 index 000000000..050787316 --- /dev/null +++ b/test/test_suite7/compile_time/untyped_conversions.c3t @@ -0,0 +1,133 @@ +// #target: macos-x64 +module test; +import std::io; +struct Foo +{ + int a; int b; +} +fn void test(int[2] a, int[] b, int[<2>] c) +{ + io::printfn("%s %s %s", a, b, c); +} +fn void main() +{ + var $x = { { 1, 2 } }; + Foo[1] abc = (Foo[1])$x; + Foo defg = (Foo)$x[0]; + int[2][1] y = (int[2][1])$x; + double[2][1] y2 = $x; + io::printfn("%s %s {%s, %s}", y, y2, defg.a, defg.b); + test({ 1, 2 }, { 3, 4}, { 5, 6 }); + var $a = { 2, 7 }; + test($a, $a, $a); +} + +/* #expect: test.ll + +%.introspect = type { i8, i64, ptr, i64, i64, i64, [0 x i64] } +%Foo = type { i32, i32 } +%"int[]" = type { ptr, i64 } +%any = type { ptr, i64 } + +@"$ct.test.Foo" = linkonce global %.introspect { i8 10, i64 0, ptr null, i64 8, i64 0, i64 2, [0 x i64] zeroinitializer }, align 8 +@.str = private unnamed_addr constant [9 x i8] c"%s %s %s\00", align 1 +@"$ct.a2$int" = linkonce global %.introspect { i8 15, i64 0, ptr null, i64 8, i64 ptrtoint (ptr @"$ct.int" to i64), i64 2, [0 x i64] zeroinitializer }, align 8 +@"$ct.int" = linkonce global %.introspect { i8 2, i64 0, ptr null, i64 4, i64 0, i64 0, [0 x i64] zeroinitializer }, align 8 +@"$ct.sa$int" = linkonce global %.introspect { i8 16, i64 0, ptr null, i64 16, i64 ptrtoint (ptr @"$ct.int" to i64), i64 0, [0 x i64] zeroinitializer }, align 8 +@"$ct.v2$int" = linkonce global %.introspect { i8 17, i64 0, ptr null, i64 8, i64 ptrtoint (ptr @"$ct.int" to i64), i64 2, [0 x i64] zeroinitializer }, align 8 +@.__const = private unnamed_addr constant [1 x %Foo] [%Foo { i32 1, i32 2 }], align 4 +@.__const.1 = private unnamed_addr constant %Foo { i32 1, i32 2 }, align 4 +@.__const.2 = private unnamed_addr constant [1 x [2 x i32]] [[2 x i32] [i32 1, i32 2]], align 4 +@.__const.3 = private unnamed_addr constant [1 x [2 x double]] [[2 x double] [double 1.000000e+00, double 2.000000e+00]], align 16 +@.str.4 = private unnamed_addr constant [15 x i8] c"%s %s {%s, %s}\00", align 1 +@"$ct.a1$a2$int" = linkonce global %.introspect { i8 15, i64 0, ptr null, i64 8, i64 ptrtoint (ptr @"$ct.a2$int" to i64), i64 1, [0 x i64] zeroinitializer }, align 8 +@"$ct.a1$a2$double" = linkonce global %.introspect { i8 15, i64 0, ptr null, i64 16, i64 ptrtoint (ptr @"$ct.a2$double" to i64), i64 1, [0 x i64] zeroinitializer }, align 8 +@"$ct.a2$double" = linkonce global %.introspect { i8 15, i64 0, ptr null, i64 16, i64 ptrtoint (ptr @"$ct.double" to i64), i64 2, [0 x i64] zeroinitializer }, align 8 +@"$ct.double" = linkonce global %.introspect { i8 4, i64 0, ptr null, i64 8, i64 0, i64 0, [0 x i64] zeroinitializer }, align 8 +@.__const.5 = private unnamed_addr constant [2 x i32] [i32 1, i32 2], align 4 +@.__const.6 = private unnamed_addr constant [2 x i32] [i32 3, i32 4], align 4 +@.__const.7 = private unnamed_addr constant [2 x i32] [i32 2, i32 7], align 4 +@.__const.8 = private unnamed_addr constant [2 x i32] [i32 2, i32 7], align 4 + +; Function Attrs: +define void @test.test(i64 %0, ptr %1, i64 %2, double %3) #0 { +entry: + %a = alloca [2 x i32], align 4 + %b = alloca %"int[]", align 8 + %c = alloca <2 x i32>, align 8 + %varargslots = alloca [3 x %any], align 16 + %retparam = alloca i64, align 8 + store i64 %0, ptr %a, align 4 + store ptr %1, ptr %b, align 8 + %ptradd = getelementptr inbounds i8, ptr %b, i64 8 + store i64 %2, ptr %ptradd, align 8 + store double %3, ptr %c, align 8 + %4 = insertvalue %any undef, ptr %a, 0 + %5 = insertvalue %any %4, i64 ptrtoint (ptr @"$ct.a2$int" to i64), 1 + store %any %5, ptr %varargslots, align 16 + %6 = insertvalue %any undef, ptr %b, 0 + %7 = insertvalue %any %6, i64 ptrtoint (ptr @"$ct.sa$int" to i64), 1 + %ptradd1 = getelementptr inbounds i8, ptr %varargslots, i64 16 + store %any %7, ptr %ptradd1, align 16 + %8 = insertvalue %any undef, ptr %c, 0 + %9 = insertvalue %any %8, i64 ptrtoint (ptr @"$ct.v2$int" to i64), 1 + %ptradd2 = getelementptr inbounds i8, ptr %varargslots, i64 32 + store %any %9, ptr %ptradd2, align 16 + %10 = call i64 @std.io.printfn(ptr %retparam, ptr @.str, i64 8, ptr %varargslots, i64 3) + ret void +} + +; Function Attrs: +define void @test.main() #0 { +entry: + %abc = alloca [1 x %Foo], align 4 + %defg = alloca %Foo, align 4 + %y = alloca [1 x [2 x i32]], align 4 + %y2 = alloca [1 x [2 x double]], align 16 + %varargslots = alloca [4 x %any], align 16 + %retparam = alloca i64, align 8 + %literal = alloca [2 x i32], align 4 + %literal4 = alloca [2 x i32], align 4 + %taddr = alloca <2 x i32>, align 8 + %literal5 = alloca [2 x i32], align 4 + %literal6 = alloca [2 x i32], align 4 + %taddr7 = alloca <2 x i32>, align 8 + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %abc, ptr align 4 @.__const, i32 8, i1 false) + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %defg, ptr align 4 @.__const.1, i32 8, i1 false) + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %y, ptr align 4 @.__const.2, i32 8, i1 false) + call void @llvm.memcpy.p0.p0.i32(ptr align 16 %y2, ptr align 16 @.__const.3, i32 16, i1 false) + %0 = insertvalue %any undef, ptr %y, 0 + %1 = insertvalue %any %0, i64 ptrtoint (ptr @"$ct.a1$a2$int" to i64), 1 + store %any %1, ptr %varargslots, align 16 + %2 = insertvalue %any undef, ptr %y2, 0 + %3 = insertvalue %any %2, i64 ptrtoint (ptr @"$ct.a1$a2$double" to i64), 1 + %ptradd = getelementptr inbounds i8, ptr %varargslots, i64 16 + store %any %3, ptr %ptradd, align 16 + %4 = insertvalue %any undef, ptr %defg, 0 + %5 = insertvalue %any %4, i64 ptrtoint (ptr @"$ct.int" to i64), 1 + %ptradd1 = getelementptr inbounds i8, ptr %varargslots, i64 32 + store %any %5, ptr %ptradd1, align 16 + %ptradd2 = getelementptr inbounds i8, ptr %defg, i64 4 + %6 = insertvalue %any undef, ptr %ptradd2, 0 + %7 = insertvalue %any %6, i64 ptrtoint (ptr @"$ct.int" to i64), 1 + %ptradd3 = getelementptr inbounds i8, ptr %varargslots, i64 48 + store %any %7, ptr %ptradd3, align 16 + %8 = call i64 @std.io.printfn(ptr %retparam, ptr @.str.4, i64 14, ptr %varargslots, i64 4) + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %literal, ptr align 4 @.__const.5, i32 8, i1 false) + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %literal4, ptr align 4 @.__const.6, i32 8, i1 false) + %9 = insertvalue %"int[]" undef, ptr %literal4, 0 + %10 = insertvalue %"int[]" %9, i64 2, 1 + %11 = load i64, ptr %literal, align 4 + store <2 x i32> , ptr %taddr, align 8 + %12 = load double, ptr %taddr, align 8 + call void @test.test(i64 %11, ptr %literal4, i64 2, double %12) + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %literal5, ptr align 4 @.__const.7, i32 8, i1 false) + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %literal6, ptr align 4 @.__const.8, i32 8, i1 false) + %13 = insertvalue %"int[]" undef, ptr %literal6, 0 + %14 = insertvalue %"int[]" %13, i64 2, 1 + %15 = load i64, ptr %literal5, align 4 + store <2 x i32> , ptr %taddr7, align 8 + %16 = load double, ptr %taddr7, align 8 + call void @test.test(i64 %15, ptr %literal6, i64 2, double %16) + ret void +} diff --git a/test/test_suite7/compile_time/untyped_with_inferred.c3 b/test/test_suite7/compile_time/untyped_with_inferred.c3 new file mode 100644 index 000000000..5c4ff88ed --- /dev/null +++ b/test/test_suite7/compile_time/untyped_with_inferred.c3 @@ -0,0 +1,6 @@ + +fn void main() +{ + var $x = { 1, 1.0 }; + double[?] z = $x; +} diff --git a/test/test_suite7/compile_time_introspection/alignof.c3t b/test/test_suite7/compile_time_introspection/alignof.c3t new file mode 100644 index 000000000..67931e9e9 --- /dev/null +++ b/test/test_suite7/compile_time_introspection/alignof.c3t @@ -0,0 +1,65 @@ +// #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 = Bob.y.alignof; +int z = Bob.w.z.alignof; +int v = $alignof(v); +int x1 = Ex.c.alignof; +int x2 = Ex.y.alignof; +int x3 = char[8].alignof; +int x9 = $alignof(izzy.br[1]); +int x10 = $alignof(izzy.br[1]); +int x11 = $alignof(izzy.br[1]); +int z0 = Foob.c.alignof; + + + +/* #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 4, 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.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 diff --git a/test/test_suite7/compile_time_introspection/defined.c3t b/test/test_suite7/compile_time_introspection/defined.c3t new file mode 100644 index 000000000..79dbb0c6b --- /dev/null +++ b/test/test_suite7/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_suite7/compile_time_introspection/defined2.c3 b/test/test_suite7/compile_time_introspection/defined2.c3 new file mode 100644 index 000000000..36ac00559 --- /dev/null +++ b/test/test_suite7/compile_time_introspection/defined2.c3 @@ -0,0 +1,15 @@ +fn void main() +{ + int[<2>] ab = { 11, 22 }; + $assert !$defined(&1); + int! a; + $assert $defined(a!!); + $assert !$defined(ab!!); + $assert $defined(a!); + $assert !$defined(ab!); + $assert !$defined(*ab); + int* z = &&1; + $assert $defined(*z); + void* g; + $assert !$defined(*g); +} \ No newline at end of file diff --git a/test/test_suite7/compile_time_introspection/defined_2.c3t b/test/test_suite7/compile_time_introspection/defined_2.c3t new file mode 100644 index 000000000..fec0f75d8 --- /dev/null +++ b/test/test_suite7/compile_time_introspection/defined_2.c3t @@ -0,0 +1,40 @@ +// #target: macos-x64 + +module testing; +import std::io; + +fn void main() +{ + Bits b1; + Bits b2; + bool x = equals(b1, b2); +} + +bitstruct Bits : char +{ + bool flag; +} + +fn bool Bits.equals(a, Bits b) +{ + return a.flag == b.flag; +} + +/* #expect: testing.ll + +entry: + %b1 = alloca i8, align 1 + %b2 = alloca i8, align 1 + %x = alloca i8, align 1 + %a = alloca i8, align 1 + %b = alloca i8, align 1 + store i8 0, ptr %b1, align 1 + store i8 0, ptr %b2, align 1 + %0 = load i8, ptr %b1, align 1 + store i8 %0, ptr %a, align 1 + %1 = load i8, ptr %b2, align 1 + store i8 %1, ptr %b, align 1 + %2 = load i8, ptr %a, align 1 + %3 = load i8, ptr %b, align 1 + %4 = call i8 @testing.Bits.equals(i8 zeroext %2, i8 zeroext %3) + store i8 %4, ptr %x, align 1 diff --git a/test/test_suite7/compile_time_introspection/defined_builtin.c3t b/test/test_suite7/compile_time_introspection/defined_builtin.c3t new file mode 100644 index 000000000..c7dc9d835 --- /dev/null +++ b/test/test_suite7/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_suite7/compile_time_introspection/defined_err.c3 b/test/test_suite7/compile_time_introspection/defined_err.c3 new file mode 100644 index 000000000..20b48c75f --- /dev/null +++ b/test/test_suite7/compile_time_introspection/defined_err.c3 @@ -0,0 +1,25 @@ +fn void test1() +{ + bool x = $defined(1); +} + +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_suite7/compile_time_introspection/defined_index.c3t b/test/test_suite7/compile_time_introspection/defined_index.c3t new file mode 100644 index 000000000..3e6a3476f --- /dev/null +++ b/test/test_suite7/compile_time_introspection/defined_index.c3t @@ -0,0 +1,29 @@ +// #target: macos-x64 +module test; +struct Abc { int x; } +fn int* Abc.get(&self, usz index) @operator(&[]) { return &self.x; } + +struct Bcd { int x; } +fn int Bcd.get(&self, usz index) @operator([]) { return 1; } + +fn void main() +{ + Abc a; + Bcd b; + int[4] c; + bool a1 = $defined(&a[0]); + bool a2 = $defined(a[0]); + bool b1 = $defined(&b[0]); + bool b2 = $defined(b[0]); + bool c1 = $defined(&c[0]); + bool c2 = $defined(c[0]); +} + +/* #expect: test.ll + + store i8 1, ptr %a1, align 1 + store i8 0, ptr %a2, align 1 + store i8 0, ptr %b1, align 1 + store i8 1, ptr %b2, align 1 + store i8 1, ptr %c1, align 1 + store i8 1, ptr %c2, align 1 \ No newline at end of file diff --git a/test/test_suite7/compile_time_introspection/defined_subscript.c3 b/test/test_suite7/compile_time_introspection/defined_subscript.c3 new file mode 100644 index 000000000..a1ccec390 --- /dev/null +++ b/test/test_suite7/compile_time_introspection/defined_subscript.c3 @@ -0,0 +1,7 @@ +fn void main() +{ + int[<2>] ab = { 11, 22 }; + $assert !$defined(ab[3]); + $assert $defined(ab[1]); + $assert !$defined(ab[0][0]); +} \ No newline at end of file diff --git a/test/test_suite7/compile_time_introspection/nameof.c3t b/test/test_suite7/compile_time_introspection/nameof.c3t new file mode 100644 index 000000000..5246aa0e9 --- /dev/null +++ b/test/test_suite7/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", Foo.qnameof); + printf("%s\n", $evaltype("Foo").qnameof); + printf("%s\n", Foo.nameof); + printf("%s\n", $evaltype("mymodule::Foo").nameof); + printf("%s\n", Foo.extnameof); + printf("%s\n", $evaltype("Foo").extnameof); + + 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_suite7/compile_time_introspection/nameof_err.c3 b/test/test_suite7/compile_time_introspection/nameof_err.c3 new file mode 100644 index 000000000..f04049945 --- /dev/null +++ b/test/test_suite7/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() +{ + $evaltype("int").extnameof; // #error: 'int' does not have a property or method 'extnameof' +} + +fn void main4() +{ + $evaltype("foo::int").extnameof; // #error: Only valid types may be resolved with $evaltype. +} diff --git a/test/test_suite7/compile_time_introspection/offsetof.c3t b/test/test_suite7/compile_time_introspection/offsetof.c3t new file mode 100644 index 000000000..920aa1805 --- /dev/null +++ b/test/test_suite7/compile_time_introspection/offsetof.c3t @@ -0,0 +1,50 @@ +// #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 = Bob.y.offsetof; +int z = Bob.w.z.offsetof; +int w = Bob.w.offsetof; +int z0 = Foob.c.offsetof; +int z03 = Foob.a.offsetof; + +/* #expect: foo.ll +@foo.y = local_unnamed_addr global i16 16, align 2 +@foo.z = local_unnamed_addr global i32 116, align 4 +@foo.w = local_unnamed_addr global i32 116, align 4 +@foo.z0 = local_unnamed_addr global i32 0, align 4 +@foo.z03 = local_unnamed_addr global i32 0, align 4 diff --git a/test/test_suite7/compile_time_introspection/paramsof.c3t b/test/test_suite7/compile_time_introspection/paramsof.c3t new file mode 100644 index 000000000..59c737e30 --- /dev/null +++ b/test/test_suite7/compile_time_introspection/paramsof.c3t @@ -0,0 +1,391 @@ +// #target: macos-x64 +module test; +import std; +fn void testme(int a, double b) +{} + +fn void main() +{ + ReflectedParam[?] z = $typeof(testme).paramsof; + foreach (r : z) + { + io::printn(r); + } + $foreach ($r : $typeof(testme).paramsof) + io::printn($r.name); + io::printn($r.type.nameof); + $endforeach +} + +/* #expect: test.ll + + +; ModuleID = 'test' + +%ReflectedParam = type { %"char[]", i64 } + +@.str = private unnamed_addr constant [2 x i8] c"a\00", align 1 +@"$ct.int" = linkonce global %.introspect { i8 2, i64 0, ptr null, i64 4, i64 0, i64 0, [0 x i64] zeroinitializer }, align 8 +@.str.1 = private unnamed_addr constant [2 x i8] c"b\00", align 1 +@"$ct.double" = linkonce global %.introspect { i8 4, i64 0, ptr null, i64 8, i64 0, i64 0, [0 x i64] zeroinitializer }, align 8 +@.__const = private unnamed_addr constant [2 x %ReflectedParam] [%ReflectedParam { %"char[]" { ptr @.str, i64 1 }, i64 ptrtoint (ptr @"$ct.int" to i64) }, %ReflectedParam { %"char[]" { ptr @.str.1, i64 1 }, i64 ptrtoint (ptr @"$ct.double" to i64) }], align 16 +@"$ct.std.io.File" = linkonce global %.introspect { i8 10, i64 0, ptr null, i64 8, i64 0, i64 1, [0 x i64] zeroinitializer }, align 8 +@.str.2 = private unnamed_addr constant [3 x i8] c"%s\00", align 1 +@"$ct.ReflectedParam" = linkonce global %.introspect { i8 10, i64 0, ptr null, i64 24, i64 0, i64 2, [0 x i64] zeroinitializer }, align 8 +@.str.3 = private unnamed_addr constant [2 x i8] c"a\00", align 1 +@.str.4 = private unnamed_addr constant [4 x i8] c"int\00", align 1 +@.str.5 = private unnamed_addr constant [2 x i8] c"b\00", align 1 +@.str.6 = private unnamed_addr constant [7 x i8] c"double\00", align 1 + +define void @test.main() #0 { +entry: + %z = alloca [2 x %ReflectedParam], align 16 + %.anon = alloca i64, align 8 + %r = alloca %ReflectedParam, align 8 + %x = alloca %ReflectedParam, align 8 + %x1 = alloca %ReflectedParam, align 8 + %len = alloca i64, align 8 + %error_var = alloca i64, align 8 + %x2 = alloca %ReflectedParam, align 8 + %varargslots = alloca [1 x %any], align 16 + %retparam = alloca i64, align 8 + %taddr = alloca %any, align 8 + %indirectarg = alloca %"any[]", align 8 + %error_var4 = alloca i64, align 8 + %error_var10 = alloca i64, align 8 + %len16 = alloca i64, align 8 + %error_var17 = alloca i64, align 8 + %retparam19 = alloca i64, align 8 + %error_var25 = alloca i64, align 8 + %error_var31 = alloca i64, align 8 + %len39 = alloca i64, align 8 + %error_var40 = alloca i64, align 8 + %retparam42 = alloca i64, align 8 + %error_var48 = alloca i64, align 8 + %error_var54 = alloca i64, align 8 + %len62 = alloca i64, align 8 + %error_var63 = alloca i64, align 8 + %retparam65 = alloca i64, align 8 + %error_var71 = alloca i64, align 8 + %error_var77 = alloca i64, align 8 + %len85 = alloca i64, align 8 + %error_var86 = alloca i64, align 8 + %retparam88 = alloca i64, align 8 + %error_var94 = alloca i64, align 8 + %error_var100 = alloca i64, align 8 + call void @llvm.memcpy.p0.p0.i32(ptr align 16 %z, ptr align 16 @.__const, i32 48, i1 false) + store i64 0, ptr %.anon, align 8 + br label %loop.cond + +loop.cond: ; preds = %voiderr, %entry + %0 = load i64, ptr %.anon, align 8 + %gt = icmp ugt i64 2, %0 + br i1 %gt, label %loop.body, label %loop.exit + +loop.body: ; preds = %loop.cond + %1 = load i64, ptr %.anon, align 8 + %ptroffset = getelementptr inbounds [24 x i8], ptr %z, i64 %1 + call void @llvm.memcpy.p0.p0.i32(ptr align 8 %r, ptr align 8 %ptroffset, i32 24, i1 false) + call void @llvm.memcpy.p0.p0.i32(ptr align 8 %x, ptr align 8 %r, i32 24, i1 false) + %2 = call ptr @std.io.stdout() + call void @llvm.memcpy.p0.p0.i32(ptr align 8 %x1, ptr align 8 %x, i32 24, i1 false) + call void @llvm.memcpy.p0.p0.i32(ptr align 8 %x2, ptr align 8 %x1, i32 24, i1 false) + %3 = insertvalue %any undef, ptr %2, 0 + %4 = insertvalue %any %3, i64 ptrtoint (ptr @"$ct.std.io.File" to i64), 1 + %5 = insertvalue %any undef, ptr %x2, 0 + %6 = insertvalue %any %5, i64 ptrtoint (ptr @"$ct.ReflectedParam" to i64), 1 + store %any %6, ptr %varargslots, align 16 + %7 = insertvalue %"any[]" undef, ptr %varargslots, 0 + %"$$temp" = insertvalue %"any[]" %7, i64 1, 1 + store %any %4, ptr %taddr, align 8 + %lo = load i64, ptr %taddr, align 8 + %ptradd = getelementptr inbounds i8, ptr %taddr, i64 8 + %hi = load ptr, ptr %ptradd, align 8 + store %"any[]" %"$$temp", ptr %indirectarg, align 8 + %8 = call i64 @std.io.fprintf(ptr %retparam, i64 %lo, ptr %hi, ptr @.str.2, i64 2, ptr byval(%"any[]") align 8 %indirectarg) + %not_err = icmp eq i64 %8, 0 + %9 = call i1 @llvm.expect.i1(i1 %not_err, i1 true) + br i1 %9, label %after_check, label %assign_optional + +assign_optional: ; preds = %loop.body + store i64 %8, ptr %error_var, align 8 + br label %guard_block + +after_check: ; preds = %loop.body + br label %noerr_block + +guard_block: ; preds = %assign_optional + br label %voiderr + +noerr_block: ; preds = %after_check + %10 = load i64, ptr %retparam, align 8 + store i64 %10, ptr %len, align 8 + %11 = call i64 @std.io.File.write_byte(ptr %2, i8 zeroext 10) + %not_err5 = icmp eq i64 %11, 0 + %12 = call i1 @llvm.expect.i1(i1 %not_err5, i1 true) + br i1 %12, label %after_check7, label %assign_optional6 + +assign_optional6: ; preds = %noerr_block + store i64 %11, ptr %error_var4, align 8 + br label %guard_block8 + +after_check7: ; preds = %noerr_block + br label %noerr_block9 + +guard_block8: ; preds = %assign_optional6 + br label %voiderr + +noerr_block9: ; preds = %after_check7 + %13 = call i64 @std.io.File.flush(ptr %2) + %not_err11 = icmp eq i64 %13, 0 + %14 = call i1 @llvm.expect.i1(i1 %not_err11, i1 true) + br i1 %14, label %after_check13, label %assign_optional12 + +assign_optional12: ; preds = %noerr_block9 + store i64 %13, ptr %error_var10, align 8 + br label %guard_block14 + +after_check13: ; preds = %noerr_block9 + br label %noerr_block15 + +guard_block14: ; preds = %assign_optional12 + br label %voiderr + +noerr_block15: ; preds = %after_check13 + %15 = load i64, ptr %len, align 8 + %add = add i64 %15, 1 + br label %voiderr + +voiderr: ; preds = %noerr_block15, %guard_block14, %guard_block8, %guard_block + %16 = load i64, ptr %.anon, align 8 + %addnuw = add nuw i64 %16, 1 + store i64 %addnuw, ptr %.anon, align 8 + br label %loop.cond + +loop.exit: ; preds = %loop.cond + %17 = call ptr @std.io.stdout() + %18 = call i64 @std.io.File.write(ptr %retparam19, ptr %17, ptr @.str.3, i64 1) + %not_err20 = icmp eq i64 %18, 0 + %19 = call i1 @llvm.expect.i1(i1 %not_err20, i1 true) + br i1 %19, label %after_check22, label %assign_optional21 + +assign_optional21: ; preds = %loop.exit + store i64 %18, ptr %error_var17, align 8 + br label %guard_block23 + +after_check22: ; preds = %loop.exit + br label %noerr_block24 + +guard_block23: ; preds = %assign_optional21 + br label %voiderr38 + +noerr_block24: ; preds = %after_check22 + %20 = load i64, ptr %retparam19, align 8 + store i64 %20, ptr %len16, align 8 + %21 = call i64 @std.io.File.write_byte(ptr %17, i8 zeroext 10) + %not_err26 = icmp eq i64 %21, 0 + %22 = call i1 @llvm.expect.i1(i1 %not_err26, i1 true) + br i1 %22, label %after_check28, label %assign_optional27 + +assign_optional27: ; preds = %noerr_block24 + store i64 %21, ptr %error_var25, align 8 + br label %guard_block29 + +after_check28: ; preds = %noerr_block24 + br label %noerr_block30 + +guard_block29: ; preds = %assign_optional27 + br label %voiderr38 + +noerr_block30: ; preds = %after_check28 + %23 = call i64 @std.io.File.flush(ptr %17) + %not_err32 = icmp eq i64 %23, 0 + %24 = call i1 @llvm.expect.i1(i1 %not_err32, i1 true) + br i1 %24, label %after_check34, label %assign_optional33 + +assign_optional33: ; preds = %noerr_block30 + store i64 %23, ptr %error_var31, align 8 + br label %guard_block35 + +after_check34: ; preds = %noerr_block30 + br label %noerr_block36 + +guard_block35: ; preds = %assign_optional33 + br label %voiderr38 + +noerr_block36: ; preds = %after_check34 + %25 = load i64, ptr %len16, align 8 + %add37 = add i64 %25, 1 + br label %voiderr38 + +voiderr38: ; preds = %noerr_block36, %guard_block35, %guard_block29, %guard_block23 + %26 = call ptr @std.io.stdout() + %27 = call i64 @std.io.File.write(ptr %retparam42, ptr %26, ptr @.str.4, i64 3) + %not_err43 = icmp eq i64 %27, 0 + %28 = call i1 @llvm.expect.i1(i1 %not_err43, i1 true) + br i1 %28, label %after_check45, label %assign_optional44 + +assign_optional44: ; preds = %voiderr38 + store i64 %27, ptr %error_var40, align 8 + br label %guard_block46 + +after_check45: ; preds = %voiderr38 + br label %noerr_block47 + +guard_block46: ; preds = %assign_optional44 + br label %voiderr61 + +noerr_block47: ; preds = %after_check45 + %29 = load i64, ptr %retparam42, align 8 + store i64 %29, ptr %len39, align 8 + %30 = call i64 @std.io.File.write_byte(ptr %26, i8 zeroext 10) + %not_err49 = icmp eq i64 %30, 0 + %31 = call i1 @llvm.expect.i1(i1 %not_err49, i1 true) + br i1 %31, label %after_check51, label %assign_optional50 + +assign_optional50: ; preds = %noerr_block47 + store i64 %30, ptr %error_var48, align 8 + br label %guard_block52 + +after_check51: ; preds = %noerr_block47 + br label %noerr_block53 + +guard_block52: ; preds = %assign_optional50 + br label %voiderr61 + +noerr_block53: ; preds = %after_check51 + %32 = call i64 @std.io.File.flush(ptr %26) + %not_err55 = icmp eq i64 %32, 0 + %33 = call i1 @llvm.expect.i1(i1 %not_err55, i1 true) + br i1 %33, label %after_check57, label %assign_optional56 + +assign_optional56: ; preds = %noerr_block53 + store i64 %32, ptr %error_var54, align 8 + br label %guard_block58 + +after_check57: ; preds = %noerr_block53 + br label %noerr_block59 + +guard_block58: ; preds = %assign_optional56 + br label %voiderr61 + +noerr_block59: ; preds = %after_check57 + %34 = load i64, ptr %len39, align 8 + %add60 = add i64 %34, 1 + br label %voiderr61 + +voiderr61: ; preds = %noerr_block59, %guard_block58, %guard_block52, %guard_block46 + %35 = call ptr @std.io.stdout() + %36 = call i64 @std.io.File.write(ptr %retparam65, ptr %35, ptr @.str.5, i64 1) + %not_err66 = icmp eq i64 %36, 0 + %37 = call i1 @llvm.expect.i1(i1 %not_err66, i1 true) + br i1 %37, label %after_check68, label %assign_optional67 + +assign_optional67: ; preds = %voiderr61 + store i64 %36, ptr %error_var63, align 8 + br label %guard_block69 + +after_check68: ; preds = %voiderr61 + br label %noerr_block70 + +guard_block69: ; preds = %assign_optional67 + br label %voiderr84 + +noerr_block70: ; preds = %after_check68 + %38 = load i64, ptr %retparam65, align 8 + store i64 %38, ptr %len62, align 8 + %39 = call i64 @std.io.File.write_byte(ptr %35, i8 zeroext 10) + %not_err72 = icmp eq i64 %39, 0 + %40 = call i1 @llvm.expect.i1(i1 %not_err72, i1 true) + br i1 %40, label %after_check74, label %assign_optional73 + +assign_optional73: ; preds = %noerr_block70 + store i64 %39, ptr %error_var71, align 8 + br label %guard_block75 + +after_check74: ; preds = %noerr_block70 + br label %noerr_block76 + +guard_block75: ; preds = %assign_optional73 + br label %voiderr84 + +noerr_block76: ; preds = %after_check74 + %41 = call i64 @std.io.File.flush(ptr %35) + %not_err78 = icmp eq i64 %41, 0 + %42 = call i1 @llvm.expect.i1(i1 %not_err78, i1 true) + br i1 %42, label %after_check80, label %assign_optional79 + +assign_optional79: ; preds = %noerr_block76 + store i64 %41, ptr %error_var77, align 8 + br label %guard_block81 + +after_check80: ; preds = %noerr_block76 + br label %noerr_block82 + +guard_block81: ; preds = %assign_optional79 + br label %voiderr84 + +noerr_block82: ; preds = %after_check80 + %43 = load i64, ptr %len62, align 8 + %add83 = add i64 %43, 1 + br label %voiderr84 + +voiderr84: ; preds = %noerr_block82, %guard_block81, %guard_block75, %guard_block69 + %44 = call ptr @std.io.stdout() + %45 = call i64 @std.io.File.write(ptr %retparam88, ptr %44, ptr @.str.6, i64 6) + %not_err89 = icmp eq i64 %45, 0 + %46 = call i1 @llvm.expect.i1(i1 %not_err89, i1 true) + br i1 %46, label %after_check91, label %assign_optional90 + +assign_optional90: ; preds = %voiderr84 + store i64 %45, ptr %error_var86, align 8 + br label %guard_block92 + +after_check91: ; preds = %voiderr84 + br label %noerr_block93 + +guard_block92: ; preds = %assign_optional90 + br label %voiderr107 + +noerr_block93: ; preds = %after_check91 + %47 = load i64, ptr %retparam88, align 8 + store i64 %47, ptr %len85, align 8 + %48 = call i64 @std.io.File.write_byte(ptr %44, i8 zeroext 10) + %not_err95 = icmp eq i64 %48, 0 + %49 = call i1 @llvm.expect.i1(i1 %not_err95, i1 true) + br i1 %49, label %after_check97, label %assign_optional96 + +assign_optional96: ; preds = %noerr_block93 + store i64 %48, ptr %error_var94, align 8 + br label %guard_block98 + +after_check97: ; preds = %noerr_block93 + br label %noerr_block99 + +guard_block98: ; preds = %assign_optional96 + br label %voiderr107 + +noerr_block99: ; preds = %after_check97 + %50 = call i64 @std.io.File.flush(ptr %44) + %not_err101 = icmp eq i64 %50, 0 + %51 = call i1 @llvm.expect.i1(i1 %not_err101, i1 true) + br i1 %51, label %after_check103, label %assign_optional102 + +assign_optional102: ; preds = %noerr_block99 + store i64 %50, ptr %error_var100, align 8 + br label %guard_block104 + +after_check103: ; preds = %noerr_block99 + br label %noerr_block105 + +guard_block104: ; preds = %assign_optional102 + br label %voiderr107 + +noerr_block105: ; preds = %after_check103 + %52 = load i64, ptr %len85, align 8 + %add106 = add i64 %52, 1 + br label %voiderr107 + +voiderr107: ; preds = %noerr_block105, %guard_block104, %guard_block98, %guard_block92 + ret void +} diff --git a/test/test_suite7/compile_time_introspection/parentof.c3t b/test/test_suite7/compile_time_introspection/parentof.c3t new file mode 100644 index 000000000..659b6b266 --- /dev/null +++ b/test/test_suite7/compile_time_introspection/parentof.c3t @@ -0,0 +1,50 @@ +// #target: macos-x64 +module foo; +struct Foo +{ + int a; +} +struct Bar +{ + inline Foo f; +} +fn void main() +{ + assert(Foo.parentof == void.typeid); + assert(Bar.parentof == Foo.typeid); + typeid x = Foo.typeid; + assert(x.parentof == void.typeid); + x = Bar.typeid; + assert(x.parentof == Foo.typeid); +} + +/* #expect: foo.ll + +@"$ct.foo.Foo" = linkonce global %.introspect { i8 10, i64 0, ptr null, i64 4, i64 0, i64 1, [0 x i64] zeroinitializer }, align 8 +@"$ct.foo.Bar" = linkonce global %.introspect { i8 10, i64 ptrtoint (ptr @"$ct.foo.Foo" to i64), ptr null, i64 4, i64 0, i64 1, [0 x i64] zeroinitializer }, align 8 +@"$ct.void" = linkonce global %.introspect { i8 0, i64 0, ptr null, i64 1, i64 0, i64 0, [0 x i64] zeroinitializer }, align 8 + +; Function Attrs: +define void @foo.main() #0 { +entry: + %x = alloca i64, align 8 + store i64 ptrtoint (ptr @"$ct.foo.Foo" to i64), ptr %x, align 8 + %0 = load i64, ptr %x, align 8 + %"introspect*" = inttoptr i64 %0 to ptr + %ptradd = getelementptr inbounds i8, ptr %"introspect*", i64 8 + %typeid.parent = load i64, ptr %ptradd, align 8 + %1 = icmp eq i64 %typeid.parent, 0 + %2 = select i1 %1, i64 ptrtoint (ptr @"$ct.void" to i64), i64 %typeid.parent + %eq = icmp eq i64 %2, ptrtoint (ptr @"$ct.void" to i64) + call void @llvm.assume(i1 %eq) + store i64 ptrtoint (ptr @"$ct.foo.Bar" to i64), ptr %x, align 8 + %3 = load i64, ptr %x, align 8 + %"introspect*1" = inttoptr i64 %3 to ptr + %ptradd2 = getelementptr inbounds i8, ptr %"introspect*1", i64 8 + %typeid.parent3 = load i64, ptr %ptradd2, align 8 + %4 = icmp eq i64 %typeid.parent3, 0 + %5 = select i1 %4, i64 ptrtoint (ptr @"$ct.void" to i64), i64 %typeid.parent3 + %eq4 = icmp eq i64 %5, ptrtoint (ptr @"$ct.foo.Foo" to i64) + call void @llvm.assume(i1 %eq4) + ret void +} \ No newline at end of file diff --git a/test/test_suite7/compile_time_introspection/qnameof.c3t b/test/test_suite7/compile_time_introspection/qnameof.c3t new file mode 100644 index 000000000..cf63a6bbb --- /dev/null +++ b/test/test_suite7/compile_time_introspection/qnameof.c3t @@ -0,0 +1,60 @@ +// #target: macos-x64 +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", Blob.qnameof); + printf("Blob: %s\n", Blob.nameof); + 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", Blob**[3].nameof); +} + +/* #expect: qnametest.ll + +@"$ct.qnametest.Blob" = linkonce global %.introspect { i8 10, i64 0, ptr null, i64 8, i64 0, i64 2, [0 x i64] zeroinitializer }, 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_suite7/compile_time_introspection/recursive_tag.c3 b/test/test_suite7/compile_time_introspection/recursive_tag.c3 new file mode 100644 index 000000000..2189d74d3 --- /dev/null +++ b/test/test_suite7/compile_time_introspection/recursive_tag.c3 @@ -0,0 +1,13 @@ +enum Test @tag("test", Test.FOO) {FOO} // #error: Recursive definition of 'Test' + +def @Test(Foo val) = {}; + +enum Foo @tag("test", Foo.BAR) // #error: Recursive definition of 'Foo' +{ + BAR, + BAZ +} + +fn void main() @Test(BAR) +{ +} diff --git a/test/test_suite7/compile_time_introspection/sizeof.c3t b/test/test_suite7/compile_time_introspection/sizeof.c3t new file mode 100644 index 000000000..eaf721234 --- /dev/null +++ b/test/test_suite7/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_suite7/compile_time_introspection/sizeof_errors.c3 b/test/test_suite7/compile_time_introspection/sizeof_errors.c3 new file mode 100644 index 000000000..b07e18623 --- /dev/null +++ b/test/test_suite7/compile_time_introspection/sizeof_errors.c3 @@ -0,0 +1,66 @@ +module foo; +import bar; + +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: Only valid types may be resolved with $evaltype +} + +fn void k() +{ + int v = $evaltype("int").x.sizeof; // #error: 'x'. +} + +fn void l() +{ + int v = $sizeof(int[].len); // #error: 'len' +} + +fn void m() +{ + int v = $sizeof(int[4].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_suite7/compile_time_introspection/tag.c3t b/test/test_suite7/compile_time_introspection/tag.c3t new file mode 100644 index 000000000..7a0c592a1 --- /dev/null +++ b/test/test_suite7/compile_time_introspection/tag.c3t @@ -0,0 +1,34 @@ +// #target: macos-x64 +module test; +struct Foo @tag("foo", 3) +{ + int a @tag("foo", "hello"); +} +bitstruct Bar : int +{ + int a: 1..4 @tag("foo", "a"); +} +fn void main() +{ + $if Foo.has_tagof("foo"): + int a = Foo.tagof("foo"); + $endif; + String b = Foo.a.tagof("foo"); + String c = Bar.a.tagof("foo"); +} + +/* #expect: test.ll + + +@.str = private unnamed_addr constant [6 x i8] c"hello\00", align 1 +@.str.1 = private unnamed_addr constant [2 x i8] c"a\00", align 1 + +entry: + %a = alloca i32, align 4 + %b = alloca %"char[]", align 8 + %c = alloca %"char[]", align 8 + store i32 3, ptr %a, align 4 + store %"char[]" { ptr @.str, i64 5 }, ptr %b, align 8 + store %"char[]" { ptr @.str.1, i64 1 }, ptr %c, align 8 + ret void +} diff --git a/test/test_suite7/compile_time_introspection/tag_1343.c3t b/test/test_suite7/compile_time_introspection/tag_1343.c3t new file mode 100644 index 000000000..91e480f83 --- /dev/null +++ b/test/test_suite7/compile_time_introspection/tag_1343.c3t @@ -0,0 +1,17 @@ +struct Foo { int a; } +struct Bar { int a; } +fn void Bar.xyz(&self) @tag("footag", 123) {} +macro void Foo.tags(&self, other) +{ + // inner to remove pointer + var $Type = $typefrom($typeof(other).inner); + var $methodcount = $Type.methodsof.len; + $for (var $i = 0; $i < $methodcount; $i++) + var $MethodType1 = $typeof($Type.$eval($Type.methodsof[$i])); + var $MethodType = $typeof(&$Type.$eval($Type.methodsof[$i])); + $MethodType a; + $MethodType1 b; + var $hasfootag = $MethodType.has_tagof("footag"); + $endfor +} +fn void main() { Bar bar; Foo foo; foo.tags(&bar); } diff --git a/test/test_suite7/concurrency/atomic_load_store.c3t b/test/test_suite7/concurrency/atomic_load_store.c3t new file mode 100644 index 000000000..9ddfc40a2 --- /dev/null +++ b/test/test_suite7/concurrency/atomic_load_store.c3t @@ -0,0 +1,46 @@ +// #target: macos-x64 +module test; +import std::io; + +struct Ghh +{ + int a; + int b; + int c; +} +fn void main() +{ + int a = 111; + int x = @atomic_load(a); + int y = @atomic_load(a, RELAXED, true); + @atomic_store(a, 123 + x); + @atomic_store(a, 33 + y, RELAXED, true); + io::printfn("%d", a); +} + +/* #expect: test.ll + +define void @test.main() #0 { +entry: + %a = alloca i32, align 4 + %x = alloca i32, align 4 + %y = alloca i32, align 4 + %varargslots = alloca [1 x %any], align 16 + %retparam = alloca i64, align 8 + store i32 111, ptr %a, align 4 + %0 = load atomic i32, ptr %a seq_cst, align 4 + store i32 %0, ptr %x, align 4 + %1 = load atomic volatile i32, ptr %a monotonic, align 4 + store i32 %1, ptr %y, align 4 + %2 = load i32, ptr %x, align 4 + %add = add i32 123, %2 + store atomic i32 %add, ptr %a seq_cst, align 4 + %3 = load i32, ptr %y, align 4 + %add1 = add i32 33, %3 + store atomic volatile i32 %add1, ptr %a monotonic, align 4 + %4 = insertvalue %any undef, ptr %a, 0 + %5 = insertvalue %any %4, i64 ptrtoint (ptr @"$ct.int" to i64), 1 + store %any %5, ptr %varargslots, align 16 + %6 = call i64 @std.io.printfn(ptr %retparam, ptr @.str, i64 2, ptr %varargslots, i64 1) + ret void +} diff --git a/test/test_suite7/concurrency/atomic_load_store_debug.c3t b/test/test_suite7/concurrency/atomic_load_store_debug.c3t new file mode 100644 index 000000000..8fd02ddb9 --- /dev/null +++ b/test/test_suite7/concurrency/atomic_load_store_debug.c3t @@ -0,0 +1,135 @@ +// #target: macos-x64 +// #debuginfo: yes +module test; +import std::io; + +struct Ghh +{ + int a; + int b; + int c; +} +fn void main() +{ + int a = 111; + int x = @atomic_load(a); + int y = @atomic_load(a, RELAXED, true); + @atomic_store(a, 123 + x); + @atomic_store(a, 33 + y, RELAXED, true); + io::printfn("%d", a); +} + +/* #expect: test.ll +%.introspect = type { i8, i64, ptr, i64, i64, i64, [0 x i64] } +%any = type { ptr, i64 } + +@"$ct.test.Ghh" = linkonce global %.introspect { i8 10, i64 0, ptr null, i64 12, i64 0, i64 3, [0 x i64] zeroinitializer }, align 8 +@.str = private unnamed_addr constant [3 x i8] c"%d\00", align 1 +@"$ct.int" = linkonce global %.introspect { i8 2, i64 0, ptr null, i64 4, i64 0, i64 0, [0 x i64] zeroinitializer }, align 8 + +define void @test.main() #0 !dbg !8 { +entry: + %a = alloca i32, align 4 + %x = alloca i32, align 4 + %y = alloca i32, align 4 + %value = alloca i32, align 4 + %value2 = alloca i32, align 4 + %varargslots = alloca [1 x %any], align 16 + %retparam = alloca i64, align 8 + store i32 111, ptr %a, align 4, !dbg !15 + %0 = load atomic i32, ptr %a seq_cst, align 4, !dbg !18 + store i32 %0, ptr %x, align 4, !dbg !18 + %1 = load atomic volatile i32, ptr %a monotonic, align 4, !dbg !24 + store i32 %1, ptr %y, align 4, !dbg !24 + %2 = load i32, ptr %x, align 4, !dbg !27 + %add = add i32 123, %2, !dbg !28 + store i32 %add, ptr %value, align 4 + %3 = load i32, ptr %value, align 4, !dbg !29 + store atomic i32 %3, ptr %a seq_cst, align 4, !dbg !29 + %4 = load i32, ptr %y, align 4, !dbg !32 + %add1 = add i32 33, %4, !dbg !33 + store i32 %add1, ptr %value2, align 4 + %5 = load i32, ptr %value2, align 4, !dbg !34 + store atomic volatile i32 %5, ptr %a monotonic, align 4, !dbg !34 + %6 = insertvalue %any undef, ptr %a, 0, !dbg !37 + %7 = insertvalue %any %6, i64 ptrtoint (ptr @"$ct.int" to i64), 1, !dbg !37 + store %any %7, ptr %varargslots, align 16, !dbg !37 + %8 = call i64 @std.io.printfn(ptr %retparam, ptr @.str, i64 2, ptr %varargslots, i64 1), !dbg !38 + ret void, !dbg !38 +} + +define i32 @main(i32 %0, ptr %1) #0 !dbg !39 { +entry: + %.anon = alloca i32, align 4 + %.anon1 = alloca ptr, align 8 + %.anon2 = alloca i32, align 4 + %.anon3 = alloca ptr, align 8 + store i32 %0, ptr %.anon, align 4 + store ptr %1, ptr %.anon1, align 8 + %2 = load i32, ptr %.anon, align 4 + store i32 %2, ptr %.anon2, align 4 + %3 = load ptr, ptr %.anon1, align 8 + store ptr %3, ptr %.anon3, align 8 + call void @test.main(), !dbg !48 + ret i32 0, !dbg !51 +} + +declare extern_weak i64 @std.io.printfn(ptr, ptr, i64, ptr, i64) #0 + +declare i1 @llvm.expect.i1(i1, i1) + +!llvm.module.flags = !{!0, !1, !2, !3, !4, !5} +!llvm.dbg.cu = !{!6} + +!0 = !{i32 2, !"Dwarf Version", i32 4} +!1 = !{i32 2, !"Debug Info Version", i32 3} +!2 = !{i32 2, !"wchar_size", i32 4} +!3 = !{i32 4, !"PIC Level", i32 2} +!4 = !{i32 1, !"uwtable", i32 2} +!5 = !{i32 2, !"frame-pointer", i32 2} +!6 = distinct !DICompileUnit(language: DW_LANG_C11, file: !7, producer: "c3c", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, splitDebugInlining: false) +!7 = !DIFile(filename: "atomic_load_store_debug.c3" +!8 = distinct !DISubprogram(name: "main", linkageName: "test.main", scope: !7, file: !7, line: 10, type: !9, scopeLine: 10, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !6, retainedNodes: !11) +!9 = !DISubroutineType(types: !10) +!10 = !{null} +!11 = !{} +!12 = !DILocalVariable(name: "a", scope: !8, file: !7, line: 12, type: !13, align: 4) +!13 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) +!14 = !DILocation(line: 12, column: 6, scope: !8) +!15 = !DILocation(line: 12, column: 10, scope: !8) +!16 = !DILocalVariable(name: "x", scope: !8, file: !7, line: 13, type: !13, align: 4) +!17 = !DILocation(line: 13, column: 6, scope: !8) +!18 = !DILocation( +!19 = distinct !DISubprogram(name: "@atomic_load", +!20 = !DIFile(filename: "mem.c3", +!21 = !DILocation(line: 13, column: 10, scope: !8) +!22 = !DILocalVariable(name: "y", scope: !8, file: !7, line: 14, type: !13, align: 4) +!23 = !DILocation(line: 14, column: 6, scope: !8) +!24 = !DILocation( +!25 = distinct !DISubprogram(name: "@atomic_load", linkageName: "@atomic_load", scope: !20, file: !20 +!26 = !DILocation(line: 14, column: 10, scope: !8) +!27 = !DILocation(line: 15, column: 25, scope: !8) +!28 = !DILocation(line: 15, column: 19, scope: !8) +!29 = !DILocation( +!30 = distinct !DISubprogram(name: "@atomic_store", linkageName: "@atomic_store", scope: !20, file: !20 +!31 = !DILocation(line: 15, column: 2, scope: !8) +!32 = !DILocation(line: 16, column: 24, scope: !8) +!33 = !DILocation(line: 16, column: 19, scope: !8) +!34 = !DILocation( +!35 = distinct !DISubprogram(name: "@atomic_store", linkageName: "@atomic_store", scope: !20, file: !20 +!36 = !DILocation(line: 16, column: 2, scope: !8) +!37 = !DILocation(line: 17, column: 20, scope: !8) +!38 = !DILocation(line: 17, column: 2, scope: !8) +!39 = distinct !DISubprogram(name: "_$main", linkageName: "main", scope: !7, file: !7, line: 10, type: !40, scopeLine: 10, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !6, retainedNodes: !11) +!40 = !DISubroutineType(types: !41) +!41 = !{!13, !13, !42} +!42 = !DIDerivedType(tag: DW_TAG_pointer_type, name: "char**", baseType: !43, size: 64, align: 64, dwarfAddressSpace: 0) +!43 = !DIDerivedType(tag: DW_TAG_pointer_type, name: "char*", baseType: !44, size: 64, align: 64, dwarfAddressSpace: 0) +!44 = !DIBasicType(name: "char", size: 8, encoding: DW_ATE_unsigned_char) +!45 = !DILocalVariable(name: ".anon", arg: 1, scope: !39, file: !7, line: 10, type: !13) +!46 = !DILocation(line: 10, column: 9, scope: !39) +!47 = !DILocalVariable(name: ".anon", arg: 2, scope: !39, file: !7, line: 10, type: !42) +!48 = !DILocation( +!49 = distinct !DISubprogram(name: "@main_to_void_main", linkageName: "@main_to_void_main", scope: !50, file: !50, line: 16, scopeLine: 16, spFlags: DISPFlagLocalToUnit | DISPFlagDefinition, unit: !6) +!50 = !DIFile(filename: "main_stub.c3", directory: +!51 = !DILocation( diff --git a/test/test_suite7/constants/assign_to_const.c3 b/test/test_suite7/constants/assign_to_const.c3 new file mode 100644 index 000000000..a5ee70633 --- /dev/null +++ b/test/test_suite7/constants/assign_to_const.c3 @@ -0,0 +1,8 @@ +module test; +import std::io; + +fn void main() +{ + const NUM = 4; + NUM += 1; // #error: You cannot assign to a constant +} \ No newline at end of file diff --git a/test/test_suite7/constants/byte_literal_fail_base64.c3 b/test/test_suite7/constants/byte_literal_fail_base64.c3 new file mode 100644 index 000000000..01ddc731f --- /dev/null +++ b/test/test_suite7/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_suite7/constants/byte_literal_fail_base64_2.c3 b/test/test_suite7/constants/byte_literal_fail_base64_2.c3 new file mode 100644 index 000000000..862f66448 --- /dev/null +++ b/test/test_suite7/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_suite7/constants/byte_literal_fail_base64_4.c3 b/test/test_suite7/constants/byte_literal_fail_base64_4.c3 new file mode 100644 index 000000000..2295dab35 --- /dev/null +++ b/test/test_suite7/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_suite7/constants/byte_literal_fail_hex.c3 b/test/test_suite7/constants/byte_literal_fail_hex.c3 new file mode 100644 index 000000000..c2312828a --- /dev/null +++ b/test/test_suite7/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_suite7/constants/byte_literals.c3t b/test/test_suite7/constants/byte_literals.c3t new file mode 100644 index 000000000..30b8943df --- /dev/null +++ b/test/test_suite7/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_suite7/constants/char_literals.c3t b/test/test_suite7/constants/char_literals.c3t new file mode 100644 index 000000000..d30028121 --- /dev/null +++ b/test/test_suite7/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_suite7/constants/const_var_copy.c3t b/test/test_suite7/constants/const_var_copy.c3t new file mode 100644 index 000000000..f5a1305b9 --- /dev/null +++ b/test/test_suite7/constants/const_var_copy.c3t @@ -0,0 +1,30 @@ +// #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 + +; Function Attrs: +define void @foo.test(i32 %0) #0 { +entry: + %s = alloca i8, align 1 + %zd = alloca i32, align 4 + %sext = sext i32 %0 to i64 + %ptradd = getelementptr inbounds i8, ptr @foo.FOO, i64 %sext + %1 = load i8, ptr %ptradd, align 1 + store i8 %1, ptr %s, align 1 + %sext1 = sext i32 %0 to i64 + %2 = extractelement <4 x i32> , i64 %sext1 + store i32 %2, ptr %zd, align 4 + ret void +} diff --git a/test/test_suite7/constants/constant_struct.c3 b/test/test_suite7/constants/constant_struct.c3 new file mode 100644 index 000000000..2bb0f1190 --- /dev/null +++ b/test/test_suite7/constants/constant_struct.c3 @@ -0,0 +1,18 @@ +import std::io; + +struct Abc +{ + int a; +} + +struct Bcd +{ + Abc x; +} + +const Abc FOO = { 2 }; + +fn void main() +{ + Bcd a = { FOO }; +} diff --git a/test/test_suite7/constants/constants.c3t b/test/test_suite7/constants/constants.c3t new file mode 100644 index 000000000..9afeb8c99 --- /dev/null +++ b/test/test_suite7/constants/constants.c3t @@ -0,0 +1,40 @@ +const char AA @private = (char)~(char)(0); +const char BB = 200 ; +const uint CC @private = ~(uint)(0); +const uint DD @private = FOO; + +const FOO @private = ~(uint)(0); + +uint x @private = AA; +uint z @private = CC; +char w @private = (char)(FOO); +ushort v @private = (ushort)(FOO); +uint z2 @private = DD; + +fn void test() +{ + int xx = (int)FOO; + uint* yy = &&FOO; +} + +/* #expect: constants.ll + +@constants.AA = internal unnamed_addr constant i8 -1, align 1 +@constants.BB = local_unnamed_addr constant i8 -56, align 1 +@constants.CC = internal unnamed_addr constant i32 -1, align 4 +@constants.DD = internal unnamed_addr constant i32 -1, align 4 +@constants.FOO = internal unnamed_addr constant i32 -1, align 4 +@constants.x = internal unnamed_addr global i32 255, align 4 +@constants.z = internal unnamed_addr global i32 -1, align 4 +@constants.w = internal unnamed_addr global i8 -1, align 1 +@constants.v = internal unnamed_addr global i16 -1, align 2 +@constants.z2 = internal 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_suite7/constants/empty_byte_literal.c3 b/test/test_suite7/constants/empty_byte_literal.c3 new file mode 100644 index 000000000..6e558ec45 --- /dev/null +++ b/test/test_suite7/constants/empty_byte_literal.c3 @@ -0,0 +1,8 @@ +import std; + +fn void main() +{ + char[] cd = {}; + char[?] b = x""; // #error: must be at least 1 byte + io::printfn("%d", b.len); +} \ No newline at end of file diff --git a/test/test_suite7/constants/float_type.c3t b/test/test_suite7/constants/float_type.c3t new file mode 100644 index 000000000..262fd0652 --- /dev/null +++ b/test/test_suite7/constants/float_type.c3t @@ -0,0 +1,11 @@ +// #target: macos-x64 +module test; +uint f0 = $typeof(1.0f).sizeof; +uint f32 = $typeof(1.0f32).sizeof; +uint f64 = $typeof(1.0f64).sizeof; + +/* #expect: test.ll + +@test.f0 = local_unnamed_addr global i32 4, align 4 +@test.f32 = local_unnamed_addr global i32 4, align 4 +@test.f64 = local_unnamed_addr global i32 8, align 4 \ No newline at end of file diff --git a/test/test_suite7/constants/init_order.c3t b/test/test_suite7/constants/init_order.c3t new file mode 100644 index 000000000..c8890c104 --- /dev/null +++ b/test/test_suite7/constants/init_order.c3t @@ -0,0 +1,23 @@ +// #target: macos-x64 +module test; + +macro foo() +{ + $if $defined(A): + return A + 1; + $else + return 1; + $endif +} + +const Z = foo(); + +const A @if(!$defined(A) && Z == 1) = 222; + +const B = foo(); + +/* #expect: test.ll + +@test.Z = local_unnamed_addr constant i32 1, align 4 +@test.B = local_unnamed_addr constant i32 223, align 4 +@test.A = local_unnamed_addr constant i32 222, align 4 \ No newline at end of file diff --git a/test/test_suite7/contracts/constant_out.c3 b/test/test_suite7/contracts/constant_out.c3 new file mode 100644 index 000000000..43958ae35 --- /dev/null +++ b/test/test_suite7/contracts/constant_out.c3 @@ -0,0 +1,36 @@ +module test; + + +struct Abc +{ + int a; +} + +fn void Abc.update(Abc* a, int ab) +{ + a.a = ab; +} + +<* + @param [out] a +*> +fn void Abc.update_fail(Abc* a, int ab) +{ + a.a = ab; +} + +const Abc X = { 2 }; + + +fn int main() +{ + const Abc Y = { 3 }; + int* z = &X.a; + *z = 31; + X.update(1); + X.update_fail(2); // #error: const parameter may not + X.a = 32; // #error: cannot assign to a constant + Y.a = 34; // #error: cannot assign to a constant + return 0; +} + diff --git a/test/test_suite7/contracts/ct_eval_of_ensure.c3 b/test/test_suite7/contracts/ct_eval_of_ensure.c3 new file mode 100644 index 000000000..7ff1956ec --- /dev/null +++ b/test/test_suite7/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(String[] args) +{ + test(1022); + printf("Hello\n"); +} + diff --git a/test/test_suite7/contracts/ensure_unsigned.c3 b/test/test_suite7/contracts/ensure_unsigned.c3 new file mode 100644 index 000000000..206524e7b --- /dev/null +++ b/test/test_suite7/contracts/ensure_unsigned.c3 @@ -0,0 +1,10 @@ + +// Check that 0 <= buf is ok. +<* + @ensure return <= buf.len + *> +fn usz foo(char[] buf) { + if (buf.len == 0) return 0; + // ... return some index into buf + return buf.len; +} \ No newline at end of file diff --git a/test/test_suite7/contracts/in_array.c3 b/test/test_suite7/contracts/in_array.c3 new file mode 100644 index 000000000..4ee8c9929 --- /dev/null +++ b/test/test_suite7/contracts/in_array.c3 @@ -0,0 +1,12 @@ +<* + @param [in] x +*> +fn void test(int* x) +{ + x[1] = 123; // #error: 'in' parameters may not be assigned to +} +fn int main() +{ + test(&&int[3]{ 1, 2, 1 }); + return 0; +} \ No newline at end of file diff --git a/test/test_suite7/contracts/in_out.c3 b/test/test_suite7/contracts/in_out.c3 new file mode 100644 index 000000000..03f81503d --- /dev/null +++ b/test/test_suite7/contracts/in_out.c3 @@ -0,0 +1,23 @@ +struct Foo { int x; } +<* @param [out] f *> +fn void bar(Foo* f) +{ + f.x = 123; +} + +<* @param [in] f *> +fn void foo(Foo* f) +{ + bar(f); // #error: An 'in' parameter may not be passed i +} + +<* @param [in] f *> +fn void foo2(Foo* f) +{ +} + +<* @param [out] f *> +fn void baz(Foo *f) +{ + foo2(f); // #error: may not be passed into a function +} \ No newline at end of file diff --git a/test/test_suite7/contracts/inout_in.c3 b/test/test_suite7/contracts/inout_in.c3 new file mode 100644 index 000000000..36ba05aa2 --- /dev/null +++ b/test/test_suite7/contracts/inout_in.c3 @@ -0,0 +1,21 @@ +<* + @param [in] foo +*> +fn void test(int* foo) +{ + test2(foo); // #error: An 'in' parameter may not be passed into +} + +<* + @param [out] foo +*> +fn void test3(int* foo) +{ + test2(foo); // #error: An 'out' parameter may not be passed into +} +<* + @param [inout] foo +*> +fn void test2(int* foo) +{ +} diff --git a/test/test_suite7/contracts/macro_ensure_static.c3 b/test/test_suite7/contracts/macro_ensure_static.c3 new file mode 100644 index 000000000..883f5bb36 --- /dev/null +++ b/test/test_suite7/contracts/macro_ensure_static.c3 @@ -0,0 +1,14 @@ +module debugstuff; + + +<* @ensure return > 0 *> +macro check(int a) +{ + if (a > 0) return 1; + if (a < 0) return -1; // #error: @ensure + return 100; +} +fn void main() +{ + check(43); +} \ No newline at end of file diff --git a/test/test_suite7/contracts/out_subscript.c3 b/test/test_suite7/contracts/out_subscript.c3 new file mode 100644 index 000000000..9d9e97cbc --- /dev/null +++ b/test/test_suite7/contracts/out_subscript.c3 @@ -0,0 +1,12 @@ +<* + @param [out] z + @param [out] out_data + *> +fn void tes2t(char* z, char[] out_data, char[] in_data) { + z[0] = 2; + z[0] += 1; // #error: 'out' parameters may not be read + out_data[0] = 3; + out_data[0] *= 1; // #error: 'out' parameters may not be read + out_data[0..3]; // #error: 'out' parameters may not be read + out_data[0..3] = 23; +} \ No newline at end of file diff --git a/test/test_suite7/contracts/pure.c3 b/test/test_suite7/contracts/pure.c3 new file mode 100644 index 000000000..6c3e8e662 --- /dev/null +++ b/test/test_suite7/contracts/pure.c3 @@ -0,0 +1,22 @@ +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_suite7/contracts/pure_calls.c3 b/test/test_suite7/contracts/pure_calls.c3 new file mode 100644 index 000000000..0430f4887 --- /dev/null +++ b/test/test_suite7/contracts/pure_calls.c3 @@ -0,0 +1,24 @@ +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_suite7/contracts/require_contract_loc.c3 b/test/test_suite7/contracts/require_contract_loc.c3 new file mode 100644 index 000000000..59283dde1 --- /dev/null +++ b/test/test_suite7/contracts/require_contract_loc.c3 @@ -0,0 +1,6 @@ +import std::io; +fn void main() +{ + int a; + bitorder::read(a, int); // #error: violated +} \ No newline at end of file diff --git a/test/test_suite7/contracts/simple_test.c3t b/test/test_suite7/contracts/simple_test.c3t new file mode 100644 index 000000000..88e3863b4 --- /dev/null +++ b/test/test_suite7/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 4 + 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 4 + %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_suite7/debug_symbols/constants.c3t b/test/test_suite7/debug_symbols/constants.c3t new file mode 100644 index 000000000..05bff4463 --- /dev/null +++ b/test/test_suite7/debug_symbols/constants.c3t @@ -0,0 +1,36 @@ +// #target: macos-x64 +// #debuginfo: yes +const char AA @private = 1; +const char BB = 200 ; +const uint CC @private = ~(uint)(0); +const FOO @private = ~(uint)(0); + +/* #expect: constants.ll + +@constants.AA = internal unnamed_addr constant i8 1, align 1, !dbg !0 +@constants.BB = local_unnamed_addr constant i8 -56, align 1, !dbg !4 +@constants.CC = internal unnamed_addr constant i32 -1, align 4, !dbg !6 +@constants.FOO = internal unnamed_addr constant i32 -1, align 4, !dbg !9 + +!llvm.module.flags = !{!11, !12, !13, !14, !15, !16} +!llvm.dbg.cu = !{!17} + +!0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression()) +!1 = distinct !DIGlobalVariable(name: "AA", linkageName: "constants.AA", scope: !2 +!2 = !DIFile(filename: "constants.c3", +!3 = !DIBasicType(name: "char", size: 8, encoding: DW_ATE_unsigned_char) +!4 = !DIGlobalVariableExpression(var: !5, expr: !DIExpression()) +!5 = distinct !DIGlobalVariable(name: "BB", linkageName: "constants.BB", scope: !2, file: !2, line: 2, type: !3, isLocal: false, isDefinition: true, align: 1) +!6 = !DIGlobalVariableExpression(var: !7, expr: !DIExpression()) +!7 = distinct !DIGlobalVariable(name: "CC", linkageName: "constants.CC", scope: !2, file: !2, line: 3, type: !8, isLocal: true, isDefinition: true, align: 4) +!8 = !DIBasicType(name: "uint", size: 32, encoding: DW_ATE_unsigned) +!9 = !DIGlobalVariableExpression(var: !10, expr: !DIExpression()) +!10 = distinct !DIGlobalVariable(name: "FOO", linkageName: "constants.FOO", scope: !2, file: !2, line: 4, type: !8, isLocal: true, isDefinition: true, align: 4) +!11 = !{i32 2, !"Dwarf Version", i32 4} +!12 = !{i32 2, !"Debug Info Version", i32 3} +!13 = !{i32 2, !"wchar_size", i32 4} +!14 = !{i32 4, !"PIC Level", i32 2} +!15 = !{i32 1, !"uwtable", i32 2} +!16 = !{i32 2, !"frame-pointer", i32 2} +!17 = distinct !DICompileUnit(language: DW_LANG_C11, file: !2, producer: "c3c", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, globals: !18, splitDebugInlining: false) +!18 = !{!0, !4, !6, !9} diff --git a/test/test_suite7/debug_symbols/constants_mingw.c3t b/test/test_suite7/debug_symbols/constants_mingw.c3t new file mode 100644 index 000000000..9c5fedc84 --- /dev/null +++ b/test/test_suite7/debug_symbols/constants_mingw.c3t @@ -0,0 +1,38 @@ +// #target: mingw-x64 +// #debuginfo: yes +const char AA @private = 1; +const char BB = 200 ; +const uint CC @private = ~(uint)(0); +const FOO @private = ~(uint)(0); + +/* #expect: constants_mingw.ll + +; ModuleID = 'constants_mingw' + +@constants_mingw.AA = internal unnamed_addr constant i8 1, align 1, !dbg !0 +@constants_mingw.BB = local_unnamed_addr constant i8 -56, align 1, !dbg !4 +@constants_mingw.CC = internal unnamed_addr constant i32 -1, align 4, !dbg !6 +@constants_mingw.FOO = internal unnamed_addr constant i32 -1, align 4, !dbg !9 + +!llvm.module.flags = !{!11, !12, !13, !14, !15, !16} +!llvm.dbg.cu = !{!17} + +!0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression()) +!1 = distinct !DIGlobalVariable(name: "AA", linkageName: "constants_mingw.AA", scope: !2, file: !2, line: 1, type: !3, isLocal: true, isDefinition: true, align: 1) +!2 = !DIFile(filename: "constants_mingw.c3", directory +!3 = !DIBasicType(name: "char", size: 8, encoding: DW_ATE_unsigned_char) +!4 = !DIGlobalVariableExpression(var: !5, expr: !DIExpression()) +!5 = distinct !DIGlobalVariable(name: "BB", linkageName: "constants_mingw.BB", scope: !2, file: !2, line: 2, type: !3, isLocal: false, isDefinition: true, align: 1) +!6 = !DIGlobalVariableExpression(var: !7, expr: !DIExpression()) +!7 = distinct !DIGlobalVariable(name: "CC", linkageName: "constants_mingw.CC", scope: !2, file: !2, line: 3, type: !8, isLocal: true, isDefinition: true, align: 4) +!8 = !DIBasicType(name: "uint", size: 32, encoding: DW_ATE_unsigned) +!9 = !DIGlobalVariableExpression(var: !10, expr: !DIExpression()) +!10 = distinct !DIGlobalVariable(name: "FOO", linkageName: "constants_mingw.FOO", scope: !2, file: !2, line: 4, type: !8, isLocal: true, isDefinition: true, align: 4) +!11 = !{i32 2, !"Dwarf Version", i32 4} +!12 = !{i32 2, !"Debug Info Version", i32 3} +!13 = !{i32 2, !"wchar_size", i32 4} +!14 = !{i32 4, !"PIC Level", i32 2} +!15 = !{i32 1, !"uwtable", i32 2} +!16 = !{i32 2, !"frame-pointer", i32 2} +!17 = distinct !DICompileUnit(language: DW_LANG_C11, file: !2, producer: "c3c", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, globals: !18, splitDebugInlining: false) +!18 = !{!0, !4, !6, !9} diff --git a/test/test_suite7/debug_symbols/ct_foreach.c3t b/test/test_suite7/debug_symbols/ct_foreach.c3t new file mode 100644 index 000000000..6e099306b --- /dev/null +++ b/test/test_suite7/debug_symbols/ct_foreach.c3t @@ -0,0 +1,55 @@ +// #target: macos-x64 +// #debuginfo: yes +module test; +struct Flags { bool flag1; } + +fn void foo() { + int[1] values; + $foreach ($i, $member : Flags.membersof) + values[$i] = $i; + $endforeach +} + +fn void main() { + foo(); +} + +/* #expect: test.ll + +define void @test.foo() #0 !dbg !8 { +entry: + %values = alloca [1 x i32], align 4 + store i32 0, ptr %values, align 4, !dbg !17 + store i32 0, ptr %values, align 4, !dbg !18 + ret void, !dbg !18 +} +!0 = !{i32 2, !"Dwarf Version", i32 4} +!1 = !{i32 2, !"Debug Info Version", i32 3} +!2 = !{i32 2, !"wchar_size", i32 4} +!3 = !{i32 4, !"PIC Level", i32 2} +!4 = !{i32 1, !"uwtable", i32 2} +!5 = !{i32 2, !"frame-pointer", i32 2} +!6 = distinct !DICompileUnit +!7 = !DIFile(filename: +!8 = distinct !DISubprogram(name: "foo", linkageName: "test.foo", scope: !7, file: !7, line: 4, type: !9, scopeLine: 4, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !6, retainedNodes: !11) +!9 = !DISubroutineType(types: !10) +!10 = !{null} +!11 = !{} +!12 = !DILocalVariable(name: "values", scope: !8 +!13 = !DICompositeType(tag: DW_TAG_array_type, baseType: !14, size: 32, align: 32, elements: !15) +!14 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) +!15 = !{!16} +!16 = !DISubrange(count: 1, lowerBound: 0) +!17 = !DILocation(line: 5, column: 10, scope: !8) +!18 = !DILocation(line: 7, column: 18, scope: !8) +!19 = distinct !DISubprogram(name: "main", linkageName: "test.main", scope: !7, file: !7, line: 11, type: !9, scopeLine: 11, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !6) +!20 = !DILocation(line: 12, column: 3, scope: !19) +!21 = distinct !DISubprogram(name: "_$main", linkageName: "main", scope: !7, file: !7, line: 11, type: !22, scopeLine: 11, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !6, retainedNodes: !11) +!22 = !DISubroutineType(types: !23) +!23 = !{!14, !14, !24} +!24 = !DIDerivedType(tag: DW_TAG_pointer_type, name: "char**", baseType: !25, size: 64, align: 64, dwarfAddressSpace: 0) +!25 = !DIDerivedType(tag: DW_TAG_pointer_type, name: "char*", baseType: !26, size: 64, align: 64, dwarfAddressSpace: 0) +!26 = !DIBasicType(name: "char", size: 8, encoding: DW_ATE_unsigned_char) +!27 = !DILocalVariable(name: ".anon", arg: 1, scope: !21, file: !7, line: 11, type: !14) +!28 = !DILocation(line: 11, column: 9, scope: !21) +!29 = !DILocalVariable(name: ".anon", arg: 2, scope: !21, file: !7, line: 11, type: !24) diff --git a/test/test_suite7/debug_symbols/defer_macro.c3t b/test/test_suite7/debug_symbols/defer_macro.c3t new file mode 100644 index 000000000..c39078338 --- /dev/null +++ b/test/test_suite7/debug_symbols/defer_macro.c3t @@ -0,0 +1,811 @@ +// #target: macos-x64 +// #debuginfo: yes +module test; +import foo; +import attach; +import std::io; + +fn void foo(int x) +{ + int! a = x; + while (try a) + { + a = 2; + } +} + +fn int main(String[] args) +{ + + // Case 1: Jump to create_foo + Foo* asdf = create_foo(attach::to_scope(), {.flag1 = true}); + + // Case 2: Ternary jump + test(args.len != 0 ? foo::BLACK : foo::WHITE); + + test2(); + return 0; +} + +struct Foo +{ + void* asdf; +} + + + +fn Foo* create_foo(Attach_Arg attach, Box_Flags flags, String name = {}) +{ + return mem::new(Foo); +} + +bitstruct Box_Flags : ulong +{ + bool flag1; +} + +fn Foo* test(Color color) +{ + io::printn(color); + return null; +} + +fn void* test2() +{ + // Case 3: Trailing macro body exit jump + @scratch(; Arena* scratch) + { + void* asdf; + return asdf; + }; +} + +module foo; +import std::io; + +enum ID_Type : char +{ + NONE, + UNIQUE, +} + +struct Id { + ulong value; + ID_Type type; +} + +macro Id make(type, value) +{ + return (Id){.type = type, .value = value}; +} + +macro Id unique() +{ + static char x; + return make(ID_Type.UNIQUE, (ulong)&x); +} + + +distinct Color = float[<4>]; + +const Color BLACK = {0, 0, 0, 1}; +const Color WHITE = {1, 1, 1, 1}; + +struct Arena @export +{ + usz cursor; +} + +struct Arena_Cursor @export +{ + Arena* arena; + usz cursor; +} + +fn void rewind(Arena* arena, usz pos) @export("arena_rewind") +{ + arena.cursor = pos; +} + +fn Arena_Cursor get_cursor(Arena* arena) @inline => (Arena_Cursor) {arena, arena.cursor}; +fn void restore_cursor(Arena_Cursor cursor) @inline => rewind(cursor.arena, cursor.cursor); + + +fn Arena_Cursor scratch_begin(Arena*[] conflicts) @export("arena_scratch_begin") +{ + static Arena scratch_arena; + Arena* arena = &scratch_arena; + return arena ? get_cursor(arena) : {}; +} + +fn void scratch_end(Arena_Cursor cursor) @inline @export("arena_scratch_end") => restore_cursor(cursor); + +macro void @scratch(Arena*... conflicts; @body(Arena* arena)) @builtin +{ + Arena_Cursor scratch = scratch_begin(conflicts); + defer scratch_end(scratch); + @body(scratch.arena); +} + +module attach; +enum Attach_Arg_Kind +{ + TOP, +} + +struct Attach_Arg +{ + Attach_Arg_Kind kind; + void* box; +} + +fn Attach_Arg to_scope() @inline +{ + return { TOP, null }; +} + +/* #expect: test.ll + +define void @test.foo(i32 %0) #0 !dbg !18 { +entry: + %x = alloca i32, align 4 + %a = alloca i32, align 4 + %a.f = alloca i64, align 8 + store i32 %0, ptr %x, align 4 + !23 + !25 + %1 = load i32, ptr %x, align 4, !dbg !26 + store i32 %1, ptr %a, align 4, !dbg !26 + store i64 0, ptr %a.f, align 8, !dbg !26 + br label %loop.cond, !dbg !27 + +loop.cond: ; preds = %loop.body, %entry + %load.err = load i64, ptr %a.f, align 8, !dbg !28 + %result = icmp eq i64 %load.err, 0, !dbg !28 + br i1 %result, label %loop.body, label %loop.exit, !dbg !28 + +loop.body: ; preds = %loop.cond + store i32 2, ptr %a, align 4, !dbg !30 + store i64 0, ptr %a.f, align 8, !dbg !30 + br label %loop.cond, !dbg !30 + +loop.exit: ; preds = %loop.cond + ret void, !dbg !30 +} + +; Function Attrs: nounwind uwtable +define i32 @test.main(ptr %0, i64 %1) #0 !dbg !32 { +entry: + %args = alloca %"char[][]", align 8 + %asdf = alloca ptr, align 8 + %result = alloca %Attach_Arg, align 8 + store ptr %0, ptr %args, align 8 + %ptradd = getelementptr inbounds i8, ptr %args, i64 8 + store i64 %1, ptr %ptradd, align 8 + !50 + !56 + %2 = call { i32, ptr } @attach.to_scope() + store { i32, ptr } %2, ptr %result, align 8 + %lo = load i32, ptr %result, align 8, !dbg !58 + %ptradd1 = getelementptr inbounds i8, ptr %result, i64 8, !dbg !58 + %hi = load ptr, ptr %ptradd1, align 8, !dbg !58 + %3 = call ptr @test.create_foo(i32 %lo, ptr %hi, i64 1, ptr null, i64 0), !dbg !60 + store ptr %3, ptr %asdf, align 8, !dbg !60 + %ptradd2 = getelementptr inbounds i8, ptr %args, i64 8, !dbg !61 + %4 = load i64, ptr %ptradd2, align 8, !dbg !61 + %neq = icmp ne i64 0, %4, !dbg !61 + %ternary = select i1 %neq, <4 x float> , <4 x float> + %5 = call ptr @test.test(<4 x float> %ternary), !dbg !63 + %6 = call ptr @test.test2(), !dbg !64 + ret i32 0, !dbg !65 +} + + +define ptr @test.create_foo(i32 %0, ptr %1, i64 %2, ptr %3, i64 %4) #0 !dbg !66 { +entry: + %attach = alloca %Attach_Arg, align 8 + %flags = alloca i64, align 8 + %name = alloca %"char[]", align 8 + store i32 %0, ptr %attach, align 8 + %ptradd = getelementptr inbounds i8, ptr %attach, i64 8 + store ptr %1, ptr %ptradd, align 8 + !70 + store i64 %2, ptr %flags, align 8 + !72 + store ptr %3, ptr %name, align 8 + %ptradd1 = getelementptr inbounds i8, ptr %name, i64 8 + store i64 %4, ptr %ptradd1, align 8 + !74 + %5 = call ptr @std.core.mem.calloc(i64 8) + ret ptr %5, !dbg !75 +} + +define ptr @test.test(<4 x float> %0) #0 !dbg !79 { +entry: + %color = alloca <4 x float>, align 16 + %x = alloca <4 x float>, align 16 + %out = alloca ptr, align 8 + %x1 = alloca <4 x float>, align 16 + %len = alloca i64, align 8 + %error_var = alloca i64, align 8 + %out2 = alloca ptr, align 8 + %x3 = alloca <4 x float>, align 16 + %varargslots = alloca [1 x %any], align 16 + %retparam = alloca i64, align 8 + %taddr = alloca %any, align 8 + %indirectarg = alloca %"any[]", align 8 + %error_var5 = alloca i64, align 8 + %error_var11 = alloca i64, align 8 + store <4 x float> %0, ptr %color, align 16 + !88 + %1 = load <4 x float>, ptr %color, align 16 + store <4 x float> %1, ptr %x, align 16 + %2 = call ptr @std.io.stdout(), !dbg !89 + store ptr %2, ptr %out, align 8 + %3 = load <4 x float>, ptr %x, align 16 + store <4 x float> %3, ptr %x1, align 16 + !95 + %4 = load ptr, ptr %out, align 8 + store ptr %4, ptr %out2, align 8 + %5 = load <4 x float>, ptr %x1, align 16 + store <4 x float> %5, ptr %x3, align 16 + %6 = load ptr, ptr %out2, align 8, !dbg !97 + %7 = insertvalue %any undef, ptr %6, 0, !dbg !97 + %8 = insertvalue %any %7, i64 ptrtoint (ptr @"$ct.std.io.File" to i64), 1, !dbg !97 + %9 = insertvalue %any undef, ptr %x3, 0, !dbg !100 + %10 = insertvalue %any %9, i64 ptrtoint (ptr @"$ct.foo.Color" to i64), 1, !dbg !100 + store %any %10, ptr %varargslots, align 16, !dbg !100 + %11 = insertvalue %"any[]" undef, ptr %varargslots, 0, !dbg !100 + %"$$temp" = insertvalue %"any[]" %11, i64 1, 1, !dbg !100 + store %any %8, ptr %taddr, align 8 + %lo = load i64, ptr %taddr, align 8 + %ptradd = getelementptr inbounds i8, ptr %taddr, i64 8 + %hi = load ptr, ptr %ptradd, align 8 + store %"any[]" %"$$temp", ptr %indirectarg, align 8 + %12 = call i64 @std.io.fprintf(ptr %retparam, i64 %lo, ptr %hi, ptr @.str, i64 2, ptr byval(%"any[]") align 8 %indirectarg), !dbg !101 + %not_err = icmp eq i64 %12, 0, !dbg !101 + %13 = call i1 @llvm.expect.i1(i1 %not_err, i1 true), !dbg !101 + br i1 %13, label %after_check, label %assign_optional, !dbg !101 + +assign_optional: ; preds = %entry + store i64 %12, ptr %error_var, align 8, !dbg !101 + br label %guard_block, !dbg !101 + +after_check: ; preds = %entry + br label %noerr_block, !dbg !101 + +guard_block: ; preds = %assign_optional + br label %voiderr, !dbg !101 + +noerr_block: ; preds = %after_check + %14 = load i64, ptr %retparam, align 8, !dbg !101 + store i64 %14, ptr %len, align 8, !dbg !101 + %15 = load ptr, ptr %out, align 8, !dbg !102 + %16 = call i64 @std.io.File.write_byte(ptr %15, i8 zeroext 10), !dbg !103 + %not_err6 = icmp eq i64 %16, 0, !dbg !103 + %17 = call i1 @llvm.expect.i1(i1 %not_err6, i1 true), !dbg !103 + br i1 %17, label %after_check8, label %assign_optional7, !dbg !103 + +assign_optional7: ; preds = %noerr_block + store i64 %16, ptr %error_var5, align 8, !dbg !103 + br label %guard_block9, !dbg !103 + +after_check8: ; preds = %noerr_block + br label %noerr_block10, !dbg !103 + +guard_block9: ; preds = %assign_optional7 + br label %voiderr, !dbg !103 + +noerr_block10: ; preds = %after_check8 + %18 = load ptr, ptr %out, align 8, !dbg !104 + %19 = call i64 @std.io.File.flush(ptr %18), !dbg !104 + %not_err12 = icmp eq i64 %19, 0, !dbg !104 + %20 = call i1 @llvm.expect.i1(i1 %not_err12, i1 true), !dbg !104 + br i1 %20, label %after_check14, label %assign_optional13, !dbg !104 + +assign_optional13: ; preds = %noerr_block10 + store i64 %19, ptr %error_var11, align 8, !dbg !104 + br label %guard_block15, !dbg !104 + +after_check14: ; preds = %noerr_block10 + br label %noerr_block16, !dbg !104 + +guard_block15: ; preds = %assign_optional13 + br label %voiderr, !dbg !104 + +noerr_block16: ; preds = %after_check14 + %21 = load i64, ptr %len, align 8, !dbg !105 + %add = add i64 %21, 1, !dbg !105 + br label %voiderr, !dbg !96 + +voiderr: ; preds = %noerr_block16, %guard_block15, %guard_block9, %guard_block + ret ptr null, !dbg !106 +} + +define ptr @test.test2() #0 !dbg !107 { +entry: + %conflicts = alloca %"Arena*[]", align 8 + %scratch = alloca %Arena_Cursor, align 8 + %result = alloca %Arena_Cursor, align 8 + %scratch1 = alloca ptr, align 8 + %asdf = alloca ptr, align 8 + store %"Arena*[]" zeroinitializer, ptr %conflicts, align 8 + !120 + %lo = load ptr, ptr %conflicts, align 8, !dbg !122 + %ptradd = getelementptr inbounds i8, ptr %conflicts, i64 8, !dbg !122 + %hi = load i64, ptr %ptradd, align 8, !dbg !122 + %0 = call { ptr, i64 } @arena_scratch_begin(ptr %lo, i64 %hi), !dbg !123 + store { ptr, i64 } %0, ptr %result, align 8 + call void @llvm.memcpy.p0.p0.i32(ptr align 8 %scratch, ptr align 8 %result, i32 16, i1 false) + !125 + %1 = load ptr, ptr %scratch, align 8, !dbg !126 + store ptr %1, ptr %scratch1, align 8, !dbg !126 + !130 + store ptr null, ptr %asdf, align 8, !dbg !130 + %2 = load ptr, ptr %asdf, align 8, !dbg !131 + %lo2 = load ptr, ptr %scratch, align 8, !dbg !132 + %ptradd3 = getelementptr inbounds i8, ptr %scratch, i64 8, !dbg !132 + %hi4 = load i64, ptr %ptradd3, align 8, !dbg !132 + call void @arena_scratch_end(ptr %lo2, i64 %hi4) + ret ptr %2, !dbg !134 +} + +define i32 @main(i32 %0, ptr %1) #0 !dbg !135 { +entry: + %.anon = alloca i32, align 4 + %.anon1 = alloca ptr, align 8 + %argc = alloca i32, align 4 + %argv = alloca ptr, align 8 + %blockret = alloca i32, align 4 + %list = alloca %"char[][]", align 8 + %argc2 = alloca i32, align 4 + %argv3 = alloca ptr, align 8 + %list5 = alloca %"char[][]", align 8 + %elements = alloca i64, align 8 + %allocator = alloca %any, align 8 + %elements6 = alloca i64, align 8 + %error_var = alloca i64, align 8 + %allocator7 = alloca %any, align 8 + %elements8 = alloca i64, align 8 + %allocator10 = alloca %any, align 8 + %size = alloca i64, align 8 + %blockret11 = alloca ptr, align 8 + %.inlinecache = alloca ptr, align 8 + %.cachedtype = alloca ptr, align 8 + %retparam = alloca ptr, align 8 + %taddr = alloca ptr, align 8 + %varargslots = alloca [1 x %any], align 16 + %indirectarg = alloca %"any[]", align 8 + %i = alloca i32, align 4 + %arg = alloca ptr, align 8 + %len = alloca i64, align 8 + %ptr = alloca ptr, align 8 + %len18 = alloca i64, align 8 + store ptr null, ptr %.cachedtype, align 8 + store i32 %0, ptr %.anon, align 4 + !140 + store ptr %1, ptr %.anon1, align 8 + !140 + %2 = load i32, ptr %.anon, align 4 + store i32 %2, ptr %argc, align 4 + %3 = load ptr, ptr %.anon1, align 8 + store ptr %3, ptr %argv, align 8 + !145 + %4 = load i32, ptr %argc, align 4 + store i32 %4, ptr %argc2, align 4 + %5 = load ptr, ptr %argv, align 8 + store ptr %5, ptr %argv3, align 8 + !148 + %6 = load i32, ptr %argc2, align 4, !dbg !150 + %sext = sext i32 %6 to i64, !dbg !150 + store i64 %sext, ptr %elements, align 8 + call void @llvm.memcpy.p0.p0.i32(ptr align 8 %allocator, ptr align 8 @std.core.mem.allocator.thread_allocator, i32 16, i1 false) + %7 = load i64, ptr %elements, align 8 + store i64 %7, ptr %elements6, align 8 + call void @llvm.memcpy.p0.p0.i32(ptr align 8 %allocator7, ptr align 8 %allocator, i32 16, i1 false) + %8 = load i64, ptr %elements6, align 8 + store i64 %8, ptr %elements8, align 8 + call void @llvm.memcpy.p0.p0.i32(ptr align 8 %allocator10, ptr align 8 %allocator7, i32 16, i1 false) + %9 = load i64, ptr %elements8, align 8, !dbg !151 + %mul = mul i64 16, %9, !dbg !159 + store i64 %mul, ptr %size, align 8 + %10 = load i64, ptr %size, align 8, !dbg !160 + %i2nb = icmp eq i64 %10, 0, !dbg !160 + br i1 %i2nb, label %if.then, label %if.exit, !dbg !160 + +if.then: ; preds = %entry + store ptr null, ptr %blockret11, align 8, !dbg !163 + br label %expr_block.exit, !dbg !163 + +if.exit: ; preds = %entry + %ptradd = getelementptr inbounds i8, ptr %allocator10, i64 8, !dbg !164 + %11 = load i64, ptr %ptradd, align 8, !dbg !164 + %12 = inttoptr i64 %11 to ptr, !dbg !164 + %type = load ptr, ptr %.cachedtype, align 8 + %13 = icmp eq ptr %12, %type + br i1 %13, label %cache_hit, label %cache_miss + +cache_miss: ; preds = %if.exit + %ptradd12 = getelementptr inbounds i8, ptr %12, i64 16 + %14 = load ptr, ptr %ptradd12, align 8 + %15 = call ptr @.dyn_search(ptr %14, ptr @"$sel.acquire") + store ptr %15, ptr %.inlinecache, align 8 + store ptr %12, ptr %.cachedtype, align 8 + br label %16 + +cache_hit: ; preds = %if.exit + %cache_hit_fn = load ptr, ptr %.inlinecache, align 8 + br label %16 + +16: ; preds = %cache_hit, %cache_miss + %fn_phi = phi ptr [ %cache_hit_fn, %cache_hit ], [ %15, %cache_miss ] + %17 = icmp eq ptr %fn_phi, null + br i1 %17, label %missing_function, label %match + +missing_function: ; preds = %16 + %18 = load ptr, ptr @std.core.builtin.panic, align 8, !dbg !166 + call void %18(ptr @.panic_msg, i64 44, ptr @.file, i64 16, ptr @.func, i64 6, i32 68) + unreachable, !dbg !166 + +match: ; preds = %16 + %19 = load ptr, ptr %allocator10, align 8 + %20 = load i64, ptr %size, align 8 + %21 = call i64 %fn_phi(ptr %retparam, ptr %19, i64 %20, i32 0, i64 0), !dbg !166 + %not_err = icmp eq i64 %21, 0, !dbg !166 + %22 = call i1 @llvm.expect.i1(i1 %not_err, i1 true), !dbg !166 + br i1 %22, label %after_check, label %assign_optional, !dbg !166 + +assign_optional: ; preds = %match + store i64 %21, ptr %error_var, align 8, !dbg !166 + br label %panic_block, !dbg !166 + +after_check: ; preds = %match + %23 = load ptr, ptr %retparam, align 8, !dbg !166 + store ptr %23, ptr %blockret11, align 8, !dbg !166 + br label %expr_block.exit, !dbg !166 + +expr_block.exit: ; preds = %after_check, %if.then + %24 = load ptr, ptr %blockret11, align 8, !dbg !166 + store ptr %24, ptr %taddr, align 8 + %25 = load ptr, ptr %taddr, align 8 + %26 = load i64, ptr %elements8, align 8, !dbg !167 + %add = add i64 0, %26, !dbg !167 + %size13 = sub i64 %add, 0, !dbg !167 + %27 = insertvalue %"char[][]" undef, ptr %25, 0, !dbg !167 + %28 = insertvalue %"char[][]" %27, i64 %size13, 1, !dbg !167 + br label %noerr_block, !dbg !167 + +panic_block: ; preds = %assign_optional + %29 = insertvalue %any undef, ptr %error_var, 0, !dbg !167 + %30 = insertvalue %any %29, i64 ptrtoint (ptr @"$ct.anyfault" to i64), 1, !dbg !167 + store %any %30, ptr %varargslots, align 16 + %31 = insertvalue %"any[]" undef, ptr %varargslots, 0 + %"$$temp" = insertvalue %"any[]" %31, i64 1, 1 + store %"any[]" %"$$temp", ptr %indirectarg, align 8 + call void @std.core.builtin.panicf(ptr @.panic_msg.1 + unreachable, !dbg !154 + +noerr_block: ; preds = %expr_block.exit + store %"char[][]" %28, ptr %list5, align 8, !dbg !154 + !170 + store i32 0, ptr %i, align 4, !dbg !171 + br label %loop.cond, !dbg !171 + +loop.cond: ; preds = %loop.exit, %noerr_block + %32 = load i32, ptr %i, align 4, !dbg !172 + %33 = load i32, ptr %argc2, align 4, !dbg !173 + %lt = icmp slt i32 %32, %33, !dbg !172 + br i1 %lt, label %loop.body, label %loop.exit26, !dbg !172 + +loop.body: ; preds = %loop.cond + !176 + %34 = load ptr, ptr %argv3, align 8, !dbg !177 + %35 = load i32, ptr %i, align 4, !dbg !178 + %sext14 = sext i32 %35 to i64, !dbg !178 + %ptroffset = getelementptr inbounds [8 x i8], ptr %34, i64 %sext14, !dbg !178 + %36 = load ptr, ptr %ptroffset, align 8, !dbg !178 + store ptr %36, ptr %arg, align 8, !dbg !178 + !180 + store i64 0, ptr %len, align 8, !dbg !181 + %37 = load ptr, ptr %list5, align 8, !dbg !182 + %38 = load i32, ptr %i, align 4, !dbg !183 + %sext15 = sext i32 %38 to i64, !dbg !183 + %ptroffset16 = getelementptr inbounds [16 x i8], ptr %37, i64 %sext15, !dbg !183 + %39 = load ptr, ptr %arg, align 8, !dbg !184 + %40 = load ptr, ptr %arg, align 8 + store ptr %40, ptr %ptr, align 8 + !187 + store i64 0, ptr %len18, align 8, !dbg !189 + br label %loop.cond19, !dbg !190 + +loop.cond19: ; preds = %loop.body21, %loop.body + %41 = load ptr, ptr %ptr, align 8, !dbg !191 + %42 = load i64, ptr %len18, align 8, !dbg !193 + %ptradd20 = getelementptr inbounds i8, ptr %41, i64 %42, !dbg !193 + %43 = load i8, ptr %ptradd20, align 1, !dbg !193 + %i2b = icmp ne i8 %43, 0, !dbg !193 + br i1 %i2b, label %loop.body21, label %loop.exit, !dbg !193 + +loop.body21: ; preds = %loop.cond19 + %44 = load i64, ptr %len18, align 8, !dbg !194 + %add22 = add i64 %44, 1, !dbg !194 + store i64 %add22, ptr %len18, align 8, !dbg !194 + br label %loop.cond19, !dbg !194 + +loop.exit: ; preds = %loop.cond19 + %45 = load i64, ptr %len18, align 8, !dbg !195 + %add23 = add i64 0, %45, !dbg !195 + %size24 = sub i64 %add23, 0, !dbg !195 + %46 = insertvalue %"char[]" undef, ptr %39, 0, !dbg !195 + %47 = insertvalue %"char[]" %46, i64 %size24, 1, !dbg !195 + store %"char[]" %47, ptr %ptroffset16, align 8, !dbg !195 + %48 = load i32, ptr %i, align 4, !dbg !196 + %add25 = add i32 %48, 1, !dbg !196 + store i32 %add25, ptr %i, align 4, !dbg !196 + br label %loop.cond, !dbg !196 + +loop.exit26: ; preds = %loop.cond + call void @llvm.memcpy.p0.p0.i32(ptr align 8 %list, ptr align 8 %list5, i32 16, i1 false), !dbg !197 + %lo = load ptr, ptr %list, align 8, !dbg !198 + %ptradd27 = getelementptr inbounds i8, ptr %list, i64 8, !dbg !198 + %hi = load i64, ptr %ptradd27, align 8, !dbg !198 + %49 = call i32 @test.main(ptr %lo, i64 %hi), !dbg !199 + store i32 %49, ptr %blockret, align 4, !dbg !199 + %50 = load ptr, ptr %list, align 8, !dbg !200 + call void @std.core.mem.free(ptr %50) + br label %expr_block.exit28, !dbg !202 + +expr_block.exit28: ; preds = %loop.exit26 + %51 = load i32, ptr %blockret, align 4, !dbg !202 + ret i32 %51, !dbg !202 +} + +declare { i32, ptr } @attach.to_scope() #0 + +declare extern_weak ptr @std.core.mem.calloc(i64) #0 + +declare extern_weak ptr @std.io.stdout() #0 + +declare extern_weak i64 @std.io.fprintf(ptr, i64, ptr, ptr, i64, ptr byval(%"any[]") align 8) #0 + +declare extern_weak i64 @std.io.File.write_byte(ptr, i8 zeroext) #0 + +declare extern_weak i64 @std.io.File.flush(ptr) #0 + +declare { ptr, i64 } @arena_scratch_begin(ptr, i64) #0 + +declare void @arena_scratch_end(ptr, i64) #0 + +define weak ptr @.dyn_search(ptr %0, ptr %1) unnamed_addr { +entry: + br label %check + +check: ; preds = %no_match, %entry + %2 = phi ptr [ %0, %entry ], [ %9, %no_match ] + %3 = icmp eq ptr %2, null + br i1 %3, label %missing_function, label %compare + +missing_function: ; preds = %check + ret ptr null + +compare: ; preds = %check + %4 = getelementptr inbounds + %5 = load ptr, ptr %4, align 8 + %6 = icmp eq ptr %5, %1 + br i1 %6, label %match, label %no_match + +match: ; preds = %compare + %7 = load ptr, ptr %2, align 8 + ret ptr %7 + +no_match: ; preds = %compare + %8 = getelementptr inbounds + %9 = load ptr, ptr %8, align 8 + br label %check +} + +!llvm.dbg.cu = !{!6} + +!0 = !{i32 2, !"Dwarf Version", i32 4} +!1 = !{i32 2, !"Debug Info Version", i32 3} +!2 = !{i32 2, !"wchar_size", i32 4} +!3 = !{i32 4, !"PIC Level", i32 2} +!4 = !{i32 1, !"uwtable", i32 2} +!5 = !{i32 2, !"frame-pointer", i32 2} +!6 = distinct !DICompileUnit(language: DW_LANG_C11 +!7 = !DIFile(filename: "defer_macro.c3" +!8 = !{!9} +!9 = !DICompositeType(tag: DW_TAG_enumeration_type, name: "Attach_Arg_Kind", scope: !10, file: !7, line: 129, baseType: !15, size: 32, align: 32, elements: !16) +!10 = !DICompositeType(tag: DW_TAG_structure_type, name: "Attach_Arg", scope: !7, file: !7, line: 134, size: 128, align: 64, elements: !11, identifier: "attach.Attach_Arg") +!11 = !{!12, !13} +!12 = !DIDerivedType(tag: DW_TAG_member, name: "kind", scope: !10, file: !7, line: 136, baseType: !9, size: 32, align: 32) +!13 = !DIDerivedType(tag: DW_TAG_member, name: "box", scope: !10, file: !7, line: 137, baseType: !14, size: 64, align: 64, offset: 64) +!14 = !DIDerivedType(tag: DW_TAG_pointer_type, name: "void*", baseType: null, size: 64, align: 64, dwarfAddressSpace: 0) +!15 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) +!16 = !{!17} +!17 = !DIEnumerator(name: "TOP", value: 0) +!18 = distinct !DISubprogram(name: "foo", linkageName: "test.foo", scope: !7, file: !7, line: 6, type: !19, scopeLine: 6, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !6, retainedNodes: !21) +!19 = !DISubroutineType(types: !20) +!20 = !{null, !15} +!21 = !{} +!22 = !DILocalVariable(name: "x", arg: 1, scope: !18, file: !7, line: 6, type: !15) +!23 = !DILocation(line: 6, column: 17, scope: !18) +!24 = !DILocalVariable(name: "a", scope: !18, file: !7, line: 8, type: !15, align: 4) +!25 = !DILocation(line: 8, column: 7, scope: !18) +!26 = !DILocation(line: 8, column: 11, scope: !18) +!27 = !DILocation(line: 9, column: 2, scope: !18) +!28 = !DILocation(line: 9, column: 9, scope: !29) +!29 = distinct !DILexicalBlock(scope: !18, file: !7, line: 9, column: 2) +!30 = !DILocation(line: 11, column: 7, scope: !31) +!31 = distinct !DILexicalBlock(scope: !29, file: !7, line: 10, column: 2) +!32 = distinct !DISubprogram(name: "main", linkageName: "test.main", scope: !7, file: !7, line: 15, type: !33, scopeLine: 15, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !6, retainedNodes: !21) +!33 = !DISubroutineType(types: !34) +!34 = !{!15, !35} +!35 = !DICompositeType(tag: DW_TAG_structure_type, name: "String[]", size: 128, align: 64, elements: !36, identifier: "String[]") +!36 = !{!37, !48} +!37 = !DIDerivedType(tag: DW_TAG_member, name: "ptr", scope: !35, baseType: !38, size: 64, align: 64) +!38 = !DIDerivedType(tag: DW_TAG_pointer_type, name: "String*", baseType: !39, size: 64, align: 64, dwarfAddressSpace: 0) +!39 = !DIDerivedType(tag: DW_TAG_typedef, name: "String", baseType: !40) +!40 = !DICompositeType(tag: DW_TAG_structure_type, name: "char[]", size: 128, align: 64, elements: !41, identifier: "char[]") +!41 = !{!42, !45} +!42 = !DIDerivedType(tag: DW_TAG_member, name: "ptr", scope: !40, baseType: !43, size: 64, align: 64) +!43 = !DIDerivedType(tag: DW_TAG_pointer_type, name: "char*", baseType: !44, size: 64, align: 64, dwarfAddressSpace: 0) +!44 = !DIBasicType(name: "char", size: 8, encoding: DW_ATE_unsigned_char) +!45 = !DIDerivedType(tag: DW_TAG_member, name: "len", scope: !40, baseType: !46, size: 64, align: 64, offset: 64) +!46 = !DIDerivedType(tag: DW_TAG_typedef, name: "usz", baseType: !47) +!47 = !DIBasicType(name: "ulong", size: 64, encoding: DW_ATE_unsigned) +!48 = !DIDerivedType(tag: DW_TAG_member, name: "len", scope: !35, baseType: !46, size: 64, align: 64, offset: 64) +!49 = !DILocalVariable(name: "args", arg: 1, scope: !32, file: !7, line: 15, type: !35) +!50 = !DILocation(line: 15, column: 22, scope: !32) +!51 = !DILocalVariable(name: "asdf", scope: !32, file: !7, line: 19, type: !52, align: 8) +!52 = !DIDerivedType(tag: DW_TAG_pointer_type, name: "Foo*", baseType: !53, size: 64, align: 64, dwarfAddressSpace: 0) +!53 = !DICompositeType(tag: DW_TAG_structure_type, name: "Foo", scope: !7, file: !7, line: 28, size: 64, align: 64, elements: !54, identifier: "test.Foo") +!54 = !{!55} +!55 = !DIDerivedType(tag: DW_TAG_member, name: "asdf", scope: !53, file: !7, line: 30, baseType: !14, size: 64, align: 64) +!56 = !DILocation(line: 19, column: 7, scope: !32) +!57 = !DILocation(line: 19, column: 25, scope: !32) +!58 = !DILocation +!59 = distinct !DISubprogram(name: "[DEFAULT INIT]", linkageName: "[DEFAULT INIT]", scope: !7, file: !7, line: 35, scopeLine: 35, spFlags: DISPFlagLocalToUnit | DISPFlagDefinition, unit: !6) +!60 = !DILocation(line: 19, column: 14, scope: !32) +!61 = !DILocation(line: 22, column: 7, scope: !32) +!62 = !DILocation(line: 22, column: 36, scope: !32) +!63 = !DILocation(line: 22, column: 2, scope: !32) +!64 = !DILocation(line: 24, column: 2, scope: !32) +!65 = !DILocation(line: 25, column: 9, scope: !32) +!66 = distinct !DISubprogram(name: "create_foo", linkageName: "test.create_foo", scope: !7, file: !7, line: 35, type: !67, scopeLine: 35, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !6, retainedNodes: !21) +!67 = !DISubroutineType(types: !68) +!68 = !{!52, !10, !47, !39} +!69 = !DILocalVariable(name: "attach", arg: 1, scope: !66, file: !7, line: 35, type: !10) +!70 = !DILocation(line: 35, column: 31, scope: !66) +!71 = !DILocalVariable(name: "flags", arg: 2, scope: !66, file: !7, line: 35, type: !47) +!72 = !DILocation(line: 35, column: 49, scope: !66) +!73 = !DILocalVariable(name: "name", arg: 3, scope: !66, file: !7, line: 35, type: !39) +!74 = !DILocation(line: 35, column: 63, scope: !66) +!75 = !DILocation(line: +!76 = distinct !DISubprogram(name: "new", linkageName: "new", scope: !77, file: !77, line: +!77 = !DIFile(filename: "mem.c3" +!78 = !DILocation(line: 37, column: 9, scope: !66) +!79 = distinct !DISubprogram(name: "test", linkageName: "test.test", scope: !7, file: !7, line: 45, type: !80, scopeLine: 45, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !6, retainedNodes: !21) +!80 = !DISubroutineType(types: !81) +!81 = !{!52, !82} +!82 = !DIDerivedType(tag: DW_TAG_typedef, name: "Color", scope: !7, file: !7, line: 87, baseType: !83, align: 16) +!83 = !DICompositeType(tag: DW_TAG_array_type, baseType: !84, size: 128, align: 32, flags: DIFlagVector, elements: !85) +!84 = !DIBasicType(name: "float", size: 32, encoding: DW_ATE_float) +!85 = !{!86} +!86 = !DISubrange(count: 4, lowerBound: 0) +!87 = !DILocalVariable(name: "color", arg: 1, scope: !79, file: !7, line: 45, type: !82) +!88 = !DILocation(line: 45, column: 20, scope: !79) +!89 = !DILocation( +!90 = distinct !DISubprogram(name: "printn", linkageName: "printn" +!91 = !DIFile(filename: "io.c3" +!92 = !DILocation(line: 47, column: 2, scope: !79) +!93 = !DILocalVariable(name: "len" +!94 = distinct !DISubprogram(name: "fprintn", linkageName: "fprintn", scope: !91 +!95 = !DILocation +!96 = !DILocation +!97 = !DILocation +!98 = distinct !DISubprogram(name: "fprint", linkageName: "fprint", scope: !91 +!99 = !DILocation +!100 = !DILocation +!101 = !DILocation +!102 = !DILocation +!103 = !DILocation +!104 = !DILocation +!105 = !DILocation +!106 = !DILocation +!107 = distinct !DISubprogram(name: "test2", linkageName: "test.test2", scope: !7, file: !7, line: 51, type: !108, scopeLine: 51, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !6, retainedNodes: !21) +!108 = !DISubroutineType(types: !109) +!109 = !{!14} +!110 = !DILocalVariable(name: "scratch", scope: !111, file: !7, line: 123, type: !112, align: 8) +!111 = distinct !DISubprogram(name: "@scratch", linkageName: "@scratch", scope: !7, file: !7, line: 121, scopeLine: 121, spFlags: DISPFlagLocalToUnit | DISPFlagDefinition, unit: !6, retainedNodes: !21) +!112 = !DICompositeType(tag: DW_TAG_structure_type, name: "Arena_Cursor", scope: !7, file: !7, line: 97, size: 128, align: 64, elements: !113, identifier: "foo__Arena_Cursor") +!113 = !{!114, !119} +!114 = !DIDerivedType(tag: DW_TAG_member, name: "arena", scope: !112, file: !7, line: 99, baseType: !115, size: 64, align: 64) +!115 = !DIDerivedType(tag: DW_TAG_pointer_type, name: "Arena*", baseType: !116, size: 64, align: 64, dwarfAddressSpace: 0) +!116 = !DICompositeType(tag: DW_TAG_structure_type, name: "Arena", scope: !7, file: !7, line: 92, size: 64, align: 64, elements: !117, identifier: "foo__Arena") +!117 = !{!118} +!118 = !DIDerivedType(tag: DW_TAG_member, name: "cursor", scope: !116, file: !7, line: 94, baseType: !46, size: 64, align: 64) +!119 = !DIDerivedType(tag: DW_TAG_member, name: "cursor", scope: !112, file: !7, line: 100, baseType: !46, size: 64, align: 64, offset: 64) +!120 = !DILocation(line: 123, column: 15, scope: !111, inlinedAt: !121) +!121 = !DILocation +!122 = !DILocation +!123 = !DILocation +!124 = !DILocalVariable(name: "scratch", scope: !107, file: !7, line: 54, type: !115, align: 8) +!125 = !DILocation(line: 54, column: 20, scope: !107) +!126 = !DILocation +!127 = distinct !DILexicalBlock(scope: !111, file: !7, line: 125, column: 2) +!128 = !DILocalVariable(name: "asdf", scope: !129, file: !7, line: 56, type: !14, align: 8) +!129 = distinct !DILexicalBlock(scope: !107, file: !7, line: 55, column: 2) +!130 = !DILocation(line: 56, column: 12, scope: !129) +!131 = !DILocation(line: 57, column: 13, scope: !129) +!132 = !DILocation +!133 = distinct !DILexicalBlock(scope: !111, file: !7, line: 124, column: 8) +!134 = !DILocation +!135 = distinct !DISubprogram(name: "_$main", linkageName: "main", scope: !7, file: !7, line: 15, type: !136, scopeLine: 15, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !6, retainedNodes: !21) +!136 = !DISubroutineType(types: !137) +!137 = !{!15, !15, !138} +!138 = !DIDerivedType(tag: DW_TAG_pointer_type, name: "char**", baseType: !43, size: 64, align: 64, dwarfAddressSpace: 0) +!139 = !DILocalVariable(name: ".anon", arg: 1, scope: !135, file: !7, line: 15, type: !15) +!140 = !DILocation(line: 15, column: 8, scope: !135) +!141 = !DILocalVariable(name: ".anon", arg: 2, scope: !135, file: !7, line: 15, type: !138) +!142 = !DILocalVariable(name: "list", scope: !143, file: !7, line: 45, type: !35, align: 8) +!143 = distinct !DISubprogram(name: "@main_to_int_main_args", linkageName: "@main_to_int_main_args", scope: !144, file: !144, line: 43, scopeLine: 43, spFlags: DISPFlagLocalToUnit | DISPFlagDefinition, unit: !6, retainedNodes: !21) +!144 = !DIFile(filename: "main_stub.c3" +!145 = !DILocation +!146 = !DILocalVariable(name: "list", scope: !147, file: !7, line: 24, type: !35, align: 8) +!147 = distinct !DISubprogram(name: "args_to_strings", linkageName: "args_to_strings", scope: !144, file: !144, line: 22, scopeLine: 22, spFlags: DISPFlagLocalToUnit | DISPFlagDefinition, unit: !6, retainedNodes: !21) +!148 = !DILocation +!149 = !DILocation +!150 = !DILocation +!151 = !DILocation +!152 = distinct !DISubprogram(name: "alloc_array_try", linkageName: "alloc_array_try", scope: !153, file: !153, line: 284, scopeLine: 284, spFlags: DISPFlagLocalToUnit | DISPFlagDefinition, unit: !6) +!153 = !DIFile(filename: "mem_allocator.c3" +!154 = !DILocation +!155 = distinct !DISubprogram(name: "alloc_array", linkageName: "alloc_array", scope: !153 +!156 = !DILocation +!157 = distinct !DISubprogram(name: "alloc_array", linkageName: "alloc_array", scope: !77 +!158 = !DILocation +!159 = !DILocation +!160 = !DILocation +!161 = distinct !DISubprogram(name: "malloc_try", linkageName: "malloc_try", scope: !153, file: !153, line: 60, scopeLine: 60, spFlags: DISPFlagLocalToUnit | DISPFlagDefinition, unit: !6) +!162 = !DILocation +!163 = !DILocation +!164 = !DILocation +!165 = distinct !DISubprogram(name: "[DEFAULT INIT]", linkageName: "[DEFAULT INIT]", scope: !153, file: !153, line: 28, scopeLine: 28, spFlags: DISPFlagLocalToUnit | DISPFlagDefinition, unit: !6) +!166 = !DILocation +!167 = !DILocation +!168 = !DILocalVariable(name: "i", scope: !169, file: !7, line: 25, type: !15, align: 4) +!169 = distinct !DILexicalBlock(scope: !147, file: !144, line: 25, column: 2) +!170 = !DILocation +!171 = !DILocation +!172 = !DILocation +!173 = !DILocation +!174 = !DILocalVariable(name: "arg", scope: !175, file: !7, line: 27, type: !43, align: 8) +!175 = distinct !DILexicalBlock(scope: !169, file: !144, line: 26, column: 2) +!176 = !DILocation +!177 = !DILocation +!178 = !DILocation +!179 = !DILocalVariable(name: "len", scope: !175, file: !7, line: 28, type: !46, align: 8) +!180 = !DILocation +!181 = !DILocation +!182 = !DILocation +!183 = !DILocation +!184 = !DILocation +!185 = !DILocalVariable(name: "len", scope: !186, file: !7, line: 5, type: !46, align: 8) +!186 = distinct !DISubprogram(name: "_strlen", linkageName: "_strlen", scope: !144, file: !144, line: 3, scopeLine: 3, spFlags: DISPFlagLocalToUnit | DISPFlagDefinition, unit: !6, retainedNodes: !21) +!187 = !DILocation +!188 = !DILocation +!189 = !DILocation +!190 = !DILocation +!191 = !DILocation +!192 = distinct !DILexicalBlock(scope: !186, file: !144, line: 6, column: 2) +!193 = !DILocation +!194 = !DILocation +!195 = !DILocation +!196 = !DILocation +!197 = !DILocation +!198 = !DILocation +!199 = !DILocation +!200 = !DILocation +!201 = distinct !DILexicalBlock(scope: !143, file: !144, line: 46, column: 8) +!202 = !DILocation \ No newline at end of file diff --git a/test/test_suite7/debug_symbols/foreach.c3t b/test/test_suite7/debug_symbols/foreach.c3t new file mode 100644 index 000000000..12b9cd963 --- /dev/null +++ b/test/test_suite7/debug_symbols/foreach.c3t @@ -0,0 +1,67 @@ +// #target: macos-x64 +// #debuginfo: yes +module test; + +fn void foo(String[] args) +{ + foreach (a : args) + { + int x = a.len; + } +} + +/* #expect: test.ll + +define void @test.foo(ptr %0, i64 %1) #0 !dbg !8 { +entry: + %args = alloca %"char[][]", align 8 + %.anon = alloca i64, align 8 + %a = alloca %"char[]", align 8 + %x = alloca i32, align 4 + store ptr %0, ptr %args, align 8 + %ptradd = getelementptr inbounds i8, ptr %args, i64 8 + store i64 %1, ptr %ptradd, align 8 + %ptradd1 = getelementptr inbounds i8, ptr %args, i64 8, !dbg !28 + %2 = load i64, ptr %ptradd1, align 8, !dbg !28 + store i64 0, ptr %.anon, align 8, !dbg !28 + br label %loop.cond, !dbg !28 + +loop.cond: ; preds = %loop.body, %entry + %3 = load i64, ptr %.anon, align 8, !dbg !28 + %lt = icmp ult i64 %3, %2, !dbg !28 + br i1 %lt, label %loop.body, label %loop.exit, !dbg !28 + +loop.body: ; preds = %loop.cond + %4 = load ptr, ptr %args, align 8, !dbg !34 + %5 = load i64, ptr %.anon, align 8, !dbg !34 + %ptroffset = getelementptr inbounds [16 x i8], ptr %4, i64 %5, !dbg !34 + call void @llvm.memcpy.p0.p0.i32(ptr align 8 %a, ptr align 8 %ptroffset, i32 16, i1 false), !dbg !34 + %ptradd2 = getelementptr inbounds i8, ptr %a, i64 8, !dbg !39 + %6 = load i64, ptr %ptradd2, align 8, !dbg !39 + %trunc = trunc i64 %6 to i32, !dbg !39 + store i32 %trunc, ptr %x, align 4, !dbg !39 + %7 = load i64, ptr %.anon, align 8, !dbg !28 + %addnuw = add nuw i64 %7, 1, !dbg !28 + store i64 %addnuw, ptr %.anon, align 8, !dbg !28 + br label %loop.cond, !dbg !28 + +loop.exit: ; preds = %loop.cond + ret void, !dbg !28 +} + +!24 = !DIDerivedType(tag: DW_TAG_member, name: "len", scope: !11, baseType: !22, size: 64, align: 64, offset: 64) +!25 = !{} +!26 = !DILocalVariable(name: "args", arg: 1, scope: !8, file: !7, line: 3, type: !11) +!27 = !DILocation(line: 3, column: 22, scope: !8) +!28 = !DILocation(line: 5, column: 15, scope: !29) +!29 = distinct !DILexicalBlock(scope: !8, file: !7, line: 5, column: 2) +!30 = !DILocalVariable(name: ".temp", scope: !29, file: !7, line: 5, type: !22, align: 8) +!31 = !DILocalVariable(name: "a", scope: !32, file: !7, line: 5, type: !15, align: 8) +!32 = distinct !DILexicalBlock(scope: !29, file: !7, line: 6, column: 2) +!33 = !DILocation(line: 5, column: 11, scope: !32) +!34 = !DILocation(line: 5, column: 15, scope: !32) +!35 = !DILocalVariable(name: "x", scope: !36, file: !7, line: 7, type: !37, align: 4) +!36 = distinct !DILexicalBlock(scope: !32, file: !7, line: 6, column: 2) +!37 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) +!38 = !DILocation(line: 7, column: 7, scope: !36) +!39 = !DILocation(line: 7, column: 11, scope: !36) \ No newline at end of file diff --git a/test/test_suite7/defer/defer_and_expr_block.c3t b/test/test_suite7/defer/defer_and_expr_block.c3t new file mode 100644 index 000000000..ad9c6c30a --- /dev/null +++ b/test/test_suite7/defer/defer_and_expr_block.c3t @@ -0,0 +1,39 @@ +// #target: macos-x64 +// #deprecation: no +module foo; +extern fn void printf(char*,...); + +fn void main() +{ + defer printf("On exit\n"); + {| + defer printf("Baz\n"); + defer (void){| + 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 + store i32 12, ptr %blockret, align 4 + call void (ptr, ...) @printf(ptr @.str) + call void (ptr, ...) @printf(ptr @.str.1) + br label %expr_block.exit +expr_block.exit: ; preds = %if.then + call void (ptr, ...) @printf(ptr @.str.2) + call void (ptr, ...) @printf(ptr @.str.3) + call void (ptr, ...) @printf(ptr @.str.4) + ret void +} + diff --git a/test/test_suite7/defer/defer_catch_direct_error.c3t b/test/test_suite7/defer/defer_catch_direct_error.c3t new file mode 100644 index 000000000..98c0d06be --- /dev/null +++ b/test/test_suite7/defer/defer_catch_direct_error.c3t @@ -0,0 +1,29 @@ +// #target: macos-x64 +module test; +import std::io; +fn void! example_fn() +{ + defer try { + int a = 1; + } + + defer (catch err) { + anyfault f = err; + } + return io::IoError.FILE_NOT_FOUND?; +} + +/* #expect: test.ll + +define i64 @test.example_fn() #0 { +entry: + %reterr = alloca i64, align 8 + %err = alloca i64, align 8 + %f = alloca i64, align 8 + store i64 ptrtoint (ptr @"std.io.IoError$FILE_NOT_FOUND" to i64), ptr %reterr, align 8 + %0 = load i64, ptr %reterr, align 8 + store i64 %0, ptr %err, align 8 + %1 = load i64, ptr %err, align 8 + store i64 %1, ptr %f, align 8 + ret i64 ptrtoint (ptr @"std.io.IoError$FILE_NOT_FOUND" to i64) +} diff --git a/test/test_suite7/defer/defer_catch_err.c3t b/test/test_suite7/defer/defer_catch_err.c3t new file mode 100644 index 000000000..c13c2c084 --- /dev/null +++ b/test/test_suite7/defer/defer_catch_err.c3t @@ -0,0 +1,156 @@ +// #target: macos-x64 +// #deprecation: no +module foo; +import std::io; + +fault Test { FOO } + +fn void! test2() +{ + defer (catch err) {}; + test()!; +} + +fn int! test() +{ + int! z = {| + const ABC = 4; + int! x = SearchResult.MISSING?; + defer (catch err) io::printfn("Hello %s", err); + defer (catch err) { io::printfn("Bye %s", err); err = Test.FOO; } + return x; + |}; + const ABC = 4; + int! x = SearchResult.MISSING?; + defer (catch err) io::printfn("Hello %s", err); + defer (catch err) { io::printfn("Bye %s", err); err = Test.FOO; } + return x; +} + +fn void main() +{ + (void)test(); +} + + +/* #expect: foo.ll + +define i64 @foo.test2() #0 { +entry: + %error_var = alloca i64, align 8 + %retparam = alloca i32, align 4 + %err = alloca i64, align 8 + %0 = call i64 @foo.test(ptr %retparam) + %not_err = icmp eq i64 %0, 0 + %1 = call i1 @llvm.expect.i1(i1 %not_err, i1 true) + br i1 %1, label %after_check, label %assign_optional + +assign_optional: ; 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 = %assign_optional + %2 = load i64, ptr %error_var, align 8 + store i64 %2, ptr %err, align 8 + %3 = load i64, ptr %error_var, align 8 + ret i64 %3 + +noerr_block: ; preds = %after_check + ret i64 0 +} + +define i64 @foo.test(ptr %0) #0 { +entry: + %z = alloca i32, align 4 + %z.f = alloca i64, align 8 + %blockret = alloca i32, align 4 + %x = alloca i32, align 4 + %x.f = alloca i64, align 8 + %err = alloca i64, align 8 + %varargslots = alloca [1 x %any], align 16 + %retparam = alloca i64, align 8 + %err3 = alloca i64, align 8 + %varargslots4 = alloca [1 x %any], align 16 + %retparam5 = alloca i64, align 8 + %x8 = alloca i32, align 4 + %x.f9 = alloca i64, align 8 + %reterr = alloca i64, align 8 + %err14 = alloca i64, align 8 + %varargslots15 = alloca [1 x %any], align 16 + %retparam16 = alloca i64, align 8 + %err19 = alloca i64, align 8 + %varargslots20 = alloca [1 x %any], align 16 + %retparam21 = alloca i64, align 8 + store i64 ptrtoint (ptr @"std.core.builtin.SearchResult$MISSING" to i64), ptr %x.f, align 8 + %optval = load i64, ptr %x.f, align 8 + %not_err = icmp eq i64 %optval, 0 + %1 = call i1 @llvm.expect.i1(i1 %not_err, i1 true) + br i1 %1, label %after_check, label %assign_optional + +assign_optional: ; preds = %entry + store i64 %optval, ptr %z.f, align 8 + br label %opt_block_cleanup + +after_check: ; preds = %entry + %2 = load i32, ptr %x, align 4 + store i32 %2, ptr %blockret, align 4 + br label %expr_block.exit + +opt_block_cleanup: ; preds = %assign_optional + %3 = load i64, ptr %z.f, align 8 + store i64 %3, ptr %err, align 8 + %4 = insertvalue %any undef, ptr %err, 0 + %5 = insertvalue %any %4, i64 ptrtoint (ptr @"$ct.anyfault" to i64), 1 + store %any %5, ptr %varargslots, align 16 + %6 = call i64 @std.io.printfn(ptr %retparam, ptr @.str, i64 6, ptr %varargslots, i64 1) + store i64 ptrtoint (ptr @"foo.Test$FOO" to i64), ptr %err, align 8 + %7 = load i64, ptr %z.f, align 8 + store i64 %7, ptr %err3, align 8 + %8 = insertvalue %any undef, ptr %err3, 0 + %9 = insertvalue %any %8, i64 ptrtoint (ptr @"$ct.anyfault" to i64), 1 + store %any %9, ptr %varargslots4, align 16 + %10 = call i64 @std.io.printfn(ptr %retparam5, ptr @.str.2, i64 8, ptr %varargslots4, i64 1) + br label %after_assign + +expr_block.exit: ; preds = %after_check + %11 = load i32, ptr %blockret, align 4 + store i32 %11, ptr %z, align 4 + store i64 0, ptr %z.f, align 8 + br label %after_assign + +after_assign: ; preds = %expr_block.exit, %opt_block_cleanup + store i64 ptrtoint (ptr @"std.core.builtin.SearchResult$MISSING" to i64), ptr %x.f9, align 8 + %optval10 = load i64, ptr %x.f9, align 8 + %not_err11 = icmp eq i64 %optval10, 0 + %12 = call i1 @llvm.expect.i1(i1 %not_err11, i1 true) + br i1 %12, label %after_check13, label %assign_optional12 + +assign_optional12: ; preds = %after_assign + store i64 %optval10, ptr %reterr, align 8 + br label %err_retblock + +after_check13: ; preds = %after_assign + %13 = load i32, ptr %x8, align 4 + store i32 %13, ptr %0, align 4 + ret i64 0 + +err_retblock: ; preds = %assign_optional12 + %14 = load i64, ptr %reterr, align 8 + store i64 %14, ptr %err14, align 8 + %15 = insertvalue %any undef, ptr %err14, 0 + %16 = insertvalue %any %15, i64 ptrtoint (ptr @"$ct.anyfault" to i64), 1 + store %any %16, ptr %varargslots15, align 16 + %17 = call i64 @std.io.printfn(ptr %retparam16, ptr @.str.4, i64 6, ptr %varargslots15, i64 1) + store i64 ptrtoint (ptr @"foo.Test$FOO" to i64), ptr %err14, align 8 + %18 = load i64, ptr %reterr, align 8 + store i64 %18, ptr %err19, align 8 + %19 = insertvalue %any undef, ptr %err19, 0 + %20 = insertvalue %any %19, i64 ptrtoint (ptr @"$ct.anyfault" to i64), 1 + store %any %20, ptr %varargslots20, align 16 + %21 = call i64 @std.io.printfn(ptr %retparam21, ptr @.str.5, i64 8, ptr %varargslots20, i64 1) + %22 = load i64, ptr %reterr, align 8 + ret i64 %22 +} \ No newline at end of file diff --git a/test/test_suite7/defer/defer_catch_mix.c3t b/test/test_suite7/defer/defer_catch_mix.c3t new file mode 100644 index 000000000..20402f275 --- /dev/null +++ b/test/test_suite7/defer/defer_catch_mix.c3t @@ -0,0 +1,358 @@ +// #target: macos-aarch64 +module test; +import std::io; + +fn char[]! fileReader(String filename, char[] buffer) +{ + io::File! file = io::file::open(filename, "r"); + defer (catch foo) io::printn("something on fail with the file"); + defer io::printn("always close the file"); + + file.read(buffer)!; + return buffer; +} + +fn void main() +{ + char[] !buffer = mem::new_array(char, 12); + buffer = fileReader("not_found.txt", buffer); + return; +} + +/* #expect: test.ll + +define i64 @test.fileReader(ptr %0, [2 x i64] %1, [2 x i64] %2) #0 { +entry: + %filename = alloca %"char[]", align 8 + %buffer = alloca %"char[]", align 8 + %file = alloca %File, align 8 + %file.f = alloca i64, align 8 + %retparam = alloca %File, align 8 + %taddr = alloca %"char[]", align 8 + %error_var = alloca i64, align 8 + %retparam4 = alloca i64, align 8 + %len = alloca i64, align 8 + %error_var8 = alloca i64, align 8 + %retparam10 = alloca i64, align 8 + %taddr11 = alloca %"char[]", align 8 + %error_var16 = alloca i64, align 8 + %error_var22 = alloca i64, align 8 + %foo = alloca i64, align 8 + %len28 = alloca i64, align 8 + %error_var29 = alloca i64, align 8 + %retparam31 = alloca i64, align 8 + %taddr32 = alloca %"char[]", align 8 + %error_var38 = alloca i64, align 8 + %error_var44 = alloca i64, align 8 + %reterr = alloca i64, align 8 + %len53 = alloca i64, align 8 + %error_var54 = alloca i64, align 8 + %retparam56 = alloca i64, align 8 + %taddr57 = alloca %"char[]", align 8 + %error_var63 = alloca i64, align 8 + %error_var69 = alloca i64, align 8 + store [2 x i64] %1, ptr %filename, align 8 + store [2 x i64] %2, ptr %buffer, align 8 + %3 = load [2 x i64], ptr %filename, align 8 + store %"char[]" { ptr @.str, i64 1 }, ptr %taddr, align 8 + %4 = load [2 x i64], ptr %taddr, align 8 + %5 = call i64 @std.io.file.open(ptr %retparam, [2 x i64] %3, [2 x i64] %4) + %not_err = icmp eq i64 %5, 0 + %6 = call i1 @llvm.expect.i1(i1 %not_err, i1 true) + br i1 %6, label %after_check, label %assign_optional +assign_optional: ; preds = %entry + store i64 %5, ptr %file.f, align 8 + br label %after_assign +after_check: ; preds = %entry + call void @llvm.memcpy.p0.p0.i32(ptr align 8 %file, ptr align 8 %retparam, i32 8, i1 false) + store i64 0, ptr %file.f, align 8 + br label %after_assign +after_assign: ; preds = %after_check, %assign_optional + %optval = load i64, ptr %file.f, align 8 + %not_err1 = icmp eq i64 %optval, 0 + %7 = call i1 @llvm.expect.i1(i1 %not_err1, i1 true) + br i1 %7, label %after_check3, label %assign_optional2 +assign_optional2: ; preds = %after_assign + store i64 %optval, ptr %error_var, align 8 + br label %guard_block +after_check3: ; preds = %after_assign + %8 = load [2 x i64], ptr %buffer, align 8 + %9 = call i64 @std.io.File.read(ptr %retparam4, ptr %file, [2 x i64] %8) + %not_err5 = icmp eq i64 %9, 0 + %10 = call i1 @llvm.expect.i1(i1 %not_err5, i1 true) + br i1 %10, label %after_check7, label %assign_optional6 +assign_optional6: ; preds = %after_check3 + store i64 %9, ptr %error_var, align 8 + br label %guard_block +after_check7: ; preds = %after_check3 + br label %noerr_block52 +guard_block: ; preds = %assign_optional6, %assign_optional2 + %11 = call ptr @std.io.stdout() + store %"char[]" { ptr @.str.1, i64 21 }, ptr %taddr11, align 8 + %12 = load [2 x i64], ptr %taddr11, align 8 + %13 = call i64 @std.io.File.write(ptr %retparam10, ptr %11, [2 x i64] %12) + %not_err12 = icmp eq i64 %13, 0 + %14 = call i1 @llvm.expect.i1(i1 %not_err12, i1 true) + br i1 %14, label %after_check14, label %assign_optional13 +assign_optional13: ; preds = %guard_block + store i64 %13, ptr %error_var8, align 8 + br label %guard_block15 +after_check14: ; preds = %guard_block + br label %noerr_block +guard_block15: ; preds = %assign_optional13 + br label %voiderr +noerr_block: ; preds = %after_check14 + %15 = load i64, ptr %retparam10, align 8 + store i64 %15, ptr %len, align 8 + %16 = call i64 @std.io.File.write_byte(ptr %11, i8 10) + %not_err17 = icmp eq i64 %16, 0 + %17 = call i1 @llvm.expect.i1(i1 %not_err17, i1 true) + br i1 %17, label %after_check19, label %assign_optional18 +assign_optional18: ; preds = %noerr_block + store i64 %16, ptr %error_var16, align 8 + br label %guard_block20 +after_check19: ; preds = %noerr_block + br label %noerr_block21 +guard_block20: ; preds = %assign_optional18 + br label %voiderr +noerr_block21: ; preds = %after_check19 + %18 = call i64 @std.io.File.flush(ptr %11) + %not_err23 = icmp eq i64 %18, 0 + %19 = call i1 @llvm.expect.i1(i1 %not_err23, i1 true) + br i1 %19, label %after_check25, label %assign_optional24 +assign_optional24: ; preds = %noerr_block21 + store i64 %18, ptr %error_var22, align 8 + br label %guard_block26 +after_check25: ; preds = %noerr_block21 + br label %noerr_block27 +guard_block26: ; preds = %assign_optional24 + br label %voiderr +noerr_block27: ; preds = %after_check25 + %20 = load i64, ptr %len, align 8 + %add = add i64 %20, 1 + br label %voiderr +voiderr: ; preds = %noerr_block27, %guard_block26, %guard_block20, %guard_block15 + %21 = load i64, ptr %error_var, align 8 + store i64 %21, ptr %foo, align 8 + %22 = call ptr @std.io.stdout() + store %"char[]" { ptr @.str.2, i64 31 }, ptr %taddr32, align 8 + %23 = load [2 x i64], ptr %taddr32, align 8 + %24 = call i64 @std.io.File.write(ptr %retparam31, ptr %22, [2 x i64] %23) + %not_err33 = icmp eq i64 %24, 0 + %25 = call i1 @llvm.expect.i1(i1 %not_err33, i1 true) + br i1 %25, label %after_check35, label %assign_optional34 +assign_optional34: ; preds = %voiderr + store i64 %24, ptr %error_var29, align 8 + br label %guard_block36 +after_check35: ; preds = %voiderr + br label %noerr_block37 +guard_block36: ; preds = %assign_optional34 + br label %voiderr51 +noerr_block37: ; preds = %after_check35 + %26 = load i64, ptr %retparam31, align 8 + store i64 %26, ptr %len28, align 8 + %27 = call i64 @std.io.File.write_byte(ptr %22, i8 10) + %not_err39 = icmp eq i64 %27, 0 + %28 = call i1 @llvm.expect.i1(i1 %not_err39, i1 true) + br i1 %28, label %after_check41, label %assign_optional40 +assign_optional40: ; preds = %noerr_block37 + store i64 %27, ptr %error_var38, align 8 + br label %guard_block42 +after_check41: ; preds = %noerr_block37 + br label %noerr_block43 +guard_block42: ; preds = %assign_optional40 + br label %voiderr51 +noerr_block43: ; preds = %after_check41 + %29 = call i64 @std.io.File.flush(ptr %22) + %not_err45 = icmp eq i64 %29, 0 + %30 = call i1 @llvm.expect.i1(i1 %not_err45, i1 true) + br i1 %30, label %after_check47, label %assign_optional46 +assign_optional46: ; preds = %noerr_block43 + store i64 %29, ptr %error_var44, align 8 + br label %guard_block48 +after_check47: ; preds = %noerr_block43 + br label %noerr_block49 +guard_block48: ; preds = %assign_optional46 + br label %voiderr51 +noerr_block49: ; preds = %after_check47 + %31 = load i64, ptr %len28, align 8 + %add50 = add i64 %31, 1 + br label %voiderr51 +voiderr51: ; preds = %noerr_block49, %guard_block48, %guard_block42, %guard_block36 + %32 = load i64, ptr %error_var, align 8 + ret i64 %32 +noerr_block52: ; preds = %after_check7 + %33 = load %"char[]", ptr %buffer, align 8 + %34 = call ptr @std.io.stdout() + store %"char[]" { ptr @.str.3, i64 21 }, ptr %taddr57, align 8 + %35 = load [2 x i64], ptr %taddr57, align 8 + %36 = call i64 @std.io.File.write(ptr %retparam56, ptr %34, [2 x i64] %35) + %not_err58 = icmp eq i64 %36, 0 + %37 = call i1 @llvm.expect.i1(i1 %not_err58, i1 true) + br i1 %37, label %after_check60, label %assign_optional59 +assign_optional59: ; preds = %noerr_block52 + store i64 %36, ptr %error_var54, align 8 + br label %guard_block61 +after_check60: ; preds = %noerr_block52 + br label %noerr_block62 +guard_block61: ; preds = %assign_optional59 + br label %voiderr76 +noerr_block62: ; preds = %after_check60 + %38 = load i64, ptr %retparam56, align 8 + store i64 %38, ptr %len53, align 8 + %39 = call i64 @std.io.File.write_byte(ptr %34, i8 10) + %not_err64 = icmp eq i64 %39, 0 + %40 = call i1 @llvm.expect.i1(i1 %not_err64, i1 true) + br i1 %40, label %after_check66, label %assign_optional65 +assign_optional65: ; preds = %noerr_block62 + store i64 %39, ptr %error_var63, align 8 + br label %guard_block67 +after_check66: ; preds = %noerr_block62 + br label %noerr_block68 +guard_block67: ; preds = %assign_optional65 + br label %voiderr76 +noerr_block68: ; preds = %after_check66 + %41 = call i64 @std.io.File.flush(ptr %34) + %not_err70 = icmp eq i64 %41, 0 + %42 = call i1 @llvm.expect.i1(i1 %not_err70, i1 true) + br i1 %42, label %after_check72, label %assign_optional71 +assign_optional71: ; preds = %noerr_block68 + store i64 %41, ptr %error_var69, align 8 + br label %guard_block73 +after_check72: ; preds = %noerr_block68 + br label %noerr_block74 +guard_block73: ; preds = %assign_optional71 + br label %voiderr76 +noerr_block74: ; preds = %after_check72 + %43 = load i64, ptr %len53, align 8 + %add75 = add i64 %43, 1 + br label %voiderr76 +voiderr76: ; preds = %noerr_block74, %guard_block73, %guard_block67, %guard_block61 + store %"char[]" %33, ptr %0, align 8 + ret i64 0 +} +; Function Attrs: nounwind uwtable(sync) +define void @test.main() #0 { +entry: + %buffer = alloca %"char[]", align 8 + %buffer.f = alloca i64, align 8 + %allocator = alloca %any, align 8 + %error_var = alloca i64, align 8 + %allocator1 = alloca %any, align 8 + %allocator2 = alloca %any, align 8 + %.inlinecache = alloca ptr, align 8 + %.cachedtype = alloca ptr, align 8 + %taddr = alloca %"char[]", align 8 + %taddr4 = alloca %"char[]", align 8 + %taddr5 = alloca %"char[]", align 8 + %retparam = alloca ptr, align 8 + %taddr6 = alloca ptr, align 8 + %taddr7 = alloca %"char[]", align 8 + %taddr8 = alloca %"char[]", align 8 + %taddr9 = alloca %"char[]", align 8 + %varargslots = alloca [1 x %any], align 8 + %taddr10 = alloca %"any[]", align 8 + %retparam14 = alloca %"char[]", align 8 + %taddr15 = alloca %"char[]", align 8 + store ptr null, ptr %.cachedtype, align 8 + call void @llvm.memcpy.p0.p0.i32(ptr align 8 %allocator, ptr align 8 @std.core.mem.allocator.thread_allocator, i32 16, i1 false) + call void @llvm.memcpy.p0.p0.i32(ptr align 8 %allocator1, ptr align 8 %allocator, i32 16, i1 false) + call void @llvm.memcpy.p0.p0.i32(ptr align 8 %allocator2, ptr align 8 %allocator1, i32 16, i1 false) + br label %if.exit +if.exit: ; preds = %entry + %ptradd = getelementptr inbounds i8, ptr %allocator2, i64 8 + %0 = load i64, ptr %ptradd, align 8 + %1 = inttoptr i64 %0 to ptr + %type = load ptr, ptr %.cachedtype, align 8 + %2 = icmp eq ptr %1, %type + br i1 %2, label %cache_hit, label %cache_miss +cache_miss: ; preds = %if.exit + %ptradd3 = getelementptr inbounds i8, ptr %1, i64 16 + %3 = load ptr, ptr %ptradd3, align 8 + %4 = call ptr @.dyn_search(ptr %3, ptr @"$sel.acquire") + store ptr %4, ptr %.inlinecache, align 8 + store ptr %1, ptr %.cachedtype, align 8 + br label %5 +cache_hit: ; preds = %if.exit + %cache_hit_fn = load ptr, ptr %.inlinecache, align 8 + br label %5 +5: ; preds = %cache_hit, %cache_miss + %fn_phi = phi ptr [ %cache_hit_fn, %cache_hit ], [ %4, %cache_miss ] + %6 = icmp eq ptr %fn_phi, null + br i1 %6, label %missing_function, label %match +missing_function: ; preds = %5 + store %"char[]" { ptr @.panic_msg, i64 44 }, ptr %taddr, align 8 + %7 = load [2 x i64], ptr %taddr, align 8 + store %"char[]" { ptr @.file, i64 16 }, ptr %taddr4, align 8 + %8 = load [2 x i64], ptr %taddr4, align 8 + store %"char[]" { ptr @.func, i64 4 }, ptr %taddr5, align 8 + %9 = load [2 x i64], ptr %taddr5, align 8 + %10 = load ptr, ptr @std.core.builtin.panic, align 8 + call void %10([2 x i64] %7, [2 x i64] %8, [2 x i64] %9, i32 80) + unreachable +match: ; preds = %5 + %11 = load ptr, ptr %allocator2, align 8 + %12 = call i64 %fn_phi(ptr %retparam, ptr %11, i64 12, i32 1, i64 0) + %not_err = icmp eq i64 %12, 0 + %13 = call i1 @llvm.expect.i1(i1 %not_err, i1 true) + br i1 %13, label %after_check, label %assign_optional +assign_optional: ; preds = %match + store i64 %12, ptr %error_var, align 8 + br label %panic_block +after_check: ; preds = %match + %14 = load ptr, ptr %retparam, align 8 + store ptr %14, ptr %taddr6, align 8 + %15 = load ptr, ptr %taddr6, align 8 + %16 = insertvalue %"char[]" undef, ptr %15, 0 + %17 = insertvalue %"char[]" %16, i64 12, 1 + br label %noerr_block +panic_block: ; preds = %assign_optional + %18 = insertvalue %any undef, ptr %error_var, 0 + %19 = insertvalue %any %18, i64 ptrtoint (ptr @"$ct.anyfault" to i64), 1 + store %"char[]" { ptr @.panic_msg.4, i64 36 }, ptr %taddr7, align 8 + %20 = load [2 x i64], ptr %taddr7, align 8 + store %"char[]" { ptr @.file, i64 16 }, ptr %taddr8, align 8 + %21 = load [2 x i64], ptr %taddr8, align 8 + store %"char[]" { ptr @.func, i64 4 }, ptr %taddr9, align 8 + %22 = load [2 x i64], ptr %taddr9, align 8 + store %any %19, ptr %varargslots, align 8 + %23 = insertvalue %"any[]" undef, ptr %varargslots, 0 + %"$$temp" = insertvalue %"any[]" %23, i64 1, 1 + store %"any[]" %"$$temp", ptr %taddr10, align 8 + %24 = load [2 x i64], ptr %taddr10, align 8 + call void @std.core.builtin.panicf([2 x i64] %20, [2 x i64] %21, [2 x i64] %22, i32 244, [2 x i64] %24) + unreachable +noerr_block: ; preds = %after_check + store %"char[]" %17, ptr %buffer, align 8 + store i64 0, ptr %buffer.f, align 8 + %optval = load i64, ptr %buffer.f, align 8 + %not_err11 = icmp eq i64 %optval, 0 + %25 = call i1 @llvm.expect.i1(i1 %not_err11, i1 true) + br i1 %25, label %after_check13, label %assign_optional12 +assign_optional12: ; preds = %noerr_block + store i64 %optval, ptr %buffer.f, align 8 + br label %after_assign +after_check13: ; preds = %noerr_block + store %"char[]" { ptr @.str.5, i64 13 }, ptr %taddr15, align 8 + %26 = load [2 x i64], ptr %taddr15, align 8 + %27 = load [2 x i64], ptr %buffer, align 8 + %28 = call i64 @test.fileReader(ptr %retparam14, [2 x i64] %26, [2 x i64] %27) + %not_err16 = icmp eq i64 %28, 0 + %29 = call i1 @llvm.expect.i1(i1 %not_err16, i1 true) + br i1 %29, label %after_check18, label %assign_optional17 +assign_optional17: ; preds = %after_check13 + store i64 %28, ptr %buffer.f, align 8 + br label %after_assign +after_check18: ; preds = %after_check13 + call void @llvm.memcpy.p0.p0.i32(ptr align 8 %buffer, ptr align 8 %retparam14, i32 16, i1 false) + store i64 0, ptr %buffer.f, align 8 + br label %after_assign +after_assign: ; preds = %after_check18, %assign_optional17, %assign_optional12 + ret void +} + +define i32 @main(i32 %0, ptr %1) #0 { +entry: + call void @test.main() + ret i32 0 +} diff --git a/test/test_suite7/defer/defer_catch_try.c3t b/test/test_suite7/defer/defer_catch_try.c3t new file mode 100644 index 000000000..ff4c3e1ab --- /dev/null +++ b/test/test_suite7/defer/defer_catch_try.c3t @@ -0,0 +1,148 @@ +// #target: macos-x64 +module test; +extern fn void printf(char*, ...); + +fault Abc +{ + FOO +} +fn int! abc(int x) +{ + printf("Enter abc\n"); + defer catch printf("Abc catch %d\n", x); + defer try printf("Abc try %d\n", x); + defer printf("Abc normal %d\n", x); + return x > 0 ? Abc.FOO? : 0; +} +fn int! bcd(int x) +{ + printf("Enter bcd\n"); + for (int i = 0; i < 10; i++) + { + printf("bcd loop\n"); + defer catch printf("Bcd %d catch %d\n", i, x); + defer try printf("Bcd %d try %d\n", i, x); + defer printf("Bcd %d normal %d\n", i, x); + if (i == 1) continue; + printf("bcd check\n"); + if (i == 2) return x > 0 ? Abc.FOO? : 0; + } + return 0; +} + +fn int main() +{ + (void)abc(3); + (void)abc(-1); + (void)bcd(3); + (void)bcd(-1); + return 1; +} + + +/* #expect: test.ll + +define i64 @test.abc(ptr %0, i32 %1) #0 { +entry: + %reterr = alloca i64, align 8 + call void (ptr, ...) @printf(ptr @.str) + %gt = icmp sgt i32 %1, 0 + br i1 %gt, label %cond.lhs, label %cond.rhs + +cond.lhs: ; preds = %entry + store i64 ptrtoint (ptr @"test.Abc$FOO" to i64), ptr %reterr, align 8 + br label %err_retblock + +cond.rhs: ; preds = %entry + br label %cond.phi + +cond.phi: ; preds = %cond.rhs + call void (ptr, ...) @printf(ptr @.str.1, i32 %1) + call void (ptr, ...) @printf(ptr @.str.2, i32 %1) + store i32 0, ptr %0, align 4 + ret i64 0 + +err_retblock: ; preds = %cond.lhs + call void (ptr, ...) @printf(ptr @.str.3, i32 %1) + call void (ptr, ...) @printf(ptr @.str.4, i32 %1) + %2 = load i64, ptr %reterr, align 8 + ret i64 %2 +} + +define i64 @test.bcd(ptr %0, i32 %1) #0 { +entry: + %i = alloca i32, align 4 + %reterr = alloca i64, align 8 + %reterr4 = alloca i64, align 8 + call void (ptr, ...) @printf(ptr @.str.5) + store i32 0, ptr %i, align 4 + br label %loop.cond + +loop.cond: ; preds = %loop.inc, %entry + %2 = load i32, ptr %i, align 4 + %lt = icmp slt i32 %2, 10 + br i1 %lt, label %loop.body, label %loop.exit + +loop.body: ; preds = %loop.cond + call void (ptr, ...) @printf(ptr @.str.6) + %3 = load i32, ptr %i, align 4 + %eq = icmp eq i32 %3, 1 + br i1 %eq, label %if.then, label %if.exit + +if.then: ; preds = %loop.body + %4 = load i32, ptr %i, align 4 + call void (ptr, ...) @printf(ptr @.str.7, i32 %4, i32 %1) + %5 = load i32, ptr %i, align 4 + call void (ptr, ...) @printf(ptr @.str.8, i32 %5, i32 %1) + br label %loop.inc + +if.exit: ; preds = %loop.body + call void (ptr, ...) @printf(ptr @.str.9) + %6 = load i32, ptr %i, align 4 + %eq1 = icmp eq i32 %6, 2 + br i1 %eq1, label %if.then2, label %if.exit3 + +if.then2: ; preds = %if.exit + %gt = icmp sgt i32 %1, 0 + br i1 %gt, label %cond.lhs, label %cond.rhs + +cond.lhs: ; preds = %if.then2 + store i64 ptrtoint (ptr @"test.Abc$FOO" to i64), ptr %reterr, align 8 + br label %err_retblock + +cond.rhs: ; preds = %if.then2 + br label %cond.phi + +cond.phi: ; preds = %cond.rhs + %7 = load i32, ptr %i, align 4 + call void (ptr, ...) @printf(ptr @.str.10, i32 %7, i32 %1) + %8 = load i32, ptr %i, align 4 + call void (ptr, ...) @printf(ptr @.str.11, i32 %8, i32 %1) + store i32 0, ptr %0, align 4 + ret i64 0 + +err_retblock: ; preds = %cond.lhs + %9 = load i32, ptr %i, align 4 + call void (ptr, ...) @printf(ptr @.str.12, i32 %9, i32 %1) + %10 = load i32, ptr %i, align 4 + call void (ptr, ...) @printf(ptr @.str.13, i32 %10, i32 %1) + %11 = load i64, ptr %reterr, align 8 + ret i64 %11 + +if.exit3: ; preds = %if.exit + %12 = load i32, ptr %i, align 4 + call void (ptr, ...) @printf(ptr @.str.14, i32 %12, i32 %1) + %13 = load i32, ptr %i, align 4 + call void (ptr, ...) @printf(ptr @.str.15, i32 %13, i32 %1) + br label %loop.inc + +loop.inc: ; preds = %if.exit3, %if.then + %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 + store i32 0, ptr %0, align 4 + ret i64 0 +} diff --git a/test/test_suite7/defer/defer_nextcase.c3t b/test/test_suite7/defer/defer_nextcase.c3t new file mode 100644 index 000000000..277dc6688 --- /dev/null +++ b/test/test_suite7/defer/defer_nextcase.c3t @@ -0,0 +1,182 @@ +// #target: macos-aarch64 +module test; +import std; + +fn void print(String y) +{ + io::printn(y); +} + +fn void foo(int x) +{ + print("---"); + switch FOO: (x) + { + case 0: + defer print("0.0"); + switch (x) + { + case 0: + defer print("0"); + nextcase FOO: 3; + } + print("Err"); + case 3: + x = 3; + defer print("3.0"); + switch (x) + { + case 3: + defer print("3"); + int j = 2; + nextcase FOO: j; + } + print("Err"); + case 2: + x = 2; + defer print("2.0"); + switch (x) + { + case 2: + defer print("2"); + break FOO; + } + break; + } +} +fn int main() +{ + foo(0); + foo(2); + return 0; +} +/* #expect: test.ll + +define void @test.foo(i32 %0) #0 { +entry: + %x = alloca i32, align 4 + %taddr = alloca %"char[]", align 8 + %switch = alloca i32, align 4 + %switch1 = alloca i32, align 4 + %taddr4 = alloca %"char[]", align 8 + %taddr5 = alloca %"char[]", align 8 + %taddr6 = alloca %"char[]", align 8 + %taddr7 = alloca %"char[]", align 8 + %switch9 = alloca i32, align 4 + %j = alloca i32, align 4 + %taddr12 = alloca %"char[]", align 8 + %taddr13 = alloca %"char[]", align 8 + %taddr15 = alloca %"char[]", align 8 + %taddr16 = alloca %"char[]", align 8 + %switch18 = alloca i32, align 4 + %taddr21 = alloca %"char[]", align 8 + %taddr22 = alloca %"char[]", align 8 + %taddr24 = alloca %"char[]", align 8 + store i32 %0, ptr %x, align 4 + store %"char[]" { ptr @.str, i64 3 }, ptr %taddr, align 8 + %1 = load [2 x i64], ptr %taddr, align 8 + call void @test.print([2 x i64] %1) + %2 = load i32, ptr %x, align 4 + store i32 %2, ptr %switch, align 4 + br label %switch.entry + +switch.entry: ; preds = %switch.case11, %entry + %3 = load i32, ptr %switch, align 4 + switch i32 %3, label %switch.exit25 [ + i32 0, label %switch.case + i32 3, label %switch.case8 + i32 2, label %switch.case17 + ] + +switch.case: ; preds = %switch.entry + %4 = load i32, ptr %x, align 4 + store i32 %4, ptr %switch1, align 4 + br label %switch.entry2 + +switch.entry2: ; preds = %switch.case + %5 = load i32, ptr %switch1, align 4 + switch i32 %5, label %switch.exit [ + i32 0, label %switch.case3 + ] + +switch.case3: ; preds = %switch.entry2 + store %"char[]" { ptr @.str.1, i64 1 }, ptr %taddr4, align 8 + %6 = load [2 x i64], ptr %taddr4, align 8 + call void @test.print([2 x i64] %6) + store %"char[]" { ptr @.str.2, i64 3 }, ptr %taddr5, align 8 + %7 = load [2 x i64], ptr %taddr5, align 8 + call void @test.print([2 x i64] %7) + br label %switch.case8 + +switch.exit: ; preds = %switch.entry2 + store %"char[]" { ptr @.str.3, i64 3 }, ptr %taddr6, align 8 + %8 = load [2 x i64], ptr %taddr6, align 8 + call void @test.print([2 x i64] %8) + store %"char[]" { ptr @.str.4, i64 3 }, ptr %taddr7, align 8 + %9 = load [2 x i64], ptr %taddr7, align 8 + call void @test.print([2 x i64] %9) + br label %switch.exit25 + +switch.case8: ; preds = %switch.entry, %switch.case3 + store i32 3, ptr %x, align 4 + %10 = load i32, ptr %x, align 4 + store i32 %10, ptr %switch9, align 4 + br label %switch.entry10 + +switch.entry10: ; preds = %switch.case8 + %11 = load i32, ptr %switch9, align 4 + switch i32 %11, label %switch.exit14 [ + i32 3, label %switch.case11 + ] + +switch.case11: ; preds = %switch.entry10 + store i32 2, ptr %j, align 4 + %12 = load i32, ptr %j, align 4 + store i32 %12, ptr %switch, align 4 + store %"char[]" { ptr @.str.5, i64 1 }, ptr %taddr12, align 8 + %13 = load [2 x i64], ptr %taddr12, align 8 + call void @test.print([2 x i64] %13) + store %"char[]" { ptr @.str.6, i64 3 }, ptr %taddr13, align 8 + %14 = load [2 x i64], ptr %taddr13, align 8 + call void @test.print([2 x i64] %14) + br label %switch.entry + +switch.exit14: ; preds = %switch.entry10 + store %"char[]" { ptr @.str.7, i64 3 }, ptr %taddr15, align 8 + %15 = load [2 x i64], ptr %taddr15, align 8 + call void @test.print([2 x i64] %15) + store %"char[]" { ptr @.str.8, i64 3 }, ptr %taddr16, align 8 + %16 = load [2 x i64], ptr %taddr16, align 8 + call void @test.print([2 x i64] %16) + br label %switch.exit25 + +switch.case17: ; preds = %switch.entry + store i32 2, ptr %x, align 4 + %17 = load i32, ptr %x, align 4 + store i32 %17, ptr %switch18, align 4 + br label %switch.entry19 + +switch.entry19: ; preds = %switch.case17 + %18 = load i32, ptr %switch18, align 4 + switch i32 %18, label %switch.exit23 [ + i32 2, label %switch.case20 + ] + +switch.case20: ; preds = %switch.entry19 + store %"char[]" { ptr @.str.9, i64 1 }, ptr %taddr21, align 8 + %19 = load [2 x i64], ptr %taddr21, align 8 + call void @test.print([2 x i64] %19) + store %"char[]" { ptr @.str.10, i64 3 }, ptr %taddr22, align 8 + %20 = load [2 x i64], ptr %taddr22, align 8 + call void @test.print([2 x i64] %20) + br label %switch.exit25 + +switch.exit23: ; preds = %switch.entry19 + store %"char[]" { ptr @.str.11, i64 3 }, ptr %taddr24, align 8 + %21 = load [2 x i64], ptr %taddr24, align 8 + call void @test.print([2 x i64] %21) + br label %switch.exit25 + +switch.exit25: ; preds = %switch.exit23, %switch.case20, %switch.exit14, %switch.exit, %switch.entry + ret void +} diff --git a/test/test_suite7/defer/defer_single_stmt.c3 b/test/test_suite7/defer/defer_single_stmt.c3 new file mode 100644 index 000000000..d6bb0cffc --- /dev/null +++ b/test/test_suite7/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_suite7/defer/defer_static_var.c3t b/test/test_suite7/defer/defer_static_var.c3t new file mode 100644 index 000000000..d2f3c456d --- /dev/null +++ b/test/test_suite7/defer/defer_static_var.c3t @@ -0,0 +1,175 @@ +// #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: + %i = alloca i32, align 4 + %i3 = alloca i32, align 4 + %i14 = 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) + call void (ptr, ...) @printf(ptr @.str.2, i32 0) + store i32 0, ptr %i, align 4 + br label %loop.cond +loop.cond: ; preds = %if.exit, %entry + %3 = load i32, ptr %i, align 4 + %lt = icmp slt i32 %3, 100 + br i1 %lt, label %loop.body, label %loop.exit +loop.body: ; preds = %loop.cond + %4 = load i32, ptr %i, align 4 + %eq = icmp eq i32 %4, 0 + br i1 %eq, label %if.then, label %if.exit +if.then: ; preds = %loop.body + %5 = load i32, ptr @main.y, align 4 + %add = add i32 %5, 1 + store i32 %add, ptr @main.y, align 4 + %6 = load i32, ptr %i, align 4 + %7 = load i32, ptr @main.y, align 4 + call void (ptr, ...) @printf(ptr @.str.3, i32 %6, i32 %7) + br label %loop.exit +if.exit: ; preds = %loop.body + call void (ptr, ...) @printf(ptr @.str.4) + %8 = load i32, ptr @main.y, align 4 + %add1 = add i32 %8, 1 + store i32 %add1, ptr @main.y, align 4 + %9 = load i32, ptr %i, align 4 + %10 = load i32, ptr @main.y, align 4 + call void (ptr, ...) @printf(ptr @.str.5, i32 %9, i32 %10) + %11 = load i32, ptr %i, align 4 + %add2 = add i32 %11, 1 + store i32 %add2, ptr %i, align 4 + br label %loop.cond +loop.exit: ; preds = %if.then, %loop.cond + call void (ptr, ...) @printf(ptr @.str.6, i32 1) + store i32 0, ptr %i3, align 4 + br label %loop.cond4 +loop.cond4: ; preds = %if.exit10, %loop.exit + %12 = load i32, ptr %i3, align 4 + %lt5 = icmp slt i32 %12, 100 + br i1 %lt5, label %loop.body6, label %loop.exit13 +loop.body6: ; preds = %loop.cond4 + %13 = load i32, ptr %i3, align 4 + %eq7 = icmp eq i32 %13, 1 + br i1 %eq7, label %if.then8, label %if.exit10 +if.then8: ; preds = %loop.body6 + %14 = load i32, ptr @main.y.7, align 4 + %add9 = add i32 %14, 1 + store i32 %add9, ptr @main.y.7, align 4 + %15 = load i32, ptr %i3, align 4 + %16 = load i32, ptr @main.y.7, align 4 + call void (ptr, ...) @printf(ptr @.str.8, i32 %15, i32 %16) + br label %loop.exit13 +if.exit10: ; preds = %loop.body6 + call void (ptr, ...) @printf(ptr @.str.9) + %17 = load i32, ptr @main.y.7, align 4 + %add11 = add i32 %17, 1 + store i32 %add11, ptr @main.y.7, align 4 + %18 = load i32, ptr %i3, align 4 + %19 = load i32, ptr @main.y.7, align 4 + call void (ptr, ...) @printf(ptr @.str.10, i32 %18, i32 %19) + %20 = load i32, ptr %i3, align 4 + %add12 = add i32 %20, 1 + store i32 %add12, ptr %i3, align 4 + br label %loop.cond4 +loop.exit13: ; preds = %if.then8, %loop.cond4 + call void (ptr, ...) @printf(ptr @.str.11, i32 2) + store i32 0, ptr %i14, align 4 + br label %loop.cond15 +loop.cond15: ; preds = %if.exit21, %loop.exit13 + %21 = load i32, ptr %i14, align 4 + %lt16 = icmp slt i32 %21, 100 + br i1 %lt16, label %loop.body17, label %loop.exit24 +loop.body17: ; preds = %loop.cond15 + %22 = load i32, ptr %i14, align 4 + %eq18 = icmp eq i32 %22, 2 + br i1 %eq18, label %if.then19, label %if.exit21 +if.then19: ; preds = %loop.body17 + %23 = load i32, ptr @main.y.12, align 4 + %add20 = add i32 %23, 1 + store i32 %add20, ptr @main.y.12, align 4 + %24 = load i32, ptr %i14, align 4 + %25 = load i32, ptr @main.y.12, align 4 + call void (ptr, ...) @printf(ptr @.str.13, i32 %24, i32 %25) + br label %loop.exit24 +if.exit21: ; preds = %loop.body17 + call void (ptr, ...) @printf(ptr @.str.14) + %26 = load i32, ptr @main.y.12, align 4 + %add22 = add i32 %26, 1 + store i32 %add22, ptr @main.y.12, align 4 + %27 = load i32, ptr %i14, align 4 + %28 = load i32, ptr @main.y.12, align 4 + call void (ptr, ...) @printf(ptr @.str.15, i32 %27, i32 %28) + %29 = load i32, ptr %i14, align 4 + %add23 = add i32 %29, 1 + store i32 %add23, ptr %i14, align 4 + br label %loop.cond15 +loop.exit24: ; preds = %if.then19, %loop.cond15 + ret void +} \ No newline at end of file diff --git a/test/test_suite7/defer/defer_try_catch.c3t b/test/test_suite7/defer/defer_try_catch.c3t new file mode 100644 index 000000000..c3e1c2f61 --- /dev/null +++ b/test/test_suite7/defer/defer_try_catch.c3t @@ -0,0 +1,10 @@ +// Check that this work. +import std::net; + +fn void main() { + Socket s; + defer { + char[1024] buf; + while (try s.read(&buf)); + } +} \ No newline at end of file diff --git a/test/test_suite7/defer/defer_with_catch.c3t b/test/test_suite7/defer/defer_with_catch.c3t new file mode 100644 index 000000000..88ed0c416 --- /dev/null +++ b/test/test_suite7/defer/defer_with_catch.c3t @@ -0,0 +1,88 @@ +// #target: macos-x64 +module test; + +fn void! test() {} +fn void main() +{ + int a; + defer { if (catch e = test()) {} } + defer { if (catch b = test()) {} } + if (a > 0) return; +} +/* #expect: test.ll + +entry: + %a = alloca i32, align 4 + %b = alloca i64, align 8 + %e = alloca i64, align 8 + %b7 = alloca i64, align 8 + %e14 = alloca i64, align 8 + store i32 0, ptr %a, align 4 + %0 = load i32, ptr %a, align 4 + %gt = icmp sgt i32 %0, 0 + br i1 %gt, label %if.then, label %if.exit +if.then: ; preds = %entry + br label %testblock +testblock: ; preds = %if.then + %1 = call i64 @test.test() + %not_err = icmp eq i64 %1, 0 + %2 = call i1 @llvm.expect.i1(i1 %not_err, i1 true) + br i1 %2, label %after_check, label %assign_optional +assign_optional: ; preds = %testblock + store i64 %1, ptr %b, align 8 + br label %end_block +after_check: ; preds = %testblock + store i64 0, ptr %b, align 8 + br label %end_block +end_block: ; preds = %after_check, %assign_optional + %3 = load i64, ptr %b, align 8 + %i2b = icmp ne i64 %3, 0 + br label %testblock1 +testblock1: ; preds = %end_block + %4 = call i64 @test.test() + %not_err2 = icmp eq i64 %4, 0 + %5 = call i1 @llvm.expect.i1(i1 %not_err2, i1 true) + br i1 %5, label %after_check4, label %assign_optional3 +assign_optional3: ; preds = %testblock1 + store i64 %4, ptr %e, align 8 + br label %end_block5 +after_check4: ; preds = %testblock1 + store i64 0, ptr %e, align 8 + br label %end_block5 +end_block5: ; preds = %after_check4, %assign_optional3 + %6 = load i64, ptr %e, align 8 + %i2b6 = icmp ne i64 %6, 0 + ret void +if.exit: ; preds = %entry + br label %testblock8 +testblock8: ; preds = %if.exit + %7 = call i64 @test.test() + %not_err9 = icmp eq i64 %7, 0 + %8 = call i1 @llvm.expect.i1(i1 %not_err9, i1 true) + br i1 %8, label %after_check11, label %assign_optional10 +assign_optional10: ; preds = %testblock8 + store i64 %7, ptr %b7, align 8 + br label %end_block12 +after_check11: ; preds = %testblock8 + store i64 0, ptr %b7, align 8 + br label %end_block12 +end_block12: ; preds = %after_check11, %assign_optional10 + %9 = load i64, ptr %b7, align 8 + %i2b13 = icmp ne i64 %9, 0 + br label %testblock15 +testblock15: ; preds = %end_block12 + %10 = call i64 @test.test() + %not_err16 = icmp eq i64 %10, 0 + %11 = call i1 @llvm.expect.i1(i1 %not_err16, i1 true) + br i1 %11, label %after_check18, label %assign_optional17 +assign_optional17: ; preds = %testblock15 + store i64 %10, ptr %e14, align 8 + br label %end_block19 +after_check18: ; preds = %testblock15 + store i64 0, ptr %e14, align 8 + br label %end_block19 +end_block19: ; preds = %after_check18, %assign_optional17 + %12 = load i64, ptr %e14, align 8 + %i2b20 = icmp ne i64 %12, 0 + ret void +} diff --git a/test/test_suite7/defer/defer_with_rethrow.c3 b/test/test_suite7/defer/defer_with_rethrow.c3 new file mode 100644 index 000000000..f107bc3be --- /dev/null +++ b/test/test_suite7/defer/defer_with_rethrow.c3 @@ -0,0 +1,15 @@ +// #deprecation: no +fn int! foo() +{ return 1; } + + +fn int! bar() +{ + defer { + {| + foo()!; + |}!!; + } + defer foo()!; // #error: Rethrows are not allowed inside of defers. + return 1; +} \ No newline at end of file diff --git a/test/test_suite7/defer/defer_with_return.c3 b/test/test_suite7/defer/defer_with_return.c3 new file mode 100644 index 000000000..a0ec5c368 --- /dev/null +++ b/test/test_suite7/defer/defer_with_return.c3 @@ -0,0 +1,11 @@ +// #deprecation: no +fn int! bar() +{ + defer { + (void){| + 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_suite7/defer/defer_with_unwrapped.c3t b/test/test_suite7/defer/defer_with_unwrapped.c3t new file mode 100644 index 000000000..365c86a9a --- /dev/null +++ b/test/test_suite7/defer/defer_with_unwrapped.c3t @@ -0,0 +1,53 @@ +// #target: macos-x64 +module test; +import std::io; +// Issue 1982 +fn int main() +{ + defer + { + int! x = 1; + if (catch err = x) unreachable(); + int y = x; + } + return 0; +} +/* #expect: test.ll + +define i32 @main() #0 { +entry: + %x = alloca i32, align 4 + %x.f = alloca i64, align 8 + %err = alloca i64, align 8 + %y = alloca i32, align 4 + store i32 1, ptr %x, align 4 + store i64 0, ptr %x.f, align 8 + br label %testblock + +testblock: ; preds = %entry + %optval = load i64, ptr %x.f, align 8 + %not_err = icmp eq i64 %optval, 0 + %0 = call i1 @llvm.expect.i1(i1 %not_err, i1 true) + br i1 %0, label %after_check, label %assign_optional + +assign_optional: ; preds = %testblock + store i64 %optval, 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, %assign_optional + %1 = load i64, ptr %err, align 8 + %i2b = icmp ne i64 %1, 0 + br i1 %i2b, label %if.then, label %if.exit + +if.then: ; preds = %end_block + unreachable + +if.exit: ; preds = %end_block + %2 = load i32, ptr %x, align 4 + store i32 %2, ptr %y, align 4 + ret i32 0 +} diff --git a/test/test_suite7/define/alias_typename.c3 b/test/test_suite7/define/alias_typename.c3 new file mode 100644 index 000000000..dd659fbbe --- /dev/null +++ b/test/test_suite7/define/alias_typename.c3 @@ -0,0 +1,2 @@ +def ShouldNotBeUppercase = FOO; // #error: A constant may not have a type name +def ShouldNotBeUppercase2 = abc; // #error: An identifier may not be aliased \ No newline at end of file diff --git a/test/test_suite7/define/aliased_consts.c3t b/test/test_suite7/define/aliased_consts.c3t new file mode 100644 index 000000000..943a690d2 --- /dev/null +++ b/test/test_suite7/define/aliased_consts.c3t @@ -0,0 +1,24 @@ +// #target: macos-x64 +module foo; +import std::io; +import std::math; +Matrix4f[2] data @export = {MATRIX4F_IDENTITY, MATRIX4F_IDENTITY}; +Matrix4f x = MATRIX4F_IDENTITY; +fn int main() +{ + io::printfn("%s", x.m00); + return 0; +} + +/* #expect: foo.ll + +@foo__data = local_unnamed_addr global <{ { { { float, [4 x float], float, [4 x float], float, [4 x float], float } } }, { { { float, [4 x float], float, [4 x float], float, [4 x float], float } } } }> <{ { { { float, [4 x float], float, [4 x float], float, [4 x float], float } } } { { { float, [4 x float], float, [4 x float], float, [4 x float], float } } { { float, [4 x float], float, [4 x float], float, [4 x float], float } { float 1.000000e+00, [4 x float] zeroinitializer, float 1.000000e+00, [4 x float] zeroinitializer, float 1.000000e+00, [4 x float] zeroinitializer, float 1.000000e+00 } } }, { { { float, [4 x float], float, [4 x float], float, [4 x float], float } } } { { { float, [4 x float], float, [4 x float], float, [4 x float], float } } { { float, [4 x float], float, [4 x float], float, [4 x float], float } { float 1.000000e+00, [4 x float] zeroinitializer, float 1.000000e+00, [4 x float] zeroinitializer, float 1.000000e+00, [4 x float] zeroinitializer, float 1.000000e+00 } } } }>, align 16 +@foo.x = local_unnamed_addr global { { { float, [4 x float], float, [4 x float], float, [4 x float], float } } } { { { float, [4 x float], float, [4 x float], float, [4 x float], float } } { { float, [4 x float], float, [4 x float], float, [4 x float], float } { float 1.000000e+00, [4 x float] zeroinitializer, float 1.000000e+00, [4 x float] zeroinitializer, float 1.000000e+00, [4 x float] zeroinitializer, float 1.000000e+00 } } }, align 4 + +entry: + %varargslots = alloca [1 x %any], align 16 + %retparam = alloca i64, align 8 + store %any { ptr @foo.x, i64 ptrtoint (ptr @"$ct.float" to i64) }, ptr %varargslots, align 16 + %0 = call i64 @std.io.printfn(ptr %retparam, ptr @.str, i64 2, ptr %varargslots, i64 1) + ret i32 0 +} diff --git a/test/test_suite7/define/common.c3 b/test/test_suite7/define/common.c3 new file mode 100644 index 000000000..d510b562f --- /dev/null +++ b/test/test_suite7/define/common.c3 @@ -0,0 +1,15 @@ +module foo; + +// def = +def standard_foo = __stdin; +def someFunctionIntBool = someFunction(); +def FooInt = Foo(); +def A_CONST_INT = A_CONST(); + +def standard_foo() = ofke; // #error: Expected '=' +def fn foo = fef; // #error: A type, variable, constant or attribute name was expected here +def feokfe = fn void(int); // #error: This looks like you're declaring a function type alias +def Helo = helo; // #error: An identifier may not be aliased +def Helo = OFKE; // #error: A constant may not have a type name alias +def int = int; // #error: 'int' is a reserved keyword, try another name +def main = foo; // #error: 'main' is reserved and cannot be used as an alias. diff --git a/test/test_suite7/define/common2.c3 b/test/test_suite7/define/common2.c3 new file mode 100644 index 000000000..0e130c5ee --- /dev/null +++ b/test/test_suite7/define/common2.c3 @@ -0,0 +1,10 @@ +int ofek; +const OFKEOK = 2; +distinct Helo = int; +fn void Helo.test(&self) {} + +def hupp = Helo.test; +def AOFKE = ofek; // #error: An uppercase alias is expected +def okfoe = OFKEOK; // #error: An alias starting with a lower +def helo = Helo; // #error: To alias a type +def HELO = Helo; // #error: To alias a type diff --git a/test/test_suite7/define/define_name_errors.c3 b/test/test_suite7/define/define_name_errors.c3 new file mode 100644 index 000000000..cd1a3ea00 --- /dev/null +++ b/test/test_suite7/define/define_name_errors.c3 @@ -0,0 +1,8 @@ + +def Foo = int; + +def hello1 = int; // #error: To alias a type, the alias +def hello2 = Foo; // #error: To alias a type, the alias + +def HELLO1 = int; // #error: To alias a type, the alias +def HELLO2 = Foo; // #error: To alias a type, the alias \ No newline at end of file diff --git a/test/test_suite7/define/forbidden_defines.c3 b/test/test_suite7/define/forbidden_defines.c3 new file mode 100644 index 000000000..82c82f2df --- /dev/null +++ b/test/test_suite7/define/forbidden_defines.c3 @@ -0,0 +1,3 @@ +def Abc = int[?]; // #error: Inferred array types can only +def Bcd = anyfault; +def Efd = any; diff --git a/test/test_suite7/define/test_at.c3 b/test/test_suite7/define/test_at.c3 new file mode 100644 index 000000000..071caf6cf --- /dev/null +++ b/test/test_suite7/define/test_at.c3 @@ -0,0 +1,24 @@ +module foo(); +import std::io; + +macro @hello(Type thing) { + io::printfn("%d", $sizeof(thing)); +} +fn void hello() {} + +module bar; + +import foo @public; + +distinct Int = int; +macro Int.@test(self) {} + +def intHello = foo::@hello(); // #error: An at-macro like +def @intHello = foo::hello(); +def @intTest = Int.@test; +def intTest = Int.@test; // #error: An at-macro like + + +fn void main(String[] args) { + @intHello(42); +} \ No newline at end of file diff --git a/test/test_suite7/define/test_at_alias.c3 b/test/test_suite7/define/test_at_alias.c3 new file mode 100644 index 000000000..d3b2f7586 --- /dev/null +++ b/test/test_suite7/define/test_at_alias.c3 @@ -0,0 +1,16 @@ +module foo(); +import std::io; + +macro @hello(Type thing) { + io::printfn("%d", $sizeof(thing)); +} + +module bar; + +import foo @public; + +def @intHello = foo::@hello(); + +fn void main(String[] args) { + @intHello(42); +} \ No newline at end of file diff --git a/test/test_suite7/define/weak_alias_fails.c3 b/test/test_suite7/define/weak_alias_fails.c3 new file mode 100644 index 000000000..522da97e6 --- /dev/null +++ b/test/test_suite7/define/weak_alias_fails.c3 @@ -0,0 +1,32 @@ +module abc; +import std::math; +def Vec2f = std::math::vector::Vec2f @weak; +fn Vec2f foo(Vec2f a) { return a * 2; } + +module gog; +import std::math; +def Vec2f = std::math::vector::Vec2f; + +module deef; +import gog; + +def Vec2f = gog::Vec2f @weak; +fn Vec2f foo(Vec2f a) { return a * 2; } + +module test; +import abc; +import std::math; +fn void test() +{ + Vec2f a; + abc::foo(a); +} + +module test2; +import abc; +import deef; +fn void test2() +{ + Vec2f a; // #error: abc::Vec2f or deef::Vec2f + abc::foo(a); +} \ No newline at end of file diff --git a/test/test_suite7/define/weak_aliases.c3 b/test/test_suite7/define/weak_aliases.c3 new file mode 100644 index 000000000..591b8c029 --- /dev/null +++ b/test/test_suite7/define/weak_aliases.c3 @@ -0,0 +1,32 @@ +module abc; +import std::math; +def Vec2f = std::math::vector::Vec2f @weak; +fn Vec2f foo(Vec2f a) { return a * 2; } + +module gog; +import std::math; +def Vec2f = std::math::vector::Vec2f @weak; + +module deef; +import gog; + +def Vec2f = gog::Vec2f @weak; +fn Vec2f foo(Vec2f a) { return a * 2; } + +module test; +import abc; +import std::math; +fn void test() +{ + Vec2f a; + abc::foo(a); +} + +module test2; +import abc; +import deef; +fn void test2() +{ + Vec2f a; + abc::foo(a); +} \ No newline at end of file diff --git a/test/test_suite7/distinct/disntinct_add_fail.c3 b/test/test_suite7/distinct/disntinct_add_fail.c3 new file mode 100644 index 000000000..d90e42d62 --- /dev/null +++ b/test/test_suite7/distinct/disntinct_add_fail.c3 @@ -0,0 +1,12 @@ +// #target: macos-x64 +module test; +import std; + +fn void main() +{ + DString y; + + y ^= 1; // #error: Expected an integer here + y += 1.0; // #error: A value of type 'DString' + y += 1; // #error: A value of type 'DString' +} diff --git a/test/test_suite7/distinct/distinct_add.c3 b/test/test_suite7/distinct/distinct_add.c3 new file mode 100644 index 000000000..2481e9e50 --- /dev/null +++ b/test/test_suite7/distinct/distinct_add.c3 @@ -0,0 +1,7 @@ +import std; +fn void main() +{ + ZString a = "abc"; + ZString b = a + 1; + io::printfn("%s", b); +} diff --git a/test/test_suite7/distinct/distinct_function.c3t b/test/test_suite7/distinct/distinct_function.c3t new file mode 100644 index 000000000..f5669fc27 --- /dev/null +++ b/test/test_suite7/distinct/distinct_function.c3t @@ -0,0 +1,33 @@ +module test; + +def FnA = fn void(int*); +distinct FnB = FnA; +distinct FnC = inline FnA; + +fn void func(int*) {} + +fn void main() +{ + FnA a = &func; + FnB b = (FnB)&func; + FnB b2 = &func; + FnB b3 = fn (int* x) {}; + FnC c = &func; + c(null); +} + +/* #expect: test.ll + + %a = alloca ptr, align 8 + %b = alloca ptr, align 8 + %b2 = alloca ptr, align 8 + %b3 = alloca ptr, align 8 + %c = alloca ptr, align 8 + store ptr @test.func, ptr %a, align 8 + store ptr @test.func, ptr %b, align 8 + store ptr @test.func, ptr %b2, align 8 + store ptr @"test.main$lambda1", ptr %b3, align 8 + store ptr @test.func, ptr %c, align 8 + %0 = load ptr, ptr %c, align 8 + call void %0(ptr null) + ret void diff --git a/test/test_suite7/distinct/distinct_function_call.c3 b/test/test_suite7/distinct/distinct_function_call.c3 new file mode 100644 index 000000000..23e5eabc3 --- /dev/null +++ b/test/test_suite7/distinct/distinct_function_call.c3 @@ -0,0 +1,16 @@ +def Abc = fn void(); +distinct Foo = inline Abc; +struct Bar +{ + inline Abc a; +} +fn void test() +{ +} +fn void main() +{ + Foo f = &test; + Bar b = { &test }; + f(); + b(); // #error: may be invoked +} \ No newline at end of file diff --git a/test/test_suite7/distinct/distinct_inline_access.c3 b/test/test_suite7/distinct/distinct_inline_access.c3 new file mode 100644 index 000000000..617ff2c63 --- /dev/null +++ b/test/test_suite7/distinct/distinct_inline_access.c3 @@ -0,0 +1,32 @@ +module testing; +import std::io; +import foo; + +fn void main() +{ + FooInt foo; +} + +distinct FooInt = inline Foo; + +struct Bar +{ + FooInt list; +} + +fn void Bar.set(&self, int x) +{ + self.list.set(x); +} + +module foo; + +struct Foo +{ + int x; +} + +fn void Foo.set(&self, int x) +{ + self.x = x; +} \ No newline at end of file diff --git a/test/test_suite7/distinct/distinct_invalid.c3 b/test/test_suite7/distinct/distinct_invalid.c3 new file mode 100644 index 000000000..0e5759dfb --- /dev/null +++ b/test/test_suite7/distinct/distinct_invalid.c3 @@ -0,0 +1,12 @@ +fault Error +{ + ABC +} + +distinct Foo1 = Error; + +distinct Foo3 = void; + +distinct Foo4 = typeid; + +distinct Foo = fn void(Foo** x); // #error: cannot define a new function type \ No newline at end of file diff --git a/test/test_suite7/distinct/distinct_max.c3t b/test/test_suite7/distinct/distinct_max.c3t new file mode 100644 index 000000000..cd48b09e0 --- /dev/null +++ b/test/test_suite7/distinct/distinct_max.c3t @@ -0,0 +1,8 @@ +module test; +distinct Time = long; + +fn void main(String[] args) +{ + Time.min; + Time.max; +} \ No newline at end of file diff --git a/test/test_suite7/distinct/distinct_shift.c3t b/test/test_suite7/distinct/distinct_shift.c3t new file mode 100644 index 000000000..61fdaeb5a --- /dev/null +++ b/test/test_suite7/distinct/distinct_shift.c3t @@ -0,0 +1,47 @@ +// #target: macos-x64 +module test; +import std::io; + +const ODD_PHI16 @local = 0x9e37; + +distinct Lcg16_8 = ushort; + +fn void Lcg16_8.seed(Lcg16_8* lcg, char[2] seed) +{ + *lcg = bitcast(seed, Lcg16_8); +} + +fn char Lcg16_8.next(Lcg16_8* lcg) +{ + Lcg16_8 s = *lcg; + char result = (char)(s >> 8); + *lcg = s * 0x915d + ODD_PHI16; + return result; +} + +fn void main() +{ + Lcg16_8 s; + io::printfn("Point: %d", s.next()); +} + +/* #expect: test.ll + +define zeroext i8 @test.Lcg16_8.next(ptr %0) #0 { +entry: + %s = alloca i16, align 2 + %result = alloca i8, align 1 + %1 = load i16, ptr %0, align 2 + store i16 %1, ptr %s, align 2 + %2 = load i16, ptr %s, align 2 + %lshr = lshr i16 %2, 8 + %3 = freeze i16 %lshr + %trunc = trunc i16 %3 to i8 + store i8 %trunc, ptr %result, align 1 + %4 = load i16, ptr %s, align 2 + %mul = mul i16 %4, -28323 + %add = add i16 %mul, -25033 + store i16 %add, ptr %0, align 2 + %5 = load i8, ptr %result, align 1 + ret i8 %5 +} diff --git a/test/test_suite7/distinct/distinct_slicing.c3 b/test/test_suite7/distinct/distinct_slicing.c3 new file mode 100644 index 000000000..0bc172857 --- /dev/null +++ b/test/test_suite7/distinct/distinct_slicing.c3 @@ -0,0 +1,10 @@ +distinct Foo = double[]; + +fn void main() +{ + Foo x = { 1.0, 4.5, 7.123 }; + Foo y = x; + Foo z = x[0:2]; + Foo w = x[1..2]; + double[] yekf = x[1..1]; // #error: 'Foo' to 'double[]' +} diff --git a/test/test_suite7/distinct/distinct_struct.c3 b/test/test_suite7/distinct/distinct_struct.c3 new file mode 100644 index 000000000..11a18d1f5 --- /dev/null +++ b/test/test_suite7/distinct/distinct_struct.c3 @@ -0,0 +1,28 @@ + +struct Struct +{ + int x; + double y; +} + +distinct Foo = 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_suite7/distinct/distinct_struct_array.c3 b/test/test_suite7/distinct/distinct_struct_array.c3 new file mode 100644 index 000000000..a8b1dee82 --- /dev/null +++ b/test/test_suite7/distinct/distinct_struct_array.c3 @@ -0,0 +1,19 @@ +module test; + +distinct Foo = int; + +struct Struct +{ + Foo x; + int y; +} + +distinct Struct2 = Struct; +distinct StructArr = Struct2[3]; + +fn void test(int x) +{ + StructArr z = { { .x = 1 }, { .y = x }, { 1, 2 }}; + usz len = z.len; + Foo zz = z[2].x; +} diff --git a/test/test_suite7/distinct/distinct_sub.c3t b/test/test_suite7/distinct/distinct_sub.c3t new file mode 100644 index 000000000..3e15c283c --- /dev/null +++ b/test/test_suite7/distinct/distinct_sub.c3t @@ -0,0 +1,58 @@ +distinct Foo = uint; + +macro @test($abc) +{ + return 1u << ($abc - 1); +} + +const Foo TEST = 5; +const Foo TEST_1 = @test(TEST); + +macro @test2($abc) +{ + return 1u << ($abc + 1); +} + +const Foo TEST_2 = @test2(TEST); + +macro @test3($abc) +{ + return 1u << ($abc * 2); +} + +const Foo TEST_3 = @test3(TEST); + +macro @test4($abc) +{ + return 1u << ($abc / 2); +} + +const Foo TEST_4 = @test4(TEST); + +macro @test5($abc) +{ + return 1u << ($abc % 2); +} + +const Foo TEST_5 = @test5(TEST); + +macro @test6($abc) +{ + return 1u << ($abc >> 1); +} + +const Foo TEST_6 = @test6(TEST); + +macro @test7($abc) +{ + return 1u << ($abc >> 1); +} + +const Foo TEST_7 = @test7(TEST); + +macro @test8($abc) +{ + return 1u << ($abc ^ 1); +} + +const Foo TEST_8 = @test8(TEST); diff --git a/test/test_suite7/distinct/distinct_union.c3 b/test/test_suite7/distinct/distinct_union.c3 new file mode 100644 index 000000000..855d509ff --- /dev/null +++ b/test/test_suite7/distinct/distinct_union.c3 @@ -0,0 +1,34 @@ +module test; + +union Union +{ + int x; + double y; +} + +distinct Foo = Union; + +union Union2 +{ + Foo f; + int d; + struct bar + { + Foo x; + } +} +Foo f = { .x = 1 }; + +distinct Union3 = Union2; + +distinct UnionArr = 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_suite7/distinct/test_errors.c3 b/test/test_suite7/distinct/test_errors.c3 new file mode 100644 index 000000000..c98887c28 --- /dev/null +++ b/test/test_suite7/distinct/test_errors.c3 @@ -0,0 +1,11 @@ +module test; + +distinct Int2 = int; + +fn void test() +{ + Int2 a = 1; + a = a + 1; + int b; + a = b; // #error: 'Int2' +} \ No newline at end of file diff --git a/test/test_suite7/distinct/test_ops_on_int.c3 b/test/test_suite7/distinct/test_ops_on_int.c3 new file mode 100644 index 000000000..4013b7c92 --- /dev/null +++ b/test/test_suite7/distinct/test_ops_on_int.c3 @@ -0,0 +1,29 @@ +module test; + +distinct Foo = 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_suite7/distinct/test_ops_on_struct.c3 b/test/test_suite7/distinct/test_ops_on_struct.c3 new file mode 100644 index 000000000..ddd8255da --- /dev/null +++ b/test/test_suite7/distinct/test_ops_on_struct.c3 @@ -0,0 +1,24 @@ +module test; + +struct Struct +{ + int x; + double y; +} + +distinct Foo = 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_suite7/dynamic/any_cast.c3 b/test/test_suite7/dynamic/any_cast.c3 new file mode 100644 index 000000000..85727eac8 --- /dev/null +++ b/test/test_suite7/dynamic/any_cast.c3 @@ -0,0 +1,22 @@ +module test; + +interface Abc : Def +{} + +interface Def +{} + +fn void! test() +{ + any x; + Abc d = x; // #error: cannot implicitly be converted to 'Abc' +} + + +fn void! test2() +{ + Abc x; + any d = x; + Def e = x; + x = e; // #error: is not a parent interface of 'Def' +} diff --git a/test/test_suite7/dynamic/duplicate_definition.c3 b/test/test_suite7/dynamic/duplicate_definition.c3 new file mode 100644 index 000000000..5d0e5583e --- /dev/null +++ b/test/test_suite7/dynamic/duplicate_definition.c3 @@ -0,0 +1,12 @@ +module test; + +interface Abc +{ + fn void abc(); + fn void abc(); // #error: Duplicate definition +} +fn void main() +{ + Abc* g; + g.abc(); +} diff --git a/test/test_suite7/dynamic/dynamic_inherit_deep.c3t b/test/test_suite7/dynamic/dynamic_inherit_deep.c3t new file mode 100644 index 000000000..7c2890401 --- /dev/null +++ b/test/test_suite7/dynamic/dynamic_inherit_deep.c3t @@ -0,0 +1,18 @@ +module abc; +interface AstNode { + fn void free(); + fn double get_span(); + fn void dump(int depth); +} + +interface AstBodyStatement : AstNode { +} + +interface AstExpression : /* AstNode,*/ AstBodyStatement { +} + +fn void main() +{ + AstExpression a = null; + a.dump(100); +} \ No newline at end of file diff --git a/test/test_suite7/dynamic/dynamic_mismatch.c3 b/test/test_suite7/dynamic/dynamic_mismatch.c3 new file mode 100644 index 000000000..b259a872a --- /dev/null +++ b/test/test_suite7/dynamic/dynamic_mismatch.c3 @@ -0,0 +1,25 @@ +interface TestProto +{ + fn int test(int ag); +} + + +struct Foo (TestProto) { int a; } + +fn int! Foo.test(Foo* f) @dynamic { return 1; } // #error: The prototype method has a return type 'int' + +struct Foo1 (TestProto) { int a; } + +fn int Foo1.test(Foo1* f, int a) @dynamic { return 1; } + +struct Foo2 (TestProto) { int a; } + +fn int Foo2.test(Foo2* f) @dynamic { return 1; } // #error: This function is missing parameters, 2 + +struct Foo3 (TestProto) { int a; } + +fn int Foo3.test(Foo3* f, double a) @dynamic { return 1; } // #error: The prototype argument has type 'int' + +struct Foo4 (TestProto) { int a; } + +fn int Foo4.test(Foo4* f, double a, int x) @dynamic { return 1; } // #error: This function has too many parameters diff --git a/test/test_suite7/dynamic/dynamic_tracing.c3t b/test/test_suite7/dynamic/dynamic_tracing.c3t new file mode 100644 index 000000000..c1f0482e1 --- /dev/null +++ b/test/test_suite7/dynamic/dynamic_tracing.c3t @@ -0,0 +1,66 @@ +// #target: macos-x64 +module test; +import std::io; + +interface IFoo { + fn void foo(); +} + +struct Aa(IFoo) { + int dummy; +} + +fn void Aa.foo(&this) @dynamic { + io::printfn("@dynamic: Aa.foo"); +} + +struct Ba(IFoo) { + int dummy; +} + +fn void Ba.foo(&this) @dynamic { + io::printfn("@dynamic: Ba.foo"); +} + +struct Ca(IFoo) { + int dummy; +} + +fn void Ca.foo(&this) @dynamic { + io::printfn("@dynamic: Ca.foo"); +} + + +macro @patch(IFoo *x, $Type) { + usz *y = (usz *) x; + y[1] = (usz) $Type.typeid; +} + +fn void main() { + IFoo foo = @clone((Ba){}); + + io::printfn("Aa.typeid: %p, Ba.typeid: %p", (usz) Aa.typeid, (usz) Ba.typeid); + io::printfn("foo.type: %p", (usz) foo.type); + + @patch(&foo, Aa); + + io::printfn("foo.type: %p", (usz) foo.type); + + foo.foo(); + + foo = (IFoo)any_make(foo.ptr, Ca.typeid); + + io::printfn("foo.type: %p", (usz) foo.type); + + foo.foo(); + +} + +/* #expect: test.ll + +@"$ct.test.Aa" = linkonce global %.introspect { i8 10, i64 0, ptr null, i64 4, i64 0, i64 1, [0 x i64] zeroinitializer }, align 8 +@"$ct.test.Ba" = linkonce global %.introspect { i8 10, i64 0, ptr null, i64 4, i64 0, i64 1, [0 x i64] zeroinitializer }, align 8 +@"$ct.test.Ca" = linkonce global %.introspect { i8 10, i64 0, ptr null, i64 4, i64 0, i64 1, [0 x i64] zeroinitializer }, align 8 +@"$sel.foo" = linkonce_odr constant [4 x i8] c"foo\00", align 1 +@"$c3_dynamic" = internal global [3 x { ptr, ptr, i64 }] [{ ptr, ptr, i64 } { ptr @test.Aa.foo, ptr @"$sel.foo", i64 ptrtoint (ptr @"$ct.test.Aa" to i64) }, { ptr, ptr, i64 } { ptr @test.Ba.foo, ptr @"$sel.foo", i64 ptrtoint (ptr @"$ct.test.Ba" to i64) }, { ptr, ptr, i64 } { ptr @test.Ca.foo, ptr @"$sel.foo", i64 ptrtoint (ptr @"$ct.test.Ca" to i64) }], section "__DATA,__c3_dynamic", align 8 +@llvm.global_ctors = appending global [1 x { i32, ptr, ptr }] [{ i32, ptr, ptr } { i32 1, ptr @.c3_dynamic_retain, ptr null }] diff --git a/test/test_suite7/dynamic/inherit_linux.c3t b/test/test_suite7/dynamic/inherit_linux.c3t new file mode 100644 index 000000000..3ce011da0 --- /dev/null +++ b/test/test_suite7/dynamic/inherit_linux.c3t @@ -0,0 +1,197 @@ +// #target: linux-x64 +module inherit; +import std::io; + +interface Base +{ + fn void tesT(); +} + +interface TestProto2 : Base +{ +} + +interface TestProto : Base +{ + fn void hello(); +} + +fn void Test.tesT(&self) @dynamic +{ +} + +fn void Test.hello(&self) @dynamic +{ +} + +struct Test (TestProto, TestProto2) +{ + void* abc; +} + +fn void main() +{ + TestProto z = mem::alloc(Test); + z.tesT(); + Base w = z; + w.tesT(); +} + +/* #expect: inherit.ll + +%.introspect = type { i8, i64, ptr, i64, i64, i64, [0 x i64] } +%any = type { ptr, i64 } +$.dyn_search = comdat any +$"$ct.inherit.Test" = comdat any +$"$sel.tesT" = comdat any +$"$sel.hello" = comdat any +@"$ct.inherit.Test" = linkonce global %.introspect { i8 10, i64 0, ptr null, i64 8, i64 0, i64 1, [0 x i64] zeroinitializer }, comdat, align 8 +@"$sel.tesT" = linkonce_odr constant [5 x i8] c"tesT\00", comdat, align 1 +@.panic_msg = internal constant [42 x i8] c"No method 'tesT' could be found on target\00", align 1 +@.func = internal constant [5 x i8] c"main\00", align 1 +@std.core.builtin.panic = extern_weak global ptr, align 8 +@"$ct.dyn.inherit.Test.tesT" = weak global { ptr, ptr, ptr } { ptr @inherit.Test.tesT, ptr @"$sel.tesT", ptr inttoptr (i64 -1 to ptr) }, comdat, align 8 +@"$ct.dyn.inherit.Test.hello" = weak global { ptr, ptr, ptr } { ptr @inherit.Test.hello, ptr @"$sel.hello", ptr inttoptr (i64 -1 to ptr) }, comdat, align 8 +@"$sel.hello" = linkonce_odr constant [6 x i8] c"hello\00", comdat, align 1 +@llvm.global_ctors = appending global [1 x { i32, ptr, ptr }] [{ i32, ptr, ptr } { i32 1, ptr @.c3_dynamic_register, ptr null }] +define void @inherit.Test.tesT(ptr %0) #0 { +entry: + ret void +} +define void @inherit.Test.hello(ptr %0) #0 { +entry: + ret void +} + +define void @inherit.main() #0 { +entry: + %z = alloca %any, align 8 + %.inlinecache = alloca ptr, align 8 + %.cachedtype = alloca ptr, align 8 + %w = alloca %any, align 8 + %.inlinecache3 = alloca ptr, align 8 + %.cachedtype4 = alloca ptr, align 8 + store ptr null, ptr %.cachedtype4, align 8 + store ptr null, ptr %.cachedtype, align 8 + %0 = call ptr @std.core.mem.malloc(i64 8) #1 + %1 = insertvalue %any undef, ptr %0, 0 + %2 = insertvalue %any %1, i64 ptrtoint (ptr @"$ct.inherit.Test" to i64), 1 + store %any %2, ptr %z, align 8 + %ptradd = getelementptr inbounds i8, ptr %z, i64 8 + %3 = load i64, ptr %ptradd, align 8 + %4 = inttoptr i64 %3 to ptr + %type = load ptr, ptr %.cachedtype, align 8 + %5 = icmp eq ptr %4, %type + br i1 %5, label %cache_hit, label %cache_miss +cache_miss: ; preds = %entry + %ptradd1 = getelementptr inbounds i8, ptr %4, i64 16 + %6 = load ptr, ptr %ptradd1, align 8 + %7 = call ptr @.dyn_search(ptr %6, ptr @"$sel.tesT") + store ptr %7, ptr %.inlinecache, align 8 + store ptr %4, ptr %.cachedtype, align 8 + br label %8 +cache_hit: ; preds = %entry + %cache_hit_fn = load ptr, ptr %.inlinecache, align 8 + br label %8 +8: ; preds = %cache_hit, %cache_miss + %fn_phi = phi ptr [ %cache_hit_fn, %cache_hit ], [ %7, %cache_miss ] + %9 = icmp eq ptr %fn_phi, null + br i1 %9, label %missing_function, label %match +missing_function: ; preds = %8 + %10 = load ptr, ptr @std.core.builtin.panic, align 8 + call void %10(ptr @.panic_msg, i64 41, ptr @.file + unreachable +match: ; preds = %8 + %11 = load ptr, ptr %z, align 8 + call void %fn_phi(ptr %11) + %12 = load %any, ptr %z, align 8 + store %any %12, ptr %w, align 8 + %ptradd2 = getelementptr inbounds i8, ptr %w, i64 8 + %13 = load i64, ptr %ptradd2, align 8 + %14 = inttoptr i64 %13 to ptr + %type5 = load ptr, ptr %.cachedtype4, align 8 + %15 = icmp eq ptr %14, %type5 + br i1 %15, label %cache_hit8, label %cache_miss6 +cache_miss6: ; preds = %match + %ptradd7 = getelementptr inbounds i8, ptr %14, i64 16 + %16 = load ptr, ptr %ptradd7, align 8 + %17 = call ptr @.dyn_search(ptr %16, ptr @"$sel.tesT") + store ptr %17, ptr %.inlinecache3, align 8 + store ptr %14, ptr %.cachedtype4, align 8 + br label %18 +cache_hit8: ; preds = %match + %cache_hit_fn9 = load ptr, ptr %.inlinecache3, align 8 + br label %18 +18: ; preds = %cache_hit8, %cache_miss6 + %fn_phi10 = phi ptr [ %cache_hit_fn9, %cache_hit8 ], [ %17, %cache_miss6 ] + %19 = icmp eq ptr %fn_phi10, null + br i1 %19, label %missing_function11, label %match12 +missing_function11: ; preds = %18 + %20 = load ptr, ptr @std.core.builtin.panic, align 8 + call void %20(ptr @.panic_msg, i64 41, ptr @.file, i64 16, ptr @.func, i64 4, i32 36) + unreachable +match12: ; preds = %18 + %21 = load ptr, ptr %w, align 8 + call void %fn_phi10(ptr %21) + ret void +} +define i32 @main(i32 %0, ptr %1) #0 { +entry: + call void @inherit.main() + ret i32 0 +} + +define weak ptr @.dyn_search(ptr %0, ptr %1) unnamed_addr comdat { +entry: + br label %check +check: ; preds = %no_match, %entry + %2 = phi ptr [ %0, %entry ], [ %9, %no_match ] + %3 = icmp eq ptr %2, null + br i1 %3, label %missing_function, label %compare +missing_function: ; preds = %check + ret ptr null +compare: ; preds = %check + %4 = getelementptr inbounds + %5 = load ptr, ptr %4, align 8 + %6 = icmp eq ptr %5, %1 + br i1 %6, label %match, label %no_match +match: ; preds = %compare + %7 = load ptr, ptr %2, align 8 + ret ptr %7 +no_match: ; preds = %compare + %8 = getelementptr inbounds + %9 = load ptr, ptr %8, align 8 + br label %check +} +define internal void @.c3_dynamic_register() align 8 { +entry: + %next_val = load ptr, ptr getelementptr inbounds + %0 = icmp eq ptr %next_val, inttoptr (i64 -1 to ptr) + br i1 %0, label %dtable_check, label %dtable_skip +dtable_check: ; preds = %dtable_check, %entry + %dtable_ref = phi ptr [ getelementptr inbounds + %dtable_ptr = load ptr, ptr %dtable_ref, align 8 + %1 = icmp eq ptr %dtable_ptr, null + %next_dtable_ref = getelementptr inbounds + br i1 %1, label %dtable_found, label %dtable_check +dtable_found: ; preds = %dtable_check + store ptr @"$ct.dyn.inherit.Test.tesT", ptr %dtable_ref, align 8 + store ptr null, ptr getelementptr inbounds + br label %dtable_skip +dtable_skip: ; preds = %dtable_found, %entry + %next_val1 = load ptr, ptr getelementptr inbounds + %2 = icmp eq ptr %next_val1, inttoptr (i64 -1 to ptr) + br i1 %2, label %dtable_check2, label %dtable_skip7 +dtable_check2: ; preds = %dtable_check2, %dtable_skip + %dtable_ref3 = phi ptr [ getelementptr inbounds + %dtable_ptr4 = load ptr, ptr %dtable_ref3, align 8 + %3 = icmp eq ptr %dtable_ptr4, null + %next_dtable_ref5 = getelementptr inbounds + br i1 %3, label %dtable_found6, label %dtable_check2 +dtable_found6: ; preds = %dtable_check2 + store ptr @"$ct.dyn.inherit.Test.hello", ptr %dtable_ref3, align 8 + store ptr null, ptr getelementptr inbounds + br label %dtable_skip7 +dtable_skip7: ; preds = %dtable_found6, %dtable_skip + ret void +} \ No newline at end of file diff --git a/test/test_suite7/dynamic/inherit_macos.c3t b/test/test_suite7/dynamic/inherit_macos.c3t new file mode 100644 index 000000000..cb62b34df --- /dev/null +++ b/test/test_suite7/dynamic/inherit_macos.c3t @@ -0,0 +1,176 @@ +// #target: macos-x64 +module inherit; +import std::io; + +interface Base +{ + fn void tesT(); +} + +interface TestProto2 : Base +{ +} + +interface TestProto : Base +{ + fn void hello(); +} + +fn void Test.tesT(&self) @dynamic +{ +} + +fn void Test.hello(&self) @dynamic +{ +} + +struct Test (TestProto, TestProto2) +{ + void* abc; +} + +fn void main() +{ + TestProto z = mem::alloc(Test); + z.tesT(); + Base w = z; + w.tesT(); +} + +/* #expect: inherit.ll + +%.introspect = type { i8, i64, ptr, i64, i64, i64, [0 x i64] } +%any = type { ptr, i64 } + +@"$ct.inherit.Test" = linkonce global %.introspect { i8 10, i64 0, ptr null, i64 8, i64 0, i64 1, [0 x i64] zeroinitializer }, align 8 +@"$sel.tesT" = linkonce_odr constant [5 x i8] c"tesT\00", align 1 +@.panic_msg = internal constant [42 x i8] c"No method 'tesT' could be found on target\00", align 1 +@.func = internal constant [5 x i8] c"main\00", align 1 +@std.core.builtin.panic = extern_weak global ptr, align 8 +@"$sel.hello" = linkonce_odr constant [6 x i8] c"hello\00", align 1 +@"$c3_dynamic" = internal global [2 x { ptr, ptr, i64 }] [{ ptr, ptr, i64 } { ptr @inherit.Test.tesT, ptr @"$sel.tesT", i64 ptrtoint (ptr @"$ct.inherit.Test" to i64) }, { ptr, ptr, i64 } { ptr @inherit.Test.hello, ptr @"$sel.hello", i64 ptrtoint (ptr @"$ct.inherit.Test" to i64) }], section "__DATA,__c3_dynamic", align 8 + +define void @inherit.Test.tesT(ptr %0) #0 { +entry: + ret void +} + +define void @inherit.Test.hello(ptr %0) #0 { +entry: + ret void +} + +define void @inherit.main() #0 { +entry: + %z = alloca %any, align 8 + %.inlinecache = alloca ptr, align 8 + %.cachedtype = alloca ptr, align 8 + %w = alloca %any, align 8 + %.inlinecache3 = alloca ptr, align 8 + %.cachedtype4 = alloca ptr, align 8 + store ptr null, ptr %.cachedtype4, align 8 + store ptr null, ptr %.cachedtype, align 8 + %0 = call ptr @std.core.mem.malloc(i64 8) #1 + %1 = insertvalue %any undef, ptr %0, 0 + %2 = insertvalue %any %1, i64 ptrtoint (ptr @"$ct.inherit.Test" to i64), 1 + store %any %2, ptr %z, align 8 + %ptradd = getelementptr inbounds i8, ptr %z, i64 8 + %3 = load i64, ptr %ptradd, align 8 + %4 = inttoptr i64 %3 to ptr + %type = load ptr, ptr %.cachedtype, align 8 + %5 = icmp eq ptr %4, %type + br i1 %5, label %cache_hit, label %cache_miss + +cache_miss: ; preds = %entry + %ptradd1 = getelementptr inbounds i8, ptr %4, i64 16 + %6 = load ptr, ptr %ptradd1, align 8 + %7 = call ptr @.dyn_search(ptr %6, ptr @"$sel.tesT") + store ptr %7, ptr %.inlinecache, align 8 + store ptr %4, ptr %.cachedtype, align 8 + br label %8 + +cache_hit: ; preds = %entry + %cache_hit_fn = load ptr, ptr %.inlinecache, align 8 + br label %8 + +8: ; preds = %cache_hit, %cache_miss + %fn_phi = phi ptr [ %cache_hit_fn, %cache_hit ], [ %7, %cache_miss ] + %9 = icmp eq ptr %fn_phi, null + br i1 %9, label %missing_function, label %match + +missing_function: ; preds = %8 + %10 = load ptr, ptr @std.core.builtin.panic, align 8 + call void %10(ptr @.panic_msg, i64 41, + unreachable + +match: ; preds = %8 + %11 = load ptr, ptr %z, align 8 + call void %fn_phi(ptr %11) + %12 = load %any, ptr %z, align 8 + store %any %12, ptr %w, align 8 + %ptradd2 = getelementptr inbounds i8, ptr %w, i64 8 + %13 = load i64, ptr %ptradd2, align 8 + %14 = inttoptr i64 %13 to ptr + %type5 = load ptr, ptr %.cachedtype4, align 8 + %15 = icmp eq ptr %14, %type5 + br i1 %15, label %cache_hit8, label %cache_miss6 + +cache_miss6: ; preds = %match + %ptradd7 = getelementptr inbounds i8, ptr %14, i64 16 + %16 = load ptr, ptr %ptradd7, align 8 + %17 = call ptr @.dyn_search(ptr %16, ptr @"$sel.tesT") + store ptr %17, ptr %.inlinecache3, align 8 + store ptr %14, ptr %.cachedtype4, align 8 + br label %18 + +cache_hit8: ; preds = %match + %cache_hit_fn9 = load ptr, ptr %.inlinecache3, align 8 + br label %18 + +18: ; preds = %cache_hit8, %cache_miss6 + %fn_phi10 = phi ptr [ %cache_hit_fn9, %cache_hit8 ], [ %17, %cache_miss6 ] + %19 = icmp eq ptr %fn_phi10, null + br i1 %19, label %missing_function11, label %match12 + +missing_function11: ; preds = %18 + %20 = load ptr, ptr @std.core.builtin.panic, align 8 + call void %20(ptr @.panic_msg, i64 41 + unreachable + +match12: ; preds = %18 + %21 = load ptr, ptr %w, align 8 + call void %fn_phi10(ptr %21) + ret void +} +define i32 @main(i32 %0, ptr %1) #0 { +entry: + call void @inherit.main() + ret i32 0 +} +define weak ptr @.dyn_search(ptr %0, ptr %1) unnamed_addr { +entry: + br label %check + +check: ; preds = %no_match, %entry + %2 = phi ptr [ %0, %entry ], [ %9, %no_match ] + %3 = icmp eq ptr %2, null + br i1 %3, label %missing_function, label %compare + +missing_function: ; preds = %check + ret ptr null + +compare: ; preds = %check + %4 = getelementptr inbounds + %5 = load ptr, ptr %4, align 8 + %6 = icmp eq ptr %5, %1 + br i1 %6, label %match, label %no_match + +match: ; preds = %compare + %7 = load ptr, ptr %2, align 8 + ret ptr %7 + +no_match: ; preds = %compare + %8 = getelementptr inbounds + %9 = load ptr, ptr %8, align 8 + br label %check +} diff --git a/test/test_suite7/dynamic/inline_protocol.c3 b/test/test_suite7/dynamic/inline_protocol.c3 new file mode 100644 index 000000000..76494b27b --- /dev/null +++ b/test/test_suite7/dynamic/inline_protocol.c3 @@ -0,0 +1,35 @@ +interface Foo +{ + fn int foo(); +} + +struct Abc (Foo) +{ + int a; +} + +struct Bcd +{ + inline Abc a; +} + +struct Def +{ + Abc a; +} + +fn int Abc.foo(&self) @dynamic => 1; + +distinct Foob = inline Abc; + +fn void test1() +{ + Foob b; + Abc x; + Bcd y; + Def d; + Foo f = &x; + f = &b; + f = &y; + f = &d; // #error: assume the interface is implemented +} \ No newline at end of file diff --git a/test/test_suite7/dynamic/null_and_protocol.c3t b/test/test_suite7/dynamic/null_and_protocol.c3t new file mode 100644 index 000000000..fed630259 --- /dev/null +++ b/test/test_suite7/dynamic/null_and_protocol.c3t @@ -0,0 +1,35 @@ +// #target: macos-x64 +module test; + +interface Test {} + +fn void main() +{ + Test a; + bool x = a == null; + a = null; + any z = a; + z = null; +} + +/* #expect: test.ll + +%any = type { ptr, i64 } +@"$ct.void" = linkonce global %.introspect { i8 0, i64 0, ptr null, i64 1, i64 0, i64 0, [0 x i64] zeroinitializer }, align 8 + +define void @test.main() #0 { +entry: + %a = alloca %any, align 8 + %x = alloca i8, align 1 + %z = alloca %any, align 8 + store %any zeroinitializer, ptr %a, align 8 + %0 = load ptr, ptr %a, align 8 + %eq = icmp eq ptr %0, null + %1 = zext i1 %eq to i8 + store i8 %1, ptr %x, align 1 + store %any { ptr null, i64 ptrtoint (ptr @"$ct.void" to i64) }, ptr %a, align 8 + %2 = load %any, ptr %a, align 8 + store %any %2, ptr %z, align 8 + store %any { ptr null, i64 ptrtoint (ptr @"$ct.void" to i64) }, ptr %z, align 8 + ret void +} \ No newline at end of file diff --git a/test/test_suite7/dynamic/overlapping_function_linux.c3t b/test/test_suite7/dynamic/overlapping_function_linux.c3t new file mode 100644 index 000000000..05c63b4df --- /dev/null +++ b/test/test_suite7/dynamic/overlapping_function_linux.c3t @@ -0,0 +1,190 @@ +// #target: linux-x64 +module overlap; +import std::io; + +interface TestProto +{ + fn void tesT(); +} + +interface TestProto2 +{ + fn void tesT(); +} + +fn void Test.tesT(&self) @dynamic +{ +} + +fn void Test.foo(&self) @dynamic {} + +struct Test (TestProto, TestProto2) +{ + void* abc; +} + +fn void main() +{ + TestProto z = mem::alloc(Test); + z.tesT(); + TestProto2 w = (TestProto2)z; + w.tesT(); +} + +/* #expect: overlap.ll + +%.introspect = type { i8, i64, ptr, i64, i64, i64, [0 x i64] } +%any = type { ptr, i64 } +@"$ct.overlap.Test" = linkonce global %.introspect { i8 10, i64 0, ptr null, i64 8, i64 0, i64 1, [0 x i64] zeroinitializer }, comdat, align 8 +@"$sel.tesT" = linkonce_odr constant [5 x i8] c"tesT\00", comdat, align 1 +@.panic_msg = internal constant [42 x i8] c"No method 'tesT' could be found on target\00", align 1 +@.file = internal constant [30 x i8] c"overlapping_function_linux.c3\00", align 1 +@.func = internal constant [5 x i8] c"main\00", align 1 +@std.core.builtin.panic = extern_weak global ptr, align 8 +@"$ct.dyn.overlap.Test.tesT" = weak global { ptr, ptr, ptr } { ptr @overlap.Test.tesT, ptr @"$sel.tesT", ptr inttoptr (i64 -1 to ptr) }, comdat, align 8 +@"$ct.dyn.overlap.Test.foo" = weak global { ptr, ptr, ptr } { ptr @overlap.Test.foo, ptr @"$sel.foo", ptr inttoptr (i64 -1 to ptr) }, comdat, align 8 +@"$sel.foo" = linkonce_odr constant [4 x i8] c"foo\00", comdat, align 1 +@llvm.global_ctors = appending global [1 x { i32, ptr, ptr }] [{ i32, ptr, ptr } { i32 1, ptr @.c3_dynamic_register, ptr null }] +; Function Attrs: nounwind uwtable +define void @overlap.Test.tesT(ptr %0) #0 { +entry: + ret void +} + +define void @overlap.Test.foo(ptr %0) #0 { +entry: + ret void +} + +define void @overlap.main() #0 { +entry: + %z = alloca %any, align 8 + %.inlinecache = alloca ptr, align 8 + %.cachedtype = alloca ptr, align 8 + %w = alloca %any, align 8 + %.inlinecache3 = alloca ptr, align 8 + %.cachedtype4 = alloca ptr, align 8 + store ptr null, ptr %.cachedtype4, align 8 + store ptr null, ptr %.cachedtype, align 8 + %0 = call ptr @std.core.mem.malloc(i64 8) #1 + %1 = insertvalue %any undef, ptr %0, 0 + %2 = insertvalue %any %1, i64 ptrtoint (ptr @"$ct.overlap.Test" to i64), 1 + store %any %2, ptr %z, align 8 + %ptradd = getelementptr inbounds i8, ptr %z, i64 8 + %3 = load i64, ptr %ptradd, align 8 + %4 = inttoptr i64 %3 to ptr + %type = load ptr, ptr %.cachedtype, align 8 + %5 = icmp eq ptr %4, %type + br i1 %5, label %cache_hit, label %cache_miss +cache_miss: ; preds = %entry + %ptradd1 = getelementptr inbounds i8, ptr %4, i64 16 + %6 = load ptr, ptr %ptradd1, align 8 + %7 = call ptr @.dyn_search(ptr %6, ptr @"$sel.tesT") + store ptr %7, ptr %.inlinecache, align 8 + store ptr %4, ptr %.cachedtype, align 8 + br label %8 +cache_hit: ; preds = %entry + %cache_hit_fn = load ptr, ptr %.inlinecache, align 8 + br label %8 +8: ; preds = %cache_hit, %cache_miss + %fn_phi = phi ptr [ %cache_hit_fn, %cache_hit ], [ %7, %cache_miss ] + %9 = icmp eq ptr %fn_phi, null + br i1 %9, label %missing_function, label %match +missing_function: ; preds = %8 + %10 = load ptr, ptr @std.core.builtin.panic, align 8 + call void %10(ptr @.panic_msg, i64 41, ptr @.file + unreachable +match: ; preds = %8 + %11 = load ptr, ptr %z, align 8 + call void %fn_phi(ptr %11) + %12 = load %any, ptr %z, align 8 + store %any %12, ptr %w, align 8 + %ptradd2 = getelementptr inbounds i8, ptr %w, i64 8 + %13 = load i64, ptr %ptradd2, align 8 + %14 = inttoptr i64 %13 to ptr + %type5 = load ptr, ptr %.cachedtype4, align 8 + %15 = icmp eq ptr %14, %type5 + br i1 %15, label %cache_hit8, label %cache_miss6 +cache_miss6: ; preds = %match + %ptradd7 = getelementptr inbounds i8, ptr %14, i64 16 + %16 = load ptr, ptr %ptradd7, align 8 + %17 = call ptr @.dyn_search(ptr %16, ptr @"$sel.tesT") + store ptr %17, ptr %.inlinecache3, align 8 + store ptr %14, ptr %.cachedtype4, align 8 + br label %18 +cache_hit8: ; preds = %match + %cache_hit_fn9 = load ptr, ptr %.inlinecache3, align 8 + br label %18 +18: ; preds = %cache_hit8, %cache_miss6 + %fn_phi10 = phi ptr [ %cache_hit_fn9, %cache_hit8 ], [ %17, %cache_miss6 ] + %19 = icmp eq ptr %fn_phi10, null + br i1 %19, label %missing_function11, label %match12 +missing_function11: ; preds = %18 + %20 = load ptr, ptr @std.core.builtin.panic, align 8 + call void %20(ptr @.panic_msg, i64 41, ptr @.file + unreachable +match12: ; preds = %18 + %21 = load ptr, ptr %w, align 8 + call void %fn_phi10(ptr %21) + ret void +} + +define i32 @main(i32 %0, ptr %1) #0 { +entry: + call void @overlap.main() + ret i32 0 +} +define weak ptr @.dyn_search(ptr %0, ptr %1) unnamed_addr comdat { +entry: + br label %check +check: ; preds = %no_match, %entry + %2 = phi ptr [ %0, %entry ], [ %9, %no_match ] + %3 = icmp eq ptr %2, null + br i1 %3, label %missing_function, label %compare +missing_function: ; preds = %check + ret ptr null +compare: ; preds = %check + %4 = getelementptr inbounds + %5 = load ptr, ptr %4, align 8 + %6 = icmp eq ptr %5, %1 + br i1 %6, label %match, label %no_match +match: ; preds = %compare + %7 = load ptr, ptr %2, align 8 + ret ptr %7 +no_match: ; preds = %compare + %8 = getelementptr inbounds + %9 = load ptr, ptr %8, align 8 + br label %check +} +define internal void @.c3_dynamic_register() align 8 { +entry: + %next_val = load ptr, ptr getelementptr inbounds + %0 = icmp eq ptr %next_val, inttoptr (i64 -1 to ptr) + br i1 %0, label %dtable_check, label %dtable_skip +dtable_check: ; preds = %dtable_check, %entry + %dtable_ref = phi ptr [ getelementptr inbounds + %dtable_ptr = load ptr, ptr %dtable_ref, align 8 + %1 = icmp eq ptr %dtable_ptr, null + %next_dtable_ref = getelementptr inbounds + br i1 %1, label %dtable_found, label %dtable_check +dtable_found: ; preds = %dtable_check + store ptr @"$ct.dyn.overlap.Test.tesT", ptr %dtable_ref, align 8 + store ptr null, ptr getelementptr inbounds + br label %dtable_skip +dtable_skip: ; preds = %dtable_found, %entry + %next_val1 = load ptr, ptr getelementptr inbounds + %2 = icmp eq ptr %next_val1, inttoptr (i64 -1 to ptr) + br i1 %2, label %dtable_check2, label %dtable_skip7 +dtable_check2: ; preds = %dtable_check2, %dtable_skip + %dtable_ref3 = phi ptr [ getelementptr inbounds + %dtable_ptr4 = load ptr, ptr %dtable_ref3, align 8 + %3 = icmp eq ptr %dtable_ptr4, null + %next_dtable_ref5 = getelementptr inbounds + br i1 %3, label %dtable_found6, label %dtable_check2 +dtable_found6: ; preds = %dtable_check2 + store ptr @"$ct.dyn.overlap.Test.foo", ptr %dtable_ref3, align 8 + store ptr null, ptr getelementptr inbounds + br label %dtable_skip7 +dtable_skip7: ; preds = %dtable_found6, %dtable_skip + ret void +} \ No newline at end of file diff --git a/test/test_suite7/dynamic/overlapping_function_macos.c3t b/test/test_suite7/dynamic/overlapping_function_macos.c3t new file mode 100644 index 000000000..a49c8a18a --- /dev/null +++ b/test/test_suite7/dynamic/overlapping_function_macos.c3t @@ -0,0 +1,174 @@ +// #target: macos-x64 +module overlap; +import std::io; + +interface TestProto +{ + fn void tesT(); +} + +interface TestProto2 +{ + fn void tesT(); +} + +fn void Test.tesT(&self) @dynamic +{ +} + +fn void Test.foo(&self) @dynamic {} + +struct Test (TestProto, TestProto2) +{ + void* abc; +} + +fn void main() +{ + TestProto z = mem::alloc(Test); + z.tesT(); + TestProto2 w = (TestProto2)z; + w.tesT(); +} + +/* #expect: overlap.ll +%.introspect = type { i8, i64, ptr, i64, i64, i64, [0 x i64] } +%any = type { ptr, i64 } + +@"$ct.overlap.Test" = linkonce global %.introspect { i8 10, i64 0, ptr null, i64 8, i64 0, i64 1, [0 x i64] zeroinitializer }, align 8 +@"$sel.tesT" = linkonce_odr constant [5 x i8] c"tesT\00", align 1 +@.panic_msg = internal constant [42 x i8] c"No method 'tesT' could be found on target\00", align 1 +@.file = internal constant [30 x i8] c"overlapping_function_macos.c3\00", align 1 +@.func = internal constant [5 x i8] c"main\00", align 1 +@std.core.builtin.panic = extern_weak global ptr, align 8 +@"$sel.foo" = linkonce_odr constant [4 x i8] c"foo\00", align 1 +@"$c3_dynamic" = internal global [2 x { ptr, ptr, i64 }] [{ ptr, ptr, i64 } { ptr @overlap.Test.tesT, ptr @"$sel.tesT", i64 ptrtoint (ptr @"$ct.overlap.Test" to i64) }, { ptr, ptr, i64 } { ptr @overlap.Test.foo, ptr @"$sel.foo", i64 ptrtoint (ptr @"$ct.overlap.Test" to i64) }], section "__DATA,__c3_dynamic", align 8 + +; Function Attrs: nounwind uwtable +define void @overlap.Test.tesT(ptr %0) #0 { +entry: + ret void +} + +define void @overlap.Test.foo(ptr %0) #0 { +entry: + ret void +} + +define void @overlap.main() #0 { +entry: + %z = alloca %any, align 8 + %.inlinecache = alloca ptr, align 8 + %.cachedtype = alloca ptr, align 8 + %w = alloca %any, align 8 + %.inlinecache3 = alloca ptr, align 8 + %.cachedtype4 = alloca ptr, align 8 + store ptr null, ptr %.cachedtype4, align 8 + store ptr null, ptr %.cachedtype, align 8 + %0 = call ptr @std.core.mem.malloc(i64 8) #1 + %1 = insertvalue %any undef, ptr %0, 0 + %2 = insertvalue %any %1, i64 ptrtoint (ptr @"$ct.overlap.Test" to i64), 1 + store %any %2, ptr %z, align 8 + %ptradd = getelementptr inbounds i8, ptr %z, i64 8 + %3 = load i64, ptr %ptradd, align 8 + %4 = inttoptr i64 %3 to ptr + %type = load ptr, ptr %.cachedtype, align 8 + %5 = icmp eq ptr %4, %type + br i1 %5, label %cache_hit, label %cache_miss + +cache_miss: ; preds = %entry + %ptradd1 = getelementptr inbounds i8, ptr %4, i64 16 + %6 = load ptr, ptr %ptradd1, align 8 + %7 = call ptr @.dyn_search(ptr %6, ptr @"$sel.tesT") + store ptr %7, ptr %.inlinecache, align 8 + store ptr %4, ptr %.cachedtype, align 8 + br label %8 + +cache_hit: ; preds = %entry + %cache_hit_fn = load ptr, ptr %.inlinecache, align 8 + br label %8 + +8: ; preds = %cache_hit, %cache_miss + %fn_phi = phi ptr [ %cache_hit_fn, %cache_hit ], [ %7, %cache_miss ] + %9 = icmp eq ptr %fn_phi, null + br i1 %9, label %missing_function, label %match + +missing_function: ; preds = %8 + %10 = load ptr, ptr @std.core.builtin.panic, align 8 + call void %10(ptr @.panic_msg, i64 41, ptr @.file + unreachable + +match: ; preds = %8 + %11 = load ptr, ptr %z, align 8 + call void %fn_phi(ptr %11) + %12 = load %any, ptr %z, align 8 + store %any %12, ptr %w, align 8 + %ptradd2 = getelementptr inbounds i8, ptr %w, i64 8 + %13 = load i64, ptr %ptradd2, align 8 + %14 = inttoptr i64 %13 to ptr + %type5 = load ptr, ptr %.cachedtype4, align 8 + %15 = icmp eq ptr %14, %type5 + br i1 %15, label %cache_hit8, label %cache_miss6 + +cache_miss6: ; preds = %match + %ptradd7 = getelementptr inbounds i8, ptr %14, i64 16 + %16 = load ptr, ptr %ptradd7, align 8 + %17 = call ptr @.dyn_search(ptr %16, ptr @"$sel.tesT") + store ptr %17, ptr %.inlinecache3, align 8 + store ptr %14, ptr %.cachedtype4, align 8 + br label %18 + +cache_hit8: ; preds = %match + %cache_hit_fn9 = load ptr, ptr %.inlinecache3, align 8 + br label %18 + +18: ; preds = %cache_hit8, %cache_miss6 + %fn_phi10 = phi ptr [ %cache_hit_fn9, %cache_hit8 ], [ %17, %cache_miss6 ] + %19 = icmp eq ptr %fn_phi10, null + br i1 %19, label %missing_function11, label %match12 + +missing_function11: ; preds = %18 + %20 = load ptr, ptr @std.core.builtin.panic, align 8 + call void %20(ptr @.panic_msg, i64 41, ptr @.file + unreachable + +match12: ; preds = %18 + %21 = load ptr, ptr %w, align 8 + call void %fn_phi10(ptr %21) + ret void +} + +; Function Attrs: +define i32 @main(i32 %0, ptr %1) #0 { +entry: + call void @overlap.main() + ret i32 0 +} + +define weak ptr @.dyn_search(ptr %0, ptr %1) unnamed_addr { +entry: + br label %check + +check: ; preds = %no_match, %entry + %2 = phi ptr [ %0, %entry ], [ %9, %no_match ] + %3 = icmp eq ptr %2, null + br i1 %3, label %missing_function, label %compare + +missing_function: ; preds = %check + ret ptr null + +compare: ; preds = %check + %4 = getelementptr inbounds + %5 = load ptr, ptr %4, align 8 + %6 = icmp eq ptr %5, %1 + br i1 %6, label %match, label %no_match + +match: ; preds = %compare + %7 = load ptr, ptr %2, align 8 + ret ptr %7 + +no_match: ; preds = %compare + %8 = getelementptr inbounds + %9 = load ptr, ptr %8, align 8 + br label %check +} diff --git a/test/test_suite7/dynamic/same_method_twice.c3 b/test/test_suite7/dynamic/same_method_twice.c3 new file mode 100644 index 000000000..e8061986f --- /dev/null +++ b/test/test_suite7/dynamic/same_method_twice.c3 @@ -0,0 +1,12 @@ +module test; +import std::io; + +interface Abc +{ + fn void test(); +} + +fn void Abc.hello(&self) {} +fn void Abc.hello(&self) {} // #error: This method is already defined + +fn void main() {} \ No newline at end of file diff --git a/test/test_suite7/embed/embed_basic.c3t b/test/test_suite7/embed/embed_basic.c3t new file mode 100644 index 000000000..c8a182f0a --- /dev/null +++ b/test/test_suite7/embed/embed_basic.c3t @@ -0,0 +1,34 @@ +// #target: macos-x64 +module testing; + +fn void main() +{ + char[?] data = $embed("embed_basic.c3"); + char* data2 = $embed("embed_basic.c3"); + char[] data3 = $embed("embed_basic.c3"); + char* data4 = $embed("fiek") ?? null; + char*! data5 = $embed("fiek"); +} + +/* #expect: testing.ll + + +@.bytes = private unnamed_addr constant [234 x i8] c"module testing;\0A\0Afn void main()\0A{\0A\09char[?] data = $embed(\22embed_basic.c3\22);\0A\09char* data2 = $embed(\22embed_basic.c3\22);\0A\09char[] data3 = $embed(\22embed_basic.c3\22);\0A\09char* data4 = $embed(\22fiek\22) ?? null;\0A\09char*! data5 = $embed(\22fiek\22);\0A}\0A\0A\00", align 1 +@.bytes.1 = private unnamed_addr constant [234 x i8] c"module testing;\0A\0Afn void main()\0A{\0A\09char[?] data = $embed(\22embed_basic.c3\22);\0A\09char* data2 = $embed(\22embed_basic.c3\22);\0A\09char[] data3 = $embed(\22embed_basic.c3\22);\0A\09char* data4 = $embed(\22fiek\22) ?? null;\0A\09char*! data5 = $embed(\22fiek\22);\0A}\0A\0A\00", align 1 +@.bytes.2 = private unnamed_addr constant [234 x i8] c"module testing;\0A\0Afn void main()\0A{\0A\09char[?] data = $embed(\22embed_basic.c3\22);\0A\09char* data2 = $embed(\22embed_basic.c3\22);\0A\09char[] data3 = $embed(\22embed_basic.c3\22);\0A\09char* data4 = $embed(\22fiek\22) ?? null;\0A\09char*! data5 = $embed(\22fiek\22);\0A}\0A\0A\00", align 1 + +define void @testing.main() #0 { +entry: + %data = alloca + %data2 = alloca ptr, align 8 + %data3 = alloca %"char[]", align 8 + %data4 = alloca ptr, align 8 + %data5 = alloca ptr, align 8 + %data5.f = alloca i64, align 8 + call void @llvm.memcpy.p0.p0.i32(ptr align 16 %data, ptr align 1 @.bytes + store ptr @.bytes.1, ptr %data2, align 8 + store %"char[]" { ptr @.bytes.2 + store ptr null, ptr %data4, align 8 + store i64 ptrtoint (ptr @"std.io.IoError$FILE_NOT_FOUND" to i64), ptr %data5.f, align 8 + ret void +} \ No newline at end of file diff --git a/test/test_suite7/enumerations/compile_time.c3t b/test/test_suite7/enumerations/compile_time.c3t new file mode 100644 index 000000000..ccea48d73 --- /dev/null +++ b/test/test_suite7/enumerations/compile_time.c3t @@ -0,0 +1,17 @@ +// #target: macos-x64 +enum MyEnum : short +{ + HELO, + WORLD, + BYE +} + +int myenum_elements = MyEnum.elements; +int myenum_alignof = MyEnum.alignof; +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_suite7/enumerations/enum_add_sub.c3t b/test/test_suite7/enumerations/enum_add_sub.c3t new file mode 100644 index 000000000..20772f44a --- /dev/null +++ b/test/test_suite7/enumerations/enum_add_sub.c3t @@ -0,0 +1,48 @@ +// #target: macos-x64 +module test; +enum Foo +{ + ABC +} +distinct Abc = inline Foo; +distinct BarInt = int; +enum Bar : BarInt +{ + ABC +} +fn int main() +{ + Foo a; + a += 1; + $assert $typeof(a++).typeid == Foo.typeid; + $assert $typeof(a += 1).typeid == Foo.typeid; + Abc b; + b += 1; + $assert $typeof(b++).typeid == Abc.typeid; + $assert $typeof(b += 1).typeid == Abc.typeid; + Bar c; + c += 1; + $assert $typeof(c++).typeid == Bar.typeid; + $assert $typeof(c += 1).typeid == Bar.typeid; + return 0; +} + + +/* #expect: test.ll + + %a = alloca i32, align 4 + %b = alloca i32, align 4 + %c = alloca i32, align 4 + store i32 0, ptr %a, align 4 + %0 = load i32, ptr %a, align 4 + %add = add i32 %0, 1 + store i32 %add, ptr %a, align 4 + store i32 0, ptr %b, align 4 + %1 = load i32, ptr %b, align 4 + %add1 = add i32 %1, 1 + store i32 %add1, ptr %b, align 4 + store i32 0, ptr %c, align 4 + %2 = load i32, ptr %c, align 4 + %add2 = add i32 %2, 1 + store i32 %add2, ptr %c, align 4 + ret i32 0 diff --git a/test/test_suite7/enumerations/enum_associated_value.c3t b/test/test_suite7/enumerations/enum_associated_value.c3t new file mode 100644 index 000000000..5c5054874 --- /dev/null +++ b/test/test_suite7/enumerations/enum_associated_value.c3t @@ -0,0 +1,61 @@ +// #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 + +%.introspect = type { i8, i64, ptr, i64, i64, i64, [0 x i64] } +%"char[]" = type { ptr, i64 } + +@.enum.A = internal constant [2 x i8] c"A\00", align 1 +@.enum.B = internal constant [2 x i8] c"B\00", align 1 +@"$ct.uint" = linkonce global %.introspect { i8 3, i64 0, ptr null, i64 4, i64 0, i64 0, [0 x i64] zeroinitializer }, align 8 +@"$ct.test.Foo" = linkonce global { i8, i64, ptr, i64, i64, i64, [2 x %"char[]"] } { i8 8, i64 0, ptr null, i64 4, i64 ptrtoint (ptr @"$ct.uint" to i64), i64 2, [2 x %"char[]"] [%"char[]" { ptr @.enum.A, i64 1 }, %"char[]" { ptr @.enum.B, i64 1 }] }, 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: +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 + %zext = zext i32 %0 to i64 + %ptroffset = getelementptr inbounds [4 x i8], ptr @"test.Foo$val", i64 %zext + %1 = load i32, ptr %f, align 4 + %zext1 = zext i32 %1 to i64 + %ptroffset2 = getelementptr inbounds [8 x i8], ptr @"test.Foo$testme", i64 %zext1 + %2 = load i32, ptr %g, align 4 + %zext3 = zext i32 %2 to i64 + %ptroffset4 = getelementptr inbounds [4 x i8], ptr @"test.Foo$val", i64 %zext3 + %3 = load i32, ptr %g, align 4 + %zext5 = zext i32 %3 to i64 + %ptroffset6 = getelementptr inbounds [8 x i8], ptr @"test.Foo$testme", i64 %zext5 + %4 = load i32, ptr %ptroffset, align 4 + %5 = load ptr, ptr %ptroffset2, align 8 + %6 = load i32, ptr %ptroffset4, align 4 + %7 = load ptr, ptr %ptroffset6, align 8 + %8 = call i32 (ptr, ...) @printf(ptr @.str.2, i32 %4, ptr %5, i32 %6, ptr %7) + ret void +} diff --git a/test/test_suite7/enumerations/enum_associated_values_other.c3t b/test/test_suite7/enumerations/enum_associated_values_other.c3t new file mode 100644 index 000000000..02fe8fe60 --- /dev/null +++ b/test/test_suite7/enumerations/enum_associated_values_other.c3t @@ -0,0 +1,37 @@ +// #target: macos-x64 +module test; +import std::io; +import abc; + +fn void main(String[] args) +{ + typeid y = Abc.typeid; + int* x = &abc::dabc; + Foo a = Foo.DEF; + String z = a.val; + io::printfn("%s", z); +} + +module abc; +int dabc; + +struct Abc { int x; } +enum Foo : int (String val) +{ + ABC = "hello" , + DEF = "world" +} + +/* #expect: abc.ll + +%.introspect = type { i8, i64, ptr, i64, i64, i64, [0 x i64] } +%"char[]" = type { ptr, i64 } +@"$ct.abc.Abc" = linkonce global %.introspect { i8 10, i64 0, ptr null, i64 4, i64 0, i64 1, [0 x i64] zeroinitializer }, align 8 +@.enum.ABC = internal constant [4 x i8] c"ABC\00", align 1 +@.enum.DEF = internal constant [4 x i8] c"DEF\00", align 1 +@"$ct.int" = linkonce global %.introspect { i8 2, i64 0, ptr null, i64 4, i64 0, i64 0, [0 x i64] zeroinitializer }, align 8 +@"$ct.abc.Foo" = linkonce global { i8, i64, ptr, i64, i64, i64, [2 x %"char[]"] } { i8 8, i64 0, ptr null, i64 4, i64 ptrtoint (ptr @"$ct.int" to i64), i64 2, [2 x %"char[]"] [%"char[]" { ptr @.enum.ABC, i64 3 }, %"char[]" { ptr @.enum.DEF, i64 3 }] }, align 8 +@.str = private unnamed_addr constant [6 x i8] c"hello\00", align 1 +@.str.1 = private unnamed_addr constant [6 x i8] c"world\00", align 1 +@"abc.Foo$val" = linkonce constant [2 x %"char[]"] [%"char[]" { ptr @.str, i64 5 }, %"char[]" { ptr @.str.1, i64 5 }], align 8 +@abc.dabc = global i32 0, align 4 \ No newline at end of file diff --git a/test/test_suite7/enumerations/enum_cast.c3t b/test/test_suite7/enumerations/enum_cast.c3t new file mode 100644 index 000000000..ff076c2f5 --- /dev/null +++ b/test/test_suite7/enumerations/enum_cast.c3t @@ -0,0 +1,97 @@ +// #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 = (char)MyEnum.FOO.ordinal; + int z = (int)MyEnum.BAR.ordinal; + var $foo = (int)MyEnum.FOO.ordinal; + var $baz = MyEnum.BAR; + MyEnum x = MyEnum.BAR; + char b2 = x.ordinal; + int z2 = (int)x.ordinal; + float d = (float)MyEnum.FOO.ordinal; + bool hello = (bool)MyEnum.FOO.ordinal; + var $d = (float)MyEnum.FOO.ordinal; + var $hello = (bool)MyEnum.FOO.ordinal; + MyEnum! xf = MyEnum.BAR; + float! e = (float)x.ordinal; + e = (float)xf.ordinal; + +} + +/* #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 + %zext = zext i8 %1 to i32 + store i32 %zext, 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 + %optval = load i64, ptr %xf.f, align 8 + %not_err = icmp eq i64 %optval, 0 + %3 = call i1 @llvm.expect.i1(i1 %not_err, i1 true) + br i1 %3, label %after_check, label %assign_optional + +assign_optional: ; preds = %entry + store i64 %optval, 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, %assign_optional + ret void +} diff --git a/test/test_suite7/enumerations/enum_cast_error.c3 b/test/test_suite7/enumerations/enum_cast_error.c3 new file mode 100644 index 000000000..3f8615e7f --- /dev/null +++ b/test/test_suite7/enumerations/enum_cast_error.c3 @@ -0,0 +1,24 @@ +enum Abc : char { ABC } + +fn void foo() +{ + Abc x = Abc.from_ordinal(10); // #error: exceeds the max +} + +fn void bar() +{ + int a; + Abc x = Abc.from_ordinal(a); +} + +fn void baz() +{ + int a; + Abc x = Abc.from_ordinal(0); +} + +fn void abc() +{ + int a; + Abc x = Abc.from_ordinal(-1); // #error: negative number +} \ No newline at end of file diff --git a/test/test_suite7/enumerations/enum_conversions.c3t b/test/test_suite7/enumerations/enum_conversions.c3t new file mode 100644 index 000000000..9922feec3 --- /dev/null +++ b/test/test_suite7/enumerations/enum_conversions.c3t @@ -0,0 +1,155 @@ +// #safe: yes +// #target: macos-x64 +module test; +enum Abc : char { ABC } + +fn void main() +{ + int a; + Abc x = Abc.from_ordinal(a); + long z; + Abc y = Abc.from_ordinal(z); + a = 256; + y = Abc.from_ordinal(a); + a = -1; + y = Abc.from_ordinal(a); +} + +/* #expect: test.ll + +define void @test.main() #0 { +entry: + %a = alloca i32, align 4 + %x = alloca i8, align 1 + %z = alloca i64, align 8 + %y = alloca i8, align 1 + store i32 0, ptr %a, align 4 + %0 = load i32, ptr %a, align 4 + %lt = icmp slt i32 %0, 0 + %1 = call i1 @llvm.expect.i1(i1 %lt, i1 false) + br i1 %1, label %panic, label %checkok +checkok: ; preds = %entry + %ge = icmp sge i32 %0, 1 + %2 = call i1 @llvm.expect.i1(i1 %ge, i1 false) + br i1 %2, label %panic1, label %checkok6 +checkok6: ; preds = %checkok + %trunc = trunc i32 %0 to i8 + store i8 %trunc, ptr %x, align 1 + store i64 0, ptr %z, align 8 + %3 = load i64, ptr %z, align 8 + %lt7 = icmp slt i64 %3, 0 + %4 = call i1 @llvm.expect.i1(i1 %lt7, i1 false) + br i1 %4, label %panic8, label %checkok13 +checkok13: ; preds = %checkok6 + %ge14 = icmp sge i64 %3, 1 + %5 = call i1 @llvm.expect.i1(i1 %ge14, i1 false) + br i1 %5, label %panic15, label %checkok20 +checkok20: ; preds = %checkok13 + %trunc21 = trunc i64 %3 to i8 + store i8 %trunc21, ptr %y, align 1 + store i32 256, ptr %a, align 4 + %6 = load i32, ptr %a, align 4 + %lt22 = icmp slt i32 %6, 0 + %7 = call i1 @llvm.expect.i1(i1 %lt22, i1 false) + br i1 %7, label %panic23, label %checkok28 +checkok28: ; preds = %checkok20 + %ge29 = icmp sge i32 %6, 1 + %8 = call i1 @llvm.expect.i1(i1 %ge29, i1 false) + br i1 %8, label %panic30, label %checkok35 +checkok35: ; preds = %checkok28 + %trunc36 = trunc i32 %6 to i8 + store i8 %trunc36, ptr %y, align 1 + store i32 -1, ptr %a, align 4 + %9 = load i32, ptr %a, align 4 + %lt37 = icmp slt i32 %9, 0 + %10 = call i1 @llvm.expect.i1(i1 %lt37, i1 false) + br i1 %10, label %panic38, label %checkok43 +checkok43: ; preds = %checkok35 + %ge44 = icmp sge i32 %9, 1 + %11 = call i1 @llvm.expect.i1(i1 %ge44, i1 false) + br i1 %11, label %panic45, label %checkok50 +checkok50: ; preds = %checkok43 + %trunc51 = trunc i32 %9 to i8 + store i8 %trunc51, ptr %y, align 1 + ret void +panic: ; preds = %entry + store i32 %0, ptr %taddr, align 4 + %12 = insertvalue %any undef, ptr %taddr, 0 + %13 = insertvalue %any %12, i64 ptrtoint (ptr @"$ct.int" to i64), 1 + store %any %13, ptr %varargslots, align 16 + %14 = insertvalue %"any[]" undef, ptr %varargslots, 0 + %"$$temp" = insertvalue %"any[]" %14, i64 1, 1 + store %"any[]" %"$$temp", ptr %indirectarg, align 8 + call void @std.core.builtin.panicf(ptr @.panic_msg + unreachable +panic1: ; preds = %checkok + store i32 %0, ptr %taddr2, align 4 + %15 = insertvalue %any undef, ptr %taddr2, 0 + %16 = insertvalue %any %15, i64 ptrtoint (ptr @"$ct.int" to i64), 1 + store %any %16, ptr %varargslots3, align 16 + %17 = insertvalue %"any[]" undef, ptr %varargslots3, 0 + %"$$temp4" = insertvalue %"any[]" %17, i64 1, 1 + store %"any[]" %"$$temp4", ptr %indirectarg5, align 8 + call void @std.core.builtin.panicf(ptr @.panic_msg.1, i64 87, ptr @.file, i64 19, ptr @.func, i64 4, i32 7, ptr byval(%"any[]") align 8 %indirectarg5) + unreachable +panic8: ; preds = %checkok6 + store i64 %3, ptr %taddr9, align 8 + %18 = insertvalue %any undef, ptr %taddr9, 0 + %19 = insertvalue %any %18, i64 ptrtoint (ptr @"$ct.long" to i64), 1 + store %any %19, ptr %varargslots10, align 16 + %20 = insertvalue %"any[]" undef, ptr %varargslots10, 0 + %"$$temp11" = insertvalue %"any[]" %20, i64 1, 1 + store %"any[]" %"$$temp11", ptr %indirectarg12, align 8 + call void @std.core.builtin.panicf(ptr @.panic_msg, + unreachable +panic15: ; preds = %checkok13 + store i64 %3, ptr %taddr16, align 8 + %21 = insertvalue %any undef, ptr %taddr16, 0 + %22 = insertvalue %any %21, i64 ptrtoint (ptr @"$ct.long" to i64), 1 + store %any %22, ptr %varargslots17, align 16 + %23 = insertvalue %"any[]" undef, ptr %varargslots17, 0 + %"$$temp18" = insertvalue %"any[]" %23, i64 1, 1 + store %"any[]" %"$$temp18", ptr %indirectarg19, align 8 + call void @std.core.builtin.panicf(ptr @.panic_msg.1, i64 87, ptr @.file, i64 19, ptr @.func, i64 4, i32 9, ptr byval(%"any[]") align 8 %indirectarg19) + unreachable +panic23: ; preds = %checkok20 + store i32 %6, ptr %taddr24, align 4 + %24 = insertvalue %any undef, ptr %taddr24, 0 + %25 = insertvalue %any %24, i64 ptrtoint (ptr @"$ct.int" to i64), 1 + store %any %25, ptr %varargslots25, align 16 + %26 = insertvalue %"any[]" undef, ptr %varargslots25, 0 + %"$$temp26" = insertvalue %"any[]" %26, i64 1, 1 + store %"any[]" %"$$temp26", ptr %indirectarg27, align 8 + call void @std.core.builtin.panicf(ptr @.panic_msg, + unreachable +panic30: ; preds = %checkok28 + store i32 %6, ptr %taddr31, align 4 + %27 = insertvalue %any undef, ptr %taddr31, 0 + %28 = insertvalue %any %27, i64 ptrtoint (ptr @"$ct.int" to i64), 1 + store %any %28, ptr %varargslots32, align 16 + %29 = insertvalue %"any[]" undef, ptr %varargslots32, 0 + %"$$temp33" = insertvalue %"any[]" %29, i64 1, 1 + store %"any[]" %"$$temp33", ptr %indirectarg34, align 8 + call void @std.core.builtin.panicf(ptr @.panic_msg.1, i64 87, ptr @.file, i64 19, ptr @.func, i64 4, i32 11, ptr byval(%"any[]") align 8 %indirectarg34) + unreachable +panic38: ; preds = %checkok35 + store i32 %9, ptr %taddr39, align 4 + %30 = insertvalue %any undef, ptr %taddr39, 0 + %31 = insertvalue %any %30, i64 ptrtoint (ptr @"$ct.int" to i64), 1 + store %any %31, ptr %varargslots40, align 16 + %32 = insertvalue %"any[]" undef, ptr %varargslots40, 0 + %"$$temp41" = insertvalue %"any[]" %32, i64 1, 1 + store %"any[]" %"$$temp41", ptr %indirectarg42, align 8 + call void @std.core.builtin.panicf(ptr @.panic_msg, + unreachable +panic45: ; preds = %checkok43 + store i32 %9, ptr %taddr46, align 4 + %33 = insertvalue %any undef, ptr %taddr46, 0 + %34 = insertvalue %any %33, i64 ptrtoint (ptr @"$ct.int" to i64), 1 + store %any %34, ptr %varargslots47, align 16 + %35 = insertvalue %"any[]" undef, ptr %varargslots47, 0 + %"$$temp48" = insertvalue %"any[]" %35, i64 1, 1 + store %"any[]" %"$$temp48", ptr %indirectarg49, align 8 + call void @std.core.builtin.panicf(ptr @.panic_msg.1, i64 87, ptr @.file, i64 19, ptr @.func, i64 4, i32 13, ptr byval(%"any[]") align 8 %indirectarg49) + unreachable +} diff --git a/test/test_suite7/enumerations/enum_invalid_param.c3 b/test/test_suite7/enumerations/enum_invalid_param.c3 new file mode 100644 index 000000000..3c49e174b --- /dev/null +++ b/test/test_suite7/enumerations/enum_invalid_param.c3 @@ -0,0 +1,14 @@ +enum Test : int (int kindof, int qnameof) +{ + FOO = {1, 2} +} + +enum Test2 : (int a, int nameof) // #error: 'nameof' is not a valid parameter name for enums +{ + FOO = {1, 2} +} + +enum Test3 : (int a, int ordinal) // #error: 'ordinal' is not a valid parameter name for enums +{ + FOO = {1, 2} +} diff --git a/test/test_suite7/enumerations/enum_missing_comma.c3 b/test/test_suite7/enumerations/enum_missing_comma.c3 new file mode 100644 index 000000000..d03e3e7cc --- /dev/null +++ b/test/test_suite7/enumerations/enum_missing_comma.c3 @@ -0,0 +1,5 @@ +enum Abc +{ + FOO + BAR // #error: It looks like you forgot a comma +} diff --git a/test/test_suite7/enumerations/enum_reflect_associated.c3t b/test/test_suite7/enumerations/enum_reflect_associated.c3t new file mode 100644 index 000000000..f39258d7f --- /dev/null +++ b/test/test_suite7/enumerations/enum_reflect_associated.c3t @@ -0,0 +1,51 @@ +// #target: macos-x64 +module test; +import std::io; + +enum Abc : int (int x, double y, String z) +{ + OFEKFE = { 1, 2.0, "foek" }, +} + +fn int main() +{ + $foreach ($type : Abc.associated) + io::printfn("%s", $type.qnameof); + $endforeach + return 0; +} +/* #expect: test.ll + +@.str.2 = private unnamed_addr constant [4 x i8] c"int\00", align 1 +@.str.4 = private unnamed_addr constant [7 x i8] c"double\00", align 1 +@.str.6 = private unnamed_addr constant [7 x i8] c"String\00", align 1 + +; Function Attrs: +define i32 @main() #0 { +entry: + %varargslots = alloca [1 x %any], align 16 + %taddr = alloca %"char[]", align 8 + %retparam = alloca i64, align 8 + %varargslots1 = alloca [1 x %any], align 16 + %taddr2 = alloca %"char[]", align 8 + %retparam3 = alloca i64, align 8 + %varargslots4 = alloca [1 x %any], align 16 + %taddr5 = alloca %"char[]", align 8 + %retparam6 = alloca i64, align 8 + store %"char[]" { ptr @.str.2, i64 3 }, ptr %taddr, align 8 + %0 = insertvalue %any undef, ptr %taddr, 0 + %1 = insertvalue %any %0, i64 ptrtoint (ptr @"$ct.String" to i64), 1 + store %any %1, ptr %varargslots, align 16 + %2 = call i64 @std.io.printfn(ptr %retparam, ptr @.str.1, i64 2, ptr %varargslots, i64 1) + store %"char[]" { ptr @.str.4, i64 6 }, ptr %taddr2, align 8 + %3 = insertvalue %any undef, ptr %taddr2, 0 + %4 = insertvalue %any %3, i64 ptrtoint (ptr @"$ct.String" to i64), 1 + store %any %4, ptr %varargslots1, align 16 + %5 = call i64 @std.io.printfn(ptr %retparam3, ptr @.str.3, i64 2, ptr %varargslots1, i64 1) + store %"char[]" { ptr @.str.6, i64 6 }, ptr %taddr5, align 8 + %6 = insertvalue %any undef, ptr %taddr5, 0 + %7 = insertvalue %any %6, i64 ptrtoint (ptr @"$ct.String" to i64), 1 + store %any %7, ptr %varargslots4, align 16 + %8 = call i64 @std.io.printfn(ptr %retparam6, ptr @.str.5, i64 2, ptr %varargslots4, i64 1) + ret i32 0 +} diff --git a/test/test_suite7/enumerations/enum_same_param.c3 b/test/test_suite7/enumerations/enum_same_param.c3 new file mode 100644 index 000000000..4f1a928fb --- /dev/null +++ b/test/test_suite7/enumerations/enum_same_param.c3 @@ -0,0 +1,9 @@ +enum Test : (int a, int b) +{ + FOO = { 1, 2 } +} + +enum Test2 : int (int a, int a) // #error: Duplicate parameter name 'a' +{ + FOO = { 1, 2 } +} diff --git a/test/test_suite7/enumerations/enum_signed_cast_swap.c3t b/test/test_suite7/enumerations/enum_signed_cast_swap.c3t new file mode 100644 index 000000000..f88545e7b --- /dev/null +++ b/test/test_suite7/enumerations/enum_signed_cast_swap.c3t @@ -0,0 +1,27 @@ +// #target: macos-x64 +module test; +enum Abc : char { ABC } + +enum Mouse_Button { + LEFT, + RIGHT, + MIDDLE, +} + +fn void foo(Mouse_Button button) +{ +} + +fn int main() { + uint x = 1; + foo(Mouse_Button.from_ordinal(x)); + return 0; +} + +/* #expect: test.ll + + %x = alloca i32, align 4 + store i32 1, ptr %x, align 4 + %0 = load i32, ptr %x, align 4 + call void @test.foo(i32 %0) + ret i32 0 diff --git a/test/test_suite7/enumerations/enum_values.c3t b/test/test_suite7/enumerations/enum_values.c3t new file mode 100644 index 000000000..fb6b6172f --- /dev/null +++ b/test/test_suite7/enumerations/enum_values.c3t @@ -0,0 +1,35 @@ +// #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 + +@test.zfok = local_unnamed_addr global i32 0, align 4 +@.taddr = private unnamed_addr global [2 x i32] [i32 0, i32 1], align 4 +@test.zw = local_unnamed_addr global %"int[]" { 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 + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %literal, ptr align 4 @.__const, i32 8, i1 false) + %sext = sext i32 %0 to i64 + %ptroffset = getelementptr inbounds [4 x i8], ptr %literal, i64 %sext + %1 = load i32, ptr %ptroffset, align 4 + store i32 %1, ptr %zonk, align 4 + ret void +} diff --git a/test/test_suite7/enumerations/enum_with_associated_value_decl.c3 b/test/test_suite7/enumerations/enum_with_associated_value_decl.c3 new file mode 100644 index 000000000..485fc9489 --- /dev/null +++ b/test/test_suite7/enumerations/enum_with_associated_value_decl.c3 @@ -0,0 +1,7 @@ +enum Test2 : (usz a, usz b) { + FOO = {4, 5, }, +} + +enum Test : (usz a, usz b) { + FOO = {a: 1, b: 1}, // #error: This looks like +} \ No newline at end of file diff --git a/test/test_suite7/enumerations/enum_with_const.c3t b/test/test_suite7/enumerations/enum_with_const.c3t new file mode 100644 index 000000000..3474872a7 --- /dev/null +++ b/test/test_suite7/enumerations/enum_with_const.c3t @@ -0,0 +1,55 @@ +// #target: macos-x64 +module test; + +const FG_YELLOW = "\e[0;38;2;255;240;128m"; +const FG_GREEN = "\e[0;38;2;192;255;192m"; +const FG_RED = "\e[0;38;2;255;40;40m"; + +enum SeverityTag : int (String fg, String label) { + INFO = { FG_GREEN, "info" }, + WARN = { FG_YELLOW, "warn" }, + FATAL = { FG_RED, "fatal" }, + FATAL2 = { FG_RED, "fatal2" }, +} + +fn void main() +{ + SeverityTag tag = WARN; + String a = tag.fg; +} + +/* #expect: test.ll + +@.enum.INFO = internal constant [5 x i8] c"INFO\00", align 1 +@.enum.WARN = internal constant [5 x i8] c"WARN\00", align 1 +@.enum.FATAL = internal constant [6 x i8] c"FATAL\00", align 1 +@.enum.FATAL2 = internal constant [7 x i8] c"FATAL2\00", align 1 +@"$ct.test.SeverityTag" = linkonce global { i8, i64, ptr, i64, i64, i64, [4 x %"char[]"] } { i8 8, i64 0, ptr null, i64 4, i64 ptrtoint (ptr @"$ct.int" to i64), i64 4, [4 x %"char[]"] [%"char[]" { ptr @.enum.INFO, i64 4 }, %"char[]" { ptr @.enum.WARN, i64 4 }, %"char[]" { ptr @.enum.FATAL, i64 5 }, %"char[]" { ptr @.enum.FATAL2, i64 6 }] }, align 8 +@.str = private unnamed_addr constant [22 x i8] c"\1B[0;38;2;192;255;192m\00", align 1 +@.str.1 = private unnamed_addr constant [22 x i8] c"\1B[0;38;2;255;240;128m\00", align 1 +@.str.2 = private unnamed_addr constant [20 x i8] c"\1B[0;38;2;255;40;40m\00", align 1 +@.str.3 = private unnamed_addr constant [20 x i8] c"\1B[0;38;2;255;40;40m\00", align 1 +@"test.SeverityTag$fg" = linkonce constant [4 x %"char[]"] [%"char[]" { ptr @.str, i64 21 }, %"char[]" { ptr @.str.1, i64 21 }, %"char[]" { ptr @.str.2, i64 19 }, %"char[]" { ptr @.str.3, i64 19 }], align 8 +@.str.4 = private unnamed_addr constant [5 x i8] c"info\00", align 1 +@.str.5 = private unnamed_addr constant [5 x i8] c"warn\00", align 1 +@.str.6 = private unnamed_addr constant [6 x i8] c"fatal\00", align 1 +@.str.7 = private unnamed_addr constant [7 x i8] c"fatal2\00", align 1 +@"test.SeverityTag$label" = linkonce constant [4 x %"char[]"] [%"char[]" { ptr @.str.4, i64 4 }, %"char[]" { ptr @.str.5, i64 4 }, %"char[]" { ptr @.str.6, i64 5 }, %"char[]" { ptr @.str.7, i64 6 }], align 8 +@.str.10 = private unnamed_addr constant [22 x i8] c"\1B[0;38;2;255;240;128m\00", align 1 +@test.FG_YELLOW = local_unnamed_addr constant %"char[]" { ptr @.str.10, i64 21 }, align 8 +@.str.11 = private unnamed_addr constant [22 x i8] c"\1B[0;38;2;192;255;192m\00", align 1 +@test.FG_GREEN = local_unnamed_addr constant %"char[]" { ptr @.str.11, i64 21 }, align 8 +@.str.12 = private unnamed_addr constant [20 x i8] c"\1B[0;38;2;255;40;40m\00", align 1 +@test.FG_RED = local_unnamed_addr constant %"char[]" { ptr @.str.12, i64 19 }, align 8 + +define void @test.main() #0 { +entry: + %tag = alloca i32, align 4 + %a = alloca %"char[]", align 8 + store i32 1, ptr %tag, align 4 + %0 = load i32, ptr %tag, align 4 + %ptroffset = getelementptr inbounds [16 x i8], ptr @"test.SeverityTag$fg", i32 %0 + call void @llvm.memcpy.p0.p0.i32(ptr align 8 %a, ptr align 8 %ptroffset, i32 16, i1 false) + ret void +} + diff --git a/test/test_suite7/enumerations/inc_assign.c3t b/test/test_suite7/enumerations/inc_assign.c3t new file mode 100644 index 000000000..88c71105a --- /dev/null +++ b/test/test_suite7/enumerations/inc_assign.c3t @@ -0,0 +1,35 @@ +// #target: macos-x64 +module test; +import std; + +enum Abc +{ + ABCD, + OKFEOFKE, + OFKEOFK +} + +distinct Bob = inline Abc; +fn void main() +{ + Abc y; + y += 1; + Bob gh; + gh += 1; +} + +/* #expect: test.ll + +entry: + %y = alloca i32, align 4 + %gh = alloca i32, align 4 + store i32 0, ptr %y, align 4 + %0 = load i32, ptr %y, align 4 + %add = add i32 %0, 1 + store i32 %add, ptr %y, align 4 + store i32 0, ptr %gh, align 4 + %1 = load i32, ptr %gh, align 4 + %add1 = add i32 %1, 1 + store i32 %add1, ptr %gh, align 4 + ret void +} \ No newline at end of file diff --git a/test/test_suite7/enumerations/inc_assign_fail.c3 b/test/test_suite7/enumerations/inc_assign_fail.c3 new file mode 100644 index 000000000..f31877c7e --- /dev/null +++ b/test/test_suite7/enumerations/inc_assign_fail.c3 @@ -0,0 +1,20 @@ +// #target: macos-x64 +module test; +import std; + +enum Abc +{ + ABCD, + OKFEOFKE, + OFKEOFK +} + +distinct Bob = Abc; +fn void main() +{ + Abc y; + y ^= 1; // #error: Expected an integer here, not a value of type + y += 1.0; // #error: The right side was 'double' + Bob gh; + gh += 1; // #error: A value of type 'Bob' +} diff --git a/test/test_suite7/enumerations/inline_enum_size.c3 b/test/test_suite7/enumerations/inline_enum_size.c3 new file mode 100644 index 000000000..916628b59 --- /dev/null +++ b/test/test_suite7/enumerations/inline_enum_size.c3 @@ -0,0 +1,19 @@ +enum Bar : inline usz +{ + FOO, + BAR, +} + +enum Bar2 : usz (inline int x) +{ + FOO = 1, + BAR = 4, +} + +int[Bar.BAR] x; + +fn int main() +{ + char[Bar2.BAR] a; + return 0; +} diff --git a/test/test_suite7/enumerations/inline_enums.c3t b/test/test_suite7/enumerations/inline_enums.c3t new file mode 100644 index 000000000..56da02b1e --- /dev/null +++ b/test/test_suite7/enumerations/inline_enums.c3t @@ -0,0 +1,38 @@ +// #target: macos-x64 +module test; + +enum Abc : inline int +{ + ABC, + DEF, +} + +enum Foo : int (inline String name, int y, int z) +{ + ABC = { "Hello", 1, 2 }, + DEF = { "World", 2, 3 }, +} +fn void main() +{ + int a = Abc.DEF; + Foo x = ABC; + Foo y = DEF; + String hello = Foo.ABC; + String world = Foo.DEF; +} +/* #expect: test.ll + +define void @test.main() #0 { +entry: + %a = alloca i32, align 4 + %x = alloca i32, align 4 + %y = alloca i32, align 4 + %hello = alloca %"char[]", align 8 + %world = alloca %"char[]", align 8 + store i32 1, ptr %a, align 4 + store i32 0, ptr %x, align 4 + store i32 1, ptr %y, align 4 + store %"char[]" { ptr @.str.2, i64 5 }, ptr %hello, align 8 + store %"char[]" { ptr @.str.3, i64 5 }, ptr %world, align 8 + ret void +} diff --git a/test/test_suite7/enumerations/introspection_data_error.c3t b/test/test_suite7/enumerations/introspection_data_error.c3t new file mode 100644 index 000000000..6d642f7f2 --- /dev/null +++ b/test/test_suite7/enumerations/introspection_data_error.c3t @@ -0,0 +1,19 @@ +// #target: macos-x64 +module boom; +enum Boom: int (String a) { + BOOM = {0} +} + +module app; +import std::io, boom; +fn void main(String[] args) { + io::printn(Boom.BOOM); +} +/* #expect: boom.ll + +@.enum.BOOM = internal constant [5 x i8] c"BOOM\00", align 1 +@"$ct.int" = linkonce global %.introspect { i8 2, i64 0, ptr null, i64 4, i64 0, i64 0, [0 x i64] zeroinitializer }, align 8 +@"$ct.boom.Boom" = linkonce global { i8, i64, ptr, i64, i64, i64, [1 x %"char[]"] } { i8 8, i64 0, ptr null, i64 4, i64 ptrtoint (ptr @"$ct.int" to i64), i64 1, [1 x %"char[]"] [%"char[]" { ptr @.enum.BOOM, i64 4 }] }, align 8 +@.__const_slice = private unnamed_addr global [1 x i8] zeroinitializer, align 1 +@"boom.Boom$a" = linkonce constant [1 x %"char[]"] [%"char[]" { ptr @.__const_slice, i64 1 }], align 8 + diff --git a/test/test_suite7/enumerations/missing_type.c3 b/test/test_suite7/enumerations/missing_type.c3 new file mode 100644 index 000000000..6f65fdc25 --- /dev/null +++ b/test/test_suite7/enumerations/missing_type.c3 @@ -0,0 +1,4 @@ +enum Kind : (x) // #error: A type name +{ + FOO (10), +} \ No newline at end of file diff --git a/test/test_suite7/enumerations/simple_inference.c3t b/test/test_suite7/enumerations/simple_inference.c3t new file mode 100644 index 000000000..018c82eda --- /dev/null +++ b/test/test_suite7/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_suite7/enumerations/too_many_associated.c3 b/test/test_suite7/enumerations/too_many_associated.c3 new file mode 100644 index 000000000..cab918c8c --- /dev/null +++ b/test/test_suite7/enumerations/too_many_associated.c3 @@ -0,0 +1,9 @@ +enum Baz : (String a, int z) +{ + BAR = { "123", 1, 3 }, // #error: You're adding too many values, only 2 associated +} + +enum Baz2 : (String a, int z) +{ + BAR = { "123" }, // #error: Expected 2 associated values for this enum value +} \ No newline at end of file diff --git a/test/test_suite7/errors/anyfault_void.c3t b/test/test_suite7/errors/anyfault_void.c3t new file mode 100644 index 000000000..0925f1b23 --- /dev/null +++ b/test/test_suite7/errors/anyfault_void.c3t @@ -0,0 +1,108 @@ +fault MyError +{ + FOO, + BAR +} +fn void! errorThing() +{ + return MyError.BAR?; +} + +fn void! errorThing2() +{ + return; +} + +extern fn void printf(char*, ...); +fn void main() +{ + anyfault z = @catch(errorThing()); + printf("Z; %llx\n", (iptr)(z)); + printf("BAR: %llx\n", (iptr)(MyError.BAR)); + printf("FOO: %llx\n", (iptr)(MyError.FOO)); + z = @catch(errorThing2()); + printf("Z2: %llx\n", (iptr)(z)); +} + +/* #expect: anyfault_void.ll + +define i64 @anyfault_void.errorThing() #0 { +entry: + ret i64 ptrtoint (ptr @"anyfault_void.MyError$BAR" to i64) +} + +define i64 @anyfault_void.errorThing2() #0 { +entry: + %reterr = alloca i64, align 8 + ret i64 0 +} + +declare void @printf(ptr, ...) #0 + +define void @anyfault_void.main() #0 { +entry: + %z = alloca i64, align 8 + %blockret = alloca i64, align 8 + %f = alloca i64, align 8 + %blockret1 = alloca i64, align 8 + %f2 = alloca i64, align 8 + br label %testblock +testblock: ; preds = %entry + %0 = call i64 @anyfault_void.errorThing() + %not_err = icmp eq i64 %0, 0 + %1 = call i1 @llvm.expect.i1(i1 %not_err, i1 true) + br i1 %1, label %after_check, label %assign_optional +assign_optional: ; preds = %testblock + store i64 %0, ptr %f, align 8 + br label %end_block +after_check: ; preds = %testblock + store i64 0, ptr %f, align 8 + br label %end_block +end_block: ; preds = %after_check, %assign_optional + %2 = load i64, ptr %f, align 8 + %i2b = icmp ne i64 %2, 0 + br i1 %i2b, label %if.then, label %if.exit +if.then: ; preds = %end_block + %3 = load i64, ptr %f, align 8 + store i64 %3, ptr %blockret, align 8 + br label %expr_block.exit +if.exit: ; preds = %end_block + store i64 0, ptr %blockret, align 8 + br label %expr_block.exit +expr_block.exit: ; preds = %if.exit, %if.then + %4 = load i64, ptr %blockret, align 8 + store i64 %4, ptr %z, align 8 + %5 = load i64, ptr %z, align 8 + call void (ptr, ...) @printf(ptr @.str, i64 %5) + call void (ptr, ...) @printf(ptr @.str.2, i64 ptrtoint (ptr @"anyfault_void.MyError$BAR" to i64)) + call void (ptr, ...) @printf(ptr @.str.3, i64 ptrtoint (ptr @"anyfault_void.MyError$FOO" to i64)) + br label %testblock3 +testblock3: ; preds = %expr_block.exit + %6 = call i64 @anyfault_void.errorThing2() + %not_err4 = icmp eq i64 %6, 0 + %7 = call i1 @llvm.expect.i1(i1 %not_err4, i1 true) + br i1 %7, label %after_check6, label %assign_optional5 +assign_optional5: ; preds = %testblock3 + store i64 %6, ptr %f2, align 8 + br label %end_block7 +after_check6: ; preds = %testblock3 + store i64 0, ptr %f2, align 8 + br label %end_block7 +end_block7: ; preds = %after_check6, %assign_optional5 + %8 = load i64, ptr %f2, align 8 + %i2b8 = icmp ne i64 %8, 0 + br i1 %i2b8, label %if.then9, label %if.exit10 +if.then9: ; preds = %end_block7 + %9 = load i64, ptr %f2, align 8 + store i64 %9, ptr %blockret1, align 8 + br label %expr_block.exit11 +if.exit10: ; preds = %end_block7 + store i64 0, ptr %blockret1, align 8 + br label %expr_block.exit11 +expr_block.exit11: ; preds = %if.exit10, %if.then9 + %10 = load i64, ptr %blockret1, align 8 + store i64 %10, ptr %z, align 8 + %11 = load i64, ptr %z, align 8 + call void (ptr, ...) @printf(ptr @.str.4, i64 %11) + ret void +} \ No newline at end of file diff --git a/test/test_suite7/errors/bitshift_failable.c3 b/test/test_suite7/errors/bitshift_failable.c3 new file mode 100644 index 000000000..61ab084c9 --- /dev/null +++ b/test/test_suite7/errors/bitshift_failable.c3 @@ -0,0 +1,5 @@ +fn void test() +{ + int! x = 0; + int! z = x << 100; // #error: the bitsize of 'int' +} \ No newline at end of file diff --git a/test/test_suite7/errors/else_checks.c3t b/test/test_suite7/errors/else_checks.c3t new file mode 100644 index 000000000..26a4e405d --- /dev/null +++ b/test/test_suite7/errors/else_checks.c3t @@ -0,0 +1,119 @@ +// #target: macos-x64 + +extern fn int! testError(); + +fn void test() +{ + + double x = ((double)testError() + testError()) ?? 100; + double y = (1 << testError()) ?? 100; + double z = testError() >> 1 ?? 100; + double w = (double)testError() * testError() ?? 100; +} + +/* #expect: else_checks.ll + + +declare i64 @testError(ptr) #0 + + +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 + %retparam5 = alloca i32, align 4 + %z = alloca double, align 8 + %retparam12 = alloca i32, align 4 + %w = alloca double, align 8 + %retparam19 = alloca i32, align 4 + %retparam23 = alloca i32, align 4 + %0 = call i64 @testError(ptr %retparam) + %not_err = icmp eq i64 %0, 0 + %1 = call i1 @llvm.expect.i1(i1 %not_err, i1 true) + br i1 %1, label %after_check, label %else_block + +after_check: ; preds = %entry + %2 = load i32, ptr %retparam, align 4 + %sifp = sitofp i32 %2 to double + %3 = call i64 @testError(ptr %retparam1) + %not_err2 = icmp eq i64 %3, 0 + %4 = call i1 @llvm.expect.i1(i1 %not_err2, i1 true) + br i1 %4, label %after_check3, label %else_block + +after_check3: ; preds = %after_check + %5 = load i32, ptr %retparam1, align 4 + %sifp4 = sitofp i32 %5 to double + %fadd = fadd double %sifp, %sifp4 + br label %phi_block + +else_block: ; preds = %after_check, %entry + br label %phi_block + +phi_block: ; preds = %else_block, %after_check3 + %val = phi double [ %fadd, %after_check3 ], [ 1.000000e+02, %else_block ] + store double %val, ptr %x, align 8 + %6 = call i64 @testError(ptr %retparam5) + %not_err6 = icmp eq i64 %6, 0 + %7 = call i1 @llvm.expect.i1(i1 %not_err6, i1 true) + br i1 %7, label %after_check7, label %else_block9 + +after_check7: ; preds = %phi_block + %8 = load i32, ptr %retparam5, align 4 + %shl = shl i32 1, %8 + %9 = freeze i32 %shl + %sifp8 = sitofp i32 %9 to double + br label %phi_block10 + +else_block9: ; preds = %phi_block + br label %phi_block10 + +phi_block10: ; preds = %else_block9, %after_check7 + %val11 = phi double [ %sifp8, %after_check7 ], [ 1.000000e+02, %else_block9 ] + store double %val11, ptr %y, align 8 + %10 = call i64 @testError(ptr %retparam12) + %not_err13 = icmp eq i64 %10, 0 + %11 = call i1 @llvm.expect.i1(i1 %not_err13, i1 true) + br i1 %11, label %after_check14, label %else_block16 + +after_check14: ; preds = %phi_block10 + %12 = load i32, ptr %retparam12, align 4 + %ashr = ashr i32 %12, 1 + %13 = freeze i32 %ashr + %sifp15 = sitofp i32 %13 to double + br label %phi_block17 + +else_block16: ; preds = %phi_block10 + br label %phi_block17 + +phi_block17: ; preds = %else_block16, %after_check14 + %val18 = phi double [ %sifp15, %after_check14 ], [ 1.000000e+02, %else_block16 ] + store double %val18, ptr %z, align 8 + %14 = call i64 @testError(ptr %retparam19) + %not_err20 = icmp eq i64 %14, 0 + %15 = call i1 @llvm.expect.i1(i1 %not_err20, i1 true) + br i1 %15, label %after_check21, label %else_block27 + +after_check21: ; preds = %phi_block17 + %16 = load i32, ptr %retparam19, align 4 + %sifp22 = sitofp i32 %16 to double + %17 = call i64 @testError(ptr %retparam23) + %not_err24 = icmp eq i64 %17, 0 + %18 = call i1 @llvm.expect.i1(i1 %not_err24, i1 true) + br i1 %18, label %after_check25, label %else_block27 + +after_check25: ; preds = %after_check21 + %19 = load i32, ptr %retparam23, align 4 + %sifp26 = sitofp i32 %19 to double + %fmul = fmul double %sifp22, %sifp26 + br label %phi_block28 + +else_block27: ; preds = %after_check21, %phi_block17 + br label %phi_block28 + +phi_block28: ; preds = %else_block27, %after_check25 + %val29 = phi double [ %fmul, %after_check25 ], [ 1.000000e+02, %else_block27 ] + store double %val29, ptr %w, align 8 + ret void +} diff --git a/test/test_suite7/errors/else_struct.c3t b/test/test_suite7/errors/else_struct.c3t new file mode 100644 index 000000000..b12f4513d --- /dev/null +++ b/test/test_suite7/errors/else_struct.c3t @@ -0,0 +1,65 @@ +// #target: macos-x64 +module test; +struct Foo +{ + int[30] a; +} + +fn void test() +{ + int! a = 0; + Foo! b = {}; + Foo c; + + int e = a ?? 1; + Foo d = b ?? c; + return; +} + +/* #expect: test.ll + +define void @test.test() #0 { +entry: + %a = alloca i32, align 4 + %a.f = alloca i64, align 8 + %b = alloca %Foo, align 4 + %b.f = alloca i64, align 8 + %c = alloca %Foo, align 4 + %e = alloca i32, align 4 + %d = alloca %Foo, align 4 + store i32 0, ptr %a, align 4 + store i64 0, ptr %a.f, align 8 + call void @llvm.memset.p0.i64(ptr align 4 %b, i8 0, i64 120, i1 false) + store i64 0, ptr %b.f, align 8 + call void @llvm.memset.p0.i64(ptr align 4 %c, i8 0, i64 120, i1 false) + %optval = load i64, ptr %a.f, align 8 + %not_err = icmp eq i64 %optval, 0 + %0 = call i1 @llvm.expect.i1(i1 %not_err, i1 true) + br i1 %0, label %after_check, label %else_block + +after_check: ; preds = %entry + %1 = load i32, ptr %a, align 4 + br label %phi_block + +else_block: ; preds = %entry + br label %phi_block + +phi_block: ; preds = %else_block, %after_check + %val = phi i32 [ %1, %after_check ], [ 1, %else_block ] + store i32 %val, ptr %e, align 4 + %optval1 = load i64, ptr %b.f, align 8 + %not_err2 = icmp eq i64 %optval1, 0 + %2 = call i1 @llvm.expect.i1(i1 %not_err2, i1 true) + br i1 %2, label %after_check3, label %else_block4 + +after_check3: ; preds = %phi_block + br label %phi_block5 + +else_block4: ; preds = %phi_block + br label %phi_block5 + +phi_block5: ; preds = %else_block4, %after_check3 + %val6 = phi ptr [ %b, %after_check3 ], [ %c, %else_block4 ] + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %d, ptr align 8 %val6, i32 120, i1 false) + ret void +} \ No newline at end of file diff --git a/test/test_suite7/errors/else_unreachable.c3t b/test/test_suite7/errors/else_unreachable.c3t new file mode 100644 index 000000000..6e9cb3199 --- /dev/null +++ b/test/test_suite7/errors/else_unreachable.c3t @@ -0,0 +1,39 @@ +// #target: macos-x64 +module test; +import std; +// Issue #1913 +fn void main() +{ + char[] bytes = file::load_temp("config.json") ?? abort("Unable to open config.json file"); + int hello; +} + +/* #expect: test.ll + +define void @test.main() #0 { +entry: + %bytes = alloca %"char[]", align 8 + %retparam = alloca %"char[]", align 8 + %blockret = alloca %"char[]", align 8 + %indirectarg = alloca %"any[]", align 8 + %hello = alloca i32, align 4 + %0 = call i64 @std.io.file.load_temp(ptr %retparam, ptr @.str, i64 11) + %not_err = icmp eq i64 %0, 0 + %1 = call i1 @llvm.expect.i1(i1 %not_err, i1 true) + br i1 %1, label %after_check, label %else_block + +after_check: ; preds = %entry + %2 = load %"char[]", ptr %retparam, align 8 + br label %phi_block + +else_block: ; preds = %entry + store %"any[]" zeroinitializer, ptr %indirectarg, align 8 + call void @std.core.builtin.panicf(ptr @.str.1, i64 31, ptr @.str.2, i64 19, ptr @.str.3, i64 4, i32 6, ptr byval(%"any[]") align 8 %indirectarg) + call void @llvm.trap() + unreachable + +phi_block: ; preds = %after_check + store %"char[]" %2, ptr %bytes, align 8 + store i32 0, ptr %hello, align 4 + ret void +} diff --git a/test/test_suite7/errors/else_unreachable_in_block.c3 b/test/test_suite7/errors/else_unreachable_in_block.c3 new file mode 100644 index 000000000..b0d0ac5d9 --- /dev/null +++ b/test/test_suite7/errors/else_unreachable_in_block.c3 @@ -0,0 +1,9 @@ +// #deprecation: no +module test; +import std; +fn void main() +{ + char[] bytes = file::load_temp("config.json") ?? {| abort("Unable to open config.json file"); // #error: Cannot find a common type for 'char[]' and 'void' + return {}; |}; // #warning: This code will never execute. + char[] bytes2; +} diff --git a/test/test_suite7/errors/empty_fault.c3 b/test/test_suite7/errors/empty_fault.c3 new file mode 100644 index 000000000..855ecfbb5 --- /dev/null +++ b/test/test_suite7/errors/empty_fault.c3 @@ -0,0 +1,4 @@ +module test; +fault Foo +{ +} // #error: no values \ No newline at end of file diff --git a/test/test_suite7/errors/error_decl_ok.c3 b/test/test_suite7/errors/error_decl_ok.c3 new file mode 100644 index 000000000..a17338068 --- /dev/null +++ b/test/test_suite7/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_suite7/errors/error_else.c3t b/test/test_suite7/errors/error_else.c3t new file mode 100644 index 000000000..c818323fd --- /dev/null +++ b/test/test_suite7/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_suite7/errors/error_introspect.c3t b/test/test_suite7/errors/error_introspect.c3t new file mode 100644 index 000000000..9dd2e1bf6 --- /dev/null +++ b/test/test_suite7/errors/error_introspect.c3t @@ -0,0 +1,72 @@ +// #target: macos-x64 +module foo; +import std::io; + +fault Foo +{ + BAR, + BAZ +} + +fn void main() +{ + String[] x = Foo.names; + io::printfn("Foo.names: %s", x); + io::printfn("Foo.values: %s", Foo.values); + io::printfn("Foo.elements: %s", Foo.elements); +} + +/* #expect: foo.ll + +@"foo.Foo$BAR" = linkonce constant %.fault { i64 ptrtoint (ptr @"$ct.foo.Foo" to i64), %"char[]" { ptr @.fault, i64 3 }, i64 1 }, align 8 +@.fault = internal constant [4 x i8] c"BAR\00", align 1 +@"foo.Foo$BAZ" = linkonce constant %.fault { i64 ptrtoint (ptr @"$ct.foo.Foo" to i64), %"char[]" { ptr @.fault.1, i64 3 }, i64 2 }, align 8 +@.fault.1 = internal constant [4 x i8] c"BAZ\00", align 1 +@"$ct.foo.Foo" = linkonce global %.introspect { i8 9, i64 0, ptr null, i64 8, i64 0, i64 2, [0 x i64] zeroinitializer }, align 8 +@.str = private unnamed_addr constant [4 x i8] c"BAR\00", align 1 +@.str.2 = private unnamed_addr constant [4 x i8] c"BAZ\00", align 1 +@.__const = private unnamed_addr constant [2 x %"char[]"] [%"char[]" { ptr @.str, i64 3 }, %"char[]" { ptr @.str.2, i64 3 }], align 16 +@.str.3 = private unnamed_addr constant [14 x i8] c"Foo.names: %s\00", align 1 +@"$ct.sa$String" = linkonce global %.introspect { i8 16, i64 0, ptr null, i64 16, i64 ptrtoint (ptr @"$ct.String" to i64), i64 0, [0 x i64] zeroinitializer }, align 8 +@"$ct.String" = linkonce global %.introspect { i8 18, i64 ptrtoint (ptr @"$ct.sa$char" to i64), ptr null, i64 16, i64 ptrtoint (ptr @"$ct.sa$char" to i64), i64 0, [0 x i64] zeroinitializer }, align 8 +@"$ct.sa$char" = linkonce global %.introspect { i8 16, i64 0, ptr null, i64 16, i64 ptrtoint (ptr @"$ct.char" to i64), i64 0, [0 x i64] zeroinitializer }, align 8 +@"$ct.char" = linkonce global %.introspect { i8 3, i64 0, ptr null, i64 1, i64 0, i64 0, [0 x i64] zeroinitializer }, align 8 +@.str.4 = private unnamed_addr constant [15 x i8] c"Foo.values: %s\00", align 1 +@.__const.5 = private unnamed_addr constant [2 x i64] [i64 ptrtoint (ptr @"foo.Foo$BAR" to i64), i64 ptrtoint (ptr @"foo.Foo$BAZ" to i64)], align 16 +@"$ct.a2$foo.Foo" = linkonce global %.introspect { i8 15, i64 0, ptr null, i64 16, i64 ptrtoint (ptr @"$ct.foo.Foo" to i64), i64 2, [0 x i64] zeroinitializer }, align 8 +@.str.6 = private unnamed_addr constant [17 x i8] c"Foo.elements: %s\00", align 1 +@"$ct.long" = linkonce global %.introspect { i8 2, i64 0, ptr null, i64 8, i64 0, i64 0, [0 x i64] zeroinitializer }, align 8 + +; Function Attrs: +define void @foo.main() #0 { +entry: + %x = alloca %"char[][]", align 8 + %literal = alloca [2 x %"char[]"], align 16 + %varargslots = alloca [1 x %any], align 16 + %retparam = alloca i64, align 8 + %varargslots1 = alloca [1 x %any], align 16 + %literal2 = alloca [2 x i64], align 16 + %retparam3 = alloca i64, align 8 + %varargslots4 = alloca [1 x %any], align 16 + %taddr = alloca i64, align 8 + %retparam5 = alloca i64, align 8 + call void @llvm.memcpy.p0.p0.i32(ptr align 8 %literal, ptr align 16 @.__const, i32 32, i1 false) + %0 = insertvalue %"char[][]" undef, ptr %literal, 0 + %1 = insertvalue %"char[][]" %0, i64 2, 1 + store %"char[][]" %1, ptr %x, align 8 + %2 = insertvalue %any undef, ptr %x, 0 + %3 = insertvalue %any %2, i64 ptrtoint (ptr @"$ct.sa$String" to i64), 1 + store %any %3, ptr %varargslots, align 16 + %4 = call i64 @std.io.printfn(ptr %retparam, ptr @.str.3, i64 13, ptr %varargslots, i64 1) + call void @llvm.memcpy.p0.p0.i32(ptr align 8 %literal2, ptr align 16 @.__const.5, i32 16, i1 false) + %5 = insertvalue %any undef, ptr %literal2, 0 + %6 = insertvalue %any %5, i64 ptrtoint (ptr @"$ct.a2$foo.Foo" to i64), 1 + store %any %6, ptr %varargslots1, align 16 + %7 = call i64 @std.io.printfn(ptr %retparam3, ptr @.str.4, i64 14, ptr %varargslots1, i64 1) + store i64 2, ptr %taddr, align 8 + %8 = insertvalue %any undef, ptr %taddr, 0 + %9 = insertvalue %any %8, i64 ptrtoint (ptr @"$ct.long" to i64), 1 + store %any %9, ptr %varargslots4, align 16 + %10 = call i64 @std.io.printfn(ptr %retparam5, ptr @.str.6, i64 16, ptr %varargslots4, i64 1) + ret void +} diff --git a/test/test_suite7/errors/error_regression_2.c3t b/test/test_suite7/errors/error_regression_2.c3t new file mode 100644 index 000000000..12649f621 --- /dev/null +++ b/test/test_suite7/errors/error_regression_2.c3t @@ -0,0 +1,835 @@ +// #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 ? (char*)"true" : (char*)"false"); +} + +fn bool contains(char[] haystack, char[] needle) +{ + usz len = haystack.len; + usz needle_len = needle.len; + if (len < needle_len) return false; + if (!needle_len) return true; + len -= needle_len - 1; + for (usz 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 = malloc($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. + isz len = libc::snprintf(null, 0, "Title of %.*s", (int)url.len, url.ptr); + char* str = malloc(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 { + .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(anyfault 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) ? (char*)"true" : (char*)"false"); + } +} + +/* #expect: test.ll + +define void @test.Summary.print(ptr %0, ptr %1) #0 { +entry: + %title = alloca %"char[]", align 8 + %2 = load ptr, ptr %0, align 8 + %i2b = icmp ne ptr %2, null + br i1 %i2b, label %cond.lhs, label %cond.rhs + +cond.lhs: ; preds = %entry + %3 = load ptr, ptr %0, align 8 + %4 = load %"char[]", ptr %3, align 8 + br label %cond.phi + +cond.rhs: ; preds = %entry + br label %cond.phi + +cond.phi: ; preds = %cond.rhs, %cond.lhs + %val = phi %"char[]" [ %4, %cond.lhs ], [ { ptr @.str.28, i64 7 }, %cond.rhs ] + store %"char[]" %val, ptr %title, align 8 + %ptradd = getelementptr inbounds i8, ptr %title, i64 8 + %5 = load i64, ptr %ptradd, align 8 + %trunc = trunc i64 %5 to i32 + %ptradd1 = getelementptr inbounds i8, ptr %0, i64 8 + %6 = load i8, ptr %ptradd1, align 8 + %7 = trunc i8 %6 to i1 + %ternary = select i1 %7, ptr @.str.30, ptr @.str.31 + %8 = load ptr, ptr %title, align 8 + %9 = call i32 (ptr, ptr, ...) @fprintf(ptr %1, ptr @.str.29, i32 %trunc, ptr %8, ptr %ternary) + ret void +} + +; Function Attrs: +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 + store ptr %0, ptr %haystack, align 8 + %ptradd = getelementptr inbounds i8, ptr %haystack, i64 8 + store i64 %1, ptr %ptradd, align 8 + store ptr %2, ptr %needle, align 8 + %ptradd1 = getelementptr inbounds i8, ptr %needle, i64 8 + store i64 %3, ptr %ptradd1, align 8 + %ptradd2 = getelementptr inbounds i8, ptr %haystack, i64 8 + %4 = load i64, ptr %ptradd2, align 8 + store i64 %4, ptr %len, align 8 + %ptradd3 = getelementptr inbounds i8, ptr %needle, i64 8 + %5 = load i64, ptr %ptradd3, align 8 + store i64 %5, ptr %needle_len, align 8 + %6 = load i64, ptr %len, align 8 + %7 = load i64, ptr %needle_len, align 8 + %lt = icmp ult i64 %6, %7 + br i1 %lt, label %if.then, label %if.exit + +if.then: ; preds = %entry + ret i8 0 + +if.exit: ; preds = %entry + %8 = load i64, ptr %needle_len, align 8 + %i2nb = icmp eq i64 %8, 0 + br i1 %i2nb, label %if.then4, label %if.exit5 + +if.then4: ; preds = %if.exit + ret i8 1 + +if.exit5: ; preds = %if.exit + %9 = load i64, ptr %len, align 8 + %10 = load i64, ptr %needle_len, align 8 + %sub = sub i64 %10, 1 + %sub6 = sub i64 %9, %sub + store i64 %sub6, ptr %len, align 8 + store i64 0, ptr %i, align 8 + br label %loop.cond + +loop.cond: ; preds = %if.exit10, %if.exit5 + %11 = load i64, ptr %i, align 8 + %12 = load i64, ptr %len, align 8 + %lt7 = icmp ult i64 %11, %12 + br i1 %lt7, label %loop.body, label %loop.exit + +loop.body: ; preds = %loop.cond + %13 = load ptr, ptr %haystack, align 8 + %14 = load i64, ptr %i, align 8 + %ptradd8 = getelementptr inbounds i8, ptr %13, i64 %14 + %15 = load ptr, ptr %needle, align 8 + %16 = load i64, ptr %needle_len, align 8 + %17 = call i32 @memcmp(ptr %ptradd8, ptr %15, i64 %16) + %eq = icmp eq i32 %17, 0 + br i1 %eq, label %if.then9, label %if.exit10 + +if.then9: ; preds = %loop.body + ret i8 1 + +if.exit10: ; preds = %loop.body + %18 = load i64, ptr %i, align 8 + %add = add i64 %18, 1 + store i64 %add, ptr %i, align 8 + br label %loop.cond + +loop.exit: ; preds = %loop.cond + ret i8 0 +} + +; Function Attrs: +define i64 @test.readDoc(ptr %0, ptr %1, i64 %2) #0 { +entry: + %url = alloca %"char[]", align 8 + %reterr = alloca i64, align 8 + %literal = alloca %Doc, align 8 + %reterr11 = alloca i64, align 8 + %literal12 = alloca %Doc, align 8 + %error_var = alloca i64, align 8 + %literal13 = alloca %Head, align 8 + %value = alloca %Head, align 8 + %temp = alloca ptr, align 8 + %reterr21 = alloca i64, align 8 + %literal22 = alloca %Doc, align 8 + %error_var23 = alloca i64, align 8 + %literal24 = alloca %Head, align 8 + %error_var25 = alloca i64, align 8 + %value26 = alloca %"char[]", align 8 + %temp27 = alloca ptr, align 8 + %value33 = alloca %Head, align 8 + %temp34 = alloca ptr, align 8 + %len = alloca i64, align 8 + %str = alloca ptr, align 8 + %reterr48 = alloca i64, align 8 + %literal49 = alloca %Doc, align 8 + %error_var50 = alloca i64, align 8 + %literal51 = alloca %Head, align 8 + %error_var52 = alloca i64, align 8 + %value53 = alloca %"char[]", align 8 + %temp54 = alloca ptr, align 8 + %value60 = alloca %Head, align 8 + %temp61 = alloca ptr, align 8 + store ptr %1, ptr %url, align 8 + %ptradd = getelementptr inbounds i8, ptr %url, i64 8 + store i64 %2, ptr %ptradd, align 8 + %lo = load ptr, ptr %url, align 8 + %ptradd1 = getelementptr inbounds i8, ptr %url, i64 8 + %hi = load i64, ptr %ptradd1, align 8 + %3 = call i8 @test.contains(ptr %lo, i64 %hi, ptr @.str, i64 4) + %4 = trunc i8 %3 to i1 + br i1 %4, label %if.then, label %if.exit + +if.then: ; preds = %entry + ret i64 ptrtoint (ptr @"test.ReadError$BAD_READ" to i64) + +if.exit: ; preds = %entry + %lo2 = load ptr, ptr %url, align 8 + %ptradd3 = getelementptr inbounds i8, ptr %url, i64 8 + %hi4 = load i64, ptr %ptradd3, align 8 + %5 = call i8 @test.contains(ptr %lo2, i64 %hi4, ptr @.str.3, i64 12) + %6 = trunc i8 %5 to i1 + br i1 %6, label %if.then5, label %if.exit6 + +if.then5: ; preds = %if.exit + call void @llvm.memcpy.p0.p0.i32(ptr align 8 %literal, ptr align 8 @.__const, i32 8, i1 false) + call void @llvm.memcpy.p0.p0.i32(ptr align 8 %0, ptr align 8 %literal, i32 8, i1 false) + ret i64 0 + +if.exit6: ; preds = %if.exit + %lo7 = load ptr, ptr %url, align 8 + %ptradd8 = getelementptr inbounds i8, ptr %url, i64 8 + %hi9 = load i64, ptr %ptradd8, align 8 + %7 = call i8 @test.contains(ptr %lo7, i64 %hi9, ptr @.str.4, i64 13) + %8 = trunc i8 %7 to i1 + br i1 %8, label %if.then10, label %if.exit16 + +if.then10: ; preds = %if.exit6 + call void @llvm.memcpy.p0.p0.i32(ptr align 8 %literal13, ptr align 8 @.__const.5, i32 8, i1 false) + call void @llvm.memcpy.p0.p0.i32(ptr align 8 %value, ptr align 8 %literal13, i32 8, i1 false) + %9 = call ptr @std.core.mem.malloc(i64 8) #3 + store ptr %9, ptr %temp, align 8 + %10 = load ptr, ptr %temp, align 8 + %i2nb = icmp eq ptr %10, null + br i1 %i2nb, label %if.then14, label %if.exit15 + +if.then14: ; preds = %if.then10 + store i64 ptrtoint (ptr @"test.ReadError$OUT_OF_MEMORY" to i64), ptr %error_var, align 8 + br label %guard_block + +if.exit15: ; preds = %if.then10 + %11 = load ptr, ptr %temp, align 8 + call void @llvm.memcpy.p0.p0.i32(ptr align 8 %11, ptr align 8 %value, i32 8, i1 false) + br label %noerr_block + +guard_block: ; preds = %if.then14 + %12 = load i64, ptr %error_var, align 8 + ret i64 %12 + +noerr_block: ; preds = %if.exit15 + %13 = load ptr, ptr %temp, align 8 + store ptr %13, ptr %literal12, align 8 + call void @llvm.memcpy.p0.p0.i32(ptr align 8 %0, ptr align 8 %literal12, i32 8, i1 false) + ret i64 0 + +if.exit16: ; preds = %if.exit6 + %lo17 = load ptr, ptr %url, align 8 + %ptradd18 = getelementptr inbounds i8, ptr %url, i64 8 + %hi19 = load i64, ptr %ptradd18, align 8 + %14 = call i8 @test.contains(ptr %lo17, i64 %hi19, ptr @.str.6, i64 11) + %15 = trunc i8 %14 to i1 + br i1 %15, label %if.then20, label %if.exit40 + +if.then20: ; preds = %if.exit16 + store ptr null, ptr %literal24, align 8 + store %"char[]" zeroinitializer, ptr %value26, align 8 + %16 = call ptr @std.core.mem.malloc(i64 16) #3 + store ptr %16, ptr %temp27, align 8 + %17 = load ptr, ptr %temp27, align 8 + %i2nb28 = icmp eq ptr %17, null + br i1 %i2nb28, label %if.then29, label %if.exit30 + +if.then29: ; preds = %if.then20 + store i64 ptrtoint (ptr @"test.ReadError$OUT_OF_MEMORY" to i64), ptr %error_var25, align 8 + br label %guard_block31 + +if.exit30: ; preds = %if.then20 + %18 = load ptr, ptr %temp27, align 8 + call void @llvm.memcpy.p0.p0.i32(ptr align 8 %18, ptr align 8 %value26, i32 16, i1 false) + br label %noerr_block32 + +guard_block31: ; preds = %if.then29 + %19 = load i64, ptr %error_var25, align 8 + ret i64 %19 + +noerr_block32: ; preds = %if.exit30 + %20 = load ptr, ptr %temp27, align 8 + store ptr %20, ptr %literal24, align 8 + call void @llvm.memcpy.p0.p0.i32(ptr align 8 %value33, ptr align 8 %literal24, i32 8, i1 false) + %21 = call ptr @std.core.mem.malloc(i64 8) #3 + store ptr %21, ptr %temp34, align 8 + %22 = load ptr, ptr %temp34, align 8 + %i2nb35 = icmp eq ptr %22, null + br i1 %i2nb35, label %if.then36, label %if.exit37 + +if.then36: ; preds = %noerr_block32 + store i64 ptrtoint (ptr @"test.ReadError$OUT_OF_MEMORY" to i64), ptr %error_var23, align 8 + br label %guard_block38 + +if.exit37: ; preds = %noerr_block32 + %23 = load ptr, ptr %temp34, align 8 + call void @llvm.memcpy.p0.p0.i32(ptr align 8 %23, ptr align 8 %value33, i32 8, i1 false) + br label %noerr_block39 + +guard_block38: ; preds = %if.then36 + %24 = load i64, ptr %error_var23, align 8 + ret i64 %24 + +noerr_block39: ; preds = %if.exit37 + %25 = load ptr, ptr %temp34, align 8 + store ptr %25, ptr %literal22, align 8 + call void @llvm.memcpy.p0.p0.i32(ptr align 8 %0, ptr align 8 %literal22, i32 8, i1 false) + ret i64 0 + +if.exit40: ; preds = %if.exit16 + %ptradd41 = getelementptr inbounds i8, ptr %url, i64 8 + %26 = load i64, ptr %ptradd41, align 8 + %trunc = trunc i64 %26 to i32 + %27 = load ptr, ptr %url, align 8 + %28 = call i32 (ptr, i64, ptr, ...) @snprintf(ptr null, i64 0, ptr @.str.7, i32 %trunc, ptr %27) + %sext = sext i32 %28 to i64 + store i64 %sext, ptr %len, align 8 + %29 = load i64, ptr %len, align 8 + %add = add i64 %29, 1 + %30 = call ptr @std.core.mem.malloc(i64 %add) #3 + store ptr %30, ptr %str, align 8 + %31 = load ptr, ptr %str, align 8 + %i2nb42 = icmp eq ptr %31, null + br i1 %i2nb42, label %if.then43, label %if.exit44 + +if.then43: ; preds = %if.exit40 + ret i64 ptrtoint (ptr @"test.ReadError$OUT_OF_MEMORY" to i64) + +if.exit44: ; preds = %if.exit40 + %32 = load i64, ptr %len, align 8 + %add45 = add i64 %32, 1 + %ptradd46 = getelementptr inbounds i8, ptr %url, i64 8 + %33 = load i64, ptr %ptradd46, align 8 + %trunc47 = trunc i64 %33 to i32 + %34 = load ptr, ptr %str, align 8 + %35 = load ptr, ptr %url, align 8 + %36 = call i32 (ptr, i64, ptr, ...) @snprintf(ptr %34, i64 %add45, ptr @.str.8, i32 %trunc47, ptr %35) + store ptr null, ptr %literal51, align 8 + %37 = load ptr, ptr %str, align 8 + %38 = load i64, ptr %len, align 8 + %sub = sub i64 %38, 1 + %39 = add i64 %sub, 1 + %size = sub i64 %39, 0 + %40 = insertvalue %"char[]" undef, ptr %37, 0 + %41 = insertvalue %"char[]" %40, i64 %size, 1 + store %"char[]" %41, ptr %value53, align 8 + %42 = call ptr @std.core.mem.malloc(i64 16) #3 + store ptr %42, ptr %temp54, align 8 + %43 = load ptr, ptr %temp54, align 8 + %i2nb55 = icmp eq ptr %43, null + br i1 %i2nb55, label %if.then56, label %if.exit57 + +if.then56: ; preds = %if.exit44 + store i64 ptrtoint (ptr @"test.ReadError$OUT_OF_MEMORY" to i64), ptr %error_var52, align 8 + br label %guard_block58 + +if.exit57: ; preds = %if.exit44 + %44 = load ptr, ptr %temp54, align 8 + call void @llvm.memcpy.p0.p0.i32(ptr align 8 %44, ptr align 8 %value53, i32 16, i1 false) + br label %noerr_block59 + +guard_block58: ; preds = %if.then56 + %45 = load i64, ptr %error_var52, align 8 + ret i64 %45 + +noerr_block59: ; preds = %if.exit57 + %46 = load ptr, ptr %temp54, align 8 + store ptr %46, ptr %literal51, align 8 + call void @llvm.memcpy.p0.p0.i32(ptr align 8 %value60, ptr align 8 %literal51, i32 8, i1 false) + %47 = call ptr @std.core.mem.malloc(i64 8) #3 + store ptr %47, ptr %temp61, align 8 + %48 = load ptr, ptr %temp61, align 8 + %i2nb62 = icmp eq ptr %48, null + br i1 %i2nb62, label %if.then63, label %if.exit64 + +if.then63: ; preds = %noerr_block59 + store i64 ptrtoint (ptr @"test.ReadError$OUT_OF_MEMORY" to i64), ptr %error_var50, align 8 + br label %guard_block65 + +if.exit64: ; preds = %noerr_block59 + %49 = load ptr, ptr %temp61, align 8 + call void @llvm.memcpy.p0.p0.i32(ptr align 8 %49, ptr align 8 %value60, i32 8, i1 false) + br label %noerr_block66 + +guard_block65: ; preds = %if.then63 + %50 = load i64, ptr %error_var50, align 8 + ret i64 %50 + +noerr_block66: ; preds = %if.exit64 + %51 = load ptr, ptr %temp61, align 8 + store ptr %51, ptr %literal49, align 8 + call void @llvm.memcpy.p0.p0.i32(ptr align 8 %0, ptr align 8 %literal49, i32 8, i1 false) + ret i64 0 +} + +; Function Attrs: +define { ptr, i8 } @test.buildSummary(ptr %0) #0 { +entry: + %doc = alloca %Doc, align 8 + %literal = alloca %Summary, align 8 + store ptr %0, ptr %doc, align 8 + store ptr null, ptr %literal, align 8 + %ptradd = getelementptr inbounds i8, ptr %literal, i64 8 + store i8 0, ptr %ptradd, align 8 + %1 = load ptr, ptr %doc, align 8 + %i2b = icmp ne ptr %1, null + br i1 %i2b, label %cond.lhs, label %cond.rhs + +cond.lhs: ; preds = %entry + %2 = load ptr, ptr %doc, align 8 + %3 = load ptr, ptr %2, align 8 + br label %cond.phi + +cond.rhs: ; preds = %entry + br label %cond.phi + +cond.phi: ; preds = %cond.rhs, %cond.lhs + %val = phi ptr [ %3, %cond.lhs ], [ null, %cond.rhs ] + store ptr %val, ptr %literal, align 8 + %ptradd1 = getelementptr inbounds i8, ptr %literal, i64 8 + store i8 1, ptr %ptradd1, align 8 + %4 = load { ptr, i8 }, ptr %literal, align 8 + ret { ptr, i8 } %4 +} + +; Function Attrs: +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 + store ptr %0, ptr %url, align 8 + %ptradd = getelementptr inbounds i8, ptr %url, i64 8 + store i64 %1, ptr %ptradd, align 8 + %lo = load ptr, ptr %url, align 8 + %ptradd1 = getelementptr inbounds i8, ptr %url, i64 8 + %hi = load i64, ptr %ptradd1, align 8 + %2 = call i64 @test.readDoc(ptr %retparam, ptr %lo, i64 %hi) + %not_err = icmp eq i64 %2, 0 + %3 = call i1 @llvm.expect.i1(i1 %not_err, i1 true) + br i1 %3, label %after_check, label %else_block + +after_check: ; preds = %entry + %4 = load ptr, ptr %retparam, align 8 + %5 = call { ptr, i8 } @test.buildSummary(ptr %4) + store { ptr, i8 } %5, ptr %result, align 8 + br label %phi_block + +else_block: ; preds = %entry + call void @llvm.memcpy.p0.p0.i32(ptr align 8 %literal, ptr align 8 @.__const.9, i32 16, i1 false) + br label %phi_block + +phi_block: ; preds = %else_block, %after_check + %val = phi ptr [ %result, %after_check ], [ %literal, %else_block ] + %6 = load { ptr, i8 }, ptr %val, align 8 + ret { ptr, i8 } %6 +} + +; Function Attrs: +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 + store ptr %1, ptr %doc, align 8 + %2 = load ptr, ptr %doc, align 8 + %i2nb = icmp eq ptr %2, null + br i1 %i2nb, label %if.then, label %if.exit + +if.then: ; preds = %entry + ret i64 ptrtoint (ptr @"test.TitleResult$TITLE_MISSING" to i64) + +if.exit: ; preds = %entry + %3 = load ptr, ptr %doc, align 8 + %4 = load ptr, ptr %3, align 8 + store ptr %4, ptr %head, align 8 + %5 = load ptr, ptr %head, align 8 + %i2nb1 = icmp eq ptr %5, null + br i1 %i2nb1, 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 + %6 = load ptr, ptr %head, align 8 + %ptradd = getelementptr inbounds i8, ptr %6, i64 8 + %7 = load i64, ptr %ptradd, align 8 + %lt = icmp ult i64 0, %7 + %8 = zext i1 %lt to i8 + store i8 %8, ptr %0, align 1 + ret i64 0 +} + +; Function Attrs: +define i64 @test.readWhetherTitleNonEmpty(ptr %0, ptr %1, i64 %2) #0 { +entry: + %url = alloca %"char[]", align 8 + %reterr = alloca i64, align 8 + %retparam = alloca %Doc, align 8 + %retparam2 = alloca i8, align 1 + store ptr %1, ptr %url, align 8 + %ptradd = getelementptr inbounds i8, ptr %url, i64 8 + store i64 %2, ptr %ptradd, align 8 + %lo = load ptr, ptr %url, align 8 + %ptradd1 = getelementptr inbounds i8, ptr %url, i64 8 + %hi = load i64, ptr %ptradd1, align 8 + %3 = call i64 @test.readDoc(ptr %retparam, ptr %lo, i64 %hi) + %not_err = icmp eq i64 %3, 0 + %4 = call i1 @llvm.expect.i1(i1 %not_err, i1 true) + br i1 %4, label %after_check, label %assign_optional + +assign_optional: ; preds = %entry + store i64 %3, ptr %reterr, align 8 + br label %err_retblock + +after_check: ; preds = %entry + %5 = load ptr, ptr %retparam, align 8 + %6 = call i64 @test.isTitleNonEmpty(ptr %retparam2, ptr %5) + %not_err3 = icmp eq i64 %6, 0 + %7 = call i1 @llvm.expect.i1(i1 %not_err3, i1 true) + br i1 %7, label %after_check5, label %assign_optional4 + +assign_optional4: ; preds = %after_check + store i64 %6, ptr %reterr, align 8 + br label %err_retblock + +after_check5: ; preds = %after_check + %8 = load i8, ptr %retparam2, align 1 + store i8 %8, ptr %0, align 1 + ret i64 0 + +err_retblock: ; preds = %assign_optional4, %assign_optional + %9 = load i64, ptr %reterr, align 8 + ret i64 %9 +} + +; Function Attrs: +define ptr @test.bool_to_string(i8 zeroext %0) #0 { +entry: + %1 = trunc i8 %0 to i1 + %ternary = select i1 %1, ptr @.str.10, ptr @.str.11 + ret ptr %ternary +} + +; Function Attrs: +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.12 + +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.13 + +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.14 + +next_if6: ; preds = %next_if3 + br label %switch.default + +switch.default: ; preds = %next_if6 + ret ptr @.str.15 +} + +; Function Attrs: +define void @test.main() #0 { +entry: + %.anon = 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 + %blockret = alloca i64, align 8 + %f = alloca i64, align 8 + %0 = load i64, ptr getelementptr inbounds (i8, ptr @main.URLS, i64 8), align 8 + store i64 0, ptr %.anon, align 8 + br label %loop.cond + +loop.cond: ; preds = %phi_block19, %entry + %1 = load i64, ptr %.anon, align 8 + %lt = icmp ult i64 %1, %0 + br i1 %lt, label %loop.body, label %loop.exit + +loop.body: ; preds = %loop.cond + %2 = load ptr, ptr @main.URLS, align 8 + %3 = load i64, ptr %.anon, align 8 + %ptroffset = getelementptr inbounds [16 x i8], ptr %2, i64 %3 + call void @llvm.memcpy.p0.p0.i32(ptr align 8 %url, ptr align 8 %ptroffset, i32 16, i1 false) + %ptradd = getelementptr inbounds i8, ptr %url, i64 8 + %4 = load i64, ptr %ptradd, align 8 + %trunc = trunc i64 %4 to i32 + %5 = load ptr, ptr %url, align 8 + %6 = call i32 (ptr, ...) @printf(ptr @.str.21, i32 %trunc, ptr %5) + %lo = load ptr, ptr %url, align 8 + %ptradd1 = getelementptr inbounds i8, ptr %url, i64 8 + %hi = load i64, ptr %ptradd1, align 8 + %7 = call { ptr, i8 } @test.readAndBuildSummary(ptr %lo, i64 %hi) + store { ptr, i8 } %7, ptr %result, align 8 + call void @llvm.memcpy.p0.p0.i32(ptr align 8 %summary, ptr align 8 %result, i32 16, i1 false) + %8 = call i32 (ptr, ...) @printf(ptr @.str.22) + %9 = load ptr, ptr @__stdoutp, align 8 + call void @test.Summary.print(ptr %summary, ptr %9) + %10 = call i32 (ptr, ...) @printf(ptr @.str.23) + %11 = load ptr, ptr %summary, align 8 + %i2b = icmp ne ptr %11, null + br i1 %i2b, label %cond.lhs, label %cond.rhs + +cond.lhs: ; preds = %loop.body + %12 = load ptr, ptr %summary, align 8 + %13 = load %"char[]", ptr %12, 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[]" [ %13, %cond.lhs ], [ zeroinitializer, %cond.rhs ] + store %"char[]" %val, ptr %title_sure, align 8 + %ptradd2 = getelementptr inbounds i8, ptr %title_sure, i64 8 + %14 = load i64, ptr %ptradd2, align 8 + %trunc3 = trunc i64 %14 to i32 + %15 = load ptr, ptr %title_sure, align 8 + %16 = call i32 (ptr, ...) @printf(ptr @.str.24, i32 %trunc3, ptr %15) + %lo4 = load ptr, ptr %url, align 8 + %ptradd5 = getelementptr inbounds i8, ptr %url, i64 8 + %hi6 = load i64, ptr %ptradd5, align 8 + %17 = call i64 @test.readWhetherTitleNonEmpty(ptr %retparam, ptr %lo4, i64 %hi6) + %not_err = icmp eq i64 %17, 0 + %18 = call i1 @llvm.expect.i1(i1 %not_err, i1 true) + br i1 %18, label %after_check, label %assign_optional + +assign_optional: ; preds = %cond.phi + store i64 %17, ptr %has_title.f, align 8 + br label %after_assign + +after_check: ; preds = %cond.phi + %19 = load i8, ptr %retparam, align 1 + store i8 %19, ptr %has_title, align 1 + store i64 0, ptr %has_title.f, align 8 + br label %after_assign + +after_assign: ; preds = %after_check, %assign_optional + %optval = load i64, ptr %has_title.f, align 8 + %not_err7 = icmp eq i64 %optval, 0 + %20 = call i1 @llvm.expect.i1(i1 %not_err7, i1 true) + br i1 %20, label %after_check8, label %else_block + +after_check8: ; preds = %after_assign + %21 = load i8, ptr %has_title, align 1 + %22 = call ptr @test.bool_to_string(i8 zeroext %21) + br label %phi_block + +else_block: ; preds = %after_assign + br label %testblock + +testblock: ; preds = %else_block + %optval9 = load i64, ptr %has_title.f, align 8 + %not_err10 = icmp eq i64 %optval9, 0 + %23 = call i1 @llvm.expect.i1(i1 %not_err10, i1 true) + br i1 %23, label %after_check12, label %assign_optional11 + +assign_optional11: ; preds = %testblock + store i64 %optval9, ptr %f, align 8 + br label %end_block + +after_check12: ; preds = %testblock + store i64 0, ptr %f, align 8 + br label %end_block + +end_block: ; preds = %after_check12, %assign_optional11 + %24 = load i64, ptr %f, align 8 + %i2b13 = icmp ne i64 %24, 0 + br i1 %i2b13, label %if.then, label %if.exit + +if.then: ; preds = %end_block + %25 = load i64, ptr %f, align 8 + store i64 %25, ptr %blockret, align 8 + br label %expr_block.exit + +if.exit: ; preds = %end_block + store i64 0, ptr %blockret, align 8 + br label %expr_block.exit + +expr_block.exit: ; preds = %if.exit, %if.then + %26 = load i64, ptr %blockret, align 8 + %27 = call ptr @test.nameFromError(i64 %26) + br label %phi_block + +phi_block: ; preds = %expr_block.exit, %after_check8 + %val14 = phi ptr [ %22, %after_check8 ], [ %27, %expr_block.exit ] + %optval15 = load i64, ptr %has_title.f, align 8 + %not_err16 = icmp eq i64 %optval15, 0 + %28 = call i1 @llvm.expect.i1(i1 %not_err16, i1 true) + br i1 %28, label %after_check17, label %else_block18 + +after_check17: ; preds = %phi_block + %29 = load i8, ptr %has_title, align 1 + %30 = trunc i8 %29 to i1 + br label %phi_block19 + +else_block18: ; preds = %phi_block + br label %phi_block19 + +phi_block19: ; preds = %else_block18, %after_check17 + %val20 = phi i1 [ %30, %after_check17 ], [ false, %else_block18 ] + %ternary = select i1 %val20, ptr @.str.26, ptr @.str.27 + %31 = call i32 (ptr, ...) @printf(ptr @.str.25, ptr %val14, ptr %ternary) + %32 = load i64, ptr %.anon, align 8 + %addnuw = add nuw i64 %32, 1 + store i64 %addnuw, ptr %.anon, align 8 + br label %loop.cond + +loop.exit: ; preds = %loop.cond + ret void +} diff --git a/test/test_suite7/errors/error_semantic_fails.c3 b/test/test_suite7/errors/error_semantic_fails.c3 new file mode 100644 index 000000000..bfafa510f --- /dev/null +++ b/test/test_suite7/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_suite7/errors/error_throw.c3 b/test/test_suite7/errors/error_throw.c3 new file mode 100644 index 000000000..e540cb29f --- /dev/null +++ b/test/test_suite7/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_suite7/errors/error_union.c3 b/test/test_suite7/errors/error_union.c3 new file mode 100644 index 000000000..9996b2c2a --- /dev/null +++ b/test/test_suite7/errors/error_union.c3 @@ -0,0 +1,11 @@ +module foo; + +fault Blurg +{ + X, Y, Z +} + +fn void main() +{ + anyfault foo; +} \ No newline at end of file diff --git a/test/test_suite7/errors/failable_catch.c3t b/test/test_suite7/errors/failable_catch.c3t new file mode 100644 index 000000000..b8b827ad3 --- /dev/null +++ b/test/test_suite7/errors/failable_catch.c3t @@ -0,0 +1,185 @@ +// #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); + (void)printf("a = %d\n", a); + (void)printf("b = %d\n", b); + (void)printf("c = %d\n", c); + if (@catch(c)) printf("c had error\n"); + c = 3; + (void)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 + %blockret = alloca i32, align 4 + %b = alloca i32, align 4 + %b.f = alloca i64, align 8 + %blockret1 = alloca i32, align 4 + %c = alloca i32, align 4 + %c.f = alloca i64, align 8 + %blockret19 = alloca i64, align 8 + %f = alloca i64, align 8 + br label %if.then + +if.then: ; preds = %entry + store i32 1, ptr %blockret, align 4 + br label %expr_block.exit + +expr_block.exit: ; preds = %if.then + %0 = load i32, ptr %blockret, align 4 + store i32 %0, ptr %a, align 4 + store i64 0, ptr %a.f, align 8 + br label %after_assign + +after_assign: ; preds = %expr_block.exit + %optval = load i64, ptr %a.f, align 8 + %not_err = icmp eq i64 %optval, 0 + %1 = call i1 @llvm.expect.i1(i1 %not_err, i1 true) + br i1 %1, label %after_check, label %else_block + +after_check: ; preds = %after_assign + %2 = load i32, ptr %a, align 4 + %add = add i32 %2, 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 ] + %i2b = icmp ne i32 %val, 0 + br i1 %i2b, label %if.then2, label %if.exit + +if.then2: ; preds = %phi_block + store i32 %val, ptr %blockret1, align 4 + br label %expr_block.exit3 + +if.exit: ; preds = %phi_block + store i64 ptrtoint (ptr @"failable_catch.MyErr$TEST" to i64), ptr %b.f, align 8 + br label %after_assign4 + +expr_block.exit3: ; preds = %if.then2 + %3 = load i32, ptr %blockret1, align 4 + store i32 %3, ptr %b, align 4 + store i64 0, ptr %b.f, align 8 + br label %after_assign4 + +after_assign4: ; preds = %expr_block.exit3, %if.exit + br label %if.exit6 + +if.exit6: ; preds = %after_assign4 + store i64 ptrtoint (ptr @"failable_catch.MyErr$TEST" to i64), ptr %c.f, align 8 + br label %after_assign7 + +after_assign7: ; preds = %if.exit6 + %optval8 = load i64, ptr %a.f, align 8 + %not_err9 = icmp eq i64 %optval8, 0 + %4 = call i1 @llvm.expect.i1(i1 %not_err9, i1 true) + br i1 %4, label %after_check10, label %voiderr + +after_check10: ; preds = %after_assign7 + %5 = load i32, ptr %a, align 4 + call void (ptr, ...) @printf(ptr @.str, i32 %5) + br label %voiderr + +voiderr: ; preds = %after_check10, %after_assign7 + %optval11 = load i64, ptr %b.f, align 8 + %not_err12 = icmp eq i64 %optval11, 0 + %6 = call i1 @llvm.expect.i1(i1 %not_err12, i1 true) + br i1 %6, label %after_check13, label %voiderr14 + +after_check13: ; preds = %voiderr + %7 = load i32, ptr %b, align 4 + call void (ptr, ...) @printf(ptr @.str.1, i32 %7) + br label %voiderr14 + +voiderr14: ; preds = %after_check13, %voiderr + %optval15 = load i64, ptr %c.f, align 8 + %not_err16 = icmp eq i64 %optval15, 0 + %8 = call i1 @llvm.expect.i1(i1 %not_err16, i1 true) + br i1 %8, label %after_check17, label %voiderr18 + +after_check17: ; preds = %voiderr14 + %9 = load i32, ptr %c, align 4 + call void (ptr, ...) @printf(ptr @.str.2, i32 %9) + br label %voiderr18 + +voiderr18: ; preds = %after_check17, %voiderr14 + br label %testblock + +testblock: ; preds = %voiderr18 + %optval20 = load i64, ptr %c.f, align 8 + %not_err21 = icmp eq i64 %optval20, 0 + %10 = call i1 @llvm.expect.i1(i1 %not_err21, i1 true) + br i1 %10, label %after_check22, label %assign_optional + +assign_optional: ; preds = %testblock + store i64 %optval20, ptr %f, align 8 + br label %end_block + +after_check22: ; preds = %testblock + store i64 0, ptr %f, align 8 + br label %end_block + +end_block: ; preds = %after_check22, %assign_optional + %11 = load i64, ptr %f, align 8 + %i2b23 = icmp ne i64 %11, 0 + br i1 %i2b23, label %if.then24, label %if.exit25 + +if.then24: ; preds = %end_block + %12 = load i64, ptr %f, align 8 + store i64 %12, ptr %blockret19, align 8 + br label %expr_block.exit26 + +if.exit25: ; preds = %end_block + store i64 0, ptr %blockret19, align 8 + br label %expr_block.exit26 + +expr_block.exit26: ; preds = %if.exit25, %if.then24 + %13 = load i64, ptr %blockret19, align 8 + %i2b27 = icmp ne i64 %13, 0 + br i1 %i2b27, label %if.then28, label %if.exit29 + +if.then28: ; preds = %expr_block.exit26 + call void (ptr, ...) @printf(ptr @.str.3) + br label %if.exit29 + +if.exit29: ; preds = %if.then28, %expr_block.exit26 + store i32 3, ptr %c, align 4 + store i64 0, ptr %c.f, align 8 + %optval30 = load i64, ptr %c.f, align 8 + %not_err31 = icmp eq i64 %optval30, 0 + %14 = call i1 @llvm.expect.i1(i1 %not_err31, i1 true) + br i1 %14, label %after_check32, label %voiderr33 + +after_check32: ; preds = %if.exit29 + %15 = load i32, ptr %c, align 4 + call void (ptr, ...) @printf(ptr @.str.4, i32 %15) + br label %voiderr33 + +voiderr33: ; preds = %after_check32, %if.exit29 + ret i32 0 +} diff --git a/test/test_suite7/errors/fault_conv.c3t b/test/test_suite7/errors/fault_conv.c3t new file mode 100644 index 000000000..e900b0aec --- /dev/null +++ b/test/test_suite7/errors/fault_conv.c3t @@ -0,0 +1,123 @@ +// #target: macos-x64 +module test; +import std::io; + +fault HadError +{ + BAD_STUFF, + WORSE_STUFF, + THE_WORST_STUFF +} + +fn int exitcode(anyfault error) +{ + switch ((HadError)error) + { + case BAD_STUFF: return 64; + case WORSE_STUFF: return 65; + case THE_WORST_STUFF: return 66; + default: return 70; + } +} + +fn void! canFail() +{ + if (34 + 35 == 69) + { + return HadError.BAD_STUFF?; + } +} + +fn int main(String[] args) +{ + if (catch err = canFail()) + { + return exitcode(err); + } + + return 0; +} + +/* #expect: test.ll + + +define i32 @test.exitcode(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.HadError$BAD_STUFF" to i64), %1 + br i1 %eq, label %switch.case, label %next_if + +switch.case: ; preds = %switch.entry + ret i32 64 + +next_if: ; preds = %switch.entry + %eq1 = icmp eq i64 ptrtoint (ptr @"test.HadError$WORSE_STUFF" to i64), %1 + br i1 %eq1, label %switch.case2, label %next_if3 + +switch.case2: ; preds = %next_if + ret i32 65 + +next_if3: ; preds = %next_if + %eq4 = icmp eq i64 ptrtoint (ptr @"test.HadError$THE_WORST_STUFF" to i64), %1 + br i1 %eq4, label %switch.case5, label %next_if6 + +switch.case5: ; preds = %next_if3 + ret i32 66 + +next_if6: ; preds = %next_if3 + br label %switch.default + +switch.default: ; preds = %next_if6 + ret i32 70 +} + +define i64 @test.canFail() #0 { +entry: + br label %if.then + +if.then: ; preds = %entry + ret i64 ptrtoint (ptr @"test.HadError$BAD_STUFF" to i64) +} + +define i32 @test.main(ptr %0, i64 %1) #0 { +entry: + %args = alloca %"char[][]", align 8 + %err = alloca i64, align 8 + store ptr %0, ptr %args, align 8 + %ptradd = getelementptr inbounds i8, ptr %args, i64 8 + store i64 %1, ptr %ptradd, align 8 + br label %testblock + +testblock: ; preds = %entry + %2 = call i64 @test.canFail() + %not_err = icmp eq i64 %2, 0 + %3 = call i1 @llvm.expect.i1(i1 %not_err, i1 true) + br i1 %3, label %after_check, label %assign_optional + +assign_optional: ; preds = %testblock + store i64 %2, 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, %assign_optional + %4 = load i64, ptr %err, align 8 + %i2b = icmp ne i64 %4, 0 + br i1 %i2b, label %if.then, label %if.exit + +if.then: ; preds = %end_block + %5 = load i64, ptr %err, align 8 + %6 = call i32 @test.exitcode(i64 %5) + ret i32 %6 + +if.exit: ; preds = %end_block + ret i32 0 +} + diff --git a/test/test_suite7/errors/general_error_regression.c3t b/test/test_suite7/errors/general_error_regression.c3t new file mode 100644 index 000000000..521baacaf --- /dev/null +++ b/test/test_suite7/errors/general_error_regression.c3t @@ -0,0 +1,324 @@ +// #target: macos-x64 +module foo; +import std::io; +import libc; +fault Foo +{ + X, + Y, + Z, + W, + W1 + + +} + +fault Foob +{ + X1, + Y2 +} + +distinct Bar = int; + +enum MyEnum +{ + A, + B +} + +fn void Foo.hello(Foo *f) +{ + io::printn("Hello from Foo"); +} + +fn void Bar.hello(Bar *b) +{ + io::printn("Hello from Bar"); +} + +fn void MyEnum.hello(MyEnum *myenum) +{ + io::printn("Hello from MyEnum"); +} +fn void main() +{ + Foo f = Foo.X; + Foo ef = Foo.Y; + anyfault 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: + %len = alloca i64, align 8 + %error_var = alloca i64, align 8 + %retparam = alloca i64, align 8 + %error_var2 = alloca i64, align 8 + %error_var8 = alloca i64, align 8 + %1 = call ptr @std.io.stdout() + %2 = call i64 @std.io.File.write(ptr %retparam, ptr %1, ptr @.str.12, i64 14) + %not_err = icmp eq i64 %2, 0 + %3 = call i1 @llvm.expect.i1(i1 %not_err, i1 true) + br i1 %3, label %after_check, label %assign_optional + +assign_optional: ; preds = %entry + store i64 %2, ptr %error_var, align 8 + br label %guard_block + +after_check: ; preds = %entry + br label %noerr_block + +guard_block: ; preds = %assign_optional + br label %voiderr + +noerr_block: ; preds = %after_check + %4 = load i64, ptr %retparam, align 8 + store i64 %4, ptr %len, align 8 + %5 = call i64 @std.io.File.write_byte(ptr %1, i8 zeroext 10) + %not_err3 = icmp eq i64 %5, 0 + %6 = call i1 @llvm.expect.i1(i1 %not_err3, i1 true) + br i1 %6, label %after_check5, label %assign_optional4 + +assign_optional4: ; preds = %noerr_block + store i64 %5, ptr %error_var2, align 8 + br label %guard_block6 + +after_check5: ; preds = %noerr_block + br label %noerr_block7 + +guard_block6: ; preds = %assign_optional4 + br label %voiderr + +noerr_block7: ; preds = %after_check5 + %7 = call i64 @std.io.File.flush(ptr %1) + %not_err9 = icmp eq i64 %7, 0 + %8 = call i1 @llvm.expect.i1(i1 %not_err9, i1 true) + br i1 %8, label %after_check11, label %assign_optional10 + +assign_optional10: ; preds = %noerr_block7 + store i64 %7, ptr %error_var8, align 8 + br label %guard_block12 + +after_check11: ; preds = %noerr_block7 + br label %noerr_block13 + +guard_block12: ; preds = %assign_optional10 + br label %voiderr + +noerr_block13: ; preds = %after_check11 + %9 = load i64, ptr %len, align 8 + %add = add i64 %9, 1 + br label %voiderr + +voiderr: ; preds = %noerr_block13, %guard_block12, %guard_block6, %guard_block + ret void +} + + +define void @foo.Bar.hello(ptr %0) #0 { +entry: + %len = alloca i64, align 8 + %error_var = alloca i64, align 8 + %retparam = alloca i64, align 8 + %error_var2 = alloca i64, align 8 + %error_var8 = alloca i64, align 8 + %1 = call ptr @std.io.stdout() + %2 = call i64 @std.io.File.write(ptr %retparam, ptr %1, ptr @.str.13, i64 14) + %not_err = icmp eq i64 %2, 0 + %3 = call i1 @llvm.expect.i1(i1 %not_err, i1 true) + br i1 %3, label %after_check, label %assign_optional + +assign_optional: ; preds = %entry + store i64 %2, ptr %error_var, align 8 + br label %guard_block + +after_check: ; preds = %entry + br label %noerr_block + +guard_block: ; preds = %assign_optional + br label %voiderr + +noerr_block: ; preds = %after_check + %4 = load i64, ptr %retparam, align 8 + store i64 %4, ptr %len, align 8 + %5 = call i64 @std.io.File.write_byte(ptr %1, i8 zeroext 10) + %not_err3 = icmp eq i64 %5, 0 + %6 = call i1 @llvm.expect.i1(i1 %not_err3, i1 true) + br i1 %6, label %after_check5, label %assign_optional4 + +assign_optional4: ; preds = %noerr_block + store i64 %5, ptr %error_var2, align 8 + br label %guard_block6 + +after_check5: ; preds = %noerr_block + br label %noerr_block7 + +guard_block6: ; preds = %assign_optional4 + br label %voiderr + +noerr_block7: ; preds = %after_check5 + %7 = call i64 @std.io.File.flush(ptr %1) + %not_err9 = icmp eq i64 %7, 0 + %8 = call i1 @llvm.expect.i1(i1 %not_err9, i1 true) + br i1 %8, label %after_check11, label %assign_optional10 + +assign_optional10: ; preds = %noerr_block7 + store i64 %7, ptr %error_var8, align 8 + br label %guard_block12 + +after_check11: ; preds = %noerr_block7 + br label %noerr_block13 + +guard_block12: ; preds = %assign_optional10 + br label %voiderr + +noerr_block13: ; preds = %after_check11 + %9 = load i64, ptr %len, align 8 + %add = add i64 %9, 1 + br label %voiderr + +voiderr: ; preds = %noerr_block13, %guard_block12, %guard_block6, %guard_block + ret void +} + + +define void @foo.MyEnum.hello(ptr %0) #0 { +entry: + %len = alloca i64, align 8 + %error_var = alloca i64, align 8 + %retparam = alloca i64, align 8 + %error_var2 = alloca i64, align 8 + %error_var8 = alloca i64, align 8 + %1 = call ptr @std.io.stdout() + %2 = call i64 @std.io.File.write(ptr %retparam, ptr %1, ptr @.str.14, i64 17) + %not_err = icmp eq i64 %2, 0 + %3 = call i1 @llvm.expect.i1(i1 %not_err, i1 true) + br i1 %3, label %after_check, label %assign_optional + +assign_optional: ; preds = %entry + store i64 %2, ptr %error_var, align 8 + br label %guard_block + +after_check: ; preds = %entry + br label %noerr_block + +guard_block: ; preds = %assign_optional + br label %voiderr + +noerr_block: ; preds = %after_check + %4 = load i64, ptr %retparam, align 8 + store i64 %4, ptr %len, align 8 + %5 = call i64 @std.io.File.write_byte(ptr %1, i8 zeroext 10) + %not_err3 = icmp eq i64 %5, 0 + %6 = call i1 @llvm.expect.i1(i1 %not_err3, i1 true) + br i1 %6, label %after_check5, label %assign_optional4 + +assign_optional4: ; preds = %noerr_block + store i64 %5, ptr %error_var2, align 8 + br label %guard_block6 + +after_check5: ; preds = %noerr_block + br label %noerr_block7 + +guard_block6: ; preds = %assign_optional4 + br label %voiderr + +noerr_block7: ; preds = %after_check5 + %7 = call i64 @std.io.File.flush(ptr %1) + %not_err9 = icmp eq i64 %7, 0 + %8 = call i1 @llvm.expect.i1(i1 %not_err9, i1 true) + br i1 %8, label %after_check11, label %assign_optional10 + +assign_optional10: ; preds = %noerr_block7 + store i64 %7, ptr %error_var8, align 8 + br label %guard_block12 + +after_check11: ; preds = %noerr_block7 + br label %noerr_block13 + +guard_block12: ; preds = %assign_optional10 + br label %voiderr + +noerr_block13: ; preds = %after_check11 + %9 = load i64, ptr %len, align 8 + %add = add i64 %9, 1 + br label %voiderr + +voiderr: ; preds = %noerr_block13, %guard_block12, %guard_block6, %guard_block + 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.7, 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.8, 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.9, 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.10, 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.11, 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_suite7/errors/illegal_use_of_optional.c3 b/test/test_suite7/errors/illegal_use_of_optional.c3 new file mode 100644 index 000000000..6d33a20ee --- /dev/null +++ b/test/test_suite7/errors/illegal_use_of_optional.c3 @@ -0,0 +1,14 @@ +fn void syntaxErrors() +{ + int! i = 0; + while (i + 1) {} // #error: optional, but was 'int!' + if (i + 1) {} // #error: optional, but was 'int!' + for (int x = i;;) {} // #error: 'int!' to 'int' + for (int x = 0; x < i + 1;) {} // #error: optional, but was 'bool!'. + for (int x = 0; x < 10; x += i + 1) {} // #error: Cannot assign an optional value to a non-optional + switch (i + 1) // #error: optional, but was 'int!' + { + default: + i + 1; + } +} diff --git a/test/test_suite7/errors/invalid_cast_ct.c3 b/test/test_suite7/errors/invalid_cast_ct.c3 new file mode 100644 index 000000000..55c14ebb2 --- /dev/null +++ b/test/test_suite7/errors/invalid_cast_ct.c3 @@ -0,0 +1,16 @@ +module exitcodes; +import std::io; + +fault HadError +{ + BAD_STUFF, + WORSE_STUFF, + THE_WORST_STUFF +} + +fn int main(String[] args) +{ + HadError err = HadError.BAD_STUFF; + SearchResult res = (SearchResult)(anyfault)HadError.BAD_STUFF; // #error: This expression is known at compile time + return 0; +} diff --git a/test/test_suite7/errors/lone_try.c3 b/test/test_suite7/errors/lone_try.c3 new file mode 100644 index 000000000..e1cd036f3 --- /dev/null +++ b/test/test_suite7/errors/lone_try.c3 @@ -0,0 +1,11 @@ +module test; + +fn void main() +{ + try a; // #error: try? +} + +fn void hello() +{ + catch a; // #error: catch? +} diff --git a/test/test_suite7/errors/macro_err.c3t b/test/test_suite7/errors/macro_err.c3t new file mode 100644 index 000000000..23e6ff617 --- /dev/null +++ b/test/test_suite7/errors/macro_err.c3t @@ -0,0 +1,58 @@ +// #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 +} + + +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 + %1 = call i1 @llvm.expect.i1(i1 %not_err, i1 true) + br i1 %1, label %after_check, label %assign_optional + +assign_optional: ; 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 = %assign_optional + br label %else_block + +noerr_block: ; preds = %after_check + %2 = load i32, ptr %retparam, align 4 + br label %phi_block + +else_block: ; preds = %guard_block + br label %phi_block + +phi_block: ; preds = %else_block, %noerr_block + %val = phi i32 [ %2, %noerr_block ], [ 2, %else_block ] + %3 = call i32 (ptr, ...) @printf(ptr @.str, i32 %val) + ret void +} \ No newline at end of file diff --git a/test/test_suite7/errors/macro_err2.c3t b/test/test_suite7/errors/macro_err2.c3t new file mode 100644 index 000000000..da045fa3f --- /dev/null +++ b/test/test_suite7/errors/macro_err2.c3t @@ -0,0 +1,60 @@ +// #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 + %1 = call i1 @llvm.expect.i1(i1 %not_err, i1 true) + br i1 %1, label %after_check, label %opt_block_cleanup + +after_check: ; preds = %entry + %2 = load i32, ptr %retparam, align 4 + store i32 %2, ptr %blockret, align 4 + %3 = call i32 (ptr, ...) @printf(ptr @.str.1) + br label %expr_block.exit + +opt_block_cleanup: ; preds = %entry + %4 = call i32 (ptr, ...) @printf(ptr @.str.2) + br label %else_block + +expr_block.exit: ; preds = %after_check + %5 = 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 [ %5, %expr_block.exit ], [ 2, %else_block ] + %6 = call i32 (ptr, ...) @printf(ptr @.str, i32 %val) + %7 = call i32 (ptr, ...) @printf(ptr @.str.3) + ret void +} diff --git a/test/test_suite7/errors/macro_err3.c3t b/test/test_suite7/errors/macro_err3.c3t new file mode 100644 index 000000000..3cff92b0e --- /dev/null +++ b/test/test_suite7/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_suite7/errors/macro_recurse_twice.c3 b/test/test_suite7/errors/macro_recurse_twice.c3 new file mode 100644 index 000000000..88a768c9d --- /dev/null +++ b/test/test_suite7/errors/macro_recurse_twice.c3 @@ -0,0 +1,13 @@ +module oups; +import std::io; + +fn void main() +{ + recm(1); +} + +macro recm(x) +{ + recm(x + 1); // #error: Failure + recm(x + 1); +} \ No newline at end of file diff --git a/test/test_suite7/errors/missing_bang.c3 b/test/test_suite7/errors/missing_bang.c3 new file mode 100644 index 000000000..93d41fa64 --- /dev/null +++ b/test/test_suite7/errors/missing_bang.c3 @@ -0,0 +1,7 @@ + +fault Bob { FOO } + +fn int! test() +{ + return Bob.FOO; // #error: You need to add a trailing +} \ No newline at end of file diff --git a/test/test_suite7/errors/mixed_decl.c3 b/test/test_suite7/errors/mixed_decl.c3 new file mode 100644 index 000000000..4231638a9 --- /dev/null +++ b/test/test_suite7/errors/mixed_decl.c3 @@ -0,0 +1,10 @@ +import std::io; + +fn void main() +{ + int a, $b; + int $c, $d; + a++; + $b++; + $d++; +} \ No newline at end of file diff --git a/test/test_suite7/errors/more_optional_discard.c3 b/test/test_suite7/errors/more_optional_discard.c3 new file mode 100644 index 000000000..c2472cb1d --- /dev/null +++ b/test/test_suite7/errors/more_optional_discard.c3 @@ -0,0 +1,15 @@ +module abc; + +macro int mtest1(int a) @nodiscard { return 0; } +macro int! mtest2(int a) { return 0; } +fn int ftest1(int a) @nodiscard { return 0; } +fn int! ftest2(int a) { return 0; } + + +fn void main() +{ + mtest1(3); // #error: The called macro is marked `@nodiscard` + mtest2(3); // #error: The macro returns 'int!', which is an optional + ftest1(3); // #error: The called function is marked `@nodiscard` + ftest2(3); // #error: The function returns 'int!' +} \ No newline at end of file diff --git a/test/test_suite7/errors/more_optional_tests.c3 b/test/test_suite7/errors/more_optional_tests.c3 new file mode 100644 index 000000000..226c57303 --- /dev/null +++ b/test/test_suite7/errors/more_optional_tests.c3 @@ -0,0 +1,13 @@ +module foo; + +fault Foo { ABC } + +fn void test() +{ + int x = Foo.ABC? ?? 123; +} + +fn void test2() +{ + int! y = Foo.ABC? ?? Foo.ABC?; +} \ No newline at end of file diff --git a/test/test_suite7/errors/multiple_catch.c3t b/test/test_suite7/errors/multiple_catch.c3t new file mode 100644 index 000000000..2be69c69d --- /dev/null +++ b/test/test_suite7/errors/multiple_catch.c3t @@ -0,0 +1,287 @@ +// #target: macos-x64 + +module demo1; +import std::io; + +fault CheckError +{ + ABC, + DEF +} + +fn int! hello(int a) +{ + io::printn("hello"); + return a < 0 ? CheckError.ABC? : a; +} + +fn void! bye() +{ + io::printn("bye"); + return CheckError.DEF?; +} +fn void main() +{ + if (catch err = hello(-1), bye()) + { + io::printfn("1 Got %s", err); + } + if (catch err = hello(0), bye()) + { + io::printfn("2 Got %s", err); + } + if (catch hello(0), bye()) + { + io::printn("3 Ok"); + } + if (catch anyfault err = hello(0), bye()) + { + io::printfn("4 Got %s", err); + } +} + +/* #expect: demo1.ll + +define void @demo1.main() #0 { +entry: + %err = alloca i64, align 8 + %retparam = alloca i32, align 4 + %varargslots = alloca [1 x %any], align 16 + %retparam5 = alloca i64, align 8 + %err8 = alloca i64, align 8 + %retparam10 = alloca i32, align 4 + %varargslots21 = alloca [1 x %any], align 16 + %retparam22 = alloca i64, align 8 + %temp_err = alloca i64, align 8 + %retparam27 = alloca i32, align 4 + %len = alloca i64, align 8 + %error_var = alloca i64, align 8 + %retparam39 = alloca i64, align 8 + %error_var43 = alloca i64, align 8 + %error_var49 = alloca i64, align 8 + %err56 = alloca i64, align 8 + %retparam58 = alloca i32, align 4 + %varargslots69 = alloca [1 x %any], align 16 + %retparam70 = alloca i64, align 8 + br label %testblock + +testblock: ; preds = %entry + %0 = call i64 @demo1.hello(ptr %retparam, i32 -1) + %not_err = icmp eq i64 %0, 0 + %1 = call i1 @llvm.expect.i1(i1 %not_err, i1 true) + br i1 %1, label %after_check, label %assign_optional + +assign_optional: ; preds = %testblock + store i64 %0, ptr %err, align 8 + br label %end_block + +after_check: ; preds = %testblock + br label %testblock1 + +testblock1: ; preds = %after_check + %2 = call i64 @demo1.bye() + %not_err2 = icmp eq i64 %2, 0 + %3 = call i1 @llvm.expect.i1(i1 %not_err2, i1 true) + br i1 %3, label %after_check4, label %assign_optional3 + +assign_optional3: ; preds = %testblock1 + store i64 %2, ptr %err, align 8 + br label %end_block + +after_check4: ; preds = %testblock1 + store i64 0, ptr %err, align 8 + br label %end_block + +end_block: ; preds = %after_check4, %assign_optional3, %assign_optional + %4 = load i64, ptr %err, align 8 + %i2b = icmp ne i64 %4, 0 + br i1 %i2b, label %if.then, label %if.exit + +if.then: ; preds = %end_block + %5 = insertvalue %any undef, ptr %err, 0 + %6 = insertvalue %any %5, i64 ptrtoint (ptr @"$ct.anyfault" to i64), 1 + store %any %6, ptr %varargslots, align 16 + %7 = call i64 @std.io.printfn(ptr %retparam5, ptr @.str.3, i64 8, ptr %varargslots, i64 1) + br label %if.exit + +if.exit: ; preds = %if.then, %end_block + br label %testblock9 + +testblock9: ; preds = %if.exit + %8 = call i64 @demo1.hello(ptr %retparam10, i32 0) + %not_err11 = icmp eq i64 %8, 0 + %9 = call i1 @llvm.expect.i1(i1 %not_err11, i1 true) + br i1 %9, label %after_check13, label %assign_optional12 + +assign_optional12: ; preds = %testblock9 + store i64 %8, ptr %err8, align 8 + br label %end_block18 + +after_check13: ; preds = %testblock9 + br label %testblock14 + +testblock14: ; preds = %after_check13 + %10 = call i64 @demo1.bye() + %not_err15 = icmp eq i64 %10, 0 + %11 = call i1 @llvm.expect.i1(i1 %not_err15, i1 true) + br i1 %11, label %after_check17, label %assign_optional16 + +assign_optional16: ; preds = %testblock14 + store i64 %10, ptr %err8, align 8 + br label %end_block18 + +after_check17: ; preds = %testblock14 + store i64 0, ptr %err8, align 8 + br label %end_block18 + +end_block18: ; preds = %after_check17, %assign_optional16, %assign_optional12 + %12 = load i64, ptr %err8, align 8 + %i2b19 = icmp ne i64 %12, 0 + br i1 %i2b19, label %if.then20, label %if.exit25 + +if.then20: ; preds = %end_block18 + %13 = insertvalue %any undef, ptr %err8, 0 + %14 = insertvalue %any %13, i64 ptrtoint (ptr @"$ct.anyfault" to i64), 1 + store %any %14, ptr %varargslots21, align 16 + %15 = call i64 @std.io.printfn(ptr %retparam22, ptr @.str.4, i64 8, ptr %varargslots21, i64 1) + br label %if.exit25 + +if.exit25: ; preds = %if.then20, %end_block18 + br label %testblock26 + +testblock26: ; preds = %if.exit25 + %16 = call i64 @demo1.hello(ptr %retparam27, i32 0) + %not_err28 = icmp eq i64 %16, 0 + %17 = call i1 @llvm.expect.i1(i1 %not_err28, i1 true) + br i1 %17, label %after_check30, label %assign_optional29 + +assign_optional29: ; preds = %testblock26 + store i64 %16, ptr %temp_err, align 8 + br label %end_block35 + +after_check30: ; preds = %testblock26 + br label %testblock31 + +testblock31: ; preds = %after_check30 + %18 = call i64 @demo1.bye() + %not_err32 = icmp eq i64 %18, 0 + %19 = call i1 @llvm.expect.i1(i1 %not_err32, i1 true) + br i1 %19, label %after_check34, label %assign_optional33 + +assign_optional33: ; preds = %testblock31 + store i64 %18, ptr %temp_err, align 8 + br label %end_block35 + +after_check34: ; preds = %testblock31 + store i64 0, ptr %temp_err, align 8 + br label %end_block35 + +end_block35: ; preds = %after_check34, %assign_optional33, %assign_optional29 + %20 = load i64, ptr %temp_err, align 8 + %i2b36 = icmp ne i64 %20, 0 + br i1 %i2b36, label %if.then37, label %if.exit55 + +if.then37: ; preds = %end_block35 + %21 = call ptr @std.io.stdout() + %22 = call i64 @std.io.File.write(ptr %retparam39, ptr %21, ptr @.str.5, i64 4) + %not_err40 = icmp eq i64 %22, 0 + %23 = call i1 @llvm.expect.i1(i1 %not_err40, i1 true) + br i1 %23, label %after_check42, label %assign_optional41 + +assign_optional41: ; preds = %if.then37 + store i64 %22, ptr %error_var, align 8 + br label %guard_block + +after_check42: ; preds = %if.then37 + br label %noerr_block + +guard_block: ; preds = %assign_optional41 + br label %voiderr + +noerr_block: ; preds = %after_check42 + %24 = load i64, ptr %retparam39, align 8 + store i64 %24, ptr %len, align 8 + %25 = call i64 @std.io.File.write_byte(ptr %21, i8 zeroext 10) + %not_err44 = icmp eq i64 %25, 0 + %26 = call i1 @llvm.expect.i1(i1 %not_err44, i1 true) + br i1 %26, label %after_check46, label %assign_optional45 + +assign_optional45: ; preds = %noerr_block + store i64 %25, ptr %error_var43, align 8 + br label %guard_block47 + +after_check46: ; preds = %noerr_block + br label %noerr_block48 + +guard_block47: ; preds = %assign_optional45 + br label %voiderr + +noerr_block48: ; preds = %after_check46 + %27 = call i64 @std.io.File.flush(ptr %21) + %not_err50 = icmp eq i64 %27, 0 + %28 = call i1 @llvm.expect.i1(i1 %not_err50, i1 true) + br i1 %28, label %after_check52, label %assign_optional51 + +assign_optional51: ; preds = %noerr_block48 + store i64 %27, ptr %error_var49, align 8 + br label %guard_block53 + +after_check52: ; preds = %noerr_block48 + br label %noerr_block54 + +guard_block53: ; preds = %assign_optional51 + br label %voiderr + +noerr_block54: ; preds = %after_check52 + %29 = load i64, ptr %len, align 8 + %add = add i64 %29, 1 + br label %voiderr + +voiderr: ; preds = %noerr_block54, %guard_block53, %guard_block47, %guard_block + br label %if.exit55 + +if.exit55: ; preds = %voiderr, %end_block35 + br label %testblock57 + +testblock57: ; preds = %if.exit55 + %30 = call i64 @demo1.hello(ptr %retparam58, i32 0) + %not_err59 = icmp eq i64 %30, 0 + %31 = call i1 @llvm.expect.i1(i1 %not_err59, i1 true) + br i1 %31, label %after_check61, label %assign_optional60 + +assign_optional60: ; preds = %testblock57 + store i64 %30, ptr %err56, align 8 + br label %end_block66 + +after_check61: ; preds = %testblock57 + br label %testblock62 + +testblock62: ; preds = %after_check61 + %32 = call i64 @demo1.bye() + %not_err63 = icmp eq i64 %32, 0 + %33 = call i1 @llvm.expect.i1(i1 %not_err63, i1 true) + br i1 %33, label %after_check65, label %assign_optional64 + +assign_optional64: ; preds = %testblock62 + store i64 %32, ptr %err56, align 8 + br label %end_block66 + +after_check65: ; preds = %testblock62 + store i64 0, ptr %err56, align 8 + br label %end_block66 + +end_block66: ; preds = %after_check65, %assign_optional64, %assign_optional60 + %34 = load i64, ptr %err56, align 8 + %i2b67 = icmp ne i64 %34, 0 + br i1 %i2b67, label %if.then68, label %if.exit73 + +if.then68: ; preds = %end_block66 + %35 = insertvalue %any undef, ptr %err56, 0 + %36 = insertvalue %any %35, i64 ptrtoint (ptr @"$ct.anyfault" to i64), 1 + store %any %36, ptr %varargslots69, align 16 + %37 = call i64 @std.io.printfn(ptr %retparam70, ptr @.str.6, i64 8, ptr %varargslots69, i64 1) + br label %if.exit73 + +if.exit73: ; preds = %if.then68, %end_block66 + ret void +} \ No newline at end of file diff --git a/test/test_suite7/errors/no_common.c3 b/test/test_suite7/errors/no_common.c3 new file mode 100644 index 000000000..2c26ee9f2 --- /dev/null +++ b/test/test_suite7/errors/no_common.c3 @@ -0,0 +1,13 @@ +fn int! abc() +{ + return 1; +} +macro test() +{ + return @catch(abc())?; +} + +fn void main() +{ + test() ?? 2; // No longer an error! +} \ No newline at end of file diff --git a/test/test_suite7/errors/optional_chained_init.c3t b/test/test_suite7/errors/optional_chained_init.c3t new file mode 100644 index 000000000..beec02d17 --- /dev/null +++ b/test/test_suite7/errors/optional_chained_init.c3t @@ -0,0 +1,440 @@ +// #target: macos-x64 +module test; +import std::io; + +fault Test { FOO } + +fn void test1() +{ + int! a = 1; + int! b = a = Test.FOO?; + if (catch err = a) io::printfn("A err was: %s", err); + if (catch err = b) io::printfn("B err was: %s", err); + (void)io::printfn("A was: %s", a); + (void)io::printfn("B was: %s", b); +} + +fn void test2() +{ + int! x = Test.FOO?; + int! a = 1; + int! b = a = x; + if (catch err = a) io::printfn("A err was: %s", err); + if (catch err = b) io::printfn("B err was: %s", err); + (void)io::printfn("A was: %s", a); + (void)io::printfn("B was: %s", b); +} + + +fn void test3() +{ + int! x = 23; + int! a = 1; + int! b = a = x; + if (catch err = a) io::printfn("A err was: %s", err); + if (catch err = b) io::printfn("B err was: %s", err); + (void)io::printfn("A was: %s", a); + (void)io::printfn("B was: %s", b); +} + +fn void main() +{ + test1(); + test2(); + test3(); +} + +/* #expect: test.ll + +define void @test.test1() #0 { +entry: + %a = alloca i32, align 4 + %a.f = alloca i64, align 8 + %b = alloca i32, align 4 + %b.f = alloca i64, align 8 + %err = alloca i64, align 8 + %varargslots = alloca [1 x %any], align 16 + %retparam = alloca i64, align 8 + %err3 = alloca i64, align 8 + %varargslots12 = alloca [1 x %any], align 16 + %retparam13 = alloca i64, align 8 + %varargslots17 = alloca [1 x %any], align 16 + %retparam21 = alloca i64, align 8 + %varargslots24 = alloca [1 x %any], align 16 + %retparam28 = alloca i64, align 8 + store i32 1, ptr %a, align 4 + store i64 0, ptr %a.f, align 8 + store i64 ptrtoint (ptr @"test.Test$FOO" to i64), ptr %a.f, align 8 + store i64 ptrtoint (ptr @"test.Test$FOO" to i64), ptr %b.f, align 8 + br label %after_assign + +after_assign: ; preds = %entry + br label %testblock + +testblock: ; preds = %after_assign + %optval = load i64, ptr %a.f, align 8 + %not_err = icmp eq i64 %optval, 0 + %0 = call i1 @llvm.expect.i1(i1 %not_err, i1 true) + br i1 %0, label %after_check, label %assign_optional + +assign_optional: ; preds = %testblock + store i64 %optval, 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, %assign_optional + %1 = load i64, ptr %err, align 8 + %i2b = icmp ne i64 %1, 0 + br i1 %i2b, label %if.then, label %if.exit + +if.then: ; preds = %end_block + %2 = insertvalue %any undef, ptr %err, 0 + %3 = insertvalue %any %2, i64 ptrtoint (ptr @"$ct.anyfault" to i64), 1 + store %any %3, ptr %varargslots, align 16 + %4 = call i64 @std.io.printfn(ptr %retparam, ptr @.str, i64 13, ptr %varargslots, i64 1) + br label %if.exit + +if.exit: ; preds = %if.then, %end_block + br label %testblock4 + +testblock4: ; preds = %if.exit + %optval5 = load i64, ptr %b.f, align 8 + %not_err6 = icmp eq i64 %optval5, 0 + %5 = call i1 @llvm.expect.i1(i1 %not_err6, i1 true) + br i1 %5, label %after_check8, label %assign_optional7 + +assign_optional7: ; preds = %testblock4 + store i64 %optval5, ptr %err3, align 8 + br label %end_block9 + +after_check8: ; preds = %testblock4 + store i64 0, ptr %err3, align 8 + br label %end_block9 + +end_block9: ; preds = %after_check8, %assign_optional7 + %6 = load i64, ptr %err3, align 8 + %i2b10 = icmp ne i64 %6, 0 + br i1 %i2b10, label %if.then11, label %if.exit16 + +if.then11: ; preds = %end_block9 + %7 = insertvalue %any undef, ptr %err3, 0 + %8 = insertvalue %any %7, i64 ptrtoint (ptr @"$ct.anyfault" to i64), 1 + store %any %8, ptr %varargslots12, align 16 + %9 = call i64 @std.io.printfn(ptr %retparam13, ptr @.str.1, i64 13, ptr %varargslots12, i64 1) + br label %if.exit16 + +if.exit16: ; preds = %if.then11, %end_block9 + %optval18 = load i64, ptr %a.f, align 8 + %not_err19 = icmp eq i64 %optval18, 0 + %10 = call i1 @llvm.expect.i1(i1 %not_err19, i1 true) + br i1 %10, label %after_check20, label %after_check23 + +after_check20: ; preds = %if.exit16 + %11 = insertvalue %any undef, ptr %a, 0 + %12 = insertvalue %any %11, i64 ptrtoint (ptr @"$ct.int" to i64), 1 + store %any %12, ptr %varargslots17, align 16 + %13 = call i64 @std.io.printfn(ptr %retparam21, ptr @.str.2, i64 9, ptr %varargslots17, i64 1) + %not_err22 = icmp eq i64 %13, 0 + %14 = call i1 @llvm.expect.i1(i1 %not_err22, i1 true) + br i1 %14, label %after_check23, label %after_check23 + +after_check23: ; preds = %if.exit16, %after_check20, %after_check20 + %optval25 = load i64, ptr %b.f, align 8 + %not_err26 = icmp eq i64 %optval25, 0 + %15 = call i1 @llvm.expect.i1(i1 %not_err26, i1 true) + br i1 %15, label %after_check27, label %after_check30 + +after_check27: ; preds = %after_check23 + %16 = insertvalue %any undef, ptr %b, 0 + %17 = insertvalue %any %16, i64 ptrtoint (ptr @"$ct.int" to i64), 1 + store %any %17, ptr %varargslots24, align 16 + %18 = call i64 @std.io.printfn(ptr %retparam28, ptr @.str.3, i64 9, ptr %varargslots24, i64 1) + %not_err29 = icmp eq i64 %18, 0 + %19 = call i1 @llvm.expect.i1(i1 %not_err29, i1 true) + br i1 %19, label %after_check30, label %after_check30 + +after_check30: ; preds = %after_check23, %after_check27, %after_check27 + ret void +} + +; Function Attrs: +define void @test.test2() #0 { +entry: + %x = alloca i32, align 4 + %x.f = alloca i64, align 8 + %a = alloca i32, align 4 + %a.f = alloca i64, align 8 + %b = alloca i32, align 4 + %b.f = alloca i64, align 8 + %err = alloca i64, align 8 + %varargslots = alloca [1 x %any], align 16 + %retparam = alloca i64, align 8 + %err8 = alloca i64, align 8 + %varargslots17 = alloca [1 x %any], align 16 + %retparam18 = alloca i64, align 8 + %varargslots22 = alloca [1 x %any], align 16 + %retparam26 = alloca i64, align 8 + %varargslots29 = alloca [1 x %any], align 16 + %retparam33 = alloca i64, align 8 + store i64 ptrtoint (ptr @"test.Test$FOO" to i64), ptr %x.f, align 8 + store i32 1, ptr %a, align 4 + store i64 0, ptr %a.f, align 8 + %optval = load i64, ptr %x.f, align 8 + %not_err = icmp eq i64 %optval, 0 + %0 = call i1 @llvm.expect.i1(i1 %not_err, i1 true) + br i1 %0, label %after_check, label %assign_optional + +assign_optional: ; preds = %entry + store i64 %optval, ptr %a.f, align 8 + br label %optional_assign_jump + +after_check: ; preds = %entry + %1 = load i32, ptr %x, align 4 + store i32 %1, ptr %a, align 4 + store i64 0, ptr %a.f, align 8 + br label %after_assign + +optional_assign_jump: ; preds = %assign_optional + %reload_err = load i64, ptr %a.f, align 8 + store i64 %reload_err, ptr %b.f, align 8 + br label %after_assign1 + +after_assign: ; preds = %after_check + store i32 %1, ptr %b, align 4 + store i64 0, ptr %b.f, align 8 + br label %after_assign1 + +after_assign1: ; preds = %after_assign, %optional_assign_jump + br label %testblock + +testblock: ; preds = %after_assign1 + %optval2 = load i64, ptr %a.f, align 8 + %not_err3 = icmp eq i64 %optval2, 0 + %2 = call i1 @llvm.expect.i1(i1 %not_err3, i1 true) + br i1 %2, label %after_check5, label %assign_optional4 + +assign_optional4: ; preds = %testblock + store i64 %optval2, ptr %err, align 8 + br label %end_block + +after_check5: ; preds = %testblock + store i64 0, ptr %err, align 8 + br label %end_block + +end_block: ; preds = %after_check5, %assign_optional4 + %3 = load i64, ptr %err, align 8 + %i2b = icmp ne i64 %3, 0 + br i1 %i2b, label %if.then, label %if.exit + +if.then: ; preds = %end_block + %4 = insertvalue %any undef, ptr %err, 0 + %5 = insertvalue %any %4, i64 ptrtoint (ptr @"$ct.anyfault" to i64), 1 + store %any %5, ptr %varargslots, align 16 + %6 = call i64 @std.io.printfn(ptr %retparam, ptr @.str.4, i64 13, ptr %varargslots, i64 1) + br label %if.exit + +if.exit: ; preds = %if.then, %end_block + br label %testblock9 + +testblock9: ; preds = %if.exit + %optval10 = load i64, ptr %b.f, align 8 + %not_err11 = icmp eq i64 %optval10, 0 + %7 = call i1 @llvm.expect.i1(i1 %not_err11, i1 true) + br i1 %7, label %after_check13, label %assign_optional12 + +assign_optional12: ; preds = %testblock9 + store i64 %optval10, ptr %err8, align 8 + br label %end_block14 + +after_check13: ; preds = %testblock9 + store i64 0, ptr %err8, align 8 + br label %end_block14 + +end_block14: ; preds = %after_check13, %assign_optional12 + %8 = load i64, ptr %err8, align 8 + %i2b15 = icmp ne i64 %8, 0 + br i1 %i2b15, label %if.then16, label %if.exit21 + +if.then16: ; preds = %end_block14 + %9 = insertvalue %any undef, ptr %err8, 0 + %10 = insertvalue %any %9, i64 ptrtoint (ptr @"$ct.anyfault" to i64), 1 + store %any %10, ptr %varargslots17, align 16 + %11 = call i64 @std.io.printfn(ptr %retparam18, ptr @.str.5, i64 13, ptr %varargslots17, i64 1) + br label %if.exit21 + +if.exit21: ; preds = %if.then16, %end_block14 + %optval23 = load i64, ptr %a.f, align 8 + %not_err24 = icmp eq i64 %optval23, 0 + %12 = call i1 @llvm.expect.i1(i1 %not_err24, i1 true) + br i1 %12, label %after_check25, label %after_check28 + +after_check25: ; preds = %if.exit21 + %13 = insertvalue %any undef, ptr %a, 0 + %14 = insertvalue %any %13, i64 ptrtoint (ptr @"$ct.int" to i64), 1 + store %any %14, ptr %varargslots22, align 16 + %15 = call i64 @std.io.printfn(ptr %retparam26, ptr @.str.6, i64 9, ptr %varargslots22, i64 1) + %not_err27 = icmp eq i64 %15, 0 + %16 = call i1 @llvm.expect.i1(i1 %not_err27, i1 true) + br i1 %16, label %after_check28, label %after_check28 + +after_check28: ; preds = %if.exit21, %after_check25, %after_check25 + %optval30 = load i64, ptr %b.f, align 8 + %not_err31 = icmp eq i64 %optval30, 0 + %17 = call i1 @llvm.expect.i1(i1 %not_err31, i1 true) + br i1 %17, label %after_check32, label %after_check35 + +after_check32: ; preds = %after_check28 + %18 = insertvalue %any undef, ptr %b, 0 + %19 = insertvalue %any %18, i64 ptrtoint (ptr @"$ct.int" to i64), 1 + store %any %19, ptr %varargslots29, align 16 + %20 = call i64 @std.io.printfn(ptr %retparam33, ptr @.str.7, i64 9, ptr %varargslots29, i64 1) + %not_err34 = icmp eq i64 %20, 0 + %21 = call i1 @llvm.expect.i1(i1 %not_err34, i1 true) + br i1 %21, label %after_check35, label %after_check35 + +after_check35: ; preds = %after_check28, %after_check32, %after_check32 + ret void +} + +; Function Attrs: +define void @test.test3() #0 { +entry: + %x = alloca i32, align 4 + %x.f = alloca i64, align 8 + %a = alloca i32, align 4 + %a.f = alloca i64, align 8 + %b = alloca i32, align 4 + %b.f = alloca i64, align 8 + %err = alloca i64, align 8 + %varargslots = alloca [1 x %any], align 16 + %retparam = alloca i64, align 8 + %err8 = alloca i64, align 8 + %varargslots17 = alloca [1 x %any], align 16 + %retparam18 = alloca i64, align 8 + %varargslots22 = alloca [1 x %any], align 16 + %retparam26 = alloca i64, align 8 + %varargslots29 = alloca [1 x %any], align 16 + %retparam33 = alloca i64, align 8 + store i32 23, ptr %x, align 4 + store i64 0, ptr %x.f, align 8 + store i32 1, ptr %a, align 4 + store i64 0, ptr %a.f, align 8 + %optval = load i64, ptr %x.f, align 8 + %not_err = icmp eq i64 %optval, 0 + %0 = call i1 @llvm.expect.i1(i1 %not_err, i1 true) + br i1 %0, label %after_check, label %assign_optional + +assign_optional: ; preds = %entry + store i64 %optval, ptr %a.f, align 8 + br label %optional_assign_jump + +after_check: ; preds = %entry + %1 = load i32, ptr %x, align 4 + store i32 %1, ptr %a, align 4 + store i64 0, ptr %a.f, align 8 + br label %after_assign + +optional_assign_jump: ; preds = %assign_optional + %reload_err = load i64, ptr %a.f, align 8 + store i64 %reload_err, ptr %b.f, align 8 + br label %after_assign1 + +after_assign: ; preds = %after_check + store i32 %1, ptr %b, align 4 + store i64 0, ptr %b.f, align 8 + br label %after_assign1 + +after_assign1: ; preds = %after_assign, %optional_assign_jump + br label %testblock + +testblock: ; preds = %after_assign1 + %optval2 = load i64, ptr %a.f, align 8 + %not_err3 = icmp eq i64 %optval2, 0 + %2 = call i1 @llvm.expect.i1(i1 %not_err3, i1 true) + br i1 %2, label %after_check5, label %assign_optional4 + +assign_optional4: ; preds = %testblock + store i64 %optval2, ptr %err, align 8 + br label %end_block + +after_check5: ; preds = %testblock + store i64 0, ptr %err, align 8 + br label %end_block + +end_block: ; preds = %after_check5, %assign_optional4 + %3 = load i64, ptr %err, align 8 + %i2b = icmp ne i64 %3, 0 + br i1 %i2b, label %if.then, label %if.exit + +if.then: ; preds = %end_block + %4 = insertvalue %any undef, ptr %err, 0 + %5 = insertvalue %any %4, i64 ptrtoint (ptr @"$ct.anyfault" to i64), 1 + store %any %5, ptr %varargslots, align 16 + %6 = call i64 @std.io.printfn(ptr %retparam, ptr @.str.8, i64 13, ptr %varargslots, i64 1) + br label %if.exit + +if.exit: ; preds = %if.then, %end_block + br label %testblock9 + +testblock9: ; preds = %if.exit + %optval10 = load i64, ptr %b.f, align 8 + %not_err11 = icmp eq i64 %optval10, 0 + %7 = call i1 @llvm.expect.i1(i1 %not_err11, i1 true) + br i1 %7, label %after_check13, label %assign_optional12 + +assign_optional12: ; preds = %testblock9 + store i64 %optval10, ptr %err8, align 8 + br label %end_block14 + +after_check13: ; preds = %testblock9 + store i64 0, ptr %err8, align 8 + br label %end_block14 + +end_block14: ; preds = %after_check13, %assign_optional12 + %8 = load i64, ptr %err8, align 8 + %i2b15 = icmp ne i64 %8, 0 + br i1 %i2b15, label %if.then16, label %if.exit21 + +if.then16: ; preds = %end_block14 + %9 = insertvalue %any undef, ptr %err8, 0 + %10 = insertvalue %any %9, i64 ptrtoint (ptr @"$ct.anyfault" to i64), 1 + store %any %10, ptr %varargslots17, align 16 + %11 = call i64 @std.io.printfn(ptr %retparam18, ptr @.str.9, i64 13, ptr %varargslots17, i64 1) + br label %if.exit21 + +if.exit21: ; preds = %if.then16, %end_block14 + %optval23 = load i64, ptr %a.f, align 8 + %not_err24 = icmp eq i64 %optval23, 0 + %12 = call i1 @llvm.expect.i1(i1 %not_err24, i1 true) + br i1 %12, label %after_check25, label %after_check28 + +after_check25: ; preds = %if.exit21 + %13 = insertvalue %any undef, ptr %a, 0 + %14 = insertvalue %any %13, i64 ptrtoint (ptr @"$ct.int" to i64), 1 + store %any %14, ptr %varargslots22, align 16 + %15 = call i64 @std.io.printfn(ptr %retparam26, ptr @.str.10, i64 9, ptr %varargslots22, i64 1) + %not_err27 = icmp eq i64 %15, 0 + %16 = call i1 @llvm.expect.i1(i1 %not_err27, i1 true) + br i1 %16, label %after_check28, label %after_check28 + +after_check28: ; preds = %if.exit21, %after_check25, %after_check25 + %optval30 = load i64, ptr %b.f, align 8 + %not_err31 = icmp eq i64 %optval30, 0 + %17 = call i1 @llvm.expect.i1(i1 %not_err31, i1 true) + br i1 %17, label %after_check32, label %after_check35 + +after_check32: ; preds = %after_check28 + %18 = insertvalue %any undef, ptr %b, 0 + %19 = insertvalue %any %18, i64 ptrtoint (ptr @"$ct.int" to i64), 1 + store %any %19, ptr %varargslots29, align 16 + %20 = call i64 @std.io.printfn(ptr %retparam33, ptr @.str.11, i64 9, ptr %varargslots29, i64 1) + %not_err34 = icmp eq i64 %20, 0 + %21 = call i1 @llvm.expect.i1(i1 %not_err34, i1 true) + br i1 %21, label %after_check35, label %after_check35 + +after_check35: ; preds = %after_check28, %after_check32, %after_check32 + ret void +} diff --git a/test/test_suite7/errors/optional_contracts.c3 b/test/test_suite7/errors/optional_contracts.c3 new file mode 100644 index 000000000..7540d47b2 --- /dev/null +++ b/test/test_suite7/errors/optional_contracts.c3 @@ -0,0 +1,35 @@ +fault Abc +{ + ABC, + DEF, + ZED +} + + +fault Foo +{ + XYZ +} +<* + + hello world + @return! Foo, Abc.ABC + *> +fn void! abc(int a, int b, int z) +{ + return Abc.ZED?; // #error: This value does not match declared optional returns +} + +<* +hello world + @return! Foo, Abc.ABC + *> +macro void! @abc(int a, int b, int z) +{ + return Abc.ZED?; // #error: This value does not match declared optional returns +} + +fn void main() +{ + @abc(2,3,3)!!; +} \ No newline at end of file diff --git a/test/test_suite7/errors/optional_designated.c3 b/test/test_suite7/errors/optional_designated.c3 new file mode 100644 index 000000000..e141767e6 --- /dev/null +++ b/test/test_suite7/errors/optional_designated.c3 @@ -0,0 +1,10 @@ +module foo; + +struct Foo { int a; } +struct Bar { int b; Foo f; } +fn void main() +{ + (Bar) { .f = (Foo) { foo() } }; // #error: not be discarded +} + +fn int! foo() => 1; \ No newline at end of file diff --git a/test/test_suite7/errors/optional_discarded_func.c3 b/test/test_suite7/errors/optional_discarded_func.c3 new file mode 100644 index 000000000..871ba7ecb --- /dev/null +++ b/test/test_suite7/errors/optional_discarded_func.c3 @@ -0,0 +1,54 @@ + +fn int abc(int x) { return 1; } +fn int! def2(int y) @maydiscard { return 1; } +fn int! def3(int z) { return 1; } + +fn void test1() +{ + int! x; + abc(x); // #error: The result of this call is optional due to its argumen +} + +fn void test2() +{ + int! x; + int y; + abc(y); + abc(x) + 4; // #error: An optional value may not be discarded +} + +fn void test3() +{ + int! x; + int y; + def2(1); + def2(x); // #error: The result of this call is optional due to its argumen +} + +fn void test4() +{ + int! x; + int y; + def2(1); + def2(x) + 4; // #error: An optional value may not be discarded +} + +fn void test5() +{ + int! x; + int y; + def3(y); // #error: The function returns 'int!' +} + +fn void test6() +{ + int! x; + int y; + def3(x); // #error: The function returns 'int!' +} + +fn void test7() +{ + int y; + def3(y) + 4; // #error: An optional value may not be discarded +} diff --git a/test/test_suite7/errors/optional_discarded_macro.c3 b/test/test_suite7/errors/optional_discarded_macro.c3 new file mode 100644 index 000000000..4dcc61e50 --- /dev/null +++ b/test/test_suite7/errors/optional_discarded_macro.c3 @@ -0,0 +1,54 @@ + +macro int abc(int x) { return 1; } +macro int! def2(int y) @maydiscard { return 1; } +macro int! def3(int z) { return 1; } + +fn void test1() +{ + int! x; + abc(x); // #error: The result of this call is optional due to its argumen +} + +fn void test2() +{ + int! x; + int y; + abc(y); + abc(x) + 4; // #error: An optional value may not be discarded +} + +fn void test3() +{ + int! x; + int y; + def2(1); + def2(x); // #error: The result of this call is optional due to its argumen +} + +fn void test4() +{ + int! x; + int y; + def2(1); + def2(x) + 4; // #error: An optional value may not be discarded +} + +fn void test5() +{ + int! x; + int y; + def3(y); // #error: The macro returns 'int!' +} + +fn void test6() +{ + int! x; + int y; + def3(x); // #error: The macro returns 'int!' +} + +fn void test7() +{ + int y; + def3(y) + 4; // #error: An optional value may not be discarded +} diff --git a/test/test_suite7/errors/optional_inits.c3t b/test/test_suite7/errors/optional_inits.c3t new file mode 100644 index 000000000..54ac32e9c --- /dev/null +++ b/test/test_suite7/errors/optional_inits.c3t @@ -0,0 +1,100 @@ +// #target: macos-x64 + +module test; +import std::io; +fault Foo +{ + MY_VAL1, + MY_VAL2, +} + +struct Bar +{ + int x; +} + +fn void! test1() @maydiscard +{ + Bar! x = Foo.MY_VAL1?; + Bar y = x!; +} + +fn void! test2() @maydiscard +{ + 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 + store i64 ptrtoint (ptr @"test.Foo$MY_VAL1" to i64), ptr %x.f, align 8 + %optval = load i64, ptr %x.f, align 8 + %not_err = icmp eq i64 %optval, 0 + %0 = call i1 @llvm.expect.i1(i1 %not_err, i1 true) + br i1 %0, label %after_check, label %assign_optional + +assign_optional: ; preds = %entry + store i64 %optval, ptr %error_var, align 8 + br label %guard_block + +after_check: ; preds = %entry + br label %noerr_block + +guard_block: ; preds = %assign_optional + %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 + store i32 0, ptr %x, align 4 + store i64 0, ptr %x.f, align 8 + %optval = load i64, ptr %x.f, align 8 + %not_err = icmp eq i64 %optval, 0 + %0 = call i1 @llvm.expect.i1(i1 %not_err, i1 true) + br i1 %0, label %after_check, label %assign_optional + +assign_optional: ; preds = %entry + store i64 %optval, ptr %error_var, align 8 + br label %guard_block + +after_check: ; preds = %entry + br label %noerr_block + +guard_block: ; preds = %assign_optional + %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 void @test.main() #0 { +entry: + %0 = call i64 @test.test1() + %1 = call i64 @test.test2() + ret void +} diff --git a/test/test_suite7/errors/optional_sizeof.c3 b/test/test_suite7/errors/optional_sizeof.c3 new file mode 100644 index 000000000..e8455b594 --- /dev/null +++ b/test/test_suite7/errors/optional_sizeof.c3 @@ -0,0 +1,43 @@ +fn int! abc() +{ + return 1; +} +macro test() +{ + return @catch(abc())?!!; +} + +macro test2() +{ + return @catch(abc())?; +} + +fn void a() +{ + String s = $typeof(test()).qnameof; // #error: This expression lacks +} + +fn void b() +{ + $sizeof(test()); // #error: This expression lacks +} + +fn void c() +{ + $sizeof(test2() ?? 1); +} + +fn void! d() +{ + $typeof(test2()!) g; // #error: This expression lacks a concrete type +} + +macro e() +{ + var g = test2()!; // #error: No type can be inferred from the optional result +} + +fn void! h() +{ + e(); +} diff --git a/test/test_suite7/errors/optional_taddr_and_access.c3t b/test/test_suite7/errors/optional_taddr_and_access.c3t new file mode 100644 index 000000000..95bfbbd2f --- /dev/null +++ b/test/test_suite7/errors/optional_taddr_and_access.c3t @@ -0,0 +1,118 @@ +// #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 }; + (void)printf("%d\n", w.x); + z = MyErr.FOO?; + w = &&(Foo){ z, 0 }; + (void)printf("Not visible: %d\n", w.x); +} + +/* #expect: test.ll + +%Foo = type { i32, i32 } + +@"$ct.test.Foo" = linkonce global %.introspect { i8 10, i64 0, ptr null, i64 8, i64 0, i64 2, [0 x i64] zeroinitializer }, align 8 +@"test.MyErr$FOO" = linkonce constant %.fault { i64 ptrtoint (ptr @"$ct.test.MyErr" to i64), %"char[]" { ptr @.fault, i64 3 }, i64 1 }, align 8 +@.fault = internal constant [4 x i8] c"FOO\00", align 1 +@"$ct.test.MyErr" = linkonce global %.introspect { i8 9, i64 0, ptr null, i64 8, i64 0, i64 1, [0 x i64] zeroinitializer }, 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: +declare i32 @printf(ptr, ...) #0 + +; Function Attrs: +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 + %literal5 = alloca %Foo, align 4 + store i32 2, ptr %z, align 4 + store i64 0, ptr %z.f, align 8 + %optval = load i64, ptr %z.f, align 8 + %not_err = icmp eq i64 %optval, 0 + %0 = call i1 @llvm.expect.i1(i1 %not_err, i1 true) + br i1 %0, label %after_check, label %assign_optional + +assign_optional: ; preds = %entry + store i64 %optval, ptr %w.f, align 8 + br label %after_assign + +after_check: ; preds = %entry + %1 = load i32, ptr %z, align 4 + store i32 %1, ptr %literal, align 4 + %ptradd = getelementptr inbounds i8, ptr %literal, i64 4 + store i32 0, ptr %ptradd, 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, %assign_optional + %optval1 = load i64, ptr %w.f, align 8 + %not_err2 = icmp eq i64 %optval1, 0 + %2 = call i1 @llvm.expect.i1(i1 %not_err2, i1 true) + br i1 %2, label %after_check3, label %voiderr + +after_check3: ; preds = %after_assign + %3 = load ptr, ptr %w, align 8 + %4 = load i32, ptr %3, align 4 + %5 = call i32 (ptr, ...) @printf(ptr @.str, i32 %4) + br label %voiderr + +voiderr: ; preds = %after_check3, %after_assign + store i64 ptrtoint (ptr @"test.MyErr$FOO" to i64), ptr %z.f, align 8 + br label %after_check4 + +after_check4: ; preds = %voiderr + %optval6 = load i64, ptr %z.f, align 8 + %not_err7 = icmp eq i64 %optval6, 0 + %6 = call i1 @llvm.expect.i1(i1 %not_err7, i1 true) + br i1 %6, label %after_check9, label %assign_optional8 + +assign_optional8: ; preds = %after_check4 + store i64 %optval6, ptr %w.f, align 8 + br label %after_assign11 + +after_check9: ; preds = %after_check4 + %7 = load i32, ptr %z, align 4 + store i32 %7, ptr %literal5, align 4 + %ptradd10 = getelementptr inbounds i8, ptr %literal5, i64 4 + store i32 0, ptr %ptradd10, align 4 + store ptr %literal5, ptr %w, align 8 + store i64 0, ptr %w.f, align 8 + br label %after_assign11 + +after_assign11: ; preds = %after_check9, %assign_optional8 + %optval12 = load i64, ptr %w.f, align 8 + %not_err13 = icmp eq i64 %optval12, 0 + %8 = call i1 @llvm.expect.i1(i1 %not_err13, i1 true) + br i1 %8, label %after_check14, label %voiderr15 + +after_check14: ; preds = %after_assign11 + %9 = load ptr, ptr %w, align 8 + %10 = load i32, ptr %9, align 4 + %11 = call i32 (ptr, ...) @printf(ptr @.str.1, i32 %10) + br label %voiderr15 + +voiderr15: ; preds = %after_check14, %after_assign11 + ret void +} \ No newline at end of file diff --git a/test/test_suite7/errors/optional_untyped_list.c3 b/test/test_suite7/errors/optional_untyped_list.c3 new file mode 100644 index 000000000..c4c2f9581 --- /dev/null +++ b/test/test_suite7/errors/optional_untyped_list.c3 @@ -0,0 +1,30 @@ +module test; +struct Foo +{ + int x, y; +} + +fault MyErr +{ + FOO +} + +extern fn int printf(char *c, ...); + +fn void foo() +{ + int z = 2; + Foo*! w = &&{ z, 0 }; // #error: An untyped list can only have constant elements +} + +fn void foo2() +{ + int! z = 2; + Foo*! w = &&{ z, 0 }; // #error: An untyped list can only have constant elements +} + +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_suite7/errors/optional_with_optional.c3t b/test/test_suite7/errors/optional_with_optional.c3t new file mode 100644 index 000000000..94e32b413 --- /dev/null +++ b/test/test_suite7/errors/optional_with_optional.c3t @@ -0,0 +1,295 @@ +// #target: macos-x64 +module test; +import std::io; + +fault Foo { ABC, DEF } + +fn void main() +{ + io::printfn("1:%d", get_a(1) ?? get_b(4) ?? -1); + io::printfn("2:%d", get_a(2) ?? get_b(4) ?? -1); + io::printfn("3:%d", get_a(1) ?? get_b(5) ?? -1); + io::printfn("4:%s", @catch(Foo.ABC? ?? Foo.DEF?)); + io::printfn("5:%s", Foo.ABC? ?? 3); + io::printfn("6:%s", @catch((3 > 2 ? Foo.ABC? : 4) ?? Foo.DEF?)); + io::printfn("7:%s", @catch((3 < 2 ? Foo.ABC? : 4) ?? Foo.DEF?)); + long x = Foo.DEF? ?? 3; + io::printfn("8:%s", x); + int! xy = Foo.ABC? ?? Foo.DEF?; +} + +fn int! get_a(int x) +{ + if (x % 2) return Foo.ABC?; + return x * 2; +} + +fn int! get_b(int x) +{ + if (x % 2 == 0) return Foo.ABC?; + return x * 2; +} + +/* #expect: test.ll + +define void @test.main() #0 { +entry: + %varargslots = alloca [1 x %any], align 16 + %retparam = alloca i32, align 4 + %retparam1 = alloca i32, align 4 + %taddr = alloca i32, align 4 + %retparam7 = alloca i64, align 8 + %varargslots10 = alloca [1 x %any], align 16 + %retparam11 = alloca i32, align 4 + %retparam15 = alloca i32, align 4 + %taddr23 = alloca i32, align 4 + %retparam24 = alloca i64, align 8 + %varargslots27 = alloca [1 x %any], align 16 + %retparam28 = alloca i32, align 4 + %retparam32 = alloca i32, align 4 + %taddr40 = alloca i32, align 4 + %retparam41 = alloca i64, align 8 + %varargslots44 = alloca [1 x %any], align 16 + %blockret = alloca i64, align 8 + %f = alloca i64, align 8 + %retparam45 = alloca i64, align 8 + %varargslots48 = alloca [1 x %any], align 16 + %taddr49 = alloca i32, align 4 + %retparam50 = alloca i64, align 8 + %varargslots53 = alloca [1 x %any], align 16 + %blockret54 = alloca i64, align 8 + %f55 = alloca i64, align 8 + %retparam62 = alloca i64, align 8 + %varargslots65 = alloca [1 x %any], align 16 + %blockret66 = alloca i64, align 8 + %f67 = alloca i64, align 8 + %retparam76 = alloca i64, align 8 + %x = alloca i64, align 8 + %varargslots79 = alloca [1 x %any], align 16 + %retparam80 = alloca i64, align 8 + %xy = alloca i32, align 4 + %xy.f = alloca i64, align 8 + %0 = call i64 @test.get_a(ptr %retparam, i32 1) + %not_err = icmp eq i64 %0, 0 + %1 = call i1 @llvm.expect.i1(i1 %not_err, i1 true) + br i1 %1, label %after_check, label %else_block + +after_check: ; preds = %entry + %2 = load i32, ptr %retparam, align 4 + br label %phi_block5 + +else_block: ; preds = %entry + %3 = call i64 @test.get_b(ptr %retparam1, i32 4) + %not_err2 = icmp eq i64 %3, 0 + %4 = call i1 @llvm.expect.i1(i1 %not_err2, i1 true) + br i1 %4, label %after_check3, label %else_block4 + +after_check3: ; preds = %else_block + %5 = load i32, ptr %retparam1, align 4 + br label %phi_block + +else_block4: ; preds = %else_block + br label %phi_block + +phi_block: ; preds = %else_block4, %after_check3 + %val = phi i32 [ %5, %after_check3 ], [ -1, %else_block4 ] + br label %phi_block5 + +phi_block5: ; preds = %phi_block, %after_check + %val6 = phi i32 [ %2, %after_check ], [ %val, %phi_block ] + store i32 %val6, ptr %taddr, align 4 + %6 = insertvalue %any undef, ptr %taddr, 0 + %7 = insertvalue %any %6, i64 ptrtoint (ptr @"$ct.int" to i64), 1 + store %any %7, ptr %varargslots, align 16 + %8 = call i64 @std.io.printfn(ptr %retparam7, ptr @.str, i64 4, ptr %varargslots, i64 1) + %9 = call i64 @test.get_a(ptr %retparam11, i32 2) + %not_err12 = icmp eq i64 %9, 0 + %10 = call i1 @llvm.expect.i1(i1 %not_err12, i1 true) + br i1 %10, label %after_check13, label %else_block14 + +after_check13: ; preds = %phi_block5 + %11 = load i32, ptr %retparam11, align 4 + br label %phi_block21 + +else_block14: ; preds = %phi_block5 + %12 = call i64 @test.get_b(ptr %retparam15, i32 4) + %not_err16 = icmp eq i64 %12, 0 + %13 = call i1 @llvm.expect.i1(i1 %not_err16, i1 true) + br i1 %13, label %after_check17, label %else_block18 + +after_check17: ; preds = %else_block14 + %14 = load i32, ptr %retparam15, align 4 + br label %phi_block19 + +else_block18: ; preds = %else_block14 + br label %phi_block19 + +phi_block19: ; preds = %else_block18, %after_check17 + %val20 = phi i32 [ %14, %after_check17 ], [ -1, %else_block18 ] + br label %phi_block21 + +phi_block21: ; preds = %phi_block19, %after_check13 + %val22 = phi i32 [ %11, %after_check13 ], [ %val20, %phi_block19 ] + store i32 %val22, ptr %taddr23, align 4 + %15 = insertvalue %any undef, ptr %taddr23, 0 + %16 = insertvalue %any %15, i64 ptrtoint (ptr @"$ct.int" to i64), 1 + store %any %16, ptr %varargslots10, align 16 + %17 = call i64 @std.io.printfn(ptr %retparam24, ptr @.str.2, i64 4, ptr %varargslots10, i64 1) + %18 = call i64 @test.get_a(ptr %retparam28, i32 1) + %not_err29 = icmp eq i64 %18, 0 + %19 = call i1 @llvm.expect.i1(i1 %not_err29, i1 true) + br i1 %19, label %after_check30, label %else_block31 + +after_check30: ; preds = %phi_block21 + %20 = load i32, ptr %retparam28, align 4 + br label %phi_block38 + +else_block31: ; preds = %phi_block21 + %21 = call i64 @test.get_b(ptr %retparam32, i32 5) + %not_err33 = icmp eq i64 %21, 0 + %22 = call i1 @llvm.expect.i1(i1 %not_err33, i1 true) + br i1 %22, label %after_check34, label %else_block35 + +after_check34: ; preds = %else_block31 + %23 = load i32, ptr %retparam32, align 4 + br label %phi_block36 + +else_block35: ; preds = %else_block31 + br label %phi_block36 + +phi_block36: ; preds = %else_block35, %after_check34 + %val37 = phi i32 [ %23, %after_check34 ], [ -1, %else_block35 ] + br label %phi_block38 + +phi_block38: ; preds = %phi_block36, %after_check30 + %val39 = phi i32 [ %20, %after_check30 ], [ %val37, %phi_block36 ] + store i32 %val39, ptr %taddr40, align 4 + %24 = insertvalue %any undef, ptr %taddr40, 0 + %25 = insertvalue %any %24, i64 ptrtoint (ptr @"$ct.int" to i64), 1 + store %any %25, ptr %varargslots27, align 16 + %26 = call i64 @std.io.printfn(ptr %retparam41, ptr @.str.3, i64 4, ptr %varargslots27, i64 1) + br label %testblock + +testblock: ; preds = %phi_block38 + store i64 ptrtoint (ptr @"test.Foo$DEF" to i64), ptr %f, align 8 + br label %end_block + +end_block: ; preds = %testblock + %27 = load i64, ptr %f, align 8 + %i2b = icmp ne i64 %27, 0 + br i1 %i2b, label %if.then, label %if.exit + +if.then: ; preds = %end_block + %28 = load i64, ptr %f, align 8 + store i64 %28, ptr %blockret, align 8 + br label %expr_block.exit + +if.exit: ; preds = %end_block + store i64 0, ptr %blockret, align 8 + br label %expr_block.exit + +expr_block.exit: ; preds = %if.exit, %if.then + %29 = insertvalue %any undef, ptr %blockret, 0 + %30 = insertvalue %any %29, i64 ptrtoint (ptr @"$ct.anyfault" to i64), 1 + store %any %30, ptr %varargslots44, align 16 + %31 = call i64 @std.io.printfn(ptr %retparam45, ptr @.str.4, i64 4, ptr %varargslots44, i64 1) + store i32 3, ptr %taddr49, align 4 + %32 = insertvalue %any undef, ptr %taddr49, 0 + %33 = insertvalue %any %32, i64 ptrtoint (ptr @"$ct.int" to i64), 1 + store %any %33, ptr %varargslots48, align 16 + %34 = call i64 @std.io.printfn(ptr %retparam50, ptr @.str.5, i64 4, ptr %varargslots48, i64 1) + br label %testblock56 + +testblock56: ; preds = %expr_block.exit + store i64 ptrtoint (ptr @"test.Foo$DEF" to i64), ptr %f55, align 8 + br label %end_block57 + +end_block57: ; preds = %testblock56 + %35 = load i64, ptr %f55, align 8 + %i2b58 = icmp ne i64 %35, 0 + br i1 %i2b58, label %if.then59, label %if.exit60 + +if.then59: ; preds = %end_block57 + %36 = load i64, ptr %f55, align 8 + store i64 %36, ptr %blockret54, align 8 + br label %expr_block.exit61 + +if.exit60: ; preds = %end_block57 + store i64 0, ptr %blockret54, align 8 + br label %expr_block.exit61 + +expr_block.exit61: ; preds = %if.exit60, %if.then59 + %37 = insertvalue %any undef, ptr %blockret54, 0 + %38 = insertvalue %any %37, i64 ptrtoint (ptr @"$ct.anyfault" to i64), 1 + store %any %38, ptr %varargslots53, align 16 + %39 = call i64 @std.io.printfn(ptr %retparam62, ptr @.str.6, i64 4, ptr %varargslots53, i64 1) + br label %testblock68 + +testblock68: ; preds = %expr_block.exit61 + br label %phi_block70 + +phi_block70: ; preds = %testblock68 + store i64 0, ptr %f67, align 8 + br label %end_block71 + +end_block71: ; preds = %phi_block70 + %40 = load i64, ptr %f67, align 8 + %i2b72 = icmp ne i64 %40, 0 + br i1 %i2b72, label %if.then73, label %if.exit74 + +if.then73: ; preds = %end_block71 + %41 = load i64, ptr %f67, align 8 + store i64 %41, ptr %blockret66, align 8 + br label %expr_block.exit75 + +if.exit74: ; preds = %end_block71 + store i64 0, ptr %blockret66, align 8 + br label %expr_block.exit75 + +expr_block.exit75: ; preds = %if.exit74, %if.then73 + %42 = insertvalue %any undef, ptr %blockret66, 0 + %43 = insertvalue %any %42, i64 ptrtoint (ptr @"$ct.anyfault" to i64), 1 + store %any %43, ptr %varargslots65, align 16 + %44 = call i64 @std.io.printfn(ptr %retparam76, ptr @.str.7, i64 4, ptr %varargslots65, i64 1) + store i64 3, ptr %x, align 8 + %45 = insertvalue %any undef, ptr %x, 0 + %46 = insertvalue %any %45, i64 ptrtoint (ptr @"$ct.long" to i64), 1 + store %any %46, ptr %varargslots79, align 16 + %47 = call i64 @std.io.printfn(ptr %retparam80, ptr @.str.8, i64 4, ptr %varargslots79, i64 1) + store i64 ptrtoint (ptr @"test.Foo$DEF" to i64), ptr %xy.f, align 8 + ret void +} + +; Function Attrs: +define i64 @test.get_a(ptr %0, i32 %1) #0 { +entry: + %reterr = alloca i64, align 8 + %smod = srem i32 %1, 2 + %i2b = icmp ne i32 %smod, 0 + br i1 %i2b, label %if.then, label %if.exit + +if.then: ; preds = %entry + ret i64 ptrtoint (ptr @"test.Foo$ABC" to i64) + +if.exit: ; preds = %entry + %mul = mul i32 %1, 2 + store i32 %mul, ptr %0, align 4 + ret i64 0 +} + +; Function Attrs: +define i64 @test.get_b(ptr %0, i32 %1) #0 { +entry: + %reterr = alloca i64, align 8 + %smod = srem i32 %1, 2 + %eq = icmp eq i32 %smod, 0 + br i1 %eq, label %if.then, label %if.exit + +if.then: ; preds = %entry + ret i64 ptrtoint (ptr @"test.Foo$ABC" to i64) + +if.exit: ; preds = %entry + %mul = mul i32 %1, 2 + store i32 %mul, ptr %0, align 4 + ret i64 0 +} \ No newline at end of file diff --git a/test/test_suite7/errors/or_and_rethrow.c3t b/test/test_suite7/errors/or_and_rethrow.c3t new file mode 100644 index 000000000..cdfad2bb4 --- /dev/null +++ b/test/test_suite7/errors/or_and_rethrow.c3t @@ -0,0 +1,474 @@ +// #target: macos-x64 +module foo; +import std::io; + +fault Foo { ABC } + +fn void blurb() { io::printn("Blurb");} + +macro int! tester() +{ + defer blurb(); + return Foo.ABC?; +} +fn void! test(int x) +{ + io::printfn("test(%d)", x); + if (x || (tester()!)) io::printn("Ok1"); + io::printn("Test next"); + if (tester()! || x) io::printn("Ok?"); + io::printn("Test ok"); +} + +fn void! test2(int x) +{ + io::printfn("test2(%d)", x); + if (x && (tester()!)) io::printn("Ok1"); + io::printn("Test next"); + if ((tester()!) && x) io::printn("Ok?"); + io::printn("Test ok"); +} + +fn void main() +{ + anyfault a = @catch(test(0)); + anyfault b = @catch(test(1)); + anyfault c = @catch(test2(0)); + anyfault d = @catch(test2(1)); +} + +/* #expect: foo.ll + +define i64 @foo.test(i32 %0) #0 { +entry: + %varargslots = alloca [1 x %any], align 16 + %taddr = alloca i32, align 4 + %retparam = alloca i64, align 8 + %error_var = alloca i64, align 8 + %blockret = alloca i32, align 4 + %len = alloca i64, align 8 + %error_var2 = alloca i64, align 8 + %retparam4 = alloca i64, align 8 + %error_var6 = alloca i64, align 8 + %error_var12 = alloca i64, align 8 + %len19 = alloca i64, align 8 + %error_var20 = alloca i64, align 8 + %retparam22 = alloca i64, align 8 + %error_var28 = alloca i64, align 8 + %error_var34 = alloca i64, align 8 + %error_var42 = alloca i64, align 8 + %blockret43 = alloca i32, align 4 + store i32 %0, ptr %taddr, align 4 + %1 = insertvalue %any undef, ptr %taddr, 0 + %2 = insertvalue %any %1, i64 ptrtoint (ptr @"$ct.int" to i64), 1 + store %any %2, ptr %varargslots, align 16 + %3 = call i64 @std.io.printfn(ptr %retparam, ptr @.str.1, i64 8, ptr %varargslots, i64 1) + %i2b = icmp ne i32 %0, 0 + br i1 %i2b, label %or.phi, label %or.rhs + +or.rhs: ; preds = %entry + store i64 ptrtoint (ptr @"foo.Foo$ABC" to i64), ptr %error_var, align 8 + br label %opt_block_cleanup + +opt_block_cleanup: ; preds = %or.rhs + call void @foo.blurb() + br label %guard_block + +guard_block: ; preds = %opt_block_cleanup + %4 = load i64, ptr %error_var, align 8 + ret i64 %4 + +or.phi: ; preds = %entry + br label %if.then + +if.then: ; preds = %or.phi + %5 = call ptr @std.io.stdout() + %6 = call i64 @std.io.File.write(ptr %retparam4, ptr %5, ptr @.str.2, i64 3) + %not_err = icmp eq i64 %6, 0 + %7 = call i1 @llvm.expect.i1(i1 %not_err, i1 true) + br i1 %7, label %after_check, label %assign_optional + +assign_optional: ; preds = %if.then + store i64 %6, ptr %error_var2, align 8 + br label %guard_block5 + +after_check: ; preds = %if.then + br label %noerr_block + +guard_block5: ; preds = %assign_optional + br label %voiderr + +noerr_block: ; preds = %after_check + %8 = load i64, ptr %retparam4, align 8 + store i64 %8, ptr %len, align 8 + %9 = call i64 @std.io.File.write_byte(ptr %5, i8 zeroext 10) + %not_err7 = icmp eq i64 %9, 0 + %10 = call i1 @llvm.expect.i1(i1 %not_err7, i1 true) + br i1 %10, label %after_check9, label %assign_optional8 + +assign_optional8: ; preds = %noerr_block + store i64 %9, ptr %error_var6, align 8 + br label %guard_block10 + +after_check9: ; preds = %noerr_block + br label %noerr_block11 + +guard_block10: ; preds = %assign_optional8 + br label %voiderr + +noerr_block11: ; preds = %after_check9 + %11 = call i64 @std.io.File.flush(ptr %5) + %not_err13 = icmp eq i64 %11, 0 + %12 = call i1 @llvm.expect.i1(i1 %not_err13, i1 true) + br i1 %12, label %after_check15, label %assign_optional14 + +assign_optional14: ; preds = %noerr_block11 + store i64 %11, ptr %error_var12, align 8 + br label %guard_block16 + +after_check15: ; preds = %noerr_block11 + br label %noerr_block17 + +guard_block16: ; preds = %assign_optional14 + br label %voiderr + +noerr_block17: ; preds = %after_check15 + %13 = load i64, ptr %len, align 8 + %add = add i64 %13, 1 + br label %voiderr + +voiderr: ; preds = %noerr_block17, %guard_block16, %guard_block10, %guard_block5 + br label %if.exit + +if.exit: ; preds = %voiderr + %14 = call ptr @std.io.stdout() + %15 = call i64 @std.io.File.write(ptr %retparam22, ptr %14, ptr @.str.3, i64 9) + %not_err23 = icmp eq i64 %15, 0 + %16 = call i1 @llvm.expect.i1(i1 %not_err23, i1 true) + br i1 %16, label %after_check25, label %assign_optional24 + +assign_optional24: ; preds = %if.exit + store i64 %15, ptr %error_var20, align 8 + br label %guard_block26 + +after_check25: ; preds = %if.exit + br label %noerr_block27 + +guard_block26: ; preds = %assign_optional24 + br label %voiderr41 + +noerr_block27: ; preds = %after_check25 + %17 = load i64, ptr %retparam22, align 8 + store i64 %17, ptr %len19, align 8 + %18 = call i64 @std.io.File.write_byte(ptr %14, i8 zeroext 10) + %not_err29 = icmp eq i64 %18, 0 + %19 = call i1 @llvm.expect.i1(i1 %not_err29, i1 true) + br i1 %19, label %after_check31, label %assign_optional30 + +assign_optional30: ; preds = %noerr_block27 + store i64 %18, ptr %error_var28, align 8 + br label %guard_block32 + +after_check31: ; preds = %noerr_block27 + br label %noerr_block33 + +guard_block32: ; preds = %assign_optional30 + br label %voiderr41 + +noerr_block33: ; preds = %after_check31 + %20 = call i64 @std.io.File.flush(ptr %14) + %not_err35 = icmp eq i64 %20, 0 + %21 = call i1 @llvm.expect.i1(i1 %not_err35, i1 true) + br i1 %21, label %after_check37, label %assign_optional36 + +assign_optional36: ; preds = %noerr_block33 + store i64 %20, ptr %error_var34, align 8 + br label %guard_block38 + +after_check37: ; preds = %noerr_block33 + br label %noerr_block39 + +guard_block38: ; preds = %assign_optional36 + br label %voiderr41 + +noerr_block39: ; preds = %after_check37 + %22 = load i64, ptr %len19, align 8 + %add40 = add i64 %22, 1 + br label %voiderr41 + +voiderr41: ; preds = %noerr_block39, %guard_block38, %guard_block32, %guard_block26 + store i64 ptrtoint (ptr @"foo.Foo$ABC" to i64), ptr %error_var42, align 8 + br label %opt_block_cleanup44 + +opt_block_cleanup44: ; preds = %voiderr41 + call void @foo.blurb() + br label %guard_block45 + +guard_block45: ; preds = %opt_block_cleanup44 + %23 = load i64, ptr %error_var42, align 8 + ret i64 %23 +} + +; Function Attrs: +define i64 @foo.test2(i32 %0) #0 { +entry: + %varargslots = alloca [1 x %any], align 16 + %taddr = alloca i32, align 4 + %retparam = alloca i64, align 8 + %error_var = alloca i64, align 8 + %blockret = alloca i32, align 4 + %len = alloca i64, align 8 + %error_var2 = alloca i64, align 8 + %retparam4 = alloca i64, align 8 + %error_var6 = alloca i64, align 8 + %error_var12 = alloca i64, align 8 + %error_var18 = alloca i64, align 8 + %blockret19 = alloca i32, align 4 + store i32 %0, ptr %taddr, align 4 + %1 = insertvalue %any undef, ptr %taddr, 0 + %2 = insertvalue %any %1, i64 ptrtoint (ptr @"$ct.int" to i64), 1 + store %any %2, ptr %varargslots, align 16 + %3 = call i64 @std.io.printfn(ptr %retparam, ptr @.str.4, i64 9, ptr %varargslots, i64 1) + %i2b = icmp ne i32 %0, 0 + br i1 %i2b, label %and.rhs, label %and.phi + +and.rhs: ; preds = %entry + store i64 ptrtoint (ptr @"foo.Foo$ABC" to i64), ptr %error_var, align 8 + br label %opt_block_cleanup + +opt_block_cleanup: ; preds = %and.rhs + call void @foo.blurb() + br label %guard_block + +guard_block: ; preds = %opt_block_cleanup + %4 = load i64, ptr %error_var, align 8 + ret i64 %4 + +and.phi: ; preds = %entry + br label %if.exit + +if.exit: ; preds = %and.phi + %5 = call ptr @std.io.stdout() + %6 = call i64 @std.io.File.write(ptr %retparam4, ptr %5, ptr @.str.5, i64 9) + %not_err = icmp eq i64 %6, 0 + %7 = call i1 @llvm.expect.i1(i1 %not_err, i1 true) + br i1 %7, label %after_check, label %assign_optional + +assign_optional: ; preds = %if.exit + store i64 %6, ptr %error_var2, align 8 + br label %guard_block5 + +after_check: ; preds = %if.exit + br label %noerr_block + +guard_block5: ; preds = %assign_optional + br label %voiderr + +noerr_block: ; preds = %after_check + %8 = load i64, ptr %retparam4, align 8 + store i64 %8, ptr %len, align 8 + %9 = call i64 @std.io.File.write_byte(ptr %5, i8 zeroext 10) + %not_err7 = icmp eq i64 %9, 0 + %10 = call i1 @llvm.expect.i1(i1 %not_err7, i1 true) + br i1 %10, label %after_check9, label %assign_optional8 + +assign_optional8: ; preds = %noerr_block + store i64 %9, ptr %error_var6, align 8 + br label %guard_block10 + +after_check9: ; preds = %noerr_block + br label %noerr_block11 + +guard_block10: ; preds = %assign_optional8 + br label %voiderr + +noerr_block11: ; preds = %after_check9 + %11 = call i64 @std.io.File.flush(ptr %5) + %not_err13 = icmp eq i64 %11, 0 + %12 = call i1 @llvm.expect.i1(i1 %not_err13, i1 true) + br i1 %12, label %after_check15, label %assign_optional14 + +assign_optional14: ; preds = %noerr_block11 + store i64 %11, ptr %error_var12, align 8 + br label %guard_block16 + +after_check15: ; preds = %noerr_block11 + br label %noerr_block17 + +guard_block16: ; preds = %assign_optional14 + br label %voiderr + +noerr_block17: ; preds = %after_check15 + %13 = load i64, ptr %len, align 8 + %add = add i64 %13, 1 + br label %voiderr + +voiderr: ; preds = %noerr_block17, %guard_block16, %guard_block10, %guard_block5 + store i64 ptrtoint (ptr @"foo.Foo$ABC" to i64), ptr %error_var18, align 8 + br label %opt_block_cleanup20 + +opt_block_cleanup20: ; preds = %voiderr + call void @foo.blurb() + br label %guard_block21 + +guard_block21: ; preds = %opt_block_cleanup20 + %14 = load i64, ptr %error_var18, align 8 + ret i64 %14 +} + +; Function Attrs: +define void @foo.main() #0 { +entry: + %a = alloca i64, align 8 + %blockret = alloca i64, align 8 + %f = alloca i64, align 8 + %b = alloca i64, align 8 + %blockret1 = alloca i64, align 8 + %f2 = alloca i64, align 8 + %c = alloca i64, align 8 + %blockret12 = alloca i64, align 8 + %f13 = alloca i64, align 8 + %d = alloca i64, align 8 + %blockret23 = alloca i64, align 8 + %f24 = alloca i64, align 8 + br label %testblock + +testblock: ; preds = %entry + %0 = call i64 @foo.test(i32 0) + %not_err = icmp eq i64 %0, 0 + %1 = call i1 @llvm.expect.i1(i1 %not_err, i1 true) + br i1 %1, label %after_check, label %assign_optional + +assign_optional: ; preds = %testblock + store i64 %0, ptr %f, align 8 + br label %end_block + +after_check: ; preds = %testblock + store i64 0, ptr %f, align 8 + br label %end_block + +end_block: ; preds = %after_check, %assign_optional + %2 = load i64, ptr %f, align 8 + %i2b = icmp ne i64 %2, 0 + br i1 %i2b, label %if.then, label %if.exit + +if.then: ; preds = %end_block + %3 = load i64, ptr %f, align 8 + store i64 %3, ptr %blockret, align 8 + br label %expr_block.exit + +if.exit: ; preds = %end_block + store i64 0, ptr %blockret, align 8 + br label %expr_block.exit + +expr_block.exit: ; preds = %if.exit, %if.then + %4 = load i64, ptr %blockret, align 8 + store i64 %4, ptr %a, align 8 + br label %testblock3 + +testblock3: ; preds = %expr_block.exit + %5 = call i64 @foo.test(i32 1) + %not_err4 = icmp eq i64 %5, 0 + %6 = call i1 @llvm.expect.i1(i1 %not_err4, i1 true) + br i1 %6, label %after_check6, label %assign_optional5 + +assign_optional5: ; preds = %testblock3 + store i64 %5, ptr %f2, align 8 + br label %end_block7 + +after_check6: ; preds = %testblock3 + store i64 0, ptr %f2, align 8 + br label %end_block7 + +end_block7: ; preds = %after_check6, %assign_optional5 + %7 = load i64, ptr %f2, align 8 + %i2b8 = icmp ne i64 %7, 0 + br i1 %i2b8, label %if.then9, label %if.exit10 + +if.then9: ; preds = %end_block7 + %8 = load i64, ptr %f2, align 8 + store i64 %8, ptr %blockret1, align 8 + br label %expr_block.exit11 + +if.exit10: ; preds = %end_block7 + store i64 0, ptr %blockret1, align 8 + br label %expr_block.exit11 + +expr_block.exit11: ; preds = %if.exit10, %if.then9 + %9 = load i64, ptr %blockret1, align 8 + store i64 %9, ptr %b, align 8 + br label %testblock14 + +testblock14: ; preds = %expr_block.exit11 + %10 = call i64 @foo.test2(i32 0) + %not_err15 = icmp eq i64 %10, 0 + %11 = call i1 @llvm.expect.i1(i1 %not_err15, i1 true) + br i1 %11, label %after_check17, label %assign_optional16 + +assign_optional16: ; preds = %testblock14 + store i64 %10, ptr %f13, align 8 + br label %end_block18 + +after_check17: ; preds = %testblock14 + store i64 0, ptr %f13, align 8 + br label %end_block18 + +end_block18: ; preds = %after_check17, %assign_optional16 + %12 = load i64, ptr %f13, align 8 + %i2b19 = icmp ne i64 %12, 0 + br i1 %i2b19, label %if.then20, label %if.exit21 + +if.then20: ; preds = %end_block18 + %13 = load i64, ptr %f13, align 8 + store i64 %13, ptr %blockret12, align 8 + br label %expr_block.exit22 + +if.exit21: ; preds = %end_block18 + store i64 0, ptr %blockret12, align 8 + br label %expr_block.exit22 + +expr_block.exit22: ; preds = %if.exit21, %if.then20 + %14 = load i64, ptr %blockret12, align 8 + store i64 %14, ptr %c, align 8 + br label %testblock25 + +testblock25: ; preds = %expr_block.exit22 + %15 = call i64 @foo.test2(i32 1) + %not_err26 = icmp eq i64 %15, 0 + %16 = call i1 @llvm.expect.i1(i1 %not_err26, i1 true) + br i1 %16, label %after_check28, label %assign_optional27 + +assign_optional27: ; preds = %testblock25 + store i64 %15, ptr %f24, align 8 + br label %end_block29 + +after_check28: ; preds = %testblock25 + store i64 0, ptr %f24, align 8 + br label %end_block29 + +end_block29: ; preds = %after_check28, %assign_optional27 + %17 = load i64, ptr %f24, align 8 + %i2b30 = icmp ne i64 %17, 0 + br i1 %i2b30, label %if.then31, label %if.exit32 + +if.then31: ; preds = %end_block29 + %18 = load i64, ptr %f24, align 8 + store i64 %18, ptr %blockret23, align 8 + br label %expr_block.exit33 + +if.exit32: ; preds = %end_block29 + store i64 0, ptr %blockret23, align 8 + br label %expr_block.exit33 + +expr_block.exit33: ; preds = %if.exit32, %if.then31 + %19 = load i64, ptr %blockret23, align 8 + store i64 %19, ptr %d, align 8 + ret void +} + +; Function Attrs: +define i32 @main(i32 %0, ptr %1) #0 { +entry: + call void @foo.main() + ret i32 0 +} diff --git a/test/test_suite7/errors/or_err_bool.c3t b/test/test_suite7/errors/or_err_bool.c3t new file mode 100644 index 000000000..4a0b48e15 --- /dev/null +++ b/test/test_suite7/errors/or_err_bool.c3t @@ -0,0 +1,35 @@ +// #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 + %optval = load i64, ptr %x.f, align 8 + %not_err = icmp eq i64 %optval, 0 + %0 = call i1 @llvm.expect.i1(i1 %not_err, i1 true) + br i1 %0, 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_suite7/errors/or_err_infer.c3t b/test/test_suite7/errors/or_err_infer.c3t new file mode 100644 index 000000000..cda307534 --- /dev/null +++ b/test/test_suite7/errors/or_err_infer.c3t @@ -0,0 +1,96 @@ +// #target: macos-x64 +enum Foo +{ + ABC, + DEF +} + +fn int main() +{ + int a; + Foo! x = ABC; + Foo f = x ?? DEF; + return 0; +} + +/* expect: test.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 + %sext = sext i32 %0 to i64 + %1 = load i32, ptr %y, align 4 + %sext1 = sext i32 %1 to i64 + %mul = mul i64 %sext, %sext1 + store i64 %mul, ptr %z, align 8 + %2 = load i32, ptr %x, align 4 + %3 = load i32, ptr %y, align 4 + %sdiv = sdiv i32 %2, %3 + %sext2 = sext i32 %sdiv to i64 + store i64 %sext2, ptr %z, align 8 + %4 = load i32, ptr %x, align 4 + %sext3 = sext i32 %4 to i64 + %5 = load i32, ptr %y, align 4 + %sext4 = sext i32 %5 to i64 + %add = add i64 %sext3, %sext4 + store i64 %add, ptr %z, align 8 + %6 = load i32, ptr %x, align 4 + %sext5 = sext i32 %6 to i64 + %7 = load i32, ptr %y, align 4 + %sext6 = sext i32 %7 to i64 + %sub = sub i64 %sext5, %sext6 + store i64 %sub, ptr %z, align 8 + %8 = load i32, ptr %x, align 4 + %9 = load i32, ptr %y, align 4 + %smod = srem i32 %8, %9 + %sext7 = sext i32 %smod to i64 + store i64 %sext7, ptr %z, align 8 + %10 = load i32, ptr %x, align 4 + %sext8 = sext i32 %10 to i64 + %11 = load i32, ptr %y, align 4 + %zext = zext i32 %11 to i64 + %shl = shl i64 %sext8, %zext + %12 = freeze i64 %shl + store i64 %12, ptr %z, align 8 + %13 = load i32, ptr %x, align 4 + %sext9 = sext i32 %13 to i64 + %14 = load i32, ptr %y, align 4 + %zext10 = zext i32 %14 to i64 + %ashr = ashr i64 %sext9, %zext10 + %15 = freeze i64 %ashr + store i64 %15, ptr %z, align 8 + %16 = load i32, ptr %x, align 4 + %bnot = xor i32 %16, -1 + %sext11 = sext i32 %bnot to i64 + store i64 %sext11, ptr %z, align 8 + %17 = load i32, ptr %x, align 4 + %neg = sub i32 0, %17 + %sext12 = sext i32 %neg to i64 + store i64 %sext12, ptr %z, align 8 + store i64 0, ptr %w.f, align 8 + store i32 0, ptr %w, align 4 + %optval = load i64, ptr %w.f, align 8 + %not_err = icmp eq i64 %optval, 0 + %18 = call i1 @llvm.expect.i1(i1 %not_err, i1 true) + br i1 %18, label %after_check, label %else_block + +after_check: ; preds = %entry + %19 = load i32, ptr %w, align 4 + %sext13 = sext i32 %19 to i64 + br label %phi_block + +else_block: ; preds = %entry + br label %phi_block + +phi_block: ; preds = %else_block, %after_check + %val = phi i64 [ %sext13, %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_suite7/errors/precedence_err.c3 b/test/test_suite7/errors/precedence_err.c3 new file mode 100644 index 000000000..0d80271cb --- /dev/null +++ b/test/test_suite7/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_suite7/errors/printing_errors.c3t b/test/test_suite7/errors/printing_errors.c3t new file mode 100644 index 000000000..4472a92c2 --- /dev/null +++ b/test/test_suite7/errors/printing_errors.c3t @@ -0,0 +1,59 @@ +// #target: macos-x64 +module test; +import std::io; + +fault Cde +{ + HELLO, + WORLD, +} +fn void main() +{ + anyfault x = Cde.WORLD; + io::printf("%s %s\n", Cde.HELLO.nameof, x.nameof); +} + +/* #expect: test.ll + +define void @test.main() #0 { +entry: + %x = alloca i64, align 8 + %varargslots = alloca [2 x %any], align 16 + %taddr = alloca %"char[]", align 8 + %faultname_zero = alloca %"char[]", align 8 + %retparam = alloca i64, align 8 + store i64 ptrtoint (ptr @"test.Cde$WORLD" to i64), ptr %x, align 8 + store %"char[]" { ptr @.str.2, i64 5 }, ptr %taddr, align 8 + %0 = insertvalue %any undef, ptr %taddr, 0 + %1 = insertvalue %any %0, i64 ptrtoint (ptr @"$ct.String" to i64), 1 + store %any %1, ptr %varargslots, align 16 + %2 = load i64, ptr %x, align 8 + %eq = icmp eq i64 %2, 0 + br i1 %eq, label %faultname_no, label %faultname_ok + +faultname_no: ; preds = %entry + call void @llvm.memset.p0.i64(ptr align 8 %faultname_zero, i8 0, i64 16, i1 false) + br label %faultname_exit + +faultname_ok: ; preds = %entry + %3 = inttoptr i64 %2 to ptr + %4 = getelementptr inbounds + br label %faultname_exit + +faultname_exit: ; preds = %faultname_ok, %faultname_no + %faultname = phi ptr [ %faultname_zero, %faultname_no ], [ %4, %faultname_ok ] + %5 = insertvalue %any undef, ptr %faultname, 0 + %6 = insertvalue %any %5, i64 ptrtoint (ptr @"$ct.String" to i64), 1 + %ptradd = getelementptr inbounds i8, ptr %varargslots, i64 16 + store %any %6, ptr %ptradd, align 16 + %7 = call i64 @std.io.printf(ptr %retparam, ptr @.str, i64 6, ptr %varargslots, i64 2) + ret void +} + +; Function Attrs: +define i32 @main(i32 %0, ptr %1) #0 { +entry: + call void @test.main() + ret i32 0 +} + diff --git a/test/test_suite7/errors/rethrow.c3t b/test/test_suite7/errors/rethrow.c3t new file mode 100644 index 000000000..c94875567 --- /dev/null +++ b/test/test_suite7/errors/rethrow.c3t @@ -0,0 +1,34 @@ +// #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 + %optval = load i64, ptr %i.f, align 8 + %not_err = icmp eq i64 %optval, 0 + %0 = call i1 @llvm.expect.i1(i1 %not_err, i1 true) + br i1 %0, label %after_check, label %assign_optional + +assign_optional: ; preds = %entry + store i64 %optval, ptr %error_var, align 8 + br label %guard_block + +after_check: ; preds = %entry + br label %noerr_block + +guard_block: ; preds = %assign_optional + %1 = load i64, ptr %error_var, align 8 + ret i64 %1 + +noerr_block: ; preds = %after_check + ret i64 0 +} diff --git a/test/test_suite7/errors/rethrow_macro.c3 b/test/test_suite7/errors/rethrow_macro.c3 new file mode 100644 index 000000000..2e9f12a46 --- /dev/null +++ b/test/test_suite7/errors/rethrow_macro.c3 @@ -0,0 +1,14 @@ +module testing; +import std::io; + +macro char[] read(src, Allocator allocator, n) +{ + char* data = allocator::malloc_try(allocator, n)!; // #error: Rethrow is only allowed in macros + io::read_all(src, data[:n])!; +} + +fn void main() +{ + ByteReader br; + read(&br, allocator::temp(), 10); +} \ No newline at end of file diff --git a/test/test_suite7/errors/rethrow_mingw.c3t b/test/test_suite7/errors/rethrow_mingw.c3t new file mode 100644 index 000000000..9713916ee --- /dev/null +++ b/test/test_suite7/errors/rethrow_mingw.c3t @@ -0,0 +1,40 @@ +// #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 + %optval = load i64, ptr %i.f, align 8 + %not_err = icmp eq i64 %optval, 0 + %0 = call i1 @llvm.expect.i1(i1 %not_err, i1 true) + br i1 %0, label %after_check, label %assign_optional + +assign_optional: ; preds = %entry + store i64 %optval, ptr %error_var, align 8 + br label %guard_block + +after_check: ; preds = %entry + br label %noerr_block + +guard_block: ; preds = %assign_optional + %1 = load i64, ptr %error_var, align 8 + ret i64 %1 + +noerr_block: ; preds = %after_check + ret i64 0 +} + + diff --git a/test/test_suite7/errors/rethrow_no_err.c3 b/test/test_suite7/errors/rethrow_no_err.c3 new file mode 100644 index 000000000..0a86ff526 --- /dev/null +++ b/test/test_suite7/errors/rethrow_no_err.c3 @@ -0,0 +1,17 @@ + +fn void test() +{ + test()!; // #error: No optional to rethrow before '!' in the expression, please remove '!' + int i = 0; + if (i!) return; // #error: No optional to rethrow before '!' in the expression, please remove '!' + int! j = 0; + if (j!) return; // #error: This expression implicitly returns with an optional result, but the function + if ((j!)!) return; // #error: This expression implicitly returns with an optional result, but the function +} + +fn void! test2() +{ + int! j = 0; + if (j!) return; + if ((j!)!) return; // #error: No optional to rethrow before '!' in the expression, please remove '!' +} \ No newline at end of file diff --git a/test/test_suite7/errors/simple_static_failable.c3t b/test/test_suite7/errors/simple_static_failable.c3t new file mode 100644 index 000000000..d284b40cb --- /dev/null +++ b/test/test_suite7/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_suite7/errors/switch_default_catch.c3 b/test/test_suite7/errors/switch_default_catch.c3 new file mode 100644 index 000000000..81b7ac8e2 --- /dev/null +++ b/test/test_suite7/errors/switch_default_catch.c3 @@ -0,0 +1,10 @@ +fn void main() +{ + int! x; + if (catch err = x) + { + default: // #warning: 'if-catch' + return; + } + return; +} \ No newline at end of file diff --git a/test/test_suite7/errors/ternary_void_fault.c3t b/test/test_suite7/errors/ternary_void_fault.c3t new file mode 100644 index 000000000..d8a279213 --- /dev/null +++ b/test/test_suite7/errors/ternary_void_fault.c3t @@ -0,0 +1,71 @@ +// #target: macos-x64 +module test; +fn void! x() {} +fn void main() +{ + int a; + @catch(a > 0 ? x() : x()); +} + +/* #expect: test.ll + +define void @test.main() #0 { +entry: + %a = alloca i32, align 4 + %blockret = alloca i64, align 8 + %f = alloca i64, align 8 + store i32 0, ptr %a, align 4 + br label %testblock + +testblock: ; preds = %entry + %0 = load i32, ptr %a, align 4 + %gt = icmp sgt i32 %0, 0 + br i1 %gt, label %cond.lhs, label %cond.rhs + +cond.lhs: ; preds = %testblock + %1 = call i64 @test.x() + %not_err = icmp eq i64 %1, 0 + %2 = call i1 @llvm.expect.i1(i1 %not_err, i1 true) + br i1 %2, label %after_check, label %assign_optional + +assign_optional: ; preds = %cond.lhs + store i64 %1, ptr %f, align 8 + br label %end_block + +after_check: ; preds = %cond.lhs + br label %cond.phi + +cond.rhs: ; preds = %testblock + %3 = call i64 @test.x() + %not_err1 = icmp eq i64 %3, 0 + %4 = call i1 @llvm.expect.i1(i1 %not_err1, i1 true) + br i1 %4, label %after_check3, label %assign_optional2 + +assign_optional2: ; preds = %cond.rhs + store i64 %3, ptr %f, align 8 + br label %end_block + +after_check3: ; preds = %cond.rhs + br label %cond.phi + +cond.phi: ; preds = %after_check3, %after_check + store i64 0, ptr %f, align 8 + br label %end_block + +end_block: ; preds = %cond.phi, %assign_optional2, %assign_optional + %5 = load i64, ptr %f, align 8 + %i2b = icmp ne i64 %5, 0 + br i1 %i2b, label %if.then, label %if.exit + +if.then: ; preds = %end_block + %6 = load i64, ptr %f, align 8 + store i64 %6, ptr %blockret, align 8 + br label %expr_block.exit + +if.exit: ; preds = %end_block + store i64 0, ptr %blockret, align 8 + br label %expr_block.exit + +expr_block.exit: ; preds = %if.exit, %if.then + ret void +} diff --git a/test/test_suite7/errors/try_assign.c3t b/test/test_suite7/errors/try_assign.c3t new file mode 100644 index 000000000..eafbee252 --- /dev/null +++ b/test/test_suite7/errors/try_assign.c3t @@ -0,0 +1,154 @@ +// #target: macos-x64 + +extern fn int! err(); +fault FooErr { QBERT } +extern fn int printf(char* fmt, ...); + +fn void main() +{ + int! z = 234; + int! w; + if (try x = z && try gh = w) + { + printf("Success %d && %d!\n", x, gh); + } + if (try x = z + w) + { + printf("Test\n"); + } + if (catch e = z) + { + printf("Oh noes!\n"); + } +} + +/* #expect: try_assign.ll + +define void @try_assign.main() #0 { +entry: + %z = alloca i32, align 4 + %z.f = alloca i64, align 8 + %w = alloca i32, align 4 + %w.f = alloca i64, align 8 + %x = alloca i32, align 4 + %gh = alloca i32, align 4 + %x8 = alloca i32, align 4 + %e = alloca i64, align 8 + 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 0, ptr %x, align 4 + %optval = load i64, ptr %z.f, align 8 + %not_err = icmp eq i64 %optval, 0 + %0 = call i1 @llvm.expect.i1(i1 %not_err, i1 true) + br i1 %0, 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 + store i32 0, ptr %gh, align 4 + %optval1 = load i64, ptr %w.f, align 8 + %not_err2 = icmp eq i64 %optval1, 0 + %2 = call i1 @llvm.expect.i1(i1 %not_err2, i1 true) + br i1 %2, label %after_check3, label %catch_landing4 + +after_check3: ; preds = %chain_next + %3 = load i32, ptr %w, align 4 + store i32 %3, ptr %gh, align 4 + br label %phi_try_catch5 + +catch_landing4: ; preds = %chain_next + br label %phi_try_catch5 + +phi_try_catch5: ; preds = %catch_landing4, %after_check3 + %val6 = phi i1 [ true, %after_check3 ], [ false, %catch_landing4 ] + br i1 %val6, label %chain_next7, label %fail_chain + +chain_next7: ; preds = %phi_try_catch5 + br label %end_chain + +fail_chain: ; preds = %phi_try_catch5, %phi_try_catch + br label %end_chain + +end_chain: ; preds = %fail_chain, %chain_next7 + %chain.phi = phi i1 [ true, %chain_next7 ], [ 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 + store i32 0, ptr %x8, align 4 + %optval9 = load i64, ptr %z.f, align 8 + %not_err10 = icmp eq i64 %optval9, 0 + %7 = call i1 @llvm.expect.i1(i1 %not_err10, i1 true) + br i1 %7, label %after_check11, label %catch_landing15 + +after_check11: ; preds = %if.exit + %8 = load i32, ptr %z, align 4 + %optval12 = load i64, ptr %w.f, align 8 + %not_err13 = icmp eq i64 %optval12, 0 + %9 = call i1 @llvm.expect.i1(i1 %not_err13, i1 true) + br i1 %9, label %after_check14, label %catch_landing15 + +after_check14: ; preds = %after_check11 + %10 = load i32, ptr %w, align 4 + %add = add i32 %8, %10 + store i32 %add, ptr %x8, align 4 + br label %phi_try_catch16 + +catch_landing15: ; preds = %after_check11, %if.exit + br label %phi_try_catch16 + +phi_try_catch16: ; preds = %catch_landing15, %after_check14 + %val17 = phi i1 [ true, %after_check14 ], [ false, %catch_landing15 ] + br i1 %val17, label %if.then18, label %if.exit19 + +if.then18: ; preds = %phi_try_catch16 + %11 = call i32 (ptr, ...) @printf(ptr @.str.1) + br label %if.exit19 + +if.exit19: ; preds = %if.then18, %phi_try_catch16 + br label %testblock + +testblock: ; preds = %if.exit19 + %optval20 = load i64, ptr %z.f, align 8 + %not_err21 = icmp eq i64 %optval20, 0 + %12 = call i1 @llvm.expect.i1(i1 %not_err21, i1 true) + br i1 %12, label %after_check22, label %assign_optional + +assign_optional: ; preds = %testblock + store i64 %optval20, ptr %e, align 8 + br label %end_block + +after_check22: ; preds = %testblock + store i64 0, ptr %e, align 8 + br label %end_block + +end_block: ; preds = %after_check22, %assign_optional + %13 = load i64, ptr %e, align 8 + %i2b = icmp ne i64 %13, 0 + br i1 %i2b, label %if.then23, label %if.exit24 + +if.then23: ; preds = %end_block + %14 = call i32 (ptr, ...) @printf(ptr @.str.2) + br label %if.exit24 + +if.exit24: ; preds = %if.then23, %end_block + ret void +} + diff --git a/test/test_suite7/errors/try_catch_if.c3t b/test/test_suite7/errors/try_catch_if.c3t new file mode 100644 index 000000000..10479e060 --- /dev/null +++ b/test/test_suite7/errors/try_catch_if.c3t @@ -0,0 +1,101 @@ +// #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 + %optval = load i64, ptr %a.f, align 8 + %not_err = icmp eq i64 %optval, 0 + %0 = call i1 @llvm.expect.i1(i1 %not_err, i1 true) + br i1 %0, label %after_check, label %assign_optional + +assign_optional: ; preds = %testblock + store i64 %optval, 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 + %2 = call i1 @llvm.expect.i1(i1 %not_err2, i1 true) + br i1 %2, label %after_check4, label %assign_optional3 + +assign_optional3: ; preds = %testblock1 + store i64 %1, ptr %err, align 8 + br label %end_block + +after_check4: ; preds = %testblock1 + store i64 0, ptr %err, align 8 + br label %end_block + +end_block: ; preds = %after_check4, %assign_optional3, %assign_optional + %3 = load i64, ptr %err, align 8 + %i2b = icmp ne i64 %3, 0 + br i1 %i2b, label %if.then, label %if.else + +if.then: ; preds = %end_block + %4 = call i32 (ptr, ...) @printf(ptr @.str.1) + br label %if.exit + +if.else: ; preds = %end_block + %5 = load i32, ptr %a, align 4 + %6 = call i32 (ptr, ...) @printf(ptr @.str.2, i32 %5) + br label %if.exit + +if.exit: ; preds = %if.else, %if.then + ret void +} \ No newline at end of file diff --git a/test/test_suite7/errors/try_catch_unwrapping_while_if.c3 b/test/test_suite7/errors/try_catch_unwrapping_while_if.c3 new file mode 100644 index 000000000..2153a110f --- /dev/null +++ b/test/test_suite7/errors/try_catch_unwrapping_while_if.c3 @@ -0,0 +1,97 @@ +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; + if (catch e = z) + { + } + else + { + int y = z; + } +} diff --git a/test/test_suite7/errors/try_expr.c3t b/test/test_suite7/errors/try_expr.c3t new file mode 100644 index 000000000..9ca8de6f2 --- /dev/null +++ b/test/test_suite7/errors/try_expr.c3t @@ -0,0 +1,49 @@ +// #target: macos-x64 +module foo; +import std::io; + +fn void main() +{ + int a; + if (try foo()) + { + a--; + } + else + { + a++; + } +} + +fn void! foo() {} + +/* #expect: foo.ll + +define void @foo.main() #0 { +entry: + %a = alloca i32, align 4 + store i32 0, ptr %a, align 4 + %0 = call i64 @foo.foo() + %not_err = icmp eq i64 %0, 0 + %1 = call i1 @llvm.expect.i1(i1 %not_err, i1 true) + br i1 %1, label %after_check, label %catch_landing +after_check: ; preds = %entry + 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 %if.then, label %if.else +if.then: ; preds = %phi_try_catch + %2 = load i32, ptr %a, align 4 + %sub = sub i32 %2, 1 + store i32 %sub, ptr %a, align 4 + br label %if.exit +if.else: ; preds = %phi_try_catch + %3 = load i32, ptr %a, align 4 + %add = add i32 %3, 1 + store i32 %add, ptr %a, align 4 + br label %if.exit +if.exit: ; preds = %if.else, %if.then + ret void +} diff --git a/test/test_suite7/errors/try_unwrap_using_assert.c3 b/test/test_suite7/errors/try_unwrap_using_assert.c3 new file mode 100644 index 000000000..3d6738861 --- /dev/null +++ b/test/test_suite7/errors/try_unwrap_using_assert.c3 @@ -0,0 +1,11 @@ +module test; + +extern fn int! maybe(); + +fn int tester(int n) +{ + int! num = maybe(); + assert(try num, "Hello"); // #error: An expression was expected + int x = num; + return num; +} diff --git a/test/test_suite7/errors/try_with_assign_to_failable.c3 b/test/test_suite7/errors/try_with_assign_to_failable.c3 new file mode 100644 index 000000000..57c054fcd --- /dev/null +++ b/test/test_suite7/errors/try_with_assign_to_failable.c3 @@ -0,0 +1,6 @@ +fn void test() +{ + int! z; + int! w; + try w = z; // #error: can only be used when unwrapping an optional +} diff --git a/test/test_suite7/errors/try_with_chained_unwrap.c3t b/test/test_suite7/errors/try_with_chained_unwrap.c3t new file mode 100644 index 000000000..5a34b82b8 --- /dev/null +++ b/test/test_suite7/errors/try_with_chained_unwrap.c3t @@ -0,0 +1,59 @@ +// #target: macos-x64 + +extern fn char*! readLine(); +extern fn int! atoi(char*); + +extern fn int printf(char* fmt, ...); + +fn void main() +{ + 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 ptr, align 8 + %retparam1 = alloca i32, align 4 + store i32 0, ptr %val, align 4 + %0 = call i64 @readLine(ptr %retparam) + %not_err = icmp eq i64 %0, 0 + %1 = call i1 @llvm.expect.i1(i1 %not_err, i1 true) + br i1 %1, label %after_check, label %catch_landing + +after_check: ; preds = %entry + %2 = load ptr, ptr %retparam, align 8 + %3 = call i64 @atoi(ptr %retparam1, ptr %2) + %not_err2 = icmp eq i64 %3, 0 + %4 = call i1 @llvm.expect.i1(i1 %not_err2, i1 true) + br i1 %4, label %after_check3, label %catch_landing + +after_check3: ; preds = %after_check + %5 = load i32, ptr %retparam1, align 4 + store i32 %5, ptr %val, align 4 + br label %phi_try_catch + +catch_landing: ; preds = %after_check, %entry + br label %phi_try_catch + +phi_try_catch: ; preds = %catch_landing, %after_check3 + %val4 = phi i1 [ true, %after_check3 ], [ false, %catch_landing ] + br i1 %val4, label %if.then, label %if.exit + +if.then: ; preds = %phi_try_catch + %6 = load i32, ptr %val, align 4 + %7 = call i32 (ptr, ...) @printf(ptr @.str, i32 %6) + ret void + +if.exit: ; preds = %phi_try_catch + %8 = call i32 (ptr, ...) @printf(ptr @.str.1) + ret void +} \ No newline at end of file diff --git a/test/test_suite7/errors/try_with_chained_unwrap_errors.c3 b/test/test_suite7/errors/try_with_chained_unwrap_errors.c3 new file mode 100644 index 000000000..29b71f47d --- /dev/null +++ b/test/test_suite7/errors/try_with_chained_unwrap_errors.c3 @@ -0,0 +1,91 @@ +fn void test() +{ + int! a; + int b; + if (try int b = a) {} // #error: 'b' would shadow a previous declaration. +} +fn void test2() +{ + int! a; + if (try b = a) {} + if (try test2 = a) {} +} + +const int BAZ = 1; + +fn void test3() +{ + + int! a; + int b; + if (try BAZ = a) {} // #error: lower case +} + + +fn void test4() +{ + + int! a; + if (try b = 1) {} // #error: remove 'try' +} + +fn void test5() +{ + + int! a; + int b; + if (try a = a) {} // #error: if (try a) +} + +fn void test6() +{ + + int! a; + int b; + int*! x; + if (try *x = a) {} // #error: variable name +} + + +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 e; + if (e == 0, try c = a && try d = a && e > 0) {} + if (try b = a && try c = a && e > 0) {} + if (try c = a && try d = 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_suite7/errors/try_with_unwrap.c3t b/test/test_suite7/errors/try_with_unwrap.c3t new file mode 100644 index 000000000..46379c269 --- /dev/null +++ b/test/test_suite7/errors/try_with_unwrap.c3t @@ -0,0 +1,86 @@ +// #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 + %1 = call i1 @llvm.expect.i1(i1 %not_err, i1 true) + br i1 %1, label %after_check, label %assign_optional + +assign_optional: ; preds = %entry + store i64 %0, ptr %line.f, align 8 + br label %after_assign + +after_check: ; preds = %entry + %2 = load ptr, ptr %retparam, align 8 + store ptr %2, ptr %line, align 8 + store i64 0, ptr %line.f, align 8 + br label %after_assign + +after_assign: ; preds = %after_check, %assign_optional + %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 + %3 = load ptr, ptr %line, align 8 + %4 = call i64 @atoi(ptr %retparam1, ptr %3) + %not_err2 = icmp eq i64 %4, 0 + %5 = call i1 @llvm.expect.i1(i1 %not_err2, i1 true) + br i1 %5, label %after_check4, label %assign_optional3 + +assign_optional3: ; preds = %if.then + store i64 %4, ptr %val.f, align 8 + br label %after_assign5 + +after_check4: ; preds = %if.then + %6 = load i32, ptr %retparam1, align 4 + store i32 %6, ptr %val, align 4 + store i64 0, ptr %val.f, align 8 + br label %after_assign5 + +after_assign5: ; preds = %after_check4, %assign_optional3 + %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 + %7 = load i32, ptr %val, align 4 + %8 = call i32 (ptr, ...) @printf(ptr @.str, i32 %7) + ret void + +if.exit: ; preds = %after_assign5 + br label %if.exit9 + +if.exit9: ; preds = %if.exit, %after_assign + %9 = call i32 (ptr, ...) @printf(ptr @.str.1) + ret void +} + diff --git a/test/test_suite7/errors/try_with_unwrapper.c3t b/test/test_suite7/errors/try_with_unwrapper.c3t new file mode 100644 index 000000000..bdc5f79da --- /dev/null +++ b/test/test_suite7/errors/try_with_unwrapper.c3t @@ -0,0 +1,185 @@ +// #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 + + +define i32 @try_with_unwrapper.hello(i32 %0) #0 { +entry: + %add = add i32 %0, 1 + ret i32 %add +} + + +declare i32 @printf(ptr, ...) #0 + + +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 +} + + +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 + %optval = load i64, ptr %a.f, align 8 + %not_err = icmp eq i64 %optval, 0 + %0 = call i1 @llvm.expect.i1(i1 %not_err, i1 true) + br i1 %0, 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 + %3 = call i1 @llvm.expect.i1(i1 %not_err1, i1 true) + br i1 %3, label %after_check2, label %catch_landing3 + +after_check2: ; preds = %chain_next + %4 = load i32, ptr %retparam, align 4 + store i32 %4, ptr %c, 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 + %5 = load i32, ptr %b, align 4 + %6 = call i32 @try_with_unwrapper.hello(i32 %5) + %7 = call i32 (ptr, ...) @printf(ptr @.str.1, i32 %6) + %8 = load i32, ptr %c, align 4 + %9 = call i32 (ptr, ...) @printf(ptr @.str.2, i32 %8) + br label %if.exit + +if.exit: ; preds = %if.then, %end_chain + ret void +} + + + +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 + %optval = load i64, ptr %a.f, align 8 + %not_err = icmp eq i64 %optval, 0 + %0 = call i1 @llvm.expect.i1(i1 %not_err, i1 true) + br i1 %0, 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) + %i2b = icmp ne i32 %3, 0 + br i1 %i2b, 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_suite7/errors/try_with_weird_stuff.c3 b/test/test_suite7/errors/try_with_weird_stuff.c3 new file mode 100644 index 000000000..2cf0bdf0f --- /dev/null +++ b/test/test_suite7/errors/try_with_weird_stuff.c3 @@ -0,0 +1,16 @@ +fn void test1() +{ + + int! a; + int b; + int*! x; + if (try int 1 = 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_suite7/errors/type_optional_declaration_order.c3 b/test/test_suite7/errors/type_optional_declaration_order.c3 new file mode 100644 index 000000000..1ea98e202 --- /dev/null +++ b/test/test_suite7/errors/type_optional_declaration_order.c3 @@ -0,0 +1,27 @@ +import std::io; + +fn void! test1() +{ + CallbackResult![] result = 123; // #error: Foo[]! +} + +fn void! test2() +{ + CallbackResult![?] result = 123; // #error: Foo[?]! +} + +fn void! test3() +{ + CallbackResult![4 + 5] result = 123; // #error: Foo[4]! +} + +fn void! test4() +{ + CallbackResult![] result = 123; // #error: Foo[]! +} + +fn void! test5() +{ + CallbackResult![] result = 123; // #error: Foo[<4>]! +} + diff --git a/test/test_suite7/examples/gameoflife.c3 b/test/test_suite7/examples/gameoflife.c3 new file mode 100644 index 000000000..623399150 --- /dev/null +++ b/test/test_suite7/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(usz 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((isz)h * w); + board.temp = malloc((isz)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_suite7/expression_block/expr_block_labelled_break.c3 b/test/test_suite7/expression_block/expr_block_labelled_break.c3 new file mode 100644 index 000000000..08c01fee4 --- /dev/null +++ b/test/test_suite7/expression_block/expr_block_labelled_break.c3 @@ -0,0 +1,10 @@ +// #deprecation: no +fn void test() +{ + for FOO: (int i = 0; i < 100; i++) + { + {| + if (i == 10) break FOO; // #error: You cannot break out of an expression block + |}; + } +} \ No newline at end of file diff --git a/test/test_suite7/expression_block/expr_block_no_assign.c3 b/test/test_suite7/expression_block/expr_block_no_assign.c3 new file mode 100644 index 000000000..98aaea52a --- /dev/null +++ b/test/test_suite7/expression_block/expr_block_no_assign.c3 @@ -0,0 +1,7 @@ +// #deprecation: no +module helloworld; + +fn void main() +{ + {| return 1; |}; // #error: which must be handled +} \ No newline at end of file diff --git a/test/test_suite7/expression_block/expression_block_break.c3 b/test/test_suite7/expression_block/expression_block_break.c3 new file mode 100644 index 000000000..0412bfc60 --- /dev/null +++ b/test/test_suite7/expression_block/expression_block_break.c3 @@ -0,0 +1,12 @@ +// #deprecation: no +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 + } +} \ No newline at end of file diff --git a/test/test_suite7/expression_block/expression_block_no_end_return.c3 b/test/test_suite7/expression_block/expression_block_no_end_return.c3 new file mode 100644 index 000000000..2a2905a40 --- /dev/null +++ b/test/test_suite7/expression_block/expression_block_no_end_return.c3 @@ -0,0 +1,9 @@ +// #deprecation: no +module foob; + +fn void main() +{ + {| + if (1) return 1; // #error: Expected a return statement following this statement + |}; +} diff --git a/test/test_suite7/expressions/2002-02-13-ConditionalInCall.c3t b/test/test_suite7/expressions/2002-02-13-ConditionalInCall.c3t new file mode 100644 index 000000000..ddb947ff9 --- /dev/null +++ b/test/test_suite7/expressions/2002-02-13-ConditionalInCall.c3t @@ -0,0 +1,16 @@ +// #target: macos-x64 + +module test; + +extern fn void foo(int, double, float); + +fn void bar(int x) +{ + foo(x, x ? 1.0 : 12.5, 1.0); +} + +/* #expect: test.ll + + %i2b = icmp ne i32 %0, 0 + %ternary = select i1 %i2b, double 1.000000e+00, double 1.250000e+01 + call void @foo(i32 %0, double %ternary, float 1.000000e+00) diff --git a/test/test_suite7/expressions/addr_compiles.c3t b/test/test_suite7/expressions/addr_compiles.c3t new file mode 100644 index 000000000..db8049d92 --- /dev/null +++ b/test/test_suite7/expressions/addr_compiles.c3t @@ -0,0 +1,138 @@ +// #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: +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 ptr, ptr %h, align 8 + %3 = load i32, ptr %1, align 4 + %4 = load i32, ptr %2, align 4 + call void (ptr, ...) @printf(ptr @.str, i32 %3, i32 %4) + ret void +} + +; Function Attrs: +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 4 + call void (ptr, ...) @printf(ptr @.str.1, i32 %1) + ret void +} + +; Function Attrs: +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) + store ptr %h, ptr %zx, align 8 + %ptradd = getelementptr inbounds i8, ptr %h, i64 4 + store ptr %ptradd, ptr %zy, align 8 + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %arr, ptr align 4 @.__const.2, i32 12, i1 false) + %0 = load ptr, ptr %zx, align 8 + %1 = load ptr, ptr %zy, align 8 + %2 = load i32, ptr %0, align 4 + %3 = load i32, ptr %1, align 4 + call void (ptr, ...) @printf(ptr @.str.3, i32 %2, i32 %3) + %4 = load i32, ptr %arr, align 4 + %sub = sub i32 %4, 1 + store i32 %sub, ptr %arr, align 4 + %ptradd1 = getelementptr inbounds i8, ptr %arr, i64 4 + %5 = load i32, ptr %ptradd1, align 4 + %sub2 = sub i32 %5, 1 + store i32 %sub2, ptr %ptradd1, align 4 + %ptradd3 = getelementptr inbounds i8, ptr %arr, i64 8 + %6 = load i32, ptr %ptradd3, align 4 + %sub4 = sub i32 %6, 1 + store i32 %sub4, ptr %ptradd3, align 4 + %ptradd5 = getelementptr inbounds i8, ptr %arr, i64 8 + store ptr %ptradd5, ptr %d, align 8 + %ptradd6 = getelementptr inbounds i8, ptr %arr, i64 4 + %7 = insertvalue %"int[]" undef, ptr %ptradd6, 0 + %8 = insertvalue %"int[]" %7, i64 2, 1 + store %"int[]" %8, ptr %taddr, align 8 + store ptr %taddr, ptr %e, align 8 + %9 = load ptr, ptr %d, align 8 + %10 = load ptr, ptr %e, align 8 + %11 = load ptr, ptr %10, align 8 + %12 = load i32, ptr %9, align 4 + %13 = load i32, ptr %11, align 4 + call void (ptr, ...) @printf(ptr @.str.4, i32 %12, i32 %13) + ret void +} \ No newline at end of file diff --git a/test/test_suite7/expressions/addr_of_fails.c3 b/test/test_suite7/expressions/addr_of_fails.c3 new file mode 100644 index 000000000..f8c1fcbb3 --- /dev/null +++ b/test/test_suite7/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; +} + +def 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 '&' +} + +def Baz = Foo; +distinct Bar = 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_suite7/expressions/arithmetics.c3 b/test/test_suite7/expressions/arithmetics.c3 new file mode 100644 index 000000000..3644ed17e --- /dev/null +++ b/test/test_suite7/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_suite7/expressions/arithmetics_sema_fail.c3 b/test/test_suite7/expressions/arithmetics_sema_fail.c3 new file mode 100644 index 000000000..5612ed71e --- /dev/null +++ b/test/test_suite7/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: to a constant expression +} + +fn void test11() +{ + '10' = '20'; // #error: to a constant expression +} + +fn void test12() +{ + true = false; // #error: to a constant expression +} + +fn void test13() +{ + "a" = "b"; // #error: to a constant expression +} + +fn void test14() +{ + 1.2 = 1.3; // #error: to a constant expression +} + +fn void test15() +{ + null = null; // #error: to a constant 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_suite7/expressions/assign.c3 b/test/test_suite7/expressions/assign.c3 new file mode 100644 index 000000000..046ae8a8d --- /dev/null +++ b/test/test_suite7/expressions/assign.c3 @@ -0,0 +1,5 @@ +fn void test1() +{ + int* p; + *p = 10; +} diff --git a/test/test_suite7/expressions/assign_deref_opt.c3 b/test/test_suite7/expressions/assign_deref_opt.c3 new file mode 100644 index 000000000..5f4584533 --- /dev/null +++ b/test/test_suite7/expressions/assign_deref_opt.c3 @@ -0,0 +1,9 @@ +module test; + +fn void main() +{ + int! a; + int*! b; + *b = a; // #error: You cannot assign to a dereferenced optional +} + diff --git a/test/test_suite7/expressions/assign_optional.c3t b/test/test_suite7/expressions/assign_optional.c3t new file mode 100644 index 000000000..d61fcf34d --- /dev/null +++ b/test/test_suite7/expressions/assign_optional.c3t @@ -0,0 +1,69 @@ +// #target: macos-x64 +module test; + +fn void main() +{ + anyfault x = SearchResult.MISSING; + int! a = x?; + int! b = a = x?; + int! c = b = a; +} + +/* #expect: test.ll + +define void @test.main() #0 { +entry: + %x = alloca i64, align 8 + %a = alloca i32, align 4 + %a.f = alloca i64, align 8 + %b = alloca i32, align 4 + %b.f = alloca i64, align 8 + %c = alloca i32, align 4 + %c.f = alloca i64, align 8 + store i64 ptrtoint (ptr @"std.core.builtin.SearchResult$MISSING" to i64), ptr %x, align 8 + %0 = load i64, ptr %x, align 8 + store i64 %0, ptr %a.f, align 8 + %1 = load i64, ptr %x, align 8 + store i64 %1, ptr %a.f, align 8 + %not_err = icmp eq i64 %1, 0 + %2 = call i1 @llvm.expect.i1(i1 %not_err, i1 true) + br i1 %2, label %after_check, label %assign_optional + +assign_optional: ; preds = %entry + store i64 %1, ptr %b.f, align 8 + br label %after_assign + +after_check: ; preds = %entry + store i32 undef, ptr %b, align 4 + store i64 0, ptr %b.f, align 8 + br label %after_assign + +after_assign: ; preds = %after_check, %assign_optional + %optval = load i64, ptr %a.f, align 8 + %not_err1 = icmp eq i64 %optval, 0 + %3 = call i1 @llvm.expect.i1(i1 %not_err1, i1 true) + br i1 %3, label %after_check3, label %assign_optional2 + +assign_optional2: ; preds = %after_assign + store i64 %optval, ptr %b.f, align 8 + br label %optional_assign_jump + +after_check3: ; preds = %after_assign + %4 = load i32, ptr %a, align 4 + store i32 %4, ptr %b, align 4 + store i64 0, ptr %b.f, align 8 + br label %after_assign4 + +optional_assign_jump: ; preds = %assign_optional2 + %reload_err = load i64, ptr %b.f, align 8 + store i64 %reload_err, ptr %c.f, align 8 + br label %after_assign5 + +after_assign4: ; preds = %after_check3 + store i32 %4, ptr %c, align 4 + store i64 0, ptr %c.f, align 8 + br label %after_assign5 + +after_assign5: ; preds = %after_assign4, %optional_assign_jump + ret void +} diff --git a/test/test_suite7/expressions/assign_to_address.c3 b/test/test_suite7/expressions/assign_to_address.c3 new file mode 100644 index 000000000..77150c3a2 --- /dev/null +++ b/test/test_suite7/expressions/assign_to_address.c3 @@ -0,0 +1,7 @@ +// Issue #1833 +fn int main() +{ + int* i; + &i[0] = null; // #error: An assignable expression + return 0; +} \ No newline at end of file diff --git a/test/test_suite7/expressions/assignability.c3 b/test/test_suite7/expressions/assignability.c3 new file mode 100644 index 000000000..4f8825393 --- /dev/null +++ b/test/test_suite7/expressions/assignability.c3 @@ -0,0 +1,39 @@ +def Number = int; + +fn void test1() +{ + 10 = 20; // #error: to a constant expression +} + +fn void test2() +{ + "foo" = "bar"; // #error: to a constant expression +} + +fn void test3() +{ + true = false; // #error: to a constant expression +} + +fn void test4() +{ + 'c' = 'd'; // #error: to a constant expression +} + +fn void test5() +{ + 3.14 = 2.14; // #error: to a constant 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_suite7/expressions/assignment_precedence.c3t b/test/test_suite7/expressions/assignment_precedence.c3t new file mode 100644 index 000000000..e484d1a88 --- /dev/null +++ b/test/test_suite7/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_suite7/expressions/bit_op_on_bool.c3t b/test/test_suite7/expressions/bit_op_on_bool.c3t new file mode 100644 index 000000000..cd084d32c --- /dev/null +++ b/test/test_suite7/expressions/bit_op_on_bool.c3t @@ -0,0 +1,14 @@ +// #target: macos-x64 +module bitop; + +fn bool is_newline_codepoint(uint codepoint) { + return (bool)((codepoint == 0x00_00_24_24) | (codepoint == 0x00_00_2B_92)); +} + +/* #expect: bitop.ll + + %eq = icmp eq i32 %0, 9252 + %eq1 = icmp eq i32 %0, 11154 + %or = or i1 %eq, %eq1 + %1 = zext i1 %or to i8 + ret i8 %1 diff --git a/test/test_suite7/expressions/bool_conversions.c3t b/test/test_suite7/expressions/bool_conversions.c3t new file mode 100644 index 000000000..972be92db --- /dev/null +++ b/test/test_suite7/expressions/bool_conversions.c3t @@ -0,0 +1,34 @@ +// #target: macos-x64 +// #deprecation: no + +fn bool f0_0(void* a0) @private { return (bool)a0; } + +fn int f0() { return (int)f0_0((void*)0x2); } + +def Test = fn void(); + +fn bool f1() { return (bool){| Test x @noinit; return x = (Test)0; |}; } + +/* #expect: bool_conversions.ll + +define internal zeroext i8 @bool_conversions.f0_0(ptr %0) #0 { +entry: + %i2b = icmp ne ptr %0, null + %1 = zext i1 %i2b to i8 + ret i8 %1 +} + +define i32 @bool_conversions.f0() #0 { +entry: + %0 = call i8 @bool_conversions.f0_0(ptr inttoptr (i64 2 to ptr)) + %1 = trunc i8 %0 to i1 + %zext = zext i1 %1 to i32 + ret i32 %zext +} + +define zeroext i8 @bool_conversions.f1() #0 { +entry: + %x = alloca ptr, align 8 + store ptr null, ptr %x, align 8 + ret i8 0 +} diff --git a/test/test_suite7/expressions/call_arg_types.c3 b/test/test_suite7/expressions/call_arg_types.c3 new file mode 100644 index 000000000..405b175be --- /dev/null +++ b/test/test_suite7/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: 'ichar' + test2(100 + a); // #error: 'ichar' + + const int X = 120; + test2(X); + + test2(100 + 100); // #error: '200' is out of range for 'ichar' +} + diff --git a/test/test_suite7/expressions/call_inline.c3t b/test/test_suite7/expressions/call_inline.c3t new file mode 100644 index 000000000..4a2311bee --- /dev/null +++ b/test/test_suite7/expressions/call_inline.c3t @@ -0,0 +1,48 @@ +// #target: macos-x64 +module inlineme; +import std::io; + +fn void test1() @inline +{ + io::printn("Inline!"); +} + +fn void test2() @noinline +{ + io::printn("No inline!"); +} + +fn void test3() +{ + io::printn("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() #3 + call void @inlineme.test2() #3 + call void @inlineme.test3() #3 + call void @inlineme.test1() #4 + call void @inlineme.test2() #4 + call void @inlineme.test3() #4 + call void @inlineme.test1() #3 + call void @inlineme.test2() + call void @inlineme.test3() + ret void +} + +attributes #3 = { alwaysinline } +attributes #4 = { noinline } diff --git a/test/test_suite7/expressions/casts/cast_const.c3 b/test/test_suite7/expressions/casts/cast_const.c3 new file mode 100644 index 000000000..1e9f68455 --- /dev/null +++ b/test/test_suite7/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: truncate the value +} diff --git a/test/test_suite7/expressions/casts/cast_enum_const_to_distinct.c3 b/test/test_suite7/expressions/casts/cast_enum_const_to_distinct.c3 new file mode 100644 index 000000000..3d2b4fd8a --- /dev/null +++ b/test/test_suite7/expressions/casts/cast_enum_const_to_distinct.c3 @@ -0,0 +1,9 @@ +enum Foo +{ + ABC +} +distinct Abc = int; +fn void main() +{ + Abc d = Foo.ABC; // #error: to 'Abc' +} diff --git a/test/test_suite7/expressions/casts/cast_enum_to_various.c3 b/test/test_suite7/expressions/casts/cast_enum_to_various.c3 new file mode 100644 index 000000000..0a75c1eb2 --- /dev/null +++ b/test/test_suite7/expressions/casts/cast_enum_to_various.c3 @@ -0,0 +1,37 @@ +struct Struct +{ + int x; +} + +enum Enum : uint +{ + A, B +} + +enum EnumB : char +{ + C, D +} + +def Func = fn void(Enum); + +fn void test1(Enum e) +{ + bool a = (bool)e; // #error: bool + char b = (char)e.ordinal; + uint c = (uint)e.ordinal; + float d = (float)e; // #error: float + uint* f = (uint*)e; // #error: 'uint*' +} + +fn void test2(Enum e) +{ + Struct* g = (Struct*)(e); // #error: 'Struct*' +} + +fn void test3(Enum e) +{ + EnumB h = (EnumB)(e); // #error: 'EnumB' + Func i = (Func)(e); // #error: 'Func' +} + diff --git a/test/test_suite7/expressions/casts/cast_expr.c3t b/test/test_suite7/expressions/casts/cast_expr.c3t new file mode 100644 index 000000000..c888e320c --- /dev/null +++ b/test/test_suite7/expressions/casts/cast_expr.c3t @@ -0,0 +1,28 @@ +// #target: macos-x64 +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 %trunc to i32 + store i32 %sext, ptr %c + ret i32 0 +} diff --git a/test/test_suite7/expressions/casts/cast_failable.c3 b/test/test_suite7/expressions/casts/cast_failable.c3 new file mode 100644 index 000000000..fdfaa6954 --- /dev/null +++ b/test/test_suite7/expressions/casts/cast_failable.c3 @@ -0,0 +1,10 @@ +fault MyErr +{ + FOO +} + +fn void test() +{ + int! x = (int!)(MyErr.FOO?); // #error: Casting to an optional type is not + int! y = MyErr.FOO?; +} \ No newline at end of file diff --git a/test/test_suite7/expressions/casts/cast_func_to_various.c3 b/test/test_suite7/expressions/casts/cast_func_to_various.c3 new file mode 100644 index 000000000..3c3989eb6 --- /dev/null +++ b/test/test_suite7/expressions/casts/cast_func_to_various.c3 @@ -0,0 +1,45 @@ +struct Struct +{ + int x; +} + +enum Enum : uptr +{ + A, B +} + +def Func = fn void(int); +def FuncOther = fn bool(char*); +def FuncSame = fn void(int); + + +fn void test1(Func arg) +{ + bool a = (bool)(arg); + bool b = arg; // #error: to 'bool' +} + +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) +{ + usz g = (usz)(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_suite7/expressions/casts/cast_implicit_inline_distinct.c3 b/test/test_suite7/expressions/casts/cast_implicit_inline_distinct.c3 new file mode 100644 index 000000000..7dce84d2b --- /dev/null +++ b/test/test_suite7/expressions/casts/cast_implicit_inline_distinct.c3 @@ -0,0 +1,9 @@ +distinct DistinctInt = inline int; +distinct DistinctInt2 = inline DistinctInt; + +fn void test() +{ + DistinctInt2 y; + DistinctInt x = y; + DistinctInt2 z = x; // #error: Implicitly casting +} \ No newline at end of file diff --git a/test/test_suite7/expressions/casts/cast_to_nonscalar.c3 b/test/test_suite7/expressions/casts/cast_to_nonscalar.c3 new file mode 100644 index 000000000..6a43d7a4c --- /dev/null +++ b/test/test_suite7/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_suite7/expressions/casts/cast_unknown.c3 b/test/test_suite7/expressions/casts/cast_unknown.c3 new file mode 100644 index 000000000..17ca4995b --- /dev/null +++ b/test/test_suite7/expressions/casts/cast_unknown.c3 @@ -0,0 +1,21 @@ +def 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_suite7/expressions/casts/cast_vector_fail.c3 b/test/test_suite7/expressions/casts/cast_vector_fail.c3 new file mode 100644 index 000000000..df92120ff --- /dev/null +++ b/test/test_suite7/expressions/casts/cast_vector_fail.c3 @@ -0,0 +1,17 @@ +module foo; +import std; +fn void test(float[<4>]* x) +{} +fn void test2(float[4]* x) +{} + +fn int main(String[] args) +{ + float[4] a; + float[<4>] b; + test(&a); // #error: Implicitly casting + test(&b); + test2(&a); + test2(&b); + return 1; +} diff --git a/test/test_suite7/expressions/casts/enum_plus_minus.c3t b/test/test_suite7/expressions/casts/enum_plus_minus.c3t new file mode 100644 index 000000000..1770a5cc0 --- /dev/null +++ b/test/test_suite7/expressions/casts/enum_plus_minus.c3t @@ -0,0 +1,72 @@ +// #target: macos-x64 +module test; +import std; +enum Foo : ichar +{ + ABC, + BCD, + BAR, + BAZ +} + +fn void main() +{ + Foo x = 1 + Foo.ABC; + ichar i = 1; + assert(x == BCD); + x = i + Foo.ABC; + assert(x == BCD); + x++; + assert(x == BAR); + x = -1 + x; + assert(x == BCD); + x = -i + x; + assert(x == ABC); + x = -1 + Foo.BAR; + assert(x == BCD); +} + +/* #expect: test.ll + +entry: + %x = alloca i8, align 1 + %i = alloca i8, align 1 + store i8 1, ptr %x, align 1 + store i8 1, ptr %i, align 1 + %0 = load i8, ptr %x, align 1 + %eq = icmp eq i8 %0, 1 + call void @llvm.assume(i1 %eq) + %1 = load i8, ptr %i, align 1 + %add = add i8 %1, 0 + store i8 %add, ptr %x, align 1 + %2 = load i8, ptr %x, align 1 + %eq1 = icmp eq i8 %2, 1 + call void @llvm.assume(i1 %eq1) + %3 = load i8, ptr %x, align 1 + %add2 = add i8 %3, 1 + store i8 %add2, ptr %x, align 1 + %4 = load i8, ptr %x, align 1 + %eq3 = icmp eq i8 %4, 2 + call void @llvm.assume(i1 %eq3) + %5 = load i8, ptr %x, align 1 + %add4 = add i8 -1, %5 + store i8 %add4, ptr %x, align 1 + %6 = load i8, ptr %x, align 1 + %eq5 = icmp eq i8 %6, 1 + call void @llvm.assume(i1 %eq5) + %7 = load i8, ptr %i, align 1 + %sext = sext i8 %7 to i32 + %neg = sub i32 0, %sext + %trunc = trunc i32 %neg to i8 + %8 = load i8, ptr %x, align 1 + %add6 = add i8 %trunc, %8 + store i8 %add6, ptr %x, align 1 + %9 = load i8, ptr %x, align 1 + %eq7 = icmp eq i8 %9, 0 + call void @llvm.assume(i1 %eq7) + store i8 1, ptr %x, align 1 + %10 = load i8, ptr %x, align 1 + %eq8 = icmp eq i8 %10, 1 + call void @llvm.assume(i1 %eq8) + ret void +} diff --git a/test/test_suite7/expressions/casts/explicit_cast.c3 b/test/test_suite7/expressions/casts/explicit_cast.c3 new file mode 100644 index 000000000..9839e33e6 --- /dev/null +++ b/test/test_suite7/expressions/casts/explicit_cast.c3 @@ -0,0 +1,16 @@ +def Number8 = char; +def Number32 = int; +distinct DNumber32 = int; +fn void test1() +{ + int a = (ichar)(10); + int b = (ichar)(200); + int c = (int)(200); + ichar d = (int)(200); // #error: truncate the value +} + +fn void test2() +{ + char e = (Number32)(200); + char f = (DNumber32)(200); // #error: DNumber32 +} \ No newline at end of file diff --git a/test/test_suite7/expressions/casts/failed_distinct_float_conversions.c3 b/test/test_suite7/expressions/casts/failed_distinct_float_conversions.c3 new file mode 100644 index 000000000..ba1d99002 --- /dev/null +++ b/test/test_suite7/expressions/casts/failed_distinct_float_conversions.c3 @@ -0,0 +1,9 @@ +distinct Foo = double; +distinct Bar = void*; +fn int main() +{ + float f = 1; + Foo foo = f; // #error: explicit cast + Bar bar = f; // #error: 'float' to 'Bar' + return 1; +} \ No newline at end of file diff --git a/test/test_suite7/expressions/casts/narrowing.c3 b/test/test_suite7/expressions/casts/narrowing.c3 new file mode 100644 index 000000000..983d0af78 --- /dev/null +++ b/test/test_suite7/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_suite7/expressions/casts/narrowing_through_casts.c3 b/test/test_suite7/expressions/casts/narrowing_through_casts.c3 new file mode 100644 index 000000000..9b4e3c6f7 --- /dev/null +++ b/test/test_suite7/expressions/casts/narrowing_through_casts.c3 @@ -0,0 +1,9 @@ +fn void main() +{ + long x; + + int i = (char)x; // Ok + char c; + short s1 = (long)c; // Ok + short s2 = (long)i; // #error: 'int' cannot implicitly be converted +} \ No newline at end of file diff --git a/test/test_suite7/expressions/casts/struct_cast_and_distinct.c3 b/test/test_suite7/expressions/casts/struct_cast_and_distinct.c3 new file mode 100644 index 000000000..a4864337c --- /dev/null +++ b/test/test_suite7/expressions/casts/struct_cast_and_distinct.c3 @@ -0,0 +1,32 @@ +module test; + +distinct Foo = int; + +fn void test1() +{ + int[2][?] x = { { 2, 3}, { 5, 6 }}; + Foo[2][2] y = x; // #error: explicit cast +} + +fn void test2() +{ + int[2][?] x = { { 2, 3}, { 5, 6 }}; + Foo[2][2] y = (Foo[2][2])x; +} + + +fn void test3() +{ + int[2][?] x = { { 2, 3}, { 5, 6 }}; + Foo[2][2]* y = &x; // #error: explicit cast +} + +struct Bar { int x; } + +struct Baz { int x; } + +fn void test4() +{ + Baz[2][?] x = { { { 2 } , { 3 } }, {{5}, {6} }}; + Bar[?][?] y = (Bar[2][2])x; +} diff --git a/test/test_suite7/expressions/casts/void_casting.c3t b/test/test_suite7/expressions/casts/void_casting.c3t new file mode 100644 index 000000000..8cdcff296 --- /dev/null +++ b/test/test_suite7/expressions/casts/void_casting.c3t @@ -0,0 +1,62 @@ +// #target: macos-x64 +module test; + +fn void! foo() +{} + +fault Abc { AAA } + +macro int! bar() +{ + return Abc.AAA?; +} + +fn int! baz() +{ + return 2; +} + +fn int main() +{ + int x; + int! y; + (void)x; + (void)y; + (void)foo(); + (void)bar(); + (void)(bar() + 1); + (void)baz(); + (void)(baz() + 1); + return 1; +} + +/* #expect: test.ll + +define i32 @main() #0 { +entry: + %x = alloca i32, align 4 + %y = alloca i32, align 4 + %y.f = alloca i64, align 8 + %retparam = alloca i32, align 4 + %retparam2 = alloca i32, align 4 + store i32 0, ptr %x, align 4 + store i64 0, ptr %y.f, align 8 + store i32 0, ptr %y, align 4 + %optval = load i64, ptr %y.f, align 8 + %0 = call i64 @test.foo() + br label %postfailed +postfailed: ; preds = %entry + br label %postfailed1 +postfailed1: ; preds = %postfailed + %1 = call i64 @test.baz(ptr %retparam) + %2 = call i64 @test.baz(ptr %retparam2) + %not_err = icmp eq i64 %2, 0 + %3 = call i1 @llvm.expect.i1(i1 %not_err, i1 true) + br i1 %3, label %after_check, label %voiderr +after_check: ; preds = %postfailed1 + %4 = load i32, ptr %retparam2, align 4 + %add = add i32 %4, 1 + br label %voiderr +voiderr: ; preds = %after_check, %postfailed1 + ret i32 1 +} \ No newline at end of file diff --git a/test/test_suite7/expressions/chained_conditional.c3t b/test/test_suite7/expressions/chained_conditional.c3t new file mode 100644 index 000000000..58ead758b --- /dev/null +++ b/test/test_suite7/expressions/chained_conditional.c3t @@ -0,0 +1,70 @@ +// #target: macos-x64 +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_suite7/expressions/chained_ternary.c3t b/test/test_suite7/expressions/chained_ternary.c3t new file mode 100644 index 000000000..28bf22952 --- /dev/null +++ b/test/test_suite7/expressions/chained_ternary.c3t @@ -0,0 +1,220 @@ +// #target: macos-x64 +module test; + +fault Test { FOO, BAR } + +fn void test() +{ + void* a; + void* b; + void* c; + a = !a ? a : !a ? b : c; + void*! x; + void*! y = !a ? x : b; + y = !a ? b : x; + y = !a ? x : x; + y = !a ? x : Test.FOO?; + y = !a ? Test.FOO? : x; + y = !a ? Test.FOO? : Test.BAR?; +} + +/* #expect: test.ll + + %0 = load ptr, ptr %a, align 8 + %i2nb = icmp eq ptr %0, null + br i1 %i2nb, label %cond.lhs, label %cond.rhs + +cond.lhs: ; preds = %entry + %1 = load ptr, ptr %a, align 8 + br label %cond.phi4 + +cond.rhs: ; preds = %entry + %2 = load ptr, ptr %a, align 8 + %i2nb1 = icmp eq ptr %2, null + br i1 %i2nb1, label %cond.lhs2, label %cond.rhs3 + +cond.lhs2: ; preds = %cond.rhs + %3 = load ptr, ptr %b, align 8 + br label %cond.phi + +cond.rhs3: ; preds = %cond.rhs + %4 = load ptr, ptr %c, align 8 + br label %cond.phi + +cond.phi: ; preds = %cond.rhs3, %cond.lhs2 + %val = phi ptr [ %3, %cond.lhs2 ], [ %4, %cond.rhs3 ] + br label %cond.phi4 + +cond.phi4: ; preds = %cond.phi, %cond.lhs + %val5 = phi ptr [ %1, %cond.lhs ], [ %val, %cond.phi ] + store ptr %val5, ptr %a, align 8 + store i64 0, ptr %x.f, align 8 + store ptr null, ptr %x, align 8 + %5 = load ptr, ptr %a, align 8 + %i2nb6 = icmp eq ptr %5, null + br i1 %i2nb6, label %cond.lhs7, label %cond.rhs8 + +cond.lhs7: ; preds = %cond.phi4 + %optval = load i64, ptr %x.f, align 8 + %not_err = icmp eq i64 %optval, 0 + %6 = call i1 @llvm.expect.i1(i1 %not_err, i1 true) + br i1 %6, label %after_check, label %assign_optional + +assign_optional: ; preds = %cond.lhs7 + store i64 %optval, ptr %y.f, align 8 + br label %after_assign + +after_check: ; preds = %cond.lhs7 + %7 = load ptr, ptr %x, align 8 + br label %cond.phi9 + +cond.rhs8: ; preds = %cond.phi4 + %8 = load ptr, ptr %b, align 8 + br label %cond.phi9 + +cond.phi9: ; preds = %cond.rhs8, %after_check + %val10 = phi ptr [ %7, %after_check ], [ %8, %cond.rhs8 ] + store ptr %val10, ptr %y, align 8 + store i64 0, ptr %y.f, align 8 + br label %after_assign + +after_assign: ; preds = %cond.phi9, %assign_optional + %9 = load ptr, ptr %a, align 8 + %i2nb11 = icmp eq ptr %9, null + br i1 %i2nb11, label %cond.lhs12, label %cond.rhs13 + +cond.lhs12: ; preds = %after_assign + %10 = load ptr, ptr %b, align 8 + br label %cond.phi18 + +cond.rhs13: ; preds = %after_assign + %optval14 = load i64, ptr %x.f, align 8 + %not_err15 = icmp eq i64 %optval14, 0 + %11 = call i1 @llvm.expect.i1(i1 %not_err15, i1 true) + br i1 %11, label %after_check17, label %assign_optional16 + +assign_optional16: ; preds = %cond.rhs13 + store i64 %optval14, ptr %y.f, align 8 + br label %after_assign20 + +after_check17: ; preds = %cond.rhs13 + %12 = load ptr, ptr %x, align 8 + br label %cond.phi18 + +cond.phi18: ; preds = %after_check17, %cond.lhs12 + %val19 = phi ptr [ %10, %cond.lhs12 ], [ %12, %after_check17 ] + store ptr %val19, ptr %y, align 8 + store i64 0, ptr %y.f, align 8 + br label %after_assign20 + +after_assign20: ; preds = %cond.phi18, %assign_optional16 + %13 = load ptr, ptr %a, align 8 + %i2nb21 = icmp eq ptr %13, null + br i1 %i2nb21, label %cond.lhs22, label %cond.rhs27 + +cond.lhs22: ; preds = %after_assign20 + %optval23 = load i64, ptr %x.f, align 8 + %not_err24 = icmp eq i64 %optval23, 0 + %14 = call i1 @llvm.expect.i1(i1 %not_err24, i1 true) + br i1 %14, label %after_check26, label %assign_optional25 + +assign_optional25: ; preds = %cond.lhs22 + store i64 %optval23, ptr %y.f, align 8 + br label %after_assign34 + +after_check26: ; preds = %cond.lhs22 + %15 = load ptr, ptr %x, align 8 + br label %cond.phi32 + +cond.rhs27: ; preds = %after_assign20 + %optval28 = load i64, ptr %x.f, align 8 + %not_err29 = icmp eq i64 %optval28, 0 + %16 = call i1 @llvm.expect.i1(i1 %not_err29, i1 true) + br i1 %16, label %after_check31, label %assign_optional30 + +assign_optional30: ; preds = %cond.rhs27 + store i64 %optval28, ptr %y.f, align 8 + br label %after_assign34 + +after_check31: ; preds = %cond.rhs27 + %17 = load ptr, ptr %x, align 8 + br label %cond.phi32 + +cond.phi32: ; preds = %after_check31, %after_check26 + %val33 = phi ptr [ %15, %after_check26 ], [ %17, %after_check31 ] + store ptr %val33, ptr %y, align 8 + store i64 0, ptr %y.f, align 8 + br label %after_assign34 + +after_assign34: ; preds = %cond.phi32, %assign_optional30, %assign_optional25 + %18 = load ptr, ptr %a, align 8 + %i2nb35 = icmp eq ptr %18, null + br i1 %i2nb35, label %cond.lhs36, label %cond.rhs41 + +cond.lhs36: ; preds = %after_assign34 + %optval37 = load i64, ptr %x.f, align 8 + %not_err38 = icmp eq i64 %optval37, 0 + %19 = call i1 @llvm.expect.i1(i1 %not_err38, i1 true) + br i1 %19, label %after_check40, label %assign_optional39 + +assign_optional39: ; preds = %cond.lhs36 + store i64 %optval37, ptr %y.f, align 8 + br label %after_assign43 + +after_check40: ; preds = %cond.lhs36 + %20 = load ptr, ptr %x, align 8 + br label %cond.phi42 + +cond.rhs41: ; preds = %after_assign34 + store i64 ptrtoint (ptr @"test.Test$FOO" to i64), ptr %y.f, align 8 + br label %after_assign43 + +cond.phi42: ; preds = %after_check40 + store ptr %20, ptr %y, align 8 + store i64 0, ptr %y.f, align 8 + br label %after_assign43 + +after_assign43: ; preds = %cond.phi42, %cond.rhs41, %assign_optional39 + %21 = load ptr, ptr %a, align 8 + %i2nb44 = icmp eq ptr %21, null + br i1 %i2nb44, label %cond.lhs45, label %cond.rhs46 + +cond.lhs45: ; preds = %after_assign43 + store i64 ptrtoint (ptr @"test.Test$FOO" to i64), ptr %y.f, align 8 + br label %after_assign52 + +cond.rhs46: ; preds = %after_assign43 + %optval47 = load i64, ptr %x.f, align 8 + %not_err48 = icmp eq i64 %optval47, 0 + %22 = call i1 @llvm.expect.i1(i1 %not_err48, i1 true) + br i1 %22, label %after_check50, label %assign_optional49 + +assign_optional49: ; preds = %cond.rhs46 + store i64 %optval47, ptr %y.f, align 8 + br label %after_assign52 + +after_check50: ; preds = %cond.rhs46 + %23 = load ptr, ptr %x, align 8 + br label %cond.phi51 + +cond.phi51: ; preds = %after_check50 + store ptr %23, ptr %y, align 8 + store i64 0, ptr %y.f, align 8 + br label %after_assign52 + +after_assign52: ; preds = %cond.phi51, %assign_optional49, %cond.lhs45 + %24 = load ptr, ptr %a, align 8 + %i2nb53 = icmp eq ptr %24, null + br i1 %i2nb53, label %cond.lhs54, label %cond.rhs55 + +cond.lhs54: ; preds = %after_assign52 + store i64 ptrtoint (ptr @"test.Test$FOO" to i64), ptr %y.f, align 8 + br label %after_assign57 + +cond.rhs55: ; preds = %after_assign52 + store i64 ptrtoint (ptr @"test.Test$BAR" to i64), ptr %y.f, align 8 + br label %after_assign57 + +after_assign57: ; preds = %cond.rhs55, %cond.lhs54 + ret void +} \ No newline at end of file diff --git a/test/test_suite7/expressions/check_implict_conversion_signed_unsigned.c3t b/test/test_suite7/expressions/check_implict_conversion_signed_unsigned.c3t new file mode 100644 index 000000000..cbc68d0cd --- /dev/null +++ b/test/test_suite7/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 + %sext = sext i32 %1 to i64 + %sub = sub i64 %0, %sext + ret i32 1 +} \ No newline at end of file diff --git a/test/test_suite7/expressions/deref_access_null.c3t b/test/test_suite7/expressions/deref_access_null.c3t new file mode 100644 index 000000000..2ebe621b1 --- /dev/null +++ b/test/test_suite7/expressions/deref_access_null.c3t @@ -0,0 +1,37 @@ +// #target: macos-x64 +// #safe: yes +module test; + +struct Foo +{ + int a; + float b; +} + +macro @offset_buggy($Type, #member) +{ + $Type *t = null; + return (usz)(uptr)&t.#member; +} + +fn int main() +{ + usz a = @offset_buggy(Foo, b); + return (int)a; +} + +/* #expect: test.ll + +define i32 @main() #0 { +entry: + %a = alloca i64, align 8 + %t = alloca ptr, align 8 + store ptr null, ptr %t, align 8 + %0 = load ptr, ptr %t, align 8 + %ptradd = getelementptr inbounds i8, ptr %0, i64 4 + %ptrxi = ptrtoint ptr %ptradd to i64 + store i64 %ptrxi, ptr %a, align 8 + %1 = load i64, ptr %a, align 8 + %trunc = trunc i64 %1 to i32 + ret i32 %trunc +} diff --git a/test/test_suite7/expressions/deref_const_string.c3t b/test/test_suite7/expressions/deref_const_string.c3t new file mode 100644 index 000000000..84a889211 --- /dev/null +++ b/test/test_suite7/expressions/deref_const_string.c3t @@ -0,0 +1,29 @@ +// #target: macos-x64 +module test; +import std; + +const char *VOWS = "aeiou"; +const char *CONS = "bcdfghjklmnpqrstvwxyz"; +const char *TEST = ""; + +fn int main (String[] args) +{ + char a = *VOWS; + char b = *CONS; + char c = *TEST; + return 0; +} + +/* #expect: test.ll + +@.str = private unnamed_addr constant [6 x i8] c"aeiou\00", align 1 +@test.VOWS = local_unnamed_addr constant ptr @.str, align 8 +@.str.3 = private unnamed_addr constant [22 x i8] c"bcdfghjklmnpqrstvwxyz\00", align 1 +@test.CONS = local_unnamed_addr constant ptr @.str.3, align 8 +@.str.4 = private unnamed_addr constant [1 x i8] zeroinitializer, align 1 +@test.TEST = local_unnamed_addr constant ptr @.str.4, align 8 + + store i8 97, ptr %a, align 1 + store i8 98, ptr %b, align 1 + store i8 0, ptr %c, align 1 + ret i32 0 diff --git a/test/test_suite7/expressions/elvis.c3t b/test/test_suite7/expressions/elvis.c3t new file mode 100644 index 000000000..aad8390f9 --- /dev/null +++ b/test/test_suite7/expressions/elvis.c3t @@ -0,0 +1,81 @@ +// #target: macos-x64 +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: + %i2b = icmp ne ptr %0, null + br i1 %i2b, label %cond.lhs, label %cond.rhs + +cond.lhs: ; preds = %entry + br label %cond.phi + +cond.rhs: ; preds = %entry + br label %cond.phi + +cond.phi: ; preds = %cond.rhs, %cond.lhs + %val = phi ptr [ %0, %cond.lhs ], [ %1, %cond.rhs ] + ret ptr %val +} + +; Function Attrs: nounwind uwtable +define ptr @elvis.elvis2(ptr %0, ptr %1) #0 { +entry: + %i2b = icmp ne ptr %0, null + br i1 %i2b, label %cond.lhs, label %cond.rhs + +cond.lhs: ; preds = %entry + br label %cond.phi4 + +cond.rhs: ; preds = %entry + %i2b1 = icmp ne ptr %1, null + br i1 %i2b1, label %cond.lhs2, label %cond.rhs3 + +cond.lhs2: ; preds = %cond.rhs + br label %cond.phi + +cond.rhs3: ; preds = %cond.rhs + br label %cond.phi + +cond.phi: ; preds = %cond.rhs3, %cond.lhs2 + %val = phi ptr [ %1, %cond.lhs2 ], [ %0, %cond.rhs3 ] + br label %cond.phi4 + +cond.phi4: ; preds = %cond.phi, %cond.lhs + %val5 = phi ptr [ %0, %cond.lhs ], [ %val, %cond.phi ] + ret ptr %val5 +} + +define zeroext i8 @elvis.elvis3(i8 zeroext %0, i8 zeroext %1) #0 { +entry: + %2 = trunc i8 %0 to i1 + br i1 %2, label %cond.lhs, label %cond.rhs + +cond.lhs: ; preds = %entry + br label %cond.phi + +cond.rhs: ; preds = %entry + %3 = trunc i8 %1 to i1 + br label %cond.phi + +cond.phi: ; preds = %cond.rhs, %cond.lhs + %val = phi i1 [ %2, %cond.lhs ], [ %3, %cond.rhs ] + %4 = zext i1 %val to i8 + ret i8 %4 +} diff --git a/test/test_suite7/expressions/enum_ct_sub.c3t b/test/test_suite7/expressions/enum_ct_sub.c3t new file mode 100644 index 000000000..50deb9772 --- /dev/null +++ b/test/test_suite7/expressions/enum_ct_sub.c3t @@ -0,0 +1,20 @@ +enum Foo : char +{ + ABC, + BCD +} +distinct Abc = int; +fn void main() +{ + $assert (Foo.ABC - Foo.BCD) == 255; + char c = Foo.ABC - Foo.BCD; + $assert $typeof(Foo.ABC - Foo.BCD).typeid == char.typeid; + $assert Foo.BCD - 1 == Foo.ABC; + $assert Foo.ABC + 1 == Foo.BCD; + $assert $typeof(Foo.BCD - 1).typeid == Foo.typeid; + $assert $typeof(Foo.ABC + 1).typeid == Foo.typeid; + Foo x = Foo.BCD; + $assert $typeof(x - 1).typeid == Foo.typeid; + x = x - 1; + $assert $typeof(x + 1).typeid == Foo.typeid; +} diff --git a/test/test_suite7/expressions/fail_index_usize.c3 b/test/test_suite7/expressions/fail_index_usize.c3 new file mode 100644 index 000000000..438d83cde --- /dev/null +++ b/test/test_suite7/expressions/fail_index_usize.c3 @@ -0,0 +1,5 @@ +fn void test(int* array, usz n) +{ + array[n] = 33; + n[array] = 33; // #error: Indexing a value of type +} diff --git a/test/test_suite7/expressions/fmuladd.c3t b/test/test_suite7/expressions/fmuladd.c3t new file mode 100644 index 000000000..c1fe384de --- /dev/null +++ b/test/test_suite7/expressions/fmuladd.c3t @@ -0,0 +1,82 @@ +// #target: macos-x64 +// #opt: --fp-math=relaxed +module test; +import std::io; + +fn float tester1(float a, float b, float c) +{ + return a * b + c; +} +fn float tester2(float a, float b, float c) +{ + return c + a * b; +} +fn float tester3(float a, float b, float c) +{ + c = -c; + return a * b - c; +} +fn float tester4(float a, float b, float c) +{ + c = -c; + return -c + a * b; +} + +fn float tester5(float a, float b, float c) +{ + c = -c; + return -(c - a * b); +} +fn float tester6(float a, float b, float c) +{ + c = -c; + return -(-a * b + c); +} + +fn void main() +{ + float a = 3.1; + float b = 1.4; + float c = 0.1; + io::printfn("%f", tester1(a, b, c)); + io::printfn("%f", tester2(a, b, c)); + io::printfn("%f", tester3(a, b, c)); + io::printfn("%f", tester4(a, b, c)); + io::printfn("%f", tester5(a, b, c)); + io::printfn("%f", tester6(a, b, c)); +} + +/* #expect: test.ll + + %3 = call reassoc arcp contract float @llvm.fmuladd.f32(float %0, float %1, float %2) + + %3 = call reassoc arcp contract float @llvm.fmuladd.f32(float %0, float %1, float %2) + + %3 = load float, ptr %c, align 4 + %fneg = fneg reassoc arcp contract float %3 + store float %fneg, ptr %c, align 4 + %4 = load float, ptr %c, align 4 + %5 = fneg reassoc arcp contract float %4 + %6 = call reassoc arcp contract float @llvm.fmuladd.f32(float %0, float %1, float %5) + + %fneg = fneg reassoc arcp contract float %3 + store float %fneg, ptr %c, align 4 + %4 = load float, ptr %c, align 4 + %fneg1 = fneg reassoc arcp contract float %4 + %5 = call reassoc arcp contract float @llvm.fmuladd.f32(float %0, float %1, float %fneg1) + + %3 = load float, ptr %c, align 4 + %fneg = fneg reassoc arcp contract float %3 + store float %fneg, ptr %c, align 4 + %4 = load float, ptr %c, align 4 + %5 = fneg reassoc arcp contract float %1 + %6 = call reassoc arcp contract float @llvm.fmuladd.f32(float %0, float %5, float %4) + %fneg1 = fneg reassoc arcp contract float %6 + + %3 = load float, ptr %c, align 4 + %fneg = fneg reassoc arcp contract float %3 + store float %fneg, ptr %c, align 4 + %fneg1 = fneg reassoc arcp contract float %0 + %4 = load float, ptr %c, align 4 + %5 = call reassoc arcp contract float @llvm.fmuladd.f32(float %fneg1, float %1, float %4) + %fneg2 = fneg reassoc arcp contract float %5 diff --git a/test/test_suite7/expressions/fmuladd_err.c3t b/test/test_suite7/expressions/fmuladd_err.c3t new file mode 100644 index 000000000..9f4569eac --- /dev/null +++ b/test/test_suite7/expressions/fmuladd_err.c3t @@ -0,0 +1,71 @@ +// #target: macos-x64 +// #opt: --fp-math=relaxed +module test; + +fn float easeElasticIn(float t, float b, float c, float d) @inline // Ease: Elastic In +{ + if (t == 0.0f) return b; + if ((t/=d) == 1.0f) return (b + c); + + float p = d*0.3f; + float a = c; + float s = p/4.0f; + float postFix = a*$$pow(2.0f, 10.0f*(t-=1.0f)); + + return (-(postFix*$$sin((t*d-s)*(2.0f*3.14f)/p )) + b); +} + +/* #expect: test.ll + + +define float @test.easeElasticIn(float %0, float %1, float %2, float %3) #0 { +entry: + %t = alloca float, align 4 + %p = alloca float, align 4 + %a = alloca float, align 4 + %s = alloca float, align 4 + %postFix = alloca float, align 4 + store float %0, ptr %t, align 4 + %4 = load float, ptr %t, align 4 + %eq = fcmp reassoc arcp contract oeq float %4, 0.000000e+00 + br i1 %eq, label %if.then, label %if.exit +if.then: ; preds = %entry + ret float %1 +if.exit: ; preds = %entry + %5 = load float, ptr %t, align 4 + %fdiv = fdiv reassoc arcp contract float %5, %3 + store float %fdiv, ptr %t, align 4 + %eq1 = fcmp reassoc arcp contract oeq float %fdiv, 1.000000e+00 + br i1 %eq1, label %if.then2, label %if.exit3 +if.then2: ; preds = %if.exit + %fadd = fadd reassoc arcp contract float %1, %2 + ret float %fadd +if.exit3: ; preds = %if.exit + %fmul = fmul reassoc arcp contract float %3, 0x3FD3333340000000 + store float %fmul, ptr %p, align 4 + store float %2, ptr %a, align 4 + %6 = load float, ptr %p, align 4 + %fdiv4 = fdiv reassoc arcp contract float %6, 4.000000e+00 + store float %fdiv4, ptr %s, align 4 + %7 = load float, ptr %a, align 4 + %8 = load float, ptr %t, align 4 + %fsub = fsub reassoc arcp contract float %8, 1.000000e+00 + store float %fsub, ptr %t, align 4 + %fmul5 = fmul reassoc arcp contract float 1.000000e+01, %fsub + %9 = call reassoc arcp contract float @llvm.pow.f32(float 2.000000e+00, float %fmul5) + %fmul6 = fmul reassoc arcp contract float %7, %9 + store float %fmul6, ptr %postFix, align 4 + %10 = load float, ptr %postFix, align 4 + %11 = load float, ptr %t, align 4 + %12 = load float, ptr %s, align 4 + %13 = fneg reassoc arcp contract float %12 + %14 = call reassoc arcp contract float @llvm.fmuladd.f32(float %11, float %3, float %13) + %fmul7 = fmul reassoc arcp contract float %14, 0x40191EB860000000 + %15 = load float, ptr %p, align 4 + %fdiv8 = fdiv reassoc arcp contract float %fmul7, %15 + %16 = call reassoc arcp contract float @llvm.sin.f32(float %fdiv8) + %17 = fneg reassoc arcp contract float %1 + %18 = call reassoc arcp contract float @llvm.fmuladd.f32(float %10, float %16, float %17) + %19 = fneg reassoc arcp contract float %18 + ret float %19 +} diff --git a/test/test_suite7/expressions/folding_ptr.c3t b/test/test_suite7/expressions/folding_ptr.c3t new file mode 100644 index 000000000..579b99b65 --- /dev/null +++ b/test/test_suite7/expressions/folding_ptr.c3t @@ -0,0 +1,32 @@ +// #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 + %i2nb = icmp eq ptr %0, null + br i1 %i2nb, 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 = load i32, ptr %1, align 4 + ret i32 %2 +} diff --git a/test/test_suite7/expressions/incdec.c3t b/test/test_suite7/expressions/incdec.c3t new file mode 100644 index 000000000..04fc6b6c9 --- /dev/null +++ b/test/test_suite7/expressions/incdec.c3t @@ -0,0 +1,45 @@ +// #target: macos-x64 +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 + %ptradd_any = getelementptr i8, ptr %1, i8 4 + store ptr %ptradd_any, ptr %foo, align 8 + %2 = load ptr, ptr %foo, align 8 + %ptradd_any1 = getelementptr i8, ptr %2, i8 -4 + store ptr %ptradd_any1, 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_suite7/expressions/incdec_overload.c3t b/test/test_suite7/expressions/incdec_overload.c3t new file mode 100644 index 000000000..fefc8c27b --- /dev/null +++ b/test/test_suite7/expressions/incdec_overload.c3t @@ -0,0 +1,179 @@ +// #target: macos-x64 +module test; +import std; + +def Abc = HashMap(); +Abc m; +fn void main() +{ + m[3] = 100; + int! x = m[3]--; + assert(m[3]!! == 99); + assert(x!! == 100); + x = ++m[3]; + assert(m[3]!! == 100); + assert(x!! == 100); +} + +/* #expect: test.ll + +entry: + %x = alloca i32, align 4 + %x.f = alloca i64, align 8 + %.anon = alloca i32, align 4 + %anon.f = alloca i64, align 8 + %retparam = alloca i32, align 4 + %.anon1 = alloca i32, align 4 + %anon.f2 = alloca i64, align 8 + %.anon18 = alloca i32, align 4 + %anon.f19 = alloca i64, align 8 + %retparam20 = alloca i32, align 4 + %.anon27 = alloca i32, align 4 + %anon.f28 = alloca i64, align 8 + %0 = call i8 @"std_collections_map$int$int$.HashMap.set"(ptr @test.m, i32 3, i32 100) + %1 = call i64 @"std_collections_map$int$int$.HashMap.get"(ptr %retparam, ptr @test.m, i32 3) + %not_err = icmp eq i64 %1, 0 + %2 = call i1 @llvm.expect.i1(i1 %not_err, i1 true) + br i1 %2, label %after_check, label %assign_optional + +assign_optional: ; preds = %entry + store i64 %1, ptr %anon.f, align 8 + br label %optional_assign_jump + +after_check: ; preds = %entry + %3 = load i32, ptr %retparam, align 4 + store i32 %3, ptr %.anon, align 4 + store i64 0, ptr %anon.f, align 8 + br label %after_assign + +optional_assign_jump: ; preds = %assign_optional + %reload_err = load i64, ptr %anon.f, align 8 + store i64 %reload_err, ptr %x.f, align 8 + br label %after_assign17 + +after_assign: ; preds = %after_check + %optval = load i64, ptr %anon.f, align 8 + %not_err3 = icmp eq i64 %optval, 0 + %4 = call i1 @llvm.expect.i1(i1 %not_err3, i1 true) + br i1 %4, label %after_check5, label %assign_optional4 + +assign_optional4: ; preds = %after_assign + store i64 %optval, ptr %anon.f2, align 8 + br label %optional_assign_jump6 + +after_check5: ; preds = %after_assign + %5 = load i32, ptr %.anon, align 4 + %sub = sub i32 %5, 1 + store i32 %sub, ptr %.anon, align 4 + store i32 %5, ptr %.anon1, align 4 + store i64 0, ptr %anon.f2, align 8 + br label %after_assign8 + +optional_assign_jump6: ; preds = %assign_optional4 + %reload_err7 = load i64, ptr %anon.f2, align 8 + store i64 %reload_err7, ptr %x.f, align 8 + br label %after_assign17 + +after_assign8: ; preds = %after_check5 + %optval9 = load i64, ptr %anon.f, align 8 + %not_err10 = icmp eq i64 %optval9, 0 + %6 = call i1 @llvm.expect.i1(i1 %not_err10, i1 true) + br i1 %6, label %after_check12, label %assign_optional11 + +assign_optional11: ; preds = %after_assign8 + store i64 %optval9, ptr %x.f, align 8 + br label %after_assign17 + +after_check12: ; preds = %after_assign8 + %7 = load i32, ptr %.anon, align 4 + %8 = call i8 @"std_collections_map$int$int$.HashMap.set"(ptr @test.m, i32 3, i32 %7) + %optval13 = load i64, ptr %anon.f2, align 8 + %not_err14 = icmp eq i64 %optval13, 0 + %9 = call i1 @llvm.expect.i1(i1 %not_err14, i1 true) + br i1 %9, label %after_check16, label %assign_optional15 + +assign_optional15: ; preds = %after_check12 + store i64 %optval13, ptr %x.f, align 8 + br label %after_assign17 + +after_check16: ; preds = %after_check12 + %10 = load i32, ptr %.anon1, align 4 + store i32 %10, ptr %x, align 4 + store i64 0, ptr %x.f, align 8 + br label %after_assign17 + +after_assign17: ; preds = %after_check16, %assign_optional15, %assign_optional11, %optional_assign_jump6, %optional_assign_jump + %11 = call i64 @"std_collections_map$int$int$.HashMap.get"(ptr %retparam20, ptr @test.m, i32 3) + %not_err21 = icmp eq i64 %11, 0 + %12 = call i1 @llvm.expect.i1(i1 %not_err21, i1 true) + br i1 %12, label %after_check23, label %assign_optional22 + +assign_optional22: ; preds = %after_assign17 + store i64 %11, ptr %anon.f19, align 8 + br label %optional_assign_jump24 + +after_check23: ; preds = %after_assign17 + %13 = load i32, ptr %retparam20, align 4 + store i32 %13, ptr %.anon18, align 4 + store i64 0, ptr %anon.f19, align 8 + br label %after_assign26 + +optional_assign_jump24: ; preds = %assign_optional22 + %reload_err25 = load i64, ptr %anon.f19, align 8 + store i64 %reload_err25, ptr %x.f, align 8 + br label %after_assign44 + +after_assign26: ; preds = %after_check23 + %optval29 = load i64, ptr %anon.f19, align 8 + %not_err30 = icmp eq i64 %optval29, 0 + %14 = call i1 @llvm.expect.i1(i1 %not_err30, i1 true) + br i1 %14, label %after_check32, label %assign_optional31 + +assign_optional31: ; preds = %after_assign26 + store i64 %optval29, ptr %anon.f28, align 8 + br label %optional_assign_jump33 + +after_check32: ; preds = %after_assign26 + %15 = load i32, ptr %.anon18, align 4 + %add = add i32 %15, 1 + store i32 %add, ptr %.anon18, align 4 + store i32 %add, ptr %.anon27, align 4 + store i64 0, ptr %anon.f28, align 8 + br label %after_assign35 + +optional_assign_jump33: ; preds = %assign_optional31 + %reload_err34 = load i64, ptr %anon.f28, align 8 + store i64 %reload_err34, ptr %x.f, align 8 + br label %after_assign44 + +after_assign35: ; preds = %after_check32 + %optval36 = load i64, ptr %anon.f19, align 8 + %not_err37 = icmp eq i64 %optval36, 0 + %16 = call i1 @llvm.expect.i1(i1 %not_err37, i1 true) + br i1 %16, label %after_check39, label %assign_optional38 + +assign_optional38: ; preds = %after_assign35 + store i64 %optval36, ptr %x.f, align 8 + br label %after_assign44 + +after_check39: ; preds = %after_assign35 + %17 = load i32, ptr %.anon18, align 4 + %18 = call i8 @"std_collections_map$int$int$.HashMap.set"(ptr @test.m, i32 3, i32 %17) + %optval40 = load i64, ptr %anon.f28, align 8 + %not_err41 = icmp eq i64 %optval40, 0 + %19 = call i1 @llvm.expect.i1(i1 %not_err41, i1 true) + br i1 %19, label %after_check43, label %assign_optional42 + +assign_optional42: ; preds = %after_check39 + store i64 %optval40, ptr %x.f, align 8 + br label %after_assign44 + +after_check43: ; preds = %after_check39 + %20 = load i32, ptr %.anon27, align 4 + store i32 %20, ptr %x, align 4 + store i64 0, ptr %x.f, align 8 + br label %after_assign44 + +after_assign44: ; preds = %after_check43, %assign_optional42, %assign_optional38, %optional_assign_jump33, %optional_assign_jump24 + ret void +} diff --git a/test/test_suite7/expressions/negate_int.c3 b/test/test_suite7/expressions/negate_int.c3 new file mode 100644 index 000000000..cf7c367d8 --- /dev/null +++ b/test/test_suite7/expressions/negate_int.c3 @@ -0,0 +1,41 @@ +fn void test1() +{ + short! a = 1; + @ok(-a); + short b = -a; // #error: 'short!' to 'short'. +} + +fn void test2() +{ + int! a = 1; + @ok(-a); + int b = -a; // #error: 'int!' to 'int' +} + +fn void test3() +{ + long! a = 1; + @ok(-a); + long b = -a; // #error: 'long!' to 'long' +} + +fn void test4() +{ + short! a = 1; + @ok(~a); + short b = ~a; // #error: 'short!' to 'short' +} + +fn void test5() +{ + int! a = 1; + @ok(~a); + int b = ~a; // #error: 'int!' to 'int' +} + +fn void test6() +{ + long! a = 1; + @ok(~a); + long b = ~a; // #error: 'long!' to 'long' +} diff --git a/test/test_suite7/expressions/negated_macro.c3t b/test/test_suite7/expressions/negated_macro.c3t new file mode 100644 index 000000000..3f7e8e8b3 --- /dev/null +++ b/test/test_suite7/expressions/negated_macro.c3t @@ -0,0 +1,37 @@ +// #target: macos-x64 +module test; +struct Foo +{ + int hello; + int bar; +} + +macro usz @offsetof($Type) { + $Type* x; + return x.bar; +} + + +fn void main(String[] argv) +{ + Foo x; + (Foo*)((void*)&x - @offsetof(Foo)); +} + + +/* #expect: test.ll + + +entry: + store i32 0, ptr %x, align 4 + %ptradd1 = getelementptr inbounds i8, ptr %x, i64 4 + store i32 0, ptr %ptradd1, align 4 + store ptr null, ptr %x2, align 8 + %2 = load ptr, ptr %x2, align 8 + %ptradd3 = getelementptr inbounds i8, ptr %2, i64 4 + %3 = load i32, ptr %ptradd3, align 4 + %sext = sext i32 %3 to i64 + %neg = sub i64 0, %sext + %ptradd_any = getelementptr i8, ptr %x, i64 %neg + ret void +} \ No newline at end of file diff --git a/test/test_suite7/expressions/no_valid_conversion_minus.c3 b/test/test_suite7/expressions/no_valid_conversion_minus.c3 new file mode 100644 index 000000000..68ad6a1c1 --- /dev/null +++ b/test/test_suite7/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_suite7/expressions/not_in_wrong_position.c3 b/test/test_suite7/expressions/not_in_wrong_position.c3 new file mode 100644 index 000000000..a0e68c976 --- /dev/null +++ b/test/test_suite7/expressions/not_in_wrong_position.c3 @@ -0,0 +1,4 @@ +fn void main() +{ + x = (a ~ a); // #error: can't appear +} diff --git a/test/test_suite7/expressions/opt_in_conv.c3 b/test/test_suite7/expressions/opt_in_conv.c3 new file mode 100644 index 000000000..3989ac32b --- /dev/null +++ b/test/test_suite7/expressions/opt_in_conv.c3 @@ -0,0 +1,9 @@ +module test; +import std; +fn void main() +{ + String s = "Hello"; + Char16* title = String.to_new_utf16(s).ptr; // #error: It is not possible to cast from + int! a; + float b = (float)a; // #error: It is not possible to cast from +} \ No newline at end of file diff --git a/test/test_suite7/expressions/optional_and_error.c3 b/test/test_suite7/expressions/optional_and_error.c3 new file mode 100644 index 000000000..aa9ce69ed --- /dev/null +++ b/test/test_suite7/expressions/optional_and_error.c3 @@ -0,0 +1,13 @@ +module testing; +import std::io; + +fn void main() +{ + bool ok; + if (ok && !foo()) io::printfn("nok"); // #error: The expression may not be an optional +} + +fn bool! foo() +{ + return false; +} \ No newline at end of file diff --git a/test/test_suite7/expressions/optional_ternary.c3t b/test/test_suite7/expressions/optional_ternary.c3t new file mode 100644 index 000000000..f29a7876b --- /dev/null +++ b/test/test_suite7/expressions/optional_ternary.c3t @@ -0,0 +1,415 @@ +// #target: macos-x64 + +module test; + +fault Foo +{ + X +} + +fn int! test(int i) +{ + return i ?: Foo.X?; +} + +fn int! test2(int i) +{ + return i ? Foo.X? : Foo.X?; +} + + +fn int! test3(int i) +{ + return i ? 2 : Foo.X?; +} + + +fn int! test4(int i) +{ + int! y = i; + return (y!) ?: Foo.X?; +} +fn int! test5(int i) +{ + int! y = i; + return (y!) ? Foo.X? : Foo.X?; +} + +fn int! test6(int i) +{ + int! y = i; + return (y!) ? 2 : Foo.X?; +} + +fn int! test7(int i) +{ + int! y = i; + return (y!) ? Foo.X? : 2; +} + +fn void main() +{ + test(1)!!; + test7(0)!!; + test6(1)!!; + int! i = test2(3); +} + +/* expect: test.ll +source_filename = "test" +target datalayout = "e-m:o-p270:32:32-p271:32 +target triple = "x86_64-apple + +%.fault = type { i64, %"char[]" } +%"char[]" = type { i8*, i64 } +%.introspect = type { i8, i64, i64, i64, [0 x i64] } + +@"test.Foo$X" = linkonce constant %.fault { i64 ptrtoint (%.introspect* @"$ct.test.Foo" to i64), %"char[]" { i8* getelementptr inbounds ([2 x i8], [2 x i8]* @.fault, i64 0, i64 0), i64 1 } }, align 8 +@.fault = internal constant [2 x i8] c"X\00", align 1 +@"$ct.test.Foo" = linkonce constant %.introspect { i8 9, i64 8, i64 0, i64 1, [0 x i64] zeroinitializer }, align 8 +@.zstr = internal constant [28 x i8] c"Runtime error force unwrap!\00", align 1 +@.zstr.1 = internal constant [20 x i8] c"optional_ternary.c3\00", align 1 +@.zstr.2 = internal constant [5 x i8] c"main\00", align 1 +@.zstr.3 = internal constant [28 x i8] c"Runtime error force unwrap!\00", align 1 +@.zstr.4 = internal constant [20 x i8] c"optional_ternary.c3\00", align 1 +@.zstr.5 = internal constant [5 x i8] c"main\00", align 1 +@.zstr.6 = internal constant [28 x i8] c"Runtime error force unwrap!\00", align 1 +@.zstr.7 = internal constant [20 x i8] c"optional_ternary.c3\00", align 1 +@.zstr.8 = internal constant [5 x i8] c"main\00", align 1 + + +define i64 @test.test(i32* %0, i32 %1) #0 { +entry: + %reterr = alloca i64, align 8 + %i2b = icmp ne i32 %1, 0 + br i1 %i2b, label %cond.phi, label %cond.rhs + +cond.rhs: ; preds = %entry + store i64 ptrtoint (%.fault* @"test.Foo$X" to i64), i64* %reterr, align 8 + br label %err_retblock + +cond.phi: ; preds = %entry + store i32 %1, i32* %0, align 4 + ret i64 0 + +err_retblock: ; preds = %cond.rhs + %2 = load i64, i64* %reterr, align 8 + ret i64 %2 +} + + +define i64 @test.test2(i32* %0, i32 %1) #0 { +entry: + %reterr = alloca i64, align 8 + %i2b = icmp ne i32 %1, 0 + br i1 %i2b, label %cond.lhs, label %cond.rhs + +cond.lhs: ; preds = %entry + store i64 ptrtoint (%.fault* @"test.Foo$X" to i64), i64* %reterr, align 8 + br label %err_retblock + +cond.rhs: ; preds = %entry + store i64 ptrtoint (%.fault* @"test.Foo$X" to i64), i64* %reterr, align 8 + br label %err_retblock + +cond.phi: ; No predecessors! + store i32 undef, i32* %0, align 4 + ret i64 0 + +err_retblock: ; preds = %cond.rhs, %cond.lhs + %2 = load i64, i64* %reterr, align 8 + ret i64 %2 +} + + +define i64 @test.test3(i32* %0, i32 %1) #0 { +entry: + %reterr = alloca i64, align 8 + %i2b = icmp ne i32 %1, 0 + br i1 %i2b, label %cond.lhs, label %cond.rhs + +cond.lhs: ; preds = %entry + br label %cond.phi + +cond.rhs: ; preds = %entry + store i64 ptrtoint (%.fault* @"test.Foo$X" to i64), i64* %reterr, align 8 + br label %err_retblock + +cond.phi: ; preds = %cond.lhs + store i32 2, i32* %0, align 4 + ret i64 0 + +err_retblock: ; preds = %cond.rhs + %2 = load i64, i64* %reterr, align 8 + ret i64 %2 +} + + +define i64 @test.test4(i32* %0, i32 %1) #0 { +entry: + %y = alloca i32, align 4 + %y.f = alloca i64, align 8 + %reterr = alloca i64, align 8 + %error_var = alloca i64, align 8 + store i32 %1, i32* %y, align 4 + store i64 0, i64* %y.f, align 8 + %optval = load i64, i64* %y.f, align 8 + %not_err = icmp eq i64 %optval, 0 + br i1 %not_err, label %after_check, label %assign_optional + +assign_optional: ; preds = %entry + store i64 %optval, i64* %error_var, align 8 + br label %guard_block + +after_check: ; preds = %entry + br label %noerr_block + +guard_block: ; preds = %assign_optional + %2 = load i64, i64* %error_var, align 8 + ret i64 %2 + +noerr_block: ; preds = %after_check + %3 = load i32, i32* %y, align 4 + %i2b = icmp ne i32 %3, 0 + br i1 %i2b, label %cond.phi, label %cond.rhs + +cond.rhs: ; preds = %noerr_block + store i64 ptrtoint (%.fault* @"test.Foo$X" to i64), i64* %reterr, align 8 + br label %err_retblock + +cond.phi: ; preds = %noerr_block + store i32 %3, i32* %0, align 4 + ret i64 0 + +err_retblock: ; preds = %cond.rhs + %4 = load i64, i64* %reterr, align 8 + ret i64 %4 +} + + +define i64 @test.test5(i32* %0, i32 %1) #0 { +entry: + %y = alloca i32, align 4 + %y.f = alloca i64, align 8 + %reterr = alloca i64, align 8 + %error_var = alloca i64, align 8 + store i32 %1, i32* %y, align 4 + store i64 0, i64* %y.f, align 8 + %optval = load i64, i64* %y.f, align 8 + %not_err = icmp eq i64 %optval, 0 + br i1 %not_err, label %after_check, label %assign_optional + +assign_optional: ; preds = %entry + store i64 %optval, i64* %error_var, align 8 + br label %guard_block + +after_check: ; preds = %entry + br label %noerr_block + +guard_block: ; preds = %assign_optional + %2 = load i64, i64* %error_var, align 8 + ret i64 %2 + +noerr_block: ; preds = %after_check + %3 = load i32, i32* %y, align 4 + %i2b = icmp ne i32 %3, 0 + br i1 %i2b, label %cond.lhs, label %cond.rhs + +cond.lhs: ; preds = %noerr_block + store i64 ptrtoint (%.fault* @"test.Foo$X" to i64), i64* %reterr, align 8 + br label %err_retblock + +cond.rhs: ; preds = %noerr_block + store i64 ptrtoint (%.fault* @"test.Foo$X" to i64), i64* %reterr, align 8 + br label %err_retblock + +cond.phi: ; No predecessors! + store i32 undef, i32* %0, align 4 + ret i64 0 + +err_retblock: ; preds = %cond.rhs, %cond.lhs + %4 = load i64, i64* %reterr, align 8 + ret i64 %4 +} + + +define i64 @test.test6(i32* %0, i32 %1) #0 { +entry: + %y = alloca i32, align 4 + %y.f = alloca i64, align 8 + %reterr = alloca i64, align 8 + %error_var = alloca i64, align 8 + store i32 %1, i32* %y, align 4 + store i64 0, i64* %y.f, align 8 + %optval = load i64, i64* %y.f, align 8 + %not_err = icmp eq i64 %optval, 0 + br i1 %not_err, label %after_check, label %assign_optional + +assign_optional: ; preds = %entry + store i64 %optval, i64* %error_var, align 8 + br label %guard_block + +after_check: ; preds = %entry + br label %noerr_block + +guard_block: ; preds = %assign_optional + %2 = load i64, i64* %error_var, align 8 + ret i64 %2 + +noerr_block: ; preds = %after_check + %3 = load i32, i32* %y, align 4 + %i2b = icmp ne i32 %3, 0 + br i1 %i2b, label %cond.lhs, label %cond.rhs + +cond.lhs: ; preds = %noerr_block + br label %cond.phi + +cond.rhs: ; preds = %noerr_block + store i64 ptrtoint (%.fault* @"test.Foo$X" to i64), i64* %reterr, align 8 + br label %err_retblock + +cond.phi: ; preds = %cond.lhs + store i32 2, i32* %0, align 4 + ret i64 0 + +err_retblock: ; preds = %cond.rhs + %4 = load i64, i64* %reterr, align 8 + ret i64 %4 +} + + +define i64 @test.test7(i32* %0, i32 %1) #0 { +entry: + %y = alloca i32, align 4 + %y.f = alloca i64, align 8 + %reterr = alloca i64, align 8 + %error_var = alloca i64, align 8 + store i32 %1, i32* %y, align 4 + store i64 0, i64* %y.f, align 8 + %optval = load i64, i64* %y.f, align 8 + %not_err = icmp eq i64 %optval, 0 + br i1 %not_err, label %after_check, label %assign_optional + +assign_optional: ; preds = %entry + store i64 %optval, i64* %error_var, align 8 + br label %guard_block + +after_check: ; preds = %entry + br label %noerr_block + +guard_block: ; preds = %assign_optional + %2 = load i64, i64* %error_var, align 8 + ret i64 %2 + +noerr_block: ; preds = %after_check + %3 = load i32, i32* %y, align 4 + %i2b = icmp ne i32 %3, 0 + br i1 %i2b, label %cond.lhs, label %cond.rhs + +cond.lhs: ; preds = %noerr_block + store i64 ptrtoint (%.fault* @"test.Foo$X" to i64), i64* %reterr, align 8 + br label %err_retblock + +cond.rhs: ; preds = %noerr_block + br label %cond.phi + +cond.phi: ; preds = %cond.rhs + store i32 2, i32* %0, align 4 + ret i64 0 + +err_retblock: ; preds = %cond.lhs + %4 = load i64, i64* %reterr, align 8 + ret i64 %4 +} + + +define void @test.main() #0 { +entry: + %error_var = alloca i64, align 8 + %retparam = alloca i32, align 4 + %error_var1 = alloca i64, align 8 + %retparam2 = alloca i32, align 4 + %error_var8 = alloca i64, align 8 + %retparam9 = alloca i32, align 4 + %i = alloca i32, align 4 + %i.f = alloca i64, align 8 + %retparam15 = alloca i32, align 4 + %0 = call i64 @test.test(i32* %retparam, i32 1) + %not_err = icmp eq i64 %0, 0 + br i1 %not_err, label %after_check, label %assign_optional + +assign_optional: ; preds = %entry + store i64 %0, i64* %error_var, align 8 + br label %panic_block + +after_check: ; preds = %entry + %1 = load i32, i32* %retparam, align 4 + br label %noerr_block + +panic_block: ; preds = %assign_optional + call void @std.core.builtin.panic(i8* getelementptr inbounds ([28 x i8], [28 x i8]* @.zstr, i64 0, i64 0), i8* getelementptr inbounds ([20 x i8], [20 x i8]* @.zstr.1, i64 0, i64 0), i8* getelementptr inbounds ([5 x i8], [5 x i8]* @.zstr.2, i64 0, i64 0), i32 51) + unreachable + +noerr_block: ; preds = %after_check + %2 = call i64 @test.test7(i32* %retparam2, i32 0) + %not_err3 = icmp eq i64 %2, 0 + br i1 %not_err3, label %after_check5, label %assign_optional4 + +assign_optional4: ; preds = %noerr_block + store i64 %2, i64* %error_var1, align 8 + br label %panic_block6 + +after_check5: ; preds = %noerr_block + %3 = load i32, i32* %retparam2, align 4 + br label %noerr_block7 + +panic_block6: ; preds = %assign_optional4 + call void @std.core.builtin.panic(i8* getelementptr inbounds ([28 x i8], [28 x i8]* @.zstr.3, i64 0, i64 0), i8* getelementptr inbounds ([20 x i8], [20 x i8]* @.zstr.4, i64 0, i64 0), i8* getelementptr inbounds ([5 x i8], [5 x i8]* @.zstr.5, i64 0, i64 0), i32 52) + unreachable + +noerr_block7: ; preds = %after_check5 + %4 = call i64 @test.test6(i32* %retparam9, i32 1) + %not_err10 = icmp eq i64 %4, 0 + br i1 %not_err10, label %after_check12, label %assign_optional11 + +assign_optional11: ; preds = %noerr_block7 + store i64 %4, i64* %error_var8, align 8 + br label %panic_block13 + +after_check12: ; preds = %noerr_block7 + %5 = load i32, i32* %retparam9, align 4 + br label %noerr_block14 + +panic_block13: ; preds = %assign_optional11 + call void @std.core.builtin.panic(i8* getelementptr inbounds ([28 x i8], [28 x i8]* @.zstr.6, i64 0, i64 0), i8* getelementptr inbounds ([20 x i8], [20 x i8]* @.zstr.7, i64 0, i64 0), i8* getelementptr inbounds ([5 x i8], [5 x i8]* @.zstr.8, i64 0, i64 0), i32 53) + unreachable + +noerr_block14: ; preds = %after_check12 + %6 = call i64 @test.test2(i32* %retparam15, i32 3) + %not_err16 = icmp eq i64 %6, 0 + br i1 %not_err16, label %after_check18, label %assign_optional17 + +assign_optional17: ; preds = %noerr_block14 + store i64 %6, i64* %i.f, align 8 + br label %after_assign + +after_check18: ; preds = %noerr_block14 + %7 = load i32, i32* %retparam15, align 4 + store i32 %7, i32* %i, align 4 + store i64 0, i64* %i.f, align 8 + br label %after_assign + +after_assign: ; preds = %after_check18, %assign_optional17 + ret void +} + + +define i32 @main(i32 %0, i8** %1) #0 { +entry: + call void @test.main() + ret i32 0 +} + +declare void @std.core.builtin.panic(i8*, i8*, i8*, i32) + +attributes #0 = { nounwind } \ No newline at end of file diff --git a/test/test_suite7/expressions/parsed_numbers.c3t b/test/test_suite7/expressions/parsed_numbers.c3t new file mode 100644 index 000000000..07d14a802 --- /dev/null +++ b/test/test_suite7/expressions/parsed_numbers.c3t @@ -0,0 +1,14 @@ +// #target: macos-x64 +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_suite7/expressions/plus_int.c3 b/test/test_suite7/expressions/plus_int.c3 new file mode 100644 index 000000000..7ebebcf46 --- /dev/null +++ b/test/test_suite7/expressions/plus_int.c3 @@ -0,0 +1,27 @@ +fn void test1() +{ + short! a = 1; + @ok(+a); + short b = +a; // #error: 'short!' to 'short'. +} + +fn void test2() +{ + int! a = 1; + @ok(+a); + int b = +a; // #error: 'int!' to 'int' +} + +fn void test3() +{ + long! a = 1; + @ok(+a); + long b = +a; // #error: 'long!' to 'long' +} + + +fn void test4() +{ + int a = 1; + +a = 3; // #error: An assignable expression +} \ No newline at end of file diff --git a/test/test_suite7/expressions/pointer_access.c3t b/test/test_suite7/expressions/pointer_access.c3t new file mode 100644 index 000000000..27f3746cb --- /dev/null +++ b/test/test_suite7/expressions/pointer_access.c3t @@ -0,0 +1,98 @@ +// #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 } + +@"$ct.pointer_access.c" = linkonce global %.introspect { i8 10, i64 0, ptr null, i64 40, i64 0, i64 5, [0 x i64] zeroinitializer }, align 8 +@"$ct.pointer_access.$anon" = linkonce global %.introspect { i8 10, i64 0, ptr null, i64 8, i64 0, i64 2, [0 x i64] zeroinitializer }, align 8 +@"$ct.pointer_access.$anon.4" = linkonce global %.introspect { i8 11, i64 0, ptr null, i64 8, i64 0, i64 2, [0 x i64] zeroinitializer }, align 8 +@"$ct.pointer_access.ExtraSimple" = linkonce global %.introspect { i8 10, i64 0, ptr null, i64 72, i64 0, i64 6, [0 x i64] zeroinitializer }, 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 + store i32 0, ptr %a, align 8 + %ptradd = getelementptr inbounds i8, ptr %a, i64 4 + store i32 0, ptr %ptradd, align 4 + %ptradd1 = getelementptr inbounds i8, ptr %a, i64 8 + store double 0.000000e+00, ptr %ptradd1, align 8 + %ptradd2 = getelementptr inbounds i8, ptr %ptradd1, i64 8 + store double 0.000000e+00, ptr %ptradd2, align 8 + %ptradd3 = getelementptr inbounds i8, ptr %ptradd1, i64 16 + store double 0.000000e+00, ptr %ptradd3, align 8 + %ptradd4 = getelementptr inbounds i8, ptr %ptradd1, i64 24 + store double 0.000000e+00, ptr %ptradd4, align 8 + %ptradd5 = getelementptr inbounds i8, ptr %ptradd1, i64 32 + store double 3.300000e+00, ptr %ptradd5, align 8 + %ptradd6 = getelementptr inbounds i8, ptr %a, i64 48 + store i32 0, ptr %ptradd6, align 8 + %ptradd7 = getelementptr inbounds i8, ptr %ptradd6, i64 4 + store i32 0, ptr %ptradd7, align 4 + %ptradd8 = getelementptr inbounds i8, ptr %a, i64 56 + call void @llvm.memset.p0.i64(ptr align 8 %ptradd8, i8 0, i64 8, i1 false) + %ptradd9 = getelementptr inbounds i8, ptr %a, i64 64 + store i32 0, ptr %ptradd9, align 8 + %ptradd10 = getelementptr inbounds i8, ptr %a, i64 8 + %ptradd11 = getelementptr inbounds i8, ptr %ptradd10, i64 32 + store double 3.400000e+00, ptr %ptradd11, align 8 + %ptradd12 = getelementptr inbounds i8, ptr %a, i64 8 + %ptradd13 = getelementptr inbounds i8, ptr %a, i64 8 + %ptradd14 = getelementptr inbounds i8, ptr %ptradd13, i64 24 + %ptradd15 = getelementptr inbounds i8, ptr %a, i64 8 + %ptradd16 = getelementptr inbounds i8, ptr %ptradd15, i64 32 + %ptradd17 = getelementptr inbounds i8, ptr %a, i64 64 + %ptradd18 = getelementptr inbounds i8, ptr %a, i64 56 + %ptradd19 = getelementptr inbounds i8, ptr %a, i64 48 + %ptradd20 = getelementptr inbounds i8, ptr %a, i64 48 + %ptradd21 = getelementptr inbounds i8, ptr %ptradd20, i64 4 + %0 = load i32, ptr %a, align 8 + %1 = load double, ptr %ptradd12, align 8 + %2 = load double, ptr %ptradd14, align 8 + %3 = load double, ptr %ptradd16, align 8 + %4 = load i32, ptr %ptradd17, align 8 + %5 = load double, ptr %ptradd18, align 8 + %6 = load i32, ptr %ptradd19, align 8 + %7 = load i32, ptr %ptradd21, align 4 + call void (ptr, ...) @printf(ptr @.str, i32 %0, double %1, double %2, double %3, i32 %4, double %5, i32 %6, i32 %7) + ret void +} diff --git a/test/test_suite7/expressions/pointer_arith.c3 b/test/test_suite7/expressions/pointer_arith.c3 new file mode 100644 index 000000000..2338aa493 --- /dev/null +++ b/test/test_suite7/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_suite7/expressions/pointer_conv_error.c3 b/test/test_suite7/expressions/pointer_conv_error.c3 new file mode 100644 index 000000000..c742f8dde --- /dev/null +++ b/test/test_suite7/expressions/pointer_conv_error.c3 @@ -0,0 +1,18 @@ +fn void test1() +{ + int myInt = 1; + int* p1 = myInt; // #error: integer smaller +} + +fn void test2() +{ + uint myUInt = 1; + int* p2 = myUInt; // #error: integer smaller +} + +fn void test3() +{ + uint myUInt = 1; + int* p2 = (int*)(myUInt); // #error: integer smaller +} + diff --git a/test/test_suite7/expressions/pointer_to_bool.c3 b/test/test_suite7/expressions/pointer_to_bool.c3 new file mode 100644 index 000000000..fcdf1292d --- /dev/null +++ b/test/test_suite7/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_suite7/expressions/rvalues.c3 b/test/test_suite7/expressions/rvalues.c3 new file mode 100644 index 000000000..fd4d9c237 --- /dev/null +++ b/test/test_suite7/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_suite7/expressions/simple_float_sub_neg.c3t b/test/test_suite7/expressions/simple_float_sub_neg.c3t new file mode 100644 index 000000000..42dd58228 --- /dev/null +++ b/test/test_suite7/expressions/simple_float_sub_neg.c3t @@ -0,0 +1,18 @@ +// #target: macos-x64 +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_suite7/expressions/strings.c3t b/test/test_suite7/expressions/strings.c3t new file mode 100644 index 000000000..5443c01bd --- /dev/null +++ b/test/test_suite7/expressions/strings.c3t @@ -0,0 +1,11 @@ +// #target: macos-x64 +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_suite7/expressions/take_address.c3t b/test/test_suite7/expressions/take_address.c3t new file mode 100644 index 000000000..920a9c6b5 --- /dev/null +++ b/test/test_suite7/expressions/take_address.c3t @@ -0,0 +1,30 @@ +// #target: macos-x64 +module testing; +import blurb; +import foo; + +def hello_int = foo::hello(); + +fn void main() +{ + blurb::test(&hello_int); +} + +module foo(); + +fn void hello() {} + +module blurb; + +def Foo = fn void(); +def Bar = fn void(); + +fn void test(Foo x) {} + +/* #expect: testing.ll + +define void @testing.main() #0 { +entry: + call void @blurb.test(ptr @"foo$int$.hello") + ret void +} diff --git a/test/test_suite7/expressions/ternary_bool.c3t b/test/test_suite7/expressions/ternary_bool.c3t new file mode 100644 index 000000000..568f46535 --- /dev/null +++ b/test/test_suite7/expressions/ternary_bool.c3t @@ -0,0 +1,103 @@ +// #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 1 + %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 1 + %5 = trunc i8 %4 to i1 + br label %cond.phi +cond.rhs: ; preds = %entry + %6 = load ptr, ptr %c, align 8 + %7 = load i8, ptr %6, align 1 + %8 = trunc i8 %7 to i1 + br label %cond.phi +cond.phi: ; preds = %cond.rhs, %cond.lhs + %val = phi i1 [ %5, %cond.lhs ], [ %8, %cond.rhs ] + br i1 %val, 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 + %9 = load i8, ptr %b, align 1 + %10 = trunc i8 %9 to i1 + br i1 %10, label %cond.lhs1, label %cond.rhs2 +cond.lhs1: ; preds = %if.exit + %11 = load i8, ptr %b, align 1 + %12 = trunc i8 %11 to i1 + br label %cond.phi3 +cond.rhs2: ; preds = %if.exit + %13 = load i8, ptr %b, align 1 + %14 = trunc i8 %13 to i1 + br label %cond.phi3 +cond.phi3: ; preds = %cond.rhs2, %cond.lhs1 + %val4 = phi i1 [ %12, %cond.lhs1 ], [ %14, %cond.rhs2 ] + br i1 %val4, 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 + %15 = load ptr, ptr %c, align 8 + %16 = load i8, ptr %15, align 1 + %17 = trunc i8 %16 to i1 + br i1 %17, label %cond.lhs7, label %cond.rhs8 +cond.lhs7: ; preds = %if.exit6 + br label %cond.phi9 +cond.rhs8: ; preds = %if.exit6 + %18 = load ptr, ptr %c, align 8 + %19 = load i8, ptr %18, align 1 + %20 = trunc i8 %19 to i1 + br label %cond.phi9 +cond.phi9: ; preds = %cond.rhs8, %cond.lhs7 + %val10 = phi i1 [ %17, %cond.lhs7 ], [ %20, %cond.rhs8 ] + br i1 %val10, label %if.then11, label %if.exit12 +if.then11: ; preds = %cond.phi9 + call void (ptr, ...) @printf(ptr @.str.2) + br label %if.exit12 +if.exit12: ; preds = %if.then11, %cond.phi9 + %21 = load i8, ptr %b, align 1 + %22 = trunc i8 %21 to i1 + br i1 %22, label %cond.lhs13, label %cond.rhs14 + +cond.lhs13: ; preds = %if.exit12 + br label %cond.phi15 + +cond.rhs14: ; preds = %if.exit12 + %23 = load i8, ptr %b, align 1 + %24 = trunc i8 %23 to i1 + br label %cond.phi15 + +cond.phi15: ; preds = %cond.rhs14, %cond.lhs13 + %val16 = phi i1 [ %22, %cond.lhs13 ], [ %24, %cond.rhs14 ] + br i1 %val16, label %if.then17, label %if.exit18 + +if.then17: ; preds = %cond.phi15 + call void (ptr, ...) @printf(ptr @.str.3) + br label %if.exit18 + +if.exit18: ; preds = %if.then17, %cond.phi15 + ret void +} diff --git a/test/test_suite7/expressions/ternary_infer.c3t b/test/test_suite7/expressions/ternary_infer.c3t new file mode 100644 index 000000000..f29b7dde6 --- /dev/null +++ b/test/test_suite7/expressions/ternary_infer.c3t @@ -0,0 +1,23 @@ +// #target: macos-x64 +module test; +fn int[<2>] foo(int x) +{ + return x > 0 ? {0, 0} : {255, 255}; +} + + +fn int main() +{ + return 0; +} +/* #expect: test.ll + +define double @test.foo(i32 %0) #0 { +entry: + %taddr = alloca <2 x i32>, align 8 + %gt = icmp sgt i32 %0, 0 + %ternary = select i1 %gt, <2 x i32> zeroinitializer, <2 x i32> + store <2 x i32> %ternary, ptr %taddr, align 8 + %1 = load double, ptr %taddr, align 8 + ret double %1 +} \ No newline at end of file diff --git a/test/test_suite7/expressions/ternary_no_ident.c3 b/test/test_suite7/expressions/ternary_no_ident.c3 new file mode 100644 index 000000000..dbd2e7457 --- /dev/null +++ b/test/test_suite7/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_suite7/expressions/ternary_void.c3t b/test/test_suite7/expressions/ternary_void.c3t new file mode 100644 index 000000000..91f1d60f8 --- /dev/null +++ b/test/test_suite7/expressions/ternary_void.c3t @@ -0,0 +1,31 @@ +// #target: macos-x64 +module test; + +fn void foo() { } +fn void bar() {} + +fn void main() +{ + bool b = true; + true ? foo() : bar(); // ok + b ? foo() : bar(); // segfault +} + +/* #expect: test.ll + +entry: + %b = alloca i8, align 1 + store i8 1, ptr %b, align 1 + call void @test.foo() + %0 = load i8, ptr %b, align 1 + %1 = trunc i8 %0 to i1 + br i1 %1, label %cond.lhs, label %cond.rhs +cond.lhs: ; preds = %entry + call void @test.foo() + br label %cond.phi +cond.rhs: ; preds = %entry + call void @test.bar() + br label %cond.phi +cond.phi: ; preds = %cond.rhs, %cond.lhs + ret void +} diff --git a/test/test_suite7/expressions/test_ct_param_bug.c3 b/test/test_suite7/expressions/test_ct_param_bug.c3 new file mode 100644 index 000000000..c8c19cf25 --- /dev/null +++ b/test/test_suite7/expressions/test_ct_param_bug.c3 @@ -0,0 +1,7 @@ +module test; +macro @foo($aaa) {} +fn int main(String[] args) +{ + @foo(int); // #error: must be followed by either + return 0; +} \ No newline at end of file diff --git a/test/test_suite7/expressions/type_support.c3t b/test/test_suite7/expressions/type_support.c3t new file mode 100644 index 000000000..3c7e130c4 --- /dev/null +++ b/test/test_suite7/expressions/type_support.c3t @@ -0,0 +1,76 @@ +// #target: macos-x64 + +module test; +import std::io; + +macro print_type_info(...) +{ + $for (var $i = 0; $i < $vacount; $i++) + io::printfn("type: %s", $vatype[$i].nameof); + io::printfn("%s.sizeof = %d", $vatype[$i].nameof, $vatype[$i].sizeof); + io::printfn("%s.min = %s", $vatype[$i].nameof, $vatype[$i].min); + io::printfn("%s.max = %s\n", $vatype[$i].nameof, $vatype[$i].max); + $endfor; +} + +fn void main() +{ + io::printfn("Unsigned integers:"); + print_type_info(char, ushort, uint, ulong, uptr, usz, usz); + io::printfn("Signed integers:"); + print_type_info(ichar, short, int, long, iptr, isz, isz); + io::printfn("Floats:"); + print_type_info(float, double); +} + +/* #expect: test.ll + + i64 0 + i64 1 + i8 0 + i8 -1 + i16 0 + i16 -1 + i64 4 + i64 2 + i32 0 + i32 -1 + i64 8 + i64 0 + i64 -1 + i64 8 + i64 0 + i64 -1 + i64 8 + i64 0 + i64 -1 + i64 8 + i64 0 + i64 -1 + i64 1 + i8 -128 + i8 127 + i64 2 + i16 -32768 + i16 32767 + i64 4 + i32 -2147483648 + i32 2147483647 + i64 8 + i64 -9223372036854775808 + i64 9223372036854775807 + i64 8 + i64 -9223372036854775808 + i64 9223372036854775807 + i64 8 + i64 -9223372036854775808 + i64 9223372036854775807 + i64 8 + i64 -9223372036854775808 + i64 9223372036854775807 + i64 4 + float 0xC7EFFFFFE0000000 + float 0x47EFFFFFE0000000 + i64 8 + double 0xFFEFFFFFFFFFFFFF + double 0x7FEFFFFFFFFFFFFF \ No newline at end of file diff --git a/test/test_suite7/expressions/underscore_errors.c3 b/test/test_suite7/expressions/underscore_errors.c3 new file mode 100644 index 000000000..e9038815c --- /dev/null +++ b/test/test_suite7/expressions/underscore_errors.c3 @@ -0,0 +1,15 @@ +fn void main() +{ + int a = 1___0; // #error: consecutive + int a = 1_0; + float b = 1_0.3__4; // #error: consecutive + float b = 1_0.3_4; + int a2 = 0x1___0; // #error: consecutive + int a2 = 0x1_0; + float b2 = 0x1_0.3__4; // #error: consecutive + float b2 = 0x1_0.3_4; + int a3 = 0b1___0; // #error: consecutive + int a3 = 0b1_0; + int a3 = 0o1___0; // #error: consecutive + int a3 = 0o1_0; +} \ No newline at end of file diff --git a/test/test_suite7/expressions/unsafe_comparisons.c3 b/test/test_suite7/expressions/unsafe_comparisons.c3 new file mode 100644 index 000000000..8f4bad071 --- /dev/null +++ b/test/test_suite7/expressions/unsafe_comparisons.c3 @@ -0,0 +1,51 @@ +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 test22(uint x) +{ + return x >= 0; // #error: 'unsigned expression >= 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 test55(uint x) +{ + return 0 <= x; // #error: '0 <= unsigned expression' +} + +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_suite7/expressions/void_arg.c3 b/test/test_suite7/expressions/void_arg.c3 new file mode 100644 index 000000000..b6f7b474f --- /dev/null +++ b/test/test_suite7/expressions/void_arg.c3 @@ -0,0 +1,33 @@ +import std::io; + +fn void test1() +{ + foo(test1()); // #error: A 'void' value cannot be passed as a parameter +} + +fn void test2() +{ + bar(test2()); // #error: You cannot cast 'void' to 'int' +} + +fn void test3() +{ + baz(test3()); // #error: A value of type 'void' cannot be passed as a raw variadic argumen +} + +fn void test4() +{ + abc(test4()); +} + +macro void abc(...) {} + +extern fn void baz(...); + +macro void foo(x) +{ +} + +fn void bar(int x) +{} + diff --git a/test/test_suite7/floats/convert_float.c3t b/test/test_suite7/floats/convert_float.c3t new file mode 100644 index 000000000..cb06a173e --- /dev/null +++ b/test/test_suite7/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_suite7/floats/explicit_float_truncation_needed.c3 b/test/test_suite7/floats/explicit_float_truncation_needed.c3 new file mode 100644 index 000000000..72774ec8c --- /dev/null +++ b/test/test_suite7/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_suite7/floats/float_exceeding_size.c3 b/test/test_suite7/floats/float_exceeding_size.c3 new file mode 100644 index 000000000..88867f28f --- /dev/null +++ b/test/test_suite7/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_suite7/floats/inf_nan.c3t b/test/test_suite7/floats/inf_nan.c3t new file mode 100644 index 000000000..a0c712bc7 --- /dev/null +++ b/test/test_suite7/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_suite7/floats/mod.c3t b/test/test_suite7/floats/mod.c3t new file mode 100644 index 000000000..54762f05a --- /dev/null +++ b/test/test_suite7/floats/mod.c3t @@ -0,0 +1,14 @@ +// #target: macos-x64 + +fn double x(double a, double b) +{ + return a % b; +} + +/* #expect: mod.ll + +define double @mod.x(double %0, double %1) #0 { +entry: + %fmod = frem double %0, %1 + ret double %fmod +} \ No newline at end of file diff --git a/test/test_suite7/from_docs/examples_defer.c3t b/test/test_suite7/from_docs/examples_defer.c3t new file mode 100644 index 000000000..d634771af --- /dev/null +++ b/test/test_suite7/from_docs/examples_defer.c3t @@ -0,0 +1,253 @@ +// #target: macos-x64 +module defer1; +import std::io; + +fn void test(int x) +{ + defer io::printn(); + 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: + %retparam = alloca i64, align 8 + %len = alloca i64, align 8 + %error_var = alloca i64, align 8 + %retparam2 = alloca i64, align 8 + %error_var3 = alloca i64, align 8 + %error_var9 = alloca i64, align 8 + %retparam17 = alloca i64, align 8 + %retparam20 = alloca i64, align 8 + %len23 = alloca i64, align 8 + %error_var24 = alloca i64, align 8 + %retparam26 = alloca i64, align 8 + %error_var32 = alloca i64, align 8 + %error_var38 = alloca i64, align 8 + %retparam47 = alloca i64, align 8 + %retparam50 = alloca i64, align 8 + %retparam53 = alloca i64, align 8 + %len56 = alloca i64, align 8 + %error_var57 = alloca i64, align 8 + %retparam59 = alloca i64, align 8 + %error_var65 = alloca i64, align 8 + %error_var71 = alloca i64, align 8 + %eq = icmp eq i32 %0, 1 + br i1 %eq, label %if.then, label %if.exit + +if.then: ; preds = %entry + %1 = call ptr @std.io.stdout() + %2 = call i64 @std.io.File.write(ptr %retparam, ptr %1, ptr @.str, i64 1) + %3 = call ptr @std.io.stdout() + %4 = call i64 @std.io.File.write(ptr %retparam2, ptr %3, ptr null, i64 0) + %not_err = icmp eq i64 %4, 0 + %5 = call i1 @llvm.expect.i1(i1 %not_err, i1 true) + br i1 %5, label %after_check, label %assign_optional + +assign_optional: ; preds = %if.then + store i64 %4, ptr %error_var, align 8 + br label %guard_block + +after_check: ; preds = %if.then + br label %noerr_block + +guard_block: ; preds = %assign_optional + br label %voiderr + +noerr_block: ; preds = %after_check + %6 = load i64, ptr %retparam2, align 8 + store i64 %6, ptr %len, align 8 + %7 = call i64 @std.io.File.write_byte(ptr %3, i8 zeroext 10) + %not_err4 = icmp eq i64 %7, 0 + %8 = call i1 @llvm.expect.i1(i1 %not_err4, i1 true) + br i1 %8, label %after_check6, label %assign_optional5 + +assign_optional5: ; preds = %noerr_block + store i64 %7, ptr %error_var3, align 8 + br label %guard_block7 + +after_check6: ; preds = %noerr_block + br label %noerr_block8 + +guard_block7: ; preds = %assign_optional5 + br label %voiderr + +noerr_block8: ; preds = %after_check6 + %9 = call i64 @std.io.File.flush(ptr %3) + %not_err10 = icmp eq i64 %9, 0 + %10 = call i1 @llvm.expect.i1(i1 %not_err10, i1 true) + br i1 %10, label %after_check12, label %assign_optional11 + +assign_optional11: ; preds = %noerr_block8 + store i64 %9, ptr %error_var9, align 8 + br label %guard_block13 + +after_check12: ; preds = %noerr_block8 + br label %noerr_block14 + +guard_block13: ; preds = %assign_optional11 + br label %voiderr + +noerr_block14: ; preds = %after_check12 + %11 = load i64, ptr %len, align 8 + %add = add i64 %11, 1 + br label %voiderr + +voiderr: ; preds = %noerr_block14, %guard_block13, %guard_block7, %guard_block + ret void + +if.exit: ; preds = %entry + %eq15 = icmp eq i32 %0, 0 + br i1 %eq15, label %if.then16, label %if.exit46 + +if.then16: ; preds = %if.exit + %12 = call ptr @std.io.stdout() + %13 = call i64 @std.io.File.write(ptr %retparam17, ptr %12, ptr @.str.1, i64 1) + %14 = call ptr @std.io.stdout() + %15 = call i64 @std.io.File.write(ptr %retparam20, ptr %14, ptr @.str.2, i64 1) + %16 = call ptr @std.io.stdout() + %17 = call i64 @std.io.File.write(ptr %retparam26, ptr %16, ptr null, i64 0) + %not_err27 = icmp eq i64 %17, 0 + %18 = call i1 @llvm.expect.i1(i1 %not_err27, i1 true) + br i1 %18, label %after_check29, label %assign_optional28 + +assign_optional28: ; preds = %if.then16 + store i64 %17, ptr %error_var24, align 8 + br label %guard_block30 + +after_check29: ; preds = %if.then16 + br label %noerr_block31 + +guard_block30: ; preds = %assign_optional28 + br label %voiderr45 + +noerr_block31: ; preds = %after_check29 + %19 = load i64, ptr %retparam26, align 8 + store i64 %19, ptr %len23, align 8 + %20 = call i64 @std.io.File.write_byte(ptr %16, i8 zeroext 10) + %not_err33 = icmp eq i64 %20, 0 + %21 = call i1 @llvm.expect.i1(i1 %not_err33, i1 true) + br i1 %21, label %after_check35, label %assign_optional34 + +assign_optional34: ; preds = %noerr_block31 + store i64 %20, ptr %error_var32, align 8 + br label %guard_block36 + +after_check35: ; preds = %noerr_block31 + br label %noerr_block37 + +guard_block36: ; preds = %assign_optional34 + br label %voiderr45 + +noerr_block37: ; preds = %after_check35 + %22 = call i64 @std.io.File.flush(ptr %16) + %not_err39 = icmp eq i64 %22, 0 + %23 = call i1 @llvm.expect.i1(i1 %not_err39, i1 true) + br i1 %23, label %after_check41, label %assign_optional40 + +assign_optional40: ; preds = %noerr_block37 + store i64 %22, ptr %error_var38, align 8 + br label %guard_block42 + +after_check41: ; preds = %noerr_block37 + br label %noerr_block43 + +guard_block42: ; preds = %assign_optional40 + br label %voiderr45 + +noerr_block43: ; preds = %after_check41 + %24 = load i64, ptr %len23, align 8 + %add44 = add i64 %24, 1 + br label %voiderr45 + +voiderr45: ; preds = %noerr_block43, %guard_block42, %guard_block36, %guard_block30 + ret void + +if.exit46: ; preds = %if.exit + %25 = call ptr @std.io.stdout() + %26 = call i64 @std.io.File.write(ptr %retparam47, ptr %25, ptr @.str.3, i64 1) + %27 = call ptr @std.io.stdout() + %28 = call i64 @std.io.File.write(ptr %retparam50, ptr %27, ptr @.str.4, i64 1) + %29 = call ptr @std.io.stdout() + %30 = call i64 @std.io.File.write(ptr %retparam53, ptr %29, ptr @.str.5, i64 1) + %31 = call ptr @std.io.stdout() + %32 = call i64 @std.io.File.write(ptr %retparam59, ptr %31, ptr null, i64 0) + %not_err60 = icmp eq i64 %32, 0 + %33 = call i1 @llvm.expect.i1(i1 %not_err60, i1 true) + br i1 %33, label %after_check62, label %assign_optional61 + +assign_optional61: ; preds = %if.exit46 + store i64 %32, ptr %error_var57, align 8 + br label %guard_block63 + +after_check62: ; preds = %if.exit46 + br label %noerr_block64 + +guard_block63: ; preds = %assign_optional61 + br label %voiderr78 + +noerr_block64: ; preds = %after_check62 + %34 = load i64, ptr %retparam59, align 8 + store i64 %34, ptr %len56, align 8 + %35 = call i64 @std.io.File.write_byte(ptr %31, i8 zeroext 10) + %not_err66 = icmp eq i64 %35, 0 + %36 = call i1 @llvm.expect.i1(i1 %not_err66, i1 true) + br i1 %36, label %after_check68, label %assign_optional67 + +assign_optional67: ; preds = %noerr_block64 + store i64 %35, ptr %error_var65, align 8 + br label %guard_block69 + +after_check68: ; preds = %noerr_block64 + br label %noerr_block70 + +guard_block69: ; preds = %assign_optional67 + br label %voiderr78 + +noerr_block70: ; preds = %after_check68 + %37 = call i64 @std.io.File.flush(ptr %31) + %not_err72 = icmp eq i64 %37, 0 + %38 = call i1 @llvm.expect.i1(i1 %not_err72, i1 true) + br i1 %38, label %after_check74, label %assign_optional73 + +assign_optional73: ; preds = %noerr_block70 + store i64 %37, ptr %error_var71, align 8 + br label %guard_block75 + +after_check74: ; preds = %noerr_block70 + br label %noerr_block76 + +guard_block75: ; preds = %assign_optional73 + br label %voiderr78 + +noerr_block76: ; preds = %after_check74 + %39 = load i64, ptr %len56, align 8 + %add77 = add i64 %39, 1 + br label %voiderr78 + +voiderr78: ; preds = %noerr_block76, %guard_block75, %guard_block69, %guard_block63 + ret void +} + + +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_suite7/from_docs/examples_forswitch.c3t b/test/test_suite7/from_docs/examples_forswitch.c3t new file mode 100644 index 000000000..24ce59f90 --- /dev/null +++ b/test/test_suite7/from_docs/examples_forswitch.c3t @@ -0,0 +1,714 @@ +// #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::printn("Not high"); + // Implicit break. + case HIGH: + io::printn("High"); + } + + // This also works + switch (h) + { + case LOW: + case MEDIUM: + io::printn("Not high"); + // Implicit break. + case Height.HIGH: + io::printn("High"); + } + + // Completely empty cases are not allowed. + switch (h) + { + case LOW: + break; // Explicit break required, since switches can't be empty. + case MEDIUM: + io::printn("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::printn("A"); + nextcase; + case MEDIUM: + int a = 2; + io::printn("B"); + nextcase; + case HIGH: + // a is not defined here + io::printn("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 + %4 = load ptr, ptr @std.core.builtin.panic, align 8 + call void %4(ptr @.panic_msg, i64 19, ptr @.file, i64 21, ptr @.func, i64 11, i32 14) + unreachable +} + + +define void @examples.demo_enum(i32 %0) #0 { +entry: + %switch = alloca i32, align 4 + %len = alloca i64, align 8 + %error_var = alloca i64, align 8 + %retparam = alloca i64, align 8 + %error_var2 = alloca i64, align 8 + %error_var8 = alloca i64, align 8 + %len15 = alloca i64, align 8 + %error_var16 = alloca i64, align 8 + %retparam18 = alloca i64, align 8 + %error_var24 = alloca i64, align 8 + %error_var30 = alloca i64, align 8 + %switch38 = alloca i32, align 4 + %len41 = alloca i64, align 8 + %error_var42 = alloca i64, align 8 + %retparam44 = alloca i64, align 8 + %error_var50 = alloca i64, align 8 + %error_var56 = alloca i64, align 8 + %len65 = alloca i64, align 8 + %error_var66 = alloca i64, align 8 + %retparam68 = alloca i64, align 8 + %error_var74 = alloca i64, align 8 + %error_var80 = alloca i64, align 8 + %switch89 = alloca i32, align 4 + %len93 = alloca i64, align 8 + %error_var94 = alloca i64, align 8 + %retparam96 = alloca i64, align 8 + %error_var102 = alloca i64, align 8 + %error_var108 = alloca i64, align 8 + %switch118 = alloca i32, align 4 + %switch122 = alloca i32, align 4 + %a = alloca i32, align 4 + %len125 = alloca i64, align 8 + %error_var126 = alloca i64, align 8 + %retparam128 = alloca i64, align 8 + %error_var134 = alloca i64, align 8 + %error_var140 = alloca i64, align 8 + %a149 = alloca i32, align 4 + %len150 = alloca i64, align 8 + %error_var151 = alloca i64, align 8 + %retparam153 = alloca i64, align 8 + %error_var159 = alloca i64, align 8 + %error_var165 = alloca i64, align 8 + %len174 = alloca i64, align 8 + %error_var175 = alloca i64, align 8 + %retparam177 = alloca i64, align 8 + %error_var183 = alloca i64, align 8 + %error_var189 = alloca i64, align 8 + 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.case14 + ] + +switch.case: ; preds = %switch.entry, %switch.entry + %2 = call ptr @std.io.stdout() + %3 = call i64 @std.io.File.write(ptr %retparam, ptr %2, ptr @.str.1, i64 8) + %not_err = icmp eq i64 %3, 0 + %4 = call i1 @llvm.expect.i1(i1 %not_err, i1 true) + br i1 %4, label %after_check, label %assign_optional + +assign_optional: ; preds = %switch.case + store i64 %3, ptr %error_var, align 8 + br label %guard_block + +after_check: ; preds = %switch.case + br label %noerr_block + +guard_block: ; preds = %assign_optional + br label %voiderr + +noerr_block: ; preds = %after_check + %5 = load i64, ptr %retparam, align 8 + store i64 %5, ptr %len, align 8 + %6 = call i64 @std.io.File.write_byte(ptr %2, i8 zeroext 10) + %not_err3 = icmp eq i64 %6, 0 + %7 = call i1 @llvm.expect.i1(i1 %not_err3, i1 true) + br i1 %7, label %after_check5, label %assign_optional4 + +assign_optional4: ; preds = %noerr_block + store i64 %6, ptr %error_var2, align 8 + br label %guard_block6 + +after_check5: ; preds = %noerr_block + br label %noerr_block7 + +guard_block6: ; preds = %assign_optional4 + br label %voiderr + +noerr_block7: ; preds = %after_check5 + %8 = call i64 @std.io.File.flush(ptr %2) + %not_err9 = icmp eq i64 %8, 0 + %9 = call i1 @llvm.expect.i1(i1 %not_err9, i1 true) + br i1 %9, label %after_check11, label %assign_optional10 + +assign_optional10: ; preds = %noerr_block7 + store i64 %8, ptr %error_var8, align 8 + br label %guard_block12 + +after_check11: ; preds = %noerr_block7 + br label %noerr_block13 + +guard_block12: ; preds = %assign_optional10 + br label %voiderr + +noerr_block13: ; preds = %after_check11 + %10 = load i64, ptr %len, align 8 + %add = add i64 %10, 1 + br label %voiderr + +voiderr: ; preds = %noerr_block13, %guard_block12, %guard_block6, %guard_block + br label %switch.exit + +switch.case14: ; preds = %switch.entry + %11 = call ptr @std.io.stdout() + %12 = call i64 @std.io.File.write(ptr %retparam18, ptr %11, ptr @.str.2, i64 4) + %not_err19 = icmp eq i64 %12, 0 + %13 = call i1 @llvm.expect.i1(i1 %not_err19, i1 true) + br i1 %13, label %after_check21, label %assign_optional20 + +assign_optional20: ; preds = %switch.case14 + store i64 %12, ptr %error_var16, align 8 + br label %guard_block22 + +after_check21: ; preds = %switch.case14 + br label %noerr_block23 + +guard_block22: ; preds = %assign_optional20 + br label %voiderr37 + +noerr_block23: ; preds = %after_check21 + %14 = load i64, ptr %retparam18, align 8 + store i64 %14, ptr %len15, align 8 + %15 = call i64 @std.io.File.write_byte(ptr %11, i8 zeroext 10) + %not_err25 = icmp eq i64 %15, 0 + %16 = call i1 @llvm.expect.i1(i1 %not_err25, i1 true) + br i1 %16, label %after_check27, label %assign_optional26 + +assign_optional26: ; preds = %noerr_block23 + store i64 %15, ptr %error_var24, align 8 + br label %guard_block28 + +after_check27: ; preds = %noerr_block23 + br label %noerr_block29 + +guard_block28: ; preds = %assign_optional26 + br label %voiderr37 + +noerr_block29: ; preds = %after_check27 + %17 = call i64 @std.io.File.flush(ptr %11) + %not_err31 = icmp eq i64 %17, 0 + %18 = call i1 @llvm.expect.i1(i1 %not_err31, i1 true) + br i1 %18, label %after_check33, label %assign_optional32 + +assign_optional32: ; preds = %noerr_block29 + store i64 %17, ptr %error_var30, align 8 + br label %guard_block34 + +after_check33: ; preds = %noerr_block29 + br label %noerr_block35 + +guard_block34: ; preds = %assign_optional32 + br label %voiderr37 + +noerr_block35: ; preds = %after_check33 + %19 = load i64, ptr %len15, align 8 + %add36 = add i64 %19, 1 + br label %voiderr37 + +voiderr37: ; preds = %noerr_block35, %guard_block34, %guard_block28, %guard_block22 + br label %switch.exit + +switch.exit: ; preds = %voiderr37, %voiderr, %switch.entry + store i32 %0, ptr %switch38, align 4 + br label %switch.entry39 + +switch.entry39: ; preds = %switch.exit + %20 = load i32, ptr %switch38, align 4 + switch i32 %20, label %switch.exit88 [ + i32 0, label %switch.case40 + i32 1, label %switch.case40 + i32 2, label %switch.case64 + ] + +switch.case40: ; preds = %switch.entry39, %switch.entry39 + %21 = call ptr @std.io.stdout() + %22 = call i64 @std.io.File.write(ptr %retparam44, ptr %21, ptr @.str.3, i64 8) + %not_err45 = icmp eq i64 %22, 0 + %23 = call i1 @llvm.expect.i1(i1 %not_err45, i1 true) + br i1 %23, label %after_check47, label %assign_optional46 + +assign_optional46: ; preds = %switch.case40 + store i64 %22, ptr %error_var42, align 8 + br label %guard_block48 + +after_check47: ; preds = %switch.case40 + br label %noerr_block49 + +guard_block48: ; preds = %assign_optional46 + br label %voiderr63 + +noerr_block49: ; preds = %after_check47 + %24 = load i64, ptr %retparam44, align 8 + store i64 %24, ptr %len41, align 8 + %25 = call i64 @std.io.File.write_byte(ptr %21, i8 zeroext 10) + %not_err51 = icmp eq i64 %25, 0 + %26 = call i1 @llvm.expect.i1(i1 %not_err51, i1 true) + br i1 %26, label %after_check53, label %assign_optional52 + +assign_optional52: ; preds = %noerr_block49 + store i64 %25, ptr %error_var50, align 8 + br label %guard_block54 + +after_check53: ; preds = %noerr_block49 + br label %noerr_block55 + +guard_block54: ; preds = %assign_optional52 + br label %voiderr63 + +noerr_block55: ; preds = %after_check53 + %27 = call i64 @std.io.File.flush(ptr %21) + %not_err57 = icmp eq i64 %27, 0 + %28 = call i1 @llvm.expect.i1(i1 %not_err57, i1 true) + br i1 %28, label %after_check59, label %assign_optional58 + +assign_optional58: ; preds = %noerr_block55 + store i64 %27, ptr %error_var56, align 8 + br label %guard_block60 + +after_check59: ; preds = %noerr_block55 + br label %noerr_block61 + +guard_block60: ; preds = %assign_optional58 + br label %voiderr63 + +noerr_block61: ; preds = %after_check59 + %29 = load i64, ptr %len41, align 8 + %add62 = add i64 %29, 1 + br label %voiderr63 + +voiderr63: ; preds = %noerr_block61, %guard_block60, %guard_block54, %guard_block48 + br label %switch.exit88 + +switch.case64: ; preds = %switch.entry39 + %30 = call ptr @std.io.stdout() + %31 = call i64 @std.io.File.write(ptr %retparam68, ptr %30, ptr @.str.4, i64 4) + %not_err69 = icmp eq i64 %31, 0 + %32 = call i1 @llvm.expect.i1(i1 %not_err69, i1 true) + br i1 %32, label %after_check71, label %assign_optional70 + +assign_optional70: ; preds = %switch.case64 + store i64 %31, ptr %error_var66, align 8 + br label %guard_block72 + +after_check71: ; preds = %switch.case64 + br label %noerr_block73 + +guard_block72: ; preds = %assign_optional70 + br label %voiderr87 + +noerr_block73: ; preds = %after_check71 + %33 = load i64, ptr %retparam68, align 8 + store i64 %33, ptr %len65, align 8 + %34 = call i64 @std.io.File.write_byte(ptr %30, i8 zeroext 10) + %not_err75 = icmp eq i64 %34, 0 + %35 = call i1 @llvm.expect.i1(i1 %not_err75, i1 true) + br i1 %35, label %after_check77, label %assign_optional76 + +assign_optional76: ; preds = %noerr_block73 + store i64 %34, ptr %error_var74, align 8 + br label %guard_block78 + +after_check77: ; preds = %noerr_block73 + br label %noerr_block79 + +guard_block78: ; preds = %assign_optional76 + br label %voiderr87 + +noerr_block79: ; preds = %after_check77 + %36 = call i64 @std.io.File.flush(ptr %30) + %not_err81 = icmp eq i64 %36, 0 + %37 = call i1 @llvm.expect.i1(i1 %not_err81, i1 true) + br i1 %37, label %after_check83, label %assign_optional82 + +assign_optional82: ; preds = %noerr_block79 + store i64 %36, ptr %error_var80, align 8 + br label %guard_block84 + +after_check83: ; preds = %noerr_block79 + br label %noerr_block85 + +guard_block84: ; preds = %assign_optional82 + br label %voiderr87 + +noerr_block85: ; preds = %after_check83 + %38 = load i64, ptr %len65, align 8 + %add86 = add i64 %38, 1 + br label %voiderr87 + +voiderr87: ; preds = %noerr_block85, %guard_block84, %guard_block78, %guard_block72 + br label %switch.exit88 + +switch.exit88: ; preds = %voiderr87, %voiderr63, %switch.entry39 + store i32 %0, ptr %switch89, align 4 + br label %switch.entry90 + +switch.entry90: ; preds = %switch.exit88 + %39 = load i32, ptr %switch89, align 4 + switch i32 %39, label %switch.exit117 [ + i32 0, label %switch.case91 + i32 1, label %switch.case92 + i32 2, label %switch.case116 + ] + +switch.case91: ; preds = %switch.entry90 + br label %switch.exit117 + +switch.case92: ; preds = %switch.entry90 + %40 = call ptr @std.io.stdout() + %41 = call i64 @std.io.File.write(ptr %retparam96, ptr %40, ptr @.str.5, i64 6) + %not_err97 = icmp eq i64 %41, 0 + %42 = call i1 @llvm.expect.i1(i1 %not_err97, i1 true) + br i1 %42, label %after_check99, label %assign_optional98 + +assign_optional98: ; preds = %switch.case92 + store i64 %41, ptr %error_var94, align 8 + br label %guard_block100 + +after_check99: ; preds = %switch.case92 + br label %noerr_block101 + +guard_block100: ; preds = %assign_optional98 + br label %voiderr115 + +noerr_block101: ; preds = %after_check99 + %43 = load i64, ptr %retparam96, align 8 + store i64 %43, ptr %len93, align 8 + %44 = call i64 @std.io.File.write_byte(ptr %40, i8 zeroext 10) + %not_err103 = icmp eq i64 %44, 0 + %45 = call i1 @llvm.expect.i1(i1 %not_err103, i1 true) + br i1 %45, label %after_check105, label %assign_optional104 + +assign_optional104: ; preds = %noerr_block101 + store i64 %44, ptr %error_var102, align 8 + br label %guard_block106 + +after_check105: ; preds = %noerr_block101 + br label %noerr_block107 + +guard_block106: ; preds = %assign_optional104 + br label %voiderr115 + +noerr_block107: ; preds = %after_check105 + %46 = call i64 @std.io.File.flush(ptr %40) + %not_err109 = icmp eq i64 %46, 0 + %47 = call i1 @llvm.expect.i1(i1 %not_err109, i1 true) + br i1 %47, label %after_check111, label %assign_optional110 + +assign_optional110: ; preds = %noerr_block107 + store i64 %46, ptr %error_var108, align 8 + br label %guard_block112 + +after_check111: ; preds = %noerr_block107 + br label %noerr_block113 + +guard_block112: ; preds = %assign_optional110 + br label %voiderr115 + +noerr_block113: ; preds = %after_check111 + %48 = load i64, ptr %len93, align 8 + %add114 = add i64 %48, 1 + br label %voiderr115 + +voiderr115: ; preds = %noerr_block113, %guard_block112, %guard_block106, %guard_block100 + br label %switch.exit117 + +switch.case116: ; preds = %switch.entry90 + br label %switch.exit117 + +switch.exit117: ; preds = %switch.case116, %voiderr115, %switch.case91, %switch.entry90 + store i32 %0, ptr %switch118, align 4 + br label %switch.entry119 + +switch.entry119: ; preds = %switch.exit117 + %49 = load i32, ptr %switch118, align 4 + switch i32 %49, label %switch.default [ + i32 0, label %switch.case120 + i32 1, label %switch.case120 + i32 2, label %switch.case120 + ] + +switch.case120: ; preds = %switch.entry119, %switch.entry119, %switch.entry119 + br label %switch.exit121 + +switch.default: ; preds = %switch.entry119 + br label %switch.exit121 + +switch.exit121: ; preds = %switch.default, %switch.case120 + store i32 %0, ptr %switch122, align 4 + br label %switch.entry123 + +switch.entry123: ; preds = %switch.exit121 + %50 = load i32, ptr %switch122, align 4 + switch i32 %50, label %switch.exit197 [ + i32 0, label %switch.case124 + i32 1, label %switch.case148 + i32 2, label %switch.case173 + ] + +switch.case124: ; preds = %switch.entry123 + store i32 1, ptr %a, align 4 + %51 = call ptr @std.io.stdout() + %52 = call i64 @std.io.File.write(ptr %retparam128, ptr %51, ptr @.str.6, i64 1) + %not_err129 = icmp eq i64 %52, 0 + %53 = call i1 @llvm.expect.i1(i1 %not_err129, i1 true) + br i1 %53, label %after_check131, label %assign_optional130 + +assign_optional130: ; preds = %switch.case124 + store i64 %52, ptr %error_var126, align 8 + br label %guard_block132 + +after_check131: ; preds = %switch.case124 + br label %noerr_block133 + +guard_block132: ; preds = %assign_optional130 + br label %voiderr147 + +noerr_block133: ; preds = %after_check131 + %54 = load i64, ptr %retparam128, align 8 + store i64 %54, ptr %len125, align 8 + %55 = call i64 @std.io.File.write_byte(ptr %51, i8 zeroext 10) + %not_err135 = icmp eq i64 %55, 0 + %56 = call i1 @llvm.expect.i1(i1 %not_err135, i1 true) + br i1 %56, label %after_check137, label %assign_optional136 + +assign_optional136: ; preds = %noerr_block133 + store i64 %55, ptr %error_var134, align 8 + br label %guard_block138 + +after_check137: ; preds = %noerr_block133 + br label %noerr_block139 + +guard_block138: ; preds = %assign_optional136 + br label %voiderr147 + +noerr_block139: ; preds = %after_check137 + %57 = call i64 @std.io.File.flush(ptr %51) + %not_err141 = icmp eq i64 %57, 0 + %58 = call i1 @llvm.expect.i1(i1 %not_err141, i1 true) + br i1 %58, label %after_check143, label %assign_optional142 + +assign_optional142: ; preds = %noerr_block139 + store i64 %57, ptr %error_var140, align 8 + br label %guard_block144 + +after_check143: ; preds = %noerr_block139 + br label %noerr_block145 + +guard_block144: ; preds = %assign_optional142 + br label %voiderr147 + +noerr_block145: ; preds = %after_check143 + %59 = load i64, ptr %len125, align 8 + %add146 = add i64 %59, 1 + br label %voiderr147 + +voiderr147: ; preds = %noerr_block145, %guard_block144, %guard_block138, %guard_block132 + br label %switch.case148 + +switch.case148: ; preds = %switch.entry123, %voiderr147 + store i32 2, ptr %a149, align 4 + %60 = call ptr @std.io.stdout() + %61 = call i64 @std.io.File.write(ptr %retparam153, ptr %60, ptr @.str.7, i64 1) + %not_err154 = icmp eq i64 %61, 0 + %62 = call i1 @llvm.expect.i1(i1 %not_err154, i1 true) + br i1 %62, label %after_check156, label %assign_optional155 + +assign_optional155: ; preds = %switch.case148 + store i64 %61, ptr %error_var151, align 8 + br label %guard_block157 + +after_check156: ; preds = %switch.case148 + br label %noerr_block158 + +guard_block157: ; preds = %assign_optional155 + br label %voiderr172 + +noerr_block158: ; preds = %after_check156 + %63 = load i64, ptr %retparam153, align 8 + store i64 %63, ptr %len150, align 8 + %64 = call i64 @std.io.File.write_byte(ptr %60, i8 zeroext 10) + %not_err160 = icmp eq i64 %64, 0 + %65 = call i1 @llvm.expect.i1(i1 %not_err160, i1 true) + br i1 %65, label %after_check162, label %assign_optional161 + +assign_optional161: ; preds = %noerr_block158 + store i64 %64, ptr %error_var159, align 8 + br label %guard_block163 + +after_check162: ; preds = %noerr_block158 + br label %noerr_block164 + +guard_block163: ; preds = %assign_optional161 + br label %voiderr172 + +noerr_block164: ; preds = %after_check162 + %66 = call i64 @std.io.File.flush(ptr %60) + %not_err166 = icmp eq i64 %66, 0 + %67 = call i1 @llvm.expect.i1(i1 %not_err166, i1 true) + br i1 %67, label %after_check168, label %assign_optional167 + +assign_optional167: ; preds = %noerr_block164 + store i64 %66, ptr %error_var165, align 8 + br label %guard_block169 + +after_check168: ; preds = %noerr_block164 + br label %noerr_block170 + +guard_block169: ; preds = %assign_optional167 + br label %voiderr172 + +noerr_block170: ; preds = %after_check168 + %68 = load i64, ptr %len150, align 8 + %add171 = add i64 %68, 1 + br label %voiderr172 + +voiderr172: ; preds = %noerr_block170, %guard_block169, %guard_block163, %guard_block157 + br label %switch.case173 + +switch.case173: ; preds = %switch.entry123, %voiderr172 + %69 = call ptr @std.io.stdout() + %70 = call i64 @std.io.File.write(ptr %retparam177, ptr %69, ptr @.str.8, i64 1) + %not_err178 = icmp eq i64 %70, 0 + %71 = call i1 @llvm.expect.i1(i1 %not_err178, i1 true) + br i1 %71, label %after_check180, label %assign_optional179 + +assign_optional179: ; preds = %switch.case173 + store i64 %70, ptr %error_var175, align 8 + br label %guard_block181 + +after_check180: ; preds = %switch.case173 + br label %noerr_block182 + +guard_block181: ; preds = %assign_optional179 + br label %voiderr196 + +noerr_block182: ; preds = %after_check180 + %72 = load i64, ptr %retparam177, align 8 + store i64 %72, ptr %len174, align 8 + %73 = call i64 @std.io.File.write_byte(ptr %69, i8 zeroext 10) + %not_err184 = icmp eq i64 %73, 0 + %74 = call i1 @llvm.expect.i1(i1 %not_err184, i1 true) + br i1 %74, label %after_check186, label %assign_optional185 + +assign_optional185: ; preds = %noerr_block182 + store i64 %73, ptr %error_var183, align 8 + br label %guard_block187 + +after_check186: ; preds = %noerr_block182 + br label %noerr_block188 + +guard_block187: ; preds = %assign_optional185 + br label %voiderr196 + +noerr_block188: ; preds = %after_check186 + %75 = call i64 @std.io.File.flush(ptr %69) + %not_err190 = icmp eq i64 %75, 0 + %76 = call i1 @llvm.expect.i1(i1 %not_err190, i1 true) + br i1 %76, label %after_check192, label %assign_optional191 + +assign_optional191: ; preds = %noerr_block188 + store i64 %75, ptr %error_var189, align 8 + br label %guard_block193 + +after_check192: ; preds = %noerr_block188 + br label %noerr_block194 + +guard_block193: ; preds = %assign_optional191 + br label %voiderr196 + +noerr_block194: ; preds = %after_check192 + %77 = load i64, ptr %len174, align 8 + %add195 = add i64 %77, 1 + br label %voiderr196 + +voiderr196: ; preds = %noerr_block194, %guard_block193, %guard_block187, %guard_block181 + br label %switch.exit197 + +switch.exit197: ; preds = %voiderr196, %switch.entry123 + ret void +} \ No newline at end of file diff --git a/test/test_suite7/from_docs/examples_functionpointer.c3t b/test/test_suite7/from_docs/examples_functionpointer.c3t new file mode 100644 index 000000000..83eabb787 --- /dev/null +++ b/test/test_suite7/from_docs/examples_functionpointer.c3t @@ -0,0 +1,34 @@ +// #target: macos-x64 + +module demo; +def 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_suite7/from_docs/examples_if_catch.c3t b/test/test_suite7/from_docs/examples_if_catch.c3t new file mode 100644 index 000000000..6ddf4ddc4 --- /dev/null +++ b/test/test_suite7/from_docs/examples_if_catch.c3t @@ -0,0 +1,163 @@ +// #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 an optional 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 + %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 + %3 = call i1 @llvm.expect.i1(i1 %not_err, i1 true) + br i1 %3, label %after_check, label %assign_optional + +assign_optional: ; preds = %entry + store i64 %2, ptr %error_var, align 8 + br label %guard_block + +after_check: ; preds = %entry + br label %noerr_block + +guard_block: ; preds = %assign_optional + %4 = load i64, ptr %error_var, align 8 + ret i64 %4 + +noerr_block: ; preds = %after_check + 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 + %3 = call i1 @llvm.expect.i1(i1 %not_err, i1 true) + br i1 %3, label %after_check, label %assign_optional + +assign_optional: ; preds = %entry + store i64 %2, ptr %ratio.f, align 8 + br label %after_assign + +after_check: ; preds = %entry + %4 = load double, ptr %retparam, align 8 + store double %4, ptr %ratio, align 8 + store i64 0, ptr %ratio.f, align 8 + br label %after_assign + +after_assign: ; preds = %after_check, %assign_optional + br label %testblock + +testblock: ; preds = %after_assign + %optval = load i64, ptr %ratio.f, align 8 + %not_err1 = icmp eq i64 %optval, 0 + %5 = call i1 @llvm.expect.i1(i1 %not_err1, i1 true) + br i1 %5, label %after_check3, label %assign_optional2 + +assign_optional2: ; preds = %testblock + store i64 %optval, ptr %err, align 8 + br label %end_block + +after_check3: ; preds = %testblock + store i64 0, ptr %err, align 8 + br label %end_block + +end_block: ; preds = %after_check3, %assign_optional2 + %6 = load i64, ptr %err, align 8 + %neq = icmp ne i64 %6, 0 + br i1 %neq, label %if.then, label %if.exit + +if.then: ; preds = %end_block + store i64 %6, ptr %switch, align 8 + br label %switch.entry + +switch.entry: ; preds = %if.then + %7 = load i64, ptr %switch, align 8 + %eq = icmp eq i64 ptrtoint (ptr @"demo.MathError$DIVISION_BY_ZERO" to i64), %7 + br i1 %eq, label %switch.case, label %next_if + +switch.case: ; preds = %switch.entry + %8 = call i32 (ptr, ...) @printf(ptr @.str) + ret void + +next_if: ; preds = %switch.entry + br label %switch.default + +switch.default: ; preds = %next_if + %9 = call i32 (ptr, ...) @printf(ptr @.str.1) + ret void + +if.exit: ; preds = %end_block + %10 = load double, ptr %ratio, align 8 + %11 = call i32 (ptr, ...) @printf(ptr @.str.2, double %10) + ret void +} \ No newline at end of file diff --git a/test/test_suite7/from_docs/examples_macro_function.c3t b/test/test_suite7/from_docs/examples_macro_function.c3t new file mode 100644 index 000000000..70202ea71 --- /dev/null +++ b/test/test_suite7/from_docs/examples_macro_function.c3t @@ -0,0 +1,44 @@ +// #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 + store i32 2, ptr %a, align 4 + store i32 3, ptr %b, align 4 + %0 = call i32 @example.square(i32 2) + %1 = load i32, ptr %a, align 4 + %add = add i32 %0, %1 + %2 = load i32, ptr %b, align 4 + %add1 = add i32 %add, %2 + ret i32 %add1 +} \ No newline at end of file diff --git a/test/test_suite7/from_docs/examples_struct.c3 b/test/test_suite7/from_docs/examples_struct.c3 new file mode 100644 index 000000000..2e0dee843 --- /dev/null +++ b/test/test_suite7/from_docs/examples_struct.c3 @@ -0,0 +1,46 @@ +def 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_suite7/functions/accidental_method_1448.c3 b/test/test_suite7/functions/accidental_method_1448.c3 new file mode 100644 index 000000000..8afbcd726 --- /dev/null +++ b/test/test_suite7/functions/accidental_method_1448.c3 @@ -0,0 +1,11 @@ +import std; +def MaybeInt = maybe::Maybe(); + +def Func = fn void (args...); + +fn int main() { + Func t; + MaybeInt m = maybe::EMPTY(); + io::printfn("%s %s", m.value, m.has_value); + return 0; +} \ No newline at end of file diff --git a/test/test_suite7/functions/after_vararg.c3 b/test/test_suite7/functions/after_vararg.c3 new file mode 100644 index 000000000..8fee2a86b --- /dev/null +++ b/test/test_suite7/functions/after_vararg.c3 @@ -0,0 +1,3 @@ +fn void test1(int... x, int) { } // #error: A parameter name was expected +fn void test2(x..., int) { } // #error: A parameter name was expected +extern fn void test3(int a, ..., int y); // #error: C-style varargs cannot be followed by regular parameters. \ No newline at end of file diff --git a/test/test_suite7/functions/assorted_tests.c3t b/test/test_suite7/functions/assorted_tests.c3t new file mode 100644 index 000000000..8abef35f5 --- /dev/null +++ b/test/test_suite7/functions/assorted_tests.c3t @@ -0,0 +1,113 @@ +// #target: macos-x64 +module test; + +fn int foo1() +{ + char *pp @noinit; + uint w_cnt @noinit; + + 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 @noinit; + double val @noinit; + int lls @noinit; + 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 1 + %zext = zext i8 %2 to i32 + %add = add i32 %0, %zext + store i32 %add, ptr %w_cnt, align 4 + %3 = load i32, ptr %w_cnt, align 4 + ret i32 %3 +} + +; Function Attrs: +define void @test.foo2(i32 %0) #0 { +entry: + %i2b = icmp ne i32 %0, 0 + %ternary = select i1 %i2b, double 1.000000e+00, double 1.250000e+01 + call void @test2(i32 %0, double %ternary, float 1.000000e+00) + ret void +} + +; Function Attrs: +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 + %i2b = icmp ne i32 %1, 0 + br i1 %i2b, 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: + store i8 0, ptr %0, align 1 + ret void +} + +; Function Attrs: +define void @test.denormalize(ptr %0) #0 { +entry: + call void @test.setInternalFPFZero(ptr %0) + ret void +} diff --git a/test/test_suite7/functions/body_argument_fail.c3 b/test/test_suite7/functions/body_argument_fail.c3 new file mode 100644 index 000000000..7af99bcf5 --- /dev/null +++ b/test/test_suite7/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_suite7/functions/c_vararg_expansion.c3t b/test/test_suite7/functions/c_vararg_expansion.c3t new file mode 100644 index 000000000..650a79681 --- /dev/null +++ b/test/test_suite7/functions/c_vararg_expansion.c3t @@ -0,0 +1,37 @@ +// #target: macos-x64 +module test; +extern fn void printf(char*,...); +distinct Foo = float; +fn void main() +{ + Foo a = 12.3; + Foo! b = 33.5; + (void)printf("%f %f %f", (float)a, a, b); +} + +/* #expect: test.ll + +define void @test.main() #0 { +entry: + %a = alloca float, align 4 + %b = alloca float, align 4 + %b.f = alloca i64, align 8 + store float 0x40289999A0000000, ptr %a, align 4 + store float 3.350000e+01, ptr %b, align 4 + store i64 0, ptr %b.f, align 8 + %0 = load float, ptr %a, align 4 + %fpfpext = fpext float %0 to double + %1 = load float, ptr %a, align 4 + %fpfpext1 = fpext float %1 to double + %optval = load i64, ptr %b.f, align 8 + %not_err = icmp eq i64 %optval, 0 + %2 = call i1 @llvm.expect.i1(i1 %not_err, i1 true) + br i1 %2, label %after_check, label %voiderr +after_check: ; preds = %entry + %3 = load float, ptr %b, align 4 + %fpfpext2 = fpext float %3 to double + call void (ptr, ...) @printf(ptr @.str, double %fpfpext, double %fpfpext1, double %fpfpext2) + br label %voiderr +voiderr: ; preds = %after_check, %entry + ret void +} \ No newline at end of file diff --git a/test/test_suite7/functions/call_conv_fntype.c3 b/test/test_suite7/functions/call_conv_fntype.c3 new file mode 100644 index 000000000..58f40a3b9 --- /dev/null +++ b/test/test_suite7/functions/call_conv_fntype.c3 @@ -0,0 +1,6 @@ +def Foo = fn int(String x, int z) @callconv("veccall"); + +fn int v(String x, int z) @callconv("veccall") +{ + return 1; +} \ No newline at end of file diff --git a/test/test_suite7/functions/ct_named_params.c3t b/test/test_suite7/functions/ct_named_params.c3t new file mode 100644 index 000000000..286b8d58f --- /dev/null +++ b/test/test_suite7/functions/ct_named_params.c3t @@ -0,0 +1,23 @@ +// #target: macos-x64 +module test; + +macro foo($bar, $Type) +{ + $Type a = $bar; + return $bar; +} + +fn void bar() +{ + int x = foo($bar: 167, $Type: int); +} + +/* #expect: test.ll + +define void @test.bar() #0 { +entry: + %x = alloca i32, align 4 + %a = alloca i32, align 4 + store i32 167, ptr %a, align 4 + store i32 167, ptr %x, align 4 + ret void \ No newline at end of file diff --git a/test/test_suite7/functions/default_param_fail.c3 b/test/test_suite7/functions/default_param_fail.c3 new file mode 100644 index 000000000..aeac261a8 --- /dev/null +++ b/test/test_suite7/functions/default_param_fail.c3 @@ -0,0 +1,11 @@ + +int z; + +fault MyError +{ + FOO, +} + +fn void test(int a = z) {} + +fn void test2(int b = MyError.FOO?) {} \ No newline at end of file diff --git a/test/test_suite7/functions/defered_default_arguments.c3t b/test/test_suite7/functions/defered_default_arguments.c3t new file mode 100644 index 000000000..baabb7beb --- /dev/null +++ b/test/test_suite7/functions/defered_default_arguments.c3t @@ -0,0 +1,56 @@ +// #target: macos-x64 +module test; +import std::io; +import test2; + +fn void test(int a = test2::bar(), int b = test2::foo()) +{ + io::printf("%d %d\n", a, b); +} + +module test2; + +fn int foo() +{ + static int x = 0; + return ++x; +} + +macro int bar() +{ + static int x = 0; + return ++x; +} + +module test3; +import test; +import std::io; + +fn void main() +{ + test::test(1, 2); + test::test(a: 3); + test::test(1, b: 32); + test::test(); + test::test(); +} + +/* #expect: test3.ll + +entry: + call void @test.test(i32 1, i32 2) + %0 = call i32 @test2.foo() + call void @test.test(i32 3, i32 %0) + call void @test.test(i32 1, i32 32) + %1 = load i32, ptr @main.x, align 4 + %add = add i32 %1, 1 + store i32 %add, ptr @main.x, align 4 + %2 = call i32 @test2.foo() + call void @test.test(i32 %add, i32 %2) + %3 = load i32, ptr @main.x.1, align 4 + %add1 = add i32 %3, 1 + store i32 %add1, ptr @main.x.1, align 4 + %4 = call i32 @test2.foo() + call void @test.test(i32 %add1, i32 %4) + ret void +} \ No newline at end of file diff --git a/test/test_suite7/functions/distinct_fn_ptr_and_lambda.c3t b/test/test_suite7/functions/distinct_fn_ptr_and_lambda.c3t new file mode 100644 index 000000000..c3e58a7da --- /dev/null +++ b/test/test_suite7/functions/distinct_fn_ptr_and_lambda.c3t @@ -0,0 +1,8 @@ +def Foo = fn void(int x); + +distinct Bar = Foo; + +fn void main() +{ + Bar t = fn (x) { }; +} \ No newline at end of file diff --git a/test/test_suite7/functions/double_return.c3 b/test/test_suite7/functions/double_return.c3 new file mode 100644 index 000000000..29ea27780 --- /dev/null +++ b/test/test_suite7/functions/double_return.c3 @@ -0,0 +1,8 @@ +module double_return; + +fn int test(bool pos, bool color) +{ + return 0; + return (int)(pos && color); // #warning: never execute +} + diff --git a/test/test_suite7/functions/failable_param.c3 b/test/test_suite7/functions/failable_param.c3 new file mode 100644 index 000000000..40633fcaf --- /dev/null +++ b/test/test_suite7/functions/failable_param.c3 @@ -0,0 +1,3 @@ +module test; + +fn void test4(void!); // #error: Parameters may not be optional. diff --git a/test/test_suite7/functions/func_ptr_conversion_alias.c3t b/test/test_suite7/functions/func_ptr_conversion_alias.c3t new file mode 100644 index 000000000..f9434f330 --- /dev/null +++ b/test/test_suite7/functions/func_ptr_conversion_alias.c3t @@ -0,0 +1,21 @@ +// #target: macos-x64 +module test; + +def Callback = fn void(); +def Callback2 = fn void(); + +def GetCallback = fn Callback2**[][123]*(); + +fn Callback**[][123]* tester() +{ + return null; +} + +GetCallback x = &tester; + + +def GetCallbackOpt = fn Callback2!(); + +fn Callback2! tester2() => null; + +GetCallbackOpt y = &tester2; \ No newline at end of file diff --git a/test/test_suite7/functions/func_ptr_conversions_and_names.c3t b/test/test_suite7/functions/func_ptr_conversions_and_names.c3t new file mode 100644 index 000000000..57cf0d55e --- /dev/null +++ b/test/test_suite7/functions/func_ptr_conversions_and_names.c3t @@ -0,0 +1,135 @@ +// #target: macos-x64 +module test; +import std::io; +def Func = fn int(int y); +def FuncOther = fn bool(char*); +def FuncSame = fn int(int z = 444); + +fn int test(int a) { return a; } +fn int test2(int b = 3) { return b; } + +fn int! test3(int b = 3) { return b; } +fn int! test4(int b = 3) { return b; } + +fn void main() +{ + Func a = &test; + Func b = &test2; + io::printfn("%d", a(y: 123)); + io::printfn("%d", (&test2)()); + FuncSame z = &test2; + io::printfn("%d", z()); + io::printfn("%s", $typeof(b ? &test2 : &test).qnameof); + io::printfn("%s", $typeof(b ? &test2 : &test).nameof); + io::printfn("%s", $typeof(&test2).qnameof); + io::printfn("%s", $typeof(&test2).nameof); + io::printfn("%s", $typeof(b ? &test4 : &test3).nameof); + + $typeof(b ? &test2 : &test) y = &test2; + typeid zfoke = $typeof(y).typeid; +} + +/* #expect: test.ll + +@.str = private unnamed_addr constant [3 x i8] c"%d\00", align 1 +@"$ct.int" = linkonce global %.introspect { i8 2, i64 0, ptr null, i64 4, i64 0, i64 0, [0 x i64] zeroinitializer }, align 8 +@.str.1 = private unnamed_addr constant [3 x i8] c"%d\00", align 1 +@.str.2 = private unnamed_addr constant [3 x i8] c"%d\00", align 1 +@.str.3 = private unnamed_addr constant [3 x i8] c"%s\00", align 1 +@.str.4 = private unnamed_addr constant [12 x i8] c"fn int(int)\00", align 1 +@"$ct.String" = linkonce global %.introspect { i8 18, i64 ptrtoint (ptr @"$ct.sa$char" to i64), ptr null, i64 16, i64 ptrtoint (ptr @"$ct.sa$char" to i64), i64 0, [0 x i64] zeroinitializer }, align 8 +@"$ct.sa$char" = linkonce global %.introspect { i8 16, i64 0, ptr null, i64 16, i64 ptrtoint (ptr @"$ct.char" to i64), i64 0, [0 x i64] zeroinitializer }, align 8 +@"$ct.char" = linkonce global %.introspect { i8 3, i64 0, ptr null, i64 1, i64 0, i64 0, [0 x i64] zeroinitializer }, align 8 +@.str.5 = private unnamed_addr constant [3 x i8] c"%s\00", align 1 +@.str.6 = private unnamed_addr constant [12 x i8] c"fn int(int)\00", align 1 +@.str.7 = private unnamed_addr constant [3 x i8] c"%s\00", align 1 +@.str.8 = private unnamed_addr constant [12 x i8] c"fn int(int)\00", align 1 +@.str.9 = private unnamed_addr constant [3 x i8] c"%s\00", align 1 +@.str.10 = private unnamed_addr constant [12 x i8] c"fn int(int)\00", align 1 +@.str.11 = private unnamed_addr constant [3 x i8] c"%s\00", align 1 +@.str.12 = private unnamed_addr constant [13 x i8] c"fn int!(int)\00", align 1 +@"$ct.fn$int$int$" = linkonce global %.introspect { i8 13, i64 0, ptr null, i64 8, i64 0, i64 0, [0 x i64] zeroinitializer }, align 8 + +define void @test.main() #0 { +entry: + %a = alloca ptr, align 8 + %b = alloca ptr, align 8 + %varargslots = alloca [1 x %any], align 16 + %taddr = alloca i32, align 4 + %retparam = alloca i64, align 8 + %varargslots1 = alloca [1 x %any], align 16 + %taddr2 = alloca i32, align 4 + %retparam3 = alloca i64, align 8 + %z = alloca ptr, align 8 + %varargslots4 = alloca [1 x %any], align 16 + %taddr5 = alloca i32, align 4 + %retparam6 = alloca i64, align 8 + %varargslots7 = alloca [1 x %any], align 16 + %taddr8 = alloca %"char[]", align 8 + %retparam9 = alloca i64, align 8 + %varargslots10 = alloca [1 x %any], align 16 + %taddr11 = alloca %"char[]", align 8 + %retparam12 = alloca i64, align 8 + %varargslots13 = alloca [1 x %any], align 16 + %taddr14 = alloca %"char[]", align 8 + %retparam15 = alloca i64, align 8 + %varargslots16 = alloca [1 x %any], align 16 + %taddr17 = alloca %"char[]", align 8 + %retparam18 = alloca i64, align 8 + %varargslots19 = alloca [1 x %any], align 16 + %taddr20 = alloca %"char[]", align 8 + %retparam21 = alloca i64, align 8 + %y = alloca ptr, align 8 + %zfoke = alloca i64, align 8 + store ptr @test.test, ptr %a, align 8 + store ptr @test.test2, ptr %b, align 8 + %0 = load ptr, ptr %a, align 8 + %1 = call i32 %0(i32 123) + store i32 %1, ptr %taddr, align 4 + %2 = insertvalue %any undef, ptr %taddr, 0 + %3 = insertvalue %any %2, i64 ptrtoint (ptr @"$ct.int" to i64), 1 + store %any %3, ptr %varargslots, align 16 + %4 = call i64 @std.io.printfn(ptr %retparam, ptr @.str, i64 2, ptr %varargslots, i64 1) + %5 = call i32 @test.test2(i32 3) + store i32 %5, ptr %taddr2, align 4 + %6 = insertvalue %any undef, ptr %taddr2, 0 + %7 = insertvalue %any %6, i64 ptrtoint (ptr @"$ct.int" to i64), 1 + store %any %7, ptr %varargslots1, align 16 + %8 = call i64 @std.io.printfn(ptr %retparam3, ptr @.str.1, i64 2, ptr %varargslots1, i64 1) + store ptr @test.test2, ptr %z, align 8 + %9 = load ptr, ptr %z, align 8 + %10 = call i32 %9(i32 444) + store i32 %10, ptr %taddr5, align 4 + %11 = insertvalue %any undef, ptr %taddr5, 0 + %12 = insertvalue %any %11, i64 ptrtoint (ptr @"$ct.int" to i64), 1 + store %any %12, ptr %varargslots4, align 16 + %13 = call i64 @std.io.printfn(ptr %retparam6, ptr @.str.2, i64 2, ptr %varargslots4, i64 1) + store %"char[]" { ptr @.str.4, i64 11 }, ptr %taddr8, align 8 + %14 = insertvalue %any undef, ptr %taddr8, 0 + %15 = insertvalue %any %14, i64 ptrtoint (ptr @"$ct.String" to i64), 1 + store %any %15, ptr %varargslots7, align 16 + %16 = call i64 @std.io.printfn(ptr %retparam9, ptr @.str.3, i64 2, ptr %varargslots7, i64 1) + store %"char[]" { ptr @.str.6, i64 11 }, ptr %taddr11, align 8 + %17 = insertvalue %any undef, ptr %taddr11, 0 + %18 = insertvalue %any %17, i64 ptrtoint (ptr @"$ct.String" to i64), 1 + store %any %18, ptr %varargslots10, align 16 + %19 = call i64 @std.io.printfn(ptr %retparam12, ptr @.str.5, i64 2, ptr %varargslots10, i64 1) + store %"char[]" { ptr @.str.8, i64 11 }, ptr %taddr14, align 8 + %20 = insertvalue %any undef, ptr %taddr14, 0 + %21 = insertvalue %any %20, i64 ptrtoint (ptr @"$ct.String" to i64), 1 + store %any %21, ptr %varargslots13, align 16 + %22 = call i64 @std.io.printfn(ptr %retparam15, ptr @.str.7, i64 2, ptr %varargslots13, i64 1) + store %"char[]" { ptr @.str.10, i64 11 }, ptr %taddr17, align 8 + %23 = insertvalue %any undef, ptr %taddr17, 0 + %24 = insertvalue %any %23, i64 ptrtoint (ptr @"$ct.String" to i64), 1 + store %any %24, ptr %varargslots16, align 16 + %25 = call i64 @std.io.printfn(ptr %retparam18, ptr @.str.9, i64 2, ptr %varargslots16, i64 1) + store %"char[]" { ptr @.str.12, i64 12 }, ptr %taddr20, align 8 + %26 = insertvalue %any undef, ptr %taddr20, 0 + %27 = insertvalue %any %26, i64 ptrtoint (ptr @"$ct.String" to i64), 1 + store %any %27, ptr %varargslots19, align 16 + %28 = call i64 @std.io.printfn(ptr %retparam21, ptr @.str.11, i64 2, ptr %varargslots19, i64 1) + store ptr @test.test2, ptr %y, align 8 + store i64 ptrtoint (ptr @"$ct.fn$int$int$" to i64), ptr %zfoke, align 8 + ret void +} diff --git a/test/test_suite7/functions/func_ptr_null.check.c3t b/test/test_suite7/functions/func_ptr_null.check.c3t new file mode 100644 index 000000000..5b30e0e23 --- /dev/null +++ b/test/test_suite7/functions/func_ptr_null.check.c3t @@ -0,0 +1,43 @@ +// #target: macos-aarch64 +// #safe: yes +module test; +def TestFn = fn void(); + +fn int main() +{ + TestFn foo; + foo(); + return 0; +} + +/* #expect: test.ll + + +define i32 @main() #0 { +entry: + %foo = alloca ptr, align 8 + %taddr = alloca %"char[]", align 8 + %taddr1 = alloca %"char[]", align 8 + %taddr2 = alloca %"char[]", align 8 + store ptr null, ptr %foo, align 8 + %0 = load ptr, ptr %foo, align 8 + %checknull = icmp eq ptr %0, null + %1 = call i1 @llvm.expect.i1(i1 %checknull, i1 false) + br i1 %1, label %panic, label %checkok + +checkok: ; preds = %entry + call void %0() + ret i32 0 + +panic: ; preds = %entry + store %"char[]" { ptr @.panic_msg, i64 46 }, ptr %taddr, align 8 + %2 = load [2 x i64], ptr %taddr, align 8 + store %"char[]" { ptr @.file, i64 22 }, ptr %taddr1, align 8 + %3 = load [2 x i64], ptr %taddr1, align 8 + store %"char[]" { ptr @.func, i64 4 }, ptr %taddr2, align 8 + %4 = load [2 x i64], ptr %taddr2, align 8 + %5 = load ptr, ptr @std.core.builtin.panic, align 8 + call void %5([2 x i64] %2, [2 x i64] %3, [2 x i64] %4, i32 7) + unreachable +} + diff --git a/test/test_suite7/functions/function_alias_llvm_check.c3t b/test/test_suite7/functions/function_alias_llvm_check.c3t new file mode 100644 index 000000000..bc95ffdb8 --- /dev/null +++ b/test/test_suite7/functions/function_alias_llvm_check.c3t @@ -0,0 +1,51 @@ +// #target: macos-x64 +module repro; + +import std::collections::list; + +def FnA = fn void(Foo*); +def FnB = fn void(Foo*); + +struct Foo +{ + List() aFuncs; + List() bFuncs; +} + +fn void! Foo.deinit(&self) +{ + self.aFuncs.free(); + self.bFuncs.free(); +} + +fn void Foo.add_fn_a(&self, FnA f) => self.aFuncs.push(f); +fn void Foo.add_fn_b(&self, FnB f) => self.bFuncs.push(f); + +fn void a_func(Foo* foo) {} +fn void b_func(Foo* foo) {} + +fn void main() +{ + Foo foo; + defer foo.deinit()!!; + foo.add_fn_a(&a_func); + foo.add_fn_b(&b_func); +} + +/* #expect: repro.ll + + +define void @repro.main() #0 { +entry: + %foo = alloca %Foo, align 8 + %error_var = alloca i64, align 8 + %varargslots = alloca [1 x %any], align 16 + %indirectarg = alloca %"any[]", align 8 + call void @llvm.memset.p0.i64(ptr align 8 %foo, i8 0, i64 80, i1 false) + call void @repro.Foo.add_fn_a(ptr %foo, ptr @repro.a_func) + call void @repro.Foo.add_fn_b(ptr %foo, ptr @repro.b_func) + %0 = call i64 @repro.Foo.deinit(ptr %foo) + %not_err = icmp eq i64 %0, 0 + %1 = call i1 @llvm.expect.i1(i1 %not_err, i1 true) + br i1 %1, label %after_check, label %assign_optional + diff --git a/test/test_suite7/functions/function_reserved_name.c3 b/test/test_suite7/functions/function_reserved_name.c3 new file mode 100644 index 000000000..129f3f821 --- /dev/null +++ b/test/test_suite7/functions/function_reserved_name.c3 @@ -0,0 +1,7 @@ +module arrays; + +import std::io; + +fn void double() {} // #error: reserved type name like 'double' + +fn void main() {} \ No newline at end of file diff --git a/test/test_suite7/functions/invalid_param.c3 b/test/test_suite7/functions/invalid_param.c3 new file mode 100644 index 000000000..7a75e9586 --- /dev/null +++ b/test/test_suite7/functions/invalid_param.c3 @@ -0,0 +1 @@ +fn void foo(int ABC) { } // #error: Parameter names may not be all uppercase. diff --git a/test/test_suite7/functions/macro_arguments.c3 b/test/test_suite7/functions/macro_arguments.c3 new file mode 100644 index 000000000..10b217897 --- /dev/null +++ b/test/test_suite7/functions/macro_arguments.c3 @@ -0,0 +1,12 @@ + +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 foo9(int x, int x) {} // #error: Duplicate parameter name 'x'. + +macro @foo($a, $b, $c, ...) {} \ No newline at end of file diff --git a/test/test_suite7/functions/macro_expr_type.c3 b/test/test_suite7/functions/macro_expr_type.c3 new file mode 100644 index 000000000..bc9d666ca --- /dev/null +++ b/test/test_suite7/functions/macro_expr_type.c3 @@ -0,0 +1,7 @@ +macro void @foo(int #a) +{ +} +fn void main() +{ + @foo(1.0); // #error: cannot implicitly be converted +} \ No newline at end of file diff --git a/test/test_suite7/functions/missing_first_paren.c3 b/test/test_suite7/functions/missing_first_paren.c3 new file mode 100644 index 000000000..384625bd2 --- /dev/null +++ b/test/test_suite7/functions/missing_first_paren.c3 @@ -0,0 +1,3 @@ +fn void foo) // #error: Expected '(' +{ +} diff --git a/test/test_suite7/functions/missing_fn.c3 b/test/test_suite7/functions/missing_fn.c3 new file mode 100644 index 000000000..29f684c8c --- /dev/null +++ b/test/test_suite7/functions/missing_fn.c3 @@ -0,0 +1 @@ +void foo(int x) {} // #error: This looks like the beginning of a function declaration \ No newline at end of file diff --git a/test/test_suite7/functions/missing_return.c3 b/test/test_suite7/functions/missing_return.c3 new file mode 100644 index 000000000..d1028c19b --- /dev/null +++ b/test/test_suite7/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_suite7/functions/missing_return_lambda.c3 b/test/test_suite7/functions/missing_return_lambda.c3 new file mode 100644 index 000000000..c3f897e43 --- /dev/null +++ b/test/test_suite7/functions/missing_return_lambda.c3 @@ -0,0 +1,9 @@ +import std::io::path; + +fn void! process_dir(String dir_name) +{ + path::Path p = path::temp_new(dir_name)!; + path::PathWalker fnwalk = fn bool!(Path p, bool is_dir, void*) { // #error: issing return statement at the end + io::printfn("path is %s", p); + }; +} \ No newline at end of file diff --git a/test/test_suite7/functions/multisplat.c3t b/test/test_suite7/functions/multisplat.c3t new file mode 100644 index 000000000..313a72b08 --- /dev/null +++ b/test/test_suite7/functions/multisplat.c3t @@ -0,0 +1,112 @@ +// #target: macos-x64 +module test; +extern fn void foo(args...); + +fn void main() +{ + int[3] y = { 33, 44, 55 }; + foo(...y); + foo(1, ...y); + int[] z = &y; + foo(...z[1..2]); + foo(1, ...z[1..2], 5); +} + +/* #expect: test.ll + +define void @test.main() #0 { +entry: + %y = alloca [3 x i32], align 4 + %varargslots = alloca [3 x %any], align 16 + %.anon = alloca [3 x i32], align 4 + %varargslots4 = alloca [4 x %any], align 16 + %taddr = alloca i32, align 4 + %.anon5 = alloca [3 x i32], align 4 + %z = alloca %"int[]", align 8 + %varargslots11 = alloca [2 x %any], align 16 + %varargslots15 = alloca [4 x %any], align 16 + %taddr16 = alloca i32, align 4 + %taddr21 = alloca i32, align 4 + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %y, ptr align 4 @.__const, i32 12, i1 false) + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %.anon, ptr align 4 %y, i32 12, i1 false) + %0 = insertvalue %any undef, ptr %.anon, 0 + %1 = insertvalue %any %0, i64 ptrtoint (ptr @"$ct.int" to i64), 1 + store %any %1, ptr %varargslots, align 16 + %ptradd = getelementptr inbounds i8, ptr %.anon, i64 4 + %2 = insertvalue %any undef, ptr %ptradd, 0 + %3 = insertvalue %any %2, i64 ptrtoint (ptr @"$ct.int" to i64), 1 + %ptradd1 = getelementptr inbounds i8, ptr %varargslots, i64 16 + store %any %3, ptr %ptradd1, align 16 + %ptradd2 = getelementptr inbounds i8, ptr %.anon, i64 8 + %4 = insertvalue %any undef, ptr %ptradd2, 0 + %5 = insertvalue %any %4, i64 ptrtoint (ptr @"$ct.int" to i64), 1 + %ptradd3 = getelementptr inbounds i8, ptr %varargslots, i64 32 + store %any %5, ptr %ptradd3, align 16 + call void @foo(ptr %varargslots, i64 3) + store i32 1, ptr %taddr, align 4 + %6 = insertvalue %any undef, ptr %taddr, 0 + %7 = insertvalue %any %6, i64 ptrtoint (ptr @"$ct.int" to i64), 1 + store %any %7, ptr %varargslots4, align 16 + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %.anon5, ptr align 4 %y, i32 12, i1 false) + %8 = insertvalue %any undef, ptr %.anon5, 0 + %9 = insertvalue %any %8, i64 ptrtoint (ptr @"$ct.int" to i64), 1 + %ptradd6 = getelementptr inbounds i8, ptr %varargslots4, i64 16 + store %any %9, ptr %ptradd6, align 16 + %ptradd7 = getelementptr inbounds i8, ptr %.anon5, i64 4 + %10 = insertvalue %any undef, ptr %ptradd7, 0 + %11 = insertvalue %any %10, i64 ptrtoint (ptr @"$ct.int" to i64), 1 + %ptradd8 = getelementptr inbounds i8, ptr %varargslots4, i64 32 + store %any %11, ptr %ptradd8, align 16 + %ptradd9 = getelementptr inbounds i8, ptr %.anon5, i64 8 + %12 = insertvalue %any undef, ptr %ptradd9, 0 + %13 = insertvalue %any %12, i64 ptrtoint (ptr @"$ct.int" to i64), 1 + %ptradd10 = getelementptr inbounds i8, ptr %varargslots4, i64 48 + store %any %13, ptr %ptradd10, align 16 + call void @foo(ptr %varargslots4, i64 4) + %14 = insertvalue %"int[]" undef, ptr %y, 0 + %15 = insertvalue %"int[]" %14, i64 3, 1 + store %"int[]" %15, ptr %z, align 8 + %16 = load %"int[]", ptr %z, align 8 + %17 = extractvalue %"int[]" %16, 0 + %ptradd12 = getelementptr inbounds i8, ptr %17, i64 4 + %18 = insertvalue %"int[]" undef, ptr %ptradd12, 0 + %19 = insertvalue %"int[]" %18, i64 2, 1 + %20 = extractvalue %"int[]" %19, 0 + %21 = insertvalue %any undef, ptr %20, 0 + %22 = insertvalue %any %21, i64 ptrtoint (ptr @"$ct.int" to i64), 1 + store %any %22, ptr %varargslots11, align 16 + %23 = extractvalue %"int[]" %19, 0 + %ptradd13 = getelementptr inbounds i8, ptr %23, i64 4 + %24 = insertvalue %any undef, ptr %ptradd13, 0 + %25 = insertvalue %any %24, i64 ptrtoint (ptr @"$ct.int" to i64), 1 + %ptradd14 = getelementptr inbounds i8, ptr %varargslots11, i64 16 + store %any %25, ptr %ptradd14, align 16 + call void @foo(ptr %varargslots11, i64 2) + store i32 1, ptr %taddr16, align 4 + %26 = insertvalue %any undef, ptr %taddr16, 0 + %27 = insertvalue %any %26, i64 ptrtoint (ptr @"$ct.int" to i64), 1 + store %any %27, ptr %varargslots15, align 16 + %28 = load %"int[]", ptr %z, align 8 + %29 = extractvalue %"int[]" %28, 0 + %ptradd17 = getelementptr inbounds i8, ptr %29, i64 4 + %30 = insertvalue %"int[]" undef, ptr %ptradd17, 0 + %31 = insertvalue %"int[]" %30, i64 2, 1 + %32 = extractvalue %"int[]" %31, 0 + %33 = insertvalue %any undef, ptr %32, 0 + %34 = insertvalue %any %33, i64 ptrtoint (ptr @"$ct.int" to i64), 1 + %ptradd18 = getelementptr inbounds i8, ptr %varargslots15, i64 16 + store %any %34, ptr %ptradd18, align 16 + %35 = extractvalue %"int[]" %31, 0 + %ptradd19 = getelementptr inbounds i8, ptr %35, i64 4 + %36 = insertvalue %any undef, ptr %ptradd19, 0 + %37 = insertvalue %any %36, i64 ptrtoint (ptr @"$ct.int" to i64), 1 + %ptradd20 = getelementptr inbounds i8, ptr %varargslots15, i64 32 + store %any %37, ptr %ptradd20, align 16 + store i32 5, ptr %taddr21, align 4 + %38 = insertvalue %any undef, ptr %taddr21, 0 + %39 = insertvalue %any %38, i64 ptrtoint (ptr @"$ct.int" to i64), 1 + %ptradd22 = getelementptr inbounds i8, ptr %varargslots15, i64 48 + store %any %39, ptr %ptradd22, align 16 + call void @foo(ptr %varargslots15, i64 4) + ret void +} diff --git a/test/test_suite7/functions/naked_function.c3t b/test/test_suite7/functions/naked_function.c3t new file mode 100644 index 000000000..91c545b61 --- /dev/null +++ b/test/test_suite7/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 uwtable "no-trapping-math"="true" "stack-protector-buffer-size"="8" } diff --git a/test/test_suite7/functions/named_arg_order.c3 b/test/test_suite7/functions/named_arg_order.c3 new file mode 100644 index 000000000..6186df429 --- /dev/null +++ b/test/test_suite7/functions/named_arg_order.c3 @@ -0,0 +1,10 @@ +import std; +macro void test(int a, int $baz) +{ + io::printn(a + $baz); +} + +fn void main() +{ + test($baz: 1, a: 4); // #error: Named arguments must always +} \ No newline at end of file diff --git a/test/test_suite7/functions/param_doc_error.c3 b/test/test_suite7/functions/param_doc_error.c3 new file mode 100644 index 000000000..3dd09dbb5 --- /dev/null +++ b/test/test_suite7/functions/param_doc_error.c3 @@ -0,0 +1,13 @@ +<* +@param some 1 *> // #error: parameter name + +fn int foo(int some){ + return some + 1; +} + +<* +@param some stuff *> // #error: did you forget enclosing the description in + +fn int foo(int some){ + return some + 1; +} diff --git a/test/test_suite7/functions/param_with_comma_at_end.c3 b/test/test_suite7/functions/param_with_comma_at_end.c3 new file mode 100644 index 000000000..a83cde8b3 --- /dev/null +++ b/test/test_suite7/functions/param_with_comma_at_end.c3 @@ -0,0 +1,6 @@ +import std::io; + +fn void foo(int a,) +{ + +} \ No newline at end of file diff --git a/test/test_suite7/functions/pointer_escape.c3 b/test/test_suite7/functions/pointer_escape.c3 new file mode 100644 index 000000000..bdfc3144f --- /dev/null +++ b/test/test_suite7/functions/pointer_escape.c3 @@ -0,0 +1,24 @@ +int[?] foo = {1,2,3}; +fn int* bar(int index) +{ + int* array = &foo; + return &array[index]; +} + +fn int* baz(int index) +{ + int[] array = &foo; + return &array[index]; +} + +fn int* abc(int index) +{ + int[3] array; + return &array[1]; // #error: invalid once the function returns +} + +fn int* abc2(int index) +{ + int val; + return &val; // #error: invalid once the function returns +} \ No newline at end of file diff --git a/test/test_suite7/functions/raw_splat.c3t b/test/test_suite7/functions/raw_splat.c3t new file mode 100644 index 000000000..ccd1b8959 --- /dev/null +++ b/test/test_suite7/functions/raw_splat.c3t @@ -0,0 +1,146 @@ +// #target: macos-x64 +module rawsplat; + +int x; +macro void foo(...) +{ + $for (var $i = 0; $i < $vacount; $i++) + x += $vaarg[$i] * $i; + $endfor +} + +fn void main() +{ + int[3] y = { 33, 44, 55 }; + foo(...y); + foo(1, ...y); + int[] z = &y; + foo(...z[1..2]); + foo(1, ...z[1..2], 5); +} + +/* #expect: rawsplat.ll + +define void @rawsplat.main() #0 { +entry: + %y = alloca [3 x i32], align 4 + %.anon = alloca [3 x i32], align 4 + %.anon1 = alloca i32, align 4 + %.anon2 = alloca i32, align 4 + %.anon4 = alloca i32, align 4 + %.anon9 = alloca [3 x i32], align 4 + %.anon10 = alloca i32, align 4 + %.anon12 = alloca i32, align 4 + %.anon14 = alloca i32, align 4 + %z = alloca %"int[]", align 8 + %.anon23 = alloca i32, align 4 + %.anon25 = alloca i32, align 4 + %.anon31 = alloca i32, align 4 + %.anon33 = alloca i32, align 4 + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %y, ptr align 4 @.__const, i32 12, i1 false) + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %.anon, ptr align 4 %y, i32 12, i1 false) + %0 = load i32, ptr %.anon, align 4 + store i32 %0, ptr %.anon1, align 4 + %ptradd = getelementptr inbounds i8, ptr %.anon, i64 4 + %1 = load i32, ptr %ptradd, align 4 + store i32 %1, ptr %.anon2, align 4 + %ptradd3 = getelementptr inbounds i8, ptr %.anon, i64 8 + %2 = load i32, ptr %ptradd3, align 4 + store i32 %2, ptr %.anon4, align 4 + %3 = load i32, ptr @rawsplat.x, align 4 + %4 = load i32, ptr %.anon1, align 4 + %mul = mul i32 %4, 0 + %add = add i32 %3, %mul + store i32 %add, ptr @rawsplat.x, align 4 + %5 = load i32, ptr @rawsplat.x, align 4 + %6 = load i32, ptr %.anon2, align 4 + %mul5 = mul i32 %6, 1 + %add6 = add i32 %5, %mul5 + store i32 %add6, ptr @rawsplat.x, align 4 + %7 = load i32, ptr @rawsplat.x, align 4 + %8 = load i32, ptr %.anon4, align 4 + %mul7 = mul i32 %8, 2 + %add8 = add i32 %7, %mul7 + store i32 %add8, ptr @rawsplat.x, align 4 + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %.anon9, ptr align 4 %y, i32 12, i1 false) + %9 = load i32, ptr %.anon9, align 4 + store i32 %9, ptr %.anon10, align 4 + %ptradd11 = getelementptr inbounds i8, ptr %.anon9, i64 4 + %10 = load i32, ptr %ptradd11, align 4 + store i32 %10, ptr %.anon12, align 4 + %ptradd13 = getelementptr inbounds i8, ptr %.anon9, i64 8 + %11 = load i32, ptr %ptradd13, align 4 + store i32 %11, ptr %.anon14, align 4 + %12 = load i32, ptr @rawsplat.x, align 4 + %add15 = add i32 %12, 0 + store i32 %add15, ptr @rawsplat.x, align 4 + %13 = load i32, ptr @rawsplat.x, align 4 + %14 = load i32, ptr %.anon10, align 4 + %mul16 = mul i32 %14, 1 + %add17 = add i32 %13, %mul16 + store i32 %add17, ptr @rawsplat.x, align 4 + %15 = load i32, ptr @rawsplat.x, align 4 + %16 = load i32, ptr %.anon12, align 4 + %mul18 = mul i32 %16, 2 + %add19 = add i32 %15, %mul18 + store i32 %add19, ptr @rawsplat.x, align 4 + %17 = load i32, ptr @rawsplat.x, align 4 + %18 = load i32, ptr %.anon14, align 4 + %mul20 = mul i32 %18, 3 + %add21 = add i32 %17, %mul20 + store i32 %add21, ptr @rawsplat.x, align 4 + %19 = insertvalue %"int[]" undef, ptr %y, 0 + %20 = insertvalue %"int[]" %19, i64 3, 1 + store %"int[]" %20, ptr %z, align 8 + %21 = load %"int[]", ptr %z, align 8 + %22 = extractvalue %"int[]" %21, 0 + %ptradd22 = getelementptr inbounds i8, ptr %22, i64 4 + %23 = insertvalue %"int[]" undef, ptr %ptradd22, 0 + %24 = insertvalue %"int[]" %23, i64 2, 1 + %25 = extractvalue %"int[]" %24, 0 + %26 = load i32, ptr %25, align 4 + store i32 %26, ptr %.anon23, align 4 + %27 = extractvalue %"int[]" %24, 0 + %ptradd24 = getelementptr inbounds i8, ptr %27, i64 4 + %28 = load i32, ptr %ptradd24, align 4 + store i32 %28, ptr %.anon25, align 4 + %29 = load i32, ptr @rawsplat.x, align 4 + %30 = load i32, ptr %.anon23, align 4 + %mul26 = mul i32 %30, 0 + %add27 = add i32 %29, %mul26 + store i32 %add27, ptr @rawsplat.x, align 4 + %31 = load i32, ptr @rawsplat.x, align 4 + %32 = load i32, ptr %.anon25, align 4 + %mul28 = mul i32 %32, 1 + %add29 = add i32 %31, %mul28 + store i32 %add29, ptr @rawsplat.x, align 4 + %33 = load %"int[]", ptr %z, align 8 + %34 = extractvalue %"int[]" %33, 0 + %ptradd30 = getelementptr inbounds i8, ptr %34, i64 4 + %35 = insertvalue %"int[]" undef, ptr %ptradd30, 0 + %36 = insertvalue %"int[]" %35, i64 2, 1 + %37 = extractvalue %"int[]" %36, 0 + %38 = load i32, ptr %37, align 4 + store i32 %38, ptr %.anon31, align 4 + %39 = extractvalue %"int[]" %36, 0 + %ptradd32 = getelementptr inbounds i8, ptr %39, i64 4 + %40 = load i32, ptr %ptradd32, align 4 + store i32 %40, ptr %.anon33, align 4 + %41 = load i32, ptr @rawsplat.x, align 4 + %add34 = add i32 %41, 0 + store i32 %add34, ptr @rawsplat.x, align 4 + %42 = load i32, ptr @rawsplat.x, align 4 + %43 = load i32, ptr %.anon31, align 4 + %mul35 = mul i32 %43, 1 + %add36 = add i32 %42, %mul35 + store i32 %add36, ptr @rawsplat.x, align 4 + %44 = load i32, ptr @rawsplat.x, align 4 + %45 = load i32, ptr %.anon33, align 4 + %mul37 = mul i32 %45, 2 + %add38 = add i32 %44, %mul37 + store i32 %add38, ptr @rawsplat.x, align 4 + %46 = load i32, ptr @rawsplat.x, align 4 + %add39 = add i32 %46, 15 + store i32 %add39, ptr @rawsplat.x, align 4 + ret void +} diff --git a/test/test_suite7/functions/recursive_fn.c3 b/test/test_suite7/functions/recursive_fn.c3 new file mode 100644 index 000000000..a4f1b95b5 --- /dev/null +++ b/test/test_suite7/functions/recursive_fn.c3 @@ -0,0 +1,2 @@ + +def Foo = fn void(Foo* x); // #error: Recursive definition diff --git a/test/test_suite7/functions/recursive_through_generic.c3 b/test/test_suite7/functions/recursive_through_generic.c3 new file mode 100644 index 000000000..ebdb41ff8 --- /dev/null +++ b/test/test_suite7/functions/recursive_through_generic.c3 @@ -0,0 +1,14 @@ +module oups; +import std::collections::map; + +fn void main() +{ +} + +def FooFunc = fn void! (Bar); // #error: Recursive definition +def Foo = HashMap(); + +struct Bar +{ + Foo foo; +} \ No newline at end of file diff --git a/test/test_suite7/functions/returning_void.c3t b/test/test_suite7/functions/returning_void.c3t new file mode 100644 index 000000000..7e1a7732d --- /dev/null +++ b/test/test_suite7/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_suite7/functions/simple_test.c3t b/test/test_suite7/functions/simple_test.c3t new file mode 100644 index 000000000..2949cc5b1 --- /dev/null +++ b/test/test_suite7/functions/simple_test.c3t @@ -0,0 +1,30 @@ +// #target: macos-x64 + +fn int foo() +{ + char *pp; + uint w_cnt; + + w_cnt += *pp; + + return w_cnt; +} + +/* #expect: simple_test.ll + + +define i32 @simple_test.foo() #0 { +entry: + %pp = alloca ptr, align 8 + %w_cnt = alloca i32, align 4 + store ptr null, ptr %pp, align 8 + store i32 0, ptr %w_cnt, align 4 + %0 = load i32, ptr %w_cnt, align 4 + %1 = load ptr, ptr %pp, align 8 + %2 = load i8, ptr %1, align 1 + %zext = zext i8 %2 to i32 + %add = add i32 %0, %zext + store i32 %add, ptr %w_cnt, align 4 + %3 = load i32, ptr %w_cnt, align 4 + ret i32 %3 +} \ No newline at end of file diff --git a/test/test_suite7/functions/splat.c3t b/test/test_suite7/functions/splat.c3t new file mode 100644 index 000000000..dbd9710ab --- /dev/null +++ b/test/test_suite7/functions/splat.c3t @@ -0,0 +1,43 @@ +// #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 + + +declare i32 @sum_us(ptr, i64) #0 + + %varargslots = alloca [3 x i32], align 4 + %x = alloca [3 x i32], align 4 + %z = alloca %"int[]", align 8 + store i32 1, ptr %varargslots, align 4 + %ptradd = getelementptr inbounds i8, ptr %varargslots, i64 4 + store i32 2, ptr %ptradd, align 4 + %ptradd1 = getelementptr inbounds i8, ptr %varargslots, i64 8 + store i32 3, ptr %ptradd1, align 4 + %0 = call i32 @sum_us(ptr %varargslots, i64 3) + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %x, ptr align 4 @.__const, i32 12, i1 false) + %1 = insertvalue %"int[]" undef, ptr %x, 0 + %2 = insertvalue %"int[]" %1, i64 3, 1 + store %"int[]" %2, ptr %z, align 8 + %3 = insertvalue %"int[]" undef, ptr %x, 0 + %4 = insertvalue %"int[]" %3, i64 3, 1 + %5 = call i32 @sum_us(ptr %x, i64 3) + %lo = load ptr, ptr %z, align 8 + %ptradd2 = getelementptr inbounds i8, ptr %z, i64 8 + %hi = load i64, ptr %ptradd2, align 8 + %6 = call i32 @sum_us(ptr %lo, i64 %hi) + %7 = call i32 @sum_us(ptr null, i64 0) + ret void +} \ No newline at end of file diff --git a/test/test_suite7/functions/splat_aarch64.c3t b/test/test_suite7/functions/splat_aarch64.c3t new file mode 100644 index 000000000..70bd6e039 --- /dev/null +++ b/test/test_suite7/functions/splat_aarch64.c3t @@ -0,0 +1,57 @@ +// #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 + +; Function Attrs: +define void @splat.test() #0 { +entry: + %varargslots = alloca [3 x i32], align 4 + %taddr = alloca %"int[]", align 8 + %x = alloca [3 x i32], align 4 + %z = alloca %"int[]", align 8 + %taddr2 = alloca %"int[]", align 8 + %taddr3 = alloca %"int[]", align 8 + store i32 1, ptr %varargslots, align 4 + %ptradd = getelementptr inbounds i8, ptr %varargslots, i64 4 + store i32 2, ptr %ptradd, align 4 + %ptradd1 = getelementptr inbounds i8, ptr %varargslots, i64 8 + store i32 3, ptr %ptradd1, align 4 + %0 = insertvalue %"int[]" undef, ptr %varargslots, 0 + %"$$temp" = insertvalue %"int[]" %0, i64 3, 1 + store %"int[]" %"$$temp", ptr %taddr, align 8 + %1 = load [2 x i64], ptr %taddr, align 8 + %2 = call i32 @sum_us([2 x i64] %1) + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %x, ptr align 4 @.__const, i32 12, i1 false) + %3 = insertvalue %"int[]" undef, ptr %x, 0 + %4 = insertvalue %"int[]" %3, i64 3, 1 + store %"int[]" %4, ptr %z, align 8 + %5 = insertvalue %"int[]" undef, ptr %x, 0 + %6 = insertvalue %"int[]" %5, i64 3, 1 + store %"int[]" %6, ptr %taddr2, align 8 + %7 = load [2 x i64], ptr %taddr2, align 8 + %8 = call i32 @sum_us([2 x i64] %7) + %9 = load [2 x i64], ptr %z, align 8 + %10 = call i32 @sum_us([2 x i64] %9) + store %"int[]" zeroinitializer, ptr %taddr3, align 8 + %11 = load [2 x i64], ptr %taddr3, align 8 + %12 = call i32 @sum_us([2 x i64] %11) + ret void +} diff --git a/test/test_suite7/functions/splat_empty.c3t b/test/test_suite7/functions/splat_empty.c3t new file mode 100644 index 000000000..414b3f98d --- /dev/null +++ b/test/test_suite7/functions/splat_empty.c3t @@ -0,0 +1,12 @@ +import std::io; + +macro foo($Type, a, ..., bool b = true, float f = 123.f) { io::printfn("%s %s %s %s", $Type.nameof, a, b, f); } +macro bar($Type, a, ..., bool b, float f) { io::printfn("%s %s %s %s", $Type.nameof, a, b, f); } + +fn void main() +{ + foo(void*, 99, 0, b: false, f: 456.f); // OK + foo(void*, 99, /*0,*/ b: false, f: 456.f); // SEGFAULT + foo(void*, 99, 0, b: false, f: 456.f); // OK + bar(void*, 99, /*0,*/ b: false, f: 456.f); // SEGFAULT +} \ No newline at end of file diff --git a/test/test_suite7/functions/splat_init.c3t b/test/test_suite7/functions/splat_init.c3t new file mode 100644 index 000000000..13d82a87f --- /dev/null +++ b/test/test_suite7/functions/splat_init.c3t @@ -0,0 +1,40 @@ +// #target: macos-x64 +module splat; +import std; + +int a = 0; + +fn int[2] test() +{ + a++; + return { 2, 3 }; +} +fn void main() +{ + int[4] z = { a, ...test(), a }; +} + +/* #expect: splat.ll + +define void @splat.main() #0 { +entry: + %z = alloca [4 x i32], align 16 + %.anon = alloca [2 x i32], align 4 + %result = alloca [2 x i32], align 4 + %0 = load i32, ptr @splat.a, align 4 + store i32 %0, ptr %z, align 4 + %ptradd = getelementptr inbounds i8, ptr %z, i64 4 + %1 = call i64 @splat.test() + store i64 %1, ptr %result, align 4 + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %.anon, ptr align 4 %result, i32 8, i1 false) + %2 = load i32, ptr %.anon, align 4 + store i32 %2, ptr %ptradd, align 4 + %ptradd1 = getelementptr inbounds i8, ptr %z, i64 8 + %ptradd2 = getelementptr inbounds i8, ptr %.anon, i64 4 + %3 = load i32, ptr %ptradd2, align 4 + store i32 %3, ptr %ptradd1, align 4 + %ptradd3 = getelementptr inbounds i8, ptr %z, i64 12 + %4 = load i32, ptr @splat.a, align 4 + store i32 %4, ptr %ptradd3, align 4 + ret void +} diff --git a/test/test_suite7/functions/splat_mingw.c3t b/test/test_suite7/functions/splat_mingw.c3t new file mode 100644 index 000000000..4b49c2f44 --- /dev/null +++ b/test/test_suite7/functions/splat_mingw.c3t @@ -0,0 +1,51 @@ +// #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 + +declare i32 @sum_us(ptr align 8) #0 + +; Function Attrs: +define void @splat.test() #0 { +entry: + %varargslots = alloca [3 x i32], align 4 + %indirectarg = alloca %"int[]", align 8 + %x = alloca [3 x i32], align 4 + %z = alloca %"int[]", align 8 + %indirectarg2 = alloca %"int[]", align 8 + %indirectarg3 = alloca %"int[]", align 8 + %indirectarg4 = alloca %"int[]", align 8 + store i32 1, ptr %varargslots, align 4 + %ptradd = getelementptr inbounds i8, ptr %varargslots, i64 4 + store i32 2, ptr %ptradd, align 4 + %ptradd1 = getelementptr inbounds i8, ptr %varargslots, i64 8 + store i32 3, ptr %ptradd1, align 4 + %0 = insertvalue %"int[]" undef, ptr %varargslots, 0 + %"$$temp" = insertvalue %"int[]" %0, i64 3, 1 + store %"int[]" %"$$temp", ptr %indirectarg, align 8 + %1 = call i32 @sum_us(ptr align 8 %indirectarg) + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %x, ptr align 4 @.__const, i32 12, i1 false) + %2 = insertvalue %"int[]" undef, ptr %x, 0 + %3 = insertvalue %"int[]" %2, i64 3, 1 + store %"int[]" %3, ptr %z, align 8 + %4 = insertvalue %"int[]" undef, ptr %x, 0 + %5 = insertvalue %"int[]" %4, i64 3, 1 + store %"int[]" %5, ptr %indirectarg2, align 8 + %6 = call i32 @sum_us(ptr align 8 %indirectarg2) + call void @llvm.memcpy.p0.p0.i32(ptr align 8 %indirectarg3, ptr align 8 %z, i32 16, i1 false) + %7 = call i32 @sum_us(ptr align 8 %indirectarg3) + store %"int[]" zeroinitializer, ptr %indirectarg4, align 8 + %8 = call i32 @sum_us(ptr align 8 %indirectarg4) + ret void diff --git a/test/test_suite7/functions/splat_post_order.c3t b/test/test_suite7/functions/splat_post_order.c3t new file mode 100644 index 000000000..c5d2803cd --- /dev/null +++ b/test/test_suite7/functions/splat_post_order.c3t @@ -0,0 +1,12 @@ +macro @foo(..., bool a = true, bool b = false) +{ + return @foo2((void*)null, $vasplat, a: a, b: b); +} + +macro @foo2(x, ..., bool a = true, bool b = false) +{ } + +fn void main() +{ + @foo(1, 2, 3, 4, a: true, b: false); +} \ No newline at end of file diff --git a/test/test_suite7/functions/splat_raw.c3 b/test/test_suite7/functions/splat_raw.c3 new file mode 100644 index 000000000..6fd5fbed0 --- /dev/null +++ b/test/test_suite7/functions/splat_raw.c3 @@ -0,0 +1,8 @@ + + +extern fn void foo(int x, ...); + +fn void test(void*... y) +{ + foo(1, ...y); // #error: raw varargs +} \ No newline at end of file diff --git a/test/test_suite7/functions/splat_untyped.c3t b/test/test_suite7/functions/splat_untyped.c3t new file mode 100644 index 000000000..ab196aca6 --- /dev/null +++ b/test/test_suite7/functions/splat_untyped.c3t @@ -0,0 +1,39 @@ +// #target: macos-x64 +module test; +import std; +fn void main() +{ + var $a = { 1, 2, "abc" }; + io::printfn("Hello %s %s %s %s", 1, ...$a); +} + +/* #expect: test.ll + + %varargslots = alloca [4 x %any], align 16 + %taddr = alloca i32, align 4 + %taddr1 = alloca i32, align 4 + %taddr2 = alloca i32, align 4 + %taddr4 = alloca %"char[]", align 8 + %retparam = alloca i64, align 8 + store i32 1, ptr %taddr, align 4 + %0 = insertvalue %any undef, ptr %taddr, 0 + %1 = insertvalue %any %0, i64 ptrtoint (ptr @"$ct.int" to i64), 1 + store %any %1, ptr %varargslots, align 16 + store i32 1, ptr %taddr1, align 4 + %2 = insertvalue %any undef, ptr %taddr1, 0 + %3 = insertvalue %any %2, i64 ptrtoint (ptr @"$ct.int" to i64), 1 + %ptradd = getelementptr inbounds i8, ptr %varargslots, i64 16 + store %any %3, ptr %ptradd, align 16 + store i32 2, ptr %taddr2, align 4 + %4 = insertvalue %any undef, ptr %taddr2, 0 + %5 = insertvalue %any %4, i64 ptrtoint (ptr @"$ct.int" to i64), 1 + %ptradd3 = getelementptr inbounds i8, ptr %varargslots, i64 32 + store %any %5, ptr %ptradd3, align 16 + store %"char[]" { ptr @.str.1, i64 3 }, ptr %taddr4, align 8 + %6 = insertvalue %any undef, ptr %taddr4, 0 + %7 = insertvalue %any %6, i64 ptrtoint (ptr @"$ct.String" to i64), 1 + %ptradd5 = getelementptr inbounds i8, ptr %varargslots, i64 48 + store %any %7, ptr %ptradd5, align 16 + %8 = call i64 @std.io.printfn(ptr %retparam, ptr @.str, i64 17, ptr %varargslots, i64 4) + ret void +} diff --git a/test/test_suite7/functions/static_vars.c3t b/test/test_suite7/functions/static_vars.c3t new file mode 100644 index 000000000..fdb68c98c --- /dev/null +++ b/test/test_suite7/functions/static_vars.c3t @@ -0,0 +1,23 @@ +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 { +entry: + %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 +} \ No newline at end of file diff --git a/test/test_suite7/functions/test_regression.c3t b/test/test_suite7/functions/test_regression.c3t new file mode 100644 index 000000000..1ce3dda56 --- /dev/null +++ b/test/test_suite7/functions/test_regression.c3t @@ -0,0 +1,582 @@ +// #target: macos-x64 + +module test; +import test2; +import std::collections::list; +import std::collections::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; +} + +def oopsInt = test2::argh(); +def oopsDouble = test2::argh(); +def Argh = fn int(double, Bobo); +def 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; +} + +def 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; +} + +def getValueInt = test2::getValue(); +def getValueDouble = test2::getValue(); +def IntBlob = test2::Blob(); +def DoubleBlob = Blob(); +def getMultInt = test2::getMult(); +def getMultDouble = test2::getMult(); + +def IntArray = List(); +def 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.push(100); + array.push(200); + array.push(400); + array.push(600); + array.insert_at(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("1Vararg4splatA: %d\n", sum_us(...x)); + printf("%d\n", fro); + int[] z = &x; + int[3] de = { 1, 2, 3 }; + printf("Vararg4splatB: %d\n", sum_us(...&x)); + printf("Vararg4splatC: %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 *, ...); +def 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; +} + +def Bye = Hello; +def wat = wut; +def 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 } +%Bobo = type { i16, float, i16, i16, float, i16 } +%"int[]" = type { ptr, i64 } +%LinkedList = type { %any, i64, ptr, ptr } +%any = type { ptr, i64 } +%List = type { i64, i64, %any, ptr } +%Foo = type { i32, i32 } + +@"$ct.test.Bobo" = linkonce global %.introspect { i8 10, i64 0, ptr null, i64 20, i64 0, i64 6, [0 x i64] zeroinitializer }, align 8 +@"$ct.test.Blob" = linkonce global %.introspect { i8 10, i64 0, ptr null, i64 8, i64 0, i64 2, [0 x i64] zeroinitializer }, align 8 +@"$ct.test.Foor" = linkonce global %.introspect { i8 11, i64 0, ptr null, i64 16, i64 0, i64 2, [0 x i64] zeroinitializer }, align 8 +@"$ct.test.Foo2" = linkonce global %.introspect { i8 10, i64 0, ptr null, i64 4, i64 0, i64 1, [0 x i64] zeroinitializer }, align 8 +@"$ct.test.Foo" = linkonce global %.introspect { i8 10, i64 0, ptr null, i64 8, i64 0, i64 2, [0 x i64] zeroinitializer }, align 8 +@"$ct.int" = linkonce global %.introspect { i8 2, i64 0, ptr null, i64 4, i64 0, i64 0, [0 x i64] zeroinitializer }, align 8 +@"$ct.test.MyEnum" = linkonce global { i8, i64, ptr, i64, i64, i64, [3 x %"char[]"] } { i8 8, i64 0, ptr null, i64 4, i64 ptrtoint (ptr @"$ct.int" to i64), i64 3, [3 x %"char[]"] [%"char[]" { ptr @.enum.HELO, i64 4 }, %"char[]" { ptr @.enum.WORLD, i64 5 }, %"char[]" { ptr @.enum.BYE, i64 3 }] }, align 8 +@test_static.x = internal unnamed_addr global i32 1, align 4 + +define void @test.Foo2.printme(ptr %0) #0 { +entry: + %1 = load i32, ptr %0, align 4 + %2 = call i32 (ptr, ...) @printf(ptr @.str.21, i32 %1) + ret void +} + +; Function Attrs: +define i32 @test.Foo2.mutate(ptr %0) #0 { +entry: + %1 = call i32 (ptr, ...) @printf(ptr @.str.22) + %2 = load i32, ptr %0, align 4 + %add = add i32 %2, 1 + store i32 %add, ptr %0, align 4 + ret i32 %add +} + +; Function Attrs: +declare i32 @printf(ptr, ...) #0 + +; Function Attrs: +define void @test.helloWorld() #0 { +entry: + %0 = call i32 (ptr, ...) @printf(ptr @.str) + ret void +} + +; Function Attrs: +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: +define i32 @test.helo(double %0, ptr byval(%Bobo) align 8 %1) #0 { +entry: + %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 %de, ptr align 4 @.__const, i32 12, i1 false) + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %c, ptr align 4 %1, 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: +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: +define i32 @test.sum_us(ptr %0, i64 %1) #0 { +entry: + %x = alloca %"int[]", align 8 + %sum = alloca i32, align 4 + store ptr %0, ptr %x, align 8 + %ptradd = getelementptr inbounds i8, ptr %x, i64 8 + store i64 %1, ptr %ptradd, align 8 + store i32 0, ptr %sum, align 4 + %ptradd1 = getelementptr inbounds i8, ptr %x, i64 8 + %2 = load i64, ptr %ptradd1, 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 = load ptr, ptr %x, align 8 + %5 = load i32, ptr %4, align 4 + %6 = load %"int[]", ptr %x, align 8 + %7 = extractvalue %"int[]" %6, 0 + %8 = extractvalue %"int[]" %6, 1 + %sub = sub i64 %8, 1 + %9 = add i64 %sub, 1 + %size = sub i64 %9, 1 + %ptradd2 = getelementptr inbounds i8, ptr %7, i64 4 + %10 = insertvalue %"int[]" undef, ptr %ptradd2, 0 + %11 = insertvalue %"int[]" %10, i64 %size, 1 + %12 = call i32 @test.sum_us(ptr %ptradd2, i64 %size) + %add = add i32 %5, %12 + %add3 = add i32 %3, %add + store i32 %add3, ptr %sum, align 4 + %13 = load i32, ptr %sum, align 4 + ret i32 %13 +} + +; Function Attrs: +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 + store ptr %0, ptr %x, align 8 + %ptradd = getelementptr inbounds i8, ptr %x, i64 8 + store i64 %1, ptr %ptradd, 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 + %2 = load i32, ptr %i, align 4 + %sext = sext i32 %2 to i64 + %ptradd1 = getelementptr inbounds i8, ptr %x, i64 8 + %3 = load i64, ptr %ptradd1, align 8 + %lt = icmp slt i64 %sext, %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 = load ptr, ptr %x, align 8 + %6 = load i32, ptr %i, align 4 + %sext2 = sext i32 %6 to i64 + %ptroffset = getelementptr inbounds [4 x i8], ptr %5, i64 %sext2 + %7 = load i32, ptr %ptroffset, align 4 + %add = add i32 %4, %7 + store i32 %add, ptr %sum, align 4 + %8 = load i32, ptr %i, align 4 + %add3 = add i32 %8, 1 + store i32 %add3, ptr %i, align 4 + br label %loop.cond + +loop.exit: ; preds = %loop.cond + %9 = load i32, ptr %sum, align 4 + ret i32 %9 +} + +; Function Attrs: +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 + %ddx = alloca %Foo, align 4 + %fro = alloca i32, align 4 + %x = alloca [4 x i32], align 16 + %z = alloca %"int[]", align 8 + %de = alloca [3 x i32], align 4 + %varargslots = alloca [4 x i32], align 16 + %varargslots14 = alloca [1 x i32], align 4 + %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 40, i1 false) + call void @"std_collections_linkedlist$int$.LinkedList.push"(ptr %list, i32 10) + call void @"std_collections_linkedlist$int$.LinkedList.push"(ptr %list, i32 15) + call void @"std_collections_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_collections_linkedlist$int$.LinkedList.len"(ptr %list) #3 + %trunc = trunc i64 %4 to i32 + %lt = icmp slt i32 %3, %trunc + br i1 %lt, label %loop.body, label %loop.exit + +loop.body: ; preds = %loop.cond + %5 = load i32, ptr %i, align 4 + %sext = sext i32 %5 to i64 + %6 = call i32 @"std_collections_linkedlist$int$.LinkedList.get"(ptr %list, i64 %sext) + %7 = load i32, ptr %i, align 4 + %8 = call i32 (ptr, ...) @printf(ptr @.str.2, i32 %7, i32 %6) + %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_collections_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 40, i1 false) + call void @"std_collections_list$int$.List.push"(ptr %array, i32 100) + call void @"std_collections_list$int$.List.push"(ptr %array, i32 200) + call void @"std_collections_list$int$.List.push"(ptr %array, i32 400) + call void @"std_collections_list$int$.List.push"(ptr %array, i32 600) #3 + call void @"std_collections_list$int$.List.insert_at"(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_collections_list$int$.List.len"(ptr %array) #3 + %trunc3 = trunc i64 %13 to i32 + %lt4 = icmp slt i32 %12, %trunc3 + br i1 %lt4, label %loop.body5, label %loop.exit8 + +loop.body5: ; preds = %loop.cond2 + %14 = load i32, ptr %i1, align 4 + %sext6 = sext i32 %14 to i64 + %15 = call i32 @"std_collections_list$int$.List.get"(ptr %array, i64 %sext6) #3 + %16 = load i32, ptr %i1, align 4 + %17 = call i32 (ptr, ...) @printf(ptr @.str.5, i32 %16, i32 %15) + %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_collections_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 = load i32, ptr %a, align 4 + %20 = call i32 @"test2$int$.getValue"(i32 %19) + %21 = call i32 (ptr, ...) @printf(ptr @.str.8, i32 %20) + %22 = load double, ptr %b, align 8 + %23 = call double @"test2$double$.getValue"(double %22) + %24 = call i32 (ptr, ...) @printf(ptr @.str.9, double %23) + %25 = call i32 @"test2$int$.getMult"(i32 25) + %26 = call i32 (ptr, ...) @printf(ptr @.str.10, i32 %25) + %27 = call double @"test2$double$.getMult"(double 3.300000e+00) + %28 = call i32 (ptr, ...) @printf(ptr @.str.11, double %27) + call void @test.helloWorld() + store i32 0, ptr %ddx, align 4 + %ptradd = getelementptr inbounds i8, ptr %ddx, i64 4 + store i32 0, ptr %ptradd, 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) + %29 = load i32, ptr %fro, align 4 + %30 = insertvalue %"int[]" undef, ptr %x, 0 + %31 = insertvalue %"int[]" %30, i64 4, 1 + %32 = call i32 @test.sum_us(ptr %x, i64 4) + %33 = call i32 (ptr, ...) @printf(ptr @.str.13, i32 %32) + %add9 = add i32 %29, %33 + store i32 %add9, ptr %fro, align 4 + %34 = load i32, ptr %fro, align 4 + %35 = call i32 (ptr, ...) @printf(ptr @.str.14, i32 %34) + %36 = insertvalue %"int[]" undef, ptr %x, 0 + %37 = insertvalue %"int[]" %36, i64 4, 1 + store %"int[]" %37, ptr %z, align 8 + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %de, ptr align 4 @.__const.15, i32 12, i1 false) + %38 = insertvalue %"int[]" undef, ptr %x, 0 + %39 = insertvalue %"int[]" %38, i64 4, 1 + %40 = call i32 @test.sum_us(ptr %x, i64 4) + %41 = call i32 (ptr, ...) @printf(ptr @.str.16, i32 %40) + %lo = load ptr, ptr %z, align 8 + %ptradd10 = getelementptr inbounds i8, ptr %z, i64 8 + %hi = load i64, ptr %ptradd10, align 8 + %42 = call i32 @test.sum_us(ptr %lo, i64 %hi) + %43 = call i32 (ptr, ...) @printf(ptr @.str.17, i32 %42) + store i32 1, ptr %varargslots, align 4 + %ptradd11 = getelementptr inbounds i8, ptr %varargslots, i64 4 + store i32 2, ptr %ptradd11, align 4 + %ptradd12 = getelementptr inbounds i8, ptr %varargslots, i64 8 + store i32 4, ptr %ptradd12, align 4 + %ptradd13 = getelementptr inbounds i8, ptr %varargslots, i64 12 + store i32 5, ptr %ptradd13, align 4 + %44 = call i32 @test.sum_us(ptr %varargslots, i64 4) + %45 = call i32 (ptr, ...) @printf(ptr @.str.18, i32 %44) + store i32 1, ptr %varargslots14, align 4 + %46 = call i32 @test.sum_us(ptr %varargslots14, i64 1) + %47 = call i32 (ptr, ...) @printf(ptr @.str.19, i32 %46) + %48 = call i32 @test.sum_us(ptr null, i64 0) + %49 = call i32 (ptr, ...) @printf(ptr @.str.20, i32 %48) + 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 weak double @"foo$double$.check"(double %0) +entry: + %fmul = fmul double %0, %0 + ret double %fmul + +// #expect: test2.double.ll + +%Blob = type { double } +@"test2$double$.argh" = weak local_unnamed_addr global double 2.340000e+02, align 8 + +define weak double @"test2$double$.getMult"(double %0) +entry: + %fmul = fmul double %0, %0 + ret double %fmul + +define weak i32 @"test2$double$.hello"() +entry: + ret i32 1 + +define weak double @"test2$double$.getValue"(double %0) +entry: + %blob = alloca %Blob, align 8 + store double %0, ptr %blob, align 8 + %1 = load double, ptr %blob, align 8 + ret double %1 diff --git a/test/test_suite7/functions/test_regression_mingw.c3t b/test/test_suite7/functions/test_regression_mingw.c3t new file mode 100644 index 000000000..523a58acc --- /dev/null +++ b/test/test_suite7/functions/test_regression_mingw.c3t @@ -0,0 +1,650 @@ +// #target: mingw-x64 + +module test; +import test2; +import std::collections::list; +import std::collections::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; +} + + + +def oopsInt = test2::argh(); +def oopsDouble = test2::argh(); +def Argh = fn int(double, Bobo); +def 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; +} + +def 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; +} + +def getValueInt = test2::getValue(); +def getValueDouble = test2::getValue(); +def IntBlob = test2::Blob(); +def DoubleBlob = Blob(); +def getMultInt = test2::getMult(); +def getMultDouble = test2::getMult(); + +def IntArray = List(); +def 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.push(100); + array.push(200); + array.push(400); + array.push(600); + array.insert_at(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("1Vararg4splatA: %d\n", sum_us(...x)); + printf("%d\n", fro); + int[] z = &x; + int[3] de = { 1, 2, 3 }; + printf("Vararg4splatB: %d\n", sum_us(...&x)); + printf("Vararg4splatC: %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 *, ...); +def 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; +} + +def Bye = Hello; +def wat = wut; +def 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 } +%Bobo = type { i16, float, i16, i16, float, i16 } +%"int[]" = type { ptr, i64 } +%LinkedList = type { %any, i64, ptr, ptr } +%any = type { ptr, i64 } +%List = type { i64, i64, %any, ptr } +%Foo = type { i32, i32 } + +$"$ct.test.Bobo" = comdat any + +$"$ct.test.Blob" = comdat any + +$"$ct.test.Foor" = comdat any + +$"$ct.test.Foo2" = comdat any + +$"$ct.test.Foo" = comdat any + +$"$ct.int" = comdat any + +$"$ct.test.MyEnum" = comdat any + +@"$ct.test.Bobo" = linkonce global %.introspect { i8 10, i64 0, ptr null, i64 20, i64 0, i64 6, [0 x i64] zeroinitializer }, comdat, align 8 +@"$ct.test.Blob" = linkonce global %.introspect { i8 10, i64 0, ptr null, i64 8, i64 0, i64 2, [0 x i64] zeroinitializer }, comdat, align 8 +@"$ct.test.Foor" = linkonce global %.introspect { i8 11, i64 0, ptr null, i64 16, i64 0, i64 2, [0 x i64] zeroinitializer }, comdat, align 8 +@"$ct.test.Foo2" = linkonce global %.introspect { i8 10, i64 0, ptr null, i64 4, i64 0, i64 1, [0 x i64] zeroinitializer }, comdat, align 8 +@"$ct.test.Foo" = linkonce global %.introspect { i8 10, i64 0, ptr null, i64 8, i64 0, i64 2, [0 x i64] zeroinitializer }, comdat, align 8 +@.enum.HELO = internal constant [5 x i8] c"HELO\00", align 1 +@.enum.WORLD = internal constant [6 x i8] c"WORLD\00", align 1 +@.enum.BYE = internal constant [4 x i8] c"BYE\00", align 1 +@"$ct.int" = linkonce global %.introspect { i8 2, i64 0, ptr null, i64 4, i64 0, i64 0, [0 x i64] zeroinitializer }, comdat, align 8 +@"$ct.test.MyEnum" = linkonce global { i8, i64, ptr, i64, i64, i64, [3 x %"char[]"] } { i8 8, i64 0, ptr null, i64 4, i64 ptrtoint (ptr @"$ct.int" to i64), i64 3, [3 x %"char[]"] [%"char[]" { ptr @.enum.HELO, i64 4 }, %"char[]" { ptr @.enum.WORLD, i64 5 }, %"char[]" { ptr @.enum.BYE, i64 3 }] }, 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 [20 x i8] c"1Vararg4splatA: %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 [19 x i8] c"Vararg4splatB: %d\0A\00", align 1 +@.str.17 = private unnamed_addr constant [19 x i8] c"Vararg4splatC: %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: +define void @test.Foo2.printme(ptr %0) #0 { +entry: + %1 = load i32, ptr %0, align 4 + %2 = call i32 (ptr, ...) @printf(ptr @.str.21, i32 %1) + ret void +} + +; Function Attrs: +define i32 @test.Foo2.mutate(ptr %0) #0 { +entry: + %1 = call i32 (ptr, ...) @printf(ptr @.str.22) + %2 = load i32, ptr %0, align 4 + %add = add i32 %2, 1 + store i32 %add, ptr %0, align 4 + ret i32 %add +} + +; Function Attrs: +declare i32 @printf(ptr, ...) #0 + +; Function Attrs: +define void @test.helloWorld() #0 { +entry: + %0 = call i32 (ptr, ...) @printf(ptr @.str) + ret void +} + +; Function Attrs: +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: +define i32 @test.helo(double %0, ptr align 4 %1) #0 { +entry: + %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 %de, ptr align 4 @.__const, i32 12, i1 false) + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %c, ptr align 4 %1, 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: +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: +define i32 @test.sum_us(ptr align 8 %0) #0 { +entry: + %sum = alloca i32, align 4 + %indirectarg = alloca %"int[]", align 8 + store i32 0, ptr %sum, align 4 + %ptradd = getelementptr inbounds i8, ptr %0, i64 8 + %1 = load i64, ptr %ptradd, align 8 + %eq = icmp eq i64 0, %1 + br i1 %eq, label %if.then, label %if.exit + +if.then: ; preds = %entry + ret i32 0 + +if.exit: ; preds = %entry + %2 = load i32, ptr %sum, align 4 + %3 = load ptr, ptr %0, align 8 + %4 = load i32, ptr %3, align 4 + %5 = load %"int[]", ptr %0, align 8 + %6 = extractvalue %"int[]" %5, 0 + %7 = extractvalue %"int[]" %5, 1 + %sub = sub i64 %7, 1 + %8 = add i64 %sub, 1 + %size = sub i64 %8, 1 + %ptradd1 = getelementptr inbounds i8, ptr %6, i64 4 + %9 = insertvalue %"int[]" undef, ptr %ptradd1, 0 + %10 = insertvalue %"int[]" %9, i64 %size, 1 + store %"int[]" %10, ptr %indirectarg, align 8 + %11 = call i32 @test.sum_us(ptr align 8 %indirectarg) + %add = add i32 %4, %11 + %add2 = add i32 %2, %add + store i32 %add2, ptr %sum, align 4 + %12 = load i32, ptr %sum, align 4 + ret i32 %12 +} + +; Function Attrs: +define i32 @test.sumd(ptr align 8 %0) #0 { +entry: + %sum = alloca i32, align 4 + %i = alloca i32, align 4 + 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 + %sext = sext i32 %1 to i64 + %ptradd = getelementptr inbounds i8, ptr %0, i64 8 + %2 = load i64, ptr %ptradd, align 8 + %lt = icmp slt i64 %sext, %2 + %check = icmp slt i64 %2, 0 + %siui-lt = or i1 %check, %lt + br i1 %siui-lt, label %loop.body, label %loop.exit + +loop.body: ; preds = %loop.cond + %3 = load i32, ptr %sum, align 4 + %4 = load ptr, ptr %0, align 8 + %5 = load i32, ptr %i, align 4 + %sext1 = sext i32 %5 to i64 + %ptroffset = getelementptr inbounds [4 x i8], ptr %4, i64 %sext1 + %6 = load i32, ptr %ptroffset, align 4 + %add = add i32 %3, %6 + store i32 %add, ptr %sum, align 4 + %7 = load i32, ptr %i, align 4 + %add2 = add i32 %7, 1 + store i32 %add2, ptr %i, align 4 + br label %loop.cond + +loop.exit: ; preds = %loop.cond + %8 = load i32, ptr %sum, align 4 + ret i32 %8 +} + +; Function Attrs: +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 + %ddx = alloca %Foo, align 4 + %fro = alloca i32, align 4 + %x = alloca [4 x i32], align 16 + %indirectarg = alloca %"int[]", align 8 + %z = alloca %"int[]", align 8 + %de = alloca [3 x i32], align 4 + %indirectarg10 = alloca %"int[]", align 8 + %indirectarg11 = alloca %"int[]", align 8 + %varargslots = alloca [4 x i32], align 16 + %indirectarg15 = alloca %"int[]", align 8 + %varargslots16 = alloca [1 x i32], align 4 + %indirectarg18 = alloca %"int[]", align 8 + %indirectarg19 = 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 40, i1 false) + call void @"std_collections_linkedlist$int$.LinkedList.push"(ptr %list, i32 10) + call void @"std_collections_linkedlist$int$.LinkedList.push"(ptr %list, i32 15) + call void @"std_collections_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_collections_linkedlist$int$.LinkedList.len"(ptr %list) #3 + %trunc = trunc i64 %4 to i32 + %lt = icmp slt i32 %3, %trunc + br i1 %lt, label %loop.body, label %loop.exit + +loop.body: ; preds = %loop.cond + %5 = load i32, ptr %i, align 4 + %sext = sext i32 %5 to i64 + %6 = call i32 @"std_collections_linkedlist$int$.LinkedList.get"(ptr %list, i64 %sext) + %7 = load i32, ptr %i, align 4 + %8 = call i32 (ptr, ...) @printf(ptr @.str.2, i32 %7, i32 %6) + %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_collections_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 40, i1 false) + call void @"std_collections_list$int$.List.push"(ptr %array, i32 100) + call void @"std_collections_list$int$.List.push"(ptr %array, i32 200) + call void @"std_collections_list$int$.List.push"(ptr %array, i32 400) + call void @"std_collections_list$int$.List.push"(ptr %array, i32 600) #3 + call void @"std_collections_list$int$.List.insert_at"(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_collections_list$int$.List.len"(ptr %array) #3 + %trunc3 = trunc i64 %13 to i32 + %lt4 = icmp slt i32 %12, %trunc3 + br i1 %lt4, label %loop.body5, label %loop.exit8 + +loop.body5: ; preds = %loop.cond2 + %14 = load i32, ptr %i1, align 4 + %sext6 = sext i32 %14 to i64 + %15 = call i32 @"std_collections_list$int$.List.get"(ptr %array, i64 %sext6) #3 + %16 = load i32, ptr %i1, align 4 + %17 = call i32 (ptr, ...) @printf(ptr @.str.5, i32 %16, i32 %15) + %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_collections_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 = load i32, ptr %a, align 4 + %20 = call i32 @"test2$int$.getValue"(i32 %19) + %21 = call i32 (ptr, ...) @printf(ptr @.str.8, i32 %20) + %22 = load i64, ptr %b, align 8 + %23 = call double @"test2$double$.getValue"(i64 %22) + %24 = call i32 (ptr, ...) @printf(ptr @.str.9, double %23) + %25 = call i32 @"test2$int$.getMult"(i32 25) + %26 = call i32 (ptr, ...) @printf(ptr @.str.10, i32 %25) + %27 = call double @"test2$double$.getMult"(double 3.300000e+00) + %28 = call i32 (ptr, ...) @printf(ptr @.str.11, double %27) + call void @test.helloWorld() + store i32 0, ptr %ddx, align 4 + %ptradd = getelementptr inbounds i8, ptr %ddx, i64 4 + store i32 0, ptr %ptradd, 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) + %29 = load i32, ptr %fro, align 4 + %30 = insertvalue %"int[]" undef, ptr %x, 0 + %31 = insertvalue %"int[]" %30, i64 4, 1 + store %"int[]" %31, ptr %indirectarg, align 8 + %32 = call i32 @test.sum_us(ptr align 8 %indirectarg) + %33 = call i32 (ptr, ...) @printf(ptr @.str.13, i32 %32) + %add9 = add i32 %29, %33 + store i32 %add9, ptr %fro, align 4 + %34 = load i32, ptr %fro, align 4 + %35 = call i32 (ptr, ...) @printf(ptr @.str.14, i32 %34) + %36 = insertvalue %"int[]" undef, ptr %x, 0 + %37 = insertvalue %"int[]" %36, i64 4, 1 + store %"int[]" %37, ptr %z, align 8 + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %de, ptr align 4 @.__const.15, i32 12, i1 false) + %38 = insertvalue %"int[]" undef, ptr %x, 0 + %39 = insertvalue %"int[]" %38, i64 4, 1 + store %"int[]" %39, ptr %indirectarg10, align 8 + %40 = call i32 @test.sum_us(ptr align 8 %indirectarg10) + %41 = call i32 (ptr, ...) @printf(ptr @.str.16, i32 %40) + call void @llvm.memcpy.p0.p0.i32(ptr align 8 %indirectarg11, ptr align 8 %z, i32 16, i1 false) + %42 = call i32 @test.sum_us(ptr align 8 %indirectarg11) + %43 = call i32 (ptr, ...) @printf(ptr @.str.17, i32 %42) + store i32 1, ptr %varargslots, align 4 + %ptradd12 = getelementptr inbounds i8, ptr %varargslots, i64 4 + store i32 2, ptr %ptradd12, align 4 + %ptradd13 = getelementptr inbounds i8, ptr %varargslots, i64 8 + store i32 4, ptr %ptradd13, align 4 + %ptradd14 = getelementptr inbounds i8, ptr %varargslots, i64 12 + store i32 5, ptr %ptradd14, align 4 + %44 = insertvalue %"int[]" undef, ptr %varargslots, 0 + %"$$temp" = insertvalue %"int[]" %44, i64 4, 1 + store %"int[]" %"$$temp", ptr %indirectarg15, align 8 + %45 = call i32 @test.sum_us(ptr align 8 %indirectarg15) + %46 = call i32 (ptr, ...) @printf(ptr @.str.18, i32 %45) + store i32 1, ptr %varargslots16, align 4 + %47 = insertvalue %"int[]" undef, ptr %varargslots16, 0 + %"$$temp17" = insertvalue %"int[]" %47, i64 1, 1 + store %"int[]" %"$$temp17", ptr %indirectarg18, align 8 + %48 = call i32 @test.sum_us(ptr align 8 %indirectarg18) + %49 = call i32 (ptr, ...) @printf(ptr @.str.19, i32 %48) + store %"int[]" zeroinitializer, ptr %indirectarg19, align 8 + %50 = call i32 @test.sum_us(ptr align 8 %indirectarg19) + %51 = call i32 (ptr, ...) @printf(ptr @.str.20, i32 %50) + 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 +declare void @hello_world.hello() #0 +declare void @llvm.memset.p0.i64(ptr +declare void @"std_collections_linkedlist$int$.LinkedList.push"(ptr, i32) #0 +declare i64 @"std_collections_linkedlist$int$.LinkedList.len"(ptr) #0 +declare i32 @"std_collections_linkedlist$int$.LinkedList.get"(ptr, i64) #0 +declare void @"std_collections_linkedlist$int$.LinkedList.free"(ptr) #0 +declare void @"std_collections_list$int$.List.push"(ptr, i32) #0 +declare void @"std_collections_list$int$.List.insert_at"(ptr, i64, i32) #0 +declare i64 @"std_collections_list$int$.List.len"(ptr) #0 +declare i32 @"std_collections_list$int$.List.get"(ptr, i64) #0 +declare void @"std_collections_list$int$.List.free"(ptr) #0 +declare i32 @"test2$int$.getValue"(i32) #0 +declare double @"test2$double$.getValue"(i64) #0 +declare i32 @"test2$int$.getMult"(i32) #0 +declare double @"test2$double$.getMult"(double) #0 + +// #expect: hello_world.ll + +define void @hello_world.hello() #0 { +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 weak_odr 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" = weak_odr local_unnamed_addr global i32 234, comdat, align 4 + +define weak_odr i32 @"test2$int$.getMult"(i32 %0) +entry: + %mul = mul i32 %0, %0 + ret i32 %mul + +!llvm.module.flags = !{!0, !1, !2, !3, !4, !5} + +!0 = !{i32 2, !"Dwarf Version", i32 4} +!1 = !{i32 2, !"Debug Info Version", i32 3} +!2 = !{i32 2, !"wchar_size", i32 4} +!3 = !{i32 4, !"PIC Level", i32 2} +!4 = !{i32 1, !"uwtable", i32 2} +!5 = !{i32 2, !"frame-pointer", i32 2} \ No newline at end of file diff --git a/test/test_suite7/functions/too_many_params.c3 b/test/test_suite7/functions/too_many_params.c3 new file mode 100644 index 000000000..5b7a190ca --- /dev/null +++ b/test/test_suite7/functions/too_many_params.c3 @@ -0,0 +1,40 @@ +import std::io; +def Tester = fn int(int x, int y, int z); + +fn int test1( + int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, // 20 + int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, // + int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, // + int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, // + int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, // 100 + int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, // 120 + int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, // + int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, // + int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, // + int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, // 200 + int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, // 220 + int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, // 240 + int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, // #error: The number of params exceeded + int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, // + int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int // 300 +) { return 1; } + +fn int test2( + int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, // 20 + int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, // + int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, // + int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, // + int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, // 100 + int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, // 120 + int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, // + int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, // + int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, // + int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, // 200 + int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, // 220 + int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, // 240 + int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, // #error: The number of params exceeded + int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, // + int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, // 300 + int... x +) { return 1; } + diff --git a/test/test_suite7/functions/type_argument_live_1461.c3t b/test/test_suite7/functions/type_argument_live_1461.c3t new file mode 100644 index 000000000..1ac3ca69c --- /dev/null +++ b/test/test_suite7/functions/type_argument_live_1461.c3t @@ -0,0 +1,9 @@ +module test; +macro @test(uint value, #type) { + +} + +fn void main() +{ + @test(1, uint); +} diff --git a/test/test_suite7/functions/typeless_varargs.c3t b/test/test_suite7/functions/typeless_varargs.c3t new file mode 100644 index 000000000..e97238ddc --- /dev/null +++ b/test/test_suite7/functions/typeless_varargs.c3t @@ -0,0 +1,74 @@ +// #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 + +@"$ct.int" = linkonce global %.introspect { i8 2, i64 0, ptr null, i64 4, i64 0, i64 0, [0 x i64] zeroinitializer }, align 8 + +define void @test.retest(ptr %0, i64 %1) #0 { +entry: + %foo = alloca %"any[]", align 8 + store ptr %0, ptr %foo, align 8 + %ptradd = getelementptr inbounds i8, ptr %foo, i64 8 + store i64 %1, ptr %ptradd, align 8 + %lo = load ptr, ptr %foo, align 8 + %ptradd1 = getelementptr inbounds i8, ptr %foo, i64 8 + %hi = load i64, ptr %ptradd1, align 8 + call void @test.test(ptr %lo, i64 %hi) + ret void +} + +; Function Attrs: +define void @test.test(ptr %0, i64 %1) #0 { +entry: + %foo = alloca %"any[]", align 8 + store ptr %0, ptr %foo, align 8 + %ptradd = getelementptr inbounds i8, ptr %foo, i64 8 + store i64 %1, ptr %ptradd, align 8 + %2 = load ptr, ptr %foo, align 8 + %3 = load ptr, ptr %2, align 8 + %4 = load i32, ptr %3, align 4 + call void (ptr, ...) @printf(ptr @.str, i32 %4) + ret void +} + +; Function Attrs: +define i32 @main() #0 { +entry: + %i = alloca i32, align 4 + %varargslots = alloca [1 x %any], align 16 + %taddr = alloca i32, align 4 + %varargslots1 = alloca [1 x %any], align 16 + %taddr2 = alloca i32, align 4 + store i32 1, ptr %i, align 4 + store i32 1, ptr %taddr, align 4 + %0 = insertvalue %any undef, ptr %taddr, 0 + %1 = insertvalue %any %0, i64 ptrtoint (ptr @"$ct.int" to i64), 1 + store %any %1, ptr %varargslots, align 16 + call void @test.test(ptr %varargslots, i64 1) + store i32 1, ptr %taddr2, align 4 + %2 = insertvalue %any undef, ptr %taddr2, 0 + %3 = insertvalue %any %2, i64 ptrtoint (ptr @"$ct.int" to i64), 1 + store %any %3, ptr %varargslots1, align 16 + call void @test.retest(ptr %varargslots1, i64 1) + ret i32 1 +} \ No newline at end of file diff --git a/test/test_suite7/functions/unsplat_named.c3 b/test/test_suite7/functions/unsplat_named.c3 new file mode 100644 index 000000000..6e5ed0503 --- /dev/null +++ b/test/test_suite7/functions/unsplat_named.c3 @@ -0,0 +1,8 @@ +fn void test(int... abc, int a) +{ } + +fn void main() +{ + int[] b = { 1, 2 }; + test(...b, a: 123); +} \ No newline at end of file diff --git a/test/test_suite7/functions/vaarg_raw.c3 b/test/test_suite7/functions/vaarg_raw.c3 new file mode 100644 index 000000000..937f05b25 --- /dev/null +++ b/test/test_suite7/functions/vaarg_raw.c3 @@ -0,0 +1,8 @@ +import std; + +fn void main() +{} + +fn void bohoo(...) // #error: C-style variadic arguments +{ +} \ No newline at end of file diff --git a/test/test_suite7/functions/vararg_and_named_tests.c3 b/test/test_suite7/functions/vararg_and_named_tests.c3 new file mode 100644 index 000000000..eb9b038e2 --- /dev/null +++ b/test/test_suite7/functions/vararg_and_named_tests.c3 @@ -0,0 +1,53 @@ +// #target: macos-x64 +module foo; + +extern fn void printf(char* format, ...); + +fn void test(int x, int... y, int z = 2) +{ +} + +fn void test2(int x, int... y, int z) +{ +} + +fn void a() +{ + test(z: 32, 3); // #error: Named arguments must be placed after positional arguments +} + +fn void b() +{ + test(1, x: 3); // #error: The parameter 'x' was already set. +} + +fn void c() +{ + test(1); +} + +fn void d() +{ + test2(1, z: 3); + test2(1, 2, 3); // #error: Expected 'z: ...' after this argument +} + + +fn void single(int x) {} + +fn void e() +{ + single(); // #error: This call expected a parameter of type 'int' +} + +fn void multiple(int x, int y) {} + +fn void f() +{ + multiple(1); // #error: Expected 1 more argument after this one +} + +fn void g() +{ + multiple(); // #error: 'multiple' expects +} \ No newline at end of file diff --git a/test/test_suite7/functions/vararg_argument_fails.c3 b/test/test_suite7/functions/vararg_argument_fails.c3 new file mode 100644 index 000000000..1a7916389 --- /dev/null +++ b/test/test_suite7/functions/vararg_argument_fails.c3 @@ -0,0 +1,5 @@ +fn void foo5(..., ...) {} // #error: Only a single variadic parameter is allowed + +fn void foo6(int ..., int ...) {} // #error: Only a single variadic parameter is allowed + +fn void foo7(int... x, int ... y) {} // #error: Only a single variadic parameter is allowed \ No newline at end of file diff --git a/test/test_suite7/functions/varargs.c3t b/test/test_suite7/functions/varargs.c3t new file mode 100644 index 000000000..2571a65d5 --- /dev/null +++ b/test/test_suite7/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 + %zext = zext i1 %1 to i32 + call void (ptr, ...) @printf(ptr @.str.3, i32 %zext) + %2 = load i8, ptr %x1, align 1 + %sext = sext i8 %2 to i32 + call void (ptr, ...) @printf(ptr @.str.4, i32 %sext) + %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_suite7/functions/varargs_followed_by_named.c3t b/test/test_suite7/functions/varargs_followed_by_named.c3t new file mode 100644 index 000000000..73c89e108 --- /dev/null +++ b/test/test_suite7/functions/varargs_followed_by_named.c3t @@ -0,0 +1,94 @@ +// #target: macos-x64 +module foo; + +extern fn void printf(char* format, ...); + +fn void test(int x, int... y, int z = 2) +{ + printf("Got %d %d %d %d\n", x, (int)y.len, z, y[0]); +} +fn void test2(int x, y..., int z = 2) +{ + printf("Got %d %d %d\n", x, (int)y.len, z); +} + +fn void main() +{ + test(3, 4, 5, z: 123); + test2(3, 4, 5, z: 123); + test(3, 4, 5); + test2(3, 4, 5); +} + +/* #expect: foo.ll + +define void @foo.test(i32 %0, ptr %1, i64 %2, i32 %3) #0 { +entry: + %y = alloca %"int[]", align 8 + store ptr %1, ptr %y, align 8 + %ptradd = getelementptr inbounds i8, ptr %y, i64 8 + store i64 %2, ptr %ptradd, align 8 + %ptradd1 = getelementptr inbounds i8, ptr %y, i64 8 + %4 = load i64, ptr %ptradd1, align 8 + %trunc = trunc i64 %4 to i32 + %5 = load ptr, ptr %y, align 8 + %6 = load i32, ptr %5, align 4 + call void (ptr, ...) @printf(ptr @.str, i32 %0, i32 %trunc, i32 %3, i32 %6) + ret void +} + +; Function Attrs: +define void @foo.test2(i32 %0, ptr %1, i64 %2, i32 %3) #0 { +entry: + %y = alloca %"any[]", align 8 + store ptr %1, ptr %y, align 8 + %ptradd = getelementptr inbounds i8, ptr %y, i64 8 + store i64 %2, ptr %ptradd, align 8 + %ptradd1 = getelementptr inbounds i8, ptr %y, i64 8 + %4 = load i64, ptr %ptradd1, align 8 + %trunc = trunc i64 %4 to i32 + call void (ptr, ...) @printf(ptr @.str.1, i32 %0, i32 %trunc, i32 %3) + ret void +} + +; Function Attrs: +define void @foo.main() #0 { +entry: + %varargslots = alloca [2 x i32], align 4 + %varargslots1 = alloca [2 x %any], align 16 + %taddr = alloca i32, align 4 + %taddr2 = alloca i32, align 4 + %varargslots4 = alloca [2 x i32], align 4 + %varargslots6 = alloca [2 x %any], align 16 + %taddr7 = alloca i32, align 4 + %taddr8 = alloca i32, align 4 + store i32 4, ptr %varargslots, align 4 + %ptradd = getelementptr inbounds i8, ptr %varargslots, i64 4 + store i32 5, ptr %ptradd, align 4 + call void @foo.test(i32 3, ptr %varargslots, i64 2, i32 123) + store i32 4, ptr %taddr, align 4 + %0 = insertvalue %any undef, ptr %taddr, 0 + %1 = insertvalue %any %0, i64 ptrtoint (ptr @"$ct.int" to i64), 1 + store %any %1, ptr %varargslots1, align 16 + store i32 5, ptr %taddr2, align 4 + %2 = insertvalue %any undef, ptr %taddr2, 0 + %3 = insertvalue %any %2, i64 ptrtoint (ptr @"$ct.int" to i64), 1 + %ptradd3 = getelementptr inbounds i8, ptr %varargslots1, i64 16 + store %any %3, ptr %ptradd3, align 16 + call void @foo.test2(i32 3, ptr %varargslots1, i64 2, i32 123) + store i32 4, ptr %varargslots4, align 4 + %ptradd5 = getelementptr inbounds i8, ptr %varargslots4, i64 4 + store i32 5, ptr %ptradd5, align 4 + call void @foo.test(i32 3, ptr %varargslots4, i64 2, i32 2) + store i32 4, ptr %taddr7, align 4 + %4 = insertvalue %any undef, ptr %taddr7, 0 + %5 = insertvalue %any %4, i64 ptrtoint (ptr @"$ct.int" to i64), 1 + store %any %5, ptr %varargslots6, align 16 + store i32 5, ptr %taddr8, align 4 + %6 = insertvalue %any undef, ptr %taddr8, 0 + %7 = insertvalue %any %6, i64 ptrtoint (ptr @"$ct.int" to i64), 1 + %ptradd9 = getelementptr inbounds i8, ptr %varargslots6, i64 16 + store %any %7, ptr %ptradd9, align 16 + call void @foo.test2(i32 3, ptr %varargslots6, i64 2, i32 2) + ret void +} \ No newline at end of file diff --git a/test/test_suite7/functions/void_params.c3 b/test/test_suite7/functions/void_params.c3 new file mode 100644 index 000000000..e4d0053bb --- /dev/null +++ b/test/test_suite7/functions/void_params.c3 @@ -0,0 +1,2 @@ +fn void test(int, void) {} // #error: Parameters may not be of type 'void'. +extern fn void test3(void); // #error: C-style 'foo(void)' style argument declarations are not valid \ No newline at end of file diff --git a/test/test_suite7/generic/different_generic_def.c3 b/test/test_suite7/generic/different_generic_def.c3 new file mode 100644 index 000000000..d22e10dd4 --- /dev/null +++ b/test/test_suite7/generic/different_generic_def.c3 @@ -0,0 +1,21 @@ +module test; +import test2; +fn int main() +{ + Foo1() a; + return 0; +} + +module test2(); + +struct Foo +{ + Type f; +} + +module test2(); // #error: declarations of the generic + +struct Foo1 +{ + Type a; +} diff --git a/test/test_suite7/generic/enum_in_other_module.c3t b/test/test_suite7/generic/enum_in_other_module.c3t new file mode 100644 index 000000000..d80a9d76d --- /dev/null +++ b/test/test_suite7/generic/enum_in_other_module.c3t @@ -0,0 +1,104 @@ +// #target: macos-x64 +module test; +import foo; + +fn int main(String[] args) { + foo::bar(ONE); + return 0; +} + +enum Enum : int {ONE, TWO, THREE} + +module foo; +import std; +import test; + +fn void bar(Enum e) { + io::printn(e.nameof); +} + +/* #expect: foo.ll + +@.enum.ONE = internal constant [4 x i8] c"ONE\00", align 1 +@.enum.TWO = internal constant [4 x i8] c"TWO\00", align 1 +@.enum.THREE = internal constant [6 x i8] c"THREE\00", align 1 +@"$ct.int" = linkonce global %.introspect { i8 2, i64 0, ptr null, i64 4, i64 0, i64 0, [0 x i64] zeroinitializer }, align 8 +@"$ct.test.Enum" = linkonce global { i8, i64, ptr, i64, i64, i64, [3 x %"char[]"] } { i8 8, i64 0, ptr null, i64 4, i64 ptrtoint (ptr @"$ct.int" to i64), i64 3, [3 x %"char[]"] [%"char[]" { ptr @.enum.ONE, i64 3 }, %"char[]" { ptr @.enum.TWO, i64 3 }, %"char[]" { ptr @.enum.THREE, i64 5 }] }, align 8 + +; Function Attrs: nounwind uwtable +define void @foo.bar(i32 %0) #0 { +entry: + %x = alloca %"char[]", align 8 + %x1 = alloca %"char[]", align 8 + %len = alloca i64, align 8 + %error_var = alloca i64, align 8 + %x2 = alloca %"char[]", align 8 + %retparam = alloca i64, align 8 + %error_var4 = alloca i64, align 8 + %error_var10 = alloca i64, align 8 + %zext = zext i32 %0 to i64 + %ptroffset_any = getelementptr [16 x i8], ptr getelementptr inbounds + call void @llvm.memcpy.p0.p0.i32(ptr align 8 %x, ptr align 8 %ptroffset_any, i32 16, i1 false) + %1 = call ptr @std.io.stdout() + call void @llvm.memcpy.p0.p0.i32(ptr align 8 %x1, ptr align 8 %x, i32 16, i1 false) + call void @llvm.memcpy.p0.p0.i32(ptr align 8 %x2, ptr align 8 %x1, i32 16, i1 false) + %lo = load ptr, ptr %x2, align 8 + %ptradd = getelementptr inbounds i8, ptr %x2, i64 8 + %hi = load i64, ptr %ptradd, align 8 + %2 = call i64 @std.io.File.write(ptr %retparam, ptr %1, ptr %lo, i64 %hi) + %not_err = icmp eq i64 %2, 0 + %3 = call i1 @llvm.expect.i1(i1 %not_err, i1 true) + br i1 %3, label %after_check, label %assign_optional + +assign_optional: ; preds = %entry + store i64 %2, ptr %error_var, align 8 + br label %guard_block + +after_check: ; preds = %entry + br label %noerr_block + +guard_block: ; preds = %assign_optional + br label %voiderr + +noerr_block: ; preds = %after_check + %4 = load i64, ptr %retparam, align 8 + store i64 %4, ptr %len, align 8 + %5 = call i64 @std.io.File.write_byte(ptr %1, i8 zeroext 10) + %not_err5 = icmp eq i64 %5, 0 + %6 = call i1 @llvm.expect.i1(i1 %not_err5, i1 true) + br i1 %6, label %after_check7, label %assign_optional6 + +assign_optional6: ; preds = %noerr_block + store i64 %5, ptr %error_var4, align 8 + br label %guard_block8 + +after_check7: ; preds = %noerr_block + br label %noerr_block9 + +guard_block8: ; preds = %assign_optional6 + br label %voiderr + +noerr_block9: ; preds = %after_check7 + %7 = call i64 @std.io.File.flush(ptr %1) + %not_err11 = icmp eq i64 %7, 0 + %8 = call i1 @llvm.expect.i1(i1 %not_err11, i1 true) + br i1 %8, label %after_check13, label %assign_optional12 + +assign_optional12: ; preds = %noerr_block9 + store i64 %7, ptr %error_var10, align 8 + br label %guard_block14 + +after_check13: ; preds = %noerr_block9 + br label %noerr_block15 + +guard_block14: ; preds = %assign_optional12 + br label %voiderr + +noerr_block15: ; preds = %after_check13 + %9 = load i64, ptr %len, align 8 + %add = add i64 %9, 1 + br label %voiderr + +voiderr: ; preds = %noerr_block15, %guard_block14, %guard_block8, %guard_block + ret void +} \ No newline at end of file diff --git a/test/test_suite7/generic/enum_set_test.c3t b/test/test_suite7/generic/enum_set_test.c3t new file mode 100644 index 000000000..6ce014982 --- /dev/null +++ b/test/test_suite7/generic/enum_set_test.c3t @@ -0,0 +1,88 @@ +// #target: macos-x64 +module test; +import std::io; +import std::collections::enumset; + +def AbcEnumSet = EnumSet(); + +enum Abc +{ + HELLO, + WORLD +} +fn void main() +{ + AbcEnumSet set; + io::printf("Has WORLD: %s\n", set.has(Abc.WORLD)); + set.add(Abc.HELLO); + io::printf("Has WORLD: %s\n", set.has(Abc.WORLD)); + set.add(Abc.WORLD); + io::printf("Has WORLD: %s\n", set.has(Abc.WORLD)); + AbcEnumSet set2; + set2.add_all(set); + io::printf("Has WORLD: %s\n", set2.has(Abc.WORLD)); + set.remove_all(set2); + io::printf("Has WORLD: %s\n", set.has(Abc.WORLD)); +} + +/* #expect: test.ll + +define void @test.main() #0 { +entry: + %set = alloca i32, align 4 + %varargslots = alloca [1 x %any], align 16 + %taddr = alloca i8, align 1 + %retparam = alloca i64, align 8 + %varargslots1 = alloca [1 x %any], align 16 + %taddr2 = alloca i8, align 1 + %retparam3 = alloca i64, align 8 + %varargslots4 = alloca [1 x %any], align 16 + %taddr5 = alloca i8, align 1 + %retparam6 = alloca i64, align 8 + %set2 = alloca i32, align 4 + %varargslots7 = alloca [1 x %any], align 16 + %taddr8 = alloca i8, align 1 + %retparam9 = alloca i64, align 8 + %varargslots10 = alloca [1 x %any], align 16 + %taddr11 = alloca i8, align 1 + %retparam12 = alloca i64, align 8 + store i32 0, ptr %set, align 4 + %0 = call i8 @"std_collections_enumset$test.Abc$.EnumSet.has"(ptr %set, i32 1) + store i8 %0, ptr %taddr, align 1 + %1 = insertvalue %any undef, ptr %taddr, 0 + %2 = insertvalue %any %1, i64 ptrtoint (ptr @"$ct.bool" to i64), 1 + store %any %2, ptr %varargslots, align 16 + %3 = call i64 @std.io.printf(ptr %retparam, ptr @.str, i64 14, ptr %varargslots, i64 1) + call void @"std_collections_enumset$test.Abc$.EnumSet.add"(ptr %set, i32 0) + %4 = call i8 @"std_collections_enumset$test.Abc$.EnumSet.has"(ptr %set, i32 1) + store i8 %4, ptr %taddr2, align 1 + %5 = insertvalue %any undef, ptr %taddr2, 0 + %6 = insertvalue %any %5, i64 ptrtoint (ptr @"$ct.bool" to i64), 1 + store %any %6, ptr %varargslots1, align 16 + %7 = call i64 @std.io.printf(ptr %retparam3, ptr @.str.1, i64 14, ptr %varargslots1, i64 1) + call void @"std_collections_enumset$test.Abc$.EnumSet.add"(ptr %set, i32 1) + %8 = call i8 @"std_collections_enumset$test.Abc$.EnumSet.has"(ptr %set, i32 1) + store i8 %8, ptr %taddr5, align 1 + %9 = insertvalue %any undef, ptr %taddr5, 0 + %10 = insertvalue %any %9, i64 ptrtoint (ptr @"$ct.bool" to i64), 1 + store %any %10, ptr %varargslots4, align 16 + %11 = call i64 @std.io.printf(ptr %retparam6, ptr @.str.2, i64 14, ptr %varargslots4, i64 1) + store i32 0, ptr %set2, align 4 + %12 = load i32, ptr %set, align 4 + call void @"std_collections_enumset$test.Abc$.EnumSet.add_all"(ptr %set2, i32 %12) + %13 = call i8 @"std_collections_enumset$test.Abc$.EnumSet.has"(ptr %set2, i32 1) + store i8 %13, ptr %taddr8, align 1 + %14 = insertvalue %any undef, ptr %taddr8, 0 + %15 = insertvalue %any %14, i64 ptrtoint (ptr @"$ct.bool" to i64), 1 + store %any %15, ptr %varargslots7, align 16 + %16 = call i64 @std.io.printf(ptr %retparam9, ptr @.str.3, i64 14, ptr %varargslots7, i64 1) + %17 = load i32, ptr %set2, align 4 + call void @"std_collections_enumset$test.Abc$.EnumSet.remove_all"(ptr %set, i32 %17) + %18 = call i8 @"std_collections_enumset$test.Abc$.EnumSet.has"(ptr %set, i32 1) + store i8 %18, ptr %taddr11, align 1 + %19 = insertvalue %any undef, ptr %taddr11, 0 + %20 = insertvalue %any %19, i64 ptrtoint (ptr @"$ct.bool" to i64), 1 + store %any %20, ptr %varargslots10, align 16 + %21 = call i64 @std.io.printf(ptr %retparam12, ptr @.str.4, i64 14, ptr %varargslots10, i64 1) + ret void +} diff --git a/test/test_suite7/generic/generic_builtin.c3t b/test/test_suite7/generic/generic_builtin.c3t new file mode 100644 index 000000000..5643b3c2d --- /dev/null +++ b/test/test_suite7/generic/generic_builtin.c3t @@ -0,0 +1,16 @@ +module add(); +fn Type add(Type a, Type b) @builtin => + a + b; + +module iadd; +fn int iadd(int a, int b) @builtin => + a + b; + +module main; +import std::io, add, iadd; + +fn void main() +{ + io::printfn("%s", iadd(1,2)); // Fine + io::printfn("%s", add()(1,2)); // Error +} \ No newline at end of file diff --git a/test/test_suite7/generic/generic_copy.c3t b/test/test_suite7/generic/generic_copy.c3t new file mode 100644 index 000000000..ade578db9 --- /dev/null +++ b/test/test_suite7/generic/generic_copy.c3t @@ -0,0 +1,12 @@ +module foo(); + +fn void abc() +{ + int i; + defer { i++; } +} + +module tester; +import foo; + +def abc_my = foo::abc(); \ No newline at end of file diff --git a/test/test_suite7/generic/generic_cyclic.c3 b/test/test_suite7/generic/generic_cyclic.c3 new file mode 100644 index 000000000..b94285bd7 --- /dev/null +++ b/test/test_suite7/generic/generic_cyclic.c3 @@ -0,0 +1,17 @@ +// #target: macos-x64 +module test; +import bar; + +def BazTest = Baz(); // #error: Recursive definition of 'BazTest' + +struct Test +{ + BazTest t; +} + +module bar(); + +struct Baz +{ + Test a; +} \ No newline at end of file diff --git a/test/test_suite7/generic/generic_idents.c3t b/test/test_suite7/generic/generic_idents.c3t new file mode 100644 index 000000000..d8293e9b6 --- /dev/null +++ b/test/test_suite7/generic/generic_idents.c3t @@ -0,0 +1,71 @@ +// #target: macos-aarch64 +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; + +def intMult = gen::mult(); +def 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 weak i32 @"gen$int$.mult"(i32 %0) #0 { +entry: + %mul = mul i32 %0, %0 + ret i32 %mul +} + +define weak 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 extern_weak i32 @"gen$int$.mult"(i32) + +declare extern_weak double @"gen$double$.addMult"(double, double, double) + +// #expect: gen.double.ll + + +define weak double @"gen$double$.addMult"(double %0, double %1, double %2) +entry: + %fmul = fmul double %0, %1 + %fadd = fadd double %fmul, %2 + ret double %fadd diff --git a/test/test_suite7/generic/generic_interface.c3t b/test/test_suite7/generic/generic_interface.c3t new file mode 100644 index 000000000..6a9b2ef6f --- /dev/null +++ b/test/test_suite7/generic/generic_interface.c3t @@ -0,0 +1,31 @@ +// #target: macos-aarch64 +module base; + +module test(); +import base; +interface Zzz +{ + fn void zzz(MyType t); +} +struct TestStruct (Zzz) +{ + String data; +} +fn void TestStruct.zzz(&self, MyType t) @dynamic { } + +module app; +import test; +fn int main() +{ + TestStruct() ts; + return 0; +} + +/* #expect: app.ll + +define i32 @main() #0 { +entry: + %ts = alloca %TestStruct, align 8 + call void @llvm.memset.p0.i64(ptr align 8 %ts, i8 0, i64 16, i1 false) + ret i32 0 +} diff --git a/test/test_suite7/generic/generic_lambda_complex.c3t b/test/test_suite7/generic/generic_lambda_complex.c3t new file mode 100644 index 000000000..e10d53993 --- /dev/null +++ b/test/test_suite7/generic/generic_lambda_complex.c3t @@ -0,0 +1,249 @@ +// #target: macos-x64 +// #deprecation: no + +<* @require Type.kindof == STRUCT *> +module abc(); +import std::io; +import std::collections::list; + +def TextTagList = List(); + +fault TextError +{ + UNTERMINATED_TAG, + EMPTY_TAG, + MISSING_TAG, + UNSUPPORTED_TAG, +} + +enum TextTagKind: char +{ + STRING, + TEMPLATE, +} + +struct TextTemplate +{ + Allocator allocator; + String template; + TextTag[] tags; + Type data; +} + +struct TextTag +{ + usz start; + usz end; + TextTagKind kind; + union { + String* data; + TextTemplate* template; + } +} + +<* + @require self.tags.len == 0 "template already initialized" + @require tag_start != tag_end + *> +fn void! TextTemplate.init(&self, String template, String tag_start = "{{", String tag_end = "}}", Allocator using = allocator::heap()) +{ + + TextTagList tags; + String tmpl = template; + uptr data = (uptr)&self.data; + while (true) + { + usz! start = tmpl.index_of(tag_start); + if (catch start) break; + tmpl = tmpl[start + tag_start.len..]; + + usz! end = tmpl.index_of(tag_end); + if (catch end) return TextError.UNTERMINATED_TAG?; + String name = tmpl[:end].trim(); + if (name == "") return TextError.EMPTY_TAG?; + // Check that the tag exists in the data struct. + TextTag tag = {| + $foreach ($m : Type.membersof) + if (name == $m.nameof) + { + $switch ($m.typeid) + $case String.typeid: + return (TextTag){ + .kind = STRING, + .data = (String*)(data + $m.offsetof), + }; + $default: + $if $defined($m.get(self.data).as_stream): + return (TextTag){ + .kind = TEMPLATE, + .template = self.data.$eval($m.nameof).as_stream(), + }; + $endif + $endswitch + //return TextError.UNSUPPORTED_TAG?; + } + $endforeach + return TextError.MISSING_TAG?; + |}!; + tmpl = tmpl[end + tag_end.len..]; + + tag.start = start; + tag.end = start + tag_start.len + end + tag_end.len; + tags.push(tag); + } + + *self = { .allocator = using, .template = template, .tags = tags.array_view() }; +} + +fn void! TextTemplate.free(&self) +{ + allocator::free(self.allocator, self.tags); + *self = {}; +} + +fn usz! TextTemplate.write_to(&self, OutStream writer) +{ + usz n; + usz pos; + foreach (tag : self.tags) + { + n += writer.write(self.template[pos:tag.start])!; + pos += tag.end; + n += tag.write(writer)!; + } + n += writer.write(self.template[pos..])!; + return n; +} + +fn usz! TextTag.write(&self, OutStream writer) +{ + switch (self.kind) + { + case STRING: + return writer.write(*self.data); + case TEMPLATE: + return self.template.write_to(writer); + } +} + +module text_test; +import abc; +import std::io; + +def Tmpl = TextTemplate(); + +struct Data +{ + String user; + String world; + bool ok; +} + + + +def FooTmpl = TextTemplate(); +def BarTmpl = TextTemplate(); + +struct Foo +{ + String foo; + BarTmpl* bar; +} + +struct Bar +{ + String bar; +} + +fn void main() +{ + + String foo_tmpl = "<<{{foo}} | {{bar}}>>"; + FooTmpl ft; + ft.init(foo_tmpl, using: allocator::temp())!!; + defer ft.free()!!; + + +} + +/* #expect: text_test.ll + +define void @text_test.main() #0 { +entry: + %foo_tmpl = alloca %"char[]", align 8 + %ft = alloca %TextTemplate, align 8 + %error_var = alloca i64, align 8 + %indirectarg = alloca %"char[]", align 8 + %indirectarg1 = alloca %any, align 8 + %varargslots = alloca [1 x %any], align 16 + %indirectarg2 = alloca %"any[]", align 8 + %error_var3 = alloca i64, align 8 + %varargslots8 = alloca [1 x %any], align 16 + %indirectarg10 = alloca %"any[]", align 8 + store %"char[]" { ptr @.str, i64 21 }, ptr %foo_tmpl, align 8 + call void @llvm.memset.p0.i64(ptr align 8 %ft, i8 0, i64 72, i1 false) + %0 = load ptr, ptr @std.core.mem.allocator.thread_temp_allocator, align 8 + %i2nb = icmp eq ptr %0, null + br i1 %i2nb, label %if.then, label %if.exit + +if.then: ; preds = %entry + call void @std.core.mem.allocator.init_default_temp_allocators() + br label %if.exit + +if.exit: ; preds = %if.then, %entry + %1 = load ptr, ptr @std.core.mem.allocator.thread_temp_allocator, align 8 + %2 = insertvalue %any undef, ptr %1, 0 + %3 = insertvalue %any %2, i64 ptrtoint (ptr @"$ct.std.core.mem.allocator.TempAllocator" to i64), 1 + %lo = load ptr, ptr %foo_tmpl, align 8 + %ptradd = getelementptr inbounds i8, ptr %foo_tmpl, i64 8 + %hi = load i64, ptr %ptradd, align 8 + store %"char[]" { ptr @.str.2, i64 2 }, ptr %indirectarg, align 8 + store %any %3, ptr %indirectarg1, align 8 + %4 = call i64 @"abc$text_test.Foo$.TextTemplate.init"(ptr %ft, ptr %lo, i64 %hi, ptr @.str.1, i64 2, ptr byval(%"char[]") align 8 %indirectarg, ptr byval(%any) align 8 %indirectarg1) + %not_err = icmp eq i64 %4, 0 + %5 = call i1 @llvm.expect.i1(i1 %not_err, i1 true) + br i1 %5, label %after_check, label %assign_optional + +assign_optional: ; preds = %if.exit + store i64 %4, ptr %error_var, align 8 + br label %panic_block + +after_check: ; preds = %if.exit + br label %noerr_block + +panic_block: ; preds = %assign_optional + %6 = insertvalue %any undef, ptr %error_var, 0 + %7 = insertvalue %any %6, i64 ptrtoint (ptr @"$ct.anyfault" to i64), 1 + store %any %7, ptr %varargslots, align 16 + %8 = insertvalue %"any[]" undef, ptr %varargslots, 0 + %"$$temp" = insertvalue %"any[]" %8, i64 1, 1 + store %"any[]" %"$$temp", ptr %indirectarg2, align 8 + call void @std.core.builtin.panicf(ptr @.panic_msg, i64 36, ptr @.file, i64 25, ptr @.func, i64 4, i32 161, ptr byval(%"any[]") align 8 %indirectarg2) + unreachable + +noerr_block: ; preds = %after_check + %9 = call i64 @"abc$text_test.Foo$.TextTemplate.free"(ptr %ft) + %not_err4 = icmp eq i64 %9, 0 + %10 = call i1 @llvm.expect.i1(i1 %not_err4, i1 true) + br i1 %10, label %after_check6, label %assign_optional5 + +assign_optional5: ; preds = %noerr_block + store i64 %9, ptr %error_var3, align 8 + br label %panic_block7 + +after_check6: ; preds = %noerr_block + br label %noerr_block11 + +panic_block7: ; preds = %assign_optional5 + %11 = insertvalue %any undef, ptr %error_var3, 0 + %12 = insertvalue %any %11, i64 ptrtoint (ptr @"$ct.anyfault" to i64), 1 + store %any %12, ptr %varargslots8, align 16 + %13 = insertvalue %"any[]" undef, ptr %varargslots8, 0 + %"$$temp9" = insertvalue %"any[]" %13, i64 1, 1 + store %"any[]" %"$$temp9", ptr %indirectarg10, align 8 + call void @std.core.builtin.panicf(ptr @.panic_msg, i64 36, ptr @.file, i64 25, ptr @.func, i64 4, i32 162, ptr byval(%"any[]") align 8 %indirectarg10) + unreachable + +noerr_block11: ; preds = %after_check6 + ret void +} diff --git a/test/test_suite7/generic/generic_local.c3 b/test/test_suite7/generic/generic_local.c3 new file mode 100644 index 000000000..6bd601425 --- /dev/null +++ b/test/test_suite7/generic/generic_local.c3 @@ -0,0 +1,23 @@ +module testing; +import std::io; +import foo; + +def Foo = foo::Foo; + +fn void main() +{ + Foo f; +} + +module foo; +import foo::private; + +// Bug #856 +distinct Foo = inline PrivateFoo(); // #error: could not be found + +module foo::private() @local; + +struct PrivateFoo +{ + Type x; +} \ No newline at end of file diff --git a/test/test_suite7/generic/generic_num.c3t b/test/test_suite7/generic/generic_num.c3t new file mode 100644 index 000000000..3833d9068 --- /dev/null +++ b/test/test_suite7/generic/generic_num.c3t @@ -0,0 +1,35 @@ +// #target: macos-x64 +module hello(); + +fn Type x(Type t) +{ + return t * t + FOO; +} + +module test; +import hello; +def xint = hello::x(); + +import std::io; + +fn void main() +{ + io::printfn("%d", xint(4)); +} + +/* #expect: test.ll + +define void @test.main() #0 { +entry: + %varargslots = alloca [1 x %any], align 16 + %taddr = alloca i32, align 4 + %retparam = alloca i64, align 8 + %0 = call i32 @"hello$int$_123$.x"(i32 4) + store i32 %0, ptr %taddr, align 4 + %1 = insertvalue %any undef, ptr %taddr, 0 + %2 = insertvalue %any %1, i64 ptrtoint (ptr @"$ct.int" to i64), 1 + store %any %2, ptr %varargslots, align 16 + %3 = call i64 @std.io.printfn(ptr %retparam, ptr @.str, i64 2, ptr %varargslots, i64 1) + ret void +} + diff --git a/test/test_suite7/generic/generic_over_fn.c3t b/test/test_suite7/generic/generic_over_fn.c3t new file mode 100644 index 000000000..156627ce2 --- /dev/null +++ b/test/test_suite7/generic/generic_over_fn.c3t @@ -0,0 +1,207 @@ +// #target: macos-x64 +module test_generic(); + +fn void sort(Type list, isz, isz, Func cmp) +{} + +module sort_test; +import std::sort; +import test_generic; + +macro quicksort(list, cmp = null) +{ + var $Type = $typeof(list); + var $CmpType = $typeof(cmp); + usz len = sort::len_from_list(list); + test_generic::sort(<$Type, $CmpType>)(list, 0, (isz)len - 1, cmp); +} + +fn void quicksort_with_value() @nostrip +{ + int[][] tcases = { + {}, + {10, 3}, + {3, 2, 1}, + {1, 2, 3}, + {2, 1, 3}, + }; + + foreach (tc : tcases) + { + quicksort(tc, &cmp_int_value); + } +} + +fn void quicksort_with_value2() @nostrip +{ + int[][] tcases = { + {}, + {10, 3}, + {3, 2, 1}, + {1, 2, 3}, + {2, 1, 3}, + }; + + foreach (tc : tcases) + { + quicksort(tc, &cmp_int_value2); + } +} + +fn int cmp_int_value(int x, int y) { + return x - y; +} + +fn int cmp_int_value2(int x, int y) { + return x - y; +} + +/* #expect: sort_test.ll + +define void @sort_test.quicksort_with_value() #0 { +entry: + %tcases = alloca %"int[][]", align 8 + %literal = alloca [5 x %"int[]"], align 16 + %literal1 = alloca [2 x i32], align 4 + %literal3 = alloca [3 x i32], align 4 + %literal5 = alloca [3 x i32], align 4 + %literal7 = alloca [3 x i32], align 4 + %.anon = alloca i64, align 8 + %tc = alloca %"int[]", align 8 + %list = alloca %"int[]", align 8 + %len = alloca i64, align 8 + %list9 = alloca %"int[]", align 8 + store %"int[]" zeroinitializer, ptr %literal, align 8 + %ptradd = getelementptr inbounds i8, ptr %literal, i64 16 + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %literal1, ptr align 4 @.__const, i32 8, i1 false) + %0 = insertvalue %"int[]" undef, ptr %literal1, 0 + %1 = insertvalue %"int[]" %0, i64 2, 1 + store %"int[]" %1, ptr %ptradd, align 8 + %ptradd2 = getelementptr inbounds i8, ptr %literal, i64 32 + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %literal3, ptr align 4 @.__const.1, i32 12, i1 false) + %2 = insertvalue %"int[]" undef, ptr %literal3, 0 + %3 = insertvalue %"int[]" %2, i64 3, 1 + store %"int[]" %3, ptr %ptradd2, align 8 + %ptradd4 = getelementptr inbounds i8, ptr %literal, i64 48 + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %literal5, ptr align 4 @.__const.2, i32 12, i1 false) + %4 = insertvalue %"int[]" undef, ptr %literal5, 0 + %5 = insertvalue %"int[]" %4, i64 3, 1 + store %"int[]" %5, ptr %ptradd4, align 8 + %ptradd6 = getelementptr inbounds i8, ptr %literal, i64 64 + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %literal7, ptr align 4 @.__const.3, i32 12, i1 false) + %6 = insertvalue %"int[]" undef, ptr %literal7, 0 + %7 = insertvalue %"int[]" %6, i64 3, 1 + store %"int[]" %7, ptr %ptradd6, align 8 + %8 = insertvalue %"int[][]" undef, ptr %literal, 0 + %9 = insertvalue %"int[][]" %8, i64 5, 1 + store %"int[][]" %9, ptr %tcases, align 8 + %ptradd8 = getelementptr inbounds i8, ptr %tcases, i64 8 + %10 = load i64, ptr %ptradd8, align 8 + store i64 0, ptr %.anon, align 8 + br label %loop.cond + +loop.cond: ; preds = %loop.body, %entry + %11 = load i64, ptr %.anon, align 8 + %lt = icmp ult i64 %11, %10 + br i1 %lt, label %loop.body, label %loop.exit + +loop.body: ; preds = %loop.cond + %12 = load ptr, ptr %tcases, align 8 + %13 = load i64, ptr %.anon, align 8 + %ptroffset = getelementptr inbounds [16 x i8], ptr %12, i64 %13 + call void @llvm.memcpy.p0.p0.i32(ptr align 8 %tc, ptr align 8 %ptroffset, i32 16, i1 false) + call void @llvm.memcpy.p0.p0.i32(ptr align 8 %list, ptr align 8 %tc, i32 16, i1 false) + call void @llvm.memcpy.p0.p0.i32(ptr align 8 %list9, ptr align 8 %list, i32 16, i1 false) + %ptradd10 = getelementptr inbounds i8, ptr %list9, i64 8 + %14 = load i64, ptr %ptradd10, align 8 + store i64 %14, ptr %len, align 8 + %15 = load i64, ptr %len, align 8 + %sub = sub i64 %15, 1 + %lo = load ptr, ptr %list, align 8 + %ptradd11 = getelementptr inbounds i8, ptr %list, i64 8 + %hi = load i64, ptr %ptradd11, align 8 + call void @"test_generic$sa$int$fn$int$int$$int$$.sort"(ptr %lo, i64 %hi, i64 0, i64 %sub, ptr @sort_test.cmp_int_value) + %16 = load i64, ptr %.anon, align 8 + %addnuw = add nuw i64 %16, 1 + store i64 %addnuw, ptr %.anon, align 8 + br label %loop.cond + +loop.exit: ; preds = %loop.cond + ret void +} + +; Function Attrs: +define void @sort_test.quicksort_with_value2() #0 { +entry: + %tcases = alloca %"int[][]", align 8 + %literal = alloca [5 x %"int[]"], align 16 + %literal1 = alloca [2 x i32], align 4 + %literal3 = alloca [3 x i32], align 4 + %literal5 = alloca [3 x i32], align 4 + %literal7 = alloca [3 x i32], align 4 + %.anon = alloca i64, align 8 + %tc = alloca %"int[]", align 8 + %list = alloca %"int[]", align 8 + %len = alloca i64, align 8 + %list9 = alloca %"int[]", align 8 + store %"int[]" zeroinitializer, ptr %literal, align 8 + %ptradd = getelementptr inbounds i8, ptr %literal, i64 16 + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %literal1, ptr align 4 @.__const.4, i32 8, i1 false) + %0 = insertvalue %"int[]" undef, ptr %literal1, 0 + %1 = insertvalue %"int[]" %0, i64 2, 1 + store %"int[]" %1, ptr %ptradd, align 8 + %ptradd2 = getelementptr inbounds i8, ptr %literal, i64 32 + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %literal3, ptr align 4 @.__const.5, i32 12, i1 false) + %2 = insertvalue %"int[]" undef, ptr %literal3, 0 + %3 = insertvalue %"int[]" %2, i64 3, 1 + store %"int[]" %3, ptr %ptradd2, align 8 + %ptradd4 = getelementptr inbounds i8, ptr %literal, i64 48 + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %literal5, ptr align 4 @.__const.6, i32 12, i1 false) + %4 = insertvalue %"int[]" undef, ptr %literal5, 0 + %5 = insertvalue %"int[]" %4, i64 3, 1 + store %"int[]" %5, ptr %ptradd4, align 8 + %ptradd6 = getelementptr inbounds i8, ptr %literal, i64 64 + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %literal7, ptr align 4 @.__const.7, i32 12, i1 false) + %6 = insertvalue %"int[]" undef, ptr %literal7, 0 + %7 = insertvalue %"int[]" %6, i64 3, 1 + store %"int[]" %7, ptr %ptradd6, align 8 + %8 = insertvalue %"int[][]" undef, ptr %literal, 0 + %9 = insertvalue %"int[][]" %8, i64 5, 1 + store %"int[][]" %9, ptr %tcases, align 8 + %ptradd8 = getelementptr inbounds i8, ptr %tcases, i64 8 + %10 = load i64, ptr %ptradd8, align 8 + store i64 0, ptr %.anon, align 8 + br label %loop.cond + +loop.cond: ; preds = %loop.body, %entry + %11 = load i64, ptr %.anon, align 8 + %lt = icmp ult i64 %11, %10 + br i1 %lt, label %loop.body, label %loop.exit + +loop.body: ; preds = %loop.cond + %12 = load ptr, ptr %tcases, align 8 + %13 = load i64, ptr %.anon, align 8 + %ptroffset = getelementptr inbounds [16 x i8], ptr %12, i64 %13 + call void @llvm.memcpy.p0.p0.i32(ptr align 8 %tc, ptr align 8 %ptroffset, i32 16, i1 false) + call void @llvm.memcpy.p0.p0.i32(ptr align 8 %list, ptr align 8 %tc, i32 16, i1 false) + call void @llvm.memcpy.p0.p0.i32(ptr align 8 %list9, ptr align 8 %list, i32 16, i1 false) + %ptradd10 = getelementptr inbounds i8, ptr %list9, i64 8 + %14 = load i64, ptr %ptradd10, align 8 + store i64 %14, ptr %len, align 8 + %15 = load i64, ptr %len, align 8 + %sub = sub i64 %15, 1 + %lo = load ptr, ptr %list, align 8 + %ptradd11 = getelementptr inbounds i8, ptr %list, i64 8 + %hi = load i64, ptr %ptradd11, align 8 + call void @"test_generic$sa$int$fn$int$int$$int$$.sort"(ptr %lo, i64 %hi, i64 0, i64 %sub, ptr @sort_test.cmp_int_value2) + %16 = load i64, ptr %.anon, align 8 + %addnuw = add nuw i64 %16, 1 + store i64 %addnuw, ptr %.anon, align 8 + br label %loop.cond + +loop.exit: ; preds = %loop.cond + ret void +} + +declare extern_weak void @"test_generic$sa$int$fn$int$int$$int$$.sort"(ptr, i64, i64, i64, ptr) #0 + diff --git a/test/test_suite7/generic/generic_parsing.c3 b/test/test_suite7/generic/generic_parsing.c3 new file mode 100644 index 000000000..652eea977 --- /dev/null +++ b/test/test_suite7/generic/generic_parsing.c3 @@ -0,0 +1,22 @@ +module test; +import std; +def ListStr = List(); +fn void test() +{ + List a = List<...>.new_init(); // #error: An expression was expected +} + +fn void test2() +{ + List() a = List<...>.new_init(); // #error: An expression was expected +} + +fn void test3() +{ + List() a = List(<...>).new_init(); // #error: An expression was expected +} + +fn void main() +{ + List a = List.new_init(); // #error: An expression was expected +} \ No newline at end of file diff --git a/test/test_suite7/generic/generic_recursion.c3t b/test/test_suite7/generic/generic_recursion.c3t new file mode 100644 index 000000000..697907dfb --- /dev/null +++ b/test/test_suite7/generic/generic_recursion.c3t @@ -0,0 +1,21 @@ +// #target: macos-x64 +module test; +import std::io; +import std::collections::list; + +def TreeNodeList = List(); + +struct TreeNode +{ + TreeNode* foo; + TreeNode* bar; + TreeNodeList list; +} + +TreeNode abc; + +/* #expect: test.ll + +%TreeNode = type { ptr, ptr, %List } +%List = type { i64, i64, %any, ptr } +@test.abc = local_unnamed_addr global %TreeNode zeroinitializer, align 8 \ No newline at end of file diff --git a/test/test_suite7/generic/generic_resolution_1402.c3t b/test/test_suite7/generic/generic_resolution_1402.c3t new file mode 100644 index 000000000..3d6a7d668 --- /dev/null +++ b/test/test_suite7/generic/generic_resolution_1402.c3t @@ -0,0 +1,33 @@ +// #target: macos-x64 +module playground::bug(); +import std::io; + +struct Foo +{ + Ty x; +} + +fn void Foo.print_it(&self) +{ + io::printf("Method %s\n", self.x); +} + +module playground::bug(); +import std::io; + +macro void print_it(...) +{ + io::printn("Macro 456"); +} + +module playground; +import playground::bug; + +def MyFoo = Foo(); + +fn void main(String[] args) +{ + MyFoo foo = { 123 }; + foo.print_it(); + bug::print_it()(); +} \ No newline at end of file diff --git a/test/test_suite7/generic/generic_void.c3t b/test/test_suite7/generic/generic_void.c3t new file mode 100644 index 000000000..5e63ce2d4 --- /dev/null +++ b/test/test_suite7/generic/generic_void.c3t @@ -0,0 +1,29 @@ +// #target: macos-x64 +module test(); + +def Callback = fn Type(); + +module mymain; + +import std::io; +import test; + +def VoidCb = test::Callback(); + +fn int main() +{ + VoidCb a = null; + void *b = a; + return 0; +} +/* #expect: mymain.ll + +define i32 @main() #0 { +entry: + %a = alloca ptr, align 8 + %b = alloca ptr, align 8 + store ptr null, ptr %a, align 8 + %0 = load ptr, ptr %a, align 8 + store ptr %0, ptr %b, align 8 + ret i32 0 +} \ No newline at end of file diff --git a/test/test_suite7/generic/generic_with_comment.c3t b/test/test_suite7/generic/generic_with_comment.c3t new file mode 100644 index 000000000..7db9f04f3 --- /dev/null +++ b/test/test_suite7/generic/generic_with_comment.c3t @@ -0,0 +1,13 @@ +module test; +import generic; + +// Issue #1821 +fn void main() { + Generic() asdf; +} + +<* + Hello +*> +module generic(); +struct Generic { int a; } \ No newline at end of file diff --git a/test/test_suite7/generic/generic_with_enum.c3t b/test/test_suite7/generic/generic_with_enum.c3t new file mode 100644 index 000000000..0fdb74f72 --- /dev/null +++ b/test/test_suite7/generic/generic_with_enum.c3t @@ -0,0 +1,36 @@ +// #target: macos-x64 +module test(); + +const Z = FOO; + +struct Foo +{ + $typeof(FOO) z; +} +module tester; +import test; + +enum Abc +{ + ONE, + TWO +} + +fn void main() +{ + Foo() x; + Abc e = test::Z(); +} + +/* #expect: tester.ll + +%Foo = type { i32 } + +define void @tester.main() #0 { +entry: + %x = alloca %Foo, align 4 + %e = alloca i32, align 4 + store i32 0, ptr %x, align 4 + store i32 0, ptr %e, align 4 + ret void +} diff --git a/test/test_suite7/generic/generic_without_param.c3 b/test/test_suite7/generic/generic_without_param.c3 new file mode 100644 index 000000000..a1915f162 --- /dev/null +++ b/test/test_suite7/generic/generic_without_param.c3 @@ -0,0 +1,9 @@ +module test; +import std; +import abc; +fn void main() +{ + abc::test(); // #error: (<...>) +} +module abc(); +fn void test() {} \ No newline at end of file diff --git a/test/test_suite7/generic/implicit_import_of_generic.c3 b/test/test_suite7/generic/implicit_import_of_generic.c3 new file mode 100644 index 000000000..d87cc2342 --- /dev/null +++ b/test/test_suite7/generic/implicit_import_of_generic.c3 @@ -0,0 +1,18 @@ +module test; +import std::io; + +import abc; +def Def2 = Def; +def Test = abc::cde::Abc(); + +module abc; + +fn void test() {} + +module abc::foo; + +struct Def { int x; } + +module abc::cde(); + +struct Abc { Type a, b; } \ No newline at end of file diff --git a/test/test_suite7/generic/incorrect_argument_type.c3 b/test/test_suite7/generic/incorrect_argument_type.c3 new file mode 100644 index 000000000..5df6bb456 --- /dev/null +++ b/test/test_suite7/generic/incorrect_argument_type.c3 @@ -0,0 +1,11 @@ +module foo(); + +struct Foo +{ + Type[SIZE] x; +} +module bar; +import foo; + +def Bar = Foo(); // #error: Expected a value, not a type +def Baz = Foo(<5, 4>); // #error: Expected a type, not a value diff --git a/test/test_suite7/generic/nested_typedef.c3t b/test/test_suite7/generic/nested_typedef.c3t new file mode 100644 index 000000000..5e467affb --- /dev/null +++ b/test/test_suite7/generic/nested_typedef.c3t @@ -0,0 +1,30 @@ +// #target: macos-x64 +module broken(); +distinct Bar = Type; +def Bar2 = Type; +struct Baz +{ + int a; +} +module test; +import broken; + +struct Foo +{ + Bar() y; +} + +struct Foo2 +{ + Bar2() y; +} +fn int test() @if(Foo.sizeof > 2) => 1; +fn int test2() @if(Foo2.sizeof > 2) => 1; +fn void main() {} + +/* #expect: test.ll + +@"$ct.test.Foo" = linkonce global %.introspect { i8 10, i64 0, ptr null, i64 4, i64 0, i64 1, [0 x i64] zeroinitializer }, align 8 +@"$ct.test.Foo2" = linkonce global %.introspect { i8 10, i64 0, ptr null, i64 4, i64 0, i64 1, [0 x i64] zeroinitializer }, align 8 +define i32 @test.test() #0 { +define i32 @test.test2() #0 { diff --git a/test/test_suite7/generic/used_without_param.c3 b/test/test_suite7/generic/used_without_param.c3 new file mode 100644 index 000000000..950c3b12f --- /dev/null +++ b/test/test_suite7/generic/used_without_param.c3 @@ -0,0 +1,8 @@ +module test; +import std::collections::maybe; + +fn void main() +{ + Maybe() f = (Maybe) {.value=6.6, .has_value=true}; // #error: Did you mean the struct + Maybe()g = (Maybe) {.value=8, .has_value=true}; +} diff --git a/test/test_suite7/generic/used_without_param2.c3 b/test/test_suite7/generic/used_without_param2.c3 new file mode 100644 index 000000000..3fc231a3d --- /dev/null +++ b/test/test_suite7/generic/used_without_param2.c3 @@ -0,0 +1,9 @@ +module test; +import std::collections::maybe; + +fn void test() +{ + maybe::Maybe() f = (Maybe) {.value=6.6, .has_value=true}; // #error: Did you mean the struct + Maybe x; // #error: Did you mean the struct +} + diff --git a/test/test_suite7/generic/used_without_param3.c3 b/test/test_suite7/generic/used_without_param3.c3 new file mode 100644 index 000000000..6ba0b4fd4 --- /dev/null +++ b/test/test_suite7/generic/used_without_param3.c3 @@ -0,0 +1,7 @@ +module test; +import std::collections::maybe; + +fn void test() +{ + maybe::Maybe() f = (Maybe) {.value=6.6, .has_value=true}; // #error: Did you mean the struct +} \ No newline at end of file diff --git a/test/test_suite7/globals/ext_global_init.c3 b/test/test_suite7/globals/ext_global_init.c3 new file mode 100644 index 000000000..446fe0050 --- /dev/null +++ b/test/test_suite7/globals/ext_global_init.c3 @@ -0,0 +1 @@ +extern int a = 1; // #error: Extern globals may not have initializers \ No newline at end of file diff --git a/test/test_suite7/globals/extern_const.c3t b/test/test_suite7/globals/extern_const.c3t new file mode 100644 index 000000000..76e6530a2 --- /dev/null +++ b/test/test_suite7/globals/extern_const.c3t @@ -0,0 +1,17 @@ +// #target: macos-x64 +module test; + +extern const int FOO @extern("foo1"); +fn int main() +{ + return FOO; +} + +module bar; +const int FOO @export("foo1") = 123; + + + +/* #expect: bar.ll + +@foo1 = local_unnamed_addr constant i32 123, align 4 \ No newline at end of file diff --git a/test/test_suite7/globals/external_global.c3t b/test/test_suite7/globals/external_global.c3t new file mode 100644 index 000000000..9515d3a8b --- /dev/null +++ b/test/test_suite7/globals/external_global.c3t @@ -0,0 +1,36 @@ +// #target: macos-x64 +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 (i8, ptr @g, i64 8), ptr getelementptr inbounds (i8, ptr @g, i64 24), align 8 + ret i32 0 +} diff --git a/test/test_suite7/globals/global_align.c3t b/test/test_suite7/globals/global_align.c3t new file mode 100644 index 000000000..d0763503c --- /dev/null +++ b/test/test_suite7/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_suite7/globals/global_extname.c3t b/test/test_suite7/globals/global_extname.c3t new file mode 100644 index 000000000..51c98776a --- /dev/null +++ b/test/test_suite7/globals/global_extname.c3t @@ -0,0 +1,8 @@ +// #target: macos-x64 +module foo; + +int baz @extern("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_suite7/globals/global_init.c3 b/test/test_suite7/globals/global_init.c3 new file mode 100644 index 000000000..7bffb33bd --- /dev/null +++ b/test/test_suite7/globals/global_init.c3 @@ -0,0 +1,22 @@ +// TODO string str = "hello"; +char* str2 = "hello"; +String str3 = "hello"; + + +int[2] a1 = { 1, 2 }; + +int[2] a2 = 30; // #error: 'int' to 'int[2]' + +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_suite7/globals/global_no_init.c3t b/test/test_suite7/globals/global_no_init.c3t new file mode 100644 index 000000000..0b7f6aa83 --- /dev/null +++ b/test/test_suite7/globals/global_no_init.c3t @@ -0,0 +1,33 @@ +// #target: macos-x64 +module test; + +struct Abc +{ + int[100] x; +} +int z @noinit; +Abc y @noinit; + +int a, b, c; +int x1, y1 @noinit; +tlocal int w, v; + +fn void main() +{ + z = y.x[0]; +} + +/* #expect: test.ll + +@test.z = local_unnamed_addr global i32 undef, align 4 +@test.y = local_unnamed_addr global %Abc undef, align 4 +@test.a = local_unnamed_addr global i32 0, align 4 +@test.b = local_unnamed_addr global i32 0, align 4 +@test.c = local_unnamed_addr global i32 0, align 4 +@test.x1 = local_unnamed_addr global i32 undef, align 4 +@test.y1 = local_unnamed_addr global i32 undef, align 4 +@test.w = thread_local local_unnamed_addr global i32 0, align 4 +@test.v = thread_local local_unnamed_addr global i32 0, align 4 + +%0 = load i32, ptr @test.y, align 4 +store i32 %0, ptr @test.z, align 4 diff --git a/test/test_suite7/globals/init_with_err.c3t b/test/test_suite7/globals/init_with_err.c3t new file mode 100644 index 000000000..ca39f116c --- /dev/null +++ b/test/test_suite7/globals/init_with_err.c3t @@ -0,0 +1,24 @@ +// #target: macos-x64 +module test; +import std::io; + +fault Hello +{ + FOO +} +const String! ABC = Hello.FOO?; +String! abc = Hello.FOO?; +const String! DEF = ABC; +String! bcd = ABC; + + +/* #expect: test.ll + +@test.ABC.f = unnamed_addr global i64 ptrtoint (ptr @"test.Hello$FOO" to i64), align 8 +@test.abc.f = unnamed_addr global i64 ptrtoint (ptr @"test.Hello$FOO" to i64), align 8 +@test.DEF.f = unnamed_addr global i64 ptrtoint (ptr @"test.Hello$FOO" to i64), align 8 +@test.bcd.f = unnamed_addr global i64 ptrtoint (ptr @"test.Hello$FOO" to i64), align 8 +@test.ABC = local_unnamed_addr constant %"char[]" zeroinitializer, align 8 +@test.abc = local_unnamed_addr global %"char[]" zeroinitializer, align 8 +@test.DEF = local_unnamed_addr constant %"char[]" zeroinitializer, align 8 +@test.bcd = local_unnamed_addr global %"char[]" zeroinitializer, align 8 diff --git a/test/test_suite7/globals/misplaced_const.c3 b/test/test_suite7/globals/misplaced_const.c3 new file mode 100644 index 000000000..6ea51e0c8 --- /dev/null +++ b/test/test_suite7/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 the start of a global declaration here \ No newline at end of file diff --git a/test/test_suite7/globals/recursive_globals.c3 b/test/test_suite7/globals/recursive_globals.c3 new file mode 100644 index 000000000..d6d2a725f --- /dev/null +++ b/test/test_suite7/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_suite7/globals/recursive_locals.c3 b/test/test_suite7/globals/recursive_locals.c3 new file mode 100644 index 000000000..1709dbf9f --- /dev/null +++ b/test/test_suite7/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_suite7/globals/self_referencing_local.c3 b/test/test_suite7/globals/self_referencing_local.c3 new file mode 100644 index 000000000..6da61b7a8 --- /dev/null +++ b/test/test_suite7/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_suite7/globals/static_global.c3 b/test/test_suite7/globals/static_global.c3 new file mode 100644 index 000000000..ddd5ccb27 --- /dev/null +++ b/test/test_suite7/globals/static_global.c3 @@ -0,0 +1 @@ +static int ifej; // #error: 'static' is only used \ No newline at end of file diff --git a/test/test_suite7/import/access_other_module.c3t b/test/test_suite7/import/access_other_module.c3t new file mode 100644 index 000000000..4853506ca --- /dev/null +++ b/test/test_suite7/import/access_other_module.c3t @@ -0,0 +1,23 @@ +// #target: macos-x64 +module foo; +import libc; +fn void main() +{ + void* foekf = &libc::printf; + int* xok = &libc::EXIT_SUCCESS; +} + +/* #expect: foo.ll + +@libc.EXIT_SUCCESS = extern_weak constant i32, align 4 + +define void @foo.main() #0 { +entry: + %foekf = alloca ptr, align 8 + %xok = alloca ptr, align 8 + store ptr @printf, ptr %foekf, align 8 + store ptr @libc.EXIT_SUCCESS, ptr %xok, align 8 + ret void +} + +declare i32 @printf(ptr, ...) \ No newline at end of file diff --git a/test/test_suite7/import/autoimport.c3 b/test/test_suite7/import/autoimport.c3 new file mode 100644 index 000000000..8b80f199e --- /dev/null +++ b/test/test_suite7/import/autoimport.c3 @@ -0,0 +1,36 @@ +module foo; + +fn int test() @builtin +{ + return 1; +} + +macro int testm() @builtin +{ + 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_suite7/import/import_error.c3 b/test/test_suite7/import/import_error.c3 new file mode 100644 index 000000000..4be9e0f7c --- /dev/null +++ b/test/test_suite7/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_suite7/import/import_error_multi.c3 b/test/test_suite7/import/import_error_multi.c3 new file mode 100644 index 000000000..e6a761a42 --- /dev/null +++ b/test/test_suite7/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_suite7/import/import_error_string.c3 b/test/test_suite7/import/import_error_string.c3 new file mode 100644 index 000000000..1810dcfe3 --- /dev/null +++ b/test/test_suite7/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_suite7/import/import_implicit.c3 b/test/test_suite7/import/import_implicit.c3 new file mode 100644 index 000000000..e88d58023 --- /dev/null +++ b/test/test_suite7/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_suite7/import/import_nonrecurse.c3 b/test/test_suite7/import/import_nonrecurse.c3 new file mode 100644 index 000000000..75c6baf32 --- /dev/null +++ b/test/test_suite7/import/import_nonrecurse.c3 @@ -0,0 +1,5 @@ +import std::io @norecurse; +fn void main() +{ + (void)file::open("test", "r"); // #error: std::io::file::open +} \ No newline at end of file diff --git a/test/test_suite7/import/import_same.c3 b/test/test_suite7/import/import_same.c3 new file mode 100644 index 000000000..96bd65b50 --- /dev/null +++ b/test/test_suite7/import/import_same.c3 @@ -0,0 +1,10 @@ +module foo::abc; +import bar; + +fn int test1() +{ + return abc::test(); +} + +module bar::abc; +fn int test() { return 1; } \ No newline at end of file diff --git a/test/test_suite7/import/import_twice.c3 b/test/test_suite7/import/import_twice.c3 new file mode 100644 index 000000000..815d41040 --- /dev/null +++ b/test/test_suite7/import/import_twice.c3 @@ -0,0 +1,8 @@ +module foo; +import std::io; +import std::io; // #error: imported more than + +fn void main() +{ + io::printn("Hello world"); +} diff --git a/test/test_suite7/import/import_works.c3t b/test/test_suite7/import/import_works.c3t new file mode 100644 index 000000000..c524cd8cf --- /dev/null +++ b/test/test_suite7/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_suite7/initialize/init_non_resolved_type.c3 b/test/test_suite7/initialize/init_non_resolved_type.c3 new file mode 100644 index 000000000..6809310fe --- /dev/null +++ b/test/test_suite7/initialize/init_non_resolved_type.c3 @@ -0,0 +1 @@ +const IS_ARCH_LITTLE_ENDIAN = (uint)((UIntLE){(uint)1}.val) == 1; // #error: This expression cannot be evaluated at compile time diff --git a/test/test_suite7/initialize/initialize_bad_prio.c3 b/test/test_suite7/initialize/initialize_bad_prio.c3 new file mode 100644 index 000000000..b1876c821 --- /dev/null +++ b/test/test_suite7/initialize/initialize_bad_prio.c3 @@ -0,0 +1,16 @@ + +fn void init1() @init("hello") // #error: Expected an integer value +{ +} + +fn void init2() @init(1, 2) // #error: Too many arguments for +{ +} + +fn void init3() @init(0) // #error: The priority must be a value +{ +} + +fn void init4() @init(65536) // #error: The priority must be a value +{ +} \ No newline at end of file diff --git a/test/test_suite7/initialize/initialize_finalize.c3t b/test/test_suite7/initialize/initialize_finalize.c3t new file mode 100644 index 000000000..f7e4a9254 --- /dev/null +++ b/test/test_suite7/initialize/initialize_finalize.c3t @@ -0,0 +1,67 @@ +// #target: linux-x64 +module test; +import std::io; + +fn void main() +{ + io::printn("Hello, world!"); +} +extern fn void puts(char*); + +fn void startup2() @init(300) +{ + puts("Hello startup2"); +} +fn void start_main() @init +{ + puts("Let's start main..."); +} +fn void startup1() @init(200) +{ + puts("Hello startup"); +} + +fn void empty_startup() @init +{} + +fn void shutdown() @finalizer +{ + puts("Bye bye"); +} + +/* #expect: test.ll + +@llvm.global_ctors = appending global [5 x { i32, ptr, ptr }] [{ i32, ptr, ptr } { i32 300, ptr @test.startup2, ptr null }, { i32, ptr, ptr } { i32 65535, ptr @test.start_main, ptr null }, { i32, ptr, ptr } { i32 200, ptr @test.startup1, ptr null }, { i32, ptr, ptr } { i32 65535, ptr @test.empty_startup, ptr null }, { i32, ptr, ptr } { i32 65535, ptr @.__c3_atexit_test.shutdown, ptr null }] + +define void @test.startup2() #0 { +entry: + call void @puts(ptr @.str.1) + ret void +} + +define void @test.start_main() #0 { +entry: + call void @puts(ptr @.str.2) + ret void +} + +define void @test.startup1() #0 { +entry: + call void @puts(ptr @.str.3) + ret void +} +define void @test.empty_startup() #0 { +entry: + ret void +} + +define void @test.shutdown() #0 { +entry: + call void @puts(ptr @.str.4) + ret void +} +define weak void @.__c3_atexit_test.shutdown() comdat { +entry: + call void @atexit(ptr @test.shutdown) + ret void +} \ No newline at end of file diff --git a/test/test_suite7/initialize/initialize_jump.c3 b/test/test_suite7/initialize/initialize_jump.c3 new file mode 100644 index 000000000..f223cd455 --- /dev/null +++ b/test/test_suite7/initialize/initialize_jump.c3 @@ -0,0 +1,9 @@ +fn void foo() @init +{ + return; // This is fine +} + +fn int foo2() @init // #error: '@init' and '@finalizer' functions may only +{ + return 123; +} \ No newline at end of file diff --git a/test/test_suite7/initialize/initialize_parse_error.c3 b/test/test_suite7/initialize/initialize_parse_error.c3 new file mode 100644 index 000000000..f07a83415 --- /dev/null +++ b/test/test_suite7/initialize/initialize_parse_error.c3 @@ -0,0 +1 @@ +static foo {} ; // #error: 'static' is only used diff --git a/test/test_suite7/initialize/initialize_prio.c3 b/test/test_suite7/initialize/initialize_prio.c3 new file mode 100644 index 000000000..360254fe7 --- /dev/null +++ b/test/test_suite7/initialize/initialize_prio.c3 @@ -0,0 +1,3 @@ +fn void test() @init() // #error: An expression was expected. +{ +} diff --git a/test/test_suite7/initialize/initializer_access.c3 b/test/test_suite7/initialize/initializer_access.c3 new file mode 100644 index 000000000..f59bf36f1 --- /dev/null +++ b/test/test_suite7/initialize/initializer_access.c3 @@ -0,0 +1,10 @@ +module test; +struct Abc +{ + int[2] a; + int b; +} +fn int main() +{ + Abc a = { .a = {} .b = 3 }; // #error: A comma or '}' was expected here. +} diff --git a/test/test_suite7/initialize/initializer_var.c3t b/test/test_suite7/initialize/initializer_var.c3t new file mode 100644 index 000000000..8f73423fc --- /dev/null +++ b/test/test_suite7/initialize/initializer_var.c3t @@ -0,0 +1,7 @@ +module test; + +fn void init() @init +{ + int a; + a = 1; +} diff --git a/test/test_suite7/initializer_lists/disallowed_lists.c3 b/test/test_suite7/initializer_lists/disallowed_lists.c3 new file mode 100644 index 000000000..5ee323e37 --- /dev/null +++ b/test/test_suite7/initializer_lists/disallowed_lists.c3 @@ -0,0 +1,8 @@ +fn void test() +{ + char* hello = "123"; + String 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_suite7/initializer_lists/fasta.c3t b/test/test_suite7/initializer_lists/fasta.c3t new file mode 100644 index 000000000..d6600add0 --- /dev/null +++ b/test/test_suite7/initializer_lists/fasta.c3t @@ -0,0 +1,340 @@ +// #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; +} + +char[] alu @private = + "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) +{ + usz len = seq.len; + int i @noinit; + 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 @noinit; + for (i = 0; i < n; i++) + { + double v = fasta_rand(1.0); + /* slowest idiomatic linear lookup. Fast if len is short though. */ + int j @noinit; + 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 int 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); + + return 0; +} + +/* #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 = internal 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 +@.__const_slice = private unnamed_addr 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 16 +@fasta.iub_p = local_unnamed_addr global %"double[]" { ptr @.__const_slice, 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 +@.__const_slice.13 = private unnamed_addr global [4 x double] [double 0x3FD3639D20BAEB5B, double 0x3FC957AE3DCD561B, double 0x3FC9493AEAB6C2BF, double 0x3FD34BEE4B030838], align 16 +@fasta.homosapiens_p = local_unnamed_addr global %"double[]" { ptr @.__const_slice.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: +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: +declare i32 @atoi(ptr) #0 + +; Function Attrs: +declare i32 @printf(ptr, ...) #0 + +; Function Attrs: +declare void @putchar(i32) #0 + +; Function Attrs: +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 + store ptr %0, ptr %seq, align 8 + %ptradd = getelementptr inbounds i8, ptr %seq, i64 8 + store i64 %1, ptr %ptradd, align 8 + %ptradd1 = getelementptr inbounds i8, ptr %seq, i64 8 + %3 = load i64, ptr %ptradd1, align 8 + store i64 %3, ptr %len, align 8 + 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, %2 + br i1 %lt, label %loop.body, label %loop.exit +loop.body: ; preds = %loop.cond + %5 = load ptr, ptr %seq, align 8 + %6 = load i32, ptr %i, align 4 + %sext = sext i32 %6 to i64 + %7 = load i64, ptr %len, align 8 + %smod = srem i64 %sext, %7 + %ptradd2 = getelementptr inbounds i8, ptr %5, i64 %smod + %8 = load i8, ptr %ptradd2, align 1 + %zext = zext i8 %8 to i32 + call void @putchar(i32 %zext) + %9 = load i32, ptr %i, align 4 + %smod3 = srem i32 %9, 60 + %eq = icmp eq i32 %smod3, 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 + %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 + %11 = load i32, ptr %i, align 4 + %smod4 = srem i32 %11, 60 + %neq = icmp ne i32 %smod4, 0 + br i1 %neq, label %if.then5, label %if.exit6 +if.then5: ; preds = %loop.exit + call void @putchar(i32 10) + br label %if.exit6 +if.exit6: ; preds = %if.then5, %loop.exit + ret void +} + +; Function Attrs: +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 + store ptr %0, ptr %symb, align 8 + %ptradd = getelementptr inbounds i8, ptr %symb, i64 8 + store i64 %1, ptr %ptradd, align 8 + store ptr %2, ptr %probability, align 8 + %ptradd1 = getelementptr inbounds i8, ptr %probability, i64 8 + store i64 %3, ptr %ptradd1, align 8 + %ptradd2 = getelementptr inbounds i8, ptr %symb, i64 8 + %5 = load i64, ptr %ptradd2, align 8 + %ptradd3 = getelementptr inbounds i8, ptr %probability, i64 8 + %6 = load i64, ptr %ptradd3, align 8 + %eq = icmp eq i64 %5, %6 + call void @llvm.assume(i1 %eq) + %ptradd4 = getelementptr inbounds i8, ptr %probability, i64 8 + %7 = load i64, ptr %ptradd4, align 8 + %trunc = trunc i64 %7 to i32 + store i32 %trunc, ptr %len, align 4 + store i32 0, ptr %i, align 4 + br label %loop.cond +loop.cond: ; preds = %if.exit13, %entry + %8 = load i32, ptr %i, align 4 + %lt = icmp slt i32 %8, %4 + br i1 %lt, label %loop.body, label %loop.exit15 +loop.body: ; preds = %loop.cond + %9 = call float @fasta.fasta_rand(float 1.000000e+00) + %fpfpext = fpext float %9 to double + store double %fpfpext, ptr %v, align 8 + store i32 0, ptr %j, align 4 + br label %loop.cond5 +loop.cond5: ; preds = %if.exit, %loop.body + %10 = load i32, ptr %j, align 4 + %11 = load i32, ptr %len, align 4 + %sub = sub i32 %11, 1 + %lt6 = icmp slt i32 %10, %sub + br i1 %lt6, label %loop.body7, label %loop.exit +loop.body7: ; preds = %loop.cond5 + %12 = load double, ptr %v, align 8 + %13 = load ptr, ptr %probability, align 8 + %14 = load i32, ptr %j, align 4 + %sext = sext i32 %14 to i64 + %ptroffset = getelementptr inbounds [8 x i8], ptr %13, i64 %sext + %15 = load double, ptr %ptroffset, align 8 + %fsub = fsub double %12, %15 + store double %fsub, ptr %v, align 8 + %16 = load double, ptr %v, align 8 + %lt8 = fcmp olt double %16, 0.000000e+00 + br i1 %lt8, label %if.then, label %if.exit +if.then: ; preds = %loop.body7 + br label %loop.exit +if.exit: ; preds = %loop.body7 + %17 = load i32, ptr %j, align 4 + %add = add i32 %17, 1 + store i32 %add, ptr %j, align 4 + br label %loop.cond5 +loop.exit: ; preds = %if.then, %loop.cond5 + %18 = load ptr, ptr %symb, align 8 + %19 = load i32, ptr %j, align 4 + %sext9 = sext i32 %19 to i64 + %ptradd10 = getelementptr inbounds i8, ptr %18, i64 %sext9 + %20 = load i8, ptr %ptradd10, align 1 + %zext = zext i8 %20 to i32 + call void @putchar(i32 %zext) + %21 = load i32, ptr %i, align 4 + %smod = srem i32 %21, 60 + %eq11 = icmp eq i32 %smod, 59 + br i1 %eq11, label %if.then12, label %if.exit13 +if.then12: ; preds = %loop.exit + call void @putchar(i32 10) + br label %if.exit13 +if.exit13: ; preds = %if.then12, %loop.exit + %22 = load i32, ptr %i, align 4 + %add14 = add i32 %22, 1 + store i32 %add14, ptr %i, align 4 + br label %loop.cond +loop.exit15: ; preds = %loop.cond + %23 = load i32, ptr %i, align 4 + %smod16 = srem i32 %23, 60 + %neq = icmp ne i32 %smod16, 0 + br i1 %neq, label %if.then17, label %if.exit18 +if.then17: ; preds = %loop.exit15 + call void @putchar(i32 10) + br label %if.exit18 +if.exit18: ; preds = %if.then17, %loop.exit15 + ret void +} + +; Function Attrs: +define i32 @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 + %ptradd = getelementptr inbounds i8, ptr %1, i64 8 + %2 = load ptr, ptr %ptradd, 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) + %5 = load i32, ptr %n, align 4 + %mul = mul i32 %5, 2 + %lo = load ptr, ptr @fasta.alu, align 8 + %hi = load i64, ptr getelementptr inbounds (i8, ptr @fasta.alu, i64 8), align 8 + call void @fasta.repeat_fasta(ptr %lo, i64 %hi, i32 %mul) + %6 = call i32 (ptr, ...) @printf(ptr @.str.15) + %7 = load i32, ptr %n, align 4 + %mul1 = mul i32 %7, 3 + %lo2 = load ptr, ptr @fasta.iub, align 8 + %hi3 = load i64, ptr getelementptr inbounds (i8, ptr @fasta.iub, i64 8), align 8 + %lo4 = load ptr, ptr @fasta.iub_p, align 8 + %hi5 = load i64, ptr getelementptr inbounds (i8, ptr @fasta.iub_p, i64 8), align 8 + call void @fasta.random_fasta(ptr %lo2, i64 %hi3, ptr %lo4, i64 %hi5, i32 %mul1) + %8 = call i32 (ptr, ...) @printf(ptr @.str.16) + %9 = load i32, ptr %n, align 4 + %mul6 = mul i32 %9, 5 + %lo7 = load ptr, ptr @fasta.homosapiens, align 8 + %hi8 = load i64, ptr getelementptr inbounds (i8, ptr @fasta.homosapiens, i64 8), align 8 + %lo9 = load ptr, ptr @fasta.homosapiens_p, align 8 + %hi10 = load i64, ptr getelementptr inbounds (i8, ptr @fasta.homosapiens_p, i64 8), align 8 + call void @fasta.random_fasta(ptr %lo7, i64 %hi8, ptr %lo9, i64 %hi10, i32 %mul6) + ret i32 0 +} \ No newline at end of file diff --git a/test/test_suite7/initializer_lists/general_tests.c3t b/test/test_suite7/initializer_lists/general_tests.c3t new file mode 100644 index 000000000..170afc755 --- /dev/null +++ b/test/test_suite7/initializer_lists/general_tests.c3t @@ -0,0 +1,72 @@ +// #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 = {}; + 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 } + +@"$ct.general_tests.Baz" = linkonce global %.introspect { i8 11, i64 0, ptr null, i64 8, i64 0, i64 2, [0 x i64] zeroinitializer }, align 8 +@"$ct.general_tests.Bar" = linkonce global %.introspect { i8 10, i64 0, ptr null, i64 8, i64 0, i64 2, [0 x i64] zeroinitializer }, 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: +define i32 @general_tests.test() #0 { +entry: + %ffe = alloca %Baz, align 8 + %azz = alloca [1 x i32], align 4 + %foo2 = alloca i32, align 4 + %str = alloca ptr, align 8 + %x = alloca i8, align 1 + %b = alloca %Bar, align 4 + %z = alloca %Baz, align 8 + %sub = alloca %"int[]", align 8 + %foo = alloca %"Bar[]", align 8 + %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) + store i32 0, ptr %azz, align 4 + store i32 33, ptr %foo2, align 4 + store ptr @.str, ptr %str, align 8 + store i8 0, ptr %x, align 1 + store i32 0, ptr %b, align 4 + %ptradd = getelementptr inbounds i8, ptr %b, i64 4 + store i32 0, ptr %ptradd, align 4 + call void @llvm.memset.p0.i64(ptr align 8 %z, i8 0, i64 8, i1 false) + store %"int[]" zeroinitializer, ptr %sub, align 8 + store %"Bar[]" zeroinitializer, 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_suite7/initializer_lists/indexing_into_complist.c3 b/test/test_suite7/initializer_lists/indexing_into_complist.c3 new file mode 100644 index 000000000..d8ce85f54 --- /dev/null +++ b/test/test_suite7/initializer_lists/indexing_into_complist.c3 @@ -0,0 +1,5 @@ +fn void test() +{ + char* c = { 1, 3, "hello"}[2]; + int x; +} \ No newline at end of file diff --git a/test/test_suite7/initializer_lists/infer_with_init.c3t b/test/test_suite7/initializer_lists/infer_with_init.c3t new file mode 100644 index 000000000..260dedb56 --- /dev/null +++ b/test/test_suite7/initializer_lists/infer_with_init.c3t @@ -0,0 +1,20 @@ +// #target: windows-x64 +module test; +const int[?] X = (int[?]) { 1, 2, 3 }; +int[?] y = (int[?]) { 1, 2, 3 }; + +fn void main() +{ + int x = $typeof((int[?]) { 1, 2, 3}).len; + int z = X.len; + int w = y.len; +} + +/* #expect: test.ll + +@test.X = local_unnamed_addr constant [3 x i32] [i32 1, i32 2, i32 3], align 4 +@test.y = local_unnamed_addr global [3 x i32] [i32 1, i32 2, i32 3], align 4 + + store i32 3, ptr %x, align 4 + store i32 3, ptr %z, align 4 + store i32 3, ptr %w, align 4 \ No newline at end of file diff --git a/test/test_suite7/initializer_lists/init_any_interface.c3 b/test/test_suite7/initializer_lists/init_any_interface.c3 new file mode 100644 index 000000000..d58f141de --- /dev/null +++ b/test/test_suite7/initializer_lists/init_any_interface.c3 @@ -0,0 +1,23 @@ +module test; + +interface Foo{} + +struct Bar (Foo) +{ + int baz; +} + +fn int main() { + Test() a = {{}}; + Test() b = {{}}; + Test() a2 = {(Bar){}}; // #error: It is not possible to cast + + return 0; +} + +module test::generic(); + +struct Test +{ + Type test; +} \ No newline at end of file diff --git a/test/test_suite7/initializer_lists/initializers_to_macros.c3 b/test/test_suite7/initializer_lists/initializers_to_macros.c3 new file mode 100644 index 000000000..f464c2625 --- /dev/null +++ b/test/test_suite7/initializer_lists/initializers_to_macros.c3 @@ -0,0 +1,11 @@ + +macro test(foo) +{ + $typeof(foo) x = foo; +} + +fn void main() +{ + test((int[]) { 1, 2 }); + test({ 1, 2 }); // #error: It is only possible to use an untyped list as a +} \ No newline at end of file diff --git a/test/test_suite7/initializer_lists/ranges_to_dynamic.c3t b/test/test_suite7/initializer_lists/ranges_to_dynamic.c3t new file mode 100644 index 000000000..70106209a --- /dev/null +++ b/test/test_suite7/initializer_lists/ranges_to_dynamic.c3t @@ -0,0 +1,63 @@ +// #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) + store i32 4, ptr %y, align 4 + %ptradd = getelementptr inbounds i8, ptr %y, i64 4 + store i32 4, ptr %ptradd, align 4 + %ptradd1 = getelementptr inbounds i8, ptr %y, i64 8 + store i32 4, ptr %ptradd1, align 4 + %ptradd2 = getelementptr inbounds i8, ptr %y, i64 12 + store i32 4, ptr %ptradd2, align 4 + %ptradd3 = getelementptr inbounds i8, ptr %y, i64 24 + store i32 %0, ptr %ptradd3, align 4 + %ptradd4 = getelementptr inbounds i8, ptr %y, i64 28 + store i32 %0, ptr %ptradd4, align 4 + %ptradd5 = getelementptr inbounds i8, ptr %y, i64 32 + store i32 %0, ptr %ptradd5, align 4 + store i64 0, ptr %.anon, align 8 + br label %loop.cond + +loop.cond: ; preds = %loop.body, %entry + %1 = load i64, ptr %.anon, align 8 + %gt = icmp ugt i64 10, %1 + br i1 %gt, label %loop.body, label %loop.exit + +loop.body: ; preds = %loop.cond + %2 = load i64, ptr %.anon, align 8 + %ptroffset = getelementptr inbounds [4 x i8], ptr %y, i64 %2 + %3 = load i32, ptr %ptroffset, align 4 + store i32 %3, ptr %v, align 4 + %4 = load i32, ptr %v, align 4 + call void (ptr, ...) @printf(ptr @.str, i32 %4) + %5 = load i64, ptr %.anon, align 8 + %addnuw = add nuw i64 %5, 1 + store i64 %addnuw, 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_suite7/initializer_lists/statics.c3t b/test/test_suite7/initializer_lists/statics.c3t new file mode 100644 index 000000000..725e9f1c3 --- /dev/null +++ b/test/test_suite7/initializer_lists/statics.c3t @@ -0,0 +1,72 @@ +// #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 } + +@"$ct.statics.Baz" = linkonce global %.introspect { i8 11, i64 0, ptr null, i64 8, i64 0, i64 2, [0 x i64] zeroinitializer }, align 8 +@"$ct.statics.Bar" = linkonce global %.introspect { i8 10, i64 0, ptr null, i64 8, i64 0, i64 2, [0 x i64] zeroinitializer }, align 8 +@.__const = private unnamed_addr constant [1 x %Bar] [%Bar { i32 1, i32 2 }], align 4 +@.__const_slice = private unnamed_addr global [1 x %Bar] [%Bar { i32 1, i32 2 }], align 4 +@test.c = internal unnamed_addr global %"Bar[]" { ptr @.__const_slice, i64 1 }, align 8 +@.str = private unnamed_addr constant [7 x i8] c"%d %d\0A\00", align 1 + +; Function Attrs: +define void @statics.test() #0 { +entry: + %b = alloca %"Bar[]", align 8 + %literal = alloca [1 x %Bar], align 4 + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %literal, ptr align 4 @.__const, i32 8, i1 false) + %0 = insertvalue %"Bar[]" undef, ptr %literal, 0 + %1 = insertvalue %"Bar[]" %0, i64 1, 1 + store %"Bar[]" %1, ptr %b, align 8 + %2 = load ptr, ptr %b, align 8 + %ptradd = getelementptr inbounds i8, ptr %2, i64 4 + %3 = load ptr, ptr @test.c, align 8 + %ptradd1 = getelementptr inbounds i8, ptr %3, i64 4 + %4 = load i32, ptr %ptradd, align 4 + %5 = load i32, ptr %ptradd1, align 4 + %6 = call i32 (ptr, ...) @printf(ptr @.str, i32 %4, i32 %5) + %7 = load ptr, ptr %b, align 8 + %ptradd2 = getelementptr inbounds i8, ptr %7, i64 4 + %8 = load i32, ptr %ptradd2, align 4 + %add = add i32 %8, 1 + store i32 %add, ptr %ptradd2, align 4 + %9 = load ptr, ptr @test.c, align 8 + %ptradd3 = getelementptr inbounds i8, ptr %9, i64 4 + %10 = load i32, ptr %ptradd3, align 4 + %add4 = add i32 %10, 1 + store i32 %add4, ptr %ptradd3, align 4 + ret void +} diff --git a/test/test_suite7/initializer_lists/subarrays.c3t b/test/test_suite7/initializer_lists/subarrays.c3t new file mode 100644 index 000000000..b978cb441 --- /dev/null +++ b/test/test_suite7/initializer_lists/subarrays.c3t @@ -0,0 +1,256 @@ +// #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::printn("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 = {}; + + //var $foo = { 1, 2, 3 }; + bool xy = !(int[]){ 1, 2, 3 }; + if (!xy) io::printn("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 } + +@"$ct.subarrays.Baz" = linkonce global %.introspect { i8 11, i64 0, ptr null, i64 8, i64 0, i64 2, [0 x i64] zeroinitializer }, align 8 +@"$ct.subarrays.Bar" = linkonce global %.introspect { i8 10, i64 0, ptr null, i64 8, i64 0, i64 2, [0 x i64] zeroinitializer }, align 8 +@.__const_slice = private unnamed_addr global [2 x %Bar] [%Bar { i32 3, i32 4 }, %Bar { i32 8, i32 9 }], align 16 +@subarrays.arrbar = local_unnamed_addr global %"Bar[]" { ptr @.__const_slice, i64 2 }, align 8 +@.__const_slice.3 = private unnamed_addr global [2 x i32] [i32 1, i32 2], align 4 +@subarrays.xd = local_unnamed_addr global %"int[]" { ptr @.__const_slice.3, i64 2 }, align 8 +@.taddr = private unnamed_addr global [2 x i32] [i32 3, i32 4], align 4 +@subarrays.fofeo = local_unnamed_addr global ptr @.taddr, align 8 +@.str = private unnamed_addr constant [4 x i8] c"%d\0A\00", align 1 +@.__const = private unnamed_addr constant [3 x i32] [i32 1, i32 2, i32 3], align 4 +@.__const.4 = private unnamed_addr constant [3 x i32] [i32 123, i32 234, i32 567], align 4 +@.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.9 = private unnamed_addr constant { i32, [4 x i8] } { i32 1, [4 x i8] undef }, align 8 +@.str.10 = 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 + %len = alloca i64, align 8 + %error_var = alloca i64, align 8 + %retparam = alloca i64, align 8 + %error_var4 = alloca i64, align 8 + %error_var10 = alloca i64, align 8 + %ffe = alloca %Baz, align 8 + %azz = alloca [1 x i32], align 4 + %xy = alloca i8, align 1 + %len20 = alloca i64, align 8 + %error_var21 = alloca i64, align 8 + %retparam23 = alloca i64, align 8 + %error_var29 = alloca i64, align 8 + %error_var35 = alloca i64, align 8 + %b = alloca %Bar, align 4 + %z = alloca %Baz, align 8 + %sub = alloca %"int[]", align 8 + %foo = alloca %"Bar[]", align 8 + %baz = alloca [3 x %Baz], align 16 + %0 = load ptr, ptr @subarrays.arrbar, align 8 + %ptradd = getelementptr inbounds i8, ptr %0, i64 8 + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %w, ptr align 4 %ptradd, i32 8, i1 false) + %1 = load ptr, ptr @subarrays.arrbar, align 8 + %ptradd1 = getelementptr inbounds i8, ptr %1, i64 8 + %2 = load i32, ptr %ptradd1, align 4 + %3 = call i32 (ptr, ...) @printf(ptr @.str, i32 %2) + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %literal, ptr align 4 @.__const, i32 12, i1 false) + %4 = insertvalue %"int[]" undef, ptr %literal, 0 + %5 = insertvalue %"int[]" %4, i64 3, 1 + store %"int[]" %5, ptr %x, align 8 + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %literal2, ptr align 4 @.__const.4, i32 12, i1 false) + store ptr %literal2, ptr %y, align 8 + %6 = call ptr @std.io.stdout() + %7 = call i64 @std.io.File.write(ptr %retparam, ptr %6, ptr @.str.5, i64 6) + %not_err = icmp eq i64 %7, 0 + %8 = call i1 @llvm.expect.i1(i1 %not_err, i1 true) + br i1 %8, label %after_check, label %assign_optional + +assign_optional: ; preds = %entry + store i64 %7, ptr %error_var, align 8 + br label %guard_block + +after_check: ; preds = %entry + br label %noerr_block + +guard_block: ; preds = %assign_optional + br label %voiderr + +noerr_block: ; preds = %after_check + %9 = load i64, ptr %retparam, align 8 + store i64 %9, ptr %len, align 8 + %10 = call i64 @std.io.File.write_byte(ptr %6, i8 zeroext 10) + %not_err5 = icmp eq i64 %10, 0 + %11 = call i1 @llvm.expect.i1(i1 %not_err5, i1 true) + br i1 %11, label %after_check7, label %assign_optional6 + +assign_optional6: ; preds = %noerr_block + store i64 %10, ptr %error_var4, align 8 + br label %guard_block8 + +after_check7: ; preds = %noerr_block + br label %noerr_block9 + +guard_block8: ; preds = %assign_optional6 + br label %voiderr + +noerr_block9: ; preds = %after_check7 + %12 = call i64 @std.io.File.flush(ptr %6) + %not_err11 = icmp eq i64 %12, 0 + %13 = call i1 @llvm.expect.i1(i1 %not_err11, i1 true) + br i1 %13, label %after_check13, label %assign_optional12 + +assign_optional12: ; preds = %noerr_block9 + store i64 %12, ptr %error_var10, align 8 + br label %guard_block14 + +after_check13: ; preds = %noerr_block9 + br label %noerr_block15 + +guard_block14: ; preds = %assign_optional12 + br label %voiderr + +noerr_block15: ; preds = %after_check13 + %14 = load i64, ptr %len, align 8 + %add = add i64 %14, 1 + br label %voiderr + +voiderr: ; preds = %noerr_block15, %guard_block14, %guard_block8, %guard_block + %ptradd16 = getelementptr inbounds i8, ptr %x, i64 8 + %15 = load i64, ptr %ptradd16, align 8 + %trunc = trunc i64 %15 to i32 + %16 = load ptr, ptr %x, align 8 + %ptradd17 = getelementptr inbounds i8, ptr %16, i64 4 + %17 = load i32, ptr %ptradd17, align 4 + %18 = call i32 (ptr, ...) @printf(ptr @.str.6, i32 %trunc, i32 %17) + %19 = load ptr, ptr %y, align 8 + %ptradd18 = getelementptr inbounds i8, ptr %19, i64 4 + %20 = load i32, ptr %ptradd18, align 4 + %21 = call i32 (ptr, ...) @printf(ptr @.str.7, i32 %20) + %22 = load ptr, ptr @subarrays.fofeo, align 8 + %ptradd19 = getelementptr inbounds i8, ptr %22, i64 4 + %23 = load i32, ptr %ptradd19, align 4 + %24 = call i32 (ptr, ...) @printf(ptr @.str.8, i32 %23) + call void @llvm.memcpy.p0.p0.i32(ptr align 8 %ffe, ptr align 8 @.__const.9, i32 8, i1 false) + store i32 0, ptr %azz, align 4 + store i8 0, ptr %xy, align 1 + %25 = load i8, ptr %xy, align 1 + %26 = trunc i8 %25 to i1 + %not = xor i1 %26, true + br i1 %not, label %if.then, label %if.exit + +if.then: ; preds = %voiderr + %27 = call ptr @std.io.stdout() + %28 = call i64 @std.io.File.write(ptr %retparam23, ptr %27, ptr @.str.10, i64 2) + %not_err24 = icmp eq i64 %28, 0 + %29 = call i1 @llvm.expect.i1(i1 %not_err24, i1 true) + br i1 %29, label %after_check26, label %assign_optional25 + +assign_optional25: ; preds = %if.then + store i64 %28, ptr %error_var21, align 8 + br label %guard_block27 + +after_check26: ; preds = %if.then + br label %noerr_block28 + +guard_block27: ; preds = %assign_optional25 + br label %voiderr42 + +noerr_block28: ; preds = %after_check26 + %30 = load i64, ptr %retparam23, align 8 + store i64 %30, ptr %len20, align 8 + %31 = call i64 @std.io.File.write_byte(ptr %27, i8 zeroext 10) + %not_err30 = icmp eq i64 %31, 0 + %32 = call i1 @llvm.expect.i1(i1 %not_err30, i1 true) + br i1 %32, label %after_check32, label %assign_optional31 + +assign_optional31: ; preds = %noerr_block28 + store i64 %31, ptr %error_var29, align 8 + br label %guard_block33 + +after_check32: ; preds = %noerr_block28 + br label %noerr_block34 + +guard_block33: ; preds = %assign_optional31 + br label %voiderr42 + +noerr_block34: ; preds = %after_check32 + %33 = call i64 @std.io.File.flush(ptr %27) + %not_err36 = icmp eq i64 %33, 0 + %34 = call i1 @llvm.expect.i1(i1 %not_err36, i1 true) + br i1 %34, label %after_check38, label %assign_optional37 + +assign_optional37: ; preds = %noerr_block34 + store i64 %33, ptr %error_var35, align 8 + br label %guard_block39 + +after_check38: ; preds = %noerr_block34 + br label %noerr_block40 + +guard_block39: ; preds = %assign_optional37 + br label %voiderr42 + +noerr_block40: ; preds = %after_check38 + %35 = load i64, ptr %len20, align 8 + %add41 = add i64 %35, 1 + br label %voiderr42 + +voiderr42: ; preds = %noerr_block40, %guard_block39, %guard_block33, %guard_block27 + br label %if.exit + +if.exit: ; preds = %voiderr42, %voiderr + store i32 0, ptr %b, align 4 + %ptradd43 = getelementptr inbounds i8, ptr %b, i64 4 + store i32 0, ptr %ptradd43, align 4 + call void @llvm.memset.p0.i64(ptr align 8 %z, i8 0, i64 8, i1 false) + store %"int[]" zeroinitializer, ptr %sub, align 8 + store %"Bar[]" zeroinitializer, 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_suite7/initializer_lists/zero_inferred_array.c3 b/test/test_suite7/initializer_lists/zero_inferred_array.c3 new file mode 100644 index 000000000..3be21cafb --- /dev/null +++ b/test/test_suite7/initializer_lists/zero_inferred_array.c3 @@ -0,0 +1,4 @@ +fn void test() +{ + int[?] a = {}; // #error: Zero length +} \ No newline at end of file diff --git a/test/test_suite7/initializer_lists/zero_init.c3t b/test/test_suite7/initializer_lists/zero_init.c3t new file mode 100644 index 000000000..d0e18dc0f --- /dev/null +++ b/test/test_suite7/initializer_lists/zero_init.c3t @@ -0,0 +1,56 @@ +// #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 = {}; + 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 + %b = alloca %Bar, align 4 + %z = alloca %Baz, align 8 + %sub = alloca %"int[]", align 8 + %foo = alloca %"Bar[]", align 8 + %baz = alloca [3 x %Baz], align 16 + call void @llvm.memset.p0.i64(ptr align 4 %m, i8 0, i64 40, i1 false) + store i32 0, ptr %azz, align 4 + store i32 0, ptr %b, align 4 + %ptradd = getelementptr inbounds i8, ptr %b, i64 4 + store i32 0, ptr %ptradd, align 4 + call void @llvm.memset.p0.i64(ptr align 8 %z, i8 0, i64 8, i1 false) + store %"int[]" zeroinitializer, ptr %sub, align 8 + store %"Bar[]" zeroinitializer, 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_suite7/lambda/ct_lambda.c3t b/test/test_suite7/lambda/ct_lambda.c3t new file mode 100644 index 000000000..d8132b6ba --- /dev/null +++ b/test/test_suite7/lambda/ct_lambda.c3t @@ -0,0 +1,138 @@ +// #target: macos-x64 +module test; +import std::io; + +def FooFn = fn void(Foo* f, int x); + +struct Foo +{ + FooFn x; +} + +struct FooTest +{ + inline Foo a; +} + +struct FooTest2 +{ + inline Foo a; + int z; +} + +fn void Foo.test(Foo* f, int x) +{ + f.x(f, x); +} + +fn void FooTest.init(FooTest* this) +{ + static FooFn foo = foo_fn(FooTest); + this.x = foo; +} + +fn void FooTest.high(FooTest* t, int x) +{ + io::printfn("High: %d", x); +} + +fn void FooTest.low(FooTest* t, int x) +{ + io::printfn("Low: %d", x); +} + +fn void FooTest2.init(FooTest2* this, int z) +{ + static FooFn foo = foo_fn(FooTest2); + this.x = foo; + this.z = z; +} + +fn void FooTest2.high(FooTest2* t, int x) +{ + io::printfn("High2: %d", x * t.z); +} + +fn void FooTest2.low(FooTest2* t, int x) +{ + io::printfn("Low2: %d", x * t.z); +} + +macro FooFn foo_fn($FooType) +{ + return fn void(Foo* f, int x) { + $FooType* z = ($FooType*)f; + if (x > 0) return z.high(x); + return z.low(x); + }; +} + +fn int main() +{ + FooTest a; + a.init(); + a.test(10); + a.test(0); + a.test(-1); + FooTest2 b; + b.init(100); + b.test(10); + b.test(0); + b.test(-1); + return 0; +} + +/* #expect: test.ll + +@init.foo = internal unnamed_addr global ptr @"test.foo_fn$lambda1", align 8 +@init.foo.2 = internal unnamed_addr global ptr @"test.foo_fn$lambda2", align 8 + +define void @test.Foo.test(ptr %0, i32 %1) #0 { +entry: + %2 = load ptr, ptr %0, align 8 + call void %2(ptr %0, i32 %1) + ret void +} + +define void @test.FooTest.init(ptr %0) #0 { +entry: + %1 = load ptr, ptr @init.foo, align 8 + store ptr %1, ptr %0, align 8 + ret void +} + +define internal void @"test.foo_fn$lambda1"(ptr %0, i32 %1) #0 { +entry: + %z = alloca ptr, align 8 + store ptr %0, ptr %z, align 8 + %gt = icmp sgt i32 %1, 0 + br i1 %gt, label %if.then, label %if.exit + +if.then: ; preds = %entry + %2 = load ptr, ptr %z, align 8 + call void @test.FooTest.high(ptr %2, i32 %1) + ret void + +if.exit: ; preds = %entry + %3 = load ptr, ptr %z, align 8 + call void @test.FooTest.low(ptr %3, i32 %1) + ret void +} + +define internal void @"test.foo_fn$lambda2"(ptr %0, i32 %1) #0 { +entry: + %z = alloca ptr, align 8 + store ptr %0, ptr %z, align 8 + %gt = icmp sgt i32 %1, 0 + br i1 %gt, label %if.then, label %if.exit + +if.then: ; preds = %entry + %2 = load ptr, ptr %z, align 8 + call void @test.FooTest2.high(ptr %2, i32 %1) + ret void + +if.exit: ; preds = %entry + %3 = load ptr, ptr %z, align 8 + call void @test.FooTest2.low(ptr %3, i32 %1) + ret void +} \ No newline at end of file diff --git a/test/test_suite7/lambda/ct_lambda2.c3t b/test/test_suite7/lambda/ct_lambda2.c3t new file mode 100644 index 000000000..57b5df2d6 --- /dev/null +++ b/test/test_suite7/lambda/ct_lambda2.c3t @@ -0,0 +1,84 @@ +// #target: macos-x64 +module test; +import std::io; + +def Call = fn void(); + +fn int main() +{ + var $x = 0; + $for (var $i = 0; $i < 10; $i++) + { + var $Type = int; + $if $i % 2 == 0: + $Type = double; + $endif + $if $i % 3 == 0: + $x++; + $endif; + Call x = fn () => (void)io::printfn("%d %s", $x, $Type.nameof); + x(); + } + $endfor + return 0; +} + +/* #expect: test.ll + +@.str.1 = private unnamed_addr constant [7 x i8] c"double\00", align 1 +@.str.3 = private unnamed_addr constant [4 x i8] c"int\00", align 1 +@.str.5 = private unnamed_addr constant [4 x i8] c"int\00", align 1 +@.str.7 = private unnamed_addr constant [7 x i8] c"double\00", align 1 +@.str.9 = private unnamed_addr constant [7 x i8] c"double\00", align 1 +@.str.11 = private unnamed_addr constant [4 x i8] c"int\00", align 1 +@.str.13 = private unnamed_addr constant [4 x i8] c"int\00", align 1 + + +define i32 @main() #0 { + store ptr @"test.main$lambda1", ptr %x, align 8 + %0 = load ptr, ptr %x, align 8 + call void %0() + store ptr @"test.main$lambda2", ptr %x1, align 8 + %1 = load ptr, ptr %x1, align 8 + call void %1() + store ptr @"test.main$lambda1", ptr %x2, align 8 + %2 = load ptr, ptr %x2, align 8 + call void %2() + store ptr @"test.main$lambda3", ptr %x3, align 8 + %3 = load ptr, ptr %x3, align 8 + call void %3() + store ptr @"test.main$lambda4", ptr %x4, align 8 + %4 = load ptr, ptr %x4, align 8 + call void %4() + store ptr @"test.main$lambda3", ptr %x5, align 8 + %5 = load ptr, ptr %x5, align 8 + call void %5() + store ptr @"test.main$lambda5", ptr %x6, align 8 + %6 = load ptr, ptr %x6, align 8 + call void %6() + store ptr @"test.main$lambda6", ptr %x7, align 8 + %7 = load ptr, ptr %x7, align 8 + call void %7() + store ptr @"test.main$lambda5", ptr %x8, align 8 + %8 = load ptr, ptr %x8, align 8 + call void %8() + store ptr @"test.main$lambda7", ptr %x9, align 8 + %9 = load ptr, ptr %x9, align 8 + call void %9() + ret i32 0 +} + +define internal void @"test.main$lambda1"() #0 { + store %"char[]" { ptr @.str.1, i64 6 }, ptr %taddr1, align 8 +define internal void @"test.main$lambda2"() #0 { + store %"char[]" { ptr @.str.3, i64 3 }, ptr %taddr1, align 8 +define internal void @"test.main$lambda3"() #0 { + store %"char[]" { ptr @.str.5, i64 3 }, ptr %taddr1, align 8 +define internal void @"test.main$lambda4"() #0 { + store %"char[]" { ptr @.str.7, i64 6 }, ptr %taddr1, align 8 +define internal void @"test.main$lambda5"() #0 { + store %"char[]" { ptr @.str.9, i64 6 }, ptr %taddr1, align 8 +define internal void @"test.main$lambda6"() #0 { + store %"char[]" { ptr @.str.11, i64 3 }, ptr %taddr1, align 8 +define internal void @"test.main$lambda7"() #0 { + store %"char[]" { ptr @.str.13, i64 3 }, ptr %taddr1, align 8 \ No newline at end of file diff --git a/test/test_suite7/lambda/lambda_checks.c3 b/test/test_suite7/lambda/lambda_checks.c3 new file mode 100644 index 000000000..a441e944c --- /dev/null +++ b/test/test_suite7/lambda/lambda_checks.c3 @@ -0,0 +1,14 @@ +module test; +def Func = fn void (bool); + +fn bool foo (String) => true; +fn void bar(Func func) => func(false); + +fn void main() +{ + Func funcX = &foo; // #error: Implicitly casting + bar(&foo); // #error: Implicitly casting + + Func func = fn bool (String) { return true; }; // #error: which doesn't match + bar(fn bool (String) { return true; }); // #error: which doesn't match +} \ No newline at end of file diff --git a/test/test_suite7/lambda/lambda_in_macro.c3t b/test/test_suite7/lambda/lambda_in_macro.c3t new file mode 100644 index 000000000..7b88e2d01 --- /dev/null +++ b/test/test_suite7/lambda/lambda_in_macro.c3t @@ -0,0 +1,45 @@ +// #target: macos-x64 +module test; +import std::io; + +def Callback1 = fn double(double x); +def Callback2 = fn int(int y); + +macro test2(y) +{ + var $Type = $typeof(y); + return fn $Type($typeof(y) x) { return x * x; }; +} + +macro test($Type) +{ + $Type z = fn (x) { return x * x; }; + return z; +} + +fn void main() +{ + io::printfn("val: %d", test(Callback2)(3)); + io::printfn("val: %s", test(Callback1)(3.3)); + io::printfn("val: %s", test(Callback1)(3.3)); + io::printfn("val: %d", test2(1)(3)); + io::printfn("val: %d", test2(1)(3)); + io::printfn("val: %s", test2(1.0)(3.3)); +} + +/* #expect: test.ll + + store ptr @"test.test$lambda1", ptr %z, align 8 + %1 = call i32 %0(i32 3) + store ptr @"test.test$lambda2", ptr %z2, align 8 + %6 = call double %5(double 3.300000e+00) + store ptr @"test.test$lambda2", ptr %z6, align 8 + %11 = call double %10(double 3.300000e+00) + %15 = call i32 @"test.test2$lambda3"(i32 3) + %19 = call i32 @"test.test2$lambda3"(i32 3) + %23 = call double @"test.test2$lambda4"(double 3.300000e+00) + +define internal i32 @"test.test$lambda1"(i32 %0) #0 { +define internal double @"test.test$lambda2"(double %0) #0 { +define internal i32 @"test.test2$lambda3"(i32 %0) #0 { +define internal double @"test.test2$lambda4"(double %0) #0 { diff --git a/test/test_suite7/lambda/lambda_ref.c3t b/test/test_suite7/lambda/lambda_ref.c3t new file mode 100644 index 000000000..8c3bd5459 --- /dev/null +++ b/test/test_suite7/lambda/lambda_ref.c3t @@ -0,0 +1,35 @@ +// #target: macos-x64 +module test; + +def FnA = fn void(int*); + +fn void func(int*) { } +fn void main() +{ + FnA* a = && &func; + a = &&(fn void(int*) { }); +} + +/* #expect: test.ll + +define void @test.func(ptr %0) #0 { +entry: + ret void +} + +define void @test.main() #0 { +entry: + %a = alloca ptr, align 8 + %taddr = alloca ptr, align 8 + %taddr1 = alloca ptr, align 8 + store ptr @test.func, ptr %taddr, align 8 + store ptr %taddr, ptr %a, align 8 + store ptr @"test.main$lambda1", ptr %taddr1, align 8 + store ptr %taddr1, ptr %a, align 8 + ret void +} + +define internal void @"test.main$lambda1"(ptr %0) #0 { +entry: + ret void +} diff --git a/test/test_suite7/lambda/nested_lambda_def.c3t b/test/test_suite7/lambda/nested_lambda_def.c3t new file mode 100644 index 000000000..7cf23fada --- /dev/null +++ b/test/test_suite7/lambda/nested_lambda_def.c3t @@ -0,0 +1,78 @@ +// #target: macos-x64 +module abc; +import bar; +import std::io; + +fn int xy(Callback a) => a(); + +fn void main() +{ + const Callback F = bar::get_callback(); + int z = xy(F); + z = xy(F); + io::printfn("val: %d", z); +} + +module foo; +import bar; +import std::io; + +int xz @private = 0; + + +macro Callback get_callback() +{ + return fn int() { return bar::get_callback2()(); }; +} + +macro Callback get_callback2() +{ + return fn int() { io::printfn("Hello"); return ++xz; }; +} + +module bar; +import foo; +def Callback = fn int(); + +macro Callback get_callback() +{ + return fn int() { return foo::get_callback()(); }; +} + +macro Callback get_callback2() +{ + return fn int() { return foo::get_callback2()(); }; +} + +/* #expect: abc.ll + +@main.F = internal unnamed_addr constant ptr @"bar.get_callback$lambda1", align 8 + %0 = call i32 @abc.xy(ptr @"bar.get_callback$lambda1") + %1 = call i32 @abc.xy(ptr @"bar.get_callback$lambda1") +declare i32 @"bar.get_callback$lambda1"() + +// #expect: foo.ll + +define i32 @"foo.get_callback2$lambda2"() #0 { + %1 = load i32, ptr @foo.xz, align 4 + +define i32 @"foo.get_callback$lambda1"() #0 { + %0 = call i32 @"bar.get_callback2$lambda2"() + +declare i32 @"bar.get_callback2$lambda2"() + +// #expect: bar.ll + +define i32 @"bar.get_callback2$lambda2"() #0 { +entry: + %0 = call i32 @"foo.get_callback2$lambda2"() + ret i32 %0 +} +define i32 @"bar.get_callback$lambda1"() #0 { +entry: + %0 = call i32 @"foo.get_callback$lambda1"() + ret i32 %0 + +declare i32 @"foo.get_callback2$lambda2"() #0 +declare i32 @"foo.get_callback$lambda1"() #0 + diff --git a/test/test_suite7/lambda/simple_lambda.c3t b/test/test_suite7/lambda/simple_lambda.c3t new file mode 100644 index 000000000..226bbbd2b --- /dev/null +++ b/test/test_suite7/lambda/simple_lambda.c3t @@ -0,0 +1,33 @@ +// #target: macos-x64 +import std::io; +import std::math::vector; +import std::math; + +def Callback = fn int(); + +fn int xy(Callback a) => a(); + +fn void main() +{ + const Callback F = fn int() { io::printfn("Hello"); return 23; }; + int z = xy(F); + io::printfn("%d", z); + int y = xy(fn () { return 3; }); +} + +/* #expect: simple_lambda.ll + +@main.F = internal unnamed_addr constant ptr @"simple_lambda.main$lambda1", align 8 + +define void @simple_lambda.main() #0 { +entry: + %z = alloca i32, align 4 + %0 = call i32 @simple_lambda.xy(ptr @"simple_lambda.main$lambda1") + %4 = call i32 @simple_lambda.xy(ptr @"simple_lambda.main$lambda2") + +define internal i32 @"simple_lambda.main$lambda1"() #0 { + +define internal i32 @"simple_lambda.main$lambda2"() #0 { +entry: + ret i32 3 +} diff --git a/test/test_suite7/lambda/var_lambda.c3 b/test/test_suite7/lambda/var_lambda.c3 new file mode 100644 index 000000000..44d0530a5 --- /dev/null +++ b/test/test_suite7/lambda/var_lambda.c3 @@ -0,0 +1,8 @@ +module test; +import std; +fn void main() +{ + var x = fn int(int y) { return y * 2; }; + io::printn(x(4)); + io::printn(x(3)); +} \ No newline at end of file diff --git a/test/test_suite7/lexing/expected_directive.c3 b/test/test_suite7/lexing/expected_directive.c3 new file mode 100644 index 000000000..46ef6465d --- /dev/null +++ b/test/test_suite7/lexing/expected_directive.c3 @@ -0,0 +1,4 @@ +<* +@hello +@param feij > 0 // #error: A string containing the description +*> diff --git a/test/test_suite7/lexing/invalid_hex_in_hexarray.c3 b/test/test_suite7/lexing/invalid_hex_in_hexarray.c3 new file mode 100644 index 000000000..536515a37 --- /dev/null +++ b/test/test_suite7/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_suite7/lexing/invalid_hex_in_hexarray2.c3 b/test/test_suite7/lexing/invalid_hex_in_hexarray2.c3 new file mode 100644 index 000000000..eb571c8b2 --- /dev/null +++ b/test/test_suite7/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_suite7/lexing/no_builtin.c3 b/test/test_suite7/lexing/no_builtin.c3 new file mode 100644 index 000000000..09ff7d6d9 --- /dev/null +++ b/test/test_suite7/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_suite7/literals/bad_bitwidth.c3 b/test/test_suite7/literals/bad_bitwidth.c3 new file mode 100644 index 000000000..e5cf75f34 --- /dev/null +++ b/test/test_suite7/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_suite7/literals/bin_literal.c3t b/test/test_suite7/literals/bin_literal.c3t new file mode 100644 index 000000000..ba0f1ea0b --- /dev/null +++ b/test/test_suite7/literals/bin_literal.c3t @@ -0,0 +1,77 @@ +// #target: macos-x64 +module test; +import std::io; +import std::bits; +fn void main() +{ + int a = 123; + int b = -23; + int c = $$min(a, b); + int d = $$max(a, b); + io::printfn("%d %d", c, d); + char z = 0b1101_1101; + io::printfn("%b %b %b", z, z.rotr(1), z.rotl(1)); +} + +/* #expect: test.ll + +define void @test.main() #0 { +entry: + %a = alloca i32, align 4 + %b = alloca i32, align 4 + %c = alloca i32, align 4 + %d = alloca i32, align 4 + %varargslots = alloca [2 x %any], align 16 + %retparam = alloca i64, align 8 + %z = alloca i8, align 1 + %varargslots1 = alloca [3 x %any], align 16 + %self = alloca i8, align 1 + %taddr = alloca i8, align 1 + %self3 = alloca i8, align 1 + %taddr4 = alloca i8, align 1 + %retparam6 = alloca i64, align 8 + store i32 123, ptr %a, align 4 + store i32 -23, ptr %b, align 4 + %0 = load i32, ptr %a, align 4 + %1 = load i32, ptr %b, align 4 + %2 = call i32 @llvm.smin.i32(i32 %0, i32 %1) + store i32 %2, ptr %c, align 4 + %3 = load i32, ptr %a, align 4 + %4 = load i32, ptr %b, align 4 + %5 = call i32 @llvm.smax.i32(i32 %3, i32 %4) + store i32 %5, ptr %d, align 4 + %6 = insertvalue %any undef, ptr %c, 0 + %7 = insertvalue %any %6, i64 ptrtoint (ptr @"$ct.int" to i64), 1 + store %any %7, ptr %varargslots, align 16 + %8 = insertvalue %any undef, ptr %d, 0 + %9 = insertvalue %any %8, i64 ptrtoint (ptr @"$ct.int" to i64), 1 + %ptradd = getelementptr inbounds i8, ptr %varargslots, i64 16 + store %any %9, ptr %ptradd, align 16 + %10 = call i64 @std.io.printfn(ptr %retparam, ptr @.str, i64 5, ptr %varargslots, i64 2) + store i8 -35, ptr %z, align 1 + %11 = insertvalue %any undef, ptr %z, 0 + %12 = insertvalue %any %11, i64 ptrtoint (ptr @"$ct.char" to i64), 1 + store %any %12, ptr %varargslots1, align 16 + %13 = load i8, ptr %z, align 1 + store i8 %13, ptr %self, align 1 + %14 = load i8, ptr %self, align 1 + %15 = load i8, ptr %self, align 1 + %16 = call i8 @llvm.fshr.i8(i8 %14, i8 %15, i8 1) + store i8 %16, ptr %taddr, align 1 + %17 = insertvalue %any undef, ptr %taddr, 0 + %18 = insertvalue %any %17, i64 ptrtoint (ptr @"$ct.char" to i64), 1 + %ptradd2 = getelementptr inbounds i8, ptr %varargslots1, i64 16 + store %any %18, ptr %ptradd2, align 16 + %19 = load i8, ptr %z, align 1 + store i8 %19, ptr %self3, align 1 + %20 = load i8, ptr %self3, align 1 + %21 = load i8, ptr %self3, align 1 + %22 = call i8 @llvm.fshl.i8(i8 %20, i8 %21, i8 1) + store i8 %22, ptr %taddr4, align 1 + %23 = insertvalue %any undef, ptr %taddr4, 0 + %24 = insertvalue %any %23, i64 ptrtoint (ptr @"$ct.char" to i64), 1 + %ptradd5 = getelementptr inbounds i8, ptr %varargslots1, i64 32 + store %any %24, ptr %ptradd5, align 16 + %25 = call i64 @std.io.printfn(ptr %retparam6, ptr @.str.1, i64 8, ptr %varargslots1, i64 3) + ret void +} diff --git a/test/test_suite7/literals/bin_literal2.c3t b/test/test_suite7/literals/bin_literal2.c3t new file mode 100644 index 000000000..bafeeb6bb --- /dev/null +++ b/test/test_suite7/literals/bin_literal2.c3t @@ -0,0 +1,30 @@ +// #target: macos-x64 +module test; + +const char C = 0b1000_0000; +const ichar IC = 0b0100_0000; + +const ushort US = 0b1000_0000_0000_0000; +const short S = 0b0100_0000_0000_0000; + +const uint UI = 0b1000_0000_0000_0000_0000_0000_0000_0000; +const int I = 0b0100_0000_0000_0000_0000_0000_0000_0000; + +const ulong UL = 0b1000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000; +const long L = 0b0100_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000; + +const uint128 UI128 = 0b1000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000; +const int128 I128 = 0b0100_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000; + +/* #expect: test.ll + +@test.C = local_unnamed_addr constant i8 -128, align 1 +@test.IC = local_unnamed_addr constant i8 64, align 1 +@test.US = local_unnamed_addr constant i16 -32768, align 2 +@test.S = local_unnamed_addr constant i16 16384, align 2 +@test.UI = local_unnamed_addr constant i32 -2147483648, align 4 +@test.I = local_unnamed_addr constant i32 1073741824, align 4 +@test.UL = local_unnamed_addr constant i64 -9223372036854775808, align 8 +@test.L = local_unnamed_addr constant i64 4611686018427387904, align 8 +@test.UI128 = local_unnamed_addr constant i128 -170141183460469231731687303715884105728, +@test.I128 = local_unnamed_addr constant i128 85070591730234615865843651857942052864, \ No newline at end of file diff --git a/test/test_suite7/literals/literal_general.c3t b/test/test_suite7/literals/literal_general.c3t new file mode 100644 index 000000000..377c6096e --- /dev/null +++ b/test/test_suite7/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_suite7/literals/multi_unicode.c3 b/test/test_suite7/literals/multi_unicode.c3 new file mode 100644 index 000000000..4d328167c --- /dev/null +++ b/test/test_suite7/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_suite7/literals/radix_numbers_errors.c3 b/test/test_suite7/literals/radix_numbers_errors.c3 new file mode 100644 index 000000000..a37970238 --- /dev/null +++ b/test/test_suite7/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_suite7/literals/too_small.c3 b/test/test_suite7/literals/too_small.c3 new file mode 100644 index 000000000..129389d4d --- /dev/null +++ b/test/test_suite7/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_suite7/macro_methods/access.c3 b/test/test_suite7/macro_methods/access.c3 new file mode 100644 index 000000000..91a5fc184 --- /dev/null +++ b/test/test_suite7/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_suite7/macro_methods/macro_method_different_args.c3t b/test/test_suite7/macro_methods/macro_method_different_args.c3t new file mode 100644 index 000000000..d4277fb1c --- /dev/null +++ b/test/test_suite7/macro_methods/macro_method_different_args.c3t @@ -0,0 +1,49 @@ +// #target: macos-x64 +module foo; + +extern fn void printf(char* fmt, ...); +struct Foo +{ + int x; +} + +macro void Foo.@hello(Foo* &this) { this.x = 3; printf("-%d\n", this.x); } +macro void Foo.hello(Foo* this) { this.x = 4; printf("-%d\n", this.x); } +macro void Foo.hello2(Foo this) { this.x = 5; printf("-%d\n", this.x); } + +fn void main() +{ + Foo a; + a.@hello(); + printf("%d\n", a.x); + a.hello(); + printf("%d\n", a.x); + a.hello2(); + printf("%d\n", a.x); +} + +/* #expect: foo.ll + +define void @foo.main() #0 { +entry: + %a = alloca %Foo, align 4 + %this = alloca %Foo, align 4 + store i32 0, ptr %a, align 4 + store i32 3, ptr %a, align 4 + %0 = load i32, ptr %a, align 4 + call void (ptr, ...) @printf(ptr @.str, i32 %0) + %1 = load i32, ptr %a, align 4 + call void (ptr, ...) @printf(ptr @.str.1, i32 %1) + store i32 4, ptr %a, align 4 + %2 = load i32, ptr %a, align 4 + call void (ptr, ...) @printf(ptr @.str.2, i32 %2) + %3 = load i32, ptr %a, align 4 + call void (ptr, ...) @printf(ptr @.str.3, i32 %3) + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %this, ptr align 4 %a, i32 4, i1 false) + store i32 5, ptr %this, align 4 + %4 = load i32, ptr %this, align 4 + call void (ptr, ...) @printf(ptr @.str.4, i32 %4) + %5 = load i32, ptr %a, align 4 + call void (ptr, ...) @printf(ptr @.str.5, i32 %5) + ret void +} \ No newline at end of file diff --git a/test/test_suite7/macro_methods/macro_method_fails.c3 b/test/test_suite7/macro_methods/macro_method_fails.c3 new file mode 100644 index 000000000..367e7fa5a --- /dev/null +++ b/test/test_suite7/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_suite7/macro_methods/macro_method_first_param.c3 b/test/test_suite7/macro_methods/macro_method_first_param.c3 new file mode 100644 index 000000000..58267b9a5 --- /dev/null +++ b/test/test_suite7/macro_methods/macro_method_first_param.c3 @@ -0,0 +1,4 @@ + +struct Foo { int y; } + +macro Foo.text(...) => f.y; // #error: The first parameter to this method must \ No newline at end of file diff --git a/test/test_suite7/macro_methods/macro_methods_defined_twice.c3 b/test/test_suite7/macro_methods/macro_methods_defined_twice.c3 new file mode 100644 index 000000000..01f70ed04 --- /dev/null +++ b/test/test_suite7/macro_methods/macro_methods_defined_twice.c3 @@ -0,0 +1,32 @@ +module foo; + +struct Bar +{ + int x; +} + +module baz; +import foo; +import std::io; + +macro void foo::Bar.@test(Bar* &bar) +{ + io::printn("Inside of baz::Bar.test"); +} + +module bad; +import foo; +macro void Bar.@test(Bar* &bar) // #error: This macro method is already defined for 'Bar'. +{ + io::printn("Inside of baz::Bar.test"); +} + +module abc; +import foo; + +fn void main() +{ + Bar bar; + bar.@test(); +} + diff --git a/test/test_suite7/macro_methods/macro_methods_no_args.c3 b/test/test_suite7/macro_methods/macro_methods_no_args.c3 new file mode 100644 index 000000000..c7d235144 --- /dev/null +++ b/test/test_suite7/macro_methods/macro_methods_no_args.c3 @@ -0,0 +1,17 @@ +import std::io; +// Issue #1990 +struct Foo +{ + uint field; +} + +macro Foo.bar() // #error: A method must start with an argument +{ + io.printn("UwU"); +} + +fn void main() +{ + Foo foo = {}; + foo.bar(); +} \ No newline at end of file diff --git a/test/test_suite7/macros/hash_ident.c3 b/test/test_suite7/macros/hash_ident.c3 new file mode 100644 index 000000000..e16659d87 --- /dev/null +++ b/test/test_suite7/macros/hash_ident.c3 @@ -0,0 +1,25 @@ +macro int @cofefe(#a) +{ + int y = 0; + return #a + #a; +} + +int abc @private = 1; + +fn int xx() +{ + abc++; + return abc; +} + +fn void main() +{ + var $x = 0; + int x = 0; + @cofefe(x += 1); + @cofefe(xx()); + $typeof($x += 1) xx; + $assert $x == 1; + @cofefe(y += 1); // #error: 'y' could not be found +} + diff --git a/test/test_suite7/macros/hash_ident_nested.c3t b/test/test_suite7/macros/hash_ident_nested.c3t new file mode 100644 index 000000000..8404a6d65 --- /dev/null +++ b/test/test_suite7/macros/hash_ident_nested.c3t @@ -0,0 +1,34 @@ +// #target: macos-x64 +module test; +fn void main() +{ + @foo(x); +} + +struct Point { float x; float y; } + +macro @foo(#x) +{ + @bar(#x); +} + +macro @bar(#x) +{ + Point pt; + var z = pt.#x; +} + +/* #expect: test.ll + +define void @test.main() #0 { +entry: + %pt = alloca %Point, align 4 + %z = alloca float, align 4 + store float 0.000000e+00, ptr %pt, align 4 + %ptradd = getelementptr inbounds i8, ptr %pt, i64 4 + store float 0.000000e+00, ptr %ptradd, align 4 + %0 = load float, ptr %pt, align 4 + store float %0, ptr %z, align 4 + ret void +} + diff --git a/test/test_suite7/macros/hash_initializer.c3t b/test/test_suite7/macros/hash_initializer.c3t new file mode 100644 index 000000000..a508a3633 --- /dev/null +++ b/test/test_suite7/macros/hash_initializer.c3t @@ -0,0 +1,23 @@ +module test; + +macro int[2] test(#abc) @safemacro +{ + return #abc; +} + +fn void main() +{ + int[2] x = (int[2]) { 1, 2 }; + int[2] y = test({ 2, 3 }); + int[2] z = test({ [0] = 1 }); +} + +/* #expect: test.ll + +@.__const = private unnamed_addr constant [2 x i32] [i32 1, i32 2], align 4 +@.__const.1 = private unnamed_addr constant [2 x i32] [i32 2, i32 3], align 4 +@.__const.2 = private unnamed_addr constant [2 x i32] [i32 1, i32 0], align 4 + + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %x, ptr align 4 @.__const, i32 8, i1 false) + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %y, ptr align 4 @.__const.1, i32 8, i1 false) + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %z, ptr align 4 @.__const.2, i32 8, i1 false) diff --git a/test/test_suite7/macros/implicit_return_opt.c3 b/test/test_suite7/macros/implicit_return_opt.c3 new file mode 100644 index 000000000..91c5cb20e --- /dev/null +++ b/test/test_suite7/macros/implicit_return_opt.c3 @@ -0,0 +1,19 @@ +module test; +import std::io; + +fn void main() +{ + int x = run()!!; // #error: You cannot cast + io::printfn("x=%d", x); +} + +macro run() +{ + int i; + while (true) + { + i++; + if (i > 10) break; + if (i > 100) return IoError.EOF?; + } +} \ No newline at end of file diff --git a/test/test_suite7/macros/macro_always_const.c3 b/test/test_suite7/macros/macro_always_const.c3 new file mode 100644 index 000000000..72a31f5df --- /dev/null +++ b/test/test_suite7/macros/macro_always_const.c3 @@ -0,0 +1,9 @@ +macro bar() @const +{ + return; // #error: provide a value +} + +macro void barz() @const // #error: return a constant +{ + return 1; +} diff --git a/test/test_suite7/macros/macro_body_as_value.c3 b/test/test_suite7/macros/macro_body_as_value.c3 new file mode 100644 index 000000000..b8df768a4 --- /dev/null +++ b/test/test_suite7/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_suite7/macros/macro_body_defer.c3t b/test/test_suite7/macros/macro_body_defer.c3t new file mode 100644 index 000000000..a3fae041b --- /dev/null +++ b/test/test_suite7/macros/macro_body_defer.c3t @@ -0,0 +1,87 @@ +// #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; + }; + } +} + +/* #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 void @foo.main() #0 { +entry: + call void (ptr, ...) @printf(ptr @.str) + call void (ptr, ...) @printf(ptr @.str.1) + call void (ptr, ...) @printf(ptr @.str.2) + call void (ptr, ...) @printf(ptr @.str.3) + call void (ptr, ...) @printf(ptr @.str.4, i32 34) + call void (ptr, ...) @printf(ptr @.str.5, i32 34) + br label %loop.body +loop.body: ; preds = %entry + call void (ptr, ...) @printf(ptr @.str.6) + call void (ptr, ...) @printf(ptr @.str.7) + call void (ptr, ...) @printf(ptr @.str.8, i32 3) + call void (ptr, ...) @printf(ptr @.str.9) + br label %loop.exit +loop.exit: ; preds = %loop.body + br label %loop.body1 +loop.body1: ; preds = %loop.exit + call void (ptr, ...) @printf(ptr @.str.10) + call void (ptr, ...) @printf(ptr @.str.11) + call void (ptr, ...) @printf(ptr @.str.12) + call void (ptr, ...) @printf(ptr @.str.13, i32 3) + call void (ptr, ...) @printf(ptr @.str.14) + ret void +} + +define i32 @main(i32 %0, ptr %1) #0 { +entry: + call void @foo.main() + ret i32 0 +} diff --git a/test/test_suite7/macros/macro_body_errors.c3 b/test/test_suite7/macros/macro_body_errors.c3 new file mode 100644 index 000000000..de4de1fa2 --- /dev/null +++ b/test/test_suite7/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_suite7/macros/macro_body_missing_type.c3 b/test/test_suite7/macros/macro_body_missing_type.c3 new file mode 100644 index 000000000..570345205 --- /dev/null +++ b/test/test_suite7/macros/macro_body_missing_type.c3 @@ -0,0 +1,17 @@ +enum Foo +{ + A, +} + +fn void main() +{ + @test(;$f) // #error: should be explicitly + { + + }; +} + +macro @test(; @body(Foo $f)) +{ + @body(A); +} \ No newline at end of file diff --git a/test/test_suite7/macros/macro_body_ref_hash_constant_type.c3t b/test/test_suite7/macros/macro_body_ref_hash_constant_type.c3t new file mode 100644 index 000000000..37d722654 --- /dev/null +++ b/test/test_suite7/macros/macro_body_ref_hash_constant_type.c3t @@ -0,0 +1,167 @@ +// #target: macos-x64 +// #deprecation: no +module test; +import std::io; + +fn void main() +{ + @boba(;#hash_val, #foo, int $value, $Type) + { + io::printn("Now invoking hash"); + #hash_val; + #hash_val; + #foo += $value; + io::printfn("The type was: %s", $Type.nameof); + }; +} + +macro void @boba(;@body(#hash, #foo, $val, $Type)) +{ + io::printn("Boba"); + int a = 0; + int b = 0; + @body({| io::printfn("Send %d", a); a++; |}, b, 3, int); + io::printfn("%d", b); +} + +/* #expect: test.ll + +define void @test.main() #0 { +entry: + %len = alloca i64, align 8 + %error_var = alloca i64, align 8 + %retparam = alloca i64, align 8 + %error_var2 = alloca i64, align 8 + %error_var8 = alloca i64, align 8 + %a = alloca i32, align 4 + %b = alloca i32, align 4 + %len14 = alloca i64, align 8 + %error_var15 = alloca i64, align 8 + %retparam17 = alloca i64, align 8 + %error_var23 = alloca i64, align 8 + %error_var29 = alloca i64, align 8 + %varargslots = alloca [1 x %any], align 16 + %retparam37 = alloca i64, align 8 + %varargslots41 = alloca [1 x %any], align 16 + %retparam42 = alloca i64, align 8 + %varargslots47 = alloca [1 x %any], align 16 + %taddr = alloca %"char[]", align 8 + %retparam48 = alloca i64, align 8 + %varargslots51 = alloca [1 x %any], align 16 + %retparam52 = alloca i64, align 8 + %0 = call ptr @std.io.stdout() + %1 = call i64 @std.io.File.write(ptr %retparam, ptr %0, ptr @.str, i64 4) + %not_err = icmp eq i64 %1, 0 + %2 = call i1 @llvm.expect.i1(i1 %not_err, i1 true) + br i1 %2, label %after_check, label %assign_optional +assign_optional: ; preds = %entry + store i64 %1, ptr %error_var, align 8 + br label %guard_block +after_check: ; preds = %entry + br label %noerr_block +guard_block: ; preds = %assign_optional + br label %voiderr +noerr_block: ; preds = %after_check + %3 = load i64, ptr %retparam, align 8 + store i64 %3, ptr %len, align 8 + %4 = call i64 @std.io.File.write_byte(ptr %0, i8 zeroext 10) + %not_err3 = icmp eq i64 %4, 0 + %5 = call i1 @llvm.expect.i1(i1 %not_err3, i1 true) + br i1 %5, label %after_check5, label %assign_optional4 +assign_optional4: ; preds = %noerr_block + store i64 %4, ptr %error_var2, align 8 + br label %guard_block6 +after_check5: ; preds = %noerr_block + br label %noerr_block7 +guard_block6: ; preds = %assign_optional4 + br label %voiderr +noerr_block7: ; preds = %after_check5 + %6 = call i64 @std.io.File.flush(ptr %0) + %not_err9 = icmp eq i64 %6, 0 + %7 = call i1 @llvm.expect.i1(i1 %not_err9, i1 true) + br i1 %7, label %after_check11, label %assign_optional10 +assign_optional10: ; preds = %noerr_block7 + store i64 %6, ptr %error_var8, align 8 + br label %guard_block12 +after_check11: ; preds = %noerr_block7 + br label %noerr_block13 +guard_block12: ; preds = %assign_optional10 + br label %voiderr +noerr_block13: ; preds = %after_check11 + %8 = load i64, ptr %len, align 8 + %add = add i64 %8, 1 + br label %voiderr +voiderr: ; preds = %noerr_block13, %guard_block12, %guard_block6, %guard_block + store i32 0, ptr %a, align 4 + store i32 0, ptr %b, align 4 + %9 = call ptr @std.io.stdout() + %10 = call i64 @std.io.File.write(ptr %retparam17, ptr %9, ptr @.str.1, i64 17) + %not_err18 = icmp eq i64 %10, 0 + %11 = call i1 @llvm.expect.i1(i1 %not_err18, i1 true) + br i1 %11, label %after_check20, label %assign_optional19 +assign_optional19: ; preds = %voiderr + store i64 %10, ptr %error_var15, align 8 + br label %guard_block21 +after_check20: ; preds = %voiderr + br label %noerr_block22 +guard_block21: ; preds = %assign_optional19 + br label %voiderr36 +noerr_block22: ; preds = %after_check20 + %12 = load i64, ptr %retparam17, align 8 + store i64 %12, ptr %len14, align 8 + %13 = call i64 @std.io.File.write_byte(ptr %9, i8 zeroext 10) + %not_err24 = icmp eq i64 %13, 0 + %14 = call i1 @llvm.expect.i1(i1 %not_err24, i1 true) + br i1 %14, label %after_check26, label %assign_optional25 +assign_optional25: ; preds = %noerr_block22 + store i64 %13, ptr %error_var23, align 8 + br label %guard_block27 +after_check26: ; preds = %noerr_block22 + br label %noerr_block28 +guard_block27: ; preds = %assign_optional25 + br label %voiderr36 +noerr_block28: ; preds = %after_check26 + %15 = call i64 @std.io.File.flush(ptr %9) + %not_err30 = icmp eq i64 %15, 0 + %16 = call i1 @llvm.expect.i1(i1 %not_err30, i1 true) + br i1 %16, label %after_check32, label %assign_optional31 +assign_optional31: ; preds = %noerr_block28 + store i64 %15, ptr %error_var29, align 8 + br label %guard_block33 +after_check32: ; preds = %noerr_block28 + br label %noerr_block34 +guard_block33: ; preds = %assign_optional31 + br label %voiderr36 +noerr_block34: ; preds = %after_check32 + %17 = load i64, ptr %len14, align 8 + %add35 = add i64 %17, 1 + br label %voiderr36 +voiderr36: ; preds = %noerr_block34, %guard_block33, %guard_block27, %guard_block21 + %18 = insertvalue %any undef, ptr %a, 0 + %19 = insertvalue %any %18, i64 ptrtoint (ptr @"$ct.int" to i64), 1 + store %any %19, ptr %varargslots, align 16 + %20 = call i64 @std.io.printfn(ptr %retparam37, ptr @.str.2, i64 7, ptr %varargslots, i64 1) + %21 = load i32, ptr %a, align 4 + %add40 = add i32 %21, 1 + store i32 %add40, ptr %a, align 4 + %22 = insertvalue %any undef, ptr %a, 0 + %23 = insertvalue %any %22, i64 ptrtoint (ptr @"$ct.int" to i64), 1 + store %any %23, ptr %varargslots41, align 16 + %24 = call i64 @std.io.printfn(ptr %retparam42, ptr @.str.3, i64 7, ptr %varargslots41, i64 1) + %25 = load i32, ptr %a, align 4 + %add45 = add i32 %25, 1 + store i32 %add45, ptr %a, align 4 + %26 = load i32, ptr %b, align 4 + %add46 = add i32 %26, 3 + store i32 %add46, ptr %b, align 4 + store %"char[]" { ptr @.str.5, i64 3 }, ptr %taddr, align 8 + %27 = insertvalue %any undef, ptr %taddr, 0 + %28 = insertvalue %any %27, i64 ptrtoint (ptr @"$ct.String" to i64), 1 + store %any %28, ptr %varargslots47, align 16 + %29 = call i64 @std.io.printfn(ptr %retparam48, ptr @.str.4, i64 16, ptr %varargslots47, i64 1) + %30 = insertvalue %any undef, ptr %b, 0 + %31 = insertvalue %any %30, i64 ptrtoint (ptr @"$ct.int" to i64), 1 + store %any %31, ptr %varargslots51, align 16 + %32 = call i64 @std.io.printfn(ptr %retparam52, ptr @.str.6, i64 2, ptr %varargslots51, i64 1) + ret void +} diff --git a/test/test_suite7/macros/macro_calls_prefix.c3 b/test/test_suite7/macros/macro_calls_prefix.c3 new file mode 100644 index 000000000..5723da636 --- /dev/null +++ b/test/test_suite7/macros/macro_calls_prefix.c3 @@ -0,0 +1,8 @@ +macro foo(a, $b, $Type) {} + +macro @foo2(a, $b, $Type) {} + +macro baz(#y) {} // #error: are not allowed in function-like + +macro baz2(a; @body()) {} // #error: Names of macros + diff --git a/test/test_suite7/macros/macro_chained_return_void_optional.c3t b/test/test_suite7/macros/macro_chained_return_void_optional.c3t new file mode 100644 index 000000000..b8724062d --- /dev/null +++ b/test/test_suite7/macros/macro_chained_return_void_optional.c3t @@ -0,0 +1,9 @@ +module abi; + +fn void! abc() {} +macro void! abc_macro() => abc(); + +fn void main() +{ + (void)abc_macro(); +} diff --git a/test/test_suite7/macros/macro_common.c3t b/test/test_suite7/macros/macro_common.c3t new file mode 100644 index 000000000..ea3a756d2 --- /dev/null +++ b/test/test_suite7/macros/macro_common.c3t @@ -0,0 +1,31 @@ +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: + %blockret = alloca double, align 8 + br label %if.exit + +if.exit: ; preds = %entry + br label %if.then + +if.then: ; preds = %if.exit + store double 0.000000e+00, ptr %blockret, align 8 + br label %expr_block.exit + +expr_block.exit: ; preds = %if.then + ret void +} \ No newline at end of file diff --git a/test/test_suite7/macros/macro_convert_literal.c3 b/test/test_suite7/macros/macro_convert_literal.c3 new file mode 100644 index 000000000..25d7900c6 --- /dev/null +++ b/test/test_suite7/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_suite7/macros/macro_defer_exit.c3t b/test/test_suite7/macros/macro_defer_exit.c3t new file mode 100644 index 000000000..e52bdd5bb --- /dev/null +++ b/test/test_suite7/macros/macro_defer_exit.c3t @@ -0,0 +1,77 @@ +// #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 + store i32 %sub, ptr %blockret, align 4 + %3 = load i32, ptr %x, align 4 + call void (ptr, ...) @printf(ptr @.str, i32 %3) + br label %expr_block.exit +if.exit: ; preds = %entry + call void (ptr, ...) @printf(ptr @.str.1) + %4 = load i32, ptr %x, align 4 + store i32 %4, ptr %blockret, align 4 + %5 = load i32, ptr %x, align 4 + call void (ptr, ...) @printf(ptr @.str.2, i32 %5) + 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 + store i32 %sub6, ptr %blockret2, align 4 + %9 = load i32, ptr %x1, align 4 + call void (ptr, ...) @printf(ptr @.str.3, i32 %9) + 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 + store i32 %10, ptr %blockret2, align 4 + %11 = load i32, ptr %x1, align 4 + call void (ptr, ...) @printf(ptr @.str.5, i32 %11) + 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_suite7/macros/macro_defer_scope.c3t b/test/test_suite7/macros/macro_defer_scope.c3t new file mode 100644 index 000000000..a347d8a0c --- /dev/null +++ b/test/test_suite7/macros/macro_defer_scope.c3t @@ -0,0 +1,42 @@ +// #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 + store i32 %add3, ptr %blockret, align 4 + %2 = call i32 (ptr, ...) @printf(ptr @.str) + 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_suite7/macros/macro_defer_with_body.c3t b/test/test_suite7/macros/macro_defer_with_body.c3t new file mode 100644 index 000000000..703e3d20e --- /dev/null +++ b/test/test_suite7/macros/macro_defer_with_body.c3t @@ -0,0 +1,51 @@ +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 + %y = alloca i32, align 4 + store i32 0, ptr %x, align 4 + store i32 1, ptr %y, align 4 + %0 = load i32, ptr %x, align 4 + %add = add i32 %0, 1 + store i32 %add, ptr %x, align 4 + %1 = call i32 (ptr, ...) @printf(ptr @.str, i32 %0) + %2 = load i32, ptr %x, align 4 + %add1 = add i32 %2, 1 + store i32 %add1, ptr %x, align 4 + %3 = call i32 (ptr, ...) @printf(ptr @.str.1, i32 %2) + store i32 1, ptr %y, align 4 + %4 = load i32, ptr %x, align 4 + %add2 = add i32 %4, 1 + store i32 %add2, ptr %x, align 4 + %5 = call i32 (ptr, ...) @printf(ptr @.str.2, i32 %4) + %6 = load i32, ptr %x, align 4 + %add3 = add i32 %6, 1 + store i32 %add3, ptr %x, align 4 + %7 = call i32 (ptr, ...) @printf(ptr @.str.3, i32 %6) + %8 = call i32 (ptr, ...) @printf(ptr @.str.4) + ret void +} + + diff --git a/test/test_suite7/macros/macro_failable_return_rethrow.c3t b/test/test_suite7/macros/macro_failable_return_rethrow.c3t new file mode 100644 index 000000000..9110112b2 --- /dev/null +++ b/test/test_suite7/macros/macro_failable_return_rethrow.c3t @@ -0,0 +1,58 @@ +// #target: macos-x64 +module test; +fn int! xy() +{ + return 1; +} +macro int! foo() +{ + xy()!; + return 1; +} +fn void main() +{ + foo()!!; +} + +/* #expect: test.ll + +define void @test.main() #0 { +entry: + %error_var = alloca i64, align 8 + %error_var1 = alloca i64, align 8 + %retparam = alloca i32, align 4 + %varargslots = alloca [1 x %any], align 16 + %indirectarg = alloca %"any[]", align 8 + %0 = call i64 @test.xy(ptr %retparam) + %not_err = icmp eq i64 %0, 0 + %1 = call i1 @llvm.expect.i1(i1 %not_err, i1 true) + br i1 %1, label %after_check, label %assign_optional + +assign_optional: ; preds = %entry + store i64 %0, ptr %error_var1, align 8 + br label %guard_block + +after_check: ; preds = %entry + br label %noerr_block + +guard_block: ; preds = %assign_optional + %2 = load i64, ptr %error_var1, align 8 + store i64 %2, ptr %error_var, align 8 + br label %panic_block + +noerr_block: ; preds = %after_check + br label %noerr_block2 + +panic_block: ; preds = %guard_block + %3 = insertvalue %any undef, ptr %error_var, 0 + %4 = insertvalue %any %3, i64 ptrtoint (ptr @"$ct.anyfault" to i64), 1 + store %any %4, ptr %varargslots, align 16 + %5 = insertvalue %"any[]" undef, ptr %varargslots, 0 + %"$$temp" = insertvalue %"any[]" %5, i64 1, 1 + store %"any[]" %"$$temp", ptr %indirectarg, align 8 + call void @std.core.builtin.panicf(ptr @.panic_msg, i64 36, ptr @.file, i64 32, ptr @.func, i64 4, i32 13, ptr byval(%"any[]") align 8 %indirectarg) + unreachable + +noerr_block2: ; preds = %noerr_block + ret void +} \ No newline at end of file diff --git a/test/test_suite7/macros/macro_import_res_private.c3t b/test/test_suite7/macros/macro_import_res_private.c3t new file mode 100644 index 000000000..2fcc69cb3 --- /dev/null +++ b/test/test_suite7/macros/macro_import_res_private.c3t @@ -0,0 +1,26 @@ +// #target: macos-x64 +module foo; +fn void foo1() @private +{} + +module bar; +import foo @public; +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_suite7/macros/macro_import_resolution.c3 b/test/test_suite7/macros/macro_import_resolution.c3 new file mode 100644 index 000000000..1772389fd --- /dev/null +++ b/test/test_suite7/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_suite7/macros/macro_nested_labels.c3t b/test/test_suite7/macros/macro_nested_labels.c3t new file mode 100644 index 000000000..0a1416bee --- /dev/null +++ b/test/test_suite7/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_suite7/macros/macro_ref_body_err1.c3 b/test/test_suite7/macros/macro_ref_body_err1.c3 new file mode 100644 index 000000000..7c88a6dfc --- /dev/null +++ b/test/test_suite7/macros/macro_ref_body_err1.c3 @@ -0,0 +1,4 @@ + +macro void @bar(;@body(int &foo)) // #error: did you mean 'int*' +{} + diff --git a/test/test_suite7/macros/macro_ref_body_err2.c3 b/test/test_suite7/macros/macro_ref_body_err2.c3 new file mode 100644 index 000000000..1ba1fd8e3 --- /dev/null +++ b/test/test_suite7/macros/macro_ref_body_err2.c3 @@ -0,0 +1,11 @@ +fn void main() +{ + @foo(;int &foo) // #error: did you mean 'int*' + { + }; +} + +macro void @foo(;@body(&foo)) +{ +} + diff --git a/test/test_suite7/macros/macro_resolution.c3 b/test/test_suite7/macros/macro_resolution.c3 new file mode 100644 index 000000000..0776d1441 --- /dev/null +++ b/test/test_suite7/macros/macro_resolution.c3 @@ -0,0 +1,24 @@ +module foo; +import bar; +fn void run() +{ + bar::test(); +} + +fn void run2() +{ + bar::test2(); +} + +fn void tester() @private {} + +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_suite7/macros/macro_rtype.c3 b/test/test_suite7/macros/macro_rtype.c3 new file mode 100644 index 000000000..394d71612 --- /dev/null +++ b/test/test_suite7/macros/macro_rtype.c3 @@ -0,0 +1,9 @@ +macro int frob() +{ + return 0.0; // #error: int +} + +fn void test1() +{ + frob(); +} \ No newline at end of file diff --git a/test/test_suite7/macros/macro_tagof.c3t b/test/test_suite7/macros/macro_tagof.c3t new file mode 100644 index 000000000..0227bba7b --- /dev/null +++ b/test/test_suite7/macros/macro_tagof.c3t @@ -0,0 +1,11 @@ +import std::io; +macro int test() @tag("hello", 1) +{ + return 1; +} + +fn void main() +{ + var $v = test.tagof("hello"); + io::printn($v); +} \ No newline at end of file diff --git a/test/test_suite7/macros/macro_typed_varargs.c3t b/test/test_suite7/macros/macro_typed_varargs.c3t new file mode 100644 index 000000000..05b34eb17 --- /dev/null +++ b/test/test_suite7/macros/macro_typed_varargs.c3t @@ -0,0 +1,128 @@ +// #target: macos-x64 + +module test; + +import std::io; + +macro foo(int... x) +{ + foreach (i : x) + { + io::printfn("%d", i); + } +} + +macro foo2(x...) +{ + foreach (i : x) + { + io::printfn("%d", *(int*)i); + } +} + +fn void main() +{ + foo(1, -1, 3141, 999 + 1); + foo2(1, -1, 3141, 999 + 1); +} + +/* #expect: test.ll + +define void @test.main() #0 { +entry: + %literal = alloca [4 x i32], align 16 + %x = alloca %"int[]", align 8 + %.anon = alloca i64, align 8 + %i = alloca i32, align 4 + %varargslots = alloca [1 x %any], align 16 + %retparam = alloca i64, align 8 + %literal1 = alloca [4 x %any], align 16 + %taddr = alloca i32, align 4 + %taddr3 = alloca i32, align 4 + %taddr5 = alloca i32, align 4 + %taddr7 = alloca i32, align 4 + %x8 = alloca %"any[]", align 8 + %.anon10 = alloca i64, align 8 + %i14 = alloca %any, align 8 + %varargslots16 = alloca [1 x %any], align 16 + %retparam17 = alloca i64, align 8 + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %literal, ptr align 16 @.__const, i32 16, i1 false) + %0 = insertvalue %"int[]" undef, ptr %literal, 0 + %1 = insertvalue %"int[]" %0, i64 4, 1 + store %"int[]" %1, ptr %x, align 8 + %ptradd = getelementptr inbounds i8, ptr %x, i64 8 + %2 = load i64, ptr %ptradd, align 8 + store i64 0, ptr %.anon, align 8 + br label %loop.cond + +loop.cond: ; preds = %loop.body, %entry + %3 = load i64, ptr %.anon, align 8 + %lt = icmp ult i64 %3, %2 + br i1 %lt, label %loop.body, label %loop.exit + +loop.body: ; preds = %loop.cond + %4 = load ptr, ptr %x, align 8 + %5 = load i64, ptr %.anon, align 8 + %ptroffset = getelementptr inbounds [4 x i8], ptr %4, i64 %5 + %6 = load i32, ptr %ptroffset, align 4 + store i32 %6, ptr %i, align 4 + %7 = insertvalue %any undef, ptr %i, 0 + %8 = insertvalue %any %7, i64 ptrtoint (ptr @"$ct.int" to i64), 1 + store %any %8, ptr %varargslots, align 16 + %9 = call i64 @std.io.printfn(ptr %retparam, ptr @.str, i64 2, ptr %varargslots, i64 1) + %10 = load i64, ptr %.anon, align 8 + %addnuw = add nuw i64 %10, 1 + store i64 %addnuw, ptr %.anon, align 8 + br label %loop.cond + +loop.exit: ; preds = %loop.cond + store i32 1, ptr %taddr, align 4 + %11 = insertvalue %any undef, ptr %taddr, 0 + %12 = insertvalue %any %11, i64 ptrtoint (ptr @"$ct.int" to i64), 1 + store %any %12, ptr %literal1, align 8 + %ptradd2 = getelementptr inbounds i8, ptr %literal1, i64 16 + store i32 -1, ptr %taddr3, align 4 + %13 = insertvalue %any undef, ptr %taddr3, 0 + %14 = insertvalue %any %13, i64 ptrtoint (ptr @"$ct.int" to i64), 1 + store %any %14, ptr %ptradd2, align 8 + %ptradd4 = getelementptr inbounds i8, ptr %literal1, i64 32 + store i32 3141, ptr %taddr5, align 4 + %15 = insertvalue %any undef, ptr %taddr5, 0 + %16 = insertvalue %any %15, i64 ptrtoint (ptr @"$ct.int" to i64), 1 + store %any %16, ptr %ptradd4, align 8 + %ptradd6 = getelementptr inbounds i8, ptr %literal1, i64 48 + store i32 1000, ptr %taddr7, align 4 + %17 = insertvalue %any undef, ptr %taddr7, 0 + %18 = insertvalue %any %17, i64 ptrtoint (ptr @"$ct.int" to i64), 1 + store %any %18, ptr %ptradd6, align 8 + %19 = insertvalue %"any[]" undef, ptr %literal1, 0 + %20 = insertvalue %"any[]" %19, i64 4, 1 + store %"any[]" %20, ptr %x8, align 8 + %ptradd9 = getelementptr inbounds i8, ptr %x8, i64 8 + %21 = load i64, ptr %ptradd9, align 8 + store i64 0, ptr %.anon10, align 8 + br label %loop.cond11 + +loop.cond11: ; preds = %loop.body13, %loop.exit + %22 = load i64, ptr %.anon10, align 8 + %lt12 = icmp ult i64 %22, %21 + br i1 %lt12, label %loop.body13, label %loop.exit19 + +loop.body13: ; preds = %loop.cond11 + %23 = load ptr, ptr %x8, align 8 + %24 = load i64, ptr %.anon10, align 8 + %ptroffset15 = getelementptr inbounds [16 x i8], ptr %23, i64 %24 + call void @llvm.memcpy.p0.p0.i32(ptr align 8 %i14, ptr align 8 %ptroffset15, i32 16, i1 false) + %25 = load ptr, ptr %i14, align 8 + %26 = insertvalue %any undef, ptr %25, 0 + %27 = insertvalue %any %26, i64 ptrtoint (ptr @"$ct.int" to i64), 1 + store %any %27, ptr %varargslots16, align 16 + %28 = call i64 @std.io.printfn(ptr %retparam17, ptr @.str.1, i64 2, ptr %varargslots16, i64 1) + %29 = load i64, ptr %.anon10, align 8 + %addnuw18 = add nuw i64 %29, 1 + store i64 %addnuw18, ptr %.anon10, align 8 + br label %loop.cond11 + +loop.exit19: ; preds = %loop.cond11 + ret void +} diff --git a/test/test_suite7/macros/macro_untyped_varargs.c3 b/test/test_suite7/macros/macro_untyped_varargs.c3 new file mode 100644 index 000000000..fd3984f6f --- /dev/null +++ b/test/test_suite7/macros/macro_untyped_varargs.c3 @@ -0,0 +1,25 @@ +macro foo(...) +{ + $vaarg["hello"]; // #error: Expected the argument index here + int x; + $vaarg[x]; // #error: Vararg functions need a constant argument + $vaarg[-1]; // #error: negative + $vaarg[100]; // #error: varargs exist +} + +macro foo2(...) +{ + $vaconst[0]; +} + +macro foo3(...) +{ + $vatype[0] a; +} +fn void main() +{ + foo(1, -1, 3141, 999 + 1); + int x; + foo2(x); // #error: This argument needs to be a compile time constant + foo3(3); // #error: The argument was not a type. +} diff --git a/test/test_suite7/macros/macro_untyped_varargs_2.c3t b/test/test_suite7/macros/macro_untyped_varargs_2.c3t new file mode 100644 index 000000000..8621fb3ef --- /dev/null +++ b/test/test_suite7/macros/macro_untyped_varargs_2.c3t @@ -0,0 +1,190 @@ +// #target: macos-x64 + +module test; + +import std::io; + +macro @foo(...) +{ + int i = $vaarg[1] + $vaarg[1]; + int j = $vaexpr[2] + $vaexpr[2]; + $for (var $i = 0; $i < $vacount; $i++) + io::printfn("%d", $vaarg[$i]); + $endfor; +} + +macro foo2(...) +{ + $for (var $i = 0; $i < $vacount; $i++) + { + $vatype[$i] x; + } + io::printfn("%s", $vatype[$i].nameof); + $endfor; +} + +macro foo3(...) +{ + var $x = 0; + $for (var $i = 0; $i < $vacount; $i++) + $x += $vaconst[$i]; + $endfor; + return $x; +} + +macro @foo4(...) +{ + $typeof($vaexpr[0]) a = $vaexpr[0]; + $vaexpr[0] = $vaexpr[1]; + $vaexpr[1] = a; +} +fn int ping(int val) +{ + io::printfn("Ping[%d]", val); + return val; +} + +fn void main() +{ + @foo(ping(1), ping(-1), ping(3141), ping(999 + 1)); + foo2(int, double); + var $x = foo3(1, 4, 100); + io::printfn("%d", $x); + int x = 123; + int y = 33; + @foo4(x, y); + io::printfn("%d, %d", x, y); + @foo4(x, y); + io::printfn("%d, %d", x, y); +} + +/* #expect: test.ll + +define i32 @test.ping(i32 %0) #0 { +entry: + %varargslots = alloca [1 x %any], align 16 + %taddr = alloca i32, align 4 + %retparam = alloca i64, align 8 + store i32 %0, ptr %taddr, align 4 + %1 = insertvalue %any undef, ptr %taddr, 0 + %2 = insertvalue %any %1, i64 ptrtoint (ptr @"$ct.int" to i64), 1 + store %any %2, ptr %varargslots, align 16 + %3 = call i64 @std.io.printfn(ptr %retparam, ptr @.str, i64 8, ptr %varargslots, i64 1) + ret i32 %0 +} + +; Function Attrs: +define void @test.main() #0 { +entry: + %i = alloca i32, align 4 + %j = alloca i32, align 4 + %varargslots = alloca [1 x %any], align 16 + %taddr = alloca i32, align 4 + %retparam = alloca i64, align 8 + %varargslots2 = alloca [1 x %any], align 16 + %taddr3 = alloca i32, align 4 + %retparam4 = alloca i64, align 8 + %varargslots5 = alloca [1 x %any], align 16 + %taddr6 = alloca i32, align 4 + %retparam7 = alloca i64, align 8 + %varargslots8 = alloca [1 x %any], align 16 + %taddr9 = alloca i32, align 4 + %retparam10 = alloca i64, align 8 + %x = alloca i32, align 4 + %varargslots11 = alloca [1 x %any], align 16 + %taddr12 = alloca %"char[]", align 8 + %retparam13 = alloca i64, align 8 + %x14 = alloca double, align 8 + %varargslots15 = alloca [1 x %any], align 16 + %taddr16 = alloca %"char[]", align 8 + %retparam17 = alloca i64, align 8 + %varargslots18 = alloca [1 x %any], align 16 + %taddr19 = alloca i32, align 4 + %retparam20 = alloca i64, align 8 + %x21 = alloca i32, align 4 + %y = alloca i32, align 4 + %a = alloca i32, align 4 + %varargslots22 = alloca [2 x %any], align 16 + %retparam23 = alloca i64, align 8 + %a24 = alloca i32, align 4 + %varargslots25 = alloca [2 x %any], align 16 + %retparam27 = alloca i64, align 8 + %0 = call i32 @test.ping(i32 -1) + %1 = call i32 @test.ping(i32 1) + %2 = call i32 @test.ping(i32 3141) + %3 = call i32 @test.ping(i32 1000) + %add = add i32 %0, %0 + store i32 %add, ptr %i, align 4 + %4 = call i32 @test.ping(i32 3141) + %5 = call i32 @test.ping(i32 3141) + %add1 = add i32 %4, %5 + store i32 %add1, ptr %j, align 4 + store i32 %1, ptr %taddr, align 4 + %6 = insertvalue %any undef, ptr %taddr, 0 + %7 = insertvalue %any %6, i64 ptrtoint (ptr @"$ct.int" to i64), 1 + store %any %7, ptr %varargslots, align 16 + %8 = call i64 @std.io.printfn(ptr %retparam, ptr @.str.1, i64 2, ptr %varargslots, i64 1) + store i32 %0, ptr %taddr3, align 4 + %9 = insertvalue %any undef, ptr %taddr3, 0 + %10 = insertvalue %any %9, i64 ptrtoint (ptr @"$ct.int" to i64), 1 + store %any %10, ptr %varargslots2, align 16 + %11 = call i64 @std.io.printfn(ptr %retparam4, ptr @.str.2, i64 2, ptr %varargslots2, i64 1) + store i32 %2, ptr %taddr6, align 4 + %12 = insertvalue %any undef, ptr %taddr6, 0 + %13 = insertvalue %any %12, i64 ptrtoint (ptr @"$ct.int" to i64), 1 + store %any %13, ptr %varargslots5, align 16 + %14 = call i64 @std.io.printfn(ptr %retparam7, ptr @.str.3, i64 2, ptr %varargslots5, i64 1) + store i32 %3, ptr %taddr9, align 4 + %15 = insertvalue %any undef, ptr %taddr9, 0 + %16 = insertvalue %any %15, i64 ptrtoint (ptr @"$ct.int" to i64), 1 + store %any %16, ptr %varargslots8, align 16 + %17 = call i64 @std.io.printfn(ptr %retparam10, ptr @.str.4, i64 2, ptr %varargslots8, i64 1) + store i32 0, ptr %x, align 4 + store %"char[]" { ptr @.str.6, i64 3 }, ptr %taddr12, align 8 + %18 = insertvalue %any undef, ptr %taddr12, 0 + %19 = insertvalue %any %18, i64 ptrtoint (ptr @"$ct.String" to i64), 1 + store %any %19, ptr %varargslots11, align 16 + %20 = call i64 @std.io.printfn(ptr %retparam13, ptr @.str.5, i64 2, ptr %varargslots11, i64 1) + store double 0.000000e+00, ptr %x14, align 8 + store %"char[]" { ptr @.str.8, i64 6 }, ptr %taddr16, align 8 + %21 = insertvalue %any undef, ptr %taddr16, 0 + %22 = insertvalue %any %21, i64 ptrtoint (ptr @"$ct.String" to i64), 1 + store %any %22, ptr %varargslots15, align 16 + %23 = call i64 @std.io.printfn(ptr %retparam17, ptr @.str.7, i64 2, ptr %varargslots15, i64 1) + store i32 105, ptr %taddr19, align 4 + %24 = insertvalue %any undef, ptr %taddr19, 0 + %25 = insertvalue %any %24, i64 ptrtoint (ptr @"$ct.int" to i64), 1 + store %any %25, ptr %varargslots18, align 16 + %26 = call i64 @std.io.printfn(ptr %retparam20, ptr @.str.9, i64 2, ptr %varargslots18, i64 1) + store i32 123, ptr %x21, align 4 + store i32 33, ptr %y, align 4 + %27 = load i32, ptr %x21, align 4 + store i32 %27, ptr %a, align 4 + %28 = load i32, ptr %y, align 4 + store i32 %28, ptr %x21, align 4 + %29 = load i32, ptr %a, align 4 + store i32 %29, ptr %y, align 4 + %30 = insertvalue %any undef, ptr %x21, 0 + %31 = insertvalue %any %30, i64 ptrtoint (ptr @"$ct.int" to i64), 1 + store %any %31, ptr %varargslots22, align 16 + %32 = insertvalue %any undef, ptr %y, 0 + %33 = insertvalue %any %32, i64 ptrtoint (ptr @"$ct.int" to i64), 1 + %ptradd = getelementptr inbounds i8, ptr %varargslots22, i64 16 + store %any %33, ptr %ptradd, align 16 + %34 = call i64 @std.io.printfn(ptr %retparam23, ptr @.str.10, i64 6, ptr %varargslots22, i64 2) + %35 = load i32, ptr %x21, align 4 + store i32 %35, ptr %a24, align 4 + %36 = load i32, ptr %y, align 4 + store i32 %36, ptr %x21, align 4 + %37 = load i32, ptr %a24, align 4 + store i32 %37, ptr %y, align 4 + %38 = insertvalue %any undef, ptr %x21, 0 + %39 = insertvalue %any %38, i64 ptrtoint (ptr @"$ct.int" to i64), 1 + store %any %39, ptr %varargslots25, align 16 + %40 = insertvalue %any undef, ptr %y, 0 + %41 = insertvalue %any %40, i64 ptrtoint (ptr @"$ct.int" to i64), 1 + %ptradd26 = getelementptr inbounds i8, ptr %varargslots25, i64 16 + store %any %41, ptr %ptradd26, align 16 + %42 = call i64 @std.io.printfn(ptr %retparam27, ptr @.str.11, i64 6, ptr %varargslots25, i64 2) + ret void +} \ No newline at end of file diff --git a/test/test_suite7/macros/macro_vasplat.c3t b/test/test_suite7/macros/macro_vasplat.c3t new file mode 100644 index 000000000..2151da33a --- /dev/null +++ b/test/test_suite7/macros/macro_vasplat.c3t @@ -0,0 +1,459 @@ +// #target: macos-x64 +module test; +import std::io; + +macro @hello(...) +{ + int[?] a = { 1, $vasplat, 3 }; + foreach (i, x : a) io::printfn("%d: %d", i, x); +} + +macro @hello1(...) +{ + int[?] a = { 1, $vasplat }; + foreach (i, x : a) io::printfn("x:%d: %d", i, x); +} + +macro @hello2(...) +{ + int[?] a = { $vasplat, 888 }; + foreach (i, x : a) io::printfn("x:%d: %d", i, x); +} + +macro @hello3(...) +{ + int[?] a = { $vasplat }; + foreach (i, x : a) io::printfn("x:%d: %d", i, x); +} + +macro @hello4(...) +{ + int[?] a = { 5, $vasplat[2..4], 77 }; + foreach (i, x : a) io::printfn("y:%d: %d", i, x); +} + +macro @hello5(...) +{ + int[?] a = { 5, $vasplat[2..], 77 }; + foreach (i, x : a) io::printfn("y:%d: %d", i, x); + int[?] b = { 55, $vasplat[2..^2], 88 }; + foreach (i, x : b) io::printfn("z:%d: %d", i, x); + int[?] c = { 55, $vasplat[0:^2], 88 }; + foreach (i, x : c) io::printfn("zz:%d: %d", i, x); +} + +macro @hello6(...) +{ + @hello(66, $vasplat); +} +fn void main() +{ + @hello1(223, 326); + @hello1(); + @hello(26, 36); + @hello(); + @hello2(2123, 3326); + @hello2(); + @hello3(2123, 3326); + @hello4(1, 2, 3, 4, 5, 6, 7, 8); + @hello5(1, 2, 3, 4, 5, 6, 7, 8); + @hello6(1, 2, 3); +} + +/* #expect: test.ll + +define void @test.main() #0 { +entry: + %a = alloca [3 x i32], align 4 + %.anon = alloca i64, align 8 + %i = alloca i64, align 8 + %x = alloca i32, align 4 + %varargslots = alloca [2 x %any], align 16 + %retparam = alloca i64, align 8 + %a1 = alloca [1 x i32], align 4 + %i2 = alloca i64, align 8 + %x3 = alloca i32, align 4 + %varargslots4 = alloca [2 x %any], align 16 + %retparam6 = alloca i64, align 8 + %a7 = alloca [4 x i32], align 16 + %.anon8 = alloca i64, align 8 + %i12 = alloca i64, align 8 + %x13 = alloca i32, align 4 + %varargslots15 = alloca [2 x %any], align 16 + %retparam17 = alloca i64, align 8 + %a20 = alloca [2 x i32], align 4 + %.anon21 = alloca i64, align 8 + %i25 = alloca i64, align 8 + %x26 = alloca i32, align 4 + %varargslots28 = alloca [2 x %any], align 16 + %retparam30 = alloca i64, align 8 + %a33 = alloca [3 x i32], align 4 + %.anon34 = alloca i64, align 8 + %i38 = alloca i64, align 8 + %x39 = alloca i32, align 4 + %varargslots41 = alloca [2 x %any], align 16 + %retparam43 = alloca i64, align 8 + %a46 = alloca [1 x i32], align 4 + %i47 = alloca i64, align 8 + %x48 = alloca i32, align 4 + %varargslots49 = alloca [2 x %any], align 16 + %retparam51 = alloca i64, align 8 + %a52 = alloca [2 x i32], align 4 + %.anon53 = alloca i64, align 8 + %i57 = alloca i64, align 8 + %x58 = alloca i32, align 4 + %varargslots60 = alloca [2 x %any], align 16 + %retparam62 = alloca i64, align 8 + %a65 = alloca [5 x i32], align 16 + %.anon66 = alloca i64, align 8 + %i70 = alloca i64, align 8 + %x71 = alloca i32, align 4 + %varargslots73 = alloca [2 x %any], align 16 + %retparam75 = alloca i64, align 8 + %a78 = alloca [8 x i32], align 16 + %.anon79 = alloca i64, align 8 + %i83 = alloca i64, align 8 + %x84 = alloca i32, align 4 + %varargslots86 = alloca [2 x %any], align 16 + %retparam88 = alloca i64, align 8 + %b = alloca [7 x i32], align 16 + %.anon91 = alloca i64, align 8 + %i95 = alloca i64, align 8 + %x96 = alloca i32, align 4 + %varargslots98 = alloca [2 x %any], align 16 + %retparam100 = alloca i64, align 8 + %c = alloca [8 x i32], align 16 + %.anon103 = alloca i64, align 8 + %i107 = alloca i64, align 8 + %x108 = alloca i32, align 4 + %varargslots110 = alloca [2 x %any], align 16 + %retparam112 = alloca i64, align 8 + %a115 = alloca [6 x i32], align 16 + %.anon116 = alloca i64, align 8 + %i120 = alloca i64, align 8 + %x121 = alloca i32, align 4 + %varargslots123 = alloca [2 x %any], align 16 + %retparam125 = alloca i64, align 8 + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %a, ptr align 4 @.__const, i32 12, i1 false) + 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 + store i64 %1, ptr %i, align 8 + %2 = load i64, ptr %.anon, align 8 + %ptroffset = getelementptr inbounds [4 x i8], ptr %a, i64 %2 + %3 = load i32, ptr %ptroffset, align 4 + store i32 %3, ptr %x, align 4 + %4 = insertvalue %any undef, ptr %i, 0 + %5 = insertvalue %any %4, i64 ptrtoint (ptr @"$ct.ulong" to i64), 1 + store %any %5, ptr %varargslots, align 16 + %6 = insertvalue %any undef, ptr %x, 0 + %7 = insertvalue %any %6, i64 ptrtoint (ptr @"$ct.int" to i64), 1 + %ptradd = getelementptr inbounds i8, ptr %varargslots, i64 16 + store %any %7, ptr %ptradd, align 16 + %8 = call i64 @std.io.printfn(ptr %retparam, ptr @.str, i64 8, ptr %varargslots, i64 2) + %9 = load i64, ptr %.anon, align 8 + %addnuw = add nuw i64 %9, 1 + store i64 %addnuw, ptr %.anon, align 8 + br label %loop.cond +loop.exit: ; preds = %loop.cond + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %a1, ptr align 4 @.__const.1, i32 4, i1 false) + store i64 0, ptr %i2, align 8 + %10 = load i32, ptr %a1, align 4 + store i32 %10, ptr %x3, align 4 + %11 = insertvalue %any undef, ptr %i2, 0 + %12 = insertvalue %any %11, i64 ptrtoint (ptr @"$ct.ulong" to i64), 1 + store %any %12, ptr %varargslots4, align 16 + %13 = insertvalue %any undef, ptr %x3, 0 + %14 = insertvalue %any %13, i64 ptrtoint (ptr @"$ct.int" to i64), 1 + %ptradd5 = getelementptr inbounds i8, ptr %varargslots4, i64 16 + store %any %14, ptr %ptradd5, align 16 + %15 = call i64 @std.io.printfn(ptr %retparam6, ptr @.str.2, i64 8, ptr %varargslots4, i64 2) + call void @llvm.memcpy.p0.p0.i32(ptr align 16 %a7, ptr align 16 @.__const.3, i32 16, i1 false) + store i64 0, ptr %.anon8, align 8 + br label %loop.cond9 + +loop.cond9: ; preds = %loop.body11, %loop.exit + %16 = load i64, ptr %.anon8, align 8 + %gt10 = icmp ugt i64 4, %16 + br i1 %gt10, label %loop.body11, label %loop.exit19 + +loop.body11: ; preds = %loop.cond9 + %17 = load i64, ptr %.anon8, align 8 + store i64 %17, ptr %i12, align 8 + %18 = load i64, ptr %.anon8, align 8 + %ptroffset14 = getelementptr inbounds [4 x i8], ptr %a7, i64 %18 + %19 = load i32, ptr %ptroffset14, align 4 + store i32 %19, ptr %x13, align 4 + %20 = insertvalue %any undef, ptr %i12, 0 + %21 = insertvalue %any %20, i64 ptrtoint (ptr @"$ct.ulong" to i64), 1 + store %any %21, ptr %varargslots15, align 16 + %22 = insertvalue %any undef, ptr %x13, 0 + %23 = insertvalue %any %22, i64 ptrtoint (ptr @"$ct.int" to i64), 1 + %ptradd16 = getelementptr inbounds i8, ptr %varargslots15, i64 16 + store %any %23, ptr %ptradd16, align 16 + %24 = call i64 @std.io.printfn(ptr %retparam17, ptr @.str.4, i64 6, ptr %varargslots15, i64 2) + %25 = load i64, ptr %.anon8, align 8 + %addnuw18 = add nuw i64 %25, 1 + store i64 %addnuw18, ptr %.anon8, align 8 + br label %loop.cond9 + +loop.exit19: ; preds = %loop.cond9 + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %a20, ptr align 4 @.__const.5, i32 8, i1 false) + store i64 0, ptr %.anon21, align 8 + br label %loop.cond22 + +loop.cond22: ; preds = %loop.body24, %loop.exit19 + %26 = load i64, ptr %.anon21, align 8 + %gt23 = icmp ugt i64 2, %26 + br i1 %gt23, label %loop.body24, label %loop.exit32 + +loop.body24: ; preds = %loop.cond22 + %27 = load i64, ptr %.anon21, align 8 + store i64 %27, ptr %i25, align 8 + %28 = load i64, ptr %.anon21, align 8 + %ptroffset27 = getelementptr inbounds [4 x i8], ptr %a20, i64 %28 + %29 = load i32, ptr %ptroffset27, align 4 + store i32 %29, ptr %x26, align 4 + %30 = insertvalue %any undef, ptr %i25, 0 + %31 = insertvalue %any %30, i64 ptrtoint (ptr @"$ct.ulong" to i64), 1 + store %any %31, ptr %varargslots28, align 16 + %32 = insertvalue %any undef, ptr %x26, 0 + %33 = insertvalue %any %32, i64 ptrtoint (ptr @"$ct.int" to i64), 1 + %ptradd29 = getelementptr inbounds i8, ptr %varargslots28, i64 16 + store %any %33, ptr %ptradd29, align 16 + %34 = call i64 @std.io.printfn(ptr %retparam30, ptr @.str.6, i64 6, ptr %varargslots28, i64 2) + %35 = load i64, ptr %.anon21, align 8 + %addnuw31 = add nuw i64 %35, 1 + store i64 %addnuw31, ptr %.anon21, align 8 + br label %loop.cond22 + +loop.exit32: ; preds = %loop.cond22 + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %a33, ptr align 4 @.__const.7, i32 12, i1 false) + store i64 0, ptr %.anon34, align 8 + br label %loop.cond35 + +loop.cond35: ; preds = %loop.body37, %loop.exit32 + %36 = load i64, ptr %.anon34, align 8 + %gt36 = icmp ugt i64 3, %36 + br i1 %gt36, label %loop.body37, label %loop.exit45 + +loop.body37: ; preds = %loop.cond35 + %37 = load i64, ptr %.anon34, align 8 + store i64 %37, ptr %i38, align 8 + %38 = load i64, ptr %.anon34, align 8 + %ptroffset40 = getelementptr inbounds [4 x i8], ptr %a33, i64 %38 + %39 = load i32, ptr %ptroffset40, align 4 + store i32 %39, ptr %x39, align 4 + %40 = insertvalue %any undef, ptr %i38, 0 + %41 = insertvalue %any %40, i64 ptrtoint (ptr @"$ct.ulong" to i64), 1 + store %any %41, ptr %varargslots41, align 16 + %42 = insertvalue %any undef, ptr %x39, 0 + %43 = insertvalue %any %42, i64 ptrtoint (ptr @"$ct.int" to i64), 1 + %ptradd42 = getelementptr inbounds i8, ptr %varargslots41, i64 16 + store %any %43, ptr %ptradd42, align 16 + %44 = call i64 @std.io.printfn(ptr %retparam43, ptr @.str.8, i64 8, ptr %varargslots41, i64 2) + %45 = load i64, ptr %.anon34, align 8 + %addnuw44 = add nuw i64 %45, 1 + store i64 %addnuw44, ptr %.anon34, align 8 + br label %loop.cond35 + +loop.exit45: ; preds = %loop.cond35 + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %a46, ptr align 4 @.__const.9, i32 4, i1 false) + store i64 0, ptr %i47, align 8 + %46 = load i32, ptr %a46, align 4 + store i32 %46, ptr %x48, align 4 + %47 = insertvalue %any undef, ptr %i47, 0 + %48 = insertvalue %any %47, i64 ptrtoint (ptr @"$ct.ulong" to i64), 1 + store %any %48, ptr %varargslots49, align 16 + %49 = insertvalue %any undef, ptr %x48, 0 + %50 = insertvalue %any %49, i64 ptrtoint (ptr @"$ct.int" to i64), 1 + %ptradd50 = getelementptr inbounds i8, ptr %varargslots49, i64 16 + store %any %50, ptr %ptradd50, align 16 + %51 = call i64 @std.io.printfn(ptr %retparam51, ptr @.str.10, i64 8, ptr %varargslots49, i64 2) + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %a52, ptr align 4 @.__const.11, i32 8, i1 false) + store i64 0, ptr %.anon53, align 8 + br label %loop.cond54 + +loop.cond54: ; preds = %loop.body56, %loop.exit45 + %52 = load i64, ptr %.anon53, align 8 + %gt55 = icmp ugt i64 2, %52 + br i1 %gt55, label %loop.body56, label %loop.exit64 + +loop.body56: ; preds = %loop.cond54 + %53 = load i64, ptr %.anon53, align 8 + store i64 %53, ptr %i57, align 8 + %54 = load i64, ptr %.anon53, align 8 + %ptroffset59 = getelementptr inbounds [4 x i8], ptr %a52, i64 %54 + %55 = load i32, ptr %ptroffset59, align 4 + store i32 %55, ptr %x58, align 4 + %56 = insertvalue %any undef, ptr %i57, 0 + %57 = insertvalue %any %56, i64 ptrtoint (ptr @"$ct.ulong" to i64), 1 + store %any %57, ptr %varargslots60, align 16 + %58 = insertvalue %any undef, ptr %x58, 0 + %59 = insertvalue %any %58, i64 ptrtoint (ptr @"$ct.int" to i64), 1 + %ptradd61 = getelementptr inbounds i8, ptr %varargslots60, i64 16 + store %any %59, ptr %ptradd61, align 16 + %60 = call i64 @std.io.printfn(ptr %retparam62, ptr @.str.12, i64 8, ptr %varargslots60, i64 2) + %61 = load i64, ptr %.anon53, align 8 + %addnuw63 = add nuw i64 %61, 1 + store i64 %addnuw63, ptr %.anon53, align 8 + br label %loop.cond54 + +loop.exit64: ; preds = %loop.cond54 + call void @llvm.memcpy.p0.p0.i32(ptr align 16 %a65, ptr align 16 @.__const.13, i32 20, i1 false) + store i64 0, ptr %.anon66, align 8 + br label %loop.cond67 + +loop.cond67: ; preds = %loop.body69, %loop.exit64 + %62 = load i64, ptr %.anon66, align 8 + %gt68 = icmp ugt i64 5, %62 + br i1 %gt68, label %loop.body69, label %loop.exit77 + +loop.body69: ; preds = %loop.cond67 + %63 = load i64, ptr %.anon66, align 8 + store i64 %63, ptr %i70, align 8 + %64 = load i64, ptr %.anon66, align 8 + %ptroffset72 = getelementptr inbounds [4 x i8], ptr %a65, i64 %64 + %65 = load i32, ptr %ptroffset72, align 4 + store i32 %65, ptr %x71, align 4 + %66 = insertvalue %any undef, ptr %i70, 0 + %67 = insertvalue %any %66, i64 ptrtoint (ptr @"$ct.ulong" to i64), 1 + store %any %67, ptr %varargslots73, align 16 + %68 = insertvalue %any undef, ptr %x71, 0 + %69 = insertvalue %any %68, i64 ptrtoint (ptr @"$ct.int" to i64), 1 + %ptradd74 = getelementptr inbounds i8, ptr %varargslots73, i64 16 + store %any %69, ptr %ptradd74, align 16 + %70 = call i64 @std.io.printfn(ptr %retparam75, ptr @.str.14, i64 8, ptr %varargslots73, i64 2) + %71 = load i64, ptr %.anon66, align 8 + %addnuw76 = add nuw i64 %71, 1 + store i64 %addnuw76, ptr %.anon66, align 8 + br label %loop.cond67 + +loop.exit77: ; preds = %loop.cond67 + call void @llvm.memcpy.p0.p0.i32(ptr align 16 %a78, ptr align 16 @.__const.15, i32 32, i1 false) + store i64 0, ptr %.anon79, align 8 + br label %loop.cond80 + +loop.cond80: ; preds = %loop.body82, %loop.exit77 + %72 = load i64, ptr %.anon79, align 8 + %gt81 = icmp ugt i64 8, %72 + br i1 %gt81, label %loop.body82, label %loop.exit90 + +loop.body82: ; preds = %loop.cond80 + %73 = load i64, ptr %.anon79, align 8 + store i64 %73, ptr %i83, align 8 + %74 = load i64, ptr %.anon79, align 8 + %ptroffset85 = getelementptr inbounds [4 x i8], ptr %a78, i64 %74 + %75 = load i32, ptr %ptroffset85, align 4 + store i32 %75, ptr %x84, align 4 + %76 = insertvalue %any undef, ptr %i83, 0 + %77 = insertvalue %any %76, i64 ptrtoint (ptr @"$ct.ulong" to i64), 1 + store %any %77, ptr %varargslots86, align 16 + %78 = insertvalue %any undef, ptr %x84, 0 + %79 = insertvalue %any %78, i64 ptrtoint (ptr @"$ct.int" to i64), 1 + %ptradd87 = getelementptr inbounds i8, ptr %varargslots86, i64 16 + store %any %79, ptr %ptradd87, align 16 + %80 = call i64 @std.io.printfn(ptr %retparam88, ptr @.str.16, i64 8, ptr %varargslots86, i64 2) + %81 = load i64, ptr %.anon79, align 8 + %addnuw89 = add nuw i64 %81, 1 + store i64 %addnuw89, ptr %.anon79, align 8 + br label %loop.cond80 + +loop.exit90: ; preds = %loop.cond80 + call void @llvm.memcpy.p0.p0.i32(ptr align 16 %b, ptr align 16 @.__const.17, i32 28, i1 false) + store i64 0, ptr %.anon91, align 8 + br label %loop.cond92 + +loop.cond92: ; preds = %loop.body94, %loop.exit90 + %82 = load i64, ptr %.anon91, align 8 + %gt93 = icmp ugt i64 7, %82 + br i1 %gt93, label %loop.body94, label %loop.exit102 + +loop.body94: ; preds = %loop.cond92 + %83 = load i64, ptr %.anon91, align 8 + store i64 %83, ptr %i95, align 8 + %84 = load i64, ptr %.anon91, align 8 + %ptroffset97 = getelementptr inbounds [4 x i8], ptr %b, i64 %84 + %85 = load i32, ptr %ptroffset97, align 4 + store i32 %85, ptr %x96, align 4 + %86 = insertvalue %any undef, ptr %i95, 0 + %87 = insertvalue %any %86, i64 ptrtoint (ptr @"$ct.ulong" to i64), 1 + store %any %87, ptr %varargslots98, align 16 + %88 = insertvalue %any undef, ptr %x96, 0 + %89 = insertvalue %any %88, i64 ptrtoint (ptr @"$ct.int" to i64), 1 + %ptradd99 = getelementptr inbounds i8, ptr %varargslots98, i64 16 + store %any %89, ptr %ptradd99, align 16 + %90 = call i64 @std.io.printfn(ptr %retparam100, ptr @.str.18, i64 8, ptr %varargslots98, i64 2) + %91 = load i64, ptr %.anon91, align 8 + %addnuw101 = add nuw i64 %91, 1 + store i64 %addnuw101, ptr %.anon91, align 8 + br label %loop.cond92 + +loop.exit102: ; preds = %loop.cond92 + call void @llvm.memcpy.p0.p0.i32(ptr align 16 %c, ptr align 16 @.__const.19, i32 32, i1 false) + store i64 0, ptr %.anon103, align 8 + br label %loop.cond104 + +loop.cond104: ; preds = %loop.body106, %loop.exit102 + %92 = load i64, ptr %.anon103, align 8 + %gt105 = icmp ugt i64 8, %92 + br i1 %gt105, label %loop.body106, label %loop.exit114 + +loop.body106: ; preds = %loop.cond104 + %93 = load i64, ptr %.anon103, align 8 + store i64 %93, ptr %i107, align 8 + %94 = load i64, ptr %.anon103, align 8 + %ptroffset109 = getelementptr inbounds [4 x i8], ptr %c, i64 %94 + %95 = load i32, ptr %ptroffset109, align 4 + store i32 %95, ptr %x108, align 4 + %96 = insertvalue %any undef, ptr %i107, 0 + %97 = insertvalue %any %96, i64 ptrtoint (ptr @"$ct.ulong" to i64), 1 + store %any %97, ptr %varargslots110, align 16 + %98 = insertvalue %any undef, ptr %x108, 0 + %99 = insertvalue %any %98, i64 ptrtoint (ptr @"$ct.int" to i64), 1 + %ptradd111 = getelementptr inbounds i8, ptr %varargslots110, i64 16 + store %any %99, ptr %ptradd111, align 16 + %100 = call i64 @std.io.printfn(ptr %retparam112, ptr @.str.20, i64 9, ptr %varargslots110, i64 2) + %101 = load i64, ptr %.anon103, align 8 + %addnuw113 = add nuw i64 %101, 1 + store i64 %addnuw113, ptr %.anon103, align 8 + br label %loop.cond104 + +loop.exit114: ; preds = %loop.cond104 + call void @llvm.memcpy.p0.p0.i32(ptr align 16 %a115, ptr align 16 @.__const.21, i32 24, i1 false) + store i64 0, ptr %.anon116, align 8 + br label %loop.cond117 + +loop.cond117: ; preds = %loop.body119, %loop.exit114 + %102 = load i64, ptr %.anon116, align 8 + %gt118 = icmp ugt i64 6, %102 + br i1 %gt118, label %loop.body119, label %loop.exit127 + +loop.body119: ; preds = %loop.cond117 + %103 = load i64, ptr %.anon116, align 8 + store i64 %103, ptr %i120, align 8 + %104 = load i64, ptr %.anon116, align 8 + %ptroffset122 = getelementptr inbounds [4 x i8], ptr %a115, i64 %104 + %105 = load i32, ptr %ptroffset122, align 4 + store i32 %105, ptr %x121, align 4 + %106 = insertvalue %any undef, ptr %i120, 0 + %107 = insertvalue %any %106, i64 ptrtoint (ptr @"$ct.ulong" to i64), 1 + store %any %107, ptr %varargslots123, align 16 + %108 = insertvalue %any undef, ptr %x121, 0 + %109 = insertvalue %any %108, i64 ptrtoint (ptr @"$ct.int" to i64), 1 + %ptradd124 = getelementptr inbounds i8, ptr %varargslots123, i64 16 + store %any %109, ptr %ptradd124, align 16 + %110 = call i64 @std.io.printfn(ptr %retparam125, ptr @.str.22, i64 6, ptr %varargslots123, i64 2) + %111 = load i64, ptr %.anon116, align 8 + %addnuw126 = add nuw i64 %111, 1 + store i64 %addnuw126, ptr %.anon116, align 8 + br label %loop.cond117 + +loop.exit127: ; preds = %loop.cond117 + ret void +} diff --git a/test/test_suite7/macros/macro_with_body.c3t b/test/test_suite7/macros/macro_with_body.c3t new file mode 100644 index 000000000..cb529d800 --- /dev/null +++ b/test/test_suite7/macros/macro_with_body.c3t @@ -0,0 +1,100 @@ +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 = load i32, ptr %0, align 4 + %add = add i32 %2, 1 + store i32 %add, ptr %0, align 4 + %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 + %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 + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %foo, ptr align 4 %f, i32 4, i1 false) + %0 = load i32, ptr %foo, align 4 + store i32 %0, ptr %y, align 4 + %1 = call i32 @withbody.Foo.mutate(ptr %foo) + store i32 %1, ptr %x, align 4 + %2 = load i32, ptr %y, align 4 + store i32 %2, ptr %dy, align 4 + %3 = load i32, ptr %x, align 4 + %4 = load i32, ptr %dy, align 4 + %5 = call i32 (ptr, ...) @printf(ptr @.str, i32 %3, i32 %4) + store i32 0, ptr %i, align 4 + br label %loop.cond + +loop.cond: ; preds = %loop.body, %entry + %6 = load i32, ptr %i, align 4 + %lt = icmp slt i32 %6, 10 + br i1 %lt, label %loop.body, label %loop.exit + +loop.body: ; preds = %loop.cond + %7 = load i32, ptr %i, align 4 + %add = add i32 %7, 1 + store i32 %add, ptr %loop, align 4 + %8 = load i32, ptr %loop, align 4 + %9 = call i32 (ptr, ...) @printf(ptr @.str.1, i32 %8) + %10 = load i32, ptr %i, align 4 + %add1 = add i32 %10, 1 + store i32 %add1, ptr %i, align 4 + br label %loop.cond + +loop.exit: ; preds = %loop.cond + ret void +} diff --git a/test/test_suite7/macros/macro_with_body_err.c3 b/test/test_suite7/macros/macro_with_body_err.c3 new file mode 100644 index 000000000..841cc1b9e --- /dev/null +++ b/test/test_suite7/macros/macro_with_body_err.c3 @@ -0,0 +1,33 @@ +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); // #error: 'int*' to 'int' +} + + +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); + }; + +} \ No newline at end of file diff --git a/test/test_suite7/macros/modify_ct_param.c3 b/test/test_suite7/macros/modify_ct_param.c3 new file mode 100644 index 000000000..80219fe80 --- /dev/null +++ b/test/test_suite7/macros/modify_ct_param.c3 @@ -0,0 +1,13 @@ +module test; + +macro test($baz, $Type) +{ + $baz = 123; + $Type = int; +} +fn void main() +{ + var $foo = 1; + $foo = 4; + test(4, double); +} diff --git a/test/test_suite7/macros/no_body.c3 b/test/test_suite7/macros/no_body.c3 new file mode 100644 index 000000000..6a71cf27f --- /dev/null +++ b/test/test_suite7/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_suite7/macros/ref_macro_method.c3 b/test/test_suite7/macros/ref_macro_method.c3 new file mode 100644 index 000000000..7cd42e8f6 --- /dev/null +++ b/test/test_suite7/macros/ref_macro_method.c3 @@ -0,0 +1,26 @@ +import std::io; + +struct MyStruct +{ + DString* dyn; +} + +fn void main() +{ + @pool() + { + usz values_len = 10; + + MyStruct ms = { + .dyn = mem::temp_new_array(DString, values_len).ptr, + }; + + for (usz i; i < values_len; ++i) + { + ms.dyn[i].temp_init(); + } + + ms.dyn[0].append_chars("sad"); + ms.dyn[0].append("sad"); + }; +} \ No newline at end of file diff --git a/test/test_suite7/macros/ref_vector.c3t b/test/test_suite7/macros/ref_vector.c3t new file mode 100644 index 000000000..2dab88a6c --- /dev/null +++ b/test/test_suite7/macros/ref_vector.c3t @@ -0,0 +1,53 @@ +// #target: macos-x64 +module test; + +fn int main() { + int[<4>] vec; + @foo(vec[0]); + @foo(vec[2]); + assert(vec[0] == 1); + assert(vec[2] == 1); + return 1; +} + +macro @foo(#ref) { + #ref += 1; +} + +/* #expect: test.ll + + +define i32 @main() #0 { +entry: + %vec = alloca <4 x i32>, align 16 + store <4 x i32> zeroinitializer, ptr %vec, align 16 + %0 = load <4 x i32>, ptr %vec, align 16 + %elem = extractelement <4 x i32> %0, i64 0 + %add = add i32 %elem, 1 + %elemset = insertelement <4 x i32> %0, i32 %add, i64 0 + store <4 x i32> %elemset, ptr %vec, align 16 + %1 = load <4 x i32>, ptr %vec, align 16 + %elem1 = extractelement <4 x i32> %1, i64 2 + %add2 = add i32 %elem1, 1 + %elemset3 = insertelement <4 x i32> %1, i32 %add2, i64 2 + store <4 x i32> %elemset3, ptr %vec, align 16 + %2 = load <4 x i32>, ptr %vec, align 16 + %3 = extractelement <4 x i32> %2, i64 0 + %eq = icmp eq i32 %3, 1 + call void @llvm.assume(i1 %eq) + %4 = load <4 x i32>, ptr %vec, align 16 + %5 = extractelement <4 x i32> %4, i64 2 + %eq4 = icmp eq i32 %5, 1 + call void @llvm.assume(i1 %eq4) + ret i32 1 +} + +declare void @llvm.assume(i1 noundef) #1 +attributes #0 = { nounwind uwtable "no-trapping-math"="true" "stack-protector-buffer-size"="8" } +!llvm.module.flags = !{!0, !1, !2, !3, !4, !5} +!0 = !{i32 2, !"Dwarf Version", i32 4} +!1 = !{i32 2, !"Debug Info Version", i32 3} +!2 = !{i32 2, !"wchar_size", i32 4} +!3 = !{i32 4, !"PIC Level", i32 2} +!4 = !{i32 1, !"uwtable", i32 2} +!5 = !{i32 2, !"frame-pointer", i32 2} \ No newline at end of file diff --git a/test/test_suite7/macros/short_trailing_body.c3t b/test/test_suite7/macros/short_trailing_body.c3t new file mode 100644 index 000000000..88e69c7b8 --- /dev/null +++ b/test/test_suite7/macros/short_trailing_body.c3t @@ -0,0 +1,122 @@ +// #target: macos-x64 +module test; +import std; + +fn int foo(int x) => @pool() +{ + String s = string::tformat("%d", x); + io::printn(s); + return 2; +} + +fn void main() +{ + foo(3); +} + +/* #expect: test.ll + +entry: + %current = alloca ptr, align 8 + %mark = alloca i64, align 8 + %s = alloca %"char[]", align 8 + %varargslots = alloca [1 x %any], align 16 + %taddr = alloca i32, align 4 + %result = alloca %"char[]", align 8 + %x = alloca %"char[]", align 8 + %x1 = alloca %"char[]", align 8 + %len = alloca i64, align 8 + %error_var = alloca i64, align 8 + %x2 = alloca %"char[]", align 8 + %retparam = alloca i64, align 8 + %error_var5 = alloca i64, align 8 + %error_var11 = alloca i64, align 8 + %1 = load ptr, ptr @std.core.mem.allocator.thread_temp_allocator, align 8 + %i2nb = icmp eq ptr %1, null + br i1 %i2nb, label %if.then, label %if.exit + +if.then: ; preds = %entry + call void @std.core.mem.allocator.init_default_temp_allocators() + br label %if.exit + +if.exit: ; preds = %if.then, %entry + %2 = load ptr, ptr @std.core.mem.allocator.thread_temp_allocator, align 8 + store ptr %2, ptr %current, align 8 + %3 = load ptr, ptr %current, align 8 + %ptradd = getelementptr inbounds i8, ptr %3, i64 24 + %4 = load i64, ptr %ptradd, align 8 + store i64 %4, ptr %mark, align 8 + store i32 %0, ptr %taddr, align 4 + %5 = insertvalue %any undef, ptr %taddr, 0 + %6 = insertvalue %any %5, i64 ptrtoint (ptr @"$ct.int" to i64), 1 + store %any %6, ptr %varargslots, align 16 + %7 = call { ptr, i64 } @std.core.string.tformat(ptr @.str, i64 2, ptr %varargslots, i64 1) + store { ptr, i64 } %7, ptr %result, align 8 + call void @llvm.memcpy.p0.p0.i32(ptr align 8 %s, ptr align 8 %result, i32 16, i1 false) + call void @llvm.memcpy.p0.p0.i32(ptr align 8 %x, ptr align 8 %s, i32 16, i1 false) + %8 = call ptr @std.io.stdout() + call void @llvm.memcpy.p0.p0.i32(ptr align 8 %x1, ptr align 8 %x, i32 16, i1 false) + call void @llvm.memcpy.p0.p0.i32(ptr align 8 %x2, ptr align 8 %x1, i32 16, i1 false) + %lo = load ptr, ptr %x2, align 8 + %ptradd4 = getelementptr inbounds i8, ptr %x2, i64 8 + %hi = load i64, ptr %ptradd4, align 8 + %9 = call i64 @std.io.File.write(ptr %retparam, ptr %8, ptr %lo, i64 %hi) + %not_err = icmp eq i64 %9, 0 + %10 = call i1 @llvm.expect.i1(i1 %not_err, i1 true) + br i1 %10, label %after_check, label %assign_optional + +assign_optional: ; preds = %if.exit + store i64 %9, ptr %error_var, align 8 + br label %guard_block + +after_check: ; preds = %if.exit + br label %noerr_block + +guard_block: ; preds = %assign_optional + br label %voiderr + +noerr_block: ; preds = %after_check + %11 = load i64, ptr %retparam, align 8 + store i64 %11, ptr %len, align 8 + %12 = call i64 @std.io.File.write_byte(ptr %8, i8 zeroext 10) + %not_err6 = icmp eq i64 %12, 0 + %13 = call i1 @llvm.expect.i1(i1 %not_err6, i1 true) + br i1 %13, label %after_check8, label %assign_optional7 + +assign_optional7: ; preds = %noerr_block + store i64 %12, ptr %error_var5, align 8 + br label %guard_block9 + +after_check8: ; preds = %noerr_block + br label %noerr_block10 + +guard_block9: ; preds = %assign_optional7 + br label %voiderr + +noerr_block10: ; preds = %after_check8 + %14 = call i64 @std.io.File.flush(ptr %8) + %not_err12 = icmp eq i64 %14, 0 + %15 = call i1 @llvm.expect.i1(i1 %not_err12, i1 true) + br i1 %15, label %after_check14, label %assign_optional13 + +assign_optional13: ; preds = %noerr_block10 + store i64 %14, ptr %error_var11, align 8 + br label %guard_block15 + +after_check14: ; preds = %noerr_block10 + br label %noerr_block16 + +guard_block15: ; preds = %assign_optional13 + br label %voiderr + +noerr_block16: ; preds = %after_check14 + %16 = load i64, ptr %len, align 8 + %add = add i64 %16, 1 + br label %voiderr + +voiderr: ; preds = %noerr_block16, %guard_block15, %guard_block9, %guard_block + %17 = load ptr, ptr %current, align 8 + %18 = load i64, ptr %mark, align 8 + call void @std.core.mem.allocator.TempAllocator.reset(ptr %17, i64 %18) + ret i32 2 +} diff --git a/test/test_suite7/macros/trailing_body_const.c3t b/test/test_suite7/macros/trailing_body_const.c3t new file mode 100644 index 000000000..acc6e66b1 --- /dev/null +++ b/test/test_suite7/macros/trailing_body_const.c3t @@ -0,0 +1,31 @@ +// #target: macos-x64 +module test; +import std::io; +macro @test(;@body($val)) +{ + @body(1); + @body(2); +} + +fn void main() +{ + int a; + @test(;int $num) + { + a += $num; + }; +} + +/* #expect: test.ll + +entry: + %a = alloca i32, align 4 + store i32 0, ptr %a, align 4 + %0 = load i32, ptr %a, align 4 + %add = add i32 %0, 1 + store i32 %add, ptr %a, align 4 + %1 = load i32, ptr %a, align 4 + %add1 = add i32 %1, 2 + store i32 %add1, ptr %a, align 4 + ret void +} diff --git a/test/test_suite7/macros/trailing_body_type.c3 b/test/test_suite7/macros/trailing_body_type.c3 new file mode 100644 index 000000000..b73746620 --- /dev/null +++ b/test/test_suite7/macros/trailing_body_type.c3 @@ -0,0 +1,10 @@ +macro @test(int x = 1; @body()) +{ + if (x > 0) @body(); + return x; +} + +fn int foo(int x) => @test(x) // #error: The macro itself returns 'int' here +{ + return 2; +} diff --git a/test/test_suite7/macros/type_params.c3t b/test/test_suite7/macros/type_params.c3t new file mode 100644 index 000000000..df1aaad78 --- /dev/null +++ b/test/test_suite7/macros/type_params.c3t @@ -0,0 +1,42 @@ +// #target: macos-x64 +macro foo($Foo) +{ + $Foo a; + return a; +} + +def 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_suite7/macros/typed_hash_access.c3 b/test/test_suite7/macros/typed_hash_access.c3 new file mode 100644 index 000000000..a0cf3291e --- /dev/null +++ b/test/test_suite7/macros/typed_hash_access.c3 @@ -0,0 +1,11 @@ + +macro void @foo(int #a) +{ + var x = float.#a; // #error: cannot already be resolved +} + +fn void main() +{ + int inf; + @foo(inf); +} \ No newline at end of file diff --git a/test/test_suite7/macros/unifying_implicit_void.c3t b/test/test_suite7/macros/unifying_implicit_void.c3t new file mode 100644 index 000000000..4c815c827 --- /dev/null +++ b/test/test_suite7/macros/unifying_implicit_void.c3t @@ -0,0 +1,115 @@ +// #target: macos-x64 +module oups; +import std::io; + +fn void main() +{ + ByteReader r; + InStream s = &r; + s.foo()!!; +} + +macro InStream.foo(&self) +{ + char! c = self.read_byte(); + if (catch err = c) + { + return err?; + } + return; +} + + +/* #expect: oups.ll + +define void @oups.main() #0 { +entry: + %r = alloca %ByteReader, align 8 + %s = alloca %any, align 8 + %error_var = alloca i64, align 8 + %c = alloca i8, align 1 + %c.f = alloca i64, align 8 + %.inlinecache = alloca ptr, align 8 + %.cachedtype = alloca ptr, align 8 + %retparam = alloca i8, align 1 + %err = alloca i64, align 8 + %varargslots = alloca [1 x %any], align 16 + %indirectarg = alloca %"any[]", align 8 + store ptr null, ptr %.cachedtype, align 8 + call void @llvm.memset.p0.i64(ptr align 8 %r, i8 0, i64 24, i1 false) + %0 = insertvalue %any undef, ptr %r, 0 + %1 = insertvalue %any %0, i64 ptrtoint (ptr @"$ct.std.io.ByteReader" to i64), 1 + store %any %1, ptr %s, align 8 + %ptradd = getelementptr inbounds i8, ptr %s, i64 8 + %2 = load i64, ptr %ptradd, align 8 + %3 = inttoptr i64 %2 to ptr + %type = load ptr, ptr %.cachedtype, align 8 + %4 = icmp eq ptr %3, %type + br i1 %4, label %cache_hit, label %cache_miss +cache_miss: ; preds = %entry + %ptradd1 = getelementptr inbounds i8, ptr %3, i64 16 + %5 = load ptr, ptr %ptradd1, align 8 + %6 = call ptr @.dyn_search(ptr %5, ptr @"$sel.read_byte") + store ptr %6, ptr %.inlinecache, align 8 + store ptr %3, ptr %.cachedtype, align 8 + br label %7 +cache_hit: ; preds = %entry + %cache_hit_fn = load ptr, ptr %.inlinecache, align 8 + br label %7 +7: ; preds = %cache_hit, %cache_miss + %fn_phi = phi ptr [ %cache_hit_fn, %cache_hit ], [ %6, %cache_miss ] + %8 = icmp eq ptr %fn_phi, null + br i1 %8, label %missing_function, label %match +missing_function: ; preds = %7 + %9 = load ptr, ptr @std.core.builtin.panic, align 8 + call void %9(ptr @.panic_msg, i64 46, ptr @.file, i64 25, ptr @.func, i64 4, i32 13) + unreachable +match: ; preds = %7 + %10 = load ptr, ptr %s, align 8 + %11 = call i64 %fn_phi(ptr %retparam, ptr %10) + %not_err = icmp eq i64 %11, 0 + %12 = call i1 @llvm.expect.i1(i1 %not_err, i1 true) + br i1 %12, label %after_check, label %assign_optional +assign_optional: ; preds = %match + store i64 %11, ptr %c.f, align 8 + br label %after_assign +after_check: ; preds = %match + %13 = load i8, ptr %retparam, align 1 + store i8 %13, ptr %c, align 1 + store i64 0, ptr %c.f, align 8 + br label %after_assign +after_assign: ; preds = %after_check, %assign_optional + br label %testblock +testblock: ; preds = %after_assign + %optval = load i64, ptr %c.f, align 8 + %not_err2 = icmp eq i64 %optval, 0 + %14 = call i1 @llvm.expect.i1(i1 %not_err2, i1 true) + br i1 %14, label %after_check4, label %assign_optional3 +assign_optional3: ; preds = %testblock + store i64 %optval, ptr %err, align 8 + br label %end_block +after_check4: ; preds = %testblock + store i64 0, ptr %err, align 8 + br label %end_block +end_block: ; preds = %after_check4, %assign_optional3 + %15 = load i64, ptr %err, align 8 + %i2b = icmp ne i64 %15, 0 + br i1 %i2b, label %if.then, label %if.exit +if.then: ; preds = %end_block + %16 = load i64, ptr %err, align 8 + store i64 %16, ptr %error_var, align 8 + br label %panic_block +if.exit: ; preds = %end_block + br label %noerr_block +panic_block: ; preds = %if.then + %17 = insertvalue %any undef, ptr %error_var, 0 + %18 = insertvalue %any %17, i64 ptrtoint (ptr @"$ct.anyfault" to i64), 1 + store %any %18, ptr %varargslots, align 16 + %19 = insertvalue %"any[]" undef, ptr %varargslots, 0 + %"$$temp" = insertvalue %"any[]" %19, i64 1, 1 + store %"any[]" %"$$temp", ptr %indirectarg, align 8 + call void @std.core.builtin.panicf(ptr @.panic_msg.1, i64 36, ptr @.file, i64 25, ptr @.func, i64 4, i32 8, ptr byval(%"any[]") align 8 %indirectarg) + unreachable +noerr_block: ; preds = %if.exit + ret void +} \ No newline at end of file diff --git a/test/test_suite7/macros/userland_bitcast.c3t b/test/test_suite7/macros/userland_bitcast.c3t new file mode 100644 index 000000000..b919b3d45 --- /dev/null +++ b/test/test_suite7/macros/userland_bitcast.c3t @@ -0,0 +1,331 @@ +// #target: macos-x64 + +macro testbitcast(expr, $Type) +{ + $assert $sizeof(expr) == $Type.sizeof : "Cannot bitcast between types of different size."; + $Type x @noinit; + var $size = (usz)($sizeof(expr)); + + $switch + $case $alignof(expr) >= 8 && $Type.alignof >= 8: + ulong *b = (ulong*)(&expr); + ulong *to = (ulong*)(&x); + for (usz i = 0; i < $size; i += 8) + { + to[i] = b[i]; + } + $case $alignof(expr) >= 4 && $Type.alignof >= 4: + uint* b = (uint*)(&expr); + uint* to = (uint*)(&x); + for (usz i = 0; i < $size; i += 4) + { + to[i] = b[i]; + } + $case $alignof(expr) >= 2 && $Type.alignof >= 2: + ushort* b = (ushort*)(&expr); + ushort* to = (ushort*)(&x); + for (usz i = 0; i < $size; i += 2) + { + to[i] = b[i]; + } + $default: + char* b = (char*)(&expr); + char* to = (char*)(&x); + for (usz i = 0; i < $size; i++) + { + to[i] = b[i]; + } + $endswitch + 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 } + +@"$ct.userland_bitcast.Foo" = linkonce global %.introspect { i8 10, i64 0, ptr null, i64 8, i64 0, i64 5, [0 x i64] zeroinitializer }, 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 + store i16 0, ptr %z, align 2 + %ptradd = getelementptr inbounds i8, ptr %z, i64 2 + store i8 0, ptr %ptradd, align 2 + %ptradd1 = getelementptr inbounds i8, ptr %z, i64 3 + store i8 0, ptr %ptradd1, align 1 + %ptradd2 = getelementptr inbounds i8, ptr %z, i64 4 + store i16 0, ptr %ptradd2, align 2 + %ptradd3 = getelementptr inbounds i8, ptr %z, i64 6 + store i16 0, ptr %ptradd3, align 2 + store i16 %0, ptr %z, align 2 + call void @llvm.memcpy.p0.p0.i32(ptr align 2 %expr, ptr align 2 %z, i32 8, i1 false) + 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, 8 + 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 [2 x i8], ptr %2, i64 %3 + %4 = load ptr, ptr %b, align 8 + %5 = load i64, ptr %i, align 8 + %ptroffset4 = getelementptr inbounds [2 x i8], ptr %4, i64 %5 + %6 = load i16, ptr %ptroffset4, align 2 + store i16 %6, ptr %ptroffset, align 2 + %7 = load i64, ptr %i, align 8 + %add = add i64 %7, 2 + store i64 %add, ptr %i, align 8 + br label %loop.cond + +loop.exit: ; preds = %loop.cond + %8 = load i64, ptr %x, align 8 + ret i64 %8 +} + +; Function Attrs: +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 + 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 + %ptradd = getelementptr inbounds i8, ptr %2, i64 %3 + %4 = load ptr, ptr %b, align 8 + %5 = load i64, ptr %i, align 8 + %ptradd1 = getelementptr inbounds i8, ptr %4, i64 %5 + %6 = load i8, ptr %ptradd1, align 1 + store i8 %6, ptr %ptradd, 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 + %8 = load i32, ptr %x, align 1 + ret i32 %8 +} + +; Function Attrs: +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 [4 x i8], ptr %2, i64 %3 + %4 = load ptr, ptr %b, align 8 + %5 = load i64, ptr %i1, align 8 + %ptroffset2 = getelementptr inbounds [4 x i8], 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 [4 x i8], ptr %11, i64 %12 + %13 = load ptr, ptr %b5, align 8 + %14 = load i64, ptr %i7, align 8 + %ptroffset12 = getelementptr inbounds [4 x i8], 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 float, ptr %f2, align 4 + %fpfpext15 = fpext float %19 to double + %20 = load i32, ptr %i, align 4 + call void (ptr, ...) @printf(ptr @.str, double %fpfpext, i32 %20, 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 + store i64 0, ptr %i20, 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 [8 x i8], ptr %23, i64 %24 + %25 = load ptr, ptr %b18, align 8 + %26 = load i64, ptr %i20, align 8 + %ptroffset25 = getelementptr inbounds [8 x i8], 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 [8 x i8], ptr %32, i64 %33 + %34 = load ptr, ptr %b30, align 8 + %35 = load i64, ptr %i32, align 8 + %ptroffset37 = getelementptr inbounds [8 x i8], 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_suite7/macros/vasplat_function_call.c3 b/test/test_suite7/macros/vasplat_function_call.c3 new file mode 100644 index 000000000..62e653473 --- /dev/null +++ b/test/test_suite7/macros/vasplat_function_call.c3 @@ -0,0 +1,18 @@ +import std; + +def IList = List{int}; +fn IList IList.new() @operator(construct) +{ + IList l; + l.init(mem, $vasplat); // #error: can only be used inside + return l; +} + + +fn void main() +{ + IList a = IList.new(123, 123, 123, 123, 123, 123, 123, 134); + a.push(567); + + io::printfn("%s", a[0]); +} diff --git a/test/test_suite7/methods/access.c3 b/test/test_suite7/methods/access.c3 new file mode 100644 index 000000000..42cf06d83 --- /dev/null +++ b/test/test_suite7/methods/access.c3 @@ -0,0 +1,37 @@ +extern fn void printf(...); + +struct An1 +{ + An3 x; +} + +struct An3 +{ + An2 y; +} + +def 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_suite7/methods/access_private_method.c3 b/test/test_suite7/methods/access_private_method.c3 new file mode 100644 index 000000000..5e81cb5db --- /dev/null +++ b/test/test_suite7/methods/access_private_method.c3 @@ -0,0 +1,9 @@ +def NodeNotifyHandler = fn void(TreeView* this, TreeNode* node, String prop, void* data); +fn void TreeView.nodeNotifyHandler(TreeView* this, TreeNode* node, String prop, void* data) @private {} + +struct TreeNode { int abc; NodeNotifyHandler notifyHandler; } +struct TreeView { int abc; } +fn void TreeView.addNodeInternal(TreeView* this, int nop, TreeNode* node, TreeNode* pnode = null, int pos = -1) @private +{ + node.notifyHandler = &TreeView.nodeNotifyHandler; // This is the line +} \ No newline at end of file diff --git a/test/test_suite7/methods/dynamic_method_fails.c3 b/test/test_suite7/methods/dynamic_method_fails.c3 new file mode 100644 index 000000000..5db7d1067 --- /dev/null +++ b/test/test_suite7/methods/dynamic_method_fails.c3 @@ -0,0 +1,6 @@ + +interface Abc {} + +fn void any.blob(any* x) @dynamic {} // #error: 'any' may not implement +fn void Abc.blob(Abc* y) @dynamic {} // #error: Interfaces may not implement +fn void int.blob(int z) @dynamic {} // #error: The first parameter must always diff --git a/test/test_suite7/methods/enum_distinct_err_methods.c3t b/test/test_suite7/methods/enum_distinct_err_methods.c3t new file mode 100644 index 000000000..d4ee7e08c --- /dev/null +++ b/test/test_suite7/methods/enum_distinct_err_methods.c3t @@ -0,0 +1,218 @@ +// #target: macos-x64 + +module foo; +import std::io; + +fault Foo +{ + X +} + +distinct Bar = int; + +enum MyEnum +{ + A, + B +} + +fn void Foo.hello(Foo *f) +{ + io::printn("Hello from Foo"); +} + +fn void Bar.hello(Bar *b) +{ + io::printn("Hello from Bar"); +} + +fn void MyEnum.hello(MyEnum *myenum) +{ + io::printn("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: + %len = alloca i64, align 8 + %error_var = alloca i64, align 8 + %retparam = alloca i64, align 8 + %error_var2 = alloca i64, align 8 + %error_var8 = alloca i64, align 8 + %1 = call ptr @std.io.stdout() + %2 = call i64 @std.io.File.write(ptr %retparam, ptr %1, ptr @.str, i64 14) + %not_err = icmp eq i64 %2, 0 + %3 = call i1 @llvm.expect.i1(i1 %not_err, i1 true) + br i1 %3, label %after_check, label %assign_optional +assign_optional: ; preds = %entry + store i64 %2, ptr %error_var, align 8 + br label %guard_block +after_check: ; preds = %entry + br label %noerr_block +guard_block: ; preds = %assign_optional + br label %voiderr +noerr_block: ; preds = %after_check + %4 = load i64, ptr %retparam, align 8 + store i64 %4, ptr %len, align 8 + %5 = call i64 @std.io.File.write_byte(ptr %1, i8 zeroext 10) + %not_err3 = icmp eq i64 %5, 0 + %6 = call i1 @llvm.expect.i1(i1 %not_err3, i1 true) + br i1 %6, label %after_check5, label %assign_optional4 +assign_optional4: ; preds = %noerr_block + store i64 %5, ptr %error_var2, align 8 + br label %guard_block6 +after_check5: ; preds = %noerr_block + br label %noerr_block7 +guard_block6: ; preds = %assign_optional4 + br label %voiderr +noerr_block7: ; preds = %after_check5 + %7 = call i64 @std.io.File.flush(ptr %1) + %not_err9 = icmp eq i64 %7, 0 + %8 = call i1 @llvm.expect.i1(i1 %not_err9, i1 true) + br i1 %8, label %after_check11, label %assign_optional10 +assign_optional10: ; preds = %noerr_block7 + store i64 %7, ptr %error_var8, align 8 + br label %guard_block12 +after_check11: ; preds = %noerr_block7 + br label %noerr_block13 +guard_block12: ; preds = %assign_optional10 + br label %voiderr +noerr_block13: ; preds = %after_check11 + %9 = load i64, ptr %len, align 8 + %add = add i64 %9, 1 + br label %voiderr +voiderr: ; preds = %noerr_block13, %guard_block12, %guard_block6, %guard_block + ret void +} + +define void @foo.Bar.hello(ptr %0) #0 { +entry: + %len = alloca i64, align 8 + %error_var = alloca i64, align 8 + %retparam = alloca i64, align 8 + %error_var2 = alloca i64, align 8 + %error_var8 = alloca i64, align 8 + %1 = call ptr @std.io.stdout() + %2 = call i64 @std.io.File.write(ptr %retparam, ptr %1, ptr @.str.1, i64 14) + %not_err = icmp eq i64 %2, 0 + %3 = call i1 @llvm.expect.i1(i1 %not_err, i1 true) + br i1 %3, label %after_check, label %assign_optional +assign_optional: ; preds = %entry + store i64 %2, ptr %error_var, align 8 + br label %guard_block +after_check: ; preds = %entry + br label %noerr_block +guard_block: ; preds = %assign_optional + br label %voiderr +noerr_block: ; preds = %after_check + %4 = load i64, ptr %retparam, align 8 + store i64 %4, ptr %len, align 8 + %5 = call i64 @std.io.File.write_byte(ptr %1, i8 zeroext 10) + %not_err3 = icmp eq i64 %5, 0 + %6 = call i1 @llvm.expect.i1(i1 %not_err3, i1 true) + br i1 %6, label %after_check5, label %assign_optional4 +assign_optional4: ; preds = %noerr_block + store i64 %5, ptr %error_var2, align 8 + br label %guard_block6 +after_check5: ; preds = %noerr_block + br label %noerr_block7 +guard_block6: ; preds = %assign_optional4 + br label %voiderr +noerr_block7: ; preds = %after_check5 + %7 = call i64 @std.io.File.flush(ptr %1) + %not_err9 = icmp eq i64 %7, 0 + %8 = call i1 @llvm.expect.i1(i1 %not_err9, i1 true) + br i1 %8, label %after_check11, label %assign_optional10 +assign_optional10: ; preds = %noerr_block7 + store i64 %7, ptr %error_var8, align 8 + br label %guard_block12 +after_check11: ; preds = %noerr_block7 + br label %noerr_block13 +guard_block12: ; preds = %assign_optional10 + br label %voiderr +noerr_block13: ; preds = %after_check11 + %9 = load i64, ptr %len, align 8 + %add = add i64 %9, 1 + br label %voiderr +voiderr: ; preds = %noerr_block13, %guard_block12, %guard_block6, %guard_block + ret void +} + +define void @foo.MyEnum.hello(ptr %0) #0 { +entry: + %len = alloca i64, align 8 + %error_var = alloca i64, align 8 + %retparam = alloca i64, align 8 + %error_var2 = alloca i64, align 8 + %error_var8 = alloca i64, align 8 + %1 = call ptr @std.io.stdout() + %2 = call i64 @std.io.File.write(ptr %retparam, ptr %1, ptr @.str.2, i64 17) + %not_err = icmp eq i64 %2, 0 + %3 = call i1 @llvm.expect.i1(i1 %not_err, i1 true) + br i1 %3, label %after_check, label %assign_optional +assign_optional: ; preds = %entry + store i64 %2, ptr %error_var, align 8 + br label %guard_block +after_check: ; preds = %entry + br label %noerr_block +guard_block: ; preds = %assign_optional + br label %voiderr +noerr_block: ; preds = %after_check + %4 = load i64, ptr %retparam, align 8 + store i64 %4, ptr %len, align 8 + %5 = call i64 @std.io.File.write_byte(ptr %1, i8 zeroext 10) + %not_err3 = icmp eq i64 %5, 0 + %6 = call i1 @llvm.expect.i1(i1 %not_err3, i1 true) + br i1 %6, label %after_check5, label %assign_optional4 +assign_optional4: ; preds = %noerr_block + store i64 %5, ptr %error_var2, align 8 + br label %guard_block6 +after_check5: ; preds = %noerr_block + br label %noerr_block7 +guard_block6: ; preds = %assign_optional4 + br label %voiderr +noerr_block7: ; preds = %after_check5 + %7 = call i64 @std.io.File.flush(ptr %1) + %not_err9 = icmp eq i64 %7, 0 + %8 = call i1 @llvm.expect.i1(i1 %not_err9, i1 true) + br i1 %8, label %after_check11, label %assign_optional10 +assign_optional10: ; preds = %noerr_block7 + store i64 %7, ptr %error_var8, align 8 + br label %guard_block12 +after_check11: ; preds = %noerr_block7 + br label %noerr_block13 +guard_block12: ; preds = %assign_optional10 + br label %voiderr +noerr_block13: ; preds = %after_check11 + %9 = load i64, ptr %len, align 8 + %add = add i64 %9, 1 + br label %voiderr +voiderr: ; preds = %noerr_block13, %guard_block12, %guard_block6, %guard_block + 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 +} \ No newline at end of file diff --git a/test/test_suite7/methods/extending_with_visibility.c3 b/test/test_suite7/methods/extending_with_visibility.c3 new file mode 100644 index 000000000..64119422e --- /dev/null +++ b/test/test_suite7/methods/extending_with_visibility.c3 @@ -0,0 +1,35 @@ +module test; +import abc; + +struct Foo +{ + int x; +} + +fn int Foo.get1(Foo* f) @private => f.x; +fn int Foo.get2(Foo* f) => f.x; +fn int Foo.get3(Foo* f) @local => f.x; + +fn int Bar.get1(Bar* f) @private => f.x; +fn int Bar.get2(Bar* f) => f.x; +fn int Bar.get3(Bar* f) @local => f.x; + +fn int main() +{ + Foo x = { 1 }; + x.get1(); + x.get2(); + x.get3(); + Bar y = { 1 }; + y.get1(); + y.get2(); + y.get3(); + return 1; +} + +module abc; + +struct Bar +{ + int x; +} diff --git a/test/test_suite7/methods/extending_with_visibility_fail.c3 b/test/test_suite7/methods/extending_with_visibility_fail.c3 new file mode 100644 index 000000000..548ad1beb --- /dev/null +++ b/test/test_suite7/methods/extending_with_visibility_fail.c3 @@ -0,0 +1,37 @@ +module test; +import abc; + +struct Foo +{ + int x; +} + +fn int Foo.get1(Foo* f) @private => f.x; +fn int Foo.get2(Foo* f) => f.x; +fn int Foo.get3(Foo* f) @local => f.x; + +fn int Bar.get1(Bar* f) @private => f.x; +fn int Bar.get2(Bar* f) => f.x; +fn int Bar.get3(Bar* f) @local => f.x; + +module abc; +import test; + +struct Bar +{ + int x; +} + +Foo x = { 1 }; +Bar y = { 1 }; + +fn int test() +{ + x.get1(); // #error: method + x.get2(); + x.get3(); // #error: method + y.get1(); // #error: method + y.get2(); + y.get3(); // #error: method + return 1; +} diff --git a/test/test_suite7/methods/extending_with_visibility_fail_private.c3 b/test/test_suite7/methods/extending_with_visibility_fail_private.c3 new file mode 100644 index 000000000..89b169507 --- /dev/null +++ b/test/test_suite7/methods/extending_with_visibility_fail_private.c3 @@ -0,0 +1,37 @@ +module test; +import abc; + +struct Foo +{ + int x; +} + +fn int Foo.get1(Foo* f) @private => f.x; +fn int Foo.get2(Foo* f) => f.x; +fn int Foo.get3(Foo* f) @local => f.x; + +fn int Bar.get1(Bar* f) @private => f.x; +fn int Bar.get2(Bar* f) => f.x; +fn int Bar.get3(Bar* f) @local => f.x; + +module abc; +import test @public; + +struct Bar +{ + int x; +} + +Foo x = { 1 }; +Bar y = { 1 }; + +fn int test() +{ + x.get1(); + x.get2(); + x.get3(); // #error: method + y.get1(); + y.get2(); + y.get3(); // #error: method + return 1; +} diff --git a/test/test_suite7/methods/extension_method.c3t b/test/test_suite7/methods/extension_method.c3t new file mode 100644 index 000000000..34b38f07f --- /dev/null +++ b/test/test_suite7/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::printn("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_suite7/methods/extension_method_already_exist.c3 b/test/test_suite7/methods/extension_method_already_exist.c3 new file mode 100644 index 000000000..8bd16a1ef --- /dev/null +++ b/test/test_suite7/methods/extension_method_already_exist.c3 @@ -0,0 +1,30 @@ +module foo; + +fn void Bar.test(Bar *bar) +{ + io::printn("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::printn("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_suite7/methods/extension_method_check.c3 b/test/test_suite7/methods/extension_method_check.c3 new file mode 100644 index 000000000..ae5ad5226 --- /dev/null +++ b/test/test_suite7/methods/extension_method_check.c3 @@ -0,0 +1,19 @@ +module test; + +def Bob = Test(); +fn void Bob.crash(&self) {} + +fn int main() +{ + Test() foo; + return 0; +} +<* + @require $defined(String.hash) +*> +module test::generic(); + +enum Test +{ + ABC +} \ No newline at end of file diff --git a/test/test_suite7/methods/extension_method_generic.c3 b/test/test_suite7/methods/extension_method_generic.c3 new file mode 100644 index 000000000..06e36cdd8 --- /dev/null +++ b/test/test_suite7/methods/extension_method_generic.c3 @@ -0,0 +1,31 @@ +module compiler_c3; +import std::collections::list; + +def IntArray = List(); + +extern fn void printf(char*, ...); + +fn void IntArray.someFunc(IntArray *this, usz param) +{ + //do something + this.push((int)param); +} + +fn int main(String[] argv) +{ + IntArray stk; + stk.someFunc(256); + + for (int i = 0; i < 256; i++) + { + stk.push(i); + } + + for (;!stk.is_empty();) + { + int value = stk.pop()!!; + printf("%i\n", value); + } + + return 0; +} \ No newline at end of file diff --git a/test/test_suite7/methods/extension_method_in_other_modules.c3t b/test/test_suite7/methods/extension_method_in_other_modules.c3t new file mode 100644 index 000000000..abe98c5c1 --- /dev/null +++ b/test/test_suite7/methods/extension_method_in_other_modules.c3t @@ -0,0 +1,42 @@ +// #target: macos-x64 +module foob; +struct Foo +{ + int x; +} +fn void Foo.test(Foo* f) +{} + +module baz; +import foob; +fn void Foo.test2(Foo* f, int x) +{} +fn void main() +{ + Foo f; + f.test(); + f.test2(123); +} + +/* #expect: foob.ll + +define void @foob.Foo.test(ptr %0) #0 { +entry: + ret void +} + +// #expect: baz.ll + +define void @foob.Foo.test2(ptr %0, i32 %1) #0 { +entry: + ret void +} + +define void @baz.main() #0 { +entry: + %f = alloca %Foo, align 4 + store i32 0, ptr %f, align 4 + call void @foob.Foo.test(ptr %f) + call void @foob.Foo.test2(ptr %f, i32 123) + ret void +} diff --git a/test/test_suite7/methods/method_extension_in_conditional_module.c3 b/test/test_suite7/methods/method_extension_in_conditional_module.c3 new file mode 100644 index 000000000..eeb28d603 --- /dev/null +++ b/test/test_suite7/methods/method_extension_in_conditional_module.c3 @@ -0,0 +1,15 @@ +module std::core::env; +const bool FOO = true; + +module foo @if(env::FOO); +struct Foo { int a; } + +module bar; +import std, foo; + +fn void Foo.baz(self) {} + +fn int main() +{ + return 0; +} diff --git a/test/test_suite7/methods/method_from_var.c3 b/test/test_suite7/methods/method_from_var.c3 new file mode 100644 index 000000000..ce5bba181 --- /dev/null +++ b/test/test_suite7/methods/method_from_var.c3 @@ -0,0 +1,9 @@ +def NodeNotifyHandler = fn void(TreeView* this, TreeNode* node, String prop, void* data); +fn void TreeView.nodeNotifyHandler(TreeView* this, TreeNode* node, String prop, void* data) @private {} + +struct TreeNode { int abc; NodeNotifyHandler notifyHandler; } +struct TreeView { int abc; } +fn void TreeView.addNodeInternal(TreeView* this, int nop, TreeNode* node, TreeNode* pnode = null, int pos = -1) @private +{ + node.notifyHandler = &(this.nodeNotifyHandler); // #error: Taking the address of a method +} \ No newline at end of file diff --git a/test/test_suite7/methods/method_name_collision.c3 b/test/test_suite7/methods/method_name_collision.c3 new file mode 100644 index 000000000..b12d33230 --- /dev/null +++ b/test/test_suite7/methods/method_name_collision.c3 @@ -0,0 +1,7 @@ +module testc3; + +fn bool any.type(self) { // #error: is not a valid method name +return true; +} + +fn void main() {} diff --git a/test/test_suite7/methods/method_ref_for_extension_method.c3 b/test/test_suite7/methods/method_ref_for_extension_method.c3 new file mode 100644 index 000000000..22d27abdb --- /dev/null +++ b/test/test_suite7/methods/method_ref_for_extension_method.c3 @@ -0,0 +1,19 @@ +module testc3; +import std::io; + +struct Foo { + int i; +} + +fn bool Foo[].is_empty(Foo[] array) { + return array.len == 0; +} + +def foo_arr_is_empty = Foo[].is_empty; + +fn void main() { + Foo[] foos = { (Foo) { .i = 0 } }; + void* foo = &Foo[].is_empty; + io::printfn("Is empty: %s", foos.is_empty()); + io::printfn("Is empty: %s", foo_arr_is_empty(foos)); +} diff --git a/test/test_suite7/methods/methods_defined_twice.c3 b/test/test_suite7/methods/methods_defined_twice.c3 new file mode 100644 index 000000000..5c60adf53 --- /dev/null +++ b/test/test_suite7/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::printn("Inside of baz::Bar.test"); +} + +fn void Bar.test(Bar *bar) // #error: This method is already defined for +{ + io::printn("Inside of baz::Bar.test"); +} + +module abc; +import foo; +import baz; + +fn void main() +{ + Bar bar; + bar.test(); +} + diff --git a/test/test_suite7/methods/methods_with_inferred_type.c3t b/test/test_suite7/methods/methods_with_inferred_type.c3t new file mode 100644 index 000000000..5e38793d8 --- /dev/null +++ b/test/test_suite7/methods/methods_with_inferred_type.c3t @@ -0,0 +1,83 @@ +// #target: macos-x64 +module test; + +distinct Foo = int; + +struct Abc +{ + int a; + int b; +} + +fn void Foo.add(&f) +{ + *f = *f + 1; +} + +macro void Foo.add_macro(&f) +{ + (*f)++; +} + +fn int Abc.add(&a) +{ + return a.a + a.b; +} + +macro int Abc.add_macro(&a) +{ + return a.a + a.b; +} + +fn void test() +{ + Abc x = { 3, 4 }; + int a = x.add(); + int b = x.add_macro(); + Foo f = 100; + f.add(); + f.add_macro(); +} + +/* #expect: test.ll + +define void @test.Foo.add(ptr %0) #0 { +entry: + %1 = load i32, ptr %0, align 4 + %add = add i32 %1, 1 + store i32 %add, ptr %0, align 4 + ret void +} + +; Function Attrs: +define i32 @test.Abc.add(ptr %0) #0 { +entry: + %1 = load i32, ptr %0, align 4 + %ptradd = getelementptr inbounds i8, ptr %0, i64 4 + %2 = load i32, ptr %ptradd, align 4 + %add = add i32 %1, %2 + ret i32 %add +} + +; Function Attrs: +define void @test.test() #0 { +entry: + %x = alloca %Abc, align 4 + %a = alloca i32, align 4 + %b = alloca i32, align 4 + %f = alloca i32, align 4 + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %x, ptr align 4 @.__const, i32 8, i1 false) + %0 = call i32 @test.Abc.add(ptr %x) + store i32 %0, ptr %a, align 4 + %1 = load i32, ptr %x, align 4 + %ptradd = getelementptr inbounds i8, ptr %x, i64 4 + %2 = load i32, ptr %ptradd, align 4 + %add = add i32 %1, %2 + store i32 %add, ptr %b, align 4 + store i32 100, ptr %f, align 4 + call void @test.Foo.add(ptr %f) + %3 = load i32, ptr %f, align 4 + %add1 = add i32 %3, 1 + store i32 %add1, ptr %f, align 4 + ret void +} diff --git a/test/test_suite7/methods/operator_assign_mutate.c3t b/test/test_suite7/methods/operator_assign_mutate.c3t new file mode 100644 index 000000000..0d9a1ac60 --- /dev/null +++ b/test/test_suite7/methods/operator_assign_mutate.c3t @@ -0,0 +1,77 @@ +// #target: macos-x64 +module test; +import std::io, std::time, std::math, std::collections; + +List() stones; + +struct Foo +{ + int[3] x; +} + +fn int Foo.get(self, usz i) @operator([]) => self.x[i]; +fn void Foo.set(&self, usz i, int z) @operator([]=) => self.x[i] = z; + +fn void main() { + stones.push(1); + stones.push(100); + stones[0] *= 3; + stones[1] *= 2; + stones[0] += 31; + Foo z; + z[1] += 5; + z[1] *= 3; +} + +/* #expect: test.ll + +define void @test.main() #0 { +entry: + %z = alloca %Foo, align 4 + %.anon = alloca i32, align 4 + %coerce = alloca %Foo, align 8 + %.anon5 = alloca i32, align 4 + %coerce6 = alloca %Foo, align 8 + call void @"std_collections_list$long$.List.push"(ptr @test.stones, i64 1) #2 + call void @"std_collections_list$long$.List.push"(ptr @test.stones, i64 100) #2 + %0 = call ptr @"std_collections_list$long$.List.get_ref"(ptr @test.stones, i64 0) #2 + %1 = load i64, ptr %0, align 8 + %mul = mul i64 %1, 3 + store i64 %mul, ptr %0, align 8 + %2 = call ptr @"std_collections_list$long$.List.get_ref"(ptr @test.stones, i64 1) #2 + %3 = load i64, ptr %2, align 8 + %mul1 = mul i64 %3, 2 + store i64 %mul1, ptr %2, align 8 + %4 = call ptr @"std_collections_list$long$.List.get_ref"(ptr @test.stones, i64 0) #2 + %5 = load i64, ptr %4, align 8 + %add = add i64 %5, 31 + store i64 %add, ptr %4, align 8 + store i32 0, ptr %z, align 4 + %ptradd = getelementptr inbounds i8, ptr %z, i64 4 + store i32 0, ptr %ptradd, align 4 + %ptradd2 = getelementptr inbounds i8, ptr %z, i64 8 + store i32 0, ptr %ptradd2, align 4 + call void @llvm.memcpy.p0.p0.i32(ptr align 8 %coerce, ptr align 4 %z, i32 12, i1 false) + %lo = load i64, ptr %coerce, align 8 + %ptradd3 = getelementptr inbounds i8, ptr %coerce, i64 8 + %hi = load i32, ptr %ptradd3, align 8 + %6 = call i32 @test.Foo.get(i64 %lo, i32 %hi, i64 1) + store i32 %6, ptr %.anon, align 4 + %7 = load i32, ptr %.anon, align 4 + %add4 = add i32 %7, 5 + store i32 %add4, ptr %.anon, align 4 + %8 = load i32, ptr %.anon, align 4 + call void @test.Foo.set(ptr %z, i64 1, i32 %8) + call void @llvm.memcpy.p0.p0.i32(ptr align 8 %coerce6, ptr align 4 %z, i32 12, i1 false) + %lo7 = load i64, ptr %coerce6, align 8 + %ptradd8 = getelementptr inbounds i8, ptr %coerce6, i64 8 + %hi9 = load i32, ptr %ptradd8, align 8 + %9 = call i32 @test.Foo.get(i64 %lo7, i32 %hi9, i64 1) + store i32 %9, ptr %.anon5, align 4 + %10 = load i32, ptr %.anon5, align 4 + %mul10 = mul i32 %10, 3 + store i32 %mul10, ptr %.anon5, align 4 + %11 = load i32, ptr %.anon5, align 4 + call void @test.Foo.set(ptr %z, i64 1, i32 %11) + ret void +} diff --git a/test/test_suite7/methods/operator_defined_twice.c3 b/test/test_suite7/methods/operator_defined_twice.c3 new file mode 100644 index 000000000..9720ec498 --- /dev/null +++ b/test/test_suite7/methods/operator_defined_twice.c3 @@ -0,0 +1,9 @@ +distinct Foo = int; + +fn int Foo.fadd(&self, int x) @operator([]) { return 1; } +fn int Foo.badd(&self, int x) @operator([]) { return 1; } // #error: This operator is already defined + +fn void main() +{ + Foo x = 1; +} diff --git a/test/test_suite7/methods/operator_inc.c3t b/test/test_suite7/methods/operator_inc.c3t new file mode 100644 index 000000000..ffb18b837 --- /dev/null +++ b/test/test_suite7/methods/operator_inc.c3t @@ -0,0 +1,52 @@ +// #target: macos-x64 +module test; + +import std; + +struct Foo +{ + int[5] a; +} +fn int Foo.get(self, usz i) @operator([]) => self.a[i]; +fn void Foo.set(&self, usz i, int j) @operator([]=) { self.a[i] = j; } + +Foo m; +fn void main() { + + m.a[3] = 100; + int x = m[3]--; +} + +/* #expect: test.ll + +define i32 @test.Foo.get(ptr byval(%Foo) align 8 %0, i64 %1) #0 { +entry: + %ptroffset = getelementptr inbounds [4 x i8], ptr %0, i64 %1 + %2 = load i32, ptr %ptroffset, align 4 + ret i32 %2 +} + +define void @test.Foo.set(ptr %0, i64 %1, i32 %2) #0 { +entry: + %ptroffset = getelementptr inbounds [4 x i8], ptr %0, i64 %1 + store i32 %2, ptr %ptroffset, align 4 + ret void +} + +define void @test.main() #0 { +entry: + %x = alloca i32, align 4 + %.anon = alloca i32, align 4 + %indirectarg = alloca %Foo, align 8 + store i32 100, ptr getelementptr inbounds (i8, ptr @test.m, i64 12), align 4 + call void @llvm.memcpy.p0.p0.i32(ptr align 8 %indirectarg, ptr align 4 @test.m, i32 20, i1 false) + %0 = call i32 @test.Foo.get(ptr byval(%Foo) align 8 %indirectarg, i64 3) + store i32 %0, ptr %.anon, align 4 + %1 = load i32, ptr %.anon, align 4 + %sub = sub i32 %1, 1 + store i32 %sub, ptr %.anon, align 4 + %2 = load i32, ptr %.anon, align 4 + call void @test.Foo.set(ptr @test.m, i64 3, i32 %2) + store i32 %1, ptr %x, align 4 + ret void +} diff --git a/test/test_suite7/methods/operator_mismatch.c3 b/test/test_suite7/methods/operator_mismatch.c3 new file mode 100644 index 000000000..d0f96160b --- /dev/null +++ b/test/test_suite7/methods/operator_mismatch.c3 @@ -0,0 +1,12 @@ +struct Foo { int a; } +struct Foo2 { int a; } +struct Bar { int a; } + +fn int Foo.x(&self, int x) @operator([]) => 1; +fn int Foo.y(&self, int x) @operator(&[]) => 1; // #error: The return type must be a pointer +fn int Foo2.y(&self, int x) @operator([]) => null; +fn int** Foo2.y2(&self, int x) @operator(&[]) => null; // #error: There is a mismatch of the 'value' type +fn void Foo.z(&self, uint x, int a) @operator([]=) {} // #error: There is a mismatch of the 'index' + +fn double Bar.x(&self, int x) @operator([]) => 0.1; +fn void Bar.y(&self, int x, float y) @operator([]=) {} // #error: There is a mismatch of the 'value' diff --git a/test/test_suite7/methods/self_methods_null.c3t b/test/test_suite7/methods/self_methods_null.c3t new file mode 100644 index 000000000..80819d3c4 --- /dev/null +++ b/test/test_suite7/methods/self_methods_null.c3t @@ -0,0 +1,27 @@ +// #target: macos-x64 +// #safe: yes +module test; +distinct Foo = int; +fn void Foo.test(&self) {} +fn int main() +{ + Foo* a = null; + a.test(); + return 0; +} +/* #expect: test.ll + +define void @test.Foo.test(ptr %0) #0 { +entry: + %1 = icmp eq ptr %0, null + %2 = call i1 @llvm.expect.i1(i1 %1, i1 false) + br i1 %2, label %panic, label %checkok + +checkok: ; preds = %entry + ret void + +panic: ; preds = %entry + %3 = load ptr, ptr @std.core.builtin.panic, align 8 + call void %3(ptr @.panic_msg, i64 62, ptr @.file, i64 20, ptr @.func, i64 4, i32 3) + unreachable +} diff --git a/test/test_suite7/methods/unsupported_operator.c3 b/test/test_suite7/methods/unsupported_operator.c3 new file mode 100755 index 000000000..8610d8f9d --- /dev/null +++ b/test/test_suite7/methods/unsupported_operator.c3 @@ -0,0 +1,3 @@ +import std::io; + +fn int int.fadd(&self, int x) @operator([]) { return 1; } // #error: Only user-defined types support operator overloading \ No newline at end of file diff --git a/test/test_suite7/module/missing_semi.c3 b/test/test_suite7/module/missing_semi.c3 new file mode 100644 index 000000000..ce8ae0942 --- /dev/null +++ b/test/test_suite7/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_suite7/module/module_bad_path_ident.c3 b/test/test_suite7/module/module_bad_path_ident.c3 new file mode 100644 index 000000000..3897c998c --- /dev/null +++ b/test/test_suite7/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_suite7/module/module_bad_path_invalid.c3 b/test/test_suite7/module/module_bad_path_invalid.c3 new file mode 100644 index 000000000..1554c001d --- /dev/null +++ b/test/test_suite7/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_suite7/module/module_bad_path_keyword.c3 b/test/test_suite7/module/module_bad_path_keyword.c3 new file mode 100644 index 000000000..918aa7389 --- /dev/null +++ b/test/test_suite7/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_suite7/module/module_error_string.c3 b/test/test_suite7/module/module_error_string.c3 new file mode 100644 index 000000000..ceb869c56 --- /dev/null +++ b/test/test_suite7/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_suite7/module/module_generic_mixing.c3 b/test/test_suite7/module/module_generic_mixing.c3 new file mode 100644 index 000000000..be62be825 --- /dev/null +++ b/test/test_suite7/module/module_generic_mixing.c3 @@ -0,0 +1,7 @@ +module test; +fn void main() {} + +module test(); // #error: generic +fn void test() { + Type a; +} \ No newline at end of file diff --git a/test/test_suite7/module/module_section_export.c3t b/test/test_suite7/module/module_section_export.c3t new file mode 100644 index 000000000..c556e4690 --- /dev/null +++ b/test/test_suite7/module/module_section_export.c3t @@ -0,0 +1,29 @@ +// #target: macos-x64 + +module test @extern("TEST"); + +fn void hello() @private {} + +fn void hello2() @private @export {} + +int a @private @export; +int b @private; + +module test @export; + +fn void helloe() @private {} + +int c @private @export; +int d @private; + +/* #expect: test.ll + + +@TEST__a = local_unnamed_addr global i32 0, align 4 +@TEST.b = internal unnamed_addr global i32 0, align 4 +@TEST__c = local_unnamed_addr global i32 0, align 4 +@TEST__d = local_unnamed_addr global i32 0, align 4 + +define internal void @TEST.hello() +define void @TEST__hello2() +define void @TEST__helloe() \ No newline at end of file diff --git a/test/test_suite7/module/module_start_bad_ident.c3 b/test/test_suite7/module/module_start_bad_ident.c3 new file mode 100644 index 000000000..3502724ba --- /dev/null +++ b/test/test_suite7/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_suite7/module/module_start_invalid.c3 b/test/test_suite7/module/module_start_invalid.c3 new file mode 100644 index 000000000..1c8e68bb9 --- /dev/null +++ b/test/test_suite7/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_suite7/module/module_start_keyword.c3 b/test/test_suite7/module/module_start_keyword.c3 new file mode 100644 index 000000000..84ff3d77c --- /dev/null +++ b/test/test_suite7/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_suite7/module/private_module.c3 b/test/test_suite7/module/private_module.c3 new file mode 100644 index 000000000..837e36b94 --- /dev/null +++ b/test/test_suite7/module/private_module.c3 @@ -0,0 +1 @@ +module foo @private; \ No newline at end of file diff --git a/test/test_suite7/module/unknown_modules.c3 b/test/test_suite7/module/unknown_modules.c3 new file mode 100644 index 000000000..a800c0fc8 --- /dev/null +++ b/test/test_suite7/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_suite7/overloading/construct_op_zero_args.c3 b/test/test_suite7/overloading/construct_op_zero_args.c3 new file mode 100644 index 000000000..670f5c845 --- /dev/null +++ b/test/test_suite7/overloading/construct_op_zero_args.c3 @@ -0,0 +1,5 @@ +struct Foo { int a; } +fn Foo Foo.foo() @operator(construct) +{ + return { 1 }; +} diff --git a/test/test_suite7/overloading/construct_operator.c3t b/test/test_suite7/overloading/construct_operator.c3t new file mode 100644 index 000000000..6b08b0424 --- /dev/null +++ b/test/test_suite7/overloading/construct_operator.c3t @@ -0,0 +1,353 @@ +// #target: macos-x64 +module test; +import std; +struct Foo +{ + int a; +} + +macro Foo Foo.baz(int y) @operator(construct) +{ + return { 2 + y } ; +} +fn Foo Foo.new(int x) @operator(construct) +{ + return { 23 }; +} + +fn int! x() { return 1; } +fn void main() +{ + io::printn(Foo.new(123)); + io::printn(Foo.baz(123)); +} +/* #expect: test.ll + + +define void @test.main() #0 { +entry: + %result = alloca %Foo, align 4 + %x = alloca %Foo, align 4 + %x1 = alloca %Foo, align 4 + %len = alloca i64, align 8 + %error_var = alloca i64, align 8 + %x2 = alloca %Foo, align 4 + %formatter = alloca %Formatter, align 8 + %taddr = alloca %any, align 8 + %value = alloca %Foo, align 4 + %total = alloca i64, align 8 + %error_var5 = alloca i64, align 8 + %retparam = alloca i64, align 8 + %error_var6 = alloca i64, align 8 + %varargslots = alloca [1 x %any], align 16 + %taddr7 = alloca %"char[]", align 8 + %retparam8 = alloca i64, align 8 + %error_var14 = alloca i64, align 8 + %varargslots15 = alloca [1 x %any], align 16 + %retparam16 = alloca i64, align 8 + %retparam23 = alloca i64, align 8 + %error_var30 = alloca i64, align 8 + %error_var36 = alloca i64, align 8 + %literal = alloca %Foo, align 4 + %x43 = alloca %Foo, align 4 + %x44 = alloca %Foo, align 4 + %len45 = alloca i64, align 8 + %error_var46 = alloca i64, align 8 + %x47 = alloca %Foo, align 4 + %formatter49 = alloca %Formatter, align 8 + %taddr50 = alloca %any, align 8 + %value51 = alloca %Foo, align 4 + %total53 = alloca i64, align 8 + %error_var54 = alloca i64, align 8 + %retparam55 = alloca i64, align 8 + %error_var61 = alloca i64, align 8 + %varargslots62 = alloca [1 x %any], align 16 + %taddr63 = alloca %"char[]", align 8 + %retparam64 = alloca i64, align 8 + %error_var71 = alloca i64, align 8 + %varargslots72 = alloca [1 x %any], align 16 + %retparam73 = alloca i64, align 8 + %retparam80 = alloca i64, align 8 + %error_var87 = alloca i64, align 8 + %error_var93 = alloca i64, align 8 + %0 = call i32 @test.Foo.new(i32 123) + store i32 %0, ptr %result, align 4 + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %x, ptr align 4 %result, i32 4, i1 false) + %1 = call ptr @std.io.stdout() + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %x1, ptr align 4 %x, i32 4, i1 false) + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %x2, ptr align 4 %x1, i32 4, i1 false) + call void @llvm.memset.p0.i64(ptr align 8 %formatter, i8 0, i64 48, i1 false) + %2 = insertvalue %any undef, ptr %1, 0 + %3 = insertvalue %any %2, i64 ptrtoint (ptr @"$ct.std.io.File" to i64), 1 + store %any %3, ptr %taddr, align 8 + call void @std.io.Formatter.init(ptr %formatter, ptr @std.io.out_putstream_fn, ptr %taddr) + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %value, ptr align 4 %x2, i32 4, i1 false) + %4 = call i64 @std.io.Formatter.print(ptr %retparam, ptr %formatter, ptr @.str, i64 2) + %not_err = icmp eq i64 %4, 0 + %5 = call i1 @llvm.expect.i1(i1 %not_err, i1 true) + br i1 %5, label %after_check, label %assign_optional + +assign_optional: ; preds = %entry + store i64 %4, ptr %error_var5, align 8 + br label %guard_block + +after_check: ; preds = %entry + br label %noerr_block + +guard_block: ; preds = %assign_optional + %6 = load i64, ptr %error_var5, align 8 + store i64 %6, ptr %error_var, align 8 + br label %guard_block28 + +noerr_block: ; preds = %after_check + %7 = load i64, ptr %retparam, align 8 + store i64 %7, ptr %total, align 8 + %8 = load i64, ptr %total, align 8 + store %"char[]" { ptr @.str.2, i64 1 }, ptr %taddr7, align 8 + %9 = insertvalue %any undef, ptr %taddr7, 0 + %10 = insertvalue %any %9, i64 ptrtoint (ptr @"$ct.String" to i64), 1 + store %any %10, ptr %varargslots, align 16 + %11 = call i64 @std.io.Formatter.printf(ptr %retparam8, ptr %formatter, ptr @.str.1, i64 4, ptr %varargslots, i64 1) + %not_err9 = icmp eq i64 %11, 0 + %12 = call i1 @llvm.expect.i1(i1 %not_err9, i1 true) + br i1 %12, label %after_check11, label %assign_optional10 + +assign_optional10: ; preds = %noerr_block + store i64 %11, ptr %error_var6, align 8 + br label %guard_block12 + +after_check11: ; preds = %noerr_block + br label %noerr_block13 + +guard_block12: ; preds = %assign_optional10 + %13 = load i64, ptr %error_var6, align 8 + store i64 %13, ptr %error_var, align 8 + br label %guard_block28 + +noerr_block13: ; preds = %after_check11 + %14 = load i64, ptr %retparam8, align 8 + %add = add i64 %8, %14 + store i64 %add, ptr %total, align 8 + %15 = load i64, ptr %total, align 8 + %16 = insertvalue %any undef, ptr %value, 0 + %17 = insertvalue %any %16, i64 ptrtoint (ptr @"$ct.int" to i64), 1 + store %any %17, ptr %varargslots15, align 16 + %18 = call i64 @std.io.Formatter.printf(ptr %retparam16, ptr %formatter, ptr @.str.3, i64 2, ptr %varargslots15, i64 1) + %not_err17 = icmp eq i64 %18, 0 + %19 = call i1 @llvm.expect.i1(i1 %not_err17, i1 true) + br i1 %19, label %after_check19, label %assign_optional18 + +assign_optional18: ; preds = %noerr_block13 + store i64 %18, ptr %error_var14, align 8 + br label %guard_block20 + +after_check19: ; preds = %noerr_block13 + br label %noerr_block21 + +guard_block20: ; preds = %assign_optional18 + %20 = load i64, ptr %error_var14, align 8 + store i64 %20, ptr %error_var, align 8 + br label %guard_block28 + +noerr_block21: ; preds = %after_check19 + %21 = load i64, ptr %retparam16, align 8 + %add22 = add i64 %15, %21 + store i64 %add22, ptr %total, align 8 + %22 = load i64, ptr %total, align 8 + %23 = call i64 @std.io.Formatter.print(ptr %retparam23, ptr %formatter, ptr @.str.4, i64 2) + %not_err24 = icmp eq i64 %23, 0 + %24 = call i1 @llvm.expect.i1(i1 %not_err24, i1 true) + br i1 %24, label %after_check26, label %assign_optional25 + +assign_optional25: ; preds = %noerr_block21 + store i64 %23, ptr %error_var, align 8 + br label %guard_block28 + +after_check26: ; preds = %noerr_block21 + %25 = load i64, ptr %retparam23, align 8 + %add27 = add i64 %22, %25 + br label %noerr_block29 + +guard_block28: ; preds = %assign_optional25, %guard_block20, %guard_block12, %guard_block + br label %voiderr + +noerr_block29: ; preds = %after_check26 + store i64 %add27, ptr %len, align 8 + %26 = call i64 @std.io.File.write_byte(ptr %1, i8 zeroext 10) + %not_err31 = icmp eq i64 %26, 0 + %27 = call i1 @llvm.expect.i1(i1 %not_err31, i1 true) + br i1 %27, label %after_check33, label %assign_optional32 + +assign_optional32: ; preds = %noerr_block29 + store i64 %26, ptr %error_var30, align 8 + br label %guard_block34 + +after_check33: ; preds = %noerr_block29 + br label %noerr_block35 + +guard_block34: ; preds = %assign_optional32 + br label %voiderr + +noerr_block35: ; preds = %after_check33 + %28 = call i64 @std.io.File.flush(ptr %1) + %not_err37 = icmp eq i64 %28, 0 + %29 = call i1 @llvm.expect.i1(i1 %not_err37, i1 true) + br i1 %29, label %after_check39, label %assign_optional38 + +assign_optional38: ; preds = %noerr_block35 + store i64 %28, ptr %error_var36, align 8 + br label %guard_block40 + +after_check39: ; preds = %noerr_block35 + br label %noerr_block41 + +guard_block40: ; preds = %assign_optional38 + br label %voiderr + +noerr_block41: ; preds = %after_check39 + %30 = load i64, ptr %len, align 8 + %add42 = add i64 %30, 1 + br label %voiderr + +voiderr: ; preds = %noerr_block41, %guard_block40, %guard_block34, %guard_block28 + store i32 125, ptr %literal, align 4 + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %x43, ptr align 4 %literal, i32 4, i1 false) + %31 = call ptr @std.io.stdout() + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %x44, ptr align 4 %x43, i32 4, i1 false) + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %x47, ptr align 4 %x44, i32 4, i1 false) + call void @llvm.memset.p0.i64(ptr align 8 %formatter49, i8 0, i64 48, i1 false) + %32 = insertvalue %any undef, ptr %31, 0 + %33 = insertvalue %any %32, i64 ptrtoint (ptr @"$ct.std.io.File" to i64), 1 + store %any %33, ptr %taddr50, align 8 + call void @std.io.Formatter.init(ptr %formatter49, ptr @std.io.out_putstream_fn, ptr %taddr50) + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %value51, ptr align 4 %x47, i32 4, i1 false) + %34 = call i64 @std.io.Formatter.print(ptr %retparam55, ptr %formatter49, ptr @.str.5, i64 2) + %not_err56 = icmp eq i64 %34, 0 + %35 = call i1 @llvm.expect.i1(i1 %not_err56, i1 true) + br i1 %35, label %after_check58, label %assign_optional57 + +assign_optional57: ; preds = %voiderr + store i64 %34, ptr %error_var54, align 8 + br label %guard_block59 + +after_check58: ; preds = %voiderr + br label %noerr_block60 + +guard_block59: ; preds = %assign_optional57 + %36 = load i64, ptr %error_var54, align 8 + store i64 %36, ptr %error_var46, align 8 + br label %guard_block85 + +noerr_block60: ; preds = %after_check58 + %37 = load i64, ptr %retparam55, align 8 + store i64 %37, ptr %total53, align 8 + %38 = load i64, ptr %total53, align 8 + store %"char[]" { ptr @.str.7, i64 1 }, ptr %taddr63, align 8 + %39 = insertvalue %any undef, ptr %taddr63, 0 + %40 = insertvalue %any %39, i64 ptrtoint (ptr @"$ct.String" to i64), 1 + store %any %40, ptr %varargslots62, align 16 + %41 = call i64 @std.io.Formatter.printf(ptr %retparam64, ptr %formatter49, ptr @.str.6, i64 4, ptr %varargslots62, i64 1) + %not_err65 = icmp eq i64 %41, 0 + %42 = call i1 @llvm.expect.i1(i1 %not_err65, i1 true) + br i1 %42, label %after_check67, label %assign_optional66 + +assign_optional66: ; preds = %noerr_block60 + store i64 %41, ptr %error_var61, align 8 + br label %guard_block68 + +after_check67: ; preds = %noerr_block60 + br label %noerr_block69 + +guard_block68: ; preds = %assign_optional66 + %43 = load i64, ptr %error_var61, align 8 + store i64 %43, ptr %error_var46, align 8 + br label %guard_block85 + +noerr_block69: ; preds = %after_check67 + %44 = load i64, ptr %retparam64, align 8 + %add70 = add i64 %38, %44 + store i64 %add70, ptr %total53, align 8 + %45 = load i64, ptr %total53, align 8 + %46 = insertvalue %any undef, ptr %value51, 0 + %47 = insertvalue %any %46, i64 ptrtoint (ptr @"$ct.int" to i64), 1 + store %any %47, ptr %varargslots72, align 16 + %48 = call i64 @std.io.Formatter.printf(ptr %retparam73, ptr %formatter49, ptr @.str.8, i64 2, ptr %varargslots72, i64 1) + %not_err74 = icmp eq i64 %48, 0 + %49 = call i1 @llvm.expect.i1(i1 %not_err74, i1 true) + br i1 %49, label %after_check76, label %assign_optional75 + +assign_optional75: ; preds = %noerr_block69 + store i64 %48, ptr %error_var71, align 8 + br label %guard_block77 + +after_check76: ; preds = %noerr_block69 + br label %noerr_block78 + +guard_block77: ; preds = %assign_optional75 + %50 = load i64, ptr %error_var71, align 8 + store i64 %50, ptr %error_var46, align 8 + br label %guard_block85 + +noerr_block78: ; preds = %after_check76 + %51 = load i64, ptr %retparam73, align 8 + %add79 = add i64 %45, %51 + store i64 %add79, ptr %total53, align 8 + %52 = load i64, ptr %total53, align 8 + %53 = call i64 @std.io.Formatter.print(ptr %retparam80, ptr %formatter49, ptr @.str.9, i64 2) + %not_err81 = icmp eq i64 %53, 0 + %54 = call i1 @llvm.expect.i1(i1 %not_err81, i1 true) + br i1 %54, label %after_check83, label %assign_optional82 + +assign_optional82: ; preds = %noerr_block78 + store i64 %53, ptr %error_var46, align 8 + br label %guard_block85 + +after_check83: ; preds = %noerr_block78 + %55 = load i64, ptr %retparam80, align 8 + %add84 = add i64 %52, %55 + br label %noerr_block86 + +guard_block85: ; preds = %assign_optional82, %guard_block77, %guard_block68, %guard_block59 + br label %voiderr100 + +noerr_block86: ; preds = %after_check83 + store i64 %add84, ptr %len45, align 8 + %56 = call i64 @std.io.File.write_byte(ptr %31, i8 zeroext 10) + %not_err88 = icmp eq i64 %56, 0 + %57 = call i1 @llvm.expect.i1(i1 %not_err88, i1 true) + br i1 %57, label %after_check90, label %assign_optional89 + +assign_optional89: ; preds = %noerr_block86 + store i64 %56, ptr %error_var87, align 8 + br label %guard_block91 + +after_check90: ; preds = %noerr_block86 + br label %noerr_block92 + +guard_block91: ; preds = %assign_optional89 + br label %voiderr100 + +noerr_block92: ; preds = %after_check90 + %58 = call i64 @std.io.File.flush(ptr %31) + %not_err94 = icmp eq i64 %58, 0 + %59 = call i1 @llvm.expect.i1(i1 %not_err94, i1 true) + br i1 %59, label %after_check96, label %assign_optional95 + +assign_optional95: ; preds = %noerr_block92 + store i64 %58, ptr %error_var93, align 8 + br label %guard_block97 + +after_check96: ; preds = %noerr_block92 + br label %noerr_block98 + +guard_block97: ; preds = %assign_optional95 + br label %voiderr100 + +noerr_block98: ; preds = %after_check96 + %60 = load i64, ptr %len45, align 8 + %add99 = add i64 %60, 1 + br label %voiderr100 + +voiderr100: ; preds = %noerr_block98, %guard_block97, %guard_block91, %guard_block85 + ret void +} diff --git a/test/test_suite7/overloading/set_not_set_overload.c3t b/test/test_suite7/overloading/set_not_set_overload.c3t new file mode 100644 index 000000000..c2e14d7f1 --- /dev/null +++ b/test/test_suite7/overloading/set_not_set_overload.c3t @@ -0,0 +1,61 @@ +// #target: macos-x64 +module test; +import std::io; +import std::collections::list; + +List{int[3]} x; + +struct Map +{ + char[20][] data; + int width; +} +fn int Map.len(self) @inline @operator(len) => self.width; +fn char[] Map.get(self, int i) @inline @operator([]) => self.data[i][:self.width]; + +fn void main () +{ + x.tinit(); + int[3] y = { 1, 2, 3 }; + x.push(y); + x[0][0] = 4; + char[20][20] z; + Map foo = { z[:10], 10 }; + foo[3][4] = 123; +} + +/* #expect: test.ll + +define void @test.main() #0 { +entry: + %y = alloca [3 x i32], align 4 + %coerce = alloca [3 x i32], align 8 + %z = alloca [20 x [20 x i8]], align 16 + %foo = alloca %Map, align 8 + %result = alloca %"char[]", align 8 + %0 = call ptr @"std_collections_list$a3$int$.List.tinit"(ptr @test.x, i64 16) + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %y, ptr align 4 @.__const, i32 12, i1 false) + call void @llvm.memcpy.p0.p0.i32(ptr align 8 %coerce, ptr align 4 %y, i32 12, i1 false) + %lo = load i64, ptr %coerce, align 8 + %ptradd = getelementptr inbounds i8, ptr %coerce, i64 8 + %hi = load i32, ptr %ptradd, align 8 + call void @"std_collections_list$a3$int$.List.push"(ptr @test.x, i64 %lo, i32 %hi) #4 + %1 = load i64, ptr @test.x, align 8 + %lt = icmp ult i64 0, %1 + call void @llvm.assume(i1 %lt) + %2 = load ptr, ptr getelementptr inbounds (i8, ptr @test.x, i64 32), align 8 + store i32 4, ptr %2, align 4 + call void @llvm.memset.p0.i64(ptr align 16 %z, i8 0, i64 400, i1 false) + %3 = insertvalue %"char[20][]" undef, ptr %z, 0 + %4 = insertvalue %"char[20][]" %3, i64 10, 1 + store %"char[20][]" %4, ptr %foo, align 8 + %ptradd1 = getelementptr inbounds i8, ptr %foo, i64 16 + store i32 10, ptr %ptradd1, align 8 + %5 = call { ptr, i64 } @test.Map.get(ptr byval(%Map) align 8 %foo, i32 3) #4 + store { ptr, i64 } %5, ptr %result, align 8 + %6 = load ptr, ptr %result, align 8 + %ptradd2 = getelementptr inbounds i8, ptr %6, i64 4 + store i8 123, ptr %ptradd2, align 1 + ret void +} + diff --git a/test/test_suite7/overloading/set_overload.c3t b/test/test_suite7/overloading/set_overload.c3t new file mode 100644 index 000000000..8a6c8fae6 --- /dev/null +++ b/test/test_suite7/overloading/set_overload.c3t @@ -0,0 +1,24 @@ +// #target: macos-x64 + +module test; +import std::collections::map; + +def IntMap = HashMap(); + +fn void main() +{ + IntMap map; + map.set("Hello", 4); + map["Bye"] = 5; +} + +/* #expect: test.ll + +define void @test.main() #0 { +entry: + %map = alloca %HashMap, align 8 + call void @llvm.memset.p0.i64(ptr align 8 %map, i8 0, i64 48, i1 false) + %0 = call i8 @"std_collections_map$sa$char$int$.HashMap.set"(ptr %map, ptr @.str, i64 5, i32 4) + %1 = call i8 @"std_collections_map$sa$char$int$.HashMap.set"(ptr %map, ptr @.str.1, i64 3, i32 5) + ret void +} \ No newline at end of file diff --git a/test/test_suite7/pointers/array_pointer_decay.c3t b/test/test_suite7/pointers/array_pointer_decay.c3t new file mode 100644 index 000000000..79586d79f --- /dev/null +++ b/test/test_suite7/pointers/array_pointer_decay.c3t @@ -0,0 +1,77 @@ +// #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[3] 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], z[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 [3 x i32], align 4 + %z1 = alloca i32, align 4 + %xx = alloca ptr, align 8 + %yy = alloca ptr, align 8 + %zz = alloca ptr, align 8 + store i32 0, ptr %x, align 4 + %ptradd = getelementptr inbounds i8, ptr %x, i64 4 + store i32 0, ptr %ptradd, align 4 + %ptradd1 = getelementptr inbounds i8, ptr %x, i64 8 + store i32 0, ptr %ptradd1, align 4 + store ptr %x, ptr %y, align 8 + %0 = load ptr, ptr %y, align 8 + store ptr %0, ptr %z, align 8 + %1 = load ptr, ptr %y, align 8 + %2 = insertvalue %"int[]" undef, ptr %1, 0 + %3 = insertvalue %"int[]" %2, i64 3, 1 + store %"int[]" %3, ptr %sub, align 8 + %4 = load ptr, ptr %y, align 8 + %ptradd2 = getelementptr inbounds i8, ptr %4, i64 12 + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %y1, ptr align 4 %ptradd2, i32 12, i1 false) + %5 = load ptr, ptr %z, align 8 + %ptradd3 = getelementptr inbounds i8, ptr %5, i64 4 + %6 = load i32, ptr %ptradd3, align 4 + store i32 %6, ptr %z1, align 4 + %ptradd_any = getelementptr i8, ptr %x, i64 12 + store ptr %ptradd_any, ptr %xx, align 8 + %7 = load ptr, ptr %xx, align 8 + store ptr %7, ptr %yy, align 8 + %8 = load ptr, ptr %yy, align 8 + %ptradd_any4 = getelementptr i8, ptr %8, i64 -12 + store ptr %ptradd_any4, ptr %zz, align 8 + %9 = load ptr, ptr %y, align 8 + %ptradd5 = getelementptr inbounds i8, ptr %9, i64 4 + %10 = load ptr, ptr %y, align 8 + %11 = load ptr, ptr %z, align 8 + %12 = load ptr, ptr %zz, align 8 + %13 = load ptr, ptr %xx, align 8 + call void (ptr, ...) @printf(ptr @.str, ptr %10, ptr %11, ptr %12, ptr %ptradd5, ptr %13) + %ptradd6 = getelementptr inbounds i8, ptr %x, i64 4 + store i32 123, ptr %ptradd6, align 4 + %ptradd7 = getelementptr inbounds i8, ptr %x, i64 4 + %14 = load ptr, ptr %z, align 8 + %ptradd8 = getelementptr inbounds i8, ptr %14, i64 4 + %15 = load i32, ptr %ptradd7, align 4 + %16 = load i32, ptr %ptradd8, align 4 + call void (ptr, ...) @printf(ptr @.str.1, i32 %15, i32 %16) + ret void +} \ No newline at end of file diff --git a/test/test_suite7/pointers/const_pointer.c3t b/test/test_suite7/pointers/const_pointer.c3t new file mode 100644 index 000000000..c1ac447c1 --- /dev/null +++ b/test/test_suite7/pointers/const_pointer.c3t @@ -0,0 +1,16 @@ +// #target: macos-x64 + +module const_pointer; + +double foo @private = 17; +double bar @private = 12.0; +float xx @private = 12.0; + +void*[3] data @private = { &foo, &bar, &xx }; + +/* #expect: const_pointer.ll + +@const_pointer.foo = internal global double 1.700000e+01, align 8 +@const_pointer.bar = internal global double 1.200000e+01, align 8 +@const_pointer.xx = internal global float 1.200000e+01, align 4 +@const_pointer.data = internal 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_suite7/pointers/const_ref.c3t b/test/test_suite7/pointers/const_ref.c3t new file mode 100644 index 000000000..13d75b378 --- /dev/null +++ b/test/test_suite7/pointers/const_ref.c3t @@ -0,0 +1,25 @@ +// #target: macos-x64 +module test; +const int[?] X = (int[?]) { 1, 2, 3 }; +int[?] y = (int[?]) { 1, 2, 3 }; + +fn int main() +{ + var $z = { &y, "hello" }; + (*$z[0])[1] = 4; + assert(y[1] == 4); + return 0; +} +/* #expect: test.ll + +@test.X = local_unnamed_addr constant [3 x i32] [i32 1, i32 2, i32 3], align 4 +@test.y = global [3 x i32] [i32 1, i32 2, i32 3], align 4 + +define i32 @main() #0 { +entry: + store i32 4, ptr getelementptr inbounds (i8, ptr @test.y, i64 4), align 4 + %0 = load i32, ptr getelementptr inbounds (i8, ptr @test.y, i64 4), align 4 + %eq = icmp eq i32 %0, 4 + call void @llvm.assume(i1 %eq) + ret i32 0 +} diff --git a/test/test_suite7/pointers/pointer_index.c3t b/test/test_suite7/pointers/pointer_index.c3t new file mode 100644 index 000000000..994021dfc --- /dev/null +++ b/test/test_suite7/pointers/pointer_index.c3t @@ -0,0 +1,77 @@ +// #target: macos-x64 +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 + %1 = load i32, ptr %0, align 4 + store i32 %1, ptr %a, align 4 + %2 = load i32, ptr %0, align 4 + store i32 %2, ptr %b, align 4 + %ptradd = getelementptr inbounds i8, ptr %0, i64 4 + %3 = load i32, ptr %ptradd, align 4 + store i32 %3, ptr %c, align 4 + %ptradd1 = getelementptr inbounds i8, ptr %0, i64 -4 + %4 = load i32, ptr %ptradd1, align 4 + store i32 %4, ptr %d, align 4 + ret void +} + +; Function Attrs: +define void @pointer_index.test2(ptr %0) #0 { +entry: + %a = alloca i8, align 1 + %b = alloca i8, align 1 + %c = alloca i8, align 1 + %1 = load i8, ptr %0, align 1 + store i8 %1, ptr %a, align 1 + %2 = load i8, ptr %0, align 1 + store i8 %2, ptr %b, align 1 + %ptradd = getelementptr inbounds i8, ptr %0, i64 1 + %3 = load i8, ptr %ptradd, align 1 + store i8 %3, ptr %c, align 1 + ret void +} + +; Function Attrs: +define void @pointer_index.test3(ptr %0) #0 { +entry: + %a = alloca i64, align 8 + %b = alloca i64, align 8 + %c = alloca i64, align 8 + %1 = load i64, ptr %0, align 8 + store i64 %1, ptr %a, align 8 + %2 = load i64, ptr %0, align 8 + store i64 %2, ptr %b, align 8 + %ptradd = getelementptr inbounds i8, ptr %0, i64 8 + %3 = load i64, ptr %ptradd, align 8 + store i64 %3, ptr %c, align 8 + ret void +} diff --git a/test/test_suite7/pointers/subarray_variant_to_ptr.c3t b/test/test_suite7/pointers/subarray_variant_to_ptr.c3t new file mode 100644 index 000000000..cc9f4d29f --- /dev/null +++ b/test/test_suite7/pointers/subarray_variant_to_ptr.c3t @@ -0,0 +1,86 @@ +// #target: macos-x64 +module foo; + +extern fn void printf(char*, ...); + +fn void test1(any 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 + +%any = type { ptr, i64 } +%"int[]" = type { ptr, i64 } + +@"$ct.int" = linkonce global %.introspect { i8 2, i64 0, ptr null, i64 4, i64 0, i64 0, [0 x i64] zeroinitializer }, align 8 + +define void @foo.test1(i64 %0, ptr %1) #0 { +entry: + %z = alloca %any, align 8 + %w = alloca ptr, align 8 + store i64 %0, ptr %z, align 8 + %ptradd = getelementptr inbounds i8, ptr %z, i64 8 + store ptr %1, ptr %ptradd, align 8 + %2 = load ptr, ptr %z, align 8 + store ptr %2, ptr %w, align 8 + %3 = load ptr, ptr %w, align 8 + %4 = load i32, ptr %3, align 4 + call void (ptr, ...) @printf(ptr @.str, i32 %4) + ret void +} + +; Function Attrs: +define void @foo.test2(ptr %0, i64 %1) #0 { +entry: + %z = alloca %"int[]", align 8 + %w = alloca ptr, align 8 + store ptr %0, ptr %z, align 8 + %ptradd = getelementptr inbounds i8, ptr %z, i64 8 + store i64 %1, ptr %ptradd, align 8 + %2 = load ptr, ptr %z, align 8 + store ptr %2, ptr %w, align 8 + %3 = load ptr, ptr %w, align 8 + %4 = load i32, ptr %3, align 4 + call void (ptr, ...) @printf(ptr @.str.1, i32 %4) + ret void +} + +; Function Attrs: +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 %any, 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 %any undef, ptr %x, 0 + %1 = insertvalue %any %0, i64 ptrtoint (ptr @"$ct.int" to i64), 1 + store %any %1, ptr %taddr, align 8 + %lo = load i64, ptr %taddr, align 8 + %ptradd = getelementptr inbounds i8, ptr %taddr, i64 8 + %hi = load ptr, ptr %ptradd, align 8 + call void @foo.test1(i64 %lo, ptr %hi) + %2 = insertvalue %"int[]" undef, ptr %w, 0 + %3 = insertvalue %"int[]" %2, i64 2, 1 + call void @foo.test2(ptr %w, i64 2) + ret void +} \ No newline at end of file diff --git a/test/test_suite7/precedence/required_parens.c3 b/test/test_suite7/precedence/required_parens.c3 new file mode 100644 index 000000000..176469480 --- /dev/null +++ b/test/test_suite7/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_suite7/regression/crash_on_right_paren_macro.c3 b/test/test_suite7/regression/crash_on_right_paren_macro.c3 new file mode 100644 index 000000000..9605bf231 --- /dev/null +++ b/test/test_suite7/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_suite7/safe/deref.c3t b/test/test_suite7/safe/deref.c3t new file mode 100644 index 000000000..b97045d65 --- /dev/null +++ b/test/test_suite7/safe/deref.c3t @@ -0,0 +1,60 @@ +// #safe: yes +// #target: macos-x64 +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 + %taddr = alloca i64, align 8 + %taddr2 = alloca i64, align 8 + %varargslots = alloca [2 x %any], align 16 + %indirectarg = alloca %"any[]", align 8 + store ptr null, ptr %x, align 8 + %0 = load ptr, ptr %x, align 8 + %checknull = icmp eq ptr %0, null + %1 = call i1 @llvm.expect.i1(i1 %checknull, i1 false) + br i1 %1, label %panic, label %checkok + +checkok: ; preds = %entry + %2 = ptrtoint ptr %0 to i64 + %3 = urem i64 %2, 4 + %4 = icmp ne i64 %3, 0 + %5 = call i1 @llvm.expect.i1(i1 %4, i1 false) + br i1 %5, label %panic1, label %checkok3 + +checkok3: ; preds = %checkok + %6 = load i32, ptr %0, align 4 + store i32 %6, ptr %y, align 4 + ret void + +panic: ; preds = %entry + %7 = load ptr, ptr @std.core.builtin.panic, align 8 + call void %7(ptr @.panic_msg, i64 42, ptr @.file, i64 8, ptr @.func, i64 4, i32 6) #2 + unreachable + +panic1: ; preds = %checkok + store i64 4, ptr %taddr, align 8 + %8 = insertvalue %any undef, ptr %taddr, 0 + %9 = insertvalue %any %8, i64 ptrtoint (ptr @"$ct.ulong" to i64), 1 + store i64 %3, ptr %taddr2, align 8 + %10 = insertvalue %any undef, ptr %taddr2, 0 + %11 = insertvalue %any %10, i64 ptrtoint (ptr @"$ct.ulong" to i64), 1 + store %any %9, ptr %varargslots, align 16 + %ptradd = getelementptr inbounds i8, ptr %varargslots, i64 16 + store %any %11, ptr %ptradd, align 16 + %12 = insertvalue %"any[]" undef, ptr %varargslots, 0 + %"$$temp" = insertvalue %"any[]" %12, i64 2, 1 + store %"any[]" %"$$temp", ptr %indirectarg, align 8 + call void @std.core.builtin.panicf(ptr @.panic_msg.1, i64 94, ptr @.file, i64 8, ptr @.func, i64 4, i32 6, ptr byval(%"any[]") align 8 %indirectarg) #2 + unreachable +} + diff --git a/test/test_suite7/safe/detect_invalid_deref_return.c3 b/test/test_suite7/safe/detect_invalid_deref_return.c3 new file mode 100644 index 000000000..f46ae7540 --- /dev/null +++ b/test/test_suite7/safe/detect_invalid_deref_return.c3 @@ -0,0 +1,40 @@ +fn int[] test1() +{ + int[3] x; + return &x; // #error: local variable will be invalid +} + +fn int* test2() +{ + int[3] x; + return &x[0]; // #error: local variable will be invalid +} + +struct Abc +{ + int a; + int[3] b; +} + +fn int* test3() +{ + Abc x; + return &x.a; // #error: local variable will be invalid +} + +fn int* test4() +{ + Abc x; + return &x.b; // #error: local variable will be invalid +} + +fn int* test5() +{ + Abc x; + return &x.b[0]; // #error: local variable will be invalid +} + +fn int* test6() +{ + return &&1; // #error: temporary value will +} diff --git a/test/test_suite7/slices/array_to_const_err.c3 b/test/test_suite7/slices/array_to_const_err.c3 new file mode 100644 index 000000000..b02186039 --- /dev/null +++ b/test/test_suite7/slices/array_to_const_err.c3 @@ -0,0 +1,8 @@ +module test; +import std; + +fn void main() +{ + char[?] z = { 1, 2 }; + char[] y = z; // #error: Conversions from arrays or vectors +} diff --git a/test/test_suite7/slices/array_to_const_slice.c3t b/test/test_suite7/slices/array_to_const_slice.c3t new file mode 100644 index 000000000..a10fd0699 --- /dev/null +++ b/test/test_suite7/slices/array_to_const_slice.c3t @@ -0,0 +1,19 @@ +// #target: macos-x64 +module test; +import std; + +fn void main() +{ + char[3] $x = { 1, 2, 5 }; + char[] y = $x; + String $a = "hello"; + char[2] $b = { 'a', 'b' }; + var $c = $a +++ $b; + String y2 = $c; + char[] $bytes = x'0103ff'; + var $d = $bytes +++ $b; + char[] z = $d; +} +/* expect: test.ll + +feofke \ No newline at end of file diff --git a/test/test_suite7/slices/slice_assign.c3t b/test/test_suite7/slices/slice_assign.c3t new file mode 100644 index 000000000..22346fbea --- /dev/null +++ b/test/test_suite7/slices/slice_assign.c3t @@ -0,0 +1,83 @@ +// #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: +declare void @printf(ptr, ...) #0 + +; Function Attrs: +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) + store i32 3, ptr %x, align 4 + %ptradd = getelementptr inbounds i8, ptr %x, i64 4 + store i32 3, ptr %ptradd, align 4 + %ptradd1 = getelementptr inbounds i8, ptr %x, i64 4 + store i32 5, ptr %ptradd1, align 4 + %ptradd2 = getelementptr inbounds i8, ptr %x, i64 8 + store i32 5, ptr %ptradd2, align 4 + %ptradd3 = getelementptr inbounds i8, ptr %x, i64 20 + store i32 52, ptr %ptradd3, align 4 + %ptradd4 = getelementptr inbounds i8, ptr %x, i64 24 + store i32 52, ptr %ptradd4, align 4 + %ptradd5 = getelementptr inbounds i8, ptr %x, i64 28 + store i32 52, ptr %ptradd5, align 4 + 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 8, %0 + br i1 %gt, label %loop.body, label %loop.exit +loop.body: ; preds = %loop.cond + %1 = load i64, ptr %.anon, align 8 + %ptroffset = getelementptr inbounds [4 x i8], ptr %x, i64 %1 + %2 = load i32, ptr %ptroffset, align 4 + store i32 %2, ptr %i, align 4 + %3 = load i32, ptr %i, align 4 + call void (ptr, ...) @printf(ptr @.str, i32 %3) + %4 = load i64, ptr %.anon, align 8 + %addnuw = add nuw i64 %4, 1 + store i64 %addnuw, ptr %.anon, align 8 + br label %loop.cond +loop.exit: ; preds = %loop.cond + br label %cond +cond: ; preds = %assign, %loop.exit + %5 = phi i64 [ 0, %loop.exit ], [ %add, %assign ] + %lt = icmp slt i64 %5, 8 + br i1 %lt, label %assign, label %exit +assign: ; preds = %cond + %ptroffset6 = getelementptr inbounds [4 x i8], ptr %x, i64 %5 + store i32 123, ptr %ptroffset6, align 4 + %add = add i64 %5, 1 + br label %cond +exit: ; preds = %cond + ret void +} + +; Function Attrs: +define i32 @main(i32 %0, ptr %1) #0 { +entry: + call void @test.main() + ret i32 0 +} diff --git a/test/test_suite7/slices/slice_assign2.c3t b/test/test_suite7/slices/slice_assign2.c3t new file mode 100644 index 000000000..7d5b96b9c --- /dev/null +++ b/test/test_suite7/slices/slice_assign2.c3t @@ -0,0 +1,48 @@ +// #target: macos-x64 +module test; + +struct Foo +{ + double x; + double z; + int h; +} +struct Bar +{ + double z; + int h; +} + +fn void main() +{ + Foo[3] x = { { 1.3, 2.4, 12 }, { 4.3, 5.6, 13 }, { 0, 0, 0 }}; + x[..] = x[1]; + Bar[3] y = { { 1.3, 12 }, { 4.3, 13 }, { 0, 0 }}; + y[..] = y[1]; +} + +/* #expect: test.ll + +define void @test.main() #0 { +entry: + %x = alloca [3 x %Foo], align 16 + %tempval = alloca %Foo, align 8 + %y = alloca [3 x %Bar], align 16 + call void @llvm.memcpy.p0.p0.i32(ptr align 16 %x, ptr align 16 @.__const, i32 72, i1 false) + %ptradd = getelementptr inbounds i8, ptr %x, i64 24 + call void @llvm.memcpy.p0.p0.i32(ptr align 8 %tempval, ptr align 8 %ptradd, i32 24, i1 false) + call void @llvm.memcpy.p0.p0.i32(ptr align 8 %x, ptr align 8 %tempval, i32 24, i1 false) + %ptradd1 = getelementptr inbounds i8, ptr %x, i64 24 + call void @llvm.memcpy.p0.p0.i32(ptr align 8 %ptradd1, ptr align 8 %tempval, i32 24, i1 false) + %ptradd2 = getelementptr inbounds i8, ptr %x, i64 48 + call void @llvm.memcpy.p0.p0.i32(ptr align 8 %ptradd2, ptr align 8 %tempval, i32 24, i1 false) + call void @llvm.memcpy.p0.p0.i32(ptr align 16 %y, ptr align 16 @.__const.1, i32 48, i1 false) + %ptradd3 = getelementptr inbounds i8, ptr %y, i64 16 + %0 = load %Bar, ptr %ptradd3, align 16 + store %Bar %0, ptr %y, align 8 + %ptradd4 = getelementptr inbounds i8, ptr %y, i64 16 + store %Bar %0, ptr %ptradd4, align 8 + %ptradd5 = getelementptr inbounds i8, ptr %y, i64 32 + store %Bar %0, ptr %ptradd5, align 8 + ret void +} diff --git a/test/test_suite7/slices/slice_checks.c3t b/test/test_suite7/slices/slice_checks.c3t new file mode 100644 index 000000000..3380831eb --- /dev/null +++ b/test/test_suite7/slices/slice_checks.c3t @@ -0,0 +1,128 @@ +// #target: macos-x64 +// #safe: yes + +module mymodule; + +fn void main() +{ + int[4] array; + int[] slice = &array; + + int[] slice1 = slice[2..5]; + int[] slice2 = slice[6..]; + int[] slice3 = slice[0..9]; + int[] slice4 = slice[5:10]; + int[] slice5 = slice[1..3]; + int[] slice6 = slice[2:10]; +} + +/* #expect: mymodule.ll + + store i32 0, ptr %array, align 4 + %ptradd = getelementptr inbounds i8, ptr %array, i64 4 + store i32 0, ptr %ptradd, align 4 + %ptradd1 = getelementptr inbounds i8, ptr %array, i64 8 + store i32 0, ptr %ptradd1, align 4 + %ptradd2 = getelementptr inbounds i8, ptr %array, i64 12 + store i32 0, ptr %ptradd2, align 4 + %0 = insertvalue %"int[]" undef, ptr %array, 0 + %1 = insertvalue %"int[]" %0, i64 4, 1 + store %"int[]" %1, ptr %slice, align 8 + %2 = load %"int[]", ptr %slice, align 8 + %3 = extractvalue %"int[]" %2, 0 + %4 = extractvalue %"int[]" %2, 1 + %gt = icmp sgt i64 2, %4 + %5 = call i1 @llvm.expect.i1(i1 %gt, i1 false) + br i1 %5, label %panic, label %checkok + +checkok: ; preds = %entry + %lt = icmp slt i64 %4, 6 + %6 = call i1 @llvm.expect.i1(i1 %lt, i1 false) + br i1 %6, label %panic5, label %checkok12 + +checkok12: ; preds = %checkok + %ptradd13 = getelementptr inbounds i8, ptr %3, i64 8 + %7 = insertvalue %"int[]" undef, ptr %ptradd13, 0 + %8 = insertvalue %"int[]" %7, i64 4, 1 + store %"int[]" %8, ptr %slice1, align 8 + %9 = load %"int[]", ptr %slice, align 8 + %10 = extractvalue %"int[]" %9, 0 + %11 = extractvalue %"int[]" %9, 1 + %gt14 = icmp sgt i64 6, %11 + %12 = call i1 @llvm.expect.i1(i1 %gt14, i1 false) + br i1 %12, label %panic15, label %checkok22 + +checkok22: ; preds = %checkok12 + %size = sub i64 %11, 6 + %ptradd23 = getelementptr inbounds i8, ptr %10, i64 24 + %13 = insertvalue %"int[]" undef, ptr %ptradd23, 0 + %14 = insertvalue %"int[]" %13, i64 %size, 1 + store %"int[]" %14, ptr %slice2, align 8 + %15 = load %"int[]", ptr %slice, align 8 + %16 = extractvalue %"int[]" %15, 0 + %17 = extractvalue %"int[]" %15, 1 + %gt24 = icmp sgt i64 0, %17 + %18 = call i1 @llvm.expect.i1(i1 %gt24, i1 false) + br i1 %18, label %panic25, label %checkok32 + +checkok32: ; preds = %checkok22 + %lt33 = icmp slt i64 %17, 10 + %19 = call i1 @llvm.expect.i1(i1 %lt33, i1 false) + br i1 %19, label %panic34, label %checkok41 + +checkok41: ; preds = %checkok32 + %20 = insertvalue %"int[]" undef, ptr %16, 0 + %21 = insertvalue %"int[]" %20, i64 10, 1 + store %"int[]" %21, ptr %slice3, align 8 + %22 = load %"int[]", ptr %slice, align 8 + %23 = extractvalue %"int[]" %22, 0 + %24 = extractvalue %"int[]" %22, 1 + %gt42 = icmp sgt i64 5, %24 + %25 = call i1 @llvm.expect.i1(i1 %gt42, i1 false) + br i1 %25, label %panic43, label %checkok50 + +checkok50: ; preds = %checkok41 + %lt51 = icmp slt i64 %24, 15 + %26 = call i1 @llvm.expect.i1(i1 %lt51, i1 false) + br i1 %26, label %panic52, label %checkok59 + +checkok59: ; preds = %checkok50 + %ptradd60 = getelementptr inbounds i8, ptr %23, i64 20 + %27 = insertvalue %"int[]" undef, ptr %ptradd60, 0 + %28 = insertvalue %"int[]" %27, i64 10, 1 + store %"int[]" %28, ptr %slice4, align 8 + %29 = load %"int[]", ptr %slice, align 8 + %30 = extractvalue %"int[]" %29, 0 + %31 = extractvalue %"int[]" %29, 1 + %gt61 = icmp sgt i64 1, %31 + %32 = call i1 @llvm.expect.i1(i1 %gt61, i1 false) + br i1 %32, label %panic62, label %checkok69 + +checkok69: ; preds = %checkok59 + %lt70 = icmp slt i64 %31, 4 + %33 = call i1 @llvm.expect.i1(i1 %lt70, i1 false) + br i1 %33, label %panic71, label %checkok78 + +checkok78: ; preds = %checkok69 + %ptradd79 = getelementptr inbounds i8, ptr %30, i64 4 + %34 = insertvalue %"int[]" undef, ptr %ptradd79, 0 + %35 = insertvalue %"int[]" %34, i64 3, 1 + store %"int[]" %35, ptr %slice5, align 8 + %36 = load %"int[]", ptr %slice, align 8 + %37 = extractvalue %"int[]" %36, 0 + %38 = extractvalue %"int[]" %36, 1 + %gt80 = icmp sgt i64 2, %38 + %39 = call i1 @llvm.expect.i1(i1 %gt80, i1 false) + br i1 %39, label %panic81, label %checkok88 + +checkok88: ; preds = %checkok78 + %lt89 = icmp slt i64 %38, 12 + %40 = call i1 @llvm.expect.i1(i1 %lt89, i1 false) + br i1 %40, label %panic90, label %checkok97 + +checkok97: ; preds = %checkok88 + %ptradd98 = getelementptr inbounds i8, ptr %37, i64 8 + %41 = insertvalue %"int[]" undef, ptr %ptradd98, 0 + %42 = insertvalue %"int[]" %41, i64 10, 1 + store %"int[]" %42, ptr %slice6, align 8 + ret void diff --git a/test/test_suite7/slices/slice_comparison.c3t b/test/test_suite7/slices/slice_comparison.c3t new file mode 100644 index 000000000..8fce3e616 --- /dev/null +++ b/test/test_suite7/slices/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 %slice_cmp_values, label %slice_cmp_exit + +slice_cmp_values: ; preds = %entry + store i64 0, ptr %cmp.idx, align 8 + br label %slice_loop_start + +slice_loop_start: ; preds = %slice_loop_comparison, %slice_cmp_values + %3 = load i64, ptr %cmp.idx, align 8 + %lt = icmp slt i64 %3, %1 + br i1 %lt, label %slice_loop_comparison, label %slice_cmp_exit + +slice_loop_comparison: ; preds = %slice_loop_start + %ptradd = getelementptr inbounds i8, ptr %2, i64 %3 + %ptradd1 = getelementptr inbounds i8, ptr @.str.2, i64 %3 + %4 = load i8, ptr %ptradd, align 1 + %5 = load i8, ptr %ptradd1, 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 %slice_loop_start, label %slice_cmp_exit + +slice_cmp_exit: ; preds = %slice_loop_comparison, %slice_loop_start, %entry + %slice_cmp_phi = phi i1 [ true, %slice_loop_start ], [ false, %entry ], [ false, %slice_loop_comparison ] + br i1 %slice_cmp_phi, label %if.then, label %if.exit + +if.then: ; preds = %slice_cmp_exit + call void (ptr, ...) @printf(ptr @.str.3) + br label %if.exit + +if.exit: ; preds = %if.then, %slice_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 %slice_cmp_values4, label %slice_cmp_exit12 + +slice_cmp_values4: ; preds = %if.exit + store i64 0, ptr %cmp.idx5, align 8 + br label %slice_loop_start6 + +slice_loop_start6: ; preds = %slice_loop_comparison8, %slice_cmp_values4 + %13 = load i64, ptr %cmp.idx5, align 8 + %lt7 = icmp slt i64 %13, %9 + br i1 %lt7, label %slice_loop_comparison8, label %slice_cmp_exit12 + +slice_loop_comparison8: ; preds = %slice_loop_start6 + %ptradd9 = getelementptr inbounds i8, ptr %11, i64 %13 + %ptradd10 = getelementptr inbounds i8, ptr %12, i64 %13 + %14 = load i8, ptr %ptradd9, align 1 + %15 = load i8, ptr %ptradd10, 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 %slice_loop_start6, label %slice_cmp_exit12 + +slice_cmp_exit12: ; preds = %slice_loop_comparison8, %slice_loop_start6, %if.exit + %slice_cmp_phi13 = phi i1 [ true, %slice_loop_start6 ], [ false, %if.exit ], [ false, %slice_loop_comparison8 ] + br i1 %slice_cmp_phi13, label %if.then14, label %if.exit15 + +if.then14: ; preds = %slice_cmp_exit12 + call void (ptr, ...) @printf(ptr @.str.4) + br label %if.exit15 + +if.exit15: ; preds = %if.then14, %slice_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 %slice_cmp_values17, label %slice_cmp_exit25 + +slice_cmp_values17: ; preds = %switch.entry + store i64 0, ptr %cmp.idx18, align 8 + br label %slice_loop_start19 + +slice_loop_start19: ; preds = %slice_loop_comparison21, %slice_cmp_values17 + %20 = load i64, ptr %cmp.idx18, align 8 + %lt20 = icmp slt i64 %20, 4 + br i1 %lt20, label %slice_loop_comparison21, label %slice_cmp_exit25 + +slice_loop_comparison21: ; preds = %slice_loop_start19 + %ptradd22 = getelementptr inbounds i8, ptr @.str.5, i64 %20 + %ptradd23 = getelementptr inbounds i8, ptr %19, i64 %20 + %21 = load i8, ptr %ptradd22, align 1 + %22 = load i8, ptr %ptradd23, 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 %slice_loop_start19, label %slice_cmp_exit25 + +slice_cmp_exit25: ; preds = %slice_loop_comparison21, %slice_loop_start19, %switch.entry + %slice_cmp_phi26 = phi i1 [ true, %slice_loop_start19 ], [ false, %switch.entry ], [ false, %slice_loop_comparison21 ] + br i1 %slice_cmp_phi26, label %switch.case, label %next_if + +switch.case: ; preds = %slice_cmp_exit25 + call void (ptr, ...) @printf(ptr @.str.6) + br label %switch.exit + +next_if: ; preds = %slice_cmp_exit25 + %24 = extractvalue %"char[]" %17, 1 + %25 = extractvalue %"char[]" %17, 0 + %eq27 = icmp eq i64 5, %24 + br i1 %eq27, label %slice_cmp_values28, label %slice_cmp_exit36 + +slice_cmp_values28: ; preds = %next_if + store i64 0, ptr %cmp.idx29, align 8 + br label %slice_loop_start30 + +slice_loop_start30: ; preds = %slice_loop_comparison32, %slice_cmp_values28 + %26 = load i64, ptr %cmp.idx29, align 8 + %lt31 = icmp slt i64 %26, 5 + br i1 %lt31, label %slice_loop_comparison32, label %slice_cmp_exit36 + +slice_loop_comparison32: ; preds = %slice_loop_start30 + %ptradd33 = getelementptr inbounds i8, ptr @.str.7, i64 %26 + %ptradd34 = getelementptr inbounds i8, ptr %25, i64 %26 + %27 = load i8, ptr %ptradd33, align 1 + %28 = load i8, ptr %ptradd34, 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 %slice_loop_start30, label %slice_cmp_exit36 + +slice_cmp_exit36: ; preds = %slice_loop_comparison32, %slice_loop_start30, %next_if + %slice_cmp_phi37 = phi i1 [ true, %slice_loop_start30 ], [ false, %next_if ], [ false, %slice_loop_comparison32 ] + br i1 %slice_cmp_phi37, label %switch.case38, label %next_if39 + +switch.case38: ; preds = %slice_cmp_exit36 + call void (ptr, ...) @printf(ptr @.str.8) + br label %switch.exit + +next_if39: ; preds = %slice_cmp_exit36 + %30 = extractvalue %"char[]" %17, 1 + %31 = extractvalue %"char[]" %17, 0 + %eq40 = icmp eq i64 4, %30 + br i1 %eq40, label %slice_cmp_values41, label %slice_cmp_exit49 + +slice_cmp_values41: ; preds = %next_if39 + store i64 0, ptr %cmp.idx42, align 8 + br label %slice_loop_start43 + +slice_loop_start43: ; preds = %slice_loop_comparison45, %slice_cmp_values41 + %32 = load i64, ptr %cmp.idx42, align 8 + %lt44 = icmp slt i64 %32, 4 + br i1 %lt44, label %slice_loop_comparison45, label %slice_cmp_exit49 + +slice_loop_comparison45: ; preds = %slice_loop_start43 + %ptradd46 = getelementptr inbounds i8, ptr @.str.9, i64 %32 + %ptradd47 = getelementptr inbounds i8, ptr %31, i64 %32 + %33 = load i8, ptr %ptradd46, align 1 + %34 = load i8, ptr %ptradd47, 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 %slice_loop_start43, label %slice_cmp_exit49 + +slice_cmp_exit49: ; preds = %slice_loop_comparison45, %slice_loop_start43, %next_if39 + %slice_cmp_phi50 = phi i1 [ true, %slice_loop_start43 ], [ false, %next_if39 ], [ false, %slice_loop_comparison45 ] + br i1 %slice_cmp_phi50, label %switch.case51, label %next_if52 + +switch.case51: ; preds = %slice_cmp_exit49 + call void (ptr, ...) @printf(ptr @.str.10) + br label %switch.exit + +next_if52: ; preds = %slice_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_suite7/slices/slice_conv_byte.c3t b/test/test_suite7/slices/slice_conv_byte.c3t new file mode 100644 index 000000000..9bba5c8b9 --- /dev/null +++ b/test/test_suite7/slices/slice_conv_byte.c3t @@ -0,0 +1,51 @@ +// #target: macos-x64 +module test; + +fn int main() +{ + char[] x = x'00aabbcc'; + bool text = x == x'00aabbcc'; + char[] $x = x'00aabbcc'; + bool $y = $x == x'00aabbcc'; + return (int)$y; +} + +/* #expect: test.ll + +define i32 @main() #0 { +entry: + %x = alloca %"char[]", align 8 + %text = alloca i8, align 1 + %cmp.idx = alloca i64, align 8 + store %"char[]" { ptr @.bytes, i64 4 }, ptr %x, align 8 + %0 = load %"char[]", ptr %x, align 8 + %1 = extractvalue %"char[]" %0, 1 + %2 = extractvalue %"char[]" %0, 0 + %eq = icmp eq i64 %1, 4 + br i1 %eq, label %slice_cmp_values, label %slice_cmp_exit + +slice_cmp_values: ; preds = %entry + store i64 0, ptr %cmp.idx, align 8 + br label %slice_loop_start + +slice_loop_start: ; preds = %slice_loop_comparison, %slice_cmp_values + %3 = load i64, ptr %cmp.idx, align 8 + %lt = icmp slt i64 %3, %1 + br i1 %lt, label %slice_loop_comparison, label %slice_cmp_exit + +slice_loop_comparison: ; preds = %slice_loop_start + %ptradd = getelementptr inbounds i8, ptr %2, i64 %3 + %ptradd1 = getelementptr inbounds i8, ptr @.bytes.1, i64 %3 + %4 = load i8, ptr %ptradd, align 1 + %5 = load i8, ptr %ptradd1, 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 %slice_loop_start, label %slice_cmp_exit + +slice_cmp_exit: ; preds = %slice_loop_comparison, %slice_loop_start, %entry + %slice_cmp_phi = phi i1 [ true, %slice_loop_start ], [ false, %entry ], [ false, %slice_loop_comparison ] + %7 = zext i1 %slice_cmp_phi to i8 + store i8 %7, ptr %text, align 1 + ret i32 1 +} \ No newline at end of file diff --git a/test/test_suite7/slices/slice_init.c3t b/test/test_suite7/slices/slice_init.c3t new file mode 100644 index 000000000..3a56d4d68 --- /dev/null +++ b/test/test_suite7/slices/slice_init.c3t @@ -0,0 +1,37 @@ +// #target: macos-x64 +module foo; +fn float[20] get() +{ + float[20] y; + for (int i = 0; i < 20; i++) y[i] = (float)i * i + 1; + return y; +} +fn void main() +{ + float[<4>] x = get()[1..^16]; + float[4] y = get()[2..^15]; +} + +/* #expect: foo.ll + +define void @foo.main() #0 { +entry: + %x = alloca <4 x float>, align 16 + %sretparam = alloca [20 x float], align 4 + %y = alloca [4 x float], align 16 + %sretparam1 = alloca [20 x float], align 4 + call void @foo.get(ptr sret([20 x float]) align 4 %sretparam) + %ptradd = getelementptr inbounds i8, ptr %sretparam, i64 4 + %0 = insertvalue %"float[]" undef, ptr %ptradd, 0 + %1 = insertvalue %"float[]" %0, i64 4, 1 + %2 = extractvalue %"float[]" %1, 0 + %3 = load <4 x float>, ptr %2, align 4 + store <4 x float> %3, ptr %x, align 16 + call void @foo.get(ptr sret([20 x float]) align 4 %sretparam1) + %ptradd2 = getelementptr inbounds i8, ptr %sretparam1, i64 8 + %4 = insertvalue %"float[]" undef, ptr %ptradd2, 0 + %5 = insertvalue %"float[]" %4, i64 4, 1 + %6 = extractvalue %"float[]" %5, 0 + call void @llvm.memcpy.p0.p0.i32(ptr align 16 %y, ptr align 4 %6, i32 16, i1 false) + ret void +} diff --git a/test/test_suite7/slices/slice_inline.c3t b/test/test_suite7/slices/slice_inline.c3t new file mode 100644 index 000000000..8a4ca0027 --- /dev/null +++ b/test/test_suite7/slices/slice_inline.c3t @@ -0,0 +1,34 @@ +// #target: macos-x64 +module foo; +struct Data{ + inline char[32] data; +} +fn void Data.not_working(self) { + self[:self.data.len]; +} + +fn void Data.working(self) { + self.data[:self.data.len]; +} +fn void main(String[] args) { + Data d; + d.not_working(); + d.working(); +} + +/* #expect: foo.ll + +define void @foo.Data.not_working(ptr byval(%Data) align 8 %0) #0 { +entry: + %1 = insertvalue %"char[]" undef, ptr %0, 0 + %2 = insertvalue %"char[]" %1, i64 32, 1 + ret void +} +; Function Attrs: nounwind uwtable +define void @foo.Data.working(ptr byval(%Data) align 8 %0) #0 { +entry: + %1 = insertvalue %"char[]" undef, ptr %0, 0 + %2 = insertvalue %"char[]" %1, i64 32, 1 + ret void +} + diff --git a/test/test_suite7/slices/slice_len_error.c3 b/test/test_suite7/slices/slice_len_error.c3 new file mode 100644 index 000000000..a40a88097 --- /dev/null +++ b/test/test_suite7/slices/slice_len_error.c3 @@ -0,0 +1,21 @@ +int[8][8] a; +fn void main() +{ + a[2..3]; + a[2:1]; + a[..3]; + a[2..]; + a[..]; + a[2:1]; + a[:4]; +} + +fn void test1() +{ + a[:]; // #error: not elide +} + +fn void test2() +{ + a[2:]; // #error: not elide +} \ No newline at end of file diff --git a/test/test_suite7/slices/slice_negative_len.c3 b/test/test_suite7/slices/slice_negative_len.c3 new file mode 100644 index 000000000..30073685a --- /dev/null +++ b/test/test_suite7/slices/slice_negative_len.c3 @@ -0,0 +1,87 @@ +fn void test() +{ + int[3] x = { 1, 2, 3}; + int[] z = x[2..2]; + z = x[2..1]; // #error: greater than the end index +} + +fn void test2() +{ + int[3] x = { 1, 2, 3}; + int[] z = x[^2..^2]; + z = x[^3..]; + z = x[^1..^2]; // #error: greater than the end index +} + +fn void test3() +{ + int[3] x = { 1, 2, 3 }; + int[] z = x[..4]; // #error: End index out of bounds, was 4, exceeding +} + +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: An index may only be negative +} + +fn void test6() +{ + int[3] x = { 1, 2, 3 }; + int[] z = x[3..]; // #error: Index out of bounds: the start index was +} + +fn void test7() +{ + int[3] x = { 1, 2, 3 }; + int[] z = x[-1..]; // #error: An index may only be negative +} + +fn void test8() +{ + int[3] x = { 1, 2, 3 }; + int[] z = x[^4..]; // #error: An index may only be negative +} + +fn void test9() +{ + int[3] x = { 1, 2, 3 }; + int[] z = x[^0..]; // #error: Index out of bounds: the start +} + +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 +} + +struct Abc +{ + int a; + char[?] z; +} + +fn void test105() +{ + Abc a; + int[] w = a.z[0..]; // #error: Omitting end index is not allowed for pointers + int[] z = a.z[^2..]; // #error: Indexing from the end is not allowed for pointers + int[] y = a.z[..^2]; // #error: Indexing from the end is not allowed for pointers + a.z[-10..-3]; // #error: An index may only be negative for pointers +} + +fn void test11() +{ + int[3] x = { 1, 2, 3 }; + int[] z = x[..^0]; // #error: End index out of bounds, was 3, exceeding +} diff --git a/test/test_suite7/slices/slice_offset.c3t b/test/test_suite7/slices/slice_offset.c3t new file mode 100644 index 000000000..7bb061d9e --- /dev/null +++ b/test/test_suite7/slices/slice_offset.c3t @@ -0,0 +1,20 @@ +// #target: macos-x64 +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) + %ptradd = getelementptr inbounds i8, ptr %x, i64 4 + %0 = insertvalue %"int[]" undef, ptr %ptradd, 0 + %1 = insertvalue %"int[]" %0, i64 2, 1 + store %"int[]" %1, ptr %y, align 8 + ret void +} diff --git a/test/test_suite7/slices/slice_offset_neg_end.c3t b/test/test_suite7/slices/slice_offset_neg_end.c3t new file mode 100644 index 000000000..bb3333398 --- /dev/null +++ b/test/test_suite7/slices/slice_offset_neg_end.c3t @@ -0,0 +1,20 @@ +// #target: macos-x64 +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) + %ptradd = getelementptr inbounds i8, ptr %x, i64 4 + %0 = insertvalue %"int[]" undef, ptr %ptradd, 0 + %1 = insertvalue %"int[]" %0, i64 2, 1 + store %"int[]" %1, ptr %y, align 8 + ret void +} diff --git a/test/test_suite7/slices/slice_offset_neg_start.c3t b/test/test_suite7/slices/slice_offset_neg_start.c3t new file mode 100644 index 000000000..18b1faea2 --- /dev/null +++ b/test/test_suite7/slices/slice_offset_neg_start.c3t @@ -0,0 +1,20 @@ +// #target: macos-x64 +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) + %ptradd = getelementptr inbounds i8, ptr %x, i64 4 + %0 = insertvalue %"int[]" undef, ptr %ptradd, 0 + %1 = insertvalue %"int[]" %0, i64 1, 1 + store %"int[]" %1, ptr %y, align 8 + ret void +} diff --git a/test/test_suite7/slices/slice_optional.c3t b/test/test_suite7/slices/slice_optional.c3t new file mode 100644 index 000000000..bc6545de6 --- /dev/null +++ b/test/test_suite7/slices/slice_optional.c3t @@ -0,0 +1,41 @@ +// #target: macos-x64 +module test; +fn void main() { + int[]! a = {1, 2}; + int! b = a[0]; +} + +/* #expect: test.ll + +define void @test.main() #0 { +entry: + %a = alloca %"int[]", align 8 + %a.f = alloca i64, align 8 + %literal = alloca [2 x i32], align 4 + %b = alloca i32, align 4 + %b.f = alloca i64, align 8 + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %literal, ptr align 4 @.__const, i32 8, i1 false) + %0 = insertvalue %"int[]" undef, ptr %literal, 0 + %1 = insertvalue %"int[]" %0, i64 2, 1 + store %"int[]" %1, ptr %a, align 8 + store i64 0, ptr %a.f, align 8 + %optval = load i64, ptr %a.f, align 8 + %not_err = icmp eq i64 %optval, 0 + %2 = call i1 @llvm.expect.i1(i1 %not_err, i1 true) + br i1 %2, label %after_check, label %assign_optional + +assign_optional: ; preds = %entry + store i64 %optval, ptr %b.f, align 8 + br label %after_assign + +after_check: ; preds = %entry + %3 = load ptr, ptr %a, align 8 + %4 = load i32, ptr %3, align 4 + store i32 %4, ptr %b, align 4 + store i64 0, ptr %b.f, align 8 + br label %after_assign + +after_assign: ; preds = %after_check, %assign_optional + ret void +} + diff --git a/test/test_suite7/slices/slice_optional_index.c3t b/test/test_suite7/slices/slice_optional_index.c3t new file mode 100644 index 000000000..a1be9cd28 --- /dev/null +++ b/test/test_suite7/slices/slice_optional_index.c3t @@ -0,0 +1,120 @@ +// #target: macos-x64 +module test; + +fn void test() +{ + int[] a = { 1, 2, 3 }; + for (int i = 0; i < 3; i++) + { + int! b = i == 0 ? SearchResult.MISSING? : i; + int[]! y = a[:b]; + int[]! w = a[b..]; + int! z = a[b]; + } +} + +/* #expect: test.ll + + store %"int[]" %1, ptr %a, align 8 + store i32 0, ptr %i, align 4 + br label %loop.cond + +loop.cond: ; preds = %after_assign15, %entry + %2 = load i32, ptr %i, align 4 + %lt = icmp slt i32 %2, 3 + br i1 %lt, label %loop.body, label %loop.exit + +loop.body: ; preds = %loop.cond + %3 = load i32, ptr %i, align 4 + %eq = icmp eq i32 %3, 0 + br i1 %eq, label %cond.lhs, label %cond.rhs + +cond.lhs: ; preds = %loop.body + store i64 ptrtoint (ptr @"std.core.builtin.SearchResult$MISSING" to i64), ptr %b.f, align 8 + br label %after_assign + +cond.rhs: ; preds = %loop.body + %4 = load i32, ptr %i, align 4 + br label %cond.phi + +cond.phi: ; preds = %cond.rhs + store i32 %4, ptr %b, align 4 + store i64 0, ptr %b.f, align 8 + br label %after_assign + +after_assign: ; preds = %cond.phi, %cond.lhs + %5 = load %"int[]", ptr %a, align 8 + %6 = extractvalue %"int[]" %5, 0 + %optval = load i64, ptr %b.f, align 8 + %not_err = icmp eq i64 %optval, 0 + %7 = call i1 @llvm.expect.i1(i1 %not_err, i1 true) + br i1 %7, label %after_check, label %assign_optional + +assign_optional: ; preds = %after_assign + store i64 %optval, ptr %y.f, align 8 + br label %after_assign1 + +after_check: ; preds = %after_assign + %8 = load i32, ptr %b, align 4 + %sext = sext i32 %8 to i64 + %add = add i64 0, %sext + %size = sub i64 %add, 0 + %9 = insertvalue %"int[]" undef, ptr %6, 0 + %10 = insertvalue %"int[]" %9, i64 %size, 1 + store %"int[]" %10, ptr %y, align 8 + store i64 0, ptr %y.f, align 8 + br label %after_assign1 + +after_assign1: ; preds = %after_check, %assign_optional + %11 = load %"int[]", ptr %a, align 8 + %12 = extractvalue %"int[]" %11, 0 + %optval2 = load i64, ptr %b.f, align 8 + %not_err3 = icmp eq i64 %optval2, 0 + %13 = call i1 @llvm.expect.i1(i1 %not_err3, i1 true) + br i1 %13, label %after_check5, label %assign_optional4 + +assign_optional4: ; preds = %after_assign1 + store i64 %optval2, ptr %w.f, align 8 + br label %after_assign8 + +after_check5: ; preds = %after_assign1 + %14 = load i32, ptr %b, align 4 + %sext6 = sext i32 %14 to i64 + %15 = extractvalue %"int[]" %11, 1 + %size7 = sub i64 %15, %sext6 + %ptroffset = getelementptr inbounds [4 x i8], ptr %12, i64 %sext6 + %16 = insertvalue %"int[]" undef, ptr %ptroffset, 0 + %17 = insertvalue %"int[]" %16, i64 %size7, 1 + store %"int[]" %17, ptr %w, align 8 + store i64 0, ptr %w.f, align 8 + br label %after_assign8 + +after_assign8: ; preds = %after_check5, %assign_optional4 + %18 = load ptr, ptr %a, align 8 + %optval9 = load i64, ptr %b.f, align 8 + %not_err10 = icmp eq i64 %optval9, 0 + %19 = call i1 @llvm.expect.i1(i1 %not_err10, i1 true) + br i1 %19, label %after_check12, label %assign_optional11 + +assign_optional11: ; preds = %after_assign8 + store i64 %optval9, ptr %z.f, align 8 + br label %after_assign15 + +after_check12: ; preds = %after_assign8 + %20 = load i32, ptr %b, align 4 + %sext13 = sext i32 %20 to i64 + %ptroffset14 = getelementptr inbounds [4 x i8], ptr %18, i64 %sext13 + %21 = load i32, ptr %ptroffset14, align 4 + store i32 %21, ptr %z, align 4 + store i64 0, ptr %z.f, align 8 + br label %after_assign15 + +after_assign15: ; preds = %after_check12, %assign_optional11 + %22 = load i32, ptr %i, align 4 + %add16 = add i32 %22, 1 + store i32 %add16, ptr %i, align 4 + br label %loop.cond + +loop.exit: ; preds = %loop.cond + ret void +} diff --git a/test/test_suite7/slices/slice_start.c3t b/test/test_suite7/slices/slice_start.c3t new file mode 100644 index 000000000..91a82af65 --- /dev/null +++ b/test/test_suite7/slices/slice_start.c3t @@ -0,0 +1,19 @@ +// #target: macos-x64 +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 = insertvalue %"int[]" undef, ptr %x, 0 + %1 = insertvalue %"int[]" %0, i64 3, 1 + store %"int[]" %1, ptr %y, align 8 + ret void +} \ No newline at end of file diff --git a/test/test_suite7/slices/slice_syntax.c3 b/test/test_suite7/slices/slice_syntax.c3 new file mode 100644 index 000000000..e4f3f641c --- /dev/null +++ b/test/test_suite7/slices/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_suite7/slices/slice_to_slice_assign.c3t b/test/test_suite7/slices/slice_to_slice_assign.c3t new file mode 100644 index 000000000..69c642eb8 --- /dev/null +++ b/test/test_suite7/slices/slice_to_slice_assign.c3t @@ -0,0 +1,129 @@ +// #target: macos-x64 +module test; +import std::io; + +fn void main() +{ + int[?] z = { 1, 2, 3, 4, 5, 6, 7 }; + int[6] y; + y[1..3] = z[3..5]; + io::printfn("%s %s", y, z); + y[4..] = z[5..6]; + io::printfn("%s %s", y, z); + int[][] a = { (int[]) { 1 } }; + int[][] b = { (int[]) { 2 } }; + io::printfn("%s", a); + a[0..0] = b[0..0]; + io::printfn("%s", a); + a[0..0] = y[2..4]; + io::printfn("%s", a); +} +/* #expect: test.ll + +define void @test.main() #0 { +entry: + %z = alloca [7 x i32], align 16 + %y = alloca [6 x i32], align 16 + %varargslots = alloca [2 x %any], align 16 + %retparam = alloca i64, align 8 + %varargslots5 = alloca [2 x %any], align 16 + %retparam7 = alloca i64, align 8 + %a = alloca %"int[][]", align 8 + %literal = alloca [1 x %"int[]"], align 16 + %literal8 = alloca [1 x i32], align 4 + %b = alloca %"int[][]", align 8 + %literal9 = alloca [1 x %"int[]"], align 16 + %literal10 = alloca [1 x i32], align 4 + %varargslots11 = alloca [1 x %any], align 16 + %retparam12 = alloca i64, align 8 + %varargslots13 = alloca [1 x %any], align 16 + %retparam14 = alloca i64, align 8 + %varargslots16 = alloca [1 x %any], align 16 + %retparam17 = alloca i64, align 8 + call void @llvm.memcpy.p0.p0.i32(ptr align 16 %z, ptr align 16 @.__const, i32 28, i1 false) + call void @llvm.memset.p0.i64(ptr align 16 %y, i8 0, i64 24, i1 false) + %ptradd = getelementptr inbounds i8, ptr %z, i64 12 + %0 = insertvalue %"int[]" undef, ptr %ptradd, 0 + %1 = insertvalue %"int[]" %0, i64 3, 1 + %ptradd1 = getelementptr inbounds i8, ptr %y, i64 4 + %2 = insertvalue %"int[]" undef, ptr %ptradd1, 0 + %3 = insertvalue %"int[]" %2, i64 3, 1 + %4 = extractvalue %"int[]" %3, 0 + %5 = extractvalue %"int[]" %1, 0 + %6 = extractvalue %"int[]" %1, 1 + %7 = mul i64 %6, 4 + call void @llvm.memmove.p0.p0.i64(ptr align 4 %4, ptr align 4 %5, i64 %7, i1 false) + %8 = insertvalue %any undef, ptr %y, 0 + %9 = insertvalue %any %8, i64 ptrtoint (ptr @"$ct.a6$int" to i64), 1 + store %any %9, ptr %varargslots, align 16 + %10 = insertvalue %any undef, ptr %z, 0 + %11 = insertvalue %any %10, i64 ptrtoint (ptr @"$ct.a7$int" to i64), 1 + %ptradd2 = getelementptr inbounds i8, ptr %varargslots, i64 16 + store %any %11, ptr %ptradd2, align 16 + %12 = call i64 @std.io.printfn(ptr %retparam, ptr @.str, i64 5, ptr %varargslots, i64 2) + %ptradd3 = getelementptr inbounds i8, ptr %z, i64 20 + %13 = insertvalue %"int[]" undef, ptr %ptradd3, 0 + %14 = insertvalue %"int[]" %13, i64 2, 1 + %ptradd4 = getelementptr inbounds i8, ptr %y, i64 16 + %15 = insertvalue %"int[]" undef, ptr %ptradd4, 0 + %16 = insertvalue %"int[]" %15, i64 2, 1 + %17 = extractvalue %"int[]" %16, 0 + %18 = extractvalue %"int[]" %14, 0 + %19 = extractvalue %"int[]" %14, 1 + %20 = mul i64 %19, 4 + call void @llvm.memmove.p0.p0.i64(ptr align 4 %17, ptr align 4 %18, i64 %20, i1 false) + %21 = insertvalue %any undef, ptr %y, 0 + %22 = insertvalue %any %21, i64 ptrtoint (ptr @"$ct.a6$int" to i64), 1 + store %any %22, ptr %varargslots5, align 16 + %23 = insertvalue %any undef, ptr %z, 0 + %24 = insertvalue %any %23, i64 ptrtoint (ptr @"$ct.a7$int" to i64), 1 + %ptradd6 = getelementptr inbounds i8, ptr %varargslots5, i64 16 + store %any %24, ptr %ptradd6, align 16 + %25 = call i64 @std.io.printfn(ptr %retparam7, ptr @.str.1, i64 5, ptr %varargslots5, i64 2) + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %literal8, ptr align 4 @.__const.2, i32 4, i1 false) + %26 = insertvalue %"int[]" undef, ptr %literal8, 0 + %27 = insertvalue %"int[]" %26, i64 1, 1 + store %"int[]" %27, ptr %literal, align 8 + %28 = insertvalue %"int[][]" undef, ptr %literal, 0 + %29 = insertvalue %"int[][]" %28, i64 1, 1 + store %"int[][]" %29, ptr %a, align 8 + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %literal10, ptr align 4 @.__const.3, i32 4, i1 false) + %30 = insertvalue %"int[]" undef, ptr %literal10, 0 + %31 = insertvalue %"int[]" %30, i64 1, 1 + store %"int[]" %31, ptr %literal9, align 8 + %32 = insertvalue %"int[][]" undef, ptr %literal9, 0 + %33 = insertvalue %"int[][]" %32, i64 1, 1 + store %"int[][]" %33, ptr %b, align 8 + %34 = insertvalue %any undef, ptr %a, 0 + %35 = insertvalue %any %34, i64 ptrtoint (ptr @"$ct.sa$sa$int" to i64), 1 + store %any %35, ptr %varargslots11, align 16 + %36 = call i64 @std.io.printfn(ptr %retparam12, ptr @.str.4, i64 2, ptr %varargslots11, i64 1) + %37 = load %"int[][]", ptr %b, align 8 + %38 = extractvalue %"int[][]" %37, 0 + %39 = insertvalue %"int[][]" undef, ptr %38, 0 + %40 = insertvalue %"int[][]" %39, i64 1, 1 + %41 = load %"int[][]", ptr %a, align 8 + %42 = extractvalue %"int[][]" %41, 0 + %43 = insertvalue %"int[][]" undef, ptr %42, 0 + %44 = insertvalue %"int[][]" %43, i64 1, 1 + %45 = extractvalue %"int[][]" %44, 0 + %46 = extractvalue %"int[][]" %40, 0 + %47 = extractvalue %"int[][]" %40, 1 + %48 = mul i64 %47, 16 + call void @llvm.memmove.p0.p0.i64(ptr align 8 %45, ptr align 8 %46, i64 %48, i1 false) + %49 = insertvalue %any undef, ptr %a, 0 + %50 = insertvalue %any %49, i64 ptrtoint (ptr @"$ct.sa$sa$int" to i64), 1 + store %any %50, ptr %varargslots13, align 16 + %51 = call i64 @std.io.printfn(ptr %retparam14, ptr @.str.5, i64 2, ptr %varargslots13, i64 1) + %ptradd15 = getelementptr inbounds i8, ptr %y, i64 8 + %52 = insertvalue %"int[]" undef, ptr %ptradd15, 0 + %53 = insertvalue %"int[]" %52, i64 3, 1 + %54 = load %"int[][]", ptr %a, align 8 + %55 = extractvalue %"int[][]" %54, 0 + store %"int[]" %53, ptr %55, align 8 + %56 = insertvalue %any undef, ptr %a, 0 + %57 = insertvalue %any %56, i64 ptrtoint (ptr @"$ct.sa$sa$int" to i64), 1 + store %any %57, ptr %varargslots16, align 16 + %58 = call i64 @std.io.printfn(ptr %retparam17, ptr @.str.6, i64 2, ptr %varargslots16, i64 1) + ret void +} diff --git a/test/test_suite7/slices/slice_to_slice_conv_err.c3t b/test/test_suite7/slices/slice_to_slice_conv_err.c3t new file mode 100644 index 000000000..593742e0c --- /dev/null +++ b/test/test_suite7/slices/slice_to_slice_conv_err.c3t @@ -0,0 +1,8 @@ +extern fn CInt execvp(CChar* file, CChar*[] argv); + +fn int main() +{ + ZString[] argv = {"ls", "-l", "-a"}; + execvp((CChar*)"ls", (CChar*[])argv); + return 0; +} diff --git a/test/test_suite7/slices/slice_to_slice_vector_assign.c3t b/test/test_suite7/slices/slice_to_slice_vector_assign.c3t new file mode 100644 index 000000000..abedcf3e3 --- /dev/null +++ b/test/test_suite7/slices/slice_to_slice_vector_assign.c3t @@ -0,0 +1,130 @@ +// #target: macos-x64 +module test; +import std::io; + +fn void main() +{ + int[] z = { 1, 2, 3, 4, 5, 6, 7 }; + int[<6>] y; + y[1..3] = z[3..5]; + io::printfn("%s %s", y, z); + y[4..] = z[5..6]; + io::printfn("%s %s", y, z); + int[][] a = { (int[]) { 1 } }; + int[][] b = { (int[]) { 2 } }; + io::printfn("%s", a); + a[0..0] = b[0..0]; + io::printfn("%s", a); + a[0..0] = y[2..4]; + io::printfn("%s", a); +} + +/* #expect: test.ll + +define void @test.main() #0 { +entry: + %z = alloca <7 x i32>, align 32 + %y = alloca <6 x i32>, align 32 + %varargslots = alloca [2 x %any], align 16 + %retparam = alloca i64, align 8 + %varargslots5 = alloca [2 x %any], align 16 + %retparam7 = alloca i64, align 8 + %a = alloca %"int[][]", align 8 + %literal = alloca [1 x %"int[]"], align 16 + %literal8 = alloca [1 x i32], align 4 + %b = alloca %"int[][]", align 8 + %literal9 = alloca [1 x %"int[]"], align 16 + %literal10 = alloca [1 x i32], align 4 + %varargslots11 = alloca [1 x %any], align 16 + %retparam12 = alloca i64, align 8 + %varargslots13 = alloca [1 x %any], align 16 + %retparam14 = alloca i64, align 8 + %varargslots16 = alloca [1 x %any], align 16 + %retparam17 = alloca i64, align 8 + store <7 x i32> , ptr %z, align 32 + store <6 x i32> zeroinitializer, ptr %y, align 32 + %ptradd = getelementptr inbounds i8, ptr %z, i64 12 + %0 = insertvalue %"int[]" undef, ptr %ptradd, 0 + %1 = insertvalue %"int[]" %0, i64 3, 1 + %ptradd1 = getelementptr inbounds i8, ptr %y, i64 4 + %2 = insertvalue %"int[]" undef, ptr %ptradd1, 0 + %3 = insertvalue %"int[]" %2, i64 3, 1 + %4 = extractvalue %"int[]" %3, 0 + %5 = extractvalue %"int[]" %1, 0 + %6 = extractvalue %"int[]" %1, 1 + %7 = mul i64 %6, 4 + call void @llvm.memmove.p0.p0.i64(ptr align 4 %4, ptr align 4 %5, i64 %7, i1 false) + %8 = insertvalue %any undef, ptr %y, 0 + %9 = insertvalue %any %8, i64 ptrtoint (ptr @"$ct.v6$int" to i64), 1 + store %any %9, ptr %varargslots, align 16 + %10 = insertvalue %any undef, ptr %z, 0 + %11 = insertvalue %any %10, i64 ptrtoint (ptr @"$ct.v7$int" to i64), 1 + %ptradd2 = getelementptr inbounds i8, ptr %varargslots, i64 16 + store %any %11, ptr %ptradd2, align 16 + %12 = call i64 @std.io.printfn(ptr %retparam, ptr @.str, i64 5, ptr %varargslots, i64 2) + %ptradd3 = getelementptr inbounds i8, ptr %z, i64 20 + %13 = insertvalue %"int[]" undef, ptr %ptradd3, 0 + %14 = insertvalue %"int[]" %13, i64 2, 1 + %ptradd4 = getelementptr inbounds i8, ptr %y, i64 16 + %15 = insertvalue %"int[]" undef, ptr %ptradd4, 0 + %16 = insertvalue %"int[]" %15, i64 2, 1 + %17 = extractvalue %"int[]" %16, 0 + %18 = extractvalue %"int[]" %14, 0 + %19 = extractvalue %"int[]" %14, 1 + %20 = mul i64 %19, 4 + call void @llvm.memmove.p0.p0.i64(ptr align 4 %17, ptr align 4 %18, i64 %20, i1 false) + %21 = insertvalue %any undef, ptr %y, 0 + %22 = insertvalue %any %21, i64 ptrtoint (ptr @"$ct.v6$int" to i64), 1 + store %any %22, ptr %varargslots5, align 16 + %23 = insertvalue %any undef, ptr %z, 0 + %24 = insertvalue %any %23, i64 ptrtoint (ptr @"$ct.v7$int" to i64), 1 + %ptradd6 = getelementptr inbounds i8, ptr %varargslots5, i64 16 + store %any %24, ptr %ptradd6, align 16 + %25 = call i64 @std.io.printfn(ptr %retparam7, ptr @.str.1, i64 5, ptr %varargslots5, i64 2) + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %literal8, ptr align 4 @.__const, i32 4, i1 false) + %26 = insertvalue %"int[]" undef, ptr %literal8, 0 + %27 = insertvalue %"int[]" %26, i64 1, 1 + store %"int[]" %27, ptr %literal, align 8 + %28 = insertvalue %"int[][]" undef, ptr %literal, 0 + %29 = insertvalue %"int[][]" %28, i64 1, 1 + store %"int[][]" %29, ptr %a, align 8 + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %literal10, ptr align 4 @.__const.2, i32 4, i1 false) + %30 = insertvalue %"int[]" undef, ptr %literal10, 0 + %31 = insertvalue %"int[]" %30, i64 1, 1 + store %"int[]" %31, ptr %literal9, align 8 + %32 = insertvalue %"int[][]" undef, ptr %literal9, 0 + %33 = insertvalue %"int[][]" %32, i64 1, 1 + store %"int[][]" %33, ptr %b, align 8 + %34 = insertvalue %any undef, ptr %a, 0 + %35 = insertvalue %any %34, i64 ptrtoint (ptr @"$ct.sa$sa$int" to i64), 1 + store %any %35, ptr %varargslots11, align 16 + %36 = call i64 @std.io.printfn(ptr %retparam12, ptr @.str.3, i64 2, ptr %varargslots11, i64 1) + %37 = load %"int[][]", ptr %b, align 8 + %38 = extractvalue %"int[][]" %37, 0 + %39 = insertvalue %"int[][]" undef, ptr %38, 0 + %40 = insertvalue %"int[][]" %39, i64 1, 1 + %41 = load %"int[][]", ptr %a, align 8 + %42 = extractvalue %"int[][]" %41, 0 + %43 = insertvalue %"int[][]" undef, ptr %42, 0 + %44 = insertvalue %"int[][]" %43, i64 1, 1 + %45 = extractvalue %"int[][]" %44, 0 + %46 = extractvalue %"int[][]" %40, 0 + %47 = extractvalue %"int[][]" %40, 1 + %48 = mul i64 %47, 16 + call void @llvm.memmove.p0.p0.i64(ptr align 8 %45, ptr align 8 %46, i64 %48, i1 false) + %49 = insertvalue %any undef, ptr %a, 0 + %50 = insertvalue %any %49, i64 ptrtoint (ptr @"$ct.sa$sa$int" to i64), 1 + store %any %50, ptr %varargslots13, align 16 + %51 = call i64 @std.io.printfn(ptr %retparam14, ptr @.str.4, i64 2, ptr %varargslots13, i64 1) + %ptradd15 = getelementptr inbounds i8, ptr %y, i64 8 + %52 = insertvalue %"int[]" undef, ptr %ptradd15, 0 + %53 = insertvalue %"int[]" %52, i64 3, 1 + %54 = load %"int[][]", ptr %a, align 8 + %55 = extractvalue %"int[][]" %54, 0 + store %"int[]" %53, ptr %55, align 8 + %56 = insertvalue %any undef, ptr %a, 0 + %57 = insertvalue %any %56, i64 ptrtoint (ptr @"$ct.sa$sa$int" to i64), 1 + store %any %57, ptr %varargslots16, align 16 + %58 = call i64 @std.io.printfn(ptr %retparam17, ptr @.str.5, i64 2, ptr %varargslots16, i64 1) + ret void +} diff --git a/test/test_suite7/slices/sub_array_init.c3 b/test/test_suite7/slices/sub_array_init.c3 new file mode 100644 index 000000000..72b6d5698 --- /dev/null +++ b/test/test_suite7/slices/sub_array_init.c3 @@ -0,0 +1,7 @@ +fn void test2() +{ + int[2] a = { 1, 2 }; + + int[2] b = 30; // #error: 'int[2]' + int[2] c = a; +} diff --git a/test/test_suite7/slices/subscript_check_1519.c3t b/test/test_suite7/slices/subscript_check_1519.c3t new file mode 100644 index 000000000..e64bdeedc --- /dev/null +++ b/test/test_suite7/slices/subscript_check_1519.c3t @@ -0,0 +1,37 @@ +// #target: macos-x64 +module test; +import std::collections::list; +macro @test_list(a) +{ + var $Type = $typeof(a); + $if $defined(a[0]) &&& $Type.typeid == List(<$typeof(a[0])>).typeid: + return 1; + $else + return 0; + $endif +} + +fn int main(String[] args) +{ + DString str = dstring::new("test"); + return @test_list(str); +} + +/* #expect: test.ll + +define i32 @test.main(ptr %0, i64 %1) #0 { +entry: + %args = alloca %"char[][]", align 8 + %str = alloca ptr, align 8 + %a = alloca ptr, align 8 + store ptr %0, ptr %args, align 8 + %ptradd = getelementptr inbounds i8, ptr %args, i64 8 + store i64 %1, ptr %ptradd, align 8 + %lo = load i64, ptr @std.core.mem.allocator.thread_allocator, align 8 + %hi = load ptr, ptr getelementptr inbounds (i8, ptr @std.core.mem.allocator.thread_allocator, i64 8), align 8 + %2 = call ptr @std.core.dstring.new(ptr @.str, i64 4, i64 %lo, ptr %hi) + store ptr %2, ptr %str, align 8 + %3 = load ptr, ptr %str, align 8 + store ptr %3, ptr %a, align 8 + ret i32 0 +} \ No newline at end of file diff --git a/test/test_suite7/slices/various_const_slicing.c3t b/test/test_suite7/slices/various_const_slicing.c3t new file mode 100644 index 000000000..6828e0877 --- /dev/null +++ b/test/test_suite7/slices/various_const_slicing.c3t @@ -0,0 +1,497 @@ +// #target: macos-x64 +module test; +import std; +const int[4] FOO = { 1, 2, 3, 4 }; +int[] y2 = FOO[1..2]; + +fn void test() +{ + int[][] a = { (int[]) { 1 } }; + char[4] $a = x'aabbccdd'; + var $b = $a[1..2]; + char[2] y = $b; + assert($b == (char[]) { 187, 204 }); + assert(y == (char[2]) { 187, 204 }); + +} +fn int main() +{ + int[?] $x = { 1, 2, 3, 4 }; + var $y = $x[1..3]; + int[] y = { 1, 2 }; + io::printn(y.ptr); + io::printn(y.len); + io::printn(y); + io::printn($y); + int[2] $z = $y[1..2]; + io::printn($z); + int[] $b = $y[:0]; + int[] $c = $y[:0]; + io::printn($c); + return 0; +} + +/* #expect: test.ll + +@test.FOO = local_unnamed_addr constant [2 x i32] [i32 2, i32 3], align 16 +@.__const_slice = private unnamed_addr global [2 x i32] [i32 2, i32 3], align 4 +@test.y2 = local_unnamed_addr global %"int[]" { ptr @.__const_slice, i64 2 }, align 8 +@.__const = private unnamed_addr constant [1 x i32] [i32 1], align 4 +@.bytes = private unnamed_addr constant [3 x i8] c"\BB\CC\00", align 1 +@.__const.2 = private unnamed_addr constant [2 x i8] c"\BB\CC", align 1 +@.__const.3 = private unnamed_addr constant [2 x i32] [i32 1, i32 2], align 4 +@.__const.6 = private unnamed_addr constant [3 x i32] [i32 2, i32 3, i32 4], align 4 +@.__const.8 = private unnamed_addr constant [2 x i32] [i32 3, i32 4], align 4 + +define void @test.test() #0 { +entry: + %a = alloca %"int[][]", align 8 + %literal = alloca [1 x %"int[]"], align 16 + %literal1 = alloca [1 x i32], align 4 + %y = alloca [2 x i8], align 1 + %literal2 = alloca [2 x i8], align 1 + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %literal1, ptr align 4 @.__const, i32 4, i1 false) + %0 = insertvalue %"int[]" undef, ptr %literal1, 0 + %1 = insertvalue %"int[]" %0, i64 1, 1 + store %"int[]" %1, ptr %literal, align 8 + %2 = insertvalue %"int[][]" undef, ptr %literal, 0 + %3 = insertvalue %"int[][]" %2, i64 1, 1 + store %"int[][]" %3, ptr %a, align 8 + call void @llvm.memcpy.p0.p0.i32(ptr align 1 %y, ptr align 1 @.bytes, i32 2, i1 false) + call void @llvm.memcpy.p0.p0.i32(ptr align 1 %literal2, ptr align 1 @.__const.2, i32 2, i1 false) + %cmp = call i32 @memcmp(ptr %y, ptr %literal2, i64 2) + %eq = icmp eq i32 %cmp, 0 + call void @llvm.assume(i1 %eq) + ret void +} + +define i32 @main() #0 { +entry: + %y = alloca %"int[]", align 8 + %literal = alloca [2 x i32], align 4 + %x = alloca ptr, align 8 + %x1 = alloca ptr, align 8 + %len = alloca i64, align 8 + %error_var = alloca i64, align 8 + %x2 = alloca ptr, align 8 + %varargslots = alloca [1 x %any], align 16 + %retparam = alloca i64, align 8 + %taddr = alloca %any, align 8 + %indirectarg = alloca %"any[]", align 8 + %error_var4 = alloca i64, align 8 + %error_var10 = alloca i64, align 8 + %x17 = alloca i64, align 8 + %x18 = alloca i64, align 8 + %len19 = alloca i64, align 8 + %error_var20 = alloca i64, align 8 + %x21 = alloca i64, align 8 + %varargslots23 = alloca [1 x %any], align 16 + %retparam25 = alloca i64, align 8 + %taddr26 = alloca %any, align 8 + %indirectarg30 = alloca %"any[]", align 8 + %error_var36 = alloca i64, align 8 + %error_var42 = alloca i64, align 8 + %x50 = alloca %"int[]", align 8 + %x51 = alloca %"int[]", align 8 + %len52 = alloca i64, align 8 + %error_var53 = alloca i64, align 8 + %x54 = alloca %"int[]", align 8 + %varargslots56 = alloca [1 x %any], align 16 + %retparam58 = alloca i64, align 8 + %taddr59 = alloca %any, align 8 + %indirectarg63 = alloca %"any[]", align 8 + %error_var69 = alloca i64, align 8 + %error_var75 = alloca i64, align 8 + %literal83 = alloca [3 x i32], align 4 + %len84 = alloca i64, align 8 + %error_var85 = alloca i64, align 8 + %varargslots87 = alloca [1 x %any], align 16 + %taddr88 = alloca %"int[]", align 8 + %retparam90 = alloca i64, align 8 + %taddr91 = alloca %any, align 8 + %indirectarg95 = alloca %"any[]", align 8 + %error_var101 = alloca i64, align 8 + %error_var107 = alloca i64, align 8 + %literal115 = alloca [2 x i32], align 4 + %x116 = alloca [2 x i32], align 4 + %x117 = alloca [2 x i32], align 4 + %len118 = alloca i64, align 8 + %error_var119 = alloca i64, align 8 + %x120 = alloca [2 x i32], align 4 + %varargslots122 = alloca [1 x %any], align 16 + %retparam124 = alloca i64, align 8 + %taddr125 = alloca %any, align 8 + %indirectarg129 = alloca %"any[]", align 8 + %error_var135 = alloca i64, align 8 + %error_var141 = alloca i64, align 8 + %len149 = alloca i64, align 8 + %error_var150 = alloca i64, align 8 + %varargslots152 = alloca [1 x %any], align 16 + %taddr153 = alloca %"int[]", align 8 + %retparam155 = alloca i64, align 8 + %taddr156 = alloca %any, align 8 + %indirectarg160 = alloca %"any[]", align 8 + %error_var166 = alloca i64, align 8 + %error_var172 = alloca i64, align 8 + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %literal, ptr align 4 @.__const.3, i32 8, i1 false) + %0 = insertvalue %"int[]" undef, ptr %literal, 0 + %1 = insertvalue %"int[]" %0, i64 2, 1 + store %"int[]" %1, ptr %y, align 8 + %2 = load ptr, ptr %y, align 8 + store ptr %2, ptr %x, align 8 + %3 = call ptr @std.io.stdout() + %4 = load ptr, ptr %x, align 8 + store ptr %4, ptr %x1, align 8 + %5 = load ptr, ptr %x1, align 8 + store ptr %5, ptr %x2, align 8 + %6 = insertvalue %any undef, ptr %3, 0 + %7 = insertvalue %any %6, i64 ptrtoint (ptr @"$ct.std.io.File" to i64), 1 + %8 = insertvalue %any undef, ptr %x2, 0 + %9 = insertvalue %any %8, i64 ptrtoint (ptr @"$ct.p$int" to i64), 1 + store %any %9, ptr %varargslots, align 16 + %10 = insertvalue %"any[]" undef, ptr %varargslots, 0 + %"$$temp" = insertvalue %"any[]" %10, i64 1, 1 + store %any %7, ptr %taddr, align 8 + %lo = load i64, ptr %taddr, align 8 + %ptradd = getelementptr inbounds i8, ptr %taddr, i64 8 + %hi = load ptr, ptr %ptradd, align 8 + store %"any[]" %"$$temp", ptr %indirectarg, align 8 + %11 = call i64 @std.io.fprintf(ptr %retparam, i64 %lo, ptr %hi, ptr @.str, i64 2, ptr byval(%"any[]") align 8 %indirectarg) + %not_err = icmp eq i64 %11, 0 + %12 = call i1 @llvm.expect.i1(i1 %not_err, i1 true) + br i1 %12, label %after_check, label %assign_optional +assign_optional: ; preds = %entry + store i64 %11, ptr %error_var, align 8 + br label %guard_block +after_check: ; preds = %entry + br label %noerr_block +guard_block: ; preds = %assign_optional + br label %voiderr +noerr_block: ; preds = %after_check + %13 = load i64, ptr %retparam, align 8 + store i64 %13, ptr %len, align 8 + %14 = call i64 @std.io.File.write_byte(ptr %3, i8 zeroext 10) + %not_err5 = icmp eq i64 %14, 0 + %15 = call i1 @llvm.expect.i1(i1 %not_err5, i1 true) + br i1 %15, label %after_check7, label %assign_optional6 +assign_optional6: ; preds = %noerr_block + store i64 %14, ptr %error_var4, align 8 + br label %guard_block8 +after_check7: ; preds = %noerr_block + br label %noerr_block9 +guard_block8: ; preds = %assign_optional6 + br label %voiderr +noerr_block9: ; preds = %after_check7 + %16 = call i64 @std.io.File.flush(ptr %3) + %not_err11 = icmp eq i64 %16, 0 + %17 = call i1 @llvm.expect.i1(i1 %not_err11, i1 true) + br i1 %17, label %after_check13, label %assign_optional12 +assign_optional12: ; preds = %noerr_block9 + store i64 %16, ptr %error_var10, align 8 + br label %guard_block14 +after_check13: ; preds = %noerr_block9 + br label %noerr_block15 +guard_block14: ; preds = %assign_optional12 + br label %voiderr +noerr_block15: ; preds = %after_check13 + %18 = load i64, ptr %len, align 8 + %add = add i64 %18, 1 + br label %voiderr +voiderr: ; preds = %noerr_block15, %guard_block14, %guard_block8, %guard_block + %ptradd16 = getelementptr inbounds i8, ptr %y, i64 8 + %19 = load i64, ptr %ptradd16, align 8 + store i64 %19, ptr %x17, align 8 + %20 = call ptr @std.io.stdout() + %21 = load i64, ptr %x17, align 8 + store i64 %21, ptr %x18, align 8 + %22 = load i64, ptr %x18, align 8 + store i64 %22, ptr %x21, align 8 + %23 = insertvalue %any undef, ptr %20, 0 + %24 = insertvalue %any %23, i64 ptrtoint (ptr @"$ct.std.io.File" to i64), 1 + %25 = insertvalue %any undef, ptr %x21, 0 + %26 = insertvalue %any %25, i64 ptrtoint (ptr @"$ct.ulong" to i64), 1 + store %any %26, ptr %varargslots23, align 16 + %27 = insertvalue %"any[]" undef, ptr %varargslots23, 0 + %"$$temp24" = insertvalue %"any[]" %27, i64 1, 1 + store %any %24, ptr %taddr26, align 8 + %lo27 = load i64, ptr %taddr26, align 8 + %ptradd28 = getelementptr inbounds i8, ptr %taddr26, i64 8 + %hi29 = load ptr, ptr %ptradd28, align 8 + store %"any[]" %"$$temp24", ptr %indirectarg30, align 8 + %28 = call i64 @std.io.fprintf(ptr %retparam25, i64 %lo27, ptr %hi29, ptr @.str.4, i64 2, ptr byval(%"any[]") align 8 %indirectarg30) + %not_err31 = icmp eq i64 %28, 0 + %29 = call i1 @llvm.expect.i1(i1 %not_err31, i1 true) + br i1 %29, label %after_check33, label %assign_optional32 +assign_optional32: ; preds = %voiderr + store i64 %28, ptr %error_var20, align 8 + br label %guard_block34 +after_check33: ; preds = %voiderr + br label %noerr_block35 +guard_block34: ; preds = %assign_optional32 + br label %voiderr49 +noerr_block35: ; preds = %after_check33 + %30 = load i64, ptr %retparam25, align 8 + store i64 %30, ptr %len19, align 8 + %31 = call i64 @std.io.File.write_byte(ptr %20, i8 zeroext 10) + %not_err37 = icmp eq i64 %31, 0 + %32 = call i1 @llvm.expect.i1(i1 %not_err37, i1 true) + br i1 %32, label %after_check39, label %assign_optional38 +assign_optional38: ; preds = %noerr_block35 + store i64 %31, ptr %error_var36, align 8 + br label %guard_block40 +after_check39: ; preds = %noerr_block35 + br label %noerr_block41 +guard_block40: ; preds = %assign_optional38 + br label %voiderr49 +noerr_block41: ; preds = %after_check39 + %33 = call i64 @std.io.File.flush(ptr %20) + %not_err43 = icmp eq i64 %33, 0 + %34 = call i1 @llvm.expect.i1(i1 %not_err43, i1 true) + br i1 %34, label %after_check45, label %assign_optional44 +assign_optional44: ; preds = %noerr_block41 + store i64 %33, ptr %error_var42, align 8 + br label %guard_block46 +after_check45: ; preds = %noerr_block41 + br label %noerr_block47 +guard_block46: ; preds = %assign_optional44 + br label %voiderr49 +noerr_block47: ; preds = %after_check45 + %35 = load i64, ptr %len19, align 8 + %add48 = add i64 %35, 1 + br label %voiderr49 +voiderr49: ; preds = %noerr_block47, %guard_block46, %guard_block40, %guard_block34 + call void @llvm.memcpy.p0.p0.i32(ptr align 8 %x50, ptr align 8 %y, i32 16, i1 false) + %36 = call ptr @std.io.stdout() + call void @llvm.memcpy.p0.p0.i32(ptr align 8 %x51, ptr align 8 %x50, i32 16, i1 false) + call void @llvm.memcpy.p0.p0.i32(ptr align 8 %x54, ptr align 8 %x51, i32 16, i1 false) + %37 = insertvalue %any undef, ptr %36, 0 + %38 = insertvalue %any %37, i64 ptrtoint (ptr @"$ct.std.io.File" to i64), 1 + %39 = insertvalue %any undef, ptr %x54, 0 + %40 = insertvalue %any %39, i64 ptrtoint (ptr @"$ct.sa$int" to i64), 1 + store %any %40, ptr %varargslots56, align 16 + %41 = insertvalue %"any[]" undef, ptr %varargslots56, 0 + %"$$temp57" = insertvalue %"any[]" %41, i64 1, 1 + store %any %38, ptr %taddr59, align 8 + %lo60 = load i64, ptr %taddr59, align 8 + %ptradd61 = getelementptr inbounds i8, ptr %taddr59, i64 8 + %hi62 = load ptr, ptr %ptradd61, align 8 + store %"any[]" %"$$temp57", ptr %indirectarg63, align 8 + %42 = call i64 @std.io.fprintf(ptr %retparam58, i64 %lo60, ptr %hi62, ptr @.str.5, i64 2, ptr byval(%"any[]") align 8 %indirectarg63) + %not_err64 = icmp eq i64 %42, 0 + %43 = call i1 @llvm.expect.i1(i1 %not_err64, i1 true) + br i1 %43, label %after_check66, label %assign_optional65 +assign_optional65: ; preds = %voiderr49 + store i64 %42, ptr %error_var53, align 8 + br label %guard_block67 +after_check66: ; preds = %voiderr49 + br label %noerr_block68 +guard_block67: ; preds = %assign_optional65 + br label %voiderr82 +noerr_block68: ; preds = %after_check66 + %44 = load i64, ptr %retparam58, align 8 + store i64 %44, ptr %len52, align 8 + %45 = call i64 @std.io.File.write_byte(ptr %36, i8 zeroext 10) + %not_err70 = icmp eq i64 %45, 0 + %46 = call i1 @llvm.expect.i1(i1 %not_err70, i1 true) + br i1 %46, label %after_check72, label %assign_optional71 +assign_optional71: ; preds = %noerr_block68 + store i64 %45, ptr %error_var69, align 8 + br label %guard_block73 +after_check72: ; preds = %noerr_block68 + br label %noerr_block74 +guard_block73: ; preds = %assign_optional71 + br label %voiderr82 +noerr_block74: ; preds = %after_check72 + %47 = call i64 @std.io.File.flush(ptr %36) + %not_err76 = icmp eq i64 %47, 0 + %48 = call i1 @llvm.expect.i1(i1 %not_err76, i1 true) + br i1 %48, label %after_check78, label %assign_optional77 +assign_optional77: ; preds = %noerr_block74 + store i64 %47, ptr %error_var75, align 8 + br label %guard_block79 +after_check78: ; preds = %noerr_block74 + br label %noerr_block80 +guard_block79: ; preds = %assign_optional77 + br label %voiderr82 +noerr_block80: ; preds = %after_check78 + %49 = load i64, ptr %len52, align 8 + %add81 = add i64 %49, 1 + br label %voiderr82 +voiderr82: ; preds = %noerr_block80, %guard_block79, %guard_block73, %guard_block67 + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %literal83, ptr align 4 @.__const.6, i32 12, i1 false) + %50 = insertvalue %"int[]" undef, ptr %literal83, 0 + %51 = insertvalue %"int[]" %50, i64 3, 1 + %52 = call ptr @std.io.stdout() + %53 = insertvalue %any undef, ptr %52, 0 + %54 = insertvalue %any %53, i64 ptrtoint (ptr @"$ct.std.io.File" to i64), 1 + store %"int[]" %51, ptr %taddr88, align 8 + %55 = insertvalue %any undef, ptr %taddr88, 0 + %56 = insertvalue %any %55, i64 ptrtoint (ptr @"$ct.sa$int" to i64), 1 + store %any %56, ptr %varargslots87, align 16 + %57 = insertvalue %"any[]" undef, ptr %varargslots87, 0 + %"$$temp89" = insertvalue %"any[]" %57, i64 1, 1 + store %any %54, ptr %taddr91, align 8 + %lo92 = load i64, ptr %taddr91, align 8 + %ptradd93 = getelementptr inbounds i8, ptr %taddr91, i64 8 + %hi94 = load ptr, ptr %ptradd93, align 8 + store %"any[]" %"$$temp89", ptr %indirectarg95, align 8 + %58 = call i64 @std.io.fprintf(ptr %retparam90, i64 %lo92, ptr %hi94, ptr @.str.7, i64 2, ptr byval(%"any[]") align 8 %indirectarg95) + %not_err96 = icmp eq i64 %58, 0 + %59 = call i1 @llvm.expect.i1(i1 %not_err96, i1 true) + br i1 %59, label %after_check98, label %assign_optional97 +assign_optional97: ; preds = %voiderr82 + store i64 %58, ptr %error_var85, align 8 + br label %guard_block99 +after_check98: ; preds = %voiderr82 + br label %noerr_block100 +guard_block99: ; preds = %assign_optional97 + br label %voiderr114 +noerr_block100: ; preds = %after_check98 + %60 = load i64, ptr %retparam90, align 8 + store i64 %60, ptr %len84, align 8 + %61 = call i64 @std.io.File.write_byte(ptr %52, i8 zeroext 10) + %not_err102 = icmp eq i64 %61, 0 + %62 = call i1 @llvm.expect.i1(i1 %not_err102, i1 true) + br i1 %62, label %after_check104, label %assign_optional103 +assign_optional103: ; preds = %noerr_block100 + store i64 %61, ptr %error_var101, align 8 + br label %guard_block105 +after_check104: ; preds = %noerr_block100 + br label %noerr_block106 +guard_block105: ; preds = %assign_optional103 + br label %voiderr114 +noerr_block106: ; preds = %after_check104 + %63 = call i64 @std.io.File.flush(ptr %52) + %not_err108 = icmp eq i64 %63, 0 + %64 = call i1 @llvm.expect.i1(i1 %not_err108, i1 true) + br i1 %64, label %after_check110, label %assign_optional109 +assign_optional109: ; preds = %noerr_block106 + store i64 %63, ptr %error_var107, align 8 + br label %guard_block111 +after_check110: ; preds = %noerr_block106 + br label %noerr_block112 +guard_block111: ; preds = %assign_optional109 + br label %voiderr114 +noerr_block112: ; preds = %after_check110 + %65 = load i64, ptr %len84, align 8 + %add113 = add i64 %65, 1 + br label %voiderr114 +voiderr114: ; preds = %noerr_block112, %guard_block111, %guard_block105, %guard_block99 + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %literal115, ptr align 4 @.__const.8, i32 8, i1 false) + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %x116, ptr align 4 %literal115, i32 8, i1 false) + %66 = call ptr @std.io.stdout() + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %x117, ptr align 4 %x116, i32 8, i1 false) + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %x120, ptr align 4 %x117, i32 8, i1 false) + %67 = insertvalue %any undef, ptr %66, 0 + %68 = insertvalue %any %67, i64 ptrtoint (ptr @"$ct.std.io.File" to i64), 1 + %69 = insertvalue %any undef, ptr %x120, 0 + %70 = insertvalue %any %69, i64 ptrtoint (ptr @"$ct.a2$int" to i64), 1 + store %any %70, ptr %varargslots122, align 16 + %71 = insertvalue %"any[]" undef, ptr %varargslots122, 0 + %"$$temp123" = insertvalue %"any[]" %71, i64 1, 1 + store %any %68, ptr %taddr125, align 8 + %lo126 = load i64, ptr %taddr125, align 8 + %ptradd127 = getelementptr inbounds i8, ptr %taddr125, i64 8 + %hi128 = load ptr, ptr %ptradd127, align 8 + store %"any[]" %"$$temp123", ptr %indirectarg129, align 8 + %72 = call i64 @std.io.fprintf(ptr %retparam124, i64 %lo126, ptr %hi128, ptr @.str.9, i64 2, ptr byval(%"any[]") align 8 %indirectarg129) + %not_err130 = icmp eq i64 %72, 0 + %73 = call i1 @llvm.expect.i1(i1 %not_err130, i1 true) + br i1 %73, label %after_check132, label %assign_optional131 +assign_optional131: ; preds = %voiderr114 + store i64 %72, ptr %error_var119, align 8 + br label %guard_block133 +after_check132: ; preds = %voiderr114 + br label %noerr_block134 +guard_block133: ; preds = %assign_optional131 + br label %voiderr148 +noerr_block134: ; preds = %after_check132 + %74 = load i64, ptr %retparam124, align 8 + store i64 %74, ptr %len118, align 8 + %75 = call i64 @std.io.File.write_byte(ptr %66, i8 zeroext 10) + %not_err136 = icmp eq i64 %75, 0 + %76 = call i1 @llvm.expect.i1(i1 %not_err136, i1 true) + br i1 %76, label %after_check138, label %assign_optional137 +assign_optional137: ; preds = %noerr_block134 + store i64 %75, ptr %error_var135, align 8 + br label %guard_block139 +after_check138: ; preds = %noerr_block134 + br label %noerr_block140 +guard_block139: ; preds = %assign_optional137 + br label %voiderr148 +noerr_block140: ; preds = %after_check138 + %77 = call i64 @std.io.File.flush(ptr %66) + %not_err142 = icmp eq i64 %77, 0 + %78 = call i1 @llvm.expect.i1(i1 %not_err142, i1 true) + br i1 %78, label %after_check144, label %assign_optional143 +assign_optional143: ; preds = %noerr_block140 + store i64 %77, ptr %error_var141, align 8 + br label %guard_block145 +after_check144: ; preds = %noerr_block140 + br label %noerr_block146 +guard_block145: ; preds = %assign_optional143 + br label %voiderr148 +noerr_block146: ; preds = %after_check144 + %79 = load i64, ptr %len118, align 8 + %add147 = add i64 %79, 1 + br label %voiderr148 +voiderr148: ; preds = %noerr_block146, %guard_block145, %guard_block139, %guard_block133 + %80 = call ptr @std.io.stdout() + %81 = insertvalue %any undef, ptr %80, 0 + %82 = insertvalue %any %81, i64 ptrtoint (ptr @"$ct.std.io.File" to i64), 1 + store %"int[]" zeroinitializer, ptr %taddr153, align 8 + %83 = insertvalue %any undef, ptr %taddr153, 0 + %84 = insertvalue %any %83, i64 ptrtoint (ptr @"$ct.sa$int" to i64), 1 + store %any %84, ptr %varargslots152, align 16 + %85 = insertvalue %"any[]" undef, ptr %varargslots152, 0 + %"$$temp154" = insertvalue %"any[]" %85, i64 1, 1 + store %any %82, ptr %taddr156, align 8 + %lo157 = load i64, ptr %taddr156, align 8 + %ptradd158 = getelementptr inbounds i8, ptr %taddr156, i64 8 + %hi159 = load ptr, ptr %ptradd158, align 8 + store %"any[]" %"$$temp154", ptr %indirectarg160, align 8 + %86 = call i64 @std.io.fprintf(ptr %retparam155, i64 %lo157, ptr %hi159, ptr @.str.10, i64 2, ptr byval(%"any[]") align 8 %indirectarg160) + %not_err161 = icmp eq i64 %86, 0 + %87 = call i1 @llvm.expect.i1(i1 %not_err161, i1 true) + br i1 %87, label %after_check163, label %assign_optional162 +assign_optional162: ; preds = %voiderr148 + store i64 %86, ptr %error_var150, align 8 + br label %guard_block164 +after_check163: ; preds = %voiderr148 + br label %noerr_block165 +guard_block164: ; preds = %assign_optional162 + br label %voiderr179 +noerr_block165: ; preds = %after_check163 + %88 = load i64, ptr %retparam155, align 8 + store i64 %88, ptr %len149, align 8 + %89 = call i64 @std.io.File.write_byte(ptr %80, i8 zeroext 10) + %not_err167 = icmp eq i64 %89, 0 + %90 = call i1 @llvm.expect.i1(i1 %not_err167, i1 true) + br i1 %90, label %after_check169, label %assign_optional168 +assign_optional168: ; preds = %noerr_block165 + store i64 %89, ptr %error_var166, align 8 + br label %guard_block170 +after_check169: ; preds = %noerr_block165 + br label %noerr_block171 +guard_block170: ; preds = %assign_optional168 + br label %voiderr179 +noerr_block171: ; preds = %after_check169 + %91 = call i64 @std.io.File.flush(ptr %80) + %not_err173 = icmp eq i64 %91, 0 + %92 = call i1 @llvm.expect.i1(i1 %not_err173, i1 true) + br i1 %92, label %after_check175, label %assign_optional174 +assign_optional174: ; preds = %noerr_block171 + store i64 %91, ptr %error_var172, align 8 + br label %guard_block176 +after_check175: ; preds = %noerr_block171 + br label %noerr_block177 +guard_block176: ; preds = %assign_optional174 + br label %voiderr179 +noerr_block177: ; preds = %after_check175 + %93 = load i64, ptr %len149, align 8 + %add178 = add i64 %93, 1 + br label %voiderr179 +voiderr179: ; preds = %noerr_block177, %guard_block176, %guard_block170, %guard_block164 + ret i32 0 +} + diff --git a/test/test_suite7/statements/binary_fail.c3 b/test/test_suite7/statements/binary_fail.c3 new file mode 100644 index 000000000..4e124de8d --- /dev/null +++ b/test/test_suite7/statements/binary_fail.c3 @@ -0,0 +1,8 @@ +fn void test() +{ + float a; + float b; + int *c; + int *d; + if (a + c) 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_suite7/statements/call_missing_paren.c3 b/test/test_suite7/statements/call_missing_paren.c3 new file mode 100644 index 000000000..3bcb40748 --- /dev/null +++ b/test/test_suite7/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_suite7/statements/comparison_widening.c3t b/test/test_suite7/statements/comparison_widening.c3t new file mode 100644 index 000000000..0fb2b4fa8 --- /dev/null +++ b/test/test_suite7/statements/comparison_widening.c3t @@ -0,0 +1,43 @@ +// #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 + %zext = zext i8 %1 to i32 + %gt = icmp sgt i32 %0, %zext + %check = icmp sge i32 %zext, 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 + %i2b = icmp ne i32 %2, 0 + br i1 %i2b, label %cond.lhs, label %cond.rhs + +cond.lhs: ; preds = %entry + br label %cond.phi + +cond.rhs: ; preds = %entry + br label %cond.phi + +cond.phi: ; preds = %cond.rhs, %cond.lhs + %val = phi i32 [ %2, %cond.lhs ], [ 1, %cond.rhs ] + store i32 %val, ptr %d, align 4 + ret void +} \ No newline at end of file diff --git a/test/test_suite7/statements/conditional_return.c3 b/test/test_suite7/statements/conditional_return.c3 new file mode 100644 index 000000000..1337d5c26 --- /dev/null +++ b/test/test_suite7/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_suite7/statements/const_statements.c3t b/test/test_suite7/statements/const_statements.c3t new file mode 100644 index 000000000..f4288e2df --- /dev/null +++ b/test/test_suite7/statements/const_statements.c3t @@ -0,0 +1,15 @@ +// #target: macos-x64 + +module test; +fn void main() +{ + var $x = { { 1, 2 } }; + $x; +} + +/* #expect: test.ll + +define void @test.main() #0 { +entry: + ret void +} \ No newline at end of file diff --git a/test/test_suite7/statements/custom_foreach_with_ref.c3t b/test/test_suite7/statements/custom_foreach_with_ref.c3t new file mode 100644 index 000000000..bd2093a87 --- /dev/null +++ b/test/test_suite7/statements/custom_foreach_with_ref.c3t @@ -0,0 +1,406 @@ +// #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(&[]) +{ + 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([]) +{ + 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] } + +@"$ct.foo.Foo" = linkonce global %.introspect { i8 10, i64 0, ptr null, i64 12, i64 0, i64 1, [0 x i64] zeroinitializer }, align 8 +@.str = private unnamed_addr constant [11 x i8] c"getFields\0A\00", align 1 +@.__const = private unnamed_addr constant [5 x i32] [i32 3, i32 5, i32 2, i32 10, i32 111], align 16 +@.str.1 = private unnamed_addr constant [11 x i8] c"Call made\0A\00", align 1 +@.__const.2 = private unnamed_addr constant %Foo { [3 x i32] [i32 1, i32 5, i32 7] }, align 4 +@.str.3 = private unnamed_addr constant [10 x i8] c"%d %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 [14 x i8] c"Hello %d: %d\0A\00", align 1 +@.str.6 = private unnamed_addr constant [18 x i8] c"After one %d: %d\0A\00", align 1 +@.str.7 = private unnamed_addr constant [19 x i8] c"By pointer %d: %d\0A\00", align 1 +@.str.8 = private unnamed_addr constant [15 x i8] c"Adding %d: %d\0A\00", align 1 +@.__const.9 = private unnamed_addr constant [5 x i32] [i32 1, i32 2, i32 10, i32 111, i32 123], align 16 +@.str.10 = private unnamed_addr constant [15 x i8] c"Adding %d: %d\0A\00", align 1 +@.str.11 = private unnamed_addr constant [19 x i8] c"Pull value %d: %d\0A\00", align 1 +@.str.12 = private unnamed_addr constant [27 x i8] c"Pull value tempptr %d: %d\0A\00", align 1 +@.str.13 = private unnamed_addr constant [7 x i8] c"%d %d\0A\00", align 1 +@.str.14 = private unnamed_addr constant [7 x i8] c"%d %d\0A\00", align 1 + +; Function Attrs: +declare void @printf(ptr, ...) #0 + +; Function Attrs: +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) + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %literal, ptr align 16 @.__const, i32 20, i1 false) + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %0, ptr align 4 %literal, i32 20, i1 false) + ret void +} + +; Function Attrs: +define ptr @foo.call(ptr %0) #0 { +entry: + call void (ptr, ...) @printf(ptr @.str.1) + ret ptr %0 +} + +; Function Attrs: +define void @foo.main() #0 { +entry: + %x = alloca %Foo, align 4 + %.anon = alloca i32, align 4 + %i = alloca i32, align 4 + %y = alloca i32, align 4 + %a = alloca i32, align 4 + %.anon2 = alloca i32, align 4 + %i6 = alloca i32, align 4 + %y7 = alloca ptr, align 8 + %a8 = alloca i32, align 4 + %.anon13 = alloca i32, align 4 + %i17 = alloca i32, align 4 + %y18 = alloca i32, align 4 + %a19 = alloca i32, align 4 + %.anon24 = alloca i32, align 4 + %i28 = alloca i32, align 4 + %y29 = alloca i32, align 4 + %a30 = alloca i32, align 4 + %.anon35 = alloca i32, align 4 + %i39 = alloca i32, align 4 + %y40 = alloca i32, align 4 + %a41 = alloca i32, align 4 + %.anon47 = alloca [5 x i32], align 16 + %.anon48 = alloca i64, align 8 + %i51 = alloca i64, align 8 + %y52 = alloca i32, align 4 + %.anon56 = alloca [5 x i32], align 16 + %.anon57 = alloca i64, align 8 + %i61 = alloca i64, align 8 + %y62 = alloca i32, align 4 + %sretparam = alloca [5 x i32], align 4 + %.anon66 = alloca i64, align 8 + %i70 = alloca i64, align 8 + %y71 = alloca i32, align 4 + %y76 = alloca ptr, align 8 + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %x, ptr align 4 @.__const.2, i32 12, i1 false) + %ptradd = getelementptr inbounds i8, ptr %x, i64 4 + %ptradd1 = getelementptr inbounds i8, ptr %x, i64 8 + %0 = load i32, ptr %x, align 4 + %1 = load i32, ptr %ptradd, align 4 + %2 = load i32, ptr %ptradd1, align 4 + call void (ptr, ...) @printf(ptr @.str.3, i32 %0, i32 %1, i32 %2) + %3 = call ptr @foo.call(ptr %x) + store i32 0, ptr %.anon, align 4 + br label %loop.cond + +loop.cond: ; preds = %loop.body, %entry + %4 = load i32, ptr %.anon, align 4 + %lt = icmp slt i32 %4, 3 + br i1 %lt, label %loop.body, label %loop.exit + +loop.body: ; preds = %loop.cond + %5 = load i32, ptr %.anon, align 4 + store i32 %5, ptr %i, align 4 + %6 = load i32, ptr %.anon, align 4 + store i32 %6, ptr %a, align 4 + %7 = load i32, ptr %a, align 4 + %sext = sext i32 %7 to i64 + %ptroffset = getelementptr inbounds [4 x i8], ptr %3, i64 %sext + %8 = load i32, ptr %ptroffset, align 4 + store i32 %8, ptr %y, align 4 + %9 = load i32, ptr %i, align 4 + %10 = load i32, ptr %y, align 4 + call void (ptr, ...) @printf(ptr @.str.4, i32 %9, i32 %10) + %11 = load i32, ptr %.anon, align 4 + %addnsw = add nsw i32 %11, 1 + store i32 %addnsw, ptr %.anon, align 4 + br label %loop.cond + +loop.exit: ; preds = %loop.cond + store i32 0, ptr %.anon2, align 4 + br label %loop.cond3 + +loop.cond3: ; preds = %loop.body5, %loop.exit + %12 = load i32, ptr %.anon2, align 4 + %lt4 = icmp slt i32 %12, 3 + br i1 %lt4, label %loop.body5, label %loop.exit12 + +loop.body5: ; preds = %loop.cond3 + %13 = load i32, ptr %.anon2, align 4 + store i32 %13, ptr %i6, align 4 + %14 = load i32, ptr %.anon2, align 4 + store i32 %14, ptr %a8, align 4 + %15 = load i32, ptr %a8, align 4 + %sext9 = sext i32 %15 to i64 + %ptroffset10 = getelementptr inbounds [4 x i8], ptr %x, i64 %sext9 + store ptr %ptroffset10, ptr %y7, align 8 + %16 = load ptr, ptr %y7, align 8 + %17 = load i32, ptr %16, align 4 + %add = add i32 %17, 1 + store i32 %add, ptr %16, align 4 + %18 = load ptr, ptr %y7, align 8 + %19 = load i32, ptr %i6, align 4 + %20 = load i32, ptr %18, align 4 + call void (ptr, ...) @printf(ptr @.str.5, i32 %19, i32 %20) + %21 = load i32, ptr %.anon2, align 4 + %addnsw11 = add nsw i32 %21, 1 + store i32 %addnsw11, ptr %.anon2, align 4 + br label %loop.cond3 + +loop.exit12: ; preds = %loop.cond3 + store i32 0, ptr %.anon13, align 4 + br label %loop.cond14 + +loop.cond14: ; preds = %loop.body16, %loop.exit12 + %22 = load i32, ptr %.anon13, align 4 + %lt15 = icmp slt i32 %22, 3 + br i1 %lt15, label %loop.body16, label %loop.exit23 + +loop.body16: ; preds = %loop.cond14 + %23 = load i32, ptr %.anon13, align 4 + store i32 %23, ptr %i17, align 4 + %24 = load i32, ptr %.anon13, align 4 + store i32 %24, ptr %a19, align 4 + %25 = load i32, ptr %a19, align 4 + %sext20 = sext i32 %25 to i64 + %ptroffset21 = getelementptr inbounds [4 x i8], ptr %x, i64 %sext20 + %26 = load i32, ptr %ptroffset21, align 4 + store i32 %26, ptr %y18, align 4 + %27 = load i32, ptr %i17, align 4 + %28 = load i32, ptr %y18, align 4 + call void (ptr, ...) @printf(ptr @.str.6, i32 %27, i32 %28) + %29 = load i32, ptr %.anon13, align 4 + %addnsw22 = add nsw i32 %29, 1 + store i32 %addnsw22, ptr %.anon13, align 4 + br label %loop.cond14 + +loop.exit23: ; preds = %loop.cond14 + store i32 0, ptr %.anon24, align 4 + br label %loop.cond25 + +loop.cond25: ; preds = %loop.body27, %loop.exit23 + %30 = load i32, ptr %.anon24, align 4 + %lt26 = icmp slt i32 %30, 3 + br i1 %lt26, label %loop.body27, label %loop.exit34 + +loop.body27: ; preds = %loop.cond25 + %31 = load i32, ptr %.anon24, align 4 + store i32 %31, ptr %i28, align 4 + %32 = load i32, ptr %.anon24, align 4 + store i32 %32, ptr %a30, align 4 + %33 = load i32, ptr %a30, align 4 + %sext31 = sext i32 %33 to i64 + %ptroffset32 = getelementptr inbounds [4 x i8], ptr %x, i64 %sext31 + %34 = load i32, ptr %ptroffset32, align 4 + store i32 %34, ptr %y29, align 4 + %35 = load i32, ptr %i28, align 4 + %36 = load i32, ptr %y29, align 4 + call void (ptr, ...) @printf(ptr @.str.7, i32 %35, i32 %36) + %37 = load i32, ptr %.anon24, align 4 + %addnsw33 = add nsw i32 %37, 1 + store i32 %addnsw33, ptr %.anon24, align 4 + br label %loop.cond25 + +loop.exit34: ; preds = %loop.cond25 + store i32 0, ptr %.anon35, align 4 + br label %loop.cond36 + +loop.cond36: ; preds = %loop.body38, %loop.exit34 + %38 = load i32, ptr %.anon35, align 4 + %lt37 = icmp slt i32 %38, 3 + br i1 %lt37, label %loop.body38, label %loop.exit46 + +loop.body38: ; preds = %loop.cond36 + %39 = load i32, ptr %.anon35, align 4 + store i32 %39, ptr %i39, align 4 + %40 = load i32, ptr %.anon35, align 4 + store i32 %40, ptr %a41, align 4 + %41 = load i32, ptr %a41, align 4 + %sext42 = sext i32 %41 to i64 + %ptroffset43 = getelementptr inbounds [4 x i8], ptr %x, i64 %sext42 + %42 = load i32, ptr %ptroffset43, align 4 + store i32 %42, ptr %y40, align 4 + %43 = load i32, ptr %i39, align 4 + %44 = load i32, ptr %y40, align 4 + call void (ptr, ...) @printf(ptr @.str.8, i32 %43, i32 %44) + %45 = load i32, ptr %i39, align 4 + %add44 = add i32 %45, 1 + store i32 %add44, ptr %i39, align 4 + %46 = load i32, ptr %.anon35, align 4 + %addnsw45 = add nsw i32 %46, 1 + store i32 %addnsw45, ptr %.anon35, align 4 + br label %loop.cond36 + +loop.exit46: ; preds = %loop.cond36 + call void @llvm.memcpy.p0.p0.i32(ptr align 16 %.anon47, ptr align 16 @.__const.9, i32 20, i1 false) + store i64 0, ptr %.anon48, align 8 + br label %loop.cond49 + +loop.cond49: ; preds = %loop.body50, %loop.exit46 + %47 = load i64, ptr %.anon48, align 8 + %gt = icmp ugt i64 5, %47 + br i1 %gt, label %loop.body50, label %loop.exit55 + +loop.body50: ; preds = %loop.cond49 + %48 = load i64, ptr %.anon48, align 8 + store i64 %48, ptr %i51, align 8 + %49 = load i64, ptr %.anon48, align 8 + %ptroffset53 = getelementptr inbounds [4 x i8], ptr %.anon47, i64 %49 + %50 = load i32, ptr %ptroffset53, align 4 + store i32 %50, ptr %y52, align 4 + %51 = load i64, ptr %i51, align 8 + %52 = load i32, ptr %y52, align 4 + call void (ptr, ...) @printf(ptr @.str.10, i64 %51, i32 %52) + %53 = load i64, ptr %i51, align 8 + %add54 = add i64 %53, 1 + store i64 %add54, ptr %i51, align 8 + %54 = load i64, ptr %.anon48, align 8 + %addnuw = add nuw i64 %54, 1 + store i64 %addnuw, ptr %.anon48, align 8 + br label %loop.cond49 + +loop.exit55: ; preds = %loop.cond49 + call void @foo.getFields(ptr sret([5 x i32]) align 4 %.anon56) + store i64 0, ptr %.anon57, align 8 + br label %loop.cond58 + +loop.cond58: ; preds = %loop.body60, %loop.exit55 + %55 = load i64, ptr %.anon57, align 8 + %gt59 = icmp ugt i64 5, %55 + br i1 %gt59, label %loop.body60, label %loop.exit65 + +loop.body60: ; preds = %loop.cond58 + %56 = load i64, ptr %.anon57, align 8 + store i64 %56, ptr %i61, align 8 + %57 = load i64, ptr %.anon57, align 8 + %ptroffset63 = getelementptr inbounds [4 x i8], ptr %.anon56, i64 %57 + %58 = load i32, ptr %ptroffset63, align 4 + store i32 %58, ptr %y62, align 4 + %59 = load i64, ptr %i61, align 8 + %60 = load i32, ptr %y62, align 4 + call void (ptr, ...) @printf(ptr @.str.11, i64 %59, i32 %60) + %61 = load i64, ptr %.anon57, align 8 + %addnuw64 = add nuw i64 %61, 1 + store i64 %addnuw64, ptr %.anon57, align 8 + br label %loop.cond58 + +loop.exit65: ; preds = %loop.cond58 + call void @foo.getFields(ptr sret([5 x i32]) align 4 %sretparam) + store i64 0, ptr %.anon66, align 8 + br label %loop.cond67 + +loop.cond67: ; preds = %loop.body69, %loop.exit65 + %62 = load i64, ptr %.anon66, align 8 + %gt68 = icmp ugt i64 5, %62 + br i1 %gt68, label %loop.body69, label %loop.exit74 + +loop.body69: ; preds = %loop.cond67 + %63 = load i64, ptr %.anon66, align 8 + store i64 %63, ptr %i70, align 8 + %64 = load i64, ptr %.anon66, align 8 + %ptroffset72 = getelementptr inbounds [4 x i8], ptr %sretparam, i64 %64 + %65 = load i32, ptr %ptroffset72, align 4 + store i32 %65, ptr %y71, align 4 + %66 = load i64, ptr %i70, align 8 + %67 = load i32, ptr %y71, align 4 + call void (ptr, ...) @printf(ptr @.str.12, i64 %66, i32 %67) + %68 = load i64, ptr %.anon66, align 8 + %addnuw73 = add nuw i64 %68, 1 + store i64 %addnuw73, ptr %.anon66, align 8 + br label %loop.cond67 + +loop.exit74: ; preds = %loop.cond67 + %ptradd75 = getelementptr inbounds i8, ptr %x, i64 4 + %69 = load i32, ptr %x, align 4 + %70 = load i32, ptr %ptradd75, align 4 + call void (ptr, ...) @printf(ptr @.str.13, i32 %69, i32 %70) + %ptradd77 = getelementptr inbounds i8, ptr %x, i64 4 + store ptr %ptradd77, ptr %y76, align 8 + %71 = load ptr, ptr %y76, align 8 + %72 = load i32, ptr %71, align 4 + %add78 = add i32 %72, 1 + store i32 %add78, ptr %71, align 4 + %ptradd79 = getelementptr inbounds i8, ptr %x, i64 4 + %73 = load i32, ptr %x, align 4 + %74 = load i32, ptr %ptradd79, align 4 + call void (ptr, ...) @printf(ptr @.str.14, i32 %73, i32 %74) + ret void +} diff --git a/test/test_suite7/statements/dead_statements.c3t b/test/test_suite7/statements/dead_statements.c3t new file mode 100644 index 000000000..341c5cb4f --- /dev/null +++ b/test/test_suite7/statements/dead_statements.c3t @@ -0,0 +1,44 @@ +// #target: macos-x64 +module test; +import std::io; +import std::io::path; +import std::collections::list; + +fn void! load_corpus2(String code, String path) @local +{ + for(;;) io::printfn("hi"); + path::Path p = path::temp_new(path)!; // #warning: This code will never execute + + if (!path::exists(p)) + { + return IoError.FILE_NOT_FOUND?; + } +} + +fn int main(String[] args) +{ + if (catch err = load_corpus2("foo", "bar")) + { + return 1; + } + return 0; +} +/* #expect: test.ll + +define internal i64 @test.load_corpus2(ptr %0, i64 %1, ptr %2, i64 %3) #0 { +entry: + %code = alloca %"char[]", align 8 + %path = alloca %"char[]", align 8 + %retparam = alloca i64, align 8 + store ptr %0, ptr %code, align 8 + %ptradd = getelementptr inbounds i8, ptr %code, i64 8 + store i64 %1, ptr %ptradd, align 8 + store ptr %2, ptr %path, align 8 + %ptradd1 = getelementptr inbounds i8, ptr %path, i64 8 + store i64 %3, ptr %ptradd1, align 8 + br label %loop.body + +loop.body: ; preds = %loop.body, %entry + %4 = call i64 @std.io.printfn(ptr %retparam, ptr @.str, i64 2, ptr null, i64 0) + br label %loop.body +} diff --git a/test/test_suite7/statements/default_args.c3 b/test/test_suite7/statements/default_args.c3 new file mode 100644 index 000000000..b90fd6caa --- /dev/null +++ b/test/test_suite7/statements/default_args.c3 @@ -0,0 +1,4 @@ + +def Foo = fn void(int a = 10); +fn int abc() { return 1; } +def Foo2 = fn void(int a = abc()); diff --git a/test/test_suite7/statements/default_macro_argc.c3t b/test/test_suite7/statements/default_macro_argc.c3t new file mode 100644 index 000000000..1d14c8a77 --- /dev/null +++ b/test/test_suite7/statements/default_macro_argc.c3t @@ -0,0 +1,287 @@ +// #target: linux-x64 +module test; +import std, test2; + +int[2] x; + +macro @test2(#a = x[1]) +{ + #a = 123; +} +macro test($Type = int) { io::printn($Type.nameof); } + +fn void testme() { io::printn("Testme"); } +macro @test3(#foo = testme()) => #foo; + +fn void main() +{ + test(); + @test2(); + @test3(); + io::printn(x); + test2::test(); + test2::@test2(); + test2::@test3(); + io::printn(test2::x); + +} + +module test2; +import std; + +int[2] x; + +macro @test2(#a = x[1]) +{ + #a = 12; +} +macro test($Type = double) { io::printn($Type.nameof); } + +fn void testme() { io::printn("Testme2"); } +macro @test3(#foo = testme()) => #foo; + +/* #expect: test.ll + + +define void @test.main() #0 { +entry: + %len = alloca i64, align 8 + %error_var = alloca i64, align 8 + %retparam = alloca i64, align 8 + %error_var2 = alloca i64, align 8 + %error_var8 = alloca i64, align 8 + %x = alloca [2 x i32], align 4 + %x14 = alloca [2 x i32], align 4 + %len15 = alloca i64, align 8 + %error_var16 = alloca i64, align 8 + %x17 = alloca [2 x i32], align 4 + %varargslots = alloca [1 x %any], align 16 + %retparam19 = alloca i64, align 8 + %taddr = alloca %any, align 8 + %indirectarg = alloca %"any[]", align 8 + %error_var25 = alloca i64, align 8 + %error_var31 = alloca i64, align 8 + %len39 = alloca i64, align 8 + %error_var40 = alloca i64, align 8 + %retparam42 = alloca i64, align 8 + %error_var48 = alloca i64, align 8 + %error_var54 = alloca i64, align 8 + %x62 = alloca [2 x i32], align 4 + %x63 = alloca [2 x i32], align 4 + %len64 = alloca i64, align 8 + %error_var65 = alloca i64, align 8 + %x66 = alloca [2 x i32], align 4 + %varargslots68 = alloca [1 x %any], align 16 + %retparam70 = alloca i64, align 8 + %taddr71 = alloca %any, align 8 + %indirectarg75 = alloca %"any[]", align 8 + %error_var81 = alloca i64, align 8 + %error_var87 = alloca i64, align 8 + %0 = call ptr @std.io.stdout() + %1 = call i64 @std.io.File.write(ptr %retparam, ptr %0, ptr @.str.1, i64 3) + %not_err = icmp eq i64 %1, 0 + %2 = call i1 @llvm.expect.i1(i1 %not_err, i1 true) + br i1 %2, label %after_check, label %assign_optional +assign_optional: ; preds = %entry + store i64 %1, ptr %error_var, align 8 + br label %guard_block +after_check: ; preds = %entry + br label %noerr_block +guard_block: ; preds = %assign_optional + br label %voiderr +noerr_block: ; preds = %after_check + %3 = load i64, ptr %retparam, align 8 + store i64 %3, ptr %len, align 8 + %4 = call i64 @std.io.File.write_byte(ptr %0, i8 zeroext 10) + %not_err3 = icmp eq i64 %4, 0 + %5 = call i1 @llvm.expect.i1(i1 %not_err3, i1 true) + br i1 %5, label %after_check5, label %assign_optional4 +assign_optional4: ; preds = %noerr_block + store i64 %4, ptr %error_var2, align 8 + br label %guard_block6 +after_check5: ; preds = %noerr_block + br label %noerr_block7 +guard_block6: ; preds = %assign_optional4 + br label %voiderr +noerr_block7: ; preds = %after_check5 + %6 = call i64 @std.io.File.flush(ptr %0) + %not_err9 = icmp eq i64 %6, 0 + %7 = call i1 @llvm.expect.i1(i1 %not_err9, i1 true) + br i1 %7, label %after_check11, label %assign_optional10 +assign_optional10: ; preds = %noerr_block7 + store i64 %6, ptr %error_var8, align 8 + br label %guard_block12 +after_check11: ; preds = %noerr_block7 + br label %noerr_block13 +guard_block12: ; preds = %assign_optional10 + br label %voiderr +noerr_block13: ; preds = %after_check11 + %8 = load i64, ptr %len, align 8 + %add = add i64 %8, 1 + br label %voiderr +voiderr: ; preds = %noerr_block13, %guard_block12, %guard_block6, %guard_block + store i32 123, ptr getelementptr inbounds (i8, ptr @test.x, i64 4), align 4 + call void @test.testme() + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %x, ptr align 4 @test.x, i32 8, i1 false) + %9 = call ptr @std.io.stdout() + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %x14, ptr align 4 %x, i32 8, i1 false) + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %x17, ptr align 4 %x14, i32 8, i1 false) + %10 = insertvalue %any undef, ptr %9, 0 + %11 = insertvalue %any %10, i64 ptrtoint (ptr @"$ct.std.io.File" to i64), 1 + %12 = insertvalue %any undef, ptr %x17, 0 + %13 = insertvalue %any %12, i64 ptrtoint (ptr @"$ct.a2$int" to i64), 1 + store %any %13, ptr %varargslots, align 16 + %14 = insertvalue %"any[]" undef, ptr %varargslots, 0 + %"$$temp" = insertvalue %"any[]" %14, i64 1, 1 + store %any %11, ptr %taddr, align 8 + %lo = load i64, ptr %taddr, align 8 + %ptradd = getelementptr inbounds i8, ptr %taddr, i64 8 + %hi = load ptr, ptr %ptradd, align 8 + store %"any[]" %"$$temp", ptr %indirectarg, align 8 + %15 = call i64 @std.io.fprintf(ptr %retparam19, i64 %lo, ptr %hi, ptr @.str.2, i64 2, ptr byval(%"any[]") align 8 %indirectarg) + %not_err20 = icmp eq i64 %15, 0 + %16 = call i1 @llvm.expect.i1(i1 %not_err20, i1 true) + br i1 %16, label %after_check22, label %assign_optional21 +assign_optional21: ; preds = %voiderr + store i64 %15, ptr %error_var16, align 8 + br label %guard_block23 +after_check22: ; preds = %voiderr + br label %noerr_block24 +guard_block23: ; preds = %assign_optional21 + br label %voiderr38 +noerr_block24: ; preds = %after_check22 + %17 = load i64, ptr %retparam19, align 8 + store i64 %17, ptr %len15, align 8 + %18 = call i64 @std.io.File.write_byte(ptr %9, i8 zeroext 10) + %not_err26 = icmp eq i64 %18, 0 + %19 = call i1 @llvm.expect.i1(i1 %not_err26, i1 true) + br i1 %19, label %after_check28, label %assign_optional27 +assign_optional27: ; preds = %noerr_block24 + store i64 %18, ptr %error_var25, align 8 + br label %guard_block29 +after_check28: ; preds = %noerr_block24 + br label %noerr_block30 +guard_block29: ; preds = %assign_optional27 + br label %voiderr38 +noerr_block30: ; preds = %after_check28 + %20 = call i64 @std.io.File.flush(ptr %9) + %not_err32 = icmp eq i64 %20, 0 + %21 = call i1 @llvm.expect.i1(i1 %not_err32, i1 true) + br i1 %21, label %after_check34, label %assign_optional33 +assign_optional33: ; preds = %noerr_block30 + store i64 %20, ptr %error_var31, align 8 + br label %guard_block35 +after_check34: ; preds = %noerr_block30 + br label %noerr_block36 +guard_block35: ; preds = %assign_optional33 + br label %voiderr38 +noerr_block36: ; preds = %after_check34 + %22 = load i64, ptr %len15, align 8 + %add37 = add i64 %22, 1 + br label %voiderr38 +voiderr38: ; preds = %noerr_block36, %guard_block35, %guard_block29, %guard_block23 + %23 = call ptr @std.io.stdout() + %24 = call i64 @std.io.File.write(ptr %retparam42, ptr %23, ptr @.str.3, i64 6) + %not_err43 = icmp eq i64 %24, 0 + %25 = call i1 @llvm.expect.i1(i1 %not_err43, i1 true) + br i1 %25, label %after_check45, label %assign_optional44 +assign_optional44: ; preds = %voiderr38 + store i64 %24, ptr %error_var40, align 8 + br label %guard_block46 +after_check45: ; preds = %voiderr38 + br label %noerr_block47 +guard_block46: ; preds = %assign_optional44 + br label %voiderr61 +noerr_block47: ; preds = %after_check45 + %26 = load i64, ptr %retparam42, align 8 + store i64 %26, ptr %len39, align 8 + %27 = call i64 @std.io.File.write_byte(ptr %23, i8 zeroext 10) + %not_err49 = icmp eq i64 %27, 0 + %28 = call i1 @llvm.expect.i1(i1 %not_err49, i1 true) + br i1 %28, label %after_check51, label %assign_optional50 +assign_optional50: ; preds = %noerr_block47 + store i64 %27, ptr %error_var48, align 8 + br label %guard_block52 +after_check51: ; preds = %noerr_block47 + br label %noerr_block53 +guard_block52: ; preds = %assign_optional50 + br label %voiderr61 +noerr_block53: ; preds = %after_check51 + %29 = call i64 @std.io.File.flush(ptr %23) + %not_err55 = icmp eq i64 %29, 0 + %30 = call i1 @llvm.expect.i1(i1 %not_err55, i1 true) + br i1 %30, label %after_check57, label %assign_optional56 +assign_optional56: ; preds = %noerr_block53 + store i64 %29, ptr %error_var54, align 8 + br label %guard_block58 +after_check57: ; preds = %noerr_block53 + br label %noerr_block59 +guard_block58: ; preds = %assign_optional56 + br label %voiderr61 +noerr_block59: ; preds = %after_check57 + %31 = load i64, ptr %len39, align 8 + %add60 = add i64 %31, 1 + br label %voiderr61 +voiderr61: ; preds = %noerr_block59, %guard_block58, %guard_block52, %guard_block46 + store i32 12, ptr getelementptr inbounds (i8, ptr @test2.x, i64 4), align 4 + call void @test2.testme() + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %x62, ptr align 4 @test2.x, i32 8, i1 false) + %32 = call ptr @std.io.stdout() + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %x63, ptr align 4 %x62, i32 8, i1 false) + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %x66, ptr align 4 %x63, i32 8, i1 false) + %33 = insertvalue %any undef, ptr %32, 0 + %34 = insertvalue %any %33, i64 ptrtoint (ptr @"$ct.std.io.File" to i64), 1 + %35 = insertvalue %any undef, ptr %x66, 0 + %36 = insertvalue %any %35, i64 ptrtoint (ptr @"$ct.a2$int" to i64), 1 + store %any %36, ptr %varargslots68, align 16 + %37 = insertvalue %"any[]" undef, ptr %varargslots68, 0 + %"$$temp69" = insertvalue %"any[]" %37, i64 1, 1 + store %any %34, ptr %taddr71, align 8 + %lo72 = load i64, ptr %taddr71, align 8 + %ptradd73 = getelementptr inbounds i8, ptr %taddr71, i64 8 + %hi74 = load ptr, ptr %ptradd73, align 8 + store %"any[]" %"$$temp69", ptr %indirectarg75, align 8 + %38 = call i64 @std.io.fprintf(ptr %retparam70, i64 %lo72, ptr %hi74, ptr @.str.4, i64 2, ptr byval(%"any[]") align 8 %indirectarg75) + %not_err76 = icmp eq i64 %38, 0 + %39 = call i1 @llvm.expect.i1(i1 %not_err76, i1 true) + br i1 %39, label %after_check78, label %assign_optional77 +assign_optional77: ; preds = %voiderr61 + store i64 %38, ptr %error_var65, align 8 + br label %guard_block79 +after_check78: ; preds = %voiderr61 + br label %noerr_block80 +guard_block79: ; preds = %assign_optional77 + br label %voiderr94 +noerr_block80: ; preds = %after_check78 + %40 = load i64, ptr %retparam70, align 8 + store i64 %40, ptr %len64, align 8 + %41 = call i64 @std.io.File.write_byte(ptr %32, i8 zeroext 10) + %not_err82 = icmp eq i64 %41, 0 + %42 = call i1 @llvm.expect.i1(i1 %not_err82, i1 true) + br i1 %42, label %after_check84, label %assign_optional83 +assign_optional83: ; preds = %noerr_block80 + store i64 %41, ptr %error_var81, align 8 + br label %guard_block85 +after_check84: ; preds = %noerr_block80 + br label %noerr_block86 +guard_block85: ; preds = %assign_optional83 + br label %voiderr94 +noerr_block86: ; preds = %after_check84 + %43 = call i64 @std.io.File.flush(ptr %32) + %not_err88 = icmp eq i64 %43, 0 + %44 = call i1 @llvm.expect.i1(i1 %not_err88, i1 true) + br i1 %44, label %after_check90, label %assign_optional89 +assign_optional89: ; preds = %noerr_block86 + store i64 %43, ptr %error_var87, align 8 + br label %guard_block91 +after_check90: ; preds = %noerr_block86 + br label %noerr_block92 +guard_block91: ; preds = %assign_optional89 + br label %voiderr94 +noerr_block92: ; preds = %after_check90 + %45 = load i64, ptr %len64, align 8 + %add93 = add i64 %45, 1 + br label %voiderr94 +voiderr94: ; preds = %noerr_block92, %guard_block91, %guard_block85, %guard_block79 + ret void +} diff --git a/test/test_suite7/statements/defer_break.c3t b/test/test_suite7/statements/defer_break.c3t new file mode 100644 index 000000000..b14d5ff4b --- /dev/null +++ b/test/test_suite7/statements/defer_break.c3t @@ -0,0 +1,114 @@ +// #target: macos-x64 +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; + } + 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 + %i2b = icmp ne i32 %3, 0 + br i1 %i2b, 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 + %i2b6 = icmp ne i32 %4, 0 + br i1 %i2b6, 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_suite7/statements/defer_break_simple.c3t b/test/test_suite7/statements/defer_break_simple.c3t new file mode 100644 index 000000000..de8c5c2fc --- /dev/null +++ b/test/test_suite7/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 + %i2b = icmp ne i32 %2, 0 + br i1 %i2b, 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_suite7/statements/defer_break_switch.c3t b/test/test_suite7/statements/defer_break_switch.c3t new file mode 100644 index 000000000..2e03a42c3 --- /dev/null +++ b/test/test_suite7/statements/defer_break_switch.c3t @@ -0,0 +1,60 @@ +// #target: macos-x64 + +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_suite7/statements/defer_continue_bug.c3t b/test/test_suite7/statements/defer_continue_bug.c3t new file mode 100644 index 000000000..c8c89e5d0 --- /dev/null +++ b/test/test_suite7/statements/defer_continue_bug.c3t @@ -0,0 +1,59 @@ +// #target: macos-aarch64 +module test; + +fn int main() +{ + int[4] x = { 1, 4, 5, 7 }; + defer + { + foreach (i : x) + { + if (i % 2 == 0) continue; + int a = 123; + } + } + return 0; +} + +/* #expect: test.ll + +entry: + %x = alloca [4 x i32], align 4 + %.anon = alloca i64, align 8 + %i = alloca i32, align 4 + %a = alloca i32, align 4 + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %x, ptr align 4 @.__const, i32 16, i1 false) + store i64 0, ptr %.anon, align 8 + br label %loop.cond + +loop.cond: ; preds = %loop.inc, %entry + %0 = load i64, ptr %.anon, align 8 + %gt = icmp ugt i64 4, %0 + br i1 %gt, label %loop.body, label %loop.exit + +loop.body: ; preds = %loop.cond + %1 = load i64, ptr %.anon, align 8 + %ptroffset = getelementptr inbounds [4 x i8], ptr %x, i64 %1 + %2 = load i32, ptr %ptroffset, align 4 + store i32 %2, ptr %i, align 4 + %3 = load i32, ptr %i, align 4 + %smod = srem i32 %3, 2 + %eq = icmp eq i32 %smod, 0 + br i1 %eq, label %if.then, label %if.exit + +if.then: ; preds = %loop.body + br label %loop.inc + +if.exit: ; preds = %loop.body + store i32 123, ptr %a, align 4 + br label %loop.inc + +loop.inc: ; preds = %if.exit, %if.then + %4 = load i64, ptr %.anon, align 8 + %addnuw = add nuw i64 %4, 1 + store i64 %addnuw, ptr %.anon, align 8 + br label %loop.cond + +loop.exit: ; preds = %loop.cond + ret i32 0 +} diff --git a/test/test_suite7/statements/defer_do_while.c3t b/test/test_suite7/statements/defer_do_while.c3t new file mode 100644 index 000000000..d401502c8 --- /dev/null +++ b/test/test_suite7/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_suite7/statements/defer_hash.c3t b/test/test_suite7/statements/defer_hash.c3t new file mode 100644 index 000000000..7e689fe4e --- /dev/null +++ b/test/test_suite7/statements/defer_hash.c3t @@ -0,0 +1,45 @@ +import std::io; + +struct Version { + uint major; + uint minor; +} + +fn void main() +{ + String s = "123.456"; + + Version v; + v.major = @read_int(s); + s = s[1..]; + v.minor = @read_int(s); + + io::printfn("Version{.major = %d, .minor = %d}", v.major, v.minor); +} + +<* + @require values::@is_lvalue(#s) +*> +macro int @read_int(String #s) +{ + int res = 0; + int i = 0; + + String s = #s; + defer #s = s[i..]; // commenting out this lines leads to a successful compilation + + while (i < s.len && s[i].is_space()) + { + ++i; + } + + if (i >= s.len) return res; + + char c; + while (i < s.len && (c = s[i]).is_digit()) + { + res = (10 * res) + (c - '0'); + ++i; + } + return res; +} \ No newline at end of file diff --git a/test/test_suite7/statements/defer_if_try_copy.c3t b/test/test_suite7/statements/defer_if_try_copy.c3t new file mode 100644 index 000000000..74c7dc7dd --- /dev/null +++ b/test/test_suite7/statements/defer_if_try_copy.c3t @@ -0,0 +1,36 @@ +// #target: macos-x64 +module foo; +import std; +fn int main() +{ + int! cmd = 3; + defer + { + if (try cmd) { io::printfn("HO! %s", cmd); } + } + return 0; +} +/* #expect: foo.ll + +define i32 @main() #0 { +entry: + %cmd = alloca i32, align 4 + %cmd.f = alloca i64, align 8 + %varargslots = alloca [1 x %any], align 16 + %retparam = alloca i64, align 8 + store i32 3, ptr %cmd, align 4 + store i64 0, ptr %cmd.f, align 8 + %load.err = load i64, ptr %cmd.f, align 8 + %result = icmp eq i64 %load.err, 0 + br i1 %result, label %if.then, label %if.exit + +if.then: ; preds = %entry + %0 = insertvalue %any undef, ptr %cmd, 0 + %1 = insertvalue %any %0, i64 ptrtoint (ptr @"$ct.int" to i64), 1 + store %any %1, ptr %varargslots, align 16 + %2 = call i64 @std.io.printfn(ptr %retparam, ptr @.str, i64 6, ptr %varargslots, i64 1) + br label %if.exit + +if.exit: ; preds = %if.then, %entry + ret i32 0 +} diff --git a/test/test_suite7/statements/defer_in_block.c3t b/test/test_suite7/statements/defer_in_block.c3t new file mode 100644 index 000000000..2421a0b02 --- /dev/null +++ b/test/test_suite7/statements/defer_in_block.c3t @@ -0,0 +1,88 @@ +// #target: macos-x64 +// #deprecation: no +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 +} + + +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_suite7/statements/defer_in_defer.c3t b/test/test_suite7/statements/defer_in_defer.c3t new file mode 100644 index 000000000..eefb0a289 --- /dev/null +++ b/test/test_suite7/statements/defer_in_defer.c3t @@ -0,0 +1,38 @@ +// #target: macos-aarch64 +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_suite7/statements/defer_in_defer2.c3t b/test/test_suite7/statements/defer_in_defer2.c3t new file mode 100644 index 000000000..5de8af3a3 --- /dev/null +++ b/test/test_suite7/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_suite7/statements/defer_in_defer3.c3t b/test/test_suite7/statements/defer_in_defer3.c3t new file mode 100644 index 000000000..cef9b6a37 --- /dev/null +++ b/test/test_suite7/statements/defer_in_defer3.c3t @@ -0,0 +1,46 @@ +// #target: macos-x64 +// #debuginfo: yes +module test; +extern fn void printf(char*,...); + +fn void test(int x) +{ + defer + { + do + { + defer { + x = 0; + printf("Hello\n"); + defer x = 1; + } + if (x < 100) break; + }; + } +} + +fn int main() +{ + test(0); + return 0; +} + +/* #expect: test.ll + + %x = alloca i32, align 4 + store i32 %0, ptr %x, align 4 + %1 = load i32, ptr %x, align 4, !dbg !15 + %lt = icmp slt i32 %1, 100, !dbg !15 + br i1 %lt, label %if.then, label %if.exit, !dbg !15 +if.then: ; preds = %entry + store i32 0, ptr %x, align 4, !dbg !19 + call void (ptr, ...) @printf(ptr @.str), !dbg !21 + store i32 1, ptr %x, align 4, !dbg !22 + br label %loop.exit, !dbg !22 +if.exit: ; preds = %entry + store i32 0, ptr %x, align 4, !dbg !24 + call void (ptr, ...) @printf(ptr @.str.1), !dbg !26 + store i32 1, ptr %x, align 4, !dbg !27 + br label %loop.exit, !dbg !27 +loop.exit: ; preds = %if.exit, %if.then + ret void, !dbg !27 \ No newline at end of file diff --git a/test/test_suite7/statements/defer_next_switch.c3t b/test/test_suite7/statements/defer_next_switch.c3t new file mode 100644 index 000000000..0c0afb59d --- /dev/null +++ b/test/test_suite7/statements/defer_next_switch.c3t @@ -0,0 +1,59 @@ +// #target: macos-aarch64 +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_suite7/statements/defer_return.c3t b/test/test_suite7/statements/defer_return.c3t new file mode 100644 index 000000000..b51506559 --- /dev/null +++ b/test/test_suite7/statements/defer_return.c3t @@ -0,0 +1,99 @@ +// #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; + } + 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 + %i2b = icmp ne i32 %2, 0 + br i1 %i2b, 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 + %i2b2 = icmp ne i32 %4, 0 + br i1 %i2b2, 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_suite7/statements/defer_test.c3 b/test/test_suite7/statements/defer_test.c3 new file mode 100644 index 000000000..81b9bf3e9 --- /dev/null +++ b/test/test_suite7/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_suite7/statements/defer_with_loop.c3t b/test/test_suite7/statements/defer_with_loop.c3t new file mode 100644 index 000000000..be69a28bc --- /dev/null +++ b/test/test_suite7/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_suite7/statements/do_without_compound.c3 b/test/test_suite7/statements/do_without_compound.c3 new file mode 100644 index 000000000..b37b73729 --- /dev/null +++ b/test/test_suite7/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_suite7/statements/exhaustive_switch.c3t b/test/test_suite7/statements/exhaustive_switch.c3t new file mode 100644 index 000000000..562536d4e --- /dev/null +++ b/test/test_suite7/statements/exhaustive_switch.c3t @@ -0,0 +1,39 @@ +// #target: macos-x64 +module test; +import std::io; + +enum Foo +{ + ABC, + DEF +} + +fn int hello(Foo a) +{ + switch (a) + { + case ABC: return 1; + case DEF: return 0; + } +} + +/* #expect: test.ll + +define i32 @test.hello(i32 %0) #0 { +entry: + %switch = 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.case1 + ] +switch.case: ; preds = %switch.entry + ret i32 1 +switch.case1: ; preds = %switch.entry + ret i32 0 +switch.exit: ; preds = %switch.entry + unreachable +} diff --git a/test/test_suite7/statements/fallthough_do.c3t b/test/test_suite7/statements/fallthough_do.c3t new file mode 100644 index 000000000..3799ea3a4 --- /dev/null +++ b/test/test_suite7/statements/fallthough_do.c3t @@ -0,0 +1,80 @@ +// #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 = call i32 @foo.test() + %2 = load i32, ptr %i, align 4 + call void (ptr, ...) @printf(ptr @.str.1, i32 %2, i32 %1) + %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 = call i32 @foo.test() + %5 = load i32, ptr %i, align 4 + call void (ptr, ...) @printf(ptr @.str.2, i32 %5, i32 %4) + 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 = call i32 @foo.test() + %8 = load i32, ptr %i, align 4 + call void (ptr, ...) @printf(ptr @.str.3, i32 %8, i32 %7) + br label %loop.exit4 + +loop.exit4: ; preds = %if.exit3, %if.then2 + ret void +} diff --git a/test/test_suite7/statements/for.c3 b/test/test_suite7/statements/for.c3 new file mode 100644 index 000000000..eff1fcdc7 --- /dev/null +++ b/test/test_suite7/statements/for.c3 @@ -0,0 +1,24 @@ +module for_test; + + + +fn int test1() +{ + for (int x = 0;;) + { + } +} + +fn int test2() +{ + for (int x = 0; 1 ;) + { + } +} + +fn int test3() +{ + for (; 1 ;2) + { + } +} diff --git a/test/test_suite7/statements/for_empty.c3 b/test/test_suite7/statements/for_empty.c3 new file mode 100644 index 000000000..d795a0173 --- /dev/null +++ b/test/test_suite7/statements/for_empty.c3 @@ -0,0 +1,8 @@ +fn int test1() +{ + for (;;); +} +fn int test2() +{ + for (;;) {} +} diff --git a/test/test_suite7/statements/for_errors.c3 b/test/test_suite7/statements/for_errors.c3 new file mode 100644 index 000000000..c013a65bc --- /dev/null +++ b/test/test_suite7/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_suite7/statements/for_statement_placement.c3 b/test/test_suite7/statements/for_statement_placement.c3 new file mode 100644 index 000000000..a3160537b --- /dev/null +++ b/test/test_suite7/statements/for_statement_placement.c3 @@ -0,0 +1,13 @@ +fn void test(int x) +{} + +fn void main() +{ + for (int i = 0; i < 10; i++) test( + i + ); + for (int i = 0; i < 10; i++) + test( // #error: A single statement after + i + ); +} \ No newline at end of file diff --git a/test/test_suite7/statements/for_with_extra_declarations.c3 b/test/test_suite7/statements/for_with_extra_declarations.c3 new file mode 100644 index 000000000..12a04a1f7 --- /dev/null +++ b/test/test_suite7/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_suite7/statements/for_with_optional.c3t b/test/test_suite7/statements/for_with_optional.c3t new file mode 100644 index 000000000..bf04c5aea --- /dev/null +++ b/test/test_suite7/statements/for_with_optional.c3t @@ -0,0 +1,128 @@ +// #target: macos-x64 +module test; + +fn void! test() +{ + int! n; + for (n += 1; n! < 10; n += 1); +} +fn int main() +{ + (void)test(); + int! n; + for (n += 1; n!! < 10; n += 1); + return 0; +} + +/* #expect: test.ll + +define i64 @test.test() #0 { +entry: + %n = alloca i32, align 4 + %n.f = alloca i64, align 8 + %error_var = alloca i64, align 8 + store i64 0, ptr %n.f, align 8 + store i32 0, ptr %n, align 4 + %optval = load i64, ptr %n.f, align 8 + %not_err = icmp eq i64 %optval, 0 + %0 = call i1 @llvm.expect.i1(i1 %not_err, i1 true) + br i1 %0, label %after_check, label %voiderr +after_check: ; preds = %entry + %1 = load i32, ptr %n, align 4 + %add = add i32 %1, 1 + store i32 %add, ptr %n, align 4 + br label %voiderr +voiderr: ; preds = %after_check, %entry + br label %loop.cond +loop.cond: ; preds = %voiderr8, %voiderr + %optval1 = load i64, ptr %n.f, align 8 + %not_err2 = icmp eq i64 %optval1, 0 + %2 = call i1 @llvm.expect.i1(i1 %not_err2, i1 true) + br i1 %2, label %after_check3, label %assign_optional +assign_optional: ; preds = %loop.cond + store i64 %optval1, ptr %error_var, align 8 + br label %guard_block +after_check3: ; preds = %loop.cond + br label %noerr_block +guard_block: ; preds = %assign_optional + %3 = load i64, ptr %error_var, align 8 + ret i64 %3 +noerr_block: ; preds = %after_check3 + %4 = load i32, ptr %n, align 4 + %lt = icmp slt i32 %4, 10 + br i1 %lt, label %loop.body, label %loop.exit +loop.body: ; preds = %noerr_block + %optval4 = load i64, ptr %n.f, align 8 + %not_err5 = icmp eq i64 %optval4, 0 + %5 = call i1 @llvm.expect.i1(i1 %not_err5, i1 true) + br i1 %5, label %after_check6, label %voiderr8 +after_check6: ; preds = %loop.body + %6 = load i32, ptr %n, align 4 + %add7 = add i32 %6, 1 + store i32 %add7, ptr %n, align 4 + br label %voiderr8 +voiderr8: ; preds = %after_check6, %loop.body + br label %loop.cond +loop.exit: ; preds = %noerr_block + ret i64 0 +} + +define i32 @main() #0 { +entry: + %n = alloca i32, align 4 + %n.f = alloca i64, align 8 + %error_var = alloca i64, align 8 + %varargslots = alloca [1 x %any], align 16 + %indirectarg = alloca %"any[]", align 8 + %0 = call i64 @test.test() + store i64 0, ptr %n.f, align 8 + store i32 0, ptr %n, align 4 + %optval = load i64, ptr %n.f, align 8 + %not_err = icmp eq i64 %optval, 0 + %1 = call i1 @llvm.expect.i1(i1 %not_err, i1 true) + br i1 %1, label %after_check, label %voiderr +after_check: ; preds = %entry + %2 = load i32, ptr %n, align 4 + %add = add i32 %2, 1 + store i32 %add, ptr %n, align 4 + br label %voiderr +voiderr: ; preds = %after_check, %entry + br label %loop.cond +loop.cond: ; preds = %voiderr8, %voiderr + %optval1 = load i64, ptr %n.f, align 8 + %not_err2 = icmp eq i64 %optval1, 0 + %3 = call i1 @llvm.expect.i1(i1 %not_err2, i1 true) + br i1 %3, label %after_check3, label %assign_optional +assign_optional: ; preds = %loop.cond + store i64 %optval1, ptr %error_var, align 8 + br label %panic_block +after_check3: ; preds = %loop.cond + br label %noerr_block +panic_block: ; preds = %assign_optional + %4 = insertvalue %any undef, ptr %error_var, 0 + %5 = insertvalue %any %4, i64 ptrtoint (ptr @"$ct.anyfault" to i64), 1 + store %any %5, ptr %varargslots, align 16 + %6 = insertvalue %"any[]" undef, ptr %varargslots, 0 + %"$$temp" = insertvalue %"any[]" %6, i64 1, 1 + store %"any[]" %"$$temp", ptr %indirectarg, align 8 + call void @std.core.builtin.panicf( + unreachable +noerr_block: ; preds = %after_check3 + %7 = load i32, ptr %n, align 4 + %lt = icmp slt i32 %7, 10 + br i1 %lt, label %loop.body, label %loop.exit +loop.body: ; preds = %noerr_block + %optval4 = load i64, ptr %n.f, align 8 + %not_err5 = icmp eq i64 %optval4, 0 + %8 = call i1 @llvm.expect.i1(i1 %not_err5, i1 true) + br i1 %8, label %after_check6, label %voiderr8 +after_check6: ; preds = %loop.body + %9 = load i32, ptr %n, align 4 + %add7 = add i32 %9, 1 + store i32 %add7, ptr %n, align 4 + br label %voiderr8 +voiderr8: ; preds = %after_check6, %loop.body + br label %loop.cond +loop.exit: ; preds = %noerr_block + ret i32 0 +} diff --git a/test/test_suite7/statements/foreach_break.c3t b/test/test_suite7/statements/foreach_break.c3t new file mode 100644 index 000000000..66bd8dcd7 --- /dev/null +++ b/test/test_suite7/statements/foreach_break.c3t @@ -0,0 +1,73 @@ +// #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 + store i32 0, ptr %x, align 4 + %ptradd = getelementptr inbounds i8, ptr %x, i64 4 + store i32 0, ptr %ptradd, align 4 + %ptradd1 = getelementptr inbounds i8, ptr %x, i64 8 + store i32 0, ptr %ptradd1, 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 + %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 + %ptroffset = getelementptr inbounds [4 x i8], ptr %x, i64 %1 + %2 = load i32, ptr %ptroffset, align 4 + store i32 %2, ptr %z, align 4 + %3 = load i32, ptr %z, align 4 + %gt2 = icmp sgt i32 %3, 0 + br i1 %gt2, label %if.then, label %if.exit + +if.then: ; preds = %loop.body + br label %loop.exit + +if.exit: ; preds = %loop.body + %4 = load i32, ptr %z, align 4 + %eq = icmp eq i32 %4, 1 + br i1 %eq, label %if.then3, label %if.exit4 + +if.then3: ; preds = %if.exit + br label %loop.inc + +if.exit4: ; preds = %if.exit + %5 = load i32, ptr %g, align 4 + %6 = load i32, ptr %z, align 4 + %add = add i32 %5, %6 + store i32 %add, ptr %g, align 4 + br label %loop.inc + +loop.inc: ; preds = %if.exit4, %if.then3 + %7 = load i64, ptr %.anon, align 8 + %addnuw = add nuw i64 %7, 1 + store i64 %addnuw, 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_suite7/statements/foreach_common.c3t b/test/test_suite7/statements/foreach_common.c3t new file mode 100644 index 000000000..66ec250d1 --- /dev/null +++ b/test/test_suite7/statements/foreach_common.c3t @@ -0,0 +1,359 @@ +// #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 (float* &a : foo2) + { + *a *= 2; + 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 + +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 + %.anon10 = alloca i64, align 8 + %a14 = alloca ptr, align 8 + %.anon19 = alloca i64, align 8 + %i = alloca i64, align 8 + %a23 = alloca float, align 4 + %.anon28 = alloca i64, align 8 + %i32 = alloca i8, align 1 + %a33 = alloca double, align 8 + %.anon38 = alloca i64, align 8 + %a42 = alloca double, align 8 + %.anon47 = alloca i64, align 8 + %a51 = alloca float, align 4 + %.anon55 = alloca i64, align 8 + %a59 = alloca ptr, align 8 + %.anon65 = alloca i64, align 8 + %i69 = alloca i64, align 8 + %a70 = alloca float, align 4 + %.anon74 = alloca i64, align 8 + %i78 = alloca i8, align 1 + %a80 = alloca double, align 8 + %.anon85 = alloca i64, align 8 + %a89 = 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 + %ptroffset = getelementptr inbounds [4 x i8], ptr %foo, i64 %1 + %2 = load float, ptr %ptroffset, align 4 + store float %2, ptr %a, align 4 + %3 = load float, ptr %a, align 4 + %fpfpext = fpext float %3 to double + call void (ptr, ...) @printf(ptr @.str, double %fpfpext) + %4 = load i64, ptr %.anon, align 8 + %addnuw = add nuw i64 %4, 1 + store i64 %addnuw, 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 + %5 = load i64, ptr %.anon1, align 8 + %gt3 = icmp ugt i64 3, %5 + br i1 %gt3, label %loop.body4, label %loop.exit9 + +loop.body4: ; preds = %loop.cond2 + %6 = load i64, ptr %.anon1, align 8 + %ptroffset6 = getelementptr inbounds [4 x i8], ptr %foo, i64 %6 + store ptr %ptroffset6, ptr %a5, align 8 + %7 = load ptr, ptr %a5, align 8 + %8 = load float, ptr %7, align 4 + %fmul = fmul float %8, 2.000000e+00 + store float %fmul, ptr %7, align 4 + %9 = load ptr, ptr %a5, align 8 + %10 = load float, ptr %9, align 4 + %fpfpext7 = fpext float %10 to double + call void (ptr, ...) @printf(ptr @.str.1, double %fpfpext7) + %11 = load i64, ptr %.anon1, align 8 + %addnuw8 = add nuw i64 %11, 1 + store i64 %addnuw8, ptr %.anon1, align 8 + br label %loop.cond2 + +loop.exit9: ; preds = %loop.cond2 + store i64 0, ptr %.anon10, align 8 + br label %loop.cond11 + +loop.cond11: ; preds = %loop.body13, %loop.exit9 + %12 = load i64, ptr %.anon10, align 8 + %gt12 = icmp ugt i64 3, %12 + br i1 %gt12, label %loop.body13, label %loop.exit18 + +loop.body13: ; preds = %loop.cond11 + %13 = load i64, ptr %.anon10, align 8 + %ptroffset15 = getelementptr inbounds [4 x i8], ptr %foo, i64 %13 + store ptr %ptroffset15, ptr %a14, align 8 + %14 = load ptr, ptr %a14, align 8 + %15 = load float, ptr %14, align 4 + %fpfpext16 = fpext float %15 to double + call void (ptr, ...) @printf(ptr @.str.2, double %fpfpext16) + %16 = load i64, ptr %.anon10, align 8 + %addnuw17 = add nuw i64 %16, 1 + store i64 %addnuw17, ptr %.anon10, align 8 + br label %loop.cond11 + +loop.exit18: ; preds = %loop.cond11 + store i64 0, ptr %.anon19, align 8 + br label %loop.cond20 + +loop.cond20: ; preds = %loop.body22, %loop.exit18 + %17 = load i64, ptr %.anon19, align 8 + %gt21 = icmp ugt i64 3, %17 + br i1 %gt21, label %loop.body22, label %loop.exit27 + +loop.body22: ; preds = %loop.cond20 + %18 = load i64, ptr %.anon19, align 8 + store i64 %18, ptr %i, align 8 + %19 = load i64, ptr %.anon19, align 8 + %ptroffset24 = getelementptr inbounds [4 x i8], ptr %foo, i64 %19 + %20 = load float, ptr %ptroffset24, align 4 + store float %20, ptr %a23, align 4 + %21 = load float, ptr %a23, align 4 + %fpfpext25 = fpext float %21 to double + %22 = load i64, ptr %i, align 8 + call void (ptr, ...) @printf(ptr @.str.3, i64 %22, double %fpfpext25) + %23 = load i64, ptr %.anon19, align 8 + %addnuw26 = add nuw i64 %23, 1 + store i64 %addnuw26, ptr %.anon19, align 8 + br label %loop.cond20 + +loop.exit27: ; preds = %loop.cond20 + store i64 0, ptr %.anon28, align 8 + br label %loop.cond29 + +loop.cond29: ; preds = %loop.body31, %loop.exit27 + %24 = load i64, ptr %.anon28, align 8 + %gt30 = icmp ugt i64 3, %24 + br i1 %gt30, label %loop.body31, label %loop.exit37 + +loop.body31: ; preds = %loop.cond29 + %25 = load i64, ptr %.anon28, align 8 + %trunc = trunc i64 %25 to i8 + store i8 %trunc, ptr %i32, align 1 + %26 = load i64, ptr %.anon28, align 8 + %ptroffset34 = getelementptr inbounds [4 x i8], ptr %foo, i64 %26 + %27 = load float, ptr %ptroffset34, align 4 + %fpfpext35 = fpext float %27 to double + store double %fpfpext35, ptr %a33, align 8 + %28 = load i8, ptr %i32, align 1 + %zext = zext i8 %28 to i32 + %29 = load double, ptr %a33, align 8 + call void (ptr, ...) @printf(ptr @.str.4, i32 %zext, double %29) + %30 = load i64, ptr %.anon28, align 8 + %addnuw36 = add nuw i64 %30, 1 + store i64 %addnuw36, ptr %.anon28, align 8 + br label %loop.cond29 + +loop.exit37: ; preds = %loop.cond29 + store i64 0, ptr %.anon38, align 8 + br label %loop.cond39 + +loop.cond39: ; preds = %loop.body41, %loop.exit37 + %31 = load i64, ptr %.anon38, align 8 + %gt40 = icmp ugt i64 3, %31 + br i1 %gt40, label %loop.body41, label %loop.exit46 + +loop.body41: ; preds = %loop.cond39 + %32 = load i64, ptr %.anon38, align 8 + %ptroffset43 = getelementptr inbounds [4 x i8], ptr %foo, i64 %32 + %33 = load float, ptr %ptroffset43, align 4 + %fpfpext44 = fpext float %33 to double + store double %fpfpext44, ptr %a42, align 8 + %34 = load double, ptr %a42, align 8 + call void (ptr, ...) @printf(ptr @.str.5, double %34) + %35 = load i64, ptr %.anon38, align 8 + %addnuw45 = add nuw i64 %35, 1 + store i64 %addnuw45, ptr %.anon38, align 8 + br label %loop.cond39 + +loop.exit46: ; preds = %loop.cond39 + store i64 0, ptr %.anon47, align 8 + br label %loop.cond48 + +loop.cond48: ; preds = %loop.body50, %loop.exit46 + %36 = load i64, ptr %.anon47, align 8 + %gt49 = icmp ugt i64 3, %36 + br i1 %gt49, label %loop.body50, label %loop.exit54 + +loop.body50: ; preds = %loop.cond48 + %37 = load <3 x float>, ptr %foo2, align 16 + %38 = load i64, ptr %.anon47, align 8 + %39 = extractelement <3 x float> %37, i64 %38 + store float %39, ptr %a51, align 4 + %40 = load float, ptr %a51, align 4 + %fpfpext52 = fpext float %40 to double + call void (ptr, ...) @printf(ptr @.str.6, double %fpfpext52) + %41 = load i64, ptr %.anon47, align 8 + %addnuw53 = add nuw i64 %41, 1 + store i64 %addnuw53, ptr %.anon47, align 8 + br label %loop.cond48 + +loop.exit54: ; preds = %loop.cond48 + store i64 0, ptr %.anon55, align 8 + br label %loop.cond56 + +loop.cond56: ; preds = %loop.body58, %loop.exit54 + %42 = load i64, ptr %.anon55, align 8 + %gt57 = icmp ugt i64 3, %42 + br i1 %gt57, label %loop.body58, label %loop.exit64 + +loop.body58: ; preds = %loop.cond56 + %43 = load i64, ptr %.anon55, align 8 + %ptroffset60 = getelementptr inbounds [4 x i8], ptr %foo2, i64 %43 + store ptr %ptroffset60, ptr %a59, align 8 + %44 = load ptr, ptr %a59, align 8 + %45 = load float, ptr %44, align 4 + %fmul61 = fmul float %45, 2.000000e+00 + store float %fmul61, ptr %44, align 4 + %46 = load ptr, ptr %a59, align 8 + %47 = load float, ptr %46, align 4 + %fpfpext62 = fpext float %47 to double + call void (ptr, ...) @printf(ptr @.str.7, double %fpfpext62) + %48 = load i64, ptr %.anon55, align 8 + %addnuw63 = add nuw i64 %48, 1 + store i64 %addnuw63, ptr %.anon55, align 8 + br label %loop.cond56 + +loop.exit64: ; preds = %loop.cond56 + store i64 0, ptr %.anon65, align 8 + br label %loop.cond66 + +loop.cond66: ; preds = %loop.body68, %loop.exit64 + %49 = load i64, ptr %.anon65, align 8 + %gt67 = icmp ugt i64 3, %49 + br i1 %gt67, label %loop.body68, label %loop.exit73 + +loop.body68: ; preds = %loop.cond66 + %50 = load i64, ptr %.anon65, align 8 + store i64 %50, ptr %i69, align 8 + %51 = load <3 x float>, ptr %foo2, align 16 + %52 = load i64, ptr %.anon65, align 8 + %53 = extractelement <3 x float> %51, i64 %52 + store float %53, ptr %a70, align 4 + %54 = load float, ptr %a70, align 4 + %fpfpext71 = fpext float %54 to double + %55 = load i64, ptr %i69, align 8 + call void (ptr, ...) @printf(ptr @.str.8, i64 %55, double %fpfpext71) + %56 = load i64, ptr %.anon65, align 8 + %addnuw72 = add nuw i64 %56, 1 + store i64 %addnuw72, ptr %.anon65, align 8 + br label %loop.cond66 + +loop.exit73: ; preds = %loop.cond66 + store i64 0, ptr %.anon74, align 8 + br label %loop.cond75 + +loop.cond75: ; preds = %loop.body77, %loop.exit73 + %57 = load i64, ptr %.anon74, align 8 + %gt76 = icmp ugt i64 3, %57 + br i1 %gt76, label %loop.body77, label %loop.exit84 + +loop.body77: ; preds = %loop.cond75 + %58 = load i64, ptr %.anon74, align 8 + %trunc79 = trunc i64 %58 to i8 + store i8 %trunc79, ptr %i78, align 1 + %59 = load <3 x float>, ptr %foo2, align 16 + %60 = load i64, ptr %.anon74, align 8 + %61 = extractelement <3 x float> %59, i64 %60 + %fpfpext81 = fpext float %61 to double + store double %fpfpext81, ptr %a80, align 8 + %62 = load i8, ptr %i78, align 1 + %zext82 = zext i8 %62 to i32 + %63 = load double, ptr %a80, align 8 + call void (ptr, ...) @printf(ptr @.str.9, i32 %zext82, double %63) + %64 = load i64, ptr %.anon74, align 8 + %addnuw83 = add nuw i64 %64, 1 + store i64 %addnuw83, ptr %.anon74, align 8 + br label %loop.cond75 + +loop.exit84: ; preds = %loop.cond75 + store i64 0, ptr %.anon85, align 8 + br label %loop.cond86 + +loop.cond86: ; preds = %loop.body88, %loop.exit84 + %65 = load i64, ptr %.anon85, align 8 + %gt87 = icmp ugt i64 3, %65 + br i1 %gt87, label %loop.body88, label %loop.exit92 + +loop.body88: ; preds = %loop.cond86 + %66 = load <3 x float>, ptr %foo2, align 16 + %67 = load i64, ptr %.anon85, align 8 + %68 = extractelement <3 x float> %66, i64 %67 + %fpfpext90 = fpext float %68 to double + store double %fpfpext90, ptr %a89, align 8 + %69 = load double, ptr %a89, align 8 + call void (ptr, ...) @printf(ptr @.str.10, double %69) + %70 = load i64, ptr %.anon85, align 8 + %addnuw91 = add nuw i64 %70, 1 + store i64 %addnuw91, ptr %.anon85, align 8 + br label %loop.cond86 + +loop.exit92: ; preds = %loop.cond86 + ret void +} diff --git a/test/test_suite7/statements/foreach_custom.c3t b/test/test_suite7/statements/foreach_custom.c3t new file mode 100644 index 000000000..f8c667c31 --- /dev/null +++ b/test/test_suite7/statements/foreach_custom.c3t @@ -0,0 +1,85 @@ +// #target: macos-x64 + +module test; +struct Foo +{ + int[] x; +} + +macro int Foo.@operator_element_at(Foo* &foo, usz index) @operator([]) +{ + return foo.x[index]; +} + +macro usz 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: test.ll + + +define void @test.main() #0 { +entry: + %i = alloca [3 x i32], align 4 + %x = alloca %Foo, align 8 + %.anon = 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 = insertvalue %"int[]" undef, ptr %i, 0 + %1 = insertvalue %"int[]" %0, i64 3, 1 + store %"int[]" %1, ptr %x, align 8 + %ptradd = getelementptr inbounds i8, ptr %x, i64 8 + %2 = load i64, ptr %ptradd, align 8 + store i64 0, ptr %.anon, align 8 + br label %loop.cond + +loop.cond: ; preds = %entry + %3 = load i64, ptr %.anon, align 8 + %lt = icmp ult i64 %3, %2 + br i1 %lt, label %loop.body, label %loop.exit + +loop.body: ; preds = %loop.cond + %4 = load i64, ptr %.anon, align 8 + store i64 %4, ptr %index, align 8 + %5 = load ptr, ptr %x, align 8 + %6 = load i64, ptr %index, align 8 + %ptroffset = getelementptr inbounds [4 x i8], ptr %5, i64 %6 + %7 = load i32, ptr %ptroffset, align 4 + store i32 %7, ptr %f, align 4 + %8 = load i32, ptr %f, align 4 + %9 = call i32 (ptr, ...) @printf(ptr @.str, i32 %8) + br label %loop.body1 + +loop.body1: ; preds = %loop.body + br label %loop.exit + +loop.exit: ; preds = %loop.body1, %loop.cond + ret void +} + +; Function Attrs: +declare i32 @printf(ptr, ...) #0 + +; Function Attrs: +define i32 @main(i32 %0, ptr %1) #0 { +entry: + call void @test.main() + ret i32 0 +} diff --git a/test/test_suite7/statements/foreach_custom_errors.c3 b/test/test_suite7/statements/foreach_custom_errors.c3 new file mode 100644 index 000000000..08c581ab9 --- /dev/null +++ b/test/test_suite7/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' +} + +distinct Test1 = 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_suite7/statements/foreach_custom_macro.c3t b/test/test_suite7/statements/foreach_custom_macro.c3t new file mode 100644 index 000000000..7fbdc6135 --- /dev/null +++ b/test/test_suite7/statements/foreach_custom_macro.c3t @@ -0,0 +1,91 @@ +// #target: macos-x64 +module foo; +struct Foo +{ + int[] x; +} + +macro int Foo.@operator_element_at(Foo* &foo, usz index) @operator([]) +{ + return foo.x[index]; +} + +macro usz 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 + +%Foo = type { %"int[]" } +%"int[]" = type { ptr, i64 } + +@"$ct.foo.Foo" = linkonce global %.introspect { i8 10, i64 0, ptr null, i64 16, i64 0, i64 1, [0 x i64] zeroinitializer }, 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: +define void @foo.main() #0 { +entry: + %i = alloca [3 x i32], align 4 + %x = alloca %Foo, align 8 + %.anon = 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 = insertvalue %"int[]" undef, ptr %i, 0 + %1 = insertvalue %"int[]" %0, i64 3, 1 + store %"int[]" %1, ptr %x, align 8 + %ptradd = getelementptr inbounds i8, ptr %x, i64 8 + %2 = load i64, ptr %ptradd, align 8 + store i64 0, ptr %.anon, align 8 + br label %loop.cond + +loop.cond: ; preds = %entry + %3 = load i64, ptr %.anon, align 8 + %lt = icmp ult i64 %3, %2 + br i1 %lt, label %loop.body, label %loop.exit + +loop.body: ; preds = %loop.cond + %4 = load i64, ptr %.anon, align 8 + store i64 %4, ptr %index, align 8 + %5 = load ptr, ptr %x, align 8 + %6 = load i64, ptr %index, align 8 + %ptroffset = getelementptr inbounds [4 x i8], ptr %5, i64 %6 + %7 = load i32, ptr %ptroffset, align 4 + store i32 %7, ptr %f, align 4 + %8 = load i32, ptr %f, align 4 + %9 = call i32 (ptr, ...) @printf(ptr @.str, i32 %8) + br label %loop.body1 + +loop.body1: ; preds = %loop.body + br label %loop.exit + +loop.exit: ; preds = %loop.body1, %loop.cond + ret void +} + +; Function Attrs: +declare i32 @printf(ptr, ...) #0 + +; Function Attrs: +define i32 @main(i32 %0, ptr %1) #0 { +entry: + call void @foo.main() + ret i32 0 +} \ No newline at end of file diff --git a/test/test_suite7/statements/foreach_distinct_iterable.c3t b/test/test_suite7/statements/foreach_distinct_iterable.c3t new file mode 100644 index 000000000..c69667fdb --- /dev/null +++ b/test/test_suite7/statements/foreach_distinct_iterable.c3t @@ -0,0 +1,61 @@ +// #target: macos-x64 +module test; +import std; +distinct TypeA = char[]; + +fn char TypeA.get(self, usz i) @operator([]) { + return ((char[])self)[i]; +} + +fn usz TypeA.len(self) @operator(len) +{ + return self.len; +} + +fn int main() { + TypeA x = "AAAAA"; + foreach(y : x) + { + int z = y; + } + return 0; +} + +/* #expect: test.ll + +define i32 @main() #0 { +entry: + %x = alloca %"char[]", align 8 + %.anon = alloca i64, align 8 + %y = alloca i8, align 1 + %z = alloca i32, align 4 + store %"char[]" { ptr @.str, i64 5 }, ptr %x, align 8 + %lo = load ptr, ptr %x, align 8 + %ptradd = getelementptr inbounds i8, ptr %x, i64 8 + %hi = load i64, ptr %ptradd, align 8 + %0 = call i64 @test.TypeA.len(ptr %lo, i64 %hi) + store i64 0, ptr %.anon, align 8 + br label %loop.cond + +loop.cond: ; preds = %loop.body, %entry + %1 = load i64, ptr %.anon, align 8 + %lt = icmp ult i64 %1, %0 + br i1 %lt, label %loop.body, label %loop.exit + +loop.body: ; preds = %loop.cond + %lo1 = load ptr, ptr %x, align 8 + %ptradd2 = getelementptr inbounds i8, ptr %x, i64 8 + %hi3 = load i64, ptr %ptradd2, align 8 + %2 = load i64, ptr %.anon, align 8 + %3 = call i8 @test.TypeA.get(ptr %lo1, i64 %hi3, i64 %2) + store i8 %3, ptr %y, align 1 + %4 = load i8, ptr %y, align 1 + %zext = zext i8 %4 to i32 + store i32 %zext, ptr %z, align 4 + %5 = load i64, ptr %.anon, align 8 + %addnuw = add nuw i64 %5, 1 + store i64 %addnuw, ptr %.anon, align 8 + br label %loop.cond + +loop.exit: ; preds = %loop.cond + ret i32 0 \ No newline at end of file diff --git a/test/test_suite7/statements/foreach_distinct_pointer_1506.c3 b/test/test_suite7/statements/foreach_distinct_pointer_1506.c3 new file mode 100644 index 000000000..5e6c2d262 --- /dev/null +++ b/test/test_suite7/statements/foreach_distinct_pointer_1506.c3 @@ -0,0 +1,14 @@ +distinct Type = char*; +fn usz Type.len(str) +{ + return 0; +} +fn int main(String[] args) +{ + Type x = "AAAAA"; // Or ZString + foreach(y : x) // #error: It's not possible to enumerate an expression + { + + } + return 0; +} \ No newline at end of file diff --git a/test/test_suite7/statements/foreach_errors.c3 b/test/test_suite7/statements/foreach_errors.c3 new file mode 100644 index 000000000..64531102b --- /dev/null +++ b/test/test_suite7/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(); +} + +fn void test6() +{ + foreach (int! i, y : z) foo(); // #error: The index may not be an optional. +} + +fn void test7() +{ + foreach (int a : { 1, 2, 3 }) foo(); + foreach (a : { 1, 2, 3 }) foo(); // #error: Add an explicit type to the variable +} + +fn void test8() +{ + foreach (int a : { z }) foo(); // #error: 'int[3]' to 'int' +} + diff --git a/test/test_suite7/statements/foreach_more_implementations.c3t b/test/test_suite7/statements/foreach_more_implementations.c3t new file mode 100644 index 000000000..88959c480 --- /dev/null +++ b/test/test_suite7/statements/foreach_more_implementations.c3t @@ -0,0 +1,126 @@ +// #target: macos-x64 +module test; + +import std::io; +struct Vector +{ + usz size; + int* elements; +} + +macro int Vector.get(Vector* vector, usz element) @operator([]) +{ + return vector.elements[element]; +} + +macro int* Vector.get_ref(Vector* vector, usz element) @operator(&[]) +{ + return &vector.elements[element]; +} + +macro usz Vector.size(Vector vector) @operator(len) { + return vector.size; +} + +fn void main() +{ + int[2] x = { 1, 2 }; + Vector v = { 2, &x }; + + foreach (int* &ref : v) + { + std::io::printf("%d\n", *ref); + *ref += 2; + } + foreach (int i : v) + { + std::io::printf("%d\n", i); + } +} + +/* #expect: test.ll + +define void @test.main() #0 { +entry: + %x = alloca [2 x i32], align 4 + %v = alloca %Vector, align 8 + %vector = alloca %Vector, align 8 + %.anon = alloca i64, align 8 + %ref = alloca ptr, align 8 + %element = alloca i64, align 8 + %varargslots = alloca [1 x %any], align 16 + %retparam = alloca i64, align 8 + %vector2 = alloca %Vector, align 8 + %.anon3 = alloca i64, align 8 + %i = alloca i32, align 4 + %element7 = alloca i64, align 8 + %varargslots10 = alloca [1 x %any], align 16 + %retparam11 = alloca i64, align 8 + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %x, ptr align 4 @.__const, i32 8, i1 false) + store i64 2, ptr %v, align 8 + %ptradd = getelementptr inbounds i8, ptr %v, i64 8 + store ptr %x, ptr %ptradd, align 8 + call void @llvm.memcpy.p0.p0.i32(ptr align 8 %vector, ptr align 8 %v, i32 16, i1 false) + %0 = load i64, ptr %vector, align 8 + store i64 0, ptr %.anon, align 8 + br label %loop.cond + +loop.cond: ; preds = %loop.body, %entry + %1 = load i64, ptr %.anon, align 8 + %lt = icmp ult i64 %1, %0 + br i1 %lt, label %loop.body, label %loop.exit + +loop.body: ; preds = %loop.cond + %2 = load i64, ptr %.anon, align 8 + store i64 %2, ptr %element, align 8 + %ptradd1 = getelementptr inbounds i8, ptr %v, i64 8 + %3 = load ptr, ptr %ptradd1, align 8 + %4 = load i64, ptr %element, align 8 + %ptroffset = getelementptr inbounds [4 x i8], ptr %3, i64 %4 + store ptr %ptroffset, ptr %ref, align 8 + %5 = load ptr, ptr %ref, align 8 + %6 = insertvalue %any undef, ptr %5, 0 + %7 = insertvalue %any %6, i64 ptrtoint (ptr @"$ct.int" to i64), 1 + store %any %7, ptr %varargslots, align 16 + %8 = call i64 @std.io.printf(ptr %retparam, ptr @.str, i64 3, ptr %varargslots, i64 1) + %9 = load ptr, ptr %ref, align 8 + %10 = load i32, ptr %9, align 4 + %add = add i32 %10, 2 + store i32 %add, ptr %9, align 4 + %11 = load i64, ptr %.anon, align 8 + %addnuw = add nuw i64 %11, 1 + store i64 %addnuw, ptr %.anon, align 8 + br label %loop.cond + +loop.exit: ; preds = %loop.cond + call void @llvm.memcpy.p0.p0.i32(ptr align 8 %vector2, ptr align 8 %v, i32 16, i1 false) + %12 = load i64, ptr %vector2, align 8 + store i64 0, ptr %.anon3, align 8 + br label %loop.cond4 + +loop.cond4: ; preds = %loop.body6, %loop.exit + %13 = load i64, ptr %.anon3, align 8 + %lt5 = icmp ult i64 %13, %12 + br i1 %lt5, label %loop.body6, label %loop.exit13 + +loop.body6: ; preds = %loop.cond4 + %14 = load i64, ptr %.anon3, align 8 + store i64 %14, ptr %element7, align 8 + %ptradd8 = getelementptr inbounds i8, ptr %v, i64 8 + %15 = load ptr, ptr %ptradd8, align 8 + %16 = load i64, ptr %element7, align 8 + %ptroffset9 = getelementptr inbounds [4 x i8], ptr %15, i64 %16 + %17 = load i32, ptr %ptroffset9, align 4 + store i32 %17, ptr %i, align 4 + %18 = insertvalue %any undef, ptr %i, 0 + %19 = insertvalue %any %18, i64 ptrtoint (ptr @"$ct.int" to i64), 1 + store %any %19, ptr %varargslots10, align 16 + %20 = call i64 @std.io.printf(ptr %retparam11, ptr @.str.1, i64 3, ptr %varargslots10, i64 1) + %21 = load i64, ptr %.anon3, align 8 + %addnuw12 = add nuw i64 %21, 1 + store i64 %addnuw12, ptr %.anon3, align 8 + br label %loop.cond4 + +loop.exit13: ; preds = %loop.cond4 + ret void +} \ No newline at end of file diff --git a/test/test_suite7/statements/foreach_parse_error.c3 b/test/test_suite7/statements/foreach_parse_error.c3 new file mode 100644 index 000000000..4a761601a --- /dev/null +++ b/test/test_suite7/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_suite7/statements/foreach_r_break.c3t b/test/test_suite7/statements/foreach_r_break.c3t new file mode 100644 index 000000000..b76700d4e --- /dev/null +++ b/test/test_suite7/statements/foreach_r_break.c3t @@ -0,0 +1,72 @@ +// #target: macos-x64 +module test; + +fn void test() +{ + int[3] x; + int g = 0; + foreach_r (z : x) + { + if (z > 0) break; + if (z == 1) continue; + g += z; + } +} + +/* #expect: test.ll + + +; Function Attrs: +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 + store i32 0, ptr %x, align 4 + %ptradd = getelementptr inbounds i8, ptr %x, i64 4 + store i32 0, ptr %ptradd, align 4 + %ptradd1 = getelementptr inbounds i8, ptr %x, i64 8 + store i32 0, ptr %ptradd1, align 4 + store i32 0, ptr %g, align 4 + store i64 3, ptr %.anon, align 8 + br label %loop.cond + +loop.cond: ; preds = %if.exit4, %if.then3, %entry + %0 = load i64, ptr %.anon, align 8 + %gt = icmp ugt i64 %0, 0 + br i1 %gt, label %loop.body, label %loop.exit + +loop.body: ; preds = %loop.cond + %1 = load i64, ptr %.anon, align 8 + %subnuw = sub nuw i64 %1, 1 + store i64 %subnuw, ptr %.anon, align 8 + %2 = load i64, ptr %.anon, align 8 + %ptroffset = getelementptr inbounds [4 x i8], ptr %x, i64 %2 + %3 = load i32, ptr %ptroffset, align 4 + store i32 %3, ptr %z, align 4 + %4 = load i32, ptr %z, align 4 + %gt2 = icmp sgt i32 %4, 0 + br i1 %gt2, label %if.then, label %if.exit + +if.then: ; preds = %loop.body + br label %loop.exit + +if.exit: ; preds = %loop.body + %5 = load i32, ptr %z, align 4 + %eq = icmp eq i32 %5, 1 + br i1 %eq, label %if.then3, label %if.exit4 + +if.then3: ; preds = %if.exit + br label %loop.cond + +if.exit4: ; preds = %if.exit + %6 = load i32, ptr %g, align 4 + %7 = load i32, ptr %z, align 4 + %add = add i32 %6, %7 + store i32 %add, ptr %g, align 4 + br label %loop.cond + +loop.exit: ; preds = %if.then, %loop.cond + ret void +} diff --git a/test/test_suite7/statements/foreach_r_common.c3t b/test/test_suite7/statements/foreach_r_common.c3t new file mode 100644 index 000000000..32e301478 --- /dev/null +++ b/test/test_suite7/statements/foreach_r_common.c3t @@ -0,0 +1,359 @@ +// #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_r (a : foo) + { + printf("Value: %f\n", a); + } + foreach_r (float* &a : foo) + { + *a *= 2; + printf("Value: %f\n", *a); + } + foreach_r (void* &a : foo) + { + printf("Value: %f\n", *((float*)(a))); + } + foreach_r (i, a : foo) + { + printf("Value[%d]: %f\n", i, a); + } + foreach_r (char i, double a : foo) + { + printf("Value2[%d]: %f\n", i, a); + } + foreach_r (double a : foo) + { + printf("Value3: %f\n", a); + } + + foreach_r (a : foo2) + { + printf("Value: %f\n", a); + } + foreach_r (float* &a : foo2) + { + *a *= 2; + printf("Value: %f\n", *a); + } + foreach_r (i, a : foo2) + { + printf("Value[%d]: %f\n", i, a); + } + foreach_r (char i, double a : foo2) + { + printf("Value2[%d]: %f\n", i, a); + } + foreach_r (double a : foo2) + { + printf("Value3: %f\n", a); + } +} + +/* #expect: test.ll + +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 + %a6 = alloca ptr, align 8 + %.anon10 = alloca i64, align 8 + %a15 = alloca ptr, align 8 + %.anon19 = alloca i64, align 8 + %i = alloca i64, align 8 + %a24 = alloca float, align 4 + %.anon28 = alloca i64, align 8 + %i33 = alloca i8, align 1 + %a34 = alloca double, align 8 + %.anon38 = alloca i64, align 8 + %a43 = alloca double, align 8 + %.anon47 = alloca i64, align 8 + %a52 = alloca float, align 4 + %.anon55 = alloca i64, align 8 + %a60 = alloca ptr, align 8 + %.anon65 = alloca i64, align 8 + %i70 = alloca i64, align 8 + %a71 = alloca float, align 4 + %.anon74 = alloca i64, align 8 + %i79 = alloca i8, align 1 + %a81 = alloca double, align 8 + %.anon85 = alloca i64, align 8 + %a90 = 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 3, 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 %0, 0 + br i1 %gt, label %loop.body, label %loop.exit + +loop.body: ; preds = %loop.cond + %1 = load i64, ptr %.anon, align 8 + %subnuw = sub nuw i64 %1, 1 + store i64 %subnuw, ptr %.anon, align 8 + %2 = load i64, ptr %.anon, align 8 + %ptroffset = getelementptr inbounds [4 x i8], ptr %foo, i64 %2 + %3 = load float, ptr %ptroffset, 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) + br label %loop.cond + +loop.exit: ; preds = %loop.cond + store i64 3, ptr %.anon1, align 8 + br label %loop.cond2 + +loop.cond2: ; preds = %loop.body4, %loop.exit + %5 = load i64, ptr %.anon1, align 8 + %gt3 = icmp ugt i64 %5, 0 + br i1 %gt3, label %loop.body4, label %loop.exit9 + +loop.body4: ; preds = %loop.cond2 + %6 = load i64, ptr %.anon1, align 8 + %subnuw5 = sub nuw i64 %6, 1 + store i64 %subnuw5, ptr %.anon1, align 8 + %7 = load i64, ptr %.anon1, align 8 + %ptroffset7 = getelementptr inbounds [4 x i8], ptr %foo, i64 %7 + store ptr %ptroffset7, ptr %a6, align 8 + %8 = load ptr, ptr %a6, align 8 + %9 = load float, ptr %8, align 4 + %fmul = fmul float %9, 2.000000e+00 + store float %fmul, ptr %8, align 4 + %10 = load ptr, ptr %a6, align 8 + %11 = load float, ptr %10, align 4 + %fpfpext8 = fpext float %11 to double + call void (ptr, ...) @printf(ptr @.str.1, double %fpfpext8) + br label %loop.cond2 + +loop.exit9: ; preds = %loop.cond2 + store i64 3, ptr %.anon10, align 8 + br label %loop.cond11 + +loop.cond11: ; preds = %loop.body13, %loop.exit9 + %12 = load i64, ptr %.anon10, align 8 + %gt12 = icmp ugt i64 %12, 0 + br i1 %gt12, label %loop.body13, label %loop.exit18 + +loop.body13: ; preds = %loop.cond11 + %13 = load i64, ptr %.anon10, align 8 + %subnuw14 = sub nuw i64 %13, 1 + store i64 %subnuw14, ptr %.anon10, align 8 + %14 = load i64, ptr %.anon10, align 8 + %ptroffset16 = getelementptr inbounds [4 x i8], ptr %foo, i64 %14 + store ptr %ptroffset16, ptr %a15, align 8 + %15 = load ptr, ptr %a15, align 8 + %16 = load float, ptr %15, align 4 + %fpfpext17 = fpext float %16 to double + call void (ptr, ...) @printf(ptr @.str.2, double %fpfpext17) + br label %loop.cond11 + +loop.exit18: ; preds = %loop.cond11 + store i64 3, ptr %.anon19, align 8 + br label %loop.cond20 + +loop.cond20: ; preds = %loop.body22, %loop.exit18 + %17 = load i64, ptr %.anon19, align 8 + %gt21 = icmp ugt i64 %17, 0 + br i1 %gt21, label %loop.body22, label %loop.exit27 + +loop.body22: ; preds = %loop.cond20 + %18 = load i64, ptr %.anon19, align 8 + %subnuw23 = sub nuw i64 %18, 1 + store i64 %subnuw23, ptr %.anon19, align 8 + %19 = load i64, ptr %.anon19, align 8 + store i64 %19, ptr %i, align 8 + %20 = load i64, ptr %.anon19, align 8 + %ptroffset25 = getelementptr inbounds [4 x i8], ptr %foo, i64 %20 + %21 = load float, ptr %ptroffset25, align 4 + store float %21, ptr %a24, align 4 + %22 = load float, ptr %a24, align 4 + %fpfpext26 = fpext float %22 to double + %23 = load i64, ptr %i, align 8 + call void (ptr, ...) @printf(ptr @.str.3, i64 %23, double %fpfpext26) + br label %loop.cond20 + +loop.exit27: ; preds = %loop.cond20 + store i64 3, ptr %.anon28, align 8 + br label %loop.cond29 + +loop.cond29: ; preds = %loop.body31, %loop.exit27 + %24 = load i64, ptr %.anon28, align 8 + %gt30 = icmp ugt i64 %24, 0 + br i1 %gt30, label %loop.body31, label %loop.exit37 + +loop.body31: ; preds = %loop.cond29 + %25 = load i64, ptr %.anon28, align 8 + %subnuw32 = sub nuw i64 %25, 1 + store i64 %subnuw32, ptr %.anon28, align 8 + %26 = load i64, ptr %.anon28, align 8 + %trunc = trunc i64 %26 to i8 + store i8 %trunc, ptr %i33, align 1 + %27 = load i64, ptr %.anon28, align 8 + %ptroffset35 = getelementptr inbounds [4 x i8], ptr %foo, i64 %27 + %28 = load float, ptr %ptroffset35, align 4 + %fpfpext36 = fpext float %28 to double + store double %fpfpext36, ptr %a34, align 8 + %29 = load i8, ptr %i33, align 1 + %zext = zext i8 %29 to i32 + %30 = load double, ptr %a34, align 8 + call void (ptr, ...) @printf(ptr @.str.4, i32 %zext, double %30) + br label %loop.cond29 + +loop.exit37: ; preds = %loop.cond29 + store i64 3, ptr %.anon38, align 8 + br label %loop.cond39 + +loop.cond39: ; preds = %loop.body41, %loop.exit37 + %31 = load i64, ptr %.anon38, align 8 + %gt40 = icmp ugt i64 %31, 0 + br i1 %gt40, label %loop.body41, label %loop.exit46 + +loop.body41: ; preds = %loop.cond39 + %32 = load i64, ptr %.anon38, align 8 + %subnuw42 = sub nuw i64 %32, 1 + store i64 %subnuw42, ptr %.anon38, align 8 + %33 = load i64, ptr %.anon38, align 8 + %ptroffset44 = getelementptr inbounds [4 x i8], ptr %foo, i64 %33 + %34 = load float, ptr %ptroffset44, align 4 + %fpfpext45 = fpext float %34 to double + store double %fpfpext45, ptr %a43, align 8 + %35 = load double, ptr %a43, align 8 + call void (ptr, ...) @printf(ptr @.str.5, double %35) + br label %loop.cond39 + +loop.exit46: ; preds = %loop.cond39 + store i64 3, ptr %.anon47, align 8 + br label %loop.cond48 + +loop.cond48: ; preds = %loop.body50, %loop.exit46 + %36 = load i64, ptr %.anon47, align 8 + %gt49 = icmp ugt i64 %36, 0 + br i1 %gt49, label %loop.body50, label %loop.exit54 + +loop.body50: ; preds = %loop.cond48 + %37 = load i64, ptr %.anon47, align 8 + %subnuw51 = sub nuw i64 %37, 1 + store i64 %subnuw51, ptr %.anon47, align 8 + %38 = load <3 x float>, ptr %foo2, align 16 + %39 = load i64, ptr %.anon47, align 8 + %40 = extractelement <3 x float> %38, i64 %39 + store float %40, ptr %a52, align 4 + %41 = load float, ptr %a52, align 4 + %fpfpext53 = fpext float %41 to double + call void (ptr, ...) @printf(ptr @.str.6, double %fpfpext53) + br label %loop.cond48 + +loop.exit54: ; preds = %loop.cond48 + store i64 3, ptr %.anon55, align 8 + br label %loop.cond56 + +loop.cond56: ; preds = %loop.body58, %loop.exit54 + %42 = load i64, ptr %.anon55, align 8 + %gt57 = icmp ugt i64 %42, 0 + br i1 %gt57, label %loop.body58, label %loop.exit64 + +loop.body58: ; preds = %loop.cond56 + %43 = load i64, ptr %.anon55, align 8 + %subnuw59 = sub nuw i64 %43, 1 + store i64 %subnuw59, ptr %.anon55, align 8 + %44 = load i64, ptr %.anon55, align 8 + %ptroffset61 = getelementptr inbounds [4 x i8], ptr %foo2, i64 %44 + store ptr %ptroffset61, ptr %a60, align 8 + %45 = load ptr, ptr %a60, align 8 + %46 = load float, ptr %45, align 4 + %fmul62 = fmul float %46, 2.000000e+00 + store float %fmul62, ptr %45, align 4 + %47 = load ptr, ptr %a60, align 8 + %48 = load float, ptr %47, align 4 + %fpfpext63 = fpext float %48 to double + call void (ptr, ...) @printf(ptr @.str.7, double %fpfpext63) + br label %loop.cond56 + +loop.exit64: ; preds = %loop.cond56 + store i64 3, ptr %.anon65, align 8 + br label %loop.cond66 + +loop.cond66: ; preds = %loop.body68, %loop.exit64 + %49 = load i64, ptr %.anon65, align 8 + %gt67 = icmp ugt i64 %49, 0 + br i1 %gt67, label %loop.body68, label %loop.exit73 + +loop.body68: ; preds = %loop.cond66 + %50 = load i64, ptr %.anon65, align 8 + %subnuw69 = sub nuw i64 %50, 1 + store i64 %subnuw69, ptr %.anon65, align 8 + %51 = load i64, ptr %.anon65, align 8 + store i64 %51, ptr %i70, align 8 + %52 = load <3 x float>, ptr %foo2, align 16 + %53 = load i64, ptr %.anon65, align 8 + %54 = extractelement <3 x float> %52, i64 %53 + store float %54, ptr %a71, align 4 + %55 = load float, ptr %a71, align 4 + %fpfpext72 = fpext float %55 to double + %56 = load i64, ptr %i70, align 8 + call void (ptr, ...) @printf(ptr @.str.8, i64 %56, double %fpfpext72) + br label %loop.cond66 + +loop.exit73: ; preds = %loop.cond66 + store i64 3, ptr %.anon74, align 8 + br label %loop.cond75 + +loop.cond75: ; preds = %loop.body77, %loop.exit73 + %57 = load i64, ptr %.anon74, align 8 + %gt76 = icmp ugt i64 %57, 0 + br i1 %gt76, label %loop.body77, label %loop.exit84 + +loop.body77: ; preds = %loop.cond75 + %58 = load i64, ptr %.anon74, align 8 + %subnuw78 = sub nuw i64 %58, 1 + store i64 %subnuw78, ptr %.anon74, align 8 + %59 = load i64, ptr %.anon74, align 8 + %trunc80 = trunc i64 %59 to i8 + store i8 %trunc80, ptr %i79, align 1 + %60 = load <3 x float>, ptr %foo2, align 16 + %61 = load i64, ptr %.anon74, align 8 + %62 = extractelement <3 x float> %60, i64 %61 + %fpfpext82 = fpext float %62 to double + store double %fpfpext82, ptr %a81, align 8 + %63 = load i8, ptr %i79, align 1 + %zext83 = zext i8 %63 to i32 + %64 = load double, ptr %a81, align 8 + call void (ptr, ...) @printf(ptr @.str.9, i32 %zext83, double %64) + br label %loop.cond75 + +loop.exit84: ; preds = %loop.cond75 + store i64 3, ptr %.anon85, align 8 + br label %loop.cond86 + +loop.cond86: ; preds = %loop.body88, %loop.exit84 + %65 = load i64, ptr %.anon85, align 8 + %gt87 = icmp ugt i64 %65, 0 + br i1 %gt87, label %loop.body88, label %loop.exit92 + +loop.body88: ; preds = %loop.cond86 + %66 = load i64, ptr %.anon85, align 8 + %subnuw89 = sub nuw i64 %66, 1 + store i64 %subnuw89, ptr %.anon85, align 8 + %67 = load <3 x float>, ptr %foo2, align 16 + %68 = load i64, ptr %.anon85, align 8 + %69 = extractelement <3 x float> %67, i64 %68 + %fpfpext91 = fpext float %69 to double + store double %fpfpext91, ptr %a90, align 8 + %70 = load double, ptr %a90, align 8 + call void (ptr, ...) @printf(ptr @.str.10, double %70) + br label %loop.cond86 + +loop.exit92: ; preds = %loop.cond86 + ret void +} diff --git a/test/test_suite7/statements/foreach_r_custom.c3t b/test/test_suite7/statements/foreach_r_custom.c3t new file mode 100644 index 000000000..1e632f19f --- /dev/null +++ b/test/test_suite7/statements/foreach_r_custom.c3t @@ -0,0 +1,88 @@ +// #target: macos-x64 + +module test; +struct Foo +{ + int[] x; +} + +macro int Foo.@operator_element_at(Foo* &foo, usz index) @operator([]) +{ + return foo.x[index]; +} + +macro usz Foo.@operator_len(Foo* &foo) @operator(len) +{ + return foo.x.len; +} + +fn void main() +{ + int[?] i = { 1, 3, 10 }; + Foo x = { &i }; + foreach_r FOO: (int f : x) { + printf("%d\n", f); + while (1) + { + break FOO; + } + } +} + +extern fn int printf(char *fmt, ...); + +/* #expect: test.ll + + +define void @test.main() #0 { +entry: + %i = alloca [3 x i32], align 4 + %x = alloca %Foo, align 8 + %.anon = 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 = insertvalue %"int[]" undef, ptr %i, 0 + %1 = insertvalue %"int[]" %0, i64 3, 1 + store %"int[]" %1, ptr %x, align 8 + %ptradd = getelementptr inbounds i8, ptr %x, i64 8 + %2 = load i64, ptr %ptradd, align 8 + store i64 %2, ptr %.anon, align 8 + br label %loop.cond + +loop.cond: ; preds = %entry + %3 = 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 + %4 = load i64, ptr %.anon, align 8 + %subnuw = sub nuw i64 %4, 1 + store i64 %subnuw, ptr %.anon, align 8 + %5 = load i64, ptr %.anon, align 8 + store i64 %5, ptr %index, align 8 + %6 = load ptr, ptr %x, align 8 + %7 = load i64, ptr %index, align 8 + %ptroffset = getelementptr inbounds [4 x i8], ptr %6, i64 %7 + %8 = load i32, ptr %ptroffset, align 4 + store i32 %8, ptr %f, align 4 + %9 = load i32, ptr %f, align 4 + %10 = call i32 (ptr, ...) @printf(ptr @.str, i32 %9) + br label %loop.body1 + +loop.body1: ; preds = %loop.body + br label %loop.exit + +loop.exit: ; preds = %loop.body1, %loop.cond + ret void +} + +; Function Attrs: +declare i32 @printf(ptr, ...) #0 + +; Function Attrs: +define i32 @main(i32 %0, ptr %1) #0 { +entry: + call void @test.main() + ret i32 0 +} diff --git a/test/test_suite7/statements/foreach_r_custom_errors.c3 b/test/test_suite7/statements/foreach_r_custom_errors.c3 new file mode 100644 index 000000000..1ef972b44 --- /dev/null +++ b/test/test_suite7/statements/foreach_r_custom_errors.c3 @@ -0,0 +1,15 @@ +fn void test1() +{ + int x; + foreach_r (a : x) { }; // #error: It's not possible to enumerate an expression of type 'int' +} + +distinct Test1 = int; + +fn void test2() +{ + Test1 x; + foreach_r (a : x) { }; // #error: It's not possible to enumerate an expression of type 'Test1' +} + + diff --git a/test/test_suite7/statements/foreach_r_custom_macro.c3t b/test/test_suite7/statements/foreach_r_custom_macro.c3t new file mode 100644 index 000000000..4c1b76dae --- /dev/null +++ b/test/test_suite7/statements/foreach_r_custom_macro.c3t @@ -0,0 +1,77 @@ +// #target: macos-x64 +module test; +struct Foo +{ + int[] x; +} + +macro int Foo.@operator_element_at(Foo* &foo, usz index) @operator([]) +{ + return foo.x[index]; +} + +macro usz Foo.@operator_len(Foo* &foo) @operator(len) +{ + return foo.x.len; +} + +fn void main() +{ + int[?] i = { 1, 3, 10 }; + Foo x = { &i }; + foreach_r FOO: (int f : x) { + printf("%d\n", f); + while (1) + { + break FOO; + } + } +} + +extern fn int printf(char *fmt, ...); + +/* #expect: test.ll + + +define void @test.main() #0 { +entry: + %i = alloca [3 x i32], align 4 + %x = alloca %Foo, align 8 + %.anon = 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 = insertvalue %"int[]" undef, ptr %i, 0 + %1 = insertvalue %"int[]" %0, i64 3, 1 + store %"int[]" %1, ptr %x, align 8 + %ptradd = getelementptr inbounds i8, ptr %x, i64 8 + %2 = load i64, ptr %ptradd, align 8 + store i64 %2, ptr %.anon, align 8 + br label %loop.cond + +loop.cond: ; preds = %entry + %3 = 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 + %4 = load i64, ptr %.anon, align 8 + %subnuw = sub nuw i64 %4, 1 + store i64 %subnuw, ptr %.anon, align 8 + %5 = load i64, ptr %.anon, align 8 + store i64 %5, ptr %index, align 8 + %6 = load ptr, ptr %x, align 8 + %7 = load i64, ptr %index, align 8 + %ptroffset = getelementptr inbounds [4 x i8], ptr %6, i64 %7 + %8 = load i32, ptr %ptroffset, align 4 + store i32 %8, ptr %f, align 4 + %9 = load i32, ptr %f, align 4 + %10 = call i32 (ptr, ...) @printf(ptr @.str, i32 %9) + br label %loop.body1 + +loop.body1: ; preds = %loop.body + br label %loop.exit + +loop.exit: ; preds = %loop.body1, %loop.cond + ret void +} diff --git a/test/test_suite7/statements/foreach_r_errors.c3 b/test/test_suite7/statements/foreach_r_errors.c3 new file mode 100644 index 000000000..df840104a --- /dev/null +++ b/test/test_suite7/statements/foreach_r_errors.c3 @@ -0,0 +1,54 @@ +module test; + +extern fn void foo(); +int[3] z; + +fn void test1() +{ + int x; + foreach_r (a : x) // #error: It's not possible to enumerate an expression of type 'int'. + { + foo(); + } +} + +fn void test2() +{ + foreach_r (a : z) foo(); + foreach_r (i, a : z) foo(); + foreach_r (double i, a : z); // #error: Index must be an integer type, 'double' is not valid. +} + +fn void test3() +{ + foreach_r (&a : z) foo(); + foreach_r (&i, &a : z) foo(); // #error: The index cannot be held by reference, did you accidentally add a '&'? +} + +fn void test4() +{ + foreach_r (&a : z) foo(); + foreach_r (&i, a : z) foo(); // #error: The index cannot be held by reference, did you accidentally add a '&'? +} + +fn void test5() +{ + foreach_r (int! y : z) foo(); +} + +fn void test6() +{ + foreach_r (int! i, y : z) foo(); // #error: The index may not be an optional. +} + +fn void test7() +{ + foreach_r (int a : { 1, 2, 3 }) foo(); + foreach_r (a : { 1, 2, 3 }) foo(); // #error: Add an explicit type to the variable +} + +fn void test8() +{ + foreach_r (int a : { z }) foo(); // #error: 'int[3]' to 'int' +} + diff --git a/test/test_suite7/statements/foreach_r_parse_error.c3 b/test/test_suite7/statements/foreach_r_parse_error.c3 new file mode 100644 index 000000000..a7a00b965 --- /dev/null +++ b/test/test_suite7/statements/foreach_r_parse_error.c3 @@ -0,0 +1,5 @@ +fn void test9() +{ + foreach_r (int a : { [2] = 1 }) foo(); + foreach_r (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_suite7/statements/foreach_r_with_error.c3 b/test/test_suite7/statements/foreach_r_with_error.c3 new file mode 100644 index 000000000..dea64e90c --- /dev/null +++ b/test/test_suite7/statements/foreach_r_with_error.c3 @@ -0,0 +1,12 @@ +module test; + +fn void test() +{ + int[3]! x; + int g; + foreach_r (z : x) // #error: The foreach iterable expression may not be + { + g += z; + x[0] = 1; + } +} diff --git a/test/test_suite7/statements/foreach_with_error.c3 b/test/test_suite7/statements/foreach_with_error.c3 new file mode 100644 index 000000000..7edd14487 --- /dev/null +++ b/test/test_suite7/statements/foreach_with_error.c3 @@ -0,0 +1,12 @@ +module test; + +fn void test() +{ + int[3]! x; + int g; + foreach (z : x) // #error: The foreach iterable expression + { + g += z; + x[0] = 1; + } +} diff --git a/test/test_suite7/statements/foreach_wrong_index.c3 b/test/test_suite7/statements/foreach_wrong_index.c3 new file mode 100644 index 000000000..67f1580b3 --- /dev/null +++ b/test/test_suite7/statements/foreach_wrong_index.c3 @@ -0,0 +1,27 @@ +import std::io; + +struct Foo +{ + int[3] elements; +} + +fn int Foo.at(Foo *vector, float index) @operator([]) +{ + return 1; +} + +fn int Foo.len(Foo *vector) @operator(len) +{ + return 3; +} + +fn void main() +{ + + Foo f; + io::printfn("%s", f[12.2]); + foreach (int i, value : f) // #error: Only integer + { + io::printfn("v[%s] = %s", i, value); + } +} \ No newline at end of file diff --git a/test/test_suite7/statements/if_decl.c3 b/test/test_suite7/statements/if_decl.c3 new file mode 100644 index 000000000..ad245ec61 --- /dev/null +++ b/test/test_suite7/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_suite7/statements/if_only_throw.c3t b/test/test_suite7/statements/if_only_throw.c3t new file mode 100644 index 000000000..de4517409 --- /dev/null +++ b/test/test_suite7/statements/if_only_throw.c3t @@ -0,0 +1,30 @@ +// #target: macos-x64 +module foo; +import std::io; + +fault Foo { ABC } +fn void! test() +{ + if ((Foo.ABC?!)) + { + } + else + { + } +} +fn void main() +{ + (void)test(); +} + +/* #expect: foo.ll + +define i64 @foo.test() #0 { +entry: + %error_var = alloca i64, align 8 + store i64 ptrtoint (ptr @"foo.Foo$ABC" to i64), ptr %error_var, align 8 + br label %guard_block +guard_block: ; preds = %entry + %0 = load i64, ptr %error_var, align 8 + ret i64 %0 +} diff --git a/test/test_suite7/statements/if_single.c3 b/test/test_suite7/statements/if_single.c3 new file mode 100644 index 000000000..94ae517ca --- /dev/null +++ b/test/test_suite7/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_suite7/statements/if_tests.c3t b/test/test_suite7/statements/if_tests.c3t new file mode 100644 index 000000000..a4a2d99b1 --- /dev/null +++ b/test/test_suite7/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_suite7/statements/if_while_do_error.c3 b/test/test_suite7/statements/if_while_do_error.c3 new file mode 100644 index 000000000..3658e1d8b --- /dev/null +++ b/test/test_suite7/statements/if_while_do_error.c3 @@ -0,0 +1,34 @@ +module test; + +fn void test1() +{ + bool! x = false; + if (x) // #error: optional, but was 'bool! + { + x = 100; + } +} + +fn void test2() +{ + bool! x = false; + while (x) // #error: optional, but was 'bool! + { + x = false; + } +} + +fn void test3() +{ + bool! x = false; + double y = 1; + do + { + y = y + 1; + } while (y); + do + { + x = !x; + } + while (x); // #error: 'bool!' cannot be implicitly converted to a regular boolean value +} \ No newline at end of file diff --git a/test/test_suite7/statements/infinite_do_while.c3t b/test/test_suite7/statements/infinite_do_while.c3t new file mode 100644 index 000000000..b980fe179 --- /dev/null +++ b/test/test_suite7/statements/infinite_do_while.c3t @@ -0,0 +1,40 @@ +// #target: macos-x64 +module test; +int x; +fn void test1() +{ + while (true) { + testx(); + } +} +fn void test2() +{ + do { + testx(); + } while (true); +} +fn void testx() {} + +fn void main() +{} + +/* #expect: test.ll + +define void @test.test1() #0 { +entry: + br label %loop.body + +loop.body: ; preds = %loop.body, %entry + call void @test.testx() + br label %loop.body +} + +define void @test.test2() #0 { +entry: + br label %loop.body + +loop.body: ; preds = %loop.body, %entry + call void @test.testx() + br label %loop.body + +} \ No newline at end of file diff --git a/test/test_suite7/statements/label_errors.c3 b/test/test_suite7/statements/label_errors.c3 new file mode 100644 index 000000000..792363085 --- /dev/null +++ b/test/test_suite7/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: A labelled statement with the name 'BAR' can't be found in the current scope + } + }; +} \ No newline at end of file diff --git a/test/test_suite7/statements/labelled_continue_for.c3t b/test/test_suite7/statements/labelled_continue_for.c3t new file mode 100644 index 000000000..c44a7ae9d --- /dev/null +++ b/test/test_suite7/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_suite7/statements/nextcase_const.c3t b/test/test_suite7/statements/nextcase_const.c3t new file mode 100644 index 000000000..1a444efb3 --- /dev/null +++ b/test/test_suite7/statements/nextcase_const.c3t @@ -0,0 +1,52 @@ +// #target: macos-x64 +module test; + +fn void main() +{ + int a; + switch (a) + { + case a++: + nextcase 0; + case 10: + nextcase a + 1; + default: + a--; + } +} + +/* #expect: test.ll + +entry: + %a = alloca i32, align 4 + %switch = alloca i32, align 4 + store i32 0, ptr %a, align 4 + %0 = load i32, ptr %a, align 4 + store i32 %0, ptr %switch, align 4 + br label %switch.entry +switch.entry: ; preds = %switch.case2, %switch.case, %entry + %1 = load i32, ptr %switch, align 4 + %2 = load i32, ptr %a, align 4 + %add = add i32 %2, 1 + store i32 %add, ptr %a, align 4 + %eq = icmp eq i32 %2, %1 + br i1 %eq, label %switch.case, label %next_if +switch.case: ; preds = %switch.entry + store i32 0, ptr %switch, align 4 + br label %switch.entry +next_if: ; preds = %switch.entry + %eq1 = icmp eq i32 10, %1 + br i1 %eq1, label %switch.case2, label %next_if4 +switch.case2: ; preds = %next_if + %3 = load i32, ptr %a, align 4 + %add3 = add i32 %3, 1 + store i32 %add3, ptr %switch, align 4 + br label %switch.entry +next_if4: ; preds = %next_if + br label %switch.default +switch.default: ; preds = %next_if4 + %4 = load i32, ptr %a, align 4 + %sub = sub i32 %4, 1 + store i32 %sub, ptr %a, align 4 + br label %switch.exit +switch.exit: ; preds = %switch.default diff --git a/test/test_suite7/statements/nextcase_default.c3t b/test/test_suite7/statements/nextcase_default.c3t new file mode 100644 index 000000000..ada26864e --- /dev/null +++ b/test/test_suite7/statements/nextcase_default.c3t @@ -0,0 +1,121 @@ +// #target: macos-x64 +module test; + +fn void main() +{ + int a = 0; + int b = 0; + switch (a) + { + case 0: + case 1: + b += 1; + nextcase default; + case 2: + b *= 2; + default: + b *= 3; + } + switch FOO: (a) + { + case 0: + case 1: + b -= 1; + switch (a) + { + case 0: + b /= 2; + nextcase FOO: default; + default: + b /= 3; + } + nextcase; + case 2: + b *= 2; + default: + b *= 10; + } +} + +/* #expect: test.ll + +entry: + %a = alloca i32, align 4 + %b = alloca i32, align 4 + %switch = alloca i32, align 4 + %switch3 = alloca i32, align 4 + %switch6 = alloca i32, align 4 + store i32 0, ptr %a, align 4 + store i32 0, ptr %b, align 4 + %0 = load i32, ptr %a, 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.default [ + i32 0, label %switch.case + i32 1, label %switch.case + i32 2, label %switch.case1 + ] +switch.case: ; preds = %switch.entry, %switch.entry + %2 = load i32, ptr %b, align 4 + %add = add i32 %2, 1 + store i32 %add, ptr %b, align 4 + br label %switch.default +switch.case1: ; preds = %switch.entry + %3 = load i32, ptr %b, align 4 + %mul = mul i32 %3, 2 + store i32 %mul, ptr %b, align 4 + br label %switch.exit +switch.default: ; preds = %switch.case, %switch.entry + %4 = load i32, ptr %b, align 4 + %mul2 = mul i32 %4, 3 + store i32 %mul2, ptr %b, align 4 + br label %switch.exit +switch.exit: ; preds = %switch.default, %switch.case1 + %5 = load i32, ptr %a, align 4 + store i32 %5, ptr %switch3, align 4 + br label %switch.entry4 +switch.entry4: ; preds = %switch.exit + %6 = load i32, ptr %switch3, align 4 + switch i32 %6, label %switch.default14 [ + i32 0, label %switch.case5 + i32 1, label %switch.case5 + i32 2, label %switch.case12 + ] +switch.case5: ; preds = %switch.entry4, %switch.entry4 + %7 = load i32, ptr %b, align 4 + %sub = sub i32 %7, 1 + store i32 %sub, ptr %b, align 4 + %8 = load i32, ptr %a, align 4 + store i32 %8, ptr %switch6, align 4 + br label %switch.entry7 +switch.entry7: ; preds = %switch.case5 + %9 = load i32, ptr %switch6, align 4 + switch i32 %9, label %switch.default9 [ + i32 0, label %switch.case8 + ] +switch.case8: ; preds = %switch.entry7 + %10 = load i32, ptr %b, align 4 + %sdiv = sdiv i32 %10, 2 + store i32 %sdiv, ptr %b, align 4 + br label %switch.default14 +switch.default9: ; preds = %switch.entry7 + %11 = load i32, ptr %b, align 4 + %sdiv10 = sdiv i32 %11, 3 + store i32 %sdiv10, ptr %b, align 4 + br label %switch.exit11 +switch.exit11: ; preds = %switch.default9 + br label %switch.case12 +switch.case12: ; preds = %switch.entry4, %switch.exit11 + %12 = load i32, ptr %b, align 4 + %mul13 = mul i32 %12, 2 + store i32 %mul13, ptr %b, align 4 + br label %switch.exit16 +switch.default14: ; preds = %switch.case8, %switch.entry4 + %13 = load i32, ptr %b, align 4 + %mul15 = mul i32 %13, 10 + store i32 %mul15, ptr %b, align 4 + br label %switch.exit16 +switch.exit16: ; preds = %switch.default14, %switch.case12 + ret void \ No newline at end of file diff --git a/test/test_suite7/statements/nextcase_missing_case.c3 b/test/test_suite7/statements/nextcase_missing_case.c3 new file mode 100644 index 000000000..1b2871b5b --- /dev/null +++ b/test/test_suite7/statements/nextcase_missing_case.c3 @@ -0,0 +1,14 @@ +module test; +import std::io; + +fn void main() +{ + int a; + switch (a) + { + case 1: + nextcase 0; // #error: There is no 'case 0' + default: + + } +} \ No newline at end of file diff --git a/test/test_suite7/statements/nextcase_no_switch.c3 b/test/test_suite7/statements/nextcase_no_switch.c3 new file mode 100644 index 000000000..357fdb505 --- /dev/null +++ b/test/test_suite7/statements/nextcase_no_switch.c3 @@ -0,0 +1,11 @@ +fn void main() +{ + int x = 0; + switch + { + case true: + nextcase false; // #error: cannot be used with + default: + break; + } +} \ No newline at end of file diff --git a/test/test_suite7/statements/ranged_switch.c3t b/test/test_suite7/statements/ranged_switch.c3t new file mode 100644 index 000000000..74ccfd861 --- /dev/null +++ b/test/test_suite7/statements/ranged_switch.c3t @@ -0,0 +1,229 @@ +// #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 +target triple = "x86_64-apple + +@.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 + + +declare void @printf(ptr, ...) #0 + + +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 +} + + +define i32 @main(i32 %0, ptr %1) #0 { +entry: + call void @foo.main() + ret i32 0 +} + diff --git a/test/test_suite7/statements/return_stmt.c3 b/test/test_suite7/statements/return_stmt.c3 new file mode 100644 index 000000000..51da39f94 --- /dev/null +++ b/test/test_suite7/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_suite7/statements/return_switch.c3t b/test/test_suite7/statements/return_switch.c3t new file mode 100644 index 000000000..cced667f5 --- /dev/null +++ b/test/test_suite7/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_suite7/statements/return_with_other_at_end.c3 b/test/test_suite7/statements/return_with_other_at_end.c3 new file mode 100644 index 000000000..a18b63709 --- /dev/null +++ b/test/test_suite7/statements/return_with_other_at_end.c3 @@ -0,0 +1,7 @@ +fn int testReturnWithOtherAtEnd() +{ + int i = 0; + return i; + if (i == 10) i++; // #warning: This code will + i = i + 2; +} diff --git a/test/test_suite7/statements/simple_do.c3t b/test/test_suite7/statements/simple_do.c3t new file mode 100644 index 000000000..34fcae25a --- /dev/null +++ b/test/test_suite7/statements/simple_do.c3t @@ -0,0 +1,112 @@ +// #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 +target triple = "x86_64-apple + +@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 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 +} + + +declare void @printf(ptr, ...) #0 + + +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 = call i32 @foo.test() + %5 = load i32, ptr %i, align 4 + call void (ptr, ...) @printf(ptr @.str.1, i32 %5, i32 %4) + %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 +} + + +define i32 @main(i32 %0, ptr %1) #0 { +entry: + call void @foo.main() + ret i32 0 +} diff --git a/test/test_suite7/statements/switch_error_fallthrough.c3 b/test/test_suite7/statements/switch_error_fallthrough.c3 new file mode 100644 index 000000000..991d1fd1d --- /dev/null +++ b/test/test_suite7/statements/switch_error_fallthrough.c3 @@ -0,0 +1,11 @@ +fn int main() +{ + int a; + switch (a) + { + case 1: // #error: Fallthrough cases + // ... + case 2: + } + return 0; +} \ No newline at end of file diff --git a/test/test_suite7/statements/switch_error_range.c3 b/test/test_suite7/statements/switch_error_range.c3 new file mode 100644 index 000000000..fe39cce9d --- /dev/null +++ b/test/test_suite7/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_suite7/statements/switch_errors.c3 b/test/test_suite7/statements/switch_errors.c3 new file mode 100644 index 000000000..b9b2415f9 --- /dev/null +++ b/test/test_suite7/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: to 'Foo' + break; + } +} + +fn void test_check_nums() +{ + Foo f = A; + switch (f) + { + case Foo.from_ordinal(1): + break; + case Foo.from_ordinal(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.from_ordinal(1): + break; + case A: // #error: same case value appears + break; + } +} + +fn void test_duplicate_case3(Foo i) +{ + switch (i) + { + case A: + break; + case Foo.from_ordinal(0): // #error: same case value appears + break; + } +} + +enum Baz +{ + A, B, C, D +} + +fn void test_missing_all_cases(Baz x) +{ + switch (x) // #error: not handled in the switch: A, B, C, ... + { + } +} + +fn void test_missing_some_cases(Baz x) +{ + switch (x) // #error: not handled in the switch: B, C and D + { + case A: + break; + } +} + +fn void test_missing_some_cases2(Baz x) +{ + switch (x) // #error: B and D + { + case C: + case A: + break; + } +} + +fn void test_missing_some_cases3(Baz x) +{ + switch (x) // #error: Enum value D was not handled in the 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_suite7/statements/various_switching.c3t b/test/test_suite7/statements/various_switching.c3t new file mode 100644 index 000000000..489991d3d --- /dev/null +++ b/test/test_suite7/statements/various_switching.c3t @@ -0,0 +1,298 @@ +// #target: macos-x64 +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"); + } + switch + { + case a < 0: + printf("A negative\n"); + case a == 1: + printf("A is 1\n"); + default: + printf("Unexpected a\n"); + } +} +fn void main() +{ + test(); + printf("Hello!\n"); +} + +/* #expect: mymodule.ll + +define void @mymodule.test() #0 { +entry: + %x = alloca i32, align 4 + %x.f = alloca i64, align 8 + %z = alloca i64, align 8 + %err = alloca i64, align 8 + %switch = alloca i64, align 8 + %switch4 = alloca i64, align 8 + %a = alloca i32, align 4 + %b = alloca i32, align 4 + %zy = alloca i32, align 4 + %switch27 = alloca i32, align 4 + %switch37 = alloca i8, align 1 + store i64 ptrtoint (ptr @"mymodule.ByeErr$BAR" to i64), ptr %x.f, align 8 + store i64 ptrtoint (ptr @"$ct.int" to i64), ptr %z, align 8 + br label %testblock + +testblock: ; preds = %entry + %optval = load i64, ptr %x.f, align 8 + %not_err = icmp eq i64 %optval, 0 + %0 = call i1 @llvm.expect.i1(i1 %not_err, i1 true) + br i1 %0, label %after_check, label %assign_optional + +assign_optional: ; preds = %testblock + store i64 %optval, 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, %assign_optional + %1 = load i64, ptr %err, align 8 + %neq = icmp ne i64 %1, 0 + br i1 %neq, label %if.then, label %if.exit + +if.then: ; preds = %end_block + store i64 %1, ptr %switch, align 8 + br label %switch.entry + +switch.entry: ; preds = %if.then + %2 = load i64, ptr %switch, align 8 + %eq = icmp eq i64 ptrtoint (ptr @"mymodule.HelloErr$FOO" to i64), %2 + 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 @"mymodule.ByeErr$BAR" to i64), %2 + br i1 %eq1, label %switch.case2, label %next_if3 + +switch.case2: ; preds = %next_if + call void (ptr, ...) @printf(ptr @.str.3) + br label %switch.exit + +next_if3: ; preds = %next_if + br label %switch.default + +switch.default: ; preds = %next_if3 + call void (ptr, ...) @printf(ptr @.str.4) + br label %switch.exit + +switch.exit: ; preds = %switch.default, %switch.case2, %switch.case + br label %if.exit + +if.exit: ; preds = %switch.exit, %end_block + %3 = load i64, ptr %z, align 8 + store i64 %3, ptr %switch4, align 8 + br label %switch.entry5 + +switch.entry5: ; preds = %if.exit + %4 = load i64, ptr %switch4, align 8 + br label %check_subtype + +check_subtype: ; preds = %parent_type_block, %switch.entry5 + %5 = phi i64 [ %4, %switch.entry5 ], [ %typeid.parent, %parent_type_block ] + %eq6 = icmp eq i64 ptrtoint (ptr @"$ct.int" to i64), %5 + br i1 %eq6, label %result_block, label %parent_type_block + +parent_type_block: ; preds = %check_subtype + %6 = inttoptr i64 %5 to ptr + %ptradd = getelementptr inbounds i8, ptr %6, i64 8 + %typeid.parent = load i64, ptr %ptradd, align 8 + %7 = icmp eq i64 %typeid.parent, 0 + br i1 %7, label %result_block, label %check_subtype + +result_block: ; preds = %parent_type_block, %check_subtype + %8 = phi i1 [ false, %parent_type_block ], [ true, %check_subtype ] + br i1 %8, label %switch.case7, label %next_if8 + +switch.case7: ; preds = %result_block + call void (ptr, ...) @printf(ptr @.str.5) + br label %switch.exit26 + +next_if8: ; preds = %result_block + br label %check_subtype9 + +check_subtype9: ; preds = %parent_type_block11, %next_if8 + %9 = phi i64 [ %4, %next_if8 ], [ %typeid.parent13, %parent_type_block11 ] + %eq10 = icmp eq i64 ptrtoint (ptr @"$ct.bool" to i64), %9 + br i1 %eq10, label %result_block14, label %parent_type_block11 + +parent_type_block11: ; preds = %check_subtype9 + %10 = inttoptr i64 %9 to ptr + %ptradd12 = getelementptr inbounds i8, ptr %10, i64 8 + %typeid.parent13 = load i64, ptr %ptradd12, align 8 + %11 = icmp eq i64 %typeid.parent13, 0 + br i1 %11, label %result_block14, label %check_subtype9 + +result_block14: ; preds = %parent_type_block11, %check_subtype9 + %12 = phi i1 [ false, %parent_type_block11 ], [ true, %check_subtype9 ] + br i1 %12, label %switch.case15, label %next_if16 + +switch.case15: ; preds = %result_block14 + br label %switch.case23 + +next_if16: ; preds = %result_block14 + br label %check_subtype17 + +check_subtype17: ; preds = %parent_type_block19, %next_if16 + %13 = phi i64 [ %4, %next_if16 ], [ %typeid.parent21, %parent_type_block19 ] + %eq18 = icmp eq i64 ptrtoint (ptr @"$ct.double" to i64), %13 + br i1 %eq18, label %result_block22, label %parent_type_block19 + +parent_type_block19: ; preds = %check_subtype17 + %14 = inttoptr i64 %13 to ptr + %ptradd20 = getelementptr inbounds i8, ptr %14, i64 8 + %typeid.parent21 = load i64, ptr %ptradd20, align 8 + %15 = icmp eq i64 %typeid.parent21, 0 + br i1 %15, label %result_block22, label %check_subtype17 + +result_block22: ; preds = %parent_type_block19, %check_subtype17 + %16 = phi i1 [ false, %parent_type_block19 ], [ true, %check_subtype17 ] + br i1 %16, label %switch.case23, label %next_if24 + +switch.case23: ; preds = %result_block22, %switch.case15 + br label %switch.default25 + +next_if24: ; preds = %result_block22 + br label %switch.default25 + +switch.default25: ; preds = %next_if24, %switch.case23 + call void (ptr, ...) @printf(ptr @.str.6) + br label %switch.exit26 + +switch.exit26: ; preds = %switch.default25, %switch.case7 + store i32 1, ptr %a, align 4 + store i32 2, ptr %b, align 4 + %17 = load i32, ptr %b, align 4 + %18 = load i32, ptr %a, align 4 + %add = add i32 %17, %18 + store i32 %add, ptr %zy, align 4 + %19 = load i32, ptr %zy, align 4 + store i32 %19, ptr %switch27, align 4 + br label %switch.entry28 + +switch.entry28: ; preds = %switch.exit26 + %20 = load i32, ptr %switch27, align 4 + %21 = load i32, ptr %a, align 4 + %eq29 = icmp eq i32 %21, %20 + br i1 %eq29, label %switch.case30, label %next_if31 + +switch.case30: ; preds = %switch.entry28 + call void (ptr, ...) @printf(ptr @.str.7) + br label %switch.exit36 + +next_if31: ; preds = %switch.entry28 + %22 = load i32, ptr %b, align 4 + %eq32 = icmp eq i32 %22, %20 + br i1 %eq32, label %switch.case33, label %next_if34 + +switch.case33: ; preds = %next_if31 + call void (ptr, ...) @printf(ptr @.str.8) + br label %switch.exit36 + +next_if34: ; preds = %next_if31 + br label %switch.default35 + +switch.default35: ; preds = %next_if34 + call void (ptr, ...) @printf(ptr @.str.9) + br label %switch.exit36 + +switch.exit36: ; preds = %switch.default35, %switch.case33, %switch.case30 + store i8 1, ptr %switch37, align 1 + br label %switch.entry38 + +switch.entry38: ; preds = %switch.exit36 + %23 = load i8, ptr %switch37, align 1 + %24 = trunc i8 %23 to i1 + %25 = load i32, ptr %a, align 4 + %lt = icmp slt i32 %25, 0 + %eq39 = icmp eq i1 %lt, %24 + br i1 %eq39, label %switch.case40, label %next_if41 + +switch.case40: ; preds = %switch.entry38 + call void (ptr, ...) @printf(ptr @.str.10) + br label %switch.exit47 + +next_if41: ; preds = %switch.entry38 + %26 = load i32, ptr %a, align 4 + %eq42 = icmp eq i32 %26, 1 + %eq43 = icmp eq i1 %eq42, %24 + br i1 %eq43, label %switch.case44, label %next_if45 + +switch.case44: ; preds = %next_if41 + call void (ptr, ...) @printf(ptr @.str.11) + br label %switch.exit47 + +next_if45: ; preds = %next_if41 + br label %switch.default46 + +switch.default46: ; preds = %next_if45 + call void (ptr, ...) @printf(ptr @.str.12) + br label %switch.exit47 + +switch.exit47: ; preds = %switch.default46, %switch.case44, %switch.case40 + ret void +} + +; Function Attrs: +define void @mymodule.main() #0 { +entry: + call void @mymodule.test() + call void (ptr, ...) @printf(ptr @.str.13) + ret void +} diff --git a/test/test_suite7/statements/while_statement_placement.c3 b/test/test_suite7/statements/while_statement_placement.c3 new file mode 100644 index 000000000..66473b6eb --- /dev/null +++ b/test/test_suite7/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_suite7/statements/while_statement_placement2.c3 b/test/test_suite7/statements/while_statement_placement2.c3 new file mode 100644 index 000000000..c53d6086f --- /dev/null +++ b/test/test_suite7/statements/while_statement_placement2.c3 @@ -0,0 +1,34 @@ +import std; + +fn void loop_start() => io::printn("Loop Start"); +fn void loop_end() => io::printn("Loop End"); +fn void do_something() => io::printn("Do something"); + +macro @thing(; @body()) +{ + loop_start(); + @body(); + loop_end(); +} + +fn void strcpy(char *s1, char *s2) { + while (*s1++ = *s2++); +} + +fn void main() +{ + while (true) @thing() + { + do_something(); + break; + }; + for (;;) @thing() + { + do_something(); + break; + }; + if (true) @thing() + { + do_something(); + }; +} \ No newline at end of file diff --git a/test/test_suite7/statements/while_switch.c3t b/test/test_suite7/statements/while_switch.c3t new file mode 100644 index 000000000..a3ebd15ac --- /dev/null +++ b/test/test_suite7/statements/while_switch.c3t @@ -0,0 +1,90 @@ +// #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 +target triple = "x86_64-apple + +@.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 + + +declare i32 @printf(ptr, ...) #0 + + +declare i32 @foo() #0 + + +define i32 @main() #0 { +entry: + %switch = alloca i32, align 4 + br label %loop.cond + +loop.cond: ; preds = %switch.exit, %entry + %0 = call i32 @foo() + %i2b = icmp ne i32 %0, 0 + br i1 %i2b, 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 +} diff --git a/test/test_suite7/stdlib/ascii.c3 b/test/test_suite7/stdlib/ascii.c3 new file mode 100644 index 000000000..8390b1160 --- /dev/null +++ b/test/test_suite7/stdlib/ascii.c3 @@ -0,0 +1,26 @@ +import std::io; +import std::ascii; + +fn void main() +{ + for(char c = 0; c < 255; c++) + { + io::printfn("%c (%s) is...:", c, c); + io::printfn("lower: %s; upper: %s; digit: %s; bdigit: %s; odigit: %s; xdigit: %s; alpha: %s; print: %s; graph: %s; space: %s; alnum: %s; punct: %s; blank: %s; cntrl: %s;", + c.is_lower(), c.is_upper(), c.is_digit(), c.is_bdigit(), c.is_odigit(), c.is_xdigit(), c.is_alpha(), c.is_print(), + c.is_graph(), c.is_space(), c.is_alnum(), c.is_punct(), c.is_blank(), c.is_cntrl()); + } + + foreach(c : "0123456789abcdefghijklmnopqrstuvwxyz") + { + io::printfn("'%c'.to_upper(): %c", c, c.to_upper()); + } + foreach(c : "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ") + { + io::printfn("'%c'.to_lower(): %c", c, c.to_lower()); + } +} + + + + diff --git a/test/test_suite7/stdlib/map_linux.c3t b/test/test_suite7/stdlib/map_linux.c3t new file mode 100644 index 000000000..ad6757706 --- /dev/null +++ b/test/test_suite7/stdlib/map_linux.c3t @@ -0,0 +1,290 @@ +// #target: linux-x64 + +module test; +import std::io; +import std::collections::map; + +struct Foo (Printable) { int x; void* bar; } + +def IntFooMap = HashMap { int, Foo }; +def IntDoubleMap = HashMap { int, double }; + +fn String Foo.to_new_string(Foo* foo, Allocator allocator = allocator::heap()) @dynamic +{ + DString s = dstring::new_with_capacity(128, allocator); + s.appendf("{%s, %p}", foo.x, foo.bar); + return s.str_view(); +} + + + +fn void main() +{ + IntFooMap map; + map.init(mem); + io::printfn("Map size: %d", map.count); + map.set(1, { 1, null }); + io::printfn("Map size: %d", map.count); + map.set(1, { 2, null }); + io::printfn("Map size: %d", map.count); + (void)io::printfn("Val: %d", map.get(1).x); + io::printfn("Has 1: %s", map.has_key(1)); + io::printfn("Has 2: %s", map.has_key(2)); + map.set(7, { 4, null }); + io::printfn("Values: %s", map.values(mem)); + IntDoubleMap map2; + map2.init(mem); + map2.set(4, 1.3); + io::printfn("Map find: %s", map2.has_value(1.3)); + io::printfn("Map find: %s", map2.has_value(1.2)); + map2.set(100, 3.4); + io::printfn("%s", map2.keys(mem)); + io::printfn("%s", map2.values(mem)); + @pool() + { + IntDoubleMap map3; + map3.init(mem); + map3.set(5, 3.2); + map3.set(7, 5.2); + io::printfn("%s", map3.keys(mem)); + }; +} + +/* #expect: test.ll + +@"$sel.to_new_string" = linkonce_odr constant [14 x i8] c"to_new_string\00", comdat, align 1 +@llvm.global_ctors = appending global [1 x { i32, ptr, ptr }] [{ i32, ptr, ptr } { i32 1, ptr @.c3_dynamic_register, ptr null }] + +define { ptr, i64 } @test.Foo.to_new_string(ptr %0, i64 %1, ptr %2) #0 { +entry: + %allocator = alloca %any, align 8 + %s = alloca ptr, align 8 + %varargslots = alloca [2 x %any], align 16 + %retparam = alloca i64, align 8 + %result = alloca %"char[]", align 8 + store i64 %1, ptr %allocator, align 8 + %ptradd = getelementptr inbounds i8, ptr %allocator, i64 8 + store ptr %2, ptr %ptradd, align 8 + %lo = load i64, ptr %allocator, align 8 + %ptradd1 = getelementptr inbounds i8, ptr %allocator, i64 8 + %hi = load ptr, ptr %ptradd1, align 8 + %3 = call ptr @std.core.dstring.new_with_capacity(i64 128, i64 %lo, ptr %hi) + store ptr %3, ptr %s, align 8 + %4 = insertvalue %any undef, ptr %0, 0 + %5 = insertvalue %any %4, i64 ptrtoint (ptr @"$ct.int" to i64), 1 + store %any %5, ptr %varargslots, align 16 + %ptradd2 = getelementptr inbounds i8, ptr %0, i64 8 + %6 = insertvalue %any undef, ptr %ptradd2, 0 + %7 = insertvalue %any %6, i64 ptrtoint (ptr @"$ct.p$void" to i64), 1 + %ptradd3 = getelementptr inbounds i8, ptr %varargslots, i64 16 + store %any %7, ptr %ptradd3, align 16 + %8 = call i64 @std.core.dstring.DString.appendf(ptr %retparam, ptr %s, ptr @.str.14, i64 8, ptr %varargslots, i64 2) + %9 = load ptr, ptr %s, align 8 + %10 = call { ptr, i64 } @std.core.dstring.DString.str_view(ptr %9) + store { ptr, i64 } %10, ptr %result, align 8 + %11 = load { ptr, i64 }, ptr %result, align 8 + ret { ptr, i64 } %11 +} + +define void @test.main() #0 { +entry: + %map = alloca %HashMap, align 8 + %varargslots = alloca [1 x %any], align 16 + %retparam = alloca i64, align 8 + %literal = alloca %Foo, align 8 + %varargslots4 = alloca [1 x %any], align 16 + %retparam6 = alloca i64, align 8 + %literal7 = alloca %Foo, align 8 + %varargslots11 = alloca [1 x %any], align 16 + %retparam13 = alloca i64, align 8 + %varargslots14 = alloca [1 x %any], align 16 + %retparam15 = alloca %Foo, align 8 + %retparam16 = alloca i64, align 8 + %varargslots19 = alloca [1 x %any], align 16 + %taddr = alloca i8, align 1 + %retparam20 = alloca i64, align 8 + %varargslots23 = alloca [1 x %any], align 16 + %taddr24 = alloca i8, align 1 + %retparam25 = alloca i64, align 8 + %literal28 = alloca %Foo, align 8 + %varargslots32 = alloca [1 x %any], align 16 + %result = alloca %"Foo[]", align 8 + %retparam35 = alloca i64, align 8 + %map2 = alloca %HashMap.0, align 8 + %varargslots40 = alloca [1 x %any], align 16 + %taddr41 = alloca i8, align 1 + %retparam42 = alloca i64, align 8 + %varargslots45 = alloca [1 x %any], align 16 + %taddr46 = alloca i8, align 1 + %retparam47 = alloca i64, align 8 + %varargslots50 = alloca [1 x %any], align 16 + %result53 = alloca %"int[]", align 8 + %retparam54 = alloca i64, align 8 + %varargslots57 = alloca [1 x %any], align 16 + %result60 = alloca %"double[]", align 8 + %retparam61 = alloca i64, align 8 + %current = alloca ptr, align 8 + %mark = alloca i64, align 8 + %map3 = alloca %HashMap.0, align 8 + %varargslots67 = alloca [1 x %any], align 16 + %result70 = alloca %"int[]", align 8 + %retparam71 = alloca i64, align 8 + call void @llvm.memset.p0.i64(ptr align 8 %map, i8 0, i64 48, i1 false) + %lo = load i64, ptr @std.core.mem.allocator.thread_allocator, align 8 + %hi = load ptr, ptr getelementptr inbounds (i8, ptr @std.core.mem.allocator.thread_allocator, i64 8), align 8 + %0 = call ptr @"std_collections_map$int$test.Foo$.HashMap.init"(ptr %map + %ptradd = getelementptr inbounds i8, ptr %map, i64 32 + %1 = insertvalue %any undef, ptr %ptradd, 0 + %2 = insertvalue %any %1, i64 ptrtoint (ptr @"$ct.uint" to i64), 1 + store %any %2, ptr %varargslots, align 16 + %3 = call i64 @std.io.printfn(ptr %retparam, ptr @.str, i64 12, ptr %varargslots, i64 1) + call void @llvm.memcpy.p0.p0.i32(ptr align 8 %literal, ptr align 8 @.__const, i32 16, i1 false) + %lo1 = load i32, ptr %literal, align 8 + %ptradd2 = getelementptr inbounds i8, ptr %literal, i64 8 + %hi3 = load ptr, ptr %ptradd2, align 8 + %4 = call i8 @"std_collections_map$int$test.Foo$.HashMap.set"(ptr %map, i32 1, i32 %lo1, ptr %hi3) + %ptradd5 = getelementptr inbounds i8, ptr %map, i64 32 + %5 = insertvalue %any undef, ptr %ptradd5, 0 + %6 = insertvalue %any %5, i64 ptrtoint (ptr @"$ct.uint" to i64), 1 + store %any %6, ptr %varargslots4, align 16 + %7 = call i64 @std.io.printfn(ptr %retparam6, ptr @.str.1, i64 12, ptr %varargslots4, i64 1) + call void @llvm.memcpy.p0.p0.i32(ptr align 8 %literal7, ptr align 8 @.__const.2, i32 16, i1 false) + %lo8 = load i32, ptr %literal7, align 8 + %ptradd9 = getelementptr inbounds i8, ptr %literal7, i64 8 + %hi10 = load ptr, ptr %ptradd9, align 8 + %8 = call i8 @"std_collections_map$int$test.Foo$.HashMap.set"(ptr %map, i32 1, i32 %lo8, ptr %hi10) + %ptradd12 = getelementptr inbounds i8, ptr %map, i64 32 + %9 = insertvalue %any undef, ptr %ptradd12, 0 + %10 = insertvalue %any %9, i64 ptrtoint (ptr @"$ct.uint" to i64), 1 + store %any %10, ptr %varargslots11, align 16 + %11 = call i64 @std.io.printfn(ptr %retparam13, ptr @.str.3, i64 12, ptr %varargslots11, i64 1) + %12 = call i64 @"std_collections_map$int$test.Foo$.HashMap.get"(ptr %retparam15, ptr %map, i32 1) + %not_err = icmp eq i64 %12, 0 + %13 = call i1 @llvm.expect.i1(i1 %not_err, i1 true) + br i1 %13, label %after_check, label %after_check18 + +after_check: ; preds = %entry + %14 = insertvalue %any undef, ptr %retparam15, 0 + %15 = insertvalue %any %14, i64 ptrtoint (ptr @"$ct.int" to i64), 1 + store %any %15, ptr %varargslots14, align 16 + %16 = call i64 @std.io.printfn(ptr %retparam16, ptr @.str.4, i64 7, ptr %varargslots14, i64 1) + %not_err17 = icmp eq i64 %16, 0 + %17 = call i1 @llvm.expect.i1(i1 %not_err17, i1 true) + br i1 %17, label %after_check18, label %after_check18 + +after_check18: ; preds = %entry, %after_check, %after_check + %18 = call i8 @"std_collections_map$int$test.Foo$.HashMap.has_key"(ptr %map, i32 1) + store i8 %18, ptr %taddr, align 1 + %19 = insertvalue %any undef, ptr %taddr, 0 + %20 = insertvalue %any %19, i64 ptrtoint (ptr @"$ct.bool" to i64), 1 + store %any %20, ptr %varargslots19, align 16 + %21 = call i64 @std.io.printfn(ptr %retparam20, ptr @.str.5, i64 9, ptr %varargslots19, i64 1) + %22 = call i8 @"std_collections_map$int$test.Foo$.HashMap.has_key"(ptr %map, i32 2) + store i8 %22, ptr %taddr24, align 1 + %23 = insertvalue %any undef, ptr %taddr24, 0 + %24 = insertvalue %any %23, i64 ptrtoint (ptr @"$ct.bool" to i64), 1 + store %any %24, ptr %varargslots23, align 16 + %25 = call i64 @std.io.printfn(ptr %retparam25, ptr @.str.6, i64 9, ptr %varargslots23, i64 1) + call void @llvm.memcpy.p0.p0.i32(ptr align 8 %literal28, ptr align 8 @.__const.7, i32 16, i1 false) + %lo29 = load i32, ptr %literal28, align 8 + %ptradd30 = getelementptr inbounds i8, ptr %literal28, i64 8 + %hi31 = load ptr, ptr %ptradd30, align 8 + %26 = call i8 @"std_collections_map$int$test.Foo$.HashMap.set"(ptr %map, i32 7, i32 %lo29, ptr %hi31) + %lo33 = load i64, ptr @std.core.mem.allocator.thread_allocator, align 8 + %hi34 = load ptr, ptr getelementptr inbounds (i8, ptr @std.core.mem.allocator.thread_allocator, i64 8), align 8 + %27 = call { ptr, i64 } @"std_collections_map$int$test.Foo$.HashMap.values"(ptr %map, i64 %lo33, ptr %hi34) + store { ptr, i64 } %27, ptr %result, align 8 + %28 = insertvalue %any undef, ptr %result, 0 + %29 = insertvalue %any %28, i64 ptrtoint (ptr @"$ct.sa$test.Foo" to i64), 1 + store %any %29, ptr %varargslots32, align 16 + %30 = call i64 @std.io.printfn(ptr %retparam35, ptr @.str.8, i64 10, ptr %varargslots32, i64 1) + call void @llvm.memset.p0.i64(ptr align 8 %map2, i8 0, i64 48, i1 false) + %lo38 = load i64, ptr @std.core.mem.allocator.thread_allocator, align 8 + %hi39 = load ptr, ptr getelementptr inbounds (i8, ptr @std.core.mem.allocator.thread_allocator, i64 8), align 8 + %31 = call ptr @"std_collections_map$int$double$.HashMap.init"(ptr %map2 + %32 = call i8 @"std_collections_map$int$double$.HashMap.set"(ptr %map2, i32 4, double 1.300000e+00) + %33 = call i8 @"std_collections_map$int$double$.HashMap.has_value"(ptr %map2, double 1.300000e+00) + store i8 %33, ptr %taddr41, align 1 + %34 = insertvalue %any undef, ptr %taddr41, 0 + %35 = insertvalue %any %34, i64 ptrtoint (ptr @"$ct.bool" to i64), 1 + store %any %35, ptr %varargslots40, align 16 + %36 = call i64 @std.io.printfn(ptr %retparam42, ptr @.str.9, i64 12, ptr %varargslots40, i64 1) + %37 = call i8 @"std_collections_map$int$double$.HashMap.has_value"(ptr %map2, double 1.200000e+00) + store i8 %37, ptr %taddr46, align 1 + %38 = insertvalue %any undef, ptr %taddr46, 0 + %39 = insertvalue %any %38, i64 ptrtoint (ptr @"$ct.bool" to i64), 1 + store %any %39, ptr %varargslots45, align 16 + %40 = call i64 @std.io.printfn(ptr %retparam47, ptr @.str.10, i64 12, ptr %varargslots45, i64 1) + %41 = call i8 @"std_collections_map$int$double$.HashMap.set"(ptr %map2, i32 100, double 3.400000e+00) + %lo51 = load i64, ptr @std.core.mem.allocator.thread_allocator, align 8 + %hi52 = load ptr, ptr getelementptr inbounds (i8, ptr @std.core.mem.allocator.thread_allocator, i64 8), align 8 + %42 = call { ptr, i64 } @"std_collections_map$int$double$.HashMap.keys"(ptr %map2, i64 %lo51, ptr %hi52) + store { ptr, i64 } %42, ptr %result53, align 8 + %43 = insertvalue %any undef, ptr %result53, 0 + %44 = insertvalue %any %43, i64 ptrtoint (ptr @"$ct.sa$int" to i64), 1 + store %any %44, ptr %varargslots50, align 16 + %45 = call i64 @std.io.printfn(ptr %retparam54, ptr @.str.11, i64 2, ptr %varargslots50, i64 1) + %lo58 = load i64, ptr @std.core.mem.allocator.thread_allocator, align 8 + %hi59 = load ptr, ptr getelementptr inbounds (i8, ptr @std.core.mem.allocator.thread_allocator, i64 8), align 8 + %46 = call { ptr, i64 } @"std_collections_map$int$double$.HashMap.values"(ptr %map2, i64 %lo58, ptr %hi59) + store { ptr, i64 } %46, ptr %result60, align 8 + %47 = insertvalue %any undef, ptr %result60, 0 + %48 = insertvalue %any %47, i64 ptrtoint (ptr @"$ct.sa$double" to i64), 1 + store %any %48, ptr %varargslots57, align 16 + %49 = call i64 @std.io.printfn(ptr %retparam61, ptr @.str.12, i64 2, ptr %varargslots57, i64 1) + %50 = load ptr, ptr @std.core.mem.allocator.thread_temp_allocator, align 8 + %i2nb = icmp eq ptr %50, null + br i1 %i2nb, label %if.then, label %if.exit + +if.then: ; preds = %after_check18 + call void @std.core.mem.allocator.init_default_temp_allocators() + br label %if.exit + +if.exit: ; preds = %if.then, %after_check18 + %51 = load ptr, ptr @std.core.mem.allocator.thread_temp_allocator, align 8 + store ptr %51, ptr %current, align 8 + %52 = load ptr, ptr %current, align 8 + %ptradd64 = getelementptr inbounds i8, ptr %52, i64 24 + %53 = load i64, ptr %ptradd64, align 8 + store i64 %53, ptr %mark, align 8 + call void @llvm.memset.p0.i64(ptr align 8 %map3, i8 0, i64 48, i1 false) + %lo65 = load i64, ptr @std.core.mem.allocator.thread_allocator, align 8 + %hi66 = load ptr, ptr getelementptr inbounds + %54 = call ptr @"std_collections_map$int$double$.HashMap.init"(ptr %map3, + %55 = call i8 @"std_collections_map$int$double$.HashMap.set"(ptr %map3, i32 5, double 3.200000e+00) + %56 = call i8 @"std_collections_map$int$double$.HashMap.set"(ptr %map3, i32 7, double 5.200000e+00) + %lo68 = load i64, ptr @std.core.mem.allocator.thread_allocator, align 8 + %hi69 = load ptr, ptr getelementptr inbounds (i8, ptr @std.core.mem.allocator.thread_allocator, i64 8), align 8 + %57 = call { ptr, i64 } @"std_collections_map$int$double$.HashMap.keys"(ptr %map3, i64 %lo68, ptr %hi69) + store { ptr, i64 } %57, ptr %result70, align 8 + %58 = insertvalue %any undef, ptr %result70, 0 + %59 = insertvalue %any %58, i64 ptrtoint (ptr @"$ct.sa$int" to i64), 1 + store %any %59, ptr %varargslots67, align 16 + %60 = call i64 @std.io.printfn(ptr %retparam71, ptr @.str.13, i64 2, ptr %varargslots67, i64 1) + %61 = load ptr, ptr %current, align 8 + %62 = load i64, ptr %mark, align 8 + call void @std.core.mem.allocator.TempAllocator.reset(ptr %61, i64 %62) + ret void +} + +define internal void @.c3_dynamic_register() align 8 { +entry: + %next_val = load ptr, ptr getelementptr + %0 = icmp eq ptr %next_val, inttoptr (i64 -1 to ptr) + br i1 %0, label %dtable_check, label %dtable_skip + +dtable_check: ; preds = %dtable_check, %entry + %dtable_ref = phi ptr [ getelementptr inbounds + %dtable_ptr = load ptr, ptr %dtable_ref, align 8 + %1 = icmp eq ptr %dtable_ptr, null + %next_dtable_ref = getelementptr inbounds + br i1 %1, label %dtable_found, label %dtable_check + +dtable_found: ; preds = %dtable_check + store ptr @"$ct.dyn.test.Foo.to_new_string", ptr %dtable_ref, align 8 + store ptr null, ptr getelementptr inbounds + br label %dtable_skip + +dtable_skip: ; preds = %dtable_found, %entry + ret void +} diff --git a/test/test_suite7/stdlib/map_macos.c3t b/test/test_suite7/stdlib/map_macos.c3t new file mode 100644 index 000000000..3b2622bb5 --- /dev/null +++ b/test/test_suite7/stdlib/map_macos.c3t @@ -0,0 +1,268 @@ +// #target: macos-x64 + +module test; +import std::io; +import std::collections::map; + +struct Foo (Printable) { int x; void* bar; } + +def IntFooMap = HashMap { int, Foo }; +def IntDoubleMap = HashMap { int, double }; + +fn String Foo.to_new_string(Foo* foo, Allocator allocator = allocator::heap()) @dynamic +{ + DString s = dstring::new_with_capacity(128, allocator); + s.appendf("{%s, %p}", foo.x, foo.bar); + return s.str_view(); +} + + + +fn void main() +{ + IntFooMap map; + map.init(mem); + io::printfn("Map size: %d", map.count); + map.set(1, { 1, null }); + io::printfn("Map size: %d", map.count); + map.set(1, { 2, null }); + io::printfn("Map size: %d", map.count); + (void)io::printfn("Val: %d", map.get(1).x); + io::printfn("Has 1: %s", map.has_key(1)); + io::printfn("Has 2: %s", map.has_key(2)); + map.set(7, { 4, null }); + io::printfn("Values: %s", map.values(mem)); + IntDoubleMap map2; + map2.init(mem); + map2.set(4, 1.3); + io::printfn("Map find: %s", map2.has_value(1.3)); + io::printfn("Map find: %s", map2.has_value(1.2)); + map2.set(100, 3.4); + io::printfn("%s", map2.keys(mem)); + io::printfn("%s", map2.values(mem)); + @pool() + { + IntDoubleMap map3; + map3.init(mem); + map3.set(5, 3.2); + map3.set(7, 5.2); + io::printfn("%s", map3.keys(mem)); + }; +} + +/* #expect: test.ll + +@"$sel.to_new_string" = linkonce_odr constant [14 x i8] c"to_new_string\00", align 1 +@"$c3_dynamic" = internal global [1 x { ptr, ptr, i64 }] [{ ptr, ptr, i64 } { ptr @test.Foo.to_new_string, ptr @"$sel.to_new_string", i64 ptrtoint (ptr @"$ct.test.Foo" to i64) }], section "__DATA,__c3_dynamic", align 8 + +define { ptr, i64 } @test.Foo.to_new_string(ptr %0, i64 %1, ptr %2) #0 { +entry: + %allocator = alloca %any, align 8 + %s = alloca ptr, align 8 + %varargslots = alloca [2 x %any], align 16 + %retparam = alloca i64, align 8 + %result = alloca %"char[]", align 8 + store i64 %1, ptr %allocator, align 8 + %ptradd = getelementptr inbounds i8, ptr %allocator, i64 8 + store ptr %2, ptr %ptradd, align 8 + %lo = load i64, ptr %allocator, align 8 + %ptradd1 = getelementptr inbounds i8, ptr %allocator, i64 8 + %hi = load ptr, ptr %ptradd1, align 8 + %3 = call ptr @std.core.dstring.new_with_capacity(i64 128, i64 %lo, ptr %hi) + store ptr %3, ptr %s, align 8 + %4 = insertvalue %any undef, ptr %0, 0 + %5 = insertvalue %any %4, i64 ptrtoint (ptr @"$ct.int" to i64), 1 + store %any %5, ptr %varargslots, align 16 + %ptradd2 = getelementptr inbounds i8, ptr %0, i64 8 + %6 = insertvalue %any undef, ptr %ptradd2, 0 + %7 = insertvalue %any %6, i64 ptrtoint (ptr @"$ct.p$void" to i64), 1 + %ptradd3 = getelementptr inbounds i8, ptr %varargslots, i64 16 + store %any %7, ptr %ptradd3, align 16 + %8 = call i64 @std.core.dstring.DString.appendf(ptr %retparam, ptr %s, ptr @.str.14, i64 8, ptr %varargslots, i64 2) + %9 = load ptr, ptr %s, align 8 + %10 = call { ptr, i64 } @std.core.dstring.DString.str_view(ptr %9) + store { ptr, i64 } %10, ptr %result, align 8 + %11 = load { ptr, i64 }, ptr %result, align 8 + ret { ptr, i64 } %11 +} + +define void @test.main() #0 { +entry: + %map = alloca %HashMap, align 8 + %varargslots = alloca [1 x %any], align 16 + %retparam = alloca i64, align 8 + %literal = alloca %Foo, align 8 + %varargslots4 = alloca [1 x %any], align 16 + %retparam6 = alloca i64, align 8 + %literal7 = alloca %Foo, align 8 + %varargslots11 = alloca [1 x %any], align 16 + %retparam13 = alloca i64, align 8 + %varargslots14 = alloca [1 x %any], align 16 + %retparam15 = alloca %Foo, align 8 + %retparam16 = alloca i64, align 8 + %varargslots19 = alloca [1 x %any], align 16 + %taddr = alloca i8, align 1 + %retparam20 = alloca i64, align 8 + %varargslots23 = alloca [1 x %any], align 16 + %taddr24 = alloca i8, align 1 + %retparam25 = alloca i64, align 8 + %literal28 = alloca %Foo, align 8 + %varargslots32 = alloca [1 x %any], align 16 + %result = alloca %"Foo[]", align 8 + %retparam35 = alloca i64, align 8 + %map2 = alloca %HashMap.0, align 8 + %varargslots40 = alloca [1 x %any], align 16 + %taddr41 = alloca i8, align 1 + %retparam42 = alloca i64, align 8 + %varargslots45 = alloca [1 x %any], align 16 + %taddr46 = alloca i8, align 1 + %retparam47 = alloca i64, align 8 + %varargslots50 = alloca [1 x %any], align 16 + %result53 = alloca %"int[]", align 8 + %retparam54 = alloca i64, align 8 + %varargslots57 = alloca [1 x %any], align 16 + %result60 = alloca %"double[]", align 8 + %retparam61 = alloca i64, align 8 + %current = alloca ptr, align 8 + %mark = alloca i64, align 8 + %map3 = alloca %HashMap.0, align 8 + %varargslots67 = alloca [1 x %any], align 16 + %result70 = alloca %"int[]", align 8 + %retparam71 = alloca i64, align 8 + call void @llvm.memset.p0.i64(ptr align 8 %map, i8 0, i64 48, i1 false) + %lo = load i64, ptr @std.core.mem.allocator.thread_allocator, align 8 + %hi = load ptr, ptr getelementptr inbounds (i8, ptr @std.core.mem.allocator.thread_allocator, i64 8), align 8 + %0 = call ptr @"std_collections_map$int$test.Foo$.HashMap.init"(ptr %map, i64 %lo, ptr %hi, i32 16, float 7.500000e-01) + %ptradd = getelementptr inbounds i8, ptr %map, i64 32 + %1 = insertvalue %any undef, ptr %ptradd, 0 + %2 = insertvalue %any %1, i64 ptrtoint (ptr @"$ct.uint" to i64), 1 + store %any %2, ptr %varargslots, align 16 + %3 = call i64 @std.io.printfn(ptr %retparam, ptr @.str, i64 12, ptr %varargslots, i64 1) + call void @llvm.memcpy.p0.p0.i32(ptr align 8 %literal, ptr align 8 @.__const, i32 16, i1 false) + %lo1 = load i32, ptr %literal, align 8 + %ptradd2 = getelementptr inbounds i8, ptr %literal, i64 8 + %hi3 = load ptr, ptr %ptradd2, align 8 + %4 = call i8 @"std_collections_map$int$test.Foo$.HashMap.set"(ptr %map, i32 1, i32 %lo1, ptr %hi3) + %ptradd5 = getelementptr inbounds i8, ptr %map, i64 32 + %5 = insertvalue %any undef, ptr %ptradd5, 0 + %6 = insertvalue %any %5, i64 ptrtoint (ptr @"$ct.uint" to i64), 1 + store %any %6, ptr %varargslots4, align 16 + %7 = call i64 @std.io.printfn(ptr %retparam6, ptr @.str.1, i64 12, ptr %varargslots4, i64 1) + call void @llvm.memcpy.p0.p0.i32(ptr align 8 %literal7, ptr align 8 @.__const.2, i32 16, i1 false) + %lo8 = load i32, ptr %literal7, align 8 + %ptradd9 = getelementptr inbounds i8, ptr %literal7, i64 8 + %hi10 = load ptr, ptr %ptradd9, align 8 + %8 = call i8 @"std_collections_map$int$test.Foo$.HashMap.set"(ptr %map, i32 1, i32 %lo8, ptr %hi10) + %ptradd12 = getelementptr inbounds i8, ptr %map, i64 32 + %9 = insertvalue %any undef, ptr %ptradd12, 0 + %10 = insertvalue %any %9, i64 ptrtoint (ptr @"$ct.uint" to i64), 1 + store %any %10, ptr %varargslots11, align 16 + %11 = call i64 @std.io.printfn(ptr %retparam13, ptr @.str.3, i64 12, ptr %varargslots11, i64 1) + %12 = call i64 @"std_collections_map$int$test.Foo$.HashMap.get"(ptr %retparam15, ptr %map, i32 1) + %not_err = icmp eq i64 %12, 0 + %13 = call i1 @llvm.expect.i1(i1 %not_err, i1 true) + br i1 %13, label %after_check, label %after_check18 + +after_check: ; preds = %entry + %14 = insertvalue %any undef, ptr %retparam15, 0 + %15 = insertvalue %any %14, i64 ptrtoint (ptr @"$ct.int" to i64), 1 + store %any %15, ptr %varargslots14, align 16 + %16 = call i64 @std.io.printfn(ptr %retparam16, ptr @.str.4, i64 7, ptr %varargslots14, i64 1) + %not_err17 = icmp eq i64 %16, 0 + %17 = call i1 @llvm.expect.i1(i1 %not_err17, i1 true) + br i1 %17, label %after_check18, label %after_check18 + +after_check18: ; preds = %entry, %after_check, %after_check + %18 = call i8 @"std_collections_map$int$test.Foo$.HashMap.has_key"(ptr %map, i32 1) + store i8 %18, ptr %taddr, align 1 + %19 = insertvalue %any undef, ptr %taddr, 0 + %20 = insertvalue %any %19, i64 ptrtoint (ptr @"$ct.bool" to i64), 1 + store %any %20, ptr %varargslots19, align 16 + %21 = call i64 @std.io.printfn(ptr %retparam20, ptr @.str.5, i64 9, ptr %varargslots19, i64 1) + %22 = call i8 @"std_collections_map$int$test.Foo$.HashMap.has_key"(ptr %map, i32 2) + store i8 %22, ptr %taddr24, align 1 + %23 = insertvalue %any undef, ptr %taddr24, 0 + %24 = insertvalue %any %23, i64 ptrtoint (ptr @"$ct.bool" to i64), 1 + store %any %24, ptr %varargslots23, align 16 + %25 = call i64 @std.io.printfn(ptr %retparam25, ptr @.str.6, i64 9, ptr %varargslots23, i64 1) + call void @llvm.memcpy.p0.p0.i32(ptr align 8 %literal28, ptr align 8 @.__const.7, i32 16, i1 false) + %lo29 = load i32, ptr %literal28, align 8 + %ptradd30 = getelementptr inbounds i8, ptr %literal28, i64 8 + %hi31 = load ptr, ptr %ptradd30, align 8 + %26 = call i8 @"std_collections_map$int$test.Foo$.HashMap.set"(ptr %map, i32 7, i32 %lo29, ptr %hi31) + %lo33 = load i64, ptr @std.core.mem.allocator.thread_allocator, align 8 + %hi34 = load ptr, ptr getelementptr inbounds (i8, ptr @std.core.mem.allocator.thread_allocator, i64 8), align 8 + %27 = call { ptr, i64 } @"std_collections_map$int$test.Foo$.HashMap.values"(ptr %map, i64 %lo33, ptr %hi34) + store { ptr, i64 } %27, ptr %result, align 8 + %28 = insertvalue %any undef, ptr %result, 0 + %29 = insertvalue %any %28, i64 ptrtoint (ptr @"$ct.sa$test.Foo" to i64), 1 + store %any %29, ptr %varargslots32, align 16 + %30 = call i64 @std.io.printfn(ptr %retparam35, ptr @.str.8, i64 10, ptr %varargslots32, i64 1) + call void @llvm.memset.p0.i64(ptr align 8 %map2, i8 0, i64 48, i1 false) + %lo38 = load i64, ptr @std.core.mem.allocator.thread_allocator, align 8 + %hi39 = load ptr, ptr getelementptr inbounds (i8, ptr @std.core.mem.allocator.thread_allocator, i64 8), align 8 + %31 = call ptr @"std_collections_map$int$double$.HashMap.init"(ptr %map2, i64 %lo38, ptr %hi39, i32 16, float 7.500000e-01) + %32 = call i8 @"std_collections_map$int$double$.HashMap.set"(ptr %map2, i32 4, double 1.300000e+00) + %33 = call i8 @"std_collections_map$int$double$.HashMap.has_value"(ptr %map2, double 1.300000e+00) + store i8 %33, ptr %taddr41, align 1 + %34 = insertvalue %any undef, ptr %taddr41, 0 + %35 = insertvalue %any %34, i64 ptrtoint (ptr @"$ct.bool" to i64), 1 + store %any %35, ptr %varargslots40, align 16 + %36 = call i64 @std.io.printfn(ptr %retparam42, ptr @.str.9, i64 12, ptr %varargslots40, i64 1) + %37 = call i8 @"std_collections_map$int$double$.HashMap.has_value"(ptr %map2, double 1.200000e+00) + store i8 %37, ptr %taddr46, align 1 + %38 = insertvalue %any undef, ptr %taddr46, 0 + %39 = insertvalue %any %38, i64 ptrtoint (ptr @"$ct.bool" to i64), 1 + store %any %39, ptr %varargslots45, align 16 + %40 = call i64 @std.io.printfn(ptr %retparam47, ptr @.str.10, i64 12, ptr %varargslots45, i64 1) + %41 = call i8 @"std_collections_map$int$double$.HashMap.set"(ptr %map2, i32 100, double 3.400000e+00) + %lo51 = load i64, ptr @std.core.mem.allocator.thread_allocator, align 8 + %hi52 = load ptr, ptr getelementptr inbounds (i8, ptr @std.core.mem.allocator.thread_allocator, i64 8), align 8 + %42 = call { ptr, i64 } @"std_collections_map$int$double$.HashMap.keys"(ptr %map2, i64 %lo51, ptr %hi52) + store { ptr, i64 } %42, ptr %result53, align 8 + %43 = insertvalue %any undef, ptr %result53, 0 + %44 = insertvalue %any %43, i64 ptrtoint (ptr @"$ct.sa$int" to i64), 1 + store %any %44, ptr %varargslots50, align 16 + %45 = call i64 @std.io.printfn(ptr %retparam54, ptr @.str.11, i64 2, ptr %varargslots50, i64 1) + %lo58 = load i64, ptr @std.core.mem.allocator.thread_allocator, align 8 + %hi59 = load ptr, ptr getelementptr inbounds (i8, ptr @std.core.mem.allocator.thread_allocator, i64 8), align 8 + %46 = call { ptr, i64 } @"std_collections_map$int$double$.HashMap.values"(ptr %map2, i64 %lo58, ptr %hi59) + store { ptr, i64 } %46, ptr %result60, align 8 + %47 = insertvalue %any undef, ptr %result60, 0 + %48 = insertvalue %any %47, i64 ptrtoint (ptr @"$ct.sa$double" to i64), 1 + store %any %48, ptr %varargslots57, align 16 + %49 = call i64 @std.io.printfn(ptr %retparam61, ptr @.str.12, i64 2, ptr %varargslots57, i64 1) + %50 = load ptr, ptr @std.core.mem.allocator.thread_temp_allocator, align 8 + %i2nb = icmp eq ptr %50, null + br i1 %i2nb, label %if.then, label %if.exit + +if.then: ; preds = %after_check18 + call void @std.core.mem.allocator.init_default_temp_allocators() + br label %if.exit + +if.exit: ; preds = %if.then, %after_check18 + %51 = load ptr, ptr @std.core.mem.allocator.thread_temp_allocator, align 8 + store ptr %51, ptr %current, align 8 + %52 = load ptr, ptr %current, align 8 + %ptradd64 = getelementptr inbounds i8, ptr %52, i64 24 + %53 = load i64, ptr %ptradd64, align 8 + store i64 %53, ptr %mark, align 8 + call void @llvm.memset.p0.i64(ptr align 8 %map3, i8 0, i64 48, i1 false) + %lo65 = load i64, ptr @std.core.mem.allocator.thread_allocator, align 8 + %hi66 = load ptr, ptr getelementptr inbounds (i8, ptr @std.core.mem.allocator.thread_allocator, i64 8), align 8 + %54 = call ptr @"std_collections_map$int$double$.HashMap.init"(ptr %map3, i64 %lo65, ptr %hi66, i32 16, float 7.500000e-01) + %55 = call i8 @"std_collections_map$int$double$.HashMap.set"(ptr %map3, i32 5, double 3.200000e+00) + %56 = call i8 @"std_collections_map$int$double$.HashMap.set"(ptr %map3, i32 7, double 5.200000e+00) + %lo68 = load i64, ptr @std.core.mem.allocator.thread_allocator, align 8 + %hi69 = load ptr, ptr getelementptr inbounds (i8, ptr @std.core.mem.allocator.thread_allocator, i64 8), align 8 + %57 = call { ptr, i64 } @"std_collections_map$int$double$.HashMap.keys"(ptr %map3, i64 %lo68, ptr %hi69) + store { ptr, i64 } %57, ptr %result70, align 8 + %58 = insertvalue %any undef, ptr %result70, 0 + %59 = insertvalue %any %58, i64 ptrtoint (ptr @"$ct.sa$int" to i64), 1 + store %any %59, ptr %varargslots67, align 16 + %60 = call i64 @std.io.printfn(ptr %retparam71, ptr @.str.13, i64 2, ptr %varargslots67, i64 1) + %61 = load ptr, ptr %current, align 8 + %62 = load i64, ptr %mark, align 8 + call void @std.core.mem.allocator.TempAllocator.reset(ptr %61, i64 %62) + ret void +} \ No newline at end of file diff --git a/test/test_suite7/stdlib/memcomp.c3t b/test/test_suite7/stdlib/memcomp.c3t new file mode 100644 index 000000000..1b9dfd516 --- /dev/null +++ b/test/test_suite7/stdlib/memcomp.c3t @@ -0,0 +1,16 @@ +// #target: macos-x64 +module test; +import std::io; +import libc; + +fn void main() +{ + int[] ab = { 3, 5, 6, 10, 0x0b2399 }; + int[] cd = { 3, 5, 6, 10, 0x0b2399 }; + char[] x = "hello world!"; + char[] y = "hello world?"; + io::printfn("is matching: %s", mem::equals(ab, cd)); + io::printfn("is matching: %s", mem::equals(x, y)); + io::printfn("is matching: %s", mem::equals(x.ptr, y.ptr, x.len)); + io::printfn("is matching: %s", mem::equals(ab.ptr, cd.ptr, ab.len * 4, 4)); +} \ No newline at end of file diff --git a/test/test_suite7/stdlib/minmax.c3 b/test/test_suite7/stdlib/minmax.c3 new file mode 100644 index 000000000..b8bfa7446 --- /dev/null +++ b/test/test_suite7/stdlib/minmax.c3 @@ -0,0 +1,9 @@ +import std::io; + +fn void main() +{ + io::printfn("min(-1, 1) == %s", min(-1, 1)); + io::printfn("max(-1, 1) == %s", max(-1, 1)); + io::printfn("min(-1, 0, 1) == %s", min(-1, 0, 1)); + io::printfn("max(-1, 0, 1) == %s", max(-1, 0, 1)); +} diff --git a/test/test_suite7/stdlib/print_env_defines.c3 b/test/test_suite7/stdlib/print_env_defines.c3 new file mode 100644 index 000000000..e764da65e --- /dev/null +++ b/test/test_suite7/stdlib/print_env_defines.c3 @@ -0,0 +1,15 @@ +import std::io; + +fn void main() +{ + io::printfn("LLVM version: %s", env::LLVM_VERSION); + io::printfn("Optimization level: %s", env::COMPILER_OPT_LEVEL); + io::printfn("Safe mode: %s", env::COMPILER_SAFE_MODE); + io::printfn("OS type: %s", env::OS_TYPE); + io::printfn("Big endian: %s", env::BIG_ENDIAN); + io::printfn("i128 support: %s", env::I128_NATIVE_SUPPORT); + io::printfn("f16 support: %s", env::F16_SUPPORT); + io::printfn("f128 support: %s", env::F128_SUPPORT); + io::printfn("Benchmarking: %s", env::BENCHMARKING); + io::printfn("Testing: %s", env::TESTING); +} \ No newline at end of file diff --git a/test/test_suite7/stdlib/priorityqueue.c3t b/test/test_suite7/stdlib/priorityqueue.c3t new file mode 100644 index 000000000..676dc2454 --- /dev/null +++ b/test/test_suite7/stdlib/priorityqueue.c3t @@ -0,0 +1,31 @@ +// #target: macos-x64 +module test; +import std::io; +import std::math; +import std::collections::priorityqueue; + +def FooPriorityQueue = PriorityQueueMax{Foo}; + +fn void main() +{ + + FooPriorityQueue agh; + agh.push((Foo) { 3 }); + agh.push((Foo) { 101 }); + agh.push({ 10 }); + while (try f = agh.pop()) io::printf("%s\n", f.x); +} + +struct Foo +{ + int x; +} + +fn bool Foo.less(Foo* x, Foo y) @inline +{ + return x.x < y.x; +} + +/* #expect: test.ll + +%PrivatePriorityQueue = type { %List } diff --git a/test/test_suite7/strings/literal_errors.c3 b/test/test_suite7/strings/literal_errors.c3 new file mode 100644 index 000000000..805772c4a --- /dev/null +++ b/test/test_suite7/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_suite7/strings/literal_hex_ok.c3 b/test/test_suite7/strings/literal_hex_ok.c3 new file mode 100644 index 000000000..943edca35 --- /dev/null +++ b/test/test_suite7/strings/literal_hex_ok.c3 @@ -0,0 +1,3 @@ +char bar1 = '\xaf'; +ichar bar2 = '\x0F'; +ushort bar4 = '\u0FaF'; diff --git a/test/test_suite7/strings/literal_to_subarray.c3t b/test/test_suite7/strings/literal_to_subarray.c3t new file mode 100644 index 000000000..141707113 --- /dev/null +++ b/test/test_suite7/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 + + +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_suite7/strings/multiline_strings.c3t b/test/test_suite7/strings/multiline_strings.c3t new file mode 100644 index 000000000..13b1f69b0 --- /dev/null +++ b/test/test_suite7/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_suite7/strings/string_escape.c3t b/test/test_suite7/strings/string_escape.c3t new file mode 100644 index 000000000..e926a940a --- /dev/null +++ b/test/test_suite7/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_suite7/strings/string_len.c3t b/test/test_suite7/strings/string_len.c3t new file mode 100644 index 000000000..8d76b2898 --- /dev/null +++ b/test/test_suite7/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_suite7/strings/string_to_array.c3t b/test/test_suite7/strings/string_to_array.c3t new file mode 100644 index 000000000..f29d45a93 --- /dev/null +++ b/test/test_suite7/strings/string_to_array.c3t @@ -0,0 +1,28 @@ +// #target: macos-x64 +module foo; + +char[2] g = "ab"; +char[?] h = "abc"; + +fn int main() +{ + char[2] x = "ab"; + char[?] y = "abc"; + return 0; +} + +/* #expect: foo.ll + +@foo.g = local_unnamed_addr global [2 x i8] c"ab", align 1 +@foo.h = local_unnamed_addr global [3 x i8] c"abc", align 1 +@.str = private unnamed_addr constant [3 x i8] c"ab\00", align 1 +@.str.2 = 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.2, i32 3, i1 false) + ret i32 0 +} \ No newline at end of file diff --git a/test/test_suite7/struct/const_access_error.c3 b/test/test_suite7/struct/const_access_error.c3 new file mode 100644 index 000000000..f9d839978 --- /dev/null +++ b/test/test_suite7/struct/const_access_error.c3 @@ -0,0 +1,6 @@ + +fn void main() +{ + int x; + x.""; // #error: Expected an identifier here +} \ No newline at end of file diff --git a/test/test_suite7/struct/const_slice_struct.c3t b/test/test_suite7/struct/const_slice_struct.c3t new file mode 100644 index 000000000..837488e2e --- /dev/null +++ b/test/test_suite7/struct/const_slice_struct.c3t @@ -0,0 +1,37 @@ +// #target: macos-x64 +module test; +// Issue #1812 +struct Foo +{ + float a; + String b; +} + +struct Bar +{ + float a; + int[] b; +} +const Foo FOO = {.a = 1}; +const Bar FOO2 = {.a = 1, .b = { 1, 3 } }; + +fn int main() +{ + Foo asdf = FOO; + Bar foek = FOO2; + return 0; +} + +/* #expect: test.ll + +@test.FOO = local_unnamed_addr constant %Foo { float 1.000000e+00, %"char[]" zeroinitializer }, align 8 +@.__const_slice = private unnamed_addr global [2 x i32] [i32 1, i32 3], align 4 +@test.FOO2 = local_unnamed_addr constant %Bar { float 1.000000e+00, %"int[]" { ptr @.__const_slice, i64 2 } }, align 8 + +entry: + %asdf = alloca %Foo, align 8 + %foek = alloca %Bar, align 8 + call void @llvm.memcpy.p0.p0.i32(ptr align 8 %asdf, ptr align 8 @test.FOO, i32 24, i1 false) + call void @llvm.memcpy.p0.p0.i32(ptr align 8 %foek, ptr align 8 @test.FOO2, i32 24, i1 false) + ret i32 0 +} diff --git a/test/test_suite7/struct/const_zero_init_1360.c3t b/test/test_suite7/struct/const_zero_init_1360.c3t new file mode 100644 index 000000000..9cbaa9545 --- /dev/null +++ b/test/test_suite7/struct/const_zero_init_1360.c3t @@ -0,0 +1,27 @@ +// #target: macos-x64 +module test; +import std::collections::map; + +def Foo = HashMap()>); +macro test() +{ + HashMap() map0; + map0["c3c"] = {}; + + Foo map; + map["c3c"] = {}; + map["c3c"] = { {}, null, 1 ,2 ,2 }; + + HashMap()>) map2; + map2["c3c"] = {}; + map2["c3c"] = { {}, null, 1 ,2 ,2 }; + +} +fn void main() +{ + test(); +} + +/* #expect: test.ll + +main \ No newline at end of file diff --git a/test/test_suite7/struct/duplicate_member.c3 b/test/test_suite7/struct/duplicate_member.c3 new file mode 100644 index 000000000..c2a6f8c54 --- /dev/null +++ b/test/test_suite7/struct/duplicate_member.c3 @@ -0,0 +1,72 @@ +// @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' +} + +union Cc2 +{ + int 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' + } + } +} + +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_suite7/struct/flex_array_comparison.c3 b/test/test_suite7/struct/flex_array_comparison.c3 new file mode 100644 index 000000000..d2f0c09be --- /dev/null +++ b/test/test_suite7/struct/flex_array_comparison.c3 @@ -0,0 +1,15 @@ +module test; + +struct Abc +{ + int x; + int[?] y; +} + + +fn void test() +{ + Abc x; + Abc y; + bool same = x.y == y.y; // #error: does not support comparisons +} \ No newline at end of file diff --git a/test/test_suite7/struct/flex_array_struct_err.c3 b/test/test_suite7/struct/flex_array_struct_err.c3 new file mode 100644 index 000000000..8ec5ae6eb --- /dev/null +++ b/test/test_suite7/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_suite7/struct/flexible_array_resolve.c3 b/test/test_suite7/struct/flexible_array_resolve.c3 new file mode 100644 index 000000000..1255468cf --- /dev/null +++ b/test/test_suite7/struct/flexible_array_resolve.c3 @@ -0,0 +1,16 @@ +struct Abc +{ + Foo[4] x; // #error: Arrays of structs with flexible array members +} + +struct Foo +{ + int a; + int[?] x; +} + +struct Foo2 +{ + int a; + int[?] x, y; // #error: must be the last element +} diff --git a/test/test_suite7/struct/func_return_struct.c3 b/test/test_suite7/struct/func_return_struct.c3 new file mode 100644 index 000000000..66ae003b3 --- /dev/null +++ b/test/test_suite7/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_suite7/struct/init_cont_struct_array_locally.c3t b/test/test_suite7/struct/init_cont_struct_array_locally.c3t new file mode 100644 index 000000000..b56588b26 --- /dev/null +++ b/test/test_suite7/struct/init_cont_struct_array_locally.c3t @@ -0,0 +1,206 @@ +// #target: macos-x64 +module test; +import std::io; +struct Test +{ + char[2] id; +} + +Test t = (Test){"id"}; +fn int main() +{ + io::printn(t); + Test y = (Test) { "id" }; + io::printn(); + return 0; +} + +/* #expect: test.ll + +entry: + %x = alloca %Test, align 1 + %x1 = alloca %Test, align 1 + %len = alloca i64, align 8 + %error_var = alloca i64, align 8 + %x2 = alloca %Test, align 1 + %formatter = alloca %Formatter, align 8 + %taddr = alloca %any, align 8 + %value = alloca %Test, align 1 + %total = alloca i64, align 8 + %error_var5 = alloca i64, align 8 + %retparam = alloca i64, align 8 + %error_var6 = alloca i64, align 8 + %varargslots = alloca [1 x %any], align 16 + %taddr7 = alloca %"char[]", align 8 + %retparam8 = alloca i64, align 8 + %error_var14 = alloca i64, align 8 + %varargslots15 = alloca [1 x %any], align 16 + %retparam16 = alloca i64, align 8 + %retparam23 = alloca i64, align 8 + %error_var30 = alloca i64, align 8 + %error_var36 = alloca i64, align 8 + %y = alloca %Test, align 1 + %len43 = alloca i64, align 8 + %error_var44 = alloca i64, align 8 + %retparam46 = alloca i64, align 8 + %error_var52 = alloca i64, align 8 + %error_var58 = alloca i64, align 8 + call void @llvm.memcpy.p0.p0.i32(ptr align 1 %x, ptr align 1 @test.t, i32 2, i1 false) + %0 = call ptr @std.io.stdout() + call void @llvm.memcpy.p0.p0.i32(ptr align 1 %x1, ptr align 1 %x, i32 2, i1 false) + call void @llvm.memcpy.p0.p0.i32(ptr align 1 %x2, ptr align 1 %x1, i32 2, i1 false) + call void @llvm.memset.p0.i64(ptr align 8 %formatter, i8 0, i64 48, i1 false) + %1 = insertvalue %any undef, ptr %0, 0 + %2 = insertvalue %any %1, i64 ptrtoint (ptr @"$ct.std.io.File" to i64), 1 + store %any %2, ptr %taddr, align 8 + call void @std.io.Formatter.init(ptr %formatter, ptr @std.io.out_putstream_fn, ptr %taddr) + call void @llvm.memcpy.p0.p0.i32(ptr align 1 %value, ptr align 1 %x2, i32 2, i1 false) + %3 = call i64 @std.io.Formatter.print(ptr %retparam, ptr %formatter, ptr @.str, i64 2) + %not_err = icmp eq i64 %3, 0 + %4 = call i1 @llvm.expect.i1(i1 %not_err, i1 true) + br i1 %4, label %after_check, label %assign_optional +assign_optional: ; preds = %entry + store i64 %3, ptr %error_var5, align 8 + br label %guard_block +after_check: ; preds = %entry + br label %noerr_block +guard_block: ; preds = %assign_optional + %5 = load i64, ptr %error_var5, align 8 + store i64 %5, ptr %error_var, align 8 + br label %guard_block28 +noerr_block: ; preds = %after_check + %6 = load i64, ptr %retparam, align 8 + store i64 %6, ptr %total, align 8 + %7 = load i64, ptr %total, align 8 + store %"char[]" { ptr @.str.2, i64 2 }, ptr %taddr7, align 8 + %8 = insertvalue %any undef, ptr %taddr7, 0 + %9 = insertvalue %any %8, i64 ptrtoint (ptr @"$ct.String" to i64), 1 + store %any %9, ptr %varargslots, align 16 + %10 = call i64 @std.io.Formatter.printf(ptr %retparam8, ptr %formatter, ptr @.str.1, i64 4, ptr %varargslots, i64 1) + %not_err9 = icmp eq i64 %10, 0 + %11 = call i1 @llvm.expect.i1(i1 %not_err9, i1 true) + br i1 %11, label %after_check11, label %assign_optional10 +assign_optional10: ; preds = %noerr_block + store i64 %10, ptr %error_var6, align 8 + br label %guard_block12 +after_check11: ; preds = %noerr_block + br label %noerr_block13 +guard_block12: ; preds = %assign_optional10 + %12 = load i64, ptr %error_var6, align 8 + store i64 %12, ptr %error_var, align 8 + br label %guard_block28 +noerr_block13: ; preds = %after_check11 + %13 = load i64, ptr %retparam8, align 8 + %add = add i64 %7, %13 + store i64 %add, ptr %total, align 8 + %14 = load i64, ptr %total, align 8 + %15 = insertvalue %any undef, ptr %value, 0 + %16 = insertvalue %any %15, i64 ptrtoint (ptr @"$ct.a2$char" to i64), 1 + store %any %16, ptr %varargslots15, align 16 + %17 = call i64 @std.io.Formatter.printf(ptr %retparam16, ptr %formatter, ptr @.str.3, i64 2, ptr %varargslots15, i64 1) + %not_err17 = icmp eq i64 %17, 0 + %18 = call i1 @llvm.expect.i1(i1 %not_err17, i1 true) + br i1 %18, label %after_check19, label %assign_optional18 +assign_optional18: ; preds = %noerr_block13 + store i64 %17, ptr %error_var14, align 8 + br label %guard_block20 +after_check19: ; preds = %noerr_block13 + br label %noerr_block21 +guard_block20: ; preds = %assign_optional18 + %19 = load i64, ptr %error_var14, align 8 + store i64 %19, ptr %error_var, align 8 + br label %guard_block28 +noerr_block21: ; preds = %after_check19 + %20 = load i64, ptr %retparam16, align 8 + %add22 = add i64 %14, %20 + store i64 %add22, ptr %total, align 8 + %21 = load i64, ptr %total, align 8 + %22 = call i64 @std.io.Formatter.print(ptr %retparam23, ptr %formatter, ptr @.str.4, i64 2) + %not_err24 = icmp eq i64 %22, 0 + %23 = call i1 @llvm.expect.i1(i1 %not_err24, i1 true) + br i1 %23, label %after_check26, label %assign_optional25 +assign_optional25: ; preds = %noerr_block21 + store i64 %22, ptr %error_var, align 8 + br label %guard_block28 +after_check26: ; preds = %noerr_block21 + %24 = load i64, ptr %retparam23, align 8 + %add27 = add i64 %21, %24 + br label %noerr_block29 +guard_block28: ; preds = %assign_optional25, %guard_block20, %guard_block12, %guard_block + br label %voiderr +noerr_block29: ; preds = %after_check26 + store i64 %add27, ptr %len, align 8 + %25 = call i64 @std.io.File.write_byte(ptr %0, i8 zeroext 10) + %not_err31 = icmp eq i64 %25, 0 + %26 = call i1 @llvm.expect.i1(i1 %not_err31, i1 true) + br i1 %26, label %after_check33, label %assign_optional32 +assign_optional32: ; preds = %noerr_block29 + store i64 %25, ptr %error_var30, align 8 + br label %guard_block34 +after_check33: ; preds = %noerr_block29 + br label %noerr_block35 +guard_block34: ; preds = %assign_optional32 + br label %voiderr +noerr_block35: ; preds = %after_check33 + %27 = call i64 @std.io.File.flush(ptr %0) + %not_err37 = icmp eq i64 %27, 0 + %28 = call i1 @llvm.expect.i1(i1 %not_err37, i1 true) + br i1 %28, label %after_check39, label %assign_optional38 +assign_optional38: ; preds = %noerr_block35 + store i64 %27, ptr %error_var36, align 8 + br label %guard_block40 +after_check39: ; preds = %noerr_block35 + br label %noerr_block41 +guard_block40: ; preds = %assign_optional38 + br label %voiderr +noerr_block41: ; preds = %after_check39 + %29 = load i64, ptr %len, align 8 + %add42 = add i64 %29, 1 + br label %voiderr +voiderr: ; preds = %noerr_block41, %guard_block40, %guard_block34, %guard_block28 + call void @llvm.memcpy.p0.p0.i32(ptr align 1 %y, ptr align 1 @.__const, i32 2, i1 false) + %30 = call ptr @std.io.stdout() + %31 = call i64 @std.io.File.write(ptr %retparam46, ptr %30, ptr null, i64 0) + %not_err47 = icmp eq i64 %31, 0 + %32 = call i1 @llvm.expect.i1(i1 %not_err47, i1 true) + br i1 %32, label %after_check49, label %assign_optional48 +assign_optional48: ; preds = %voiderr + store i64 %31, ptr %error_var44, align 8 + br label %guard_block50 +after_check49: ; preds = %voiderr + br label %noerr_block51 +guard_block50: ; preds = %assign_optional48 + br label %voiderr65 +noerr_block51: ; preds = %after_check49 + %33 = load i64, ptr %retparam46, align 8 + store i64 %33, ptr %len43, align 8 + %34 = call i64 @std.io.File.write_byte(ptr %30, i8 zeroext 10) + %not_err53 = icmp eq i64 %34, 0 + %35 = call i1 @llvm.expect.i1(i1 %not_err53, i1 true) + br i1 %35, label %after_check55, label %assign_optional54 +assign_optional54: ; preds = %noerr_block51 + store i64 %34, ptr %error_var52, align 8 + br label %guard_block56 +after_check55: ; preds = %noerr_block51 + br label %noerr_block57 +guard_block56: ; preds = %assign_optional54 + br label %voiderr65 +noerr_block57: ; preds = %after_check55 + %36 = call i64 @std.io.File.flush(ptr %30) + %not_err59 = icmp eq i64 %36, 0 + %37 = call i1 @llvm.expect.i1(i1 %not_err59, i1 true) + br i1 %37, label %after_check61, label %assign_optional60 +assign_optional60: ; preds = %noerr_block57 + store i64 %36, ptr %error_var58, align 8 + br label %guard_block62 +after_check61: ; preds = %noerr_block57 + br label %noerr_block63 +guard_block62: ; preds = %assign_optional60 + br label %voiderr65 +noerr_block63: ; preds = %after_check61 + %38 = load i64, ptr %len43, align 8 + %add64 = add i64 %38, 1 + br label %voiderr65 +voiderr65: ; preds = %noerr_block63, %guard_block62, %guard_block56, %guard_block50 + ret i32 0 +} diff --git a/test/test_suite7/struct/initialize_inline_designated.c3t b/test/test_suite7/struct/initialize_inline_designated.c3t new file mode 100644 index 000000000..f8c0fe5d9 --- /dev/null +++ b/test/test_suite7/struct/initialize_inline_designated.c3t @@ -0,0 +1,31 @@ +// #target: macos-x64 +module test; +import std; +struct Abc +{ + int a; + int b; +} + +struct Bcd +{ + inline Abc x; + int y; +} +fn void main() +{ + Bcd z = { .x.b = 333, .a = 123 }; +} +/* #expect: test.ll + +%Bcd = type { %Abc, i32 } +%Abc = type { i32, i32 } + + %z = alloca %Bcd, align 4 + store i32 123, ptr %z, align 4 + %ptradd = getelementptr inbounds i8, ptr %z, i64 4 + store i32 333, ptr %ptradd, align 4 + %ptradd1 = getelementptr inbounds i8, ptr %z, i64 8 + store i32 0, ptr %ptradd1, align 4 + ret void +} diff --git a/test/test_suite7/struct/inline_array_access.c3t b/test/test_suite7/struct/inline_array_access.c3t new file mode 100644 index 000000000..44665f6c8 --- /dev/null +++ b/test/test_suite7/struct/inline_array_access.c3t @@ -0,0 +1,33 @@ +// #target: macos-x64 +module test; +import std; +struct Abc +{ + inline int[4] x; +} +fn void main() +{ + Abc y; + y.x[3] = 123; + int z = y[3]; +} + +/* #expect: test.ll + +entry: + %y = alloca %Abc, align 4 + %z = alloca i32, align 4 + store i32 0, ptr %y, align 4 + %ptradd = getelementptr inbounds i8, ptr %y, i64 4 + store i32 0, ptr %ptradd, align 4 + %ptradd1 = getelementptr inbounds i8, ptr %y, i64 8 + store i32 0, ptr %ptradd1, align 4 + %ptradd2 = getelementptr inbounds i8, ptr %y, i64 12 + store i32 0, ptr %ptradd2, align 4 + %ptradd3 = getelementptr inbounds i8, ptr %y, i64 12 + store i32 123, ptr %ptradd3, align 4 + %ptradd4 = getelementptr inbounds i8, ptr %y, i64 12 + %0 = load i32, ptr %ptradd4, align 4 + store i32 %0, ptr %z, align 4 + ret void +} \ No newline at end of file diff --git a/test/test_suite7/struct/inner_struct_name.c3 b/test/test_suite7/struct/inner_struct_name.c3 new file mode 100644 index 000000000..01d8fa6f1 --- /dev/null +++ b/test/test_suite7/struct/inner_struct_name.c3 @@ -0,0 +1,5 @@ +struct Foo { + union Bar { // #error: name of an inner struct + int a; + } +} diff --git a/test/test_suite7/struct/member_access.c3 b/test/test_suite7/struct/member_access.c3 new file mode 100644 index 000000000..c8a95f80e --- /dev/null +++ b/test/test_suite7/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: 'Aa1.bb' to '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_suite7/struct/member_expr.c3 b/test/test_suite7/struct/member_expr.c3 new file mode 100644 index 000000000..2e5d18c70 --- /dev/null +++ b/test/test_suite7/struct/member_expr.c3 @@ -0,0 +1,31 @@ + +def Func = fn int(int); + +def 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_suite7/struct/multi_member_attributes.c3t b/test/test_suite7/struct/multi_member_attributes.c3t new file mode 100644 index 000000000..73d8880c7 --- /dev/null +++ b/test/test_suite7/struct/multi_member_attributes.c3t @@ -0,0 +1,22 @@ +// #target: macos-x64 + +module test; + +char x, y, z @align(64); + +struct Vector3 +{ + char x, y, z @align(8); // Issue #1266 +} + +Vector3 a = { 6, 8, 16 }; + +/* #expect: test.ll + + +%Vector3 = type { i8, [7 x i8], i8, [7 x i8], i8, [7 x i8] } + +@test.x = local_unnamed_addr global i8 0, align 64 +@test.y = local_unnamed_addr global i8 0, align 64 +@test.z = local_unnamed_addr global i8 0, align 64 +@test.a = local_unnamed_addr global %Vector3 { i8 6, [7 x i8] undef, i8 8, [7 x i8] undef, i8 16, [7 x i8] undef }, align 8 diff --git a/test/test_suite7/struct/nested_struct_init.c3t b/test/test_suite7/struct/nested_struct_init.c3t new file mode 100644 index 000000000..c67162466 --- /dev/null +++ b/test/test_suite7/struct/nested_struct_init.c3t @@ -0,0 +1,71 @@ +// #target: macos-x64 +module foo; +import libc; + +struct Matrix2x2 +{ + union + { + struct { + float m00, m01, m10, m11; + } + float[4] m; + } +} + +struct Matrix2x2_b +{ + union + { + float[4] m; + struct { + float m00, m01, m10, m11; + } + } +} + +fn void main() +{ + Matrix2x2 m = { 1, 2, 3, 4 }; + Matrix2x2_b m2 = { { 1, 2, 3, 4 } }; + libc::printf("%f %f %f %f\n", m.m00, m.m[1], m.m10, m.m[3]); +} +/* #expect: foo.ll + +%Matrix2x2 = type { %.anon } +%.anon = type { %.anon.0 } +%.anon.0 = type { float, float, float, float } +%Matrix2x2_b = type { %.anon.1 } +%.anon.1 = type { [4 x float] } + +@"$ct.foo.$anon" = linkonce global %.introspect { i8 10, i64 0, ptr null, i64 16, i64 0, i64 4, [0 x i64] zeroinitializer }, align 8 +@"$ct.foo.$anon.3" = linkonce global %.introspect { i8 11, i64 0, ptr null, i64 16, i64 0, i64 2, [0 x i64] zeroinitializer }, align 8 +@"$ct.foo.Matrix2x2" = linkonce global %.introspect { i8 10, i64 0, ptr null, i64 16, i64 0, i64 1, [0 x i64] zeroinitializer }, align 8 +@"$ct.foo.$anon.6" = linkonce global %.introspect { i8 10, i64 0, ptr null, i64 16, i64 0, i64 4, [0 x i64] zeroinitializer }, align 8 +@"$ct.foo.$anon.7" = linkonce global %.introspect { i8 11, i64 0, ptr null, i64 16, i64 0, i64 2, [0 x i64] zeroinitializer }, align 8 +@"$ct.foo.Matrix2x2_b" = linkonce global %.introspect { i8 10, i64 0, ptr null, i64 16, i64 0, i64 1, [0 x i64] zeroinitializer }, align 8 +@.__const = private unnamed_addr constant %Matrix2x2 { %.anon { %.anon.0 { float 1.000000e+00, float 2.000000e+00, float 3.000000e+00, float 4.000000e+00 } } }, align 4 +@.__const.8 = private unnamed_addr constant %Matrix2x2_b { %.anon.1 { [4 x float] [float 1.000000e+00, float 2.000000e+00, float 3.000000e+00, float 4.000000e+00] } }, align 4 +@.str = private unnamed_addr constant [13 x i8] c"%f %f %f %f\0A\00", align 1 + +; Function Attrs: +define void @foo.main() #0 { +entry: + %m = alloca %Matrix2x2, align 4 + %m2 = alloca %Matrix2x2_b, align 4 + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %m, ptr align 4 @.__const, i32 16, i1 false) + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %m2, ptr align 4 @.__const.8, i32 16, i1 false) + %0 = load float, ptr %m, align 4 + %fpfpext = fpext float %0 to double + %ptradd = getelementptr inbounds i8, ptr %m, i64 4 + %1 = load float, ptr %ptradd, align 4 + %fpfpext1 = fpext float %1 to double + %ptradd2 = getelementptr inbounds i8, ptr %m, i64 8 + %2 = load float, ptr %ptradd2, align 4 + %fpfpext3 = fpext float %2 to double + %ptradd4 = getelementptr inbounds i8, ptr %m, i64 12 + %3 = load float, ptr %ptradd4, align 4 + %fpfpext5 = fpext float %3 to double + %4 = call i32 (ptr, ...) @printf(ptr @.str, double %fpfpext, double %fpfpext1, double %fpfpext3, double %fpfpext5) + ret void +} diff --git a/test/test_suite7/struct/nested_struct_union_init.c3t b/test/test_suite7/struct/nested_struct_union_init.c3t new file mode 100644 index 000000000..5be6af01b --- /dev/null +++ b/test/test_suite7/struct/nested_struct_union_init.c3t @@ -0,0 +1,110 @@ +// #target: macos-x64 +module foob; +import libc; +struct Matrix2x2 +{ + union + { + float[4] m; + struct + { + float m00, m01, m10, m11; + } + } +} + +struct Matrix2x2_b +{ + union + { + struct + { + float m00, m01, m10, m11; + } + float[4] m; + } +} +struct Matrix4x4 +{ + union + { + struct + { + float m00, m01, m02, m03; + float m10, m11, m12, m13; + float m20, m21, m22, m23; + float m30, m31, m32, m33; + } + float[16] m; + } +} + + +struct Matrix3x3 +{ + union + { + struct + { + float m00, m01, m02, m10, m11, m12, m20, m21, m22; + } + float[9] m; + } +} +fn void main() +{ + Matrix3x3 x = { 1, 2, 3, 4, 5, 6, 7,8 ,9}; + Matrix2x2 m = { (float[4]) { 1, 2, 3, 4 } }; + Matrix2x2_b m2 = { 1, 2, 3, 4 }; + libc::printf("%f %f %f %f\n", x.m00, x.m[1], x.m10, x.m[3]); +} + +/* #expect: foob.ll + +%Matrix2x2 = type { %.anon.1 } +%.anon.1 = type { [4 x float] } +%Matrix2x2_b = type { %.anon.2 } +%.anon.2 = type { %.anon.3 } +%.anon.3 = type { float, float, float, float } +%Matrix3x3 = type { %.anon } +%.anon = type { %.anon.0 } +%.anon.0 = type { float, float, float, float, float, float, float, float, float } + +define void @foob.main() #0 { +entry: + %x = alloca %Matrix3x3, align 4 + %m = alloca %Matrix2x2, align 4 + %m2 = alloca %Matrix2x2_b, align 4 + store float 1.000000e+00, ptr %x, align 4 + %ptradd = getelementptr inbounds i8, ptr %x, i64 4 + store float 2.000000e+00, ptr %ptradd, align 4 + %ptradd1 = getelementptr inbounds i8, ptr %x, i64 8 + store float 3.000000e+00, ptr %ptradd1, align 4 + %ptradd2 = getelementptr inbounds i8, ptr %x, i64 12 + store float 4.000000e+00, ptr %ptradd2, align 4 + %ptradd3 = getelementptr inbounds i8, ptr %x, i64 16 + store float 5.000000e+00, ptr %ptradd3, align 4 + %ptradd4 = getelementptr inbounds i8, ptr %x, i64 20 + store float 6.000000e+00, ptr %ptradd4, align 4 + %ptradd5 = getelementptr inbounds i8, ptr %x, i64 24 + store float 7.000000e+00, ptr %ptradd5, align 4 + %ptradd6 = getelementptr inbounds i8, ptr %x, i64 28 + store float 8.000000e+00, ptr %ptradd6, align 4 + %ptradd7 = getelementptr inbounds i8, ptr %x, i64 32 + store float 9.000000e+00, ptr %ptradd7, align 4 + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %m, ptr align 4 @.__const, i32 16, i1 false) + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %m2, ptr align 4 @.__const.16, i32 16, i1 false) + %0 = load float, ptr %x, align 4 + %fpfpext = fpext float %0 to double + %ptradd8 = getelementptr inbounds i8, ptr %x, i64 4 + %1 = load float, ptr %ptradd8, align 4 + %fpfpext9 = fpext float %1 to double + %ptradd10 = getelementptr inbounds i8, ptr %x, i64 12 + %2 = load float, ptr %ptradd10, align 4 + %fpfpext11 = fpext float %2 to double + %ptradd12 = getelementptr inbounds i8, ptr %x, i64 12 + %3 = load float, ptr %ptradd12, align 4 + %fpfpext13 = fpext float %3 to double + %4 = call i32 (ptr, ...) @printf(ptr @.str, double %fpfpext, double %fpfpext9, double %fpfpext11, double %fpfpext13) + ret void +} diff --git a/test/test_suite7/struct/recursive_structs.c3 b/test/test_suite7/struct/recursive_structs.c3 new file mode 100644 index 000000000..19dbbf06a --- /dev/null +++ b/test/test_suite7/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_suite7/struct/simple_struct.c3t b/test/test_suite7/struct/simple_struct.c3t new file mode 100644 index 000000000..89a87c560 --- /dev/null +++ b/test/test_suite7/struct/simple_struct.c3t @@ -0,0 +1,14 @@ +module test; + +Foo a @private; + +struct Foo +{ + int x; + double a; +} + +/* #expect: test.ll + +%Foo = type { i32, double } +@test.a = internal unnamed_addr global %Foo zeroinitializer, align 8 \ No newline at end of file diff --git a/test/test_suite7/struct/sret.c3t b/test/test_suite7/struct/sret.c3t new file mode 100644 index 000000000..a96701630 --- /dev/null +++ b/test/test_suite7/struct/sret.c3t @@ -0,0 +1,26 @@ +// #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(); +} + + +/* #expect: sret.ll + +sret(%Abc) +sret(%Abc) +sret(%Abc) +sret(%Abc) \ No newline at end of file diff --git a/test/test_suite7/struct/struct_as_value.c3t b/test/test_suite7/struct/struct_as_value.c3t new file mode 100644 index 000000000..58d5a0602 --- /dev/null +++ b/test/test_suite7/struct/struct_as_value.c3t @@ -0,0 +1,46 @@ +// #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 } + +@"$ct.test.Event" = linkonce global %.introspect { i8 10, i64 0, ptr null, i64 4, i64 0, i64 1, [0 x i64] zeroinitializer }, 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) + %i2b = icmp ne i32 %0, 0 + br i1 %i2b, 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 = load i32, ptr %taddr, align 4 + ret i32 %3 +} \ No newline at end of file diff --git a/test/test_suite7/struct/struct_as_value_aarch64.c3t b/test/test_suite7/struct/struct_as_value_aarch64.c3t new file mode 100644 index 000000000..7c76ec120 --- /dev/null +++ b/test/test_suite7/struct/struct_as_value_aarch64.c3t @@ -0,0 +1,41 @@ +// #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) + %i2b = icmp ne i32 %0, 0 + br i1 %i2b, 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 = load i32, ptr %taddr, align 4 + ret i32 %3 +} diff --git a/test/test_suite7/struct/struct_bad_member.c3 b/test/test_suite7/struct/struct_bad_member.c3 new file mode 100644 index 000000000..49486d7ed --- /dev/null +++ b/test/test_suite7/struct/struct_bad_member.c3 @@ -0,0 +1,19 @@ +struct Foo { + void bar; // #error: Members cannot be of +} + +def Void = void; +struct Foo2 { + Void bar; // #error: Members cannot be of +} + +distinct Void2 = void; +struct Foo3 { + Void2 bar; // #error: has unknown size +} + +fn void main(String[] args) { + Foo foo; + Foo2 foo2; + Foo3 foo3; +} diff --git a/test/test_suite7/struct/struct_codegen.c3t b/test/test_suite7/struct/struct_codegen.c3t new file mode 100644 index 000000000..966691695 --- /dev/null +++ b/test/test_suite7/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 } + +@"$ct.test.Point" = linkonce global %.introspect { i8 10, i64 0, ptr null, i64 8, i64 0, i64 2, [0 x i64] zeroinitializer }, 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_suite7/struct/struct_codegen_empty.c3t b/test/test_suite7/struct/struct_codegen_empty.c3t new file mode 100644 index 000000000..e2ccf101d --- /dev/null +++ b/test/test_suite7/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_suite7/struct/struct_codegen_fam.c3t b/test/test_suite7/struct/struct_codegen_fam.c3t new file mode 100644 index 000000000..daaeb7c81 --- /dev/null +++ b/test/test_suite7/struct/struct_codegen_fam.c3t @@ -0,0 +1,30 @@ +// #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: + %ptradd = getelementptr inbounds i8, ptr %0, i64 8 + %ptradd1 = getelementptr inbounds i8, ptr %ptradd, i64 4 + ret void +} \ No newline at end of file diff --git a/test/test_suite7/struct/struct_comma.c3 b/test/test_suite7/struct/struct_comma.c3 new file mode 100644 index 000000000..4fcecc5d2 --- /dev/null +++ b/test/test_suite7/struct/struct_comma.c3 @@ -0,0 +1,7 @@ +import std::io; + + struct Test + { + int a, // #error: Did you accidentally use ',' + int b, + } diff --git a/test/test_suite7/struct/struct_const_construct_simple.c3t b/test/test_suite7/struct/struct_const_construct_simple.c3t new file mode 100644 index 000000000..2a81d9db5 --- /dev/null +++ b/test/test_suite7/struct/struct_const_construct_simple.c3t @@ -0,0 +1,32 @@ +// #target: macos-x64 +module structo; + +struct Foo +{ + int foo; + long bar; +} + +usz x @private = Foo.sizeof; + +Foo foo1 @private = { 1, 2 }; +Foo foo2 @private = { .foo = 2 }; +Foo foo3 @private = { .bar = 3 }; +Foo foo4 @private = { .bar = 4, .foo = 4, .bar = 1 }; +Foo foo5 @private = {}; +Foo foo6 @private; +const Foo FOO7 @private = { 1, 2 }; +Foo foo8 @private = FOO7; + +/* #expect: structo.ll + +@"$ct.structo.Foo" = linkonce global %.introspect { i8 10, i64 0, ptr null, i64 16, i64 0, i64 2, [0 x i64] zeroinitializer }, align 8 +@structo.x = internal unnamed_addr global i64 16, align 8 +@structo.foo1 = internal unnamed_addr global %Foo { i32 1, i64 2 }, align 8 +@structo.foo2 = internal unnamed_addr global %Foo { i32 2, i64 0 }, align 8 +@structo.foo3 = internal unnamed_addr global %Foo { i32 0, i64 3 }, align 8 +@structo.foo4 = internal unnamed_addr global %Foo { i32 4, i64 1 }, align 8 +@structo.foo5 = internal unnamed_addr global %Foo zeroinitializer, align 8 +@structo.foo6 = internal unnamed_addr global %Foo zeroinitializer, align 8 +@structo.FOO7 = internal unnamed_addr constant %Foo { i32 1, i64 2 }, align 8 +@structo.foo8 = internal unnamed_addr global %Foo { i32 1, i64 2 }, align 8 diff --git a/test/test_suite7/struct/struct_nopadding_compact.c3t b/test/test_suite7/struct/struct_nopadding_compact.c3t new file mode 100644 index 000000000..e96d58244 --- /dev/null +++ b/test/test_suite7/struct/struct_nopadding_compact.c3t @@ -0,0 +1,272 @@ +module struct2; + +struct Foo1 +{ + bool a @nopadding; + int b; + int c @nopadding; +} + +union Foo1_Union +{ + bool a @nopadding; + int b; + int c @nopadding; +} + +struct Foo2 @nopadding +{ + bool a; + bool b; + bool c; +} + +union Foo2_Union @nopadding +{ + bool a; + bool b; + bool c; +} + +struct Foo3 +{ + bool a; + int b @nopadding; // #error: 3 bytes of padding would be added + int c @nopadding; +} + +struct Foo4 @nopadding +{ + bool a; + int b; // #error: 3 bytes of padding would be added + int c; +} + +struct Foo5 @nopadding // #error: 3 bytes of padding would be added +{ + int a; + bool b; +} + +struct Foo5_B @align(16) @nopadding // #error: 8 bytes of padding would be added +{ + int a; + int b; +} + +struct Foo6 @nopadding +{ + int a; + struct // #error: 3 bytes of padding would be added + { + int b; + bool c; + } +} + +struct Foo7 @nopadding +{ + int a; + struct nested + { + bool b; + int c; // #error: 3 bytes of padding would be added + } +} + +struct Foo7_A @nopadding +{ + int a; + struct + { + bool b; + union // #error: 7 bytes of padding would be added + { + int c; + long d; + } + } +} + +struct Foo7_B @nopadding +{ + int a; + char[4] _pad; + struct + { + long b; + union + { + int c; + long d; + struct // #error: 3 bytes of padding would be added + { + int e; + bool f; + } + } + } +} + +struct Foo7_C @nopadding +{ + int a; + char[4] _pad; + struct + { + int b @align(8); + union // #error: 4 bytes of padding would be added + { + int c; + long d; + struct + { + bool f; + } + } + } +} + +struct Foo10 @nopadding +{ + inline Foo2 a; +} + +struct Foo11 @nopadding +{ + inline Foo1 a; // #error: An inlined struct or union type also requires the `@nopadding` attribute +} + +struct Foo11_A @nopadding +{ + inline Foo1_Union a; // #error: An inlined struct or union type also requires the `@nopadding` attribute +} + +union Foo12 @nopadding +{ + int b; + bool a; + long c; + struct + { + bool d; + int e; // #error: 3 bytes of padding would be added + } +} + +union Foo12_A @nopadding +{ + int b; + bool a; + long c; +} + +struct Foo13 @nopadding +{ + inline Foo12_A a; + short b @align(32); // #error: 24 bytes of padding would be added +} + +struct Foo14 @compact // #error: 2 bytes of padding would be added to the end +{ + Foo10 a @align(4); + char[1] _pad; + short b; +} + +struct Foo1_Compact +{ + bool a @compact; // #error: '@compact' is not a valid member attribute + int b; + int c @compact; +} + +struct Foo2_Compact @compact +{ + bool a; + bool b; + bool c; +} + +struct Foo4_Compact @compact +{ + bool a; + int b; // #error: 3 bytes of padding would be added + int c; +} + +struct Foo5_Compact @compact // #error: 3 bytes of padding would be added +{ + int a; + bool b; +} + +struct Foo6_Compact @compact +{ + int a; + struct nested // #error: 3 bytes of padding would be added + { + int a; + bool b; + } +} + +struct Foo7_Compact @compact +{ + int a; + struct nested + { + bool b; + int a; // #error: 3 bytes of padding would be added + } +} + +struct Foo8 @compact +{ + Foo8_A a; // #error: 'Foo8_A' has padding +} + +struct Foo8_A +{ + long a; + Foo8_B b; +} + +struct Foo8_B +{ + int a; + char[4] _pad; + struct + { + long b; + union + { + int c; + long d; + struct + { + int e; + Foo8_C f; + } + } + } +} + +struct Foo8_C +{ + bool a; + int b; +} + +struct Foo9 @compact +{ + Foo10 a; + char[13] _pad; + Foo9_A b; // #error: 'Foo9_A' has padding +} + +struct Foo9_A @align(16) +{ + int a; + int b; +} diff --git a/test/test_suite7/struct/struct_pack_and_align.c3t b/test/test_suite7/struct/struct_pack_and_align.c3t new file mode 100644 index 000000000..db00f4275 --- /dev/null +++ b/test/test_suite7/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 + +; Function Attrs: +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) + %ptradd = getelementptr inbounds i8, ptr %y, i64 16 + store i8 %0, ptr %ptradd, align 16 + %ptradd1 = getelementptr inbounds i8, ptr %y, i64 16 + %1 = load i8, ptr %ptradd1, align 16 + %sext = sext i8 %1 to i32 + %2 = load i32, ptr %y, align 16 + %add = add i32 %sext, %2 + ret i32 %add +} diff --git a/test/test_suite7/struct/struct_pack_error.c3t b/test/test_suite7/struct/struct_pack_error.c3t new file mode 100644 index 000000000..cb8022635 --- /dev/null +++ b/test/test_suite7/struct/struct_pack_error.c3t @@ -0,0 +1,48 @@ +// #target: macos-x64 +module test; +import std; + +// issue 1966 + +struct MsgHeader @packed +{ + ulong enqueued_by_router_us; +} + +enum ClientState +{ + NOT_INITIALIZED, + WAITING_FOR_LOGIN, + READY, + WAITING_FOR_CLOSE, +} + +struct Client +{ + ClientState state; + MsgHeader header; + ushort service_id; + ElasticArray() subscribers; +} + +Client[10] clients; + +fn void main() +{ + void* a = ((void*)(&clients[0])) + Client.sizeof; + void* b = &clients[1]; +} + +/* #expect: test.ll + +%Client = type <{ i32, %MsgHeader, i16, [2 x i8], %ElasticArray }> +%MsgHeader = type { i64 } +%ElasticArray = type { i64, [1 x i64] } +define void @test.main() #0 { +entry: + %a = alloca ptr, align 8 + %b = alloca ptr, align 8 + store ptr getelementptr (i8, ptr @test.clients, i64 32), ptr %a, align 8 + store ptr getelementptr inbounds (i8, ptr @test.clients, i64 32), ptr %b, align 8 + ret void +} \ No newline at end of file diff --git a/test/test_suite7/struct/struct_params.c3 b/test/test_suite7/struct/struct_params.c3 new file mode 100644 index 000000000..8a4bd2f69 --- /dev/null +++ b/test/test_suite7/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_suite7/struct/struct_reinit.c3t b/test/test_suite7/struct/struct_reinit.c3t new file mode 100644 index 000000000..656a88118 --- /dev/null +++ b/test/test_suite7/struct/struct_reinit.c3t @@ -0,0 +1,40 @@ +// #target: macos-x64 +module test; +import std; +struct Abc +{ + int a; + int b; +} + +fn void print(Abc* x) +{ + io::printfn("%d %d", x.a, x.b); +} +fn void main() +{ + Abc x = { 1, 4}; + print(&x) @noinline; + x = (Abc) { x.b, x.a }; + print(&x) @noinline; +} + +/* #expect: test.ll + +define void @test.main() #0 { +entry: + %x = alloca %Abc, align 4 + %.assign_list = alloca %Abc, align 4 + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %x, ptr align 4 @.__const, i32 8, i1 false) + call void @test.print(ptr %x) #3 + %ptradd = getelementptr inbounds i8, ptr %x, i64 4 + %0 = load i32, ptr %ptradd, align 4 + store i32 %0, ptr %.assign_list, align 4 + %ptradd1 = getelementptr inbounds i8, ptr %.assign_list, i64 4 + %1 = load i32, ptr %x, align 4 + store i32 %1, ptr %ptradd1, align 4 + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %x, ptr align 4 %.assign_list, i32 8, i1 false) + call void @test.print(ptr %x) #3 + ret void +} + diff --git a/test/test_suite7/struct/struct_union_inner_align.c3t b/test/test_suite7/struct/struct_union_inner_align.c3t new file mode 100644 index 000000000..6fe14a932 --- /dev/null +++ b/test/test_suite7/struct/struct_union_inner_align.c3t @@ -0,0 +1,43 @@ +// #target: macos-x64 +module test; + +union Test @align(16) +{ + char foo; +} + +union Test3 +{ + Test test; + ulong a @align(32); +} + +struct Test2 +{ + Test test; + uint a; +} + +fn int main() +{ + Test2 a; + Test b; + Test3 c; + $assert(32 == Test3.sizeof); + $assert(32 == Test3.alignof); + $assert(32 == Test2.sizeof); + $assert(16 == Test2.alignof); + $assert(16 == Test.sizeof); + $assert(16 == Test.alignof); + return 0; +} + +/* #expect: test.ll + +%Test2 = type { %Test, i32, [12 x i8] } +%Test = type { i8, [15 x i8] } +%Test3 = type { i64, [24 x i8] } + + %a = alloca %Test2, align 16 + %b = alloca %Test, align 16 + %c = alloca %Test3, align 32 diff --git a/test/test_suite7/struct/zero_member.c3 b/test/test_suite7/struct/zero_member.c3 new file mode 100644 index 000000000..fab779baa --- /dev/null +++ b/test/test_suite7/struct/zero_member.c3 @@ -0,0 +1,7 @@ +def Foo = int[0]; // #error: An array may not have zero + +struct Bar +{ + Foo x; + int b; +} \ No newline at end of file diff --git a/test/test_suite7/switch/bad_ranges.c3 b/test/test_suite7/switch/bad_ranges.c3 new file mode 100644 index 000000000..af839145d --- /dev/null +++ b/test/test_suite7/switch/bad_ranges.c3 @@ -0,0 +1,22 @@ +module test; + +fn void! test1() +{ + double a; + switch (a) + { + case 1.3 .. 4.5: // #error: Ranges must be constant integers + default: + } +} + +fn void! test2() +{ + int a; + switch (a) + { + case 2 .. 3: + case a .. 3: // #error: Ranges must be constant integers + default: + } +} \ No newline at end of file diff --git a/test/test_suite7/switch/enum_jump_switch_and_range.c3t b/test/test_suite7/switch/enum_jump_switch_and_range.c3t new file mode 100644 index 000000000..6cb2f6f2b --- /dev/null +++ b/test/test_suite7/switch/enum_jump_switch_and_range.c3t @@ -0,0 +1,503 @@ +// #target: macos-aarch64 +module test; +import std; +enum JumpTest // :int fails also +{ + ONE, + TWO, + THREE, +} + +fn void second_test(JumpTest enu) +{ + switch (enu) @jump + { + case ONE..THREE: io::printn ("."); + } +} + +fn void third_test(int a) +{ + switch (a) @jump + { + case 1..3: io::printn ("."); + case 9: io::printn (".."); + } +} + +fn void main(String[] args) +{ + JumpTest enu = TWO; + switch (enu) @jump + { + case ONE: io::printn ("."); + case TWO: io::printn (".."); + default : io::printn ("def"); + } +} + +/* #expect: test.ll + + +@jumptable = private unnamed_addr constant [3 x ptr] [ptr blockaddress(@test.second_test, %switch.case), ptr blockaddress(@test.second_test, %switch.case), ptr blockaddress(@test.second_test, %switch.case)], align 4 +@jumptable.1 = private unnamed_addr constant [9 x ptr] [ptr blockaddress(@test.third_test, %switch.case), ptr blockaddress(@test.third_test, %switch.case), ptr blockaddress(@test.third_test, %switch.case), ptr blockaddress(@test.third_test, %switch.exit), ptr blockaddress(@test.third_test, %switch.exit), ptr blockaddress(@test.third_test, %switch.exit), ptr blockaddress(@test.third_test, %switch.exit), ptr blockaddress(@test.third_test, %switch.exit), ptr blockaddress(@test.third_test, %switch.case14)], align 4 +@jumptable.4 = private unnamed_addr constant [2 x ptr] [ptr blockaddress(@test.main, %switch.case), ptr blockaddress(@test.main, %switch.case14)], align 4 + + store i32 %0, ptr %switch, align 4 + br label %switch.entry + +switch.entry: ; preds = %entry + %1 = load i32, ptr %switch, align 4 + %2 = icmp ugt i32 %1, 2 + br i1 %2, label %switch.exit, label %jumpblock + +jumpblock: ; preds = %switch.entry + %ptroffset = getelementptr inbounds [8 x i8], ptr @jumptable, i32 %1 + %target = load ptr, ptr %ptroffset, align 8 + indirectbr ptr %target, [label %switch.case] + +switch.case: ; preds = %jumpblock + %3 = call ptr @std.io.stdout() + store %"char[]" { ptr @.str, i64 1 }, ptr %taddr, align 8 + %4 = load [2 x i64], ptr %taddr, align 8 + %5 = call i64 @std.io.File.write(ptr %retparam, ptr %3, [2 x i64] %4) + %not_err = icmp eq i64 %5, 0 + %6 = call i1 @llvm.expect.i1(i1 %not_err, i1 true) + br i1 %6, label %after_check, label %assign_optional + +assign_optional: ; preds = %switch.case + store i64 %5, ptr %error_var, align 8 + br label %guard_block + +after_check: ; preds = %switch.case + br label %noerr_block + +guard_block: ; preds = %assign_optional + br label %voiderr + +noerr_block: ; preds = %after_check + %7 = load i64, ptr %retparam, align 8 + store i64 %7, ptr %len, align 8 + %8 = call i64 @std.io.File.write_byte(ptr %3, i8 10) + %not_err3 = icmp eq i64 %8, 0 + %9 = call i1 @llvm.expect.i1(i1 %not_err3, i1 true) + br i1 %9, label %after_check5, label %assign_optional4 + +assign_optional4: ; preds = %noerr_block + store i64 %8, ptr %error_var2, align 8 + br label %guard_block6 + +after_check5: ; preds = %noerr_block + br label %noerr_block7 + +guard_block6: ; preds = %assign_optional4 + br label %voiderr + +noerr_block7: ; preds = %after_check5 + %10 = call i64 @std.io.File.flush(ptr %3) + %not_err9 = icmp eq i64 %10, 0 + %11 = call i1 @llvm.expect.i1(i1 %not_err9, i1 true) + br i1 %11, label %after_check11, label %assign_optional10 + +assign_optional10: ; preds = %noerr_block7 + store i64 %10, ptr %error_var8, align 8 + br label %guard_block12 + +after_check11: ; preds = %noerr_block7 + br label %noerr_block13 + +guard_block12: ; preds = %assign_optional10 + br label %voiderr + +noerr_block13: ; preds = %after_check11 + %12 = load i64, ptr %len, align 8 + %add = add i64 %12, 1 + br label %voiderr + +voiderr: ; preds = %noerr_block13, %guard_block12, %guard_block6, %guard_block + br label %switch.exit + +switch.exit: ; preds = %voiderr, %switch.entry + ret void +} + +define void @test.third_test(i32 %0) #0 { +entry: + %switch = alloca i32, align 4 + %len = alloca i64, align 8 + %error_var = alloca i64, align 8 + %retparam = alloca i64, align 8 + %taddr = alloca %"char[]", align 8 + %error_var2 = alloca i64, align 8 + %error_var8 = alloca i64, align 8 + %len15 = alloca i64, align 8 + %error_var16 = alloca i64, align 8 + %retparam18 = alloca i64, align 8 + %taddr19 = alloca %"char[]", align 8 + %error_var25 = alloca i64, align 8 + %error_var31 = alloca i64, align 8 + store i32 %0, ptr %switch, align 4 + br label %switch.entry + +switch.entry: ; preds = %entry + %1 = load i32, ptr %switch, align 4 + %2 = sub i32 %1, 1 + %3 = icmp ugt i32 %2, 8 + br i1 %3, label %switch.exit, label %jumpblock + +jumpblock: ; preds = %switch.entry + %ptroffset = getelementptr inbounds [8 x i8], ptr @jumptable.1, i32 %2 + %target = load ptr, ptr %ptroffset, align 8 + indirectbr ptr %target, [label %switch.case, label %switch.case14, label %switch.exit] + +switch.case: ; preds = %jumpblock + %4 = call ptr @std.io.stdout() + store %"char[]" { ptr @.str.2, i64 1 }, ptr %taddr, align 8 + %5 = load [2 x i64], ptr %taddr, align 8 + %6 = call i64 @std.io.File.write(ptr %retparam, ptr %4, [2 x i64] %5) + %not_err = icmp eq i64 %6, 0 + %7 = call i1 @llvm.expect.i1(i1 %not_err, i1 true) + br i1 %7, label %after_check, label %assign_optional + +assign_optional: ; preds = %switch.case + store i64 %6, ptr %error_var, align 8 + br label %guard_block + +after_check: ; preds = %switch.case + br label %noerr_block + +guard_block: ; preds = %assign_optional + br label %voiderr + +noerr_block: ; preds = %after_check + %8 = load i64, ptr %retparam, align 8 + store i64 %8, ptr %len, align 8 + %9 = call i64 @std.io.File.write_byte(ptr %4, i8 10) + %not_err3 = icmp eq i64 %9, 0 + %10 = call i1 @llvm.expect.i1(i1 %not_err3, i1 true) + br i1 %10, label %after_check5, label %assign_optional4 + +assign_optional4: ; preds = %noerr_block + store i64 %9, ptr %error_var2, align 8 + br label %guard_block6 + +after_check5: ; preds = %noerr_block + br label %noerr_block7 + +guard_block6: ; preds = %assign_optional4 + br label %voiderr + +noerr_block7: ; preds = %after_check5 + %11 = call i64 @std.io.File.flush(ptr %4) + %not_err9 = icmp eq i64 %11, 0 + %12 = call i1 @llvm.expect.i1(i1 %not_err9, i1 true) + br i1 %12, label %after_check11, label %assign_optional10 + +assign_optional10: ; preds = %noerr_block7 + store i64 %11, ptr %error_var8, align 8 + br label %guard_block12 + +after_check11: ; preds = %noerr_block7 + br label %noerr_block13 + +guard_block12: ; preds = %assign_optional10 + br label %voiderr + +noerr_block13: ; preds = %after_check11 + %13 = load i64, ptr %len, align 8 + %add = add i64 %13, 1 + br label %voiderr + +voiderr: ; preds = %noerr_block13, %guard_block12, %guard_block6, %guard_block + br label %switch.exit + +switch.case14: ; preds = %jumpblock + %14 = call ptr @std.io.stdout() + store %"char[]" { ptr @.str.3, i64 2 }, ptr %taddr19, align 8 + %15 = load [2 x i64], ptr %taddr19, align 8 + %16 = call i64 @std.io.File.write(ptr %retparam18, ptr %14, [2 x i64] %15) + %not_err20 = icmp eq i64 %16, 0 + %17 = call i1 @llvm.expect.i1(i1 %not_err20, i1 true) + br i1 %17, label %after_check22, label %assign_optional21 + +assign_optional21: ; preds = %switch.case14 + store i64 %16, ptr %error_var16, align 8 + br label %guard_block23 + +after_check22: ; preds = %switch.case14 + br label %noerr_block24 + +guard_block23: ; preds = %assign_optional21 + br label %voiderr38 + +noerr_block24: ; preds = %after_check22 + %18 = load i64, ptr %retparam18, align 8 + store i64 %18, ptr %len15, align 8 + %19 = call i64 @std.io.File.write_byte(ptr %14, i8 10) + %not_err26 = icmp eq i64 %19, 0 + %20 = call i1 @llvm.expect.i1(i1 %not_err26, i1 true) + br i1 %20, label %after_check28, label %assign_optional27 + +assign_optional27: ; preds = %noerr_block24 + store i64 %19, ptr %error_var25, align 8 + br label %guard_block29 + +after_check28: ; preds = %noerr_block24 + br label %noerr_block30 + +guard_block29: ; preds = %assign_optional27 + br label %voiderr38 + +noerr_block30: ; preds = %after_check28 + %21 = call i64 @std.io.File.flush(ptr %14) + %not_err32 = icmp eq i64 %21, 0 + %22 = call i1 @llvm.expect.i1(i1 %not_err32, i1 true) + br i1 %22, label %after_check34, label %assign_optional33 + +assign_optional33: ; preds = %noerr_block30 + store i64 %21, ptr %error_var31, align 8 + br label %guard_block35 + +after_check34: ; preds = %noerr_block30 + br label %noerr_block36 + +guard_block35: ; preds = %assign_optional33 + br label %voiderr38 + +noerr_block36: ; preds = %after_check34 + %23 = load i64, ptr %len15, align 8 + %add37 = add i64 %23, 1 + br label %voiderr38 + +voiderr38: ; preds = %noerr_block36, %guard_block35, %guard_block29, %guard_block23 + br label %switch.exit + +switch.exit: ; preds = %jumpblock, %voiderr38, %voiderr, %switch.entry + ret void +} + +entry: + %args = alloca %"char[][]", align 8 + %enu = alloca i32, align 4 + %switch = alloca i32, align 4 + %len = alloca i64, align 8 + %error_var = alloca i64, align 8 + %retparam = alloca i64, align 8 + %taddr = alloca %"char[]", align 8 + %error_var2 = alloca i64, align 8 + %error_var8 = alloca i64, align 8 + %len15 = alloca i64, align 8 + %error_var16 = alloca i64, align 8 + %retparam18 = alloca i64, align 8 + %taddr19 = alloca %"char[]", align 8 + %error_var25 = alloca i64, align 8 + %error_var31 = alloca i64, align 8 + %len39 = alloca i64, align 8 + %error_var40 = alloca i64, align 8 + %retparam42 = alloca i64, align 8 + %taddr43 = alloca %"char[]", align 8 + %error_var49 = alloca i64, align 8 + %error_var55 = alloca i64, align 8 + store [2 x i64] %0, ptr %args, align 8 + store i32 1, ptr %enu, align 4 + %1 = load i32, ptr %enu, align 4 + store i32 %1, ptr %switch, align 4 + br label %switch.entry + +switch.entry: ; preds = %entry + %2 = load i32, ptr %switch, align 4 + %3 = icmp ugt i32 %2, 1 + br i1 %3, label %switch.default, label %jumpblock + +jumpblock: ; preds = %switch.entry + %ptroffset = getelementptr inbounds [8 x i8], ptr @jumptable.4, i32 %2 + %target = load ptr, ptr %ptroffset, align 8 + indirectbr ptr %target, [label %switch.case, label %switch.case14] + +switch.case: ; preds = %jumpblock + %4 = call ptr @std.io.stdout() + store %"char[]" { ptr @.str.5, i64 1 }, ptr %taddr, align 8 + %5 = load [2 x i64], ptr %taddr, align 8 + %6 = call i64 @std.io.File.write(ptr %retparam, ptr %4, [2 x i64] %5) + %not_err = icmp eq i64 %6, 0 + %7 = call i1 @llvm.expect.i1(i1 %not_err, i1 true) + br i1 %7, label %after_check, label %assign_optional + +assign_optional: ; preds = %switch.case + store i64 %6, ptr %error_var, align 8 + br label %guard_block + +after_check: ; preds = %switch.case + br label %noerr_block + +guard_block: ; preds = %assign_optional + br label %voiderr + +noerr_block: ; preds = %after_check + %8 = load i64, ptr %retparam, align 8 + store i64 %8, ptr %len, align 8 + %9 = call i64 @std.io.File.write_byte(ptr %4, i8 10) + %not_err3 = icmp eq i64 %9, 0 + %10 = call i1 @llvm.expect.i1(i1 %not_err3, i1 true) + br i1 %10, label %after_check5, label %assign_optional4 + +assign_optional4: ; preds = %noerr_block + store i64 %9, ptr %error_var2, align 8 + br label %guard_block6 + +after_check5: ; preds = %noerr_block + br label %noerr_block7 + +guard_block6: ; preds = %assign_optional4 + br label %voiderr + +noerr_block7: ; preds = %after_check5 + %11 = call i64 @std.io.File.flush(ptr %4) + %not_err9 = icmp eq i64 %11, 0 + %12 = call i1 @llvm.expect.i1(i1 %not_err9, i1 true) + br i1 %12, label %after_check11, label %assign_optional10 + +assign_optional10: ; preds = %noerr_block7 + store i64 %11, ptr %error_var8, align 8 + br label %guard_block12 + +after_check11: ; preds = %noerr_block7 + br label %noerr_block13 + +guard_block12: ; preds = %assign_optional10 + br label %voiderr + +noerr_block13: ; preds = %after_check11 + %13 = load i64, ptr %len, align 8 + %add = add i64 %13, 1 + br label %voiderr + +voiderr: ; preds = %noerr_block13, %guard_block12, %guard_block6, %guard_block + br label %switch.exit + +switch.case14: ; preds = %jumpblock + %14 = call ptr @std.io.stdout() + store %"char[]" { ptr @.str.6, i64 2 }, ptr %taddr19, align 8 + %15 = load [2 x i64], ptr %taddr19, align 8 + %16 = call i64 @std.io.File.write(ptr %retparam18, ptr %14, [2 x i64] %15) + %not_err20 = icmp eq i64 %16, 0 + %17 = call i1 @llvm.expect.i1(i1 %not_err20, i1 true) + br i1 %17, label %after_check22, label %assign_optional21 + +assign_optional21: ; preds = %switch.case14 + store i64 %16, ptr %error_var16, align 8 + br label %guard_block23 + +after_check22: ; preds = %switch.case14 + br label %noerr_block24 + +guard_block23: ; preds = %assign_optional21 + br label %voiderr38 + +noerr_block24: ; preds = %after_check22 + %18 = load i64, ptr %retparam18, align 8 + store i64 %18, ptr %len15, align 8 + %19 = call i64 @std.io.File.write_byte(ptr %14, i8 10) + %not_err26 = icmp eq i64 %19, 0 + %20 = call i1 @llvm.expect.i1(i1 %not_err26, i1 true) + br i1 %20, label %after_check28, label %assign_optional27 + +assign_optional27: ; preds = %noerr_block24 + store i64 %19, ptr %error_var25, align 8 + br label %guard_block29 + +after_check28: ; preds = %noerr_block24 + br label %noerr_block30 + +guard_block29: ; preds = %assign_optional27 + br label %voiderr38 + +noerr_block30: ; preds = %after_check28 + %21 = call i64 @std.io.File.flush(ptr %14) + %not_err32 = icmp eq i64 %21, 0 + %22 = call i1 @llvm.expect.i1(i1 %not_err32, i1 true) + br i1 %22, label %after_check34, label %assign_optional33 + +assign_optional33: ; preds = %noerr_block30 + store i64 %21, ptr %error_var31, align 8 + br label %guard_block35 + +after_check34: ; preds = %noerr_block30 + br label %noerr_block36 + +guard_block35: ; preds = %assign_optional33 + br label %voiderr38 + +noerr_block36: ; preds = %after_check34 + %23 = load i64, ptr %len15, align 8 + %add37 = add i64 %23, 1 + br label %voiderr38 + +voiderr38: ; preds = %noerr_block36, %guard_block35, %guard_block29, %guard_block23 + br label %switch.exit + +switch.default: ; preds = %switch.entry + %24 = call ptr @std.io.stdout() + store %"char[]" { ptr @.str.7, i64 3 }, ptr %taddr43, align 8 + %25 = load [2 x i64], ptr %taddr43, align 8 + %26 = call i64 @std.io.File.write(ptr %retparam42, ptr %24, [2 x i64] %25) + %not_err44 = icmp eq i64 %26, 0 + %27 = call i1 @llvm.expect.i1(i1 %not_err44, i1 true) + br i1 %27, label %after_check46, label %assign_optional45 + +assign_optional45: ; preds = %switch.default + store i64 %26, ptr %error_var40, align 8 + br label %guard_block47 + +after_check46: ; preds = %switch.default + br label %noerr_block48 + +guard_block47: ; preds = %assign_optional45 + br label %voiderr62 + +noerr_block48: ; preds = %after_check46 + %28 = load i64, ptr %retparam42, align 8 + store i64 %28, ptr %len39, align 8 + %29 = call i64 @std.io.File.write_byte(ptr %24, i8 10) + %not_err50 = icmp eq i64 %29, 0 + %30 = call i1 @llvm.expect.i1(i1 %not_err50, i1 true) + br i1 %30, label %after_check52, label %assign_optional51 + +assign_optional51: ; preds = %noerr_block48 + store i64 %29, ptr %error_var49, align 8 + br label %guard_block53 + +after_check52: ; preds = %noerr_block48 + br label %noerr_block54 + +guard_block53: ; preds = %assign_optional51 + br label %voiderr62 + +noerr_block54: ; preds = %after_check52 + %31 = call i64 @std.io.File.flush(ptr %24) + %not_err56 = icmp eq i64 %31, 0 + %32 = call i1 @llvm.expect.i1(i1 %not_err56, i1 true) + br i1 %32, label %after_check58, label %assign_optional57 + +assign_optional57: ; preds = %noerr_block54 + store i64 %31, ptr %error_var55, align 8 + br label %guard_block59 + +after_check58: ; preds = %noerr_block54 + br label %noerr_block60 + +guard_block59: ; preds = %assign_optional57 + br label %voiderr62 + +noerr_block60: ; preds = %after_check58 + %33 = load i64, ptr %len39, align 8 + %add61 = add i64 %33, 1 + br label %voiderr62 + +voiderr62: ; preds = %noerr_block60, %guard_block59, %guard_block53, %guard_block47 + br label %switch.exit + +switch.exit: ; preds = %voiderr62, %voiderr38, %voiderr + ret void +} + diff --git a/test/test_suite7/switch/failable_switch.c3 b/test/test_suite7/switch/failable_switch.c3 new file mode 100644 index 000000000..52489999d --- /dev/null +++ b/test/test_suite7/switch/failable_switch.c3 @@ -0,0 +1,14 @@ +fault MyError +{ + FOO +} + +fn void test() +{ + int x = 0; + switch (x) + { + case MyError.FOO? : // #error: 'int!' to 'int' + x = x + 1; + } +} \ No newline at end of file diff --git a/test/test_suite7/switch/jump_bug_nested.c3t b/test/test_suite7/switch/jump_bug_nested.c3t new file mode 100644 index 000000000..125bc6e3f --- /dev/null +++ b/test/test_suite7/switch/jump_bug_nested.c3t @@ -0,0 +1,139 @@ +// #target: macos-aarch64 +module test; +import std; +fn void main() +{ + switch (0) @jump + { + case 0: + foo(); + } +} + + +macro void foo() +{ + io::printn("Inside Foo"); + switch (1) @jump + { + case 2: + io::printfn("This should never happen"); + } +} + +/* #expect: test.ll + +define void @test.main() #0 { +entry: + %switch = alloca i32, align 4 + %len = alloca i64, align 8 + %error_var = alloca i64, align 8 + %retparam = alloca i64, align 8 + %taddr = alloca %"char[]", align 8 + %error_var2 = alloca i64, align 8 + %error_var8 = alloca i64, align 8 + %switch14 = alloca i32, align 4 + %retparam20 = alloca i64, align 8 + %taddr21 = alloca %"char[]", align 8 + %taddr22 = alloca %"any[]", align 8 + store i32 0, ptr %switch, align 4 + br label %switch.entry + +switch.entry: ; preds = %entry + %0 = load i32, ptr %switch, align 4 + %1 = icmp ugt i32 %0, 0 + br i1 %1, label %switch.exit25, label %jumpblock + +jumpblock: ; preds = %switch.entry + %ptroffset = getelementptr inbounds [8 x i8], ptr @jumptable, i32 %0 + %target = load ptr, ptr %ptroffset, align 8 + indirectbr ptr %target, [label %switch.case] + +switch.case: ; preds = %jumpblock + %2 = call ptr @std.io.stdout() + store %"char[]" { ptr @.str, i64 10 }, ptr %taddr, align 8 + %3 = load [2 x i64], ptr %taddr, align 8 + %4 = call i64 @std.io.File.write(ptr %retparam, ptr %2, [2 x i64] %3) + %not_err = icmp eq i64 %4, 0 + %5 = call i1 @llvm.expect.i1(i1 %not_err, i1 true) + br i1 %5, label %after_check, label %assign_optional + +assign_optional: ; preds = %switch.case + store i64 %4, ptr %error_var, align 8 + br label %guard_block + +after_check: ; preds = %switch.case + br label %noerr_block + +guard_block: ; preds = %assign_optional + br label %voiderr + +noerr_block: ; preds = %after_check + %6 = load i64, ptr %retparam, align 8 + store i64 %6, ptr %len, align 8 + %7 = call i64 @std.io.File.write_byte(ptr %2, i8 10) + %not_err3 = icmp eq i64 %7, 0 + %8 = call i1 @llvm.expect.i1(i1 %not_err3, i1 true) + br i1 %8, label %after_check5, label %assign_optional4 + +assign_optional4: ; preds = %noerr_block + store i64 %7, ptr %error_var2, align 8 + br label %guard_block6 + +after_check5: ; preds = %noerr_block + br label %noerr_block7 + +guard_block6: ; preds = %assign_optional4 + br label %voiderr + +noerr_block7: ; preds = %after_check5 + %9 = call i64 @std.io.File.flush(ptr %2) + %not_err9 = icmp eq i64 %9, 0 + %10 = call i1 @llvm.expect.i1(i1 %not_err9, i1 true) + br i1 %10, label %after_check11, label %assign_optional10 + +assign_optional10: ; preds = %noerr_block7 + store i64 %9, ptr %error_var8, align 8 + br label %guard_block12 + +after_check11: ; preds = %noerr_block7 + br label %noerr_block13 + +guard_block12: ; preds = %assign_optional10 + br label %voiderr + +noerr_block13: ; preds = %after_check11 + %11 = load i64, ptr %len, align 8 + %add = add i64 %11, 1 + br label %voiderr + +voiderr: ; preds = %noerr_block13, %guard_block12, %guard_block6, %guard_block + store i32 1, ptr %switch14, align 4 + br label %switch.entry15 + +switch.entry15: ; preds = %voiderr + %12 = load i32, ptr %switch14, align 4 + %13 = sub i32 %12, 2 + %14 = icmp ugt i32 %13, 0 + br i1 %14, label %switch.exit, label %jumpblock16 + +jumpblock16: ; preds = %switch.entry15 + %ptroffset17 = getelementptr inbounds [8 x i8], ptr @jumptable.1, i32 %13 + %target18 = load ptr, ptr %ptroffset17, align 8 + indirectbr ptr %target18, [label %switch.case19] + +switch.case19: ; preds = %jumpblock16 + store %"char[]" { ptr @.str.2, i64 24 }, ptr %taddr21, align 8 + %15 = load [2 x i64], ptr %taddr21, align 8 + store %"any[]" zeroinitializer, ptr %taddr22, align 8 + %16 = load [2 x i64], ptr %taddr22, align 8 + %17 = call i64 @std.io.printfn(ptr %retparam20, [2 x i64] %15, [2 x i64] %16) + br label %switch.exit + +switch.exit: ; preds = %switch.case19, %switch.entry15 + br label %switch.exit25 + +switch.exit25: ; preds = %switch.exit, %switch.entry + ret void +} + diff --git a/test/test_suite7/switch/jump_bugs.c3t b/test/test_suite7/switch/jump_bugs.c3t new file mode 100644 index 000000000..8947effc0 --- /dev/null +++ b/test/test_suite7/switch/jump_bugs.c3t @@ -0,0 +1,70 @@ +// #target: macos-aarch64 +module test; + +fn void test1() +{ + switch (0) @jump + { + case 0: + break; + default: + } +} + +enum Foo { A, B, } + +fn void main() +{ + test1(); + switch (Foo.A) @jump + { + default: + break; + } +} + +/* #expect: test.ll + +@jumptable = private unnamed_addr constant [1 x ptr] [ptr blockaddress(@test.test1, %switch.case)], align 4 + +define void @test.test1() #0 { +entry: + %switch = alloca i32, align 4 + store i32 0, ptr %switch, align 4 + br label %switch.entry + +switch.entry: ; preds = %entry + %0 = load i32, ptr %switch, align 4 + %1 = icmp ugt i32 %0, 0 + br i1 %1, label %switch.exit, label %jumpblock + +jumpblock: ; preds = %switch.entry + %ptroffset = getelementptr inbounds [8 x i8], ptr @jumptable, i32 %0 + %target = load ptr, ptr %ptroffset, align 8 + indirectbr ptr %target, [label %switch.case] + +switch.case: ; preds = %jumpblock + br label %switch.exit + +switch.exit: ; preds = %switch.case, %switch.entry + ret void +} + +define void @test.main() #0 { +entry: + %switch = alloca i32, align 4 + call void @test.test1() + store i32 0, ptr %switch, align 4 + br label %switch.entry + +switch.entry: ; preds = %entry + %0 = load i32, ptr %switch, align 4 + switch i32 %0, label %switch.default [ + ] + +switch.default: ; preds = %switch.entry + br label %switch.exit + +switch.exit: ; preds = %switch.default + ret void +} diff --git a/test/test_suite7/switch/jump_with_inc.c3t b/test/test_suite7/switch/jump_with_inc.c3t new file mode 100644 index 000000000..ce8de6db7 --- /dev/null +++ b/test/test_suite7/switch/jump_with_inc.c3t @@ -0,0 +1,65 @@ +// #target: macos-aarch64 +module test; +extern fn int b(int y); + +fn int foo(int x) @export +{ + switch (x) @jump + { + case 1: + nextcase (b(x)); + case 0: + x++; + nextcase x; + default: + unreachable(); + } +} +/* #expect: test.ll + +define i32 @test__foo(i32 %0) #0 { +entry: + %x = alloca i32, align 4 + %switch = alloca i32, align 4 + store i32 %0, ptr %x, align 4 + %1 = load i32, ptr %x, align 4 + store i32 %1, ptr %switch, align 4 + br label %switch.entry + +switch.entry: ; preds = %entry + %2 = load i32, ptr %switch, align 4 + %3 = icmp ugt i32 %2, 1 + br i1 %3, label %switch.default, label %jumpblock + +jumpblock: ; preds = %switch.entry + %ptroffset = getelementptr inbounds [8 x i8], ptr @jumptable, i32 %2 + %target = load ptr, ptr %ptroffset, align 8 + indirectbr ptr %target, [label %switch.case, label %switch.case4] + +switch.case: ; preds = %jumpblock5, %jumpblock1, %jumpblock + %4 = load i32, ptr %x, align 4 + %5 = call i32 @b(i32 %4) + %6 = icmp ugt i32 %5, 1 + br i1 %6, label %switch.default, label %jumpblock1 + +jumpblock1: ; preds = %switch.case + %ptroffset2 = getelementptr inbounds [8 x i8], ptr @jumptable, i32 %5 + %target3 = load ptr, ptr %ptroffset2, align 8 + indirectbr ptr %target3, [label %switch.case, label %switch.case4, label %switch.default] + +switch.case4: ; preds = %jumpblock5, %jumpblock, %jumpblock1 + %7 = load i32, ptr %x, align 4 + %add = add i32 %7, 1 + store i32 %add, ptr %x, align 4 + %8 = load i32, ptr %x, align 4 + %9 = icmp ugt i32 %8, 1 + br i1 %9, label %switch.default, label %jumpblock5 + +jumpblock5: ; preds = %switch.case4 + %ptroffset6 = getelementptr inbounds [8 x i8], ptr @jumptable, i32 %8 + %target7 = load ptr, ptr %ptroffset6, align 8 + indirectbr ptr %target7, [label %switch.case, label %switch.case4, label %switch.default] + +switch.default: ; preds = %jumpblock5, %switch.case4, %jumpblock1, %switch.case, %switch.entry + unreachable +} diff --git a/test/test_suite7/switch/simple_jump.c3t b/test/test_suite7/switch/simple_jump.c3t new file mode 100644 index 000000000..883fcf557 --- /dev/null +++ b/test/test_suite7/switch/simple_jump.c3t @@ -0,0 +1,283 @@ +// #target: macos-x64 +import std::io; + +fn void res(int a) +{ + io::printn(a); +} +fn void test1(int a) +{ + switch (a) @jump + { + case 1: res(1); + case 0: + case 2: res(2); + } + res(0); +} + +fn void test2(int a) +{ + switch (a) @jump + { + case 1: res(1); + case 2: res(2); + } +} + +fn void test3(int a) +{ + switch (a) @jump + { + case 1: res(1); + case 3: res(3); + } +} + +fn void test4(int a) +{ + switch (a) @jump + { + case 1: res(1); + default: res(-1); + } +} + +fn void test5(int a) +{ + switch (a) @jump + { + case 1: res(1); + case 4: res(4); + default: res(-1); + } +} + +fn void test6(int a) +{ + switch (a) @jump + { + case 1: res(1); + case 4: res(4); + case 5: nextcase(a * 2); + default: res(-1); + } +} + +/* #expect: simple_jump.ll + +@jumptable = private unnamed_addr constant [3 x ptr] [ptr blockaddress(@simple_jump.test1, %switch.case1), ptr blockaddress(@simple_jump.test1, %switch.case), ptr blockaddress(@simple_jump.test1, %switch.case1)], align 4 +@jumptable.1 = private unnamed_addr constant [2 x ptr] [ptr blockaddress(@simple_jump.test2, %switch.case), ptr blockaddress(@simple_jump.test2, %switch.case1)], align 4 +@jumptable.2 = private unnamed_addr constant [3 x ptr] [ptr blockaddress(@simple_jump.test3, %switch.case), ptr blockaddress(@simple_jump.test3, %switch.exit), ptr blockaddress(@simple_jump.test3, %switch.case1)], align 4 +@jumptable.3 = private unnamed_addr constant [1 x ptr] [ptr blockaddress(@simple_jump.test4, %switch.case)], align 4 +@jumptable.4 = private unnamed_addr constant [4 x ptr] [ptr blockaddress(@simple_jump.test5, %switch.case), ptr blockaddress(@simple_jump.test5, %switch.default), ptr blockaddress(@simple_jump.test5, %switch.default), ptr blockaddress(@simple_jump.test5, %switch.case1)], align 4 +@jumptable.5 = private unnamed_addr constant [5 x ptr] [ptr blockaddress(@simple_jump.test6, %switch.case), ptr blockaddress(@simple_jump.test6, %switch.default), ptr blockaddress(@simple_jump.test6, %switch.default), ptr blockaddress(@simple_jump.test6, %switch.case1), ptr blockaddress(@simple_jump.test6, %switch.case2)], align 4 + +after_check12: ; preds = %noerr_block8 + br label %noerr_block14 + +guard_block13: ; preds = %assign_optional11 + br label %voiderr + +noerr_block14: ; preds = %after_check12 + %14 = load i64, ptr %len, align 8 + %add = add i64 %14, 1 + br label %voiderr + +voiderr: ; preds = %noerr_block14, %guard_block13, %guard_block7, %guard_block + ret void +} + +define void @simple_jump.test1(i32 %0) #0 { +entry: + %switch = 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 + %2 = icmp ugt i32 %1, 2 + br i1 %2, label %switch.exit, label %jumpblock + +jumpblock: ; preds = %switch.entry + %ptroffset = getelementptr inbounds [8 x i8], ptr @jumptable, i32 %1 + %target = load ptr, ptr %ptroffset, align 8 + indirectbr ptr %target, [label %switch.case, label %switch.case1] + +switch.case: ; preds = %jumpblock + call void @simple_jump.res(i32 1) + br label %switch.exit + +switch.case1: ; preds = %jumpblock + call void @simple_jump.res(i32 2) + br label %switch.exit + +switch.exit: ; preds = %switch.case1, %switch.case, %switch.entry + call void @simple_jump.res(i32 0) + ret void +} + +define void @simple_jump.test2(i32 %0) #0 { +entry: + %switch = 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 + %2 = sub i32 %1, 1 + %3 = icmp ugt i32 %2, 1 + br i1 %3, label %switch.exit, label %jumpblock + +jumpblock: ; preds = %switch.entry + %ptroffset = getelementptr inbounds [8 x i8], ptr @jumptable.1, i32 %2 + %target = load ptr, ptr %ptroffset, align 8 + indirectbr ptr %target, [label %switch.case, label %switch.case1] + +switch.case: ; preds = %jumpblock + call void @simple_jump.res(i32 1) + br label %switch.exit + +switch.case1: ; preds = %jumpblock + call void @simple_jump.res(i32 2) + br label %switch.exit + +switch.exit: ; preds = %switch.case1, %switch.case, %switch.entry + ret void +} + +define void @simple_jump.test3(i32 %0) #0 { +entry: + %switch = 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 + %2 = sub i32 %1, 1 + %3 = icmp ugt i32 %2, 2 + br i1 %3, label %switch.exit, label %jumpblock + +jumpblock: ; preds = %switch.entry + %ptroffset = getelementptr inbounds [8 x i8], ptr @jumptable.2, i32 %2 + %target = load ptr, ptr %ptroffset, align 8 + indirectbr ptr %target, [label %switch.case, label %switch.case1, label %switch.exit] + +switch.case: ; preds = %jumpblock + call void @simple_jump.res(i32 1) + br label %switch.exit + +switch.case1: ; preds = %jumpblock + call void @simple_jump.res(i32 3) + br label %switch.exit + +switch.exit: ; preds = %jumpblock, %switch.case1, %switch.case, %switch.entry + ret void +} + +define void @simple_jump.test4(i32 %0) #0 { +entry: + %switch = 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 + %2 = sub i32 %1, 1 + %3 = icmp ugt i32 %2, 0 + br i1 %3, label %switch.default, label %jumpblock + +jumpblock: ; preds = %switch.entry + %ptroffset = getelementptr inbounds [8 x i8], ptr @jumptable.3, i32 %2 + %target = load ptr, ptr %ptroffset, align 8 + indirectbr ptr %target, [label %switch.case] + +switch.case: ; preds = %jumpblock + call void @simple_jump.res(i32 1) + br label %switch.exit + +switch.default: ; preds = %switch.entry + call void @simple_jump.res(i32 -1) + br label %switch.exit + +switch.exit: ; preds = %switch.default, %switch.case + ret void +} + +define void @simple_jump.test5(i32 %0) #0 { +entry: + %switch = 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 + %2 = sub i32 %1, 1 + %3 = icmp ugt i32 %2, 3 + br i1 %3, label %switch.default, label %jumpblock + +jumpblock: ; preds = %switch.entry + %ptroffset = getelementptr inbounds [8 x i8], ptr @jumptable.4, i32 %2 + %target = load ptr, ptr %ptroffset, align 8 + indirectbr ptr %target, [label %switch.case, label %switch.case1, label %switch.default] + +switch.case: ; preds = %jumpblock + call void @simple_jump.res(i32 1) + br label %switch.exit + +switch.case1: ; preds = %jumpblock + call void @simple_jump.res(i32 4) + br label %switch.exit + +switch.default: ; preds = %jumpblock, %switch.entry + call void @simple_jump.res(i32 -1) + br label %switch.exit + +switch.exit: ; preds = %switch.default, %switch.case1, %switch.case + ret void +} + +; Function Attrs: nounwind uwtable +define void @simple_jump.test6(i32 %0) #0 { +entry: + %switch = 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 + %2 = sub i32 %1, 1 + %3 = icmp ugt i32 %2, 4 + br i1 %3, label %switch.default, label %jumpblock + +jumpblock: ; preds = %switch.entry + %ptroffset = getelementptr inbounds [8 x i8], ptr @jumptable.5, i32 %2 + %target = load ptr, ptr %ptroffset, align 8 + indirectbr ptr %target, [label %switch.case, label %switch.case1, label %switch.case2, label %switch.default] + +switch.case: ; preds = %jumpblock3, %jumpblock + call void @simple_jump.res(i32 1) + br label %switch.exit + +switch.case1: ; preds = %jumpblock3, %jumpblock + call void @simple_jump.res(i32 4) + br label %switch.exit + +switch.case2: ; preds = %jumpblock3, %jumpblock + %mul = mul i32 %0, 2 + %4 = sub i32 %mul, 1 + %5 = icmp ugt i32 %4, 4 + br i1 %5, label %switch.default, label %jumpblock3 + +jumpblock3: ; preds = %switch.case2 + %ptroffset4 = getelementptr inbounds [8 x i8], ptr @jumptable.5, i32 %4 + %target5 = load ptr, ptr %ptroffset4, align 8 + indirectbr ptr %target5, [label %switch.case, label %switch.case1, label %switch.case2, label %switch.default] + +switch.default: ; preds = %jumpblock, %jumpblock3, %switch.case2, %switch.entry + call void @simple_jump.res(i32 -1) + br label %switch.exit + +switch.exit: ; preds = %switch.default, %switch.case1, %switch.case + ret void +} \ No newline at end of file diff --git a/test/test_suite7/switch/switch_in_defer_macro.c3t b/test/test_suite7/switch/switch_in_defer_macro.c3t new file mode 100644 index 000000000..0ed5f27bf --- /dev/null +++ b/test/test_suite7/switch/switch_in_defer_macro.c3t @@ -0,0 +1,838 @@ +// #target: macos-x64 + +<* + @require Token.kindof == ENUM && $typefrom(Token.inner).kindof == UNSIGNED_INT + @require $defined((Token){}.token) + @require $defined((Comment){}.start) && $defined((Comment){}.end) + *> +module lexer {Token, Comment}; +import std::io; +import trie; + +enum Kind : char +{ + UNKNOWN, + UINT, + STRING, + RUNE, + TOKEN, + IDENTIFIER, +} + +fault LexerError +{ + UNTERMINATED_STRING, + UNTERMINATED_RUNE, + UNTERMINATED_COMMENT, +} + +def TokenTrie = Trie{Token, ushort}; + +def Ident = fn bool (usz index, char c); + +struct Lexer +{ + Allocator allocator; + InStream reader; + char[] buf; + TokenTrie tokens; + Ident ident; + bool peeked; + Kind kind; + uint line; + uint column; + uint span; + union + { + ulong x; // UINT + String string; // STRING, IDENTIFIER + char rune; // RUNE + Token token; // TOKEN + } +} + +fn void! Lexer.init(&self, InStream reader, Ident ident, Allocator using = mem) +{ + TokenTrie trie; + ushort max_token; + foreach (i, tok : Token.values) + { + String name = tok.token; + assert(name.len > 0 && name.len <= ushort.max); + trie.set(name, Token.from_ordinal(i))!; + max_token = max(max_token, (ushort)name.len); + } + foreach (tok : Comment.values) + { + String end = tok.end; + assert(end.len > 0 && end.len <= ushort.max); + max_token = max(max_token, (ushort)end.len); + } + char* buf = allocator::malloc_try(using, max_token)!; + *self = { .allocator = using, .reader = reader, .buf = buf[:max_token], .tokens = trie }; +} + +fn void! Lexer.free(&self) +{ + allocator::free(self.allocator, self.buf); + *self = {}; +} + +fn Kind! Lexer.next(&self) +{ + if (self.peeked) + { + self.peeked = false; + return self.kind; + } + char c = self.reader.read_byte()!; + switch + { + case c.is_digit(): + self.reader.pushback_byte()!!; + self.x = self.parse_uint()!; + return UINT; + case c == '"': + self.string = self.parse_string(c)!; + return STRING; + case c == '\'': + self.rune = self.parse_rune()!; + return RUNE; + } + if (try tok = self.parse_token()) + { + foreach (comment : Comment.values) + { + if (comment.start == tok) + { + self.parse_comment(comment.end)!; + break; + } + } + self.token = tok; + return TOKEN; + } + if (try tok = self.parse_ident()) + { + self.string = tok; + return IDENTIFIER; + } + + return UNKNOWN; +} + +fn Kind! Lexer.peek(&self) +{ + if (!self.peeked) + { + self.kind = self.next()!; + self.peeked = true; + } + return self.kind; +} + +fn Token! Lexer.expect(&self, anyfault err, Token... tokens) +{ + Kind kind = self.next()!; + if (kind == TOKEN) + { + foreach (tok : tokens) + { + if (tok == self.token) return tok; + } + } + return err?; +} + +fn void! Lexer.skip_whitespace(&self) @private +{ + self.span = 0; + while (true) + { + char c = self.reader.read_byte()!; + if (!c.is_space()) + { + self.reader.pushback_byte()!!; + return; + } + if (c == '\n') + { + self.line++; + self.column = 0; + } + else + { + self.column++; + } + } +} + +fn ulong! Lexer.parse_uint(&self) @private +{ + ulong x; + char c = self.reader.read_byte()!; + if (c == '0') + { + c = self.reader.read_byte()!; + switch (c) + { + case 'x': + self.span = 2; + return self.parse_hexadecimal()!; + case 'b': + self.span = 2; + return self.parse_binary()!; + case 'o': + self.span = 2; + return self.parse_octal()!; + } + } + self.span = 0; + return self.parse_decimal()!; +} + +fn ulong! Lexer.parse_decimal(&self) @private +{ + return @parse_uint(self, ulong; ulong x, char c, bool ok) + { + if (c.is_digit()) + { + x = x * 10 + (ulong)(c - '0'); + ok = true; + } + }; +} + +fn ulong! Lexer.parse_hexadecimal(&self) @private +{ + return @parse_uint(self, ulong; ulong x, char c, bool ok) + { + switch + { + case c.is_digit(): + x = x * 10 + (ulong)(c - '0'); + ok = true; + case c.is_xdigit(): + c -= c < 'A' ? 'a' : 'A'; + x = x * 16 + (ulong)c; + ok = true; + } + }; +} + +fn ulong! Lexer.parse_binary(&self) @private +{ + return @parse_uint(self, ulong; ulong x, char c, bool ok) + { + if (c.is_digit()) + { + x = x * 2 + (ulong)(c - '0'); + ok = true; + } + }; +} + +fn ulong! Lexer.parse_octal(&self) @private +{ + return @parse_uint(self, ulong; ulong x, char c, bool ok) + { + if (c.is_odigit()) + { + x = x * 8 + (ulong)(c - '0'); + ok = true; + } + }; +} + +macro @parse_uint(self, $Type; @body(x, c, ok)) @private +{ + $Type x; + uint column = self.column; + while (true) + { + char! c = self.reader.read_byte(); + if (catch err = c) + { + case IoError.EOF: + break; + default: + return err?; + } + else + { + self.column++; + if (c == '_') continue; + $Type xx = x; + bool ok; + @body(x, c, ok); + if (xx > x) return NumberConversion.INTEGER_OVERFLOW?; + if (!ok) + { + self.column--; + self.reader.pushback_byte()!!; + break; + } + } + } + self.span = self.column - column; + return x; +} + +fn String! Lexer.parse_string(&self, char quote) @private +{ + char c = self.read_char_for_string()!; + if (c == quote) return ""; + DString str; + str.new_init(8, self.allocator); + char prev; + while (true) + { + c = self.read_char_for_string()!; + if (prev != '\\') + { + str.append_char(prev); + if (c == quote) + { + self.span = (uint)str.len(); + self.column += self.span + 2; + return str.str_view(); + } + prev = c; + continue; + } + prev = c; + switch (c) + { + case 'a': + case 'b': + case '\\': + case '\n': + case '\f': + case '\r': + case '\v': + case '"': + case '\'': + break; + default: c = '\\'; + } + str.append_char(c); + } +} + +fn char! Lexer.parse_rune(&self) @private +{ + char x = self.reader.read_byte()!; + char c = self.reader.read_byte()!; + if (c != '\'') return LexerError.UNTERMINATED_RUNE?; + return x; +} + +macro char! Lexer.read_char_for_string(&self) @private +{ + char! c = self.reader.read_byte(); + if (catch err = c) + { + case IoError.EOF: + return LexerError.UNTERMINATED_STRING?; + default: + return err?; + } + return c; +} + +fn Token! Lexer.parse_token(&self) @private +{ + usz n = self.reader.read(self.buf)!; + defer self.unread(n); + Token tok = self.tokens.get_best(self.buf[:n])!; + n = self.buf.len - tok.token.len; + return tok; +} + +fn void! Lexer.parse_comment(&self, String end) @private +{ + // Find the end token and accumulate the data in between. + DString acc; + acc.new_init(8, self.allocator); + char[] buf = self.buf[:end.len]; + while (true) + { + if (catch err = io::read_all(self.reader, buf)) + { + case IoError.UNEXPECTED_EOF: + case IoError.EOF: + return LexerError.UNTERMINATED_COMMENT?; + default: + return err?; + } + if (end == (String)buf) + { + self.string = acc.str_view(); + return; + } + acc.append_char(buf[0]); + self.unread(buf.len - 1); + } +} + +macro Lexer.unread(self, n) @private +{ + switch + { + case n == 1: + self.reader.pushback_byte()!!; + case n > 1: + if (&self.reader.seek) + { + self.reader.seek(-n, CURSOR)!!; + break; + } + for (; n > 0; n--) self.reader.pushback_byte()!!; + } +} + +fn String! Lexer.parse_ident(&self) @private +{ + DString str; + str.new_init(8, self.allocator); + while (true) + { + char! c = self.reader.read_byte(); + if (catch err = c) + { + case IoError.EOF: + return str.str_view(); + default: + return err?; + } + if (!self.ident(str.len(), c)) return str.str_view(); + str.append_char(c); + } +} + +module lexer_test; +import lexer; +import std::io; + +def Lexer = Lexer{Token, Comment}; +def Kind = Kind{Token, Comment}; + +enum Token : char (String token) +{ + KEYWORD1 = "keword1", + KEYWORD2 = "keyword2", + SINGLE = "//", + MULTI = "/*", +} + +enum Comment : char (Token start, String end) +{ + SINGLE = { SINGLE, "\n" }, + MULTI = { MULTI, "*/" }, +} + +fn bool is_ident_char(usz i, char c) +{ + return (i == 0 && c.is_alpha()) || (i > 0 && c.is_alnum()); +} + +struct UintTest +{ + String in; + ulong out; +} + +fn void! lex_uint() +{ + UintTest[] tcases = {}; + foreach (tc : tcases) + { + ByteReader br; + Lexer lex; + lex.init(br.init((char[])tc.in), &is_ident_char)!; + + Kind kind = lex.next()!; + assert(kind == UINT, "got %s; want %s", kind, Kind.UINT); + } +} +module lexer2; +import std::io; + +fn int main(String[] args) +{ + io::printn("Hello, World!"); + return 0; +} +<* + @require Index.kindof == TypeKind.UNSIGNED_INT + *> +module trie{Value, Index}; +import std::collections::list; +import trie::bitmap; + +def TrieNodeList = List{TrieNode}; +def TriePath = List{Index} @private; + +fault TrieError +{ + TRIE_FULL, +} + +struct Trie +{ + TrieNodeList nodes; +} + +struct TrieNode +{ + Index[256] children; + Value value; + bool valid; +} + +fn void Trie.init(&self, usz initial_capacity = 8, Allocator using = allocator::heap()) +{ + *self = {}; + self.nodes.init(using, initial_capacity); + self.nodes.push((TrieNode){}); +} + +<* + @require self.nodes.len() > 0 + *> +fn Value! Trie.get(&self, char[] key) +{ + return self.nodes[0].get(self, key); +} + +<* + @require self.nodes.len() > 0 + *> +fn Value! Trie.get_best(&self, char[] key) +{ + TrieNode* root = &self.nodes[0]; + if (key.len == 0) return root.valid ? root.value : SearchResult.MISSING?; + return root.get_best(self, key, 0); +} + +<* + @require self.nodes.len() > 0 + *> +fn void! Trie.set(&self, char[] key, Value value) +{ + self.nodes[0].set(self, key, value)!!; +} + +<* + @require self.nodes.len() > 0 + *> +fn void! Trie.del(&self, char[] key) +{ + if (key.len == 0) + { + Value zero; + (&self.nodes[0]).valid = false; + return; + } + TriePath path; + path.init(self.nodes.allocator, 8); + defer path.free(); + path.push(0); + self.nodes[0].del(self, key, path)!; +} + +fn Value! TrieNode.get(&self, Trie *t, char[] key) @private +{ + if (key.len == 0) return self.valid ? self.value : SearchResult.MISSING?; + char c = key[0]; + Index idx = self.children[c]; + if (idx == 0) return SearchResult.MISSING?; + return t.nodes[idx].get(t, key[1..]); +} + +fn Value! TrieNode.get_best(&self, Trie *t, char[] key, Index result) @private +{ + if (key.len == 0) + { + if (result == 0) return SearchResult.MISSING?; + return t.nodes[result].value; + } + char c = key[0]; + Index idx = self.children[c]; + if (idx == 0) + { + if (result == 0) return SearchResult.MISSING?; + return t.nodes[result].value; + } + TrieNode* next = &t.nodes[idx]; + if (next.valid) result = idx; + return next.get_best(t, key[1..], result); +} + +fn void! TrieNode.set(&self, Trie *t, char[] key, Value value) @private +{ + if (key.len == 0) + { + self.value = value; + self.valid = true; + return; + } + char c = key[0]; + Index idx = self.children[c]; + if (idx == 0) + { + usz new_idx = t.nodes.len(); + assert(new_idx != 0); + if (new_idx > Index.max) return TrieError.TRIE_FULL?; + idx = (Index)new_idx; + self.children[c] = idx; + t.nodes.push((TrieNode){}); + } + t.nodes[idx].set(t, key[1..], value)!; +} + +fn void! TrieNode.del(&self, Trie* t, char[] key, TriePath path) @private +{ + if (key.len > 0) + { + char c = key[0]; + Index idx = self.children[c]; + if (idx != 0) + { + path.push(idx); + t.nodes[idx].del(t, key[1..], path)!; + } + return; + } + Index current = path.pop()!; + for (isz i = path.len() - 1; i >= 0; i--) + { + Index parent = path[i]; + bool is_empty = true; + TrieNode* node = &t.nodes[parent]; + foreach (j, p : node.children) + { + if (p == current) + { + node.children[j] = 0; + (&t.nodes[p]).valid = false; + } + is_empty = is_empty && node.children[j] == 0; + } + if (!is_empty) break; + } +} + +module trie::bitmap @private; + +struct Bitmap +{ + ulong[4] data; +} + +fn bool Bitmap.get(&self, char x) +{ + char i = x & 0b11; + char j = 1 << (x >> 2); + return self.data[i] & j != 0; +} + +fn void Bitmap.set(&self, char x) +{ + char i = x & 0b11; + char j = 1 << (x >> 2); + self.data[i] |= j; +} + +fn bool Bitmap.is_empty(&self) +{ + return self.data[0] == 0 && self.data[1] == 0 && self.data[2] == 0 && self.data[3] == 0; +} +module trie_test; +import trie; + +def Trie = Trie{String, char}; + +fn void test() +{ + Trie t; + t.init(); + String! v = t.get("a"); + if (try v) unreachable("key 'a' should not exist"); + if (catch t.set("a", "va")) unreachable("key 'a' not added"); + String w = t.get("a")!!; + assert(w == "va"); + + if (catch t.set("hello world", "hi")) unreachable("key not added"); + w = t.get("hello world")!!; + assert(w == "hi"); + if (try invalid = t.get("hello")) unreachable("key 'hello' should not exist"); + + if (catch t.set("hello", "hoi")) unreachable("key not added"); + String ww = t.get("hello")!!; + assert(ww == "hoi"); + ww = t.get_best("hello world")!!; + assert(ww == "hi"); + + t.del("a")!!; + String! x = t.get("a"); + if (try x) unreachable("key 'a' should not exist"); +} + +/* #expect: lexer_test.ll + +%.introspect = type { i8, i64, ptr, i64, i64, i64, [0 x i64] } +%"char[]" = type { ptr, i64 } +%any = type { ptr, i64 } +%"UintTest[]" = type { ptr, i64 } +%UintTest = type { %"char[]", i64 } +%ByteReader = type { %"char[]", i64 } +%Lexer = type { %any, %any, %"char[]", %Trie, ptr, i8, i8, i32, i32, i32, %.anon } +%Trie = type { %List } +%List = type { i64, i64, %any, ptr } +%.anon = type { %"char[]" } + +@"$ct.lexer_test.UintTest" = linkonce global %.introspect { i8 10, i64 0, ptr null, i64 24, i64 0, i64 2, [0 x i64] zeroinitializer }, align 8 +@.enum.KEYWORD1 = internal constant [9 x i8] c"KEYWORD1\00", align 1 +@.enum.KEYWORD2 = internal constant [9 x i8] c"KEYWORD2\00", align 1 +@.enum.SINGLE = internal constant [7 x i8] c"SINGLE\00", align 1 +@.enum.MULTI = internal constant [6 x i8] c"MULTI\00", align 1 +@"$ct.char" = linkonce global %.introspect { i8 3, i64 0, ptr null, i64 1, i64 0, i64 0, [0 x i64] zeroinitializer }, align 8 +@"$ct.lexer_test.Token" = linkonce global { i8, i64, ptr, i64, i64, i64, [4 x %"char[]"] } { i8 8, i64 0, ptr null, i64 1, i64 ptrtoint (ptr @"$ct.char" to i64), i64 4, [4 x %"char[]"] [%"char[]" { ptr @.enum.KEYWORD1, i64 8 }, %"char[]" { ptr @.enum.KEYWORD2, i64 8 }, %"char[]" { ptr @.enum.SINGLE, i64 6 }, %"char[]" { ptr @.enum.MULTI, i64 5 }] }, align 8 +@.str = private unnamed_addr constant [8 x i8] c"keword1\00", align 1 +@.str.1 = private unnamed_addr constant [9 x i8] c"keyword2\00", align 1 +@.str.2 = private unnamed_addr constant [3 x i8] c"//\00", align 1 +@.str.3 = private unnamed_addr constant [3 x i8] c"/*\00", align 1 +@"lexer_test.Token$token" = linkonce constant [4 x %"char[]"] [%"char[]" { ptr @.str, i64 7 }, %"char[]" { ptr @.str.1, i64 8 }, %"char[]" { ptr @.str.2, i64 2 }, %"char[]" { ptr @.str.3, i64 2 }], align 8 +@"$ct.lexer_test.Comment" = linkonce global { i8, i64, ptr, i64, i64, i64, [2 x %"char[]"] } { i8 8, i64 0, ptr null, i64 1, i64 ptrtoint (ptr @"$ct.char" to i64), i64 2, [2 x %"char[]"] [%"char[]" { ptr @.enum.SINGLE, i64 6 }, %"char[]" { ptr @.enum.MULTI, i64 5 }] }, align 8 +@"lexer_test.Comment$start" = linkonce constant [2 x i8] c"\02\03", align 1 +@.str.4 = private unnamed_addr constant [2 x i8] c"\0A\00", align 1 +@.str.5 = private unnamed_addr constant [3 x i8] c"*/\00", align 1 +@"lexer_test.Comment$end" = linkonce constant [2 x %"char[]"] [%"char[]" { ptr @.str.4, i64 1 }, %"char[]" { ptr @.str.5, i64 2 }], align 8 +@"$ct.std.io.ByteReader" = linkonce global %.introspect { i8 10, i64 0, ptr null, i64 24, i64 0, i64 2, [0 x i64] zeroinitializer }, align 8 +@std.core.mem.allocator.thread_allocator = extern_weak thread_local global %any, align 8 + +; Function Attrs: +define zeroext i8 @lexer_test.is_ident_char(i64 %0, i8 zeroext %1) #0 { +entry: + %eq = icmp eq i64 0, %0 + br i1 %eq, label %and.rhs, label %and.phi + +and.rhs: ; preds = %entry + %2 = call i8 @std.ascii.char.is_alpha(i8 zeroext %1) + %3 = trunc i8 %2 to i1 + br label %and.phi + +and.phi: ; preds = %and.rhs, %entry + %val = phi i1 [ false, %entry ], [ %3, %and.rhs ] + br i1 %val, label %or.phi, label %or.rhs + +or.rhs: ; preds = %and.phi + %lt = icmp ult i64 0, %0 + br i1 %lt, label %and.rhs1, label %and.phi2 + +and.rhs1: ; preds = %or.rhs + %4 = call i8 @std.ascii.char.is_alnum(i8 zeroext %1) + %5 = trunc i8 %4 to i1 + br label %and.phi2 + +and.phi2: ; preds = %and.rhs1, %or.rhs + %val3 = phi i1 [ false, %or.rhs ], [ %5, %and.rhs1 ] + br label %or.phi + +or.phi: ; preds = %and.phi2, %and.phi + %val4 = phi i1 [ true, %and.phi ], [ %val3, %and.phi2 ] + %6 = zext i1 %val4 to i8 + ret i8 %6 +} + +; Function Attrs: +define i64 @lexer_test.lex_uint() #0 { +entry: + %tcases = alloca %"UintTest[]", align 8 + %.anon = alloca i64, align 8 + %tc = alloca %UintTest, align 8 + %br = alloca %ByteReader, align 8 + %lex = alloca %Lexer, align 8 + %error_var = alloca i64, align 8 + %taddr = alloca %any, align 8 + %kind = alloca i8, align 1 + %error_var7 = alloca i64, align 8 + %retparam = alloca i8, align 1 + store %"UintTest[]" zeroinitializer, ptr %tcases, align 8 + %ptradd = getelementptr inbounds i8, ptr %tcases, i64 8 + %0 = load i64, ptr %ptradd, align 8 + store i64 0, ptr %.anon, align 8 + br label %loop.cond + +loop.cond: ; preds = %noerr_block12, %entry + %1 = load i64, ptr %.anon, align 8 + %lt = icmp ult i64 %1, %0 + br i1 %lt, label %loop.body, label %loop.exit + +loop.body: ; preds = %loop.cond + %2 = load ptr, ptr %tcases, align 8 + %3 = load i64, ptr %.anon, align 8 + %ptroffset = getelementptr inbounds [24 x i8], ptr %2, i64 %3 + call void @llvm.memcpy.p0.p0.i32(ptr align 8 %tc, ptr align 8 %ptroffset, i32 24, i1 false) + call void @llvm.memset.p0.i64(ptr align 8 %br, i8 0, i64 24, i1 false) + call void @llvm.memset.p0.i64(ptr align 8 %lex, i8 0, i64 128, i1 false) + %lo = load ptr, ptr %tc, align 8 + %ptradd1 = getelementptr inbounds i8, ptr %tc, i64 8 + %hi = load i64, ptr %ptradd1, align 8 + %4 = call ptr @std.io.ByteReader.init(ptr %br, ptr %lo, i64 %hi) + %5 = insertvalue %any undef, ptr %4, 0 + %6 = insertvalue %any %5, i64 ptrtoint (ptr @"$ct.std.io.ByteReader" to i64), 1 + store %any %6, ptr %taddr, align 8 + %lo2 = load i64, ptr %taddr, align 8 + %ptradd3 = getelementptr inbounds i8, ptr %taddr, i64 8 + %hi4 = load ptr, ptr %ptradd3, align 8 + %lo5 = load i64, ptr @std.core.mem.allocator.thread_allocator, align 8 + %hi6 = load ptr, ptr getelementptr inbounds (i8, ptr @std.core.mem.allocator.thread_allocator, i64 8), align 8 + %7 = call i64 @"lexer$lexer_test.Token$lexer_test.Comment$.Lexer.init"(ptr %lex, i64 %lo2, ptr %hi4, ptr @lexer_test.is_ident_char, i64 %lo5, ptr %hi6) + %not_err = icmp eq i64 %7, 0 + %8 = call i1 @llvm.expect.i1(i1 %not_err, i1 true) + br i1 %8, label %after_check, label %assign_optional + +assign_optional: ; preds = %loop.body + store i64 %7, ptr %error_var, align 8 + br label %guard_block + +after_check: ; preds = %loop.body + br label %noerr_block + +guard_block: ; preds = %assign_optional + %9 = load i64, ptr %error_var, align 8 + ret i64 %9 + +noerr_block: ; preds = %after_check + %10 = call i64 @"lexer$lexer_test.Token$lexer_test.Comment$.Lexer.next"(ptr %retparam, ptr %lex) + %not_err8 = icmp eq i64 %10, 0 + %11 = call i1 @llvm.expect.i1(i1 %not_err8, i1 true) + br i1 %11, label %after_check10, label %assign_optional9 + +assign_optional9: ; preds = %noerr_block + store i64 %10, ptr %error_var7, align 8 + br label %guard_block11 + +after_check10: ; preds = %noerr_block + br label %noerr_block12 + +guard_block11: ; preds = %assign_optional9 + %12 = load i64, ptr %error_var7, align 8 + ret i64 %12 + +noerr_block12: ; preds = %after_check10 + %13 = load i8, ptr %retparam, align 1 + store i8 %13, ptr %kind, align 1 + %14 = load i8, ptr %kind, align 1 + %eq = icmp eq i8 %14, 1 + call void @llvm.assume(i1 %eq) + %15 = load i64, ptr %.anon, align 8 + %addnuw = add nuw i64 %15, 1 + store i64 %addnuw, ptr %.anon, align 8 + br label %loop.cond + +loop.exit: ; preds = %loop.cond + ret i64 0 +} diff --git a/test/test_suite7/symbols/allow_local_shadowing.c3 b/test/test_suite7/symbols/allow_local_shadowing.c3 new file mode 100644 index 000000000..802eaf090 --- /dev/null +++ b/test/test_suite7/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_suite7/symbols/shadow_struct.c3 b/test/test_suite7/symbols/shadow_struct.c3 new file mode 100644 index 000000000..a9cb4b10b --- /dev/null +++ b/test/test_suite7/symbols/shadow_struct.c3 @@ -0,0 +1,15 @@ +struct Foo +{ + Foo *x; + int y; +} + +def Foo = float; // #error: shadow a previous declaration + +enum Bar +{ + TEST1, + TEST2 +} + +def Bar = float; // #error: shadow a previous declaration \ No newline at end of file diff --git a/test/test_suite7/symbols/various.c3 b/test/test_suite7/symbols/various.c3 new file mode 100644 index 000000000..1218be130 --- /dev/null +++ b/test/test_suite7/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: '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]; +} + +def Number = int; + +fn void test8() +{ + Number a = 10; + ichar c = a; // #error: 'Number' (int) +} + + +fn void test9() +{ + const char A = 1; + char b = A; + A = b; // #error: You cannot assign to a constant +} + +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; // #error: It is not possible to cast + ichar b = Enum.B; // #error: It is not possible to cast +} + +fn void test12() +{ + float f = 3.14; + ichar a = f; // #error: 'ichar' +} + +fn void test13() +{ + int a = 1; + ichar b = a; // #error: '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: 'ichar' + int g = 1 ? i : f; // #error: 'float' + int a = f ? 1 : 0; +} + +fn void test17() +{ + int a = "test"; // #error: 'String' to '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' to 'ichar' + short b = foo(); // #error: 'void' to 'short' + int c = foo(); // #error: 'void' to 'int' + long d = foo(); // #error: 'void' to 'long' + char e = foo(); // #error: 'void' to 'char' + ushort f = foo(); // #error: 'void' to 'ushort' + uint g = foo(); // #error: 'void' to 'uint' + ulong h = foo(); // #error: 'void' to 'ulong' + bool i = foo(); // #error: 'void' to 'bool' +} + + +int num = 10; + +fn void test23() +{ + int a = num; + int b = test::num; + char c = test::num; // #error: 'char' +} + +int[2][3] b123; + +fn void test24() +{ + int a = b123; // #error: 'int[2][3]' to 'int' +} + + + diff --git a/test/test_suite7/types/enum_illegal_type.c3 b/test/test_suite7/types/enum_illegal_type.c3 new file mode 100644 index 000000000..0c2a2610a --- /dev/null +++ b/test/test_suite7/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_suite7/types/enum_implicit_overflow.c3 b/test/test_suite7/types/enum_implicit_overflow.c3 new file mode 100644 index 000000000..aa64a25ae --- /dev/null +++ b/test/test_suite7/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_suite7/types/enum_inference.c3 b/test/test_suite7/types/enum_inference.c3 new file mode 100644 index 000000000..880e1b90d --- /dev/null +++ b/test/test_suite7/types/enum_inference.c3 @@ -0,0 +1,43 @@ + +enum Inf +{ + A, + B, + C +} + +enum Inf2 : char +{ + A, + B, + C, +} + +def 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 == Inf2.from_ordinal(1)) return; + z = Inf2.from_ordinal(2); + switch (z) + { + case Inf2.A: + x1++; + return; + case B: + return; + case Inf2.from_ordinal(2): + x1 += 1; + return; + default: + return; + } +} \ No newline at end of file diff --git a/test/test_suite7/types/enum_ok.c3 b/test/test_suite7/types/enum_ok.c3 new file mode 100644 index 000000000..c75c8c005 --- /dev/null +++ b/test/test_suite7/types/enum_ok.c3 @@ -0,0 +1,35 @@ +enum EnumTest : long +{ + VALUE1, + VALUE2 +} + +def Frob = long; + +enum EnumTestAlias : Frob +{ + VALUE1, + VALUE2 +} + +enum EnumTestDefault +{ + VALUE, + VALUE2 +} + + +enum EnumWithErrorData2 : int (int bar,) +{ + TEST // #error: associated value +} + +enum EnumTestErrorType4 +{ +} + +enum EnumTest5 +{ + B, + C, +} \ No newline at end of file diff --git a/test/test_suite7/types/enum_param.c3 b/test/test_suite7/types/enum_param.c3 new file mode 100644 index 000000000..f369a64ed --- /dev/null +++ b/test/test_suite7/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_suite7/types/enum_parse_errors.c3 b/test/test_suite7/types/enum_parse_errors.c3 new file mode 100644 index 000000000..2284bfd6c --- /dev/null +++ b/test/test_suite7/types/enum_parse_errors.c3 @@ -0,0 +1,22 @@ + +enum EnumWithErrorWithMissingName : (int) // #error: Expected a member name here +{ + TEST +} + +enum EnumWithErrorData : ( int +,{ // #error: Expected a member name here + TEST +} + +enum EnumWithErrorData2 : ( int, int bar ) // #error: Expected a member name here +{ + TEST +} + + +enum EnumTestErrorType3 : int +{ + A, + A // #error: This enum constant is declared twice +} \ No newline at end of file diff --git a/test/test_suite7/types/illegal_array_size_constant.c3 b/test/test_suite7/types/illegal_array_size_constant.c3 new file mode 100644 index 000000000..d4785c7ad --- /dev/null +++ b/test/test_suite7/types/illegal_array_size_constant.c3 @@ -0,0 +1,12 @@ +module testing; + +struct Foo +{ + Entry[1 << N] data; // #error: 'N' could not be found +} + +struct Entry +{ + String key; + String value; +} \ No newline at end of file diff --git a/test/test_suite7/types/non_rec_fn.c3 b/test/test_suite7/types/non_rec_fn.c3 new file mode 100644 index 000000000..8e65c8a12 --- /dev/null +++ b/test/test_suite7/types/non_rec_fn.c3 @@ -0,0 +1,11 @@ + +def BlahFn = fn int(Foo f); +def FooFn = fn int(Foo f, int j); +struct Foo +{ + BlahFn x; + FooFn okf; +} + + +Foo g; \ No newline at end of file diff --git a/test/test_suite7/types/recursive_array.c3 b/test/test_suite7/types/recursive_array.c3 new file mode 100644 index 000000000..199a6c013 --- /dev/null +++ b/test/test_suite7/types/recursive_array.c3 @@ -0,0 +1,4 @@ +struct Qq +{ + Qq[3]* a; +} \ No newline at end of file diff --git a/test/test_suite7/types/recursive_fn.c3 b/test/test_suite7/types/recursive_fn.c3 new file mode 100644 index 000000000..9e2bb1b17 --- /dev/null +++ b/test/test_suite7/types/recursive_fn.c3 @@ -0,0 +1 @@ +def BlahFn = fn int(BlahFn f); // #error: Recursive definition of 'BlahFn' \ No newline at end of file diff --git a/test/test_suite7/types/recursive_typedef.c3 b/test/test_suite7/types/recursive_typedef.c3 new file mode 100644 index 000000000..07ee1ab76 --- /dev/null +++ b/test/test_suite7/types/recursive_typedef.c3 @@ -0,0 +1,9 @@ +def Number2 = Number1; // #error: Recursive definition of 'Number2' +def Number1 = Number2; + +def Number = Number; // #error: Recursive definition of 'Number' + + +def Loop2 = Loop; // #error: Recursive definition of 'Loop2' +def Loop3 = Loop2; +def Loop = Loop3; diff --git a/test/test_suite7/types/redefinition.c3 b/test/test_suite7/types/redefinition.c3 new file mode 100644 index 000000000..b17fe2247 --- /dev/null +++ b/test/test_suite7/types/redefinition.c3 @@ -0,0 +1,2 @@ +def Number = int; +def Number = uint; // #error: 'Number' would shadow a previous declaration. \ No newline at end of file diff --git a/test/test_suite7/types/typedefs.c3 b/test/test_suite7/types/typedefs.c3 new file mode 100644 index 000000000..8e293f9bb --- /dev/null +++ b/test/test_suite7/types/typedefs.c3 @@ -0,0 +1,11 @@ +def 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]) to 'int' + int d = a; // #error: 'Arr' (int[4]) to 'int' +} + diff --git a/test/test_suite7/types/various.c3 b/test/test_suite7/types/various.c3 new file mode 100644 index 000000000..00026afe8 --- /dev/null +++ b/test/test_suite7/types/various.c3 @@ -0,0 +1,5 @@ +func1 a = 1; // #error: The name of a type + +fn void func1() {} + +uint b = -1; \ No newline at end of file diff --git a/test/test_suite7/unicode/commenting-out.c3 b/test/test_suite7/unicode/commenting-out.c3 new file mode 100644 index 000000000..2c9a908db --- /dev/null +++ b/test/test_suite7/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_suite7/union/designated_union_zeroing.c3t b/test/test_suite7/union/designated_union_zeroing.c3t new file mode 100644 index 000000000..1b3fdf78b --- /dev/null +++ b/test/test_suite7/union/designated_union_zeroing.c3t @@ -0,0 +1,33 @@ +// #target: macos-x64 +module test; +union Rect { + struct { float[<2>] min, max; } +} + +fn Rect test_rect(float[<2>] max) { + Rect rect = {.max = max}; + assert(rect.min == {}); + return rect; +} + +/* #expect: test.ll + +%Rect = type { %.anon } +%.anon = type { <2 x float>, <2 x float> } + +define { double, double } @test.test_rect(double %0) #0 { +entry: + %max = alloca <2 x float>, align 8 + %rect = alloca %Rect, align 8 + store double %0, ptr %max, align 8 + call void @llvm.memset.p0.i64(ptr align 8 %rect, i8 0, i64 16, i1 false) + %ptradd = getelementptr inbounds i8, ptr %rect, i64 8 + %1 = load <2 x float>, ptr %max, align 8 + store <2 x float> %1, ptr %ptradd, align 8 + %2 = load <2 x float>, ptr %rect, align 8 + %eq = fcmp oeq <2 x float> %2, zeroinitializer + %3 = call i1 @llvm.vector.reduce.and.v2i1(<2 x i1> %eq) + call void @llvm.assume(i1 %3) + %4 = load { double, double }, ptr %rect, align 8 + ret { double, double } %4 +} diff --git a/test/test_suite7/union/flexible_array_union.c3 b/test/test_suite7/union/flexible_array_union.c3 new file mode 100644 index 000000000..1cb6e05a9 --- /dev/null +++ b/test/test_suite7/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_suite7/union/inferred_size_vector.c3 b/test/test_suite7/union/inferred_size_vector.c3 new file mode 100644 index 000000000..2adce22bd --- /dev/null +++ b/test/test_suite7/union/inferred_size_vector.c3 @@ -0,0 +1,4 @@ +union Foo +{ + int[] x; // #error: Inferred vector types can only +} diff --git a/test/test_suite7/union/test_unions.c3 b/test/test_suite7/union/test_unions.c3 new file mode 100644 index 000000000..8f465442b --- /dev/null +++ b/test/test_suite7/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_suite7/union/union_codegen_const.c3t b/test/test_suite7/union/union_codegen_const.c3t new file mode 100644 index 000000000..7aeb313ca --- /dev/null +++ b/test/test_suite7/union/union_codegen_const.c3t @@ -0,0 +1,20 @@ +// #target: macos-x64 +module test; + +union Foo +{ + int a; + double b; +} + +Foo f @private = { .a = 23 }; +Foo g @private = { .b = 2.3 }; +Foo h @private = { .a = 23, .b = 2.3 }; +Foo i = { .b = 2.3, .a = 23 }; + +/* #expect: test.ll + +@test.f = internal unnamed_addr global { i32, [4 x i8] } { i32 23, [4 x i8] undef }, align 8 +@test.g = internal unnamed_addr global %Foo { double 2.300000e+00 }, align 8 +@test.h = internal 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_suite7/union/union_codegen_empty.c3t b/test/test_suite7/union/union_codegen_empty.c3t new file mode 100644 index 000000000..9e86916b1 --- /dev/null +++ b/test/test_suite7/union/union_codegen_empty.c3t @@ -0,0 +1,45 @@ +// #target: macos-x64 +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_suite7/union/union_codegen_overwrite_call.c3t b/test/test_suite7/union/union_codegen_overwrite_call.c3t new file mode 100644 index 000000000..91ebc0ebb --- /dev/null +++ b/test/test_suite7/union/union_codegen_overwrite_call.c3t @@ -0,0 +1,30 @@ +// #target: macos-x64 +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_suite7/union/union_in_struct.c3t b/test/test_suite7/union/union_in_struct.c3t new file mode 100644 index 000000000..2380eb4b8 --- /dev/null +++ b/test/test_suite7/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_suite7/union/union_member_voidcast.c3 b/test/test_suite7/union/union_member_voidcast.c3 new file mode 100644 index 000000000..aeea25047 --- /dev/null +++ b/test/test_suite7/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_suite7/union/union_zero.c3 b/test/test_suite7/union/union_zero.c3 new file mode 100644 index 000000000..a56f039de --- /dev/null +++ b/test/test_suite7/union/union_zero.c3 @@ -0,0 +1,3 @@ +union Abs // #error: Zero sized unions +{ +} \ No newline at end of file diff --git a/test/test_suite7/variables/const_in_func.c3t b/test/test_suite7/variables/const_in_func.c3t new file mode 100644 index 000000000..fadc81f34 --- /dev/null +++ b/test/test_suite7/variables/const_in_func.c3t @@ -0,0 +1,19 @@ +// #target: linux-x64 +module scratch; +import std::test; +fn void main() +{ + int x = test::abc(); +} + +module std::test; + +macro abc() +{ + const int A = 256; + return A; +} + +/* #expect: scratch.ll + +@main.A = internal local_unnamed_addr constant i32 256, align 4 \ No newline at end of file diff --git a/test/test_suite7/variables/consts.c3 b/test/test_suite7/variables/consts.c3 new file mode 100644 index 000000000..a571906b7 --- /dev/null +++ b/test/test_suite7/variables/consts.c3 @@ -0,0 +1,7 @@ +const int foo = 3; // #error: must be all uppercase + +fn void foo(int i) +{ + const int x = i; // #error: must be all uppercase + const int Y = i; +} \ No newline at end of file diff --git a/test/test_suite7/variables/static_in_macro.c3t b/test/test_suite7/variables/static_in_macro.c3t new file mode 100644 index 000000000..7de212799 --- /dev/null +++ b/test/test_suite7/variables/static_in_macro.c3t @@ -0,0 +1,76 @@ +// #target: macos-x64 +module test; +import asdf; +import foo; +import std::io; + +fn int main(String[] args) { + bar(); + bar2(); + foo::bar(); + foo::bar2(); + return 0; +} + +fn void bar() { + asdf::get_static(); +} + +fn void* bar2() { + return asdf::get_static_ref(); +} + +module foo; +import asdf; +import std::io; + +// Same function name +fn void bar() { + asdf::get_static(); +} + +fn void* bar2() { + return asdf::get_static_ref(); +} + +module asdf; + +macro get_static() { + static char x; + return x; +} + +macro get_static_ref() { + static char x; + return &x; +} + +/* #expect: foo.ll + +@bar.x = internal local_unnamed_addr global i8 0, align 1 +@bar2.x = internal global i8 0, align 1 + +define void @foo.bar() #0 { +entry: + ret void +} + +define ptr @foo.bar2() #0 { +entry: + ret ptr @bar2.x +} + +// #expect: test.ll + +@bar.x = internal local_unnamed_addr global i8 0, align 1 +@bar2.x = internal global i8 0, align 1 + +define void @test.bar() #0 { +entry: + ret void +} + +define ptr @test.bar2() #0 { +entry: + ret ptr @bar2.x +} diff --git a/test/test_suite7/variables/var_init.c3t b/test/test_suite7/variables/var_init.c3t new file mode 100644 index 000000000..0e0b6dae9 --- /dev/null +++ b/test/test_suite7/variables/var_init.c3t @@ -0,0 +1,26 @@ +module test; + +struct Abc +{ + int[100] x; +} + + +fn void main() +{ + int z @noinit; + Abc y @noinit; + int x; + Abc w; +} + +/* #expect: test.ll + +entry: + %z = alloca i32, align 4 + %y = alloca %Abc, align 4 + %x = alloca i32, align 4 + %w = alloca %Abc, align 4 + store i32 0, ptr %x, align 4 + call void @llvm.memset.p0.i64(ptr align 4 %w, i8 0, i64 400, i1 false) + ret void diff --git a/test/test_suite7/variables/var_init_multi.c3t b/test/test_suite7/variables/var_init_multi.c3t new file mode 100644 index 000000000..595f5a311 --- /dev/null +++ b/test/test_suite7/variables/var_init_multi.c3t @@ -0,0 +1,28 @@ +// #target: macos-x64 +module test; +fn int main() +{ + static int sx, sy; + tlocal int tx, ty; + int x, y; + int* z, w @noinit @align(16); + return x; +} + +/* #expect: test.ll + +@main.sx = internal unnamed_addr global i32 0, align 4 +@main.sy = internal unnamed_addr global i32 0, align 4 +@main.tx = internal thread_local(localdynamic) unnamed_addr global i32 0, align 4 +@main.ty = internal thread_local(localdynamic) unnamed_addr global i32 0, align 4 + +entry: + %x = alloca i32, align 4 + %y = alloca i32, align 4 + %z = alloca ptr, align 16 + %w = alloca ptr, align 16 + store i32 0, ptr %x, align 4 + store i32 0, ptr %y, align 4 + %0 = load i32, ptr %x, align 4 + ret i32 %0 +} diff --git a/test/test_suite7/vector/gather_scatter.c3t b/test/test_suite7/vector/gather_scatter.c3t new file mode 100644 index 000000000..f4868ae16 --- /dev/null +++ b/test/test_suite7/vector/gather_scatter.c3t @@ -0,0 +1,30 @@ +// #target: macos-x64 +module foo; + +fn void main() +{ + int[5] a = { 1, 2, 3, 4, 5 }; + void*[<2>] x = { &a[0], &a[4] }; + int*[<2>] y = x; + int[<2>] result = mem::@gather_aligned(y, (bool[<2>]) { true, false }, (int[<2>]){ 10, 20 }, 4); + assert(result == { 1, 20}); + result = mem::gather(y, (bool[<2>]) { true, false }, (int[<2>]){ 10, 20 }); + assert(result == { 1, 20}); + mem::@scatter_aligned(y, (int[<2>]){ 66, 77 }, (bool[<2>]) { false, true } , 4); + assert(a == (int[5]){ 1, 2, 3, 4, 77}); + mem::scatter(y, (int[<2>]){ 88, 99 }, (bool[<2>]) { true, false }); + assert(a == (int[5]){ 88, 2, 3, 4, 77}); +} + +/* #expect: foo.ll + + %4 = load <2 x ptr>, ptr %ptrvec, align 16 + %5 = call <2 x i32> @llvm.masked.gather.v2i32.v2p0(<2 x ptr> %4, i32 4, <2 x i1> , <2 x i32> ) + + %9 = load <2 x ptr>, ptr %ptrvec1, align 16 + %10 = call <2 x i32> @llvm.masked.gather.v2i32.v2p0(<2 x ptr> %9, i32 4, <2 x i1> , <2 x i32> ) + + %14 = load <2 x ptr>, ptr %ptrvec3, align 16 + call void @llvm.masked.scatter.v2i32.v2p0(<2 x i32> , <2 x ptr> %14, i32 4, <2 x i1> ) + %16 = load <2 x ptr>, ptr %ptrvec5, align 16 + call void @llvm.masked.scatter.v2i32.v2p0(<2 x i32> , <2 x ptr> %16, i32 4, <2 x i1> ) diff --git a/test/test_suite7/vector/swizzle_vector_ref.c3t b/test/test_suite7/vector/swizzle_vector_ref.c3t new file mode 100644 index 000000000..f8c9f5fc4 --- /dev/null +++ b/test/test_suite7/vector/swizzle_vector_ref.c3t @@ -0,0 +1,27 @@ +// #target: macos-x64 +module foo; + +import std; +fn int main() +{ + int[<2>] vec; + int* a = &vec.x; + *a = 1; + assert(vec.x == 1); + return 0; +} + +/* #expect: foo.ll + + %vec = alloca <2 x i32>, align 8 + %a = alloca ptr, align 8 + store <2 x i32> zeroinitializer, ptr %vec, align 8 + store ptr %vec, ptr %a, align 8 + %0 = load ptr, ptr %a, align 8 + store i32 1, ptr %0, align 4 + %1 = load <2 x i32>, ptr %vec, align 8 + %2 = extractelement <2 x i32> %1, i64 0 + %eq = icmp eq i32 %2, 1 + call void @llvm.assume(i1 %eq) + ret i32 0 +} diff --git a/test/test_suite7/vector/swizzling.c3 b/test/test_suite7/vector/swizzling.c3 new file mode 100644 index 000000000..e7b4c72b4 --- /dev/null +++ b/test/test_suite7/vector/swizzling.c3 @@ -0,0 +1,22 @@ +// #target: macos-x64 + +fn void! swizzle_test() +{ + int[<4>] abc = { 1, 2, 3, 4 }; + int[<3>] z = abc.rbx; // #error: Mixing + int[<2>] gh; + int[<2>] uh = gh.xz; // #error: component is not present + +} + + + +fn int main() +{ + int[<2>] $test = {3, 3}; + int[<2>] $test2 = {4, 4}; + $if ($test2.x != $test.x): + y++; // #error: did you spell it + $endif + return 0; +} \ No newline at end of file diff --git a/test/test_suite7/vector/vector_bit.c3t b/test/test_suite7/vector/vector_bit.c3t new file mode 100644 index 000000000..8a4e4577e --- /dev/null +++ b/test/test_suite7/vector/vector_bit.c3t @@ -0,0 +1,153 @@ +// #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 ueq <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 +} + + +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 + %neg = sub <4 x i32> zeroinitializer, %43 + store <4 x i32> %neg, ptr %w, align 16 + %44 = load <4 x i32>, ptr %w, align 16 + %45 = extractelement <4 x i32> %44, i64 0 + %46 = load <4 x i32>, ptr %w, align 16 + %47 = extractelement <4 x i32> %46, i64 1 + %48 = load <4 x i32>, ptr %w, align 16 + %49 = extractelement <4 x i32> %48, i64 2 + %50 = load <4 x i32>, ptr %w, align 16 + %51 = extractelement <4 x i32> %50, i64 3 + %52 = call i32 (ptr, ...) @printf(ptr @.str.5, i32 %45, i32 %47, i32 %49, i32 %51) + %53 = load <4 x i32>, ptr %y, align 16 + %not = icmp eq <4 x i32> %53, zeroinitializer + %54 = sext <4 x i1> %not to <4 x i32> + store <4 x i32> %54, ptr %w, align 16 + store <4 x i32> , ptr %w, align 16 + %55 = load <4 x i32>, ptr %w, align 16 + %not1 = icmp eq <4 x i32> %55, zeroinitializer + %56 = sext <4 x i1> %not1 to <4 x i32> + store <4 x i32> %56, ptr %w, align 16 + %57 = load <4 x i32>, ptr %w, align 16 + %58 = extractelement <4 x i32> %57, i64 0 + %59 = load <4 x i32>, ptr %w, align 16 + %60 = extractelement <4 x i32> %59, i64 1 + %61 = load <4 x i32>, ptr %w, align 16 + %62 = extractelement <4 x i32> %61, i64 2 + %63 = load <4 x i32>, ptr %w, align 16 + %64 = extractelement <4 x i32> %63, i64 3 + %65 = call i32 (ptr, ...) @printf(ptr @.str.6, i32 %58, i32 %60, i32 %62, i32 %64) + ret void +} diff --git a/test/test_suite7/vector/vector_consts.c3t b/test/test_suite7/vector/vector_consts.c3t new file mode 100644 index 000000000..1a2c76710 --- /dev/null +++ b/test/test_suite7/vector/vector_consts.c3t @@ -0,0 +1,43 @@ +// #target: macos-x64 +module foo; +import std::math; +fn int x(char[<8>] a, char[<8>] b) +{ + bool[<8>] z = a.comp_eq(b); + return ((char[<8>]) { [0..7] = 255 } & (char[<8>])z + ~(char[<8>])z & (char[<8>]) { 0, 1, 2, 3, 4, 5, 6, 7 }).min(); +} + +/* #expect: foo.ll + +define i32 @foo.x(double %0, double %1) #0 { +entry: + %a = alloca <8 x i8>, align 8 + %b = alloca <8 x i8>, align 8 + %z = alloca <8 x i8>, align 8 + %x = alloca <8 x i8>, align 1 + %y = alloca <8 x i8>, align 1 + store double %0, ptr %a, align 8 + store double %1, ptr %b, align 8 + %2 = load <8 x i8>, ptr %a, align 8 + store <8 x i8> %2, ptr %x, align 1 + %3 = load <8 x i8>, ptr %b, align 8 + store <8 x i8> %3, ptr %y, align 1 + %4 = load <8 x i8>, ptr %x, align 1 + %5 = load <8 x i8>, ptr %y, align 1 + %eq = icmp eq <8 x i8> %4, %5 + %6 = sext <8 x i1> %eq to <8 x i8> + store <8 x i8> %6, ptr %z, align 8 + %7 = load <8 x i8>, ptr %z, align 8 + %8 = trunc <8 x i8> %7 to <8 x i1> + %sext = sext <8 x i1> %8 to <8 x i8> + %and = and <8 x i8> + %9 = load <8 x i8>, ptr %z, align 8 + %10 = trunc <8 x i8> %9 to <8 x i1> + %sext1 = sext <8 x i1> %10 to <8 x i8> + %bnot = xor <8 x i8> + %and2 = and <8 x i8> %bnot, + %add = add <8 x i8> %and, %and2 + %11 = call i8 @llvm.vector.reduce.umin.v8i8(<8 x i8> %add) + %zext = zext i8 %11 to i32 + ret i32 %zext +} \ No newline at end of file diff --git a/test/test_suite7/vector/vector_conversion_scalar.c3 b/test/test_suite7/vector/vector_conversion_scalar.c3 new file mode 100644 index 000000000..1b99dc30c --- /dev/null +++ b/test/test_suite7/vector/vector_conversion_scalar.c3 @@ -0,0 +1,15 @@ +// #deprecation: no +fn void test2(int[<2>] x) {} +fn void main() +{ + int[<2>] y = 1; + y[..] = 3; + y.xy = 3; // #error: cannot use swizzling + y *= 2; + y = 3; // #error: explicit cast + test2(3); // #error: explicit cast + {| + if (y[0] == 3) return 1; // #error: explicit cast + return y; + |}; +} \ No newline at end of file diff --git a/test/test_suite7/vector/vector_from_i1.c3t b/test/test_suite7/vector/vector_from_i1.c3t new file mode 100644 index 000000000..5741e166f --- /dev/null +++ b/test/test_suite7/vector/vector_from_i1.c3t @@ -0,0 +1,31 @@ +// #target: macos-x64 +module test; +import std; + +// issue 1954 +macro splat($Type, x) +{ + return ($Type) {x,x,x,x}; +} + +fn void main() +{ + int[<4>] v1 = splat(int[<4>], 2); + int[<4>] v2 = splat(int[<4>], 1); + bool[<4>] vb = (v1 == v2); +} + +/* #expect: test.ll + + store <4 x i32> + store <4 x i32> + %0 = load <4 x i32>, ptr %v1, align 16 + %1 = load <4 x i32>, ptr %v2, align 16 + %eq = icmp eq <4 x i32> %0, %1 + %2 = call i1 @llvm.vector.reduce.and.v4i1(<4 x i1> %eq) + %3 = zext i1 %2 to i8 + %4 = insertelement <4 x i8> undef, i8 %3, i64 0 + %5 = insertelement <4 x i8> %4, i8 %3, i64 1 + %6 = insertelement <4 x i8> %5, i8 %3, i64 2 + %7 = insertelement <4 x i8> %6, i8 %3, i64 3 + store <4 x i8> %7, ptr %vb, align 4 diff --git a/test/test_suite7/vector/vector_incdec.c3t b/test/test_suite7/vector/vector_incdec.c3t new file mode 100644 index 000000000..822296f45 --- /dev/null +++ b/test/test_suite7/vector/vector_incdec.c3t @@ -0,0 +1,189 @@ +// #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 +} + +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_suite7/vector/vector_init.c3t b/test/test_suite7/vector/vector_init.c3t new file mode 100644 index 000000000..18469b719 --- /dev/null +++ b/test/test_suite7/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 + + +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_suite7/vector/vector_init_regression.c3t b/test/test_suite7/vector/vector_init_regression.c3t new file mode 100644 index 000000000..73ad3b1e0 --- /dev/null +++ b/test/test_suite7/vector/vector_init_regression.c3t @@ -0,0 +1,414 @@ +// #target: macos-x64 +// #opt: --fp-math=relaxed +module test; +extern fn int printf(char* format, ...); + +fn void main() { + float radians = 3.1415 / 4; + float[<3>] axis = {0.0, 0.0, 1.0}; + + float cosr = (float) $$cos(radians); + float sinr = (float) $$sin(radians); + float x = axis[0]; + float y = axis[1]; + float z = axis[2]; + + float[<4>][4] a = {}; + a[0] = { + cosr + (x * x) * (float) (1.0 - cosr), + (x * y) * (float) (1.0 - cosr) - (z * sinr), + (x * z) * (float) (1.0 - cosr) + (y * sinr), + 0.0 + }; + + a[1] = { + (y * x) * (float) (1.0 - cosr) + (z * sinr), + cosr + (y * y) * (float) (1.0 - cosr), + (y * z) * (float) (1.0 - cosr) - (x * sinr), + 0.0 + }; + + a[2] = { + (z * x) * (float) (1.0 - cosr) - (y * sinr), + (z * y) * (float) (1.0 - cosr) + (x * sinr), + cosr + (z * z) * (float) (1.0 - cosr), + 0.0 + }; + + a[3] = { + 0.0, + 0.0, + 0.0, + 1.0 + }; + + float[<4>][4] b = { + { + cosr + (x * x) * (float) (1.0 - cosr), + (x * y) * (float) (1.0 - cosr) - (z * sinr), + (x * z) * (float) (1.0 - cosr) + (y * sinr), + 0.0 + }, + { + (y * x) * (float) (1.0 - cosr) + (z * sinr), + cosr + (y * y) * (float) (1.0 - cosr), + (y * z) * (float) (1.0 - cosr) - (x * sinr), + 0.0 + }, + { + (z * x) * (float) (1.0 - cosr) - (y * sinr), + (z * y) * (float) (1.0 - cosr) + (x * sinr), + cosr + (z * z) * (float) (1.0 - cosr), + 0.0 + }, + { + 0.0, + 0.0, + 0.0, + 1.0 + } + }; + + foreach(v : a) { + printf("A: %f %f %f %f\n", v[0], v[1], v[2], v[3]); + } + + printf("\n"); + + foreach(v : b) { + printf("B: %f %f %f %f\n", v[0], v[1], v[2], v[3]); + } +} + +/* #expect: test.ll + +define void @test.main() #0 { +entry: + %radians = alloca float, align 4 + %axis = alloca <3 x float>, align 16 + %cosr = alloca float, align 4 + %sinr = alloca float, align 4 + %x = alloca float, align 4 + %y = alloca float, align 4 + %z = alloca float, align 4 + %a = alloca [4 x <4 x float>], align 16 + %b = alloca [4 x <4 x float>], align 16 + %.anon = alloca i64, align 8 + %v = alloca <4 x float>, align 16 + %.anon90 = alloca i64, align 8 + %v94 = alloca <4 x float>, align 16 + store float 0x3FE921CAC0000000, ptr %radians, align 4 + store <3 x float> , ptr %axis, align 16 + %0 = load float, ptr %radians, align 4 + %1 = call reassoc arcp contract float @llvm.cos.f32(float %0) + store float %1, ptr %cosr, align 4 + %2 = load float, ptr %radians, align 4 + %3 = call reassoc arcp contract float @llvm.sin.f32(float %2) + store float %3, ptr %sinr, align 4 + %4 = load <3 x float>, ptr %axis, align 16 + %5 = extractelement <3 x float> %4, i64 0 + store float %5, ptr %x, align 4 + %6 = load <3 x float>, ptr %axis, align 16 + %7 = extractelement <3 x float> %6, i64 1 + store float %7, ptr %y, align 4 + %8 = load <3 x float>, ptr %axis, align 16 + %9 = extractelement <3 x float> %8, i64 2 + store float %9, ptr %z, align 4 + call void @llvm.memset.p0.i64(ptr align 16 %a, i8 0, i64 64, i1 false) + %10 = load float, ptr %cosr, align 4 + %11 = load float, ptr %x, align 4 + %12 = load float, ptr %x, align 4 + %fmul = fmul reassoc arcp contract float %11, %12 + %13 = load float, ptr %cosr, align 4 + %fpfpext = fpext + %fsub = fsub reassoc arcp contract double 1.000000e+00, %fpfpext + %fpfptrunc = fptrunc + %14 = call reassoc arcp contract float @llvm.fmuladd.f32(float %fmul, float %fpfptrunc, float %10) + %15 = insertelement <4 x float> undef, float %14, i64 0 + %16 = load float, ptr %x, align 4 + %17 = load float, ptr %y, align 4 + %fmul1 = fmul reassoc arcp contract float %16, %17 + %18 = load float, ptr %cosr, align 4 + %fpfpext2 = fpext + %fsub3 = fsub reassoc arcp contract double 1.000000e+00, %fpfpext2 + %fpfptrunc4 = fptrunc + %19 = load float, ptr %z, align 4 + %20 = load float, ptr %sinr, align 4 + %fmul5 = fmul reassoc arcp contract float %19, %20 + %21 = fneg reassoc arcp contract float %fmul5 + %22 = call reassoc arcp contract float @llvm.fmuladd.f32(float %fmul1, float %fpfptrunc4, float %21) + %23 = insertelement <4 x float> %15, float %22, i64 1 + %24 = load float, ptr %x, align 4 + %25 = load float, ptr %z, align 4 + %fmul6 = fmul reassoc arcp contract float %24, %25 + %26 = load float, ptr %cosr, align 4 + %fpfpext7 = fpext + %fsub8 = fsub reassoc arcp contract double 1.000000e+00, %fpfpext7 + %fpfptrunc9 = fptrunc + %27 = load float, ptr %y, align 4 + %28 = load float, ptr %sinr, align 4 + %fmul10 = fmul reassoc arcp contract float %27, %28 + %29 = call reassoc arcp contract float @llvm.fmuladd.f32(float %fmul6, float %fpfptrunc9, float %fmul10) + %30 = insertelement <4 x float> %23, float %29, i64 2 + %31 = insertelement <4 x float> %30, float 0.000000e+00, i64 3 + store <4 x float> %31, ptr %a, align 16 + %ptradd = getelementptr inbounds i8, ptr %a, i64 16 + %32 = load float, ptr %y, align 4 + %33 = load float, ptr %x, align 4 + %fmul11 = fmul reassoc arcp contract float %32, %33 + %34 = load float, ptr %cosr, align 4 + %fpfpext12 = fpext + %fsub13 = fsub reassoc arcp contract double 1.000000e+00, %fpfpext12 + %fpfptrunc14 = fptrunc + %35 = load float, ptr %z, align 4 + %36 = load float, ptr %sinr, align 4 + %fmul15 = fmul reassoc arcp contract float %35, %36 + %37 = call reassoc arcp contract float @llvm.fmuladd.f32(float %fmul11, float %fpfptrunc14, float %fmul15) + %38 = insertelement <4 x float> undef, float %37, i64 0 + %39 = load float, ptr %cosr, align 4 + %40 = load float, ptr %y, align 4 + %41 = load float, ptr %y, align 4 + %fmul16 = fmul reassoc arcp contract float %40, %41 + %42 = load float, ptr %cosr, align 4 + %fpfpext17 = fpext + %fsub18 = fsub reassoc arcp contract double 1.000000e+00, %fpfpext17 + %fpfptrunc19 = fptrunc + %43 = call reassoc arcp contract float @llvm.fmuladd.f32(float %fmul16, float %fpfptrunc19, float %39) + %44 = insertelement <4 x float> %38, float %43, i64 1 + %45 = load float, ptr %y, align 4 + %46 = load float, ptr %z, align 4 + %fmul20 = fmul reassoc arcp contract float %45, %46 + %47 = load float, ptr %cosr, align 4 + %fpfpext21 = fpext + %fsub22 = fsub reassoc arcp contract double 1.000000e+00, %fpfpext21 + %fpfptrunc23 = fptrunc + %48 = load float, ptr %x, align 4 + %49 = load float, ptr %sinr, align 4 + %fmul24 = fmul reassoc arcp contract float %48, %49 + %50 = fneg reassoc arcp contract float %fmul24 + %51 = call reassoc arcp contract float @llvm.fmuladd.f32(float %fmul20, float %fpfptrunc23, float %50) + %52 = insertelement <4 x float> %44, float %51, i64 2 + %53 = insertelement <4 x float> %52, float 0.000000e+00, i64 3 + store <4 x float> %53, ptr %ptradd, align 16 + %ptradd25 = getelementptr inbounds i8, ptr %a, i64 32 + %54 = load float, ptr %z, align 4 + %55 = load float, ptr %x, align 4 + %fmul26 = fmul reassoc arcp contract float %54, %55 + %56 = load float, ptr %cosr, align 4 + %fpfpext27 = fpext + %fsub28 = fsub reassoc arcp contract double 1.000000e+00, %fpfpext27 + %fpfptrunc29 = fptrunc + %57 = load float, ptr %y, align 4 + %58 = load float, ptr %sinr, align 4 + %fmul30 = fmul reassoc arcp contract float %57, %58 + %59 = fneg reassoc arcp contract float %fmul30 + %60 = call reassoc arcp contract float @llvm.fmuladd.f32(float %fmul26, float %fpfptrunc29, float %59) + %61 = insertelement <4 x float> undef, float %60, i64 0 + %62 = load float, ptr %z, align 4 + %63 = load float, ptr %y, align 4 + %fmul31 = fmul reassoc arcp contract float %62, %63 + %64 = load float, ptr %cosr, align 4 + %fpfpext32 = fpext + %fsub33 = fsub reassoc arcp contract double 1.000000e+00, %fpfpext32 + %fpfptrunc34 = fptrunc + %65 = load float, ptr %x, align 4 + %66 = load float, ptr %sinr, align 4 + %fmul35 = fmul reassoc arcp contract float %65, %66 + %67 = call reassoc arcp contract float @llvm.fmuladd.f32(float %fmul31, float %fpfptrunc34, float %fmul35) + %68 = insertelement <4 x float> %61, float %67, i64 1 + %69 = load float, ptr %cosr, align 4 + %70 = load float, ptr %z, align 4 + %71 = load float, ptr %z, align 4 + %fmul36 = fmul reassoc arcp contract float %70, %71 + %72 = load float, ptr %cosr, align 4 + %fpfpext37 = fpext + %fsub38 = fsub reassoc arcp contract double 1.000000e+00, %fpfpext37 + %fpfptrunc39 = fptrunc + %73 = call reassoc arcp contract float @llvm.fmuladd.f32(float %fmul36, float %fpfptrunc39, float %69) + %74 = insertelement <4 x float> %68, float %73, i64 2 + %75 = insertelement <4 x float> %74, float 0.000000e+00, i64 3 + store <4 x float> %75, ptr %ptradd25, align 16 + %ptradd40 = getelementptr inbounds i8, ptr %a, i64 48 + store <4 x float> , ptr %ptradd40, align 16 + %76 = load float, ptr %cosr, align 4 + %77 = load float, ptr %x, align 4 + %78 = load float, ptr %x, align 4 + %fmul41 = fmul reassoc arcp contract float %77, %78 + %79 = load float, ptr %cosr, align 4 + %fpfpext42 = fpext + %fsub43 = fsub reassoc arcp contract double 1.000000e+00, %fpfpext42 + %fpfptrunc44 = fptrunc + %80 = call reassoc arcp contract float @llvm.fmuladd.f32(float %fmul41, float %fpfptrunc44, float %76) + %81 = insertelement <4 x float> undef, float %80, i64 0 + %82 = load float, ptr %x, align 4 + %83 = load float, ptr %y, align 4 + %fmul45 = fmul reassoc arcp contract float %82, %83 + %84 = load float, ptr %cosr, align 4 + %fpfpext46 = fpext + %fsub47 = fsub reassoc arcp contract double 1.000000e+00, %fpfpext46 + %fpfptrunc48 = fptrunc + %85 = load float, ptr %z, align 4 + %86 = load float, ptr %sinr, align 4 + %fmul49 = fmul reassoc arcp contract float %85, %86 + %87 = fneg reassoc arcp contract float %fmul49 + %88 = call reassoc arcp contract float @llvm.fmuladd.f32(float %fmul45, float %fpfptrunc48, float %87) + %89 = insertelement <4 x float> %81, float %88, i64 1 + %90 = load float, ptr %x, align 4 + %91 = load float, ptr %z, align 4 + %fmul50 = fmul reassoc arcp contract float %90, %91 + %92 = load float, ptr %cosr, align 4 + %fpfpext51 = fpext + %fsub52 = fsub reassoc arcp contract double 1.000000e+00, %fpfpext51 + %fpfptrunc53 = fptrunc + %93 = load float, ptr %y, align 4 + %94 = load float, ptr %sinr, align 4 + %fmul54 = fmul reassoc arcp contract float %93, %94 + %95 = call reassoc arcp contract float @llvm.fmuladd.f32(float %fmul50, float %fpfptrunc53, float %fmul54) + %96 = insertelement <4 x float> %89, float %95, i64 2 + %97 = insertelement <4 x float> %96, float 0.000000e+00, i64 3 + store <4 x float> %97, ptr %b, align 16 + %ptradd55 = getelementptr inbounds i8, ptr %b, i64 16 + %98 = load float, ptr %y, align 4 + %99 = load float, ptr %x, align 4 + %fmul56 = fmul reassoc arcp contract float %98, %99 + %100 = load float, ptr %cosr, align 4 + %fpfpext57 = fpext + %fsub58 = fsub reassoc arcp contract double 1.000000e+00, %fpfpext57 + %fpfptrunc59 = fptrunc + %101 = load float, ptr %z, align 4 + %102 = load float, ptr %sinr, align 4 + %fmul60 = fmul reassoc arcp contract float %101, %102 + %103 = call reassoc arcp contract float @llvm.fmuladd.f32(float %fmul56, float %fpfptrunc59, float %fmul60) + %104 = insertelement <4 x float> undef, float %103, i64 0 + %105 = load float, ptr %cosr, align 4 + %106 = load float, ptr %y, align 4 + %107 = load float, ptr %y, align 4 + %fmul61 = fmul reassoc arcp contract float %106, %107 + %108 = load float, ptr %cosr, align 4 + %fpfpext62 = fpext + %fsub63 = fsub reassoc arcp contract double 1.000000e+00, %fpfpext62 + %fpfptrunc64 = fptrunc + %109 = call reassoc arcp contract float @llvm.fmuladd.f32(float %fmul61, float %fpfptrunc64, float %105) + %110 = insertelement <4 x float> %104, float %109, i64 1 + %111 = load float, ptr %y, align 4 + %112 = load float, ptr %z, align 4 + %fmul65 = fmul reassoc arcp contract float %111, %112 + %113 = load float, ptr %cosr, align 4 + %fpfpext66 = fpext + %fsub67 = fsub reassoc arcp contract double 1.000000e+00, %fpfpext66 + %fpfptrunc68 = fptrunc + %114 = load float, ptr %x, align 4 + %115 = load float, ptr %sinr, align 4 + %fmul69 = fmul reassoc arcp contract float %114, %115 + %116 = fneg reassoc arcp contract float %fmul69 + %117 = call reassoc arcp contract float @llvm.fmuladd.f32(float %fmul65, float %fpfptrunc68, float %116) + %118 = insertelement <4 x float> %110, float %117, i64 2 + %119 = insertelement <4 x float> %118, float 0.000000e+00, i64 3 + store <4 x float> %119, ptr %ptradd55, align 16 + %ptradd70 = getelementptr inbounds i8, ptr %b, i64 32 + %120 = load float, ptr %z, align 4 + %121 = load float, ptr %x, align 4 + %fmul71 = fmul reassoc arcp contract float %120, %121 + %122 = load float, ptr %cosr, align 4 + %fpfpext72 = fpext + %fsub73 = fsub reassoc arcp contract double 1.000000e+00, %fpfpext72 + %fpfptrunc74 = fptrunc + %123 = load float, ptr %y, align 4 + %124 = load float, ptr %sinr, align 4 + %fmul75 = fmul reassoc arcp contract float %123, %124 + %125 = fneg reassoc arcp contract float %fmul75 + %126 = call reassoc arcp contract float @llvm.fmuladd.f32(float %fmul71, float %fpfptrunc74, float %125) + %127 = insertelement <4 x float> undef, float %126, i64 0 + %128 = load float, ptr %z, align 4 + %129 = load float, ptr %y, align 4 + %fmul76 = fmul reassoc arcp contract float %128, %129 + %130 = load float, ptr %cosr, align 4 + %fpfpext77 = fpext + %fsub78 = fsub reassoc arcp contract double 1.000000e+00, %fpfpext77 + %fpfptrunc79 = fptrunc + %131 = load float, ptr %x, align 4 + %132 = load float, ptr %sinr, align 4 + %fmul80 = fmul reassoc arcp contract float %131, %132 + %133 = call reassoc arcp contract float @llvm.fmuladd.f32(float %fmul76, float %fpfptrunc79, float %fmul80) + %134 = insertelement <4 x float> %127, float %133, i64 1 + %135 = load float, ptr %cosr, align 4 + %136 = load float, ptr %z, align 4 + %137 = load float, ptr %z, align 4 + %fmul81 = fmul reassoc arcp contract float %136, %137 + %138 = load float, ptr %cosr, align 4 + %fpfpext82 = fpext + %fsub83 = fsub reassoc arcp contract double 1.000000e+00, %fpfpext82 + %fpfptrunc84 = fptrunc + %139 = call reassoc arcp contract float @llvm.fmuladd.f32(float %fmul81, float %fpfptrunc84, float %135) + %140 = insertelement <4 x float> %134, float %139, i64 2 + %141 = insertelement <4 x float> %140, float 0.000000e+00, i64 3 + store <4 x float> %141, ptr %ptradd70, align 16 + %ptradd85 = getelementptr inbounds i8, ptr %b, i64 48 + store <4 x float> , ptr %ptradd85, align 16 + store i64 0, ptr %.anon, align 8 + br label %loop.cond + +loop.cond: ; preds = %loop.body, %entry + %142 = load i64, ptr %.anon, align 8 + %gt = icmp ugt i64 4, %142 + br i1 %gt, label %loop.body, label %loop.exit + +loop.body: ; preds = %loop.cond + %143 = load i64, ptr %.anon, align 8 + %ptroffset = getelementptr inbounds [16 x i8], ptr %a, i64 %143 + %144 = load <4 x float>, ptr %ptroffset, align 16 + store <4 x float> %144, ptr %v, align 16 + %145 = load <4 x float>, ptr %v, align 16 + %146 = extractelement <4 x float> %145, i64 0 + %fpfpext86 = fpext + %147 = load <4 x float>, ptr %v, align 16 + %148 = extractelement <4 x float> %147, i64 1 + %fpfpext87 = fpext + %149 = load <4 x float>, ptr %v, align 16 + %150 = extractelement <4 x float> %149, i64 2 + %fpfpext88 = fpext + %151 = load <4 x float>, ptr %v, align 16 + %152 = extractelement <4 x float> %151, i64 3 + %fpfpext89 = fpext + %153 = call i32 (ptr, ...) @printf(ptr @.str, double %fpfpext86, double %fpfpext87, double %fpfpext88, double %fpfpext89) + %154 = load i64, ptr %.anon, align 8 + %addnuw = add nuw i64 %154, 1 + store i64 %addnuw, ptr %.anon, align 8 + br label %loop.cond + +loop.exit: ; preds = %loop.cond + %155 = call i32 (ptr, ...) @printf(ptr @.str.1) + store i64 0, ptr %.anon90, align 8 + br label %loop.cond91 + +loop.cond91: ; preds = %loop.body93, %loop.exit + %156 = load i64, ptr %.anon90, align 8 + %gt92 = icmp ugt i64 4, %156 + br i1 %gt92, label %loop.body93, label %loop.exit101 + +loop.body93: ; preds = %loop.cond91 + %157 = load i64, ptr %.anon90, align 8 + %ptroffset95 = getelementptr inbounds [16 x i8], ptr %b, i64 %157 + %158 = load <4 x float>, ptr %ptroffset95, align 16 + store <4 x float> %158, ptr %v94, align 16 + %159 = load <4 x float>, ptr %v94, align 16 + %160 = extractelement <4 x float> %159, i64 0 + %fpfpext96 = fpext + %161 = load <4 x float>, ptr %v94, align 16 + %162 = extractelement <4 x float> %161, i64 1 + %fpfpext97 = fpext + %163 = load <4 x float>, ptr %v94, align 16 + %164 = extractelement <4 x float> %163, i64 2 + %fpfpext98 = fpext + %165 = load <4 x float>, ptr %v94, align 16 + %166 = extractelement <4 x float> %165, i64 3 + %fpfpext99 = fpext + %167 = call i32 (ptr, ...) @printf(ptr @.str.2, double %fpfpext96, double %fpfpext97, double %fpfpext98, double %fpfpext99) + %168 = load i64, ptr %.anon90, align 8 + %addnuw100 = add nuw i64 %168, 1 + store i64 %addnuw100, ptr %.anon90, align 8 + br label %loop.cond91 + +loop.exit101: ; preds = %loop.cond91 + ret void +} \ No newline at end of file diff --git a/test/test_suite7/vector/vector_lowering_regression1.c3t b/test/test_suite7/vector/vector_lowering_regression1.c3t new file mode 100644 index 000000000..e44d51573 --- /dev/null +++ b/test/test_suite7/vector/vector_lowering_regression1.c3t @@ -0,0 +1,12 @@ +// #target: linux-x64 +module test; +union Vec4f @export @align(16) { + struct { float x,y,z,w; } + float[<4>] v; +} + +extern fn void foo(Vec4f) @extern("foo"); + +/* #expect: test.ll + +declare void @foo(double, double) #0 \ No newline at end of file diff --git a/test/test_suite7/vector/vector_ops2.c3t b/test/test_suite7/vector/vector_ops2.c3t new file mode 100644 index 000000000..c98b66e2f --- /dev/null +++ b/test/test_suite7/vector/vector_ops2.c3t @@ -0,0 +1,55 @@ +// #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; + w = y / z; +} + + +fn void testi() +{ + int[<4>] y = { 1, 2, 3, 4 }; + int[<4>] z = { 2, 2, 2, -100 }; + int[<4>] w = y / z; + w = z >> y; + w = z << y; +} + +/* #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 + 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 %y, align 16 + %3 = load <4 x float>, ptr %z, align 16 + %4 = call <4 x float> @llvm.fabs.v4f32(<4 x float> %3) + %5 = call float @llvm.vector.reduce.fmin.v4f32(<4 x float> %4) + %zero = fcmp ueq float %5, 0.000000e+00 + %6 = call i1 @llvm.expect.i1(i1 %zero, i1 false) + br i1 %6, label %panic, label %checkok + +checkok: ; preds = %entry + %fdiv = fdiv <4 x float> %2, %3 + store <4 x float> %fdiv, ptr %w, align 16 + ret void + +panic: ; preds = %entry + %7 = load ptr, ptr @std.core.builtin.panic, align 8 + call void %7(ptr @.panic_msg, i64 17, ptr @.file, i64 14, ptr @.func, i64 5, i32 9) + unreachable +} diff --git a/test/test_suite7/vector/vector_param.c3t b/test/test_suite7/vector/vector_param.c3t new file mode 100644 index 000000000..2cb143223 --- /dev/null +++ b/test/test_suite7/vector/vector_param.c3t @@ -0,0 +1,34 @@ +// #target: macos-x64 +module test; + +fn void test(int[<4>] x) +{ + x[1] = 123; + int y = x[1]; + assert(y == 123); +} + +fn int main() +{ + test({ 1, 2, 1, 4 }); + return 0; +} + +/* #expect: test.ll + +define void @test.test(<4 x i32> %0) #0 { +entry: + %x = alloca <4 x i32>, align 16 + %y = alloca i32, align 4 + store <4 x i32> %0, ptr %x, align 16 + %1 = load <4 x i32>, ptr %x, align 16 + %elemset = insertelement <4 x i32> %1, i32 123, i64 1 + store <4 x i32> %elemset, ptr %x, align 16 + %2 = load <4 x i32>, ptr %x, align 16 + %3 = extractelement <4 x i32> %2, i64 1 + store i32 %3, ptr %y, align 4 + %4 = load i32, ptr %y, align 4 + %eq = icmp eq i32 %4, 123 + call void @llvm.assume(i1 %eq) + ret void +} \ No newline at end of file diff --git a/test/test_suite7/vector/vector_pointer_errors.c3 b/test/test_suite7/vector/vector_pointer_errors.c3 new file mode 100644 index 000000000..26810af30 --- /dev/null +++ b/test/test_suite7/vector/vector_pointer_errors.c3 @@ -0,0 +1,14 @@ +module vecpointer; + +fn void pointer_add_sub_diff() +{ + int[5] a; + int*[<2>] y; + double*[<2>] z = y; // #error: 'int*[<2>]' to 'double*[<2>]' + y / y; // #error: Cannot divide + y % y; // #error: not defined + y * y; // #error: multiply + y ^ y; // #error: not defined + iptr[<2>] g = (iptr[<2>])y; + g | g; +} diff --git a/test/test_suite7/vector/vector_shift.c3t b/test/test_suite7/vector/vector_shift.c3t new file mode 100644 index 000000000..deea3d271 --- /dev/null +++ b/test/test_suite7/vector/vector_shift.c3t @@ -0,0 +1,43 @@ +// #target: macos-x64 +module test; +fn int main() +{ + int[<2>] z = { 1, 2 }; + z <<= 2; + z << 2; + int x; + z <<= { x, 2 }; + z << { 1, 2 }; + z <<= { 1, 2 }; + return 0; +} + +/* #expect: test.ll + +entry: + %z = alloca <2 x i32>, align 8 + %x = alloca i32, align 4 + store <2 x i32> , ptr %z, align 8 + %0 = load <2 x i32>, ptr %z, align 8 + %shl = shl <2 x i32> %0, + %1 = freeze <2 x i32> %shl + store <2 x i32> %1, ptr %z, align 8 + %2 = load <2 x i32>, ptr %z, align 8 + %shl1 = shl <2 x i32> %2, + %3 = freeze <2 x i32> %shl1 + store i32 0, ptr %x, align 4 + %4 = load <2 x i32>, ptr %z, align 8 + %5 = load i32, ptr %x, align 4 + %6 = insertelement <2 x i32> undef, i32 %5, i64 0 + %7 = insertelement <2 x i32> %6, i32 2, i64 1 + %shl2 = shl <2 x i32> %4, %7 + %8 = freeze <2 x i32> %shl2 + store <2 x i32> %8, ptr %z, align 8 + %9 = load <2 x i32>, ptr %z, align 8 + %shl3 = shl <2 x i32> %9, + %10 = freeze <2 x i32> %shl3 + %11 = load <2 x i32>, ptr %z, align 8 + %shl4 = shl <2 x i32> %11, + %12 = freeze <2 x i32> %shl4 + store <2 x i32> %12, ptr %z, align 8 + ret i32 0 diff --git a/test/test_suite7/vector/vector_to_array_cast.c3t b/test/test_suite7/vector/vector_to_array_cast.c3t new file mode 100644 index 000000000..65218e8cd --- /dev/null +++ b/test/test_suite7/vector/vector_to_array_cast.c3t @@ -0,0 +1,39 @@ +// #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); + double[<2>] zz = y; + 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 + %zz = alloca <2 x double>, align 16 + 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 + %sifp = sitofp <2 x i32> %5 to <2 x double> + store <2 x double> %sifp, ptr %zz, align 16 + %6 = load <2 x i32>, ptr %y, align 4 + store <2 x i32> %6, ptr %x, align 8 + ret void +} diff --git a/test/test_suite7/vector/vector_to_array_fail.c3 b/test/test_suite7/vector/vector_to_array_fail.c3 new file mode 100644 index 000000000..25ff8fe9e --- /dev/null +++ b/test/test_suite7/vector/vector_to_array_fail.c3 @@ -0,0 +1,13 @@ +module test; +import std::io; +fn void main() +{ + int[<2>] x = { 4, 7 }; + int[2] y = x; + int[?] y1 = y; + int[?] y2 = x; + int[] z = x; + int[] w = y; + double[<2>] ww = x; + short[<2>] www = y; // #error: Implicitly casting 'int[2]' to 'short[<2>]' +} \ No newline at end of file diff --git a/test/test_suite7/vector/vector_to_vector_const_fail.c3 b/test/test_suite7/vector/vector_to_vector_const_fail.c3 new file mode 100644 index 000000000..bd595d27d --- /dev/null +++ b/test/test_suite7/vector/vector_to_vector_const_fail.c3 @@ -0,0 +1,5 @@ +fn int main(String[] args) +{ + const double[4] ONE = { 1.0, 1.0, 1.0, 1.0 }; + float[<4>] vec4 = ONE; // #error: Implicitly casting 'double[4]' to 'float[<4>]' +} \ No newline at end of file diff --git a/test/test_suite7/visibility/ambiguous_recursive.c3 b/test/test_suite7/visibility/ambiguous_recursive.c3 new file mode 100644 index 000000000..66b5937f8 --- /dev/null +++ b/test/test_suite7/visibility/ambiguous_recursive.c3 @@ -0,0 +1,33 @@ +module ttf::utilities; + +struct Point +{ + float x; + float z; + bitstruct : uint { + uint spl : 0..0; + uint onc : 1..1; + uint shd : 2..2; + uint res : 3..31; + } +} + +module ttf; +import std::io; +struct Point (Printable) { + float x; + float y; + bitstruct : uint { + uint spl : 0..0; + uint onc : 1..1; + uint shd : 2..2; + uint res : 3..31; + } +} + +module test; +import ttf; +fn void main() +{ + Point x = { .z = 2 }; // #error: resolve the ambiguity +} \ No newline at end of file diff --git a/test/test_suite7/visibility/ambiguous_var.c3t b/test/test_suite7/visibility/ambiguous_var.c3t new file mode 100644 index 000000000..9e27bb0c0 --- /dev/null +++ b/test/test_suite7/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; + +fn void test2() + @private{ + int c = a; // This is fine. + c = foo::b; + c = bar::b; + c = foo::a; + c = b; // #error: global variable needs a path prefix (e.g. 'foo::b') +} diff --git a/test/test_suite7/visibility/export_property.c3t b/test/test_suite7/visibility/export_property.c3t new file mode 100644 index 000000000..3aa969ce4 --- /dev/null +++ b/test/test_suite7/visibility/export_property.c3t @@ -0,0 +1,39 @@ +// #target: macos-aarch64 +module test; +fn void test(Test a) @export +{ +} + +enum Abc +{ + ABC, + DEF +} +struct Test +{ + struct + { + int a; + int b; + } + bitstruct : int + { + int fa : 1..6; + } + Abc y; + int[?] x; +} + +/* #expect: test.ll + +%.introspect = type { i8, i64, ptr, i64, i64, i64, [0 x i64] } +%"char[]" = type { ptr, i64 } +%Test = type { %.anon, i32, i32, [0 x i32] } +%.anon = type { i32, i32 } + +@"$ct.test.$anon" = linkonce global %.introspect { i8 10, i64 0, ptr null, i64 8, i64 0, i64 2, [0 x i64] zeroinitializer }, align 8 +@"$ct.test.Test" = linkonce global %.introspect { i8 10, i64 0, ptr null, i64 16, i64 0, i64 4, [0 x i64] zeroinitializer }, align 8 +@.enum.ABC = internal constant [4 x i8] c"ABC\00", align 1 +@.enum.DEF = internal constant [4 x i8] c"DEF\00", align 1 +@"$ct.int" = linkonce global %.introspect { i8 2, i64 0, ptr null, i64 4, i64 0, i64 0, [0 x i64] zeroinitializer }, align 8 +@"$ct.test.Abc" = linkonce global { i8, i64, ptr, i64, i64, i64, [2 x %"char[]"] } { i8 8, i64 0, ptr null, i64 4, i64 ptrtoint (ptr @"$ct.int" to i64), i64 2, [2 x %"char[]"] [%"char[]" { ptr @.enum.ABC, i64 3 }, %"char[]" { ptr @.enum.DEF, i64 3 }] }, align 8 diff --git a/test/test_suite7/visibility/no_shared_imports.c3t b/test/test_suite7/visibility/no_shared_imports.c3t new file mode 100644 index 000000000..3555ee02c --- /dev/null +++ b/test/test_suite7/visibility/no_shared_imports.c3t @@ -0,0 +1,22 @@ +// #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 bar @public; + +fn void visible() @private +{ + bar::barFunc(); +} + +// #file: file3.c3 +module bar; + +fn void barFunc() @private {} \ No newline at end of file diff --git a/test/test_suite7/visibility/not_visible.c3t b/test/test_suite7/visibility/not_visible.c3t new file mode 100644 index 000000000..d4cc2875d --- /dev/null +++ b/test/test_suite7/visibility/not_visible.c3t @@ -0,0 +1,16 @@ +// #file: file1.c3 +module baz; +import bar; + +fn void runBar() +{ + bar::notVisible(); // #error: 'bar::notVisible' is '@private' +} + +// #file: file2.c3 +module bar; + +fn void notVisible() + @private{ + +} \ No newline at end of file diff --git a/test/test_suite7/visibility/private_import.c3 b/test/test_suite7/visibility/private_import.c3 new file mode 100644 index 000000000..16fa409e7 --- /dev/null +++ b/test/test_suite7/visibility/private_import.c3 @@ -0,0 +1,21 @@ +module foo; + +fn void hidden() @private +{ +} + +module bar; +import foo; + +fn void test() +{ + foo::hidden(); // #error: 'foo::hidden' is '@private' +} + +module baz; +import foo @public; + +fn void test() +{ + foo::hidden(); +} \ No newline at end of file diff --git a/test/test_suite7/visibility/private_import2.c3 b/test/test_suite7/visibility/private_import2.c3 new file mode 100644 index 000000000..b3032e6ee --- /dev/null +++ b/test/test_suite7/visibility/private_import2.c3 @@ -0,0 +1,27 @@ +module test; + +fn void bar() @private +{ +} +fn void bar2() @local +{ +} + +module baz; +import test @public; + +fn void abc() +{ + test::bar(); + test::bar2(); // #error: could not be found +} + +module baz2; + +import test; + +fn void abc() +{ + test::bar(); // #error: is '@private' + test::bar2(); // #error: could not be found +} \ No newline at end of file diff --git a/test/test_suite7/visibility/private_to_extern.c3t b/test/test_suite7/visibility/private_to_extern.c3t new file mode 100644 index 000000000..599c230ae --- /dev/null +++ b/test/test_suite7/visibility/private_to_extern.c3t @@ -0,0 +1,21 @@ +// #target: macos-x64 + +module test; +import foo; + +fn int main(String[] args) { + foo::one(); + return 0; +} + +module foo; + +macro one() => two(); +macro two() => three(); +fn void three() @private { four(); } +fn void four() @private {} + +/* #expect: foo.ll + +define void @foo.three() +define internal void @foo.four() \ No newline at end of file diff --git a/test/test_suite7/visibility/shared_module.c3t b/test/test_suite7/visibility/shared_module.c3t new file mode 100644 index 000000000..34daced46 --- /dev/null +++ b/test/test_suite7/visibility/shared_module.c3t @@ -0,0 +1,12 @@ +// #file: file1.c3 +module baz; + +fn void runBar() +{ + visible(); +} + +// #file: file2.c3 +module baz; + +fn void visible() @private {} \ No newline at end of file diff --git a/test/test_suite7/visibility/simple_visibility.c3t b/test/test_suite7/visibility/simple_visibility.c3t new file mode 100644 index 000000000..a88afec45 --- /dev/null +++ b/test/test_suite7/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() +{ + +} diff --git a/test/unit/stdlib/collections/priorityqueue.c3 b/test/unit/stdlib/collections/priorityqueue.c3 index 44bd0c7bc..671c93a2d 100644 --- a/test/unit/stdlib/collections/priorityqueue.c3 +++ b/test/unit/stdlib/collections/priorityqueue.c3 @@ -2,7 +2,7 @@ module priorityqueue_test @test; import std::collections; import std::collections::priorityqueue; -def Queue = PriorityQueue(); +def Queue = PriorityQueue{int}; fn void priorityqueue() { @@ -32,7 +32,7 @@ fn void priorityqueue() assert(x == 3, "got %d; want %d", x, 3); } -def QueueMax = PriorityQueueMax(); +def QueueMax = PriorityQueueMax{int}; fn void priorityqueue_max() {