diff options
| author | Andrew Kelley <andrew@ziglang.org> | 2022-01-24 20:38:56 -0700 |
|---|---|---|
| committer | Andrew Kelley <andrew@ziglang.org> | 2022-01-24 21:53:57 -0700 |
| commit | a2abbeef90bc3fa33acaf85902b4b97383999aaf (patch) | |
| tree | ba7dfaf67adf2420ac40cbb765e01407387c399b /src/AstGen.zig | |
| parent | 8bb679bc6e25d1f7c08bb4e5e5272ae5f27aed47 (diff) | |
| download | zig-a2abbeef90bc3fa33acaf85902b4b97383999aaf.tar.gz zig-a2abbeef90bc3fa33acaf85902b4b97383999aaf.zip | |
stage2: rework a lot of stuff
AstGen:
* rename the known_has_bits flag to known_non_opv to make it better
reflect what it actually means.
* add a known_comptime_only flag.
* make the flags take advantage of identifiers of primitives and the
fact that zig has no shadowing.
* correct the known_non_opv flag for function bodies.
Sema:
* Rename `hasCodeGenBits` to `hasRuntimeBits` to better reflect what it
does.
- This function got a bit more complicated in this commit because of
the duality of function bodies: on one hand they have runtime bits,
but on the other hand they require being comptime known.
* WipAnonDecl now takes a LazySrcDecl parameter and performs the type
resolutions that it needs during finish().
* Implement comptime `@ptrToInt`.
Codegen:
* Improved handling of lowering decl_ref; make it work for
comptime-known ptr-to-int values.
- This same change had to be made many different times; perhaps we
should look into merging the implementations of `genTypedValue`
across x86, arm, aarch64, and riscv.
Diffstat (limited to 'src/AstGen.zig')
| -rw-r--r-- | src/AstGen.zig | 329 |
1 files changed, 317 insertions, 12 deletions
diff --git a/src/AstGen.zig b/src/AstGen.zig index d75ae82e0a..6adec3fc53 100644 --- a/src/AstGen.zig +++ b/src/AstGen.zig @@ -3828,7 +3828,8 @@ fn structDeclInner( .fields_len = 0, .body_len = 0, .decls_len = 0, - .known_has_bits = false, + .known_non_opv = false, + .known_comptime_only = false, }); return indexToRef(decl_inst); } @@ -3869,7 +3870,8 @@ fn structDeclInner( var wip_members = try WipMembers.init(gpa, &astgen.scratch, decl_count, field_count, bits_per_field, max_field_size); defer wip_members.deinit(); - var known_has_bits = false; + var known_non_opv = false; + var known_comptime_only = false; for (container_decl.ast.members) |member_node| { const member = switch (try containerMember(gz, &namespace.base, &wip_members, member_node)) { .decl => continue, @@ -3892,7 +3894,10 @@ fn structDeclInner( const doc_comment_index = try astgen.docCommentAsString(member.firstToken()); wip_members.appendToField(doc_comment_index); - known_has_bits = known_has_bits or nodeImpliesRuntimeBits(tree, member.ast.type_expr); + known_non_opv = known_non_opv or + nodeImpliesMoreThanOnePossibleValue(tree, member.ast.type_expr); + known_comptime_only = known_comptime_only or + nodeImpliesComptimeOnly(tree, member.ast.type_expr); const have_align = member.ast.align_expr != 0; const have_value = member.ast.value_expr != 0; @@ -3926,7 +3931,8 @@ fn structDeclInner( .body_len = @intCast(u32, body.len), .fields_len = field_count, .decls_len = decl_count, - .known_has_bits = known_has_bits, + .known_non_opv = known_non_opv, + .known_comptime_only = known_comptime_only, }); wip_members.finishBits(bits_per_field); @@ -8195,7 +8201,9 @@ fn nodeMayEvalToError(tree: *const Ast, start_node: Ast.Node.Index) BuiltinFn.Ev } } -fn nodeImpliesRuntimeBits(tree: *const Ast, start_node: Ast.Node.Index) bool { +/// Returns `true` if it is known the type expression has more than one possible value; +/// `false` otherwise. +fn nodeImpliesMoreThanOnePossibleValue(tree: *const Ast, start_node: Ast.Node.Index) bool { const node_tags = tree.nodes.items(.tag); const node_datas = tree.nodes.items(.data); @@ -8241,7 +8249,6 @@ fn nodeImpliesRuntimeBits(tree: *const Ast, start_node: Ast.Node.Index) bool { .multiline_string_literal, .char_literal, .unreachable_literal, - .identifier, .error_set_decl, .container_decl, .container_decl_trailing, @@ -8355,6 +8362,11 @@ fn nodeImpliesRuntimeBits(tree: *const Ast, start_node: Ast.Node.Index) bool { .builtin_call_comma, .builtin_call_two, .builtin_call_two_comma, + // these are function bodies, not pointers + .fn_proto_simple, + .fn_proto_multi, + .fn_proto_one, + .fn_proto, => return false, // Forward the question to the LHS sub-expression. @@ -8366,10 +8378,6 @@ fn nodeImpliesRuntimeBits(tree: *const Ast, start_node: Ast.Node.Index) bool { .unwrap_optional, => node = node_datas[node].lhs, - .fn_proto_simple, - .fn_proto_multi, - .fn_proto_one, - .fn_proto, .ptr_type_aligned, .ptr_type_sentinel, .ptr_type, @@ -8378,6 +8386,301 @@ fn nodeImpliesRuntimeBits(tree: *const Ast, start_node: Ast.Node.Index) bool { .anyframe_type, .array_type_sentinel, => return true, + + .identifier => { + const main_tokens = tree.nodes.items(.main_token); + const ident_bytes = tree.tokenSlice(main_tokens[node]); + if (primitives.get(ident_bytes)) |primitive| switch (primitive) { + .anyerror_type, + .anyframe_type, + .anyopaque_type, + .bool_type, + .c_int_type, + .c_long_type, + .c_longdouble_type, + .c_longlong_type, + .c_short_type, + .c_uint_type, + .c_ulong_type, + .c_ulonglong_type, + .c_ushort_type, + .comptime_float_type, + .comptime_int_type, + .f128_type, + .f16_type, + .f32_type, + .f64_type, + .i16_type, + .i32_type, + .i64_type, + .i128_type, + .i8_type, + .isize_type, + .type_type, + .u16_type, + .u32_type, + .u64_type, + .u128_type, + .u1_type, + .u8_type, + .usize_type, + => return true, + + .void_type, + .bool_false, + .bool_true, + .null_value, + .undef, + .noreturn_type, + => return false, + + else => unreachable, // that's all the values from `primitives`. + } else { + return false; + } + }, + } + } +} + +/// Returns `true` if it is known the expression is a type that cannot be used at runtime; +/// `false` otherwise. +fn nodeImpliesComptimeOnly(tree: *const Ast, start_node: Ast.Node.Index) bool { + const node_tags = tree.nodes.items(.tag); + const node_datas = tree.nodes.items(.data); + + var node = start_node; + while (true) { + switch (node_tags[node]) { + .root, + .@"usingnamespace", + .test_decl, + .switch_case, + .switch_case_one, + .container_field_init, + .container_field_align, + .container_field, + .asm_output, + .asm_input, + .global_var_decl, + .local_var_decl, + .simple_var_decl, + .aligned_var_decl, + => unreachable, + + .@"return", + .@"break", + .@"continue", + .bit_not, + .bool_not, + .@"defer", + .@"errdefer", + .address_of, + .negation, + .negation_wrap, + .@"resume", + .array_type, + .@"suspend", + .@"anytype", + .fn_decl, + .anyframe_literal, + .integer_literal, + .float_literal, + .enum_literal, + .string_literal, + .multiline_string_literal, + .char_literal, + .unreachable_literal, + .error_set_decl, + .container_decl, + .container_decl_trailing, + .container_decl_two, + .container_decl_two_trailing, + .container_decl_arg, + .container_decl_arg_trailing, + .tagged_union, + .tagged_union_trailing, + .tagged_union_two, + .tagged_union_two_trailing, + .tagged_union_enum_tag, + .tagged_union_enum_tag_trailing, + .@"asm", + .asm_simple, + .add, + .add_wrap, + .add_sat, + .array_cat, + .array_mult, + .assign, + .assign_bit_and, + .assign_bit_or, + .assign_shl, + .assign_shl_sat, + .assign_shr, + .assign_bit_xor, + .assign_div, + .assign_sub, + .assign_sub_wrap, + .assign_sub_sat, + .assign_mod, + .assign_add, + .assign_add_wrap, + .assign_add_sat, + .assign_mul, + .assign_mul_wrap, + .assign_mul_sat, + .bang_equal, + .bit_and, + .bit_or, + .shl, + .shl_sat, + .shr, + .bit_xor, + .bool_and, + .bool_or, + .div, + .equal_equal, + .error_union, + .greater_or_equal, + .greater_than, + .less_or_equal, + .less_than, + .merge_error_sets, + .mod, + .mul, + .mul_wrap, + .mul_sat, + .switch_range, + .field_access, + .sub, + .sub_wrap, + .sub_sat, + .slice, + .slice_open, + .slice_sentinel, + .deref, + .array_access, + .error_value, + .while_simple, + .while_cont, + .for_simple, + .if_simple, + .@"catch", + .@"orelse", + .array_init_one, + .array_init_one_comma, + .array_init_dot_two, + .array_init_dot_two_comma, + .array_init_dot, + .array_init_dot_comma, + .array_init, + .array_init_comma, + .struct_init_one, + .struct_init_one_comma, + .struct_init_dot_two, + .struct_init_dot_two_comma, + .struct_init_dot, + .struct_init_dot_comma, + .struct_init, + .struct_init_comma, + .@"while", + .@"if", + .@"for", + .@"switch", + .switch_comma, + .call_one, + .call_one_comma, + .async_call_one, + .async_call_one_comma, + .call, + .call_comma, + .async_call, + .async_call_comma, + .block_two, + .block_two_semicolon, + .block, + .block_semicolon, + .builtin_call, + .builtin_call_comma, + .builtin_call_two, + .builtin_call_two_comma, + .ptr_type_aligned, + .ptr_type_sentinel, + .ptr_type, + .ptr_type_bit_range, + .optional_type, + .anyframe_type, + .array_type_sentinel, + => return false, + + // these are function bodies, not pointers + .fn_proto_simple, + .fn_proto_multi, + .fn_proto_one, + .fn_proto, + => return true, + + // Forward the question to the LHS sub-expression. + .grouped_expression, + .@"try", + .@"await", + .@"comptime", + .@"nosuspend", + .unwrap_optional, + => node = node_datas[node].lhs, + + .identifier => { + const main_tokens = tree.nodes.items(.main_token); + const ident_bytes = tree.tokenSlice(main_tokens[node]); + if (primitives.get(ident_bytes)) |primitive| switch (primitive) { + .anyerror_type, + .anyframe_type, + .anyopaque_type, + .bool_type, + .c_int_type, + .c_long_type, + .c_longdouble_type, + .c_longlong_type, + .c_short_type, + .c_uint_type, + .c_ulong_type, + .c_ulonglong_type, + .c_ushort_type, + .f128_type, + .f16_type, + .f32_type, + .f64_type, + .i16_type, + .i32_type, + .i64_type, + .i128_type, + .i8_type, + .isize_type, + .u16_type, + .u32_type, + .u64_type, + .u128_type, + .u1_type, + .u8_type, + .usize_type, + .void_type, + .bool_false, + .bool_true, + .null_value, + .undef, + .noreturn_type, + => return false, + + .comptime_float_type, + .comptime_int_type, + .type_type, + => return true, + + else => unreachable, // that's all the values from `primitives`. + } else { + return false; + } + }, } } } @@ -10118,7 +10421,8 @@ const GenZir = struct { fields_len: u32, decls_len: u32, layout: std.builtin.TypeInfo.ContainerLayout, - known_has_bits: bool, + known_non_opv: bool, + known_comptime_only: bool, }) !void { const astgen = gz.astgen; const gpa = astgen.gpa; @@ -10148,7 +10452,8 @@ const GenZir = struct { .has_body_len = args.body_len != 0, .has_fields_len = args.fields_len != 0, .has_decls_len = args.decls_len != 0, - .known_has_bits = args.known_has_bits, + .known_non_opv = args.known_non_opv, + .known_comptime_only = args.known_comptime_only, .name_strategy = gz.anon_name_strategy, .layout = args.layout, }), |
