From ac0cda8df81d5dc7d782ad8a32c0e5b064dd24ec Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Thu, 13 Sep 2018 13:48:41 -0400 Subject: add compile error for merging non- error sets closes #1509 --- test/compile_errors.zig | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'test/compile_errors.zig') diff --git a/test/compile_errors.zig b/test/compile_errors.zig index dda45a5897..8fb64e21e2 100644 --- a/test/compile_errors.zig +++ b/test/compile_errors.zig @@ -1,6 +1,19 @@ const tests = @import("tests.zig"); pub fn addCases(cases: *tests.CompileErrorContext) void { + cases.add( + "non error sets used in merge error sets operator", + \\export fn foo() void { + \\ const Errors = u8 || u16; + \\} + \\export fn bar() void { + \\ const Errors = error{} || u16; + \\} + , + ".tmp_source.zig:2:20: error: expected error set type, found 'u8'", + ".tmp_source.zig:5:31: error: expected error set type, found 'u16'", + ); + cases.add( "variable initialization compile error then referenced", \\fn Undeclared() type { -- cgit v1.2.3 From 7c3636aaa38e8efa77b73ba94362802517ea739e Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Thu, 13 Sep 2018 15:46:34 -0400 Subject: remove the scope parameter of setFloatMode also document that scopes inherit this value. See #367 See #1283 --- doc/langref.html.in | 18 ++++++++----- src/all_types.hpp | 2 +- src/codegen.cpp | 12 ++++----- src/ir.cpp | 72 ++++++++++++++++++------------------------------- test/cases/eval.zig | 2 +- test/compile_errors.zig | 4 +-- 6 files changed, 47 insertions(+), 63 deletions(-) (limited to 'test/compile_errors.zig') diff --git a/doc/langref.html.in b/doc/langref.html.in index 6f12f0339f..aefbfc5650 100644 --- a/doc/langref.html.in +++ b/doc/langref.html.in @@ -734,7 +734,7 @@ export fn foo_strict(x: f64) f64 { } export fn foo_optimized(x: f64) f64 { - @setFloatMode(this, builtin.FloatMode.Optimized); + @setFloatMode(builtin.FloatMode.Optimized); return x + big - big; } {#code_end#} @@ -6030,17 +6030,20 @@ test "foo" { {#see_also|comptime#} {#header_close#} {#header_open|@setFloatMode#} -
@setFloatMode(scope, mode: @import("builtin").FloatMode)
+
@setFloatMode(mode: @import("builtin").FloatMode)

- Sets the floating point mode for a given scope. Possible values are: + Sets the floating point mode of the current scope. Possible values are:

{#code_begin|syntax#} pub const FloatMode = enum { - Optimized, Strict, + Optimized, }; {#code_end#} +

+ The floating point mode is inherited by child scopes, and can be overridden in any scope. + You can set the floating point mode in a struct or module scope by using a comptime block. +

{#see_also|Floating Point Operations#} {#header_close#} {#header_open|@setGlobalLinkage#} diff --git a/src/all_types.hpp b/src/all_types.hpp index 8aa2718d30..27871156d6 100644 --- a/src/all_types.hpp +++ b/src/all_types.hpp @@ -3287,8 +3287,8 @@ static const size_t stack_trace_ptr_count = 30; enum FloatMode { - FloatModeOptimized, FloatModeStrict, + FloatModeOptimized, }; enum FnWalkId { diff --git a/src/codegen.cpp b/src/codegen.cpp index 4e28613285..38f31074d0 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -6729,7 +6729,7 @@ static void define_builtin_fns(CodeGen *g) { create_builtin_fn(g, BuiltinFnIdIntType, "IntType", 2); // TODO rename to Int create_builtin_fn(g, BuiltinFnIdSetCold, "setCold", 1); create_builtin_fn(g, BuiltinFnIdSetRuntimeSafety, "setRuntimeSafety", 1); - create_builtin_fn(g, BuiltinFnIdSetFloatMode, "setFloatMode", 2); + create_builtin_fn(g, BuiltinFnIdSetFloatMode, "setFloatMode", 1); create_builtin_fn(g, BuiltinFnIdPanic, "panic", 1); create_builtin_fn(g, BuiltinFnIdPtrCast, "ptrCast", 2); create_builtin_fn(g, BuiltinFnIdBitCast, "bitCast", 2); @@ -7115,11 +7115,11 @@ Buf *codegen_generate_builtin_source(CodeGen *g) { { buf_appendf(contents, "pub const FloatMode = enum {\n" - " Optimized,\n" " Strict,\n" + " Optimized,\n" "};\n\n"); - assert(FloatModeOptimized == 0); - assert(FloatModeStrict == 1); + assert(FloatModeStrict == 0); + assert(FloatModeOptimized == 1); } { buf_appendf(contents, @@ -7127,8 +7127,8 @@ Buf *codegen_generate_builtin_source(CodeGen *g) { " Big,\n" " Little,\n" "};\n\n"); - assert(FloatModeOptimized == 0); - assert(FloatModeStrict == 1); + //assert(EndianBig == 0); + //assert(EndianLittle == 1); } { const char *endian_str = g->is_big_endian ? "Endian.Big" : "Endian.Little"; diff --git a/src/ir.cpp b/src/ir.cpp index b432facb36..6f1a7a741a 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -1577,13 +1577,11 @@ static IrInstruction *ir_build_set_runtime_safety(IrBuilder *irb, Scope *scope, } static IrInstruction *ir_build_set_float_mode(IrBuilder *irb, Scope *scope, AstNode *source_node, - IrInstruction *scope_value, IrInstruction *mode_value) + IrInstruction *mode_value) { IrInstructionSetFloatMode *instruction = ir_build_instruction(irb, scope, source_node); - instruction->scope_value = scope_value; instruction->mode_value = mode_value; - ir_ref_instruction(scope_value, irb->current_basic_block); ir_ref_instruction(mode_value, irb->current_basic_block); return &instruction->base; @@ -3959,12 +3957,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo 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; - - IrInstruction *set_float_mode = ir_build_set_float_mode(irb, scope, node, arg0_value, arg1_value); + IrInstruction *set_float_mode = ir_build_set_float_mode(irb, scope, node, arg0_value); return ir_lval_wrap(irb, scope, set_float_mode, lval); } case BuiltinFnIdSizeof: @@ -15379,6 +15372,7 @@ static ZigType *ir_analyze_instruction_set_cold(IrAnalyze *ira, IrInstructionSet ir_build_const_from(ira, &instruction->base); return ira->codegen->builtin_types.entry_void; } + static ZigType *ir_analyze_instruction_set_runtime_safety(IrAnalyze *ira, IrInstructionSetRuntimeSafety *set_runtime_safety_instruction) { @@ -15439,14 +15433,6 @@ static ZigType *ir_analyze_instruction_set_runtime_safety(IrAnalyze *ira, static ZigType *ir_analyze_instruction_set_float_mode(IrAnalyze *ira, IrInstructionSetFloatMode *instruction) { - IrInstruction *target_instruction = instruction->scope_value->other; - ZigType *target_type = target_instruction->value.type; - if (type_is_invalid(target_type)) - return ira->codegen->builtin_types.entry_invalid; - ConstExprValue *target_val = ir_resolve_const(ira, target_instruction, UndefBad); - if (!target_val) - return ira->codegen->builtin_types.entry_invalid; - if (ira->new_irb.exec->is_inline) { // ignore setFloatMode when running functions at compile time ir_build_const_from(ira, &instruction->base); @@ -15455,40 +15441,34 @@ static ZigType *ir_analyze_instruction_set_float_mode(IrAnalyze *ira, bool *fast_math_on_ptr; AstNode **fast_math_set_node_ptr; - if (target_type->id == ZigTypeIdBlock) { - ScopeBlock *block_scope = (ScopeBlock *)target_val->data.x_block; - fast_math_on_ptr = &block_scope->fast_math_on; - fast_math_set_node_ptr = &block_scope->fast_math_set_node; - } else if (target_type->id == ZigTypeIdFn) { - assert(target_val->data.x_ptr.special == ConstPtrSpecialFunction); - ZigFn *target_fn = target_val->data.x_ptr.data.fn.fn_entry; - assert(target_fn->def_scope); - fast_math_on_ptr = &target_fn->def_scope->fast_math_on; - fast_math_set_node_ptr = &target_fn->def_scope->fast_math_set_node; - } else if (target_type->id == ZigTypeIdMetaType) { - ScopeDecls *decls_scope; - ZigType *type_arg = target_val->data.x_type; - if (type_arg->id == ZigTypeIdStruct) { - decls_scope = type_arg->data.structure.decls_scope; - } else if (type_arg->id == ZigTypeIdEnum) { - decls_scope = type_arg->data.enumeration.decls_scope; - } else if (type_arg->id == ZigTypeIdUnion) { - decls_scope = type_arg->data.unionation.decls_scope; + + Scope *scope = instruction->base.scope; + while (scope != nullptr) { + if (scope->id == ScopeIdBlock) { + ScopeBlock *block_scope = (ScopeBlock *)scope; + fast_math_on_ptr = &block_scope->fast_math_on; + fast_math_set_node_ptr = &block_scope->fast_math_set_node; + break; + } else if (scope->id == ScopeIdFnDef) { + ScopeFnDef *def_scope = (ScopeFnDef *)scope; + ZigFn *target_fn = def_scope->fn_entry; + assert(target_fn->def_scope != nullptr); + fast_math_on_ptr = &target_fn->def_scope->fast_math_on; + fast_math_set_node_ptr = &target_fn->def_scope->fast_math_set_node; + break; + } else if (scope->id == ScopeIdDecls) { + ScopeDecls *decls_scope = (ScopeDecls *)scope; + fast_math_on_ptr = &decls_scope->fast_math_on; + fast_math_set_node_ptr = &decls_scope->fast_math_set_node; + break; } else { - ir_add_error_node(ira, target_instruction->source_node, - buf_sprintf("expected scope reference, found type '%s'", buf_ptr(&type_arg->name))); - return ira->codegen->builtin_types.entry_invalid; + scope = scope->parent; + continue; } - fast_math_on_ptr = &decls_scope->fast_math_on; - fast_math_set_node_ptr = &decls_scope->fast_math_set_node; - } else { - ir_add_error_node(ira, target_instruction->source_node, - buf_sprintf("expected scope reference, found type '%s'", buf_ptr(&target_type->name))); - return ira->codegen->builtin_types.entry_invalid; } + assert(scope != nullptr); IrInstruction *float_mode_value = instruction->mode_value->other; - FloatMode float_mode_scalar; if (!ir_resolve_float_mode(ira, float_mode_value, &float_mode_scalar)) return ira->codegen->builtin_types.entry_invalid; diff --git a/test/cases/eval.zig b/test/cases/eval.zig index b8d80bda02..4286821183 100644 --- a/test/cases/eval.zig +++ b/test/cases/eval.zig @@ -275,7 +275,7 @@ test "eval @setFloatMode at compile-time" { } fn fnWithFloatMode() f32 { - @setFloatMode(this, builtin.FloatMode.Strict); + @setFloatMode(builtin.FloatMode.Strict); return 1234.0; } diff --git a/test/compile_errors.zig b/test/compile_errors.zig index 8fb64e21e2..750794c909 100644 --- a/test/compile_errors.zig +++ b/test/compile_errors.zig @@ -3996,8 +3996,8 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { cases.add( "@setFloatMode twice for same scope", \\export fn foo() void { - \\ @setFloatMode(this, @import("builtin").FloatMode.Optimized); - \\ @setFloatMode(this, @import("builtin").FloatMode.Optimized); + \\ @setFloatMode(@import("builtin").FloatMode.Optimized); + \\ @setFloatMode(@import("builtin").FloatMode.Optimized); \\} , ".tmp_source.zig:3:5: error: float mode set twice for same scope", -- cgit v1.2.3 From c06a61e9bf93810174255474598cfeae785cfbd6 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Thu, 13 Sep 2018 16:34:33 -0400 Subject: remove `this`. add `@This()`. closes #1283 --- doc/langref.html.in | 13 ++------ src-self-hosted/type.zig | 12 ------- src/all_types.hpp | 4 +-- src/analyze.cpp | 68 +++----------------------------------- src/analyze.hpp | 1 - src/ast_render.cpp | 7 ---- src/codegen.cpp | 13 +------- src/ir.cpp | 81 ++++++++++++---------------------------------- src/parser.cpp | 9 +----- src/tokenizer.cpp | 2 -- src/tokenizer.hpp | 1 - std/array_list.zig | 2 +- std/atomic/int.zig | 2 +- std/atomic/queue.zig | 2 +- std/atomic/stack.zig | 2 +- std/build.zig | 2 +- std/crypto/blake2.zig | 4 +-- std/crypto/hmac.zig | 2 +- std/crypto/md5.zig | 2 +- std/crypto/poly1305.zig | 2 +- std/crypto/sha1.zig | 2 +- std/crypto/sha2.zig | 4 +-- std/crypto/sha3.zig | 2 +- std/event/channel.zig | 2 +- std/event/fs.zig | 2 +- std/event/future.zig | 2 +- std/event/group.zig | 2 +- std/event/locked.zig | 2 +- std/event/rwlocked.zig | 2 +- std/event/tcp.zig | 2 +- std/fmt/index.zig | 2 +- std/hash/crc.zig | 4 +-- std/hash/fnv.zig | 2 +- std/hash/siphash.zig | 2 +- std/hash_map.zig | 4 +-- std/heap.zig | 2 +- std/io.zig | 12 +++---- std/lazy_init.zig | 2 +- std/linked_list.zig | 2 +- std/math/complex/index.zig | 2 +- std/mem.zig | 2 +- std/net.zig | 2 +- std/os/index.zig | 2 +- std/segmented_list.zig | 2 +- std/zig/ast.zig | 4 +-- std/zig/parser_test.zig | 2 +- std/zig/render.zig | 2 +- test/cases/cast.zig | 4 +-- test/cases/eval.zig | 2 +- test/cases/misc.zig | 3 -- test/cases/reflection.zig | 2 +- test/cases/struct.zig | 4 +-- test/cases/this.zig | 13 ++------ test/cases/type_info.zig | 4 +-- test/compile_errors.zig | 28 ++++++++-------- 55 files changed, 97 insertions(+), 266 deletions(-) (limited to 'test/compile_errors.zig') diff --git a/doc/langref.html.in b/doc/langref.html.in index aefbfc5650..3f2e741e36 100644 --- a/doc/langref.html.in +++ b/doc/langref.html.in @@ -478,13 +478,9 @@ pub fn main() void { undefined used to leave a value unspecified - - this - refers to the thing in immediate scope - - {#see_also|Optionals|this#} + {#see_also|Optionals#} {#header_close#} {#header_open|String Literals#} {#code_begin|test#} @@ -4186,11 +4182,6 @@ fn foo() void {} {#code_end#} {#header_close#} - {#header_open|this#} -

TODO: example of this referring to Self struct

-

TODO: example of this referring to recursion function

-

TODO: example of this referring to basic block for @setRuntimeSafety

- {#header_close#} {#header_open|comptime#}

Zig places importance on the concept of whether an expression is known at compile-time. @@ -7744,7 +7735,7 @@ ArrayType : "[" option(Expression) "]" option("align" "(" Expression option(":" GroupedExpression = "(" Expression ")" -KeywordLiteral = "true" | "false" | "null" | "undefined" | "error" | "this" | "unreachable" | "suspend" +KeywordLiteral = "true" | "false" | "null" | "undefined" | "error" | "unreachable" | "suspend" ErrorSetDecl = "error" "{" list(Symbol, ",") "}" diff --git a/src-self-hosted/type.zig b/src-self-hosted/type.zig index 47dd3772e5..aa00bb876d 100644 --- a/src-self-hosted/type.zig +++ b/src-self-hosted/type.zig @@ -40,7 +40,6 @@ pub const Type = struct { Id.Enum => @fieldParentPtr(Enum, "base", base).destroy(comp), Id.Union => @fieldParentPtr(Union, "base", base).destroy(comp), Id.Namespace => @fieldParentPtr(Namespace, "base", base).destroy(comp), - Id.Block => @fieldParentPtr(Block, "base", base).destroy(comp), Id.BoundFn => @fieldParentPtr(BoundFn, "base", base).destroy(comp), Id.ArgTuple => @fieldParentPtr(ArgTuple, "base", base).destroy(comp), Id.Opaque => @fieldParentPtr(Opaque, "base", base).destroy(comp), @@ -74,7 +73,6 @@ pub const Type = struct { Id.Enum => return @fieldParentPtr(Enum, "base", base).getLlvmType(allocator, llvm_context), Id.Union => return @fieldParentPtr(Union, "base", base).getLlvmType(allocator, llvm_context), Id.Namespace => unreachable, - Id.Block => unreachable, Id.BoundFn => return @fieldParentPtr(BoundFn, "base", base).getLlvmType(allocator, llvm_context), Id.ArgTuple => unreachable, Id.Opaque => return @fieldParentPtr(Opaque, "base", base).getLlvmType(allocator, llvm_context), @@ -90,7 +88,6 @@ pub const Type = struct { Id.Undefined, Id.Null, Id.Namespace, - Id.Block, Id.BoundFn, Id.ArgTuple, Id.Opaque, @@ -124,7 +121,6 @@ pub const Type = struct { Id.Undefined, Id.Null, Id.Namespace, - Id.Block, Id.BoundFn, Id.ArgTuple, Id.Opaque, @@ -1012,14 +1008,6 @@ pub const Type = struct { } }; - pub const Block = struct { - base: Type, - - pub fn destroy(self: *Block, comp: *Compilation) void { - comp.gpa().destroy(self); - } - }; - pub const BoundFn = struct { base: Type, diff --git a/src/all_types.hpp b/src/all_types.hpp index 27871156d6..fefbae0fe3 100644 --- a/src/all_types.hpp +++ b/src/all_types.hpp @@ -283,7 +283,6 @@ struct ConstExprValue { ConstArrayValue x_array; ConstPtrValue x_ptr; ImportTableEntry *x_import; - Scope *x_block; ConstArgTuple x_arg_tuple; // populated if special == ConstValSpecialRuntime @@ -413,7 +412,6 @@ enum NodeType { NodeTypeBoolLiteral, NodeTypeNullLiteral, NodeTypeUndefinedLiteral, - NodeTypeThisLiteral, NodeTypeUnreachable, NodeTypeIfBoolExpr, NodeTypeWhileExpr, @@ -1205,7 +1203,6 @@ enum ZigTypeId { ZigTypeIdUnion, ZigTypeIdFn, ZigTypeIdNamespace, - ZigTypeIdBlock, ZigTypeIdBoundFn, ZigTypeIdArgTuple, ZigTypeIdOpaque, @@ -1413,6 +1410,7 @@ enum BuiltinFnId { BuiltinFnIdSetEvalBranchQuota, BuiltinFnIdAlignCast, BuiltinFnIdOpaqueType, + BuiltinFnIdThis, BuiltinFnIdSetAlignStack, BuiltinFnIdArgType, BuiltinFnIdExport, diff --git a/src/analyze.cpp b/src/analyze.cpp index 9a9e9a0513..9af4f7347c 100644 --- a/src/analyze.cpp +++ b/src/analyze.cpp @@ -246,7 +246,6 @@ AstNode *type_decl_node(ZigType *type_entry) { case ZigTypeIdErrorSet: case ZigTypeIdFn: case ZigTypeIdNamespace: - case ZigTypeIdBlock: case ZigTypeIdBoundFn: case ZigTypeIdArgTuple: case ZigTypeIdPromise: @@ -284,7 +283,6 @@ bool type_is_complete(ZigType *type_entry) { case ZigTypeIdErrorSet: case ZigTypeIdFn: case ZigTypeIdNamespace: - case ZigTypeIdBlock: case ZigTypeIdBoundFn: case ZigTypeIdArgTuple: case ZigTypeIdPromise: @@ -320,7 +318,6 @@ bool type_has_zero_bits_known(ZigType *type_entry) { case ZigTypeIdErrorSet: case ZigTypeIdFn: case ZigTypeIdNamespace: - case ZigTypeIdBlock: case ZigTypeIdBoundFn: case ZigTypeIdArgTuple: case ZigTypeIdOpaque: @@ -1414,7 +1411,6 @@ static bool type_allowed_in_packed_struct(ZigType *type_entry) { case ZigTypeIdErrorUnion: case ZigTypeIdErrorSet: case ZigTypeIdNamespace: - case ZigTypeIdBlock: case ZigTypeIdBoundFn: case ZigTypeIdArgTuple: case ZigTypeIdOpaque: @@ -1455,7 +1451,6 @@ static bool type_allowed_in_extern(CodeGen *g, ZigType *type_entry) { case ZigTypeIdErrorUnion: case ZigTypeIdErrorSet: case ZigTypeIdNamespace: - case ZigTypeIdBlock: case ZigTypeIdBoundFn: case ZigTypeIdArgTuple: case ZigTypeIdPromise: @@ -1613,7 +1608,6 @@ static ZigType *analyze_fn_type(CodeGen *g, AstNode *proto_node, Scope *child_sc case ZigTypeIdComptimeFloat: case ZigTypeIdComptimeInt: case ZigTypeIdNamespace: - case ZigTypeIdBlock: case ZigTypeIdBoundFn: case ZigTypeIdMetaType: case ZigTypeIdVoid: @@ -1703,7 +1697,6 @@ static ZigType *analyze_fn_type(CodeGen *g, AstNode *proto_node, Scope *child_sc case ZigTypeIdComptimeFloat: case ZigTypeIdComptimeInt: case ZigTypeIdNamespace: - case ZigTypeIdBlock: case ZigTypeIdBoundFn: case ZigTypeIdMetaType: case ZigTypeIdUnreachable: @@ -3437,7 +3430,6 @@ void scan_decls(CodeGen *g, ScopeDecls *decls_scope, AstNode *node) { case NodeTypeBoolLiteral: case NodeTypeNullLiteral: case NodeTypeUndefinedLiteral: - case NodeTypeThisLiteral: case NodeTypeSymbol: case NodeTypePrefixOpExpr: case NodeTypePointerType: @@ -3497,7 +3489,6 @@ ZigType *validate_var_type(CodeGen *g, AstNode *source_node, ZigType *type_entry case ZigTypeIdUnreachable: case ZigTypeIdUndefined: case ZigTypeIdNull: - case ZigTypeIdBlock: case ZigTypeIdArgTuple: case ZigTypeIdOpaque: add_node_error(g, source_node, buf_sprintf("variable of type '%s' not allowed", @@ -3798,34 +3789,6 @@ ZigFn *scope_fn_entry(Scope *scope) { return nullptr; } -ZigFn *scope_get_fn_if_root(Scope *scope) { - assert(scope); - scope = scope->parent; - while (scope) { - switch (scope->id) { - case ScopeIdBlock: - return nullptr; - case ScopeIdDecls: - case ScopeIdDefer: - case ScopeIdDeferExpr: - case ScopeIdVarDecl: - case ScopeIdCImport: - case ScopeIdLoop: - case ScopeIdSuspend: - case ScopeIdCompTime: - case ScopeIdCoroPrelude: - case ScopeIdRuntime: - scope = scope->parent; - continue; - case ScopeIdFnDef: - ScopeFnDef *fn_scope = (ScopeFnDef *)scope; - return fn_scope->fn_entry; - } - zig_unreachable(); - } - return nullptr; -} - TypeEnumField *find_enum_type_field(ZigType *enum_type, Buf *name) { assert(enum_type->id == ZigTypeIdEnum); if (enum_type->data.enumeration.src_field_count == 0) @@ -3907,7 +3870,6 @@ static bool is_container(ZigType *type_entry) { case ZigTypeIdErrorSet: case ZigTypeIdFn: case ZigTypeIdNamespace: - case ZigTypeIdBlock: case ZigTypeIdBoundFn: case ZigTypeIdArgTuple: case ZigTypeIdOpaque: @@ -3966,7 +3928,6 @@ void resolve_container_type(CodeGen *g, ZigType *type_entry) { case ZigTypeIdErrorSet: case ZigTypeIdFn: case ZigTypeIdNamespace: - case ZigTypeIdBlock: case ZigTypeIdBoundFn: case ZigTypeIdInvalid: case ZigTypeIdArgTuple: @@ -4427,7 +4388,6 @@ bool handle_is_ptr(ZigType *type_entry) { case ZigTypeIdUndefined: case ZigTypeIdNull: case ZigTypeIdNamespace: - case ZigTypeIdBlock: case ZigTypeIdBoundFn: case ZigTypeIdArgTuple: case ZigTypeIdOpaque: @@ -4842,8 +4802,6 @@ static uint32_t hash_const_val(ConstExprValue *const_val) { return const_val->data.x_err_set->value ^ 2630160122; case ZigTypeIdNamespace: return hash_ptr(const_val->data.x_import); - case ZigTypeIdBlock: - return hash_ptr(const_val->data.x_block); case ZigTypeIdBoundFn: case ZigTypeIdInvalid: case ZigTypeIdUnreachable: @@ -4904,7 +4862,6 @@ static bool can_mutate_comptime_var_state(ConstExprValue *value) { case ZigTypeIdNamespace: case ZigTypeIdBoundFn: case ZigTypeIdFn: - case ZigTypeIdBlock: case ZigTypeIdOpaque: case ZigTypeIdPromise: case ZigTypeIdErrorSet: @@ -4971,7 +4928,6 @@ static bool return_type_is_cacheable(ZigType *return_type) { case ZigTypeIdNamespace: case ZigTypeIdBoundFn: case ZigTypeIdFn: - case ZigTypeIdBlock: case ZigTypeIdOpaque: case ZigTypeIdPromise: case ZigTypeIdErrorSet: @@ -5083,7 +5039,6 @@ bool type_requires_comptime(ZigType *type_entry) { case ZigTypeIdNull: case ZigTypeIdMetaType: case ZigTypeIdNamespace: - case ZigTypeIdBlock: case ZigTypeIdBoundFn: case ZigTypeIdArgTuple: return true; @@ -5615,8 +5570,6 @@ bool const_values_equal(ConstExprValue *a, ConstExprValue *b) { zig_panic("TODO"); case ZigTypeIdNamespace: return a->data.x_import == b->data.x_import; - case ZigTypeIdBlock: - return a->data.x_block == b->data.x_block; case ZigTypeIdArgTuple: return a->data.x_arg_tuple.start_index == b->data.x_arg_tuple.start_index && a->data.x_arg_tuple.end_index == b->data.x_arg_tuple.end_index; @@ -5795,12 +5748,6 @@ void render_const_value(CodeGen *g, Buf *buf, ConstExprValue *const_val) { } case ZigTypeIdPointer: return render_const_val_ptr(g, buf, const_val, type_entry); - case ZigTypeIdBlock: - { - AstNode *node = const_val->data.x_block->source_node; - buf_appendf(buf, "(scope:%" ZIG_PRI_usize ":%" ZIG_PRI_usize ")", node->line + 1, node->column + 1); - return; - } case ZigTypeIdArray: { ZigType *child_type = type_entry->data.array.child_type; @@ -5980,7 +5927,6 @@ uint32_t type_id_hash(TypeId x) { case ZigTypeIdUnion: case ZigTypeIdFn: case ZigTypeIdNamespace: - case ZigTypeIdBlock: case ZigTypeIdBoundFn: case ZigTypeIdArgTuple: case ZigTypeIdPromise: @@ -6027,7 +5973,6 @@ bool type_id_eql(TypeId a, TypeId b) { case ZigTypeIdUnion: case ZigTypeIdFn: case ZigTypeIdNamespace: - case ZigTypeIdBlock: case ZigTypeIdBoundFn: case ZigTypeIdArgTuple: case ZigTypeIdOpaque: @@ -6153,7 +6098,6 @@ static const ZigTypeId all_type_ids[] = { ZigTypeIdUnion, ZigTypeIdFn, ZigTypeIdNamespace, - ZigTypeIdBlock, ZigTypeIdBoundFn, ZigTypeIdArgTuple, ZigTypeIdOpaque, @@ -6215,16 +6159,14 @@ size_t type_id_index(ZigType *entry) { return 18; case ZigTypeIdNamespace: return 19; - case ZigTypeIdBlock: - return 20; case ZigTypeIdBoundFn: - return 21; + return 20; case ZigTypeIdArgTuple: - return 22; + return 21; case ZigTypeIdOpaque: - return 23; + return 22; case ZigTypeIdPromise: - return 24; + return 23; } zig_unreachable(); } @@ -6273,8 +6215,6 @@ const char *type_id_name(ZigTypeId id) { return "Fn"; case ZigTypeIdNamespace: return "Namespace"; - case ZigTypeIdBlock: - return "Block"; case ZigTypeIdBoundFn: return "BoundFn"; case ZigTypeIdArgTuple: diff --git a/src/analyze.hpp b/src/analyze.hpp index d69265f974..02f3d65800 100644 --- a/src/analyze.hpp +++ b/src/analyze.hpp @@ -87,7 +87,6 @@ ZigFn *create_fn(AstNode *proto_node); ZigFn *create_fn_raw(FnInline inline_value, GlobalLinkageId linkage); void init_fn_type_id(FnTypeId *fn_type_id, AstNode *proto_node, size_t param_count_alloc); AstNode *get_param_decl_node(ZigFn *fn_entry, size_t index); -ZigFn *scope_get_fn_if_root(Scope *scope); bool type_requires_comptime(ZigType *type_entry); Error ATTRIBUTE_MUST_USE ensure_complete_type(CodeGen *g, ZigType *type_entry); Error ATTRIBUTE_MUST_USE type_ensure_zero_bits_known(CodeGen *g, ZigType *type_entry); diff --git a/src/ast_render.cpp b/src/ast_render.cpp index 984b4230b1..37d4221eef 100644 --- a/src/ast_render.cpp +++ b/src/ast_render.cpp @@ -193,8 +193,6 @@ static const char *node_type_str(NodeType node_type) { return "NullLiteral"; case NodeTypeUndefinedLiteral: return "UndefinedLiteral"; - case NodeTypeThisLiteral: - return "ThisLiteral"; case NodeTypeIfBoolExpr: return "IfBoolExpr"; case NodeTypeWhileExpr: @@ -897,11 +895,6 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) { } break; } - case NodeTypeThisLiteral: - { - fprintf(ar->f, "this"); - break; - } case NodeTypeBoolLiteral: { const char *bool_str = node->data.bool_literal.value ? "true" : "false"; diff --git a/src/codegen.cpp b/src/codegen.cpp index 38f31074d0..86ede7411d 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -5479,7 +5479,6 @@ static LLVMValueRef pack_const_int(CodeGen *g, LLVMTypeRef big_int_type_ref, Con case ZigTypeIdErrorUnion: case ZigTypeIdErrorSet: case ZigTypeIdNamespace: - case ZigTypeIdBlock: case ZigTypeIdBoundFn: case ZigTypeIdArgTuple: case ZigTypeIdVoid: @@ -5954,7 +5953,6 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val, const c case ZigTypeIdUndefined: case ZigTypeIdNull: case ZigTypeIdNamespace: - case ZigTypeIdBlock: case ZigTypeIdBoundFn: case ZigTypeIdArgTuple: case ZigTypeIdOpaque: @@ -6477,12 +6475,6 @@ static void define_builtin_types(CodeGen *g) { entry->zero_bits = true; g->builtin_types.entry_namespace = entry; } - { - ZigType *entry = new_type_table_entry(ZigTypeIdBlock); - buf_init_from_str(&entry->name, "(block)"); - entry->zero_bits = true; - g->builtin_types.entry_block = entry; - } { ZigType *entry = new_type_table_entry(ZigTypeIdComptimeFloat); buf_init_from_str(&entry->name, "comptime_float"); @@ -6763,6 +6755,7 @@ static void define_builtin_fns(CodeGen *g) { create_builtin_fn(g, BuiltinFnIdErrSetCast, "errSetCast", 2); create_builtin_fn(g, BuiltinFnIdToBytes, "sliceToBytes", 1); create_builtin_fn(g, BuiltinFnIdFromBytes, "bytesToSlice", 2); + create_builtin_fn(g, BuiltinFnIdThis, "This", 0); } static const char *bool_to_str(bool b) { @@ -6944,7 +6937,6 @@ Buf *codegen_generate_builtin_source(CodeGen *g) { " Union: Union,\n" " Fn: Fn,\n" " Namespace: void,\n" - " Block: void,\n" " BoundFn: Fn,\n" " ArgTuple: void,\n" " Opaque: void,\n" @@ -7589,7 +7581,6 @@ static void prepend_c_type_to_decl_list(CodeGen *g, GenH *gen_h, ZigType *type_e case ZigTypeIdUndefined: case ZigTypeIdNull: case ZigTypeIdNamespace: - case ZigTypeIdBlock: case ZigTypeIdBoundFn: case ZigTypeIdArgTuple: case ZigTypeIdErrorUnion: @@ -7768,7 +7759,6 @@ static void get_c_type(CodeGen *g, GenH *gen_h, ZigType *type_entry, Buf *out_bu case ZigTypeIdMetaType: case ZigTypeIdBoundFn: case ZigTypeIdNamespace: - case ZigTypeIdBlock: case ZigTypeIdComptimeFloat: case ZigTypeIdComptimeInt: case ZigTypeIdUndefined: @@ -7921,7 +7911,6 @@ static void gen_h_file(CodeGen *g) { case ZigTypeIdErrorUnion: case ZigTypeIdErrorSet: case ZigTypeIdNamespace: - case ZigTypeIdBlock: case ZigTypeIdBoundFn: case ZigTypeIdArgTuple: case ZigTypeIdOptional: diff --git a/src/ir.cpp b/src/ir.cpp index 6f1a7a741a..7448d3fffe 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -1029,12 +1029,6 @@ static IrInstruction *ir_create_const_fn(IrBuilder *irb, Scope *scope, AstNode * return &const_instruction->base; } -static IrInstruction *ir_build_const_fn(IrBuilder *irb, Scope *scope, AstNode *source_node, ZigFn *fn_entry) { - IrInstruction *instruction = ir_create_const_fn(irb, scope, source_node, fn_entry); - ir_instruction_append(irb->current_basic_block, instruction); - return instruction; -} - static IrInstruction *ir_build_const_import(IrBuilder *irb, Scope *scope, AstNode *source_node, ImportTableEntry *import) { IrInstructionConst *const_instruction = ir_build_instruction(irb, scope, source_node); const_instruction->base.value.type = irb->codegen->builtin_types.entry_namespace; @@ -1043,16 +1037,6 @@ static IrInstruction *ir_build_const_import(IrBuilder *irb, Scope *scope, AstNod return &const_instruction->base; } -static IrInstruction *ir_build_const_scope(IrBuilder *irb, Scope *parent_scope, AstNode *source_node, - Scope *target_scope) -{ - IrInstructionConst *const_instruction = ir_build_instruction(irb, parent_scope, source_node); - const_instruction->base.value.type = irb->codegen->builtin_types.entry_block; - const_instruction->base.value.special = ConstValSpecialStatic; - const_instruction->base.value.data.x_block = target_scope; - return &const_instruction->base; -} - static IrInstruction *ir_build_const_bool(IrBuilder *irb, Scope *scope, AstNode *source_node, bool value) { IrInstructionConst *const_instruction = ir_build_instruction(irb, scope, source_node); const_instruction->base.value.type = irb->codegen->builtin_types.entry_bool; @@ -3892,6 +3876,21 @@ static IrInstruction *ir_gen_overflow_op(IrBuilder *irb, Scope *scope, AstNode * return ir_build_overflow_op(irb, scope, node, op, type_value, op1, op2, result_ptr, nullptr); } +static IrInstruction *ir_gen_this(IrBuilder *irb, Scope *orig_scope, AstNode *node) { + for (Scope *it_scope = orig_scope; it_scope != nullptr; it_scope = it_scope->parent) { + if (it_scope->id == ScopeIdDecls) { + ScopeDecls *decls_scope = (ScopeDecls *)it_scope; + ZigType *container_type = decls_scope->container_type; + if (container_type != nullptr) { + return ir_build_const_type(irb, orig_scope, node, container_type); + } else { + return ir_build_const_import(irb, orig_scope, node, decls_scope->import); + } + } + } + zig_unreachable(); +} + static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNode *node, LVal lval) { assert(node->type == NodeTypeFnCallExpr); @@ -4830,6 +4829,11 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo IrInstruction *opaque_type = ir_build_opaque_type(irb, scope, node); return ir_lval_wrap(irb, scope, opaque_type, lval); } + case BuiltinFnIdThis: + { + IrInstruction *this_inst = ir_gen_this(irb, scope, node); + return ir_lval_wrap(irb, scope, this_inst, lval); + } case BuiltinFnIdSetAlignStack: { AstNode *arg0_node = node->data.fn_call_expr.params.at(0); @@ -5681,33 +5685,6 @@ static IrInstruction *ir_gen_for_expr(IrBuilder *irb, Scope *parent_scope, AstNo return ir_build_phi(irb, parent_scope, node, incoming_blocks.length, incoming_blocks.items, incoming_values.items); } -static IrInstruction *ir_gen_this_literal(IrBuilder *irb, Scope *scope, AstNode *node) { - assert(node->type == NodeTypeThisLiteral); - - if (!scope->parent) - return ir_build_const_import(irb, scope, node, node->owner); - - ZigFn *fn_entry = scope_get_fn_if_root(scope); - if (fn_entry) - return ir_build_const_fn(irb, scope, node, fn_entry); - - while (scope->id != ScopeIdBlock && scope->id != ScopeIdDecls) { - scope = scope->parent; - } - - if (scope->id == ScopeIdDecls) { - ScopeDecls *decls_scope = (ScopeDecls *)scope; - ZigType *container_type = decls_scope->container_type; - assert(container_type); - return ir_build_const_type(irb, scope, node, container_type); - } - - if (scope->id == ScopeIdBlock) - return ir_build_const_scope(irb, scope, node, scope); - - zig_unreachable(); -} - static IrInstruction *ir_gen_bool_literal(IrBuilder *irb, Scope *scope, AstNode *node) { assert(node->type == NodeTypeBoolLiteral); return ir_build_const_bool(irb, scope, node, node->data.bool_literal.value); @@ -7285,8 +7262,6 @@ static IrInstruction *ir_gen_node_raw(IrBuilder *irb, AstNode *node, Scope *scop return ir_build_load_ptr(irb, scope, node, unwrapped_ptr); } - case NodeTypeThisLiteral: - return ir_lval_wrap(irb, scope, ir_gen_this_literal(irb, scope, node), lval); case NodeTypeBoolLiteral: return ir_lval_wrap(irb, scope, ir_gen_bool_literal(irb, scope, node), lval); case NodeTypeArrayType: @@ -11621,7 +11596,6 @@ static ZigType *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp *bin_op case ZigTypeIdFn: case ZigTypeIdOpaque: case ZigTypeIdNamespace: - case ZigTypeIdBlock: case ZigTypeIdBoundFn: case ZigTypeIdArgTuple: case ZigTypeIdPromise: @@ -12822,7 +12796,6 @@ static ZigType *ir_analyze_instruction_export(IrAnalyze *ira, IrInstructionExpor case ZigTypeIdErrorUnion: case ZigTypeIdErrorSet: case ZigTypeIdNamespace: - case ZigTypeIdBlock: case ZigTypeIdBoundFn: case ZigTypeIdArgTuple: case ZigTypeIdOpaque: @@ -12847,7 +12820,6 @@ static ZigType *ir_analyze_instruction_export(IrAnalyze *ira, IrInstructionExpor case ZigTypeIdErrorSet: zig_panic("TODO export const value of type %s", buf_ptr(&target->value.type->name)); case ZigTypeIdNamespace: - case ZigTypeIdBlock: case ZigTypeIdBoundFn: case ZigTypeIdArgTuple: case ZigTypeIdOpaque: @@ -13905,7 +13877,6 @@ static ZigType *ir_analyze_maybe(IrAnalyze *ira, IrInstructionUnOp *un_op_instru case ZigTypeIdUnion: case ZigTypeIdFn: case ZigTypeIdNamespace: - case ZigTypeIdBlock: case ZigTypeIdBoundFn: case ZigTypeIdArgTuple: case ZigTypeIdPromise: @@ -15263,7 +15234,6 @@ static ZigType *ir_analyze_instruction_typeof(IrAnalyze *ira, IrInstructionTypeO case ZigTypeIdUndefined: case ZigTypeIdNull: case ZigTypeIdNamespace: - case ZigTypeIdBlock: case ZigTypeIdBoundFn: case ZigTypeIdMetaType: case ZigTypeIdVoid: @@ -15516,7 +15486,6 @@ static ZigType *ir_analyze_instruction_slice_type(IrAnalyze *ira, case ZigTypeIdUnreachable: case ZigTypeIdUndefined: case ZigTypeIdNull: - case ZigTypeIdBlock: case ZigTypeIdArgTuple: case ZigTypeIdOpaque: ir_add_error_node(ira, slice_type_instruction->base.source_node, @@ -15627,7 +15596,6 @@ static ZigType *ir_analyze_instruction_array_type(IrAnalyze *ira, case ZigTypeIdUnreachable: case ZigTypeIdUndefined: case ZigTypeIdNull: - case ZigTypeIdBlock: case ZigTypeIdArgTuple: case ZigTypeIdOpaque: ir_add_error_node(ira, array_type_instruction->base.source_node, @@ -15698,7 +15666,6 @@ static ZigType *ir_analyze_instruction_size_of(IrAnalyze *ira, case ZigTypeIdUnreachable: case ZigTypeIdUndefined: case ZigTypeIdNull: - case ZigTypeIdBlock: case ZigTypeIdComptimeFloat: case ZigTypeIdComptimeInt: case ZigTypeIdBoundFn: @@ -16184,7 +16151,6 @@ static ZigType *ir_analyze_instruction_switch_target(IrAnalyze *ira, case ZigTypeIdUndefined: case ZigTypeIdNull: case ZigTypeIdOptional: - case ZigTypeIdBlock: case ZigTypeIdBoundFn: case ZigTypeIdArgTuple: case ZigTypeIdOpaque: @@ -16705,7 +16671,6 @@ static ZigType *ir_analyze_min_max(IrAnalyze *ira, IrInstruction *source_instruc case ZigTypeIdUnion: case ZigTypeIdFn: case ZigTypeIdNamespace: - case ZigTypeIdBlock: case ZigTypeIdBoundFn: case ZigTypeIdArgTuple: case ZigTypeIdOpaque: @@ -17368,7 +17333,6 @@ static Error ir_make_type_info_value(IrAnalyze *ira, ZigType *type_entry, ConstE case ZigTypeIdUndefined: case ZigTypeIdNull: case ZigTypeIdNamespace: - case ZigTypeIdBlock: case ZigTypeIdArgTuple: case ZigTypeIdOpaque: *out = nullptr; @@ -19341,7 +19305,6 @@ static ZigType *ir_analyze_instruction_align_of(IrAnalyze *ira, IrInstructionAli case ZigTypeIdUndefined: case ZigTypeIdNull: case ZigTypeIdNamespace: - case ZigTypeIdBlock: case ZigTypeIdBoundFn: case ZigTypeIdArgTuple: case ZigTypeIdVoid: @@ -20102,7 +20065,6 @@ static void buf_write_value_bytes(CodeGen *codegen, uint8_t *buf, ConstExprValue case ZigTypeIdBoundFn: case ZigTypeIdArgTuple: case ZigTypeIdNamespace: - case ZigTypeIdBlock: case ZigTypeIdUnreachable: case ZigTypeIdComptimeFloat: case ZigTypeIdComptimeInt: @@ -20169,7 +20131,6 @@ static void buf_read_value_bytes(CodeGen *codegen, uint8_t *buf, ConstExprValue case ZigTypeIdBoundFn: case ZigTypeIdArgTuple: case ZigTypeIdNamespace: - case ZigTypeIdBlock: case ZigTypeIdUnreachable: case ZigTypeIdComptimeFloat: case ZigTypeIdComptimeInt: @@ -20249,7 +20210,6 @@ static ZigType *ir_analyze_instruction_bit_cast(IrAnalyze *ira, IrInstructionBit case ZigTypeIdBoundFn: case ZigTypeIdArgTuple: case ZigTypeIdNamespace: - case ZigTypeIdBlock: case ZigTypeIdUnreachable: case ZigTypeIdComptimeFloat: case ZigTypeIdComptimeInt: @@ -20275,7 +20235,6 @@ static ZigType *ir_analyze_instruction_bit_cast(IrAnalyze *ira, IrInstructionBit case ZigTypeIdBoundFn: case ZigTypeIdArgTuple: case ZigTypeIdNamespace: - case ZigTypeIdBlock: case ZigTypeIdUnreachable: case ZigTypeIdComptimeFloat: case ZigTypeIdComptimeInt: diff --git a/src/parser.cpp b/src/parser.cpp index 453ab7ce2c..8e6076c5e5 100644 --- a/src/parser.cpp +++ b/src/parser.cpp @@ -700,7 +700,7 @@ static AstNode *ast_parse_comptime_expr(ParseContext *pc, size_t *token_index, b /* PrimaryExpression = Integer | Float | String | CharLiteral | KeywordLiteral | GroupedExpression | BlockExpression(BlockOrExpression) | Symbol | ("@" Symbol FnCallExpression) | ArrayType | FnProto | AsmExpression | ContainerDecl | ("continue" option(":" Symbol)) | ErrorSetDecl | PromiseType -KeywordLiteral = "true" | "false" | "null" | "undefined" | "error" | "this" | "unreachable" | "suspend" +KeywordLiteral = "true" | "false" | "null" | "undefined" | "error" | "unreachable" | "suspend" ErrorSetDecl = "error" "{" list(Symbol, ",") "}" */ static AstNode *ast_parse_primary_expr(ParseContext *pc, size_t *token_index, bool mandatory) { @@ -756,10 +756,6 @@ static AstNode *ast_parse_primary_expr(ParseContext *pc, size_t *token_index, bo AstNode *node = ast_create_node(pc, NodeTypeUndefinedLiteral, token); *token_index += 1; return node; - } else if (token->id == TokenIdKeywordThis) { - AstNode *node = ast_create_node(pc, NodeTypeThisLiteral, token); - *token_index += 1; - return node; } else if (token->id == TokenIdKeywordUnreachable) { AstNode *node = ast_create_node(pc, NodeTypeUnreachable, token); *token_index += 1; @@ -3021,9 +3017,6 @@ void ast_visit_node_children(AstNode *node, void (*visit)(AstNode **, void *cont case NodeTypeUndefinedLiteral: // none break; - case NodeTypeThisLiteral: - // none - break; case NodeTypeIfBoolExpr: visit_field(&node->data.if_bool_expr.condition, visit, context); visit_field(&node->data.if_bool_expr.then_block, visit, context); diff --git a/src/tokenizer.cpp b/src/tokenizer.cpp index 1d3db5567a..84d1d90518 100644 --- a/src/tokenizer.cpp +++ b/src/tokenizer.cpp @@ -146,7 +146,6 @@ static const struct ZigKeyword zig_keywords[] = { {"suspend", TokenIdKeywordSuspend}, {"switch", TokenIdKeywordSwitch}, {"test", TokenIdKeywordTest}, - {"this", TokenIdKeywordThis}, {"true", TokenIdKeywordTrue}, {"try", TokenIdKeywordTry}, {"undefined", TokenIdKeywordUndefined}, @@ -1588,7 +1587,6 @@ const char * token_name(TokenId id) { case TokenIdKeywordStruct: return "struct"; case TokenIdKeywordSwitch: return "switch"; case TokenIdKeywordTest: return "test"; - case TokenIdKeywordThis: return "this"; case TokenIdKeywordTrue: return "true"; case TokenIdKeywordTry: return "try"; case TokenIdKeywordUndefined: return "undefined"; diff --git a/src/tokenizer.hpp b/src/tokenizer.hpp index 75c7feb476..cae6835d0f 100644 --- a/src/tokenizer.hpp +++ b/src/tokenizer.hpp @@ -87,7 +87,6 @@ enum TokenId { TokenIdKeywordSuspend, TokenIdKeywordSwitch, TokenIdKeywordTest, - TokenIdKeywordThis, TokenIdKeywordTrue, TokenIdKeywordTry, TokenIdKeywordUndefined, diff --git a/std/array_list.zig b/std/array_list.zig index dda6f176eb..3ee425fe14 100644 --- a/std/array_list.zig +++ b/std/array_list.zig @@ -11,7 +11,7 @@ pub fn ArrayList(comptime T: type) type { pub fn AlignedArrayList(comptime T: type, comptime A: u29) type { return struct { - const Self = this; + const Self = @This(); /// Use toSlice instead of slicing this directly, because if you don't /// specify the end position of the slice, this will potentially give diff --git a/std/atomic/int.zig b/std/atomic/int.zig index 4103d52719..6e07ef571a 100644 --- a/std/atomic/int.zig +++ b/std/atomic/int.zig @@ -6,7 +6,7 @@ pub fn Int(comptime T: type) type { return struct { unprotected_value: T, - pub const Self = this; + pub const Self = @This(); pub fn init(init_val: T) Self { return Self{ .unprotected_value = init_val }; diff --git a/std/atomic/queue.zig b/std/atomic/queue.zig index 6948af43ba..c1e2a4c98b 100644 --- a/std/atomic/queue.zig +++ b/std/atomic/queue.zig @@ -12,7 +12,7 @@ pub fn Queue(comptime T: type) type { tail: ?*Node, mutex: std.Mutex, - pub const Self = this; + pub const Self = @This(); pub const Node = std.LinkedList(T).Node; pub fn init() Self { diff --git a/std/atomic/stack.zig b/std/atomic/stack.zig index 16d5c9503b..71896c66df 100644 --- a/std/atomic/stack.zig +++ b/std/atomic/stack.zig @@ -9,7 +9,7 @@ pub fn Stack(comptime T: type) type { root: ?*Node, lock: u8, - pub const Self = this; + pub const Self = @This(); pub const Node = struct { next: ?*Node, diff --git a/std/build.zig b/std/build.zig index 5800e69c62..f9fed6ad2f 100644 --- a/std/build.zig +++ b/std/build.zig @@ -1890,7 +1890,7 @@ const InstallArtifactStep = struct { artifact: *LibExeObjStep, dest_file: []const u8, - const Self = this; + const Self = @This(); pub fn create(builder: *Builder, artifact: *LibExeObjStep) *Self { const dest_dir = switch (artifact.kind) { diff --git a/std/crypto/blake2.zig b/std/crypto/blake2.zig index 467ddde5db..dc68d806d2 100644 --- a/std/crypto/blake2.zig +++ b/std/crypto/blake2.zig @@ -33,7 +33,7 @@ pub const Blake2s256 = Blake2s(256); fn Blake2s(comptime out_len: usize) type { return struct { - const Self = this; + const Self = @This(); const block_length = 64; const digest_length = out_len / 8; @@ -266,7 +266,7 @@ pub const Blake2b512 = Blake2b(512); fn Blake2b(comptime out_len: usize) type { return struct { - const Self = this; + const Self = @This(); const block_length = 128; const digest_length = out_len / 8; diff --git a/std/crypto/hmac.zig b/std/crypto/hmac.zig index 23eeff2a00..996c96062c 100644 --- a/std/crypto/hmac.zig +++ b/std/crypto/hmac.zig @@ -9,7 +9,7 @@ pub const HmacSha256 = Hmac(crypto.Sha256); pub fn Hmac(comptime Hash: type) type { return struct { - const Self = this; + const Self = @This(); pub const mac_length = Hash.digest_length; pub const minimum_key_length = 0; diff --git a/std/crypto/md5.zig b/std/crypto/md5.zig index 20334ec7d8..8663fa751f 100644 --- a/std/crypto/md5.zig +++ b/std/crypto/md5.zig @@ -28,7 +28,7 @@ fn Rp(a: usize, b: usize, c: usize, d: usize, k: usize, s: u32, t: u32) RoundPar } pub const Md5 = struct { - const Self = this; + const Self = @This(); const block_length = 64; const digest_length = 16; diff --git a/std/crypto/poly1305.zig b/std/crypto/poly1305.zig index f5e11fc0a1..a5d9fcdf57 100644 --- a/std/crypto/poly1305.zig +++ b/std/crypto/poly1305.zig @@ -10,7 +10,7 @@ const readInt = std.mem.readInt; const writeInt = std.mem.writeInt; pub const Poly1305 = struct { - const Self = this; + const Self = @This(); pub const mac_length = 16; pub const minimum_key_length = 32; diff --git a/std/crypto/sha1.zig b/std/crypto/sha1.zig index 6d6b4dbd3f..1cb0b17434 100644 --- a/std/crypto/sha1.zig +++ b/std/crypto/sha1.zig @@ -25,7 +25,7 @@ fn Rp(a: usize, b: usize, c: usize, d: usize, e: usize, i: u32) RoundParam { } pub const Sha1 = struct { - const Self = this; + const Self = @This(); const block_length = 64; const digest_length = 20; diff --git a/std/crypto/sha2.zig b/std/crypto/sha2.zig index 8a25fecc43..7e9749364b 100644 --- a/std/crypto/sha2.zig +++ b/std/crypto/sha2.zig @@ -77,7 +77,7 @@ pub const Sha256 = Sha2_32(Sha256Params); fn Sha2_32(comptime params: Sha2Params32) type { return struct { - const Self = this; + const Self = @This(); const block_length = 64; const digest_length = params.out_len / 8; @@ -418,7 +418,7 @@ pub const Sha512 = Sha2_64(Sha512Params); fn Sha2_64(comptime params: Sha2Params64) type { return struct { - const Self = this; + const Self = @This(); const block_length = 128; const digest_length = params.out_len / 8; diff --git a/std/crypto/sha3.zig b/std/crypto/sha3.zig index 827bbd0680..881370e686 100644 --- a/std/crypto/sha3.zig +++ b/std/crypto/sha3.zig @@ -12,7 +12,7 @@ pub const Sha3_512 = Keccak(512, 0x06); fn Keccak(comptime bits: usize, comptime delim: u8) type { return struct { - const Self = this; + const Self = @This(); const block_length = 200; const digest_length = bits / 8; diff --git a/std/event/channel.zig b/std/event/channel.zig index 9ea75a2dd8..133ce1c69c 100644 --- a/std/event/channel.zig +++ b/std/event/channel.zig @@ -25,7 +25,7 @@ pub fn Channel(comptime T: type) type { buffer_index: usize, buffer_len: usize, - const SelfChannel = this; + const SelfChannel = @This(); const GetNode = struct { tick_node: *Loop.NextTickNode, data: Data, diff --git a/std/event/fs.zig b/std/event/fs.zig index 5635471212..bde5a306b6 100644 --- a/std/event/fs.zig +++ b/std/event/fs.zig @@ -724,7 +724,7 @@ pub fn Watch(comptime V: type) type { const FileToHandle = std.AutoHashMap([]const u8, promise); - const Self = this; + const Self = @This(); pub const Event = struct { id: Id, diff --git a/std/event/future.zig b/std/event/future.zig index 8abdce7d02..d61768b198 100644 --- a/std/event/future.zig +++ b/std/event/future.zig @@ -21,7 +21,7 @@ pub fn Future(comptime T: type) type { /// 2 - finished available: u8, - const Self = this; + const Self = @This(); const Queue = std.atomic.Queue(promise); pub fn init(loop: *Loop) Self { diff --git a/std/event/group.zig b/std/event/group.zig index 2b5a517b2f..0bb3298cf8 100644 --- a/std/event/group.zig +++ b/std/event/group.zig @@ -13,7 +13,7 @@ pub fn Group(comptime ReturnType: type) type { alloc_stack: Stack, lock: Lock, - const Self = this; + const Self = @This(); const Error = switch (@typeInfo(ReturnType)) { builtin.TypeId.ErrorUnion => |payload| payload.error_set, diff --git a/std/event/locked.zig b/std/event/locked.zig index 7df56c4571..6718b1bf9c 100644 --- a/std/event/locked.zig +++ b/std/event/locked.zig @@ -10,7 +10,7 @@ pub fn Locked(comptime T: type) type { lock: Lock, private_data: T, - const Self = this; + const Self = @This(); pub const HeldLock = struct { value: *T, diff --git a/std/event/rwlocked.zig b/std/event/rwlocked.zig index 1a6e77c27a..d305b1791e 100644 --- a/std/event/rwlocked.zig +++ b/std/event/rwlocked.zig @@ -10,7 +10,7 @@ pub fn RwLocked(comptime T: type) type { lock: RwLock, locked_data: T, - const Self = this; + const Self = @This(); pub const HeldReadLock = struct { value: *const T, diff --git a/std/event/tcp.zig b/std/event/tcp.zig index 69b143dda0..5715e46a62 100644 --- a/std/event/tcp.zig +++ b/std/event/tcp.zig @@ -132,7 +132,7 @@ test "listen on a port, send bytes, receive bytes" { const MyServer = struct { tcp_server: Server, - const Self = this; + const Self = @This(); async<*mem.Allocator> fn handler(tcp_server: *Server, _addr: *const std.net.Address, _socket: *const std.os.File) void { const self = @fieldParentPtr(Self, "tcp_server", tcp_server); var socket = _socket.*; // TODO https://github.com/ziglang/zig/issues/733 diff --git a/std/fmt/index.zig b/std/fmt/index.zig index 80af750f3d..14c944e9d5 100644 --- a/std/fmt/index.zig +++ b/std/fmt/index.zig @@ -1183,7 +1183,7 @@ test "fmt.format" { //custom type format { const Vec2 = struct { - const SelfType = this; + const SelfType = @This(); x: f32, y: f32, diff --git a/std/hash/crc.zig b/std/hash/crc.zig index c455140785..c4bd92884a 100644 --- a/std/hash/crc.zig +++ b/std/hash/crc.zig @@ -20,7 +20,7 @@ pub const Crc32 = Crc32WithPoly(Polynomial.IEEE); // slicing-by-8 crc32 implementation. pub fn Crc32WithPoly(comptime poly: u32) type { return struct { - const Self = this; + const Self = @This(); const lookup_tables = comptime block: { @setEvalBranchQuota(20000); var tables: [8][256]u32 = undefined; @@ -117,7 +117,7 @@ test "crc32 castagnoli" { // half-byte lookup table implementation. pub fn Crc32SmallWithPoly(comptime poly: u32) type { return struct { - const Self = this; + const Self = @This(); const lookup_table = comptime block: { var table: [16]u32 = undefined; diff --git a/std/hash/fnv.zig b/std/hash/fnv.zig index 447c996772..9bb18f14b3 100644 --- a/std/hash/fnv.zig +++ b/std/hash/fnv.zig @@ -13,7 +13,7 @@ pub const Fnv1a_128 = Fnv1a(u128, 0x1000000000000000000013b, 0x6c62272e07bb01426 fn Fnv1a(comptime T: type, comptime prime: T, comptime offset: T) type { return struct { - const Self = this; + const Self = @This(); value: T, diff --git a/std/hash/siphash.zig b/std/hash/siphash.zig index cdad77e59e..0fe958c38b 100644 --- a/std/hash/siphash.zig +++ b/std/hash/siphash.zig @@ -25,7 +25,7 @@ fn SipHash(comptime T: type, comptime c_rounds: usize, comptime d_rounds: usize) debug.assert(c_rounds > 0 and d_rounds > 0); return struct { - const Self = this; + const Self = @This(); const digest_size = 64; const block_size = 64; diff --git a/std/hash_map.zig b/std/hash_map.zig index 9654d612a5..1b299eff78 100644 --- a/std/hash_map.zig +++ b/std/hash_map.zig @@ -22,7 +22,7 @@ pub fn HashMap(comptime K: type, comptime V: type, comptime hash: fn (key: K) u3 // this is used to detect bugs where a hashtable is edited while an iterator is running. modification_count: debug_u32, - const Self = this; + const Self = @This(); pub const KV = struct { key: K, @@ -472,7 +472,6 @@ pub fn autoHash(key: var, comptime rng: *std.rand.Random, comptime HashInt: type builtin.TypeId.Promise, builtin.TypeId.Fn => return autoHash(@ptrToInt(key), rng), builtin.TypeId.Namespace, - builtin.TypeId.Block, builtin.TypeId.BoundFn, builtin.TypeId.ComptimeFloat, builtin.TypeId.ComptimeInt, @@ -517,7 +516,6 @@ pub fn autoEql(a: var, b: @typeOf(a)) bool { builtin.TypeId.ComptimeFloat, builtin.TypeId.ComptimeInt, builtin.TypeId.Namespace, - builtin.TypeId.Block, builtin.TypeId.Promise, builtin.TypeId.Enum, builtin.TypeId.BoundFn, diff --git a/std/heap.zig b/std/heap.zig index f5e0484b25..58a9961d79 100644 --- a/std/heap.zig +++ b/std/heap.zig @@ -385,7 +385,7 @@ pub fn stackFallback(comptime size: usize, fallback_allocator: *Allocator) Stack pub fn StackFallbackAllocator(comptime size: usize) type { return struct { - const Self = this; + const Self = @This(); buffer: [size]u8, allocator: Allocator, diff --git a/std/io.zig b/std/io.zig index 2b31bc0548..c10fdcbbe2 100644 --- a/std/io.zig +++ b/std/io.zig @@ -76,7 +76,7 @@ pub const FileOutStream = struct { pub fn InStream(comptime ReadError: type) type { return struct { - const Self = this; + const Self = @This(); pub const Error = ReadError; /// Return the number of bytes read. If the number read is smaller than buf.len, it @@ -218,7 +218,7 @@ pub fn InStream(comptime ReadError: type) type { pub fn OutStream(comptime WriteError: type) type { return struct { - const Self = this; + const Self = @This(); pub const Error = WriteError; writeFn: fn (self: *Self, bytes: []const u8) Error!void, @@ -291,7 +291,7 @@ pub fn BufferedInStream(comptime Error: type) type { pub fn BufferedInStreamCustom(comptime buffer_size: usize, comptime Error: type) type { return struct { - const Self = this; + const Self = @This(); const Stream = InStream(Error); pub stream: Stream, @@ -361,7 +361,7 @@ pub fn BufferedInStreamCustom(comptime buffer_size: usize, comptime Error: type) /// This makes look-ahead style parsing much easier. pub fn PeekStream(comptime buffer_size: usize, comptime InStreamError: type) type { return struct { - const Self = this; + const Self = @This(); pub const Error = InStreamError; pub const Stream = InStream(Error); @@ -424,7 +424,7 @@ pub fn PeekStream(comptime buffer_size: usize, comptime InStreamError: type) typ } pub const SliceInStream = struct { - const Self = this; + const Self = @This(); pub const Error = error{}; pub const Stream = InStream(Error); @@ -505,7 +505,7 @@ pub fn BufferedOutStream(comptime Error: type) type { pub fn BufferedOutStreamCustom(comptime buffer_size: usize, comptime OutStreamError: type) type { return struct { - const Self = this; + const Self = @This(); pub const Stream = OutStream(Error); pub const Error = OutStreamError; diff --git a/std/lazy_init.zig b/std/lazy_init.zig index c46c067810..f08c01e874 100644 --- a/std/lazy_init.zig +++ b/std/lazy_init.zig @@ -18,7 +18,7 @@ fn LazyInit(comptime T: type) type { state: u8, // TODO make this an enum data: Data, - const Self = this; + const Self = @This(); // TODO this isn't working for void, investigate and then remove this special case const Data = if (@sizeOf(T) == 0) u8 else T; diff --git a/std/linked_list.zig b/std/linked_list.zig index 130ddbce5d..46cbeb03c4 100644 --- a/std/linked_list.zig +++ b/std/linked_list.zig @@ -7,7 +7,7 @@ const Allocator = mem.Allocator; /// Generic doubly linked list. pub fn LinkedList(comptime T: type) type { return struct { - const Self = this; + const Self = @This(); /// Node inside the linked list wrapping the actual data. pub const Node = struct { diff --git a/std/math/complex/index.zig b/std/math/complex/index.zig index 63a2616984..171c4c5829 100644 --- a/std/math/complex/index.zig +++ b/std/math/complex/index.zig @@ -25,7 +25,7 @@ pub const tan = @import("tan.zig").tan; pub fn Complex(comptime T: type) type { return struct { - const Self = this; + const Self = @This(); re: T, im: T, diff --git a/std/mem.zig b/std/mem.zig index 4390f8ad5b..dd5adc06c2 100644 --- a/std/mem.zig +++ b/std/mem.zig @@ -3,7 +3,7 @@ const debug = std.debug; const assert = debug.assert; const math = std.math; const builtin = @import("builtin"); -const mem = this; +const mem = @This(); pub const Allocator = struct { pub const Error = error{OutOfMemory}; diff --git a/std/net.zig b/std/net.zig index 8c1aeb92d7..c20435893a 100644 --- a/std/net.zig +++ b/std/net.zig @@ -1,7 +1,7 @@ const std = @import("index.zig"); const builtin = @import("builtin"); const assert = std.debug.assert; -const net = this; +const net = @This(); const posix = std.os.posix; const mem = std.mem; diff --git a/std/os/index.zig b/std/os/index.zig index 8e92fc23c5..d4110bd759 100644 --- a/std/os/index.zig +++ b/std/os/index.zig @@ -6,7 +6,7 @@ const is_posix = switch (builtin.os) { builtin.Os.linux, builtin.Os.macosx => true, else => false, }; -const os = this; +const os = @This(); test "std.os" { _ = @import("child_process.zig"); diff --git a/std/segmented_list.zig b/std/segmented_list.zig index c6d8effdd2..93942dde9b 100644 --- a/std/segmented_list.zig +++ b/std/segmented_list.zig @@ -75,7 +75,7 @@ const Allocator = std.mem.Allocator; /// size is small. `prealloc_item_count` must be 0, or a power of 2. pub fn SegmentedList(comptime T: type, comptime prealloc_item_count: usize) type { return struct { - const Self = this; + const Self = @This(); const prealloc_exp = blk: { // we don't use the prealloc_exp constant when prealloc_item_count is 0. assert(prealloc_item_count != 0); diff --git a/std/zig/ast.zig b/std/zig/ast.zig index 0046dff1a2..9ca77d4950 100644 --- a/std/zig/ast.zig +++ b/std/zig/ast.zig @@ -231,7 +231,7 @@ pub const Error = union(enum) { fn SingleTokenError(comptime msg: []const u8) type { return struct { - const ThisError = this; + const ThisError = @This(); token: TokenIndex, @@ -244,7 +244,7 @@ pub const Error = union(enum) { fn SimpleError(comptime msg: []const u8) type { return struct { - const ThisError = this; + const ThisError = @This(); token: TokenIndex, diff --git a/std/zig/parser_test.zig b/std/zig/parser_test.zig index 7f3ce7bd8a..3cee9b98dd 100644 --- a/std/zig/parser_test.zig +++ b/std/zig/parser_test.zig @@ -1354,7 +1354,7 @@ test "zig fmt: indexing" { test "zig fmt: struct declaration" { try testCanonical( \\const S = struct { - \\ const Self = this; + \\ const Self = @This(); \\ f1: u8, \\ pub f3: u8, \\ diff --git a/std/zig/render.zig b/std/zig/render.zig index 868902a0d1..050f172ae8 100644 --- a/std/zig/render.zig +++ b/std/zig/render.zig @@ -20,7 +20,7 @@ pub fn render(allocator: *mem.Allocator, stream: var, tree: *ast.Tree) (@typeOf( // make a passthrough stream that checks whether something changed const MyStream = struct { - const MyStream = this; + const MyStream = @This(); const StreamError = @typeOf(stream).Child.Error; const Stream = std.io.OutStream(StreamError); diff --git a/test/cases/cast.zig b/test/cases/cast.zig index 94fbda7899..e2b67f036d 100644 --- a/test/cases/cast.zig +++ b/test/cases/cast.zig @@ -64,7 +64,7 @@ test "implicitly cast a container to a const pointer of it" { fn Struct(comptime T: type) type { return struct { - const Self = this; + const Self = @This(); x: T, fn pointer(self: *const Self) Self { @@ -106,7 +106,7 @@ const Enum = enum { test "implicitly cast indirect pointer to maybe-indirect pointer" { const S = struct { - const Self = this; + const Self = @This(); x: u8, fn constConst(p: *const *const Self) u8 { return p.*.x; diff --git a/test/cases/eval.zig b/test/cases/eval.zig index 4286821183..7e9c9a739d 100644 --- a/test/cases/eval.zig +++ b/test/cases/eval.zig @@ -628,7 +628,7 @@ test "call method with comptime pass-by-non-copying-value self parameter" { const S = struct { a: u8, - fn b(comptime s: this) u8 { + fn b(comptime s: @This()) u8 { return s.a; } }; diff --git a/test/cases/misc.zig b/test/cases/misc.zig index 1c0189571b..4343cb3b90 100644 --- a/test/cases/misc.zig +++ b/test/cases/misc.zig @@ -510,9 +510,6 @@ test "@typeId" { assert(@typeId(AUnion) == Tid.Union); assert(@typeId(fn () void) == Tid.Fn); assert(@typeId(@typeOf(builtin)) == Tid.Namespace); - assert(@typeId(@typeOf(x: { - break :x this; - })) == Tid.Block); // TODO bound fn // TODO arg tuple // TODO opaque diff --git a/test/cases/reflection.zig b/test/cases/reflection.zig index 3d3af3c889..677fd90192 100644 --- a/test/cases/reflection.zig +++ b/test/cases/reflection.zig @@ -1,6 +1,6 @@ const assert = @import("std").debug.assert; const mem = @import("std").mem; -const reflection = this; +const reflection = @This(); test "reflection: array, pointer, optional, error union type child" { comptime { diff --git a/test/cases/struct.zig b/test/cases/struct.zig index 20d46999d5..163c69e670 100644 --- a/test/cases/struct.zig +++ b/test/cases/struct.zig @@ -423,10 +423,10 @@ fn alloc(comptime T: type) []T { test "call method with mutable reference to struct with no fields" { const S = struct { - fn doC(s: *const this) bool { + fn doC(s: *const @This()) bool { return true; } - fn do(s: *this) bool { + fn do(s: *@This()) bool { return true; } }; diff --git a/test/cases/this.zig b/test/cases/this.zig index ba51d0ac90..c7be074f36 100644 --- a/test/cases/this.zig +++ b/test/cases/this.zig @@ -1,10 +1,10 @@ const assert = @import("std").debug.assert; -const module = this; +const module = @This(); fn Point(comptime T: type) type { return struct { - const Self = this; + const Self = @This(); x: T, y: T, @@ -19,11 +19,6 @@ fn add(x: i32, y: i32) i32 { return x + y; } -fn factorial(x: i32) i32 { - const selfFn = this; - return if (x == 0) 1 else x * selfFn(x - 1); -} - test "this refer to module call private fn" { assert(module.add(1, 2) == 3); } @@ -37,7 +32,3 @@ test "this refer to container" { assert(pt.x == 13); assert(pt.y == 35); } - -test "this refer to fn" { - assert(factorial(5) == 120); -} diff --git a/test/cases/type_info.zig b/test/cases/type_info.zig index b8fc4cf14e..6f99268c08 100644 --- a/test/cases/type_info.zig +++ b/test/cases/type_info.zig @@ -166,7 +166,7 @@ fn testUnion() void { assert(TypeId(typeinfo_info) == TypeId.Union); assert(typeinfo_info.Union.layout == TypeInfo.ContainerLayout.Auto); assert(typeinfo_info.Union.tag_type.? == TypeId); - assert(typeinfo_info.Union.fields.len == 25); + assert(typeinfo_info.Union.fields.len == 24); assert(typeinfo_info.Union.fields[4].enum_field != null); assert(typeinfo_info.Union.fields[4].enum_field.?.value == 4); assert(typeinfo_info.Union.fields[4].field_type == @typeOf(@typeInfo(u8).Int)); @@ -217,7 +217,7 @@ fn testStruct() void { } const TestStruct = packed struct { - const Self = this; + const Self = @This(); fieldA: usize, fieldB: void, diff --git a/test/compile_errors.zig b/test/compile_errors.zig index 750794c909..6bdbca9ff5 100644 --- a/test/compile_errors.zig +++ b/test/compile_errors.zig @@ -3813,11 +3813,11 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { \\ return struct { \\ b: B(), \\ - \\ const Self = this; + \\ const Self = @This(); \\ \\ fn B() type { \\ return struct { - \\ const Self = this; + \\ const Self = @This(); \\ }; \\ } \\ }; @@ -4314,12 +4314,11 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { \\ var a = undefined; \\ var b = 1; \\ var c = 1.0; - \\ var d = this; - \\ var e = null; - \\ var f = opaque.*; - \\ var g = i32; - \\ var h = @import("std",); - \\ var i = (Foo {}).bar; + \\ var d = null; + \\ var e = opaque.*; + \\ var f = i32; + \\ var g = @import("std",); + \\ var h = (Foo {}).bar; \\ \\ var z: noreturn = return; \\} @@ -4332,13 +4331,12 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { ".tmp_source.zig:7:4: error: variable of type '(undefined)' must be const or comptime", ".tmp_source.zig:8:4: error: variable of type 'comptime_int' must be const or comptime", ".tmp_source.zig:9:4: error: variable of type 'comptime_float' must be const or comptime", - ".tmp_source.zig:10:4: error: variable of type '(block)' must be const or comptime", - ".tmp_source.zig:11:4: error: variable of type '(null)' must be const or comptime", - ".tmp_source.zig:12:4: error: variable of type 'Opaque' not allowed", - ".tmp_source.zig:13:4: error: variable of type 'type' must be const or comptime", - ".tmp_source.zig:14:4: error: variable of type '(namespace)' must be const or comptime", - ".tmp_source.zig:15:4: error: variable of type '(bound fn(*const Foo) void)' must be const or comptime", - ".tmp_source.zig:17:4: error: unreachable code", + ".tmp_source.zig:10:4: error: variable of type '(null)' must be const or comptime", + ".tmp_source.zig:11:4: error: variable of type 'Opaque' not allowed", + ".tmp_source.zig:12:4: error: variable of type 'type' must be const or comptime", + ".tmp_source.zig:13:4: error: variable of type '(namespace)' must be const or comptime", + ".tmp_source.zig:14:4: error: variable of type '(bound fn(*const Foo) void)' must be const or comptime", + ".tmp_source.zig:16:4: error: unreachable code", ); cases.add( -- cgit v1.2.3 From 3f776af3fa58b47d15a81b17c15e5b0e1c5ccf28 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Fri, 14 Sep 2018 18:56:30 -0400 Subject: fix alignment of structs closes #1248 closes #1052 closes #1154 --- src/all_types.hpp | 47 +++--- src/analyze.cpp | 387 +++++++++++++++++++++++++++--------------------- src/analyze.hpp | 4 +- src/codegen.cpp | 19 ++- src/ir.cpp | 376 +++++++++++++++++++++++++++++++--------------- std/debug/index.zig | 6 +- test/cases/align.zig | 7 + test/compile_errors.zig | 2 +- 8 files changed, 524 insertions(+), 324 deletions(-) (limited to 'test/compile_errors.zig') diff --git a/src/all_types.hpp b/src/all_types.hpp index fefbae0fe3..ed1dcb1f9b 100644 --- a/src/all_types.hpp +++ b/src/all_types.hpp @@ -1012,13 +1012,13 @@ enum PtrLen { struct ZigTypePointer { ZigType *child_type; + ZigType *slice_parent; PtrLen ptr_len; - bool is_const; - bool is_volatile; - uint32_t alignment; + uint32_t explicit_alignment; // 0 means use ABI alignment uint32_t bit_offset; uint32_t unaligned_bit_count; - ZigType *slice_parent; + bool is_const; + bool is_volatile; }; struct ZigTypeInt { @@ -1046,32 +1046,35 @@ struct TypeStructField { size_t unaligned_bit_count; AstNode *decl_node; }; + +enum ResolveStatus { + ResolveStatusUnstarted, + ResolveStatusInvalid, + ResolveStatusZeroBitsKnown, + ResolveStatusAlignmentKnown, + ResolveStatusSizeKnown, +}; + struct ZigTypeStruct { AstNode *decl_node; - ContainerLayout layout; - uint32_t src_field_count; - uint32_t gen_field_count; TypeStructField *fields; - uint64_t size_bytes; - bool is_invalid; // true if any fields are invalid - bool is_slice; ScopeDecls *decls_scope; + uint64_t size_bytes; + HashMap fields_by_name; - // set this flag temporarily to detect infinite loops - bool embedded_in_current; - bool reported_infinite_err; - // whether we've finished resolving it - bool complete; + uint32_t src_field_count; + uint32_t gen_field_count; + + uint32_t abi_alignment; // known after ResolveStatusAlignmentKnown + ContainerLayout layout; + ResolveStatus resolve_status; + bool is_slice; + bool resolve_loop_flag; // set this flag temporarily to detect infinite loops + bool reported_infinite_err; // whether any of the fields require comptime - // the value is not valid until zero_bits_known == true + // known after ResolveStatusZeroBitsKnown bool requires_comptime; - - bool zero_bits_loop_flag; - bool zero_bits_known; - uint32_t abi_alignment; // also figured out with zero_bits pass - - HashMap fields_by_name; }; struct ZigTypeOptional { diff --git a/src/analyze.cpp b/src/analyze.cpp index d403433c5c..c9ae865390 100644 --- a/src/analyze.cpp +++ b/src/analyze.cpp @@ -23,6 +23,7 @@ static Error resolve_enum_type(CodeGen *g, ZigType *enum_type); static Error resolve_struct_type(CodeGen *g, ZigType *struct_type); static Error ATTRIBUTE_MUST_USE resolve_struct_zero_bits(CodeGen *g, ZigType *struct_type); +static Error ATTRIBUTE_MUST_USE resolve_struct_alignment(CodeGen *g, ZigType *struct_type); static Error ATTRIBUTE_MUST_USE resolve_enum_zero_bits(CodeGen *g, ZigType *enum_type); static Error ATTRIBUTE_MUST_USE resolve_union_zero_bits(CodeGen *g, ZigType *union_type); static void analyze_fn_body(CodeGen *g, ZigFn *fn_table_entry); @@ -254,18 +255,42 @@ AstNode *type_decl_node(ZigType *type_entry) { zig_unreachable(); } -bool type_is_complete(ZigType *type_entry) { +bool type_is_resolved(ZigType *type_entry, ResolveStatus status) { switch (type_entry->id) { case ZigTypeIdInvalid: zig_unreachable(); case ZigTypeIdStruct: - return type_entry->data.structure.complete; + return type_entry->data.structure.resolve_status >= status; case ZigTypeIdEnum: - return type_entry->data.enumeration.complete; + switch (status) { + case ResolveStatusUnstarted: + return true; + case ResolveStatusInvalid: + zig_unreachable(); + case ResolveStatusZeroBitsKnown: + return type_entry->data.enumeration.zero_bits_known; + case ResolveStatusAlignmentKnown: + return type_entry->data.enumeration.zero_bits_known; + case ResolveStatusSizeKnown: + return type_entry->data.enumeration.complete; + } + zig_unreachable(); case ZigTypeIdUnion: - return type_entry->data.unionation.complete; + switch (status) { + case ResolveStatusUnstarted: + return true; + case ResolveStatusInvalid: + zig_unreachable(); + case ResolveStatusZeroBitsKnown: + return type_entry->data.unionation.zero_bits_known; + case ResolveStatusAlignmentKnown: + return type_entry->data.unionation.zero_bits_known; + case ResolveStatusSizeKnown: + return type_entry->data.unionation.complete; + } + zig_unreachable(); case ZigTypeIdOpaque: - return false; + return status < ResolveStatusSizeKnown; case ZigTypeIdMetaType: case ZigTypeIdVoid: case ZigTypeIdBool: @@ -291,43 +316,10 @@ bool type_is_complete(ZigType *type_entry) { zig_unreachable(); } -bool type_has_zero_bits_known(ZigType *type_entry) { - switch (type_entry->id) { - case ZigTypeIdInvalid: - zig_unreachable(); - case ZigTypeIdStruct: - return type_entry->data.structure.zero_bits_known; - case ZigTypeIdEnum: - return type_entry->data.enumeration.zero_bits_known; - case ZigTypeIdUnion: - return type_entry->data.unionation.zero_bits_known; - case ZigTypeIdMetaType: - case ZigTypeIdVoid: - case ZigTypeIdBool: - case ZigTypeIdUnreachable: - case ZigTypeIdInt: - case ZigTypeIdFloat: - case ZigTypeIdPointer: - case ZigTypeIdArray: - case ZigTypeIdComptimeFloat: - case ZigTypeIdComptimeInt: - case ZigTypeIdUndefined: - case ZigTypeIdNull: - case ZigTypeIdOptional: - case ZigTypeIdErrorUnion: - case ZigTypeIdErrorSet: - case ZigTypeIdFn: - case ZigTypeIdNamespace: - case ZigTypeIdBoundFn: - case ZigTypeIdArgTuple: - case ZigTypeIdOpaque: - case ZigTypeIdPromise: - return true; - } - zig_unreachable(); +bool type_is_complete(ZigType *type_entry) { + return type_is_resolved(type_entry, ResolveStatusSizeKnown); } - uint64_t type_size(CodeGen *g, ZigType *type_entry) { assert(type_is_complete(type_entry)); @@ -376,7 +368,7 @@ uint64_t type_size_bits(CodeGen *g, ZigType *type_entry) { Result type_is_copyable(CodeGen *g, ZigType *type_entry) { Error err; - if ((err = type_ensure_zero_bits_known(g, type_entry))) + if ((err = type_resolve(g, type_entry, ResolveStatusZeroBitsKnown))) return err; if (!type_has_bits(type_entry)) @@ -431,10 +423,15 @@ ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, bool is_cons assert(!type_is_invalid(child_type)); assert(ptr_len == PtrLenSingle || child_type->id != ZigTypeIdOpaque); + if (byte_alignment != 0) { + uint32_t abi_alignment = get_abi_alignment(g, child_type); + if (byte_alignment == abi_alignment) + byte_alignment = 0; + } + TypeId type_id = {}; ZigType **parent_pointer = nullptr; - uint32_t abi_alignment = get_abi_alignment(g, child_type); - if (unaligned_bit_count != 0 || is_volatile || byte_alignment != abi_alignment || ptr_len != PtrLenSingle) { + if (unaligned_bit_count != 0 || is_volatile || byte_alignment != 0 || ptr_len != PtrLenSingle) { type_id.id = ZigTypeIdPointer; type_id.data.pointer.child_type = child_type; type_id.data.pointer.is_const = is_const; @@ -451,12 +448,12 @@ ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, bool is_cons assert(bit_offset == 0); parent_pointer = &child_type->pointer_parent[(is_const ? 1 : 0)]; if (*parent_pointer) { - assert((*parent_pointer)->data.pointer.alignment == byte_alignment); + assert((*parent_pointer)->data.pointer.explicit_alignment == 0); return *parent_pointer; } } - assertNoError(type_ensure_zero_bits_known(g, child_type)); + assert(type_is_resolved(child_type, ResolveStatusZeroBitsKnown)); ZigType *entry = new_type_table_entry(ZigTypeIdPointer); entry->is_copyable = true; @@ -465,11 +462,14 @@ ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, bool is_cons const char *const_str = is_const ? "const " : ""; const char *volatile_str = is_volatile ? "volatile " : ""; buf_resize(&entry->name, 0); - if (unaligned_bit_count == 0 && byte_alignment == abi_alignment) { + if (unaligned_bit_count == 0 && byte_alignment == 0) { buf_appendf(&entry->name, "%s%s%s%s", star_str, const_str, volatile_str, buf_ptr(&child_type->name)); } else if (unaligned_bit_count == 0) { buf_appendf(&entry->name, "%salign(%" PRIu32 ") %s%s%s", star_str, byte_alignment, const_str, volatile_str, buf_ptr(&child_type->name)); + } else if (byte_alignment == 0) { + buf_appendf(&entry->name, "%salign(:%" PRIu32 ":%" PRIu32 ") %s%s%s", star_str, + bit_offset, bit_offset + unaligned_bit_count, const_str, volatile_str, buf_ptr(&child_type->name)); } else { buf_appendf(&entry->name, "%salign(%" PRIu32 ":%" PRIu32 ":%" PRIu32 ") %s%s%s", star_str, byte_alignment, bit_offset, bit_offset + unaligned_bit_count, const_str, volatile_str, buf_ptr(&child_type->name)); @@ -480,8 +480,7 @@ ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, bool is_cons entry->zero_bits = !type_has_bits(child_type); if (!entry->zero_bits) { - assert(byte_alignment > 0); - if (is_const || is_volatile || unaligned_bit_count != 0 || byte_alignment != abi_alignment || + if (is_const || is_volatile || unaligned_bit_count != 0 || byte_alignment != 0 || ptr_len != PtrLenSingle) { ZigType *peer_type = get_pointer_to_type(g, child_type, false); @@ -505,7 +504,7 @@ ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, bool is_cons entry->data.pointer.child_type = child_type; entry->data.pointer.is_const = is_const; entry->data.pointer.is_volatile = is_volatile; - entry->data.pointer.alignment = byte_alignment; + entry->data.pointer.explicit_alignment = byte_alignment; entry->data.pointer.bit_offset = bit_offset; entry->data.pointer.unaligned_bit_count = unaligned_bit_count; @@ -518,8 +517,7 @@ ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, bool is_cons } ZigType *get_pointer_to_type(CodeGen *g, ZigType *child_type, bool is_const) { - return get_pointer_to_type_extra(g, child_type, is_const, false, PtrLenSingle, - get_abi_alignment(g, child_type), 0, 0); + return get_pointer_to_type_extra(g, child_type, is_const, false, PtrLenSingle, 0, 0, 0); } ZigType *get_promise_frame_type(CodeGen *g, ZigType *return_type) { @@ -800,8 +798,7 @@ static void slice_type_common_init(CodeGen *g, ZigType *pointer_type, ZigType *e 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]); - assert(type_has_zero_bits_known(pointer_type->data.pointer.child_type)); - if (pointer_type->data.pointer.child_type->zero_bits) { + if (!type_has_bits(pointer_type->data.pointer.child_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; @@ -826,20 +823,18 @@ ZigType *get_slice_type(CodeGen *g, ZigType *ptr_type) { buf_appendf(&entry->name, "[]%s", buf_ptr(&ptr_type->name) + name_offset); ZigType *child_type = ptr_type->data.pointer.child_type; - uint32_t abi_alignment = get_abi_alignment(g, child_type); if (ptr_type->data.pointer.is_const || ptr_type->data.pointer.is_volatile || - ptr_type->data.pointer.alignment != abi_alignment) + ptr_type->data.pointer.explicit_alignment != 0) { ZigType *peer_ptr_type = get_pointer_to_type_extra(g, child_type, false, false, - PtrLenUnknown, abi_alignment, 0, 0); + PtrLenUnknown, 0, 0, 0); ZigType *peer_slice_type = get_slice_type(g, peer_ptr_type); slice_type_common_init(g, ptr_type, entry); entry->type_ref = peer_slice_type->type_ref; entry->di_type = peer_slice_type->di_type; - entry->data.structure.complete = true; - entry->data.structure.zero_bits_known = true; + entry->data.structure.resolve_status = ResolveStatusSizeKnown; entry->data.structure.abi_alignment = peer_slice_type->data.structure.abi_alignment; *parent_pointer = entry; @@ -851,15 +846,15 @@ ZigType *get_slice_type(CodeGen *g, ZigType *ptr_type) { if (is_slice(child_type)) { ZigType *child_ptr_type = child_type->data.structure.fields[slice_ptr_index].type_entry; assert(child_ptr_type->id == ZigTypeIdPointer); - ZigType *grand_child_type = child_ptr_type->data.pointer.child_type; if (child_ptr_type->data.pointer.is_const || child_ptr_type->data.pointer.is_volatile || - child_ptr_type->data.pointer.alignment != get_abi_alignment(g, grand_child_type)) + child_ptr_type->data.pointer.explicit_alignment != 0) { + ZigType *grand_child_type = child_ptr_type->data.pointer.child_type; ZigType *bland_child_ptr_type = get_pointer_to_type_extra(g, grand_child_type, false, false, - PtrLenUnknown, get_abi_alignment(g, grand_child_type), 0, 0); + PtrLenUnknown, 0, 0, 0); ZigType *bland_child_slice = get_slice_type(g, bland_child_ptr_type); ZigType *peer_ptr_type = get_pointer_to_type_extra(g, bland_child_slice, false, false, - PtrLenUnknown, get_abi_alignment(g, bland_child_slice), 0, 0); + PtrLenUnknown, 0, 0, 0); ZigType *peer_slice_type = get_slice_type(g, peer_ptr_type); entry->type_ref = peer_slice_type->type_ref; @@ -961,8 +956,7 @@ ZigType *get_slice_type(CodeGen *g, ZigType *ptr_type) { } - entry->data.structure.complete = true; - entry->data.structure.zero_bits_known = true; + entry->data.structure.resolve_status = ResolveStatusSizeKnown; *parent_pointer = entry; return entry; @@ -1367,7 +1361,7 @@ static bool analyze_const_align(CodeGen *g, Scope *scope, AstNode *node, uint32_ static bool analyze_const_string(CodeGen *g, Scope *scope, AstNode *node, Buf **out_buffer) { ZigType *ptr_type = get_pointer_to_type_extra(g, g->builtin_types.entry_u8, true, false, - PtrLenUnknown, get_abi_alignment(g, g->builtin_types.entry_u8), 0, 0); + PtrLenUnknown, 0, 0, 0); ZigType *str_type = get_slice_type(g, ptr_type); IrInstruction *instr = analyze_const_value(g, scope, node, str_type, nullptr); if (type_is_invalid(instr->value.type)) @@ -1576,7 +1570,7 @@ static ZigType *analyze_fn_type(CodeGen *g, AstNode *proto_node, Scope *child_sc return g->builtin_types.entry_invalid; } if (!calling_convention_allows_zig_types(fn_type_id.cc)) { - if ((err = type_ensure_zero_bits_known(g, type_entry))) + if ((err = type_resolve(g, type_entry, ResolveStatusZeroBitsKnown))) return g->builtin_types.entry_invalid; if (!type_has_bits(type_entry)) { add_node_error(g, param_node->data.param_decl.type, @@ -1624,7 +1618,7 @@ static ZigType *analyze_fn_type(CodeGen *g, AstNode *proto_node, Scope *child_sc case ZigTypeIdUnion: case ZigTypeIdFn: case ZigTypeIdPromise: - if ((err = type_ensure_zero_bits_known(g, type_entry))) + if ((err = type_resolve(g, type_entry, ResolveStatusZeroBitsKnown))) return g->builtin_types.entry_invalid; if (type_requires_comptime(type_entry)) { add_node_error(g, param_node->data.param_decl.type, @@ -1714,7 +1708,7 @@ static ZigType *analyze_fn_type(CodeGen *g, AstNode *proto_node, Scope *child_sc case ZigTypeIdUnion: case ZigTypeIdFn: case ZigTypeIdPromise: - if ((err = type_ensure_zero_bits_known(g, fn_type_id.return_type))) + if ((err = type_resolve(g, fn_type_id.return_type, ResolveStatusZeroBitsKnown))) return g->builtin_types.entry_invalid; if (type_requires_comptime(fn_type_id.return_type)) { return get_generic_fn_type(g, &fn_type_id); @@ -1740,7 +1734,7 @@ bool type_is_invalid(ZigType *type_entry) { case ZigTypeIdInvalid: return true; case ZigTypeIdStruct: - return type_entry->data.structure.is_invalid; + return type_entry->data.structure.resolve_status == ResolveStatusInvalid; case ZigTypeIdEnum: return type_entry->data.enumeration.is_invalid; case ZigTypeIdUnion: @@ -1855,8 +1849,7 @@ ZigType *get_struct_type(CodeGen *g, const char *type_name, const char *field_na struct_type->data.structure.src_field_count = field_count; struct_type->data.structure.gen_field_count = 0; - struct_type->data.structure.zero_bits_known = true; - struct_type->data.structure.complete = true; + struct_type->data.structure.resolve_status = ResolveStatusSizeKnown; struct_type->data.structure.fields = allocate(field_count); struct_type->data.structure.fields_by_name.init(field_count); @@ -1928,26 +1921,29 @@ ZigType *get_struct_type(CodeGen *g, const char *type_name, const char *field_na static Error resolve_struct_type(CodeGen *g, ZigType *struct_type) { assert(struct_type->id == ZigTypeIdStruct); - if (struct_type->data.structure.complete) + Error err; + + if (struct_type->data.structure.resolve_status == ResolveStatusInvalid) + return ErrorSemanticAnalyzeFail; + if (struct_type->data.structure.resolve_status >= ResolveStatusSizeKnown) return ErrorNone; - Error err; - if ((err = resolve_struct_zero_bits(g, struct_type))) + if ((err = resolve_struct_alignment(g, struct_type))) return err; AstNode *decl_node = struct_type->data.structure.decl_node; - if (struct_type->data.structure.embedded_in_current) { - struct_type->data.structure.is_invalid = true; - if (!struct_type->data.structure.reported_infinite_err) { - struct_type->data.structure.reported_infinite_err = true; + if (struct_type->data.structure.resolve_loop_flag) { + if (struct_type->data.structure.resolve_status != ResolveStatusInvalid) { + struct_type->data.structure.resolve_status = ResolveStatusInvalid; add_node_error(g, decl_node, - buf_sprintf("struct '%s' contains itself", buf_ptr(&struct_type->name))); + buf_sprintf("struct '%s' contains itself", buf_ptr(&struct_type->name))); } return ErrorSemanticAnalyzeFail; } - assert(!struct_type->data.structure.zero_bits_loop_flag); + struct_type->data.structure.resolve_loop_flag = true; + assert(struct_type->data.structure.fields || struct_type->data.structure.src_field_count == 0); assert(decl_node->type == NodeTypeContainerDecl); @@ -1956,9 +1952,6 @@ static Error resolve_struct_type(CodeGen *g, ZigType *struct_type) { size_t gen_field_count = struct_type->data.structure.gen_field_count; LLVMTypeRef *element_types = allocate(gen_field_count); - // this field should be set to true only during the recursive calls to resolve_struct_type - struct_type->data.structure.embedded_in_current = true; - Scope *scope = &struct_type->data.structure.decls_scope->base; size_t gen_field_index = 0; @@ -1972,7 +1965,7 @@ static Error resolve_struct_type(CodeGen *g, ZigType *struct_type) { ZigType *field_type = type_struct_field->type_entry; if ((err = ensure_complete_type(g, field_type))) { - struct_type->data.structure.is_invalid = true; + struct_type->data.structure.resolve_status = ResolveStatusInvalid; break; } @@ -1982,7 +1975,7 @@ static Error resolve_struct_type(CodeGen *g, ZigType *struct_type) { add_node_error(g, field_source_node, buf_sprintf("extern structs cannot contain fields of type '%s'", buf_ptr(&field_type->name))); - struct_type->data.structure.is_invalid = true; + struct_type->data.structure.resolve_status = ResolveStatusInvalid; break; } } @@ -1998,7 +1991,7 @@ static Error resolve_struct_type(CodeGen *g, ZigType *struct_type) { add_node_error(g, field_source_node, buf_sprintf("packed structs cannot contain fields of type '%s'", buf_ptr(&field_type->name))); - struct_type->data.structure.is_invalid = true; + struct_type->data.structure.resolve_status = ResolveStatusInvalid; break; } @@ -2049,12 +2042,13 @@ static Error resolve_struct_type(CodeGen *g, ZigType *struct_type) { gen_field_index += 1; } - struct_type->data.structure.embedded_in_current = false; - struct_type->data.structure.complete = true; + struct_type->data.structure.resolve_loop_flag = false; - if (struct_type->data.structure.is_invalid) + if (struct_type->data.structure.resolve_status == ResolveStatusInvalid) return ErrorSemanticAnalyzeFail; + struct_type->data.structure.resolve_status = ResolveStatusSizeKnown; + if (struct_type->zero_bits) { struct_type->type_ref = LLVMVoidType(); @@ -2116,7 +2110,7 @@ static Error resolve_struct_type(CodeGen *g, ZigType *struct_type) { assert(field_type->type_ref); assert(struct_type->type_ref); - assert(struct_type->data.structure.complete); + assert(struct_type->data.structure.resolve_status == ResolveStatusSizeKnown); uint64_t debug_size_in_bits; uint64_t debug_align_in_bits; uint64_t debug_offset_in_bits; @@ -2570,30 +2564,18 @@ static Error resolve_struct_zero_bits(CodeGen *g, ZigType *struct_type) { Error err; - if (struct_type->data.structure.is_invalid) + if (struct_type->data.structure.resolve_status == ResolveStatusInvalid) return ErrorSemanticAnalyzeFail; - - if (struct_type->data.structure.zero_bits_known) + if (struct_type->data.structure.resolve_status >= ResolveStatusZeroBitsKnown) return ErrorNone; - if (struct_type->data.structure.zero_bits_loop_flag) { - // If we get here it's due to recursion. This is a design flaw in the compiler, - // we should be able to still figure out alignment, but here we give up and say that - // the alignment is pointer width, then assert that the first field is within that - // alignment - struct_type->data.structure.zero_bits_known = true; - struct_type->data.structure.zero_bits_loop_flag = false; - if (struct_type->data.structure.abi_alignment == 0) { - if (struct_type->data.structure.layout == ContainerLayoutPacked) { - struct_type->data.structure.abi_alignment = 1; - } else { - struct_type->data.structure.abi_alignment = LLVMABIAlignmentOfType(g->target_data_ref, LLVMPointerType(LLVMInt8Type(), 0)); - } - } + if (struct_type->data.structure.resolve_loop_flag) { + struct_type->data.structure.resolve_status = ResolveStatusZeroBitsKnown; + struct_type->data.structure.resolve_loop_flag = false; return ErrorNone; } - struct_type->data.structure.zero_bits_loop_flag = true; + struct_type->data.structure.resolve_loop_flag = true; AstNode *decl_node = struct_type->data.structure.decl_node; assert(decl_node->type == NodeTypeContainerDecl); @@ -2616,7 +2598,7 @@ static Error resolve_struct_zero_bits(CodeGen *g, ZigType *struct_type) { if (field_node->data.struct_field.type == nullptr) { add_node_error(g, field_node, buf_sprintf("struct field missing type")); - struct_type->data.structure.is_invalid = true; + struct_type->data.structure.resolve_status = ResolveStatusInvalid; continue; } @@ -2625,7 +2607,7 @@ static Error resolve_struct_zero_bits(CodeGen *g, ZigType *struct_type) { ErrorMsg *msg = add_node_error(g, field_node, buf_sprintf("duplicate struct field: '%s'", buf_ptr(type_struct_field->name))); add_error_note(g, msg, field_entry->value->decl_node, buf_sprintf("other field here")); - struct_type->data.structure.is_invalid = true; + struct_type->data.structure.resolve_status = ResolveStatusInvalid; continue; } @@ -2639,8 +2621,8 @@ static Error resolve_struct_zero_bits(CodeGen *g, ZigType *struct_type) { buf_sprintf("enums, not structs, support field assignment")); } - if ((err = type_ensure_zero_bits_known(g, field_type))) { - struct_type->data.structure.is_invalid = true; + if ((err = type_resolve(g, field_type, ResolveStatusZeroBitsKnown))) { + struct_type->data.structure.resolve_status = ResolveStatusInvalid; continue; } @@ -2651,36 +2633,87 @@ static Error resolve_struct_zero_bits(CodeGen *g, ZigType *struct_type) { if (!type_has_bits(field_type)) continue; - if (gen_field_index == 0) { - if (struct_type->data.structure.layout == ContainerLayoutPacked) { - struct_type->data.structure.abi_alignment = 1; - } else if (struct_type->data.structure.abi_alignment == 0) { - // Alignment of structs is the alignment of the first field, for now. - // TODO change this when we re-order struct fields (issue #168) - struct_type->data.structure.abi_alignment = get_abi_alignment(g, field_type); - assert(struct_type->data.structure.abi_alignment != 0); - } else { - // due to a design flaw in the compiler we assumed that alignment was - // pointer width, so we assert that this wasn't violated. - if (get_abi_alignment(g, field_type) > struct_type->data.structure.abi_alignment) { - zig_panic("compiler design flaw: incorrect alignment assumption"); - } - } - } - type_struct_field->gen_index = gen_field_index; gen_field_index += 1; } - struct_type->data.structure.zero_bits_loop_flag = false; + struct_type->data.structure.resolve_loop_flag = false; struct_type->data.structure.gen_field_count = (uint32_t)gen_field_index; struct_type->zero_bits = (gen_field_index == 0); - struct_type->data.structure.zero_bits_known = true; - if (struct_type->data.structure.is_invalid) { + if (struct_type->data.structure.resolve_status == ResolveStatusInvalid) + return ErrorSemanticAnalyzeFail; + + struct_type->data.structure.resolve_status = ResolveStatusZeroBitsKnown; + return ErrorNone; +} + +static Error resolve_struct_alignment(CodeGen *g, ZigType *struct_type) { + assert(struct_type->id == ZigTypeIdStruct); + + Error err; + + if (struct_type->data.structure.resolve_status == ResolveStatusInvalid) + return ErrorSemanticAnalyzeFail; + if (struct_type->data.structure.resolve_status >= ResolveStatusAlignmentKnown) + return ErrorNone; + + if ((err = resolve_struct_zero_bits(g, struct_type))) + return err; + + AstNode *decl_node = struct_type->data.structure.decl_node; + + if (struct_type->data.structure.resolve_loop_flag) { + if (struct_type->data.structure.resolve_status != ResolveStatusInvalid) { + struct_type->data.structure.resolve_status = ResolveStatusInvalid; + add_node_error(g, decl_node, + buf_sprintf("struct '%s' contains itself", buf_ptr(&struct_type->name))); + } return ErrorSemanticAnalyzeFail; } + struct_type->data.structure.resolve_loop_flag = true; + assert(decl_node->type == NodeTypeContainerDecl); + assert(struct_type->di_type); + + if (struct_type->data.structure.layout == ContainerLayoutPacked) { + struct_type->data.structure.abi_alignment = 1; + } + + size_t field_count = struct_type->data.structure.src_field_count; + for (size_t i = 0; i < field_count; i += 1) { + TypeStructField *field = &struct_type->data.structure.fields[i]; + + // If this assertion trips, look up the call stack. Probably something is + // calling type_resolve with ResolveStatusAlignmentKnown when it should only + // be resolving ResolveStatusZeroBitsKnown + assert(field->type_entry != nullptr); + + if (!type_has_bits(field->type_entry)) + continue; + + // alignment of structs is the alignment of the most-aligned field + if (struct_type->data.structure.layout != ContainerLayoutPacked) { + if ((err = type_resolve(g, field->type_entry, ResolveStatusAlignmentKnown))) { + struct_type->data.structure.resolve_status = ResolveStatusInvalid; + break; + } + + uint32_t this_field_align = get_abi_alignment(g, field->type_entry); + assert(this_field_align != 0); + if (this_field_align > struct_type->data.structure.abi_alignment) { + struct_type->data.structure.abi_alignment = this_field_align; + } + } + } + + struct_type->data.structure.resolve_loop_flag = false; + + if (struct_type->data.structure.resolve_status == ResolveStatusInvalid) { + return ErrorSemanticAnalyzeFail; + } + + struct_type->data.structure.resolve_status = ResolveStatusAlignmentKnown; return ErrorNone; } @@ -2807,7 +2840,7 @@ static Error resolve_union_zero_bits(CodeGen *g, ZigType *union_type) { buf_sprintf("expected enum tag type, found '%s'", buf_ptr(&enum_type->name))); return ErrorSemanticAnalyzeFail; } - if ((err = type_ensure_zero_bits_known(g, enum_type))) { + if ((err = type_resolve(g, enum_type, ResolveStatusAlignmentKnown))) { assert(g->errors.length != 0); return err; } @@ -2848,7 +2881,7 @@ static Error resolve_union_zero_bits(CodeGen *g, ZigType *union_type) { } } else { field_type = analyze_type_expr(g, scope, field_node->data.struct_field.type); - if ((err = type_ensure_zero_bits_known(g, field_type))) { + if ((err = type_resolve(g, field_type, ResolveStatusAlignmentKnown))) { union_type->data.unionation.is_invalid = true; continue; } @@ -3111,7 +3144,7 @@ static void typecheck_panic_fn(CodeGen *g, ZigFn *panic_fn) { return wrong_panic_prototype(g, proto_node, fn_type); } ZigType *const_u8_ptr = get_pointer_to_type_extra(g, g->builtin_types.entry_u8, true, false, - PtrLenUnknown, get_abi_alignment(g, g->builtin_types.entry_u8), 0, 0); + PtrLenUnknown, 0, 0, 0); ZigType *const_u8_slice = get_slice_type(g, const_u8_ptr); if (fn_type_id->param_info[0].type != const_u8_slice) { return wrong_panic_prototype(g, proto_node, fn_type); @@ -3801,7 +3834,7 @@ TypeEnumField *find_enum_type_field(ZigType *enum_type, Buf *name) { TypeStructField *find_struct_type_field(ZigType *type_entry, Buf *name) { assert(type_entry->id == ZigTypeIdStruct); - assert(type_entry->data.structure.complete); + assert(type_is_resolved(type_entry, ResolveStatusZeroBitsKnown)); if (type_entry->data.structure.src_field_count == 0) return nullptr; auto entry = type_entry->data.structure.fields_by_name.maybe_get(name); @@ -3956,9 +3989,12 @@ bool type_is_codegen_pointer(ZigType *type) { uint32_t get_ptr_align(CodeGen *g, ZigType *type) { ZigType *ptr_type = get_codegen_ptr_type(type); if (ptr_type->id == ZigTypeIdPointer) { - return ptr_type->data.pointer.alignment; + return (ptr_type->data.pointer.explicit_alignment == 0) ? + get_abi_alignment(g, ptr_type->data.pointer.child_type) : ptr_type->data.pointer.explicit_alignment; } else if (ptr_type->id == ZigTypeIdFn) { - return (ptr_type->data.fn.fn_type_id.alignment == 0) ? 1 : ptr_type->data.fn.fn_type_id.alignment; + return (ptr_type->data.fn.fn_type_id.alignment == 0) ? + LLVMABIAlignmentOfType(g->target_data_ref, ptr_type->data.fn.raw_type_ref) : + ptr_type->data.fn.fn_type_id.alignment; } else if (ptr_type->id == ZigTypeIdPromise) { return get_coro_frame_align_bytes(g); } else { @@ -5023,8 +5059,8 @@ bool fn_eval_eql(Scope *a, Scope *b) { bool type_has_bits(ZigType *type_entry) { assert(type_entry); - assert(type_entry->id != ZigTypeIdInvalid); - assert(type_has_zero_bits_known(type_entry)); + assert(!type_is_invalid(type_entry)); + assert(type_is_resolved(type_entry, ResolveStatusZeroBitsKnown)); return !type_entry->zero_bits; } @@ -5045,10 +5081,10 @@ bool type_requires_comptime(ZigType *type_entry) { case ZigTypeIdArray: return type_requires_comptime(type_entry->data.array.child_type); case ZigTypeIdStruct: - assert(type_has_zero_bits_known(type_entry)); + assert(type_is_resolved(type_entry, ResolveStatusZeroBitsKnown)); return type_entry->data.structure.requires_comptime; case ZigTypeIdUnion: - assert(type_has_zero_bits_known(type_entry)); + assert(type_is_resolved(type_entry, ResolveStatusZeroBitsKnown)); return type_entry->data.unionation.requires_comptime; case ZigTypeIdOptional: return type_requires_comptime(type_entry->data.maybe.child_type); @@ -5124,7 +5160,7 @@ void init_const_c_str_lit(CodeGen *g, ConstExprValue *const_val, Buf *str) { const_val->special = ConstValSpecialStatic; // TODO make this `[*]null u8` instead of `[*]u8` const_val->type = get_pointer_to_type_extra(g, g->builtin_types.entry_u8, true, false, - PtrLenUnknown, get_abi_alignment(g, g->builtin_types.entry_u8), 0, 0); + PtrLenUnknown, 0, 0, 0); const_val->data.x_ptr.special = ConstPtrSpecialBaseArray; const_val->data.x_ptr.data.base_array.array_val = array_val; const_val->data.x_ptr.data.base_array.elem_index = 0; @@ -5269,8 +5305,7 @@ void init_const_slice(CodeGen *g, ConstExprValue *const_val, ConstExprValue *arr assert(array_val->type->id == ZigTypeIdArray); ZigType *ptr_type = get_pointer_to_type_extra(g, array_val->type->data.array.child_type, - is_const, false, PtrLenUnknown, get_abi_alignment(g, array_val->type->data.array.child_type), - 0, 0); + is_const, false, PtrLenUnknown, 0, 0, 0); const_val->special = ConstValSpecialStatic; const_val->type = get_slice_type(g, ptr_type); @@ -5295,7 +5330,7 @@ void init_const_ptr_array(CodeGen *g, ConstExprValue *const_val, ConstExprValue const_val->special = ConstValSpecialStatic; const_val->type = get_pointer_to_type_extra(g, child_type, is_const, false, - ptr_len, get_abi_alignment(g, child_type), 0, 0); + ptr_len, 0, 0, 0); const_val->data.x_ptr.special = ConstPtrSpecialBaseArray; const_val->data.x_ptr.data.base_array.array_val = array_val; const_val->data.x_ptr.data.base_array.elem_index = elem_index; @@ -5394,32 +5429,46 @@ ConstExprValue *create_const_vals(size_t count) { } Error ensure_complete_type(CodeGen *g, ZigType *type_entry) { - if (type_is_invalid(type_entry)) - return ErrorSemanticAnalyzeFail; - if (type_entry->id == ZigTypeIdStruct) { - if (!type_entry->data.structure.complete) - return resolve_struct_type(g, type_entry); - } else if (type_entry->id == ZigTypeIdEnum) { - if (!type_entry->data.enumeration.complete) - return resolve_enum_type(g, type_entry); - } else if (type_entry->id == ZigTypeIdUnion) { - if (!type_entry->data.unionation.complete) - return resolve_union_type(g, type_entry); - } - return ErrorNone; + return type_resolve(g, type_entry, ResolveStatusSizeKnown); } -Error type_ensure_zero_bits_known(CodeGen *g, ZigType *type_entry) { - if (type_is_invalid(type_entry)) +Error type_resolve(CodeGen *g, ZigType *ty, ResolveStatus status) { + if (type_is_invalid(ty)) return ErrorSemanticAnalyzeFail; - if (type_entry->id == ZigTypeIdStruct) { - return resolve_struct_zero_bits(g, type_entry); - } else if (type_entry->id == ZigTypeIdEnum) { - return resolve_enum_zero_bits(g, type_entry); - } else if (type_entry->id == ZigTypeIdUnion) { - return resolve_union_zero_bits(g, type_entry); + switch (status) { + case ResolveStatusUnstarted: + return ErrorNone; + case ResolveStatusInvalid: + zig_unreachable(); + case ResolveStatusZeroBitsKnown: + if (ty->id == ZigTypeIdStruct) { + return resolve_struct_zero_bits(g, ty); + } else if (ty->id == ZigTypeIdEnum) { + return resolve_enum_zero_bits(g, ty); + } else if (ty->id == ZigTypeIdUnion) { + return resolve_union_zero_bits(g, ty); + } + return ErrorNone; + case ResolveStatusAlignmentKnown: + if (ty->id == ZigTypeIdStruct) { + return resolve_struct_alignment(g, ty); + } else if (ty->id == ZigTypeIdEnum) { + return resolve_enum_zero_bits(g, ty); + } else if (ty->id == ZigTypeIdUnion) { + return resolve_union_zero_bits(g, ty); + } + return ErrorNone; + case ResolveStatusSizeKnown: + if (ty->id == ZigTypeIdStruct) { + return resolve_struct_type(g, ty); + } else if (ty->id == ZigTypeIdEnum) { + return resolve_enum_type(g, ty); + } else if (ty->id == ZigTypeIdUnion) { + return resolve_union_type(g, ty); + } + return ErrorNone; } - return ErrorNone; + zig_unreachable(); } bool ir_get_var_is_comptime(ZigVar *var) { @@ -6262,7 +6311,7 @@ LinkLib *add_link_lib(CodeGen *g, Buf *name) { } uint32_t get_abi_alignment(CodeGen *g, ZigType *type_entry) { - assertNoError(type_ensure_zero_bits_known(g, type_entry)); + assert(type_is_resolved(type_entry, ResolveStatusAlignmentKnown)); if (type_entry->zero_bits) return 0; // We need to make this function work without requiring ensure_complete_type diff --git a/src/analyze.hpp b/src/analyze.hpp index 76f2000cf7..874a29ceb8 100644 --- a/src/analyze.hpp +++ b/src/analyze.hpp @@ -59,9 +59,9 @@ bool get_ptr_const(ZigType *type); ZigType *validate_var_type(CodeGen *g, AstNode *source_node, ZigType *type_entry); ZigType *container_ref_type(ZigType *type_entry); bool type_is_complete(ZigType *type_entry); +bool type_is_resolved(ZigType *type_entry, ResolveStatus status); bool type_is_invalid(ZigType *type_entry); bool type_is_global_error_set(ZigType *err_set_type); -bool type_has_zero_bits_known(ZigType *type_entry); void resolve_container_type(CodeGen *g, ZigType *type_entry); ScopeDecls *get_container_scope(ZigType *type_entry); TypeStructField *find_struct_type_field(ZigType *type_entry, Buf *name); @@ -89,7 +89,7 @@ void init_fn_type_id(FnTypeId *fn_type_id, AstNode *proto_node, size_t param_cou AstNode *get_param_decl_node(ZigFn *fn_entry, size_t index); bool type_requires_comptime(ZigType *type_entry); Error ATTRIBUTE_MUST_USE ensure_complete_type(CodeGen *g, ZigType *type_entry); -Error ATTRIBUTE_MUST_USE type_ensure_zero_bits_known(CodeGen *g, ZigType *type_entry); +Error ATTRIBUTE_MUST_USE type_resolve(CodeGen *g, ZigType *type_entry, ResolveStatus status); void complete_enum(CodeGen *g, ZigType *enum_type); bool ir_get_var_is_comptime(ZigVar *var); bool const_values_equal(ConstExprValue *a, ConstExprValue *b); diff --git a/src/codegen.cpp b/src/codegen.cpp index 98bb06e6ee..090812bbb9 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -775,7 +775,8 @@ static LLVMValueRef gen_store_untyped(CodeGen *g, LLVMValueRef value, LLVMValueR static LLVMValueRef gen_store(CodeGen *g, LLVMValueRef value, LLVMValueRef ptr, ZigType *ptr_type) { assert(ptr_type->id == ZigTypeIdPointer); - return gen_store_untyped(g, value, ptr, ptr_type->data.pointer.alignment, ptr_type->data.pointer.is_volatile); + uint32_t alignment = get_ptr_align(g, ptr_type); + return gen_store_untyped(g, value, ptr, alignment, ptr_type->data.pointer.is_volatile); } static LLVMValueRef gen_load_untyped(CodeGen *g, LLVMValueRef ptr, uint32_t alignment, bool is_volatile, @@ -793,7 +794,8 @@ static LLVMValueRef gen_load_untyped(CodeGen *g, LLVMValueRef ptr, uint32_t alig static LLVMValueRef gen_load(CodeGen *g, LLVMValueRef ptr, ZigType *ptr_type, const char *name) { assert(ptr_type->id == ZigTypeIdPointer); - return gen_load_untyped(g, ptr, ptr_type->data.pointer.alignment, ptr_type->data.pointer.is_volatile, name); + uint32_t alignment = get_ptr_align(g, ptr_type); + return gen_load_untyped(g, ptr, alignment, ptr_type->data.pointer.is_volatile, name); } static LLVMValueRef get_handle_value(CodeGen *g, LLVMValueRef ptr, ZigType *type, ZigType *ptr_type) { @@ -1795,7 +1797,7 @@ static LLVMValueRef gen_assign_raw(CodeGen *g, LLVMValueRef ptr, ZigType *ptr_ty ZigType *usize = g->builtin_types.entry_usize; uint64_t size_bytes = LLVMStoreSizeOfType(g->target_data_ref, child_type->type_ref); - uint64_t align_bytes = ptr_type->data.pointer.alignment; + uint64_t align_bytes = get_ptr_align(g, ptr_type); assert(size_bytes > 0); assert(align_bytes > 0); @@ -4084,7 +4086,7 @@ static LLVMValueRef ir_render_align_cast(CodeGen *g, IrExecutable *executable, I LLVMValueRef ptr_val; if (target_type->id == ZigTypeIdPointer) { - align_bytes = target_type->data.pointer.alignment; + align_bytes = get_ptr_align(g, target_type); ptr_val = target_val; } else if (target_type->id == ZigTypeIdFn) { align_bytes = target_type->data.fn.fn_type_id.alignment; @@ -4092,7 +4094,7 @@ static LLVMValueRef ir_render_align_cast(CodeGen *g, IrExecutable *executable, I } else if (target_type->id == ZigTypeIdOptional && target_type->data.maybe.child_type->id == ZigTypeIdPointer) { - align_bytes = target_type->data.maybe.child_type->data.pointer.alignment; + align_bytes = get_ptr_align(g, target_type->data.maybe.child_type); ptr_val = target_val; } else if (target_type->id == ZigTypeIdOptional && target_type->data.maybe.child_type->id == ZigTypeIdFn) @@ -4105,7 +4107,7 @@ static LLVMValueRef ir_render_align_cast(CodeGen *g, IrExecutable *executable, I zig_panic("TODO audit this function"); } 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; - align_bytes = slice_ptr_type->data.pointer.alignment; + align_bytes = get_ptr_align(g, slice_ptr_type); 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, ""); @@ -4260,7 +4262,8 @@ static LLVMValueRef ir_render_memset(CodeGen *g, IrExecutable *executable, IrIns LLVMValueRef is_volatile = ptr_type->data.pointer.is_volatile ? LLVMConstAllOnes(LLVMInt1Type()) : LLVMConstNull(LLVMInt1Type()); - LLVMValueRef align_val = LLVMConstInt(LLVMInt32Type(), ptr_type->data.pointer.alignment, false); + uint32_t alignment = get_ptr_align(g, ptr_type); + LLVMValueRef align_val = LLVMConstInt(LLVMInt32Type(), alignment, false); LLVMValueRef params[] = { dest_ptr_casted, @@ -4293,7 +4296,7 @@ static LLVMValueRef ir_render_memcpy(CodeGen *g, IrExecutable *executable, IrIns LLVMValueRef is_volatile = (dest_ptr_type->data.pointer.is_volatile || src_ptr_type->data.pointer.is_volatile) ? LLVMConstAllOnes(LLVMInt1Type()) : LLVMConstNull(LLVMInt1Type()); - uint32_t min_align_bytes = min(src_ptr_type->data.pointer.alignment, dest_ptr_type->data.pointer.alignment); + uint32_t min_align_bytes = min(get_ptr_align(g, src_ptr_type), get_ptr_align(g, dest_ptr_type)); LLVMValueRef align_val = LLVMConstInt(LLVMInt32Type(), min_align_bytes, false); LLVMValueRef params[] = { diff --git a/src/ir.cpp b/src/ir.cpp index fd23992a9e..ce044aa0f3 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -40,6 +40,7 @@ struct IrAnalyze { enum ConstCastResultId { ConstCastResultIdOk, + ConstCastResultIdInvalid, ConstCastResultIdErrSet, ConstCastResultIdErrSetGlobal, ConstCastResultIdPointerChild, @@ -7490,8 +7491,7 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec if (type_has_bits(return_type)) { IrInstruction *u8_ptr_type_unknown_len = ir_build_const_type(irb, scope, node, get_pointer_to_type_extra(irb->codegen, irb->codegen->builtin_types.entry_u8, - false, false, PtrLenUnknown, get_abi_alignment(irb->codegen, irb->codegen->builtin_types.entry_u8), - 0, 0)); + false, false, PtrLenUnknown, 0, 0, 0)); IrInstruction *result_ptr = ir_build_load_ptr(irb, scope, node, irb->exec->coro_result_ptr_field_ptr); IrInstruction *result_ptr_as_u8_ptr = ir_build_ptr_cast(irb, scope, node, u8_ptr_type_unknown_len, result_ptr); IrInstruction *return_value_ptr_as_u8_ptr = ir_build_ptr_cast(irb, scope, node, u8_ptr_type_unknown_len, @@ -7544,8 +7544,7 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec IrInstruction *coro_mem_ptr_maybe = ir_build_coro_free(irb, scope, node, coro_id, irb->exec->coro_handle); IrInstruction *u8_ptr_type_unknown_len = ir_build_const_type(irb, scope, node, get_pointer_to_type_extra(irb->codegen, irb->codegen->builtin_types.entry_u8, - false, false, PtrLenUnknown, get_abi_alignment(irb->codegen, irb->codegen->builtin_types.entry_u8), - 0, 0)); + false, false, PtrLenUnknown, 0, 0, 0)); IrInstruction *coro_mem_ptr = ir_build_ptr_cast(irb, scope, node, u8_ptr_type_unknown_len, coro_mem_ptr_maybe); IrInstruction *coro_mem_ptr_ref = ir_build_ref(irb, scope, node, coro_mem_ptr, true, false); IrInstruction *coro_size_ptr = ir_build_var_ptr(irb, scope, node, coro_size_var); @@ -8516,6 +8515,8 @@ static ConstCastOnly types_match_const_cast_only(IrAnalyze *ira, ZigType *wanted ConstCastOnly result = {}; result.id = ConstCastResultIdOk; + Error err; + if (wanted_type == actual_type) return result; @@ -8528,6 +8529,8 @@ static ConstCastOnly types_match_const_cast_only(IrAnalyze *ira, ZigType *wanted { ConstCastOnly child = types_match_const_cast_only(ira, wanted_type->data.maybe.child_type, actual_type, source_node, wanted_is_mutable); + if (child.id == ConstCastResultIdInvalid) + return child; if (child.id != ConstCastResultIdOk) { result.id = ConstCastResultIdNullWrapPtr; result.data.null_wrap_ptr_child = allocate_nonzero(1); @@ -8544,7 +8547,6 @@ static ConstCastOnly types_match_const_cast_only(IrAnalyze *ira, ZigType *wanted (!actual_type->data.pointer.is_const || wanted_type->data.pointer.is_const) && (!actual_type->data.pointer.is_volatile || wanted_type->data.pointer.is_volatile)) { - assert(actual_type->data.pointer.alignment >= wanted_type->data.pointer.alignment); return result; } @@ -8552,6 +8554,8 @@ static ConstCastOnly types_match_const_cast_only(IrAnalyze *ira, ZigType *wanted if (wanted_type->id == ZigTypeIdPointer && actual_type->id == ZigTypeIdPointer) { ConstCastOnly child = types_match_const_cast_only(ira, wanted_type->data.pointer.child_type, actual_type->data.pointer.child_type, source_node, !wanted_type->data.pointer.is_const); + if (child.id == ConstCastResultIdInvalid) + return child; if (child.id != ConstCastResultIdOk) { result.id = ConstCastResultIdPointerChild; result.data.pointer_mismatch = allocate_nonzero(1); @@ -8560,12 +8564,20 @@ static ConstCastOnly types_match_const_cast_only(IrAnalyze *ira, ZigType *wanted result.data.pointer_mismatch->actual_child = actual_type->data.pointer.child_type; return result; } + if ((err = type_resolve(g, actual_type->data.pointer.child_type, ResolveStatusAlignmentKnown))) { + result.id = ConstCastResultIdInvalid; + return result; + } + if ((err = type_resolve(g, wanted_type->data.pointer.child_type, ResolveStatusAlignmentKnown))) { + result.id = ConstCastResultIdInvalid; + return result; + } if ((actual_type->data.pointer.ptr_len == wanted_type->data.pointer.ptr_len) && (!actual_type->data.pointer.is_const || wanted_type->data.pointer.is_const) && (!actual_type->data.pointer.is_volatile || wanted_type->data.pointer.is_volatile) && actual_type->data.pointer.bit_offset == wanted_type->data.pointer.bit_offset && actual_type->data.pointer.unaligned_bit_count == wanted_type->data.pointer.unaligned_bit_count && - actual_type->data.pointer.alignment >= wanted_type->data.pointer.alignment) + get_ptr_align(ira->codegen, actual_type) >= get_ptr_align(ira->codegen, wanted_type)) { return result; } @@ -8575,14 +8587,24 @@ static ConstCastOnly types_match_const_cast_only(IrAnalyze *ira, ZigType *wanted 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; + if ((err = type_resolve(g, actual_ptr_type->data.pointer.child_type, ResolveStatusAlignmentKnown))) { + result.id = ConstCastResultIdInvalid; + return result; + } + if ((err = type_resolve(g, wanted_ptr_type->data.pointer.child_type, ResolveStatusAlignmentKnown))) { + result.id = ConstCastResultIdInvalid; + return result; + } if ((!actual_ptr_type->data.pointer.is_const || wanted_ptr_type->data.pointer.is_const) && (!actual_ptr_type->data.pointer.is_volatile || wanted_ptr_type->data.pointer.is_volatile) && actual_ptr_type->data.pointer.bit_offset == wanted_ptr_type->data.pointer.bit_offset && actual_ptr_type->data.pointer.unaligned_bit_count == wanted_ptr_type->data.pointer.unaligned_bit_count && - actual_ptr_type->data.pointer.alignment >= wanted_ptr_type->data.pointer.alignment) + get_ptr_align(g, actual_ptr_type) >= get_ptr_align(g, wanted_ptr_type)) { ConstCastOnly child = types_match_const_cast_only(ira, wanted_ptr_type->data.pointer.child_type, actual_ptr_type->data.pointer.child_type, source_node, !wanted_ptr_type->data.pointer.is_const); + if (child.id == ConstCastResultIdInvalid) + return child; if (child.id != ConstCastResultIdOk) { result.id = ConstCastResultIdSliceChild; result.data.slice_mismatch = allocate_nonzero(1); @@ -8598,6 +8620,8 @@ static ConstCastOnly types_match_const_cast_only(IrAnalyze *ira, ZigType *wanted if (wanted_type->id == ZigTypeIdOptional && actual_type->id == ZigTypeIdOptional) { ConstCastOnly child = types_match_const_cast_only(ira, wanted_type->data.maybe.child_type, actual_type->data.maybe.child_type, source_node, wanted_is_mutable); + if (child.id == ConstCastResultIdInvalid) + return child; if (child.id != ConstCastResultIdOk) { result.id = ConstCastResultIdOptionalChild; result.data.optional = allocate_nonzero(1); @@ -8612,6 +8636,8 @@ static ConstCastOnly types_match_const_cast_only(IrAnalyze *ira, ZigType *wanted if (wanted_type->id == ZigTypeIdErrorUnion && actual_type->id == ZigTypeIdErrorUnion) { ConstCastOnly payload_child = types_match_const_cast_only(ira, wanted_type->data.error_union.payload_type, actual_type->data.error_union.payload_type, source_node, wanted_is_mutable); + if (payload_child.id == ConstCastResultIdInvalid) + return payload_child; if (payload_child.id != ConstCastResultIdOk) { result.id = ConstCastResultIdErrorUnionPayload; result.data.error_union_payload = allocate_nonzero(1); @@ -8622,6 +8648,8 @@ static ConstCastOnly types_match_const_cast_only(IrAnalyze *ira, ZigType *wanted } ConstCastOnly error_set_child = types_match_const_cast_only(ira, wanted_type->data.error_union.err_set_type, actual_type->data.error_union.err_set_type, source_node, wanted_is_mutable); + if (error_set_child.id == ConstCastResultIdInvalid) + return error_set_child; if (error_set_child.id != ConstCastResultIdOk) { result.id = ConstCastResultIdErrorUnionErrorSet; result.data.error_union_error_set = allocate_nonzero(1); @@ -8709,6 +8737,8 @@ static ConstCastOnly types_match_const_cast_only(IrAnalyze *ira, ZigType *wanted { ConstCastOnly child = types_match_const_cast_only(ira, wanted_type->data.fn.fn_type_id.return_type, actual_type->data.fn.fn_type_id.return_type, source_node, false); + if (child.id == ConstCastResultIdInvalid) + return child; if (child.id != ConstCastResultIdOk) { result.id = ConstCastResultIdFnReturnType; result.data.return_type = allocate_nonzero(1); @@ -8721,6 +8751,8 @@ static ConstCastOnly types_match_const_cast_only(IrAnalyze *ira, ZigType *wanted actual_type->data.fn.fn_type_id.async_allocator_type, wanted_type->data.fn.fn_type_id.async_allocator_type, source_node, false); + if (child.id == ConstCastResultIdInvalid) + return child; if (child.id != ConstCastResultIdOk) { result.id = ConstCastResultIdAsyncAllocatorType; result.data.async_allocator_type = allocate_nonzero(1); @@ -8745,6 +8777,8 @@ static ConstCastOnly types_match_const_cast_only(IrAnalyze *ira, ZigType *wanted ConstCastOnly arg_child = types_match_const_cast_only(ira, actual_param_info->type, expected_param_info->type, source_node, false); + if (arg_child.id == ConstCastResultIdInvalid) + return arg_child; if (arg_child.id != ConstCastResultIdOk) { result.id = ConstCastResultIdFnArg; result.data.fn_arg.arg_index = i; @@ -9238,7 +9272,7 @@ static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigT if (prev_type->id == ZigTypeIdEnum && cur_type->id == ZigTypeIdUnion && (cur_type->data.unionation.decl_node->data.container_decl.auto_enum || cur_type->data.unionation.decl_node->data.container_decl.init_arg_expr != nullptr)) { - if ((err = type_ensure_zero_bits_known(ira->codegen, cur_type))) + if ((err = type_resolve(ira->codegen, cur_type, ResolveStatusZeroBitsKnown))) return ira->codegen->builtin_types.entry_invalid; if (cur_type->data.unionation.tag_type == prev_type) { continue; @@ -9248,7 +9282,7 @@ static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigT if (cur_type->id == ZigTypeIdEnum && prev_type->id == ZigTypeIdUnion && (prev_type->data.unionation.decl_node->data.container_decl.auto_enum || prev_type->data.unionation.decl_node->data.container_decl.init_arg_expr != nullptr)) { - if ((err = type_ensure_zero_bits_known(ira->codegen, prev_type))) + if ((err = type_resolve(ira->codegen, prev_type, ResolveStatusZeroBitsKnown))) return ira->codegen->builtin_types.entry_invalid; if (prev_type->data.unionation.tag_type == cur_type) { prev_inst = cur_inst; @@ -9274,8 +9308,7 @@ static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigT ZigType *ptr_type = get_pointer_to_type_extra( ira->codegen, prev_inst->value.type->data.array.child_type, true, false, PtrLenUnknown, - get_abi_alignment(ira->codegen, prev_inst->value.type->data.array.child_type), - 0, 0); + 0, 0, 0); ZigType *slice_type = get_slice_type(ira->codegen, ptr_type); if (err_set_type != nullptr) { return get_error_union_type(ira->codegen, err_set_type, slice_type); @@ -9472,7 +9505,16 @@ static IrInstruction *ir_resolve_ptr_of_array_to_unknown_len_ptr(IrAnalyze *ira, IrInstruction *value, ZigType *wanted_type) { assert(value->value.type->id == ZigTypeIdPointer); - wanted_type = adjust_ptr_align(ira->codegen, wanted_type, value->value.type->data.pointer.alignment); + + Error err; + + if ((err = type_resolve(ira->codegen, value->value.type->data.pointer.child_type, + ResolveStatusAlignmentKnown))) + { + return ira->codegen->invalid_instruction; + } + + wanted_type = adjust_ptr_align(ira->codegen, wanted_type, get_ptr_align(ira->codegen, value->value.type)); if (instr_is_comptime(value)) { ConstExprValue *pointee = ir_const_ptr_pointee(ira, &value->value, source_instr->source_node); @@ -9500,7 +9542,15 @@ static IrInstruction *ir_resolve_ptr_of_array_to_unknown_len_ptr(IrAnalyze *ira, static IrInstruction *ir_resolve_ptr_of_array_to_slice(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *value, ZigType *wanted_type) { - wanted_type = adjust_slice_align(ira->codegen, wanted_type, value->value.type->data.pointer.alignment); + Error err; + + if ((err = type_resolve(ira->codegen, value->value.type->data.pointer.child_type, + ResolveStatusAlignmentKnown))) + { + return ira->codegen->invalid_instruction; + } + + wanted_type = adjust_slice_align(ira->codegen, wanted_type, get_ptr_align(ira->codegen, value->value.type)); if (instr_is_comptime(value)) { ConstExprValue *pointee = ir_const_ptr_pointee(ira, &value->value, source_instr->source_node); @@ -9687,8 +9737,7 @@ static ZigType *ir_analyze_const_ptr(IrAnalyze *ira, IrInstruction *instruction, ConstPtrMut ptr_mut, bool ptr_is_const, bool ptr_is_volatile) { IrInstruction *const_instr = ir_get_const_ptr(ira, instruction, pointee, - pointee_type, ptr_mut, ptr_is_const, ptr_is_volatile, - get_abi_alignment(ira->codegen, pointee_type)); + pointee_type, ptr_mut, ptr_is_const, ptr_is_volatile, 0); ir_link_new_instruction(const_instr, instruction); return const_instr->value.type; } @@ -10005,20 +10054,24 @@ static IrInstruction *ir_analyze_null_to_maybe(IrAnalyze *ira, IrInstruction *so static IrInstruction *ir_get_ref(IrAnalyze *ira, IrInstruction *source_instruction, IrInstruction *value, bool is_const, bool is_volatile) { + Error err; + if (type_is_invalid(value->value.type)) return ira->codegen->invalid_instruction; + if ((err = type_resolve(ira->codegen, value->value.type, ResolveStatusZeroBitsKnown))) + return ira->codegen->invalid_instruction; + if (instr_is_comptime(value)) { ConstExprValue *val = ir_resolve_const(ira, value, UndefOk); if (!val) return ira->codegen->invalid_instruction; return ir_get_const_ptr(ira, source_instruction, val, value->value.type, - ConstPtrMutComptimeConst, is_const, is_volatile, - get_abi_alignment(ira->codegen, value->value.type)); + ConstPtrMutComptimeConst, is_const, is_volatile, 0); } ZigType *ptr_type = get_pointer_to_type_extra(ira->codegen, value->value.type, - is_const, is_volatile, PtrLenSingle, get_abi_alignment(ira->codegen, value->value.type), 0, 0); + is_const, is_volatile, PtrLenSingle, 0, 0, 0); IrInstruction *new_instruction = ir_build_ref(&ira->new_irb, source_instruction->scope, source_instruction->source_node, value, is_const, is_volatile); new_instruction->value.type = ptr_type; @@ -10185,9 +10238,9 @@ static IrInstruction *ir_analyze_enum_to_union(IrAnalyze *ira, IrInstruction *so return ira->codegen->invalid_instruction; TypeUnionField *union_field = find_union_field_by_tag(wanted_type, &val->data.x_enum_tag); assert(union_field != nullptr); - if ((err = type_ensure_zero_bits_known(ira->codegen, union_field->type_entry))) + if ((err = type_resolve(ira->codegen, union_field->type_entry, ResolveStatusZeroBitsKnown))) return ira->codegen->invalid_instruction; - if (!union_field->type_entry->zero_bits) { + if (type_has_bits(union_field->type_entry)) { AstNode *field_node = wanted_type->data.unionation.decl_node->data.container_decl.fields.at( union_field->enum_field->decl_index); ErrorMsg *msg = ir_add_error(ira, source_instr, @@ -10490,7 +10543,10 @@ static IrInstruction *ir_analyze_ptr_to_array(IrAnalyze *ira, IrInstruction *sou ZigType *wanted_type) { assert(wanted_type->id == ZigTypeIdPointer); - wanted_type = adjust_ptr_align(ira->codegen, wanted_type, target->value.type->data.pointer.alignment); + Error err; + if ((err = type_resolve(ira->codegen, target->value.type->data.pointer.child_type, ResolveStatusAlignmentKnown))) + return ira->codegen->invalid_instruction; + wanted_type = adjust_ptr_align(ira->codegen, wanted_type, get_ptr_align(ira->codegen, target->value.type)); ZigType *array_type = wanted_type->data.pointer.child_type; assert(array_type->id == ZigTypeIdArray); assert(array_type->data.array.len == 1); @@ -10537,6 +10593,8 @@ static void report_recursive_error(IrAnalyze *ira, AstNode *source_node, ConstCa switch (cast_result->id) { case ConstCastResultIdOk: zig_unreachable(); + case ConstCastResultIdInvalid: + zig_unreachable(); case ConstCastResultIdOptionalChild: { ErrorMsg *msg = add_error_note(ira->codegen, parent_msg, source_node, buf_sprintf("optional type child '%s' cannot cast into optional type child '%s'", @@ -10636,6 +10694,8 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst // perfect match or non-const to const ConstCastOnly const_cast_result = types_match_const_cast_only(ira, wanted_type, actual_type, source_node, false); + if (const_cast_result.id == ConstCastResultIdInvalid) + return ira->codegen->invalid_instruction; if (const_cast_result.id == ConstCastResultIdOk) { return ir_resolve_cast(ira, source_instr, value, wanted_type, CastOpNoop, false); } @@ -10751,13 +10811,19 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst wanted_type->data.pointer.ptr_len == PtrLenUnknown && actual_type->id == ZigTypeIdPointer && actual_type->data.pointer.ptr_len == PtrLenSingle && - actual_type->data.pointer.child_type->id == ZigTypeIdArray && - actual_type->data.pointer.alignment >= wanted_type->data.pointer.alignment && - types_match_const_cast_only(ira, wanted_type->data.pointer.child_type, - actual_type->data.pointer.child_type->data.array.child_type, source_node, - !wanted_type->data.pointer.is_const).id == ConstCastResultIdOk) + actual_type->data.pointer.child_type->id == ZigTypeIdArray) { - return ir_resolve_ptr_of_array_to_unknown_len_ptr(ira, source_instr, value, wanted_type); + if ((err = type_resolve(ira->codegen, actual_type->data.pointer.child_type, ResolveStatusAlignmentKnown))) + return ira->codegen->invalid_instruction; + if ((err = type_resolve(ira->codegen, wanted_type->data.pointer.child_type, ResolveStatusAlignmentKnown))) + return ira->codegen->invalid_instruction; + if (get_ptr_align(ira->codegen, actual_type) >= get_ptr_align(ira->codegen, wanted_type) && + types_match_const_cast_only(ira, wanted_type->data.pointer.child_type, + actual_type->data.pointer.child_type->data.array.child_type, source_node, + !wanted_type->data.pointer.is_const).id == ConstCastResultIdOk) + { + return ir_resolve_ptr_of_array_to_unknown_len_ptr(ira, source_instr, value, wanted_type); + } } // *[N]T to []T @@ -10811,16 +10877,23 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst wanted_child_type->data.pointer.ptr_len == PtrLenUnknown && actual_type->id == ZigTypeIdPointer && actual_type->data.pointer.ptr_len == PtrLenSingle && - actual_type->data.pointer.child_type->id == ZigTypeIdArray && - actual_type->data.pointer.alignment >= wanted_child_type->data.pointer.alignment && - types_match_const_cast_only(ira, wanted_child_type->data.pointer.child_type, - actual_type->data.pointer.child_type->data.array.child_type, source_node, - !wanted_child_type->data.pointer.is_const).id == ConstCastResultIdOk) + actual_type->data.pointer.child_type->id == ZigTypeIdArray) { - IrInstruction *cast1 = ir_resolve_ptr_of_array_to_unknown_len_ptr(ira, source_instr, value, wanted_child_type); - if (type_is_invalid(cast1->value.type)) + if ((err = type_resolve(ira->codegen, actual_type->data.pointer.child_type, ResolveStatusAlignmentKnown))) return ira->codegen->invalid_instruction; - return ir_analyze_maybe_wrap(ira, source_instr, cast1, wanted_type); + if ((err = type_resolve(ira->codegen, wanted_child_type->data.pointer.child_type, ResolveStatusAlignmentKnown))) + return ira->codegen->invalid_instruction; + if (get_ptr_align(ira->codegen, actual_type) >= get_ptr_align(ira->codegen, wanted_child_type) && + types_match_const_cast_only(ira, wanted_child_type->data.pointer.child_type, + actual_type->data.pointer.child_type->data.array.child_type, source_node, + !wanted_child_type->data.pointer.is_const).id == ConstCastResultIdOk) + { + IrInstruction *cast1 = ir_resolve_ptr_of_array_to_unknown_len_ptr(ira, source_instr, value, + wanted_child_type); + if (type_is_invalid(cast1->value.type)) + return ira->codegen->invalid_instruction; + return ir_analyze_maybe_wrap(ira, source_instr, cast1, wanted_type); + } } } @@ -10963,7 +11036,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst // cast from union to the enum type of the union if (actual_type->id == ZigTypeIdUnion && wanted_type->id == ZigTypeIdEnum) { - if ((err = type_ensure_zero_bits_known(ira->codegen, actual_type))) + if ((err = type_resolve(ira->codegen, actual_type, ResolveStatusZeroBitsKnown))) return ira->codegen->invalid_instruction; if (actual_type->data.unionation.tag_type == wanted_type) { @@ -10976,7 +11049,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst (wanted_type->data.unionation.decl_node->data.container_decl.auto_enum || wanted_type->data.unionation.decl_node->data.container_decl.init_arg_expr != nullptr)) { - if ((err = type_ensure_zero_bits_known(ira->codegen, wanted_type))) + if ((err = type_resolve(ira->codegen, wanted_type, ResolveStatusZeroBitsKnown))) return ira->codegen->invalid_instruction; if (wanted_type->data.unionation.tag_type == actual_type) { @@ -10990,7 +11063,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst if (union_type->data.unionation.decl_node->data.container_decl.auto_enum || union_type->data.unionation.decl_node->data.container_decl.init_arg_expr != nullptr) { - if ((err = type_ensure_zero_bits_known(ira->codegen, union_type))) + if ((err = type_resolve(ira->codegen, union_type, ResolveStatusZeroBitsKnown))) return ira->codegen->invalid_instruction; if (union_type->data.unionation.tag_type == actual_type) { @@ -11017,14 +11090,24 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst actual_type->data.pointer.child_type, source_node, !wanted_type->data.pointer.is_const).id == ConstCastResultIdOk) { - if (wanted_type->data.pointer.alignment > actual_type->data.pointer.alignment) { + if ((err = type_resolve(ira->codegen, wanted_type->data.pointer.child_type, + ResolveStatusAlignmentKnown))) + { + return ira->codegen->invalid_instruction; + } + if ((err = type_resolve(ira->codegen, actual_type->data.pointer.child_type, + ResolveStatusAlignmentKnown))) + { + return ira->codegen->invalid_instruction; + } + uint32_t wanted_align = get_ptr_align(ira->codegen, wanted_type); + uint32_t actual_align = get_ptr_align(ira->codegen, actual_type); + if (wanted_align > actual_align) { ErrorMsg *msg = ir_add_error(ira, source_instr, buf_sprintf("cast increases pointer alignment")); add_error_note(ira->codegen, msg, value->source_node, - buf_sprintf("'%s' has alignment %" PRIu32, buf_ptr(&actual_type->name), - actual_type->data.pointer.alignment)); + buf_sprintf("'%s' has alignment %" PRIu32, buf_ptr(&actual_type->name), actual_align)); add_error_note(ira->codegen, msg, source_instr->source_node, - buf_sprintf("'%s' has alignment %" PRIu32, buf_ptr(&wanted_type->name), - wanted_type->data.pointer.alignment)); + buf_sprintf("'%s' has alignment %" PRIu32, buf_ptr(&wanted_type->name), wanted_align)); return ira->codegen->invalid_instruction; } return ir_analyze_ptr_to_array(ira, source_instr, value, wanted_type); @@ -11036,7 +11119,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst types_match_const_cast_only(ira, wanted_type->data.pointer.child_type, actual_type, source_node, !wanted_type->data.pointer.is_const).id == ConstCastResultIdOk) { - if ((err = type_ensure_zero_bits_known(ira->codegen, actual_type))) { + if ((err = type_resolve(ira->codegen, actual_type, ResolveStatusZeroBitsKnown))) { return ira->codegen->invalid_instruction; } if (!type_has_bits(actual_type)) { @@ -11282,8 +11365,7 @@ static Buf *ir_resolve_str(IrAnalyze *ira, IrInstruction *value) { return nullptr; ZigType *ptr_type = get_pointer_to_type_extra(ira->codegen, ira->codegen->builtin_types.entry_u8, - true, false, PtrLenUnknown, - get_abi_alignment(ira->codegen, ira->codegen->builtin_types.entry_u8), 0, 0); + true, false, PtrLenUnknown, 0, 0, 0); ZigType *str_type = get_slice_type(ira->codegen, ptr_type); IrInstruction *casted_value = ir_implicit_cast(ira, value, str_type); if (type_is_invalid(casted_value->value.type)) @@ -11573,8 +11655,6 @@ static ZigType *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp *bin_op ZigType *resolved_type = ir_resolve_peer_types(ira, source_node, nullptr, instructions, 2); if (type_is_invalid(resolved_type)) return resolved_type; - if ((err = type_ensure_zero_bits_known(ira->codegen, resolved_type))) - return resolved_type; bool operator_allowed; switch (resolved_type->id) { @@ -11630,6 +11710,9 @@ static ZigType *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp *bin_op if (casted_op2 == ira->codegen->invalid_instruction) return ira->codegen->builtin_types.entry_invalid; + if ((err = type_resolve(ira->codegen, resolved_type, ResolveStatusZeroBitsKnown))) + return resolved_type; + bool one_possible_value = !type_requires_comptime(resolved_type) && !type_has_bits(resolved_type); if (one_possible_value || (instr_is_comptime(casted_op1) && instr_is_comptime(casted_op2))) { ConstExprValue *op1_val = one_possible_value ? &casted_op1->value : ir_resolve_const(ira, casted_op1, UndefBad); @@ -12316,7 +12399,7 @@ static ZigType *ir_analyze_array_cat(IrAnalyze *ira, IrInstructionBinOp *instruc out_array_val = out_val; } else if (is_slice(op1_type) || is_slice(op2_type)) { ZigType *ptr_type = get_pointer_to_type_extra(ira->codegen, child_type, - true, false, PtrLenUnknown, get_abi_alignment(ira->codegen, child_type), 0, 0); + true, false, PtrLenUnknown, 0, 0, 0); result_type = get_slice_type(ira->codegen, ptr_type); out_array_val = create_const_vals(1); out_array_val->special = ConstValSpecialStatic; @@ -12337,8 +12420,7 @@ static ZigType *ir_analyze_array_cat(IrAnalyze *ira, IrInstructionBinOp *instruc new_len += 1; // null byte // TODO make this `[*]null T` instead of `[*]T` - result_type = get_pointer_to_type_extra(ira->codegen, child_type, true, false, - PtrLenUnknown, get_abi_alignment(ira->codegen, child_type), 0, 0); + result_type = get_pointer_to_type_extra(ira->codegen, child_type, true, false, PtrLenUnknown, 0, 0, 0); out_array_val = create_const_vals(1); out_array_val->special = ConstValSpecialStatic; @@ -12563,7 +12645,7 @@ static ZigType *ir_analyze_instruction_decl_var(IrAnalyze *ira, IrInstructionDec if (type_is_invalid(result_type)) { result_type = ira->codegen->builtin_types.entry_invalid; } else { - if ((err = type_ensure_zero_bits_known(ira->codegen, result_type))) { + if ((err = type_resolve(ira->codegen, result_type, ResolveStatusZeroBitsKnown))) { result_type = ira->codegen->builtin_types.entry_invalid; } } @@ -12631,6 +12713,11 @@ static ZigType *ir_analyze_instruction_decl_var(IrAnalyze *ira, IrInstructionDec } if (decl_var_instruction->align_value == nullptr) { + if ((err = type_resolve(ira->codegen, result_type, ResolveStatusAlignmentKnown))) { + var->value->type = ira->codegen->builtin_types.entry_invalid; + decl_var_instruction->base.other = &decl_var_instruction->base; + return ira->codegen->builtin_types.entry_void; + } var->align_bytes = get_abi_alignment(ira->codegen, result_type); } else { if (!ir_resolve_align(ira, decl_var_instruction->align_value->other, &var->align_bytes)) { @@ -13100,7 +13187,6 @@ static ZigVar *get_fn_var_by_index(ZigFn *fn_entry, size_t index) { static IrInstruction *ir_get_var_ptr(IrAnalyze *ira, IrInstruction *instruction, ZigVar *var) { - Error err; while (var->next_var != nullptr) { var = var->next_var; } @@ -13158,8 +13244,6 @@ no_mem_slot: instruction->scope, instruction->source_node, var); var_ptr_instruction->value.type = get_pointer_to_type_extra(ira->codegen, var->value->type, var->src_is_const, is_volatile, PtrLenSingle, var->align_bytes, 0, 0); - if ((err = type_ensure_zero_bits_known(ira->codegen, var->value->type))) - return ira->codegen->invalid_instruction; bool in_fn_scope = (scope_fn_entry(var->parent_scope) != nullptr); var_ptr_instruction->value.data.rh_ptr = in_fn_scope ? RuntimeHintPtrStack : RuntimeHintPtrNonStack; @@ -13356,8 +13440,7 @@ static ZigType *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *call_instr IrInstruction *casted_new_stack = nullptr; if (call_instruction->new_stack != nullptr) { ZigType *u8_ptr = get_pointer_to_type_extra(ira->codegen, ira->codegen->builtin_types.entry_u8, - false, false, PtrLenUnknown, - get_abi_alignment(ira->codegen, ira->codegen->builtin_types.entry_u8), 0, 0); + false, false, PtrLenUnknown, 0, 0, 0); ZigType *u8_slice = get_slice_type(ira->codegen, u8_ptr); IrInstruction *new_stack = call_instruction->new_stack->other; if (type_is_invalid(new_stack->value.type)) @@ -13536,7 +13619,7 @@ static ZigType *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *call_instr inst_fn_type_id.return_type = specified_return_type; } - if ((err = type_ensure_zero_bits_known(ira->codegen, specified_return_type))) + if ((err = type_resolve(ira->codegen, specified_return_type, ResolveStatusZeroBitsKnown))) return ira->codegen->builtin_types.entry_invalid; if (type_requires_comptime(specified_return_type)) { @@ -14212,7 +14295,7 @@ static ZigType *adjust_ptr_len(CodeGen *g, ZigType *ptr_type, PtrLen ptr_len) { ptr_type->data.pointer.child_type, ptr_type->data.pointer.is_const, ptr_type->data.pointer.is_volatile, ptr_len, - ptr_type->data.pointer.alignment, + ptr_type->data.pointer.explicit_alignment, ptr_type->data.pointer.bit_offset, ptr_type->data.pointer.unaligned_bit_count); } @@ -14264,7 +14347,7 @@ static ZigType *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstructionEle return_type = get_pointer_to_type_extra(ira->codegen, child_type, ptr_type->data.pointer.is_const, ptr_type->data.pointer.is_volatile, elem_ptr_instruction->ptr_len, - ptr_type->data.pointer.alignment, 0, 0); + ptr_type->data.pointer.explicit_alignment, 0, 0); } else { uint64_t elem_val_scalar; if (!ir_resolve_usize(ira, elem_index, &elem_val_scalar)) @@ -14336,7 +14419,7 @@ static ZigType *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstructionEle uint64_t elem_size = type_size(ira->codegen, return_type->data.pointer.child_type); uint64_t abi_align = get_abi_alignment(ira->codegen, return_type->data.pointer.child_type); - uint64_t ptr_align = return_type->data.pointer.alignment; + uint64_t ptr_align = get_ptr_align(ira->codegen, return_type); if (instr_is_comptime(casted_elem_index)) { uint64_t index = bigint_as_unsigned(&casted_elem_index->value.data.x_bigint); if (array_type->id == ZigTypeIdArray) { @@ -14653,9 +14736,7 @@ static IrInstruction *ir_analyze_container_field_ptr(IrAnalyze *ira, Buf *field_ } ZigType *ptr_type = get_pointer_to_type_extra(ira->codegen, field_type, - is_const, is_volatile, - PtrLenSingle, - get_abi_alignment(ira->codegen, field_type), 0, 0); + is_const, is_volatile, PtrLenSingle, 0, 0, 0); IrInstruction *result = ir_get_const(ira, source_instr); ConstExprValue *const_val = &result->value; @@ -14669,7 +14750,7 @@ static IrInstruction *ir_analyze_container_field_ptr(IrAnalyze *ira, Buf *field_ IrInstruction *result = ir_build_union_field_ptr(&ira->new_irb, source_instr->scope, source_instr->source_node, container_ptr, field); result->value.type = get_pointer_to_type_extra(ira->codegen, field->type_entry, is_const, is_volatile, - PtrLenSingle, get_abi_alignment(ira->codegen, field->type_entry), 0, 0); + PtrLenSingle, 0, 0, 0); return result; } else { return ir_analyze_container_member_access_inner(ira, bare_type, field_name, @@ -15002,9 +15083,14 @@ static ZigType *ir_analyze_instruction_field_ptr(IrAnalyze *ira, IrInstructionFi } else if (buf_eql_str(field_name, "alignment")) { bool ptr_is_const = true; bool ptr_is_volatile = false; + if ((err = type_resolve(ira->codegen, child_type->data.pointer.child_type, + ResolveStatusAlignmentKnown))) + { + return ira->codegen->builtin_types.entry_invalid; + } return ir_analyze_const_ptr(ira, &field_ptr_instruction->base, create_const_unsigned_negative(ira->codegen->builtin_types.entry_num_lit_int, - child_type->data.pointer.alignment, false), + get_ptr_align(ira->codegen, child_type), false), ira->codegen->builtin_types.entry_num_lit_int, ConstPtrMutComptimeConst, ptr_is_const, ptr_is_volatile); } else { @@ -15461,7 +15547,7 @@ static ZigType *ir_analyze_instruction_slice_type(IrAnalyze *ira, IrInstructionSliceType *slice_type_instruction) { Error err; - uint32_t align_bytes; + uint32_t align_bytes = 0; if (slice_type_instruction->align_value != nullptr) { if (!ir_resolve_align(ira, slice_type_instruction->align_value->other, &align_bytes)) return ira->codegen->builtin_types.entry_invalid; @@ -15471,12 +15557,6 @@ static ZigType *ir_analyze_instruction_slice_type(IrAnalyze *ira, if (type_is_invalid(child_type)) return ira->codegen->builtin_types.entry_invalid; - if (slice_type_instruction->align_value == nullptr) { - if ((err = type_ensure_zero_bits_known(ira->codegen, child_type))) - return ira->codegen->builtin_types.entry_invalid; - align_bytes = get_abi_alignment(ira->codegen, child_type); - } - bool is_const = slice_type_instruction->is_const; bool is_volatile = slice_type_instruction->is_volatile; @@ -15511,7 +15591,7 @@ static ZigType *ir_analyze_instruction_slice_type(IrAnalyze *ira, case ZigTypeIdBoundFn: case ZigTypeIdPromise: { - if ((err = type_ensure_zero_bits_known(ira->codegen, child_type))) + if ((err = type_resolve(ira->codegen, child_type, ResolveStatusZeroBitsKnown))) return ira->codegen->builtin_types.entry_invalid; ZigType *slice_ptr_type = get_pointer_to_type_extra(ira->codegen, child_type, is_const, is_volatile, PtrLenUnknown, align_bytes, 0, 0); @@ -15751,9 +15831,7 @@ static ZigType *ir_analyze_instruction_unwrap_maybe(IrAnalyze *ira, } ZigType *child_type = type_entry->data.maybe.child_type; ZigType *result_type = get_pointer_to_type_extra(ira->codegen, child_type, - ptr_type->data.pointer.is_const, ptr_type->data.pointer.is_volatile, - PtrLenSingle, - get_abi_alignment(ira->codegen, child_type), 0, 0); + ptr_type->data.pointer.is_const, ptr_type->data.pointer.is_volatile, PtrLenSingle, 0, 0, 0); if (instr_is_comptime(value)) { ConstExprValue *val = ir_resolve_const(ira, value, UndefBad); @@ -16123,7 +16201,7 @@ static ZigType *ir_analyze_instruction_switch_target(IrAnalyze *ira, return tag_type; } case ZigTypeIdEnum: { - if ((err = type_ensure_zero_bits_known(ira->codegen, target_type))) + if ((err = type_resolve(ira->codegen, target_type, ResolveStatusZeroBitsKnown))) return ira->codegen->builtin_types.entry_invalid; if (target_type->data.enumeration.src_field_count < 2) { TypeEnumField *only_field = &target_type->data.enumeration.fields[0]; @@ -16352,7 +16430,7 @@ static ZigType *ir_analyze_container_init_fields_union(IrAnalyze *ira, IrInstruc if (casted_field_value == ira->codegen->invalid_instruction) return ira->codegen->builtin_types.entry_invalid; - if ((err = type_ensure_zero_bits_known(ira->codegen, casted_field_value->value.type))) + if ((err = type_resolve(ira->codegen, casted_field_value->value.type, ResolveStatusZeroBitsKnown))) return ira->codegen->builtin_types.entry_invalid; bool is_comptime = ir_should_inline(ira->new_irb.exec, instruction->scope); @@ -16752,7 +16830,7 @@ static ZigType *ir_analyze_instruction_err_name(IrAnalyze *ira, IrInstructionErr return ira->codegen->builtin_types.entry_invalid; ZigType *u8_ptr_type = get_pointer_to_type_extra(ira->codegen, ira->codegen->builtin_types.entry_u8, - true, false, PtrLenUnknown, get_abi_alignment(ira->codegen, ira->codegen->builtin_types.entry_u8), 0, 0); + true, false, PtrLenUnknown, 0, 0, 0); ZigType *str_type = get_slice_type(ira->codegen, u8_ptr_type); if (casted_value->value.special == ConstValSpecialStatic) { ErrorTableEntry *err = casted_value->value.data.x_err_set; @@ -16779,7 +16857,7 @@ static ZigType *ir_analyze_instruction_enum_tag_name(IrAnalyze *ira, IrInstructi assert(target->value.type->id == ZigTypeIdEnum); if (instr_is_comptime(target)) { - if ((err = type_ensure_zero_bits_known(ira->codegen, target->value.type))) + if ((err = type_resolve(ira->codegen, target->value.type, ResolveStatusZeroBitsKnown))) return ira->codegen->builtin_types.entry_invalid; TypeEnumField *field = find_enum_field_by_tag(target->value.type, &target->value.data.x_bigint); ConstExprValue *array_val = create_const_str_lit(ira->codegen, field->name); @@ -16794,8 +16872,7 @@ static ZigType *ir_analyze_instruction_enum_tag_name(IrAnalyze *ira, IrInstructi ZigType *u8_ptr_type = get_pointer_to_type_extra( ira->codegen, ira->codegen->builtin_types.entry_u8, true, false, PtrLenUnknown, - get_abi_alignment(ira->codegen, ira->codegen->builtin_types.entry_u8), - 0, 0); + 0, 0, 0); result->value.type = get_slice_type(ira->codegen, u8_ptr_type); return result->value.type; } @@ -17158,8 +17235,7 @@ static Error ir_make_type_info_defs(IrAnalyze *ira, ConstExprValue *out_val, Sco ZigType *u8_ptr = get_pointer_to_type_extra( ira->codegen, ira->codegen->builtin_types.entry_u8, true, false, PtrLenUnknown, - get_abi_alignment(ira->codegen, ira->codegen->builtin_types.entry_u8), - 0, 0); + 0, 0, 0); fn_def_fields[6].type = get_optional_type(ira->codegen, get_slice_type(ira->codegen, u8_ptr)); if (fn_node->is_extern && buf_len(fn_node->lib_name) > 0) { fn_def_fields[6].data.x_optional = create_const_vals(1); @@ -17279,7 +17355,7 @@ static ConstExprValue *create_ptr_like_type_info(IrAnalyze *ira, ZigType *ptr_ty ensure_field_index(result->type, "alignment", 3); fields[3].special = ConstValSpecialStatic; fields[3].type = get_int_type(ira->codegen, false, 29); - bigint_init_unsigned(&fields[3].data.x_bigint, attrs_type->data.pointer.alignment); + 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; @@ -18369,7 +18445,21 @@ static ZigType *ir_analyze_instruction_err_set_cast(IrAnalyze *ira, IrInstructio return dest_type; } +static Error resolve_ptr_align(IrAnalyze *ira, ZigType *ty, uint32_t *result_align) { + Error err; + + if (ty->id == ZigTypeIdPointer) { + if ((err = type_resolve(ira->codegen, ty->data.pointer.child_type, ResolveStatusAlignmentKnown))) + return err; + } + + *result_align = get_ptr_align(ira->codegen, ty); + return ErrorNone; +} + static ZigType *ir_analyze_instruction_from_bytes(IrAnalyze *ira, IrInstructionFromBytes *instruction) { + Error err; + ZigType *dest_child_type = ir_resolve_type(ira, instruction->dest_child_type->other); if (type_is_invalid(dest_child_type)) return ira->codegen->builtin_types.entry_invalid; @@ -18384,15 +18474,23 @@ static ZigType *ir_analyze_instruction_from_bytes(IrAnalyze *ira, IrInstructionF if (target->value.type->id == ZigTypeIdPointer) { src_ptr_const = target->value.type->data.pointer.is_const; src_ptr_volatile = target->value.type->data.pointer.is_volatile; - src_ptr_align = target->value.type->data.pointer.alignment; + + if ((err = resolve_ptr_align(ira, target->value.type, &src_ptr_align))) + return ira->codegen->builtin_types.entry_invalid; } else if (is_slice(target->value.type)) { 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; - src_ptr_align = src_ptr_type->data.pointer.alignment; + + if ((err = resolve_ptr_align(ira, src_ptr_type, &src_ptr_align))) + return ira->codegen->builtin_types.entry_invalid; } else { src_ptr_const = true; src_ptr_volatile = false; + + if ((err = type_resolve(ira->codegen, target->value.type, ResolveStatusAlignmentKnown))) + return ira->codegen->builtin_types.entry_invalid; + src_ptr_align = get_abi_alignment(ira->codegen, target->value.type); } @@ -18450,6 +18548,8 @@ static ZigType *ir_analyze_instruction_from_bytes(IrAnalyze *ira, IrInstructionF } static ZigType *ir_analyze_instruction_to_bytes(IrAnalyze *ira, IrInstructionToBytes *instruction) { + Error err; + IrInstruction *target = instruction->target->other; if (type_is_invalid(target->value.type)) return ira->codegen->builtin_types.entry_invalid; @@ -18462,9 +18562,13 @@ static ZigType *ir_analyze_instruction_to_bytes(IrAnalyze *ira, IrInstructionToB 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))) + return ira->codegen->builtin_types.entry_invalid; + ZigType *dest_ptr_type = get_pointer_to_type_extra(ira->codegen, ira->codegen->builtin_types.entry_u8, src_ptr_type->data.pointer.is_const, src_ptr_type->data.pointer.is_volatile, PtrLenUnknown, - src_ptr_type->data.pointer.alignment, 0, 0); + alignment, 0, 0); ZigType *dest_slice_type = get_slice_type(ira->codegen, dest_ptr_type); IrInstruction *result = ir_resolve_cast(ira, &instruction->base, target, dest_slice_type, CastOpResizeSlice, true); @@ -18622,6 +18726,8 @@ static ZigType *ir_analyze_instruction_bool_not(IrAnalyze *ira, IrInstructionBoo } static ZigType *ir_analyze_instruction_memset(IrAnalyze *ira, IrInstructionMemset *instruction) { + Error err; + IrInstruction *dest_ptr = instruction->dest_ptr->other; if (type_is_invalid(dest_ptr->value.type)) return ira->codegen->builtin_types.entry_invalid; @@ -18640,8 +18746,13 @@ static ZigType *ir_analyze_instruction_memset(IrAnalyze *ira, IrInstructionMemse ZigType *usize = ira->codegen->builtin_types.entry_usize; ZigType *u8 = ira->codegen->builtin_types.entry_u8; - uint32_t dest_align = (dest_uncasted_type->id == ZigTypeIdPointer) ? - dest_uncasted_type->data.pointer.alignment : get_abi_alignment(ira->codegen, u8); + uint32_t dest_align; + if (dest_uncasted_type->id == ZigTypeIdPointer) { + if ((err = resolve_ptr_align(ira, dest_uncasted_type, &dest_align))) + return ira->codegen->builtin_types.entry_invalid; + } else { + dest_align = get_abi_alignment(ira->codegen, u8); + } ZigType *u8_ptr = get_pointer_to_type_extra(ira->codegen, u8, false, dest_is_volatile, PtrLenUnknown, dest_align, 0, 0); @@ -18714,6 +18825,8 @@ static ZigType *ir_analyze_instruction_memset(IrAnalyze *ira, IrInstructionMemse } static ZigType *ir_analyze_instruction_memcpy(IrAnalyze *ira, IrInstructionMemcpy *instruction) { + Error err; + IrInstruction *dest_ptr = instruction->dest_ptr->other; if (type_is_invalid(dest_ptr->value.type)) return ira->codegen->builtin_types.entry_invalid; @@ -18733,10 +18846,22 @@ static ZigType *ir_analyze_instruction_memcpy(IrAnalyze *ira, IrInstructionMemcp dest_uncasted_type->data.pointer.is_volatile; bool src_is_volatile = (src_uncasted_type->id == ZigTypeIdPointer) && src_uncasted_type->data.pointer.is_volatile; - uint32_t dest_align = (dest_uncasted_type->id == ZigTypeIdPointer) ? - dest_uncasted_type->data.pointer.alignment : get_abi_alignment(ira->codegen, u8); - uint32_t src_align = (src_uncasted_type->id == ZigTypeIdPointer) ? - src_uncasted_type->data.pointer.alignment : get_abi_alignment(ira->codegen, u8); + + uint32_t dest_align; + if (dest_uncasted_type->id == ZigTypeIdPointer) { + if ((err = resolve_ptr_align(ira, dest_uncasted_type, &dest_align))) + return ira->codegen->builtin_types.entry_invalid; + } else { + dest_align = get_abi_alignment(ira->codegen, u8); + } + + uint32_t src_align; + if (src_uncasted_type->id == ZigTypeIdPointer) { + if ((err = resolve_ptr_align(ira, src_uncasted_type, &src_align))) + return ira->codegen->builtin_types.entry_invalid; + } else { + src_align = get_abi_alignment(ira->codegen, u8); + } ZigType *usize = ira->codegen->builtin_types.entry_usize; ZigType *u8_ptr_mut = get_pointer_to_type_extra(ira->codegen, u8, false, dest_is_volatile, @@ -18881,17 +19006,13 @@ static ZigType *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstructionSlice ZigType *return_type; if (array_type->id == ZigTypeIdArray) { - uint32_t byte_alignment = ptr_type->data.pointer.alignment; - if (array_type->data.array.len == 0 && byte_alignment == 0) { - byte_alignment = get_abi_alignment(ira->codegen, array_type->data.array.child_type); - } bool is_comptime_const = ptr_ptr->value.special == ConstValSpecialStatic && ptr_ptr->value.data.x_ptr.mut == ConstPtrMutComptimeConst; ZigType *slice_ptr_type = get_pointer_to_type_extra(ira->codegen, array_type->data.array.child_type, ptr_type->data.pointer.is_const || is_comptime_const, ptr_type->data.pointer.is_volatile, PtrLenUnknown, - byte_alignment, 0, 0); + ptr_type->data.pointer.explicit_alignment, 0, 0); return_type = get_slice_type(ira->codegen, slice_ptr_type); } else if (array_type->id == ZigTypeIdPointer) { if (array_type->data.pointer.ptr_len == PtrLenSingle) { @@ -18901,7 +19022,7 @@ static ZigType *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstructionSlice main_type->data.pointer.child_type, array_type->data.pointer.is_const, array_type->data.pointer.is_volatile, PtrLenUnknown, - array_type->data.pointer.alignment, 0, 0); + array_type->data.pointer.explicit_alignment, 0, 0); return_type = get_slice_type(ira->codegen, slice_ptr_type); } else { ir_add_error(ira, &instruction->base, buf_sprintf("slice of single-item pointer")); @@ -18911,7 +19032,7 @@ static ZigType *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstructionSlice ZigType *slice_ptr_type = get_pointer_to_type_extra(ira->codegen, array_type->data.pointer.child_type, array_type->data.pointer.is_const, array_type->data.pointer.is_volatile, PtrLenUnknown, - array_type->data.pointer.alignment, 0, 0); + array_type->data.pointer.explicit_alignment, 0, 0); return_type = get_slice_type(ira->codegen, slice_ptr_type); if (!end) { ir_add_error(ira, &instruction->base, buf_sprintf("slice of pointer must include end value")); @@ -19292,7 +19413,7 @@ static ZigType *ir_analyze_instruction_align_of(IrAnalyze *ira, IrInstructionAli return ira->codegen->builtin_types.entry_invalid; ZigType *type_entry = ir_resolve_type(ira, type_value); - if ((err = type_ensure_zero_bits_known(ira->codegen, type_entry))) + if ((err = type_resolve(ira->codegen, type_entry, ResolveStatusAlignmentKnown))) return ira->codegen->builtin_types.entry_invalid; switch (type_entry->id) { @@ -19336,6 +19457,8 @@ static ZigType *ir_analyze_instruction_align_of(IrAnalyze *ira, IrInstructionAli } static ZigType *ir_analyze_instruction_overflow_op(IrAnalyze *ira, IrInstructionOverflowOp *instruction) { + Error err; + IrInstruction *type_value = instruction->type_value->other; if (type_is_invalid(type_value->value.type)) return ira->codegen->builtin_types.entry_invalid; @@ -19379,10 +19502,13 @@ static ZigType *ir_analyze_instruction_overflow_op(IrAnalyze *ira, IrInstruction ZigType *expected_ptr_type; if (result_ptr->value.type->id == ZigTypeIdPointer) { + uint32_t alignment; + if ((err = resolve_ptr_align(ira, result_ptr->value.type, &alignment))) + return ira->codegen->builtin_types.entry_invalid; expected_ptr_type = get_pointer_to_type_extra(ira->codegen, dest_type, false, result_ptr->value.type->data.pointer.is_volatile, PtrLenSingle, - result_ptr->value.type->data.pointer.alignment, 0, 0); + alignment, 0, 0); } else { expected_ptr_type = get_pointer_to_type(ira->codegen, dest_type, false); } @@ -19544,8 +19670,7 @@ static ZigType *ir_analyze_instruction_unwrap_err_payload(IrAnalyze *ira, } ZigType *result_type = get_pointer_to_type_extra(ira->codegen, payload_type, ptr_type->data.pointer.is_const, ptr_type->data.pointer.is_volatile, - PtrLenSingle, - get_abi_alignment(ira->codegen, payload_type), 0, 0); + PtrLenSingle, 0, 0, 0); if (instr_is_comptime(value)) { ConstExprValue *ptr_val = ir_resolve_const(ira, value, UndefBad); if (!ptr_val) @@ -19624,7 +19749,7 @@ static ZigType *ir_analyze_instruction_fn_proto(IrAnalyze *ira, IrInstructionFnP ZigType *param_type = ir_resolve_type(ira, param_type_value); if (type_is_invalid(param_type)) return ira->codegen->builtin_types.entry_invalid; - if ((err = type_ensure_zero_bits_known(ira->codegen, param_type))) + if ((err = type_resolve(ira->codegen, param_type, ResolveStatusZeroBitsKnown))) return ira->codegen->builtin_types.entry_invalid; if (type_requires_comptime(param_type)) { if (!calling_convention_allows_zig_types(fn_type_id.cc)) { @@ -19899,7 +20024,7 @@ static ZigType *ir_analyze_instruction_panic(IrAnalyze *ira, IrInstructionPanic } ZigType *u8_ptr_type = get_pointer_to_type_extra(ira->codegen, ira->codegen->builtin_types.entry_u8, - true, false, PtrLenUnknown, get_abi_alignment(ira->codegen, ira->codegen->builtin_types.entry_u8), 0, 0); + true, false, PtrLenUnknown, 0, 0, 0); ZigType *str_type = get_slice_type(ira->codegen, u8_ptr_type); IrInstruction *casted_msg = ir_implicit_cast(ira, msg, str_type); if (type_is_invalid(casted_msg->value.type)) @@ -19912,6 +20037,8 @@ static ZigType *ir_analyze_instruction_panic(IrAnalyze *ira, IrInstructionPanic } static IrInstruction *ir_align_cast(IrAnalyze *ira, IrInstruction *target, uint32_t align_bytes, bool safety_check_on) { + Error err; + ZigType *target_type = target->value.type; assert(!type_is_invalid(target_type)); @@ -19920,7 +20047,8 @@ static IrInstruction *ir_align_cast(IrAnalyze *ira, IrInstruction *target, uint3 if (target_type->id == ZigTypeIdPointer) { result_type = adjust_ptr_align(ira->codegen, target_type, align_bytes); - old_align_bytes = target_type->data.pointer.alignment; + if ((err = resolve_ptr_align(ira, target_type, &old_align_bytes))) + return ira->codegen->invalid_instruction; } else if (target_type->id == ZigTypeIdFn) { FnTypeId fn_type_id = target_type->data.fn.fn_type_id; old_align_bytes = fn_type_id.alignment; @@ -19930,7 +20058,8 @@ static IrInstruction *ir_align_cast(IrAnalyze *ira, IrInstruction *target, uint3 target_type->data.maybe.child_type->id == ZigTypeIdPointer) { ZigType *ptr_type = target_type->data.maybe.child_type; - old_align_bytes = ptr_type->data.pointer.alignment; + if ((err = resolve_ptr_align(ira, ptr_type, &old_align_bytes))) + return ira->codegen->invalid_instruction; ZigType *better_ptr_type = adjust_ptr_align(ira->codegen, ptr_type, align_bytes); result_type = get_optional_type(ira->codegen, better_ptr_type); @@ -19944,7 +20073,8 @@ static IrInstruction *ir_align_cast(IrAnalyze *ira, IrInstruction *target, uint3 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; - old_align_bytes = slice_ptr_type->data.pointer.alignment; + 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); result_type = get_slice_type(ira->codegen, result_ptr_type); } else { @@ -20023,8 +20153,13 @@ static ZigType *ir_analyze_instruction_ptr_cast(IrAnalyze *ira, IrInstructionPtr return dest_type; } - uint32_t src_align_bytes = get_ptr_align(ira->codegen, src_type); - uint32_t dest_align_bytes = get_ptr_align(ira->codegen, dest_type); + uint32_t src_align_bytes; + if ((err = resolve_ptr_align(ira, src_type, &src_align_bytes))) + return ira->codegen->builtin_types.entry_invalid; + + uint32_t dest_align_bytes; + if ((err = resolve_ptr_align(ira, dest_type, &dest_align_bytes))) + return ira->codegen->builtin_types.entry_invalid; if (dest_align_bytes > src_align_bytes) { ErrorMsg *msg = ir_add_error(ira, &instruction->base, buf_sprintf("cast increases pointer alignment")); @@ -20041,7 +20176,7 @@ static ZigType *ir_analyze_instruction_ptr_cast(IrAnalyze *ira, IrInstructionPtr // Keep the bigger alignment, it can only help- // unless the target is zero bits. - if ((err = type_ensure_zero_bits_known(ira->codegen, dest_type))) + if ((err = type_resolve(ira->codegen, dest_type, ResolveStatusZeroBitsKnown))) return ira->codegen->builtin_types.entry_invalid; IrInstruction *result; @@ -20289,7 +20424,7 @@ static ZigType *ir_analyze_instruction_int_to_ptr(IrAnalyze *ira, IrInstructionI return ira->codegen->builtin_types.entry_invalid; } - if ((err = type_ensure_zero_bits_known(ira->codegen, dest_type))) + if ((err = type_resolve(ira->codegen, dest_type, ResolveStatusZeroBitsKnown))) return ira->codegen->builtin_types.entry_invalid; if (!type_has_bits(dest_type)) { ir_add_error(ira, dest_type_value, @@ -20440,12 +20575,15 @@ static ZigType *ir_analyze_instruction_ptr_type(IrAnalyze *ira, IrInstructionPtr if (instruction->align_value != nullptr) { if (!ir_resolve_align(ira, instruction->align_value->other, &align_bytes)) return ira->codegen->builtin_types.entry_invalid; + if ((err = type_resolve(ira->codegen, child_type, ResolveStatusAlignmentKnown))) + return ira->codegen->builtin_types.entry_invalid; } else { - if ((err = type_ensure_zero_bits_known(ira->codegen, child_type))) + if ((err = type_resolve(ira->codegen, child_type, ResolveStatusZeroBitsKnown))) return ira->codegen->builtin_types.entry_invalid; - align_bytes = get_abi_alignment(ira->codegen, child_type); + align_bytes = 0; } + ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base); out_val->data.x_type = get_pointer_to_type_extra(ira->codegen, child_type, instruction->is_const, instruction->is_volatile, @@ -21089,7 +21227,7 @@ static ZigType *ir_analyze_instruction_enum_to_int(IrAnalyze *ira, IrInstruction return ira->codegen->builtin_types.entry_invalid; } - if ((err = type_ensure_zero_bits_known(ira->codegen, target->value.type))) + if ((err = type_resolve(ira->codegen, target->value.type, ResolveStatusZeroBitsKnown))) return ira->codegen->builtin_types.entry_invalid; ZigType *tag_type = target->value.type->data.enumeration.tag_int_type; @@ -21112,7 +21250,7 @@ static ZigType *ir_analyze_instruction_int_to_enum(IrAnalyze *ira, IrInstruction return ira->codegen->builtin_types.entry_invalid; } - if ((err = type_ensure_zero_bits_known(ira->codegen, dest_type))) + if ((err = type_resolve(ira->codegen, dest_type, ResolveStatusZeroBitsKnown))) return ira->codegen->builtin_types.entry_invalid; ZigType *tag_type = dest_type->data.enumeration.tag_int_type; diff --git a/std/debug/index.zig b/std/debug/index.zig index 14e8b9197a..9ad15ccd7e 100644 --- a/std/debug/index.zig +++ b/std/debug/index.zig @@ -916,7 +916,7 @@ fn openSelfDebugInfoMacOs(allocator: *mem.Allocator) !DebugInfo { } else { return error.MissingDebugInfo; }; - const syms = @ptrCast([*]macho.nlist_64, hdr_base + symtab.symoff)[0..symtab.nsyms]; + const syms = @ptrCast([*]macho.nlist_64, @alignCast(@alignOf(macho.nlist_64), hdr_base + symtab.symoff))[0..symtab.nsyms]; const strings = @ptrCast([*]u8, hdr_base + symtab.stroff)[0..symtab.strsize]; const symbols_buf = try allocator.alloc(MachoSymbol, syms.len); @@ -1497,14 +1497,14 @@ fn getLineNumberInfoMacOs(di: *DebugInfo, symbol: MachoSymbol, target_address: u const segcmd = while (ncmd != 0) : (ncmd -= 1) { const lc = @ptrCast(*const std.macho.load_command, ptr); switch (lc.cmd) { - std.macho.LC_SEGMENT_64 => break @ptrCast(*const std.macho.segment_command_64, ptr), + std.macho.LC_SEGMENT_64 => break @ptrCast(*const std.macho.segment_command_64, @alignCast(@alignOf(std.macho.segment_command_64), ptr)), else => {}, } ptr += lc.cmdsize; // TODO https://github.com/ziglang/zig/issues/1403 } else { return error.MissingDebugInfo; }; - const sections = @alignCast(@alignOf(macho.section_64), @ptrCast([*]const macho.section_64, ptr + @sizeOf(std.macho.segment_command_64)))[0..segcmd.nsects]; + const sections = @ptrCast([*]const macho.section_64, @alignCast(@alignOf(macho.section_64), ptr + @sizeOf(std.macho.segment_command_64)))[0..segcmd.nsects]; for (sections) |*sect| { if (sect.flags & macho.SECTION_TYPE == macho.S_REGULAR and (sect.flags & macho.SECTION_ATTRIBUTES) & macho.S_ATTR_DEBUG == macho.S_ATTR_DEBUG) diff --git a/test/cases/align.zig b/test/cases/align.zig index 64f0788efc..e052c3c3ad 100644 --- a/test/cases/align.zig +++ b/test/cases/align.zig @@ -212,3 +212,10 @@ fn fnWithAlignedStack() i32 { @setAlignStack(256); return 1234; } + +test "alignment of structs" { + assert(@alignOf(struct { + a: i32, + b: *i32, + }) == @alignOf(usize)); +} diff --git a/test/compile_errors.zig b/test/compile_errors.zig index 6bdbca9ff5..40afc6df2d 100644 --- a/test/compile_errors.zig +++ b/test/compile_errors.zig @@ -3444,7 +3444,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { \\ \\export fn entry() usize { return @sizeOf(@typeOf(foo)); } , - ".tmp_source.zig:8:26: error: expected type '*const u3', found '*align(1:3:6) const u3'", + ".tmp_source.zig:8:26: error: expected type '*const u3', found '*align(:3:6) const u3'", ); cases.add( -- cgit v1.2.3