diff --git a/lib/std/core/builtin.c3 b/lib/std/core/builtin.c3 index ba74422d8..ee2a879eb 100644 --- a/lib/std/core/builtin.c3 +++ b/lib/std/core/builtin.c3 @@ -86,7 +86,7 @@ fn void panic(char* message, char *file, char *function, uint line) @builtin $$trap(); } -macro unreachable($string = "Unreachable statement reached.") @builtin @noreturn +macro void unreachable($string = "Unreachable statement reached.") @builtin @noreturn { panic($string, $$FILE, $$FUNC, $$LINE); $$unreachable(); diff --git a/lib/std/core/conv.c3 b/lib/std/core/conv.c3 index f799cdb12..203e17283 100644 --- a/lib/std/core/conv.c3 +++ b/lib/std/core/conv.c3 @@ -12,35 +12,34 @@ private const uint UTF16_SURROGATE_HIGH_VALUE = 0xD800; /** * @param c `The utf32 codepoint to convert` * @param [out] output `the resulting buffer` - * @param [inout] size `the size available` + * @param available `the size available` **/ -fn void! char32_to_utf8(Char32 c, char* output, usize *size) +fn usize! char32_to_utf8(Char32 c, char* output, usize available) { - usize available = *size; if (!available) return UnicodeResult.CONVERSION_FAILED!; switch (true) { case c < 0x7f: output[0] = (char)c; - *size = 1; + return 1; case c < 0x7ff: if (available < 2) return UnicodeResult.CONVERSION_FAILED!; output[0] = (char)(0xC0 | c >> 6); output[1] = (char)(0x80 | (c & 0x3F)); - *size = 2; + return 2; case c < 0xffff: if (available < 3) return UnicodeResult.CONVERSION_FAILED!; output[0] = (char)(0xE0 | c >> 12); output[1] = (char)(0x80 | (c >> 6 & 0x3F)); output[2] = (char)(0x80 | (c & 0x3F)); - *size = 3; + return 3; default: if (available < 4) return UnicodeResult.CONVERSION_FAILED!; output[0] = (char)(0xF0 | c >> 18); output[1] = (char)(0x80 | (c >> 12 & 0x3F)); output[2] = (char)(0x80 | (c >> 6 & 0x3F)); output[3] = (char)(0x80 | (c & 0x3F)); - *size = 4; + return 4; } } @@ -297,10 +296,9 @@ fn usize! utf32to8(Char32[] utf32, char[] utf8_buffer) char* ptr = utf8_buffer.ptr; foreach (Char32 uc : utf32) { - usize size = len; - char32_to_utf8(uc, ptr, &size) @inline?; - len -= size; - ptr += size; + usize used = char32_to_utf8(uc, ptr, len) @inline?; + len -= used; + ptr += used; } return utf8_buffer.len - len; } diff --git a/lib/std/core/types.c3 b/lib/std/core/types.c3 index 5a5618f22..0eca10561 100644 --- a/lib/std/core/types.c3 +++ b/lib/std/core/types.c3 @@ -1,9 +1,6 @@ module std::core::types; import libc; -macro bool kind_is_int(TypeKind kind) -{ - return kind == TypeKind.SIGNED_INT || kind == TypeKind.UNSIGNED_INT; -} + fault ConversionResult { @@ -95,6 +92,11 @@ macro bool is_numerical($Type) $endif; } +fn bool TypeKind.is_int(TypeKind kind) @inline +{ + return kind == TypeKind.SIGNED_INT || kind == TypeKind.UNSIGNED_INT; +} + macro bool is_comparable($Type) { var $kind = $Type.kind; @@ -125,8 +127,6 @@ macro bool is_comparable_value(value) $endif; } - - enum TypeKind : char { VOID, diff --git a/lib/std/enumset.c3 b/lib/std/enumset.c3 index 6c46d83b8..f9fcce7b7 100644 --- a/lib/std/enumset.c3 +++ b/lib/std/enumset.c3 @@ -1,5 +1,5 @@ // TODO: ensure the type is an enum first. -module enumset; +module std::enumset; $assert(Enum.elements < 64, "Maximum number of elements for an enum used as enum set is 63"); @@ -24,17 +24,17 @@ $endswitch; define EnumSet = distinct EnumSetType; -fn void EnumSet.add(EnumSet *this, Enum v) +fn void EnumSet.add(EnumSet* this, Enum v) { *this = (EnumSet)((EnumSetType)*this | 1u << (EnumSetType)v); } -fn void EnumSet.clear(EnumSet *this) +fn void EnumSet.clear(EnumSet* this) { *this = 0; } -fn bool EnumSet.remove(EnumSet *this, Enum v) +fn bool EnumSet.remove(EnumSet* this, Enum v) { EnumSetType old = (EnumSetType)*this; EnumSetType new = old & ~(1u << (EnumSetType)v); @@ -42,37 +42,42 @@ fn bool EnumSet.remove(EnumSet *this, Enum v) return old != new; } -fn bool EnumSet.has(EnumSet *this, Enum v) +fn bool EnumSet.has(EnumSet* this, Enum v) { return ((EnumSetType)*this & (1u << (EnumSetType)v)) != 0; } -fn void EnumSet.add_all(EnumSet *this, EnumSet s) +fn void EnumSet.add_all(EnumSet* this, EnumSet s) { *this = (EnumSet)((EnumSetType)*this | (EnumSetType)s); } -fn void EnumSet.retain_all(EnumSet *this, EnumSet s) +fn void EnumSet.retain_all(EnumSet* this, EnumSet s) { *this = (EnumSet)((EnumSetType)*this & (EnumSetType)s); } -fn EnumSet EnumSet.and_of(EnumSet *this, EnumSet s) +fn void EnumSet.remove_all(EnumSet* this, EnumSet s) +{ + *this = (EnumSet)((EnumSetType)*this & ~(EnumSetType)s); +} + +fn EnumSet EnumSet.and_of(EnumSet* this, EnumSet s) { return (EnumSet)((EnumSetType)*this & (EnumSetType)s); } -fn EnumSet EnumSet.or_of(EnumSet *this, EnumSet s) +fn EnumSet EnumSet.or_of(EnumSet* this, EnumSet s) { return (EnumSet)((EnumSetType)*this | (EnumSetType)s); } -fn EnumSet EnumSet.diff_of(EnumSet *this, EnumSet s) +fn EnumSet EnumSet.diff_of(EnumSet* this, EnumSet s) { return (EnumSet)((EnumSetType)*this & ~(EnumSetType)s); } -fn EnumSet EnumSet.xor_of(EnumSet *this, EnumSet s) +fn EnumSet EnumSet.xor_of(EnumSet* this, EnumSet s) { return (EnumSet)((EnumSetType)*this ^ (EnumSetType)s); } \ No newline at end of file diff --git a/lib/std/io.c3 b/lib/std/io.c3 index e2511aa9d..0afdb7fc3 100644 --- a/lib/std/io.c3 +++ b/lib/std/io.c3 @@ -171,6 +171,16 @@ fn File stdout() return { libc::stdout() }; } +fn File stderr() +{ + return { libc::stderr() }; +} + +fn File stdin() +{ + return { libc::stdin() }; +} + /* diff --git a/lib/std/io_printf.c3 b/lib/std/io_printf.c3 index a60aaffc8..dbc0a12b5 100644 --- a/lib/std/io_printf.c3 +++ b/lib/std/io_printf.c3 @@ -194,7 +194,7 @@ private fn int! printf_parse_format_field(variant* args_ptr, usize args_len, usi if (c != '*') return 0; printf_advance_format(format_len, index_ptr)?; variant val = next_variant(args_ptr, args_len, args_index_ptr)?; - if (!types::kind_is_int(val.type.kind)) return FormattingFault.INVALID_WIDTH_ARG!; + if (!val.type.kind.is_int()) return FormattingFault.INVALID_WIDTH_ARG!; uint! intval = types::variant_to_int(val, int); if (catch intval) return FormattingFault.INVALID_WIDTH_ARG!; return intval; diff --git a/lib/std/list.c3 b/lib/std/list.c3 index a2a77d0e6..e54889c9b 100644 --- a/lib/std/list.c3 +++ b/lib/std/list.c3 @@ -19,12 +19,13 @@ private fn void List.ensure_capacity(List *list) @inline } } + fn void List.push(List *list, Type element) @inline { list.append(element); } -fn void List.append(List *list, Type element) +fn void List.append(List* list, Type element) { list.ensure_capacity(); list.entries[list.size++] = element; @@ -33,7 +34,7 @@ fn void List.append(List *list, Type element) /** * @require list.size > 0 */ -fn Type List.pop(List *list) +fn Type List.pop(List* list) { return list.entries[--list.size]; } @@ -62,7 +63,7 @@ fn void List.push_front(List *list, Type type) @inline list.insert_at(0, type); } -fn void List.insert_at(List *list, usize index, Type type) +fn void List.insert_at(List* list, usize index, Type type) { list.ensure_capacity(); for (usize i = list.size; i > index; i--) @@ -73,7 +74,7 @@ fn void List.insert_at(List *list, usize index, Type type) list.entries[index] = type; } -fn void List.remove_last(List *list) +fn void List.remove_last(List* list) { list.size--; } diff --git a/src/compiler/copying.c b/src/compiler/copying.c index c9d947f4e..9fbdc64bc 100644 --- a/src/compiler/copying.c +++ b/src/compiler/copying.c @@ -556,6 +556,7 @@ static void copy_function_signature_deep(CopyStruct *c, FunctionSignature *signa void copy_decl_type(Decl *decl) { Type *type = decl->type; + if (!type) return; Type *copy = type_new(type->type_kind, type->name); *copy = *type; copy->type_cache = NULL; @@ -608,10 +609,16 @@ Decl *copy_decl(CopyStruct *c, Decl *decl) MACRO_COPY_DECL_LIST(copy->methods); break; case DECL_DECLARRAY: - case DECL_BITSTRUCT: UNREACHABLE + case DECL_BITSTRUCT: + copy_decl_type(copy); + MACRO_COPY_DECL_LIST(copy->bitstruct.members); + MACRO_COPY_TYPE(copy->bitstruct.base_type); + MACRO_COPY_DECL_LIST(copy->methods); + MACRO_COPY_DECL_LIST(copy->methods); + break; case DECL_ENUM: - case DECL_FAULT: + case DECL_FAULT: copy_decl_type(copy); MACRO_COPY_DECL_LIST(copy->methods); MACRO_COPY_DECL_LIST(copy->enums.parameters); @@ -619,6 +626,7 @@ Decl *copy_decl(CopyStruct *c, Decl *decl) MACRO_COPY_DECL_LIST(copy->enums.values); break; case DECL_FUNC: + copy_decl_type(copy); MACRO_COPY_TYPEID(copy->func_decl.type_parent); MACRO_COPY_ASTID(copy->func_decl.docs); copy_function_signature_deep(c, ©->func_decl.function_signature); @@ -644,6 +652,7 @@ Decl *copy_decl(CopyStruct *c, Decl *decl) case DECL_FAULTVALUE: break; case DECL_TYPEDEF: + copy_decl_type(copy); if (copy->typedef_decl.is_func) { copy_function_signature_deep(c, ©->typedef_decl.function_signature); @@ -652,6 +661,7 @@ Decl *copy_decl(CopyStruct *c, Decl *decl) MACRO_COPY_TYPE(copy->typedef_decl.type_info); break; case DECL_DISTINCT: + copy_decl_type(copy); MACRO_COPY_DECL_LIST(copy->methods); if (copy->distinct_decl.typedef_decl.is_func) { diff --git a/src/compiler/sema_decls.c b/src/compiler/sema_decls.c index a0c9ea82e..00540e2fa 100644 --- a/src/compiler/sema_decls.c +++ b/src/compiler/sema_decls.c @@ -2103,7 +2103,7 @@ bool sema_analyse_var_decl(SemaContext *context, Decl *decl, bool local) if (!sema_add_local(context, decl)) return decl_poison(decl); } - // 1. Local constants: const int FOO = 123. + // 1. Local or global constants: const int FOO = 123. if (decl->var.kind == VARDECL_CONST) { Expr *init_expr = decl->var.init_expr; @@ -2117,6 +2117,11 @@ bool sema_analyse_var_decl(SemaContext *context, Decl *decl, bool local) if (!decl->var.type_info) { if (!sema_analyse_expr(context, init_expr)) return false; + if (is_global && !expr_is_constant_eval(init_expr, CONSTANT_EVAL_ANY)) + { + SEMA_ERROR(init_expr, "This expression cannot be evaluated at compile time."); + return false; + } decl->type = init_expr->type; if (!decl->alignment) decl->alignment = type_alloca_alignment(decl->type); if (!sema_analyse_decl_type(context, decl->type, init_expr->span)) return false; diff --git a/src/compiler/sema_expr.c b/src/compiler/sema_expr.c index 1eff28309..cceccc166 100644 --- a/src/compiler/sema_expr.c +++ b/src/compiler/sema_expr.c @@ -3796,7 +3796,7 @@ CHECK_DEEPER: SEMA_ERROR(expr, "The method '%s' has private visibility.", kw); return false; } - SEMA_ERROR(expr, "There is no field or method '%s.%s'.", decl->name, kw); + SEMA_ERROR(expr, "There is no field or method '%s.%s'.", type_to_error_string(parent->type), kw); return false; } diff --git a/src/compiler/semantic_analyser.c b/src/compiler/semantic_analyser.c index 157e47e1f..70fe7d233 100644 --- a/src/compiler/semantic_analyser.c +++ b/src/compiler/semantic_analyser.c @@ -190,19 +190,19 @@ static void register_generic_decls(Module *module, Decl **decls) case DECL_ATTRIBUTE: break; case DECL_CT_CASE: - register_generic_decls(module, decl->ct_case_decl.body); +// register_generic_decls(module, decl->ct_case_decl.body); continue; case DECL_CT_ELIF: - register_generic_decls(module, decl->ct_elif_decl.then); +// register_generic_decls(module, decl->ct_elif_decl.then); continue; case DECL_CT_ELSE: - register_generic_decls(module, decl->ct_else_decl); +// register_generic_decls(module, decl->ct_else_decl); continue; case DECL_CT_IF: - register_generic_decls(module, decl->ct_if_decl.then); +// register_generic_decls(module, decl->ct_if_decl.then); continue; case DECL_CT_SWITCH: - register_generic_decls(module, decl->ct_switch_decl.cases); +// register_generic_decls(module, decl->ct_switch_decl.cases); continue; case DECL_MACRO: case DECL_DEFINE: diff --git a/src/version.h b/src/version.h index c0954336a..5bcd6112a 100644 --- a/src/version.h +++ b/src/version.h @@ -1 +1 @@ -#define COMPILER_VERSION "0.2.25" \ No newline at end of file +#define COMPILER_VERSION "0.2.26" \ No newline at end of file diff --git a/test/test_suite/constants/init_order.c3t b/test/test_suite/constants/init_order.c3t new file mode 100644 index 000000000..e4390261a --- /dev/null +++ b/test/test_suite/constants/init_order.c3t @@ -0,0 +1,25 @@ +// #target: macos-x64 +module test; + +macro foo() +{ + $if ($defined(A)): + return A + 1; + $else: + return 1; + $endif; +} + +const Z = foo(); + +$if (!$defined(A) && Z == 1): + const A = 222; +$endif; + +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_suite/generic/enum_set_test.c3t b/test/test_suite/generic/enum_set_test.c3t new file mode 100644 index 000000000..67fb38f77 --- /dev/null +++ b/test/test_suite/generic/enum_set_test.c3t @@ -0,0 +1,218 @@ +// #target: macos-x64 +module test; +import std::io; +import std::enumset; + +define 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 + %retparam = alloca i64, align 8 + %taddr = alloca %"char[]", align 8 + %vararg = alloca %"variant[]", align 8 + %varargslots = alloca [1 x %variant], align 16 + %taddr1 = alloca i8, align 1 + %retparam4 = alloca i64, align 8 + %taddr5 = alloca %"char[]", align 8 + %vararg8 = alloca %"variant[]", align 8 + %varargslots9 = alloca [1 x %variant], align 16 + %taddr10 = alloca i8, align 1 + %retparam16 = alloca i64, align 8 + %taddr17 = alloca %"char[]", align 8 + %vararg20 = alloca %"variant[]", align 8 + %varargslots21 = alloca [1 x %variant], align 16 + %taddr22 = alloca i8, align 1 + %set2 = alloca i32, align 4 + %retparam28 = alloca i64, align 8 + %taddr29 = alloca %"char[]", align 8 + %vararg32 = alloca %"variant[]", align 8 + %varargslots33 = alloca [1 x %variant], align 16 + %taddr34 = alloca i8, align 1 + %retparam40 = alloca i64, align 8 + %taddr41 = alloca %"char[]", align 8 + %vararg44 = alloca %"variant[]", align 8 + %varargslots45 = alloca [1 x %variant], align 16 + %taddr46 = alloca i8, align 1 + store i32 0, i32* %set, align 4 + store %"char[]" { i8* getelementptr inbounds ([15 x i8], [15 x i8]* @.str, i32 0, i32 0), i64 14 }, %"char[]"* %taddr, align 8 + %0 = bitcast %"char[]"* %taddr to { i8*, i64 }* + %1 = getelementptr inbounds { i8*, i64 }, { i8*, i64 }* %0, i32 0, i32 0 + %lo = load i8*, i8** %1, align 8 + %2 = getelementptr inbounds { i8*, i64 }, { i8*, i64 }* %0, i32 0, i32 1 + %hi = load i64, i64* %2, align 8 + %3 = call i8 @"std_enumset$$test_Abc_EnumSet_has"(i32* %set, i32 1) + store i8 %3, i8* %taddr1, align 1 + %4 = insertvalue %variant undef, i8* %taddr1, 0 + %5 = insertvalue %variant %4, i64 ptrtoint (%.introspect* @"ct$bool" to i64), 1 + %6 = getelementptr inbounds [1 x %variant], [1 x %variant]* %varargslots, i64 0, i64 0 + store %variant %5, %variant* %6, align 16 + %7 = getelementptr inbounds %"variant[]", %"variant[]"* %vararg, i32 0, i32 1 + store i64 1, i64* %7, align 8 + %8 = getelementptr inbounds %"variant[]", %"variant[]"* %vararg, i32 0, i32 0 + %9 = bitcast [1 x %variant]* %varargslots to %variant* + store %variant* %9, %variant** %8, align 8 + %10 = bitcast %"variant[]"* %vararg to { i8*, i64 }* + %11 = getelementptr inbounds { i8*, i64 }, { i8*, i64 }* %10, i32 0, i32 0 + %lo2 = load i8*, i8** %11, align 8 + %12 = getelementptr inbounds { i8*, i64 }, { i8*, i64 }* %10, i32 0, i32 1 + %hi3 = load i64, i64* %12, align 8 + %13 = call i64 @std_io_printf(i64* %retparam, i8* %lo, i64 %hi, i8* %lo2, i64 %hi3) + %not_err = icmp eq i64 %13, 0 + br i1 %not_err, label %after.errcheck, label %voiderr + +after.errcheck: ; preds = %entry + br label %voiderr + +voiderr: ; preds = %after.errcheck, %entry + call void @"std_enumset$$test_Abc_EnumSet_add"(i32* %set, i32 0) + store %"char[]" { i8* getelementptr inbounds ([15 x i8], [15 x i8]* @.str.1, i32 0, i32 0), i64 14 }, %"char[]"* %taddr5, align 8 + %14 = bitcast %"char[]"* %taddr5 to { i8*, i64 }* + %15 = getelementptr inbounds { i8*, i64 }, { i8*, i64 }* %14, i32 0, i32 0 + %lo6 = load i8*, i8** %15, align 8 + %16 = getelementptr inbounds { i8*, i64 }, { i8*, i64 }* %14, i32 0, i32 1 + %hi7 = load i64, i64* %16, align 8 + %17 = call i8 @"std_enumset$$test_Abc_EnumSet_has"(i32* %set, i32 1) + store i8 %17, i8* %taddr10, align 1 + %18 = insertvalue %variant undef, i8* %taddr10, 0 + %19 = insertvalue %variant %18, i64 ptrtoint (%.introspect* @"ct$bool" to i64), 1 + %20 = getelementptr inbounds [1 x %variant], [1 x %variant]* %varargslots9, i64 0, i64 0 + store %variant %19, %variant* %20, align 16 + %21 = getelementptr inbounds %"variant[]", %"variant[]"* %vararg8, i32 0, i32 1 + store i64 1, i64* %21, align 8 + %22 = getelementptr inbounds %"variant[]", %"variant[]"* %vararg8, i32 0, i32 0 + %23 = bitcast [1 x %variant]* %varargslots9 to %variant* + store %variant* %23, %variant** %22, align 8 + %24 = bitcast %"variant[]"* %vararg8 to { i8*, i64 }* + %25 = getelementptr inbounds { i8*, i64 }, { i8*, i64 }* %24, i32 0, i32 0 + %lo11 = load i8*, i8** %25, align 8 + %26 = getelementptr inbounds { i8*, i64 }, { i8*, i64 }* %24, i32 0, i32 1 + %hi12 = load i64, i64* %26, align 8 + %27 = call i64 @std_io_printf(i64* %retparam4, i8* %lo6, i64 %hi7, i8* %lo11, i64 %hi12) + %not_err13 = icmp eq i64 %27, 0 + br i1 %not_err13, label %after.errcheck14, label %voiderr15 + +after.errcheck14: ; preds = %voiderr + br label %voiderr15 + +voiderr15: ; preds = %after.errcheck14, %voiderr + call void @"std_enumset$$test_Abc_EnumSet_add"(i32* %set, i32 1) + store %"char[]" { i8* getelementptr inbounds ([15 x i8], [15 x i8]* @.str.2, i32 0, i32 0), i64 14 }, %"char[]"* %taddr17, align 8 + %28 = bitcast %"char[]"* %taddr17 to { i8*, i64 }* + %29 = getelementptr inbounds { i8*, i64 }, { i8*, i64 }* %28, i32 0, i32 0 + %lo18 = load i8*, i8** %29, align 8 + %30 = getelementptr inbounds { i8*, i64 }, { i8*, i64 }* %28, i32 0, i32 1 + %hi19 = load i64, i64* %30, align 8 + %31 = call i8 @"std_enumset$$test_Abc_EnumSet_has"(i32* %set, i32 1) + store i8 %31, i8* %taddr22, align 1 + %32 = insertvalue %variant undef, i8* %taddr22, 0 + %33 = insertvalue %variant %32, i64 ptrtoint (%.introspect* @"ct$bool" to i64), 1 + %34 = getelementptr inbounds [1 x %variant], [1 x %variant]* %varargslots21, i64 0, i64 0 + store %variant %33, %variant* %34, align 16 + %35 = getelementptr inbounds %"variant[]", %"variant[]"* %vararg20, i32 0, i32 1 + store i64 1, i64* %35, align 8 + %36 = getelementptr inbounds %"variant[]", %"variant[]"* %vararg20, i32 0, i32 0 + %37 = bitcast [1 x %variant]* %varargslots21 to %variant* + store %variant* %37, %variant** %36, align 8 + %38 = bitcast %"variant[]"* %vararg20 to { i8*, i64 }* + %39 = getelementptr inbounds { i8*, i64 }, { i8*, i64 }* %38, i32 0, i32 0 + %lo23 = load i8*, i8** %39, align 8 + %40 = getelementptr inbounds { i8*, i64 }, { i8*, i64 }* %38, i32 0, i32 1 + %hi24 = load i64, i64* %40, align 8 + %41 = call i64 @std_io_printf(i64* %retparam16, i8* %lo18, i64 %hi19, i8* %lo23, i64 %hi24) + %not_err25 = icmp eq i64 %41, 0 + br i1 %not_err25, label %after.errcheck26, label %voiderr27 + +after.errcheck26: ; preds = %voiderr15 + br label %voiderr27 + +voiderr27: ; preds = %after.errcheck26, %voiderr15 + store i32 0, i32* %set2, align 4 + %42 = load i32, i32* %set, align 4 + call void @"std_enumset$$test_Abc_EnumSet_add_all"(i32* %set2, i32 %42) + store %"char[]" { i8* getelementptr inbounds ([15 x i8], [15 x i8]* @.str.3, i32 0, i32 0), i64 14 }, %"char[]"* %taddr29, align 8 + %43 = bitcast %"char[]"* %taddr29 to { i8*, i64 }* + %44 = getelementptr inbounds { i8*, i64 }, { i8*, i64 }* %43, i32 0, i32 0 + %lo30 = load i8*, i8** %44, align 8 + %45 = getelementptr inbounds { i8*, i64 }, { i8*, i64 }* %43, i32 0, i32 1 + %hi31 = load i64, i64* %45, align 8 + %46 = call i8 @"std_enumset$$test_Abc_EnumSet_has"(i32* %set2, i32 1) + store i8 %46, i8* %taddr34, align 1 + %47 = insertvalue %variant undef, i8* %taddr34, 0 + %48 = insertvalue %variant %47, i64 ptrtoint (%.introspect* @"ct$bool" to i64), 1 + %49 = getelementptr inbounds [1 x %variant], [1 x %variant]* %varargslots33, i64 0, i64 0 + store %variant %48, %variant* %49, align 16 + %50 = getelementptr inbounds %"variant[]", %"variant[]"* %vararg32, i32 0, i32 1 + store i64 1, i64* %50, align 8 + %51 = getelementptr inbounds %"variant[]", %"variant[]"* %vararg32, i32 0, i32 0 + %52 = bitcast [1 x %variant]* %varargslots33 to %variant* + store %variant* %52, %variant** %51, align 8 + %53 = bitcast %"variant[]"* %vararg32 to { i8*, i64 }* + %54 = getelementptr inbounds { i8*, i64 }, { i8*, i64 }* %53, i32 0, i32 0 + %lo35 = load i8*, i8** %54, align 8 + %55 = getelementptr inbounds { i8*, i64 }, { i8*, i64 }* %53, i32 0, i32 1 + %hi36 = load i64, i64* %55, align 8 + %56 = call i64 @std_io_printf(i64* %retparam28, i8* %lo30, i64 %hi31, i8* %lo35, i64 %hi36) + %not_err37 = icmp eq i64 %56, 0 + br i1 %not_err37, label %after.errcheck38, label %voiderr39 + +after.errcheck38: ; preds = %voiderr27 + br label %voiderr39 + +voiderr39: ; preds = %after.errcheck38, %voiderr27 + %57 = load i32, i32* %set2, align 4 + call void @"std_enumset$$test_Abc_EnumSet_remove_all"(i32* %set, i32 %57) + store %"char[]" { i8* getelementptr inbounds ([15 x i8], [15 x i8]* @.str.4, i32 0, i32 0), i64 14 }, %"char[]"* %taddr41, align 8 + %58 = bitcast %"char[]"* %taddr41 to { i8*, i64 }* + %59 = getelementptr inbounds { i8*, i64 }, { i8*, i64 }* %58, i32 0, i32 0 + %lo42 = load i8*, i8** %59, align 8 + %60 = getelementptr inbounds { i8*, i64 }, { i8*, i64 }* %58, i32 0, i32 1 + %hi43 = load i64, i64* %60, align 8 + %61 = call i8 @"std_enumset$$test_Abc_EnumSet_has"(i32* %set, i32 1) + store i8 %61, i8* %taddr46, align 1 + %62 = insertvalue %variant undef, i8* %taddr46, 0 + %63 = insertvalue %variant %62, i64 ptrtoint (%.introspect* @"ct$bool" to i64), 1 + %64 = getelementptr inbounds [1 x %variant], [1 x %variant]* %varargslots45, i64 0, i64 0 + store %variant %63, %variant* %64, align 16 + %65 = getelementptr inbounds %"variant[]", %"variant[]"* %vararg44, i32 0, i32 1 + store i64 1, i64* %65, align 8 + %66 = getelementptr inbounds %"variant[]", %"variant[]"* %vararg44, i32 0, i32 0 + %67 = bitcast [1 x %variant]* %varargslots45 to %variant* + store %variant* %67, %variant** %66, align 8 + %68 = bitcast %"variant[]"* %vararg44 to { i8*, i64 }* + %69 = getelementptr inbounds { i8*, i64 }, { i8*, i64 }* %68, i32 0, i32 0 + %lo47 = load i8*, i8** %69, align 8 + %70 = getelementptr inbounds { i8*, i64 }, { i8*, i64 }* %68, i32 0, i32 1 + %hi48 = load i64, i64* %70, align 8 + %71 = call i64 @std_io_printf(i64* %retparam40, i8* %lo42, i64 %hi43, i8* %lo47, i64 %hi48) + %not_err49 = icmp eq i64 %71, 0 + br i1 %not_err49, label %after.errcheck50, label %voiderr51 + +after.errcheck50: ; preds = %voiderr39 + br label %voiderr51 + +voiderr51: ; preds = %after.errcheck50, %voiderr39 + ret void +} diff --git a/test/test_suite2/constants/init_order.c3t b/test/test_suite2/constants/init_order.c3t new file mode 100644 index 000000000..e4390261a --- /dev/null +++ b/test/test_suite2/constants/init_order.c3t @@ -0,0 +1,25 @@ +// #target: macos-x64 +module test; + +macro foo() +{ + $if ($defined(A)): + return A + 1; + $else: + return 1; + $endif; +} + +const Z = foo(); + +$if (!$defined(A) && Z == 1): + const A = 222; +$endif; + +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_suite2/generic/enum_set_test.c3t b/test/test_suite2/generic/enum_set_test.c3t new file mode 100644 index 000000000..3624124a2 --- /dev/null +++ b/test/test_suite2/generic/enum_set_test.c3t @@ -0,0 +1,203 @@ +// #target: macos-x64 +module test; +import std::io; +import std::enumset; + +define 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 + %retparam = alloca i64, align 8 + %taddr = alloca %"char[]", align 8 + %vararg = alloca %"variant[]", align 8 + %varargslots = alloca [1 x %variant], align 16 + %taddr1 = alloca i8, align 1 + %retparam4 = alloca i64, align 8 + %taddr5 = alloca %"char[]", align 8 + %vararg8 = alloca %"variant[]", align 8 + %varargslots9 = alloca [1 x %variant], align 16 + %taddr10 = alloca i8, align 1 + %retparam16 = alloca i64, align 8 + %taddr17 = alloca %"char[]", align 8 + %vararg20 = alloca %"variant[]", align 8 + %varargslots21 = alloca [1 x %variant], align 16 + %taddr22 = alloca i8, align 1 + %set2 = alloca i32, align 4 + %retparam28 = alloca i64, align 8 + %taddr29 = alloca %"char[]", align 8 + %vararg32 = alloca %"variant[]", align 8 + %varargslots33 = alloca [1 x %variant], align 16 + %taddr34 = alloca i8, align 1 + %retparam40 = alloca i64, align 8 + %taddr41 = alloca %"char[]", align 8 + %vararg44 = alloca %"variant[]", align 8 + %varargslots45 = alloca [1 x %variant], align 16 + %taddr46 = alloca i8, align 1 + store i32 0, ptr %set, align 4 + store %"char[]" { ptr @.str, i64 14 }, ptr %taddr, align 8 + %0 = getelementptr inbounds { ptr, i64 }, ptr %taddr, i32 0, i32 0 + %lo = load ptr, ptr %0, align 8 + %1 = getelementptr inbounds { ptr, i64 }, ptr %taddr, i32 0, i32 1 + %hi = load i64, ptr %1, align 8 + %2 = call i8 @"std_enumset$$test_Abc_EnumSet_has"(ptr %set, i32 1) + store i8 %2, ptr %taddr1, align 1 + %3 = insertvalue %variant undef, ptr %taddr1, 0 + %4 = insertvalue %variant %3, i64 ptrtoint (ptr @"ct$bool" to i64), 1 + %5 = getelementptr inbounds [1 x %variant], ptr %varargslots, i64 0, i64 0 + store %variant %4, ptr %5, align 16 + %6 = getelementptr inbounds %"variant[]", ptr %vararg, i32 0, i32 1 + store i64 1, ptr %6, align 8 + %7 = getelementptr inbounds %"variant[]", ptr %vararg, i32 0, i32 0 + store ptr %varargslots, ptr %7, align 8 + %8 = getelementptr inbounds { ptr, i64 }, ptr %vararg, i32 0, i32 0 + %lo2 = load ptr, ptr %8, align 8 + %9 = getelementptr inbounds { ptr, i64 }, ptr %vararg, i32 0, i32 1 + %hi3 = load i64, ptr %9, align 8 + %10 = call i64 @std_io_printf(ptr %retparam, ptr %lo, i64 %hi, ptr %lo2, i64 %hi3) + %not_err = icmp eq i64 %10, 0 + br i1 %not_err, label %after.errcheck, label %voiderr + +after.errcheck: ; preds = %entry + br label %voiderr + +voiderr: ; preds = %after.errcheck, %entry + call void @"std_enumset$$test_Abc_EnumSet_add"(ptr %set, i32 0) + store %"char[]" { ptr @.str.1, i64 14 }, ptr %taddr5, align 8 + %11 = getelementptr inbounds { ptr, i64 }, ptr %taddr5, i32 0, i32 0 + %lo6 = load ptr, ptr %11, align 8 + %12 = getelementptr inbounds { ptr, i64 }, ptr %taddr5, i32 0, i32 1 + %hi7 = load i64, ptr %12, align 8 + %13 = call i8 @"std_enumset$$test_Abc_EnumSet_has"(ptr %set, i32 1) + store i8 %13, ptr %taddr10, align 1 + %14 = insertvalue %variant undef, ptr %taddr10, 0 + %15 = insertvalue %variant %14, i64 ptrtoint (ptr @"ct$bool" to i64), 1 + %16 = getelementptr inbounds [1 x %variant], ptr %varargslots9, i64 0, i64 0 + store %variant %15, ptr %16, align 16 + %17 = getelementptr inbounds %"variant[]", ptr %vararg8, i32 0, i32 1 + store i64 1, ptr %17, align 8 + %18 = getelementptr inbounds %"variant[]", ptr %vararg8, i32 0, i32 0 + store ptr %varargslots9, ptr %18, align 8 + %19 = getelementptr inbounds { ptr, i64 }, ptr %vararg8, i32 0, i32 0 + %lo11 = load ptr, ptr %19, align 8 + %20 = getelementptr inbounds { ptr, i64 }, ptr %vararg8, i32 0, i32 1 + %hi12 = load i64, ptr %20, align 8 + %21 = call i64 @std_io_printf(ptr %retparam4, ptr %lo6, i64 %hi7, ptr %lo11, i64 %hi12) + %not_err13 = icmp eq i64 %21, 0 + br i1 %not_err13, label %after.errcheck14, label %voiderr15 + +after.errcheck14: ; preds = %voiderr + br label %voiderr15 + +voiderr15: ; preds = %after.errcheck14, %voiderr + call void @"std_enumset$$test_Abc_EnumSet_add"(ptr %set, i32 1) + store %"char[]" { ptr @.str.2, i64 14 }, ptr %taddr17, align 8 + %22 = getelementptr inbounds { ptr, i64 }, ptr %taddr17, i32 0, i32 0 + %lo18 = load ptr, ptr %22, align 8 + %23 = getelementptr inbounds { ptr, i64 }, ptr %taddr17, i32 0, i32 1 + %hi19 = load i64, ptr %23, align 8 + %24 = call i8 @"std_enumset$$test_Abc_EnumSet_has"(ptr %set, i32 1) + store i8 %24, ptr %taddr22, align 1 + %25 = insertvalue %variant undef, ptr %taddr22, 0 + %26 = insertvalue %variant %25, i64 ptrtoint (ptr @"ct$bool" to i64), 1 + %27 = getelementptr inbounds [1 x %variant], ptr %varargslots21, i64 0, i64 0 + store %variant %26, ptr %27, align 16 + %28 = getelementptr inbounds %"variant[]", ptr %vararg20, i32 0, i32 1 + store i64 1, ptr %28, align 8 + %29 = getelementptr inbounds %"variant[]", ptr %vararg20, i32 0, i32 0 + store ptr %varargslots21, ptr %29, align 8 + %30 = getelementptr inbounds { ptr, i64 }, ptr %vararg20, i32 0, i32 0 + %lo23 = load ptr, ptr %30, align 8 + %31 = getelementptr inbounds { ptr, i64 }, ptr %vararg20, i32 0, i32 1 + %hi24 = load i64, ptr %31, align 8 + %32 = call i64 @std_io_printf(ptr %retparam16, ptr %lo18, i64 %hi19, ptr %lo23, i64 %hi24) + %not_err25 = icmp eq i64 %32, 0 + br i1 %not_err25, label %after.errcheck26, label %voiderr27 + +after.errcheck26: ; preds = %voiderr15 + br label %voiderr27 + +voiderr27: ; preds = %after.errcheck26, %voiderr15 + store i32 0, ptr %set2, align 4 + %33 = load i32, ptr %set, align 4 + call void @"std_enumset$$test_Abc_EnumSet_add_all"(ptr %set2, i32 %33) + store %"char[]" { ptr @.str.3, i64 14 }, ptr %taddr29, align 8 + %34 = getelementptr inbounds { ptr, i64 }, ptr %taddr29, i32 0, i32 0 + %lo30 = load ptr, ptr %34, align 8 + %35 = getelementptr inbounds { ptr, i64 }, ptr %taddr29, i32 0, i32 1 + %hi31 = load i64, ptr %35, align 8 + %36 = call i8 @"std_enumset$$test_Abc_EnumSet_has"(ptr %set2, i32 1) + store i8 %36, ptr %taddr34, align 1 + %37 = insertvalue %variant undef, ptr %taddr34, 0 + %38 = insertvalue %variant %37, i64 ptrtoint (ptr @"ct$bool" to i64), 1 + %39 = getelementptr inbounds [1 x %variant], ptr %varargslots33, i64 0, i64 0 + store %variant %38, ptr %39, align 16 + %40 = getelementptr inbounds %"variant[]", ptr %vararg32, i32 0, i32 1 + store i64 1, ptr %40, align 8 + %41 = getelementptr inbounds %"variant[]", ptr %vararg32, i32 0, i32 0 + store ptr %varargslots33, ptr %41, align 8 + %42 = getelementptr inbounds { ptr, i64 }, ptr %vararg32, i32 0, i32 0 + %lo35 = load ptr, ptr %42, align 8 + %43 = getelementptr inbounds { ptr, i64 }, ptr %vararg32, i32 0, i32 1 + %hi36 = load i64, ptr %43, align 8 + %44 = call i64 @std_io_printf(ptr %retparam28, ptr %lo30, i64 %hi31, ptr %lo35, i64 %hi36) + %not_err37 = icmp eq i64 %44, 0 + br i1 %not_err37, label %after.errcheck38, label %voiderr39 + +after.errcheck38: ; preds = %voiderr27 + br label %voiderr39 + +voiderr39: ; preds = %after.errcheck38, %voiderr27 + %45 = load i32, ptr %set2, align 4 + call void @"std_enumset$$test_Abc_EnumSet_remove_all"(ptr %set, i32 %45) + store %"char[]" { ptr @.str.4, i64 14 }, ptr %taddr41, align 8 + %46 = getelementptr inbounds { ptr, i64 }, ptr %taddr41, i32 0, i32 0 + %lo42 = load ptr, ptr %46, align 8 + %47 = getelementptr inbounds { ptr, i64 }, ptr %taddr41, i32 0, i32 1 + %hi43 = load i64, ptr %47, align 8 + %48 = call i8 @"std_enumset$$test_Abc_EnumSet_has"(ptr %set, i32 1) + store i8 %48, ptr %taddr46, align 1 + %49 = insertvalue %variant undef, ptr %taddr46, 0 + %50 = insertvalue %variant %49, i64 ptrtoint (ptr @"ct$bool" to i64), 1 + %51 = getelementptr inbounds [1 x %variant], ptr %varargslots45, i64 0, i64 0 + store %variant %50, ptr %51, align 16 + %52 = getelementptr inbounds %"variant[]", ptr %vararg44, i32 0, i32 1 + store i64 1, ptr %52, align 8 + %53 = getelementptr inbounds %"variant[]", ptr %vararg44, i32 0, i32 0 + store ptr %varargslots45, ptr %53, align 8 + %54 = getelementptr inbounds { ptr, i64 }, ptr %vararg44, i32 0, i32 0 + %lo47 = load ptr, ptr %54, align 8 + %55 = getelementptr inbounds { ptr, i64 }, ptr %vararg44, i32 0, i32 1 + %hi48 = load i64, ptr %55, align 8 + %56 = call i64 @std_io_printf(ptr %retparam40, ptr %lo42, i64 %hi43, ptr %lo47, i64 %hi48) + %not_err49 = icmp eq i64 %56, 0 + br i1 %not_err49, label %after.errcheck50, label %voiderr51 + +after.errcheck50: ; preds = %voiderr39 + br label %voiderr51 + +voiderr51: ; preds = %after.errcheck50, %voiderr39 + ret void +}