diff options
| author | Vexu <15308111+Vexu@users.noreply.github.com> | 2019-11-23 19:13:48 +0200 |
|---|---|---|
| committer | Vexu <15308111+Vexu@users.noreply.github.com> | 2019-11-23 19:13:48 +0200 |
| commit | 03cc81665bb28eb35c8c6d4be17b5a56fa66261f (patch) | |
| tree | e686671775e606c3cf1129b535f2c2487e4e6e3c /src | |
| parent | 86d9563d1539cd7581dc120023bb830fae77ba0f (diff) | |
| parent | ad0871ea4bf2dfbed07282ffe14738b5347d5d32 (diff) | |
| download | zig-03cc81665bb28eb35c8c6d4be17b5a56fa66261f.tar.gz zig-03cc81665bb28eb35c8c6d4be17b5a56fa66261f.zip | |
Merge branch 'master' into modernize-stage2
Diffstat (limited to 'src')
| -rw-r--r-- | src/all_types.hpp | 63 | ||||
| -rw-r--r-- | src/analyze.cpp | 288 | ||||
| -rw-r--r-- | src/analyze.hpp | 9 | ||||
| -rw-r--r-- | src/ast_render.cpp | 22 | ||||
| -rw-r--r-- | src/codegen.cpp | 184 | ||||
| -rw-r--r-- | src/dump_analysis.cpp | 7 | ||||
| -rw-r--r-- | src/ir.cpp | 1603 | ||||
| -rw-r--r-- | src/ir_print.cpp | 72 | ||||
| -rw-r--r-- | src/ir_print.hpp | 1 | ||||
| -rw-r--r-- | src/parser.cpp | 60 | ||||
| -rw-r--r-- | src/range_set.cpp | 3 | ||||
| -rw-r--r-- | src/tokenizer.cpp | 33 | ||||
| -rw-r--r-- | src/tokenizer.hpp | 1 | ||||
| -rw-r--r-- | src/translate_c.cpp | 35 | ||||
| -rw-r--r-- | src/zig_clang.cpp | 5 | ||||
| -rw-r--r-- | src/zig_clang.h | 3 |
16 files changed, 1681 insertions, 708 deletions
diff --git a/src/all_types.hpp b/src/all_types.hpp index 42f14539f3..c4178cb130 100644 --- a/src/all_types.hpp +++ b/src/all_types.hpp @@ -48,6 +48,7 @@ struct ResultLoc; struct ResultLocPeer; struct ResultLocPeerParent; struct ResultLocBitCast; +struct ResultLocCast; struct ResultLocReturn; enum PtrLen { @@ -151,7 +152,7 @@ struct ConstParent { }; struct ConstStructValue { - ConstExprValue *fields; + ConstExprValue **fields; }; struct ConstUnionValue { @@ -967,6 +968,7 @@ struct AstNodeContainerDecl { AstNode *init_arg_expr; // enum(T), struct(endianness), or union(T), or union(enum(T)) ZigList<AstNode *> fields; ZigList<AstNode *> decls; + Buf doc_comments; ContainerKind kind; ContainerLayout layout; @@ -1186,10 +1188,22 @@ bool fn_type_id_eql(FnTypeId *a, FnTypeId *b); static const uint32_t VECTOR_INDEX_NONE = UINT32_MAX; static const uint32_t VECTOR_INDEX_RUNTIME = UINT32_MAX - 1; +struct InferredStructField { + ZigType *inferred_struct_type; + Buf *field_name; +}; + struct ZigTypePointer { ZigType *child_type; ZigType *slice_parent; + // Anonymous struct literal syntax uses this when the result location has + // no type in it. This field is null if this pointer does not refer to + // a field of a currently-being-inferred struct type. + // When this is non-null, the pointer is pointing to the base of the inferred + // struct. + InferredStructField *inferred_struct_field; + PtrLen ptr_len; uint32_t explicit_alignment; // 0 means use ABI alignment @@ -1236,6 +1250,7 @@ struct TypeStructField { enum ResolveStatus { ResolveStatusUnstarted, ResolveStatusInvalid, + ResolveStatusBeingInferred, ResolveStatusZeroBitsKnown, ResolveStatusAlignmentKnown, ResolveStatusSizeKnown, @@ -1265,7 +1280,7 @@ struct RootStruct { struct ZigTypeStruct { AstNode *decl_node; - TypeStructField *fields; + TypeStructField **fields; ScopeDecls *decls_scope; HashMap<Buf *, TypeStructField *, buf_hash, buf_eql_buf> fields_by_name; RootStruct *root_struct; @@ -1284,6 +1299,7 @@ struct ZigTypeStruct { bool requires_comptime; bool resolve_loop_flag_zero_bits; bool resolve_loop_flag_other; + bool is_inferred; }; struct ZigTypeOptional { @@ -1685,12 +1701,14 @@ enum BuiltinFnId { BuiltinFnIdErrorReturnTrace, BuiltinFnIdAtomicRmw, BuiltinFnIdAtomicLoad, + BuiltinFnIdAtomicStore, BuiltinFnIdHasDecl, BuiltinFnIdUnionInit, BuiltinFnIdFrameAddress, BuiltinFnIdFrameType, BuiltinFnIdFrameHandle, BuiltinFnIdFrameSize, + BuiltinFnIdAs, }; struct BuiltinFnEntry { @@ -1739,6 +1757,7 @@ struct TypeId { union { struct { ZigType *child_type; + InferredStructField *inferred_struct_field; PtrLen ptr_len; uint32_t alignment; @@ -2552,6 +2571,7 @@ enum IrInstructionId { IrInstructionIdErrorUnion, IrInstructionIdAtomicRmw, IrInstructionIdAtomicLoad, + IrInstructionIdAtomicStore, IrInstructionIdSaveErrRetAddr, IrInstructionIdAddImplicitReturnType, IrInstructionIdErrSetCast, @@ -2810,7 +2830,7 @@ struct IrInstructionElemPtr { IrInstruction *array_ptr; IrInstruction *elem_index; - IrInstruction *init_array_type; + AstNode *init_array_type_source_node; PtrLen ptr_len; bool safety_check_on; }; @@ -2907,11 +2927,11 @@ struct IrInstructionResizeSlice { struct IrInstructionContainerInitList { IrInstruction base; - IrInstruction *container_type; IrInstruction *elem_type; size_t item_count; IrInstruction **elem_result_loc_list; IrInstruction *result_loc; + AstNode *init_array_type_source_node; }; struct IrInstructionContainerInitFieldsField { @@ -2924,7 +2944,6 @@ struct IrInstructionContainerInitFieldsField { struct IrInstructionContainerInitFields { IrInstruction base; - IrInstruction *container_type; size_t field_count; IrInstructionContainerInitFieldsField *fields; IrInstruction *result_loc; @@ -3458,6 +3477,13 @@ struct IrInstructionPtrCastGen { bool safety_check_on; }; +struct IrInstructionImplicitCast { + IrInstruction base; + + IrInstruction *operand; + ResultLocCast *result_loc_cast; +}; + struct IrInstructionBitCastSrc { IrInstruction base; @@ -3642,6 +3668,7 @@ struct IrInstructionArgType { IrInstruction *fn_type; IrInstruction *arg_index; + bool allow_var; }; struct IrInstructionExport { @@ -3690,6 +3717,16 @@ struct IrInstructionAtomicLoad { AtomicOrder resolved_ordering; }; +struct IrInstructionAtomicStore { + IrInstruction base; + + IrInstruction *operand_type; + IrInstruction *ptr; + IrInstruction *value; + IrInstruction *ordering; + AtomicOrder resolved_ordering; +}; + struct IrInstructionSaveErrRetAddr { IrInstruction base; }; @@ -3823,14 +3860,6 @@ struct IrInstructionEndExpr { ResultLoc *result_loc; }; -struct IrInstructionImplicitCast { - IrInstruction base; - - IrInstruction *dest_type; - IrInstruction *target; - ResultLoc *result_loc; -}; - // This one is for writing through the result pointer. struct IrInstructionResolveResult { IrInstruction base; @@ -3928,6 +3957,7 @@ enum ResultLocId { ResultLocIdPeerParent, ResultLocIdInstruction, ResultLocIdBitCast, + ResultLocIdCast, }; // Additions to this struct may need to be handled in @@ -3995,6 +4025,13 @@ struct ResultLocBitCast { ResultLoc *parent; }; +// The source_instruction is the destination type +struct ResultLocCast { + ResultLoc base; + + ResultLoc *parent; +}; + static const size_t slice_ptr_index = 0; static const size_t slice_len_index = 1; diff --git a/src/analyze.cpp b/src/analyze.cpp index 66e1f8984b..0a8b32dca7 100644 --- a/src/analyze.cpp +++ b/src/analyze.cpp @@ -140,7 +140,6 @@ void init_scope(CodeGen *g, Scope *dest, ScopeId id, AstNode *source_node, Scope static ScopeDecls *create_decls_scope(CodeGen *g, AstNode *node, Scope *parent, ZigType *container_type, ZigType *import, Buf *bare_name) { - assert(node == nullptr || node->type == NodeTypeContainerDecl || node->type == NodeTypeFnCallExpr); ScopeDecls *scope = allocate<ScopeDecls>(1); init_scope(g, &scope->base, ScopeIdDecls, node, parent); scope->decl_table.init(4); @@ -346,6 +345,8 @@ bool type_is_resolved(ZigType *type_entry, ResolveStatus status) { switch (status) { case ResolveStatusInvalid: zig_unreachable(); + case ResolveStatusBeingInferred: + zig_unreachable(); case ResolveStatusUnstarted: case ResolveStatusZeroBitsKnown: return true; @@ -362,6 +363,8 @@ bool type_is_resolved(ZigType *type_entry, ResolveStatus status) { switch (status) { case ResolveStatusInvalid: zig_unreachable(); + case ResolveStatusBeingInferred: + zig_unreachable(); case ResolveStatusUnstarted: return true; case ResolveStatusZeroBitsKnown: @@ -483,7 +486,7 @@ ZigType *get_fn_frame_type(CodeGen *g, ZigFn *fn) { ZigType *get_pointer_to_type_extra2(CodeGen *g, ZigType *child_type, bool is_const, bool is_volatile, PtrLen ptr_len, uint32_t byte_alignment, uint32_t bit_offset_in_host, uint32_t host_int_bytes, bool allow_zero, - uint32_t vector_index) + uint32_t vector_index, InferredStructField *inferred_struct_field) { assert(ptr_len != PtrLenC || allow_zero); assert(!type_is_invalid(child_type)); @@ -506,7 +509,7 @@ ZigType *get_pointer_to_type_extra2(CodeGen *g, ZigType *child_type, bool is_con TypeId type_id = {}; ZigType **parent_pointer = nullptr; if (host_int_bytes != 0 || is_volatile || byte_alignment != 0 || ptr_len != PtrLenSingle || - allow_zero || vector_index != VECTOR_INDEX_NONE) + allow_zero || vector_index != VECTOR_INDEX_NONE || inferred_struct_field != nullptr) { type_id.id = ZigTypeIdPointer; type_id.data.pointer.child_type = child_type; @@ -518,6 +521,7 @@ ZigType *get_pointer_to_type_extra2(CodeGen *g, ZigType *child_type, bool is_con type_id.data.pointer.ptr_len = ptr_len; type_id.data.pointer.allow_zero = allow_zero; type_id.data.pointer.vector_index = vector_index; + type_id.data.pointer.inferred_struct_field = inferred_struct_field; auto existing_entry = g->type_table.maybe_get(type_id); if (existing_entry) @@ -545,8 +549,15 @@ ZigType *get_pointer_to_type_extra2(CodeGen *g, ZigType *child_type, bool is_con } buf_resize(&entry->name, 0); if (host_int_bytes == 0 && byte_alignment == 0 && vector_index == VECTOR_INDEX_NONE) { - buf_appendf(&entry->name, "%s%s%s%s%s", - star_str, const_str, volatile_str, allow_zero_str, buf_ptr(&child_type->name)); + if (inferred_struct_field == nullptr) { + buf_appendf(&entry->name, "%s%s%s%s%s", + star_str, const_str, volatile_str, allow_zero_str, buf_ptr(&child_type->name)); + } else { + buf_appendf(&entry->name, "(%s%s%s%s field '%s' of %s)", + star_str, const_str, volatile_str, allow_zero_str, + buf_ptr(inferred_struct_field->field_name), + buf_ptr(&inferred_struct_field->inferred_struct_type->name)); + } } else if (host_int_bytes == 0 && vector_index == VECTOR_INDEX_NONE) { buf_appendf(&entry->name, "%salign(%" PRIu32 ") %s%s%s%s", star_str, byte_alignment, const_str, volatile_str, allow_zero_str, buf_ptr(&child_type->name)); @@ -603,6 +614,7 @@ ZigType *get_pointer_to_type_extra2(CodeGen *g, ZigType *child_type, bool is_con entry->data.pointer.host_int_bytes = host_int_bytes; entry->data.pointer.allow_zero = allow_zero; entry->data.pointer.vector_index = vector_index; + entry->data.pointer.inferred_struct_field = inferred_struct_field; if (parent_pointer) { *parent_pointer = entry; @@ -617,12 +629,12 @@ ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, bool is_cons uint32_t bit_offset_in_host, uint32_t host_int_bytes, bool allow_zero) { return get_pointer_to_type_extra2(g, child_type, is_const, is_volatile, ptr_len, - byte_alignment, bit_offset_in_host, host_int_bytes, allow_zero, VECTOR_INDEX_NONE); + byte_alignment, bit_offset_in_host, host_int_bytes, allow_zero, VECTOR_INDEX_NONE, nullptr); } ZigType *get_pointer_to_type(CodeGen *g, ZigType *child_type, bool is_const) { return get_pointer_to_type_extra2(g, child_type, is_const, false, PtrLenSingle, 0, 0, 0, false, - VECTOR_INDEX_NONE); + VECTOR_INDEX_NONE, nullptr); } ZigType *get_optional_type(CodeGen *g, ZigType *child_type) { @@ -791,19 +803,19 @@ ZigType *get_slice_type(CodeGen *g, ZigType *ptr_type) { entry->data.structure.is_slice = true; entry->data.structure.src_field_count = element_count; entry->data.structure.gen_field_count = element_count; - entry->data.structure.fields = allocate<TypeStructField>(element_count); + entry->data.structure.fields = alloc_type_struct_fields(element_count); entry->data.structure.fields_by_name.init(element_count); - entry->data.structure.fields[slice_ptr_index].name = ptr_field_name; - entry->data.structure.fields[slice_ptr_index].type_entry = ptr_type; - entry->data.structure.fields[slice_ptr_index].src_index = slice_ptr_index; - entry->data.structure.fields[slice_ptr_index].gen_index = 0; - entry->data.structure.fields[slice_len_index].name = len_field_name; - entry->data.structure.fields[slice_len_index].type_entry = g->builtin_types.entry_usize; - entry->data.structure.fields[slice_len_index].src_index = slice_len_index; - entry->data.structure.fields[slice_len_index].gen_index = 1; - - entry->data.structure.fields_by_name.put(ptr_field_name, &entry->data.structure.fields[slice_ptr_index]); - entry->data.structure.fields_by_name.put(len_field_name, &entry->data.structure.fields[slice_len_index]); + entry->data.structure.fields[slice_ptr_index]->name = ptr_field_name; + entry->data.structure.fields[slice_ptr_index]->type_entry = ptr_type; + entry->data.structure.fields[slice_ptr_index]->src_index = slice_ptr_index; + entry->data.structure.fields[slice_ptr_index]->gen_index = 0; + entry->data.structure.fields[slice_len_index]->name = len_field_name; + entry->data.structure.fields[slice_len_index]->type_entry = g->builtin_types.entry_usize; + entry->data.structure.fields[slice_len_index]->src_index = slice_len_index; + entry->data.structure.fields[slice_len_index]->gen_index = 1; + + entry->data.structure.fields_by_name.put(ptr_field_name, entry->data.structure.fields[slice_ptr_index]); + entry->data.structure.fields_by_name.put(len_field_name, entry->data.structure.fields[slice_len_index]); switch (type_requires_comptime(g, ptr_type)) { case ReqCompTimeInvalid: @@ -816,8 +828,8 @@ ZigType *get_slice_type(CodeGen *g, ZigType *ptr_type) { if (!type_has_bits(ptr_type)) { entry->data.structure.gen_field_count = 1; - entry->data.structure.fields[slice_ptr_index].gen_index = SIZE_MAX; - entry->data.structure.fields[slice_len_index].gen_index = 0; + entry->data.structure.fields[slice_ptr_index]->gen_index = SIZE_MAX; + entry->data.structure.fields[slice_len_index]->gen_index = 0; } ZigType *child_type = ptr_type->data.pointer.child_type; @@ -1449,8 +1461,8 @@ static bool analyze_const_string(CodeGen *g, Scope *scope, AstNode *node, Buf ** if (type_is_invalid(result_val->type)) return false; - ConstExprValue *ptr_field = &result_val->data.x_struct.fields[slice_ptr_index]; - ConstExprValue *len_field = &result_val->data.x_struct.fields[slice_len_index]; + ConstExprValue *ptr_field = result_val->data.x_struct.fields[slice_ptr_index]; + ConstExprValue *len_field = result_val->data.x_struct.fields[slice_len_index]; assert(ptr_field->data.x_ptr.special == ConstPtrSpecialBaseArray); ConstExprValue *array_val = ptr_field->data.x_ptr.data.base_array.array_val; @@ -1972,12 +1984,12 @@ static ZigType *get_struct_type(CodeGen *g, const char *type_name, SrcField fiel struct_type->data.structure.src_field_count = field_count; struct_type->data.structure.gen_field_count = 0; struct_type->data.structure.resolve_status = ResolveStatusSizeKnown; - struct_type->data.structure.fields = allocate<TypeStructField>(field_count); + struct_type->data.structure.fields = alloc_type_struct_fields(field_count); struct_type->data.structure.fields_by_name.init(field_count); size_t abi_align = min_abi_align; for (size_t i = 0; i < field_count; i += 1) { - TypeStructField *field = &struct_type->data.structure.fields[i]; + TypeStructField *field = struct_type->data.structure.fields[i]; field->name = buf_create_from_str(fields[i].name); field->type_entry = fields[i].ty; field->src_index = i; @@ -1997,7 +2009,7 @@ static ZigType *get_struct_type(CodeGen *g, const char *type_name, SrcField fiel size_t next_offset = 0; for (size_t i = 0; i < field_count; i += 1) { - TypeStructField *field = &struct_type->data.structure.fields[i]; + TypeStructField *field = struct_type->data.structure.fields[i]; if (!type_has_bits(field->type_entry)) continue; @@ -2006,7 +2018,7 @@ static ZigType *get_struct_type(CodeGen *g, const char *type_name, SrcField fiel // find the next non-zero-byte field for offset calculations size_t next_src_field_index = i + 1; for (; next_src_field_index < field_count; next_src_field_index += 1) { - if (type_has_bits(struct_type->data.structure.fields[next_src_field_index].type_entry)) + if (type_has_bits(struct_type->data.structure.fields[next_src_field_index]->type_entry)) break; } size_t next_abi_align; @@ -2014,7 +2026,7 @@ static ZigType *get_struct_type(CodeGen *g, const char *type_name, SrcField fiel next_abi_align = abi_align; } else { next_abi_align = max(fields[next_src_field_index].align, - struct_type->data.structure.fields[next_src_field_index].type_entry->abi_align); + struct_type->data.structure.fields[next_src_field_index]->type_entry->abi_align); } next_offset = next_field_offset(next_offset, abi_align, field->type_entry->abi_size, next_abi_align); } @@ -2079,7 +2091,7 @@ static Error resolve_struct_type(CodeGen *g, ZigType *struct_type) { } assert(struct_type->data.structure.fields || struct_type->data.structure.src_field_count == 0); - assert(decl_node->type == NodeTypeContainerDecl); + assert(decl_node->type == NodeTypeContainerDecl || decl_node->type == NodeTypeContainerInitExpr); size_t field_count = struct_type->data.structure.src_field_count; @@ -2097,7 +2109,7 @@ static Error resolve_struct_type(CodeGen *g, ZigType *struct_type) { // Calculate offsets for (size_t i = 0; i < field_count; i += 1) { - TypeStructField *field = &struct_type->data.structure.fields[i]; + TypeStructField *field = struct_type->data.structure.fields[i]; if (field->gen_index == SIZE_MAX) continue; @@ -2166,12 +2178,12 @@ static Error resolve_struct_type(CodeGen *g, ZigType *struct_type) { gen_field_index += 1; size_t next_src_field_index = i + 1; for (; next_src_field_index < field_count; next_src_field_index += 1) { - if (struct_type->data.structure.fields[next_src_field_index].gen_index != SIZE_MAX) { + if (struct_type->data.structure.fields[next_src_field_index]->gen_index != SIZE_MAX) { break; } } size_t next_align = (next_src_field_index == field_count) ? - abi_align : struct_type->data.structure.fields[next_src_field_index].align; + abi_align : struct_type->data.structure.fields[next_src_field_index]->align; next_offset = next_field_offset(next_offset, abi_align, field_abi_size, next_align); size_in_bits = next_offset * 8; } @@ -2194,7 +2206,7 @@ static Error resolve_struct_type(CodeGen *g, ZigType *struct_type) { // Resolve types for fields for (size_t i = 0; i < field_count; i += 1) { - TypeStructField *field = &struct_type->data.structure.fields[i]; + TypeStructField *field = struct_type->data.structure.fields[i]; ZigType *field_type = resolve_struct_field_type(g, field); if (field_type == nullptr) { struct_type->data.structure.resolve_status = ResolveStatusInvalid; @@ -2667,7 +2679,6 @@ static Error resolve_struct_zero_bits(CodeGen *g, ZigType *struct_type) { return ErrorNone; AstNode *decl_node = struct_type->data.structure.decl_node; - assert(decl_node->type == NodeTypeContainerDecl); if (struct_type->data.structure.resolve_loop_flag_zero_bits) { if (struct_type->data.structure.resolve_status != ResolveStatusInvalid) { @@ -2678,29 +2689,46 @@ static Error resolve_struct_zero_bits(CodeGen *g, ZigType *struct_type) { } return ErrorSemanticAnalyzeFail; } - struct_type->data.structure.resolve_loop_flag_zero_bits = true; - assert(!struct_type->data.structure.fields); - size_t field_count = decl_node->data.container_decl.fields.length; - struct_type->data.structure.src_field_count = (uint32_t)field_count; - struct_type->data.structure.fields = allocate<TypeStructField>(field_count); + size_t field_count; + if (decl_node->type == NodeTypeContainerDecl) { + field_count = decl_node->data.container_decl.fields.length; + struct_type->data.structure.src_field_count = (uint32_t)field_count; + + src_assert(struct_type->data.structure.fields == nullptr, decl_node); + struct_type->data.structure.fields = alloc_type_struct_fields(field_count); + } else if (decl_node->type == NodeTypeContainerInitExpr) { + src_assert(struct_type->data.structure.is_inferred, decl_node); + src_assert(struct_type->data.structure.fields != nullptr, decl_node); + + field_count = struct_type->data.structure.src_field_count; + } else zig_unreachable(); + struct_type->data.structure.fields_by_name.init(field_count); Scope *scope = &struct_type->data.structure.decls_scope->base; size_t gen_field_index = 0; for (size_t i = 0; i < field_count; i += 1) { - AstNode *field_node = decl_node->data.container_decl.fields.at(i); - TypeStructField *type_struct_field = &struct_type->data.structure.fields[i]; - type_struct_field->name = field_node->data.struct_field.name; - type_struct_field->decl_node = field_node; + TypeStructField *type_struct_field = struct_type->data.structure.fields[i]; - if (field_node->data.struct_field.type == nullptr) { - add_node_error(g, field_node, buf_sprintf("struct field missing type")); - struct_type->data.structure.resolve_status = ResolveStatusInvalid; - return ErrorSemanticAnalyzeFail; - } + AstNode *field_node; + if (decl_node->type == NodeTypeContainerDecl) { + field_node = decl_node->data.container_decl.fields.at(i); + type_struct_field->name = field_node->data.struct_field.name; + type_struct_field->decl_node = field_node; + + if (field_node->data.struct_field.type == nullptr) { + add_node_error(g, field_node, buf_sprintf("struct field missing type")); + struct_type->data.structure.resolve_status = ResolveStatusInvalid; + return ErrorSemanticAnalyzeFail; + } + } else if (decl_node->type == NodeTypeContainerInitExpr) { + field_node = type_struct_field->decl_node; + + src_assert(type_struct_field->type_entry != nullptr, field_node); + } else zig_unreachable(); auto field_entry = struct_type->data.structure.fields_by_name.put_unique(type_struct_field->name, type_struct_field); if (field_entry != nullptr) { @@ -2711,16 +2739,21 @@ static Error resolve_struct_zero_bits(CodeGen *g, ZigType *struct_type) { return ErrorSemanticAnalyzeFail; } - ConstExprValue *field_type_val = analyze_const_value(g, scope, - field_node->data.struct_field.type, g->builtin_types.entry_type, nullptr, LazyOkNoUndef); - if (type_is_invalid(field_type_val->type)) { - struct_type->data.structure.resolve_status = ResolveStatusInvalid; - return ErrorSemanticAnalyzeFail; - } - assert(field_type_val->special != ConstValSpecialRuntime); - type_struct_field->type_val = field_type_val; - if (struct_type->data.structure.resolve_status == ResolveStatusInvalid) - return ErrorSemanticAnalyzeFail; + ConstExprValue *field_type_val; + if (decl_node->type == NodeTypeContainerDecl) { + field_type_val = analyze_const_value(g, scope, + field_node->data.struct_field.type, g->builtin_types.entry_type, nullptr, LazyOkNoUndef); + if (type_is_invalid(field_type_val->type)) { + struct_type->data.structure.resolve_status = ResolveStatusInvalid; + return ErrorSemanticAnalyzeFail; + } + assert(field_type_val->special != ConstValSpecialRuntime); + type_struct_field->type_val = field_type_val; + if (struct_type->data.structure.resolve_status == ResolveStatusInvalid) + return ErrorSemanticAnalyzeFail; + } else if (decl_node->type == NodeTypeContainerInitExpr) { + field_type_val = type_struct_field->type_val; + } else zig_unreachable(); bool field_is_opaque_type; if ((err = type_val_resolve_is_opaque_type(g, field_type_val, &field_is_opaque_type))) { @@ -2804,17 +2837,18 @@ static Error resolve_struct_alignment(CodeGen *g, ZigType *struct_type) { } struct_type->data.structure.resolve_loop_flag_other = true; - assert(decl_node->type == NodeTypeContainerDecl); + assert(decl_node->type == NodeTypeContainerDecl || decl_node->type == NodeTypeContainerInitExpr); size_t field_count = struct_type->data.structure.src_field_count; bool packed = struct_type->data.structure.layout == ContainerLayoutPacked; for (size_t i = 0; i < field_count; i += 1) { - TypeStructField *field = &struct_type->data.structure.fields[i]; + TypeStructField *field = struct_type->data.structure.fields[i]; if (field->gen_index == SIZE_MAX) continue; - AstNode *align_expr = field->decl_node->data.struct_field.align_expr; + AstNode *align_expr = (field->decl_node->type == NodeTypeStructField) ? + field->decl_node->data.struct_field.align_expr : nullptr; if (align_expr != nullptr) { if (!analyze_const_align(g, &struct_type->data.structure.decls_scope->base, align_expr, &field->align)) @@ -5249,7 +5283,7 @@ static bool can_mutate_comptime_var_state(ConstExprValue *value) { zig_unreachable(); case ZigTypeIdStruct: for (uint32_t i = 0; i < value->type->data.structure.src_field_count; i += 1) { - if (can_mutate_comptime_var_state(&value->data.x_struct.fields[i])) + if (can_mutate_comptime_var_state(value->data.x_struct.fields[i])) return true; } return false; @@ -5398,7 +5432,7 @@ bool fn_eval_eql(Scope *a, Scope *b) { return false; } -// Whether the type has bits at runtime. +// Deprecated. Use type_has_bits2. bool type_has_bits(ZigType *type_entry) { assert(type_entry != nullptr); assert(!type_is_invalid(type_entry)); @@ -5406,6 +5440,27 @@ bool type_has_bits(ZigType *type_entry) { return type_entry->abi_size != 0; } +// Whether the type has bits at runtime. +Error type_has_bits2(CodeGen *g, ZigType *type_entry, bool *result) { + Error err; + + if (type_is_invalid(type_entry)) + return ErrorSemanticAnalyzeFail; + + if (type_entry->id == ZigTypeIdStruct && + type_entry->data.structure.resolve_status == ResolveStatusBeingInferred) + { + *result = true; + return ErrorNone; + } + + if ((err = type_resolve(g, type_entry, ResolveStatusZeroBitsKnown))) + return err; + + *result = type_entry->abi_size != 0; + return ErrorNone; +} + // Whether you can infer the value based solely on the type. OnePossibleValue type_has_one_possible_value(CodeGen *g, ZigType *type_entry) { assert(type_entry != nullptr); @@ -5413,6 +5468,12 @@ OnePossibleValue type_has_one_possible_value(CodeGen *g, ZigType *type_entry) { if (type_entry->one_possible_value != OnePossibleValueInvalid) return type_entry->one_possible_value; + if (type_entry->id == ZigTypeIdStruct && + type_entry->data.structure.resolve_status == ResolveStatusBeingInferred) + { + return OnePossibleValueNo; + } + Error err; if ((err = type_resolve(g, type_entry, ResolveStatusZeroBitsKnown))) return OnePossibleValueInvalid; @@ -5445,7 +5506,7 @@ OnePossibleValue type_has_one_possible_value(CodeGen *g, ZigType *type_entry) { return type_has_one_possible_value(g, type_entry->data.array.child_type); case ZigTypeIdStruct: for (size_t i = 0; i < type_entry->data.structure.src_field_count; i += 1) { - TypeStructField *field = &type_entry->data.structure.fields[i]; + TypeStructField *field = type_entry->data.structure.fields[i]; OnePossibleValue opv = (field->type_entry != nullptr) ? type_has_one_possible_value(g, field->type_entry) : type_val_resolve_has_one_possible_value(g, field->type_val); @@ -5737,11 +5798,11 @@ void init_const_slice(CodeGen *g, ConstExprValue *const_val, ConstExprValue *arr const_val->special = ConstValSpecialStatic; const_val->type = get_slice_type(g, ptr_type); - const_val->data.x_struct.fields = create_const_vals(2); + const_val->data.x_struct.fields = alloc_const_vals_ptrs(2); - init_const_ptr_array(g, &const_val->data.x_struct.fields[slice_ptr_index], array_val, start, is_const, + init_const_ptr_array(g, const_val->data.x_struct.fields[slice_ptr_index], array_val, start, is_const, PtrLenUnknown); - init_const_usize(g, &const_val->data.x_struct.fields[slice_len_index], len); + init_const_usize(g, const_val->data.x_struct.fields[slice_len_index], len); } ConstExprValue *create_const_slice(CodeGen *g, ConstExprValue *array_val, size_t start, size_t len, bool is_const) { @@ -5825,6 +5886,38 @@ ConstExprValue *create_const_vals(size_t count) { return vals; } +ConstExprValue **alloc_const_vals_ptrs(size_t count) { + return realloc_const_vals_ptrs(nullptr, 0, count); +} + +ConstExprValue **realloc_const_vals_ptrs(ConstExprValue **ptr, size_t old_count, size_t new_count) { + assert(new_count >= old_count); + + size_t new_item_count = new_count - old_count; + ConstExprValue **result = reallocate(ptr, old_count, new_count, "ConstExprValue*"); + ConstExprValue *vals = create_const_vals(new_item_count); + for (size_t i = old_count; i < new_count; i += 1) { + result[i] = &vals[i - old_count]; + } + return result; +} + +TypeStructField **alloc_type_struct_fields(size_t count) { + return realloc_type_struct_fields(nullptr, 0, count); +} + +TypeStructField **realloc_type_struct_fields(TypeStructField **ptr, size_t old_count, size_t new_count) { + assert(new_count >= old_count); + + size_t new_item_count = new_count - old_count; + TypeStructField **result = reallocate(ptr, old_count, new_count, "TypeStructField*"); + TypeStructField *vals = allocate<TypeStructField>(new_item_count, "TypeStructField"); + for (size_t i = old_count; i < new_count; i += 1) { + result[i] = &vals[i - old_count]; + } + return result; +} + static ZigType *get_async_fn_type(CodeGen *g, ZigType *orig_fn_type) { if (orig_fn_type->data.fn.fn_type_id.cc == CallingConventionAsync) return orig_fn_type; @@ -6132,6 +6225,8 @@ static Error resolve_async_frame(CodeGen *g, ZigType *frame_type) { continue; if (instruction->ref_count == 0) continue; + if ((err = type_resolve(g, instruction->value.type, ResolveStatusZeroBitsKnown))) + return ErrorSemanticAnalyzeFail; if (!type_has_bits(instruction->value.type)) continue; if (scope_needs_spill(instruction->scope)) { @@ -6271,6 +6366,8 @@ Error type_resolve(CodeGen *g, ZigType *ty, ResolveStatus status) { switch (status) { case ResolveStatusUnstarted: return ErrorNone; + case ResolveStatusBeingInferred: + zig_unreachable(); case ResolveStatusInvalid: zig_unreachable(); case ResolveStatusZeroBitsKnown: @@ -6502,8 +6599,8 @@ bool const_values_equal(CodeGen *g, ConstExprValue *a, ConstExprValue *b) { } case ZigTypeIdStruct: for (size_t i = 0; i < a->type->data.structure.src_field_count; i += 1) { - ConstExprValue *field_a = &a->data.x_struct.fields[i]; - ConstExprValue *field_b = &b->data.x_struct.fields[i]; + ConstExprValue *field_a = a->data.x_struct.fields[i]; + ConstExprValue *field_b = b->data.x_struct.fields[i]; if (!const_values_equal(g, field_a, field_b)) return false; } @@ -6811,10 +6908,10 @@ void render_const_value(CodeGen *g, Buf *buf, ConstExprValue *const_val) { case ZigTypeIdStruct: { if (is_slice(type_entry)) { - ConstExprValue *len_val = &const_val->data.x_struct.fields[slice_len_index]; + ConstExprValue *len_val = const_val->data.x_struct.fields[slice_len_index]; size_t len = bigint_as_usize(&len_val->data.x_bigint); - ConstExprValue *ptr_val = &const_val->data.x_struct.fields[slice_ptr_index]; + ConstExprValue *ptr_val = const_val->data.x_struct.fields[slice_ptr_index]; if (ptr_val->special == ConstValSpecialUndef) { assert(len == 0); buf_appendf(buf, "((%s)(undefined))[0..0]", buf_ptr(&type_entry->name)); @@ -6995,7 +7092,16 @@ bool type_id_eql(TypeId a, TypeId b) { a.data.pointer.alignment == b.data.pointer.alignment && a.data.pointer.bit_offset_in_host == b.data.pointer.bit_offset_in_host && a.data.pointer.vector_index == b.data.pointer.vector_index && - a.data.pointer.host_int_bytes == b.data.pointer.host_int_bytes; + a.data.pointer.host_int_bytes == b.data.pointer.host_int_bytes && + ( + a.data.pointer.inferred_struct_field == b.data.pointer.inferred_struct_field || + (a.data.pointer.inferred_struct_field != nullptr && + b.data.pointer.inferred_struct_field != nullptr && + a.data.pointer.inferred_struct_field->inferred_struct_type == + b.data.pointer.inferred_struct_field->inferred_struct_type && + buf_eql_buf(a.data.pointer.inferred_struct_field->field_name, + b.data.pointer.inferred_struct_field->field_name)) + ); case ZigTypeIdArray: return a.data.array.child_type == b.data.array.child_type && a.data.array.size == b.data.array.size; @@ -7082,10 +7188,10 @@ static void init_const_undefined(CodeGen *g, ConstExprValue *const_val) { const_val->special = ConstValSpecialStatic; size_t field_count = wanted_type->data.structure.src_field_count; - const_val->data.x_struct.fields = create_const_vals(field_count); + const_val->data.x_struct.fields = alloc_const_vals_ptrs(field_count); for (size_t i = 0; i < field_count; i += 1) { - ConstExprValue *field_val = &const_val->data.x_struct.fields[i]; - field_val->type = wanted_type->data.structure.fields[i].type_entry; + ConstExprValue *field_val = const_val->data.x_struct.fields[i]; + field_val->type = resolve_struct_field_type(g, wanted_type->data.structure.fields[i]); assert(field_val->type); init_const_undefined(g, field_val); field_val->parent.id = ConstParentIdStruct; @@ -7517,7 +7623,7 @@ static X64CABIClass type_system_V_abi_x86_64_class(CodeGen *g, ZigType *ty, size } X64CABIClass working_class = X64CABIClass_Unknown; for (uint32_t i = 0; i < ty->data.structure.src_field_count; i += 1) { - X64CABIClass field_class = type_c_abi_x86_64_class(g, ty->data.structure.fields->type_entry); + X64CABIClass field_class = type_c_abi_x86_64_class(g, ty->data.structure.fields[0]->type_entry); if (field_class == X64CABIClass_Unknown) return X64CABIClass_Unknown; if (i == 0 || field_class == X64CABIClass_MEMORY || working_class == X64CABIClass_SSE) { @@ -7649,7 +7755,7 @@ Buf *type_h_name(ZigType *t) { static void resolve_llvm_types_slice(CodeGen *g, ZigType *type, ResolveStatus wanted_resolve_status) { if (type->data.structure.resolve_status >= wanted_resolve_status) return; - ZigType *ptr_type = type->data.structure.fields[slice_ptr_index].type_entry; + ZigType *ptr_type = type->data.structure.fields[slice_ptr_index]->type_entry; ZigType *child_type = ptr_type->data.pointer.child_type; ZigType *usize_type = g->builtin_types.entry_usize; @@ -7671,7 +7777,7 @@ static void resolve_llvm_types_slice(CodeGen *g, ZigType *type, ResolveStatus wa // If the child type is []const T then we need to make sure the type ref // and debug info is the same as if the child type were []T. if (is_slice(child_type)) { - ZigType *child_ptr_type = child_type->data.structure.fields[slice_ptr_index].type_entry; + ZigType *child_ptr_type = child_type->data.structure.fields[slice_ptr_index]->type_entry; assert(child_ptr_type->id == ZigTypeIdPointer); if (child_ptr_type->data.pointer.is_const || child_ptr_type->data.pointer.is_volatile || child_ptr_type->data.pointer.explicit_alignment != 0 || child_ptr_type->data.pointer.allow_zero) @@ -7808,7 +7914,6 @@ static void resolve_llvm_types_struct(CodeGen *g, ZigType *struct_type, ResolveS ZigLLVMDIScope *di_scope; unsigned line; if (decl_node != nullptr) { - assert(decl_node->type == NodeTypeContainerDecl); Scope *scope = &struct_type->data.structure.decls_scope->base; ZigType *import = get_scope_import(scope); di_file = import->data.structure.root_struct->di_file; @@ -7849,7 +7954,7 @@ static void resolve_llvm_types_struct(CodeGen *g, ZigType *struct_type, ResolveS // trigger all the recursive get_llvm_type calls for (size_t i = 0; i < field_count; i += 1) { - TypeStructField *field = &struct_type->data.structure.fields[i]; + TypeStructField *field = struct_type->data.structure.fields[i]; ZigType *field_type = field->type_entry; if (!type_has_bits(field_type)) continue; @@ -7863,7 +7968,7 @@ static void resolve_llvm_types_struct(CodeGen *g, ZigType *struct_type, ResolveS // inserting padding bytes where LLVM would do it automatically. size_t llvm_struct_abi_align = 0; for (size_t i = 0; i < field_count; i += 1) { - ZigType *field_type = struct_type->data.structure.fields[i].type_entry; + ZigType *field_type = struct_type->data.structure.fields[i]->type_entry; if (!type_has_bits(field_type)) continue; LLVMTypeRef field_llvm_type = get_llvm_type(g, field_type); @@ -7872,7 +7977,7 @@ static void resolve_llvm_types_struct(CodeGen *g, ZigType *struct_type, ResolveS } for (size_t i = 0; i < field_count; i += 1) { - TypeStructField *field = &struct_type->data.structure.fields[i]; + TypeStructField *field = struct_type->data.structure.fields[i]; ZigType *field_type = field->type_entry; if (!type_has_bits(field_type)) { @@ -7922,23 +8027,23 @@ static void resolve_llvm_types_struct(CodeGen *g, ZigType *struct_type, ResolveS // find the next non-zero-byte field for offset calculations size_t next_src_field_index = i + 1; for (; next_src_field_index < field_count; next_src_field_index += 1) { - if (type_has_bits(struct_type->data.structure.fields[next_src_field_index].type_entry)) + if (type_has_bits(struct_type->data.structure.fields[next_src_field_index]->type_entry)) break; } size_t next_abi_align; if (next_src_field_index == field_count) { next_abi_align = struct_type->abi_align; } else { - if (struct_type->data.structure.fields[next_src_field_index].align == 0) { - next_abi_align = struct_type->data.structure.fields[next_src_field_index].type_entry->abi_align; + if (struct_type->data.structure.fields[next_src_field_index]->align == 0) { + next_abi_align = struct_type->data.structure.fields[next_src_field_index]->type_entry->abi_align; } else { - next_abi_align = struct_type->data.structure.fields[next_src_field_index].align; + next_abi_align = struct_type->data.structure.fields[next_src_field_index]->align; } } size_t llvm_next_abi_align = (next_src_field_index == field_count) ? llvm_struct_abi_align : LLVMABIAlignmentOfType(g->target_data_ref, - get_llvm_type(g, struct_type->data.structure.fields[next_src_field_index].type_entry)); + get_llvm_type(g, struct_type->data.structure.fields[next_src_field_index]->type_entry)); size_t next_offset = next_field_offset(field->offset, struct_type->abi_align, field_type->abi_size, next_abi_align); @@ -7977,7 +8082,7 @@ static void resolve_llvm_types_struct(CodeGen *g, ZigType *struct_type, ResolveS ZigLLVMDIType **di_element_types = allocate<ZigLLVMDIType*>(debug_field_count); size_t debug_field_index = 0; for (size_t i = 0; i < field_count; i += 1) { - TypeStructField *field = &struct_type->data.structure.fields[i]; + TypeStructField *field = struct_type->data.structure.fields[i]; size_t gen_field_index = field->gen_index; if (gen_field_index == SIZE_MAX) { continue; @@ -8011,7 +8116,7 @@ static void resolve_llvm_types_struct(CodeGen *g, ZigType *struct_type, ResolveS } unsigned line; if (decl_node != nullptr) { - AstNode *field_node = decl_node->data.container_decl.fields.at(i); + AstNode *field_node = field->decl_node; line = field_node->line + 1; } else { line = 0; @@ -8307,12 +8412,12 @@ static void resolve_llvm_types_pointer(CodeGen *g, ZigType *type, ResolveStatus if (type->data.pointer.vector_index == VECTOR_INDEX_NONE) { peer_type = get_pointer_to_type_extra2(g, elem_type, false, false, PtrLenSingle, 0, 0, type->data.pointer.host_int_bytes, false, - VECTOR_INDEX_NONE); + VECTOR_INDEX_NONE, nullptr); } else { uint32_t host_vec_len = type->data.pointer.host_int_bytes; ZigType *host_vec_type = get_vector_type(g, host_vec_len, elem_type); peer_type = get_pointer_to_type_extra2(g, host_vec_type, false, false, - PtrLenSingle, 0, 0, 0, false, VECTOR_INDEX_NONE); + PtrLenSingle, 0, 0, 0, false, VECTOR_INDEX_NONE, nullptr); } type->llvm_type = get_llvm_type(g, peer_type); type->llvm_di_type = get_llvm_di_type(g, peer_type); @@ -9038,4 +9143,3 @@ Error analyze_import(CodeGen *g, ZigType *source_import, Buf *import_target_str, *out_import = add_source_file(g, target_package, resolved_path, import_code, source_kind); return ErrorNone; } - diff --git a/src/analyze.hpp b/src/analyze.hpp index a6af371e25..ddfb31c286 100644 --- a/src/analyze.hpp +++ b/src/analyze.hpp @@ -24,7 +24,7 @@ ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, ZigType *get_pointer_to_type_extra2(CodeGen *g, ZigType *child_type, bool is_const, bool is_volatile, PtrLen ptr_len, uint32_t byte_alignment, uint32_t bit_offset, uint32_t unaligned_bit_count, - bool allow_zero, uint32_t vector_index); + bool allow_zero, uint32_t vector_index, InferredStructField *inferred_struct_field); uint64_t type_size(CodeGen *g, ZigType *type_entry); uint64_t type_size_bits(CodeGen *g, ZigType *type_entry); ZigType *get_int_type(CodeGen *g, bool is_signed, uint32_t size_in_bits); @@ -46,6 +46,8 @@ ZigType *get_any_frame_type(CodeGen *g, ZigType *result_type); bool handle_is_ptr(ZigType *type_entry); bool type_has_bits(ZigType *type_entry); +Error type_has_bits2(CodeGen *g, ZigType *type_entry, bool *result); + Error type_allowed_in_extern(CodeGen *g, ZigType *type_entry, bool *result); bool ptr_allows_addr_zero(ZigType *ptr_type); bool type_is_nonnull_ptr(ZigType *type); @@ -175,6 +177,11 @@ void init_const_arg_tuple(CodeGen *g, ConstExprValue *const_val, size_t arg_inde ConstExprValue *create_const_arg_tuple(CodeGen *g, size_t arg_index_start, size_t arg_index_end); ConstExprValue *create_const_vals(size_t count); +ConstExprValue **alloc_const_vals_ptrs(size_t count); +ConstExprValue **realloc_const_vals_ptrs(ConstExprValue **ptr, size_t old_count, size_t new_count); + +TypeStructField **alloc_type_struct_fields(size_t count); +TypeStructField **realloc_type_struct_fields(TypeStructField **ptr, size_t old_count, size_t new_count); ZigType *make_int_type(CodeGen *g, bool is_signed, uint32_t size_in_bits); void expand_undef_array(CodeGen *g, ConstExprValue *const_val); diff --git a/src/ast_render.cpp b/src/ast_render.cpp index 18940c4b80..34cbed245a 100644 --- a/src/ast_render.cpp +++ b/src/ast_render.cpp @@ -821,7 +821,9 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) { break; } case NodeTypeContainerInitExpr: - render_node_ungrouped(ar, node->data.container_init_expr.type); + if (node->data.container_init_expr.type != nullptr) { + render_node_ungrouped(ar, node->data.container_init_expr.type); + } if (node->data.container_init_expr.kind == ContainerInitKindStruct) { fprintf(ar->f, "{\n"); ar->indent += ar->indent_size; @@ -1137,10 +1139,20 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) { for (size_t i = 0; i < node->data.err_set_decl.decls.length; i += 1) { AstNode *field_node = node->data.err_set_decl.decls.at(i); - assert(field_node->type == NodeTypeSymbol); - print_indent(ar); - print_symbol(ar, field_node->data.symbol_expr.symbol); - fprintf(ar->f, ",\n"); + switch (field_node->type) { + case NodeTypeSymbol: + print_indent(ar); + print_symbol(ar, field_node->data.symbol_expr.symbol); + fprintf(ar->f, ",\n"); + break; + case NodeTypeErrorSetField: + print_indent(ar); + print_symbol(ar, field_node->data.err_set_field.field_name->data.symbol_expr.symbol); + fprintf(ar->f, ",\n"); + break; + default: + zig_unreachable(); + } } ar->indent -= ar->indent_size; diff --git a/src/codegen.cpp b/src/codegen.cpp index 154c21893a..f90777c983 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -1108,15 +1108,15 @@ static LLVMValueRef get_add_error_return_trace_addr_fn(CodeGen *g) { LLVMValueRef err_ret_trace_ptr = LLVMGetParam(fn_val, 0); LLVMValueRef address_value = LLVMGetParam(fn_val, 1); - size_t index_field_index = g->stack_trace_type->data.structure.fields[0].gen_index; + size_t index_field_index = g->stack_trace_type->data.structure.fields[0]->gen_index; LLVMValueRef index_field_ptr = LLVMBuildStructGEP(g->builder, err_ret_trace_ptr, (unsigned)index_field_index, ""); - size_t addresses_field_index = g->stack_trace_type->data.structure.fields[1].gen_index; + size_t addresses_field_index = g->stack_trace_type->data.structure.fields[1]->gen_index; LLVMValueRef addresses_field_ptr = LLVMBuildStructGEP(g->builder, err_ret_trace_ptr, (unsigned)addresses_field_index, ""); - ZigType *slice_type = g->stack_trace_type->data.structure.fields[1].type_entry; - size_t ptr_field_index = slice_type->data.structure.fields[slice_ptr_index].gen_index; + ZigType *slice_type = g->stack_trace_type->data.structure.fields[1]->type_entry; + size_t ptr_field_index = slice_type->data.structure.fields[slice_ptr_index]->gen_index; LLVMValueRef ptr_field_ptr = LLVMBuildStructGEP(g->builder, addresses_field_ptr, (unsigned)ptr_field_index, ""); - size_t len_field_index = slice_type->data.structure.fields[slice_len_index].gen_index; + size_t len_field_index = slice_type->data.structure.fields[slice_len_index]->gen_index; LLVMValueRef len_field_ptr = LLVMBuildStructGEP(g->builder, addresses_field_ptr, (unsigned)len_field_index, ""); LLVMValueRef len_value = gen_load_untyped(g, len_field_ptr, 0, false, ""); @@ -1699,6 +1699,10 @@ static void gen_var_debug_decl(CodeGen *g, ZigVar *var) { } static LLVMValueRef ir_llvm_value(CodeGen *g, IrInstruction *instruction) { + Error err; + if ((err = type_resolve(g, instruction->value.type, ResolveStatusZeroBitsKnown))) { + codegen_report_errors_and_exit(g); + } if (!type_has_bits(instruction->value.type)) return nullptr; if (!instruction->llvm_value) { @@ -2172,16 +2176,16 @@ static LLVMValueRef get_merge_err_ret_traces_fn_val(CodeGen *g) { LLVMBuildCondBr(g->builder, null_bit, return_block, non_null_block); LLVMPositionBuilderAtEnd(g->builder, non_null_block); - size_t src_index_field_index = g->stack_trace_type->data.structure.fields[0].gen_index; - size_t src_addresses_field_index = g->stack_trace_type->data.structure.fields[1].gen_index; + size_t src_index_field_index = g->stack_trace_type->data.structure.fields[0]->gen_index; + size_t src_addresses_field_index = g->stack_trace_type->data.structure.fields[1]->gen_index; LLVMValueRef src_index_field_ptr = LLVMBuildStructGEP(g->builder, src_stack_trace_ptr, (unsigned)src_index_field_index, ""); LLVMValueRef src_addresses_field_ptr = LLVMBuildStructGEP(g->builder, src_stack_trace_ptr, (unsigned)src_addresses_field_index, ""); - ZigType *slice_type = g->stack_trace_type->data.structure.fields[1].type_entry; - size_t ptr_field_index = slice_type->data.structure.fields[slice_ptr_index].gen_index; + ZigType *slice_type = g->stack_trace_type->data.structure.fields[1]->type_entry; + size_t ptr_field_index = slice_type->data.structure.fields[slice_ptr_index]->gen_index; LLVMValueRef src_ptr_field_ptr = LLVMBuildStructGEP(g->builder, src_addresses_field_ptr, (unsigned)ptr_field_index, ""); - size_t len_field_index = slice_type->data.structure.fields[slice_len_index].gen_index; + size_t len_field_index = slice_type->data.structure.fields[slice_len_index]->gen_index; LLVMValueRef src_len_field_ptr = LLVMBuildStructGEP(g->builder, src_addresses_field_ptr, (unsigned)len_field_index, ""); LLVMValueRef src_index_val = LLVMBuildLoad(g->builder, src_index_field_ptr, ""); LLVMValueRef src_ptr_val = LLVMBuildLoad(g->builder, src_ptr_field_ptr, ""); @@ -3006,21 +3010,21 @@ static LLVMValueRef ir_render_resize_slice(CodeGen *g, IrExecutable *executable, assert(actual_type->id == ZigTypeIdStruct); assert(actual_type->data.structure.is_slice); - ZigType *actual_pointer_type = actual_type->data.structure.fields[0].type_entry; + ZigType *actual_pointer_type = actual_type->data.structure.fields[0]->type_entry; ZigType *actual_child_type = actual_pointer_type->data.pointer.child_type; - ZigType *wanted_pointer_type = wanted_type->data.structure.fields[0].type_entry; + ZigType *wanted_pointer_type = wanted_type->data.structure.fields[0]->type_entry; ZigType *wanted_child_type = wanted_pointer_type->data.pointer.child_type; - size_t actual_ptr_index = actual_type->data.structure.fields[slice_ptr_index].gen_index; - size_t actual_len_index = actual_type->data.structure.fields[slice_len_index].gen_index; - size_t wanted_ptr_index = wanted_type->data.structure.fields[slice_ptr_index].gen_index; - size_t wanted_len_index = wanted_type->data.structure.fields[slice_len_index].gen_index; + size_t actual_ptr_index = actual_type->data.structure.fields[slice_ptr_index]->gen_index; + size_t actual_len_index = actual_type->data.structure.fields[slice_len_index]->gen_index; + size_t wanted_ptr_index = wanted_type->data.structure.fields[slice_ptr_index]->gen_index; + size_t wanted_len_index = wanted_type->data.structure.fields[slice_len_index]->gen_index; LLVMValueRef src_ptr_ptr = LLVMBuildStructGEP(g->builder, expr_val, (unsigned)actual_ptr_index, ""); LLVMValueRef src_ptr = gen_load_untyped(g, src_ptr_ptr, 0, false, ""); LLVMValueRef src_ptr_casted = LLVMBuildBitCast(g->builder, src_ptr, - get_llvm_type(g, wanted_type->data.structure.fields[0].type_entry), ""); + get_llvm_type(g, wanted_type->data.structure.fields[0]->type_entry), ""); LLVMValueRef dest_ptr_ptr = LLVMBuildStructGEP(g->builder, result_loc, (unsigned)wanted_ptr_index, ""); gen_store_untyped(g, src_ptr_casted, dest_ptr_ptr, 0, false); @@ -3136,9 +3140,9 @@ static LLVMValueRef ir_render_ptr_of_array_to_slice(CodeGen *g, IrExecutable *ex { ZigType *actual_type = instruction->operand->value.type; ZigType *slice_type = instruction->base.value.type; - ZigType *slice_ptr_type = slice_type->data.structure.fields[slice_ptr_index].type_entry; - size_t ptr_index = slice_type->data.structure.fields[slice_ptr_index].gen_index; - size_t len_index = slice_type->data.structure.fields[slice_len_index].gen_index; + ZigType *slice_ptr_type = slice_type->data.structure.fields[slice_ptr_index]->type_entry; + size_t ptr_index = slice_type->data.structure.fields[slice_ptr_index]->gen_index; + size_t len_index = slice_type->data.structure.fields[slice_len_index]->gen_index; LLVMValueRef result_loc = ir_llvm_value(g, instruction->result_loc); @@ -3504,7 +3508,7 @@ static bool value_is_all_undef(CodeGen *g, ConstExprValue *const_val) { case ConstValSpecialStatic: if (const_val->type->id == ZigTypeIdStruct) { for (size_t i = 0; i < const_val->type->data.structure.src_field_count; i += 1) { - if (!value_is_all_undef(g, &const_val->data.x_struct.fields[i])) + if (!value_is_all_undef(g, const_val->data.x_struct.fields[i])) return false; } return true; @@ -3618,9 +3622,14 @@ static void gen_undef_init(CodeGen *g, uint32_t ptr_align_bytes, ZigType *value_ } static LLVMValueRef ir_render_store_ptr(CodeGen *g, IrExecutable *executable, IrInstructionStorePtr *instruction) { + Error err; + ZigType *ptr_type = instruction->ptr->value.type; assert(ptr_type->id == ZigTypeIdPointer); - if (!type_has_bits(ptr_type)) + bool ptr_type_has_bits; + if ((err = type_has_bits2(g, ptr_type, &ptr_type_has_bits))) + codegen_report_errors_and_exit(g); + if (!ptr_type_has_bits) return nullptr; if (instruction->ptr->ref_count == 0) { // In this case, this StorePtr instruction should be elided. Something happened like this: @@ -3757,14 +3766,14 @@ static LLVMValueRef ir_render_elem_ptr(CodeGen *g, IrExecutable *executable, IrI assert(LLVMGetTypeKind(LLVMGetElementType(LLVMTypeOf(array_ptr))) == LLVMStructTypeKind); if (safety_check_on) { - size_t len_index = array_type->data.structure.fields[slice_len_index].gen_index; + size_t len_index = array_type->data.structure.fields[slice_len_index]->gen_index; assert(len_index != SIZE_MAX); LLVMValueRef len_ptr = LLVMBuildStructGEP(g->builder, array_ptr, (unsigned)len_index, ""); LLVMValueRef len = gen_load_untyped(g, len_ptr, 0, false, ""); add_bounds_check(g, subscript_value, LLVMIntEQ, nullptr, LLVMIntULT, len); } - size_t ptr_index = array_type->data.structure.fields[slice_ptr_index].gen_index; + size_t ptr_index = array_type->data.structure.fields[slice_ptr_index]->gen_index; assert(ptr_index != SIZE_MAX); LLVMValueRef ptr_ptr = LLVMBuildStructGEP(g->builder, array_ptr, (unsigned)ptr_index, ""); LLVMValueRef ptr = gen_load_untyped(g, ptr_ptr, 0, false, ""); @@ -3856,7 +3865,7 @@ static void render_async_spills(CodeGen *g) { if (instruction->field_index == SIZE_MAX) continue; - size_t gen_index = frame_type->data.structure.fields[instruction->field_index].gen_index; + size_t gen_index = frame_type->data.structure.fields[instruction->field_index]->gen_index; instruction->base.llvm_value = LLVMBuildStructGEP(g->builder, g->cur_frame_ptr, gen_index, instruction->name_hint); } @@ -4342,17 +4351,32 @@ static LLVMValueRef ir_render_union_field_ptr(CodeGen *g, IrExecutable *executab TypeUnionField *field = instruction->field; if (!type_has_bits(field->type_entry)) { - if (union_type->data.unionation.gen_tag_index == SIZE_MAX) { + ZigType *tag_type = union_type->data.unionation.tag_type; + if (!instruction->initializing || !type_has_bits(tag_type)) return nullptr; + + // The field has no bits but we still have to change the discriminant + // value here + LLVMValueRef union_ptr = ir_llvm_value(g, instruction->union_ptr); + + LLVMTypeRef tag_type_ref = get_llvm_type(g, tag_type); + LLVMValueRef tag_field_ptr = nullptr; + if (union_type->data.unionation.gen_field_count == 0) { + assert(union_type->data.unionation.gen_tag_index == SIZE_MAX); + // The whole union is collapsed into the discriminant + tag_field_ptr = LLVMBuildBitCast(g->builder, union_ptr, + LLVMPointerType(tag_type_ref, 0), ""); + } else { + assert(union_type->data.unionation.gen_tag_index != SIZE_MAX); + tag_field_ptr = LLVMBuildStructGEP(g->builder, union_ptr, + union_type->data.unionation.gen_tag_index, ""); } - if (instruction->initializing) { - LLVMValueRef union_ptr = ir_llvm_value(g, instruction->union_ptr); - LLVMValueRef tag_field_ptr = LLVMBuildStructGEP(g->builder, union_ptr, - union_type->data.unionation.gen_tag_index, ""); - LLVMValueRef tag_value = bigint_to_llvm_const(get_llvm_type(g, union_type->data.unionation.tag_type), - &field->enum_field->value); - gen_store_untyped(g, tag_value, tag_field_ptr, 0, false); - } + + LLVMValueRef tag_value = bigint_to_llvm_const(tag_type_ref, + &field->enum_field->value); + assert(tag_field_ptr != nullptr); + gen_store_untyped(g, tag_value, tag_field_ptr, 0, false); + return nullptr; } @@ -4983,10 +5007,10 @@ static LLVMValueRef ir_render_align_cast(CodeGen *g, IrExecutable *executable, I align_bytes = target_type->data.maybe.child_type->data.fn.fn_type_id.alignment; ptr_val = target_val; } else if (target_type->id == ZigTypeIdStruct && target_type->data.structure.is_slice) { - ZigType *slice_ptr_type = target_type->data.structure.fields[slice_ptr_index].type_entry; + ZigType *slice_ptr_type = target_type->data.structure.fields[slice_ptr_index]->type_entry; align_bytes = get_ptr_align(g, slice_ptr_type); - size_t ptr_index = target_type->data.structure.fields[slice_ptr_index].gen_index; + size_t ptr_index = target_type->data.structure.fields[slice_ptr_index]->gen_index; LLVMValueRef ptr_val_ptr = LLVMBuildStructGEP(g->builder, target_val, (unsigned)ptr_index, ""); ptr_val = gen_load_untyped(g, ptr_val_ptr, 0, false, ""); } else { @@ -5128,7 +5152,7 @@ static LLVMValueRef ir_render_memset(CodeGen *g, IrExecutable *executable, IrIns bool val_is_undef = value_is_all_undef(g, &instruction->byte->value); LLVMValueRef fill_char; - if (val_is_undef) { + if (val_is_undef && ir_want_runtime_safety_scope(g, instruction->base.scope)) { fill_char = LLVMConstInt(LLVMInt8Type(), 0xaa, false); } else { fill_char = ir_llvm_value(g, instruction->byte); @@ -5231,13 +5255,13 @@ static LLVMValueRef ir_render_slice(CodeGen *g, IrExecutable *executable, IrInst } if (type_has_bits(array_type)) { - size_t gen_ptr_index = instruction->base.value.type->data.structure.fields[slice_ptr_index].gen_index; + size_t gen_ptr_index = instruction->base.value.type->data.structure.fields[slice_ptr_index]->gen_index; LLVMValueRef ptr_field_ptr = LLVMBuildStructGEP(g->builder, tmp_struct_ptr, gen_ptr_index, ""); LLVMValueRef slice_start_ptr = LLVMBuildInBoundsGEP(g->builder, array_ptr, &start_val, 1, ""); gen_store_untyped(g, slice_start_ptr, ptr_field_ptr, 0, false); } - size_t gen_len_index = instruction->base.value.type->data.structure.fields[slice_len_index].gen_index; + size_t gen_len_index = instruction->base.value.type->data.structure.fields[slice_len_index]->gen_index; LLVMValueRef len_field_ptr = LLVMBuildStructGEP(g->builder, tmp_struct_ptr, gen_len_index, ""); LLVMValueRef len_value = LLVMBuildNSWSub(g->builder, end_val, start_val, ""); gen_store_untyped(g, len_value, len_field_ptr, 0, false); @@ -5249,9 +5273,9 @@ static LLVMValueRef ir_render_slice(CodeGen *g, IrExecutable *executable, IrInst assert(LLVMGetTypeKind(LLVMGetElementType(LLVMTypeOf(array_ptr))) == LLVMStructTypeKind); assert(LLVMGetTypeKind(LLVMGetElementType(LLVMTypeOf(tmp_struct_ptr))) == LLVMStructTypeKind); - size_t ptr_index = array_type->data.structure.fields[slice_ptr_index].gen_index; + size_t ptr_index = array_type->data.structure.fields[slice_ptr_index]->gen_index; assert(ptr_index != SIZE_MAX); - size_t len_index = array_type->data.structure.fields[slice_len_index].gen_index; + size_t len_index = array_type->data.structure.fields[slice_len_index]->gen_index; assert(len_index != SIZE_MAX); LLVMValueRef prev_end = nullptr; @@ -5646,6 +5670,17 @@ static LLVMValueRef ir_render_atomic_load(CodeGen *g, IrExecutable *executable, return load_inst; } +static LLVMValueRef ir_render_atomic_store(CodeGen *g, IrExecutable *executable, + IrInstructionAtomicStore *instruction) +{ + LLVMAtomicOrdering ordering = to_LLVMAtomicOrdering(instruction->resolved_ordering); + LLVMValueRef ptr = ir_llvm_value(g, instruction->ptr); + LLVMValueRef value = ir_llvm_value(g, instruction->value); + LLVMValueRef store_inst = gen_store(g, value, ptr, instruction->ptr->value.type); + LLVMSetOrdering(store_inst, ordering); + return nullptr; +} + static LLVMValueRef ir_render_float_op(CodeGen *g, IrExecutable *executable, IrInstructionFloatOp *instruction) { LLVMValueRef op = ir_llvm_value(g, instruction->op1); assert(instruction->base.value.type->id == ZigTypeIdFloat); @@ -6249,6 +6284,8 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable, return ir_render_atomic_rmw(g, executable, (IrInstructionAtomicRmw *)instruction); case IrInstructionIdAtomicLoad: return ir_render_atomic_load(g, executable, (IrInstructionAtomicLoad *)instruction); + case IrInstructionIdAtomicStore: + return ir_render_atomic_store(g, executable, (IrInstructionAtomicStore *)instruction); case IrInstructionIdSaveErrRetAddr: return ir_render_save_err_ret_addr(g, executable, (IrInstructionSaveErrRetAddr *)instruction); case IrInstructionIdFloatOp: @@ -6546,11 +6583,11 @@ static LLVMValueRef pack_const_int(CodeGen *g, LLVMTypeRef big_int_type_ref, Con LLVMValueRef val = LLVMConstInt(big_int_type_ref, 0, false); size_t used_bits = 0; for (size_t i = 0; i < type_entry->data.structure.src_field_count; i += 1) { - TypeStructField *field = &type_entry->data.structure.fields[i]; + TypeStructField *field = type_entry->data.structure.fields[i]; if (field->gen_index == SIZE_MAX) { continue; } - LLVMValueRef child_val = pack_const_int(g, big_int_type_ref, &const_val->data.x_struct.fields[i]); + LLVMValueRef child_val = pack_const_int(g, big_int_type_ref, const_val->data.x_struct.fields[i]); uint32_t packed_bits_size = type_size_bits(g, field->type_entry); if (is_big_endian) { LLVMValueRef shift_amt = LLVMConstInt(big_int_type_ref, packed_bits_size, false); @@ -6625,7 +6662,7 @@ static LLVMValueRef gen_const_val_ptr(CodeGen *g, ConstExprValue *const_val, con return const_val->global_refs->llvm_value; } size_t src_field_index = const_val->data.x_ptr.data.base_struct.field_index; - size_t gen_field_index = struct_const_val->type->data.structure.fields[src_field_index].gen_index; + size_t gen_field_index = struct_const_val->type->data.structure.fields[src_field_index]->gen_index; LLVMValueRef uncasted_ptr_val = gen_const_ptr_struct_recursive(g, struct_const_val, gen_field_index); LLVMValueRef ptr_val = LLVMConstBitCast(uncasted_ptr_val, get_llvm_type(g, const_val->type)); @@ -6804,7 +6841,7 @@ check: switch (const_val->special) { if (type_entry->data.structure.layout == ContainerLayoutPacked) { size_t src_field_index = 0; while (src_field_index < src_field_count) { - TypeStructField *type_struct_field = &type_entry->data.structure.fields[src_field_index]; + TypeStructField *type_struct_field = type_entry->data.structure.fields[src_field_index]; if (type_struct_field->gen_index == SIZE_MAX) { src_field_index += 1; continue; @@ -6812,13 +6849,13 @@ check: switch (const_val->special) { size_t src_field_index_end = src_field_index + 1; for (; src_field_index_end < src_field_count; src_field_index_end += 1) { - TypeStructField *it_field = &type_entry->data.structure.fields[src_field_index_end]; + TypeStructField *it_field = type_entry->data.structure.fields[src_field_index_end]; if (it_field->gen_index != type_struct_field->gen_index) break; } if (src_field_index + 1 == src_field_index_end) { - ConstExprValue *field_val = &const_val->data.x_struct.fields[src_field_index]; + ConstExprValue *field_val = const_val->data.x_struct.fields[src_field_index]; LLVMValueRef val = gen_const_val(g, field_val, ""); fields[type_struct_field->gen_index] = val; make_unnamed_struct = make_unnamed_struct || is_llvm_value_unnamed_type(g, field_val->type, val); @@ -6831,12 +6868,12 @@ check: switch (const_val->special) { LLVMValueRef val = LLVMConstInt(big_int_type_ref, 0, false); size_t used_bits = 0; for (size_t i = src_field_index; i < src_field_index_end; i += 1) { - TypeStructField *it_field = &type_entry->data.structure.fields[i]; + TypeStructField *it_field = type_entry->data.structure.fields[i]; if (it_field->gen_index == SIZE_MAX) { continue; } LLVMValueRef child_val = pack_const_int(g, big_int_type_ref, - &const_val->data.x_struct.fields[i]); + const_val->data.x_struct.fields[i]); uint32_t packed_bits_size = type_size_bits(g, it_field->type_entry); if (is_big_endian) { LLVMValueRef shift_amt = LLVMConstInt(big_int_type_ref, @@ -6871,11 +6908,11 @@ check: switch (const_val->special) { } } else { for (uint32_t i = 0; i < src_field_count; i += 1) { - TypeStructField *type_struct_field = &type_entry->data.structure.fields[i]; + TypeStructField *type_struct_field = type_entry->data.structure.fields[i]; if (type_struct_field->gen_index == SIZE_MAX) { continue; } - ConstExprValue *field_val = &const_val->data.x_struct.fields[i]; + ConstExprValue *field_val = const_val->data.x_struct.fields[i]; assert(field_val->type != nullptr); if ((err = ensure_const_val_repr(nullptr, g, nullptr, field_val, type_struct_field->type_entry))) @@ -6888,10 +6925,10 @@ check: switch (const_val->special) { make_unnamed_struct = make_unnamed_struct || is_llvm_value_unnamed_type(g, field_val->type, val); size_t end_pad_gen_index = (i + 1 < src_field_count) ? - type_entry->data.structure.fields[i + 1].gen_index : + type_entry->data.structure.fields[i + 1]->gen_index : type_entry->data.structure.gen_field_count; size_t next_offset = (i + 1 < src_field_count) ? - type_entry->data.structure.fields[i + 1].offset : type_entry->abi_size; + type_entry->data.structure.fields[i + 1]->offset : type_entry->abi_size; if (end_pad_gen_index != SIZE_MAX) { for (size_t gen_i = type_struct_field->gen_index + 1; gen_i < end_pad_gen_index; gen_i += 1) @@ -7050,16 +7087,12 @@ check: switch (const_val->special) { case ZigTypeIdEnum: return bigint_to_llvm_const(get_llvm_type(g, type_entry), &const_val->data.x_enum_tag); case ZigTypeIdFn: - if (const_val->data.x_ptr.special == ConstPtrSpecialFunction) { - assert(const_val->data.x_ptr.mut == ConstPtrMutComptimeConst); - return fn_llvm_value(g, const_val->data.x_ptr.data.fn.fn_entry); - } else if (const_val->data.x_ptr.special == ConstPtrSpecialHardCodedAddr) { - LLVMTypeRef usize_type_ref = g->builtin_types.entry_usize->llvm_type; - uint64_t addr = const_val->data.x_ptr.data.hard_coded_addr.addr; - return LLVMConstIntToPtr(LLVMConstInt(usize_type_ref, addr, false), get_llvm_type(g, type_entry)); - } else { + if (const_val->data.x_ptr.special == ConstPtrSpecialFunction && + const_val->data.x_ptr.mut != ConstPtrMutComptimeConst) { zig_unreachable(); } + // Treat it the same as we do for pointers + return gen_const_val_ptr(g, const_val, name); case ZigTypeIdPointer: return gen_const_val_ptr(g, const_val, name); case ZigTypeIdErrorUnion: @@ -7558,15 +7591,15 @@ static void do_code_gen(CodeGen *g) { // finishing error return trace setup. we have to do this after all the allocas. if (have_err_ret_trace_stack) { ZigType *usize = g->builtin_types.entry_usize; - size_t index_field_index = g->stack_trace_type->data.structure.fields[0].gen_index; + size_t index_field_index = g->stack_trace_type->data.structure.fields[0]->gen_index; LLVMValueRef index_field_ptr = LLVMBuildStructGEP(g->builder, g->cur_err_ret_trace_val_stack, (unsigned)index_field_index, ""); gen_store_untyped(g, LLVMConstNull(usize->llvm_type), index_field_ptr, 0, false); - size_t addresses_field_index = g->stack_trace_type->data.structure.fields[1].gen_index; + size_t addresses_field_index = g->stack_trace_type->data.structure.fields[1]->gen_index; LLVMValueRef addresses_field_ptr = LLVMBuildStructGEP(g->builder, g->cur_err_ret_trace_val_stack, (unsigned)addresses_field_index, ""); - ZigType *slice_type = g->stack_trace_type->data.structure.fields[1].type_entry; - size_t ptr_field_index = slice_type->data.structure.fields[slice_ptr_index].gen_index; + ZigType *slice_type = g->stack_trace_type->data.structure.fields[1]->type_entry; + size_t ptr_field_index = slice_type->data.structure.fields[slice_ptr_index]->gen_index; LLVMValueRef ptr_field_ptr = LLVMBuildStructGEP(g->builder, addresses_field_ptr, (unsigned)ptr_field_index, ""); LLVMValueRef zero = LLVMConstNull(usize->llvm_type); LLVMValueRef indices[] = {zero, zero}; @@ -7575,7 +7608,7 @@ static void do_code_gen(CodeGen *g) { ZigType *ptr_ptr_usize_type = get_pointer_to_type(g, get_pointer_to_type(g, usize, false), false); gen_store(g, err_ret_array_val_elem0_ptr, ptr_field_ptr, ptr_ptr_usize_type); - size_t len_field_index = slice_type->data.structure.fields[slice_len_index].gen_index; + size_t len_field_index = slice_type->data.structure.fields[slice_len_index]->gen_index; LLVMValueRef len_field_ptr = LLVMBuildStructGEP(g->builder, addresses_field_ptr, (unsigned)len_field_index, ""); gen_store(g, LLVMConstInt(usize->llvm_type, stack_trace_ptr_count, false), len_field_ptr, get_pointer_to_type(g, usize, false)); } @@ -7692,7 +7725,7 @@ static void do_code_gen(CodeGen *g) { char *error = nullptr; if (LLVMVerifyModule(g->module, LLVMReturnStatusAction, &error)) { - zig_panic("broken LLVM module found: %s", error); + zig_panic("broken LLVM module found: %s\nThis is a bug in the Zig compiler.", error); } } @@ -7821,6 +7854,11 @@ static void define_builtin_types(CodeGen *g) { g->builtin_types.entry_null = entry; } { + ZigType *entry = new_type_table_entry(ZigTypeIdOpaque); + buf_init_from_str(&entry->name, "(var)"); + g->builtin_types.entry_var = entry; + } + { ZigType *entry = new_type_table_entry(ZigTypeIdArgTuple); buf_init_from_str(&entry->name, "(args)"); g->builtin_types.entry_arg_tuple = entry; @@ -8064,6 +8102,7 @@ static void define_builtin_fns(CodeGen *g) { create_builtin_fn(g, BuiltinFnIdErrorReturnTrace, "errorReturnTrace", 0); create_builtin_fn(g, BuiltinFnIdAtomicRmw, "atomicRmw", 5); create_builtin_fn(g, BuiltinFnIdAtomicLoad, "atomicLoad", 3); + create_builtin_fn(g, BuiltinFnIdAtomicStore, "atomicStore", 4); create_builtin_fn(g, BuiltinFnIdErrSetCast, "errSetCast", 2); create_builtin_fn(g, BuiltinFnIdToBytes, "sliceToBytes", 1); create_builtin_fn(g, BuiltinFnIdFromBytes, "bytesToSlice", 2); @@ -8074,6 +8113,7 @@ static void define_builtin_fns(CodeGen *g) { create_builtin_fn(g, BuiltinFnIdFrameType, "Frame", 1); create_builtin_fn(g, BuiltinFnIdFrameAddress, "frameAddress", 0); create_builtin_fn(g, BuiltinFnIdFrameSize, "frameSize", 1); + create_builtin_fn(g, BuiltinFnIdAs, "as", 2); } static const char *bool_to_str(bool b) { @@ -9049,13 +9089,13 @@ static void create_test_compile_var_and_add_test_runner(CodeGen *g) { this_val->parent.id = ConstParentIdArray; this_val->parent.data.p_array.array_val = test_fn_array; this_val->parent.data.p_array.elem_index = i; - this_val->data.x_struct.fields = create_const_vals(2); + this_val->data.x_struct.fields = alloc_const_vals_ptrs(2); - ConstExprValue *name_field = &this_val->data.x_struct.fields[0]; + ConstExprValue *name_field = this_val->data.x_struct.fields[0]; ConstExprValue *name_array_val = create_const_str_lit(g, &test_fn_entry->symbol_name); init_const_slice(g, name_field, name_array_val, 0, buf_len(&test_fn_entry->symbol_name), true); - ConstExprValue *fn_field = &this_val->data.x_struct.fields[1]; + ConstExprValue *fn_field = this_val->data.x_struct.fields[1]; fn_field->type = fn_type; fn_field->special = ConstValSpecialStatic; fn_field->data.x_ptr.special = ConstPtrSpecialFunction; @@ -9483,7 +9523,7 @@ static void prepend_c_type_to_decl_list(CodeGen *g, GenH *gen_h, ZigType *type_e return; case ZigTypeIdStruct: for (uint32_t i = 0; i < type_entry->data.structure.src_field_count; i += 1) { - TypeStructField *field = &type_entry->data.structure.fields[i]; + TypeStructField *field = type_entry->data.structure.fields[i]; prepend_c_type_to_decl_list(g, gen_h, field->type_entry); } gen_h->types_to_declare.append(type_entry); @@ -9849,7 +9889,7 @@ static void gen_h_file(CodeGen *g) { if (type_entry->data.structure.layout == ContainerLayoutExtern) { fprintf(out_h, "struct %s {\n", buf_ptr(type_h_name(type_entry))); for (uint32_t field_i = 0; field_i < type_entry->data.structure.src_field_count; field_i += 1) { - TypeStructField *struct_field = &type_entry->data.structure.fields[field_i]; + TypeStructField *struct_field = type_entry->data.structure.fields[field_i]; Buf *type_name_buf = buf_alloc(); get_c_type(g, gen_h, struct_field->type_entry, type_name_buf); diff --git a/src/dump_analysis.cpp b/src/dump_analysis.cpp index 9703d3e57d..98bbcc6a42 100644 --- a/src/dump_analysis.cpp +++ b/src/dump_analysis.cpp @@ -268,7 +268,7 @@ static void tree_print_struct(FILE *f, ZigType *struct_type, size_t indent) { ZigList<ZigType *> children = {}; uint64_t sum_from_fields = 0; for (size_t i = 0; i < struct_type->data.structure.src_field_count; i += 1) { - TypeStructField *field = &struct_type->data.structure.fields[i]; + TypeStructField *field = struct_type->data.structure.fields[i]; children.append(field->type_entry); sum_from_fields += field->type_entry->abi_size; } @@ -747,7 +747,7 @@ static void anal_dump_type(AnalDumpCtx *ctx, ZigType *ty) { if (ty->data.structure.is_slice) { jw_object_field(jw, "len"); jw_int(jw, 2); - anal_dump_pointer_attrs(ctx, ty->data.structure.fields[slice_ptr_index].type_entry); + anal_dump_pointer_attrs(ctx, ty->data.structure.fields[slice_ptr_index]->type_entry); break; } @@ -803,7 +803,7 @@ static void anal_dump_type(AnalDumpCtx *ctx, ZigType *ty) { for(size_t i = 0; i < ty->data.structure.src_field_count; i += 1) { jw_array_elem(jw); - anal_dump_type_ref(ctx, ty->data.structure.fields[i].type_entry); + anal_dump_type_ref(ctx, ty->data.structure.fields[i]->type_entry); } jw_end_array(jw); } @@ -1088,6 +1088,7 @@ static void anal_dump_node(AnalDumpCtx *ctx, const AstNode *node) { break; case NodeTypeContainerDecl: field_nodes = &node->data.container_decl.fields; + doc_comments_buf = &node->data.container_decl.doc_comments; break; default: break; diff --git a/src/ir.cpp b/src/ir.cpp index d4687e5adb..9f0fc40ded 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -200,6 +200,13 @@ static IrInstruction *ir_gen_union_init_expr(IrBuilder *irb, Scope *scope, AstNo static void ir_reset_result(ResultLoc *result_loc); static Buf *get_anon_type_name(CodeGen *codegen, IrExecutable *exec, const char *kind_name, Scope *scope, AstNode *source_node, Buf *out_bare_name); +static ResultLocCast *ir_build_cast_result_loc(IrBuilder *irb, IrInstruction *dest_type, + ResultLoc *parent_result_loc); +static IrInstruction *ir_analyze_struct_field_ptr(IrAnalyze *ira, IrInstruction *source_instr, + TypeStructField *field, IrInstruction *struct_ptr, ZigType *struct_type, bool initializing); +static IrInstruction *ir_analyze_inferred_field_ptr(IrAnalyze *ira, Buf *field_name, + IrInstruction *source_instr, IrInstruction *container_ptr, ZigType *container_type); +static ResultLoc *no_result_loc(void); static ConstExprValue *const_ptr_pointee_unchecked(CodeGen *g, ConstExprValue *const_val) { assert(get_src_ptr_type(const_val->type) != nullptr); @@ -233,7 +240,7 @@ static ConstExprValue *const_ptr_pointee_unchecked(CodeGen *g, ConstExprValue *c case ConstPtrSpecialBaseStruct: { ConstExprValue *struct_val = const_val->data.x_ptr.data.base_struct.struct_val; expand_undef_struct(g, struct_val); - result = &struct_val->data.x_struct.fields[const_val->data.x_ptr.data.base_struct.field_index]; + result = struct_val->data.x_struct.fields[const_val->data.x_ptr.data.base_struct.field_index]; break; } case ConstPtrSpecialBaseErrorUnionCode: @@ -270,7 +277,7 @@ static bool is_slice(ZigType *type) { static bool slice_is_const(ZigType *type) { assert(is_slice(type)); - return type->data.structure.fields[slice_ptr_index].type_entry->data.pointer.is_const; + return type->data.structure.fields[slice_ptr_index]->type_entry->data.pointer.is_const; } // This function returns true when you can change the type of a ConstExprValue and the @@ -1003,6 +1010,10 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionAtomicLoad *) { return IrInstructionIdAtomicLoad; } +static constexpr IrInstructionId ir_instruction_id(IrInstructionAtomicStore *) { + return IrInstructionIdAtomicStore; +} + static constexpr IrInstructionId ir_instruction_id(IrInstructionSaveErrRetAddr *) { return IrInstructionIdSaveErrRetAddr; } @@ -1348,18 +1359,17 @@ static IrInstruction *ir_build_return_ptr(IrAnalyze *ira, IrInstruction *source_ static IrInstruction *ir_build_elem_ptr(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *array_ptr, IrInstruction *elem_index, bool safety_check_on, PtrLen ptr_len, - IrInstruction *init_array_type) + AstNode *init_array_type_source_node) { IrInstructionElemPtr *instruction = ir_build_instruction<IrInstructionElemPtr>(irb, scope, source_node); instruction->array_ptr = array_ptr; instruction->elem_index = elem_index; instruction->safety_check_on = safety_check_on; instruction->ptr_len = ptr_len; - instruction->init_array_type = init_array_type; + instruction->init_array_type_source_node = init_array_type_source_node; ir_ref_instruction(array_ptr, irb->current_basic_block); ir_ref_instruction(elem_index, irb->current_basic_block); - if (init_array_type != nullptr) ir_ref_instruction(init_array_type, irb->current_basic_block); return &instruction->base; } @@ -1573,17 +1583,16 @@ static IrInstruction *ir_build_un_op(IrBuilder *irb, Scope *scope, AstNode *sour } static IrInstruction *ir_build_container_init_list(IrBuilder *irb, Scope *scope, AstNode *source_node, - IrInstruction *container_type, size_t item_count, IrInstruction **elem_result_loc_list, - IrInstruction *result_loc) + size_t item_count, IrInstruction **elem_result_loc_list, IrInstruction *result_loc, + AstNode *init_array_type_source_node) { IrInstructionContainerInitList *container_init_list_instruction = ir_build_instruction<IrInstructionContainerInitList>(irb, scope, source_node); - container_init_list_instruction->container_type = container_type; container_init_list_instruction->item_count = item_count; container_init_list_instruction->elem_result_loc_list = elem_result_loc_list; container_init_list_instruction->result_loc = result_loc; + container_init_list_instruction->init_array_type_source_node = init_array_type_source_node; - ir_ref_instruction(container_type, irb->current_basic_block); for (size_t i = 0; i < item_count; i += 1) { ir_ref_instruction(elem_result_loc_list[i], irb->current_basic_block); } @@ -1593,17 +1602,14 @@ static IrInstruction *ir_build_container_init_list(IrBuilder *irb, Scope *scope, } static IrInstruction *ir_build_container_init_fields(IrBuilder *irb, Scope *scope, AstNode *source_node, - IrInstruction *container_type, size_t field_count, IrInstructionContainerInitFieldsField *fields, - IrInstruction *result_loc) + size_t field_count, IrInstructionContainerInitFieldsField *fields, IrInstruction *result_loc) { IrInstructionContainerInitFields *container_init_fields_instruction = ir_build_instruction<IrInstructionContainerInitFields>(irb, scope, source_node); - container_init_fields_instruction->container_type = container_type; container_init_fields_instruction->field_count = field_count; container_init_fields_instruction->fields = fields; container_init_fields_instruction->result_loc = result_loc; - ir_ref_instruction(container_type, irb->current_basic_block); for (size_t i = 0; i < field_count; i += 1) { ir_ref_instruction(fields[i].result_loc, irb->current_basic_block); } @@ -2766,6 +2772,18 @@ static IrInstruction *ir_build_load_ptr_gen(IrAnalyze *ira, IrInstruction *sourc return &instruction->base; } +static IrInstruction *ir_build_implicit_cast(IrBuilder *irb, Scope *scope, AstNode *source_node, + IrInstruction *operand, ResultLocCast *result_loc_cast) +{ + IrInstructionImplicitCast *instruction = ir_build_instruction<IrInstructionImplicitCast>(irb, scope, source_node); + instruction->operand = operand; + instruction->result_loc_cast = result_loc_cast; + + ir_ref_instruction(operand, irb->current_basic_block); + + return &instruction->base; +} + static IrInstruction *ir_build_bit_cast_src(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *operand, ResultLocBitCast *result_loc_bit_cast) { @@ -3063,20 +3081,6 @@ static IrInstruction *ir_build_align_cast(IrBuilder *irb, Scope *scope, AstNode return &instruction->base; } -static IrInstruction *ir_build_implicit_cast(IrBuilder *irb, Scope *scope, AstNode *source_node, - IrInstruction *dest_type, IrInstruction *target, ResultLoc *result_loc) -{ - IrInstructionImplicitCast *instruction = ir_build_instruction<IrInstructionImplicitCast>(irb, scope, source_node); - instruction->dest_type = dest_type; - instruction->target = target; - instruction->result_loc = result_loc; - - ir_ref_instruction(dest_type, irb->current_basic_block); - ir_ref_instruction(target, irb->current_basic_block); - - return &instruction->base; -} - static IrInstruction *ir_build_resolve_result(IrBuilder *irb, Scope *scope, AstNode *source_node, ResultLoc *result_loc, IrInstruction *ty) { @@ -3084,7 +3088,7 @@ static IrInstruction *ir_build_resolve_result(IrBuilder *irb, Scope *scope, AstN instruction->result_loc = result_loc; instruction->ty = ty; - ir_ref_instruction(ty, irb->current_basic_block); + if (ty != nullptr) ir_ref_instruction(ty, irb->current_basic_block); return &instruction->base; } @@ -3116,11 +3120,12 @@ static IrInstruction *ir_build_set_align_stack(IrBuilder *irb, Scope *scope, Ast } static IrInstruction *ir_build_arg_type(IrBuilder *irb, Scope *scope, AstNode *source_node, - IrInstruction *fn_type, IrInstruction *arg_index) + IrInstruction *fn_type, IrInstruction *arg_index, bool allow_var) { IrInstructionArgType *instruction = ir_build_instruction<IrInstructionArgType>(irb, scope, source_node); instruction->fn_type = fn_type; instruction->arg_index = arg_index; + instruction->allow_var = allow_var; ir_ref_instruction(fn_type, irb->current_basic_block); ir_ref_instruction(arg_index, irb->current_basic_block); @@ -3187,6 +3192,25 @@ static IrInstruction *ir_build_atomic_load(IrBuilder *irb, Scope *scope, AstNode return &instruction->base; } +static IrInstruction *ir_build_atomic_store(IrBuilder *irb, Scope *scope, AstNode *source_node, + IrInstruction *operand_type, IrInstruction *ptr, IrInstruction *value, + IrInstruction *ordering, AtomicOrder resolved_ordering) +{ + IrInstructionAtomicStore *instruction = ir_build_instruction<IrInstructionAtomicStore>(irb, scope, source_node); + instruction->operand_type = operand_type; + instruction->ptr = ptr; + instruction->value = value; + instruction->ordering = ordering; + instruction->resolved_ordering = resolved_ordering; + + if (operand_type != nullptr) ir_ref_instruction(operand_type, irb->current_basic_block); + ir_ref_instruction(ptr, irb->current_basic_block); + ir_ref_instruction(value, irb->current_basic_block); + if (ordering != nullptr) ir_ref_instruction(ordering, irb->current_basic_block); + + return &instruction->base; +} + static IrInstruction *ir_build_save_err_ret_addr(IrBuilder *irb, Scope *scope, AstNode *source_node) { IrInstructionSaveErrRetAddr *instruction = ir_build_instruction<IrInstructionSaveErrRetAddr>(irb, scope, source_node); return &instruction->base; @@ -5374,6 +5398,24 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo IrInstruction *bitcast = ir_build_bit_cast_src(irb, scope, arg1_node, arg1_value, result_loc_bit_cast); return ir_lval_wrap(irb, scope, bitcast, lval, result_loc); } + case BuiltinFnIdAs: + { + AstNode *dest_type_node = node->data.fn_call_expr.params.at(0); + IrInstruction *dest_type = ir_gen_node(irb, dest_type_node, scope); + if (dest_type == irb->codegen->invalid_instruction) + return dest_type; + + ResultLocCast *result_loc_cast = ir_build_cast_result_loc(irb, dest_type, result_loc); + + AstNode *arg1_node = node->data.fn_call_expr.params.at(1); + IrInstruction *arg1_value = ir_gen_node_extra(irb, arg1_node, scope, LValNone, + &result_loc_cast->base); + if (arg1_value == irb->codegen->invalid_instruction) + return arg1_value; + + IrInstruction *result = ir_build_implicit_cast(irb, scope, node, arg1_value, result_loc_cast); + return ir_lval_wrap(irb, scope, result, lval, result_loc); + } case BuiltinFnIdIntToPtr: { AstNode *arg0_node = node->data.fn_call_expr.params.at(0); @@ -5630,7 +5672,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo if (arg1_value == irb->codegen->invalid_instruction) return arg1_value; - IrInstruction *arg_type = ir_build_arg_type(irb, scope, node, arg0_value, arg1_value); + IrInstruction *arg_type = ir_build_arg_type(irb, scope, node, arg0_value, arg1_value, false); return ir_lval_wrap(irb, scope, arg_type, lval, result_loc); } case BuiltinFnIdExport: @@ -5713,6 +5755,33 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo AtomicOrderMonotonic); return ir_lval_wrap(irb, scope, inst, lval, result_loc); } + case BuiltinFnIdAtomicStore: + { + AstNode *arg0_node = node->data.fn_call_expr.params.at(0); + IrInstruction *arg0_value = ir_gen_node(irb, arg0_node, scope); + if (arg0_value == irb->codegen->invalid_instruction) + return arg0_value; + + AstNode *arg1_node = node->data.fn_call_expr.params.at(1); + IrInstruction *arg1_value = ir_gen_node(irb, arg1_node, scope); + if (arg1_value == irb->codegen->invalid_instruction) + return arg1_value; + + AstNode *arg2_node = node->data.fn_call_expr.params.at(2); + IrInstruction *arg2_value = ir_gen_node(irb, arg2_node, scope); + if (arg2_value == irb->codegen->invalid_instruction) + return arg2_value; + + AstNode *arg3_node = node->data.fn_call_expr.params.at(3); + IrInstruction *arg3_value = ir_gen_node(irb, arg3_node, scope); + if (arg3_value == irb->codegen->invalid_instruction) + return arg3_value; + + IrInstruction *inst = ir_build_atomic_store(irb, scope, node, arg0_value, arg1_value, arg2_value, arg3_value, + // this value does not mean anything since we passed non-null values for other arg + AtomicOrderMonotonic); + return ir_lval_wrap(irb, scope, inst, lval, result_loc); + } case BuiltinFnIdIntToEnum: { AstNode *arg0_node = node->data.fn_call_expr.params.at(0); @@ -5825,13 +5894,22 @@ static IrInstruction *ir_gen_fn_call(IrBuilder *irb, Scope *scope, AstNode *node if (fn_ref == irb->codegen->invalid_instruction) return fn_ref; + IrInstruction *fn_type = ir_build_typeof(irb, scope, node, fn_ref); + size_t arg_count = node->data.fn_call_expr.params.length; IrInstruction **args = allocate<IrInstruction*>(arg_count); for (size_t i = 0; i < arg_count; i += 1) { AstNode *arg_node = node->data.fn_call_expr.params.at(i); - args[i] = ir_gen_node(irb, arg_node, scope); - if (args[i] == irb->codegen->invalid_instruction) - return args[i]; + + IrInstruction *arg_index = ir_build_const_usize(irb, scope, arg_node, i); + IrInstruction *arg_type = ir_build_arg_type(irb, scope, node, fn_type, arg_index, true); + ResultLocCast *result_loc_cast = ir_build_cast_result_loc(irb, arg_type, no_result_loc()); + + IrInstruction *arg = ir_gen_node_extra(irb, arg_node, scope, LValNone, &result_loc_cast->base); + if (arg == irb->codegen->invalid_instruction) + return arg; + + args[i] = ir_build_implicit_cast(irb, scope, arg_node, arg, result_loc_cast); } IrInstruction *fn_call = ir_build_call_src(irb, scope, node, nullptr, fn_ref, arg_count, args, false, @@ -6109,28 +6187,46 @@ static IrInstruction *ir_gen_container_init_expr(IrBuilder *irb, Scope *scope, A AstNodeContainerInitExpr *container_init_expr = &node->data.container_init_expr; ContainerInitKind kind = container_init_expr->kind; - IrInstruction *container_type = nullptr; - IrInstruction *elem_type = nullptr; - if (container_init_expr->type->type == NodeTypeInferredArrayType) { - elem_type = ir_gen_node(irb, container_init_expr->type->data.inferred_array_type.child_type, scope); - if (elem_type == irb->codegen->invalid_instruction) - return elem_type; - } else { - container_type = ir_gen_node(irb, container_init_expr->type, scope); - if (container_type == irb->codegen->invalid_instruction) - return container_type; - } - - switch (kind) { - case ContainerInitKindStruct: { - if (elem_type != nullptr) { + ResultLocCast *result_loc_cast = nullptr; + ResultLoc *child_result_loc; + AstNode *init_array_type_source_node; + if (container_init_expr->type != nullptr) { + IrInstruction *container_type; + if (container_init_expr->type->type == NodeTypeInferredArrayType) { + if (kind == ContainerInitKindStruct) { add_node_error(irb->codegen, container_init_expr->type, buf_sprintf("initializing array with struct syntax")); return irb->codegen->invalid_instruction; } + IrInstruction *elem_type = ir_gen_node(irb, + container_init_expr->type->data.inferred_array_type.child_type, scope); + if (elem_type == irb->codegen->invalid_instruction) + return elem_type; + size_t item_count = container_init_expr->entries.length; + IrInstruction *item_count_inst = ir_build_const_usize(irb, scope, node, item_count); + container_type = ir_build_array_type(irb, scope, node, item_count_inst, elem_type); + } else { + container_type = ir_gen_node(irb, container_init_expr->type, scope); + if (container_type == irb->codegen->invalid_instruction) + return container_type; + } - IrInstruction *container_ptr = ir_build_resolve_result(irb, scope, node, parent_result_loc, - container_type); + result_loc_cast = ir_build_cast_result_loc(irb, container_type, parent_result_loc); + child_result_loc = &result_loc_cast->base; + init_array_type_source_node = container_type->source_node; + } else { + child_result_loc = parent_result_loc; + if (parent_result_loc->source_instruction != nullptr) { + init_array_type_source_node = parent_result_loc->source_instruction->source_node; + } else { + init_array_type_source_node = node; + } + } + + switch (kind) { + case ContainerInitKindStruct: { + IrInstruction *container_ptr = ir_build_resolve_result(irb, scope, node, child_result_loc, + nullptr); size_t field_count = container_init_expr->entries.length; IrInstructionContainerInitFieldsField *fields = allocate<IrInstructionContainerInitFieldsField>(field_count); @@ -6158,29 +6254,27 @@ static IrInstruction *ir_gen_container_init_expr(IrBuilder *irb, Scope *scope, A fields[i].source_node = entry_node; fields[i].result_loc = field_ptr; } - IrInstruction *init_fields = ir_build_container_init_fields(irb, scope, node, container_type, - field_count, fields, container_ptr); + IrInstruction *result = ir_build_container_init_fields(irb, scope, node, field_count, + fields, container_ptr); - return ir_lval_wrap(irb, scope, init_fields, lval, parent_result_loc); + if (result_loc_cast != nullptr) { + result = ir_build_implicit_cast(irb, scope, node, result, result_loc_cast); + } + return ir_lval_wrap(irb, scope, result, lval, parent_result_loc); } case ContainerInitKindArray: { size_t item_count = container_init_expr->entries.length; - if (container_type == nullptr) { - IrInstruction *item_count_inst = ir_build_const_usize(irb, scope, node, item_count); - container_type = ir_build_array_type(irb, scope, node, item_count_inst, elem_type); - } - - IrInstruction *container_ptr = ir_build_resolve_result(irb, scope, node, parent_result_loc, - container_type); + IrInstruction *container_ptr = ir_build_resolve_result(irb, scope, node, child_result_loc, + nullptr); IrInstruction **result_locs = allocate<IrInstruction *>(item_count); for (size_t i = 0; i < item_count; i += 1) { AstNode *expr_node = container_init_expr->entries.at(i); IrInstruction *elem_index = ir_build_const_usize(irb, scope, expr_node, i); - IrInstruction *elem_ptr = ir_build_elem_ptr(irb, scope, expr_node, container_ptr, elem_index, - false, PtrLenSingle, container_type); + IrInstruction *elem_ptr = ir_build_elem_ptr(irb, scope, expr_node, container_ptr, + elem_index, false, PtrLenSingle, init_array_type_source_node); ResultLocInstruction *result_loc_inst = allocate<ResultLocInstruction>(1); result_loc_inst->base.id = ResultLocIdInstruction; result_loc_inst->base.source_instruction = elem_ptr; @@ -6195,9 +6289,12 @@ static IrInstruction *ir_gen_container_init_expr(IrBuilder *irb, Scope *scope, A result_locs[i] = elem_ptr; } - IrInstruction *init_list = ir_build_container_init_list(irb, scope, node, container_type, - item_count, result_locs, container_ptr); - return ir_lval_wrap(irb, scope, init_list, lval, parent_result_loc); + IrInstruction *result = ir_build_container_init_list(irb, scope, node, item_count, + result_locs, container_ptr, init_array_type_source_node); + if (result_loc_cast != nullptr) { + result = ir_build_implicit_cast(irb, scope, node, result, result_loc_cast); + } + return ir_lval_wrap(irb, scope, result, lval, parent_result_loc); } } zig_unreachable(); @@ -6214,6 +6311,20 @@ static ResultLocVar *ir_build_var_result_loc(IrBuilder *irb, IrInstruction *allo return result_loc_var; } +static ResultLocCast *ir_build_cast_result_loc(IrBuilder *irb, IrInstruction *dest_type, + ResultLoc *parent_result_loc) +{ + ResultLocCast *result_loc_cast = allocate<ResultLocCast>(1); + result_loc_cast->base.id = ResultLocIdCast; + result_loc_cast->base.source_instruction = dest_type; + ir_ref_instruction(dest_type, irb->current_basic_block); + result_loc_cast->parent = parent_result_loc; + + ir_build_reset_result(irb, dest_type->scope, dest_type->source_node, &result_loc_cast->base); + + return result_loc_cast; +} + static void build_decl_var_and_init(IrBuilder *irb, Scope *scope, AstNode *source_node, ZigVar *var, IrInstruction *init, const char *name_hint, IrInstruction *is_comptime) { @@ -6282,7 +6393,15 @@ static IrInstruction *ir_gen_var_decl(IrBuilder *irb, Scope *scope, AstNode *nod // Create a result location for the initialization expression. ResultLocVar *result_loc_var = ir_build_var_result_loc(irb, alloca, var); - ResultLoc *init_result_loc = (type_instruction == nullptr) ? &result_loc_var->base : nullptr; + ResultLoc *init_result_loc; + ResultLocCast *result_loc_cast; + if (type_instruction != nullptr) { + result_loc_cast = ir_build_cast_result_loc(irb, type_instruction, &result_loc_var->base); + init_result_loc = &result_loc_cast->base; + } else { + result_loc_cast = nullptr; + init_result_loc = &result_loc_var->base; + } Scope *init_scope = is_comptime_scalar ? create_comptime_scope(irb->codegen, variable_declaration->expr, scope) : scope; @@ -6298,9 +6417,9 @@ static IrInstruction *ir_gen_var_decl(IrBuilder *irb, Scope *scope, AstNode *nod if (init_value == irb->codegen->invalid_instruction) return irb->codegen->invalid_instruction; - if (type_instruction != nullptr) { - IrInstruction *implicit_cast = ir_build_implicit_cast(irb, scope, node, type_instruction, init_value, - &result_loc_var->base); + if (result_loc_cast != nullptr) { + IrInstruction *implicit_cast = ir_build_implicit_cast(irb, scope, init_value->source_node, + init_value, result_loc_cast); ir_build_end_expr(irb, scope, node, implicit_cast, &result_loc_var->base); } @@ -7895,14 +8014,14 @@ static bool render_instance_name_recursive(CodeGen *codegen, Buf *name, Scope *o static Buf *get_anon_type_name(CodeGen *codegen, IrExecutable *exec, const char *kind_name, Scope *scope, AstNode *source_node, Buf *out_bare_name) { - if (exec->name) { + if (exec != nullptr && exec->name) { ZigType *import = get_scope_import(scope); Buf *namespace_name = buf_alloc(); append_namespace_qualification(codegen, namespace_name, import); buf_append_buf(namespace_name, exec->name); buf_init_from_buf(out_bare_name, exec->name); return namespace_name; - } else if (exec->name_fn != nullptr) { + } else if (exec != nullptr && exec->name_fn != nullptr) { Buf *name = buf_alloc(); buf_append_buf(name, &exec->name_fn->symbol_name); buf_appendf(name, "("); @@ -8009,7 +8128,6 @@ static ZigType *get_error_set_union(CodeGen *g, ErrorTableEntry **errors, ZigTyp } } assert(index == count); - assert(count != 0); if (type_name == nullptr) { buf_appendf(&err_set_type->name, "}"); @@ -9571,7 +9689,7 @@ static bool ir_num_lit_fits_in_other_type(IrAnalyze *ira, IrInstruction *instruc } ir_add_error(ira, instruction, - buf_sprintf("%s value %s cannot be implicitly casted to type '%s'", + buf_sprintf("%s value %s cannot be coerced to type '%s'", num_lit_str, buf_ptr(val_buf), buf_ptr(&other_type->name))); @@ -9739,8 +9857,8 @@ static ConstCastOnly types_match_const_cast_only(IrAnalyze *ira, ZigType *wanted // slice const if (is_slice(wanted_type) && is_slice(actual_type)) { - ZigType *actual_ptr_type = actual_type->data.structure.fields[slice_ptr_index].type_entry; - ZigType *wanted_ptr_type = wanted_type->data.structure.fields[slice_ptr_index].type_entry; + ZigType *actual_ptr_type = actual_type->data.structure.fields[slice_ptr_index]->type_entry; + ZigType *wanted_ptr_type = wanted_type->data.structure.fields[slice_ptr_index]->type_entry; if ((err = type_resolve(g, actual_ptr_type->data.pointer.child_type, ResolveStatusAlignmentKnown))) { result.id = ConstCastResultIdInvalid; return result; @@ -10494,22 +10612,67 @@ static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigT continue; } + // *[N]T to []T + // *[N]T to E![]T + if (cur_type->id == ZigTypeIdPointer && + cur_type->data.pointer.child_type->id == ZigTypeIdArray && + ((prev_type->id == ZigTypeIdErrorUnion && is_slice(prev_type->data.error_union.payload_type)) || + is_slice(prev_type))) + { + ZigType *array_type = cur_type->data.pointer.child_type; + ZigType *slice_type = (prev_type->id == ZigTypeIdErrorUnion) ? + prev_type->data.error_union.payload_type : prev_type; + ZigType *slice_ptr_type = slice_type->data.structure.fields[slice_ptr_index]->type_entry; + if ((slice_ptr_type->data.pointer.is_const || array_type->data.array.len == 0) && + types_match_const_cast_only(ira, + slice_ptr_type->data.pointer.child_type, + array_type->data.array.child_type, source_node, false).id == ConstCastResultIdOk) + { + convert_to_const_slice = false; + continue; + } + } + + // *[N]T to []T + // *[N]T to E![]T + if (prev_type->id == ZigTypeIdPointer && + prev_type->data.pointer.child_type->id == ZigTypeIdArray && + ((cur_type->id == ZigTypeIdErrorUnion && is_slice(cur_type->data.error_union.payload_type)) || + is_slice(cur_type))) + { + ZigType *array_type = prev_type->data.pointer.child_type; + ZigType *slice_type = (cur_type->id == ZigTypeIdErrorUnion) ? + cur_type->data.error_union.payload_type : cur_type; + ZigType *slice_ptr_type = slice_type->data.structure.fields[slice_ptr_index]->type_entry; + if ((slice_ptr_type->data.pointer.is_const || array_type->data.array.len == 0) && + types_match_const_cast_only(ira, + slice_ptr_type->data.pointer.child_type, + array_type->data.array.child_type, source_node, false).id == ConstCastResultIdOk) + { + prev_inst = cur_inst; + convert_to_const_slice = false; + continue; + } + } + + // [N]T to []T if (cur_type->id == ZigTypeIdArray && is_slice(prev_type) && - (prev_type->data.structure.fields[slice_ptr_index].type_entry->data.pointer.is_const || + (prev_type->data.structure.fields[slice_ptr_index]->type_entry->data.pointer.is_const || cur_type->data.array.len == 0) && types_match_const_cast_only(ira, - prev_type->data.structure.fields[slice_ptr_index].type_entry->data.pointer.child_type, + prev_type->data.structure.fields[slice_ptr_index]->type_entry->data.pointer.child_type, cur_type->data.array.child_type, source_node, false).id == ConstCastResultIdOk) { convert_to_const_slice = false; continue; } + // [N]T to []T if (prev_type->id == ZigTypeIdArray && is_slice(cur_type) && - (cur_type->data.structure.fields[slice_ptr_index].type_entry->data.pointer.is_const || + (cur_type->data.structure.fields[slice_ptr_index]->type_entry->data.pointer.is_const || prev_type->data.array.len == 0) && types_match_const_cast_only(ira, - cur_type->data.structure.fields[slice_ptr_index].type_entry->data.pointer.child_type, + cur_type->data.structure.fields[slice_ptr_index]->type_entry->data.pointer.child_type, prev_type->data.array.child_type, source_node, false).id == ConstCastResultIdOk) { prev_inst = cur_inst; @@ -10620,9 +10783,9 @@ static void copy_const_val(ConstExprValue *dest, ConstExprValue *src, bool same_ if (src->special != ConstValSpecialStatic) return; if (dest->type->id == ZigTypeIdStruct) { - dest->data.x_struct.fields = create_const_vals(dest->type->data.structure.src_field_count); + dest->data.x_struct.fields = alloc_const_vals_ptrs(dest->type->data.structure.src_field_count); for (size_t i = 0; i < dest->type->data.structure.src_field_count; i += 1) { - copy_const_val(&dest->data.x_struct.fields[i], &src->data.x_struct.fields[i], false); + copy_const_val(dest->data.x_struct.fields[i], src->data.x_struct.fields[i], false); } } } @@ -10814,12 +10977,11 @@ static IrInstruction *ir_resolve_ptr_of_array_to_slice(IrAnalyze *ira, IrInstruc assert(value->value.type->id == ZigTypeIdPointer); ZigType *array_type = value->value.type->data.pointer.child_type; assert(is_slice(wanted_type)); - bool is_const = wanted_type->data.structure.fields[slice_ptr_index].type_entry->data.pointer.is_const; + bool is_const = wanted_type->data.structure.fields[slice_ptr_index]->type_entry->data.pointer.is_const; IrInstruction *result = ir_const(ira, source_instr, wanted_type); init_const_slice(ira->codegen, &result->value, pointee, 0, array_type->data.array.len, is_const); - result->value.data.x_struct.fields[slice_ptr_index].data.x_ptr.mut = - value->value.data.x_ptr.mut; + result->value.data.x_struct.fields[slice_ptr_index]->data.x_ptr.mut = value->value.data.x_ptr.mut; result->value.type = wanted_type; return result; } @@ -12401,6 +12563,27 @@ static IrInstruction *ir_analyze_enum_literal(IrAnalyze *ira, IrInstruction *sou return result; } +static IrInstruction *ir_analyze_struct_literal_to_array(IrAnalyze *ira, IrInstruction *source_instr, + IrInstruction *value, ZigType *wanted_type) +{ + ir_add_error(ira, source_instr, buf_sprintf("TODO: type coercion of anon list literal to array")); + return ira->codegen->invalid_instruction; +} + +static IrInstruction *ir_analyze_struct_literal_to_struct(IrAnalyze *ira, IrInstruction *source_instr, + IrInstruction *value, ZigType *wanted_type) +{ + ir_add_error(ira, source_instr, buf_sprintf("TODO: type coercion of anon struct literal to struct")); + return ira->codegen->invalid_instruction; +} + +static IrInstruction *ir_analyze_struct_literal_to_union(IrAnalyze *ira, IrInstruction *source_instr, + IrInstruction *value, ZigType *wanted_type) +{ + ir_add_error(ira, source_instr, buf_sprintf("TODO: type coercion of anon struct literal to union")); + return ira->codegen->invalid_instruction; +} + static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_instr, ZigType *wanted_type, IrInstruction *value, ResultLoc *result_loc) { @@ -12412,6 +12595,11 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst return ira->codegen->invalid_instruction; } + // This means the wanted type is anything. + if (wanted_type == ira->codegen->builtin_types.entry_var) { + return value; + } + // perfect match or non-const to const ConstCastOnly const_cast_result = types_match_const_cast_only(ira, wanted_type, actual_type, source_node, false); @@ -12586,7 +12774,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst // cast from [N]T to []const T // TODO: once https://github.com/ziglang/zig/issues/265 lands, remove this if (is_slice(wanted_type) && actual_type->id == ZigTypeIdArray) { - ZigType *ptr_type = wanted_type->data.structure.fields[slice_ptr_index].type_entry; + ZigType *ptr_type = wanted_type->data.structure.fields[slice_ptr_index]->type_entry; assert(ptr_type->id == ZigTypeIdPointer); if ((ptr_type->data.pointer.is_const || actual_type->data.array.len == 0) && types_match_const_cast_only(ira, ptr_type->data.pointer.child_type, actual_type->data.array.child_type, @@ -12603,7 +12791,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst actual_type->id == ZigTypeIdArray) { ZigType *ptr_type = - wanted_type->data.maybe.child_type->data.structure.fields[slice_ptr_index].type_entry; + wanted_type->data.maybe.child_type->data.structure.fields[slice_ptr_index]->type_entry; assert(ptr_type->id == ZigTypeIdPointer); if ((ptr_type->data.pointer.is_const || actual_type->data.array.len == 0) && types_match_const_cast_only(ira, ptr_type->data.pointer.child_type, actual_type->data.array.child_type, @@ -12642,12 +12830,71 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst } // *[N]T to []T - if (is_slice(wanted_type) && + // *[N]T to E![]T + if ((is_slice(wanted_type) || + (wanted_type->id == ZigTypeIdErrorUnion && + is_slice(wanted_type->data.error_union.payload_type))) && actual_type->id == ZigTypeIdPointer && actual_type->data.pointer.ptr_len == PtrLenSingle && actual_type->data.pointer.child_type->id == ZigTypeIdArray) { - ZigType *slice_ptr_type = wanted_type->data.structure.fields[slice_ptr_index].type_entry; + ZigType *slice_type = (wanted_type->id == ZigTypeIdErrorUnion) ? + wanted_type->data.error_union.payload_type : wanted_type; + ZigType *slice_ptr_type = slice_type->data.structure.fields[slice_ptr_index]->type_entry; + assert(slice_ptr_type->id == ZigTypeIdPointer); + ZigType *array_type = actual_type->data.pointer.child_type; + bool const_ok = (slice_ptr_type->data.pointer.is_const || array_type->data.array.len == 0 + || !actual_type->data.pointer.is_const); + if (const_ok && types_match_const_cast_only(ira, slice_ptr_type->data.pointer.child_type, + array_type->data.array.child_type, source_node, + !slice_ptr_type->data.pointer.is_const).id == ConstCastResultIdOk) + { + // If the pointers both have ABI align, it works. + // Or if the array length is 0, alignment doesn't matter. + bool ok_align = array_type->data.array.len == 0 || + (slice_ptr_type->data.pointer.explicit_alignment == 0 && + actual_type->data.pointer.explicit_alignment == 0); + if (!ok_align) { + // If either one has non ABI align, we have to resolve them both + if ((err = type_resolve(ira->codegen, actual_type->data.pointer.child_type, + ResolveStatusAlignmentKnown))) + { + return ira->codegen->invalid_instruction; + } + if ((err = type_resolve(ira->codegen, slice_ptr_type->data.pointer.child_type, + ResolveStatusAlignmentKnown))) + { + return ira->codegen->invalid_instruction; + } + ok_align = get_ptr_align(ira->codegen, actual_type) >= get_ptr_align(ira->codegen, slice_ptr_type); + } + if (ok_align) { + if (wanted_type->id == ZigTypeIdErrorUnion) { + IrInstruction *cast1 = ir_analyze_cast(ira, source_instr, slice_type, value, nullptr); + if (type_is_invalid(cast1->value.type)) + return ira->codegen->invalid_instruction; + + IrInstruction *cast2 = ir_analyze_cast(ira, source_instr, wanted_type, cast1, result_loc); + if (type_is_invalid(cast2->value.type)) + return ira->codegen->invalid_instruction; + + return cast2; + } else { + return ir_resolve_ptr_of_array_to_slice(ira, source_instr, value, slice_type, result_loc); + } + } + } + } + + // *[N]T to E![]T + if (wanted_type->id == ZigTypeIdErrorUnion && + is_slice(wanted_type->data.error_union.payload_type) && + actual_type->id == ZigTypeIdPointer && + actual_type->data.pointer.ptr_len == PtrLenSingle && + actual_type->data.pointer.child_type->id == ZigTypeIdArray) + { + ZigType *slice_type = wanted_type->data.error_union.payload_type; + ZigType *slice_ptr_type = slice_type->data.structure.fields[slice_ptr_index]->type_entry; assert(slice_ptr_type->id == ZigTypeIdPointer); ZigType *array_type = actual_type->data.pointer.child_type; bool const_ok = (slice_ptr_type->data.pointer.is_const || array_type->data.array.len == 0 @@ -12674,7 +12921,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst ok_align = get_ptr_align(ira->codegen, actual_type) >= get_ptr_align(ira->codegen, slice_ptr_type); } if (ok_align) { - return ir_resolve_ptr_of_array_to_slice(ira, source_instr, value, wanted_type, result_loc); + return ir_resolve_ptr_of_array_to_slice(ira, source_instr, value, slice_type, result_loc); } } } @@ -12724,7 +12971,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst actual_type->id == ZigTypeIdArray) { ZigType *ptr_type = - wanted_type->data.error_union.payload_type->data.structure.fields[slice_ptr_index].type_entry; + wanted_type->data.error_union.payload_type->data.structure.fields[slice_ptr_index]->type_entry; assert(ptr_type->id == ZigTypeIdPointer); if ((ptr_type->data.pointer.is_const || actual_type->data.array.len == 0) && types_match_const_cast_only(ira, ptr_type->data.pointer.child_type, actual_type->data.array.child_type, @@ -12909,6 +13156,25 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst return ir_analyze_int_to_c_ptr(ira, source_instr, value, wanted_type); } + // cast from inferred struct type to array, union, or struct + if (actual_type->id == ZigTypeIdStruct && actual_type->data.structure.is_inferred) { + AstNode *decl_node = actual_type->data.structure.decl_node; + ir_assert(decl_node->type == NodeTypeContainerInitExpr, source_instr); + ContainerInitKind init_kind = decl_node->data.container_init_expr.kind; + uint32_t field_count = actual_type->data.structure.src_field_count; + if (wanted_type->id == ZigTypeIdArray && (init_kind == ContainerInitKindArray || field_count == 0) && + wanted_type->data.array.len == field_count) + { + return ir_analyze_struct_literal_to_array(ira, source_instr, value, wanted_type); + } else if (wanted_type->id == ZigTypeIdStruct && + (init_kind == ContainerInitKindStruct || field_count == 0)) + { + return ir_analyze_struct_literal_to_struct(ira, source_instr, value, wanted_type); + } else if (wanted_type->id == ZigTypeIdUnion && init_kind == ContainerInitKindStruct && field_count == 1) { + return ir_analyze_struct_literal_to_union(ira, source_instr, value, wanted_type); + } + } + // cast from undefined to anything if (actual_type->id == ZigTypeIdUndefined) { return ir_analyze_undefined_to_anything(ira, source_instr, value, wanted_type); @@ -12922,8 +13188,8 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst return ira->codegen->invalid_instruction; } -static IrInstruction *ir_implicit_cast_with_result(IrAnalyze *ira, IrInstruction *value, ZigType *expected_type, - ResultLoc *result_loc) +static IrInstruction *ir_implicit_cast_with_result(IrAnalyze *ira, IrInstruction *source_instr, + IrInstruction *value, ZigType *expected_type, ResultLoc *result_loc) { assert(value); assert(value != ira->codegen->invalid_instruction); @@ -12937,11 +13203,11 @@ static IrInstruction *ir_implicit_cast_with_result(IrAnalyze *ira, IrInstruction if (value->value.type->id == ZigTypeIdUnreachable) return value; - return ir_analyze_cast(ira, value, expected_type, value, result_loc); + return ir_analyze_cast(ira, source_instr, expected_type, value, result_loc); } static IrInstruction *ir_implicit_cast(IrAnalyze *ira, IrInstruction *value, ZigType *expected_type) { - return ir_implicit_cast_with_result(ira, value, expected_type, nullptr); + return ir_implicit_cast_with_result(ira, value, value, expected_type, nullptr); } static IrInstruction *ir_get_deref(IrAnalyze *ira, IrInstruction *source_instruction, IrInstruction *ptr, @@ -13223,8 +13489,8 @@ static Buf *ir_resolve_str(IrAnalyze *ira, IrInstruction *value) { if (!const_val) return nullptr; - ConstExprValue *ptr_field = &const_val->data.x_struct.fields[slice_ptr_index]; - ConstExprValue *len_field = &const_val->data.x_struct.fields[slice_len_index]; + ConstExprValue *ptr_field = const_val->data.x_struct.fields[slice_ptr_index]; + ConstExprValue *len_field = const_val->data.x_struct.fields[slice_len_index]; assert(ptr_field->data.x_ptr.special == ConstPtrSpecialBaseArray); ConstExprValue *array_val = ptr_field->data.x_ptr.data.base_array.array_val; @@ -13269,16 +13535,6 @@ static IrInstruction *ir_analyze_instruction_return(IrAnalyze *ira, IrInstructio if (type_is_invalid(operand->value.type)) return ir_unreach_error(ira); - if (!instr_is_comptime(operand) && ira->explicit_return_type != nullptr && - handle_is_ptr(ira->explicit_return_type)) - { - // result location mechanism took care of it. - IrInstruction *result = ir_build_return(&ira->new_irb, instruction->base.scope, - instruction->base.source_node, nullptr); - result->value.type = ira->codegen->builtin_types.entry_unreachable; - return ir_finish_anal(ira, result); - } - IrInstruction *casted_operand = ir_implicit_cast(ira, operand, ira->explicit_return_type); if (type_is_invalid(casted_operand->value.type)) { AstNode *source_node = ira->explicit_return_type_source_node; @@ -13290,6 +13546,16 @@ static IrInstruction *ir_analyze_instruction_return(IrAnalyze *ira, IrInstructio return ir_unreach_error(ira); } + if (!instr_is_comptime(operand) && ira->explicit_return_type != nullptr && + handle_is_ptr(ira->explicit_return_type)) + { + // result location mechanism took care of it. + IrInstruction *result = ir_build_return(&ira->new_irb, instruction->base.scope, + instruction->base.source_node, nullptr); + result->value.type = ira->codegen->builtin_types.entry_unreachable; + return ir_finish_anal(ira, result); + } + if (casted_operand->value.special == ConstValSpecialRuntime && casted_operand->value.type->id == ZigTypeIdPointer && casted_operand->value.data.rh_ptr == RuntimeHintPtrStack) @@ -14550,13 +14816,13 @@ static IrInstruction *ir_analyze_array_cat(IrAnalyze *ira, IrInstructionBinOp *i op1_array_index = op1_val->data.x_ptr.data.base_array.elem_index; op1_array_end = op1_array_val->type->data.array.len - 1; } else if (is_slice(op1_type)) { - ZigType *ptr_type = op1_type->data.structure.fields[slice_ptr_index].type_entry; + ZigType *ptr_type = op1_type->data.structure.fields[slice_ptr_index]->type_entry; child_type = ptr_type->data.pointer.child_type; - ConstExprValue *ptr_val = &op1_val->data.x_struct.fields[slice_ptr_index]; + ConstExprValue *ptr_val = op1_val->data.x_struct.fields[slice_ptr_index]; assert(ptr_val->data.x_ptr.special == ConstPtrSpecialBaseArray); op1_array_val = ptr_val->data.x_ptr.data.base_array.array_val; op1_array_index = ptr_val->data.x_ptr.data.base_array.elem_index; - ConstExprValue *len_val = &op1_val->data.x_struct.fields[slice_len_index]; + ConstExprValue *len_val = op1_val->data.x_struct.fields[slice_len_index]; op1_array_end = op1_array_index + bigint_as_usize(&len_val->data.x_bigint); } else { ir_add_error(ira, op1, @@ -14583,13 +14849,13 @@ static IrInstruction *ir_analyze_array_cat(IrAnalyze *ira, IrInstructionBinOp *i op2_array_index = op2_val->data.x_ptr.data.base_array.elem_index; op2_array_end = op2_array_val->type->data.array.len - 1; } else if (is_slice(op2_type)) { - ZigType *ptr_type = op2_type->data.structure.fields[slice_ptr_index].type_entry; + ZigType *ptr_type = op2_type->data.structure.fields[slice_ptr_index]->type_entry; op2_type_valid = ptr_type->data.pointer.child_type == child_type; - ConstExprValue *ptr_val = &op2_val->data.x_struct.fields[slice_ptr_index]; + ConstExprValue *ptr_val = op2_val->data.x_struct.fields[slice_ptr_index]; assert(ptr_val->data.x_ptr.special == ConstPtrSpecialBaseArray); op2_array_val = ptr_val->data.x_ptr.data.base_array.array_val; op2_array_index = ptr_val->data.x_ptr.data.base_array.elem_index; - ConstExprValue *len_val = &op2_val->data.x_struct.fields[slice_len_index]; + ConstExprValue *len_val = op2_val->data.x_struct.fields[slice_len_index]; op2_array_end = op2_array_index + bigint_as_usize(&len_val->data.x_bigint); } else { ir_add_error(ira, op2, @@ -14621,17 +14887,17 @@ static IrInstruction *ir_analyze_array_cat(IrAnalyze *ira, IrInstructionBinOp *i out_array_val->special = ConstValSpecialStatic; out_array_val->type = get_array_type(ira->codegen, child_type, new_len); - out_val->data.x_struct.fields = create_const_vals(2); + out_val->data.x_struct.fields = alloc_const_vals_ptrs(2); - out_val->data.x_struct.fields[slice_ptr_index].type = ptr_type; - out_val->data.x_struct.fields[slice_ptr_index].special = ConstValSpecialStatic; - out_val->data.x_struct.fields[slice_ptr_index].data.x_ptr.special = ConstPtrSpecialBaseArray; - out_val->data.x_struct.fields[slice_ptr_index].data.x_ptr.data.base_array.array_val = out_array_val; - out_val->data.x_struct.fields[slice_ptr_index].data.x_ptr.data.base_array.elem_index = 0; + out_val->data.x_struct.fields[slice_ptr_index]->type = ptr_type; + out_val->data.x_struct.fields[slice_ptr_index]->special = ConstValSpecialStatic; + out_val->data.x_struct.fields[slice_ptr_index]->data.x_ptr.special = ConstPtrSpecialBaseArray; + out_val->data.x_struct.fields[slice_ptr_index]->data.x_ptr.data.base_array.array_val = out_array_val; + out_val->data.x_struct.fields[slice_ptr_index]->data.x_ptr.data.base_array.elem_index = 0; - out_val->data.x_struct.fields[slice_len_index].type = ira->codegen->builtin_types.entry_usize; - out_val->data.x_struct.fields[slice_len_index].special = ConstValSpecialStatic; - bigint_init_unsigned(&out_val->data.x_struct.fields[slice_len_index].data.x_bigint, new_len); + out_val->data.x_struct.fields[slice_len_index]->type = ira->codegen->builtin_types.entry_usize; + out_val->data.x_struct.fields[slice_len_index]->special = ConstValSpecialStatic; + bigint_init_unsigned(&out_val->data.x_struct.fields[slice_len_index]->data.x_bigint, new_len); } else { new_len += 1; // null byte @@ -15295,15 +15561,16 @@ static IrInstruction *ir_analyze_alloca(IrAnalyze *ira, IrInstruction *source_in result->base.value.data.x_ptr.mut = force_comptime ? ConstPtrMutComptimeVar : ConstPtrMutInfer; result->base.value.data.x_ptr.data.ref.pointee = pointee; - if ((err = type_resolve(ira->codegen, var_type, ResolveStatusZeroBitsKnown))) + bool var_type_has_bits; + if ((err = type_has_bits2(ira->codegen, var_type, &var_type_has_bits))) return ira->codegen->invalid_instruction; if (align != 0) { if ((err = type_resolve(ira->codegen, var_type, ResolveStatusAlignmentKnown))) return ira->codegen->invalid_instruction; - if (!type_has_bits(var_type)) { - ir_add_error(ira, source_inst, - buf_sprintf("variable '%s' of zero-bit type '%s' has no in-memory representation, it cannot be aligned", - name_hint, buf_ptr(&var_type->name))); + if (!var_type_has_bits) { + ir_add_error(ira, source_inst, + buf_sprintf("variable '%s' of zero-bit type '%s' has no in-memory representation, it cannot be aligned", + name_hint, buf_ptr(&var_type->name))); return ira->codegen->invalid_instruction; } } @@ -15331,6 +15598,7 @@ static ZigType *ir_result_loc_expected_type(IrAnalyze *ira, IrInstruction *suspe case ResultLocIdNone: case ResultLocIdVar: case ResultLocIdBitCast: + case ResultLocIdCast: return nullptr; case ResultLocIdInstruction: return result_loc->source_instruction->child->value.type; @@ -15374,24 +15642,51 @@ static void set_up_result_loc_for_inferred_comptime(IrInstruction *ptr) { ptr->value.data.x_ptr.data.ref.pointee = undef_child; } -static bool ir_result_has_type(ResultLoc *result_loc) { +static Error ir_result_has_type(IrAnalyze *ira, ResultLoc *result_loc, bool *out) { switch (result_loc->id) { case ResultLocIdInvalid: case ResultLocIdPeerParent: zig_unreachable(); case ResultLocIdNone: case ResultLocIdPeer: - return false; + *out = false; + return ErrorNone; case ResultLocIdReturn: case ResultLocIdInstruction: case ResultLocIdBitCast: - return true; + *out = true; + return ErrorNone; + case ResultLocIdCast: { + ResultLocCast *result_cast = reinterpret_cast<ResultLocCast *>(result_loc); + ZigType *dest_type = ir_resolve_type(ira, result_cast->base.source_instruction->child); + if (type_is_invalid(dest_type)) + return ErrorSemanticAnalyzeFail; + *out = (dest_type != ira->codegen->builtin_types.entry_var); + return ErrorNone; + } case ResultLocIdVar: - return reinterpret_cast<ResultLocVar *>(result_loc)->var->decl_node->data.variable_declaration.type != nullptr; + *out = reinterpret_cast<ResultLocVar *>(result_loc)->var->decl_node->data.variable_declaration.type != nullptr; + return ErrorNone; } zig_unreachable(); } +static IrInstruction *ir_resolve_no_result_loc(IrAnalyze *ira, IrInstruction *suspend_source_instr, + ResultLoc *result_loc, ZigType *value_type, bool force_runtime, bool non_null_comptime) +{ + IrInstructionAllocaGen *alloca_gen = ir_build_alloca_gen(ira, suspend_source_instr, 0, ""); + alloca_gen->base.value.type = get_pointer_to_type_extra(ira->codegen, value_type, false, false, + PtrLenSingle, 0, 0, 0, false); + set_up_result_loc_for_inferred_comptime(&alloca_gen->base); + ZigFn *fn_entry = exec_fn_entry(ira->new_irb.exec); + if (fn_entry != nullptr && get_scope_typeof(suspend_source_instr->scope) == nullptr) { + fn_entry->alloca_gen_list.append(alloca_gen); + } + result_loc->written = true; + result_loc->resolved_loc = &alloca_gen->base; + return result_loc->resolved_loc; +} + // when calling this function, at the callsite must check for result type noreturn and propagate it up static IrInstruction *ir_resolve_result_raw(IrAnalyze *ira, IrInstruction *suspend_source_instr, ResultLoc *result_loc, ZigType *value_type, IrInstruction *value, bool force_runtime, bool non_null_comptime) @@ -15414,19 +15709,8 @@ static IrInstruction *ir_resolve_result_raw(IrAnalyze *ira, IrInstruction *suspe return nullptr; } // need to return a result location and don't have one. use a stack allocation - IrInstructionAllocaGen *alloca_gen = ir_build_alloca_gen(ira, suspend_source_instr, 0, ""); - if ((err = type_resolve(ira->codegen, value_type, ResolveStatusZeroBitsKnown))) - return ira->codegen->invalid_instruction; - alloca_gen->base.value.type = get_pointer_to_type_extra(ira->codegen, value_type, false, false, - PtrLenSingle, 0, 0, 0, false); - set_up_result_loc_for_inferred_comptime(&alloca_gen->base); - ZigFn *fn_entry = exec_fn_entry(ira->new_irb.exec); - if (fn_entry != nullptr && get_scope_typeof(suspend_source_instr->scope) == nullptr) { - fn_entry->alloca_gen_list.append(alloca_gen); - } - result_loc->written = true; - result_loc->resolved_loc = &alloca_gen->base; - return result_loc->resolved_loc; + return ir_resolve_no_result_loc(ira, suspend_source_instr, result_loc, value_type, + force_runtime, non_null_comptime); } case ResultLocIdVar: { ResultLocVar *result_loc_var = reinterpret_cast<ResultLocVar *>(result_loc); @@ -15529,7 +15813,10 @@ static IrInstruction *ir_resolve_result_raw(IrAnalyze *ira, IrInstruction *suspe } return nullptr; } - if (ir_result_has_type(peer_parent->parent)) { + bool peer_parent_has_type; + if ((err = ir_result_has_type(ira, peer_parent->parent, &peer_parent_has_type))) + return ira->codegen->invalid_instruction; + if (peer_parent_has_type) { if (peer_parent->parent->id == ResultLocIdReturn && value != nullptr) { reinterpret_cast<ResultLocReturn *>(peer_parent->parent)->implicit_return_type_done = true; ira->src_implicit_return_type_list.append(value); @@ -15564,6 +15851,89 @@ static IrInstruction *ir_resolve_result_raw(IrAnalyze *ira, IrInstruction *suspe result_loc->resolved_loc = parent_result_loc; return result_loc->resolved_loc; } + case ResultLocIdCast: { + if (value != nullptr && value->value.special != ConstValSpecialRuntime) + return nullptr; + ResultLocCast *result_cast = reinterpret_cast<ResultLocCast *>(result_loc); + ZigType *dest_type = ir_resolve_type(ira, result_cast->base.source_instruction->child); + if (type_is_invalid(dest_type)) + return ira->codegen->invalid_instruction; + + if (dest_type == ira->codegen->builtin_types.entry_var) { + return ir_resolve_no_result_loc(ira, suspend_source_instr, result_loc, value_type, + force_runtime, non_null_comptime); + } + + ConstCastOnly const_cast_result = types_match_const_cast_only(ira, dest_type, value_type, + result_cast->base.source_instruction->source_node, false); + if (const_cast_result.id == ConstCastResultIdInvalid) + return ira->codegen->invalid_instruction; + if (const_cast_result.id != ConstCastResultIdOk) { + // We will not be able to provide a result location for this value. Create + // a new result location. + return ir_resolve_no_result_loc(ira, suspend_source_instr, result_loc, value_type, + force_runtime, non_null_comptime); + } + + // In this case we can pointer cast the result location. + IrInstruction *casted_value; + if (value != nullptr) { + casted_value = ir_implicit_cast(ira, value, dest_type); + } else { + casted_value = nullptr; + } + + if (casted_value != nullptr && type_is_invalid(casted_value->value.type)) { + return casted_value; + } + + bool old_parent_result_loc_written = result_cast->parent->written; + IrInstruction *parent_result_loc = ir_resolve_result(ira, suspend_source_instr, result_cast->parent, + dest_type, casted_value, force_runtime, non_null_comptime, true); + if (parent_result_loc == nullptr || type_is_invalid(parent_result_loc->value.type) || + parent_result_loc->value.type->id == ZigTypeIdUnreachable) + { + return parent_result_loc; + } + ZigType *parent_ptr_type = parent_result_loc->value.type; + assert(parent_ptr_type->id == ZigTypeIdPointer); + if ((err = type_resolve(ira->codegen, parent_ptr_type->data.pointer.child_type, + ResolveStatusAlignmentKnown))) + { + return ira->codegen->invalid_instruction; + } + uint64_t parent_ptr_align = get_ptr_align(ira->codegen, parent_ptr_type); + if ((err = type_resolve(ira->codegen, value_type, ResolveStatusAlignmentKnown))) { + return ira->codegen->invalid_instruction; + } + if (!type_has_bits(value_type)) { + parent_ptr_align = 0; + } + ZigType *ptr_type = get_pointer_to_type_extra(ira->codegen, value_type, + parent_ptr_type->data.pointer.is_const, parent_ptr_type->data.pointer.is_volatile, PtrLenSingle, + parent_ptr_align, 0, 0, parent_ptr_type->data.pointer.allow_zero); + + { + // we also need to check that this cast is OK. + ConstCastOnly const_cast_result = types_match_const_cast_only(ira, + parent_result_loc->value.type, ptr_type, + result_cast->base.source_instruction->source_node, false); + if (const_cast_result.id == ConstCastResultIdInvalid) + return ira->codegen->invalid_instruction; + if (const_cast_result.id != ConstCastResultIdOk) { + // We will not be able to provide a result location for this value. Create + // a new result location. + result_cast->parent->written = old_parent_result_loc_written; + return ir_resolve_no_result_loc(ira, suspend_source_instr, result_loc, value_type, + force_runtime, non_null_comptime); + } + } + + result_loc->written = true; + result_loc->resolved_loc = ir_analyze_ptr_cast(ira, suspend_source_instr, parent_result_loc, + ptr_type, result_cast->base.source_instruction, false); + return result_loc->resolved_loc; + } case ResultLocIdBitCast: { ResultLocBitCast *result_bit_cast = reinterpret_cast<ResultLocBitCast *>(result_loc); ZigType *dest_type = ir_resolve_type(ira, result_bit_cast->base.source_instruction->child); @@ -15686,22 +16056,40 @@ static IrInstruction *ir_resolve_result(IrAnalyze *ira, IrInstruction *suspend_s return result_loc; } -static IrInstruction *ir_analyze_instruction_implicit_cast(IrAnalyze *ira, IrInstructionImplicitCast *instruction) { - ZigType *dest_type = ir_resolve_type(ira, instruction->dest_type->child); - if (type_is_invalid(dest_type)) - return ira->codegen->invalid_instruction; - - IrInstruction *target = instruction->target->child; - if (type_is_invalid(target->value.type)) - return ira->codegen->invalid_instruction; - - return ir_implicit_cast_with_result(ira, target, dest_type, instruction->result_loc); -} +static IrInstruction *ir_analyze_instruction_resolve_result(IrAnalyze *ira, + IrInstructionResolveResult *instruction) +{ + ZigType *implicit_elem_type; + if (instruction->ty == nullptr) { + if (instruction->result_loc->id == ResultLocIdCast) { + implicit_elem_type = ir_resolve_type(ira, + instruction->result_loc->source_instruction->child); + if (type_is_invalid(implicit_elem_type)) + return ira->codegen->invalid_instruction; + } else if (instruction->result_loc->id == ResultLocIdReturn) { + implicit_elem_type = ira->explicit_return_type; + if (type_is_invalid(implicit_elem_type)) + return ira->codegen->invalid_instruction; + } else { + implicit_elem_type = ira->codegen->builtin_types.entry_var; + } + if (implicit_elem_type == ira->codegen->builtin_types.entry_var) { + Buf *bare_name = buf_alloc(); + Buf *name = get_anon_type_name(ira->codegen, nullptr, container_string(ContainerKindStruct), + instruction->base.scope, instruction->base.source_node, bare_name); -static IrInstruction *ir_analyze_instruction_resolve_result(IrAnalyze *ira, IrInstructionResolveResult *instruction) { - ZigType *implicit_elem_type = ir_resolve_type(ira, instruction->ty->child); - if (type_is_invalid(implicit_elem_type)) - return ira->codegen->invalid_instruction; + ZigType *inferred_struct_type = get_partial_container_type(ira->codegen, + instruction->base.scope, ContainerKindStruct, instruction->base.source_node, + buf_ptr(name), bare_name, ContainerLayoutAuto); + inferred_struct_type->data.structure.is_inferred = true; + inferred_struct_type->data.structure.resolve_status = ResolveStatusBeingInferred; + implicit_elem_type = inferred_struct_type; + } + } else { + implicit_elem_type = ir_resolve_type(ira, instruction->ty->child); + if (type_is_invalid(implicit_elem_type)) + return ira->codegen->invalid_instruction; + } IrInstruction *result_loc = ir_resolve_result(ira, &instruction->base, instruction->result_loc, implicit_elem_type, nullptr, false, true, true); if (result_loc != nullptr) @@ -15760,6 +16148,7 @@ static void ir_reset_result(ResultLoc *result_loc) { case ResultLocIdNone: case ResultLocIdInstruction: case ResultLocIdBitCast: + case ResultLocIdCast: break; } } @@ -16062,13 +16451,63 @@ static IrInstruction *ir_analyze_store_ptr(IrAnalyze *ira, IrInstruction *source return ir_const_void(ira, source_instr); } - ZigType *child_type = ptr->value.type->data.pointer.child_type; + InferredStructField *isf = ptr->value.type->data.pointer.inferred_struct_field; + if (allow_write_through_const && isf != nullptr) { + // Now it's time to add the field to the struct type. + uint32_t old_field_count = isf->inferred_struct_type->data.structure.src_field_count; + uint32_t new_field_count = old_field_count + 1; + isf->inferred_struct_type->data.structure.src_field_count = new_field_count; + isf->inferred_struct_type->data.structure.fields = realloc_type_struct_fields( + isf->inferred_struct_type->data.structure.fields, old_field_count, new_field_count); + + TypeStructField *field = isf->inferred_struct_type->data.structure.fields[old_field_count]; + field->name = isf->field_name; + field->type_entry = uncasted_value->value.type; + field->type_val = create_const_type(ira->codegen, field->type_entry); + field->src_index = old_field_count; + field->decl_node = uncasted_value->source_node; + + ZigType *struct_ptr_type = get_pointer_to_type(ira->codegen, isf->inferred_struct_type, false); + IrInstruction *casted_ptr; + if (instr_is_comptime(ptr)) { + casted_ptr = ir_const(ira, source_instr, struct_ptr_type); + copy_const_val(&casted_ptr->value, &ptr->value, false); + casted_ptr->value.type = struct_ptr_type; + } else { + casted_ptr = ir_build_cast(&ira->new_irb, source_instr->scope, + source_instr->source_node, struct_ptr_type, ptr, CastOpNoop); + casted_ptr->value.type = struct_ptr_type; + } + if (instr_is_comptime(casted_ptr)) { + ConstExprValue *ptr_val = ir_resolve_const(ira, casted_ptr, UndefBad); + if (!ptr_val) + return ira->codegen->invalid_instruction; + if (ptr_val->data.x_ptr.special != ConstPtrSpecialHardCodedAddr) { + ConstExprValue *struct_val = const_ptr_pointee(ira, ira->codegen, ptr_val, + source_instr->source_node); + struct_val->special = ConstValSpecialStatic; + struct_val->data.x_struct.fields = realloc_const_vals_ptrs(struct_val->data.x_struct.fields, + old_field_count, new_field_count); + + ConstExprValue *field_val = struct_val->data.x_struct.fields[old_field_count]; + field_val->special = ConstValSpecialUndef; + field_val->type = field->type_entry; + field_val->parent.id = ConstParentIdStruct; + field_val->parent.data.p_struct.struct_val = struct_val; + field_val->parent.data.p_struct.field_index = old_field_count; + } + } + + ptr = ir_analyze_struct_field_ptr(ira, source_instr, field, casted_ptr, + isf->inferred_struct_type, true); + } if (ptr->value.type->data.pointer.is_const && !allow_write_through_const) { ir_add_error(ira, source_instr, buf_sprintf("cannot assign to constant")); return ira->codegen->invalid_instruction; } + ZigType *child_type = ptr->value.type->data.pointer.child_type; IrInstruction *value = ir_implicit_cast(ira, uncasted_value, child_type); if (value == ira->codegen->invalid_instruction) return ira->codegen->invalid_instruction; @@ -16799,25 +17238,14 @@ static IrInstruction *ir_analyze_instruction_call(IrAnalyze *ira, IrInstructionC if (is_comptime || instr_is_comptime(fn_ref)) { if (fn_ref->value.type->id == ZigTypeIdMetaType) { - ZigType *dest_type = ir_resolve_type(ira, fn_ref); - if (type_is_invalid(dest_type)) - return ira->codegen->invalid_instruction; - - size_t actual_param_count = call_instruction->arg_count; - - if (actual_param_count != 1) { - ir_add_error_node(ira, call_instruction->base.source_node, - buf_sprintf("cast expression expects exactly one parameter")); + ZigType *ty = ir_resolve_type(ira, fn_ref); + if (ty == nullptr) return ira->codegen->invalid_instruction; - } - - IrInstruction *arg = call_instruction->args[0]->child; - - IrInstruction *cast_instruction = ir_analyze_cast(ira, &call_instruction->base, dest_type, arg, - call_instruction->result_loc); - if (type_is_invalid(cast_instruction->value.type)) - return ira->codegen->invalid_instruction; - return ir_finish_anal(ira, cast_instruction); + ErrorMsg *msg = ir_add_error_node(ira, fn_ref->source_node, + buf_sprintf("type '%s' not a function", buf_ptr(&ty->name))); + add_error_note(ira->codegen, msg, call_instruction->base.source_node, + buf_sprintf("use @as builtin for type coercion")); + return ira->codegen->invalid_instruction; } else if (fn_ref->value.type->id == ZigTypeIdFn) { ZigFn *fn_table_entry = ir_resolve_fn(ira, fn_ref); ZigType *fn_type = fn_table_entry ? fn_table_entry->type_entry : fn_ref->value.type; @@ -17215,6 +17643,8 @@ static IrInstruction *ir_analyze_instruction_unreachable(IrAnalyze *ira, } static IrInstruction *ir_analyze_instruction_phi(IrAnalyze *ira, IrInstructionPhi *phi_instruction) { + Error err; + if (ira->const_predecessor_bb) { for (size_t i = 0; i < phi_instruction->incoming_count; i += 1) { IrBasicBlock *predecessor = phi_instruction->incoming_blocks[i]; @@ -17264,6 +17694,8 @@ static IrInstruction *ir_analyze_instruction_phi(IrAnalyze *ira, IrInstructionPh peer_parent->resolved_type = ir_resolve_peer_types(ira, peer_parent->base.source_instruction->source_node, expected_type, instructions, peer_parent->peers.length); + if (type_is_invalid(peer_parent->resolved_type)) + return ira->codegen->invalid_instruction; // the logic below assumes there are no instructions in the new current basic block yet ir_assert(ira->new_irb.current_basic_block->instruction_list.length == 0, &phi_instruction->base); @@ -17346,20 +17778,32 @@ static IrInstruction *ir_analyze_instruction_phi(IrAnalyze *ira, IrInstructionPh } ZigType *resolved_type; - if (peer_parent != nullptr && ir_result_has_type(peer_parent->parent)) { - if (peer_parent->parent->id == ResultLocIdReturn) { - resolved_type = ira->explicit_return_type; - } else { - ZigType *resolved_loc_ptr_type = peer_parent->parent->resolved_loc->value.type; - ir_assert(resolved_loc_ptr_type->id == ZigTypeIdPointer, &phi_instruction->base); - resolved_type = resolved_loc_ptr_type->data.pointer.child_type; + if (peer_parent != nullptr) { + bool peer_parent_has_type; + if ((err = ir_result_has_type(ira, peer_parent->parent, &peer_parent_has_type))) + return ira->codegen->invalid_instruction; + if (peer_parent_has_type) { + if (peer_parent->parent->id == ResultLocIdReturn) { + resolved_type = ira->explicit_return_type; + } else if (peer_parent->parent->id == ResultLocIdCast) { + resolved_type = ir_resolve_type(ira, peer_parent->parent->source_instruction->child); + if (type_is_invalid(resolved_type)) + return ira->codegen->invalid_instruction; + } else { + ZigType *resolved_loc_ptr_type = peer_parent->parent->resolved_loc->value.type; + ir_assert(resolved_loc_ptr_type->id == ZigTypeIdPointer, &phi_instruction->base); + resolved_type = resolved_loc_ptr_type->data.pointer.child_type; + } + goto skip_resolve_peer_types; } - } else { + } + { resolved_type = ir_resolve_peer_types(ira, phi_instruction->base.source_node, nullptr, new_incoming_values.items, new_incoming_values.length); if (type_is_invalid(resolved_type)) return ira->codegen->invalid_instruction; } +skip_resolve_peer_types: switch (type_has_one_possible_value(ira->codegen, resolved_type)) { case OnePossibleValueInvalid: @@ -17449,7 +17893,7 @@ static ZigType *adjust_ptr_align(CodeGen *g, ZigType *ptr_type, uint32_t new_ali static ZigType *adjust_slice_align(CodeGen *g, ZigType *slice_type, uint32_t new_align) { assert(is_slice(slice_type)); - ZigType *ptr_type = adjust_ptr_align(g, slice_type->data.structure.fields[slice_ptr_index].type_entry, + ZigType *ptr_type = adjust_ptr_align(g, slice_type->data.structure.fields[slice_ptr_index]->type_entry, new_align); return get_slice_type(g, ptr_type); } @@ -17535,7 +17979,7 @@ static IrInstruction *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruct } return_type = adjust_ptr_len(ira->codegen, array_type, elem_ptr_instruction->ptr_len); } else if (is_slice(array_type)) { - return_type = adjust_ptr_len(ira->codegen, array_type->data.structure.fields[slice_ptr_index].type_entry, + return_type = adjust_ptr_len(ira->codegen, array_type->data.structure.fields[slice_ptr_index]->type_entry, elem_ptr_instruction->ptr_len); } else if (array_type->id == ZigTypeIdArgTuple) { ConstExprValue *ptr_val = ir_resolve_const(ira, array_ptr, UndefBad); @@ -17571,6 +18015,19 @@ static IrInstruction *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruct } else if (array_type->id == ZigTypeIdVector) { // This depends on whether the element index is comptime, so it is computed later. return_type = nullptr; + } else if (elem_ptr_instruction->init_array_type_source_node != nullptr && + array_type->id == ZigTypeIdStruct && + array_type->data.structure.resolve_status == ResolveStatusBeingInferred) + { + ZigType *usize = ira->codegen->builtin_types.entry_usize; + IrInstruction *casted_elem_index = ir_implicit_cast(ira, elem_index, usize); + if (casted_elem_index == ira->codegen->invalid_instruction) + return ira->codegen->invalid_instruction; + ir_assert(instr_is_comptime(casted_elem_index), &elem_ptr_instruction->base); + Buf *field_name = buf_alloc(); + bigint_append_buf(field_name, &casted_elem_index->value.data.x_bigint, 10); + return ir_analyze_inferred_field_ptr(ira, field_name, &elem_ptr_instruction->base, + array_ptr, array_type); } else { ir_add_error_node(ira, elem_ptr_instruction->base.source_node, buf_sprintf("array access of non-array type '%s'", buf_ptr(&array_type->name))); @@ -17601,7 +18058,8 @@ static IrInstruction *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruct return_type = get_pointer_to_type_extra2(ira->codegen, elem_type, ptr_type->data.pointer.is_const, ptr_type->data.pointer.is_volatile, elem_ptr_instruction->ptr_len, - get_ptr_align(ira->codegen, ptr_type), 0, host_vec_len, false, (uint32_t)index); + get_ptr_align(ira->codegen, ptr_type), 0, host_vec_len, false, (uint32_t)index, + nullptr); } else if (return_type->data.pointer.explicit_alignment != 0) { // figure out the largest alignment possible @@ -17639,7 +18097,9 @@ static IrInstruction *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruct if (array_ptr_val == nullptr) return ira->codegen->invalid_instruction; - if (array_ptr_val->special == ConstValSpecialUndef && elem_ptr_instruction->init_array_type != nullptr) { + if (array_ptr_val->special == ConstValSpecialUndef && + elem_ptr_instruction->init_array_type_source_node != nullptr) + { if (array_type->id == ZigTypeIdArray || array_type->id == ZigTypeIdVector) { array_ptr_val->data.x_array.special = ConstArraySpecialNone; array_ptr_val->data.x_array.data.s_none.elements = create_const_vals(array_type->data.array.len); @@ -17653,11 +18113,13 @@ static IrInstruction *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruct elem_val->parent.data.p_array.elem_index = i; } } else if (is_slice(array_type)) { - ZigType *actual_array_type = ir_resolve_type(ira, elem_ptr_instruction->init_array_type->child); + ir_assert(array_ptr->value.type->id == ZigTypeIdPointer, &elem_ptr_instruction->base); + ZigType *actual_array_type = array_ptr->value.type->data.pointer.child_type; + if (type_is_invalid(actual_array_type)) return ira->codegen->invalid_instruction; if (actual_array_type->id != ZigTypeIdArray) { - ir_add_error(ira, elem_ptr_instruction->init_array_type, + ir_add_error_node(ira, elem_ptr_instruction->init_array_type_source_node, buf_sprintf("expected array type or [_], found slice")); return ira->codegen->invalid_instruction; } @@ -17679,9 +18141,9 @@ static IrInstruction *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruct init_const_slice(ira->codegen, array_ptr_val, array_init_val, 0, actual_array_type->data.array.len, false); - array_ptr_val->data.x_struct.fields[slice_ptr_index].data.x_ptr.mut = ConstPtrMutInfer; + array_ptr_val->data.x_struct.fields[slice_ptr_index]->data.x_ptr.mut = ConstPtrMutInfer; } else { - ir_add_error(ira, elem_ptr_instruction->init_array_type, + ir_add_error_node(ira, elem_ptr_instruction->init_array_type_source_node, buf_sprintf("expected array type or [_], found '%s'", buf_ptr(&array_type->name))); return ira->codegen->invalid_instruction; @@ -17751,7 +18213,7 @@ static IrInstruction *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruct } return result; } else if (is_slice(array_type)) { - ConstExprValue *ptr_field = &array_ptr_val->data.x_struct.fields[slice_ptr_index]; + ConstExprValue *ptr_field = array_ptr_val->data.x_struct.fields[slice_ptr_index]; ir_assert(ptr_field != nullptr, &elem_ptr_instruction->base); if (ptr_field->data.x_ptr.special == ConstPtrSpecialHardCodedAddr) { IrInstruction *result = ir_build_elem_ptr(&ira->new_irb, elem_ptr_instruction->base.scope, @@ -17760,7 +18222,7 @@ static IrInstruction *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruct result->value.type = return_type; return result; } - ConstExprValue *len_field = &array_ptr_val->data.x_struct.fields[slice_len_index]; + ConstExprValue *len_field = array_ptr_val->data.x_struct.fields[slice_len_index]; IrInstruction *result = ir_const(ira, &elem_ptr_instruction->base, return_type); ConstExprValue *out_val = &result->value; uint64_t slice_len = bigint_as_u64(&len_field->data.x_bigint); @@ -17814,7 +18276,7 @@ static IrInstruction *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruct if (orig_array_ptr_val->data.x_ptr.mut == ConstPtrMutInfer) { result = ir_build_elem_ptr(&ira->new_irb, elem_ptr_instruction->base.scope, elem_ptr_instruction->base.source_node, array_ptr, casted_elem_index, - false, elem_ptr_instruction->ptr_len, elem_ptr_instruction->init_array_type); + false, elem_ptr_instruction->ptr_len, nullptr); result->value.type = return_type; result->value.special = ConstValSpecialStatic; } else { @@ -17838,7 +18300,8 @@ static IrInstruction *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruct return_type = get_pointer_to_type_extra2(ira->codegen, elem_type, ptr_type->data.pointer.is_const, ptr_type->data.pointer.is_volatile, elem_ptr_instruction->ptr_len, - get_ptr_align(ira->codegen, ptr_type), 0, host_vec_len, false, VECTOR_INDEX_RUNTIME); + get_ptr_align(ira->codegen, ptr_type), 0, host_vec_len, false, VECTOR_INDEX_RUNTIME, + nullptr); } else { // runtime known element index switch (type_requires_comptime(ira->codegen, return_type)) { @@ -17875,7 +18338,7 @@ static IrInstruction *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruct IrInstruction *result = ir_build_elem_ptr(&ira->new_irb, elem_ptr_instruction->base.scope, elem_ptr_instruction->base.source_node, array_ptr, casted_elem_index, safety_check_on, - elem_ptr_instruction->ptr_len, elem_ptr_instruction->init_array_type); + elem_ptr_instruction->ptr_len, nullptr); result->value.type = return_type; return result; } @@ -17954,43 +18417,47 @@ static IrInstruction *ir_analyze_struct_field_ptr(IrAnalyze *ira, IrInstruction case OnePossibleValueNo: break; } - ResolveStatus needed_resolve_status = - (struct_type->data.structure.layout == ContainerLayoutAuto) ? - ResolveStatusZeroBitsKnown : ResolveStatusSizeKnown; - if ((err = type_resolve(ira->codegen, struct_type, needed_resolve_status))) - return ira->codegen->invalid_instruction; - assert(struct_ptr->value.type->id == ZigTypeIdPointer); - uint32_t ptr_bit_offset = struct_ptr->value.type->data.pointer.bit_offset_in_host; - uint32_t ptr_host_int_bytes = struct_ptr->value.type->data.pointer.host_int_bytes; - uint32_t host_int_bytes_for_result_type = (ptr_host_int_bytes == 0) ? - get_host_int_bytes(ira->codegen, struct_type, field) : ptr_host_int_bytes; bool is_const = struct_ptr->value.type->data.pointer.is_const; bool is_volatile = struct_ptr->value.type->data.pointer.is_volatile; - ZigType *ptr_type = get_pointer_to_type_extra(ira->codegen, field_type, - is_const, is_volatile, PtrLenSingle, field->align, - (uint32_t)(ptr_bit_offset + field->bit_offset_in_host), - (uint32_t)host_int_bytes_for_result_type, false); + ZigType *ptr_type; + if (struct_type->data.structure.is_inferred) { + ptr_type = get_pointer_to_type_extra(ira->codegen, field_type, + is_const, is_volatile, PtrLenSingle, 0, 0, 0, false); + } else { + ResolveStatus needed_resolve_status = + (struct_type->data.structure.layout == ContainerLayoutAuto) ? + ResolveStatusZeroBitsKnown : ResolveStatusSizeKnown; + if ((err = type_resolve(ira->codegen, struct_type, needed_resolve_status))) + return ira->codegen->invalid_instruction; + assert(struct_ptr->value.type->id == ZigTypeIdPointer); + uint32_t ptr_bit_offset = struct_ptr->value.type->data.pointer.bit_offset_in_host; + uint32_t ptr_host_int_bytes = struct_ptr->value.type->data.pointer.host_int_bytes; + uint32_t host_int_bytes_for_result_type = (ptr_host_int_bytes == 0) ? + get_host_int_bytes(ira->codegen, struct_type, field) : ptr_host_int_bytes; + ptr_type = get_pointer_to_type_extra(ira->codegen, field_type, + is_const, is_volatile, PtrLenSingle, field->align, + (uint32_t)(ptr_bit_offset + field->bit_offset_in_host), + (uint32_t)host_int_bytes_for_result_type, false); + } if (instr_is_comptime(struct_ptr)) { ConstExprValue *ptr_val = ir_resolve_const(ira, struct_ptr, UndefBad); if (!ptr_val) return ira->codegen->invalid_instruction; if (ptr_val->data.x_ptr.special != ConstPtrSpecialHardCodedAddr) { - if ((err = type_resolve(ira->codegen, struct_type, ResolveStatusSizeKnown))) - return ira->codegen->invalid_instruction; - ConstExprValue *struct_val = const_ptr_pointee(ira, ira->codegen, ptr_val, source_instr->source_node); if (struct_val == nullptr) return ira->codegen->invalid_instruction; if (type_is_invalid(struct_val->type)) return ira->codegen->invalid_instruction; if (initializing && struct_val->special == ConstValSpecialUndef) { - struct_val->data.x_struct.fields = create_const_vals(struct_type->data.structure.src_field_count); + struct_val->data.x_struct.fields = alloc_const_vals_ptrs(struct_type->data.structure.src_field_count); struct_val->special = ConstValSpecialStatic; for (size_t i = 0; i < struct_type->data.structure.src_field_count; i += 1) { - ConstExprValue *field_val = &struct_val->data.x_struct.fields[i]; + ConstExprValue *field_val = struct_val->data.x_struct.fields[i]; field_val->special = ConstValSpecialUndef; - field_val->type = struct_type->data.structure.fields[i].type_entry; + field_val->type = resolve_struct_field_type(ira->codegen, + struct_type->data.structure.fields[i]); field_val->parent.id = ConstParentIdStruct; field_val->parent.data.p_struct.struct_val = struct_val; field_val->parent.data.p_struct.field_index = i; @@ -18019,12 +18486,53 @@ static IrInstruction *ir_analyze_struct_field_ptr(IrAnalyze *ira, IrInstruction return result; } +static IrInstruction *ir_analyze_inferred_field_ptr(IrAnalyze *ira, Buf *field_name, + IrInstruction *source_instr, IrInstruction *container_ptr, ZigType *container_type) +{ + // The type of the field is not available until a store using this pointer happens. + // So, here we create a special pointer type which has the inferred struct type and + // field name encoded in the type. Later, when there is a store via this pointer, + // the field type will then be available, and the field will be added to the inferred + // struct. + + ZigType *container_ptr_type = container_ptr->value.type; + ir_assert(container_ptr_type->id == ZigTypeIdPointer, source_instr); + + InferredStructField *inferred_struct_field = allocate<InferredStructField>(1, "InferredStructField"); + inferred_struct_field->inferred_struct_type = container_type; + inferred_struct_field->field_name = field_name; + + ZigType *elem_type = ira->codegen->builtin_types.entry_var; + ZigType *field_ptr_type = get_pointer_to_type_extra2(ira->codegen, elem_type, + container_ptr_type->data.pointer.is_const, container_ptr_type->data.pointer.is_volatile, + PtrLenSingle, 0, 0, 0, false, VECTOR_INDEX_NONE, inferred_struct_field); + + if (instr_is_comptime(container_ptr)) { + IrInstruction *result = ir_const(ira, source_instr, field_ptr_type); + copy_const_val(&result->value, &container_ptr->value, false); + result->value.type = field_ptr_type; + return result; + } + + IrInstruction *result = ir_build_cast(&ira->new_irb, source_instr->scope, + source_instr->source_node, field_ptr_type, container_ptr, CastOpNoop); + result->value.type = field_ptr_type; + return result; +} + static IrInstruction *ir_analyze_container_field_ptr(IrAnalyze *ira, Buf *field_name, IrInstruction *source_instr, IrInstruction *container_ptr, ZigType *container_type, bool initializing) { Error err; ZigType *bare_type = container_ref_type(container_type); + + if (initializing && bare_type->id == ZigTypeIdStruct && + bare_type->data.structure.resolve_status == ResolveStatusBeingInferred) + { + return ir_analyze_inferred_field_ptr(ira, field_name, source_instr, container_ptr, bare_type); + } + if ((err = type_resolve(ira->codegen, bare_type, ResolveStatusZeroBitsKnown))) return ira->codegen->invalid_instruction; @@ -18065,7 +18573,8 @@ static IrInstruction *ir_analyze_container_field_ptr(IrAnalyze *ira, Buf *field_ if (!ptr_val) return ira->codegen->invalid_instruction; - if (ptr_val->data.x_ptr.special != ConstPtrSpecialHardCodedAddr) { + if (ptr_val->data.x_ptr.mut != ConstPtrMutRuntimeVar && + ptr_val->data.x_ptr.special != ConstPtrSpecialHardCodedAddr) { ConstExprValue *union_val = const_ptr_pointee(ira, ira->codegen, ptr_val, source_instr->source_node); if (union_val == nullptr) return ira->codegen->invalid_instruction; @@ -18097,7 +18606,6 @@ static IrInstruction *ir_analyze_container_field_ptr(IrAnalyze *ira, Buf *field_ ConstExprValue *payload_val = union_val->data.x_union.payload; - IrInstruction *result; if (ptr_val->data.x_ptr.mut == ConstPtrMutInfer) { result = ir_build_union_field_ptr(&ira->new_irb, source_instr->scope, @@ -19799,6 +20307,11 @@ static IrInstruction *ir_analyze_container_init_fields(IrAnalyze *ira, IrInstruc return ira->codegen->invalid_instruction; } + if (container_type->data.structure.resolve_status == ResolveStatusBeingInferred) { + // We're now done inferring the type. + container_type->data.structure.resolve_status = ResolveStatusUnstarted; + } + if ((err = type_resolve(ira->codegen, container_type, ResolveStatusSizeKnown))) return ira->codegen->invalid_instruction; @@ -19865,14 +20378,18 @@ static IrInstruction *ir_analyze_container_init_fields(IrAnalyze *ira, IrInstruc if (field_assign_nodes[i] != nullptr) continue; // look for a default field value - TypeStructField *field = &container_type->data.structure.fields[i]; + TypeStructField *field = container_type->data.structure.fields[i]; if (field->init_val == nullptr) { // it's not memoized. time to go analyze it - assert(field->decl_node->type == NodeTypeStructField); - AstNode *init_node = field->decl_node->data.struct_field.value; + AstNode *init_node; + if (field->decl_node->type == NodeTypeStructField) { + init_node = field->decl_node->data.struct_field.value; + } else { + init_node = nullptr; + } if (init_node == nullptr) { ir_add_error_node(ira, instruction->source_node, - buf_sprintf("missing field: '%s'", buf_ptr(container_type->data.structure.fields[i].name))); + buf_sprintf("missing field: '%s'", buf_ptr(container_type->data.structure.fields[i]->name))); any_missing = true; continue; } @@ -19926,14 +20443,18 @@ static IrInstruction *ir_analyze_container_init_fields(IrAnalyze *ira, IrInstruc static IrInstruction *ir_analyze_instruction_container_init_list(IrAnalyze *ira, IrInstructionContainerInitList *instruction) { - ZigType *container_type = ir_resolve_type(ira, instruction->container_type->child); - if (type_is_invalid(container_type)) - return ira->codegen->invalid_instruction; + ir_assert(instruction->result_loc != nullptr, &instruction->base); + IrInstruction *result_loc = instruction->result_loc->child; + if (type_is_invalid(result_loc->value.type)) + return result_loc; + ir_assert(result_loc->value.type->id == ZigTypeIdPointer, &instruction->base); + + ZigType *container_type = result_loc->value.type->data.pointer.child_type; size_t elem_count = instruction->item_count; if (is_slice(container_type)) { - ir_add_error(ira, instruction->container_type, + ir_add_error_node(ira, instruction->init_array_type_source_node, buf_sprintf("expected array type or [_], found slice")); return ira->codegen->invalid_instruction; } @@ -19955,29 +20476,28 @@ static IrInstruction *ir_analyze_instruction_container_init_list(IrAnalyze *ira, return ir_analyze_container_init_fields(ira, &instruction->base, container_type, 0, nullptr, result_loc); } - if (container_type->id != ZigTypeIdArray) { + if (container_type->id == ZigTypeIdArray) { + ZigType *child_type = container_type->data.array.child_type; + if (container_type->data.array.len != elem_count) { + ZigType *literal_type = get_array_type(ira->codegen, child_type, elem_count); + + ir_add_error(ira, &instruction->base, + buf_sprintf("expected %s literal, found %s literal", + buf_ptr(&container_type->name), buf_ptr(&literal_type->name))); + return ira->codegen->invalid_instruction; + } + } else if (container_type->id == ZigTypeIdStruct && + container_type->data.structure.resolve_status == ResolveStatusBeingInferred) + { + // We're now done inferring the type. + container_type->data.structure.resolve_status = ResolveStatusUnstarted; + } else { ir_add_error_node(ira, instruction->base.source_node, buf_sprintf("type '%s' does not support array initialization", buf_ptr(&container_type->name))); return ira->codegen->invalid_instruction; } - ir_assert(instruction->result_loc != nullptr, &instruction->base); - IrInstruction *result_loc = instruction->result_loc->child; - if (type_is_invalid(result_loc->value.type)) - return result_loc; - ir_assert(result_loc->value.type->id == ZigTypeIdPointer, &instruction->base); - - ZigType *child_type = container_type->data.array.child_type; - if (container_type->data.array.len != elem_count) { - ZigType *literal_type = get_array_type(ira->codegen, child_type, elem_count); - - ir_add_error(ira, &instruction->base, - buf_sprintf("expected %s literal, found %s literal", - buf_ptr(&container_type->name), buf_ptr(&literal_type->name))); - return ira->codegen->invalid_instruction; - } - switch (type_has_one_possible_value(ira->codegen, container_type)) { case OnePossibleValueInvalid: return ira->codegen->invalid_instruction; @@ -20064,16 +20584,14 @@ static IrInstruction *ir_analyze_instruction_container_init_list(IrAnalyze *ira, static IrInstruction *ir_analyze_instruction_container_init_fields(IrAnalyze *ira, IrInstructionContainerInitFields *instruction) { - IrInstruction *container_type_value = instruction->container_type->child; - ZigType *container_type = ir_resolve_type(ira, container_type_value); - if (type_is_invalid(container_type)) - return ira->codegen->invalid_instruction; - ir_assert(instruction->result_loc != nullptr, &instruction->base); IrInstruction *result_loc = instruction->result_loc->child; if (type_is_invalid(result_loc->value.type)) return result_loc; + ir_assert(result_loc->value.type->id == ZigTypeIdPointer, &instruction->base); + ZigType *container_type = result_loc->value.type->data.pointer.child_type; + return ir_analyze_container_init_fields(ira, &instruction->base, container_type, instruction->field_count, instruction->fields, result_loc); } @@ -20472,17 +20990,17 @@ static Error ir_make_type_info_decls(IrAnalyze *ira, IrInstruction *source_instr declaration_val->special = ConstValSpecialStatic; declaration_val->type = type_info_declaration_type; - ConstExprValue *inner_fields = create_const_vals(3); + ConstExprValue **inner_fields = alloc_const_vals_ptrs(3); ConstExprValue *name = create_const_str_lit(ira->codegen, curr_entry->key); - init_const_slice(ira->codegen, &inner_fields[0], name, 0, buf_len(curr_entry->key), true); - inner_fields[1].special = ConstValSpecialStatic; - inner_fields[1].type = ira->codegen->builtin_types.entry_bool; - inner_fields[1].data.x_bool = curr_entry->value->visib_mod == VisibModPub; - inner_fields[2].special = ConstValSpecialStatic; - inner_fields[2].type = type_info_declaration_data_type; - inner_fields[2].parent.id = ConstParentIdStruct; - inner_fields[2].parent.data.p_struct.struct_val = declaration_val; - inner_fields[2].parent.data.p_struct.field_index = 1; + init_const_slice(ira->codegen, inner_fields[0], name, 0, buf_len(curr_entry->key), true); + inner_fields[1]->special = ConstValSpecialStatic; + inner_fields[1]->type = ira->codegen->builtin_types.entry_bool; + inner_fields[1]->data.x_bool = curr_entry->value->visib_mod == VisibModPub; + inner_fields[2]->special = ConstValSpecialStatic; + inner_fields[2]->type = type_info_declaration_data_type; + inner_fields[2]->parent.id = ConstParentIdStruct; + inner_fields[2]->parent.data.p_struct.struct_val = declaration_val; + inner_fields[2]->parent.data.p_struct.field_index = 1; switch (curr_entry->value->id) { case TldIdVar: @@ -20494,19 +21012,19 @@ static Error ir_make_type_info_decls(IrAnalyze *ira, IrInstruction *source_instr if (var->const_value->type->id == ZigTypeIdMetaType) { // We have a variable of type 'type', so it's actually a type declaration. // 0: Data.Type: type - bigint_init_unsigned(&inner_fields[2].data.x_union.tag, 0); - inner_fields[2].data.x_union.payload = var->const_value; + bigint_init_unsigned(&inner_fields[2]->data.x_union.tag, 0); + inner_fields[2]->data.x_union.payload = var->const_value; } else { // We have a variable of another type, so we store the type of the variable. // 1: Data.Var: type - bigint_init_unsigned(&inner_fields[2].data.x_union.tag, 1); + bigint_init_unsigned(&inner_fields[2]->data.x_union.tag, 1); ConstExprValue *payload = create_const_vals(1); payload->special = ConstValSpecialStatic; payload->type = ira->codegen->builtin_types.entry_type; payload->data.x_type = var->const_value->type; - inner_fields[2].data.x_union.payload = payload; + inner_fields[2]->data.x_union.payload = payload; } break; @@ -20514,7 +21032,7 @@ static Error ir_make_type_info_decls(IrAnalyze *ira, IrInstruction *source_instr case TldIdFn: { // 2: Data.Fn: Data.FnDecl - bigint_init_unsigned(&inner_fields[2].data.x_union.tag, 2); + bigint_init_unsigned(&inner_fields[2]->data.x_union.tag, 2); ZigFn *fn_entry = ((TldFn *)curr_entry->value)->fn_entry; assert(!fn_entry->is_test); @@ -20530,63 +21048,63 @@ static Error ir_make_type_info_decls(IrAnalyze *ira, IrInstruction *source_instr fn_decl_val->special = ConstValSpecialStatic; fn_decl_val->type = type_info_fn_decl_type; fn_decl_val->parent.id = ConstParentIdUnion; - fn_decl_val->parent.data.p_union.union_val = &inner_fields[2]; + fn_decl_val->parent.data.p_union.union_val = inner_fields[2]; - ConstExprValue *fn_decl_fields = create_const_vals(9); + ConstExprValue **fn_decl_fields = alloc_const_vals_ptrs(9); fn_decl_val->data.x_struct.fields = fn_decl_fields; // fn_type: type ensure_field_index(fn_decl_val->type, "fn_type", 0); - fn_decl_fields[0].special = ConstValSpecialStatic; - fn_decl_fields[0].type = ira->codegen->builtin_types.entry_type; - fn_decl_fields[0].data.x_type = fn_entry->type_entry; + fn_decl_fields[0]->special = ConstValSpecialStatic; + fn_decl_fields[0]->type = ira->codegen->builtin_types.entry_type; + fn_decl_fields[0]->data.x_type = fn_entry->type_entry; // inline_type: Data.FnDecl.Inline ensure_field_index(fn_decl_val->type, "inline_type", 1); - fn_decl_fields[1].special = ConstValSpecialStatic; - fn_decl_fields[1].type = type_info_fn_decl_inline_type; - bigint_init_unsigned(&fn_decl_fields[1].data.x_enum_tag, fn_entry->fn_inline); + fn_decl_fields[1]->special = ConstValSpecialStatic; + fn_decl_fields[1]->type = type_info_fn_decl_inline_type; + bigint_init_unsigned(&fn_decl_fields[1]->data.x_enum_tag, fn_entry->fn_inline); // calling_convention: TypeInfo.CallingConvention ensure_field_index(fn_decl_val->type, "calling_convention", 2); - fn_decl_fields[2].special = ConstValSpecialStatic; - fn_decl_fields[2].type = ir_type_info_get_type(ira, "CallingConvention", nullptr); - bigint_init_unsigned(&fn_decl_fields[2].data.x_enum_tag, fn_node->cc); + fn_decl_fields[2]->special = ConstValSpecialStatic; + fn_decl_fields[2]->type = ir_type_info_get_type(ira, "CallingConvention", nullptr); + bigint_init_unsigned(&fn_decl_fields[2]->data.x_enum_tag, fn_node->cc); // is_var_args: bool ensure_field_index(fn_decl_val->type, "is_var_args", 3); bool is_varargs = fn_node->is_var_args; - fn_decl_fields[3].special = ConstValSpecialStatic; - fn_decl_fields[3].type = ira->codegen->builtin_types.entry_bool; - fn_decl_fields[3].data.x_bool = is_varargs; + fn_decl_fields[3]->special = ConstValSpecialStatic; + fn_decl_fields[3]->type = ira->codegen->builtin_types.entry_bool; + fn_decl_fields[3]->data.x_bool = is_varargs; // is_extern: bool ensure_field_index(fn_decl_val->type, "is_extern", 4); - fn_decl_fields[4].special = ConstValSpecialStatic; - fn_decl_fields[4].type = ira->codegen->builtin_types.entry_bool; - fn_decl_fields[4].data.x_bool = fn_node->is_extern; + fn_decl_fields[4]->special = ConstValSpecialStatic; + fn_decl_fields[4]->type = ira->codegen->builtin_types.entry_bool; + fn_decl_fields[4]->data.x_bool = fn_node->is_extern; // is_export: bool ensure_field_index(fn_decl_val->type, "is_export", 5); - fn_decl_fields[5].special = ConstValSpecialStatic; - fn_decl_fields[5].type = ira->codegen->builtin_types.entry_bool; - fn_decl_fields[5].data.x_bool = fn_node->is_export; + fn_decl_fields[5]->special = ConstValSpecialStatic; + fn_decl_fields[5]->type = ira->codegen->builtin_types.entry_bool; + fn_decl_fields[5]->data.x_bool = fn_node->is_export; // lib_name: ?[]const u8 ensure_field_index(fn_decl_val->type, "lib_name", 6); - fn_decl_fields[6].special = ConstValSpecialStatic; + fn_decl_fields[6]->special = ConstValSpecialStatic; ZigType *u8_ptr = get_pointer_to_type_extra( ira->codegen, ira->codegen->builtin_types.entry_u8, true, false, PtrLenUnknown, 0, 0, 0, false); - fn_decl_fields[6].type = get_optional_type(ira->codegen, get_slice_type(ira->codegen, u8_ptr)); + fn_decl_fields[6]->type = get_optional_type(ira->codegen, get_slice_type(ira->codegen, u8_ptr)); if (fn_node->is_extern && fn_node->lib_name != nullptr && buf_len(fn_node->lib_name) > 0) { - fn_decl_fields[6].data.x_optional = create_const_vals(1); + fn_decl_fields[6]->data.x_optional = create_const_vals(1); ConstExprValue *lib_name = create_const_str_lit(ira->codegen, fn_node->lib_name); - init_const_slice(ira->codegen, fn_decl_fields[6].data.x_optional, lib_name, 0, + init_const_slice(ira->codegen, fn_decl_fields[6]->data.x_optional, lib_name, 0, buf_len(fn_node->lib_name), true); } else { - fn_decl_fields[6].data.x_optional = nullptr; + fn_decl_fields[6]->data.x_optional = nullptr; } // return_type: type ensure_field_index(fn_decl_val->type, "return_type", 7); - fn_decl_fields[7].special = ConstValSpecialStatic; - fn_decl_fields[7].type = ira->codegen->builtin_types.entry_type; - fn_decl_fields[7].data.x_type = fn_entry->type_entry->data.fn.fn_type_id.return_type; + fn_decl_fields[7]->special = ConstValSpecialStatic; + fn_decl_fields[7]->type = ira->codegen->builtin_types.entry_type; + fn_decl_fields[7]->data.x_type = fn_entry->type_entry->data.fn.fn_type_id.return_type; // arg_names: [][] const u8 ensure_field_index(fn_decl_val->type, "arg_names", 8); size_t fn_arg_count = fn_entry->variable_list.length; @@ -20597,7 +21115,7 @@ static Error ir_make_type_info_decls(IrAnalyze *ira, IrInstruction *source_instr fn_arg_name_array->data.x_array.special = ConstArraySpecialNone; fn_arg_name_array->data.x_array.data.s_none.elements = create_const_vals(fn_arg_count); - init_const_slice(ira->codegen, &fn_decl_fields[8], fn_arg_name_array, 0, fn_arg_count, false); + init_const_slice(ira->codegen, fn_decl_fields[8], fn_arg_name_array, 0, fn_arg_count, false); for (size_t fn_arg_index = 0; fn_arg_index < fn_arg_count; fn_arg_index++) { ZigVar *arg_var = fn_entry->variable_list.at(fn_arg_index); @@ -20610,7 +21128,7 @@ static Error ir_make_type_info_decls(IrAnalyze *ira, IrInstruction *source_instr fn_arg_name_val->parent.data.p_array.elem_index = fn_arg_index; } - inner_fields[2].data.x_union.payload = fn_decl_val; + inner_fields[2]->data.x_union.payload = fn_decl_val; break; } case TldIdContainer: @@ -20620,14 +21138,14 @@ static Error ir_make_type_info_decls(IrAnalyze *ira, IrInstruction *source_instr return ErrorSemanticAnalyzeFail; // This is a type. - bigint_init_unsigned(&inner_fields[2].data.x_union.tag, 0); + bigint_init_unsigned(&inner_fields[2]->data.x_union.tag, 0); ConstExprValue *payload = create_const_vals(1); payload->special = ConstValSpecialStatic; payload->type = ira->codegen->builtin_types.entry_type; payload->data.x_type = type_entry; - inner_fields[2].data.x_union.payload = payload; + inner_fields[2]->data.x_union.payload = payload; break; } @@ -20636,7 +21154,7 @@ static Error ir_make_type_info_decls(IrAnalyze *ira, IrInstruction *source_instr } declaration_val->data.x_struct.fields = inner_fields; - declaration_index++; + declaration_index += 1; } assert(declaration_index == declaration_count); @@ -20673,7 +21191,7 @@ static ConstExprValue *create_ptr_like_type_info(IrAnalyze *ira, ZigType *ptr_ty ZigType *attrs_type; BuiltinPtrSize size_enum_index; if (is_slice(ptr_type_entry)) { - attrs_type = ptr_type_entry->data.structure.fields[slice_ptr_index].type_entry; + attrs_type = ptr_type_entry->data.structure.fields[slice_ptr_index]->type_entry; size_enum_index = BuiltinPtrSizeSlice; } else if (ptr_type_entry->id == ZigTypeIdPointer) { attrs_type = ptr_type_entry; @@ -20692,42 +21210,42 @@ static ConstExprValue *create_ptr_like_type_info(IrAnalyze *ira, ZigType *ptr_ty result->special = ConstValSpecialStatic; result->type = type_info_pointer_type; - ConstExprValue *fields = create_const_vals(6); + ConstExprValue **fields = alloc_const_vals_ptrs(6); result->data.x_struct.fields = fields; // size: Size ensure_field_index(result->type, "size", 0); ZigType *type_info_pointer_size_type = ir_type_info_get_type(ira, "Size", type_info_pointer_type); assertNoError(type_resolve(ira->codegen, type_info_pointer_size_type, ResolveStatusSizeKnown)); - fields[0].special = ConstValSpecialStatic; - fields[0].type = type_info_pointer_size_type; - bigint_init_unsigned(&fields[0].data.x_enum_tag, size_enum_index); + fields[0]->special = ConstValSpecialStatic; + fields[0]->type = type_info_pointer_size_type; + bigint_init_unsigned(&fields[0]->data.x_enum_tag, size_enum_index); // is_const: bool ensure_field_index(result->type, "is_const", 1); - fields[1].special = ConstValSpecialStatic; - fields[1].type = ira->codegen->builtin_types.entry_bool; - fields[1].data.x_bool = attrs_type->data.pointer.is_const; + fields[1]->special = ConstValSpecialStatic; + fields[1]->type = ira->codegen->builtin_types.entry_bool; + fields[1]->data.x_bool = attrs_type->data.pointer.is_const; // is_volatile: bool ensure_field_index(result->type, "is_volatile", 2); - fields[2].special = ConstValSpecialStatic; - fields[2].type = ira->codegen->builtin_types.entry_bool; - fields[2].data.x_bool = attrs_type->data.pointer.is_volatile; + fields[2]->special = ConstValSpecialStatic; + fields[2]->type = ira->codegen->builtin_types.entry_bool; + fields[2]->data.x_bool = attrs_type->data.pointer.is_volatile; // alignment: u32 ensure_field_index(result->type, "alignment", 3); - fields[3].special = ConstValSpecialStatic; - fields[3].type = ira->codegen->builtin_types.entry_num_lit_int; - bigint_init_unsigned(&fields[3].data.x_bigint, get_ptr_align(ira->codegen, attrs_type)); + fields[3]->special = ConstValSpecialStatic; + fields[3]->type = ira->codegen->builtin_types.entry_num_lit_int; + bigint_init_unsigned(&fields[3]->data.x_bigint, get_ptr_align(ira->codegen, attrs_type)); // child: type ensure_field_index(result->type, "child", 4); - fields[4].special = ConstValSpecialStatic; - fields[4].type = ira->codegen->builtin_types.entry_type; - fields[4].data.x_type = attrs_type->data.pointer.child_type; + fields[4]->special = ConstValSpecialStatic; + fields[4]->type = ira->codegen->builtin_types.entry_type; + fields[4]->data.x_type = attrs_type->data.pointer.child_type; // is_allowzero: bool ensure_field_index(result->type, "is_allowzero", 5); - fields[5].special = ConstValSpecialStatic; - fields[5].type = ira->codegen->builtin_types.entry_bool; - fields[5].data.x_bool = attrs_type->data.pointer.allow_zero; + fields[5]->special = ConstValSpecialStatic; + fields[5]->type = ira->codegen->builtin_types.entry_bool; + fields[5]->data.x_bool = attrs_type->data.pointer.allow_zero; return result; }; @@ -20738,14 +21256,14 @@ static void make_enum_field_val(IrAnalyze *ira, ConstExprValue *enum_field_val, enum_field_val->special = ConstValSpecialStatic; enum_field_val->type = type_info_enum_field_type; - ConstExprValue *inner_fields = create_const_vals(2); - inner_fields[1].special = ConstValSpecialStatic; - inner_fields[1].type = ira->codegen->builtin_types.entry_num_lit_int; + ConstExprValue **inner_fields = alloc_const_vals_ptrs(2); + inner_fields[1]->special = ConstValSpecialStatic; + inner_fields[1]->type = ira->codegen->builtin_types.entry_num_lit_int; ConstExprValue *name = create_const_str_lit(ira->codegen, enum_field->name); - init_const_slice(ira->codegen, &inner_fields[0], name, 0, buf_len(enum_field->name), true); + init_const_slice(ira->codegen, inner_fields[0], name, 0, buf_len(enum_field->name), true); - bigint_init_bigint(&inner_fields[1].data.x_bigint, &enum_field->value); + bigint_init_bigint(&inner_fields[1]->data.x_bigint, &enum_field->value); enum_field_val->data.x_struct.fields = inner_fields; } @@ -20789,19 +21307,19 @@ static Error ir_make_type_info_value(IrAnalyze *ira, IrInstruction *source_instr result->special = ConstValSpecialStatic; result->type = ir_type_info_get_type(ira, "Int", nullptr); - ConstExprValue *fields = create_const_vals(2); + ConstExprValue **fields = alloc_const_vals_ptrs(2); result->data.x_struct.fields = fields; // is_signed: bool ensure_field_index(result->type, "is_signed", 0); - fields[0].special = ConstValSpecialStatic; - fields[0].type = ira->codegen->builtin_types.entry_bool; - fields[0].data.x_bool = type_entry->data.integral.is_signed; + fields[0]->special = ConstValSpecialStatic; + fields[0]->type = ira->codegen->builtin_types.entry_bool; + fields[0]->data.x_bool = type_entry->data.integral.is_signed; // bits: u8 ensure_field_index(result->type, "bits", 1); - fields[1].special = ConstValSpecialStatic; - fields[1].type = ira->codegen->builtin_types.entry_num_lit_int; - bigint_init_unsigned(&fields[1].data.x_bigint, type_entry->data.integral.bit_count); + fields[1]->special = ConstValSpecialStatic; + fields[1]->type = ira->codegen->builtin_types.entry_num_lit_int; + bigint_init_unsigned(&fields[1]->data.x_bigint, type_entry->data.integral.bit_count); break; } @@ -20811,14 +21329,14 @@ static Error ir_make_type_info_value(IrAnalyze *ira, IrInstruction *source_instr result->special = ConstValSpecialStatic; result->type = ir_type_info_get_type(ira, "Float", nullptr); - ConstExprValue *fields = create_const_vals(1); + ConstExprValue **fields = alloc_const_vals_ptrs(1); result->data.x_struct.fields = fields; // bits: u8 ensure_field_index(result->type, "bits", 0); - fields[0].special = ConstValSpecialStatic; - fields[0].type = ira->codegen->builtin_types.entry_num_lit_int; - bigint_init_unsigned(&fields->data.x_bigint, type_entry->data.floating.bit_count); + fields[0]->special = ConstValSpecialStatic; + fields[0]->type = ira->codegen->builtin_types.entry_num_lit_int; + bigint_init_unsigned(&fields[0]->data.x_bigint, type_entry->data.floating.bit_count); break; } @@ -20835,19 +21353,19 @@ static Error ir_make_type_info_value(IrAnalyze *ira, IrInstruction *source_instr result->special = ConstValSpecialStatic; result->type = ir_type_info_get_type(ira, "Array", nullptr); - ConstExprValue *fields = create_const_vals(2); + ConstExprValue **fields = alloc_const_vals_ptrs(2); result->data.x_struct.fields = fields; // len: usize ensure_field_index(result->type, "len", 0); - fields[0].special = ConstValSpecialStatic; - fields[0].type = ira->codegen->builtin_types.entry_num_lit_int; - bigint_init_unsigned(&fields[0].data.x_bigint, type_entry->data.array.len); + fields[0]->special = ConstValSpecialStatic; + fields[0]->type = ira->codegen->builtin_types.entry_num_lit_int; + bigint_init_unsigned(&fields[0]->data.x_bigint, type_entry->data.array.len); // child: type ensure_field_index(result->type, "child", 1); - fields[1].special = ConstValSpecialStatic; - fields[1].type = ira->codegen->builtin_types.entry_type; - fields[1].data.x_type = type_entry->data.array.child_type; + fields[1]->special = ConstValSpecialStatic; + fields[1]->type = ira->codegen->builtin_types.entry_type; + fields[1]->data.x_type = type_entry->data.array.child_type; break; } @@ -20856,19 +21374,19 @@ static Error ir_make_type_info_value(IrAnalyze *ira, IrInstruction *source_instr result->special = ConstValSpecialStatic; result->type = ir_type_info_get_type(ira, "Vector", nullptr); - ConstExprValue *fields = create_const_vals(2); + ConstExprValue **fields = alloc_const_vals_ptrs(2); result->data.x_struct.fields = fields; // len: usize ensure_field_index(result->type, "len", 0); - fields[0].special = ConstValSpecialStatic; - fields[0].type = ira->codegen->builtin_types.entry_num_lit_int; - bigint_init_unsigned(&fields[0].data.x_bigint, type_entry->data.vector.len); + fields[0]->special = ConstValSpecialStatic; + fields[0]->type = ira->codegen->builtin_types.entry_num_lit_int; + bigint_init_unsigned(&fields[0]->data.x_bigint, type_entry->data.vector.len); // child: type ensure_field_index(result->type, "child", 1); - fields[1].special = ConstValSpecialStatic; - fields[1].type = ira->codegen->builtin_types.entry_type; - fields[1].data.x_type = type_entry->data.vector.elem_type; + fields[1]->special = ConstValSpecialStatic; + fields[1]->type = ira->codegen->builtin_types.entry_type; + fields[1]->data.x_type = type_entry->data.vector.elem_type; break; } @@ -20878,14 +21396,14 @@ static Error ir_make_type_info_value(IrAnalyze *ira, IrInstruction *source_instr result->special = ConstValSpecialStatic; result->type = ir_type_info_get_type(ira, "Optional", nullptr); - ConstExprValue *fields = create_const_vals(1); + ConstExprValue **fields = alloc_const_vals_ptrs(1); result->data.x_struct.fields = fields; // child: type ensure_field_index(result->type, "child", 0); - fields[0].special = ConstValSpecialStatic; - fields[0].type = ira->codegen->builtin_types.entry_type; - fields[0].data.x_type = type_entry->data.maybe.child_type; + fields[0]->special = ConstValSpecialStatic; + fields[0]->type = ira->codegen->builtin_types.entry_type; + fields[0]->data.x_type = type_entry->data.maybe.child_type; break; } @@ -20894,14 +21412,14 @@ static Error ir_make_type_info_value(IrAnalyze *ira, IrInstruction *source_instr result->special = ConstValSpecialStatic; result->type = ir_type_info_get_type(ira, "AnyFrame", nullptr); - ConstExprValue *fields = create_const_vals(1); + ConstExprValue **fields = alloc_const_vals_ptrs(1); result->data.x_struct.fields = fields; // child: ?type ensure_field_index(result->type, "child", 0); - fields[0].special = ConstValSpecialStatic; - fields[0].type = get_optional_type(ira->codegen, ira->codegen->builtin_types.entry_type); - fields[0].data.x_optional = (type_entry->data.any_frame.result_type == nullptr) ? nullptr : + fields[0]->special = ConstValSpecialStatic; + fields[0]->type = get_optional_type(ira->codegen, ira->codegen->builtin_types.entry_type); + fields[0]->data.x_optional = (type_entry->data.any_frame.result_type == nullptr) ? nullptr : create_const_type(ira->codegen, type_entry->data.any_frame.result_type); break; } @@ -20911,19 +21429,19 @@ static Error ir_make_type_info_value(IrAnalyze *ira, IrInstruction *source_instr result->special = ConstValSpecialStatic; result->type = ir_type_info_get_type(ira, "Enum", nullptr); - ConstExprValue *fields = create_const_vals(4); + ConstExprValue **fields = alloc_const_vals_ptrs(4); result->data.x_struct.fields = fields; // layout: ContainerLayout ensure_field_index(result->type, "layout", 0); - fields[0].special = ConstValSpecialStatic; - fields[0].type = ir_type_info_get_type(ira, "ContainerLayout", nullptr); - bigint_init_unsigned(&fields[0].data.x_enum_tag, type_entry->data.enumeration.layout); + fields[0]->special = ConstValSpecialStatic; + fields[0]->type = ir_type_info_get_type(ira, "ContainerLayout", nullptr); + bigint_init_unsigned(&fields[0]->data.x_enum_tag, type_entry->data.enumeration.layout); // tag_type: type ensure_field_index(result->type, "tag_type", 1); - fields[1].special = ConstValSpecialStatic; - fields[1].type = ira->codegen->builtin_types.entry_type; - fields[1].data.x_type = type_entry->data.enumeration.tag_int_type; + fields[1]->special = ConstValSpecialStatic; + fields[1]->type = ira->codegen->builtin_types.entry_type; + fields[1]->data.x_type = type_entry->data.enumeration.tag_int_type; // fields: []TypeInfo.EnumField ensure_field_index(result->type, "fields", 2); @@ -20939,7 +21457,7 @@ static Error ir_make_type_info_value(IrAnalyze *ira, IrInstruction *source_instr enum_field_array->data.x_array.special = ConstArraySpecialNone; enum_field_array->data.x_array.data.s_none.elements = create_const_vals(enum_field_count); - init_const_slice(ira->codegen, &fields[2], enum_field_array, 0, enum_field_count, false); + init_const_slice(ira->codegen, fields[2], enum_field_array, 0, enum_field_count, false); for (uint32_t enum_field_index = 0; enum_field_index < enum_field_count; enum_field_index++) { @@ -20952,7 +21470,7 @@ static Error ir_make_type_info_value(IrAnalyze *ira, IrInstruction *source_instr } // decls: []TypeInfo.Declaration ensure_field_index(result->type, "decls", 3); - if ((err = ir_make_type_info_decls(ira, source_instr, &fields[3], + if ((err = ir_make_type_info_decls(ira, source_instr, fields[3], type_entry->data.enumeration.decls_scope))) { return err; @@ -20995,17 +21513,17 @@ static Error ir_make_type_info_value(IrAnalyze *ira, IrInstruction *source_instr error_val->special = ConstValSpecialStatic; error_val->type = type_info_error_type; - ConstExprValue *inner_fields = create_const_vals(2); - inner_fields[1].special = ConstValSpecialStatic; - inner_fields[1].type = ira->codegen->builtin_types.entry_num_lit_int; + ConstExprValue **inner_fields = alloc_const_vals_ptrs(2); + inner_fields[1]->special = ConstValSpecialStatic; + inner_fields[1]->type = ira->codegen->builtin_types.entry_num_lit_int; ConstExprValue *name = nullptr; if (error->cached_error_name_val != nullptr) name = error->cached_error_name_val; if (name == nullptr) name = create_const_str_lit(ira->codegen, &error->name); - init_const_slice(ira->codegen, &inner_fields[0], name, 0, buf_len(&error->name), true); - bigint_init_unsigned(&inner_fields[1].data.x_bigint, error->value); + init_const_slice(ira->codegen, inner_fields[0], name, 0, buf_len(&error->name), true); + bigint_init_unsigned(&inner_fields[1]->data.x_bigint, error->value); error_val->data.x_struct.fields = inner_fields; error_val->parent.id = ConstParentIdArray; @@ -21021,20 +21539,20 @@ static Error ir_make_type_info_value(IrAnalyze *ira, IrInstruction *source_instr result->special = ConstValSpecialStatic; result->type = ir_type_info_get_type(ira, "ErrorUnion", nullptr); - ConstExprValue *fields = create_const_vals(2); + ConstExprValue **fields = alloc_const_vals_ptrs(2); result->data.x_struct.fields = fields; // error_set: type ensure_field_index(result->type, "error_set", 0); - fields[0].special = ConstValSpecialStatic; - fields[0].type = ira->codegen->builtin_types.entry_type; - fields[0].data.x_type = type_entry->data.error_union.err_set_type; + fields[0]->special = ConstValSpecialStatic; + fields[0]->type = ira->codegen->builtin_types.entry_type; + fields[0]->data.x_type = type_entry->data.error_union.err_set_type; // payload: type ensure_field_index(result->type, "payload", 1); - fields[1].special = ConstValSpecialStatic; - fields[1].type = ira->codegen->builtin_types.entry_type; - fields[1].data.x_type = type_entry->data.error_union.payload_type; + fields[1]->special = ConstValSpecialStatic; + fields[1]->type = ira->codegen->builtin_types.entry_type; + fields[1]->data.x_type = type_entry->data.error_union.payload_type; break; } @@ -21044,18 +21562,18 @@ static Error ir_make_type_info_value(IrAnalyze *ira, IrInstruction *source_instr result->special = ConstValSpecialStatic; result->type = ir_type_info_get_type(ira, "Union", nullptr); - ConstExprValue *fields = create_const_vals(4); + ConstExprValue **fields = alloc_const_vals_ptrs(4); result->data.x_struct.fields = fields; // layout: ContainerLayout ensure_field_index(result->type, "layout", 0); - fields[0].special = ConstValSpecialStatic; - fields[0].type = ir_type_info_get_type(ira, "ContainerLayout", nullptr); - bigint_init_unsigned(&fields[0].data.x_enum_tag, type_entry->data.unionation.layout); + fields[0]->special = ConstValSpecialStatic; + fields[0]->type = ir_type_info_get_type(ira, "ContainerLayout", nullptr); + bigint_init_unsigned(&fields[0]->data.x_enum_tag, type_entry->data.unionation.layout); // tag_type: ?type ensure_field_index(result->type, "tag_type", 1); - fields[1].special = ConstValSpecialStatic; - fields[1].type = get_optional_type(ira->codegen, ira->codegen->builtin_types.entry_type); + fields[1]->special = ConstValSpecialStatic; + fields[1]->type = get_optional_type(ira->codegen, ira->codegen->builtin_types.entry_type); AstNode *union_decl_node = type_entry->data.unionation.decl_node; if (union_decl_node->data.container_decl.auto_enum || @@ -21065,9 +21583,9 @@ static Error ir_make_type_info_value(IrAnalyze *ira, IrInstruction *source_instr tag_type->special = ConstValSpecialStatic; tag_type->type = ira->codegen->builtin_types.entry_type; tag_type->data.x_type = type_entry->data.unionation.tag_type; - fields[1].data.x_optional = tag_type; + fields[1]->data.x_optional = tag_type; } else { - fields[1].data.x_optional = nullptr; + fields[1]->data.x_optional = nullptr; } // fields: []TypeInfo.UnionField ensure_field_index(result->type, "fields", 2); @@ -21083,7 +21601,7 @@ static Error ir_make_type_info_value(IrAnalyze *ira, IrInstruction *source_instr union_field_array->data.x_array.special = ConstArraySpecialNone; union_field_array->data.x_array.data.s_none.elements = create_const_vals(union_field_count); - init_const_slice(ira->codegen, &fields[2], union_field_array, 0, union_field_count, false); + init_const_slice(ira->codegen, fields[2], union_field_array, 0, union_field_count, false); ZigType *type_info_enum_field_type = ir_type_info_get_type(ira, "EnumField", nullptr); @@ -21094,23 +21612,23 @@ static Error ir_make_type_info_value(IrAnalyze *ira, IrInstruction *source_instr union_field_val->special = ConstValSpecialStatic; union_field_val->type = type_info_union_field_type; - ConstExprValue *inner_fields = create_const_vals(3); - inner_fields[1].special = ConstValSpecialStatic; - inner_fields[1].type = get_optional_type(ira->codegen, type_info_enum_field_type); + ConstExprValue **inner_fields = alloc_const_vals_ptrs(3); + inner_fields[1]->special = ConstValSpecialStatic; + inner_fields[1]->type = get_optional_type(ira->codegen, type_info_enum_field_type); - if (fields[1].data.x_optional == nullptr) { - inner_fields[1].data.x_optional = nullptr; + if (fields[1]->data.x_optional == nullptr) { + inner_fields[1]->data.x_optional = nullptr; } else { - inner_fields[1].data.x_optional = create_const_vals(1); - make_enum_field_val(ira, inner_fields[1].data.x_optional, union_field->enum_field, type_info_enum_field_type); + inner_fields[1]->data.x_optional = create_const_vals(1); + make_enum_field_val(ira, inner_fields[1]->data.x_optional, union_field->enum_field, type_info_enum_field_type); } - inner_fields[2].special = ConstValSpecialStatic; - inner_fields[2].type = ira->codegen->builtin_types.entry_type; - inner_fields[2].data.x_type = union_field->type_entry; + inner_fields[2]->special = ConstValSpecialStatic; + inner_fields[2]->type = ira->codegen->builtin_types.entry_type; + inner_fields[2]->data.x_type = union_field->type_entry; ConstExprValue *name = create_const_str_lit(ira->codegen, union_field->name); - init_const_slice(ira->codegen, &inner_fields[0], name, 0, buf_len(union_field->name), true); + init_const_slice(ira->codegen, inner_fields[0], name, 0, buf_len(union_field->name), true); union_field_val->data.x_struct.fields = inner_fields; union_field_val->parent.id = ConstParentIdArray; @@ -21119,7 +21637,7 @@ static Error ir_make_type_info_value(IrAnalyze *ira, IrInstruction *source_instr } // decls: []TypeInfo.Declaration ensure_field_index(result->type, "decls", 3); - if ((err = ir_make_type_info_decls(ira, source_instr, &fields[3], + if ((err = ir_make_type_info_decls(ira, source_instr, fields[3], type_entry->data.unionation.decls_scope))) { return err; @@ -21140,14 +21658,14 @@ static Error ir_make_type_info_value(IrAnalyze *ira, IrInstruction *source_instr result->special = ConstValSpecialStatic; result->type = ir_type_info_get_type(ira, "Struct", nullptr); - ConstExprValue *fields = create_const_vals(3); + ConstExprValue **fields = alloc_const_vals_ptrs(3); result->data.x_struct.fields = fields; // layout: ContainerLayout ensure_field_index(result->type, "layout", 0); - fields[0].special = ConstValSpecialStatic; - fields[0].type = ir_type_info_get_type(ira, "ContainerLayout", nullptr); - bigint_init_unsigned(&fields[0].data.x_enum_tag, type_entry->data.structure.layout); + fields[0]->special = ConstValSpecialStatic; + fields[0]->type = ir_type_info_get_type(ira, "ContainerLayout", nullptr); + bigint_init_unsigned(&fields[0]->data.x_enum_tag, type_entry->data.structure.layout); // fields: []TypeInfo.StructField ensure_field_index(result->type, "fields", 1); @@ -21163,18 +21681,18 @@ static Error ir_make_type_info_value(IrAnalyze *ira, IrInstruction *source_instr struct_field_array->data.x_array.special = ConstArraySpecialNone; struct_field_array->data.x_array.data.s_none.elements = create_const_vals(struct_field_count); - init_const_slice(ira->codegen, &fields[1], struct_field_array, 0, struct_field_count, false); + init_const_slice(ira->codegen, fields[1], struct_field_array, 0, struct_field_count, false); for (uint32_t struct_field_index = 0; struct_field_index < struct_field_count; struct_field_index++) { - TypeStructField *struct_field = &type_entry->data.structure.fields[struct_field_index]; + TypeStructField *struct_field = type_entry->data.structure.fields[struct_field_index]; ConstExprValue *struct_field_val = &struct_field_array->data.x_array.data.s_none.elements[struct_field_index]; struct_field_val->special = ConstValSpecialStatic; struct_field_val->type = type_info_struct_field_type; - ConstExprValue *inner_fields = create_const_vals(3); - inner_fields[1].special = ConstValSpecialStatic; - inner_fields[1].type = get_optional_type(ira->codegen, ira->codegen->builtin_types.entry_num_lit_int); + ConstExprValue **inner_fields = alloc_const_vals_ptrs(3); + inner_fields[1]->special = ConstValSpecialStatic; + inner_fields[1]->type = get_optional_type(ira->codegen, ira->codegen->builtin_types.entry_num_lit_int); ZigType *field_type = resolve_struct_field_type(ira->codegen, struct_field); if (field_type == nullptr) @@ -21182,21 +21700,21 @@ static Error ir_make_type_info_value(IrAnalyze *ira, IrInstruction *source_instr if ((err = type_resolve(ira->codegen, field_type, ResolveStatusZeroBitsKnown))) return err; if (!type_has_bits(struct_field->type_entry)) { - inner_fields[1].data.x_optional = nullptr; + inner_fields[1]->data.x_optional = nullptr; } else { size_t byte_offset = struct_field->offset; - inner_fields[1].data.x_optional = create_const_vals(1); - inner_fields[1].data.x_optional->special = ConstValSpecialStatic; - inner_fields[1].data.x_optional->type = ira->codegen->builtin_types.entry_num_lit_int; - bigint_init_unsigned(&inner_fields[1].data.x_optional->data.x_bigint, byte_offset); + inner_fields[1]->data.x_optional = create_const_vals(1); + inner_fields[1]->data.x_optional->special = ConstValSpecialStatic; + inner_fields[1]->data.x_optional->type = ira->codegen->builtin_types.entry_num_lit_int; + bigint_init_unsigned(&inner_fields[1]->data.x_optional->data.x_bigint, byte_offset); } - inner_fields[2].special = ConstValSpecialStatic; - inner_fields[2].type = ira->codegen->builtin_types.entry_type; - inner_fields[2].data.x_type = struct_field->type_entry; + inner_fields[2]->special = ConstValSpecialStatic; + inner_fields[2]->type = ira->codegen->builtin_types.entry_type; + inner_fields[2]->data.x_type = struct_field->type_entry; ConstExprValue *name = create_const_str_lit(ira->codegen, struct_field->name); - init_const_slice(ira->codegen, &inner_fields[0], name, 0, buf_len(struct_field->name), true); + init_const_slice(ira->codegen, inner_fields[0], name, 0, buf_len(struct_field->name), true); struct_field_val->data.x_struct.fields = inner_fields; struct_field_val->parent.id = ConstParentIdArray; @@ -21205,7 +21723,7 @@ static Error ir_make_type_info_value(IrAnalyze *ira, IrInstruction *source_instr } // decls: []TypeInfo.Declaration ensure_field_index(result->type, "decls", 2); - if ((err = ir_make_type_info_decls(ira, source_instr, &fields[2], + if ((err = ir_make_type_info_decls(ira, source_instr, fields[2], type_entry->data.structure.decls_scope))) { return err; @@ -21219,38 +21737,38 @@ static Error ir_make_type_info_value(IrAnalyze *ira, IrInstruction *source_instr result->special = ConstValSpecialStatic; result->type = ir_type_info_get_type(ira, "Fn", nullptr); - ConstExprValue *fields = create_const_vals(5); + ConstExprValue **fields = alloc_const_vals_ptrs(5); result->data.x_struct.fields = fields; // calling_convention: TypeInfo.CallingConvention ensure_field_index(result->type, "calling_convention", 0); - fields[0].special = ConstValSpecialStatic; - fields[0].type = ir_type_info_get_type(ira, "CallingConvention", nullptr); - bigint_init_unsigned(&fields[0].data.x_enum_tag, type_entry->data.fn.fn_type_id.cc); + fields[0]->special = ConstValSpecialStatic; + fields[0]->type = ir_type_info_get_type(ira, "CallingConvention", nullptr); + bigint_init_unsigned(&fields[0]->data.x_enum_tag, type_entry->data.fn.fn_type_id.cc); // is_generic: bool ensure_field_index(result->type, "is_generic", 1); bool is_generic = type_entry->data.fn.is_generic; - fields[1].special = ConstValSpecialStatic; - fields[1].type = ira->codegen->builtin_types.entry_bool; - fields[1].data.x_bool = is_generic; + fields[1]->special = ConstValSpecialStatic; + fields[1]->type = ira->codegen->builtin_types.entry_bool; + fields[1]->data.x_bool = is_generic; // is_varargs: bool ensure_field_index(result->type, "is_var_args", 2); bool is_varargs = type_entry->data.fn.fn_type_id.is_var_args; - fields[2].special = ConstValSpecialStatic; - fields[2].type = ira->codegen->builtin_types.entry_bool; - fields[2].data.x_bool = type_entry->data.fn.fn_type_id.is_var_args; + fields[2]->special = ConstValSpecialStatic; + fields[2]->type = ira->codegen->builtin_types.entry_bool; + fields[2]->data.x_bool = type_entry->data.fn.fn_type_id.is_var_args; // return_type: ?type ensure_field_index(result->type, "return_type", 3); - fields[3].special = ConstValSpecialStatic; - fields[3].type = get_optional_type(ira->codegen, ira->codegen->builtin_types.entry_type); + fields[3]->special = ConstValSpecialStatic; + fields[3]->type = get_optional_type(ira->codegen, ira->codegen->builtin_types.entry_type); if (type_entry->data.fn.fn_type_id.return_type == nullptr) - fields[3].data.x_optional = nullptr; + fields[3]->data.x_optional = nullptr; else { ConstExprValue *return_type = create_const_vals(1); return_type->special = ConstValSpecialStatic; return_type->type = ira->codegen->builtin_types.entry_type; return_type->data.x_type = type_entry->data.fn.fn_type_id.return_type; - fields[3].data.x_optional = return_type; + fields[3]->data.x_optional = return_type; } // args: []TypeInfo.FnArg ZigType *type_info_fn_arg_type = ir_type_info_get_type(ira, "FnArg", nullptr); @@ -21266,7 +21784,7 @@ static Error ir_make_type_info_value(IrAnalyze *ira, IrInstruction *source_instr fn_arg_array->data.x_array.special = ConstArraySpecialNone; fn_arg_array->data.x_array.data.s_none.elements = create_const_vals(fn_arg_count); - init_const_slice(ira->codegen, &fields[4], fn_arg_array, 0, fn_arg_count, false); + init_const_slice(ira->codegen, fields[4], fn_arg_array, 0, fn_arg_count, false); for (size_t fn_arg_index = 0; fn_arg_index < fn_arg_count; fn_arg_index++) { FnTypeParamInfo *fn_param_info = &type_entry->data.fn.fn_type_id.param_info[fn_arg_index]; @@ -21278,24 +21796,24 @@ static Error ir_make_type_info_value(IrAnalyze *ira, IrInstruction *source_instr bool arg_is_generic = fn_param_info->type == nullptr; if (arg_is_generic) assert(is_generic); - ConstExprValue *inner_fields = create_const_vals(3); - inner_fields[0].special = ConstValSpecialStatic; - inner_fields[0].type = ira->codegen->builtin_types.entry_bool; - inner_fields[0].data.x_bool = arg_is_generic; - inner_fields[1].special = ConstValSpecialStatic; - inner_fields[1].type = ira->codegen->builtin_types.entry_bool; - inner_fields[1].data.x_bool = fn_param_info->is_noalias; - inner_fields[2].special = ConstValSpecialStatic; - inner_fields[2].type = get_optional_type(ira->codegen, ira->codegen->builtin_types.entry_type); + ConstExprValue **inner_fields = alloc_const_vals_ptrs(3); + inner_fields[0]->special = ConstValSpecialStatic; + inner_fields[0]->type = ira->codegen->builtin_types.entry_bool; + inner_fields[0]->data.x_bool = arg_is_generic; + inner_fields[1]->special = ConstValSpecialStatic; + inner_fields[1]->type = ira->codegen->builtin_types.entry_bool; + inner_fields[1]->data.x_bool = fn_param_info->is_noalias; + inner_fields[2]->special = ConstValSpecialStatic; + inner_fields[2]->type = get_optional_type(ira->codegen, ira->codegen->builtin_types.entry_type); if (arg_is_generic) - inner_fields[2].data.x_optional = nullptr; + inner_fields[2]->data.x_optional = nullptr; else { ConstExprValue *arg_type = create_const_vals(1); arg_type->special = ConstValSpecialStatic; arg_type->type = ira->codegen->builtin_types.entry_type; arg_type->data.x_type = fn_param_info->type; - inner_fields[2].data.x_optional = arg_type; + inner_fields[2]->data.x_optional = arg_type; } fn_arg_val->data.x_struct.fields = inner_fields; @@ -21356,8 +21874,8 @@ static IrInstruction *ir_analyze_instruction_type_info(IrAnalyze *ira, static ConstExprValue *get_const_field(IrAnalyze *ira, ConstExprValue *struct_value, const char *name, size_t field_index) { ensure_field_index(struct_value->type, name, field_index); - assert(struct_value->data.x_struct.fields[field_index].special == ConstValSpecialStatic); - return &struct_value->data.x_struct.fields[field_index]; + assert(struct_value->data.x_struct.fields[field_index]->special == ConstValSpecialStatic); + return struct_value->data.x_struct.fields[field_index]; } static bool get_const_field_bool(IrAnalyze *ira, ConstExprValue *struct_value, const char *name, size_t field_index) @@ -21656,15 +22174,15 @@ static IrInstruction *ir_analyze_instruction_c_import(IrAnalyze *ira, IrInstruct } for (size_t i = 0; i < errors_len; i += 1) { Stage2ErrorMsg *clang_err = &errors_ptr[i]; - // Clang can emit "too many errors, stopping now", in which case `source` and `filename_ptr` are null - if (clang_err->source && clang_err->filename_ptr) { + // Clang can emit "too many errors, stopping now", in which case `source` and `filename_ptr` are null + if (clang_err->source && clang_err->filename_ptr) { ErrorMsg *err_msg = err_msg_create_with_offset( clang_err->filename_ptr ? buf_create_from_mem(clang_err->filename_ptr, clang_err->filename_len) : buf_alloc(), clang_err->line, clang_err->column, clang_err->offset, clang_err->source, buf_create_from_mem(clang_err->msg_ptr, clang_err->msg_len)); err_msg_add_note(parent_err_msg, err_msg); - } + } } return ira->codegen->invalid_instruction; @@ -22122,7 +22640,7 @@ static IrInstruction *ir_analyze_instruction_from_bytes(IrAnalyze *ira, IrInstru if ((err = resolve_ptr_align(ira, target->value.type, &src_ptr_align))) return ira->codegen->invalid_instruction; } else if (is_slice(target->value.type)) { - ZigType *src_ptr_type = target->value.type->data.structure.fields[slice_ptr_index].type_entry; + ZigType *src_ptr_type = target->value.type->data.structure.fields[slice_ptr_index]->type_entry; src_ptr_const = src_ptr_type->data.pointer.is_const; src_ptr_volatile = src_ptr_type->data.pointer.is_volatile; @@ -22165,7 +22683,7 @@ static IrInstruction *ir_analyze_instruction_from_bytes(IrAnalyze *ira, IrInstru if (!val) return ira->codegen->invalid_instruction; - ConstExprValue *len_val = &val->data.x_struct.fields[slice_len_index]; + ConstExprValue *len_val = val->data.x_struct.fields[slice_len_index]; if (value_is_comptime(len_val)) { known_len = bigint_as_u64(&len_val->data.x_bigint); have_known_len = true; @@ -22215,7 +22733,7 @@ static IrInstruction *ir_analyze_instruction_to_bytes(IrAnalyze *ira, IrInstruct return ira->codegen->invalid_instruction; } - ZigType *src_ptr_type = target->value.type->data.structure.fields[slice_ptr_index].type_entry; + ZigType *src_ptr_type = target->value.type->data.structure.fields[slice_ptr_index]->type_entry; uint32_t alignment; if ((err = resolve_ptr_align(ira, src_ptr_type, &alignment))) @@ -22232,17 +22750,17 @@ static IrInstruction *ir_analyze_instruction_to_bytes(IrAnalyze *ira, IrInstruct return ira->codegen->invalid_instruction; IrInstruction *result = ir_const(ira, &instruction->base, dest_slice_type); - result->value.data.x_struct.fields = create_const_vals(2); + result->value.data.x_struct.fields = alloc_const_vals_ptrs(2); - ConstExprValue *ptr_val = &result->value.data.x_struct.fields[slice_ptr_index]; - ConstExprValue *target_ptr_val = &target_val->data.x_struct.fields[slice_ptr_index]; + ConstExprValue *ptr_val = result->value.data.x_struct.fields[slice_ptr_index]; + ConstExprValue *target_ptr_val = target_val->data.x_struct.fields[slice_ptr_index]; copy_const_val(ptr_val, target_ptr_val, false); ptr_val->type = dest_ptr_type; - ConstExprValue *len_val = &result->value.data.x_struct.fields[slice_len_index]; + ConstExprValue *len_val = result->value.data.x_struct.fields[slice_len_index]; len_val->special = ConstValSpecialStatic; len_val->type = ira->codegen->builtin_types.entry_usize; - ConstExprValue *target_len_val = &target_val->data.x_struct.fields[slice_len_index]; + ConstExprValue *target_len_val = target_val->data.x_struct.fields[slice_len_index]; ZigType *elem_type = src_ptr_type->data.pointer.child_type; BigInt elem_size_bigint; bigint_init_unsigned(&elem_size_bigint, type_size(ira->codegen, elem_type)); @@ -23023,7 +23541,7 @@ static IrInstruction *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstruction } } } else if (is_slice(array_type)) { - ZigType *ptr_type = array_type->data.structure.fields[slice_ptr_index].type_entry; + ZigType *ptr_type = array_type->data.structure.fields[slice_ptr_index]->type_entry; return_type = get_slice_type(ira->codegen, ptr_type); } else { ir_add_error(ira, &instruction->base, @@ -23131,13 +23649,13 @@ static IrInstruction *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstruction return ira->codegen->invalid_instruction; } - parent_ptr = &slice_ptr->data.x_struct.fields[slice_ptr_index]; + parent_ptr = slice_ptr->data.x_struct.fields[slice_ptr_index]; if (parent_ptr->special == ConstValSpecialUndef) { ir_add_error(ira, &instruction->base, buf_sprintf("slice of undefined")); return ira->codegen->invalid_instruction; } - ConstExprValue *len_val = &slice_ptr->data.x_struct.fields[slice_len_index]; + ConstExprValue *len_val = slice_ptr->data.x_struct.fields[slice_len_index]; switch (parent_ptr->data.x_ptr.special) { case ConstPtrSpecialInvalid: @@ -23209,9 +23727,9 @@ static IrInstruction *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstruction IrInstruction *result = ir_const(ira, &instruction->base, return_type); ConstExprValue *out_val = &result->value; - out_val->data.x_struct.fields = create_const_vals(2); + out_val->data.x_struct.fields = alloc_const_vals_ptrs(2); - ConstExprValue *ptr_val = &out_val->data.x_struct.fields[slice_ptr_index]; + ConstExprValue *ptr_val = out_val->data.x_struct.fields[slice_ptr_index]; if (array_val) { size_t index = abs_offset + start_scalar; @@ -23258,7 +23776,7 @@ static IrInstruction *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstruction zig_panic("TODO"); } - ConstExprValue *len_val = &out_val->data.x_struct.fields[slice_len_index]; + ConstExprValue *len_val = out_val->data.x_struct.fields[slice_len_index]; init_const_usize(ira->codegen, len_val, end_scalar - start_scalar); return result; @@ -23332,7 +23850,7 @@ static IrInstruction *ir_analyze_instruction_member_type(IrAnalyze *ira, IrInstr member_index, buf_ptr(&container_type->name), container_type->data.structure.src_field_count)); return ira->codegen->invalid_instruction; } - TypeStructField *field = &container_type->data.structure.fields[member_index]; + TypeStructField *field = container_type->data.structure.fields[member_index]; return ir_const_type(ira, &instruction->base, field->type_entry); } else if (container_type->id == ZigTypeIdUnion) { @@ -23374,7 +23892,7 @@ static IrInstruction *ir_analyze_instruction_member_name(IrAnalyze *ira, IrInstr member_index, buf_ptr(&container_type->name), container_type->data.structure.src_field_count)); return ira->codegen->invalid_instruction; } - TypeStructField *field = &container_type->data.structure.fields[member_index]; + TypeStructField *field = container_type->data.structure.fields[member_index]; IrInstruction *result = ir_const(ira, &instruction->base, nullptr); init_const_str_lit(ira->codegen, &result->value, field->name); @@ -24360,7 +24878,7 @@ static IrInstruction *ir_align_cast(IrAnalyze *ira, IrInstruction *target, uint3 ZigType *fn_type = get_fn_type(ira->codegen, &fn_type_id); result_type = get_optional_type(ira->codegen, fn_type); } else if (is_slice(target_type)) { - ZigType *slice_ptr_type = target_type->data.structure.fields[slice_ptr_index].type_entry; + ZigType *slice_ptr_type = target_type->data.structure.fields[slice_ptr_index]->type_entry; if ((err = resolve_ptr_align(ira, slice_ptr_type, &old_align_bytes))) return ira->codegen->invalid_instruction; ZigType *result_ptr_type = adjust_ptr_align(ira->codegen, slice_ptr_type, align_bytes); @@ -24409,6 +24927,10 @@ static IrInstruction *ir_analyze_ptr_cast(IrAnalyze *ira, IrInstruction *source_ ZigType *src_type = ptr->value.type; assert(!type_is_invalid(src_type)); + if (src_type == dest_type) { + return ptr; + } + // We have a check for zero bits later so we use get_src_ptr_type to // validate src_type and dest_type. @@ -24458,6 +24980,9 @@ static IrInstruction *ir_analyze_ptr_cast(IrAnalyze *ira, IrInstruction *source_ IrInstruction *result; if (ptr->value.data.x_ptr.mut == ConstPtrMutInfer) { result = ir_build_ptr_cast_gen(ira, source_instr, dest_type, ptr, safety_check_on); + + if ((err = type_resolve(ira->codegen, dest_type, ResolveStatusZeroBitsKnown))) + return ira->codegen->invalid_instruction; } else { result = ir_const(ira, source_instr, dest_type); } @@ -24598,10 +25123,10 @@ static void buf_write_value_bytes(CodeGen *codegen, uint8_t *buf, ConstExprValue case ContainerLayoutExtern: { size_t src_field_count = val->type->data.structure.src_field_count; for (size_t field_i = 0; field_i < src_field_count; field_i += 1) { - TypeStructField *struct_field = &val->type->data.structure.fields[field_i]; + TypeStructField *struct_field = val->type->data.structure.fields[field_i]; if (struct_field->gen_index == SIZE_MAX) continue; - ConstExprValue *field_val = &val->data.x_struct.fields[field_i]; + ConstExprValue *field_val = val->data.x_struct.fields[field_i]; size_t offset = struct_field->offset; buf_write_value_bytes(codegen, buf + offset, field_val); } @@ -24627,12 +25152,12 @@ static void buf_write_value_bytes(CodeGen *codegen, uint8_t *buf, ConstExprValue bigint_init_unsigned(&big_int, 0); size_t used_bits = 0; while (src_i < src_field_count) { - TypeStructField *field = &val->type->data.structure.fields[src_i]; + TypeStructField *field = val->type->data.structure.fields[src_i]; assert(field->gen_index != SIZE_MAX); if (field->gen_index != gen_i) break; uint32_t packed_bits_size = type_size_bits(codegen, field->type_entry); - buf_write_value_bytes(codegen, child_buf, &val->data.x_struct.fields[src_i]); + buf_write_value_bytes(codegen, child_buf, val->data.x_struct.fields[src_i]); BigInt child_val; bigint_read_twos_complement(&child_val, child_buf, packed_bits_size, is_big_endian, false); @@ -24770,11 +25295,11 @@ static Error buf_read_value_bytes(IrAnalyze *ira, CodeGen *codegen, AstNode *sou } case ContainerLayoutExtern: { size_t src_field_count = val->type->data.structure.src_field_count; - val->data.x_struct.fields = create_const_vals(src_field_count); + val->data.x_struct.fields = alloc_const_vals_ptrs(src_field_count); for (size_t field_i = 0; field_i < src_field_count; field_i += 1) { - ConstExprValue *field_val = &val->data.x_struct.fields[field_i]; + ConstExprValue *field_val = val->data.x_struct.fields[field_i]; field_val->special = ConstValSpecialStatic; - TypeStructField *struct_field = &val->type->data.structure.fields[field_i]; + TypeStructField *struct_field = val->type->data.structure.fields[field_i]; field_val->type = struct_field->type_entry; if (struct_field->gen_index == SIZE_MAX) continue; @@ -24787,7 +25312,7 @@ static Error buf_read_value_bytes(IrAnalyze *ira, CodeGen *codegen, AstNode *sou } case ContainerLayoutPacked: { size_t src_field_count = val->type->data.structure.src_field_count; - val->data.x_struct.fields = create_const_vals(src_field_count); + val->data.x_struct.fields = alloc_const_vals_ptrs(src_field_count); size_t gen_field_count = val->type->data.structure.gen_field_count; size_t gen_i = 0; size_t src_i = 0; @@ -24805,11 +25330,11 @@ static Error buf_read_value_bytes(IrAnalyze *ira, CodeGen *codegen, AstNode *sou BigInt big_int; bigint_read_twos_complement(&big_int, buf + offset, big_int_byte_count * 8, is_big_endian, false); while (src_i < src_field_count) { - TypeStructField *field = &val->type->data.structure.fields[src_i]; + TypeStructField *field = val->type->data.structure.fields[src_i]; src_assert(field->gen_index != SIZE_MAX, source_node); if (field->gen_index != gen_i) break; - ConstExprValue *field_val = &val->data.x_struct.fields[src_i]; + ConstExprValue *field_val = val->data.x_struct.fields[src_i]; field_val->special = ConstValSpecialStatic; field_val->type = field->type_entry; uint32_t packed_bits_size = type_size_bits(codegen, field->type_entry); @@ -24992,6 +25517,7 @@ static IrInstruction *ir_analyze_instruction_decl_ref(IrAnalyze *ira, } static IrInstruction *ir_analyze_instruction_ptr_to_int(IrAnalyze *ira, IrInstructionPtrToInt *instruction) { + Error err; IrInstruction *target = instruction->target->child; if (type_is_invalid(target->value.type)) return ira->codegen->invalid_instruction; @@ -25005,6 +25531,8 @@ static IrInstruction *ir_analyze_instruction_ptr_to_int(IrAnalyze *ira, IrInstru return ira->codegen->invalid_instruction; } + if ((err = type_resolve(ira->codegen, target->value.type, ResolveStatusZeroBitsKnown))) + return ira->codegen->invalid_instruction; if (!type_has_bits(target->value.type)) { ir_add_error(ira, target, buf_sprintf("pointer to size 0 type has no address")); @@ -25065,7 +25593,7 @@ static IrInstruction *ir_analyze_instruction_align_cast(IrAnalyze *ira, IrInstru ZigType *elem_type = nullptr; if (is_slice(target->value.type)) { - ZigType *slice_ptr_type = target->value.type->data.structure.fields[slice_ptr_index].type_entry; + ZigType *slice_ptr_type = target->value.type->data.structure.fields[slice_ptr_index]->type_entry; elem_type = slice_ptr_type->data.pointer.child_type; } else if (target->value.type->id == ZigTypeIdPointer) { elem_type = target->value.type->data.pointer.child_type; @@ -25142,6 +25670,10 @@ static IrInstruction *ir_analyze_instruction_arg_type(IrAnalyze *ira, IrInstruct if (!ir_resolve_usize(ira, arg_index_inst, &arg_index)) return ira->codegen->invalid_instruction; + if (fn_type->id == ZigTypeIdBoundFn) { + fn_type = fn_type->data.bound_fn.fn_type; + arg_index += 1; + } if (fn_type->id != ZigTypeIdFn) { ir_add_error(ira, fn_type_inst, buf_sprintf("expected function, found '%s'", buf_ptr(&fn_type->name))); return ira->codegen->invalid_instruction; @@ -25149,6 +25681,10 @@ static IrInstruction *ir_analyze_instruction_arg_type(IrAnalyze *ira, IrInstruct FnTypeId *fn_type_id = &fn_type->data.fn.fn_type_id; if (arg_index >= fn_type_id->param_count) { + if (instruction->allow_var) { + // TODO remove this with var args + return ir_const_type(ira, &instruction->base, ira->codegen->builtin_types.entry_var); + } ir_add_error(ira, arg_index_inst, buf_sprintf("arg index %" ZIG_PRI_u64 " out of bounds; '%s' has %" ZIG_PRI_usize " arguments", arg_index, buf_ptr(&fn_type->name), fn_type_id->param_count)); @@ -25160,10 +25696,14 @@ static IrInstruction *ir_analyze_instruction_arg_type(IrAnalyze *ira, IrInstruct // Args are only unresolved if our function is generic. ir_assert(fn_type->data.fn.is_generic, &instruction->base); - ir_add_error(ira, arg_index_inst, - buf_sprintf("@ArgType could not resolve the type of arg %" ZIG_PRI_u64 " because '%s' is generic", - arg_index, buf_ptr(&fn_type->name))); - return ira->codegen->invalid_instruction; + if (instruction->allow_var) { + return ir_const_type(ira, &instruction->base, ira->codegen->builtin_types.entry_var); + } else { + ir_add_error(ira, arg_index_inst, + buf_sprintf("@ArgType could not resolve the type of arg %" ZIG_PRI_u64 " because '%s' is generic", + arg_index, buf_ptr(&fn_type->name))); + return ira->codegen->invalid_instruction; + } } return ir_const_type(ira, &instruction->base, result_type); } @@ -25216,9 +25756,29 @@ static ZigType *ir_resolve_atomic_operand_type(IrAnalyze *ira, IrInstruction *op buf_sprintf("%" PRIu32 "-bit integer type is not a power of 2", operand_type->data.integral.bit_count)); return ira->codegen->builtin_types.entry_invalid; } + } else if (operand_type->id == ZigTypeIdEnum) { + ZigType *int_type = operand_type->data.enumeration.tag_int_type; + if (int_type->data.integral.bit_count < 8) { + ir_add_error(ira, op, + buf_sprintf("expected enum tag type 8 bits or larger, found %" PRIu32 "-bit tag type", + int_type->data.integral.bit_count)); + return ira->codegen->builtin_types.entry_invalid; + } + uint32_t max_atomic_bits = target_arch_largest_atomic_bits(ira->codegen->zig_target->arch); + if (int_type->data.integral.bit_count > max_atomic_bits) { + ir_add_error(ira, op, + buf_sprintf("expected %" PRIu32 "-bit enum tag type or smaller, found %" PRIu32 "-bit tag type", + max_atomic_bits, int_type->data.integral.bit_count)); + return ira->codegen->builtin_types.entry_invalid; + } + if (!is_power_of_2(int_type->data.integral.bit_count)) { + ir_add_error(ira, op, + buf_sprintf("%" PRIu32 "-bit enum tag type is not a power of 2", int_type->data.integral.bit_count)); + return ira->codegen->builtin_types.entry_invalid; + } } else if (get_codegen_ptr_type(operand_type) == nullptr) { ir_add_error(ira, op, - buf_sprintf("expected integer or pointer type, found '%s'", buf_ptr(&operand_type->name))); + buf_sprintf("expected integer, enum or pointer type, found '%s'", buf_ptr(&operand_type->name))); return ira->codegen->builtin_types.entry_invalid; } @@ -25249,6 +25809,12 @@ static IrInstruction *ir_analyze_instruction_atomic_rmw(IrAnalyze *ira, IrInstru } } + if (operand_type->id == ZigTypeIdEnum && op != AtomicRmwOp_xchg) { + ir_add_error(ira, instruction->op, + buf_sprintf("@atomicRmw on enum only works with .Xchg")); + return ira->codegen->invalid_instruction; + } + IrInstruction *operand = instruction->operand->child; if (type_is_invalid(operand->value.type)) return ira->codegen->invalid_instruction; @@ -25323,6 +25889,56 @@ static IrInstruction *ir_analyze_instruction_atomic_load(IrAnalyze *ira, IrInstr return result; } +static IrInstruction *ir_analyze_instruction_atomic_store(IrAnalyze *ira, IrInstructionAtomicStore *instruction) { + ZigType *operand_type = ir_resolve_atomic_operand_type(ira, instruction->operand_type->child); + if (type_is_invalid(operand_type)) + return ira->codegen->invalid_instruction; + + IrInstruction *ptr_inst = instruction->ptr->child; + if (type_is_invalid(ptr_inst->value.type)) + return ira->codegen->invalid_instruction; + + ZigType *ptr_type = get_pointer_to_type(ira->codegen, operand_type, false); + IrInstruction *casted_ptr = ir_implicit_cast(ira, ptr_inst, ptr_type); + if (type_is_invalid(casted_ptr->value.type)) + return ira->codegen->invalid_instruction; + + IrInstruction *value = instruction->value->child; + if (type_is_invalid(value->value.type)) + return ira->codegen->invalid_instruction; + + IrInstruction *casted_value = ir_implicit_cast(ira, value, operand_type); + if (type_is_invalid(casted_value->value.type)) + return ira->codegen->invalid_instruction; + + + AtomicOrder ordering; + if (instruction->ordering == nullptr) { + ordering = instruction->resolved_ordering; + } else { + if (!ir_resolve_atomic_order(ira, instruction->ordering->child, &ordering)) + return ira->codegen->invalid_instruction; + } + + if (ordering == AtomicOrderAcquire || ordering == AtomicOrderAcqRel) { + ir_assert(instruction->ordering != nullptr, &instruction->base); + ir_add_error(ira, instruction->ordering, + buf_sprintf("@atomicStore atomic ordering must not be Acquire or AcqRel")); + return ira->codegen->invalid_instruction; + } + + if (instr_is_comptime(casted_value) && instr_is_comptime(casted_ptr)) { + IrInstruction *result = ir_analyze_store_ptr(ira, &instruction->base, casted_ptr, value, false); + result->value.type = ira->codegen->builtin_types.entry_void; + return result; + } + + IrInstruction *result = ir_build_atomic_store(&ira->new_irb, instruction->base.scope, + instruction->base.source_node, nullptr, casted_ptr, casted_value, nullptr, ordering); + result->value.type = ira->codegen->builtin_types.entry_void; + return result; +} + static IrInstruction *ir_analyze_instruction_save_err_ret_addr(IrAnalyze *ira, IrInstructionSaveErrRetAddr *instruction) { IrInstruction *result = ir_build_save_err_ret_addr(&ira->new_irb, instruction->base.scope, instruction->base.source_node); @@ -25854,6 +26470,26 @@ static IrInstruction *ir_analyze_instruction_end_expr(IrAnalyze *ira, IrInstruct return ir_const_void(ira, &instruction->base); } +static IrInstruction *ir_analyze_instruction_implicit_cast(IrAnalyze *ira, IrInstructionImplicitCast *instruction) { + IrInstruction *operand = instruction->operand->child; + if (type_is_invalid(operand->value.type)) + return operand; + + IrInstruction *result_loc = ir_resolve_result(ira, &instruction->base, + &instruction->result_loc_cast->base, operand->value.type, operand, false, false, true); + if (result_loc != nullptr && (type_is_invalid(result_loc->value.type) || instr_is_unreachable(result_loc))) + return result_loc; + + if (instruction->result_loc_cast->parent->gen_instruction != nullptr) { + return instruction->result_loc_cast->parent->gen_instruction; + } + + ZigType *dest_type = ir_resolve_type(ira, instruction->result_loc_cast->base.source_instruction->child); + if (type_is_invalid(dest_type)) + return ira->codegen->invalid_instruction; + return ir_implicit_cast_with_result(ira, &instruction->base, operand, dest_type, nullptr); +} + static IrInstruction *ir_analyze_instruction_bit_cast_src(IrAnalyze *ira, IrInstructionBitCastSrc *instruction) { IrInstruction *operand = instruction->operand->child; if (type_is_invalid(operand->value.type)) @@ -26337,6 +26973,8 @@ static IrInstruction *ir_analyze_instruction_base(IrAnalyze *ira, IrInstruction return ir_analyze_instruction_atomic_rmw(ira, (IrInstructionAtomicRmw *)instruction); case IrInstructionIdAtomicLoad: return ir_analyze_instruction_atomic_load(ira, (IrInstructionAtomicLoad *)instruction); + case IrInstructionIdAtomicStore: + return ir_analyze_instruction_atomic_store(ira, (IrInstructionAtomicStore *)instruction); case IrInstructionIdSaveErrRetAddr: return ir_analyze_instruction_save_err_ret_addr(ira, (IrInstructionSaveErrRetAddr *)instruction); case IrInstructionIdAddImplicitReturnType: @@ -26517,6 +27155,7 @@ bool ir_has_side_effects(IrInstruction *instruction) { case IrInstructionIdSaveErrRetAddr: case IrInstructionIdAddImplicitReturnType: case IrInstructionIdAtomicRmw: + case IrInstructionIdAtomicStore: case IrInstructionIdCmpxchgGen: case IrInstructionIdCmpxchgSrc: case IrInstructionIdAssertZero: diff --git a/src/ir_print.cpp b/src/ir_print.cpp index aa53b11e03..03224d8037 100644 --- a/src/ir_print.cpp +++ b/src/ir_print.cpp @@ -324,6 +324,8 @@ const char* ir_instruction_type_str(IrInstructionId id) { return "AtomicRmw"; case IrInstructionIdAtomicLoad: return "AtomicLoad"; + case IrInstructionIdAtomicStore: + return "AtomicStore"; case IrInstructionIdSaveErrRetAddr: return "SaveErrRetAddr"; case IrInstructionIdAddImplicitReturnType: @@ -601,6 +603,12 @@ static void ir_print_result_loc_bit_cast(IrPrint *irp, ResultLocBitCast *result_ fprintf(irp->f, ")"); } +static void ir_print_result_loc_cast(IrPrint *irp, ResultLocCast *result_loc_cast) { + fprintf(irp->f, "cast(ty="); + ir_print_other_instruction(irp, result_loc_cast->base.source_instruction); + fprintf(irp->f, ")"); +} + static void ir_print_result_loc(IrPrint *irp, ResultLoc *result_loc) { switch (result_loc->id) { case ResultLocIdInvalid: @@ -619,6 +627,8 @@ static void ir_print_result_loc(IrPrint *irp, ResultLoc *result_loc) { return ir_print_result_loc_peer(irp, (ResultLocPeer *)result_loc); case ResultLocIdBitCast: return ir_print_result_loc_bit_cast(irp, (ResultLocBitCast *)result_loc); + case ResultLocIdCast: + return ir_print_result_loc_cast(irp, (ResultLocCast *)result_loc); case ResultLocIdPeerParent: fprintf(irp->f, "peer_parent"); return; @@ -723,7 +733,6 @@ static void ir_print_phi(IrPrint *irp, IrInstructionPhi *phi_instruction) { } static void ir_print_container_init_list(IrPrint *irp, IrInstructionContainerInitList *instruction) { - ir_print_other_instruction(irp, instruction->container_type); fprintf(irp->f, "{"); if (instruction->item_count > 50) { fprintf(irp->f, "...(%" ZIG_PRI_usize " items)...", instruction->item_count); @@ -735,11 +744,11 @@ static void ir_print_container_init_list(IrPrint *irp, IrInstructionContainerIni ir_print_other_instruction(irp, result_loc); } } - fprintf(irp->f, "}"); + fprintf(irp->f, "}result="); + ir_print_other_instruction(irp, instruction->result_loc); } static void ir_print_container_init_fields(IrPrint *irp, IrInstructionContainerInitFields *instruction) { - ir_print_other_instruction(irp, instruction->container_type); fprintf(irp->f, "{"); for (size_t i = 0; i < instruction->field_count; i += 1) { IrInstructionContainerInitFieldsField *field = &instruction->fields[i]; @@ -747,7 +756,8 @@ static void ir_print_container_init_fields(IrPrint *irp, IrInstructionContainerI fprintf(irp->f, "%s.%s = ", comma, buf_ptr(field->name)); ir_print_other_instruction(irp, field->result_loc); } - fprintf(irp->f, "} // container init"); + fprintf(irp->f, "}result="); + ir_print_other_instruction(irp, instruction->result_loc); } static void ir_print_unreachable(IrPrint *irp, IrInstructionUnreachable *instruction) { @@ -1484,6 +1494,13 @@ static void ir_print_ptr_cast_gen(IrPrint *irp, IrInstructionPtrCastGen *instruc fprintf(irp->f, ")"); } +static void ir_print_implicit_cast(IrPrint *irp, IrInstructionImplicitCast *instruction) { + fprintf(irp->f, "@implicitCast("); + ir_print_other_instruction(irp, instruction->operand); + fprintf(irp->f, ")result="); + ir_print_result_loc(irp, &instruction->result_loc_cast->base); +} + static void ir_print_bit_cast_src(IrPrint *irp, IrInstructionBitCastSrc *instruction) { fprintf(irp->f, "@bitCast("); ir_print_other_instruction(irp, instruction->operand); @@ -1739,14 +1756,6 @@ static void ir_print_align_cast(IrPrint *irp, IrInstructionAlignCast *instructio fprintf(irp->f, ")"); } -static void ir_print_implicit_cast(IrPrint *irp, IrInstructionImplicitCast *instruction) { - fprintf(irp->f, "@implicitCast("); - ir_print_other_instruction(irp, instruction->dest_type); - fprintf(irp->f, ","); - ir_print_other_instruction(irp, instruction->target); - fprintf(irp->f, ")"); -} - static void ir_print_resolve_result(IrPrint *irp, IrInstructionResolveResult *instruction) { fprintf(irp->f, "ResolveResult("); ir_print_result_loc(irp, instruction->result_loc); @@ -1864,6 +1873,27 @@ static void ir_print_atomic_load(IrPrint *irp, IrInstructionAtomicLoad *instruct fprintf(irp->f, ")"); } +static void ir_print_atomic_store(IrPrint *irp, IrInstructionAtomicStore *instruction) { + fprintf(irp->f, "@atomicStore("); + if (instruction->operand_type != nullptr) { + ir_print_other_instruction(irp, instruction->operand_type); + } else { + fprintf(irp->f, "[TODO print]"); + } + fprintf(irp->f, ","); + ir_print_other_instruction(irp, instruction->ptr); + fprintf(irp->f, ","); + ir_print_other_instruction(irp, instruction->value); + fprintf(irp->f, ","); + if (instruction->ordering != nullptr) { + ir_print_other_instruction(irp, instruction->ordering); + } else { + fprintf(irp->f, "[TODO print]"); + } + fprintf(irp->f, ")"); +} + + static void ir_print_save_err_ret_addr(IrPrint *irp, IrInstructionSaveErrRetAddr *instruction) { fprintf(irp->f, "@saveErrRetAddr()"); } @@ -2424,6 +2454,9 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction, bool case IrInstructionIdAtomicLoad: ir_print_atomic_load(irp, (IrInstructionAtomicLoad *)instruction); break; + case IrInstructionIdAtomicStore: + ir_print_atomic_store(irp, (IrInstructionAtomicStore *)instruction); + break; case IrInstructionIdEnumToInt: ir_print_enum_to_int(irp, (IrInstructionEnumToInt *)instruction); break; @@ -2542,3 +2575,18 @@ void ir_print_instruction(CodeGen *codegen, FILE *f, IrInstruction *instruction, ir_print_instruction(irp, instruction, false); } + +void ir_print_const_expr(CodeGen *codegen, FILE *f, ConstExprValue *value, int indent_size, IrPass pass) { + IrPrint ir_print = {}; + IrPrint *irp = &ir_print; + irp->pass = pass; + irp->codegen = codegen; + irp->f = f; + irp->indent = indent_size; + irp->indent_size = indent_size; + irp->printed = {}; + irp->printed.init(4); + irp->pending = {}; + + ir_print_const_value(irp, value); +} diff --git a/src/ir_print.hpp b/src/ir_print.hpp index e3947077c8..64af959f53 100644 --- a/src/ir_print.hpp +++ b/src/ir_print.hpp @@ -14,6 +14,7 @@ void ir_print(CodeGen *codegen, FILE *f, IrExecutable *executable, int indent_size, IrPass pass); void ir_print_instruction(CodeGen *codegen, FILE *f, IrInstruction *instruction, int indent_size, IrPass pass); +void ir_print_const_expr(CodeGen *codegen, FILE *f, ConstExprValue *value, int indent_size, IrPass pass); const char* ir_instruction_type_str(IrInstructionId id); diff --git a/src/parser.cpp b/src/parser.cpp index a1ece3ed10..e87c83a276 100644 --- a/src/parser.cpp +++ b/src/parser.cpp @@ -81,7 +81,7 @@ static AstNode *ast_parse_for_type_expr(ParseContext *pc); static AstNode *ast_parse_while_type_expr(ParseContext *pc); static AstNode *ast_parse_switch_expr(ParseContext *pc); static AstNode *ast_parse_asm_expr(ParseContext *pc); -static AstNode *ast_parse_enum_lit(ParseContext *pc); +static AstNode *ast_parse_anon_lit(ParseContext *pc); static AstNode *ast_parse_asm_output(ParseContext *pc); static AsmOutput *ast_parse_asm_output_item(ParseContext *pc); static AstNode *ast_parse_asm_input(ParseContext *pc); @@ -493,6 +493,9 @@ static AstNode *ast_parse_root(ParseContext *pc) { node->data.container_decl.layout = ContainerLayoutAuto; node->data.container_decl.kind = ContainerKindStruct; node->data.container_decl.is_root = true; + if (buf_len(&members.doc_comments) != 0) { + node->data.container_decl.doc_comments = members.doc_comments; + } return node; } @@ -514,6 +517,21 @@ static Token *ast_parse_doc_comments(ParseContext *pc, Buf *buf) { return first_doc_token; } +static void ast_parse_container_doc_comments(ParseContext *pc, Buf *buf) { + if (buf_len(buf) != 0 && peek_token(pc)->id == TokenIdContainerDocComment) { + buf_append_char(buf, '\n'); + } + Token *doc_token = nullptr; + while ((doc_token = eat_token_if(pc, TokenIdContainerDocComment))) { + if (buf->list.length == 0) { + buf_resize(buf, 0); + } + // chops off '//!' but leaves '\n' + buf_append_mem(buf, buf_ptr(pc->buf) + doc_token->start_pos + 3, + doc_token->end_pos - doc_token->start_pos - 3); + } +} + // ContainerMembers // <- TestDecl ContainerMembers // / TopLevelComptime ContainerMembers @@ -523,7 +541,11 @@ static Token *ast_parse_doc_comments(ParseContext *pc, Buf *buf) { // / static AstNodeContainerDecl ast_parse_container_members(ParseContext *pc) { AstNodeContainerDecl res = {}; + Buf tld_doc_comment_buf = BUF_INIT; + buf_resize(&tld_doc_comment_buf, 0); for (;;) { + ast_parse_container_doc_comments(pc, &tld_doc_comment_buf); + AstNode *test_decl = ast_parse_test_decl(pc); if (test_decl != nullptr) { res.decls.append(test_decl); @@ -566,7 +588,7 @@ static AstNodeContainerDecl ast_parse_container_members(ParseContext *pc) { break; } - + res.doc_comments = tld_doc_comment_buf; return res; } @@ -1600,9 +1622,9 @@ static AstNode *ast_parse_primary_type_expr(ParseContext *pc) { if (container_decl != nullptr) return container_decl; - AstNode *enum_lit = ast_parse_enum_lit(pc); - if (enum_lit != nullptr) - return enum_lit; + AstNode *anon_lit = ast_parse_anon_lit(pc); + if (anon_lit != nullptr) + return anon_lit; AstNode *error_set_decl = ast_parse_error_set_decl(pc); if (error_set_decl != nullptr) @@ -1876,16 +1898,22 @@ static AstNode *ast_parse_asm_expr(ParseContext *pc) { return res; } -static AstNode *ast_parse_enum_lit(ParseContext *pc) { +static AstNode *ast_parse_anon_lit(ParseContext *pc) { Token *period = eat_token_if(pc, TokenIdDot); if (period == nullptr) return nullptr; - Token *identifier = expect_token(pc, TokenIdSymbol); - AstNode *res = ast_create_node(pc, NodeTypeEnumLiteral, period); - res->data.enum_literal.period = period; - res->data.enum_literal.identifier = identifier; - return res; + // anon enum literal + Token *identifier = eat_token_if(pc, TokenIdSymbol); + if (identifier != nullptr) { + AstNode *res = ast_create_node(pc, NodeTypeEnumLiteral, period); + res->data.enum_literal.period = period; + res->data.enum_literal.identifier = identifier; + return res; + } + + // anon container literal + return ast_parse_init_list(pc); } // AsmOutput <- COLON AsmOutputList AsmInput? @@ -2019,7 +2047,12 @@ static AstNode *ast_parse_field_init(ParseContext *pc) { if (first == nullptr) return nullptr; - Token *name = expect_token(pc, TokenIdSymbol); + Token *name = eat_token_if(pc, TokenIdSymbol); + if (name == nullptr) { + // Because of anon literals ".{" is also valid. + put_back_token(pc); + return nullptr; + } if (eat_token_if(pc, TokenIdEq) == nullptr) { // Because ".Name" can also be intepreted as an enum literal, we should put back // those two tokens again so that the parser can try to parse them as the enum @@ -2791,6 +2824,9 @@ static AstNode *ast_parse_container_decl_auto(ParseContext *pc) { res->data.container_decl.fields = members.fields; res->data.container_decl.decls = members.decls; + if (buf_len(&members.doc_comments) != 0) { + res->data.container_decl.doc_comments = members.doc_comments; + } return res; } diff --git a/src/range_set.cpp b/src/range_set.cpp index fd0076191b..9e621d2f13 100644 --- a/src/range_set.cpp +++ b/src/range_set.cpp @@ -40,6 +40,9 @@ void rangeset_sort(RangeSet *rs) { } bool rangeset_spans(RangeSet *rs, BigInt *first, BigInt *last) { + if (rs->src_range_list.length == 0) + return false; + rangeset_sort(rs); const Range *first_range = &rs->src_range_list.at(0).range; diff --git a/src/tokenizer.cpp b/src/tokenizer.cpp index 674f0c2b96..7ece5ff3fe 100644 --- a/src/tokenizer.cpp +++ b/src/tokenizer.cpp @@ -153,7 +153,6 @@ static const struct ZigKeyword zig_keywords[] = { {"undefined", TokenIdKeywordUndefined}, {"union", TokenIdKeywordUnion}, {"unreachable", TokenIdKeywordUnreachable}, - {"use", TokenIdKeywordUsingNamespace}, {"usingnamespace", TokenIdKeywordUsingNamespace}, {"var", TokenIdKeywordVar}, {"volatile", TokenIdKeywordVolatile}, @@ -199,6 +198,7 @@ enum TokenizeState { TokenizeStateSawSlash, TokenizeStateSawSlash2, TokenizeStateSawSlash3, + TokenizeStateSawSlashBang, TokenizeStateSawBackslash, TokenizeStateSawPercent, TokenizeStateSawPlus, @@ -210,6 +210,7 @@ enum TokenizeState { TokenizeStateSawBar, TokenizeStateSawBarBar, TokenizeStateDocComment, + TokenizeStateContainerDocComment, TokenizeStateLineComment, TokenizeStateLineString, TokenizeStateLineStringEnd, @@ -939,6 +940,9 @@ void tokenize(Buf *buf, Tokenization *out) { case '/': t.state = TokenizeStateSawSlash3; break; + case '!': + t.state = TokenizeStateSawSlashBang; + break; case '\n': cancel_token(&t); t.state = TokenizeStateStart; @@ -966,6 +970,19 @@ void tokenize(Buf *buf, Tokenization *out) { break; } break; + case TokenizeStateSawSlashBang: + switch (c) { + case '\n': + set_token_id(&t, t.cur_tok, TokenIdContainerDocComment); + end_token(&t); + t.state = TokenizeStateStart; + break; + default: + set_token_id(&t, t.cur_tok, TokenIdContainerDocComment); + t.state = TokenizeStateContainerDocComment; + break; + } + break; case TokenizeStateSawBackslash: switch (c) { case '\\': @@ -1056,6 +1073,17 @@ void tokenize(Buf *buf, Tokenization *out) { break; } break; + case TokenizeStateContainerDocComment: + switch (c) { + case '\n': + end_token(&t); + t.state = TokenizeStateStart; + break; + default: + // do nothing + break; + } + break; case TokenizeStateSymbolFirstC: switch (c) { case '"': @@ -1546,6 +1574,7 @@ void tokenize(Buf *buf, Tokenization *out) { case TokenizeStateSawBarBar: case TokenizeStateLBracket: case TokenizeStateDocComment: + case TokenizeStateContainerDocComment: end_token(&t); break; case TokenizeStateSawDotDot: @@ -1560,6 +1589,7 @@ void tokenize(Buf *buf, Tokenization *out) { case TokenizeStateLineComment: case TokenizeStateSawSlash2: case TokenizeStateSawSlash3: + case TokenizeStateSawSlashBang: break; } if (t.state != TokenizeStateError) { @@ -1607,6 +1637,7 @@ const char * token_name(TokenId id) { case TokenIdDash: return "-"; case TokenIdDivEq: return "/="; case TokenIdDocComment: return "DocComment"; + case TokenIdContainerDocComment: return "ContainerDocComment"; case TokenIdDot: return "."; case TokenIdDotStar: return ".*"; case TokenIdEllipsis2: return ".."; diff --git a/src/tokenizer.hpp b/src/tokenizer.hpp index ee336123bb..149e58b6a7 100644 --- a/src/tokenizer.hpp +++ b/src/tokenizer.hpp @@ -43,6 +43,7 @@ enum TokenId { TokenIdDash, TokenIdDivEq, TokenIdDocComment, + TokenIdContainerDocComment, TokenIdDot, TokenIdDotStar, TokenIdEllipsis2, diff --git a/src/translate_c.cpp b/src/translate_c.cpp index 6765bf45fb..3acfb05e85 100644 --- a/src/translate_c.cpp +++ b/src/translate_c.cpp @@ -221,6 +221,15 @@ static AstNode *trans_create_node_opaque(Context *c) { return trans_create_node_builtin_fn_call_str(c, "OpaqueType"); } +static AstNode *trans_create_node_cast(Context *c, AstNode *dest_type, AstNode *operand) { + AstNode *node = trans_create_node(c, NodeTypeFnCallExpr); + node->data.fn_call_expr.fn_ref_expr = trans_create_node_symbol(c, buf_create_from_str("as")); + node->data.fn_call_expr.modifier = CallModifierBuiltin; + node->data.fn_call_expr.params.append(dest_type); + node->data.fn_call_expr.params.append(operand); + return node; +} + static AstNode *trans_create_node_fn_call_1(Context *c, AstNode *fn_ref_expr, AstNode *arg1) { AstNode *node = trans_create_node(c, NodeTypeFnCallExpr); node->data.fn_call_expr.fn_ref_expr = fn_ref_expr; @@ -337,14 +346,6 @@ static AstNode *trans_create_node_unsigned(Context *c, uint64_t x) { return trans_create_node_unsigned_negative(c, x, false); } -static AstNode *trans_create_node_cast(Context *c, AstNode *dest, AstNode *src) { - AstNode *node = trans_create_node(c, NodeTypeFnCallExpr); - node->data.fn_call_expr.fn_ref_expr = dest; - node->data.fn_call_expr.params.resize(1); - node->data.fn_call_expr.params.items[0] = src; - return node; -} - static AstNode *trans_create_node_unsigned_negative_type(Context *c, uint64_t x, bool is_negative, const char *type_name) { @@ -701,7 +702,7 @@ static AstNode* trans_c_cast(Context *c, ZigClangSourceLocation source_location, if (c_is_unsigned_integer(c, dest_type) && qual_type_is_ptr(src_type)) { AstNode *addr_node = trans_create_node_builtin_fn_call_str(c, "ptrToInt"); addr_node->data.fn_call_expr.params.append(expr); - return trans_create_node_fn_call_1(c, trans_qual_type(c, dest_type, source_location), addr_node); + return trans_create_node_cast(c, trans_qual_type(c, dest_type, source_location), addr_node); } if (c_is_unsigned_integer(c, src_type) && qual_type_is_ptr(dest_type)) { AstNode *ptr_node = trans_create_node_builtin_fn_call_str(c, "intToPtr"); @@ -712,7 +713,7 @@ static AstNode* trans_c_cast(Context *c, ZigClangSourceLocation source_location, // TODO: maybe widen to increase size // TODO: maybe bitcast to change sign // TODO: maybe truncate to reduce size - return trans_create_node_fn_call_1(c, trans_qual_type(c, dest_type, source_location), expr); + return trans_create_node_cast(c, trans_qual_type(c, dest_type, source_location), expr); } static bool c_is_signed_integer(Context *c, ZigClangQualType qt) { @@ -1212,6 +1213,11 @@ static AstNode *trans_type(Context *c, const ZigClangType *ty, ZigClangSourceLoc const ZigClangAttributedType *attributed_ty = reinterpret_cast<const ZigClangAttributedType *>(ty); return trans_qual_type(c, ZigClangAttributedType_getEquivalentType(attributed_ty), source_loc); } + case ZigClangType_MacroQualified: + { + const ZigClangMacroQualifiedType *macroqualified_ty = reinterpret_cast<const ZigClangMacroQualifiedType *>(ty); + return trans_qual_type(c, ZigClangMacroQualifiedType_getModifiedType(macroqualified_ty), source_loc); + } case ZigClangType_IncompleteArray: { const ZigClangIncompleteArrayType *incomplete_array_ty = reinterpret_cast<const ZigClangIncompleteArrayType *>(ty); @@ -1261,7 +1267,6 @@ static AstNode *trans_type(Context *c, const ZigClangType *ty, ZigClangSourceLoc case ZigClangType_DeducedTemplateSpecialization: case ZigClangType_DependentAddressSpace: case ZigClangType_DependentVector: - case ZigClangType_MacroQualified: emit_warning(c, source_loc, "unsupported type: '%s'", ZigClangType_getTypeClassName(ty)); return nullptr; } @@ -1527,7 +1532,7 @@ static AstNode *trans_create_shift_op(Context *c, TransScope *scope, ZigClangQua AstNode *rhs = trans_expr(c, ResultUsedYes, scope, rhs_expr, TransRValue); if (rhs == nullptr) return nullptr; - AstNode *coerced_rhs = trans_create_node_fn_call_1(c, rhs_type, rhs); + AstNode *coerced_rhs = trans_create_node_cast(c, rhs_type, rhs); return trans_create_node_bin_op(c, lhs, bin_op, coerced_rhs); } @@ -1702,7 +1707,7 @@ static AstNode *trans_create_compound_assign_shift(Context *c, ResultUsed result AstNode *rhs = trans_expr(c, ResultUsedYes, scope, ZigClangCompoundAssignOperator_getRHS(stmt), TransRValue); if (rhs == nullptr) return nullptr; - AstNode *coerced_rhs = trans_create_node_fn_call_1(c, rhs_type, rhs); + AstNode *coerced_rhs = trans_create_node_cast(c, rhs_type, rhs); return trans_create_node_bin_op(c, lhs, assign_op, coerced_rhs); } else { @@ -1733,7 +1738,7 @@ static AstNode *trans_create_compound_assign_shift(Context *c, ResultUsed result AstNode *rhs = trans_expr(c, ResultUsedYes, &child_scope->base, ZigClangCompoundAssignOperator_getRHS(stmt), TransRValue); if (rhs == nullptr) return nullptr; - AstNode *coerced_rhs = trans_create_node_fn_call_1(c, rhs_type, rhs); + AstNode *coerced_rhs = trans_create_node_cast(c, rhs_type, rhs); // operation_type(*_ref) AstNode *operation_type_cast = trans_c_cast(c, rhs_location, @@ -2684,7 +2689,7 @@ static AstNode *to_enum_zero_cmp(Context *c, AstNode *expr, AstNode *enum_type) // @TagType(Enum)(0) AstNode *zero = trans_create_node_unsigned_negative(c, 0, false); - AstNode *casted_zero = trans_create_node_fn_call_1(c, tag_type, zero); + AstNode *casted_zero = trans_create_node_cast(c, tag_type, zero); // @bitCast(Enum, @TagType(Enum)(0)) AstNode *bitcast = trans_create_node_builtin_fn_call_str(c, "bitCast"); diff --git a/src/zig_clang.cpp b/src/zig_clang.cpp index 1025216dc9..3c04a2dc8a 100644 --- a/src/zig_clang.cpp +++ b/src/zig_clang.cpp @@ -2214,6 +2214,11 @@ struct ZigClangQualType ZigClangAttributedType_getEquivalentType(const struct Zi return bitcast(casted->getEquivalentType()); } +struct ZigClangQualType ZigClangMacroQualifiedType_getModifiedType(const struct ZigClangMacroQualifiedType *self) { + auto casted = reinterpret_cast<const clang::MacroQualifiedType *>(self); + return bitcast(casted->getModifiedType()); +} + struct ZigClangQualType ZigClangElaboratedType_getNamedType(const struct ZigClangElaboratedType *self) { auto casted = reinterpret_cast<const clang::ElaboratedType *>(self); return bitcast(casted->getNamedType()); diff --git a/src/zig_clang.h b/src/zig_clang.h index baa0105553..c4c5c378eb 100644 --- a/src/zig_clang.h +++ b/src/zig_clang.h @@ -112,6 +112,7 @@ struct ZigClangImplicitCastExpr; struct ZigClangIncompleteArrayType; struct ZigClangIntegerLiteral; struct ZigClangMacroDefinitionRecord; +struct ZigClangMacroQualifiedType; struct ZigClangMemberExpr; struct ZigClangNamedDecl; struct ZigClangNone; @@ -1004,6 +1005,8 @@ ZIG_EXTERN_C struct ZigClangQualType ZigClangParenType_getInnerType(const struct ZIG_EXTERN_C struct ZigClangQualType ZigClangAttributedType_getEquivalentType(const struct ZigClangAttributedType *); +ZIG_EXTERN_C struct ZigClangQualType ZigClangMacroQualifiedType_getModifiedType(const struct ZigClangMacroQualifiedType *); + ZIG_EXTERN_C struct ZigClangQualType ZigClangElaboratedType_getNamedType(const struct ZigClangElaboratedType *); ZIG_EXTERN_C enum ZigClangElaboratedTypeKeyword ZigClangElaboratedType_getKeyword(const struct ZigClangElaboratedType *); |
