From 9f4da339c36ac4bf31b442fe1bc09f539869dce8 Mon Sep 17 00:00:00 2001 From: Christoffer Lerno Date: Thu, 12 Sep 2024 00:11:09 +0200 Subject: [PATCH] Support `int[*] { 1, 2, 3 }` expressions. --- releasenotes.md | 1 + src/compiler/sema_expr.c | 11 ++++------ src/utils/lib.h | 17 ++++++++++++++++ .../initializer_lists/infer_with_init.c3t | 20 +++++++++++++++++++ 4 files changed, 42 insertions(+), 7 deletions(-) create mode 100644 test/test_suite/initializer_lists/infer_with_init.c3t diff --git a/releasenotes.md b/releasenotes.md index b4b9f7ca6..57c729658 100644 --- a/releasenotes.md +++ b/releasenotes.md @@ -6,6 +6,7 @@ - Introduce `arg: x` named arguments instead of `.arg = x`, deprecate old style. - Support splat for varargs #1352. - Allow `var` in lambdas in macros. +- Support `int[*] { 1, 2, 3 }` expressions. ### Fixes - Issue where a lambda wasn't correctly registered as external. #1408 diff --git a/src/compiler/sema_expr.c b/src/compiler/sema_expr.c index 005dd6426..5a5c581f3 100644 --- a/src/compiler/sema_expr.c +++ b/src/compiler/sema_expr.c @@ -8913,17 +8913,15 @@ static inline bool sema_expr_analyse_builtin(SemaContext *context, Expr *expr, b return true; } - static inline bool sema_expr_analyse_compound_literal(SemaContext *context, Expr *expr) { TypeInfo *type_info = expr->expr_compound_literal.type_info; - if (!sema_resolve_type_info(context, type_info, RESOLVE_TYPE_DEFAULT)) return false; + // We allow infering the size of arrays. + if (!sema_resolve_type_info(context, type_info, RESOLVE_TYPE_ALLOW_INFER)) return false; Type *type = type_info->type; if (type_is_optional(type)) { - SEMA_ERROR(type_info, - "The type here should always be written as a plain type and not an optional, please remove the '!'."); - return false; + RETURN_SEMA_ERROR(type_info, "The type here should always be written as a plain type and not an optional, please remove the '!'."); } if (!sema_resolve_type_structure(context, type, type_info->span)) return false; if (!sema_expr_analyse_initializer_list(context, type, expr->expr_compound_literal.initializer)) return false; @@ -8970,8 +8968,7 @@ static inline bool sema_analyse_expr_dispatch(SemaContext *context, Expr *expr, case EXPR_EMBED: return sema_expr_analyse_embed(context, expr, false); case EXPR_VASPLAT: - SEMA_ERROR(expr, "'$vasplat' can only be used inside of macros."); - return false; + RETURN_SEMA_ERROR(expr, "'$vasplat' can only be used inside of macros."); case EXPR_GENERIC_IDENT: return sema_expr_analyse_generic_ident(context, expr); case EXPR_LAMBDA: diff --git a/src/utils/lib.h b/src/utils/lib.h index 7bfb7bf84..10ed52007 100644 --- a/src/utils/lib.h +++ b/src/utils/lib.h @@ -9,6 +9,7 @@ #if PLATFORM_WINDOWS #include "direct.h" +#include "intrin.h" #endif #if FETCH_AVAILABLE @@ -412,6 +413,22 @@ static inline bool is_power_of_two(uint64_t x) return x != 0 && (x & (x - 1)) == 0; } +static int clz(uint64_t num) +{ +#if IS_CLANG || IS_GCC + return (int)__builtin_ctzll(num); +#else + unsigned long index; + _BitScanReverse64(&index, (__int64)num); + return (int)index; +#endif +} + +static inline unsigned char power_of_2(uint64_t pot_value) +{ + return 64 - clz(pot_value); +} + static inline uint32_t next_highest_power_of_2(uint32_t v) { v--; diff --git a/test/test_suite/initializer_lists/infer_with_init.c3t b/test/test_suite/initializer_lists/infer_with_init.c3t new file mode 100644 index 000000000..4e7c62983 --- /dev/null +++ b/test/test_suite/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