aboutsummaryrefslogtreecommitdiff
path: root/src/AstGen.zig
diff options
context:
space:
mode:
authorAndrew Kelley <andrew@ziglang.org>2021-07-23 22:23:03 -0700
committerAndrew Kelley <andrew@ziglang.org>2021-07-23 22:42:31 -0700
commit7b8cb881df7e034a8626caabf355055ee81a0fef (patch)
treee56858cd22ccf90217a49c51c7d8ff7df49ab0f3 /src/AstGen.zig
parentf9798108f8434f277de6089502446f2544ee98b3 (diff)
downloadzig-7b8cb881df7e034a8626caabf355055ee81a0fef.tar.gz
zig-7b8cb881df7e034a8626caabf355055ee81a0fef.zip
stage2: improvements towards `zig test`
* There is now a main_pkg in addition to root_pkg. They are usually the same. When using `zig test`, main_pkg is the user's source file and root_pkg has the test runner. * scanDecl no longer looks for test decls outside the package being tested. honoring `--test-filter` is still TODO. * test runner main function has a void return value rather than `anyerror!void` * Sema is improved to generate better AIR for for loops on slices. * Sema: fix incorrect capacity calculation in zirBoolBr * Sema: add compile errors for trying to use slice fields as an lvalue. * Sema: fix type coercion for error unions * Sema: fix analyzeVarRef generating garbage AIR * C codegen: fix renderValue for error unions with 0 bit payload * C codegen: implement function pointer calls * CLI: fix usage text Adds 4 new AIR instructions: * slice_len, slice_ptr: to get the ptr and len fields of a slice. * slice_elem_val, ptr_slice_elem_val: to get the element value of a slice, and a pointer to a slice. AstGen gains a new functionality: * One of the unused flags of struct decls is now used to indicate structs that are known to have non-zero size based on the AST alone.
Diffstat (limited to 'src/AstGen.zig')
-rw-r--r--src/AstGen.zig190
1 files changed, 190 insertions, 0 deletions
diff --git a/src/AstGen.zig b/src/AstGen.zig
index 8fb7cde6de..a00b43288b 100644
--- a/src/AstGen.zig
+++ b/src/AstGen.zig
@@ -3470,6 +3470,7 @@ fn structDeclInner(
.fields_len = 0,
.body_len = 0,
.decls_len = 0,
+ .known_has_bits = false,
});
return indexToRef(decl_inst);
}
@@ -3510,6 +3511,7 @@ fn structDeclInner(
var bit_bag = ArrayListUnmanaged(u32){};
defer bit_bag.deinit(gpa);
+ var known_has_bits = false;
var cur_bit_bag: u32 = 0;
var field_index: usize = 0;
for (container_decl.ast.members) |member_node| {
@@ -3657,6 +3659,8 @@ fn structDeclInner(
try typeExpr(&block_scope, &block_scope.base, member.ast.type_expr);
fields_data.appendAssumeCapacity(@enumToInt(field_type));
+ known_has_bits = known_has_bits or nodeImpliesRuntimeBits(tree, member.ast.type_expr);
+
const have_align = member.ast.align_expr != 0;
const have_value = member.ast.value_expr != 0;
const is_comptime = member.comptime_token != null;
@@ -3706,6 +3710,7 @@ fn structDeclInner(
.body_len = @intCast(u32, block_scope.instructions.items.len),
.fields_len = @intCast(u32, field_index),
.decls_len = @intCast(u32, wip_decls.decl_index),
+ .known_has_bits = known_has_bits,
});
try astgen.extra.ensureUnusedCapacity(gpa, bit_bag.items.len +
@@ -8150,6 +8155,189 @@ fn nodeMayEvalToError(tree: *const ast.Tree, start_node: ast.Node.Index) enum {
}
}
+fn nodeImpliesRuntimeBits(tree: *const ast.Tree, 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,
+ .true_literal,
+ .false_literal,
+ .null_literal,
+ .undefined_literal,
+ .unreachable_literal,
+ .identifier,
+ .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,
+ .array_cat,
+ .array_mult,
+ .assign,
+ .assign_bit_and,
+ .assign_bit_or,
+ .assign_bit_shift_left,
+ .assign_bit_shift_right,
+ .assign_bit_xor,
+ .assign_div,
+ .assign_sub,
+ .assign_sub_wrap,
+ .assign_mod,
+ .assign_add,
+ .assign_add_wrap,
+ .assign_mul,
+ .assign_mul_wrap,
+ .bang_equal,
+ .bit_and,
+ .bit_or,
+ .bit_shift_left,
+ .bit_shift_right,
+ .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,
+ .switch_range,
+ .field_access,
+ .sub,
+ .sub_wrap,
+ .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,
+ => return false,
+
+ // Forward the question to the LHS sub-expression.
+ .grouped_expression,
+ .@"try",
+ .@"await",
+ .@"comptime",
+ .@"nosuspend",
+ .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,
+ .ptr_type_bit_range,
+ .optional_type,
+ .anyframe_type,
+ .array_type_sentinel,
+ => return true,
+ }
+ }
+}
+
/// Applies `rl` semantics to `inst`. Expressions which do not do their own handling of
/// result locations must call this function on their result.
/// As an example, if the `ResultLoc` is `ptr`, it will write the result to the pointer.
@@ -9556,6 +9744,7 @@ const GenZir = struct {
fields_len: u32,
decls_len: u32,
layout: std.builtin.TypeInfo.ContainerLayout,
+ known_has_bits: bool,
}) !void {
const astgen = gz.astgen;
const gpa = astgen.gpa;
@@ -9585,6 +9774,7 @@ 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,
.name_strategy = gz.anon_name_strategy,
.layout = args.layout,
}),