diff --git a/src/compiler/compiler_internal.h b/src/compiler/compiler_internal.h index e550f832d..d260454d5 100644 --- a/src/compiler/compiler_internal.h +++ b/src/compiler/compiler_internal.h @@ -1406,6 +1406,9 @@ extern Type *type_virtual, *type_virtual_generic; extern const char *attribute_list[NUMBER_OF_ATTRIBUTES]; extern const char *kw_std; +extern const char *kw_max; +extern const char *kw_min; +extern const char *kw_elements; extern const char *kw_align; extern const char *kw_alignof; extern const char *kw_distinct; diff --git a/src/compiler/sema_expr.c b/src/compiler/sema_expr.c index 617424d76..fd81cde15 100644 --- a/src/compiler/sema_expr.c +++ b/src/compiler/sema_expr.c @@ -1783,6 +1783,28 @@ static void add_members_to_context(Context *context, Decl *decl) } } +static Expr *enum_minmax_value(Decl *decl, BinaryOp comparison) +{ + assert(decl->decl_kind == DECL_ENUM); + bool is_signed = type_is_signed(decl->enums.type_info->type->canonical); + Expr *expr = NULL; + VECEACH(decl->enums.values, i) + { + Decl *enum_constant = decl->enums.values[i]; + Expr *candidate = enum_constant->enum_constant.expr; + assert(candidate->expr_kind == EXPR_CONST); + if (!expr) + { + expr = candidate; + continue; + } + if (expr_const_compare(&candidate->const_expr, &expr->const_expr, comparison)) + { + expr = candidate; + } + } + return expr; +} static inline bool sema_expr_analyse_type_access(Expr *expr, TypeInfo *parent, bool was_group) { if (!was_group && type_kind_is_derived(parent->type->type_kind)) @@ -1807,12 +1829,12 @@ static inline bool sema_expr_analyse_type_access(Expr *expr, TypeInfo *parent, b } if (name == kw_sizeof) { - expr_rewrite_to_int_const(expr, type_usize, type_size(canonical)); + expr_rewrite_to_int_const(expr, type_compint, type_size(canonical)); return true; } if (name == kw_alignof) { - expr_rewrite_to_int_const(expr, type_usize, type_abi_alignment(canonical)); + expr_rewrite_to_int_const(expr, type_compint, type_abi_alignment(canonical)); return true; } if (name == kw_nameof) @@ -1845,30 +1867,37 @@ static inline bool sema_expr_analyse_type_access(Expr *expr, TypeInfo *parent, b } return true; } - if (name == kw_sizeof) + if (name == kw_elements) { - expr_rewrite_to_int_const(expr, type_usize, type_size(decl->enums.type_info->type)); + expr_rewrite_to_int_const(expr, type_compint, vec_size(decl->enums.values)); return true; } - if (name == kw_alignof) + if (name == kw_max) { - expr_rewrite_to_int_const(expr, type_usize, type_abi_alignment(decl->enums.type_info->type)); + Expr *max = enum_minmax_value(decl, BINARYOP_GT); + if (!max) + { + expr_rewrite_to_int_const(expr, decl->enums.type_info->type->canonical, 0); + return true; + } + expr_replace(expr, max); + return true; + } + if (name == kw_min) + { + Expr *min = enum_minmax_value(decl, BINARYOP_LT); + if (!min) + { + expr_rewrite_to_int_const(expr, decl->enums.type_info->type->canonical, 0); + return true; + } + expr_replace(expr, min); return true; } break; case DECL_ERR: case DECL_UNION: case DECL_STRUCT: - if (name == kw_sizeof) - { - expr_rewrite_to_int_const(expr, type_usize, type_size(decl->type)); - return true; - } - if (name == kw_alignof) - { - expr_rewrite_to_int_const(expr, type_usize, type_abi_alignment(decl->type)); - return true; - } break; default: UNREACHABLE diff --git a/src/compiler/symtab.c b/src/compiler/symtab.c index 367b20007..0d5412713 100644 --- a/src/compiler/symtab.c +++ b/src/compiler/symtab.c @@ -36,16 +36,18 @@ static SymTab symtab; const char *attribute_list[NUMBER_OF_ATTRIBUTES]; -const char *kw_std; const char *kw_align; const char *kw_alignof; const char *kw_distinct; const char *kw_ensure; +const char *kw_elements; const char *kw_errors; const char *kw_inline; const char *kw_kindof; const char *kw_len; const char *kw_main; +const char *kw_max; +const char *kw_min; const char *kw_nameof; const char *kw_offsetof; const char *kw_ordinal; @@ -55,6 +57,7 @@ const char *kw_qnameof; const char *kw_reqparse; const char *kw_require; const char *kw_sizeof; +const char *kw_std; const char *kw___ceil; const char *kw___round; const char *kw___sqrt; @@ -96,12 +99,15 @@ void symtab_init(uint32_t capacity) kw_align = KW_DEF("align"); kw_alignof = KW_DEF("alignof"); kw_distinct = KW_DEF("distinct"); + kw_elements = KW_DEF("elements"); kw_ensure = KW_DEF("ensure"); kw_errors = KW_DEF("errors"); kw_inline = KW_DEF("inline"); kw_kindof = KW_DEF("kindof"); kw_len = KW_DEF("len"); kw_main = KW_DEF("main"); + kw_max = KW_DEF("max"); + kw_min = KW_DEF("min"); kw_nameof = KW_DEF("nameof"); kw_offsetof = KW_DEF("offsetof"); kw_ordinal = KW_DEF("ordinal"); @@ -110,11 +116,11 @@ void symtab_init(uint32_t capacity) kw_qnameof = KW_DEF("qnameof"); kw_require = KW_DEF("required"); kw_sizeof = KW_DEF("sizeof"); + kw_std = KW_DEF("std"); kw___ceil = KW_DEF("__ceil"); kw___round = KW_DEF("__round"); kw___sqrt = KW_DEF("__sqrt"); kw___trunc = KW_DEF("__trunc"); - kw_std = KW_DEF("std"); attribute_list[ATTRIBUTE_INLINE] = kw_inline; attribute_list[ATTRIBUTE_NOINLINE] = KW_DEF("noinline"); diff --git a/src/version.h b/src/version.h index d31f00a96..56adff314 100644 --- a/src/version.h +++ b/src/version.h @@ -1 +1 @@ -#define COMPILER_VERSION "A222" \ No newline at end of file +#define COMPILER_VERSION "A223" \ No newline at end of file diff --git a/test/test_suite/enumerations/compile_time.c3t b/test/test_suite/enumerations/compile_time.c3t new file mode 100644 index 000000000..66307d26b --- /dev/null +++ b/test/test_suite/enumerations/compile_time.c3t @@ -0,0 +1,20 @@ +enum MyEnum : short +{ + HELO = 12, + WORLD = 14, + BYE = -5 +} + +int myenum_max = MyEnum.max; +int myenum_min = MyEnum.min; +int myenum_elements = MyEnum.elements; +int myenum_alignof = MyEnum.alignof; +int myenum_sizeof = MyEnum.sizeof; + +// #expect: compile_time.ll + +@compile_time.myenum_max = protected global i32 14, align 4 +@compile_time.myenum_min = protected global i32 -5, align 4 +@compile_time.myenum_elements = protected global i32 3, align 4 +@compile_time.myenum_alignof = protected global i32 2, align 4 +@compile_time.myenum_sizeof = protected global i32 2, align 4 \ No newline at end of file