diff --git a/lib/std/core/mem.c3 b/lib/std/core/mem.c3 index 45140b479..604b0a5db 100644 --- a/lib/std/core/mem.c3 +++ b/lib/std/core/mem.c3 @@ -88,6 +88,13 @@ struct Allocator AllocatorFunction function; } +macro @clone(&value) @builtin +{ + $typeof(value)* x = malloc($typeof(value)); + *x = value; + return x; +} + macro malloc($Type) @builtin { return ($Type*)(mem::alloc($Type.sizeof)); diff --git a/lib/std/core/mem_array.c3 b/lib/std/core/mem_array.c3 index 45e928fc3..e87869bdd 100644 --- a/lib/std/core/mem_array.c3 +++ b/lib/std/core/mem_array.c3 @@ -4,7 +4,7 @@ module std::core::mem::array; /** - * @require usize.typeid.max / elements > $Type.sizeof + * @require usize.max / elements > $Type.sizeof **/ macro alloc($Type, usize elements) { @@ -13,7 +13,7 @@ macro alloc($Type, usize elements) } /** - * @require (usize.typeid.max / elements > $Type.sizeof) + * @require (usize.max / elements > $Type.sizeof) **/ macro make($Type, usize elements) { diff --git a/lib/std/core/string.c3 b/lib/std/core/string.c3 index c43c1c250..fa654aead 100644 --- a/lib/std/core/string.c3 +++ b/lib/std/core/string.c3 @@ -268,9 +268,9 @@ macro void String.append(String* str, value) $case Char32: str.append_char32(value); $default: - $if ($convertable($Type, Char32)): + $if ($convertible($Type, Char32)): str.append_char32(value); - $elif ($convertable($Type, char[])): + $elif ($convertible($Type, char[])): str.append_chars(value); $else: $assert("Unsupported type for appending"); diff --git a/lib/std/core/types.c3 b/lib/std/core/types.c3 index 08c51e8b8..5a5618f22 100644 --- a/lib/std/core/types.c3 +++ b/lib/std/core/types.c3 @@ -1,5 +1,5 @@ module std::core::types; - +import libc; macro bool kind_is_int(TypeKind kind) { return kind == TypeKind.SIGNED_INT || kind == TypeKind.UNSIGNED_INT; @@ -11,37 +11,44 @@ fault ConversionResult VALUE_OUT_OF_UNSIGNED_RANGE, } /** - * @require type.typeid == SIGNED_INT || type.typeid == UNSIGNED_INT, "Argument was not an integer" + * @require type.kind == SIGNED_INT || type.kind == UNSIGNED_INT || type.kind == ENUM, "Argument was not an integer" **/ macro variant_to_int(variant v, $Type) { - bool is_mixed_signed = $Type.typeid.kind != v.type.kind; + typeid variant_type = v.type; + TypeKind kind = variant_type.kind; + if (kind == TypeKind.ENUM) + { + variant_type = variant_type.inner; + kind = variant_type.kind; + } + bool is_mixed_signed = $Type.kind != variant_type.kind; $Type max = $Type.max; $Type min = $Type.min; - switch (v) + switch (variant_type) { case ichar: - ichar c = *v; + ichar c = *(char*)v.ptr; if (is_mixed_signed && c < 0) return ConversionResult.VALUE_OUT_OF_UNSIGNED_RANGE!; return ($Type)c; case short: - short s = *v; + short s = *(short*)v.ptr; if (is_mixed_signed && s < 0) return ConversionResult.VALUE_OUT_OF_UNSIGNED_RANGE!; if (s > max || s < min) return ConversionResult.VALUE_OUT_OF_RANGE!; return ($Type)s; case int: - int i = *v; + int i = *(int*)v.ptr; if (is_mixed_signed && i < 0) return ConversionResult.VALUE_OUT_OF_UNSIGNED_RANGE!; if (i > max || i < min) return ConversionResult.VALUE_OUT_OF_RANGE!; return ($Type)i; case long: - long l = *v; + long l = *(long*)v.ptr;; if (is_mixed_signed && l < 0) return ConversionResult.VALUE_OUT_OF_UNSIGNED_RANGE!; if (l > max || l < min) return ConversionResult.VALUE_OUT_OF_RANGE!; return ($Type)l; case int128: $if (env::I128_SUPPORT): - int128 i = *v; + int128 i = *(int128*)v.ptr; if (is_mixed_signed && i < 0) return ConversionResult.VALUE_OUT_OF_UNSIGNED_RANGE!; if (i > max || i < min) return ConversionResult.VALUE_OUT_OF_RANGE!; return ($Type)i; @@ -49,24 +56,24 @@ macro variant_to_int(variant v, $Type) unreachable(); $endif; case char: - char c = *v; + char c = *(char*)v.ptr; if (c > max) return ConversionResult.VALUE_OUT_OF_RANGE!; return ($Type)c; case ushort: - ushort s = *v; + ushort s = *(ushort*)v.ptr;; if (s > max || s < min) return ConversionResult.VALUE_OUT_OF_RANGE!; return ($Type)s; case uint: - uint i = *v; + uint i = *(uint*)v.ptr;; if (i > max || i < min) return ConversionResult.VALUE_OUT_OF_RANGE!; return ($Type)i; case ulong: - ulong l = *v; + ulong l = *(ulong*)v.ptr;; if (l > max || l < min) return ConversionResult.VALUE_OUT_OF_RANGE!; return ($Type)l; case uint128: $if (env::I128_SUPPORT): - uint128 i = *v; + uint128 i = *(uint128*)v.ptr; if (i > max || i < min) return ConversionResult.VALUE_OUT_OF_RANGE!; return ($Type)i; $else: @@ -79,9 +86,9 @@ macro variant_to_int(variant v, $Type) macro bool is_numerical($Type) { - var $kind = $Type.typeid.kind; + var $kind = $Type.kind; $if ($kind == TypeKind.DISTINCT): - return is_numerical($Type.typeid.inner); + return is_numerical($Type.inner); $else: return $kind == TypeKind.SIGNED_INT || $kind == TypeKind.UNSIGNED_INT || $kind == TypeKind.FLOAT || $kind == TypeKind.VECTOR; @@ -90,9 +97,9 @@ macro bool is_numerical($Type) macro bool is_comparable($Type) { - var $kind = $Type.typeid.kind; + var $kind = $Type.kind; $if ($kind == TypeKind.DISTINCT): - return is_comparable($Type.typeid.inner); + return is_comparable($Type.inner); $else: return $kind == TypeKind.SIGNED_INT || $kind == TypeKind.UNSIGNED_INT || $kind == TypeKind.FLOAT || $kind == TypeKind.VECTOR || $kind == TypeKind.BOOL || $kind == TypeKind.POINTER diff --git a/lib/std/io_printf.c3 b/lib/std/io_printf.c3 index 393921206..a08d56b8e 100644 --- a/lib/std/io_printf.c3 +++ b/lib/std/io_printf.c3 @@ -52,13 +52,12 @@ private fn void! out_str(PrintParam* param, variant arg) case VOID: return out_substr(param, "void"); case ANYERR: - return out_substr(param, ""); + case FAULT: + return out_substr(param, (*(anyerr*)arg.ptr).nameof); case VARIANT: return out_substr(param, ""); case ENUM: - return out_substr(param, ""); - case FAULT: - return out_substr(param, ""); + return out_substr(param, arg.type.names[types::variant_to_int(arg, usize)!!]); case STRUCT: return out_substr(param, ""); case UNION: diff --git a/resources/testfragments/boolerr.c3 b/resources/testfragments/boolerr.c3 index 289bd33eb..b39893cbe 100644 --- a/resources/testfragments/boolerr.c3 +++ b/resources/testfragments/boolerr.c3 @@ -1,5 +1,4 @@ module test; - import libc; struct Doc { Head *head; } @@ -108,20 +107,6 @@ fn char* bool_to_string(bool b) { return b ? "true" : "false"; } -fn char* nameFromError(anyerr e) -{ - switch (e) - { - case TitleResult.TITLE_MISSING: - return "no title"; - case ReadError.BAD_READ: - return "bad read"; - case AllocationFailure.OUT_OF_MEMORY: - return "out of memory"; - default: - return "unknown error"; - } -} fn void main() @@ -145,7 +130,7 @@ fn void main() bool! has_title = readWhetherTitleNonEmpty(url); // This looks a bit less than elegant, but as you see it's mostly due to having to // use printf here. - libc::printf(" Has title: %s vs %s\n", bool_to_string(has_title) ?? nameFromError(catch(has_title)), (has_title ?? false) ? "true" : "false"); + libc::printf(" Has title: %s vs %s\n", bool_to_string(has_title) ?? catch(has_title).nameof, (has_title ?? false) ? "true" : "false"); }; allocator.reset(); } diff --git a/src/compiler/ast.c b/src/compiler/ast.c index 0fc0aa089..65ef88dcf 100644 --- a/src/compiler/ast.c +++ b/src/compiler/ast.c @@ -251,13 +251,14 @@ bool expr_is_pure(Expr *expr) { case EXPR_BUILTIN: return false; + case EXPR_BUILTIN_ACCESS: + return exprid_is_pure(expr->builtin_access_expr.inner); case EXPR_VARIANT: return exprid_is_pure(expr->variant_expr.type_id) && exprid_is_pure(expr->variant_expr.ptr); case EXPR_COMPILER_CONST: case EXPR_CONST: case EXPR_IDENTIFIER: case EXPR_NOP: - case EXPR_PTR: case EXPR_STRINGIFY: case EXPR_RETVAL: case EXPR_CT_CONV: @@ -320,11 +321,8 @@ bool expr_is_pure(Expr *expr) return true; case EXPR_TYPEID_INFO: return exprid_is_pure(expr->typeid_info_expr.parent); - case EXPR_TYPEOFANY: case EXPR_CT_EVAL: return expr_is_pure(expr->inner_expr); - case EXPR_LEN: - return expr_is_pure(expr->len_expr.inner); case EXPR_SLICE: return exprid_is_pure(expr->slice_expr.expr) && exprid_is_pure(expr->slice_expr.start) diff --git a/src/compiler/compiler_internal.h b/src/compiler/compiler_internal.h index 75b9cb09f..fc008abc9 100644 --- a/src/compiler/compiler_internal.h +++ b/src/compiler/compiler_internal.h @@ -243,7 +243,7 @@ struct Type_ TypeBuiltin builtin; // Type[], Type[*], Type[123], Type[<123>] or Type<[123]> TypeArray array; - // func Type1(Type2, Type3, ...) throws Err1, Err2, ... + // fn Type1(Type2, Type3, ...) throws Err1, Err2, ... TypeFunc func; // Type* Type *pointer; @@ -583,6 +583,7 @@ typedef struct Decl_ bool is_maybe_unused : 1; bool is_must_use : 1; bool will_reflect : 1; + bool obfuscate : 1; bool is_dynamic : 1; OperatorOverload operator : 4; union @@ -728,6 +729,20 @@ typedef struct ExprId type_id; } ExprVariant; +typedef enum +{ + ACCESS_LEN, + ACCESS_PTR, + ACCESS_TYPEOFANY, + ACCESS_ENUMNAME, + ACCESS_FAULTNAME, +} BuiltinAccessKind; + +typedef struct +{ + BuiltinAccessKind kind : 8; + ExprId inner; +} ExprBuiltinAccess; typedef struct { Expr *parent; @@ -957,7 +972,6 @@ struct Expr_ union { ExprTypeidInfo typeid_info_expr; ExprVariantSwitch variant_switch; // 32 - ExprLen len_expr; // 8 ExprCast cast_expr; // 12 ExprVariant variant_expr; TypeInfo *type_expr; // 8 @@ -974,6 +988,7 @@ struct Expr_ ExprCall call_expr; // 32 ExprSlice slice_expr; // 16 Expr *inner_expr; // 8 + ExprBuiltinAccess builtin_access_expr; ExprCatchUnwrap catch_unwrap_expr; // 24 ExprSubscript subscript_expr; // 12 ExprAccess access_expr; // 16 @@ -1607,6 +1622,8 @@ extern Type *type_complist; extern Type *type_anyfail; extern Type *type_cint; extern Type *type_cuint; +extern Type *type_chars; + extern const char *attribute_list[NUMBER_OF_ATTRIBUTES]; extern const char *builtin_list[NUMBER_OF_BUILTINS]; @@ -1621,8 +1638,8 @@ extern const char *kw_min; extern const char *kw_elements; extern const char *kw_align; -extern const char *kw_castable; -extern const char *kw_convertable; +extern const char *kw_nameof; +extern const char *kw_names; extern const char *kw_sizeof; extern const char *kw_in; extern const char *kw_out; @@ -1931,6 +1948,7 @@ Expr *expr_generate_decl(Decl *decl, Expr *assign); void expr_insert_addr(Expr *original); void expr_insert_deref(Expr *expr); Expr *expr_variable(Decl *decl); +void expr_rewrite_to_builtin_access(SemaContext *context, Expr *expr, Expr *parent, BuiltinAccessKind kind, Type *type); typedef enum { CONSTANT_EVAL_ANY, diff --git a/src/compiler/copying.c b/src/compiler/copying.c index 525b847cc..c9d947f4e 100644 --- a/src/compiler/copying.c +++ b/src/compiler/copying.c @@ -184,6 +184,9 @@ Expr *copy_expr(CopyStruct *c, Expr *source_expr) case EXPR_BUILTIN: case EXPR_RETVAL: return expr; + case EXPR_BUILTIN_ACCESS: + MACRO_COPY_EXPRID(expr->builtin_access_expr.inner); + return expr; case EXPR_CT_CONV: MACRO_COPY_TYPEID(expr->ct_call_expr.type_from); MACRO_COPY_TYPEID(expr->ct_call_expr.type_to); @@ -237,16 +240,11 @@ Expr *copy_expr(CopyStruct *c, Expr *source_expr) MACRO_COPY_EXPRID(expr->slice_expr.start); MACRO_COPY_EXPRID(expr->slice_expr.end); return expr; - case EXPR_LEN: - MACRO_COPY_EXPR(expr->len_expr.inner); - return expr; case EXPR_FORCE_UNWRAP: case EXPR_TRY: case EXPR_CATCH: case EXPR_FAILABLE: case EXPR_GROUP: - case EXPR_TYPEOFANY: - case EXPR_PTR: case EXPR_STRINGIFY: case EXPR_CT_EVAL: MACRO_COPY_EXPR(expr->inner_expr); diff --git a/src/compiler/enums.h b/src/compiler/enums.h index 172d58d74..2657dc48f 100644 --- a/src/compiler/enums.h +++ b/src/compiler/enums.h @@ -229,8 +229,6 @@ typedef enum EXPR_FLATPATH, EXPR_INITIALIZER_LIST, EXPR_DESIGNATED_INITIALIZER_LIST, - EXPR_LEN, - EXPR_PTR, EXPR_POST_UNARY, EXPR_SLICE, EXPR_SLICE_ASSIGN, @@ -243,13 +241,13 @@ typedef enum EXPR_TRY_UNWRAP, EXPR_TRY_UNWRAP_CHAIN, EXPR_TYPEID, - EXPR_TYPEOFANY, EXPR_TYPEINFO, EXPR_UNARY, EXPR_VARIANTSWITCH, EXPR_NOP, EXPR_TYPEID_INFO, EXPR_VARIANT, + EXPR_BUILTIN_ACCESS, } ExprKind; typedef enum @@ -260,6 +258,7 @@ typedef enum TYPEID_INFO_INNER, TYPEID_INFO_LEN, TYPEID_INFO_SIZEOF, + TYPEID_INFO_NAMES, } TypeIdInfoKind; typedef enum @@ -483,7 +482,6 @@ typedef enum TOKEN_FOR, TOKEN_FOREACH, TOKEN_FN, - TOKEN_FUNC, TOKEN_GENERIC, TOKEN_TLOCAL, TOKEN_IF, @@ -527,7 +525,7 @@ typedef enum TOKEN_CT_STRINGIFY, // $stringify TOKEN_CT_SWITCH, // $switch TOKEN_CT_TYPEOF, // $typeof - TOKEN_CT_CONVERTABLE, // $convertable + TOKEN_CT_CONVERTIBLE, // $convertible TOKEN_CT_CASTABLE, // $castable TOKEN_DOCS_START, // /** @@ -706,6 +704,7 @@ typedef enum ATTRIBUTE_OPERATOR, ATTRIBUTE_PURE, ATTRIBUTE_REFLECT, + ATTRIBUTE_OBFUSCATE, ATTRIBUTE_MAYDISCARD, ATTRIBUTE_NODISCARD, ATTRIBUTE_NONE, diff --git a/src/compiler/llvm_codegen.c b/src/compiler/llvm_codegen.c index 7c586af7e..a19347f30 100644 --- a/src/compiler/llvm_codegen.c +++ b/src/compiler/llvm_codegen.c @@ -266,8 +266,6 @@ void llvm_emit_ptr_from_array(GenContext *c, BEValue *value) return; case TYPE_SUBARRAY: { - // TODO insert trap on overflow. - assert(value->kind == BE_ADDRESS); BEValue member; llvm_emit_subarray_pointer(c, value, &member); llvm_value_rvalue(c, &member); diff --git a/src/compiler/llvm_codegen_expr.c b/src/compiler/llvm_codegen_expr.c index 4aa964670..b5c03aaec 100644 --- a/src/compiler/llvm_codegen_expr.c +++ b/src/compiler/llvm_codegen_expr.c @@ -2183,11 +2183,6 @@ void llvm_emit_len_for_expr(GenContext *c, BEValue *be_value, BEValue *expr_to_l UNREACHABLE } } -static void llvm_emit_len(GenContext *c, BEValue *be_value, Expr *expr) -{ - llvm_emit_expr(c, be_value, expr->len_expr.inner); - llvm_emit_len_for_expr(c, be_value, be_value); -} static void llvm_emit_trap_negative(GenContext *c, Expr *expr, LLVMValueRef value, const char *error) { @@ -3493,26 +3488,6 @@ static inline void llvm_emit_rethrow_expr(GenContext *c, BEValue *be_value, Expr } -static inline void llvm_emit_typeofany(GenContext *c, BEValue *be_value, Expr *expr) -{ - llvm_emit_expr(c, be_value, expr->inner_expr); - llvm_value_fold_failable(c, be_value); - if (llvm_value_is_addr(be_value)) - { - AlignSize alignment = 0; - LLVMValueRef pointer_addr = llvm_emit_struct_gep_raw(c, - be_value->value, - llvm_get_type(c, type_any), - 1, - be_value->alignment, - &alignment); - llvm_value_set_address(be_value, pointer_addr, type_typeid, alignment); - } - else - { - llvm_value_set(be_value, llvm_emit_extract_value(c, be_value->value, 1), type_typeid); - } -} /** * This is the foo? instruction. @@ -5311,17 +5286,6 @@ void llvm_emit_catch_unwrap(GenContext *c, BEValue *value, Expr *expr) llvm_value_set(value, addr.value, type_anyerr); } -static inline void llvm_emit_ptr(GenContext *c, BEValue *value, Expr *expr) -{ - llvm_emit_expr(c, value, expr->inner_expr); - if (value->type == type_any) - { - llvm_emit_any_pointer(c, value, value); - return; - } - assert(value->type->type_kind == TYPE_SUBARRAY); - llvm_emit_subarray_pointer(c, value, value); -} static inline void llvm_emit_typeid_info(GenContext *c, BEValue *value, Expr *expr) { @@ -5372,14 +5336,45 @@ static inline void llvm_emit_typeid_info(GenContext *c, BEValue *value, Expr *ex llvm_value_set(value, val, expr->type); } break; + case TYPEID_INFO_NAMES: + if (active_target.feature.safe_mode) + { + BEValue check; + LLVMBasicBlockRef exit = llvm_basic_block_new(c, "check_type_ok"); + IntrospectType checks[1] = { INTROSPECT_TYPE_ENUM }; + for (int i = 0; i < 1; i++) + { + llvm_emit_int_comp(c, &check, type_char, type_char, kind, llvm_const_int(c, type_char, checks[i]), BINARYOP_EQ); + LLVMBasicBlockRef next = llvm_basic_block_new(c, "check_next"); + llvm_emit_cond_br(c, &check, exit, next); + llvm_emit_block(c, next); + } + File *file = source_file_by_id(expr->span.file_id); + llvm_emit_panic(c, "Attempted to access 'names' on non enum/fault type.", file->name, c->cur_func_decl->name, expr->span.row); + c->current_block = NULL; + c->current_block_is_target = false; + LLVMBuildUnreachable(c->builder); + llvm_emit_block(c, exit); + } + { + LLVMTypeRef typeid = llvm_get_type(c, type_typeid); + LLVMValueRef len = llvm_emit_struct_gep_raw(c, ref, c->introspect_type, INTROSPECT_INDEX_LEN, align, &alignment); + len = llvm_load(c, c->size_type, len, alignment, "namelen"); + LLVMValueRef val = llvm_emit_struct_gep_raw(c, ref, c->introspect_type, INTROSPECT_INDEX_ADDITIONAL, align, &alignment); + LLVMValueRef ptr_to_first = llvm_emit_bitcast(c, val, type_get_ptr(type_chars)); + Type *subarray = type_get_subarray(type_chars); + llvm_value_set(value, llvm_emit_aggregate_two(c, subarray, ptr_to_first, len), subarray); + } + break; case TYPEID_INFO_LEN: if (active_target.feature.safe_mode) { BEValue check; LLVMBasicBlockRef exit = llvm_basic_block_new(c, "check_type_ok"); - IntrospectType checks[3] = { INTROSPECT_TYPE_ARRAY, INTROSPECT_TYPE_VECTOR, + IntrospectType checks[4] = { INTROSPECT_TYPE_ARRAY, INTROSPECT_TYPE_VECTOR, + INTROSPECT_TYPE_ENUM, INTROSPECT_TYPE_SUBARRAY }; - for (int i = 0; i < 3; i++) + for (int i = 0; i < 4; i++) { llvm_emit_int_comp(c, &check, type_char, type_char, kind, llvm_const_int(c, type_char, checks[i]), BINARYOP_EQ); LLVMBasicBlockRef next = llvm_basic_block_new(c, "check_next"); @@ -5488,7 +5483,7 @@ static inline void llvm_emit_argv_to_subarray(GenContext *c, BEValue *value, Exp llvm_value_rvalue(c, &argv_value); LLVMValueRef argv_ptr = argv_value.value; LLVMValueRef count = argc_value.value; - Type *arg_array_type = type_get_subarray(type_char); + Type *arg_array_type = type_chars; AlignSize alignment = type_alloca_alignment(type_get_array(arg_array_type, 1)); LLVMTypeRef arg_array_elem_type = llvm_get_type(c, arg_array_type); LLVMValueRef arg_array = LLVMBuildArrayAlloca(c->builder, arg_array_elem_type, count, "argarray"); @@ -5560,6 +5555,91 @@ static inline void llvm_emit_argv_to_subarray(GenContext *c, BEValue *value, Exp EMIT_LOC(c, expr); } +static inline void llvm_emit_builtin_access(GenContext *c, BEValue *be_value, Expr *expr) +{ + Expr *inner = exprptr(expr->builtin_access_expr.inner); + llvm_emit_expr(c, be_value, inner); + llvm_value_fold_failable(c, be_value); + switch (expr->builtin_access_expr.kind) + { + case ACCESS_LEN: + llvm_emit_len_for_expr(c, be_value, be_value); + return; + case ACCESS_PTR: + if (be_value->type == type_any) + { + llvm_emit_any_pointer(c, be_value, be_value); + return; + } + assert(be_value->type->type_kind == TYPE_SUBARRAY); + llvm_emit_subarray_pointer(c, be_value, be_value); + return; + case ACCESS_FAULTNAME: + { + assert(inner->type->canonical->type_kind == TYPE_FAULTTYPE || inner->type->canonical->type_kind == TYPE_ANYERR); + llvm_value_rvalue(c, be_value); + LLVMValueRef val = llvm_emit_alloca_aligned(c, type_chars, "faultname_zero"); + BEValue zero; + llvm_value_set_address_abi_aligned(&zero, val, type_chars); + LLVMBasicBlockRef exit_block = llvm_basic_block_new(c, "faultname_exit"); + LLVMBasicBlockRef zero_block = llvm_basic_block_new(c, "faultname_no"); + LLVMBasicBlockRef ok_block = llvm_basic_block_new(c, "faultname_ok"); + BEValue check; + llvm_emit_int_comp_zero(c, &check, be_value, BINARYOP_EQ); + llvm_emit_cond_br(c, &check, zero_block, ok_block); + llvm_emit_block(c, zero_block); + llvm_store_zero(c, &zero); + llvm_emit_br(c, exit_block); + llvm_emit_block(c, ok_block); + LLVMValueRef fault_data = LLVMBuildIntToPtr(c->builder, be_value->value, + LLVMPointerType(c->fault_type, 0), ""); + LLVMTypeRef subarray = llvm_get_type(c, type_chars); + LLVMValueRef ptr = LLVMBuildStructGEP2(c->builder, c->fault_type, fault_data, 1, ""); + llvm_emit_br(c, exit_block); + llvm_emit_block(c, exit_block); + LLVMValueRef phi = LLVMBuildPhi(c->builder, llvm_get_ptr_type(c, type_chars), "faultname"); + LLVMValueRef values[] = { zero.value, ptr }; + LLVMBasicBlockRef blocks[] = { zero_block, ok_block }; + LLVMAddIncoming(phi, values, blocks, 2); + llvm_value_set_address_abi_aligned(be_value, phi, type_chars); + return; + } + case ACCESS_ENUMNAME: + { + assert(inner->type->canonical->type_kind == TYPE_ENUM); + llvm_value_rvalue(c, be_value); + LLVMTypeRef subarray = llvm_get_type(c, type_chars); + + LLVMTypeRef backend = LLVMTypeOf(inner->type->canonical->backend_typeid); + LLVMValueRef to_introspect = LLVMBuildIntToPtr(c->builder, inner->type->canonical->backend_typeid, + LLVMPointerType(c->introspect_type, 0), ""); + LLVMValueRef ptr = LLVMBuildStructGEP2(c->builder, c->introspect_type, to_introspect, INTROSPECT_INDEX_ADDITIONAL, ""); + LLVMValueRef ptr_to_first = llvm_emit_bitcast(c, ptr, type_get_ptr(type_chars)); + LLVMValueRef val = llvm_zext_trunc(c, be_value->value, llvm_get_type(c, type_usize)); + llvm_value_set_address(be_value, llvm_emit_pointer_gep_raw(c, subarray, ptr_to_first, val), + type_chars, llvm_abi_alignment(c, subarray)); + return; + } + case ACCESS_TYPEOFANY: + if (llvm_value_is_addr(be_value)) + { + AlignSize alignment = 0; + LLVMValueRef pointer_addr = llvm_emit_struct_gep_raw(c, + be_value->value, + llvm_get_type(c, type_any), + 1, + be_value->alignment, + &alignment); + llvm_value_set_address(be_value, pointer_addr, type_typeid, alignment); + } + else + { + llvm_value_set(be_value, llvm_emit_extract_value(c, be_value->value, 1), type_typeid); + } + return; + } + UNREACHABLE +} void llvm_emit_expr(GenContext *c, BEValue *value, Expr *expr) { EMIT_LOC(c, expr); @@ -5569,6 +5649,9 @@ void llvm_emit_expr(GenContext *c, BEValue *value, Expr *expr) case EXPR_COND: case EXPR_CT_CONV: UNREACHABLE + case EXPR_BUILTIN_ACCESS: + llvm_emit_builtin_access(c, value, expr); + return; case EXPR_RETVAL: *value = c->retval; return; @@ -5587,9 +5670,6 @@ void llvm_emit_expr(GenContext *c, BEValue *value, Expr *expr) case EXPR_CATCH_UNWRAP: llvm_emit_catch_unwrap(c, value, expr); return; - case EXPR_PTR: - llvm_emit_ptr(c, value, expr); - return; case EXPR_TYPEID_INFO: llvm_emit_typeid_info(c, value, expr); return; @@ -5604,9 +5684,6 @@ void llvm_emit_expr(GenContext *c, BEValue *value, Expr *expr) case EXPR_SLICE: gencontext_emit_slice(c, value, expr); return; - case EXPR_LEN: - llvm_emit_len(c, value, expr); - return; case EXPR_FAILABLE: llvm_emit_failable(c, value, expr); return; @@ -5658,9 +5735,6 @@ void llvm_emit_expr(GenContext *c, BEValue *value, Expr *expr) case EXPR_RETHROW: llvm_emit_rethrow_expr(c, value, expr); return; - case EXPR_TYPEOFANY: - llvm_emit_typeofany(c, value, expr); - return; case EXPR_TYPEID: case EXPR_GROUP: // These are folded in the semantic analysis step. diff --git a/src/compiler/llvm_codegen_internal.h b/src/compiler/llvm_codegen_internal.h index d5f3d2058..445b517c2 100644 --- a/src/compiler/llvm_codegen_internal.h +++ b/src/compiler/llvm_codegen_internal.h @@ -86,6 +86,8 @@ typedef struct LLVMTypeRef bool_type; LLVMTypeRef byte_type; LLVMTypeRef introspect_type; + LLVMTypeRef fault_type; + LLVMTypeRef size_type; Decl *panicfn; Decl *cur_code_decl; Decl *cur_func_decl; @@ -331,6 +333,7 @@ void llvm_emit_memcpy(GenContext *c, LLVMValueRef dest, unsigned dest_align, LLV void llvm_emit_memcpy_to_decl(GenContext *c, Decl *decl, LLVMValueRef source, unsigned source_alignment); void llvm_emit_stmt(GenContext *c, Ast *ast); LLVMValueRef llvm_emit_zstring(GenContext *c, const char *str); +LLVMValueRef llvm_emit_zstring_named(GenContext *c, const char *str, const char *extname); static inline LLVMValueRef llvm_emit_store(GenContext *c, Decl *decl, LLVMValueRef value); void llvm_emit_panic_on_true(GenContext *c, LLVMValueRef value, const char *panic_name, SourceSpan loc); void llvm_emit_panic_if_true(GenContext *c, BEValue *value, const char *panic_name, SourceSpan loc); diff --git a/src/compiler/llvm_codegen_module.c b/src/compiler/llvm_codegen_module.c index 88cbdd327..d655d2138 100644 --- a/src/compiler/llvm_codegen_module.c +++ b/src/compiler/llvm_codegen_module.c @@ -23,6 +23,19 @@ static inline LLVMTypeRef create_introspection_type(GenContext *c) return type; } +static inline LLVMTypeRef create_fault_type(GenContext *c) +{ + LLVMTypeRef type = LLVMStructCreateNamed(c->context, ".fault"); + LLVMTypeRef typeid_type = llvm_get_type(c, type_typeid); + LLVMTypeRef chars_type = llvm_get_type(c, type_chars); + LLVMTypeRef fault_type[] = { + [0] = typeid_type, + [1] = chars_type, + }; + LLVMStructSetBody(type, fault_type, 2, false); + return type; +} + void gencontext_begin_module(GenContext *c) { assert(!c->module && "Expected no module"); @@ -105,7 +118,8 @@ void gencontext_begin_module(GenContext *c) c->bool_type = LLVMInt1TypeInContext(c->context); c->byte_type = LLVMInt8TypeInContext(c->context); c->introspect_type = create_introspection_type(c); - + c->fault_type = create_fault_type(c); + c->size_type = llvm_get_type(c, type_usize); if (c->panicfn) c->panicfn->backend_ref = NULL; if (active_target.debug_info != DEBUG_INFO_NONE) diff --git a/src/compiler/llvm_codegen_stmt.c b/src/compiler/llvm_codegen_stmt.c index 941c9a061..4b8334c09 100644 --- a/src/compiler/llvm_codegen_stmt.c +++ b/src/compiler/llvm_codegen_stmt.c @@ -1064,11 +1064,16 @@ void gencontext_emit_expr_stmt(GenContext *c, Ast *ast) } LLVMValueRef llvm_emit_zstring(GenContext *c, const char *str) +{ + return llvm_emit_zstring_named(c, str, ".zstr"); +} + +LLVMValueRef llvm_emit_zstring_named(GenContext *c, const char *str, const char *extname) { LLVMTypeRef char_type = llvm_get_type(c, type_char); unsigned len = (unsigned)strlen(str); LLVMTypeRef char_array_type = LLVMArrayType(char_type, len + 1); - LLVMValueRef global_string = llvm_add_global_type(c, ".zstr", char_array_type, 0); + LLVMValueRef global_string = llvm_add_global_type(c, extname, char_array_type, 0); llvm_set_internal_linkage(global_string); LLVMSetGlobalConstant(global_string, 1); LLVMSetInitializer(global_string, LLVMConstStringInContext(c->context, str, len, 0)); diff --git a/src/compiler/llvm_codegen_type.c b/src/compiler/llvm_codegen_type.c index 51e4fba2b..13dfc9807 100644 --- a/src/compiler/llvm_codegen_type.c +++ b/src/compiler/llvm_codegen_type.c @@ -576,19 +576,37 @@ static LLVMValueRef llvm_get_introspection_for_enum(GenContext *c, Type *type) { elements = 0; } - LLVMValueRef en_values[] = { llvm_const_int(c, type_char, INTROSPECT_TYPE_ENUM ), - llvm_const_int(c, type_usize, elements), - llvm_const_int(c, type_usize, associated_value_count) }; - LLVMValueRef strukt = LLVMConstStructInContext(c->context, en_values, 3, false); if (!is_dynamic) is_external = false; - LLVMValueRef ref = llvm_generate_temp_introspection_global(c, type); - LLVMValueRef val = llvm_generate_introspection_global(c, ref, type, INTROSPECT_TYPE_ENUM, type_flatten(type), elements, NULL, is_external); - if (!associated_value_count) return val; - + LLVMTypeRef subarray = llvm_get_type(c, type_chars); LLVMValueRef *values = elements ? malloc_arena(elements * sizeof(LLVMValueRef)) : NULL; + + bool obfuscate = decl->obfuscate; + for (unsigned i = 0; i < elements; i++) + { + BEValue value; + const char *name = enum_vals[i]->name; + size_t len = strlen(name); + scratch_buffer_clear(); + scratch_buffer_append(".enum."); + scratch_buffer_append_unsigned_int(i); + const char *name_desc = scratch_buffer_to_string(); + if (obfuscate) + { + len = strlen(name_desc); + name = name_desc; + } + LLVMValueRef name_ref = llvm_emit_zstring_named(c, name, scratch_buffer_to_string()); + LLVMValueRef data[2] = { name_ref, llvm_const_int(c, type_usize, len) }; + values[i] = LLVMConstNamedStruct(subarray, data, 2); + } + LLVMValueRef names = LLVMConstArray(subarray, values, elements); + + LLVMValueRef val = llvm_generate_introspection_global(c, NULL, type, INTROSPECT_TYPE_ENUM, type_flatten(type), elements, names, is_external); LLVMTypeRef val_type; + + VECEACH(associated_values, ai) { val_type = NULL; @@ -669,9 +687,15 @@ static LLVMValueRef llvm_get_introspection_for_fault(GenContext *c, Type *type) scratch_buffer_append_char('$'); Decl *val = fault_vals[i]; scratch_buffer_append(val->name); - LLVMValueRef global_name = llvm_add_global_var(c, scratch_buffer_to_string(), type_char, 0); + LLVMValueRef global_name = LLVMAddGlobal(c->module, c->fault_type, scratch_buffer_to_string()); + LLVMSetAlignment(global_name, LLVMPreferredAlignmentOfGlobal(c->target_data, global_name)); LLVMSetGlobalConstant(global_name, 1); - LLVMSetInitializer(global_name, LLVMConstInt(llvm_get_type(c, type_char), 1, false)); + + LLVMValueRef vals[2] = { LLVMConstPtrToInt(ref, llvm_get_type(c, type_typeid)), + llvm_emit_aggregate_two(c, type_chars, llvm_emit_zstring_named(c, val->name, ".fault"), + llvm_const_int(c, type_usize, strlen(val->name))) }; + + LLVMSetInitializer(global_name, LLVMConstNamedStruct(c->fault_type, vals, 2)); llvm_set_linkonce(c, global_name); val->backend_ref = LLVMConstPointerCast(global_name, llvm_get_type(c, type_typeid)); } diff --git a/src/compiler/parse_expr.c b/src/compiler/parse_expr.c index b0344a2ac..8f5216df2 100644 --- a/src/compiler/parse_expr.c +++ b/src/compiler/parse_expr.c @@ -1724,7 +1724,7 @@ ParseRule rules[TOKEN_EOF + 1] = { [TOKEN_CT_TYPEOF] = { parse_type_expr, NULL, PREC_NONE }, [TOKEN_CT_STRINGIFY] = { parse_ct_stringify, NULL, PREC_NONE }, [TOKEN_CT_EVALTYPE] = { parse_type_expr, NULL, PREC_NONE }, - [TOKEN_CT_CONVERTABLE] = { parse_ct_conv, NULL, PREC_NONE }, + [TOKEN_CT_CONVERTIBLE] = { parse_ct_conv, NULL, PREC_NONE }, [TOKEN_CT_CASTABLE] = { parse_ct_conv, NULL, PREC_NONE }, [TOKEN_LBRACE] = { parse_initializer_list, NULL, PREC_NONE }, }; diff --git a/src/compiler/parse_global.c b/src/compiler/parse_global.c index 38525d0a4..b19fff165 100644 --- a/src/compiler/parse_global.c +++ b/src/compiler/parse_global.c @@ -49,7 +49,6 @@ void recover_top_level(ParseContext *c) case TOKEN_CT_IF: case TOKEN_CT_FOR: case TOKEN_CT_SWITCH: - case TOKEN_FUNC: case TOKEN_FN: case TOKEN_STRUCT: case TOKEN_UNION: @@ -1495,7 +1494,7 @@ static inline TypeInfo **parse_generic_parameters(ParseContext *c) /** * define_type_body ::= TYPE_IDENT '=' 'distinct'? (func_typedef | type generic_params?) ';' * - * func_typedef ::= 'func' failable_type parameter_type_list + * func_typedef ::= 'fn' failable_type parameter_type_list */ static inline Decl *parse_define_type(ParseContext *c, Visibility visibility) { @@ -1513,8 +1512,8 @@ static inline Decl *parse_define_type(ParseContext *c, Visibility visibility) advance(c); } - // 1. Did we have `func`? In that case it's a function pointer. - if (try_consume(c, TOKEN_FUNC) || try_consume(c, TOKEN_FN)) + // 1. Did we have `fn`? In that case it's a function pointer. + if (try_consume(c, TOKEN_FN)) { Decl *decl = decl_new_with_type(alias_name, name_loc, DECL_TYPEDEF, visibility); decl->typedef_decl.is_func = true; @@ -1913,6 +1912,8 @@ static inline Decl *parse_enum_declaration(ParseContext *c, Visibility visibilit if (!parse_enum_spec(c, &type, &decl->enums.parameters, visibility)) return poisoned_decl; } + if (!parse_attributes(c, &decl->attributes)) return poisoned_decl; + CONSUME_OR_RET(TOKEN_LBRACE, poisoned_decl); decl->enums.type_info = type ? type : type_info_new_base(type_int, decl->span); @@ -1957,7 +1958,7 @@ static inline Decl *parse_enum_declaration(ParseContext *c, Visibility visibilit /** - * Starts after 'func' + * Starts after 'fn' * * func_name * : path TYPE_IDENT '.' IDENT @@ -1979,14 +1980,7 @@ static inline Decl *parse_enum_declaration(ParseContext *c, Visibility visibilit */ static inline Decl *parse_func_definition(ParseContext *c, Visibility visibility, AstId docs, bool is_interface) { - if (tok_is(c, TOKEN_FUNC)) - { - advance_and_verify(c, TOKEN_FUNC); - } - else - { - advance_and_verify(c, TOKEN_FN); - } + advance_and_verify(c, TOKEN_FN); Decl *func = decl_calloc(); func->decl_kind = DECL_FUNC; func->visibility = visibility; @@ -2369,7 +2363,6 @@ Decl *parse_top_level_statement(ParseContext *c) ASSIGN_DECL_OR_RET(decl, parse_define(c, visibility), poisoned_decl); break; } - case TOKEN_FUNC: case TOKEN_FN: { ASSIGN_DECL_OR_RET(decl, parse_func_definition(c, visibility, docs, false), poisoned_decl); diff --git a/src/compiler/parse_stmt.c b/src/compiler/parse_stmt.c index 6b24aad70..209f60999 100644 --- a/src/compiler/parse_stmt.c +++ b/src/compiler/parse_stmt.c @@ -1005,7 +1005,6 @@ Ast *parse_stmt(ParseContext *c) case TOKEN_ELSE: case TOKEN_QUESTQUEST: case TOKEN_ENUM: - case TOKEN_FUNC: case TOKEN_FN: case TOKEN_GENERIC: case TOKEN_IMPORT: @@ -1035,7 +1034,7 @@ Ast *parse_stmt(ParseContext *c) case TOKEN_CT_ENDFOR: case TOKEN_CT_ENDFOREACH: case TOKEN_CT_CASTABLE: - case TOKEN_CT_CONVERTABLE: + case TOKEN_CT_CONVERTIBLE: SEMA_ERROR_HERE("Unexpected '%s' found when expecting a statement.", token_type_to_string(c->tok)); advance(c); diff --git a/src/compiler/sema_casts.c b/src/compiler/sema_casts.c index f5df18d55..300411355 100644 --- a/src/compiler/sema_casts.c +++ b/src/compiler/sema_casts.c @@ -634,7 +634,7 @@ bool cast_may_implicit(Type *from_type, Type *to_type, bool is_simple_expr, bool if (to_type->type_kind == TYPE_INFERRED_ARRAY) { - if (from_type->type_kind == TYPE_ARRAY && type_flatten_distinct(from_type->array.base) == type_flatten_distinct(to_type->array.base)) return true; + if (from->type_kind == TYPE_ARRAY && type_flatten_distinct(from->array.base) == type_flatten_distinct(to_type->array.base)) return true; return false; } @@ -663,7 +663,7 @@ bool cast_may_implicit(Type *from_type, Type *to_type, bool is_simple_expr, bool // 9. Any cast if (to->type_kind == TYPE_ANY) { - return from_type->type_kind == TYPE_POINTER; + return from->type_kind == TYPE_POINTER; } @@ -823,14 +823,11 @@ Expr *recursive_may_narrow_float(Expr *expr, Type *type) case EXPR_TYPEINFO: case EXPR_CT_CALL: case EXPR_NOP: - case EXPR_LEN: case EXPR_CATCH: case EXPR_BUILTIN: case EXPR_TRY_UNWRAP: case EXPR_TRY_UNWRAP_CHAIN: case EXPR_SUBSCRIPT_ADDR: - case EXPR_TYPEOFANY: - case EXPR_PTR: case EXPR_VARIANTSWITCH: case EXPR_ARGV_TO_SUBARRAY: case EXPR_COMPILER_CONST: @@ -839,6 +836,8 @@ Expr *recursive_may_narrow_float(Expr *expr, Type *type) case EXPR_VARIANT: case EXPR_CT_CONV: UNREACHABLE + case EXPR_BUILTIN_ACCESS: + return false; case EXPR_POST_UNARY: return recursive_may_narrow_float(expr->unary_expr.expr, type); case EXPR_TRY: @@ -940,9 +939,19 @@ Expr *recursive_may_narrow_int(Expr *expr, Type *type) case EXPR_TYPEID_INFO: if (type_size(expr->type) > type_size(type)) return expr; return NULL; - case EXPR_LEN: - if (type_size(type) < type_size(type_cint)) return expr; - return NULL; + case EXPR_BUILTIN_ACCESS: + switch (expr->builtin_access_expr.kind) + { + case ACCESS_LEN: + if (type_size(type) < type_size(type_cint)) return expr; + return NULL; + case ACCESS_TYPEOFANY: + case ACCESS_PTR: + case ACCESS_ENUMNAME: + case ACCESS_FAULTNAME: + return NULL; + } + UNREACHABLE; case EXPR_EXPRESSION_LIST: return recursive_may_narrow_int(VECLAST(expr->expression_list), type); case EXPR_RETHROW: @@ -984,8 +993,6 @@ Expr *recursive_may_narrow_int(Expr *expr, Type *type) case EXPR_TRY_UNWRAP: case EXPR_TRY_UNWRAP_CHAIN: case EXPR_SUBSCRIPT_ADDR: - case EXPR_TYPEOFANY: - case EXPR_PTR: case EXPR_ARGV_TO_SUBARRAY: case EXPR_VARIANTSWITCH: case EXPR_COMPILER_CONST: diff --git a/src/compiler/sema_decls.c b/src/compiler/sema_decls.c index d5120944b..a0c9ea82e 100644 --- a/src/compiler/sema_decls.c +++ b/src/compiler/sema_decls.c @@ -703,7 +703,6 @@ static inline bool sema_analyse_enum_param(SemaContext *context, Decl *param, bo SEMA_ERROR(param, "An associated value must be a normal typed parameter."); return false; } - if (vec_size(param->attributes)) { SEMA_ERROR(param->attributes[0], "There are no valid attributes for associated values."); @@ -715,6 +714,19 @@ static inline bool sema_analyse_enum_param(SemaContext *context, Decl *param, bo param->var.type_info->type = type_get_subarray(param->var.type_info->type); } param->type = param->var.type_info->type; + assert(param->name); + if (param->name == kw_nameof) + { + SEMA_ERROR(param, "'nameof' is not a valid parameter name for enums."); + return false; + } + Decl *other = sema_resolve_symbol_in_current_dynamic_scope(context, param->name); + if (other) + { + SEMA_ERROR(param, "Duplicate parameter name '%s'.", param->name); + return false; + } + sema_add_member(context, param); if (param->var.init_expr) { Expr *expr = param->var.init_expr; @@ -753,10 +765,13 @@ static inline bool sema_analyse_enum(SemaContext *context, Decl *decl) DEBUG_LOG("* Enum type resolved to %s.", type->name); + if (!sema_analyse_attributes(context, decl, decl->attributes, ATTR_ENUM)) return decl_poison(decl); + Decl **associated_values = decl->enums.parameters; unsigned associated_value_count = vec_size(associated_values); unsigned mandatory_count = 0; bool default_values_used = false; + SCOPE_START for (unsigned i = 0; i < associated_value_count; i++) { Decl *value = associated_values[i]; @@ -766,25 +781,26 @@ static inline bool sema_analyse_enum(SemaContext *context, Decl *decl) continue; case RESOLVE_RUNNING: SEMA_ERROR(value, "Recursive definition found."); - return false; + return SCOPE_POP_ERROR(); case RESOLVE_NOT_DONE: value->resolve_status = RESOLVE_RUNNING; break; } bool has_default = false; - if (!sema_analyse_enum_param(context, value, &has_default)) return false; + if (!sema_analyse_enum_param(context, value, &has_default)) return SCOPE_POP_ERROR(); if (!has_default) { mandatory_count++; if (default_values_used && !value->var.vararg) { SEMA_ERROR(value, "Non-default parameters cannot appear after default parameters."); - return false; + return SCOPE_POP_ERROR(); } } default_values_used |= has_default; value->resolve_status = RESOLVE_DONE; } + SCOPE_END; bool success = true; unsigned enums = vec_size(decl->enums.values); @@ -1195,6 +1211,7 @@ static bool sema_analyse_attribute(SemaContext *context, Decl *decl, Attr *attr, [ATTRIBUTE_BUILTIN] = ATTR_MACRO | ATTR_FUNC, [ATTRIBUTE_OPERATOR] = ATTR_MACRO | ATTR_FUNC, [ATTRIBUTE_REFLECT] = ATTR_ENUM, + [ATTRIBUTE_OBFUSCATE] = ATTR_ENUM, [ATTRIBUTE_PURE] = ATTR_CALL, }; @@ -1431,6 +1448,9 @@ static bool sema_analyse_attribute(SemaContext *context, Decl *decl, Attr *attr, case ATTRIBUTE_REFLECT: decl->will_reflect = true; break; + case ATTRIBUTE_OBFUSCATE: + decl->obfuscate = true; + break; case ATTRIBUTE_NONE: UNREACHABLE } diff --git a/src/compiler/sema_expr.c b/src/compiler/sema_expr.c index 183a12956..277224c97 100644 --- a/src/compiler/sema_expr.c +++ b/src/compiler/sema_expr.c @@ -9,6 +9,8 @@ * - Disallow jumping in and out of an expression block. */ +static bool sema_expr_apply_typeid_property(SemaContext *context, Expr *expr, Expr *typeid, const char *kw); +static bool sema_expr_apply_type_property(SemaContext *context, Expr *expr, Type *type, const char *kw); static inline bool sema_expr_analyse_ct_eval(SemaContext *context, Expr *expr); static bool sema_take_addr_of(Expr *inner); static inline bool sema_expr_analyse_binary(SemaContext *context, Expr *expr); @@ -54,11 +56,19 @@ int BINOP_PREC_REQ[BINARYOP_LAST + 1] = [BINARYOP_SHR] = 3, [BINARYOP_SHL] = 3, - }; const char *ct_eval_error = "EVAL_ERROR"; +void expr_rewrite_to_builtin_access(SemaContext *context, Expr *expr, Expr *parent, BuiltinAccessKind kind, Type *type) +{ + expr->expr_kind = EXPR_BUILTIN_ACCESS; + expr->builtin_access_expr.kind = kind; + expr->builtin_access_expr.inner = exprid(parent); + expr->type = type; + expr->resolve_status = RESOLVE_DONE; +} + const char *ct_eval_expr(SemaContext *c, const char *expr_type, Expr *inner, TokenType *type, Path **path_ref, bool report_missing) { if (!sema_analyse_expr(c, inner)) return false; @@ -330,6 +340,19 @@ bool expr_is_constant_eval(Expr *expr, ConstantEvalKind eval_kind) return false; case EXPR_BITASSIGN: return false; + case EXPR_BUILTIN_ACCESS: + switch (expr->builtin_access_expr.kind) + { + case ACCESS_ENUMNAME: + case ACCESS_FAULTNAME: + case ACCESS_LEN: + case ACCESS_PTR: + break; + case ACCESS_TYPEOFANY: + if (eval_kind != CONSTANT_EVAL_ANY) return false; + break; + } + return exprid_is_constant_eval(expr->builtin_access_expr.inner, eval_kind); case EXPR_VARIANT: return exprid_is_constant_eval(expr->variant_expr.type_id, eval_kind) && exprid_is_constant_eval(expr->variant_expr.ptr, eval_kind); case EXPR_BINARY: @@ -387,13 +410,6 @@ bool expr_is_constant_eval(Expr *expr, ConstantEvalKind eval_kind) return expr_list_is_constant_eval(expr->initializer_list, eval_kind); case EXPR_DESIGNATED_INITIALIZER_LIST: return expr_list_is_constant_eval(expr->designated_init_list, eval_kind); - case EXPR_LEN: - expr = expr->len_expr.inner; - goto RETRY; - case EXPR_TYPEOFANY: - if (eval_kind != CONSTANT_EVAL_ANY) return false; - expr = expr->inner_expr; - goto RETRY; case EXPR_SLICE: if (expr->slice_expr.start && !exprid_is_constant_eval(expr->slice_expr.start, CONSTANT_EVAL_FOLDABLE)) return false; if (expr->slice_expr.end && !exprid_is_constant_eval(expr->slice_expr.end, CONSTANT_EVAL_FOLDABLE)) return false; @@ -431,7 +447,6 @@ bool expr_is_constant_eval(Expr *expr, ConstantEvalKind eval_kind) case EXPR_FORCE_UNWRAP: case EXPR_TRY: case EXPR_CATCH: - case EXPR_PTR: expr = expr->inner_expr; goto RETRY; case EXPR_TYPEID: @@ -3196,157 +3211,7 @@ static inline bool sema_expr_analyse_type_access(SemaContext *context, Expr *exp if (!is_const) { - TypeKind kind = canonical->type_kind; - if (name == kw_min) - { - if (type_is_integer(canonical)) - { - expr->expr_kind = EXPR_CONST; - expr->const_expr.const_kind = CONST_INTEGER; - expr->type = parent->type; - expr->resolve_status = RESOLVE_DONE; - expr->const_expr.ixx.type = kind; - switch (kind) - { - case TYPE_I8: - expr->const_expr.ixx.i = (Int128){ 0, 0xFF }; - break; - case TYPE_I16: - expr->const_expr.ixx.i = (Int128){ 0, 0xFFFF }; - break; - case TYPE_I32: - expr->const_expr.ixx.i = (Int128){ 0, 0xFFFFFFFFLL }; - break; - case TYPE_I64: - expr->const_expr.ixx.i = (Int128){ 0, ~((uint64_t)0) }; - break; - case TYPE_I128: - expr->const_expr.ixx.i = (Int128){ ~((uint64_t)0), ~((uint64_t)0) }; - break; - default: - expr->const_expr.ixx.i = (Int128){ 0, 0 }; - break; - } - return true; - } - if (type_is_float(canonical)) - { - expr->expr_kind = EXPR_CONST; - expr->const_expr.const_kind = CONST_FLOAT; - expr->type = parent->type; - expr->resolve_status = RESOLVE_DONE; - expr->const_expr.fxx.type = kind; - switch (kind) - { - case TYPE_F32: - expr->const_expr.fxx.f = FLT_MIN; - break; - case TYPE_F64: - expr->const_expr.fxx.f = DBL_MIN; - break; - case TYPE_F128: - REMINDER("Float 128 not complete"); - expr->const_expr.fxx.f = DBL_MIN; - break; - default: - UNREACHABLE; - } - return true; - } - } - if (name == kw_max) - { - if (type_is_integer(canonical)) - { - expr->expr_kind = EXPR_CONST; - expr->const_expr.const_kind = CONST_INTEGER; - expr->type = parent->type; - expr->resolve_status = RESOLVE_DONE; - expr->const_expr.ixx.type = kind; - switch (kind) - { - case TYPE_I8: - expr->const_expr.ixx.i = (Int128){ 0, 0x7F }; - break; - case TYPE_I16: - expr->const_expr.ixx.i = (Int128){ 0, 0x7FFF }; - break; - case TYPE_I32: - expr->const_expr.ixx.i = (Int128){ 0, 0x7FFFFFFFLL }; - break; - case TYPE_I64: - expr->const_expr.ixx.i = (Int128){ 0, 0x7FFFFFFFFFFFFFFFLL }; - break; - case TYPE_I128: - expr->const_expr.ixx.i = (Int128){ 0x7FFFFFFFFFFFFFFFLL, 0xFFFFFFFFFFFFFFFFLL }; - break; - case TYPE_U8: - expr->const_expr.ixx.i = (Int128){ 0, 0xFF }; - break; - case TYPE_U16: - expr->const_expr.ixx.i = (Int128){ 0, 0xFFFF }; - break; - case TYPE_U32: - expr->const_expr.ixx.i = (Int128){ 0, 0xFFFFFFFFLL }; - break; - case TYPE_U64: - expr->const_expr.ixx.i = (Int128){ 0, 0xFFFFFFFFFFFFFFFFLL }; - break; - case TYPE_U128: - expr->const_expr.ixx.i = (Int128){ 0xFFFFFFFFFFFFFFFFLL, 0xFFFFFFFFFFFFFFFFLL }; - break; - default: - UNREACHABLE - } - return true; - } - if (type_is_float(canonical)) - { - expr->expr_kind = EXPR_CONST; - expr->const_expr.const_kind = CONST_FLOAT; - expr->type = parent->type; - expr->resolve_status = RESOLVE_DONE; - expr->const_expr.fxx.type = kind; - switch (kind) - { - case TYPE_F32: - expr->const_expr.fxx.f = FLT_MAX; - break; - case TYPE_F64: - expr->const_expr.fxx.f = DBL_MAX; - break; - case TYPE_F128: - REMINDER("Float 128 not complete"); - expr->const_expr.fxx.f = DBL_MAX; - break; - default: - UNREACHABLE; - } - return true; - } - } - } - // 3. Handle float.nan, double.inf etc - if (!is_const && type_is_float(canonical)) - { - if (name == kw_nan) - { - expr->expr_kind = EXPR_CONST; - expr->const_expr.const_kind = CONST_FLOAT; - expr->const_expr.fxx = (Float) { nan(""), canonical->type_kind }; - expr->type = parent->type; - expr->resolve_status = RESOLVE_DONE; - return true; - } - if (name == kw_inf) - { - expr->expr_kind = EXPR_CONST; - expr->const_expr.const_kind = CONST_FLOAT; - expr->const_expr.fxx = (Float) { INFINITY, parent->type->canonical->type_kind }; - expr->type = parent->type->canonical; - expr->resolve_status = RESOLVE_DONE; - return true; - } + if (sema_expr_apply_type_property(context, expr, canonical, name)) return true; } if (!type_may_have_sub_elements(canonical)) @@ -3383,7 +3248,6 @@ static inline bool sema_expr_analyse_type_access(SemaContext *context, Expr *exp break; case DECL_FAULT: unit_register_external_symbol(context->compilation_unit, decl); - if (is_const) { if (!sema_expr_analyse_enum_constant(expr, name, decl)) @@ -3413,14 +3277,12 @@ static inline bool sema_expr_analyse_type_access(SemaContext *context, Expr *exp add_members_to_context(context, decl); member = sema_resolve_symbol_in_current_dynamic_scope(context, name); SCOPE_END; - if (!member) { SEMA_ERROR(expr, "No method or inner struct/union '%s.%s' found.", type_to_error_string(decl->type), name); return false; } - if (member->decl_kind == DECL_VAR) { expr->expr_kind = EXPR_TYPEINFO; @@ -3447,111 +3309,282 @@ static inline bool sema_expr_analyse_type_access(SemaContext *context, Expr *exp return true; } -static inline void sema_rewrite_typeid_kind(Expr *expr, Expr *parent, Expr *current_parent) +static inline void sema_rewrite_typeid_kind(Expr *expr, Expr *parent) { Module *module = global_context_find_module(kw_std__core__types); Decl *type_kind = module ? module_find_symbol(module, kw_typekind) : NULL; Type *type_for_kind = type_kind ? type_kind->type : type_char; - if (current_parent->expr_kind == EXPR_CONST) - { - unsigned val = type_get_introspection_kind(current_parent->const_expr.typeid->type_kind); - assert(type_for_kind->type_kind == TYPE_ENUM); - expr_rewrite_to_int_const(expr, type_flatten(type_for_kind), val, false); - cast(expr, type_for_kind); - return; - } expr->expr_kind = EXPR_TYPEID_INFO; expr->typeid_info_expr.parent = exprid(parent); expr->typeid_info_expr.kind = TYPEID_INFO_KIND; expr->type = type_for_kind; } -static inline bool sema_rewrite_typeid_inner(Expr *expr, Expr *parent, Expr *current_parent) + +static inline bool sema_create_const_kind(SemaContext *context, Expr *expr, Type *type) { - if (current_parent->expr_kind == EXPR_CONST) + Module *module = global_context_find_module(kw_std__core__types); + Decl *type_kind = module ? module_find_symbol(module, kw_typekind) : NULL; + Type *type_for_kind = type_kind ? type_kind->type : type_char; + unsigned val = type_get_introspection_kind(type->type_kind); + assert(type_for_kind->type_kind == TYPE_ENUM); + expr_rewrite_to_int_const(expr, type_flatten(type_for_kind), val, false); + return cast(expr, type_for_kind); +} + +static inline bool sema_create_const_len(SemaContext *context, Expr *expr, Type *type) +{ + assert(type == type_flatten_distinct(type) && "Should be flattened already."); + size_t len; + switch (type->type_kind) { - Type *type = type_flatten_distinct(current_parent->const_expr.typeid); - Type *inner = NULL; - switch (type->type_kind) - { - case TYPE_POINTER: - inner = type->pointer; - break; - case TYPE_FAILABLE: - inner = type->failable; - break; - case TYPE_DISTINCT: - inner = type->decl->distinct_decl.base_type->canonical; - break; - case TYPE_ARRAY: - case TYPE_FLEXIBLE_ARRAY: - case TYPE_SUBARRAY: - case TYPE_INFERRED_ARRAY: - case TYPE_VECTOR: - inner = type->array.base; - break; - default: - inner = NULL; - break; - } - if (!inner) - { - SEMA_ERROR(expr, "Cannot %s does not have a property 'inner'.", type_quoted_error_string(current_parent->const_expr.typeid)); + case TYPE_ARRAY: + case TYPE_VECTOR: + len = type->array.len; + break; + case TYPE_ENUM: + case TYPE_FAULTTYPE: + len = vec_size(type->decl->enums.values); + break; + case TYPE_INFERRED_ARRAY: + case TYPE_FLEXIBLE_ARRAY: + case TYPE_SUBARRAY: + default: return false; - } - expr_replace(expr, current_parent); - expr->const_expr.typeid = inner; - return true; } - expr->expr_kind = EXPR_TYPEID_INFO; - expr->typeid_info_expr.parent = exprid(parent); - expr->typeid_info_expr.kind = TYPEID_INFO_INNER; - expr->type = type_typeid; + expr_rewrite_to_int_const(expr, type_usize, len, true); return true; } -static inline bool sema_rewrite_typeid_len(Expr *expr, Expr *parent, Expr *current_parent) +static inline bool sema_create_const_inner(SemaContext *context, Expr *expr, Type *type) { - if (current_parent->expr_kind == EXPR_CONST) + Type *inner = NULL; + switch (type->type_kind) { - Type *type = type_flatten_distinct(current_parent->const_expr.typeid); - size_t len; - switch (type->type_kind) + case TYPE_POINTER: + inner = type->pointer; + break; + case TYPE_FAILABLE: + inner = type->failable; + break; + case TYPE_DISTINCT: + inner = type->decl->distinct_decl.base_type->canonical; + break; + case TYPE_ENUM: + inner = type->decl->enums.type_info->type->canonical; + break; + case TYPE_ARRAY: + case TYPE_FLEXIBLE_ARRAY: + case TYPE_SUBARRAY: + case TYPE_INFERRED_ARRAY: + case TYPE_VECTOR: + inner = type->array.base; + break; + default: + return false; + } + expr->expr_kind = EXPR_CONST; + expr->const_expr.const_kind = CONST_TYPEID; + expr->const_expr.typeid = inner->canonical; + return true; +} + +static inline bool sema_create_const_min(SemaContext *context, Expr *expr, Type *type, Type *flat) +{ + if (type_is_float(flat)) + { + expr->expr_kind = EXPR_CONST; + expr->const_expr.const_kind = CONST_FLOAT; + expr->type = type; + expr->resolve_status = RESOLVE_DONE; + expr->const_expr.fxx.type = flat->type_kind; + switch (flat->type_kind) { - case TYPE_ARRAY: - case TYPE_FLEXIBLE_ARRAY: - case TYPE_SUBARRAY: - case TYPE_INFERRED_ARRAY: - case TYPE_VECTOR: - len = type->array.len; + case TYPE_F32: + expr->const_expr.fxx.f = FLT_MIN; + break; + case TYPE_F64: + expr->const_expr.fxx.f = DBL_MIN; + break; + case TYPE_F128: + REMINDER("Float 128 not complete"); + expr->const_expr.fxx.f = DBL_MIN; break; default: - SEMA_ERROR(expr, "Cannot access 'len' of non array/vector type %s.", type_quoted_error_string(current_parent->const_expr.typeid)); - return false; + UNREACHABLE; } - expr_rewrite_to_int_const(expr, type_usize, len, true); return true; } - expr->expr_kind = EXPR_TYPEID_INFO; - expr->typeid_info_expr.parent = exprid(parent); - expr->typeid_info_expr.kind = TYPEID_INFO_LEN; - expr->type = type_usize; - return true; + else if (type_is_integer(type)) + { + expr->expr_kind = EXPR_CONST; + expr->const_expr.const_kind = CONST_INTEGER; + expr->type = type; + expr->resolve_status = RESOLVE_DONE; + expr->const_expr.ixx.type = flat->type_kind; + switch (flat->type_kind) + { + case TYPE_I8: + expr->const_expr.ixx.i = (Int128){ 0, 0xFF }; + break; + case TYPE_I16: + expr->const_expr.ixx.i = (Int128){ 0, 0xFFFF }; + break; + case TYPE_I32: + expr->const_expr.ixx.i = (Int128){ 0, 0xFFFFFFFFLL }; + break; + case TYPE_I64: + expr->const_expr.ixx.i = (Int128){ 0, ~((uint64_t)0) }; + break; + case TYPE_I128: + expr->const_expr.ixx.i = (Int128){ ~((uint64_t)0), ~((uint64_t)0) }; + break; + default: + expr->const_expr.ixx.i = (Int128){ 0, 0 }; + break; + } + return true; + } + return false; } -static inline bool sema_rewrite_typeid_sizeof(Expr *expr, Expr *parent, Expr *current_parent) +static inline bool sema_create_const_max(SemaContext *context, Expr *expr, Type *type, Type *flat) { - if (current_parent->expr_kind == EXPR_CONST) + if (type_is_integer(flat)) + { + expr->expr_kind = EXPR_CONST; + expr->const_expr.const_kind = CONST_INTEGER; + expr->type = type; + expr->resolve_status = RESOLVE_DONE; + expr->const_expr.ixx.type = flat->type_kind; + switch (flat->type_kind) + { + case TYPE_I8: + expr->const_expr.ixx.i = (Int128){ 0, 0x7F }; + break; + case TYPE_I16: + expr->const_expr.ixx.i = (Int128){ 0, 0x7FFF }; + break; + case TYPE_I32: + expr->const_expr.ixx.i = (Int128){ 0, 0x7FFFFFFFLL }; + break; + case TYPE_I64: + expr->const_expr.ixx.i = (Int128){ 0, 0x7FFFFFFFFFFFFFFFLL }; + break; + case TYPE_I128: + expr->const_expr.ixx.i = (Int128){ 0x7FFFFFFFFFFFFFFFLL, 0xFFFFFFFFFFFFFFFFLL }; + break; + case TYPE_U8: + expr->const_expr.ixx.i = (Int128){ 0, 0xFF }; + break; + case TYPE_U16: + expr->const_expr.ixx.i = (Int128){ 0, 0xFFFF }; + break; + case TYPE_U32: + expr->const_expr.ixx.i = (Int128){ 0, 0xFFFFFFFFLL }; + break; + case TYPE_U64: + expr->const_expr.ixx.i = (Int128){ 0, 0xFFFFFFFFFFFFFFFFLL }; + break; + case TYPE_U128: + expr->const_expr.ixx.i = (Int128){ 0xFFFFFFFFFFFFFFFFLL, 0xFFFFFFFFFFFFFFFFLL }; + break; + default: + UNREACHABLE + } + return true; + } + else if (type_is_float(flat)) + { + expr->expr_kind = EXPR_CONST; + expr->const_expr.const_kind = CONST_FLOAT; + expr->type = type; + expr->resolve_status = RESOLVE_DONE; + expr->const_expr.fxx.type = flat->type_kind; + switch (flat->type_kind) + { + case TYPE_F32: + expr->const_expr.fxx.f = FLT_MAX; + break; + case TYPE_F64: + expr->const_expr.fxx.f = DBL_MAX; + break; + case TYPE_F128: + REMINDER("Float 128 not complete"); + expr->const_expr.fxx.f = DBL_MAX; + break; + default: + UNREACHABLE; + } + return true; + } + return false; +} + +static bool sema_expr_rewrite_typeid_call(Expr *expr, Expr *typeid, TypeIdInfoKind kind, Type *result_type) +{ + expr->expr_kind = EXPR_TYPEID_INFO; + expr->typeid_info_expr.parent = exprid(typeid); + expr->typeid_info_expr.kind = kind; + expr->type = result_type; + return true; +} +static bool sema_expr_apply_typeid_property(SemaContext *context, Expr *expr, Expr *typeid, const char *kw) +{ + if (typeid->expr_kind == EXPR_CONST) + { + if (kw_min == kw) return false; + if (kw_min == kw) return false; + if (kw_inf == kw) return false; + if (kw_nan == kw) return false; + return sema_expr_apply_type_property(context, expr, typeid->const_expr.typeid, kw); + } + if (kw == kw_kind) + { + sema_rewrite_typeid_kind(expr, typeid); + return true; + } + if (kw == kw_inner) return sema_expr_rewrite_typeid_call(expr, typeid, TYPEID_INFO_INNER, type_typeid); + if (kw == kw_len) return sema_expr_rewrite_typeid_call(expr, typeid, TYPEID_INFO_LEN, type_usize); + if (kw == kw_sizeof) return sema_expr_rewrite_typeid_call(expr, typeid, TYPEID_INFO_SIZEOF, type_usize); + if (kw == kw_names) return sema_expr_rewrite_typeid_call(expr, typeid, TYPEID_INFO_NAMES, type_get_subarray(type_chars)); + return false; +} + +static bool sema_expr_apply_type_property(SemaContext *context, Expr *expr, Type *type, const char *kw) +{ + assert(type == type->canonical); + if (kw == kw_sizeof) { - Type *type = type_flatten_distinct(current_parent->const_expr.typeid); expr_rewrite_to_int_const(expr, type_usize, type_size(type), true); return true; } - expr->expr_kind = EXPR_TYPEID_INFO; - expr->typeid_info_expr.parent = exprid(parent); - expr->typeid_info_expr.kind = TYPEID_INFO_SIZEOF; - expr->type = type_usize; - return true; + if (kw == kw_kind) return sema_create_const_kind(context, expr, type); + if (kw == kw_inner) return sema_create_const_inner(context, expr, type); + + Type *flat = type_flatten_distinct(type); + if (kw == kw_len) return sema_create_const_len(context, expr, type); + if (kw == kw_min) return sema_create_const_min(context, expr, type, flat); + if (kw == kw_max) return sema_create_const_max(context, expr, type, flat); + if (kw == kw_nan && type_is_float(flat)) + { + expr->expr_kind = EXPR_CONST; + expr->const_expr.const_kind = CONST_FLOAT; + expr->const_expr.fxx = (Float) { nan(""), flat->type_kind }; + expr->type = type; + expr->resolve_status = RESOLVE_DONE; + return true; + } + if (kw == kw_inf && type_is_float(flat)) + { + expr->expr_kind = EXPR_CONST; + expr->const_expr.const_kind = CONST_FLOAT; + expr->const_expr.fxx = (Float) { INFINITY, flat->type_kind }; + expr->type = type; + expr->resolve_status = RESOLVE_DONE; + return true; + } + return false; } /** @@ -3627,9 +3660,7 @@ static inline bool sema_expr_analyse_access(SemaContext *context, Expr *expr) if (kw_type == kw && flat_type->type_kind == TYPE_ANY) { - expr->expr_kind = EXPR_TYPEOFANY; - expr->inner_expr = parent; - expr->type = type_typeid; + expr_rewrite_to_builtin_access(context, expr, parent, ACCESS_TYPEOFANY, type_typeid); return true; } @@ -3640,10 +3671,7 @@ CHECK_DEEPER: { if (flat_type->type_kind == TYPE_SUBARRAY) { - expr->expr_kind = EXPR_LEN; - expr->len_expr.inner = parent; - expr->type = type_usize; - expr->resolve_status = RESOLVE_DONE; + expr_rewrite_to_builtin_access(context, expr, current_parent, ACCESS_LEN, type_usize); return true; } if (flat_type->type_kind == TYPE_ARRAY || flat_type->type_kind == TYPE_VECTOR) @@ -3654,23 +3682,9 @@ CHECK_DEEPER: } if (flat_type->type_kind == TYPE_TYPEID) { - if (kw == kw_kind) - { - sema_rewrite_typeid_kind(expr, parent, current_parent); - return true; - } - if (kw == kw_inner) - { - return sema_rewrite_typeid_inner(expr, parent, current_parent); - } - if (kw == kw_len) - { - return sema_rewrite_typeid_len(expr, parent, current_parent); - } - if (kw == kw_sizeof) - { - return sema_rewrite_typeid_sizeof(expr, parent, current_parent); - } + if (sema_expr_apply_typeid_property(context, expr, parent, kw)) return true; + SEMA_ERROR(identifier, "'%s' is not a valid proprty for typeid.", kw); + return false; } // Hard coded ptr on subarrays and variant @@ -3678,18 +3692,12 @@ CHECK_DEEPER: { if (flat_type->type_kind == TYPE_SUBARRAY) { - expr->expr_kind = EXPR_PTR; - expr->inner_expr = parent; - expr->type = type_get_ptr(flat_type->array.base); - expr->resolve_status = RESOLVE_DONE; + expr_rewrite_to_builtin_access(context, expr, current_parent, ACCESS_PTR, type_get_ptr(flat_type->array.base)); return true; } if (flat_type->type_kind == TYPE_ANY) { - expr->expr_kind = EXPR_PTR; - expr->inner_expr = parent; - expr->type = type_voidptr; - expr->resolve_status = RESOLVE_DONE; + expr_rewrite_to_builtin_access(context, expr, current_parent, ACCESS_PTR, type_voidptr); return true; } } @@ -3698,8 +3706,34 @@ CHECK_DEEPER: { if (type->type_kind == TYPE_ENUM) { - if (!cast(parent, type->decl->enums.type_info->type)) return false; - expr_replace(expr, parent); + if (!cast(current_parent, type->decl->enums.type_info->type)) return false; + expr_replace(expr, current_parent); + return true; + } + } + if (kw == kw_nameof) + { + if (type->type_kind == TYPE_ENUM) + { + if (current_parent->expr_kind == EXPR_CONST) + { + expr_rewrite_to_string(expr, current_parent->const_expr.enum_val->name); + return true; + } + else + { + expr_rewrite_to_builtin_access(context, expr, current_parent, ACCESS_ENUMNAME, type_chars); + return true; + } + } + if (type->type_kind == TYPE_FAULTTYPE || type->type_kind == TYPE_ANYERR) + { + if (current_parent->expr_kind == EXPR_CONST) + { + expr_rewrite_to_string(expr, current_parent->const_expr.enum_val->name); + return true; + } + expr_rewrite_to_builtin_access(context, expr, current_parent, ACCESS_FAULTNAME, type_chars); return true; } } @@ -3722,7 +3756,7 @@ CHECK_DEEPER: if (member && decl_is_enum_kind(decl) && parent->expr_kind == EXPR_CONST) { assert(parent->const_expr.const_kind == CONST_ENUM); - Expr *copy_init = expr_macro_copy(parent->const_expr.enum_val->enum_constant.args[member->var.index]); + Expr *copy_init = expr_macro_copy(current_parent->const_expr.enum_val->enum_constant.args[member->var.index]); expr_replace(expr, copy_init); return true; } @@ -7324,7 +7358,7 @@ static inline bool sema_expr_analyse_ct_conv(SemaContext *c, Expr *expr) bool result; switch (expr->ct_call_expr.token_type) { - case TOKEN_CT_CONVERTABLE: + case TOKEN_CT_CONVERTIBLE: result = cast_may_implicit(from_type, to_type, true, false); break; case TOKEN_CT_CASTABLE: @@ -7398,7 +7432,6 @@ static inline bool sema_analyse_expr_dispatch(SemaContext *context, Expr *expr) case EXPR_TRY_UNWRAP_CHAIN: case EXPR_TRY_UNWRAP: case EXPR_CATCH_UNWRAP: - case EXPR_PTR: case EXPR_VARIANTSWITCH: case EXPR_TYPEID_INFO: UNREACHABLE @@ -7408,7 +7441,7 @@ static inline bool sema_analyse_expr_dispatch(SemaContext *context, Expr *expr) if (!sema_expr_analyse_ct_stringify(context, expr)) return false; return true; case EXPR_ARGV_TO_SUBARRAY: - expr->type = type_get_subarray(type_get_subarray(type_char)); + expr->type = type_get_subarray(type_chars); return true; case EXPR_DECL: if (!sema_analyse_var_decl(context, expr->decl_expr, true)) return false; @@ -7432,9 +7465,8 @@ static inline bool sema_analyse_expr_dispatch(SemaContext *context, Expr *expr) return sema_expr_analyse_compiler_const(context, expr); case EXPR_POISONED: return false; - case EXPR_LEN: case EXPR_SLICE_ASSIGN: - case EXPR_TYPEOFANY: + case EXPR_BUILTIN_ACCESS: // Created during semantic analysis UNREACHABLE case EXPR_MACRO_BLOCK: diff --git a/src/compiler/sema_stmts.c b/src/compiler/sema_stmts.c index de6babd18..fa41e51d3 100644 --- a/src/compiler/sema_stmts.c +++ b/src/compiler/sema_stmts.c @@ -1139,9 +1139,10 @@ static inline bool sema_analyse_foreach_stmt(SemaContext *context, Ast *statemen } else { - len_call = expr_new(EXPR_LEN, enumerator->span); + len_call = expr_new(EXPR_BUILTIN_ACCESS, enumerator->span); if (!sema_analyse_expr(context, enum_val)) return false; - len_call->len_expr.inner = enum_val; + len_call->builtin_access_expr.inner = exprid(enum_val); + len_call->builtin_access_expr.kind = ACCESS_LEN; len_call->resolve_status = RESOLVE_DONE; len_call->type = type_isize; } @@ -2087,9 +2088,7 @@ static bool sema_analyse_switch_stmt(SemaContext *context, Ast *statement) inner->type = type_any; inner->resolve_status = RESOLVE_DONE; } - last->type = type_typeid; - last->expr_kind = EXPR_TYPEOFANY; - last->inner_expr = inner; + expr_rewrite_to_builtin_access(context, last, inner, ACCESS_TYPEOFANY, type_typeid); switch_type = type_typeid; cond->type = type_typeid; } diff --git a/src/compiler/symtab.c b/src/compiler/symtab.c index bd1e95e8f..1c4bd533d 100644 --- a/src/compiler/symtab.c +++ b/src/compiler/symtab.c @@ -43,8 +43,8 @@ const char *kw_std__core; const char *kw_std__core__types; const char *kw_typekind; -const char *kw_castable; -const char *kw_convertable; +const char *kw_nameof; +const char *kw_names; const char *kw_in; const char *kw_out; const char *kw_inout; @@ -141,6 +141,8 @@ void symtab_init(uint32_t capacity) kw_std__core = KW_DEF("std::core"); kw_std__core__types = KW_DEF("std::core::types"); kw_sizeof = KW_DEF("sizeof"); + kw_nameof = KW_DEF("nameof"); + kw_names = KW_DEF("names"); kw_in = KW_DEF("in"); kw_out = KW_DEF("out"); kw_inout = KW_DEF("inout"); @@ -231,6 +233,7 @@ void symtab_init(uint32_t capacity) attribute_list[ATTRIBUTE_OPERATOR] = KW_DEF("@operator"); attribute_list[ATTRIBUTE_PURE] = kw_at_pure; attribute_list[ATTRIBUTE_REFLECT] = KW_DEF("@reflect"); + attribute_list[ATTRIBUTE_OBFUSCATE] = KW_DEF("@obfuscate"); attribute_list[ATTRIBUTE_BUILTIN] = KW_DEF("@builtin"); attribute_list[ATTRIBUTE_MAYDISCARD] = KW_DEF("@maydiscard"); attribute_list[ATTRIBUTE_NODISCARD] = KW_DEF("@nodiscard"); diff --git a/src/compiler/tokens.c b/src/compiler/tokens.c index 573960b37..dd97e2c66 100644 --- a/src/compiler/tokens.c +++ b/src/compiler/tokens.c @@ -233,8 +233,6 @@ const char *token_type_to_string(TokenType type) return "foreach"; case TOKEN_FN: return "fn"; - case TOKEN_FUNC: - return "func"; case TOKEN_GENERIC: return "generic"; case TOKEN_IF: @@ -374,8 +372,8 @@ const char *token_type_to_string(TokenType type) return "$switch"; case TOKEN_CT_TYPEOF: return "$typeof"; - case TOKEN_CT_CONVERTABLE: - return "$convertable"; + case TOKEN_CT_CONVERTIBLE: + return "$convertible"; case TOKEN_CT_CASTABLE: return "$castable"; case TOKEN_CT_STRINGIFY: diff --git a/src/compiler/types.c b/src/compiler/types.c index e9a1e03ca..f81678a90 100644 --- a/src/compiler/types.c +++ b/src/compiler/types.c @@ -43,6 +43,7 @@ Type *type_usize = &t.usz; Type *type_anyerr = &t.anyerr; Type *type_complist = &t.ctlist; Type *type_anyfail = &t.anyfail; +Type *type_chars = NULL; static unsigned size_subarray; static AlignSize alignment_subarray; @@ -1213,7 +1214,6 @@ void type_setup(PlatformTarget *target) type_create("complist", &t.ctlist, TYPE_UNTYPED_LIST, 1, 1, 1); type_create("void!", &t.anyfail, TYPE_FAILABLE_ANY, 1, 1, 1); type_init("typeid", &t.typeid, TYPE_TYPEID, target->width_pointer, target->align_pointer); - type_init("void*", &t.voidstar, TYPE_POINTER, target->width_pointer, target->align_pointer); create_type_cache(type_void); type_void->type_cache[0] = &t.voidstar; @@ -1222,7 +1222,6 @@ void type_setup(PlatformTarget *target) type_create_alias("usize", &t.usz, type_int_unsigned_by_bitsize(target->width_pointer)); type_create_alias("isize", &t.isz, type_int_signed_by_bitsize(target->width_pointer)); - type_create_alias("uptr", &t.uptr, type_int_unsigned_by_bitsize(target->width_pointer)); type_create_alias("iptr", &t.iptr, type_int_signed_by_bitsize(target->width_pointer)); @@ -1232,6 +1231,8 @@ void type_setup(PlatformTarget *target) alignment_subarray = MAX(type_abi_alignment(&t.voidstar), type_abi_alignment(t.usz.canonical)); size_subarray = (unsigned)(alignment_subarray * 2); type_init("anyerr", &t.anyerr, TYPE_ANYERR, target->width_pointer, target->align_pointer); + type_chars = type_get_subarray(type_char); + } int type_kind_bitsize(TypeKind kind) diff --git a/src/version.h b/src/version.h index 21ededcee..6a508efb7 100644 --- a/src/version.h +++ b/src/version.h @@ -1 +1 @@ -#define COMPILER_VERSION "0.2.23" \ No newline at end of file +#define COMPILER_VERSION "0.2.24" \ No newline at end of file diff --git a/test/test_suite/compile_time_introspection/sizeof_errors.c3 b/test/test_suite/compile_time_introspection/sizeof_errors.c3 index a86de52ed..300493acb 100644 --- a/test/test_suite/compile_time_introspection/sizeof_errors.c3 +++ b/test/test_suite/compile_time_introspection/sizeof_errors.c3 @@ -40,7 +40,7 @@ fn void l() fn void m() { - int v = $sizeof(int[4].len); // #error: 'int[4]' does not have a property 'len' + int v = $sizeof(int[4].len); } fn void n() diff --git a/test/test_suite/enumerations/enum_associated_value.c3t b/test/test_suite/enumerations/enum_associated_value.c3t index f6a117193..fcf37b228 100644 --- a/test/test_suite/enumerations/enum_associated_value.c3t +++ b/test/test_suite/enumerations/enum_associated_value.c3t @@ -18,8 +18,10 @@ fn void main() /* #expect: test.ll +@.enum.0 = internal constant [2 x i8] c"A\00", align 1 +@.enum.1 = internal constant [2 x i8] c"B\00", align 1 @"ct$uint" = linkonce constant %.introspect { i8 3, i64 4, i64 0, i64 0, [0 x i64] zeroinitializer }, align 8 -@"ct$test_Foo" = linkonce constant %.introspect { i8 8, i64 4, i64 ptrtoint (%.introspect* @"ct$uint" to i64), i64 2, [0 x i64] zeroinitializer }, align 8 +@"ct$test_Foo" = linkonce constant { i8, i64, i64, i64, [2 x %"char[]"] } { i8 8, i64 4, i64 ptrtoint (%.introspect* @"ct$uint" to i64), i64 2, [2 x %"char[]"] [%"char[]" { i8* getelementptr inbounds ([2 x i8], [2 x i8]* @.enum.0, i64 0, i64 0), i64 1 }, %"char[]" { i8* getelementptr inbounds ([2 x i8], [2 x i8]* @.enum.1, i64 0, i64 0), 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 diff --git a/test/test_suite/enumerations/enum_invalid_param.c3 b/test/test_suite/enumerations/enum_invalid_param.c3 new file mode 100644 index 000000000..ff86eb5f9 --- /dev/null +++ b/test/test_suite/enumerations/enum_invalid_param.c3 @@ -0,0 +1,9 @@ +enum Test : int (int a, int b) +{ + FOO(1, 2) +} + +enum Test2 : int (int a, int nameof) // #error: 'nameof' is not a valid parameter name for enums +{ + FOO(1, 2) +} diff --git a/test/test_suite/enumerations/enum_same_param.c3 b/test/test_suite/enumerations/enum_same_param.c3 new file mode 100644 index 000000000..1196ed7ca --- /dev/null +++ b/test/test_suite/enumerations/enum_same_param.c3 @@ -0,0 +1,9 @@ +enum Test : int (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_suite/errors/anyerr_void.c3t b/test/test_suite/errors/anyerr_void.c3t index 65156ad91..3222b70e4 100644 --- a/test/test_suite/errors/anyerr_void.c3t +++ b/test/test_suite/errors/anyerr_void.c3t @@ -28,7 +28,7 @@ fn void main() define i64 @anyerr_void_errorThing() #0 { entry: - ret i64 ptrtoint (i8* @"anyerr_void_MyError$BAR" to i64) + ret i64 ptrtoint (%.fault* @"anyerr_void_MyError$BAR" to i64) } define i64 @anyerr_void_errorThing2() #0 { @@ -63,8 +63,8 @@ noerr_block: ; preds = %after.errcheck, %er store i64 %1, i64* %z, align 8 %2 = load i64, i64* %z, align 8 call void (i8*, ...) @printf(i8* getelementptr inbounds ([11 x i8], [11 x i8]* @.str, i32 0, i32 0), i64 %2) - call void (i8*, ...) @printf(i8* getelementptr inbounds ([11 x i8], [11 x i8]* @.str.1, i32 0, i32 0), i64 ptrtoint (i8* @"anyerr_void_MyError$BAR" to i64)) - call void (i8*, ...) @printf(i8* getelementptr inbounds ([11 x i8], [11 x i8]* @.str.2, i32 0, i32 0), i64 ptrtoint (i8* @"anyerr_void_MyError$FOO" to i64)) + call void (i8*, ...) @printf(i8* getelementptr inbounds ([11 x i8], [11 x i8]* @.str.2, i32 0, i32 0), i64 ptrtoint (%.fault* @"anyerr_void_MyError$BAR" to i64)) + call void (i8*, ...) @printf(i8* getelementptr inbounds ([11 x i8], [11 x i8]* @.str.3, i32 0, i32 0), i64 ptrtoint (%.fault* @"anyerr_void_MyError$FOO" to i64)) store i64 0, i64* %error_var1, align 8 %3 = call i64 @anyerr_void_errorThing2() %not_err2 = icmp eq i64 %3, 0 @@ -81,6 +81,6 @@ noerr_block5: ; preds = %after.errcheck4, %e %4 = load i64, i64* %error_var1, align 8 store i64 %4, i64* %z, align 8 %5 = load i64, i64* %z, align 8 - call void (i8*, ...) @printf(i8* getelementptr inbounds ([11 x i8], [11 x i8]* @.str.3, i32 0, i32 0), i64 %5) + call void (i8*, ...) @printf(i8* getelementptr inbounds ([11 x i8], [11 x i8]* @.str.4, i32 0, i32 0), i64 %5) ret void } \ No newline at end of file diff --git a/test/test_suite/errors/error_regression_2.c3t b/test/test_suite/errors/error_regression_2.c3t index 5b43e14bc..66e555c19 100644 --- a/test/test_suite/errors/error_regression_2.c3t +++ b/test/test_suite/errors/error_regression_2.c3t @@ -168,7 +168,7 @@ cond.rhs: ; preds = %entry br label %cond.phi cond.phi: ; preds = %cond.rhs, %cond.lhs - %val = phi %"char[]" [ %6, %cond.lhs ], [ { i8* getelementptr inbounds ([8 x i8], [8 x i8]* @.str.26, i32 0, i32 0), i64 7 }, %cond.rhs ] + %val = phi %"char[]" [ %6, %cond.lhs ], [ { i8* getelementptr inbounds ([8 x i8], [8 x i8]* @.str.28, i32 0, i32 0), i64 7 }, %cond.rhs ] store %"char[]" %val, %"char[]"* %title, align 8 %7 = getelementptr inbounds %"char[]", %"char[]"* %title, i32 0, i32 1 %8 = load i64, i64* %7, align 8 @@ -178,8 +178,8 @@ cond.phi: ; preds = %cond.rhs, %cond.lhs %11 = getelementptr inbounds %Summary, %Summary* %0, i32 0, i32 1 %12 = load i8, i8* %11, align 8 %13 = trunc i8 %12 to i1 - %ternary = select i1 %13, i8* getelementptr inbounds ([5 x i8], [5 x i8]* @.str.28, i32 0, i32 0), i8* getelementptr inbounds ([6 x i8], [6 x i8]* @.str.29, i32 0, i32 0) - %14 = call i32 (i8*, i8*, ...) @fprintf(i8* %1, i8* getelementptr inbounds ([36 x i8], [36 x i8]* @.str.27, i32 0, i32 0), i32 %uisitrunc, i8* %10, i8* %ternary) + %ternary = select i1 %13, i8* getelementptr inbounds ([5 x i8], [5 x i8]* @.str.30, i32 0, i32 0), i8* getelementptr inbounds ([6 x i8], [6 x i8]* @.str.31, i32 0, i32 0) + %14 = call i32 (i8*, i8*, ...) @fprintf(i8* %1, i8* getelementptr inbounds ([36 x i8], [36 x i8]* @.str.29, i32 0, i32 0), i32 %uisitrunc, i8* %10, i8* %ternary) ret void } @@ -320,7 +320,7 @@ entry: br i1 %12, label %if.then, label %if.exit if.then: ; preds = %entry - ret i64 ptrtoint (i8* @"test_ReadError$BAD_READ" to i64) + ret i64 ptrtoint (%.fault* @"test_ReadError$BAD_READ" to i64) if.exit: ; preds = %entry %13 = bitcast %"char[]"* %url to { i8*, i64 }* @@ -328,7 +328,7 @@ if.exit: ; preds = %entry %lo3 = load i8*, i8** %14, align 8 %15 = getelementptr inbounds { i8*, i64 }, { i8*, i64 }* %13, i32 0, i32 1 %hi4 = load i64, i64* %15, align 8 - store %"char[]" { i8* getelementptr inbounds ([13 x i8], [13 x i8]* @.str.1, i32 0, i32 0), i64 12 }, %"char[]"* %taddr5, align 8 + store %"char[]" { i8* getelementptr inbounds ([13 x i8], [13 x i8]* @.str.3, i32 0, i32 0), i64 12 }, %"char[]"* %taddr5, align 8 %16 = bitcast %"char[]"* %taddr5 to { i8*, i64 }* %17 = getelementptr inbounds { i8*, i64 }, { i8*, i64 }* %16, i32 0, i32 0 %lo6 = load i8*, i8** %17, align 8 @@ -352,7 +352,7 @@ if.exit9: ; preds = %if.exit %lo10 = load i8*, i8** %25, align 8 %26 = getelementptr inbounds { i8*, i64 }, { i8*, i64 }* %24, i32 0, i32 1 %hi11 = load i64, i64* %26, align 8 - store %"char[]" { i8* getelementptr inbounds ([14 x i8], [14 x i8]* @.str.2, i32 0, i32 0), i64 13 }, %"char[]"* %taddr12, align 8 + store %"char[]" { i8* getelementptr inbounds ([14 x i8], [14 x i8]* @.str.4, i32 0, i32 0), i64 13 }, %"char[]"* %taddr12, align 8 %27 = bitcast %"char[]"* %taddr12 to { i8*, i64 }* %28 = getelementptr inbounds { i8*, i64 }, { i8*, i64 }* %27, i32 0, i32 0 %lo13 = load i8*, i8** %28, align 8 @@ -376,7 +376,7 @@ if.then15: ; preds = %if.exit9 br i1 %not, label %if.then19, label %if.exit20 if.then19: ; preds = %if.then15 - store i64 ptrtoint (i8* @"test_ReadError$OUT_OF_MEMORY" to i64), i64* %error_var, align 8 + store i64 ptrtoint (%.fault* @"test_ReadError$OUT_OF_MEMORY" to i64), i64* %error_var, align 8 br label %guard_block if.exit20: ; preds = %if.then15 @@ -404,7 +404,7 @@ if.exit21: ; preds = %if.exit9 %lo22 = load i8*, i8** %45, align 8 %46 = getelementptr inbounds { i8*, i64 }, { i8*, i64 }* %44, i32 0, i32 1 %hi23 = load i64, i64* %46, align 8 - store %"char[]" { i8* getelementptr inbounds ([12 x i8], [12 x i8]* @.str.3, i32 0, i32 0), i64 11 }, %"char[]"* %taddr24, align 8 + store %"char[]" { i8* getelementptr inbounds ([12 x i8], [12 x i8]* @.str.5, i32 0, i32 0), i64 11 }, %"char[]"* %taddr24, align 8 %47 = bitcast %"char[]"* %taddr24 to { i8*, i64 }* %48 = getelementptr inbounds { i8*, i64 }, { i8*, i64 }* %47, i32 0, i32 0 %lo25 = load i8*, i8** %48, align 8 @@ -428,7 +428,7 @@ if.then27: ; preds = %if.exit21 br i1 %not37, label %if.then38, label %if.exit39 if.then38: ; preds = %if.then27 - store i64 ptrtoint (i8* @"test_ReadError$OUT_OF_MEMORY" to i64), i64* %error_var33, align 8 + store i64 ptrtoint (%.fault* @"test_ReadError$OUT_OF_MEMORY" to i64), i64* %error_var33, align 8 br label %guard_block40 if.exit39: ; preds = %if.then27 @@ -455,7 +455,7 @@ noerr_block41: ; preds = %if.exit39 br i1 %not44, label %if.then45, label %if.exit46 if.then45: ; preds = %noerr_block41 - store i64 ptrtoint (i8* @"test_ReadError$OUT_OF_MEMORY" to i64), i64* %error_var30, align 8 + store i64 ptrtoint (%.fault* @"test_ReadError$OUT_OF_MEMORY" to i64), i64* %error_var30, align 8 br label %guard_block47 if.exit46: ; preds = %noerr_block41 @@ -483,7 +483,7 @@ if.exit49: ; preds = %if.exit21 %uisitrunc = trunc i64 %73 to i32 %74 = getelementptr inbounds %"char[]", %"char[]"* %url, i32 0, i32 0 %75 = load i8*, i8** %74, align 8 - %76 = call i32 (i8*, i64, i8*, ...) @snprintf(i8* null, i64 0, i8* getelementptr inbounds ([14 x i8], [14 x i8]* @.str.5, i32 0, i32 0), i32 %uisitrunc, i8* %75) + %76 = call i32 (i8*, i64, i8*, ...) @snprintf(i8* null, i64 0, i8* getelementptr inbounds ([14 x i8], [14 x i8]* @.str.7, i32 0, i32 0), i32 %uisitrunc, i8* %75) store i32 %76, i32* %len, align 4 %77 = load i32, i32* %len, align 4 %siuiext = sext i32 %77 to i64 @@ -495,7 +495,7 @@ if.exit49: ; preds = %if.exit21 br i1 %not50, label %if.then51, label %if.exit52 if.then51: ; preds = %if.exit49 - ret i64 ptrtoint (i8* @"test_ReadError$OUT_OF_MEMORY" to i64) + ret i64 ptrtoint (%.fault* @"test_ReadError$OUT_OF_MEMORY" to i64) if.exit52: ; preds = %if.exit49 %80 = load i8*, i8** %str, align 8 @@ -507,7 +507,7 @@ if.exit52: ; preds = %if.exit49 %uisitrunc55 = trunc i64 %83 to i32 %84 = getelementptr inbounds %"char[]", %"char[]"* %url, i32 0, i32 0 %85 = load i8*, i8** %84, align 8 - %86 = call i32 (i8*, i64, i8*, ...) @snprintf(i8* %80, i64 %add54, i8* getelementptr inbounds ([14 x i8], [14 x i8]* @.str.6, i32 0, i32 0), i32 %uisitrunc55, i8* %85) + %86 = call i32 (i8*, i64, i8*, ...) @snprintf(i8* %80, i64 %add54, i8* getelementptr inbounds ([14 x i8], [14 x i8]* @.str.8, i32 0, i32 0), i32 %uisitrunc55, i8* %85) %87 = getelementptr inbounds %Doc, %Doc* %literal57, i32 0, i32 0 %88 = bitcast %Head* %literal60 to %"char[]"** store %"char[]"* null, %"char[]"** %88, align 8 @@ -530,7 +530,7 @@ if.exit52: ; preds = %if.exit49 br i1 %not65, label %if.then66, label %if.exit67 if.then66: ; preds = %if.exit52 - store i64 ptrtoint (i8* @"test_ReadError$OUT_OF_MEMORY" to i64), i64* %error_var61, align 8 + store i64 ptrtoint (%.fault* @"test_ReadError$OUT_OF_MEMORY" to i64), i64* %error_var61, align 8 br label %guard_block68 if.exit67: ; preds = %if.exit52 @@ -557,7 +557,7 @@ noerr_block69: ; preds = %if.exit67 br i1 %not72, label %if.then73, label %if.exit74 if.then73: ; preds = %noerr_block69 - store i64 ptrtoint (i8* @"test_ReadError$OUT_OF_MEMORY" to i64), i64* %error_var58, align 8 + store i64 ptrtoint (%.fault* @"test_ReadError$OUT_OF_MEMORY" to i64), i64* %error_var58, align 8 br label %guard_block75 if.exit74: ; preds = %noerr_block69 @@ -686,7 +686,7 @@ entry: br i1 %not, label %if.then, label %if.exit if.then: ; preds = %entry - ret i64 ptrtoint (i8* @"test_TitleResult$TITLE_MISSING" to i64) + ret i64 ptrtoint (%.fault* @"test_TitleResult$TITLE_MISSING" to i64) if.exit: ; preds = %entry %5 = getelementptr inbounds %Doc, %Doc* %doc, i32 0, i32 0 @@ -699,7 +699,7 @@ if.exit: ; preds = %entry br i1 %not1, label %if.then2, label %if.exit3 if.then2: ; preds = %if.exit - ret i64 ptrtoint (i8* @"test_TitleResult$TITLE_MISSING" to i64) + ret i64 ptrtoint (%.fault* @"test_TitleResult$TITLE_MISSING" to i64) if.exit3: ; preds = %if.exit %10 = load %"char[]"*, %"char[]"** %head, align 8 @@ -761,7 +761,7 @@ err_retblock: ; preds = %error3, %error define i8* @test_bool_to_string(i8 zeroext %0) #0 { entry: %1 = trunc i8 %0 to i1 - %ternary = select i1 %1, %"char[]" { i8* getelementptr inbounds ([5 x i8], [5 x i8]* @.str.7, i32 0, i32 0), i64 4 }, %"char[]" { i8* getelementptr inbounds ([6 x i8], [6 x i8]* @.str.8, i32 0, i32 0), i64 5 } + %ternary = select i1 %1, %"char[]" { i8* getelementptr inbounds ([5 x i8], [5 x i8]* @.str.9, i32 0, i32 0), i64 4 }, %"char[]" { i8* getelementptr inbounds ([6 x i8], [6 x i8]* @.str.10, i32 0, i32 0), i64 5 } %2 = extractvalue %"char[]" %ternary, 0 ret i8* %2 } @@ -775,31 +775,31 @@ entry: switch.entry: ; preds = %entry %1 = load i64, i64* %switch, align 8 - %eq = icmp eq i64 ptrtoint (i8* @"test_TitleResult$TITLE_MISSING" to i64), %1 + %eq = icmp eq i64 ptrtoint (%.fault* @"test_TitleResult$TITLE_MISSING" to i64), %1 br i1 %eq, label %switch.case, label %next_if switch.case: ; preds = %switch.entry - ret i8* getelementptr inbounds ([9 x i8], [9 x i8]* @.str.9, i32 0, i32 0) + ret i8* getelementptr inbounds ([9 x i8], [9 x i8]* @.str.11, i32 0, i32 0) next_if: ; preds = %switch.entry - %eq1 = icmp eq i64 ptrtoint (i8* @"test_ReadError$BAD_READ" to i64), %1 + %eq1 = icmp eq i64 ptrtoint (%.fault* @"test_ReadError$BAD_READ" to i64), %1 br i1 %eq1, label %switch.case2, label %next_if3 switch.case2: ; preds = %next_if - ret i8* getelementptr inbounds ([9 x i8], [9 x i8]* @.str.10, i32 0, i32 0) + ret i8* getelementptr inbounds ([9 x i8], [9 x i8]* @.str.12, i32 0, i32 0) next_if3: ; preds = %next_if - %eq4 = icmp eq i64 ptrtoint (i8* @"test_ReadError$OUT_OF_MEMORY" to i64), %1 + %eq4 = icmp eq i64 ptrtoint (%.fault* @"test_ReadError$OUT_OF_MEMORY" to i64), %1 br i1 %eq4, label %switch.case5, label %next_if6 switch.case5: ; preds = %next_if3 - ret i8* getelementptr inbounds ([14 x i8], [14 x i8]* @.str.11, i32 0, i32 0) + ret i8* getelementptr inbounds ([14 x i8], [14 x i8]* @.str.13, i32 0, i32 0) next_if6: ; preds = %next_if3 br label %switch.default switch.default: ; preds = %next_if6 - ret i8* getelementptr inbounds ([14 x i8], [14 x i8]* @.str.12, i32 0, i32 0) + ret i8* getelementptr inbounds ([14 x i8], [14 x i8]* @.str.14, i32 0, i32 0) } ; Function Attrs: nounwind @@ -818,15 +818,15 @@ entry: %has_title.f = alloca i64, align 8 %retparam = alloca i8, align 1 %0 = getelementptr inbounds [5 x %"char[]"], [5 x %"char[]"]* %literal, i64 0, i64 0 - store %"char[]" { i8* getelementptr inbounds ([5 x i8], [5 x i8]* @.str.13, i32 0, i32 0), i64 4 }, %"char[]"* %0, align 8 + store %"char[]" { i8* getelementptr inbounds ([5 x i8], [5 x i8]* @.str.15, i32 0, i32 0), i64 4 }, %"char[]"* %0, align 8 %1 = getelementptr inbounds [5 x %"char[]"], [5 x %"char[]"]* %literal, i64 0, i64 1 - store %"char[]" { i8* getelementptr inbounds ([12 x i8], [12 x i8]* @.str.14, i32 0, i32 0), i64 11 }, %"char[]"* %1, align 8 + store %"char[]" { i8* getelementptr inbounds ([12 x i8], [12 x i8]* @.str.16, i32 0, i32 0), i64 11 }, %"char[]"* %1, align 8 %2 = getelementptr inbounds [5 x %"char[]"], [5 x %"char[]"]* %literal, i64 0, i64 2 - store %"char[]" { i8* getelementptr inbounds ([14 x i8], [14 x i8]* @.str.15, i32 0, i32 0), i64 13 }, %"char[]"* %2, align 8 + store %"char[]" { i8* getelementptr inbounds ([14 x i8], [14 x i8]* @.str.17, i32 0, i32 0), i64 13 }, %"char[]"* %2, align 8 %3 = getelementptr inbounds [5 x %"char[]"], [5 x %"char[]"]* %literal, i64 0, i64 3 - store %"char[]" { i8* getelementptr inbounds ([13 x i8], [13 x i8]* @.str.16, i32 0, i32 0), i64 12 }, %"char[]"* %3, align 8 + store %"char[]" { i8* getelementptr inbounds ([13 x i8], [13 x i8]* @.str.18, i32 0, i32 0), i64 12 }, %"char[]"* %3, align 8 %4 = getelementptr inbounds [5 x %"char[]"], [5 x %"char[]"]* %literal, i64 0, i64 4 - store %"char[]" { i8* getelementptr inbounds ([5 x i8], [5 x i8]* @.str.17, i32 0, i32 0), i64 4 }, %"char[]"* %4, align 8 + store %"char[]" { i8* getelementptr inbounds ([5 x i8], [5 x i8]* @.str.19, i32 0, i32 0), i64 4 }, %"char[]"* %4, align 8 %5 = bitcast [5 x %"char[]"]* %literal to %"char[]"* %6 = insertvalue %"char[][]" undef, %"char[]"* %5, 0 %7 = insertvalue %"char[][]" %6, i64 5, 1 @@ -859,7 +859,7 @@ loop.body: ; preds = %loop.cond %uisitrunc = trunc i64 %20 to i32 %21 = getelementptr inbounds %"char[]", %"char[]"* %url, i32 0, i32 0 %22 = load i8*, i8** %21, align 8 - %23 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([27 x i8], [27 x i8]* @.str.18, i32 0, i32 0), i32 %uisitrunc, i8* %22) + %23 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([27 x i8], [27 x i8]* @.str.20, i32 0, i32 0), i32 %uisitrunc, i8* %22) %24 = bitcast %"char[]"* %url to { i8*, i64 }* %25 = getelementptr inbounds { i8*, i64 }, { i8*, i64 }* %24, i32 0, i32 0 %lo = load i8*, i8** %25, align 8 @@ -871,10 +871,10 @@ loop.body: ; preds = %loop.cond %29 = bitcast %Summary* %summary to i8* %30 = bitcast %Summary* %result to i8* call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 8 %29, i8* align 8 %30, i32 16, i1 false) - %31 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([12 x i8], [12 x i8]* @.str.19, i32 0, i32 0)) + %31 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([12 x i8], [12 x i8]* @.str.21, i32 0, i32 0)) %32 = load i8*, i8** @__stdoutp, align 8 call void @test_Summary_print(%Summary* %summary, i8* %32) - %33 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([2 x i8], [2 x i8]* @.str.20, i32 0, i32 0)) + %33 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([2 x i8], [2 x i8]* @.str.22, i32 0, i32 0)) %34 = getelementptr inbounds %Summary, %Summary* %summary, i32 0, i32 0 %35 = load %"char[]"*, %"char[]"** %34, align 8 %ptrbool = icmp ne %"char[]"* %35, null @@ -897,7 +897,7 @@ cond.phi: ; preds = %cond.rhs, %cond.lhs %uisitrunc3 = trunc i64 %40 to i32 %41 = getelementptr inbounds %"char[]", %"char[]"* %title_sure, i32 0, i32 0 %42 = load i8*, i8** %41, align 8 - %43 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([15 x i8], [15 x i8]* @.str.22, i32 0, i32 0), i32 %uisitrunc3, i8* %42) + %43 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([15 x i8], [15 x i8]* @.str.24, i32 0, i32 0), i32 %uisitrunc3, i8* %42) %44 = bitcast %"char[]"* %url to { i8*, i64 }* %45 = getelementptr inbounds { i8*, i64 }, { i8*, i64 }* %44, i32 0, i32 0 %lo4 = load i8*, i8** %45, align 8 @@ -948,8 +948,8 @@ else_block10: ; preds = %phi_block phi_block11: ; preds = %else_block10, %after_check9 %val12 = phi i1 [ %56, %after_check9 ], [ false, %else_block10 ] - %ternary = select i1 %val12, i8* getelementptr inbounds ([5 x i8], [5 x i8]* @.str.24, i32 0, i32 0), i8* getelementptr inbounds ([6 x i8], [6 x i8]* @.str.25, i32 0, i32 0) - %57 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([23 x i8], [23 x i8]* @.str.23, i32 0, i32 0), i8* %val7, i8* %ternary) + %ternary = select i1 %val12, i8* getelementptr inbounds ([5 x i8], [5 x i8]* @.str.26, i32 0, i32 0), i8* getelementptr inbounds ([6 x i8], [6 x i8]* @.str.27, i32 0, i32 0) + %57 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([23 x i8], [23 x i8]* @.str.25, i32 0, i32 0), i8* %val7, i8* %ternary) %58 = load i64, i64* %anon, align 8 %add = add i64 %58, 1 store i64 %add, i64* %anon, align 8 diff --git a/test/test_suite/errors/failable_inits.c3t b/test/test_suite/errors/failable_inits.c3t index 6c3effea1..f3b964bb8 100644 --- a/test/test_suite/errors/failable_inits.c3t +++ b/test/test_suite/errors/failable_inits.c3t @@ -40,7 +40,7 @@ entry: %y = alloca %Bar, align 4 %error_var = alloca i64, align 8 %reterr = alloca i64, align 8 - store i64 ptrtoint (i8* @"test_Foo$MY_VAL1" to i64), i64* %x.f, align 8 + store i64 ptrtoint (%.fault* @"test_Foo$MY_VAL1" to i64), i64* %x.f, align 8 %0 = load i64, i64* %x.f, align 8 %not_err = icmp eq i64 %0, 0 br i1 %not_err, label %after_check, label %error diff --git a/test/test_suite/errors/failable_taddr_and_access.c3t b/test/test_suite/errors/failable_taddr_and_access.c3t index 41d674671..d54ff60dc 100644 --- a/test/test_suite/errors/failable_taddr_and_access.c3t +++ b/test/test_suite/errors/failable_taddr_and_access.c3t @@ -28,7 +28,8 @@ fn void main() %Foo = type { i32, i32 } @"ct$test_Foo" = linkonce constant %.introspect { i8 10, i64 8, i64 0, i64 2, [0 x i64] zeroinitializer }, align 8 -@"test_MyErr$FOO" = linkonce constant i8 1, align 1 +@"test_MyErr$FOO" = linkonce constant %.fault { i64 ptrtoint (%.introspect* @"ct$test_MyErr" to i64), %"char[]" { i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.fault, i64 0, i64 0), i64 3 } }, align 8 +@.fault = internal constant [4 x i8] c"FOO\00", align 1 @"ct$test_MyErr" = linkonce constant %.introspect { i8 9, 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 @@ -78,7 +79,7 @@ after_check2: ; preds = %after_assign br label %voiderr voiderr: ; preds = %after_check2, %after_assign - store i64 ptrtoint (i8* @"test_MyErr$FOO" to i64), i64* %z.f, align 8 + store i64 ptrtoint (%.fault* @"test_MyErr$FOO" to i64), i64* %z.f, align 8 br label %voiderr3 voiderr3: ; preds = %voiderr diff --git a/test/test_suite/errors/general_error_regression.c3t b/test/test_suite/errors/general_error_regression.c3t index d9fa1d86a..7f3da1d8f 100644 --- a/test/test_suite/errors/general_error_regression.c3t +++ b/test/test_suite/errors/general_error_regression.c3t @@ -74,19 +74,19 @@ fn void main() define void @foo_Foo_hello(i64* %0) #0 { entry: - %1 = call i32 @std_io_println(i8* getelementptr inbounds ([15 x i8], [15 x i8]* @.str.6, i32 0, i32 0)) #1 + %1 = call i32 @std_io_println(i8* getelementptr inbounds ([15 x i8], [15 x i8]* @.str.12, i32 0, i32 0)) #1 ret void } define void @foo_Bar_hello(i32* %0) #0 { entry: - %1 = call i32 @std_io_println(i8* getelementptr inbounds ([15 x i8], [15 x i8]* @.str.7, i32 0, i32 0)) #1 + %1 = call i32 @std_io_println(i8* getelementptr inbounds ([15 x i8], [15 x i8]* @.str.13, i32 0, i32 0)) #1 ret void } define void @foo_MyEnum_hello(i32* %0) #0 { entry: - %1 = call i32 @std_io_println(i8* getelementptr inbounds ([18 x i8], [18 x i8]* @.str.8, i32 0, i32 0)) #1 + %1 = call i32 @std_io_println(i8* getelementptr inbounds ([18 x i8], [18 x i8]* @.str.14, i32 0, i32 0)) #1 ret void } @@ -98,8 +98,8 @@ entry: %z = alloca i64, align 8 %b = alloca i32, align 4 %a = alloca i32, align 4 - store i64 ptrtoint (i8* @"foo_Foo$X" to i64), i64* %f, align 8 - store i64 ptrtoint (i8* @"foo_Foo$Y" to i64), i64* %ef, align 8 + store i64 ptrtoint (%.fault* @"foo_Foo$X" to i64), i64* %f, align 8 + store i64 ptrtoint (%.fault* @"foo_Foo$Y" to i64), i64* %ef, align 8 %0 = load i64, i64* %f, align 8 store i64 %0, i64* %x, align 8 %1 = load i64, i64* %x, align 8 @@ -111,27 +111,27 @@ entry: %5 = load i64, i64* %x, align 8 store i64 %5, i64* %z, align 8 %6 = load i64, i64* %z, align 8 - %7 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([7 x i8], [7 x i8]* @.str.1, i32 0, i32 0), i64 %6) - store i64 ptrtoint (i8* @"foo_Foo$W" to i64), i64* %x, align 8 + %7 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([7 x i8], [7 x i8]* @.str.7, i32 0, i32 0), i64 %6) + store i64 ptrtoint (%.fault* @"foo_Foo$W" to i64), i64* %x, align 8 %8 = load i64, i64* %x, align 8 store i64 %8, i64* %z, align 8 %9 = load i64, i64* %z, align 8 - %10 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([8 x i8], [8 x i8]* @.str.2, i32 0, i32 0), i64 %9) - store i64 ptrtoint (i8* @"foo_Foo$W1" to i64), i64* %x, align 8 + %10 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([8 x i8], [8 x i8]* @.str.8, i32 0, i32 0), i64 %9) + store i64 ptrtoint (%.fault* @"foo_Foo$W1" to i64), i64* %x, align 8 %11 = load i64, i64* %x, align 8 store i64 %11, i64* %z, align 8 %12 = load i64, i64* %z, align 8 - %13 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([8 x i8], [8 x i8]* @.str.3, i32 0, i32 0), i64 %12) - store i64 ptrtoint (i8* @"foo_Foob$X1" to i64), i64* %x, align 8 + %13 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([8 x i8], [8 x i8]* @.str.9, i32 0, i32 0), i64 %12) + store i64 ptrtoint (%.fault* @"foo_Foob$X1" to i64), i64* %x, align 8 %14 = load i64, i64* %x, align 8 store i64 %14, i64* %z, align 8 %15 = load i64, i64* %z, align 8 - %16 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([7 x i8], [7 x i8]* @.str.4, i32 0, i32 0), i64 %15) - store i64 ptrtoint (i8* @"foo_Foob$Y2" to i64), i64* %x, align 8 + %16 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([7 x i8], [7 x i8]* @.str.10, i32 0, i32 0), i64 %15) + store i64 ptrtoint (%.fault* @"foo_Foob$Y2" to i64), i64* %x, align 8 %17 = load i64, i64* %x, align 8 store i64 %17, i64* %z, align 8 %18 = load i64, i64* %z, align 8 - %19 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([7 x i8], [7 x i8]* @.str.5, i32 0, i32 0), i64 %18) + %19 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([7 x i8], [7 x i8]* @.str.11, i32 0, i32 0), i64 %18) store i32 0, i32* %b, align 4 store i32 0, i32* %a, align 4 call void @foo_Foo_hello(i64* %f) diff --git a/test/test_suite/errors/macro_err2.c3t b/test/test_suite/errors/macro_err2.c3t index 52ed835f3..8aed9fc7c 100644 --- a/test/test_suite/errors/macro_err2.c3t +++ b/test/test_suite/errors/macro_err2.c3t @@ -23,7 +23,7 @@ fn void main() define i64 @test_abc(i32* %0) #0 { entry: - ret i64 ptrtoint (i8* @"test_Tester$FOO" to i64) + ret i64 ptrtoint (%.fault* @"test_Tester$FOO" to i64) } define void @test_main() #0 { diff --git a/test/test_suite/errors/printing_errors.c3t b/test/test_suite/errors/printing_errors.c3t new file mode 100644 index 000000000..1acbe55f0 --- /dev/null +++ b/test/test_suite/errors/printing_errors.c3t @@ -0,0 +1,80 @@ +// #target: macos-x64 +module test; +import std::io; + +fault Cde +{ + HELLO, + WORLD, +} +fn void main() +{ + anyerr 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 + %retparam = alloca i64, align 8 + %taddr = alloca %"char[]", align 8 + %vararg = alloca %"variant[]", align 8 + %varargslots = alloca [2 x %variant], align 16 + %taddr1 = alloca [5 x i8]*, align 8 + %faultname_zero = alloca %"char[]", align 8 + store i64 ptrtoint (%.fault* @"test_Cde$WORLD" to i64), i64* %x, align 8 + store %"char[]" { i8* getelementptr inbounds ([7 x i8], [7 x i8]* @.str, i32 0, i32 0), i64 6 }, %"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 + store [5 x i8]* bitcast ([6 x i8]* @.str.2 to [5 x i8]*), [5 x i8]** %taddr1, align 8 + %3 = bitcast [5 x i8]** %taddr1 to i8* + %4 = insertvalue %variant undef, i8* %3, 0 + %5 = insertvalue %variant %4, i64 ptrtoint (%.introspect* @"ct$p$a5$char" to i64), 1 + %6 = getelementptr inbounds [2 x %variant], [2 x %variant]* %varargslots, i64 0, i64 0 + store %variant %5, %variant* %6, align 16 + %7 = load i64, i64* %x, align 8 + %eq = icmp eq i64 %7, 0 + br i1 %eq, label %faultname_no, label %faultname_ok + +faultname_no: ; preds = %entry + %8 = bitcast %"char[]"* %faultname_zero to i8* + call void @llvm.memset.p0i8.i64(i8* align 8 %8, i8 0, i64 16, i1 false) + br label %faultname_exit + +faultname_ok: ; preds = %entry + %9 = inttoptr i64 %7 to %.fault* + %10 = getelementptr inbounds %.fault, %.fault* %9, i32 0, i32 1 + br label %faultname_exit + +faultname_exit: ; preds = %faultname_ok, %faultname_no + %faultname = phi %"char[]"* [ %faultname_zero, %faultname_no ], [ %10, %faultname_ok ] + %11 = bitcast %"char[]"* %faultname to i8* + %12 = insertvalue %variant undef, i8* %11, 0 + %13 = insertvalue %variant %12, i64 ptrtoint (%.introspect* @"ct$sa$char" to i64), 1 + %14 = getelementptr inbounds [2 x %variant], [2 x %variant]* %varargslots, i64 0, i64 1 + store %variant %13, %variant* %14, align 16 + %15 = getelementptr inbounds %"variant[]", %"variant[]"* %vararg, i32 0, i32 1 + store i64 2, i64* %15, align 8 + %16 = getelementptr inbounds %"variant[]", %"variant[]"* %vararg, i32 0, i32 0 + %17 = bitcast [2 x %variant]* %varargslots to %variant* + store %variant* %17, %variant** %16, align 8 + %18 = bitcast %"variant[]"* %vararg to { i8*, i64 }* + %19 = getelementptr inbounds { i8*, i64 }, { i8*, i64 }* %18, i32 0, i32 0 + %lo2 = load i8*, i8** %19, align 8 + %20 = getelementptr inbounds { i8*, i64 }, { i8*, i64 }* %18, i32 0, i32 1 + %hi3 = load i64, i64* %20, align 8 + %21 = call i64 @std_io_printf(i64* %retparam, i8* %lo, i64 %hi, i8* %lo2, i64 %hi3) + %not_err = icmp eq i64 %21, 0 + br i1 %not_err, label %after.errcheck, label %voiderr + +after.errcheck: ; preds = %faultname_exit + br label %voiderr + +voiderr: ; preds = %after.errcheck, %faultname_exit + ret void +} diff --git a/test/test_suite/errors/simple_static_failable.c3t b/test/test_suite/errors/simple_static_failable.c3t index 5f3ebf6b2..de3f5c634 100644 --- a/test/test_suite/errors/simple_static_failable.c3t +++ b/test/test_suite/errors/simple_static_failable.c3t @@ -19,6 +19,6 @@ define void @foo_main() #0 { entry: %i = alloca i32, align 4 %i.f = alloca i64, align 8 - store i64 ptrtoint (i8* @"foo_Blurg$Y" to i64), i64* %i.f, align 8 + store i64 ptrtoint (%.fault* @"foo_Blurg$Y" to i64), i64* %i.f, align 8 ret void } \ No newline at end of file diff --git a/test/test_suite/failable_catch.c3t b/test/test_suite/failable_catch.c3t index edf2f26cd..314b8c21c 100644 --- a/test/test_suite/failable_catch.c3t +++ b/test/test_suite/failable_catch.c3t @@ -48,129 +48,104 @@ entry: %0 = load i32, i32* %x, align 4 %intbool = icmp ne i32 %0, 0 br i1 %intbool, label %if.then, label %if.exit - if.then: ; preds = %entry %1 = load i32, i32* %x, align 4 store i32 %1, i32* %blockret, align 4 br label %expr_block.exit - if.exit: ; preds = %entry - store i64 ptrtoint (i8* @"failable_catch_MyErr$TEST" to i64), i64* %a.f, align 8 + store i64 ptrtoint (%.fault* @"failable_catch_MyErr$TEST" to i64), i64* %a.f, align 8 br label %after_assign - expr_block.exit: ; preds = %if.then %2 = load i32, i32* %blockret, align 4 store i32 %2, i32* %a, align 4 store i64 0, i64* %a.f, align 8 br label %after_assign - after_assign: ; preds = %expr_block.exit, %if.exit %3 = load i64, i64* %a.f, align 8 %not_err = icmp eq i64 %3, 0 br i1 %not_err, label %after_check, label %else_block - after_check: ; preds = %after_assign %4 = load i32, i32* %a, align 4 %add = add i32 %4, 3 br label %phi_block - else_block: ; preds = %after_assign br label %phi_block - phi_block: ; preds = %else_block, %after_check %val = phi i32 [ %add, %after_check ], [ 2, %else_block ] store i32 %val, i32* %x1, align 4 %5 = load i32, i32* %x1, align 4 %intbool3 = icmp ne i32 %5, 0 br i1 %intbool3, label %if.then4, label %if.exit5 - if.then4: ; preds = %phi_block %6 = load i32, i32* %x1, align 4 store i32 %6, i32* %blockret2, align 4 br label %expr_block.exit6 - if.exit5: ; preds = %phi_block - store i64 ptrtoint (i8* @"failable_catch_MyErr$TEST" to i64), i64* %b.f, align 8 + store i64 ptrtoint (%.fault* @"failable_catch_MyErr$TEST" to i64), i64* %b.f, align 8 br label %after_assign7 - expr_block.exit6: ; preds = %if.then4 %7 = load i32, i32* %blockret2, align 4 store i32 %7, i32* %b, align 4 store i64 0, i64* %b.f, align 8 br label %after_assign7 - after_assign7: ; preds = %expr_block.exit6, %if.exit5 store i32 0, i32* %x8, align 4 %8 = load i32, i32* %x8, align 4 %intbool10 = icmp ne i32 %8, 0 br i1 %intbool10, label %if.then11, label %if.exit12 - if.then11: ; preds = %after_assign7 %9 = load i32, i32* %x8, align 4 store i32 %9, i32* %blockret9, align 4 br label %expr_block.exit13 - if.exit12: ; preds = %after_assign7 - store i64 ptrtoint (i8* @"failable_catch_MyErr$TEST" to i64), i64* %c.f, align 8 + store i64 ptrtoint (%.fault* @"failable_catch_MyErr$TEST" to i64), i64* %c.f, align 8 br label %after_assign14 - expr_block.exit13: ; preds = %if.then11 %10 = load i32, i32* %blockret9, align 4 store i32 %10, i32* %c, align 4 store i64 0, i64* %c.f, align 8 br label %after_assign14 - after_assign14: ; preds = %expr_block.exit13, %if.exit12 %11 = load i64, i64* %a.f, align 8 %not_err15 = icmp eq i64 %11, 0 br i1 %not_err15, label %after_check16, label %voiderr - after_check16: ; preds = %after_assign14 %12 = load i32, i32* %a, align 4 call void (i8*, ...) @printf(i8* getelementptr inbounds ([8 x i8], [8 x i8]* @.str, i32 0, i32 0), i32 %12) br label %voiderr - voiderr: ; preds = %after_check16, %after_assign14 %13 = load i64, i64* %b.f, align 8 %not_err17 = icmp eq i64 %13, 0 br i1 %not_err17, label %after_check18, label %voiderr19 - after_check18: ; preds = %voiderr %14 = load i32, i32* %b, align 4 call void (i8*, ...) @printf(i8* getelementptr inbounds ([8 x i8], [8 x i8]* @.str.1, i32 0, i32 0), i32 %14) br label %voiderr19 - voiderr19: ; preds = %after_check18, %voiderr %15 = load i64, i64* %c.f, align 8 %not_err20 = icmp eq i64 %15, 0 br i1 %not_err20, label %after_check21, label %voiderr22 - after_check21: ; preds = %voiderr19 %16 = load i32, i32* %c, align 4 call void (i8*, ...) @printf(i8* getelementptr inbounds ([8 x i8], [8 x i8]* @.str.2, i32 0, i32 0), i32 %16) br label %voiderr22 - voiderr22: ; preds = %after_check21, %voiderr19 %17 = load i64, i64* %c.f, align 8 %neq = icmp ne i64 %17, 0 br i1 %neq, label %if.then23, label %if.exit24 - if.then23: ; preds = %voiderr22 call void (i8*, ...) @printf(i8* getelementptr inbounds ([13 x i8], [13 x i8]* @.str.3, i32 0, i32 0)) br label %if.exit24 - if.exit24: ; preds = %if.then23, %voiderr22 store i32 3, i32* %c, align 4 store i64 0, i64* %c.f, align 8 %18 = load i64, i64* %c.f, align 8 %not_err25 = icmp eq i64 %18, 0 br i1 %not_err25, label %after_check26, label %voiderr27 - after_check26: ; preds = %if.exit24 %19 = load i32, i32* %c, align 4 call void (i8*, ...) @printf(i8* getelementptr inbounds ([8 x i8], [8 x i8]* @.str.4, i32 0, i32 0), i32 %19) br label %voiderr27 - voiderr27: ; preds = %after_check26, %if.exit24 ret i32 0 } diff --git a/test/test_suite/from_docs/examples_if_catch.c3t b/test/test_suite/from_docs/examples_if_catch.c3t index e9aaf4802..ff05e0bce 100644 --- a/test/test_suite/from_docs/examples_if_catch.c3t +++ b/test/test_suite/from_docs/examples_if_catch.c3t @@ -54,7 +54,7 @@ entry: br i1 %eq, label %if.then, label %if.exit if.then: ; preds = %entry - ret i64 ptrtoint (i8* @"demo_MathError$DIVISION_BY_ZERO" to i64) + ret i64 ptrtoint (%.fault* @"demo_MathError$DIVISION_BY_ZERO" to i64) if.exit: ; preds = %entry %sifp = sitofp i32 %1 to double @@ -142,7 +142,7 @@ if.then: ; preds = %end_block switch.entry: ; preds = %if.then %6 = load i64, i64* %switch, align 8 - %eq = icmp eq i64 ptrtoint (i8* @"demo_MathError$DIVISION_BY_ZERO" to i64), %6 + %eq = icmp eq i64 ptrtoint (%.fault* @"demo_MathError$DIVISION_BY_ZERO" to i64), %6 br i1 %eq, label %switch.case, label %next_if switch.case: ; preds = %switch.entry diff --git a/test/test_suite/functions/test_regression.c3t b/test/test_suite/functions/test_regression.c3t index c03597270..8c706a992 100644 --- a/test/test_suite/functions/test_regression.c3t +++ b/test/test_suite/functions/test_regression.c3t @@ -250,9 +250,7 @@ fn Type getValue(Blob blob) @"ct$test_Foo2" = linkonce constant %.introspect { i8 10, i64 4, i64 0, i64 1, [0 x i64] zeroinitializer }, align 8 @"ct$test_Foo" = linkonce constant %.introspect { i8 10, i64 8, i64 0, i64 2, [0 x i64] zeroinitializer }, align 8 @"ct$int" = linkonce constant %.introspect { i8 2, i64 4, i64 0, i64 0, [0 x i64] zeroinitializer }, align 8 -@"ct$test_MyEnum" = linkonce constant %.introspect { i8 8, i64 4, i64 ptrtoint (%.introspect* @"ct$int" to i64), i64 3, [0 x i64] zeroinitializer }, align 8 -@"test_static$x" = internal unnamed_addr global i32 1, align 4 - +@"ct$test_MyEnum" = linkonce constant { i8, i64, i64, i64, [3 x %"char[]"] } { i8 8, i64 4, i64 ptrtoint (%.introspect* @"ct$int" to i64), i64 3, [3 x %"char[]"] [%"char[]" { i8* getelementptr define void @test_Foo2_printme(%Foo2* %0) #0 { entry: %1 = getelementptr inbounds %Foo2, %Foo2* %0, i32 0, i32 0 diff --git a/test/test_suite/functions/test_regression_mingw.c3t b/test/test_suite/functions/test_regression_mingw.c3t index b171b7d3b..1f572b7f5 100644 --- a/test/test_suite/functions/test_regression_mingw.c3t +++ b/test/test_suite/functions/test_regression_mingw.c3t @@ -266,7 +266,7 @@ $"ct$test_MyEnum" = comdat any @"ct$test_Foo2" = linkonce constant %.introspect { i8 10, i64 4, i64 0, i64 1, [0 x i64] zeroinitializer }, comdat, align 8 @"ct$test_Foo" = linkonce constant %.introspect { i8 10, i64 8, i64 0, i64 2, [0 x i64] zeroinitializer }, comdat, align 8 @"ct$int" = linkonce constant %.introspect { i8 2, i64 4, i64 0, i64 0, [0 x i64] zeroinitializer }, comdat, align 8 -@"ct$test_MyEnum" = linkonce constant %.introspect { i8 8, i64 4, i64 ptrtoint (%.introspect* @"ct$int" to i64), i64 3, [0 x i64] zeroinitializer }, comdat, align 8 +@"ct$test_MyEnum" = linkonce constant { i8, i64, i64, i64, [3 x %"char[]"] } { i8 8, i64 4, i64 ptrtoint (%.introspect* @"ct$int" to i64), i64 3, [3 x %"char[]"] [%"char[]" { i8* getelementptr inbounds ([5 x i8], [5 x i8]* @.enum.0, i64 0, i64 0), i64 4 }, %"char[]" { i8* getelementptr inbounds ([6 x i8], [6 x i8]* @.enum.1, i64 0, i64 0), i64 5 }, %"char[]" { i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.enum.2, i64 0, i64 0), 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 diff --git a/test/test_suite/statements/various_switching.c3t b/test/test_suite/statements/various_switching.c3t index d9e8e2a28..3af5dfebe 100644 --- a/test/test_suite/statements/various_switching.c3t +++ b/test/test_suite/statements/various_switching.c3t @@ -81,7 +81,7 @@ entry: %zy = alloca i32, align 4 %switch17 = alloca i32, align 4 %switch27 = alloca i8, align 1 - store i64 ptrtoint (i8* @"mymodule_ByeErr$BAR" to i64), i64* %x.f, align 8 + store i64 ptrtoint (%.fault* @"mymodule_ByeErr$BAR" to i64), i64* %x.f, align 8 store i64 ptrtoint (%.introspect* @"ct$int" to i64), i64* %z, align 8 br label %testblock @@ -109,7 +109,7 @@ if.then: ; preds = %end_block switch.entry: ; preds = %if.then %2 = load i64, i64* %switch, align 8 - %eq = icmp eq i64 ptrtoint (i8* @"mymodule_HelloErr$FOO" to i64), %2 + %eq = icmp eq i64 ptrtoint (%.fault* @"mymodule_HelloErr$FOO" to i64), %2 br i1 %eq, label %switch.case, label %next_if switch.case: ; preds = %switch.entry @@ -117,18 +117,18 @@ switch.case: ; preds = %switch.entry br label %switch.exit next_if: ; preds = %switch.entry - %eq1 = icmp eq i64 ptrtoint (i8* @"mymodule_ByeErr$BAR" to i64), %2 + %eq1 = icmp eq i64 ptrtoint (%.fault* @"mymodule_ByeErr$BAR" to i64), %2 br i1 %eq1, label %switch.case2, label %next_if3 switch.case2: ; preds = %next_if - call void (i8*, ...) @printf(i8* getelementptr inbounds ([5 x i8], [5 x i8]* @.str.1, i32 0, i32 0)) + call void (i8*, ...) @printf(i8* getelementptr inbounds ([5 x i8], [5 x i8]* @.str.3, i32 0, i32 0)) br label %switch.exit next_if3: ; preds = %next_if br label %switch.default switch.default: ; preds = %next_if3 - call void (i8*, ...) @printf(i8* getelementptr inbounds ([12 x i8], [12 x i8]* @.str.2, i32 0, i32 0)) + call void (i8*, ...) @printf(i8* getelementptr inbounds ([12 x i8], [12 x i8]* @.str.4, i32 0, i32 0)) br label %switch.exit switch.exit: ; preds = %switch.default, %switch.case2, %switch.case @@ -145,7 +145,7 @@ switch.entry5: ; preds = %if.exit br i1 %eq6, label %switch.case7, label %next_if8 switch.case7: ; preds = %switch.entry5 - call void (i8*, ...) @printf(i8* getelementptr inbounds ([10 x i8], [10 x i8]* @.str.3, i32 0, i32 0)) + call void (i8*, ...) @printf(i8* getelementptr inbounds ([10 x i8], [10 x i8]* @.str.5, i32 0, i32 0)) br label %switch.exit16 next_if8: ; preds = %switch.entry5 @@ -166,7 +166,7 @@ next_if14: ; preds = %next_if11 br label %switch.default15 switch.default15: ; preds = %next_if14, %switch.case13 - call void (i8*, ...) @printf(i8* getelementptr inbounds ([15 x i8], [15 x i8]* @.str.4, i32 0, i32 0)) + call void (i8*, ...) @printf(i8* getelementptr inbounds ([15 x i8], [15 x i8]* @.str.6, i32 0, i32 0)) br label %switch.exit16 switch.exit16: ; preds = %switch.default15, %switch.case7 @@ -187,7 +187,7 @@ switch.entry18: ; preds = %switch.exit16 br i1 %eq19, label %switch.case20, label %next_if21 switch.case20: ; preds = %switch.entry18 - call void (i8*, ...) @printf(i8* getelementptr inbounds ([7 x i8], [7 x i8]* @.str.5, i32 0, i32 0)) + call void (i8*, ...) @printf(i8* getelementptr inbounds ([7 x i8], [7 x i8]* @.str.7, i32 0, i32 0)) br label %switch.exit26 next_if21: ; preds = %switch.entry18 @@ -196,14 +196,14 @@ next_if21: ; preds = %switch.entry18 br i1 %eq22, label %switch.case23, label %next_if24 switch.case23: ; preds = %next_if21 - call void (i8*, ...) @printf(i8* getelementptr inbounds ([7 x i8], [7 x i8]* @.str.6, i32 0, i32 0)) + call void (i8*, ...) @printf(i8* getelementptr inbounds ([7 x i8], [7 x i8]* @.str.8, i32 0, i32 0)) br label %switch.exit26 next_if24: ; preds = %next_if21 br label %switch.default25 switch.default25: ; preds = %next_if24 - call void (i8*, ...) @printf(i8* getelementptr inbounds ([19 x i8], [19 x i8]* @.str.7, i32 0, i32 0)) + call void (i8*, ...) @printf(i8* getelementptr inbounds ([19 x i8], [19 x i8]* @.str.9, i32 0, i32 0)) br label %switch.exit26 switch.exit26: ; preds = %switch.default25, %switch.case23, %switch.case20 @@ -219,7 +219,7 @@ switch.entry28: ; preds = %switch.exit26 br i1 %eq29, label %switch.case30, label %next_if31 switch.case30: ; preds = %switch.entry28 - call void (i8*, ...) @printf(i8* getelementptr inbounds ([12 x i8], [12 x i8]* @.str.8, i32 0, i32 0)) + call void (i8*, ...) @printf(i8* getelementptr inbounds ([12 x i8], [12 x i8]* @.str.10, i32 0, i32 0)) br label %switch.exit37 next_if31: ; preds = %switch.entry28 @@ -229,14 +229,14 @@ next_if31: ; preds = %switch.entry28 br i1 %eq33, label %switch.case34, label %next_if35 switch.case34: ; preds = %next_if31 - call void (i8*, ...) @printf(i8* getelementptr inbounds ([8 x i8], [8 x i8]* @.str.9, i32 0, i32 0)) + call void (i8*, ...) @printf(i8* getelementptr inbounds ([8 x i8], [8 x i8]* @.str.11, i32 0, i32 0)) br label %switch.exit37 next_if35: ; preds = %next_if31 br label %switch.default36 switch.default36: ; preds = %next_if35 - call void (i8*, ...) @printf(i8* getelementptr inbounds ([14 x i8], [14 x i8]* @.str.10, i32 0, i32 0)) + call void (i8*, ...) @printf(i8* getelementptr inbounds ([14 x i8], [14 x i8]* @.str.12, i32 0, i32 0)) br label %switch.exit37 switch.exit37: ; preds = %switch.default36, %switch.case34, %switch.case30 diff --git a/test/test_suite2/compile_time_introspection/sizeof_errors.c3 b/test/test_suite2/compile_time_introspection/sizeof_errors.c3 index a86de52ed..300493acb 100644 --- a/test/test_suite2/compile_time_introspection/sizeof_errors.c3 +++ b/test/test_suite2/compile_time_introspection/sizeof_errors.c3 @@ -40,7 +40,7 @@ fn void l() fn void m() { - int v = $sizeof(int[4].len); // #error: 'int[4]' does not have a property 'len' + int v = $sizeof(int[4].len); } fn void n() diff --git a/test/test_suite2/enumerations/compile_time.c3t b/test/test_suite2/enumerations/compile_time.c3t index 1e7e7c21f..adc1d698a 100644 --- a/test/test_suite2/enumerations/compile_time.c3t +++ b/test/test_suite2/enumerations/compile_time.c3t @@ -9,7 +9,7 @@ int myenum_elements = MyEnum.elements; int myenum_alignof = $alignof(MyEnum); int myenum_sizeof = MyEnum.sizeof; -// #expect: compile_time.ll +/* #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 diff --git a/test/test_suite2/enumerations/enum_associated_value.c3t b/test/test_suite2/enumerations/enum_associated_value.c3t index 1e90d6c20..980cd93b1 100644 --- a/test/test_suite2/enumerations/enum_associated_value.c3t +++ b/test/test_suite2/enumerations/enum_associated_value.c3t @@ -19,7 +19,7 @@ fn void main() /* #expect: test.ll @"ct$uint" = linkonce constant %.introspect { i8 3, i64 4, i64 0, i64 0, [0 x i64] zeroinitializer }, align 8 -@"ct$test_Foo" = linkonce constant %.introspect { i8 8, i64 4, i64 ptrtoint (ptr @"ct$uint" to i64), i64 2, [0 x i64] zeroinitializer }, align 8 +@"ct$test_Foo" = linkonce constant { i8, i64, i64, i64, [2 x %"char[]"] } { i8 8, i64 4, i64 ptrtoint (ptr @"ct$uint" to i64), i64 2, [2 x %"char[]"] [%"char[]" { ptr @.enum.0, i64 1 }, %"char[]" { ptr @.enum.1, 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 diff --git a/test/test_suite2/enumerations/enum_invalid_param.c3 b/test/test_suite2/enumerations/enum_invalid_param.c3 new file mode 100644 index 000000000..ff86eb5f9 --- /dev/null +++ b/test/test_suite2/enumerations/enum_invalid_param.c3 @@ -0,0 +1,9 @@ +enum Test : int (int a, int b) +{ + FOO(1, 2) +} + +enum Test2 : int (int a, int nameof) // #error: 'nameof' is not a valid parameter name for enums +{ + FOO(1, 2) +} diff --git a/test/test_suite2/enumerations/enum_same_param.c3 b/test/test_suite2/enumerations/enum_same_param.c3 new file mode 100644 index 000000000..1196ed7ca --- /dev/null +++ b/test/test_suite2/enumerations/enum_same_param.c3 @@ -0,0 +1,9 @@ +enum Test : int (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_suite2/errors/anyerr_void.c3t b/test/test_suite2/errors/anyerr_void.c3t index 3856d81ec..4afac5f3f 100644 --- a/test/test_suite2/errors/anyerr_void.c3t +++ b/test/test_suite2/errors/anyerr_void.c3t @@ -26,7 +26,6 @@ fn void main() /* #expect: anyerr_void.ll -; Function Attrs: nounwind define i64 @anyerr_void_errorThing() #0 { entry: ret i64 ptrtoint (ptr @"anyerr_void_MyError$BAR" to i64) @@ -65,8 +64,8 @@ noerr_block: ; preds = %after.errcheck, %er store i64 %1, ptr %z, align 8 %2 = load i64, ptr %z, align 8 call void (ptr, ...) @printf(ptr @.str, i64 %2) - call void (ptr, ...) @printf(ptr @.str.1, i64 ptrtoint (ptr @"anyerr_void_MyError$BAR" to i64)) - call void (ptr, ...) @printf(ptr @.str.2, i64 ptrtoint (ptr @"anyerr_void_MyError$FOO" to i64)) + call void (ptr, ...) @printf(ptr @.str.2, i64 ptrtoint (ptr @"anyerr_void_MyError$BAR" to i64)) + call void (ptr, ...) @printf(ptr @.str.3, i64 ptrtoint (ptr @"anyerr_void_MyError$FOO" to i64)) store i64 0, ptr %error_var1, align 8 %3 = call i64 @anyerr_void_errorThing2() %not_err2 = icmp eq i64 %3, 0 @@ -83,6 +82,6 @@ noerr_block5: ; preds = %after.errcheck4, %e %4 = load i64, ptr %error_var1, align 8 store i64 %4, ptr %z, align 8 %5 = load i64, ptr %z, align 8 - call void (ptr, ...) @printf(ptr @.str.3, i64 %5) + call void (ptr, ...) @printf(ptr @.str.4, i64 %5) ret void } \ No newline at end of file diff --git a/test/test_suite2/errors/error_regression_2.c3t b/test/test_suite2/errors/error_regression_2.c3t index f82bc2f87..ae17adaf9 100644 --- a/test/test_suite2/errors/error_regression_2.c3t +++ b/test/test_suite2/errors/error_regression_2.c3t @@ -169,7 +169,7 @@ cond.rhs: ; preds = %entry br label %cond.phi cond.phi: ; preds = %cond.rhs, %cond.lhs - %val = phi %"char[]" [ %6, %cond.lhs ], [ { ptr @.str.26, i64 7 }, %cond.rhs ] + %val = phi %"char[]" [ %6, %cond.lhs ], [ { ptr @.str.28, i64 7 }, %cond.rhs ] store %"char[]" %val, ptr %title, align 8 %7 = getelementptr inbounds %"char[]", ptr %title, i32 0, i32 1 %8 = load i64, ptr %7, align 8 @@ -179,8 +179,8 @@ cond.phi: ; preds = %cond.rhs, %cond.lhs %11 = getelementptr inbounds %Summary, ptr %0, i32 0, i32 1 %12 = load i8, ptr %11, align 8 %13 = trunc i8 %12 to i1 - %ternary = select i1 %13, ptr @.str.28, ptr @.str.29 - %14 = call i32 (ptr, ptr, ...) @fprintf(ptr %1, ptr @.str.27, i32 %uisitrunc, ptr %10, ptr %ternary) + %ternary = select i1 %13, ptr @.str.30, ptr @.str.31 + %14 = call i32 (ptr, ptr, ...) @fprintf(ptr %1, ptr @.str.29, i32 %uisitrunc, ptr %10, ptr %ternary) ret void } @@ -323,7 +323,7 @@ if.exit: ; preds = %entry %lo3 = load ptr, ptr %11, align 8 %12 = getelementptr inbounds { ptr, i64 }, ptr %url, i32 0, i32 1 %hi4 = load i64, ptr %12, align 8 - store %"char[]" { ptr @.str.1, i64 12 }, ptr %taddr5, align 8 + store %"char[]" { ptr @.str.3, i64 12 }, ptr %taddr5, align 8 %13 = getelementptr inbounds { ptr, i64 }, ptr %taddr5, i32 0, i32 0 %lo6 = load ptr, ptr %13, align 8 %14 = getelementptr inbounds { ptr, i64 }, ptr %taddr5, i32 0, i32 1 @@ -343,7 +343,7 @@ if.exit9: ; preds = %if.exit %lo10 = load ptr, ptr %18, align 8 %19 = getelementptr inbounds { ptr, i64 }, ptr %url, i32 0, i32 1 %hi11 = load i64, ptr %19, align 8 - store %"char[]" { ptr @.str.2, i64 13 }, ptr %taddr12, align 8 + store %"char[]" { ptr @.str.4, i64 13 }, ptr %taddr12, align 8 %20 = getelementptr inbounds { ptr, i64 }, ptr %taddr12, i32 0, i32 0 %lo13 = load ptr, ptr %20, align 8 %21 = getelementptr inbounds { ptr, i64 }, ptr %taddr12, i32 0, i32 1 @@ -388,7 +388,7 @@ if.exit21: ; preds = %if.exit9 %lo22 = load ptr, ptr %32, align 8 %33 = getelementptr inbounds { ptr, i64 }, ptr %url, i32 0, i32 1 %hi23 = load i64, ptr %33, align 8 - store %"char[]" { ptr @.str.3, i64 11 }, ptr %taddr24, align 8 + store %"char[]" { ptr @.str.5, i64 11 }, ptr %taddr24, align 8 %34 = getelementptr inbounds { ptr, i64 }, ptr %taddr24, i32 0, i32 0 %lo25 = load ptr, ptr %34, align 8 %35 = getelementptr inbounds { ptr, i64 }, ptr %taddr24, i32 0, i32 1 @@ -457,7 +457,7 @@ if.exit47: ; preds = %if.exit21 %uisitrunc = trunc i64 %52 to i32 %53 = getelementptr inbounds %"char[]", ptr %url, i32 0, i32 0 %54 = load ptr, ptr %53, align 8 - %55 = call i32 (ptr, i64, ptr, ...) @snprintf(ptr null, i64 0, ptr @.str.5, i32 %uisitrunc, ptr %54) + %55 = call i32 (ptr, i64, ptr, ...) @snprintf(ptr null, i64 0, ptr @.str.7, i32 %uisitrunc, ptr %54) store i32 %55, ptr %len, align 4 %56 = load i32, ptr %len, align 4 %siuiext = sext i32 %56 to i64 @@ -481,7 +481,7 @@ if.exit50: ; preds = %if.exit47 %uisitrunc53 = trunc i64 %62 to i32 %63 = getelementptr inbounds %"char[]", ptr %url, i32 0, i32 0 %64 = load ptr, ptr %63, align 8 - %65 = call i32 (ptr, i64, ptr, ...) @snprintf(ptr %59, i64 %add52, ptr @.str.6, i32 %uisitrunc53, ptr %64) + %65 = call i32 (ptr, i64, ptr, ...) @snprintf(ptr %59, i64 %add52, ptr @.str.8, i32 %uisitrunc53, ptr %64) %66 = getelementptr inbounds %Doc, ptr %literal55, i32 0, i32 0 store ptr null, ptr %literal58, align 8 %67 = getelementptr inbounds %Head, ptr %literal58, i32 0, i32 0 @@ -715,7 +715,7 @@ err_retblock: ; preds = %error3, %error define ptr @test_bool_to_string(i8 zeroext %0) #0 { entry: %1 = trunc i8 %0 to i1 - %ternary = select i1 %1, %"char[]" { ptr @.str.7, i64 4 }, %"char[]" { ptr @.str.8, i64 5 } + %ternary = select i1 %1, %"char[]" { ptr @.str.9, i64 4 }, %"char[]" { ptr @.str.10, i64 5 } %2 = extractvalue %"char[]" %ternary, 0 ret ptr %2 } @@ -733,27 +733,27 @@ switch.entry: ; preds = %entry br i1 %eq, label %switch.case, label %next_if switch.case: ; preds = %switch.entry - ret ptr @.str.9 + ret ptr @.str.11 next_if: ; preds = %switch.entry %eq1 = icmp eq i64 ptrtoint (ptr @"test_ReadError$BAD_READ" to i64), %1 br i1 %eq1, label %switch.case2, label %next_if3 switch.case2: ; preds = %next_if - ret ptr @.str.10 + ret ptr @.str.12 next_if3: ; preds = %next_if %eq4 = icmp eq i64 ptrtoint (ptr @"test_ReadError$OUT_OF_MEMORY" to i64), %1 br i1 %eq4, label %switch.case5, label %next_if6 switch.case5: ; preds = %next_if3 - ret ptr @.str.11 + ret ptr @.str.13 next_if6: ; preds = %next_if3 br label %switch.default switch.default: ; preds = %next_if6 - ret ptr @.str.12 + ret ptr @.str.14 } ; Function Attrs: nounwind @@ -772,15 +772,15 @@ entry: %has_title.f = alloca i64, align 8 %retparam = alloca i8, align 1 %0 = getelementptr inbounds [5 x %"char[]"], ptr %literal, i64 0, i64 0 - store %"char[]" { ptr @.str.13, i64 4 }, ptr %0, align 8 + store %"char[]" { ptr @.str.15, i64 4 }, ptr %0, align 8 %1 = getelementptr inbounds [5 x %"char[]"], ptr %literal, i64 0, i64 1 - store %"char[]" { ptr @.str.14, i64 11 }, ptr %1, align 8 + store %"char[]" { ptr @.str.16, i64 11 }, ptr %1, align 8 %2 = getelementptr inbounds [5 x %"char[]"], ptr %literal, i64 0, i64 2 - store %"char[]" { ptr @.str.15, i64 13 }, ptr %2, align 8 + store %"char[]" { ptr @.str.17, i64 13 }, ptr %2, align 8 %3 = getelementptr inbounds [5 x %"char[]"], ptr %literal, i64 0, i64 3 - store %"char[]" { ptr @.str.16, i64 12 }, ptr %3, align 8 + store %"char[]" { ptr @.str.18, i64 12 }, ptr %3, align 8 %4 = getelementptr inbounds [5 x %"char[]"], ptr %literal, i64 0, i64 4 - store %"char[]" { ptr @.str.17, i64 4 }, ptr %4, align 8 + store %"char[]" { ptr @.str.19, i64 4 }, ptr %4, align 8 %5 = insertvalue %"char[][]" undef, ptr %literal, 0 %6 = insertvalue %"char[][]" %5, i64 5, 1 store %"char[][]" %6, ptr %URLS, align 8 @@ -808,7 +808,7 @@ loop.body: ; preds = %loop.cond %uisitrunc = trunc i64 %15 to i32 %16 = getelementptr inbounds %"char[]", ptr %url, i32 0, i32 0 %17 = load ptr, ptr %16, align 8 - %18 = call i32 (ptr, ...) @printf(ptr @.str.18, i32 %uisitrunc, ptr %17) + %18 = call i32 (ptr, ...) @printf(ptr @.str.20, i32 %uisitrunc, ptr %17) %19 = getelementptr inbounds { ptr, i64 }, ptr %url, i32 0, i32 0 %lo = load ptr, ptr %19, align 8 %20 = getelementptr inbounds { ptr, i64 }, ptr %url, i32 0, i32 1 @@ -816,10 +816,10 @@ loop.body: ; preds = %loop.cond %21 = call { ptr, i8 } @test_readAndBuildSummary(ptr %lo, i64 %hi) store { ptr, i8 } %21, ptr %result, align 8 call void @llvm.memcpy.p0.p0.i32(ptr align 8 %summary, ptr align 8 %result, i32 16, i1 false) - %22 = call i32 (ptr, ...) @printf(ptr @.str.19) + %22 = call i32 (ptr, ...) @printf(ptr @.str.21) %23 = load ptr, ptr @__stdoutp, align 8 call void @test_Summary_print(ptr %summary, ptr %23) - %24 = call i32 (ptr, ...) @printf(ptr @.str.20) + %24 = call i32 (ptr, ...) @printf(ptr @.str.22) %25 = getelementptr inbounds %Summary, ptr %summary, i32 0, i32 0 %26 = load ptr, ptr %25, align 8 %ptrbool = icmp ne ptr %26, null @@ -842,7 +842,7 @@ cond.phi: ; preds = %cond.rhs, %cond.lhs %uisitrunc3 = trunc i64 %31 to i32 %32 = getelementptr inbounds %"char[]", ptr %title_sure, i32 0, i32 0 %33 = load ptr, ptr %32, align 8 - %34 = call i32 (ptr, ...) @printf(ptr @.str.22, i32 %uisitrunc3, ptr %33) + %34 = call i32 (ptr, ...) @printf(ptr @.str.24, i32 %uisitrunc3, ptr %33) %35 = getelementptr inbounds { ptr, i64 }, ptr %url, i32 0, i32 0 %lo4 = load ptr, ptr %35, align 8 %36 = getelementptr inbounds { ptr, i64 }, ptr %url, i32 0, i32 1 @@ -892,8 +892,8 @@ else_block10: ; preds = %phi_block phi_block11: ; preds = %else_block10, %after_check9 %val12 = phi i1 [ %46, %after_check9 ], [ false, %else_block10 ] - %ternary = select i1 %val12, ptr @.str.24, ptr @.str.25 - %47 = call i32 (ptr, ...) @printf(ptr @.str.23, ptr %val7, ptr %ternary) + %ternary = select i1 %val12, ptr @.str.26, ptr @.str.27 + %47 = call i32 (ptr, ...) @printf(ptr @.str.25, ptr %val7, ptr %ternary) %48 = load i64, ptr %anon, align 8 %add = add i64 %48, 1 store i64 %add, ptr %anon, align 8 diff --git a/test/test_suite2/errors/failable_taddr_and_access.c3t b/test/test_suite2/errors/failable_taddr_and_access.c3t index e36593e5c..6de69c597 100644 --- a/test/test_suite2/errors/failable_taddr_and_access.c3t +++ b/test/test_suite2/errors/failable_taddr_and_access.c3t @@ -28,7 +28,7 @@ fn void main() %Foo = type { i32, i32 } @"ct$test_Foo" = linkonce constant %.introspect { i8 10, i64 8, i64 0, i64 2, [0 x i64] zeroinitializer }, align 8 -@"test_MyErr$FOO" = linkonce constant i8 1, align 1 +@"test_MyErr$FOO" = linkonce constant %.fault { i64 ptrtoint (ptr @"ct$test_MyErr" to i64), %"char[]" { ptr @.fault, i64 3 } }, align 8 @"ct$test_MyErr" = linkonce constant %.introspect { i8 9, 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 diff --git a/test/test_suite2/errors/general_error_regression.c3t b/test/test_suite2/errors/general_error_regression.c3t index d20daf4a1..cd268875a 100644 --- a/test/test_suite2/errors/general_error_regression.c3t +++ b/test/test_suite2/errors/general_error_regression.c3t @@ -74,19 +74,19 @@ fn void main() define void @foo_Foo_hello(ptr %0) #0 { entry: - %1 = call i32 @std_io_println(ptr @.str.6) #1 + %1 = call i32 @std_io_println(ptr @.str.12) #1 ret void } define void @foo_Bar_hello(ptr %0) #0 { entry: - %1 = call i32 @std_io_println(ptr @.str.7) #1 + %1 = call i32 @std_io_println(ptr @.str.13) #1 ret void } define void @foo_MyEnum_hello(ptr %0) #0 { entry: - %1 = call i32 @std_io_println(ptr @.str.8) #1 + %1 = call i32 @std_io_println(ptr @.str.14) #1 ret void } @@ -111,27 +111,27 @@ entry: %5 = load i64, ptr %x, align 8 store i64 %5, ptr %z, align 8 %6 = load i64, ptr %z, align 8 - %7 = call i32 (ptr, ...) @printf(ptr @.str.1, i64 %6) + %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.2, i64 %9) + %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.3, i64 %12) + %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.4, i64 %15) + %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.5, i64 %18) + %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) diff --git a/test/test_suite2/errors/printing_errors.c3t b/test/test_suite2/errors/printing_errors.c3t new file mode 100644 index 000000000..7b4d452c6 --- /dev/null +++ b/test/test_suite2/errors/printing_errors.c3t @@ -0,0 +1,74 @@ +// #target: macos-x64 +module test; +import std::io; + +fault Cde +{ + HELLO, + WORLD, +} +fn void main() +{ + anyerr 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 + %retparam = alloca i64, align 8 + %taddr = alloca %"char[]", align 8 + %vararg = alloca %"variant[]", align 8 + %varargslots = alloca [2 x %variant], align 16 + %taddr1 = alloca ptr, align 8 + %faultname_zero = alloca %"char[]", align 8 + store i64 ptrtoint (ptr @"test_Cde$WORLD" to i64), ptr %x, align 8 + store %"char[]" { ptr @.str, i64 6 }, 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 + store ptr @.str.2, ptr %taddr1, align 8 + %2 = insertvalue %variant undef, ptr %taddr1, 0 + %3 = insertvalue %variant %2, i64 ptrtoint (ptr @"ct$p$a5$char" to i64), 1 + %4 = getelementptr inbounds [2 x %variant], ptr %varargslots, i64 0, i64 0 + store %variant %3, ptr %4, align 16 + %5 = load i64, ptr %x, align 8 + %eq = icmp eq i64 %5, 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 + %6 = inttoptr i64 %5 to ptr + %7 = getelementptr inbounds %.fault, ptr %6, i32 0, i32 1 + br label %faultname_exit + +faultname_exit: ; preds = %faultname_ok, %faultname_no + %faultname = phi ptr [ %faultname_zero, %faultname_no ], [ %7, %faultname_ok ] + %8 = insertvalue %variant undef, ptr %faultname, 0 + %9 = insertvalue %variant %8, i64 ptrtoint (ptr @"ct$sa$char" to i64), 1 + %10 = getelementptr inbounds [2 x %variant], ptr %varargslots, i64 0, i64 1 + store %variant %9, ptr %10, align 16 + %11 = getelementptr inbounds %"variant[]", ptr %vararg, i32 0, i32 1 + store i64 2, ptr %11, align 8 + %12 = getelementptr inbounds %"variant[]", ptr %vararg, i32 0, i32 0 + store ptr %varargslots, ptr %12, align 8 + %13 = getelementptr inbounds { ptr, i64 }, ptr %vararg, i32 0, i32 0 + %lo2 = load ptr, ptr %13, align 8 + %14 = getelementptr inbounds { ptr, i64 }, ptr %vararg, i32 0, i32 1 + %hi3 = load i64, ptr %14, align 8 + %15 = call i64 @std_io_printf(ptr %retparam, ptr %lo, i64 %hi, ptr %lo2, i64 %hi3) + %not_err = icmp eq i64 %15, 0 + br i1 %not_err, label %after.errcheck, label %voiderr + +after.errcheck: ; preds = %faultname_exit + br label %voiderr + +voiderr: ; preds = %after.errcheck, %faultname_exit + ret void +} diff --git a/test/test_suite2/functions/test_regression.c3t b/test/test_suite2/functions/test_regression.c3t index 5470a8b63..7b6ea6f8b 100644 --- a/test/test_suite2/functions/test_regression.c3t +++ b/test/test_suite2/functions/test_regression.c3t @@ -249,7 +249,7 @@ fn Type getValue(Blob blob) @"ct$test_Foo2" = linkonce constant %.introspect { i8 10, i64 4, i64 0, i64 1, [0 x i64] zeroinitializer }, align 8 @"ct$test_Foo" = linkonce constant %.introspect { i8 10, i64 8, i64 0, i64 2, [0 x i64] zeroinitializer }, align 8 @"ct$int" = linkonce constant %.introspect { i8 2, i64 4, i64 0, i64 0, [0 x i64] zeroinitializer }, align 8 -@"ct$test_MyEnum" = linkonce constant %.introspect { i8 8, i64 4, i64 ptrtoint (ptr @"ct$int" to i64), i64 3, [0 x i64] zeroinitializer }, align 8 +@"ct$test_MyEnum" = linkonce constant { i8, i64, i64, i64, [3 x %"char[]"] } { i8 8, i64 4, i64 ptrtoint (ptr @"ct$int" to i64), i64 3, [3 x %"char[]"] [%"char[]" { ptr @.enum.0, i64 4 }, %"char[]" { ptr @.enum.1, i64 5 }, %"char[]" { ptr @.enum.2, i64 3 }] }, align 8 @"test_static$x" = internal unnamed_addr global i32 1, align 4 define void @test_Foo2_printme(ptr %0) #0 { diff --git a/test/test_suite2/functions/test_regression_mingw.c3t b/test/test_suite2/functions/test_regression_mingw.c3t index 19e5a5fe5..96ada348c 100644 --- a/test/test_suite2/functions/test_regression_mingw.c3t +++ b/test/test_suite2/functions/test_regression_mingw.c3t @@ -265,7 +265,7 @@ $"ct$test_MyEnum" = comdat any @"ct$test_Foo2" = linkonce constant %.introspect { i8 10, i64 4, i64 0, i64 1, [0 x i64] zeroinitializer }, comdat, align 8 @"ct$test_Foo" = linkonce constant %.introspect { i8 10, i64 8, i64 0, i64 2, [0 x i64] zeroinitializer }, comdat, align 8 @"ct$int" = linkonce constant %.introspect { i8 2, i64 4, i64 0, i64 0, [0 x i64] zeroinitializer }, comdat, align 8 -@"ct$test_MyEnum" = linkonce constant %.introspect { i8 8, i64 4, i64 ptrtoint (ptr @"ct$int" to i64), i64 3, [0 x i64] zeroinitializer }, comdat, align 8 +@"ct$test_MyEnum" = linkonce constant { i8, i64, i64, i64, [3 x %"char[]"] } { i8 8, i64 4, i64 ptrtoint (ptr @"ct$int" to i64), i64 3, [3 x %"char[]"] [%"char[]" { ptr @.enum.0, i64 4 }, %"char[]" { ptr @.enum.1, i64 5 }, %"char[]" { ptr @.enum.2, 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 diff --git a/test/test_suite2/statements/foreach_custom_macro.c3t b/test/test_suite2/statements/foreach_custom_macro.c3t index 18f530482..6faf10cd3 100644 --- a/test/test_suite2/statements/foreach_custom_macro.c3t +++ b/test/test_suite2/statements/foreach_custom_macro.c3t @@ -31,9 +31,6 @@ fn void main() extern fn int printf(char *fmt, ...); /* #expect: foo.ll -source_filename = "foo" -target datalayout = "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" -target triple = "x86_64-apple-darwin" %Foo = type { %"int[]" } %"int[]" = type { ptr, i64 } @@ -98,7 +95,4 @@ define i32 @main(i32 %0, ptr %1) #0 { entry: call void @foo_main() ret i32 0 -} - -; Function Attrs: argmemonly nofree nounwind willreturn -declare void @llvm.memcpy.p0.p0.i32(ptr noalias nocapture writeonly, ptr noalias nocapture readonly, i32, i1 immarg) #1 +} \ No newline at end of file diff --git a/test/test_suite2/statements/various_switching.c3t b/test/test_suite2/statements/various_switching.c3t index 223ed2cc1..ee9740bec 100644 --- a/test/test_suite2/statements/various_switching.c3t +++ b/test/test_suite2/statements/various_switching.c3t @@ -121,14 +121,14 @@ next_if: ; preds = %switch.entry br i1 %eq1, label %switch.case2, label %next_if3 switch.case2: ; preds = %next_if - call void (ptr, ...) @printf(ptr @.str.1) + 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.2) + call void (ptr, ...) @printf(ptr @.str.4) br label %switch.exit switch.exit: ; preds = %switch.default, %switch.case2, %switch.case @@ -145,7 +145,7 @@ switch.entry5: ; preds = %if.exit br i1 %eq6, label %switch.case7, label %next_if8 switch.case7: ; preds = %switch.entry5 - call void (ptr, ...) @printf(ptr @.str.3) + call void (ptr, ...) @printf(ptr @.str.5) br label %switch.exit16 next_if8: ; preds = %switch.entry5 @@ -166,7 +166,7 @@ next_if14: ; preds = %next_if11 br label %switch.default15 switch.default15: ; preds = %next_if14, %switch.case13 - call void (ptr, ...) @printf(ptr @.str.4) + call void (ptr, ...) @printf(ptr @.str.6) br label %switch.exit16 switch.exit16: ; preds = %switch.default15, %switch.case7 @@ -187,7 +187,7 @@ switch.entry18: ; preds = %switch.exit16 br i1 %eq19, label %switch.case20, label %next_if21 switch.case20: ; preds = %switch.entry18 - call void (ptr, ...) @printf(ptr @.str.5) + call void (ptr, ...) @printf(ptr @.str.7) br label %switch.exit26 next_if21: ; preds = %switch.entry18 @@ -196,14 +196,14 @@ next_if21: ; preds = %switch.entry18 br i1 %eq22, label %switch.case23, label %next_if24 switch.case23: ; preds = %next_if21 - call void (ptr, ...) @printf(ptr @.str.6) + call void (ptr, ...) @printf(ptr @.str.8) br label %switch.exit26 next_if24: ; preds = %next_if21 br label %switch.default25 switch.default25: ; preds = %next_if24 - call void (ptr, ...) @printf(ptr @.str.7) + call void (ptr, ...) @printf(ptr @.str.9) br label %switch.exit26 switch.exit26: ; preds = %switch.default25, %switch.case23, %switch.case20 @@ -219,7 +219,7 @@ switch.entry28: ; preds = %switch.exit26 br i1 %eq29, label %switch.case30, label %next_if31 switch.case30: ; preds = %switch.entry28 - call void (ptr, ...) @printf(ptr @.str.8) + call void (ptr, ...) @printf(ptr @.str.10) br label %switch.exit37 next_if31: ; preds = %switch.entry28 @@ -229,14 +229,14 @@ next_if31: ; preds = %switch.entry28 br i1 %eq33, label %switch.case34, label %next_if35 switch.case34: ; preds = %next_if31 - call void (ptr, ...) @printf(ptr @.str.9) + call void (ptr, ...) @printf(ptr @.str.11) br label %switch.exit37 next_if35: ; preds = %next_if31 br label %switch.default36 switch.default36: ; preds = %next_if35 - call void (ptr, ...) @printf(ptr @.str.10) + call void (ptr, ...) @printf(ptr @.str.12) br label %switch.exit37 switch.exit37: ; preds = %switch.default36, %switch.case34, %switch.case30