authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-07-23 22:23:03-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-07-23 22:42:31-07:00
log7b8cb881df7e034a8626caabf355055ee81a0fef
treee56858cd22ccf90217a49c51c7d8ff7df49ab0f3
parentf9798108f8434f277de6089502446f2544ee98b3

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.

25 files changed, 610 insertions(+), 173 deletions(-)

lib/std/special/test_runner.zig+2-2
......@@ -21,9 +21,9 @@ fn processArgs() void {
2121 std.testing.zig_exe_path = args[1];
2222}
2323
24pub fn main() anyerror!void {
24pub fn main() void {
2525 if (builtin.zig_is_stage2) {
26 return main2();
26 return main2() catch @panic("test failure");
2727 }
2828 processArgs();
2929 const test_fn_list = builtin.test_functions;
src/Air.zig+29-1
......@@ -247,6 +247,21 @@ pub const Inst = struct {
247247 /// Given a pointer to a struct and a field index, returns a pointer to the field.
248248 /// Uses the `ty_pl` field, payload is `StructField`.
249249 struct_field_ptr,
250 /// Given a slice value, return the length.
251 /// Result type is always usize.
252 /// Uses the `ty_op` field.
253 slice_len,
254 /// Given a slice value, return the pointer.
255 /// Uses the `ty_op` field.
256 slice_ptr,
257 /// Given a slice value, and element index, return the element value at that index.
258 /// Result type is the element type of the slice operand.
259 /// Uses the `bin_op` field.
260 slice_elem_val,
261 /// Given a pointer to a slice, and element index, return the element value at that index.
262 /// Result type is the element type of the slice operand (2 element type operations).
263 /// Uses the `bin_op` field.
264 ptr_slice_elem_val,
250265
251266 pub fn fromCmpOp(op: std.math.CompareOperator) Tag {
252267 return switch (op) {
......@@ -450,6 +465,7 @@ pub fn typeOfIndex(air: Air, inst: Air.Inst.Index) Type {
450465 .unwrap_errunion_err_ptr,
451466 .wrap_errunion_payload,
452467 .wrap_errunion_err,
468 .slice_ptr,
453469 => return air.getRefType(datas[inst].ty_op.ty),
454470
455471 .loop,
......@@ -465,12 +481,24 @@ pub fn typeOfIndex(air: Air, inst: Air.Inst.Index) Type {
465481 .store,
466482 => return Type.initTag(.void),
467483
468 .ptrtoint => return Type.initTag(.usize),
484 .ptrtoint,
485 .slice_len,
486 => return Type.initTag(.usize),
469487
470488 .call => {
471489 const callee_ty = air.typeOf(datas[inst].pl_op.operand);
472490 return callee_ty.fnReturnType();
473491 },
492
493 .slice_elem_val => {
494 const slice_ty = air.typeOf(datas[inst].bin_op.lhs);
495 return slice_ty.elemType();
496 },
497 .ptr_slice_elem_val => {
498 const ptr_slice_ty = air.typeOf(datas[inst].bin_op.lhs);
499 const slice_ty = ptr_slice_ty.elemType();
500 return slice_ty.elemType();
501 },
474502 }
475503}
476504
src/AstGen.zig+190
......@@ -3470,6 +3470,7 @@ fn structDeclInner(
34703470 .fields_len = 0,
34713471 .body_len = 0,
34723472 .decls_len = 0,
3473 .known_has_bits = false,
34733474 });
34743475 return indexToRef(decl_inst);
34753476 }
......@@ -3510,6 +3511,7 @@ fn structDeclInner(
35103511 var bit_bag = ArrayListUnmanaged(u32){};
35113512 defer bit_bag.deinit(gpa);
35123513
3514 var known_has_bits = false;
35133515 var cur_bit_bag: u32 = 0;
35143516 var field_index: usize = 0;
35153517 for (container_decl.ast.members) |member_node| {
......@@ -3657,6 +3659,8 @@ fn structDeclInner(
36573659 try typeExpr(&block_scope, &block_scope.base, member.ast.type_expr);
36583660 fields_data.appendAssumeCapacity(@enumToInt(field_type));
36593661
3662 known_has_bits = known_has_bits or nodeImpliesRuntimeBits(tree, member.ast.type_expr);
3663
36603664 const have_align = member.ast.align_expr != 0;
36613665 const have_value = member.ast.value_expr != 0;
36623666 const is_comptime = member.comptime_token != null;
......@@ -3706,6 +3710,7 @@ fn structDeclInner(
37063710 .body_len = @intCast(u32, block_scope.instructions.items.len),
37073711 .fields_len = @intCast(u32, field_index),
37083712 .decls_len = @intCast(u32, wip_decls.decl_index),
3713 .known_has_bits = known_has_bits,
37093714 });
37103715
37113716 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 {
81508155 }
81518156}
81528157
8158fn nodeImpliesRuntimeBits(tree: *const ast.Tree, start_node: ast.Node.Index) bool {
8159 const node_tags = tree.nodes.items(.tag);
8160 const node_datas = tree.nodes.items(.data);
8161
8162 var node = start_node;
8163 while (true) {
8164 switch (node_tags[node]) {
8165 .root,
8166 .@"usingnamespace",
8167 .test_decl,
8168 .switch_case,
8169 .switch_case_one,
8170 .container_field_init,
8171 .container_field_align,
8172 .container_field,
8173 .asm_output,
8174 .asm_input,
8175 .global_var_decl,
8176 .local_var_decl,
8177 .simple_var_decl,
8178 .aligned_var_decl,
8179 => unreachable,
8180
8181 .@"return",
8182 .@"break",
8183 .@"continue",
8184 .bit_not,
8185 .bool_not,
8186 .@"defer",
8187 .@"errdefer",
8188 .address_of,
8189 .negation,
8190 .negation_wrap,
8191 .@"resume",
8192 .array_type,
8193 .@"suspend",
8194 .@"anytype",
8195 .fn_decl,
8196 .anyframe_literal,
8197 .integer_literal,
8198 .float_literal,
8199 .enum_literal,
8200 .string_literal,
8201 .multiline_string_literal,
8202 .char_literal,
8203 .true_literal,
8204 .false_literal,
8205 .null_literal,
8206 .undefined_literal,
8207 .unreachable_literal,
8208 .identifier,
8209 .error_set_decl,
8210 .container_decl,
8211 .container_decl_trailing,
8212 .container_decl_two,
8213 .container_decl_two_trailing,
8214 .container_decl_arg,
8215 .container_decl_arg_trailing,
8216 .tagged_union,
8217 .tagged_union_trailing,
8218 .tagged_union_two,
8219 .tagged_union_two_trailing,
8220 .tagged_union_enum_tag,
8221 .tagged_union_enum_tag_trailing,
8222 .@"asm",
8223 .asm_simple,
8224 .add,
8225 .add_wrap,
8226 .array_cat,
8227 .array_mult,
8228 .assign,
8229 .assign_bit_and,
8230 .assign_bit_or,
8231 .assign_bit_shift_left,
8232 .assign_bit_shift_right,
8233 .assign_bit_xor,
8234 .assign_div,
8235 .assign_sub,
8236 .assign_sub_wrap,
8237 .assign_mod,
8238 .assign_add,
8239 .assign_add_wrap,
8240 .assign_mul,
8241 .assign_mul_wrap,
8242 .bang_equal,
8243 .bit_and,
8244 .bit_or,
8245 .bit_shift_left,
8246 .bit_shift_right,
8247 .bit_xor,
8248 .bool_and,
8249 .bool_or,
8250 .div,
8251 .equal_equal,
8252 .error_union,
8253 .greater_or_equal,
8254 .greater_than,
8255 .less_or_equal,
8256 .less_than,
8257 .merge_error_sets,
8258 .mod,
8259 .mul,
8260 .mul_wrap,
8261 .switch_range,
8262 .field_access,
8263 .sub,
8264 .sub_wrap,
8265 .slice,
8266 .slice_open,
8267 .slice_sentinel,
8268 .deref,
8269 .array_access,
8270 .error_value,
8271 .while_simple,
8272 .while_cont,
8273 .for_simple,
8274 .if_simple,
8275 .@"catch",
8276 .@"orelse",
8277 .array_init_one,
8278 .array_init_one_comma,
8279 .array_init_dot_two,
8280 .array_init_dot_two_comma,
8281 .array_init_dot,
8282 .array_init_dot_comma,
8283 .array_init,
8284 .array_init_comma,
8285 .struct_init_one,
8286 .struct_init_one_comma,
8287 .struct_init_dot_two,
8288 .struct_init_dot_two_comma,
8289 .struct_init_dot,
8290 .struct_init_dot_comma,
8291 .struct_init,
8292 .struct_init_comma,
8293 .@"while",
8294 .@"if",
8295 .@"for",
8296 .@"switch",
8297 .switch_comma,
8298 .call_one,
8299 .call_one_comma,
8300 .async_call_one,
8301 .async_call_one_comma,
8302 .call,
8303 .call_comma,
8304 .async_call,
8305 .async_call_comma,
8306 .block_two,
8307 .block_two_semicolon,
8308 .block,
8309 .block_semicolon,
8310 .builtin_call,
8311 .builtin_call_comma,
8312 .builtin_call_two,
8313 .builtin_call_two_comma,
8314 => return false,
8315
8316 // Forward the question to the LHS sub-expression.
8317 .grouped_expression,
8318 .@"try",
8319 .@"await",
8320 .@"comptime",
8321 .@"nosuspend",
8322 .unwrap_optional,
8323 => node = node_datas[node].lhs,
8324
8325 .fn_proto_simple,
8326 .fn_proto_multi,
8327 .fn_proto_one,
8328 .fn_proto,
8329 .ptr_type_aligned,
8330 .ptr_type_sentinel,
8331 .ptr_type,
8332 .ptr_type_bit_range,
8333 .optional_type,
8334 .anyframe_type,
8335 .array_type_sentinel,
8336 => return true,
8337 }
8338 }
8339}
8340
81538341/// Applies `rl` semantics to `inst`. Expressions which do not do their own handling of
81548342/// result locations must call this function on their result.
81558343/// As an example, if the `ResultLoc` is `ptr`, it will write the result to the pointer.
......@@ -9556,6 +9744,7 @@ const GenZir = struct {
95569744 fields_len: u32,
95579745 decls_len: u32,
95589746 layout: std.builtin.TypeInfo.ContainerLayout,
9747 known_has_bits: bool,
95599748 }) !void {
95609749 const astgen = gz.astgen;
95619750 const gpa = astgen.gpa;
......@@ -9585,6 +9774,7 @@ const GenZir = struct {
95859774 .has_body_len = args.body_len != 0,
95869775 .has_fields_len = args.fields_len != 0,
95879776 .has_decls_len = args.decls_len != 0,
9777 .known_has_bits = args.known_has_bits,
95889778 .name_strategy = gz.anon_name_strategy,
95899779 .layout = args.layout,
95909780 }),
src/Compilation.zig+44-26
......@@ -622,7 +622,7 @@ pub const InitOptions = struct {
622622 global_cache_directory: Directory,
623623 target: Target,
624624 root_name: []const u8,
625 root_pkg: ?*Package,
625 main_pkg: ?*Package,
626626 output_mode: std.builtin.OutputMode,
627627 thread_pool: *ThreadPool,
628628 dynamic_linker: ?[]const u8 = null,
......@@ -826,7 +826,7 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {
826826 const ofmt = options.object_format orelse options.target.getObjectFormat();
827827
828828 const use_stage1 = options.use_stage1 orelse blk: {
829 // Even though we may have no Zig code to compile (depending on `options.root_pkg`),
829 // Even though we may have no Zig code to compile (depending on `options.main_pkg`),
830830 // we may need to use stage1 for building compiler-rt and other dependencies.
831831
832832 if (build_options.omit_stage2)
......@@ -846,7 +846,7 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {
846846 break :blk explicit;
847847
848848 // If we have no zig code to compile, no need for LLVM.
849 if (options.root_pkg == null)
849 if (options.main_pkg == null)
850850 break :blk false;
851851
852852 // If we are outputting .c code we must use Zig backend.
......@@ -929,7 +929,7 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {
929929 if (use_llvm) {
930930 // If stage1 generates an object file, self-hosted linker is not
931931 // yet sophisticated enough to handle that.
932 break :blk options.root_pkg != null;
932 break :blk options.main_pkg != null;
933933 }
934934
935935 break :blk false;
......@@ -1159,7 +1159,7 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {
11591159 if (options.target.os.tag == .wasi) cache.hash.add(wasi_exec_model);
11601160 // TODO audit this and make sure everything is in it
11611161
1162 const module: ?*Module = if (options.root_pkg) |root_pkg| blk: {
1162 const module: ?*Module = if (options.main_pkg) |main_pkg| blk: {
11631163 // Options that are specific to zig source files, that cannot be
11641164 // modified between incremental updates.
11651165 var hash = cache.hash;
......@@ -1169,13 +1169,13 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {
11691169 // incremental compilation will handle it, but we do want to namespace different
11701170 // source file names because they are likely different compilations and therefore this
11711171 // would be likely to cause cache hits.
1172 hash.addBytes(root_pkg.root_src_path);
1173 hash.addOptionalBytes(root_pkg.root_src_directory.path);
1172 hash.addBytes(main_pkg.root_src_path);
1173 hash.addOptionalBytes(main_pkg.root_src_directory.path);
11741174 {
11751175 var local_arena = std.heap.ArenaAllocator.init(gpa);
11761176 defer local_arena.deinit();
11771177 var seen_table = std.AutoHashMap(*Package, void).init(&local_arena.allocator);
1178 try addPackageTableToCacheHash(&hash, &local_arena, root_pkg.table, &seen_table, .path_bytes);
1178 try addPackageTableToCacheHash(&hash, &local_arena, main_pkg.table, &seen_table, .path_bytes);
11791179 }
11801180 hash.add(valgrind);
11811181 hash.add(single_threaded);
......@@ -1212,9 +1212,26 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {
12121212 );
12131213 errdefer std_pkg.destroy(gpa);
12141214
1215 try root_pkg.addAndAdopt(gpa, "builtin", builtin_pkg);
1216 try root_pkg.add(gpa, "root", root_pkg);
1217 try root_pkg.addAndAdopt(gpa, "std", std_pkg);
1215 const root_pkg = if (options.is_test) root_pkg: {
1216 const test_pkg = try Package.createWithDir(
1217 gpa,
1218 options.zig_lib_directory,
1219 "std" ++ std.fs.path.sep_str ++ "special",
1220 "test_runner.zig",
1221 );
1222 errdefer test_pkg.destroy(gpa);
1223
1224 try test_pkg.add(gpa, "builtin", builtin_pkg);
1225 try test_pkg.add(gpa, "root", test_pkg);
1226 try test_pkg.add(gpa, "std", std_pkg);
1227
1228 break :root_pkg test_pkg;
1229 } else main_pkg;
1230 errdefer if (options.is_test) root_pkg.destroy(gpa);
1231
1232 try main_pkg.addAndAdopt(gpa, "builtin", builtin_pkg);
1233 try main_pkg.add(gpa, "root", root_pkg);
1234 try main_pkg.addAndAdopt(gpa, "std", std_pkg);
12181235
12191236 try std_pkg.add(gpa, "builtin", builtin_pkg);
12201237 try std_pkg.add(gpa, "root", root_pkg);
......@@ -1258,6 +1275,7 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {
12581275 module.* = .{
12591276 .gpa = gpa,
12601277 .comp = comp,
1278 .main_pkg = main_pkg,
12611279 .root_pkg = root_pkg,
12621280 .zig_cache_artifact_directory = zig_cache_artifact_directory,
12631281 .global_zir_cache = global_zir_cache,
......@@ -1684,7 +1702,7 @@ pub fn update(self: *Compilation) !void {
16841702
16851703 // Make sure std.zig is inside the import_table. We unconditionally need
16861704 // it for start.zig.
1687 const std_pkg = module.root_pkg.table.get("std").?;
1705 const std_pkg = module.main_pkg.table.get("std").?;
16881706 _ = try module.importPkg(std_pkg);
16891707
16901708 // Normally we rely on importing std to in turn import the root source file
......@@ -1692,7 +1710,7 @@ pub fn update(self: *Compilation) !void {
16921710 // so in order to run AstGen on the root source file we put it into the
16931711 // import_table here.
16941712 if (use_stage1) {
1695 _ = try module.importPkg(module.root_pkg);
1713 _ = try module.importPkg(module.main_pkg);
16961714 }
16971715
16981716 // Put a work item in for every known source file to detect if
......@@ -3873,7 +3891,7 @@ fn buildOutputFromZig(
38733891 var special_dir = try comp.zig_lib_directory.handle.openDir(special_sub, .{});
38743892 defer special_dir.close();
38753893
3876 var root_pkg: Package = .{
3894 var main_pkg: Package = .{
38773895 .root_src_directory = .{
38783896 .path = special_path,
38793897 .handle = special_dir,
......@@ -3899,7 +3917,7 @@ fn buildOutputFromZig(
38993917 .zig_lib_directory = comp.zig_lib_directory,
39003918 .target = target,
39013919 .root_name = root_name,
3902 .root_pkg = &root_pkg,
3920 .main_pkg = &main_pkg,
39033921 .output_mode = output_mode,
39043922 .thread_pool = comp.thread_pool,
39053923 .libc_installation = comp.bin_file.options.libc_installation,
......@@ -3969,8 +3987,8 @@ fn updateStage1Module(comp: *Compilation, main_progress_node: *std.Progress.Node
39693987 // Here we use the legacy stage1 C++ compiler to compile Zig code.
39703988 const mod = comp.bin_file.options.module.?;
39713989 const directory = mod.zig_cache_artifact_directory; // Just an alias to make it shorter to type.
3972 const main_zig_file = try mod.root_pkg.root_src_directory.join(arena, &[_][]const u8{
3973 mod.root_pkg.root_src_path,
3990 const main_zig_file = try mod.main_pkg.root_src_directory.join(arena, &[_][]const u8{
3991 mod.main_pkg.root_src_path,
39743992 });
39753993 const zig_lib_dir = comp.zig_lib_directory.path.?;
39763994 const builtin_zig_path = try directory.join(arena, &[_][]const u8{"builtin.zig"});
......@@ -4002,7 +4020,7 @@ fn updateStage1Module(comp: *Compilation, main_progress_node: *std.Progress.Node
40024020 _ = try man.addFile(main_zig_file, null);
40034021 {
40044022 var seen_table = std.AutoHashMap(*Package, void).init(&arena_allocator.allocator);
4005 try addPackageTableToCacheHash(&man.hash, &arena_allocator, mod.root_pkg.table, &seen_table, .{ .files = &man });
4023 try addPackageTableToCacheHash(&man.hash, &arena_allocator, mod.main_pkg.table, &seen_table, .{ .files = &man });
40064024 }
40074025 man.hash.add(comp.bin_file.options.valgrind);
40084026 man.hash.add(comp.bin_file.options.single_threaded);
......@@ -4045,7 +4063,7 @@ fn updateStage1Module(comp: *Compilation, main_progress_node: *std.Progress.Node
40454063 &prev_digest_buf,
40464064 ) catch |err| blk: {
40474065 log.debug("stage1 {s} new_digest={s} error: {s}", .{
4048 mod.root_pkg.root_src_path,
4066 mod.main_pkg.root_src_path,
40494067 std.fmt.fmtSliceHexLower(&digest),
40504068 @errorName(err),
40514069 });
......@@ -4057,7 +4075,7 @@ fn updateStage1Module(comp: *Compilation, main_progress_node: *std.Progress.Node
40574075 break :hit;
40584076
40594077 log.debug("stage1 {s} digest={s} match - skipping invocation", .{
4060 mod.root_pkg.root_src_path,
4078 mod.main_pkg.root_src_path,
40614079 std.fmt.fmtSliceHexLower(&digest),
40624080 });
40634081 var flags_bytes: [1]u8 = undefined;
......@@ -4083,7 +4101,7 @@ fn updateStage1Module(comp: *Compilation, main_progress_node: *std.Progress.Node
40834101 return;
40844102 }
40854103 log.debug("stage1 {s} prev_digest={s} new_digest={s}", .{
4086 mod.root_pkg.root_src_path,
4104 mod.main_pkg.root_src_path,
40874105 std.fmt.fmtSliceHexLower(prev_digest),
40884106 std.fmt.fmtSliceHexLower(&digest),
40894107 });
......@@ -4109,7 +4127,7 @@ fn updateStage1Module(comp: *Compilation, main_progress_node: *std.Progress.Node
41094127
41104128 comp.stage1_cache_manifest = &man;
41114129
4112 const main_pkg_path = mod.root_pkg.root_src_directory.path orelse "";
4130 const main_pkg_path = mod.main_pkg.root_src_directory.path orelse "";
41134131
41144132 const stage1_module = stage1.create(
41154133 @enumToInt(comp.bin_file.options.optimize_mode),
......@@ -4142,7 +4160,7 @@ fn updateStage1Module(comp: *Compilation, main_progress_node: *std.Progress.Node
41424160 const emit_llvm_bc_path = try stage1LocPath(arena, comp.emit_llvm_bc, directory);
41434161 const emit_analysis_path = try stage1LocPath(arena, comp.emit_analysis, directory);
41444162 const emit_docs_path = try stage1LocPath(arena, comp.emit_docs, directory);
4145 const stage1_pkg = try createStage1Pkg(arena, "root", mod.root_pkg, null);
4163 const stage1_pkg = try createStage1Pkg(arena, "root", mod.main_pkg, null);
41464164 const test_filter = comp.test_filter orelse ""[0..0];
41474165 const test_name_prefix = comp.test_name_prefix orelse ""[0..0];
41484166 const subsystem = if (comp.bin_file.options.subsystem) |s|
......@@ -4173,7 +4191,7 @@ fn updateStage1Module(comp: *Compilation, main_progress_node: *std.Progress.Node
41734191 .test_name_prefix_ptr = test_name_prefix.ptr,
41744192 .test_name_prefix_len = test_name_prefix.len,
41754193 .userdata = @ptrToInt(comp),
4176 .root_pkg = stage1_pkg,
4194 .main_pkg = stage1_pkg,
41774195 .code_model = @enumToInt(comp.bin_file.options.machine_code_model),
41784196 .subsystem = subsystem,
41794197 .err_color = @enumToInt(comp.color),
......@@ -4239,7 +4257,7 @@ fn updateStage1Module(comp: *Compilation, main_progress_node: *std.Progress.Node
42394257 // means that the next invocation will have an unnecessary cache miss.
42404258 const stage1_flags_byte = @bitCast(u8, mod.stage1_flags);
42414259 log.debug("stage1 {s} final digest={s} flags={x}", .{
4242 mod.root_pkg.root_src_path, std.fmt.fmtSliceHexLower(&digest), stage1_flags_byte,
4260 mod.main_pkg.root_src_path, std.fmt.fmtSliceHexLower(&digest), stage1_flags_byte,
42434261 });
42444262 var digest_plus_flags: [digest.len + 2]u8 = undefined;
42454263 digest_plus_flags[0..digest.len].* = digest;
......@@ -4333,7 +4351,7 @@ pub fn build_crt_file(
43334351 .zig_lib_directory = comp.zig_lib_directory,
43344352 .target = target,
43354353 .root_name = root_name,
4336 .root_pkg = null,
4354 .main_pkg = null,
43374355 .output_mode = output_mode,
43384356 .thread_pool = comp.thread_pool,
43394357 .libc_installation = comp.bin_file.options.libc_installation,
src/Liveness.zig+4
......@@ -243,6 +243,8 @@ fn analyzeInst(
243243 .bool_and,
244244 .bool_or,
245245 .store,
246 .slice_elem_val,
247 .ptr_slice_elem_val,
246248 => {
247249 const o = inst_datas[inst].bin_op;
248250 return trackOperands(a, new_set, inst, main_tomb, .{ o.lhs, o.rhs, .none });
......@@ -273,6 +275,8 @@ fn analyzeInst(
273275 .unwrap_errunion_err_ptr,
274276 .wrap_errunion_payload,
275277 .wrap_errunion_err,
278 .slice_ptr,
279 .slice_len,
276280 => {
277281 const o = inst_datas[inst].ty_op;
278282 return trackOperands(a, new_set, inst, main_tomb, .{ o.operand, .none, .none });
src/Module.zig+31-8
......@@ -35,8 +35,11 @@ comp: *Compilation,
3535
3636/// Where our incremental compilation metadata serialization will go.
3737zig_cache_artifact_directory: Compilation.Directory,
38/// Pointer to externally managed resource. `null` if there is no zig file being compiled.
38/// Pointer to externally managed resource.
3939root_pkg: *Package,
40/// Normally, `main_pkg` and `root_pkg` are the same. The exception is `zig test`, in which
41/// `root_pkg` is the test runner, and `main_pkg` is the user's source file which has the tests.
42main_pkg: *Package,
4043
4144/// Used by AstGen worker to load and store ZIR cache.
4245global_zir_cache: Compilation.Directory,
......@@ -598,6 +601,9 @@ pub const Struct = struct {
598601 layout_wip,
599602 have_layout,
600603 },
604 /// If true, definitely nonzero size at runtime. If false, resolving the fields
605 /// is necessary to determine whether it has bits at runtime.
606 known_has_bits: bool,
601607
602608 pub const Field = struct {
603609 /// Uses `noreturn` to indicate `anytype`.
......@@ -2048,19 +2054,22 @@ pub fn deinit(mod: *Module) void {
20482054
20492055 mod.deletion_set.deinit(gpa);
20502056
2051 // The callsite of `Compilation.create` owns the `root_pkg`, however
2057 // The callsite of `Compilation.create` owns the `main_pkg`, however
20522058 // Module owns the builtin and std packages that it adds.
2053 if (mod.root_pkg.table.fetchRemove("builtin")) |kv| {
2059 if (mod.main_pkg.table.fetchRemove("builtin")) |kv| {
20542060 gpa.free(kv.key);
20552061 kv.value.destroy(gpa);
20562062 }
2057 if (mod.root_pkg.table.fetchRemove("std")) |kv| {
2063 if (mod.main_pkg.table.fetchRemove("std")) |kv| {
20582064 gpa.free(kv.key);
20592065 kv.value.destroy(gpa);
20602066 }
2061 if (mod.root_pkg.table.fetchRemove("root")) |kv| {
2067 if (mod.main_pkg.table.fetchRemove("root")) |kv| {
20622068 gpa.free(kv.key);
20632069 }
2070 if (mod.root_pkg != mod.main_pkg) {
2071 mod.root_pkg.destroy(gpa);
2072 }
20642073
20652074 mod.compile_log_text.deinit(gpa);
20662075
......@@ -2148,7 +2157,7 @@ pub fn astGenFile(mod: *Module, file: *Scope.File) !void {
21482157
21492158 const stat = try source_file.stat();
21502159
2151 const want_local_cache = file.pkg == mod.root_pkg;
2160 const want_local_cache = file.pkg == mod.main_pkg;
21522161 const digest = hash: {
21532162 var path_hash: Cache.HashHelper = .{};
21542163 path_hash.addBytes(build_options.version);
......@@ -2792,6 +2801,7 @@ pub fn semaFile(mod: *Module, file: *Scope.File) SemaError!void {
27922801 .zir_index = undefined, // set below
27932802 .layout = .Auto,
27942803 .status = .none,
2804 .known_has_bits = undefined,
27952805 .namespace = .{
27962806 .parent = null,
27972807 .ty = struct_ty,
......@@ -3301,10 +3311,23 @@ fn scanDecl(iter: *ScanDeclIter, decl_sub_index: usize, flags: u4) SemaError!voi
33013311 gop.value_ptr.* = new_decl;
33023312 // Exported decls, comptime decls, usingnamespace decls, and
33033313 // test decls if in test mode, get analyzed.
3314 const decl_pkg = namespace.file_scope.pkg;
33043315 const want_analysis = is_exported or switch (decl_name_index) {
33053316 0 => true, // comptime decl
3306 1 => mod.comp.bin_file.options.is_test, // test decl
3307 else => is_named_test and mod.comp.bin_file.options.is_test,
3317 1 => blk: {
3318 // test decl with no name. Skip the part where we check against
3319 // the test name filter.
3320 if (!mod.comp.bin_file.options.is_test) break :blk false;
3321 if (decl_pkg != mod.main_pkg) break :blk false;
3322 break :blk true;
3323 },
3324 else => blk: {
3325 if (!is_named_test) break :blk false;
3326 if (!mod.comp.bin_file.options.is_test) break :blk false;
3327 if (decl_pkg != mod.main_pkg) break :blk false;
3328 // TODO check the name against --test-filter
3329 break :blk true;
3330 },
33083331 };
33093332 if (want_analysis) {
33103333 mod.comp.work_queue.writeItemAssumeCapacity(.{ .analyze_decl = new_decl });
src/Sema.zig+125-49
......@@ -768,6 +768,8 @@ pub fn analyzeStructDecl(
768768 assert(extended.opcode == .struct_decl);
769769 const small = @bitCast(Zir.Inst.StructDecl.Small, extended.small);
770770
771 struct_obj.known_has_bits = small.known_has_bits;
772
771773 var extra_index: usize = extended.operand;
772774 extra_index += @boolToInt(small.has_src_node);
773775 extra_index += @boolToInt(small.has_body_len);
......@@ -812,6 +814,7 @@ fn zirStructDecl(
812814 .zir_index = inst,
813815 .layout = small.layout,
814816 .status = .none,
817 .known_has_bits = undefined,
815818 .namespace = .{
816819 .parent = sema.owner_decl.namespace,
817820 .ty = struct_ty,
......@@ -1259,8 +1262,13 @@ fn zirIndexablePtrLen(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) Co
12591262 const inst_data = sema.code.instructions.items(.data)[inst].un_node;
12601263 const src = inst_data.src();
12611264 const array_ptr = sema.resolveInst(inst_data.operand);
1265 const array_ptr_src = src;
12621266
12631267 const elem_ty = sema.typeOf(array_ptr).elemType();
1268 if (elem_ty.isSlice()) {
1269 const slice_inst = try sema.analyzeLoad(block, src, array_ptr, array_ptr_src);
1270 return sema.analyzeSliceLen(block, src, slice_inst);
1271 }
12641272 if (!elem_ty.isIndexable()) {
12651273 const cond_src: LazySrcLoc = .{ .node_offset_for_cond = inst_data.src_node };
12661274 const msg = msg: {
......@@ -1283,7 +1291,7 @@ fn zirIndexablePtrLen(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) Co
12831291 return sema.mod.failWithOwnedErrorMsg(&block.base, msg);
12841292 }
12851293 const result_ptr = try sema.namedFieldPtr(block, src, array_ptr, "len", src);
1286 const result_ptr_src = src;
1294 const result_ptr_src = array_ptr_src;
12871295 return sema.analyzeLoad(block, src, result_ptr, result_ptr_src);
12881296}
12891297
......@@ -2928,17 +2936,15 @@ fn zirErrUnionPayload(
29282936 return sema.mod.fail(&block.base, src, "caught unexpected error '{s}'", .{name});
29292937 }
29302938 const data = val.castTag(.error_union).?.data;
2931 return sema.addConstant(
2932 operand_ty.castTag(.error_union).?.data.payload,
2933 data,
2934 );
2939 const result_ty = operand_ty.errorUnionPayload();
2940 return sema.addConstant(result_ty, data);
29352941 }
29362942 try sema.requireRuntimeBlock(block, src);
29372943 if (safety_check and block.wantSafety()) {
29382944 const is_non_err = try block.addUnOp(.is_err, operand);
29392945 try sema.addSafetyCheck(block, is_non_err, .unwrap_errunion);
29402946 }
2941 const result_ty = operand_ty.castTag(.error_union).?.data.payload;
2947 const result_ty = operand_ty.errorUnionPayload();
29422948 return block.addTyOp(.unwrap_errunion_payload, result_ty, operand);
29432949}
29442950
......@@ -2961,7 +2967,8 @@ fn zirErrUnionPayloadPtr(
29612967 if (operand_ty.elemType().zigTypeTag() != .ErrorUnion)
29622968 return sema.mod.fail(&block.base, src, "expected error union type, found {}", .{operand_ty.elemType()});
29632969
2964 const operand_pointer_ty = try Module.simplePtrType(sema.arena, operand_ty.elemType().castTag(.error_union).?.data.payload, !operand_ty.isConstPtr(), .One);
2970 const payload_ty = operand_ty.elemType().errorUnionPayload();
2971 const operand_pointer_ty = try Module.simplePtrType(sema.arena, payload_ty, !operand_ty.isConstPtr(), .One);
29652972
29662973 if (try sema.resolveDefinedValue(block, src, operand)) |pointer_val| {
29672974 const val = try pointer_val.pointerDeref(sema.arena);
......@@ -2999,7 +3006,7 @@ fn zirErrUnionCode(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) Compi
29993006 if (operand_ty.zigTypeTag() != .ErrorUnion)
30003007 return sema.mod.fail(&block.base, src, "expected error union type, found '{}'", .{operand_ty});
30013008
3002 const result_ty = operand_ty.castTag(.error_union).?.data.error_set;
3009 const result_ty = operand_ty.errorUnionSet();
30033010
30043011 if (try sema.resolveDefinedValue(block, src, operand)) |val| {
30053012 assert(val.getError() != null);
......@@ -3025,7 +3032,7 @@ fn zirErrUnionCodePtr(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) Co
30253032 if (operand_ty.elemType().zigTypeTag() != .ErrorUnion)
30263033 return sema.mod.fail(&block.base, src, "expected error union type, found {}", .{operand_ty.elemType()});
30273034
3028 const result_ty = operand_ty.elemType().castTag(.error_union).?.data.error_set;
3035 const result_ty = operand_ty.elemType().errorUnionSet();
30293036
30303037 if (try sema.resolveDefinedValue(block, src, operand)) |pointer_val| {
30313038 const val = try pointer_val.pointerDeref(sema.arena);
......@@ -3048,7 +3055,7 @@ fn zirEnsureErrPayloadVoid(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Inde
30483055 const operand_ty = sema.typeOf(operand);
30493056 if (operand_ty.zigTypeTag() != .ErrorUnion)
30503057 return sema.mod.fail(&block.base, src, "expected error union type, found '{}'", .{operand_ty});
3051 if (operand_ty.castTag(.error_union).?.data.payload.zigTypeTag() != .Void) {
3058 if (operand_ty.errorUnionPayload().zigTypeTag() != .Void) {
30523059 return sema.mod.fail(&block.base, src, "expression value is ignored", .{});
30533060 }
30543061}
......@@ -3460,14 +3467,8 @@ fn zirElemVal(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileErr
34603467
34613468 const bin_inst = sema.code.instructions.items(.data)[inst].bin;
34623469 const array = sema.resolveInst(bin_inst.lhs);
3463 const array_ty = sema.typeOf(array);
3464 const array_ptr = if (array_ty.zigTypeTag() == .Pointer)
3465 array
3466 else
3467 try sema.analyzeRef(block, sema.src, array);
34683470 const elem_index = sema.resolveInst(bin_inst.rhs);
3469 const result_ptr = try sema.elemPtr(block, sema.src, array_ptr, elem_index, sema.src);
3470 return sema.analyzeLoad(block, sema.src, result_ptr, sema.src);
3471 return sema.elemVal(block, sema.src, array, elem_index, sema.src);
34713472}
34723473
34733474fn zirElemValNode(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
......@@ -3479,14 +3480,8 @@ fn zirElemValNode(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) Compil
34793480 const elem_index_src: LazySrcLoc = .{ .node_offset_array_access_index = inst_data.src_node };
34803481 const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data;
34813482 const array = sema.resolveInst(extra.lhs);
3482 const array_ty = sema.typeOf(array);
3483 const array_ptr = if (array_ty.zigTypeTag() == .Pointer)
3484 array
3485 else
3486 try sema.analyzeRef(block, src, array);
34873483 const elem_index = sema.resolveInst(extra.rhs);
3488 const result_ptr = try sema.elemPtr(block, src, array_ptr, elem_index, elem_index_src);
3489 return sema.analyzeLoad(block, src, result_ptr, src);
3484 return sema.elemVal(block, src, array, elem_index, elem_index_src);
34903485}
34913486
34923487fn zirElemPtr(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
......@@ -5338,7 +5333,7 @@ fn zirBoolBr(
53385333
53395334 try sema.air_extra.ensureUnusedCapacity(gpa, @typeInfo(Air.CondBr).Struct.fields.len +
53405335 then_block.instructions.items.len + else_block.instructions.items.len +
5341 @typeInfo(Air.Block).Struct.fields.len + child_block.instructions.items.len);
5336 @typeInfo(Air.Block).Struct.fields.len + child_block.instructions.items.len + 1);
53425337
53435338 const cond_br_payload = sema.addExtraAssumeCapacity(Air.CondBr{
53445339 .then_body_len = @intCast(u32, then_block.instructions.items.len),
......@@ -6217,8 +6212,9 @@ fn zirVarExtended(
62176212 const init_val: Value = if (small.has_init) blk: {
62186213 const init_ref = @intToEnum(Zir.Inst.Ref, sema.code.extra[extra_index]);
62196214 extra_index += 1;
6220 const init_tv = try sema.resolveInstConst(block, init_src, init_ref);
6221 break :blk init_tv.val;
6215 const init_air_inst = sema.resolveInst(init_ref);
6216 break :blk (try sema.resolvePossiblyUndefinedValue(block, init_src, init_air_inst)) orelse
6217 return sema.failWithNeededComptime(block, init_src);
62226218 } else Value.initTag(.unreachable_value);
62236219
62246220 if (!var_ty.isValidVarType(small.is_extern)) {
......@@ -6586,7 +6582,30 @@ fn namedFieldPtr(
65866582 },
65876583 .Pointer => {
65886584 const ptr_child = elem_ty.elemType();
6589 switch (ptr_child.zigTypeTag()) {
6585 if (ptr_child.isSlice()) {
6586 if (mem.eql(u8, field_name, "ptr")) {
6587 return mod.fail(
6588 &block.base,
6589 field_name_src,
6590 "cannot obtain reference to pointer field of slice '{}'",
6591 .{elem_ty},
6592 );
6593 } else if (mem.eql(u8, field_name, "len")) {
6594 return mod.fail(
6595 &block.base,
6596 field_name_src,
6597 "cannot obtain reference to length field of slice '{}'",
6598 .{elem_ty},
6599 );
6600 } else {
6601 return mod.fail(
6602 &block.base,
6603 field_name_src,
6604 "no member named '{s}' in '{}'",
6605 .{ field_name, elem_ty },
6606 );
6607 }
6608 } else switch (ptr_child.zigTypeTag()) {
65906609 .Array => {
65916610 if (mem.eql(u8, field_name, "len")) {
65926611 return sema.addConstant(
......@@ -6836,6 +6855,50 @@ fn elemPtr(
68366855 return sema.mod.fail(&block.base, src, "TODO implement more analyze elemptr", .{});
68376856}
68386857
6858fn elemVal(
6859 sema: *Sema,
6860 block: *Scope.Block,
6861 src: LazySrcLoc,
6862 array_maybe_ptr: Air.Inst.Ref,
6863 elem_index: Air.Inst.Ref,
6864 elem_index_src: LazySrcLoc,
6865) CompileError!Air.Inst.Ref {
6866 const array_ptr_src = src; // TODO better source location
6867 const maybe_ptr_ty = sema.typeOf(array_maybe_ptr);
6868 if (maybe_ptr_ty.isSinglePointer()) {
6869 const indexable_ty = maybe_ptr_ty.elemType();
6870 if (indexable_ty.isSlice()) {
6871 // We have a pointer to a slice and we want an element value.
6872 if (try sema.isComptimeKnown(block, src, array_maybe_ptr)) {
6873 const slice = try sema.analyzeLoad(block, src, array_maybe_ptr, array_ptr_src);
6874 if (try sema.resolveDefinedValue(block, src, slice)) |slice_val| {
6875 _ = slice_val;
6876 return sema.mod.fail(&block.base, src, "TODO implement Sema for elemVal for comptime known slice", .{});
6877 }
6878 try sema.requireRuntimeBlock(block, src);
6879 return block.addBinOp(.slice_elem_val, slice, elem_index);
6880 }
6881 try sema.requireRuntimeBlock(block, src);
6882 return block.addBinOp(.ptr_slice_elem_val, array_maybe_ptr, elem_index);
6883 }
6884 }
6885 if (maybe_ptr_ty.isSlice()) {
6886 if (try sema.resolveDefinedValue(block, src, array_maybe_ptr)) |slice_val| {
6887 _ = slice_val;
6888 return sema.mod.fail(&block.base, src, "TODO implement Sema for elemVal for comptime known slice", .{});
6889 }
6890 try sema.requireRuntimeBlock(block, src);
6891 return block.addBinOp(.slice_elem_val, array_maybe_ptr, elem_index);
6892 }
6893
6894 const array_ptr = if (maybe_ptr_ty.zigTypeTag() == .Pointer)
6895 array_maybe_ptr
6896 else
6897 try sema.analyzeRef(block, src, array_maybe_ptr);
6898 const ptr = try sema.elemPtr(block, src, array_ptr, elem_index, elem_index_src);
6899 return sema.analyzeLoad(block, src, ptr, elem_index_src);
6900}
6901
68396902fn elemPtrArray(
68406903 sema: *Sema,
68416904 block: *Scope.Block,
......@@ -6896,11 +6959,6 @@ fn coerce(
68966959 }
68976960 assert(inst_ty.zigTypeTag() != .Undefined);
68986961
6899 // T to E!T or E to E!T
6900 if (dest_type.tag() == .error_union) {
6901 return try sema.wrapErrorUnion(block, dest_type, inst, inst_src);
6902 }
6903
69046962 // comptime known number to other number
69056963 if (try sema.coerceNum(block, dest_type, inst, inst_src)) |some|
69066964 return some;
......@@ -7028,6 +7086,10 @@ fn coerce(
70287086 );
70297087 }
70307088 },
7089 .ErrorUnion => {
7090 // T to E!T or E to E!T
7091 return sema.wrapErrorUnion(block, dest_type, inst, inst_src);
7092 },
70317093 else => {},
70327094 }
70337095
......@@ -7257,16 +7319,13 @@ fn analyzeVarRef(sema: *Sema, block: *Scope.Block, src: LazySrcLoc, tv: TypedVal
72577319 const gpa = sema.gpa;
72587320 try sema.requireRuntimeBlock(block, src);
72597321 try sema.air_variables.append(gpa, variable);
7260 const result_inst = @intCast(Air.Inst.Index, sema.air_instructions.len);
7261 try sema.air_instructions.append(gpa, .{
7322 return block.addInst(.{
72627323 .tag = .varptr,
72637324 .data = .{ .ty_pl = .{
72647325 .ty = try sema.addType(ty),
72657326 .payload = @intCast(u32, sema.air_variables.items.len - 1),
72667327 } },
72677328 });
7268 try block.instructions.append(gpa, result_inst);
7269 return Air.indexToRef(result_inst);
72707329}
72717330
72727331fn analyzeRef(
......@@ -7309,6 +7368,22 @@ fn analyzeLoad(
73097368 return block.addTyOp(.load, elem_ty, ptr);
73107369}
73117370
7371fn analyzeSliceLen(
7372 sema: *Sema,
7373 block: *Scope.Block,
7374 src: LazySrcLoc,
7375 slice_inst: Air.Inst.Ref,
7376) CompileError!Air.Inst.Ref {
7377 if (try sema.resolvePossiblyUndefinedValue(block, src, slice_inst)) |slice_val| {
7378 if (slice_val.isUndef()) {
7379 return sema.addConstUndef(Type.initTag(.usize));
7380 }
7381 return sema.mod.fail(&block.base, src, "TODO implement Sema analyzeSliceLen on comptime slice", .{});
7382 }
7383 try sema.requireRuntimeBlock(block, src);
7384 return block.addTyOp(.slice_len, Type.initTag(.usize), slice_inst);
7385}
7386
73127387fn analyzeIsNull(
73137388 sema: *Sema,
73147389 block: *Scope.Block,
......@@ -7645,27 +7720,28 @@ fn wrapErrorUnion(
76457720 inst_src: LazySrcLoc,
76467721) !Air.Inst.Ref {
76477722 const inst_ty = sema.typeOf(inst);
7648 const err_union = dest_type.castTag(.error_union).?;
7723 const dest_err_set_ty = dest_type.errorUnionSet();
7724 const dest_payload_ty = dest_type.errorUnionPayload();
76497725 if (try sema.resolvePossiblyUndefinedValue(block, inst_src, inst)) |val| {
76507726 if (inst_ty.zigTypeTag() != .ErrorSet) {
7651 _ = try sema.coerce(block, err_union.data.payload, inst, inst_src);
7652 } else switch (err_union.data.error_set.tag()) {
7727 _ = try sema.coerce(block, dest_payload_ty, inst, inst_src);
7728 } else switch (dest_err_set_ty.tag()) {
76537729 .anyerror => {},
76547730 .error_set_single => {
76557731 const expected_name = val.castTag(.@"error").?.data.name;
7656 const n = err_union.data.error_set.castTag(.error_set_single).?.data;
7732 const n = dest_err_set_ty.castTag(.error_set_single).?.data;
76577733 if (!mem.eql(u8, expected_name, n)) {
76587734 return sema.mod.fail(
76597735 &block.base,
76607736 inst_src,
76617737 "expected type '{}', found type '{}'",
7662 .{ err_union.data.error_set, inst_ty },
7738 .{ dest_err_set_ty, inst_ty },
76637739 );
76647740 }
76657741 },
76667742 .error_set => {
76677743 const expected_name = val.castTag(.@"error").?.data.name;
7668 const error_set = err_union.data.error_set.castTag(.error_set).?.data;
7744 const error_set = dest_err_set_ty.castTag(.error_set).?.data;
76697745 const names = error_set.names_ptr[0..error_set.names_len];
76707746 // TODO this is O(N). I'm putting off solving this until we solve inferred
76717747 // error sets at the same time.
......@@ -7677,19 +7753,19 @@ fn wrapErrorUnion(
76777753 &block.base,
76787754 inst_src,
76797755 "expected type '{}', found type '{}'",
7680 .{ err_union.data.error_set, inst_ty },
7756 .{ dest_err_set_ty, inst_ty },
76817757 );
76827758 }
76837759 },
76847760 .error_set_inferred => {
76857761 const expected_name = val.castTag(.@"error").?.data.name;
7686 const map = &err_union.data.error_set.castTag(.error_set_inferred).?.data.map;
7762 const map = &dest_err_set_ty.castTag(.error_set_inferred).?.data.map;
76877763 if (!map.contains(expected_name)) {
76887764 return sema.mod.fail(
76897765 &block.base,
76907766 inst_src,
76917767 "expected type '{}', found type '{}'",
7692 .{ err_union.data.error_set, inst_ty },
7768 .{ dest_err_set_ty, inst_ty },
76937769 );
76947770 }
76957771 },
......@@ -7704,10 +7780,10 @@ fn wrapErrorUnion(
77047780
77057781 // we are coercing from E to E!T
77067782 if (inst_ty.zigTypeTag() == .ErrorSet) {
7707 var coerced = try sema.coerce(block, err_union.data.error_set, inst, inst_src);
7783 var coerced = try sema.coerce(block, dest_err_set_ty, inst, inst_src);
77087784 return block.addTyOp(.wrap_errunion_err, dest_type, coerced);
77097785 } else {
7710 var coerced = try sema.coerce(block, err_union.data.payload, inst, inst_src);
7786 var coerced = try sema.coerce(block, dest_payload_ty, inst, inst_src);
77117787 return block.addTyOp(.wrap_errunion_payload, dest_type, coerced);
77127788 }
77137789}
......@@ -7857,7 +7933,7 @@ fn getBuiltin(
78577933 name: []const u8,
78587934) CompileError!Air.Inst.Ref {
78597935 const mod = sema.mod;
7860 const std_pkg = mod.root_pkg.table.get("std").?;
7936 const std_pkg = mod.main_pkg.table.get("std").?;
78617937 const std_file = (mod.importPkg(std_pkg) catch unreachable).file;
78627938 const opt_builtin_inst = try sema.analyzeNamespaceLookup(
78637939 block,
src/Zir.zig+3-1
......@@ -2462,9 +2462,10 @@ pub const Inst = struct {
24622462 has_body_len: bool,
24632463 has_fields_len: bool,
24642464 has_decls_len: bool,
2465 known_has_bits: bool,
24652466 name_strategy: NameStrategy,
24662467 layout: std.builtin.TypeInfo.ContainerLayout,
2467 _: u8 = undefined,
2468 _: u7 = undefined,
24682469 };
24692470 };
24702471
......@@ -3543,6 +3544,7 @@ const Writer = struct {
35433544 break :blk decls_len;
35443545 } else 0;
35453546
3547 try self.writeFlag(stream, "known_has_bits, ", small.known_has_bits);
35463548 try stream.print("{s}, {s}, ", .{
35473549 @tagName(small.name_strategy), @tagName(small.layout),
35483550 });
src/codegen.zig+37
......@@ -853,6 +853,11 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
853853 .struct_field_ptr=> try self.airStructFieldPtr(inst),
854854 .switch_br => try self.airSwitch(inst),
855855 .varptr => try self.airVarPtr(inst),
856 .slice_ptr => try self.airSlicePtr(inst),
857 .slice_len => try self.airSliceLen(inst),
858
859 .slice_elem_val => try self.airSliceElemVal(inst),
860 .ptr_slice_elem_val => try self.airPtrSliceElemVal(inst),
856861
857862 .constant => unreachable, // excluded from function bodies
858863 .const_ty => unreachable, // excluded from function bodies
......@@ -1333,6 +1338,38 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
13331338 return self.finishAir(inst, result, .{ .none, .none, .none });
13341339 }
13351340
1341 fn airSlicePtr(self: *Self, inst: Air.Inst.Index) !void {
1342 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
1343 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else switch (arch) {
1344 else => return self.fail("TODO implement slice_ptr for {}", .{self.target.cpu.arch}),
1345 };
1346 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });
1347 }
1348
1349 fn airSliceLen(self: *Self, inst: Air.Inst.Index) !void {
1350 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
1351 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else switch (arch) {
1352 else => return self.fail("TODO implement slice_len for {}", .{self.target.cpu.arch}),
1353 };
1354 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });
1355 }
1356
1357 fn airSliceElemVal(self: *Self, inst: Air.Inst.Index) !void {
1358 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
1359 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else switch (arch) {
1360 else => return self.fail("TODO implement slice_elem_val for {}", .{self.target.cpu.arch}),
1361 };
1362 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });
1363 }
1364
1365 fn airPtrSliceElemVal(self: *Self, inst: Air.Inst.Index) !void {
1366 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
1367 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else switch (arch) {
1368 else => return self.fail("TODO implement ptr_slice_elem_val for {}", .{self.target.cpu.arch}),
1369 };
1370 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });
1371 }
1372
13361373 fn reuseOperand(self: *Self, inst: Air.Inst.Index, operand: Air.Inst.Ref, op_index: Liveness.OperandInt, mcv: MCValue) bool {
13371374 if (!self.liveness.operandDies(inst, op_index))
13381375 return false;
src/codegen/c.zig+89-41
......@@ -237,7 +237,8 @@ pub const DeclGen = struct {
237237 // This should lower to 0xaa bytes in safe modes, and for unsafe modes should
238238 // lower to leaving variables uninitialized (that might need to be implemented
239239 // outside of this function).
240 return dg.fail("TODO: C backend: implement renderValue undef", .{});
240 return writer.writeAll("{}");
241 //return dg.fail("TODO: C backend: implement renderValue undef", .{});
241242 }
242243 switch (t.zigTypeTag()) {
243244 .Int => {
......@@ -361,18 +362,27 @@ pub const DeclGen = struct {
361362 }
362363 },
363364 .ErrorSet => {
364 const payload = val.castTag(.@"error").?;
365 // error values will be #defined at the top of the file
366 return writer.print("zig_error_{s}", .{payload.data.name});
365 switch (val.tag()) {
366 .@"error" => {
367 const payload = val.castTag(.@"error").?;
368 // error values will be #defined at the top of the file
369 return writer.print("zig_error_{s}", .{payload.data.name});
370 },
371 else => {
372 // In this case we are rendering an error union which has a
373 // 0 bits payload.
374 return writer.writeAll("0");
375 },
376 }
367377 },
368378 .ErrorUnion => {
369379 const error_type = t.errorUnionSet();
370 const payload_type = t.errorUnionChild();
371 const data = val.castTag(.error_union).?.data;
380 const payload_type = t.errorUnionPayload();
381 const sub_val = val.castTag(.error_union).?.data;
372382
373383 if (!payload_type.hasCodeGenBits()) {
374384 // We use the error type directly as the type.
375 return dg.renderValue(writer, error_type, data);
385 return dg.renderValue(writer, error_type, sub_val);
376386 }
377387
378388 try writer.writeByte('(');
......@@ -383,7 +393,7 @@ pub const DeclGen = struct {
383393 try dg.renderValue(
384394 writer,
385395 error_type,
386 data,
396 sub_val,
387397 );
388398 try writer.writeAll(" }");
389399 } else {
......@@ -391,7 +401,7 @@ pub const DeclGen = struct {
391401 try dg.renderValue(
392402 writer,
393403 payload_type,
394 data,
404 sub_val,
395405 );
396406 try writer.writeAll(", .error = 0 }");
397407 }
......@@ -616,7 +626,7 @@ pub const DeclGen = struct {
616626 if (dg.typedefs.get(t)) |some| {
617627 return w.writeAll(some.name);
618628 }
619 const child_type = t.errorUnionChild();
629 const child_type = t.errorUnionPayload();
620630 const err_set_type = t.errorUnionSet();
621631
622632 if (!child_type.hasCodeGenBits()) {
......@@ -926,6 +936,11 @@ fn genBody(o: *Object, body: []const Air.Inst.Index) error{ AnalysisFail, OutOfM
926936 .ref => try airRef(o, inst),
927937 .struct_field_ptr => try airStructFieldPtr(o, inst),
928938 .varptr => try airVarPtr(o, inst),
939 .slice_ptr => try airSliceField(o, inst, ".ptr;\n"),
940 .slice_len => try airSliceField(o, inst, ".len;\n"),
941
942 .slice_elem_val => try airSliceElemVal(o, inst, "["),
943 .ptr_slice_elem_val => try airSliceElemVal(o, inst, "[0]["),
929944
930945 .unwrap_errunion_payload => try airUnwrapErrUnionPay(o, inst),
931946 .unwrap_errunion_err => try airUnwrapErrUnionErr(o, inst),
......@@ -948,6 +963,37 @@ fn genBody(o: *Object, body: []const Air.Inst.Index) error{ AnalysisFail, OutOfM
948963 try writer.writeAll("}");
949964}
950965
966fn airSliceField(o: *Object, inst: Air.Inst.Index, suffix: []const u8) !CValue {
967 if (o.liveness.isUnused(inst))
968 return CValue.none;
969
970 const ty_op = o.air.instructions.items(.data)[inst].ty_op;
971 const operand = try o.resolveInst(ty_op.operand);
972 const writer = o.writer();
973 const local = try o.allocLocal(Type.initTag(.usize), .Const);
974 try writer.writeAll(" = ");
975 try o.writeCValue(writer, operand);
976 try writer.writeAll(suffix);
977 return local;
978}
979
980fn airSliceElemVal(o: *Object, inst: Air.Inst.Index, prefix: []const u8) !CValue {
981 if (o.liveness.isUnused(inst))
982 return CValue.none;
983
984 const bin_op = o.air.instructions.items(.data)[inst].bin_op;
985 const slice = try o.resolveInst(bin_op.lhs);
986 const index = try o.resolveInst(bin_op.rhs);
987 const writer = o.writer();
988 const local = try o.allocLocal(o.air.typeOfIndex(inst), .Const);
989 try writer.writeAll(" = ");
990 try o.writeCValue(writer, slice);
991 try writer.writeAll(prefix);
992 try o.writeCValue(writer, index);
993 try writer.writeAll("];\n");
994 return local;
995}
996
951997fn airVarPtr(o: *Object, inst: Air.Inst.Index) !CValue {
952998 const ty_pl = o.air.instructions.items(.data)[inst].ty_pl;
953999 const variable = o.air.variables[ty_pl.payload];
......@@ -1233,6 +1279,20 @@ fn airCall(o: *Object, inst: Air.Inst.Index) !CValue {
12331279 const pl_op = o.air.instructions.items(.data)[inst].pl_op;
12341280 const extra = o.air.extraData(Air.Call, pl_op.payload);
12351281 const args = @bitCast([]const Air.Inst.Ref, o.air.extra[extra.end..][0..extra.data.args_len]);
1282 const fn_ty = o.air.typeOf(pl_op.operand);
1283 const ret_ty = fn_ty.fnReturnType();
1284 const unused_result = o.liveness.isUnused(inst);
1285 const writer = o.writer();
1286
1287 var result_local: CValue = .none;
1288 if (unused_result) {
1289 if (ret_ty.hasCodeGenBits()) {
1290 try writer.print("(void)", .{});
1291 }
1292 } else {
1293 result_local = try o.allocLocal(ret_ty, .Const);
1294 try writer.writeAll(" = ");
1295 }
12361296
12371297 if (o.air.value(pl_op.operand)) |func_val| {
12381298 const fn_decl = if (func_val.castTag(.extern_fn)) |extern_fn|
......@@ -1242,38 +1302,26 @@ fn airCall(o: *Object, inst: Air.Inst.Index) !CValue {
12421302 else
12431303 unreachable;
12441304
1245 const fn_ty = fn_decl.ty;
1246 const ret_ty = fn_ty.fnReturnType();
1247 const unused_result = o.liveness.isUnused(inst);
1248 var result_local: CValue = .none;
1305 try writer.writeAll(mem.spanZ(fn_decl.name));
1306 } else {
1307 const callee = try o.resolveInst(pl_op.operand);
1308 try o.writeCValue(writer, callee);
1309 }
12491310
1250 const writer = o.writer();
1251 if (unused_result) {
1252 if (ret_ty.hasCodeGenBits()) {
1253 try writer.print("(void)", .{});
1254 }
1255 } else {
1256 result_local = try o.allocLocal(ret_ty, .Const);
1257 try writer.writeAll(" = ");
1311 try writer.writeAll("(");
1312 for (args) |arg, i| {
1313 if (i != 0) {
1314 try writer.writeAll(", ");
12581315 }
1259 const fn_name = mem.spanZ(fn_decl.name);
1260 try writer.print("{s}(", .{fn_name});
1261 for (args) |arg, i| {
1262 if (i != 0) {
1263 try writer.writeAll(", ");
1264 }
1265 if (o.air.value(arg)) |val| {
1266 try o.dg.renderValue(writer, o.air.typeOf(arg), val);
1267 } else {
1268 const val = try o.resolveInst(arg);
1269 try o.writeCValue(writer, val);
1270 }
1316 if (o.air.value(arg)) |val| {
1317 try o.dg.renderValue(writer, o.air.typeOf(arg), val);
1318 } else {
1319 const val = try o.resolveInst(arg);
1320 try o.writeCValue(writer, val);
12711321 }
1272 try writer.writeAll(");\n");
1273 return result_local;
1274 } else {
1275 return o.dg.fail("TODO: C backend: implement function pointers", .{});
12761322 }
1323 try writer.writeAll(");\n");
1324 return result_local;
12771325}
12781326
12791327fn airDbgStmt(o: *Object, inst: Air.Inst.Index) !CValue {
......@@ -1643,7 +1691,7 @@ fn airUnwrapErrUnionErr(o: *Object, inst: Air.Inst.Index) !CValue {
16431691 const operand = try o.resolveInst(ty_op.operand);
16441692 const operand_ty = o.air.typeOf(ty_op.operand);
16451693
1646 const payload_ty = operand_ty.errorUnionChild();
1694 const payload_ty = operand_ty.errorUnionPayload();
16471695 if (!payload_ty.hasCodeGenBits()) {
16481696 if (operand_ty.zigTypeTag() == .Pointer) {
16491697 const local = try o.allocLocal(inst_ty, .Const);
......@@ -1675,7 +1723,7 @@ fn airUnwrapErrUnionPay(o: *Object, inst: Air.Inst.Index) !CValue {
16751723 const operand = try o.resolveInst(ty_op.operand);
16761724 const operand_ty = o.air.typeOf(ty_op.operand);
16771725
1678 const payload_ty = operand_ty.errorUnionChild();
1726 const payload_ty = operand_ty.errorUnionPayload();
16791727 if (!payload_ty.hasCodeGenBits()) {
16801728 return CValue.none;
16811729 }
......@@ -1760,7 +1808,7 @@ fn airIsErr(
17601808 const operand = try o.resolveInst(un_op);
17611809 const operand_ty = o.air.typeOf(un_op);
17621810 const local = try o.allocLocal(Type.initTag(.bool), .Const);
1763 const payload_ty = operand_ty.errorUnionChild();
1811 const payload_ty = operand_ty.errorUnionPayload();
17641812 if (!payload_ty.hasCodeGenBits()) {
17651813 try writer.print(" = {s}", .{deref_prefix});
17661814 try o.writeCValue(writer, operand);
src/codegen/wasm.zig+3-3
......@@ -646,7 +646,7 @@ pub const Context = struct {
646646 } };
647647 },
648648 .ErrorUnion => {
649 const payload_type = ty.errorUnionChild();
649 const payload_type = ty.errorUnionPayload();
650650 const val_type = try self.genValtype(payload_type);
651651
652652 // we emit the error value as the first local, and the payload as the following.
......@@ -699,7 +699,7 @@ pub const Context = struct {
699699 .Struct => return self.fail("TODO: Implement struct as return type for wasm", .{}),
700700 .Optional => return self.fail("TODO: Implement optionals as return type for wasm", .{}),
701701 .ErrorUnion => {
702 const val_type = try self.genValtype(return_type.errorUnionChild());
702 const val_type = try self.genValtype(return_type.errorUnionPayload());
703703
704704 // write down the amount of return values
705705 try leb.writeULEB128(writer, @as(u32, 2));
......@@ -1055,7 +1055,7 @@ pub const Context = struct {
10551055 .ErrorUnion => {
10561056 const data = value.castTag(.error_union).?.data;
10571057 const error_type = ty.errorUnionSet();
1058 const payload_type = ty.errorUnionChild();
1058 const payload_type = ty.errorUnionPayload();
10591059 if (value.getError()) |_| {
10601060 // write the error value
10611061 try self.emitConstant(data, error_type);
src/glibc.zig+1-1
......@@ -943,7 +943,7 @@ fn buildSharedLib(
943943 .zig_lib_directory = comp.zig_lib_directory,
944944 .target = comp.getTarget(),
945945 .root_name = lib.name,
946 .root_pkg = null,
946 .main_pkg = null,
947947 .output_mode = .Lib,
948948 .link_mode = .Dynamic,
949949 .thread_pool = comp.thread_pool,
src/libcxx.zig+2-2
......@@ -169,7 +169,7 @@ pub fn buildLibCXX(comp: *Compilation) !void {
169169 .zig_lib_directory = comp.zig_lib_directory,
170170 .target = target,
171171 .root_name = root_name,
172 .root_pkg = null,
172 .main_pkg = null,
173173 .output_mode = output_mode,
174174 .thread_pool = comp.thread_pool,
175175 .libc_installation = comp.bin_file.options.libc_installation,
......@@ -301,7 +301,7 @@ pub fn buildLibCXXABI(comp: *Compilation) !void {
301301 .zig_lib_directory = comp.zig_lib_directory,
302302 .target = target,
303303 .root_name = root_name,
304 .root_pkg = null,
304 .main_pkg = null,
305305 .output_mode = output_mode,
306306 .thread_pool = comp.thread_pool,
307307 .libc_installation = comp.bin_file.options.libc_installation,
src/libtsan.zig+1-1
......@@ -201,7 +201,7 @@ pub fn buildTsan(comp: *Compilation) !void {
201201 .zig_lib_directory = comp.zig_lib_directory,
202202 .target = target,
203203 .root_name = root_name,
204 .root_pkg = null,
204 .main_pkg = null,
205205 .output_mode = output_mode,
206206 .thread_pool = comp.thread_pool,
207207 .libc_installation = comp.bin_file.options.libc_installation,
src/libunwind.zig+1-1
......@@ -101,7 +101,7 @@ pub fn buildStaticLib(comp: *Compilation) !void {
101101 .zig_lib_directory = comp.zig_lib_directory,
102102 .target = target,
103103 .root_name = root_name,
104 .root_pkg = null,
104 .main_pkg = null,
105105 .output_mode = output_mode,
106106 .thread_pool = comp.thread_pool,
107107 .libc_installation = comp.bin_file.options.libc_installation,
src/main.zig+15-15
......@@ -263,12 +263,12 @@ pub fn mainArgs(gpa: *Allocator, arena: *Allocator, args: []const []const u8) !v
263263}
264264
265265const usage_build_generic =
266 \\Usage: zig build-exe <options> [files]
267 \\ zig build-lib <options> [files]
268 \\ zig build-obj <options> [files]
269 \\ zig test <options> [files]
270 \\ zig run <options> [file] [-- [args]]
271 \\ zig translate-c <options> [file]
266 \\Usage: zig build-exe [options] [files]
267 \\ zig build-lib [options] [files]
268 \\ zig build-obj [options] [files]
269 \\ zig test [options] [files]
270 \\ zig run [options] [files] [-- [args]]
271 \\ zig translate-c [options] [file]
272272 \\
273273 \\Supported file types:
274274 \\ .zig Zig source code
......@@ -1915,7 +1915,7 @@ fn buildOutputType(
19151915 };
19161916 defer emit_docs_resolved.deinit();
19171917
1918 const root_pkg: ?*Package = if (root_src_file) |src_path| blk: {
1918 const main_pkg: ?*Package = if (root_src_file) |src_path| blk: {
19191919 if (main_pkg_path) |p| {
19201920 const rel_src_path = try fs.path.relative(gpa, p, src_path);
19211921 defer gpa.free(rel_src_path);
......@@ -1924,10 +1924,10 @@ fn buildOutputType(
19241924 break :blk try Package.create(gpa, fs.path.dirname(src_path), fs.path.basename(src_path));
19251925 }
19261926 } else null;
1927 defer if (root_pkg) |p| p.destroy(gpa);
1927 defer if (main_pkg) |p| p.destroy(gpa);
19281928
19291929 // Transfer packages added with --pkg-begin/--pkg-end to the root package
1930 if (root_pkg) |pkg| {
1930 if (main_pkg) |pkg| {
19311931 pkg.table = pkg_tree_root.table;
19321932 pkg_tree_root.table = .{};
19331933 }
......@@ -1980,7 +1980,7 @@ fn buildOutputType(
19801980 if (arg_mode == .run) {
19811981 break :l global_cache_directory;
19821982 }
1983 if (root_pkg) |pkg| {
1983 if (main_pkg) |pkg| {
19841984 const cache_dir_path = try pkg.root_src_directory.join(arena, &[_][]const u8{"zig-cache"});
19851985 const dir = try pkg.root_src_directory.handle.makeOpenPath("zig-cache", .{});
19861986 cleanup_local_cache_dir = dir;
......@@ -2018,7 +2018,7 @@ fn buildOutputType(
20182018 .dynamic_linker = target_info.dynamic_linker.get(),
20192019 .sysroot = sysroot,
20202020 .output_mode = output_mode,
2021 .root_pkg = root_pkg,
2021 .main_pkg = main_pkg,
20222022 .emit_bin = emit_bin_loc,
20232023 .emit_h = emit_h_resolved.data,
20242024 .emit_asm = emit_asm_resolved.data,
......@@ -2823,7 +2823,7 @@ pub fn cmdBuild(gpa: *Allocator, arena: *Allocator, args: []const []const u8) !v
28232823 const std_special = "std" ++ fs.path.sep_str ++ "special";
28242824 const special_dir_path = try zig_lib_directory.join(arena, &[_][]const u8{std_special});
28252825
2826 var root_pkg: Package = .{
2826 var main_pkg: Package = .{
28272827 .root_src_directory = .{
28282828 .path = special_dir_path,
28292829 .handle = zig_lib_directory.handle.openDir(std_special, .{}) catch |err| {
......@@ -2832,7 +2832,7 @@ pub fn cmdBuild(gpa: *Allocator, arena: *Allocator, args: []const []const u8) !v
28322832 },
28332833 .root_src_path = "build_runner.zig",
28342834 };
2835 defer root_pkg.root_src_directory.handle.close();
2835 defer main_pkg.root_src_directory.handle.close();
28362836
28372837 var cleanup_build_dir: ?fs.Dir = null;
28382838 defer if (cleanup_build_dir) |*dir| dir.close();
......@@ -2881,7 +2881,7 @@ pub fn cmdBuild(gpa: *Allocator, arena: *Allocator, args: []const []const u8) !v
28812881 .root_src_directory = build_directory,
28822882 .root_src_path = build_zig_basename,
28832883 };
2884 try root_pkg.addAndAdopt(arena, "@build", &build_pkg);
2884 try main_pkg.addAndAdopt(arena, "@build", &build_pkg);
28852885
28862886 var global_cache_directory: Compilation.Directory = l: {
28872887 const p = override_global_cache_dir orelse try introspect.resolveGlobalCacheDir(arena);
......@@ -2938,7 +2938,7 @@ pub fn cmdBuild(gpa: *Allocator, arena: *Allocator, args: []const []const u8) !v
29382938 .is_native_abi = cross_target.isNativeAbi(),
29392939 .dynamic_linker = target_info.dynamic_linker.get(),
29402940 .output_mode = .Exe,
2941 .root_pkg = &root_pkg,
2941 .main_pkg = &main_pkg,
29422942 .emit_bin = emit_bin,
29432943 .emit_h = null,
29442944 .optimize_mode = .Debug,
src/musl.zig+1-1
......@@ -197,7 +197,7 @@ pub fn buildCRTFile(comp: *Compilation, crt_file: CRTFile) !void {
197197 .zig_lib_directory = comp.zig_lib_directory,
198198 .target = comp.getTarget(),
199199 .root_name = "c",
200 .root_pkg = null,
200 .main_pkg = null,
201201 .output_mode = .Lib,
202202 .link_mode = .Dynamic,
203203 .thread_pool = comp.thread_pool,
src/print_air.zig+4
......@@ -124,6 +124,8 @@ const Writer = struct {
124124 .bool_and,
125125 .bool_or,
126126 .store,
127 .slice_elem_val,
128 .ptr_slice_elem_val,
127129 => try w.writeBinOp(s, inst),
128130
129131 .is_null,
......@@ -161,6 +163,8 @@ const Writer = struct {
161163 .unwrap_errunion_err_ptr,
162164 .wrap_errunion_payload,
163165 .wrap_errunion_err,
166 .slice_ptr,
167 .slice_len,
164168 => try w.writeTyOp(s, inst),
165169
166170 .block,
src/stage1.zig+1-1
......@@ -107,7 +107,7 @@ pub const Module = extern struct {
107107 test_name_prefix_ptr: [*]const u8,
108108 test_name_prefix_len: usize,
109109 userdata: usize,
110 root_pkg: *Pkg,
110 main_pkg: *Pkg,
111111 main_progress_node: ?*std.Progress.Node,
112112 code_model: CodeModel,
113113 subsystem: TargetSubsystem,
src/stage1/stage1.cpp+1-1
......@@ -126,7 +126,7 @@ void zig_stage1_build_object(struct ZigStage1 *stage1) {
126126
127127 g->main_progress_node = stage1->main_progress_node;
128128
129 add_package(g, stage1->root_pkg, g->main_pkg);
129 add_package(g, stage1->main_pkg, g->main_pkg);
130130
131131 codegen_build_object(g);
132132}
src/stage1/stage1.h+1-1
......@@ -176,7 +176,7 @@ struct ZigStage1 {
176176 size_t test_name_prefix_len;
177177
178178 void *userdata;
179 struct ZigStage1Pkg *root_pkg;
179 struct ZigStage1Pkg *main_pkg;
180180 struct Stage2ProgressNode *main_progress_node;
181181
182182 enum CodeModel code_model;
src/stage1/zig0.cpp+1-1
......@@ -465,7 +465,7 @@ int main(int argc, char **argv) {
465465 stage1->verbose_llvm_cpu_features = verbose_llvm_cpu_features;
466466 stage1->emit_o_ptr = emit_bin_path;
467467 stage1->emit_o_len = strlen(emit_bin_path);
468 stage1->root_pkg = cur_pkg;
468 stage1->main_pkg = cur_pkg;
469469 stage1->err_color = color;
470470 stage1->link_libc = link_libc;
471471 stage1->link_libcpp = link_libcpp;
src/test.zig+3-3
......@@ -848,11 +848,11 @@ pub const TestContext = struct {
848848 .path = local_cache_path,
849849 };
850850
851 var root_pkg: Package = .{
851 var main_pkg: Package = .{
852852 .root_src_directory = .{ .path = tmp_dir_path, .handle = tmp.dir },
853853 .root_src_path = tmp_src_path,
854854 };
855 defer root_pkg.table.deinit(allocator);
855 defer main_pkg.table.deinit(allocator);
856856
857857 const bin_name = try std.zig.binNameAlloc(arena, .{
858858 .root_name = "test_case",
......@@ -896,7 +896,7 @@ pub const TestContext = struct {
896896 .optimize_mode = case.optimize_mode,
897897 .emit_bin = emit_bin,
898898 .emit_h = emit_h,
899 .root_pkg = &root_pkg,
899 .main_pkg = &main_pkg,
900900 .keep_source_files_loaded = true,
901901 .object_format = case.object_format,
902902 .is_native_os = case.target.isNativeOs(),
src/type.zig+20-13
......@@ -525,9 +525,19 @@ pub const Type = extern union {
525525 const b_data = b.castTag(.error_union).?.data;
526526 return a_data.error_set.eql(b_data.error_set) and a_data.payload.eql(b_data.payload);
527527 },
528 .ErrorSet => {
529 const a_is_anyerror = a.tag() == .anyerror;
530 const b_is_anyerror = b.tag() == .anyerror;
531
532 if (a_is_anyerror and b_is_anyerror) return true;
533 if (a_is_anyerror or b_is_anyerror) return false;
534
535 std.debug.panic("TODO implement Type equality comparison of {} and {}", .{
536 a.tag(), b.tag(),
537 });
538 },
528539 .Opaque,
529540 .Float,
530 .ErrorSet,
531541 .BoundFn,
532542 .Frame,
533543 => std.debug.panic("TODO implement Type equality comparison of {} and {}", .{ a, b }),
......@@ -1190,6 +1200,9 @@ pub const Type = extern union {
11901200 .@"struct" => {
11911201 // TODO introduce lazy value mechanism
11921202 const struct_obj = self.castTag(.@"struct").?.data;
1203 if (struct_obj.known_has_bits) {
1204 return true;
1205 }
11931206 assert(struct_obj.status == .have_field_types or
11941207 struct_obj.status == .layout_wip or
11951208 struct_obj.status == .have_layout);
......@@ -1645,7 +1658,7 @@ pub const Type = extern union {
16451658 } else if (!payload.payload.hasCodeGenBits()) {
16461659 return payload.error_set.abiSize(target);
16471660 }
1648 @panic("TODO abiSize error union");
1661 std.debug.panic("TODO abiSize error union {}", .{self});
16491662 },
16501663 };
16511664 }
......@@ -2038,7 +2051,7 @@ pub const Type = extern union {
20382051 return ty.optionalChild(&buf).isValidVarType(is_extern);
20392052 },
20402053 .Pointer, .Array, .Vector => ty = ty.elemType(),
2041 .ErrorUnion => ty = ty.errorUnionChild(),
2054 .ErrorUnion => ty = ty.errorUnionPayload(),
20422055
20432056 .Fn => @panic("TODO fn isValidVarType"),
20442057 .Struct => {
......@@ -2119,13 +2132,10 @@ pub const Type = extern union {
21192132 }
21202133
21212134 /// Asserts that the type is an error union.
2122 pub fn errorUnionChild(self: Type) Type {
2135 pub fn errorUnionPayload(self: Type) Type {
21232136 return switch (self.tag()) {
2124 .anyerror_void_error_union => Type.initTag(.anyerror),
2125 .error_union => {
2126 const payload = self.castTag(.error_union).?;
2127 return payload.data.payload;
2128 },
2137 .anyerror_void_error_union => Type.initTag(.void),
2138 .error_union => self.castTag(.error_union).?.data.payload,
21292139 else => unreachable,
21302140 };
21312141 }
......@@ -2133,10 +2143,7 @@ pub const Type = extern union {
21332143 pub fn errorUnionSet(self: Type) Type {
21342144 return switch (self.tag()) {
21352145 .anyerror_void_error_union => Type.initTag(.anyerror),
2136 .error_union => {
2137 const payload = self.castTag(.error_union).?;
2138 return payload.data.error_set;
2139 },
2146 .error_union => self.castTag(.error_union).?.data.error_set,
21402147 else => unreachable,
21412148 };
21422149 }
test/behavior.zig+1-1
......@@ -1,6 +1,6 @@
11const builtin = @import("builtin");
22
3comptime {
3test {
44 // Tests that pass for both.
55 {}
66