| author | |
| committer | |
| log | f75cdd1acd0929792c33766bd1d093d897c65113 |
| tree | 4f67752f34d4d3d8b78631b48d48fb971000c7a1 |
| parent | 952032b40cd6e3dbffc5642d17a7a05fa7c83895 |
| parent | afe5862111034ea4100b0eea5971e181d70ffc39 |
| signature | Signed by PGP key 4AEE18F83AFDEB23 |
stage2: blaze the trail for std lib integration17 files changed, 662 insertions(+), 290 deletions(-)
lib/std/start.zig+89-27| ... | @@ -7,7 +7,7 @@ | ... | @@ -7,7 +7,7 @@ |
| 7 | 7 | ||
| 8 | const root = @import("root"); | 8 | const root = @import("root"); |
| 9 | const std = @import("std.zig"); | 9 | const std = @import("std.zig"); |
| 10 | const builtin = std.builtin; | 10 | const builtin = @import("builtin"); |
| 11 | const assert = std.debug.assert; | 11 | const assert = std.debug.assert; |
| 12 | const uefi = std.os.uefi; | 12 | const uefi = std.os.uefi; |
| 13 | const tlcsprng = @import("crypto/tlcsprng.zig"); | 13 | const tlcsprng = @import("crypto/tlcsprng.zig"); |
| ... | @@ -17,39 +17,101 @@ var argc_argv_ptr: [*]usize = undefined; | ... | @@ -17,39 +17,101 @@ var argc_argv_ptr: [*]usize = undefined; |
| 17 | const start_sym_name = if (builtin.arch.isMIPS()) "__start" else "_start"; | 17 | const start_sym_name = if (builtin.arch.isMIPS()) "__start" else "_start"; |
| 18 | 18 | ||
| 19 | comptime { | 19 | comptime { |
| 20 | if (builtin.output_mode == .Lib and builtin.link_mode == .Dynamic) { | 20 | // The self-hosted compiler is not fully capable of handling all of this start.zig file. |
| 21 | if (builtin.os.tag == .windows and !@hasDecl(root, "_DllMainCRTStartup")) { | 21 | // Until then, we have simplified logic here for self-hosted. TODO remove this once |
| 22 | @export(_DllMainCRTStartup, .{ .name = "_DllMainCRTStartup" }); | 22 | // self-hosted is capable enough to handle all of the real start.zig logic. |
| 23 | if (builtin.zig_is_stage2) { | ||
| 24 | if (builtin.output_mode == .Exe) { | ||
| 25 | if (builtin.link_libc or builtin.object_format == .c) { | ||
| 26 | if (!@hasDecl(root, "main")) { | ||
| 27 | @export(main2, "main"); | ||
| 28 | } | ||
| 29 | } else { | ||
| 30 | if (!@hasDecl(root, "_start")) { | ||
| 31 | @export(_start2, "_start"); | ||
| 32 | } | ||
| 33 | } | ||
| 23 | } | 34 | } |
| 24 | } else if (builtin.output_mode == .Exe or @hasDecl(root, "main")) { | 35 | } else { |
| 25 | if (builtin.link_libc and @hasDecl(root, "main")) { | 36 | if (builtin.output_mode == .Lib and builtin.link_mode == .Dynamic) { |
| 26 | if (@typeInfo(@TypeOf(root.main)).Fn.calling_convention != .C) { | 37 | if (builtin.os.tag == .windows and !@hasDecl(root, "_DllMainCRTStartup")) { |
| 27 | @export(main, .{ .name = "main", .linkage = .Weak }); | 38 | @export(_DllMainCRTStartup, .{ .name = "_DllMainCRTStartup" }); |
| 28 | } | 39 | } |
| 29 | } else if (builtin.os.tag == .windows) { | 40 | } else if (builtin.output_mode == .Exe or @hasDecl(root, "main")) { |
| 30 | if (!@hasDecl(root, "WinMain") and !@hasDecl(root, "WinMainCRTStartup") and | 41 | if (builtin.link_libc and @hasDecl(root, "main")) { |
| 31 | !@hasDecl(root, "wWinMain") and !@hasDecl(root, "wWinMainCRTStartup")) | 42 | if (@typeInfo(@TypeOf(root.main)).Fn.calling_convention != .C) { |
| 32 | { | 43 | @export(main, .{ .name = "main", .linkage = .Weak }); |
| 33 | @export(WinStartup, .{ .name = "wWinMainCRTStartup" }); | 44 | } |
| 34 | } else if (@hasDecl(root, "WinMain") and !@hasDecl(root, "WinMainCRTStartup") and | 45 | } else if (builtin.os.tag == .windows) { |
| 35 | !@hasDecl(root, "wWinMain") and !@hasDecl(root, "wWinMainCRTStartup")) | 46 | if (!@hasDecl(root, "WinMain") and !@hasDecl(root, "WinMainCRTStartup") and |
| 36 | { | 47 | !@hasDecl(root, "wWinMain") and !@hasDecl(root, "wWinMainCRTStartup")) |
| 37 | @compileError("WinMain not supported; declare wWinMain or main instead"); | 48 | { |
| 38 | } else if (@hasDecl(root, "wWinMain") and !@hasDecl(root, "wWinMainCRTStartup") and | 49 | @export(WinStartup, .{ .name = "wWinMainCRTStartup" }); |
| 39 | !@hasDecl(root, "WinMain") and !@hasDecl(root, "WinMainCRTStartup")) | 50 | } else if (@hasDecl(root, "WinMain") and !@hasDecl(root, "WinMainCRTStartup") and |
| 40 | { | 51 | !@hasDecl(root, "wWinMain") and !@hasDecl(root, "wWinMainCRTStartup")) |
| 41 | @export(wWinMainCRTStartup, .{ .name = "wWinMainCRTStartup" }); | 52 | { |
| 53 | @compileError("WinMain not supported; declare wWinMain or main instead"); | ||
| 54 | } else if (@hasDecl(root, "wWinMain") and !@hasDecl(root, "wWinMainCRTStartup") and | ||
| 55 | !@hasDecl(root, "WinMain") and !@hasDecl(root, "WinMainCRTStartup")) | ||
| 56 | { | ||
| 57 | @export(wWinMainCRTStartup, .{ .name = "wWinMainCRTStartup" }); | ||
| 58 | } | ||
| 59 | } else if (builtin.os.tag == .uefi) { | ||
| 60 | if (!@hasDecl(root, "EfiMain")) @export(EfiMain, .{ .name = "EfiMain" }); | ||
| 61 | } else if (builtin.arch.isWasm() and builtin.os.tag == .freestanding) { | ||
| 62 | if (!@hasDecl(root, start_sym_name)) @export(wasm_freestanding_start, .{ .name = start_sym_name }); | ||
| 63 | } else if (builtin.os.tag != .other and builtin.os.tag != .freestanding) { | ||
| 64 | if (!@hasDecl(root, start_sym_name)) @export(_start, .{ .name = start_sym_name }); | ||
| 42 | } | 65 | } |
| 43 | } else if (builtin.os.tag == .uefi) { | ||
| 44 | if (!@hasDecl(root, "EfiMain")) @export(EfiMain, .{ .name = "EfiMain" }); | ||
| 45 | } else if (builtin.arch.isWasm() and builtin.os.tag == .freestanding) { | ||
| 46 | if (!@hasDecl(root, start_sym_name)) @export(wasm_freestanding_start, .{ .name = start_sym_name }); | ||
| 47 | } else if (builtin.os.tag != .other and builtin.os.tag != .freestanding) { | ||
| 48 | if (!@hasDecl(root, start_sym_name)) @export(_start, .{ .name = start_sym_name }); | ||
| 49 | } | 66 | } |
| 50 | } | 67 | } |
| 51 | } | 68 | } |
| 52 | 69 | ||
| 70 | // Simplified start code for stage2 until it supports more language features /// | ||
| 71 | |||
| 72 | fn main2() callconv(.C) c_int { | ||
| 73 | root.main(); | ||
| 74 | return 0; | ||
| 75 | } | ||
| 76 | |||
| 77 | fn _start2() callconv(.Naked) noreturn { | ||
| 78 | root.main(); | ||
| 79 | exit2(0); | ||
| 80 | } | ||
| 81 | |||
| 82 | fn exit2(code: u8) noreturn { | ||
| 83 | switch (builtin.arch) { | ||
| 84 | .x86_64 => { | ||
| 85 | asm volatile ("syscall" | ||
| 86 | : | ||
| 87 | : [number] "{rax}" (231), | ||
| 88 | [arg1] "{rdi}" (code) | ||
| 89 | : "rcx", "r11", "memory" | ||
| 90 | ); | ||
| 91 | }, | ||
| 92 | .arm => { | ||
| 93 | asm volatile ("svc #0" | ||
| 94 | : | ||
| 95 | : [number] "{r7}" (1), | ||
| 96 | [arg1] "{r0}" (code) | ||
| 97 | : "memory" | ||
| 98 | ); | ||
| 99 | }, | ||
| 100 | .aarch64 => { | ||
| 101 | asm volatile ("svc #0" | ||
| 102 | : | ||
| 103 | : [number] "{x8}" (93), | ||
| 104 | [arg1] "{x0}" (code) | ||
| 105 | : "memory", "cc" | ||
| 106 | ); | ||
| 107 | }, | ||
| 108 | else => @compileError("TODO"), | ||
| 109 | } | ||
| 110 | unreachable; | ||
| 111 | } | ||
| 112 | |||
| 113 | //////////////////////////////////////////////////////////////////////////////// | ||
| 114 | |||
| 53 | fn _DllMainCRTStartup( | 115 | fn _DllMainCRTStartup( |
| 54 | hinstDLL: std.os.windows.HINSTANCE, | 116 | hinstDLL: std.os.windows.HINSTANCE, |
| 55 | fdwReason: std.os.windows.DWORD, | 117 | fdwReason: std.os.windows.DWORD, |
lib/std/std.zig+1-1| ... | @@ -92,7 +92,7 @@ pub const zig = @import("zig.zig"); | ... | @@ -92,7 +92,7 @@ pub const zig = @import("zig.zig"); |
| 92 | pub const start = @import("start.zig"); | 92 | pub const start = @import("start.zig"); |
| 93 | 93 | ||
| 94 | // This forces the start.zig file to be imported, and the comptime logic inside that | 94 | // This forces the start.zig file to be imported, and the comptime logic inside that |
| 95 | // file decides whether to export any appropriate start symbols. | 95 | // file decides whether to export any appropriate start symbols, and call main. |
| 96 | comptime { | 96 | comptime { |
| 97 | _ = start; | 97 | _ = start; |
| 98 | } | 98 | } |
lib/std/zig.zig+11-8| ... | @@ -18,16 +18,19 @@ pub const CrossTarget = @import("zig/cross_target.zig").CrossTarget; | ... | @@ -18,16 +18,19 @@ pub const CrossTarget = @import("zig/cross_target.zig").CrossTarget; |
| 18 | 18 | ||
| 19 | pub const SrcHash = [16]u8; | 19 | pub const SrcHash = [16]u8; |
| 20 | 20 | ||
| 21 | /// If the source is small enough, it is used directly as the hash. | ||
| 22 | /// If it is long, blake3 hash is computed. | ||
| 23 | pub fn hashSrc(src: []const u8) SrcHash { | 21 | pub fn hashSrc(src: []const u8) SrcHash { |
| 24 | var out: SrcHash = undefined; | 22 | var out: SrcHash = undefined; |
| 25 | if (src.len <= @typeInfo(SrcHash).Array.len) { | 23 | std.crypto.hash.Blake3.hash(src, &out, .{}); |
| 26 | std.mem.copy(u8, &out, src); | 24 | return out; |
| 27 | std.mem.set(u8, out[src.len..], 0); | 25 | } |
| 28 | } else { | 26 | |
| 29 | std.crypto.hash.Blake3.hash(src, &out, .{}); | 27 | pub fn hashName(parent_hash: SrcHash, sep: []const u8, name: []const u8) SrcHash { |
| 30 | } | 28 | var out: SrcHash = undefined; |
| 29 | var hasher = std.crypto.hash.Blake3.init(.{}); | ||
| 30 | hasher.update(&parent_hash); | ||
| 31 | hasher.update(sep); | ||
| 32 | hasher.update(name); | ||
| 33 | hasher.final(&out); | ||
| 31 | return out; | 34 | return out; |
| 32 | } | 35 | } |
| 33 | 36 |
src/AstGen.zig+61-5| ... | @@ -823,7 +823,31 @@ pub fn structInitExpr( | ... | @@ -823,7 +823,31 @@ pub fn structInitExpr( |
| 823 | .none, .none_or_ref => return mod.failNode(scope, node, "TODO implement structInitExpr none", .{}), | 823 | .none, .none_or_ref => return mod.failNode(scope, node, "TODO implement structInitExpr none", .{}), |
| 824 | .ref => unreachable, // struct literal not valid as l-value | 824 | .ref => unreachable, // struct literal not valid as l-value |
| 825 | .ty => |ty_inst| { | 825 | .ty => |ty_inst| { |
| 826 | return mod.failNode(scope, node, "TODO implement structInitExpr ty", .{}); | 826 | const fields_list = try gpa.alloc(zir.Inst.StructInit.Item, struct_init.ast.fields.len); |
| 827 | defer gpa.free(fields_list); | ||
| 828 | |||
| 829 | for (struct_init.ast.fields) |field_init, i| { | ||
| 830 | const name_token = tree.firstToken(field_init) - 2; | ||
| 831 | const str_index = try gz.identAsString(name_token); | ||
| 832 | |||
| 833 | const field_ty_inst = try gz.addPlNode(.field_type, field_init, zir.Inst.FieldType{ | ||
| 834 | .container_type = ty_inst, | ||
| 835 | .name_start = str_index, | ||
| 836 | }); | ||
| 837 | fields_list[i] = .{ | ||
| 838 | .field_type = astgen.refToIndex(field_ty_inst).?, | ||
| 839 | .init = try expr(gz, scope, .{ .ty = field_ty_inst }, field_init), | ||
| 840 | }; | ||
| 841 | } | ||
| 842 | const init_inst = try gz.addPlNode(.struct_init, node, zir.Inst.StructInit{ | ||
| 843 | .fields_len = @intCast(u32, fields_list.len), | ||
| 844 | }); | ||
| 845 | try astgen.extra.ensureCapacity(gpa, astgen.extra.items.len + | ||
| 846 | fields_list.len * @typeInfo(zir.Inst.StructInit.Item).Struct.fields.len); | ||
| 847 | for (fields_list) |field| { | ||
| 848 | _ = gz.astgen.addExtraAssumeCapacity(field); | ||
| 849 | } | ||
| 850 | return rvalue(gz, scope, rl, init_inst, node); | ||
| 827 | }, | 851 | }, |
| 828 | .ptr => |ptr_inst| { | 852 | .ptr => |ptr_inst| { |
| 829 | const field_ptr_list = try gpa.alloc(zir.Inst.Index, struct_init.ast.fields.len); | 853 | const field_ptr_list = try gpa.alloc(zir.Inst.Index, struct_init.ast.fields.len); |
| ... | @@ -1245,6 +1269,7 @@ fn blockExprStmts( | ... | @@ -1245,6 +1269,7 @@ fn blockExprStmts( |
| 1245 | .fn_type_var_args, | 1269 | .fn_type_var_args, |
| 1246 | .fn_type_cc, | 1270 | .fn_type_cc, |
| 1247 | .fn_type_cc_var_args, | 1271 | .fn_type_cc_var_args, |
| 1272 | .has_decl, | ||
| 1248 | .int, | 1273 | .int, |
| 1249 | .float, | 1274 | .float, |
| 1250 | .float128, | 1275 | .float128, |
| ... | @@ -1320,6 +1345,8 @@ fn blockExprStmts( | ... | @@ -1320,6 +1345,8 @@ fn blockExprStmts( |
| 1320 | .switch_capture_else, | 1345 | .switch_capture_else, |
| 1321 | .switch_capture_else_ref, | 1346 | .switch_capture_else_ref, |
| 1322 | .struct_init_empty, | 1347 | .struct_init_empty, |
| 1348 | .struct_init, | ||
| 1349 | .field_type, | ||
| 1323 | .struct_decl, | 1350 | .struct_decl, |
| 1324 | .struct_decl_packed, | 1351 | .struct_decl_packed, |
| 1325 | .struct_decl_extern, | 1352 | .struct_decl_extern, |
| ... | @@ -1329,6 +1356,7 @@ fn blockExprStmts( | ... | @@ -1329,6 +1356,7 @@ fn blockExprStmts( |
| 1329 | .opaque_decl, | 1356 | .opaque_decl, |
| 1330 | .int_to_enum, | 1357 | .int_to_enum, |
| 1331 | .enum_to_int, | 1358 | .enum_to_int, |
| 1359 | .type_info, | ||
| 1332 | => break :b false, | 1360 | => break :b false, |
| 1333 | 1361 | ||
| 1334 | // ZIR instructions that are always either `noreturn` or `void`. | 1362 | // ZIR instructions that are always either `noreturn` or `void`. |
| ... | @@ -1336,6 +1364,7 @@ fn blockExprStmts( | ... | @@ -1336,6 +1364,7 @@ fn blockExprStmts( |
| 1336 | .dbg_stmt_node, | 1364 | .dbg_stmt_node, |
| 1337 | .ensure_result_used, | 1365 | .ensure_result_used, |
| 1338 | .ensure_result_non_error, | 1366 | .ensure_result_non_error, |
| 1367 | .@"export", | ||
| 1339 | .set_eval_branch_quota, | 1368 | .set_eval_branch_quota, |
| 1340 | .compile_log, | 1369 | .compile_log, |
| 1341 | .ensure_err_payload_void, | 1370 | .ensure_err_payload_void, |
| ... | @@ -2347,7 +2376,7 @@ fn arrayAccess( | ... | @@ -2347,7 +2376,7 @@ fn arrayAccess( |
| 2347 | ), | 2376 | ), |
| 2348 | else => return rvalue(gz, scope, rl, try gz.addBin( | 2377 | else => return rvalue(gz, scope, rl, try gz.addBin( |
| 2349 | .elem_val, | 2378 | .elem_val, |
| 2350 | try expr(gz, scope, .none, node_datas[node].lhs), | 2379 | try expr(gz, scope, .none_or_ref, node_datas[node].lhs), |
| 2351 | try expr(gz, scope, .{ .ty = .usize_type }, node_datas[node].rhs), | 2380 | try expr(gz, scope, .{ .ty = .usize_type }, node_datas[node].rhs), |
| 2352 | ), node), | 2381 | ), node), |
| 2353 | } | 2382 | } |
| ... | @@ -4146,6 +4175,36 @@ fn builtinCall( | ... | @@ -4146,6 +4175,36 @@ fn builtinCall( |
| 4146 | return rvalue(gz, scope, rl, result, node); | 4175 | return rvalue(gz, scope, rl, result, node); |
| 4147 | }, | 4176 | }, |
| 4148 | 4177 | ||
| 4178 | .@"export" => { | ||
| 4179 | // TODO: @export is supposed to be able to export things other than functions. | ||
| 4180 | // Instead of `comptimeExpr` here we need `decl_ref`. | ||
| 4181 | const fn_to_export = try comptimeExpr(gz, scope, .none, params[0]); | ||
| 4182 | // TODO: the second parameter here is supposed to be | ||
| 4183 | // `std.builtin.ExportOptions`, not a string. | ||
| 4184 | const export_name = try comptimeExpr(gz, scope, .{ .ty = .const_slice_u8_type }, params[1]); | ||
| 4185 | _ = try gz.addPlNode(.@"export", node, zir.Inst.Bin{ | ||
| 4186 | .lhs = fn_to_export, | ||
| 4187 | .rhs = export_name, | ||
| 4188 | }); | ||
| 4189 | return rvalue(gz, scope, rl, .void_value, node); | ||
| 4190 | }, | ||
| 4191 | |||
| 4192 | .has_decl => { | ||
| 4193 | const container_type = try typeExpr(gz, scope, params[0]); | ||
| 4194 | const name = try comptimeExpr(gz, scope, .{ .ty = .const_slice_u8_type }, params[1]); | ||
| 4195 | const result = try gz.addPlNode(.has_decl, node, zir.Inst.Bin{ | ||
| 4196 | .lhs = container_type, | ||
| 4197 | .rhs = name, | ||
| 4198 | }); | ||
| 4199 | return rvalue(gz, scope, rl, result, node); | ||
| 4200 | }, | ||
| 4201 | |||
| 4202 | .type_info => { | ||
| 4203 | const operand = try typeExpr(gz, scope, params[0]); | ||
| 4204 | const result = try gz.addUnNode(.type_info, operand, node); | ||
| 4205 | return rvalue(gz, scope, rl, result, node); | ||
| 4206 | }, | ||
| 4207 | |||
| 4149 | .add_with_overflow, | 4208 | .add_with_overflow, |
| 4150 | .align_cast, | 4209 | .align_cast, |
| 4151 | .align_of, | 4210 | .align_of, |
| ... | @@ -4175,11 +4234,9 @@ fn builtinCall( | ... | @@ -4175,11 +4234,9 @@ fn builtinCall( |
| 4175 | .error_name, | 4234 | .error_name, |
| 4176 | .error_return_trace, | 4235 | .error_return_trace, |
| 4177 | .err_set_cast, | 4236 | .err_set_cast, |
| 4178 | .@"export", | ||
| 4179 | .fence, | 4237 | .fence, |
| 4180 | .field_parent_ptr, | 4238 | .field_parent_ptr, |
| 4181 | .float_to_int, | 4239 | .float_to_int, |
| 4182 | .has_decl, | ||
| 4183 | .has_field, | 4240 | .has_field, |
| 4184 | .int_to_float, | 4241 | .int_to_float, |
| 4185 | .int_to_ptr, | 4242 | .int_to_ptr, |
| ... | @@ -4224,7 +4281,6 @@ fn builtinCall( | ... | @@ -4224,7 +4281,6 @@ fn builtinCall( |
| 4224 | .This, | 4281 | .This, |
| 4225 | .truncate, | 4282 | .truncate, |
| 4226 | .Type, | 4283 | .Type, |
| 4227 | .type_info, | ||
| 4228 | .type_name, | 4284 | .type_name, |
| 4229 | .union_init, | 4285 | .union_init, |
| 4230 | => return mod.failNode(scope, node, "TODO: implement builtin function {s}", .{ | 4286 | => return mod.failNode(scope, node, "TODO: implement builtin function {s}", .{ |
src/Compilation.zig+55-36| ... | @@ -932,38 +932,56 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation { | ... | @@ -932,38 +932,56 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation { |
| 932 | artifact_sub_dir, | 932 | artifact_sub_dir, |
| 933 | }; | 933 | }; |
| 934 | 934 | ||
| 935 | // TODO when we implement serialization and deserialization of incremental compilation metadata, | 935 | // If we rely on stage1, we must not redundantly add these packages. |
| 936 | // this is where we would load it. We have open a handle to the directory where | 936 | const use_stage1 = build_options.is_stage1 and use_llvm; |
| 937 | // the output either already is, or will be. | 937 | if (!use_stage1) { |
| 938 | const builtin_pkg = try Package.createWithDir( | ||
| 939 | gpa, | ||
| 940 | zig_cache_artifact_directory, | ||
| 941 | null, | ||
| 942 | "builtin.zig", | ||
| 943 | ); | ||
| 944 | errdefer builtin_pkg.destroy(gpa); | ||
| 945 | |||
| 946 | const std_pkg = try Package.createWithDir( | ||
| 947 | gpa, | ||
| 948 | options.zig_lib_directory, | ||
| 949 | "std", | ||
| 950 | "std.zig", | ||
| 951 | ); | ||
| 952 | errdefer std_pkg.destroy(gpa); | ||
| 953 | |||
| 954 | try root_pkg.addAndAdopt(gpa, "builtin", builtin_pkg); | ||
| 955 | try root_pkg.add(gpa, "root", root_pkg); | ||
| 956 | try root_pkg.addAndAdopt(gpa, "std", std_pkg); | ||
| 957 | |||
| 958 | try std_pkg.add(gpa, "builtin", builtin_pkg); | ||
| 959 | try std_pkg.add(gpa, "root", root_pkg); | ||
| 960 | } | ||
| 961 | |||
| 962 | // TODO when we implement serialization and deserialization of incremental | ||
| 963 | // compilation metadata, this is where we would load it. We have open a handle | ||
| 964 | // to the directory where the output either already is, or will be. | ||
| 938 | // However we currently do not have serialization of such metadata, so for now | 965 | // However we currently do not have serialization of such metadata, so for now |
| 939 | // we set up an empty Module that does the entire compilation fresh. | 966 | // we set up an empty Module that does the entire compilation fresh. |
| 940 | 967 | ||
| 941 | const root_scope = rs: { | 968 | const root_scope = try gpa.create(Module.Scope.File); |
| 942 | if (mem.endsWith(u8, root_pkg.root_src_path, ".zig")) { | 969 | errdefer gpa.destroy(root_scope); |
| 943 | const root_scope = try gpa.create(Module.Scope.File); | 970 | |
| 944 | const struct_ty = try Type.Tag.empty_struct.create( | 971 | const struct_ty = try Type.Tag.empty_struct.create(gpa, &root_scope.root_container); |
| 945 | gpa, | 972 | root_scope.* = .{ |
| 946 | &root_scope.root_container, | 973 | // TODO this is duped so it can be freed in Container.deinit |
| 947 | ); | 974 | .sub_file_path = try gpa.dupe(u8, root_pkg.root_src_path), |
| 948 | root_scope.* = .{ | 975 | .source = .{ .unloaded = {} }, |
| 949 | // TODO this is duped so it can be freed in Container.deinit | 976 | .tree = undefined, |
| 950 | .sub_file_path = try gpa.dupe(u8, root_pkg.root_src_path), | 977 | .status = .never_loaded, |
| 951 | .source = .{ .unloaded = {} }, | 978 | .pkg = root_pkg, |
| 952 | .tree = undefined, | 979 | .root_container = .{ |
| 953 | .status = .never_loaded, | 980 | .file_scope = root_scope, |
| 954 | .pkg = root_pkg, | 981 | .decls = .{}, |
| 955 | .root_container = .{ | 982 | .ty = struct_ty, |
| 956 | .file_scope = root_scope, | 983 | .parent_name_hash = root_pkg.namespace_hash, |
| 957 | .decls = .{}, | 984 | }, |
| 958 | .ty = struct_ty, | ||
| 959 | }, | ||
| 960 | }; | ||
| 961 | break :rs root_scope; | ||
| 962 | } else if (mem.endsWith(u8, root_pkg.root_src_path, ".zir")) { | ||
| 963 | return error.ZirFilesUnsupported; | ||
| 964 | } else { | ||
| 965 | unreachable; | ||
| 966 | } | ||
| 967 | }; | 985 | }; |
| 968 | 986 | ||
| 969 | const module = try arena.create(Module); | 987 | const module = try arena.create(Module); |
| ... | @@ -1365,7 +1383,8 @@ pub fn update(self: *Compilation) !void { | ... | @@ -1365,7 +1383,8 @@ pub fn update(self: *Compilation) !void { |
| 1365 | self.c_object_work_queue.writeItemAssumeCapacity(entry.key); | 1383 | self.c_object_work_queue.writeItemAssumeCapacity(entry.key); |
| 1366 | } | 1384 | } |
| 1367 | 1385 | ||
| 1368 | const use_stage1 = build_options.omit_stage2 or build_options.is_stage1 and self.bin_file.options.use_llvm; | 1386 | const use_stage1 = build_options.omit_stage2 or |
| 1387 | (build_options.is_stage1 and self.bin_file.options.use_llvm); | ||
| 1369 | if (!use_stage1) { | 1388 | if (!use_stage1) { |
| 1370 | if (self.bin_file.options.module) |module| { | 1389 | if (self.bin_file.options.module) |module| { |
| 1371 | module.compile_log_text.shrinkAndFree(module.gpa, 0); | 1390 | module.compile_log_text.shrinkAndFree(module.gpa, 0); |
| ... | @@ -2490,7 +2509,7 @@ pub fn addCCArgs( | ... | @@ -2490,7 +2509,7 @@ pub fn addCCArgs( |
| 2490 | try argv.append("-fPIC"); | 2509 | try argv.append("-fPIC"); |
| 2491 | } | 2510 | } |
| 2492 | }, | 2511 | }, |
| 2493 | .shared_library, .assembly, .ll, .bc, .unknown, .static_library, .object, .zig, .zir => {}, | 2512 | .shared_library, .assembly, .ll, .bc, .unknown, .static_library, .object, .zig => {}, |
| 2494 | } | 2513 | } |
| 2495 | if (out_dep_path) |p| { | 2514 | if (out_dep_path) |p| { |
| 2496 | try argv.appendSlice(&[_][]const u8{ "-MD", "-MV", "-MF", p }); | 2515 | try argv.appendSlice(&[_][]const u8{ "-MD", "-MV", "-MF", p }); |
| ... | @@ -2564,7 +2583,6 @@ pub const FileExt = enum { | ... | @@ -2564,7 +2583,6 @@ pub const FileExt = enum { |
| 2564 | object, | 2583 | object, |
| 2565 | static_library, | 2584 | static_library, |
| 2566 | zig, | 2585 | zig, |
| 2567 | zir, | ||
| 2568 | unknown, | 2586 | unknown, |
| 2569 | 2587 | ||
| 2570 | pub fn clangSupportsDepFile(ext: FileExt) bool { | 2588 | pub fn clangSupportsDepFile(ext: FileExt) bool { |
| ... | @@ -2578,7 +2596,6 @@ pub const FileExt = enum { | ... | @@ -2578,7 +2596,6 @@ pub const FileExt = enum { |
| 2578 | .object, | 2596 | .object, |
| 2579 | .static_library, | 2597 | .static_library, |
| 2580 | .zig, | 2598 | .zig, |
| 2581 | .zir, | ||
| 2582 | .unknown, | 2599 | .unknown, |
| 2583 | => false, | 2600 | => false, |
| 2584 | }; | 2601 | }; |
| ... | @@ -2650,8 +2667,6 @@ pub fn classifyFileExt(filename: []const u8) FileExt { | ... | @@ -2650,8 +2667,6 @@ pub fn classifyFileExt(filename: []const u8) FileExt { |
| 2650 | return .h; | 2667 | return .h; |
| 2651 | } else if (mem.endsWith(u8, filename, ".zig")) { | 2668 | } else if (mem.endsWith(u8, filename, ".zig")) { |
| 2652 | return .zig; | 2669 | return .zig; |
| 2653 | } else if (mem.endsWith(u8, filename, ".zir")) { | ||
| 2654 | return .zir; | ||
| 2655 | } else if (hasSharedLibraryExt(filename)) { | 2670 | } else if (hasSharedLibraryExt(filename)) { |
| 2656 | return .shared_library; | 2671 | return .shared_library; |
| 2657 | } else if (hasStaticLibraryExt(filename)) { | 2672 | } else if (hasStaticLibraryExt(filename)) { |
| ... | @@ -2672,7 +2687,6 @@ test "classifyFileExt" { | ... | @@ -2672,7 +2687,6 @@ test "classifyFileExt" { |
| 2672 | std.testing.expectEqual(FileExt.shared_library, classifyFileExt("foo.so.1.2.3")); | 2687 | std.testing.expectEqual(FileExt.shared_library, classifyFileExt("foo.so.1.2.3")); |
| 2673 | std.testing.expectEqual(FileExt.unknown, classifyFileExt("foo.so.1.2.3~")); | 2688 | std.testing.expectEqual(FileExt.unknown, classifyFileExt("foo.so.1.2.3~")); |
| 2674 | std.testing.expectEqual(FileExt.zig, classifyFileExt("foo.zig")); | 2689 | std.testing.expectEqual(FileExt.zig, classifyFileExt("foo.zig")); |
| 2675 | std.testing.expectEqual(FileExt.zir, classifyFileExt("foo.zir")); | ||
| 2676 | } | 2690 | } |
| 2677 | 2691 | ||
| 2678 | fn haveFramePointer(comp: *const Compilation) bool { | 2692 | fn haveFramePointer(comp: *const Compilation) bool { |
| ... | @@ -2867,6 +2881,8 @@ pub fn generateBuiltinZigSource(comp: *Compilation, allocator: *Allocator) ![]u8 | ... | @@ -2867,6 +2881,8 @@ pub fn generateBuiltinZigSource(comp: *Compilation, allocator: *Allocator) ![]u8 |
| 2867 | 2881 | ||
| 2868 | const target = comp.getTarget(); | 2882 | const target = comp.getTarget(); |
| 2869 | const generic_arch_name = target.cpu.arch.genericName(); | 2883 | const generic_arch_name = target.cpu.arch.genericName(); |
| 2884 | const use_stage1 = build_options.omit_stage2 or | ||
| 2885 | (build_options.is_stage1 and comp.bin_file.options.use_llvm); | ||
| 2870 | 2886 | ||
| 2871 | @setEvalBranchQuota(4000); | 2887 | @setEvalBranchQuota(4000); |
| 2872 | try buffer.writer().print( | 2888 | try buffer.writer().print( |
| ... | @@ -2879,6 +2895,7 @@ pub fn generateBuiltinZigSource(comp: *Compilation, allocator: *Allocator) ![]u8 | ... | @@ -2879,6 +2895,7 @@ pub fn generateBuiltinZigSource(comp: *Compilation, allocator: *Allocator) ![]u8 |
| 2879 | \\/// Zig version. When writing code that supports multiple versions of Zig, prefer | 2895 | \\/// Zig version. When writing code that supports multiple versions of Zig, prefer |
| 2880 | \\/// feature detection (i.e. with `@hasDecl` or `@hasField`) over version checks. | 2896 | \\/// feature detection (i.e. with `@hasDecl` or `@hasField`) over version checks. |
| 2881 | \\pub const zig_version = try @import("std").SemanticVersion.parse("{s}"); | 2897 | \\pub const zig_version = try @import("std").SemanticVersion.parse("{s}"); |
| 2898 | \\pub const zig_is_stage2 = {}; | ||
| 2882 | \\ | 2899 | \\ |
| 2883 | \\pub const output_mode = OutputMode.{}; | 2900 | \\pub const output_mode = OutputMode.{}; |
| 2884 | \\pub const link_mode = LinkMode.{}; | 2901 | \\pub const link_mode = LinkMode.{}; |
| ... | @@ -2892,6 +2909,7 @@ pub fn generateBuiltinZigSource(comp: *Compilation, allocator: *Allocator) ![]u8 | ... | @@ -2892,6 +2909,7 @@ pub fn generateBuiltinZigSource(comp: *Compilation, allocator: *Allocator) ![]u8 |
| 2892 | \\ | 2909 | \\ |
| 2893 | , .{ | 2910 | , .{ |
| 2894 | build_options.version, | 2911 | build_options.version, |
| 2912 | !use_stage1, | ||
| 2895 | std.zig.fmtId(@tagName(comp.bin_file.options.output_mode)), | 2913 | std.zig.fmtId(@tagName(comp.bin_file.options.output_mode)), |
| 2896 | std.zig.fmtId(@tagName(comp.bin_file.options.link_mode)), | 2914 | std.zig.fmtId(@tagName(comp.bin_file.options.link_mode)), |
| 2897 | comp.bin_file.options.is_test, | 2915 | comp.bin_file.options.is_test, |
| ... | @@ -3101,6 +3119,7 @@ fn buildOutputFromZig( | ... | @@ -3101,6 +3119,7 @@ fn buildOutputFromZig( |
| 3101 | .handle = special_dir, | 3119 | .handle = special_dir, |
| 3102 | }, | 3120 | }, |
| 3103 | .root_src_path = src_basename, | 3121 | .root_src_path = src_basename, |
| 3122 | .namespace_hash = Package.root_namespace_hash, | ||
| 3104 | }; | 3123 | }; |
| 3105 | const root_name = src_basename[0 .. src_basename.len - std.fs.path.extension(src_basename).len]; | 3124 | const root_name = src_basename[0 .. src_basename.len - std.fs.path.extension(src_basename).len]; |
| 3106 | const target = comp.getTarget(); | 3125 | const target = comp.getTarget(); |
src/Module.zig+68-90| ... | @@ -150,9 +150,15 @@ pub const Decl = struct { | ... | @@ -150,9 +150,15 @@ pub const Decl = struct { |
| 150 | /// The direct parent container of the Decl. | 150 | /// The direct parent container of the Decl. |
| 151 | /// Reference to externally owned memory. | 151 | /// Reference to externally owned memory. |
| 152 | container: *Scope.Container, | 152 | container: *Scope.Container, |
| 153 | /// The AST Node decl index or ZIR Inst index that contains this declaration. | 153 | |
| 154 | /// An integer that can be checked against the corresponding incrementing | ||
| 155 | /// generation field of Module. This is used to determine whether `complete` status | ||
| 156 | /// represents pre- or post- re-analysis. | ||
| 157 | generation: u32, | ||
| 158 | /// The AST Node index or ZIR Inst index that contains this declaration. | ||
| 154 | /// Must be recomputed when the corresponding source file is modified. | 159 | /// Must be recomputed when the corresponding source file is modified. |
| 155 | src_index: usize, | 160 | src_node: ast.Node.Index, |
| 161 | |||
| 156 | /// The most recent value of the Decl after a successful semantic analysis. | 162 | /// The most recent value of the Decl after a successful semantic analysis. |
| 157 | typed_value: union(enum) { | 163 | typed_value: union(enum) { |
| 158 | never_succeeded: void, | 164 | never_succeeded: void, |
| ... | @@ -198,11 +204,6 @@ pub const Decl = struct { | ... | @@ -198,11 +204,6 @@ pub const Decl = struct { |
| 198 | /// Whether the corresponding AST decl has a `pub` keyword. | 204 | /// Whether the corresponding AST decl has a `pub` keyword. |
| 199 | is_pub: bool, | 205 | is_pub: bool, |
| 200 | 206 | ||
| 201 | /// An integer that can be checked against the corresponding incrementing | ||
| 202 | /// generation field of Module. This is used to determine whether `complete` status | ||
| 203 | /// represents pre- or post- re-analysis. | ||
| 204 | generation: u32, | ||
| 205 | |||
| 206 | /// Represents the position of the code in the output file. | 207 | /// Represents the position of the code in the output file. |
| 207 | /// This is populated regardless of semantic analysis and code generation. | 208 | /// This is populated regardless of semantic analysis and code generation. |
| 208 | link: link.File.LinkBlock, | 209 | link: link.File.LinkBlock, |
| ... | @@ -249,11 +250,11 @@ pub const Decl = struct { | ... | @@ -249,11 +250,11 @@ pub const Decl = struct { |
| 249 | } | 250 | } |
| 250 | 251 | ||
| 251 | pub fn relativeToNodeIndex(decl: Decl, offset: i32) ast.Node.Index { | 252 | pub fn relativeToNodeIndex(decl: Decl, offset: i32) ast.Node.Index { |
| 252 | return @bitCast(ast.Node.Index, offset + @bitCast(i32, decl.srcNode())); | 253 | return @bitCast(ast.Node.Index, offset + @bitCast(i32, decl.src_node)); |
| 253 | } | 254 | } |
| 254 | 255 | ||
| 255 | pub fn nodeIndexToRelative(decl: Decl, node_index: ast.Node.Index) i32 { | 256 | pub fn nodeIndexToRelative(decl: Decl, node_index: ast.Node.Index) i32 { |
| 256 | return @bitCast(i32, node_index) - @bitCast(i32, decl.srcNode()); | 257 | return @bitCast(i32, node_index) - @bitCast(i32, decl.src_node); |
| 257 | } | 258 | } |
| 258 | 259 | ||
| 259 | pub fn tokSrcLoc(decl: Decl, token_index: ast.TokenIndex) LazySrcLoc { | 260 | pub fn tokSrcLoc(decl: Decl, token_index: ast.TokenIndex) LazySrcLoc { |
| ... | @@ -271,14 +272,9 @@ pub const Decl = struct { | ... | @@ -271,14 +272,9 @@ pub const Decl = struct { |
| 271 | }; | 272 | }; |
| 272 | } | 273 | } |
| 273 | 274 | ||
| 274 | pub fn srcNode(decl: Decl) u32 { | ||
| 275 | const tree = &decl.container.file_scope.tree; | ||
| 276 | return tree.rootDecls()[decl.src_index]; | ||
| 277 | } | ||
| 278 | |||
| 279 | pub fn srcToken(decl: Decl) u32 { | 275 | pub fn srcToken(decl: Decl) u32 { |
| 280 | const tree = &decl.container.file_scope.tree; | 276 | const tree = &decl.container.file_scope.tree; |
| 281 | return tree.firstToken(decl.srcNode()); | 277 | return tree.firstToken(decl.src_node); |
| 282 | } | 278 | } |
| 283 | 279 | ||
| 284 | pub fn srcByteOffset(decl: Decl) u32 { | 280 | pub fn srcByteOffset(decl: Decl) u32 { |
| ... | @@ -678,6 +674,7 @@ pub const Scope = struct { | ... | @@ -678,6 +674,7 @@ pub const Scope = struct { |
| 678 | base: Scope = Scope{ .tag = base_tag }, | 674 | base: Scope = Scope{ .tag = base_tag }, |
| 679 | 675 | ||
| 680 | file_scope: *Scope.File, | 676 | file_scope: *Scope.File, |
| 677 | parent_name_hash: NameHash, | ||
| 681 | 678 | ||
| 682 | /// Direct children of the file. | 679 | /// Direct children of the file. |
| 683 | decls: std.AutoArrayHashMapUnmanaged(*Decl, void) = .{}, | 680 | decls: std.AutoArrayHashMapUnmanaged(*Decl, void) = .{}, |
| ... | @@ -696,8 +693,7 @@ pub const Scope = struct { | ... | @@ -696,8 +693,7 @@ pub const Scope = struct { |
| 696 | } | 693 | } |
| 697 | 694 | ||
| 698 | pub fn fullyQualifiedNameHash(cont: *Container, name: []const u8) NameHash { | 695 | pub fn fullyQualifiedNameHash(cont: *Container, name: []const u8) NameHash { |
| 699 | // TODO container scope qualified names. | 696 | return std.zig.hashName(cont.parent_name_hash, ".", name); |
| 700 | return std.zig.hashSrc(name); | ||
| 701 | } | 697 | } |
| 702 | 698 | ||
| 703 | pub fn renderFullyQualifiedName(cont: Container, name: []const u8, writer: anytype) !void { | 699 | pub fn renderFullyQualifiedName(cont: Container, name: []const u8, writer: anytype) !void { |
| ... | @@ -2296,6 +2292,20 @@ pub const InnerError = error{ OutOfMemory, AnalysisFail }; | ... | @@ -2296,6 +2292,20 @@ pub const InnerError = error{ OutOfMemory, AnalysisFail }; |
| 2296 | pub fn deinit(mod: *Module) void { | 2292 | pub fn deinit(mod: *Module) void { |
| 2297 | const gpa = mod.gpa; | 2293 | const gpa = mod.gpa; |
| 2298 | 2294 | ||
| 2295 | // The callsite of `Compilation.create` owns the `root_pkg`, however | ||
| 2296 | // Module owns the builtin and std packages that it adds. | ||
| 2297 | if (mod.root_pkg.table.remove("builtin")) |entry| { | ||
| 2298 | gpa.free(entry.key); | ||
| 2299 | entry.value.destroy(gpa); | ||
| 2300 | } | ||
| 2301 | if (mod.root_pkg.table.remove("std")) |entry| { | ||
| 2302 | gpa.free(entry.key); | ||
| 2303 | entry.value.destroy(gpa); | ||
| 2304 | } | ||
| 2305 | if (mod.root_pkg.table.remove("root")) |entry| { | ||
| 2306 | gpa.free(entry.key); | ||
| 2307 | } | ||
| 2308 | |||
| 2299 | mod.compile_log_text.deinit(gpa); | 2309 | mod.compile_log_text.deinit(gpa); |
| 2300 | 2310 | ||
| 2301 | mod.zig_cache_artifact_directory.handle.close(); | 2311 | mod.zig_cache_artifact_directory.handle.close(); |
| ... | @@ -2458,7 +2468,7 @@ fn astgenAndSemaDecl(mod: *Module, decl: *Decl) !bool { | ... | @@ -2458,7 +2468,7 @@ fn astgenAndSemaDecl(mod: *Module, decl: *Decl) !bool { |
| 2458 | const tree = try mod.getAstTree(decl.container.file_scope); | 2468 | const tree = try mod.getAstTree(decl.container.file_scope); |
| 2459 | const node_tags = tree.nodes.items(.tag); | 2469 | const node_tags = tree.nodes.items(.tag); |
| 2460 | const node_datas = tree.nodes.items(.data); | 2470 | const node_datas = tree.nodes.items(.data); |
| 2461 | const decl_node = tree.rootDecls()[decl.src_index]; | 2471 | const decl_node = decl.src_node; |
| 2462 | switch (node_tags[decl_node]) { | 2472 | switch (node_tags[decl_node]) { |
| 2463 | .fn_decl => { | 2473 | .fn_decl => { |
| 2464 | const fn_proto = node_datas[decl_node].lhs; | 2474 | const fn_proto = node_datas[decl_node].lhs; |
| ... | @@ -2513,6 +2523,7 @@ fn astgenAndSemaDecl(mod: *Module, decl: *Decl) !bool { | ... | @@ -2513,6 +2523,7 @@ fn astgenAndSemaDecl(mod: *Module, decl: *Decl) !bool { |
| 2513 | 2523 | ||
| 2514 | const block_expr = node_datas[decl_node].lhs; | 2524 | const block_expr = node_datas[decl_node].lhs; |
| 2515 | _ = try AstGen.comptimeExpr(&gen_scope, &gen_scope.base, .none, block_expr); | 2525 | _ = try AstGen.comptimeExpr(&gen_scope, &gen_scope.base, .none, block_expr); |
| 2526 | _ = try gen_scope.addBreak(.break_inline, 0, .void_value); | ||
| 2516 | 2527 | ||
| 2517 | const code = try gen_scope.finish(); | 2528 | const code = try gen_scope.finish(); |
| 2518 | if (std.builtin.mode == .Debug and mod.comp.verbose_ir) { | 2529 | if (std.builtin.mode == .Debug and mod.comp.verbose_ir) { |
| ... | @@ -3294,7 +3305,7 @@ pub fn analyzeContainer(mod: *Module, container_scope: *Scope.Container) !void { | ... | @@ -3294,7 +3305,7 @@ pub fn analyzeContainer(mod: *Module, container_scope: *Scope.Container) !void { |
| 3294 | var outdated_decls = std.AutoArrayHashMap(*Decl, void).init(mod.gpa); | 3305 | var outdated_decls = std.AutoArrayHashMap(*Decl, void).init(mod.gpa); |
| 3295 | defer outdated_decls.deinit(); | 3306 | defer outdated_decls.deinit(); |
| 3296 | 3307 | ||
| 3297 | for (decls) |decl_node, decl_i| switch (node_tags[decl_node]) { | 3308 | for (decls) |decl_node| switch (node_tags[decl_node]) { |
| 3298 | .fn_decl => { | 3309 | .fn_decl => { |
| 3299 | const fn_proto = node_datas[decl_node].lhs; | 3310 | const fn_proto = node_datas[decl_node].lhs; |
| 3300 | const body = node_datas[decl_node].rhs; | 3311 | const body = node_datas[decl_node].rhs; |
| ... | @@ -3306,7 +3317,6 @@ pub fn analyzeContainer(mod: *Module, container_scope: *Scope.Container) !void { | ... | @@ -3306,7 +3317,6 @@ pub fn analyzeContainer(mod: *Module, container_scope: *Scope.Container) !void { |
| 3306 | &deleted_decls, | 3317 | &deleted_decls, |
| 3307 | &outdated_decls, | 3318 | &outdated_decls, |
| 3308 | decl_node, | 3319 | decl_node, |
| 3309 | decl_i, | ||
| 3310 | tree.*, | 3320 | tree.*, |
| 3311 | body, | 3321 | body, |
| 3312 | tree.fnProtoSimple(&params, fn_proto), | 3322 | tree.fnProtoSimple(&params, fn_proto), |
| ... | @@ -3317,7 +3327,6 @@ pub fn analyzeContainer(mod: *Module, container_scope: *Scope.Container) !void { | ... | @@ -3317,7 +3327,6 @@ pub fn analyzeContainer(mod: *Module, container_scope: *Scope.Container) !void { |
| 3317 | &deleted_decls, | 3327 | &deleted_decls, |
| 3318 | &outdated_decls, | 3328 | &outdated_decls, |
| 3319 | decl_node, | 3329 | decl_node, |
| 3320 | decl_i, | ||
| 3321 | tree.*, | 3330 | tree.*, |
| 3322 | body, | 3331 | body, |
| 3323 | tree.fnProtoMulti(fn_proto), | 3332 | tree.fnProtoMulti(fn_proto), |
| ... | @@ -3329,7 +3338,6 @@ pub fn analyzeContainer(mod: *Module, container_scope: *Scope.Container) !void { | ... | @@ -3329,7 +3338,6 @@ pub fn analyzeContainer(mod: *Module, container_scope: *Scope.Container) !void { |
| 3329 | &deleted_decls, | 3338 | &deleted_decls, |
| 3330 | &outdated_decls, | 3339 | &outdated_decls, |
| 3331 | decl_node, | 3340 | decl_node, |
| 3332 | decl_i, | ||
| 3333 | tree.*, | 3341 | tree.*, |
| 3334 | body, | 3342 | body, |
| 3335 | tree.fnProtoOne(&params, fn_proto), | 3343 | tree.fnProtoOne(&params, fn_proto), |
| ... | @@ -3340,7 +3348,6 @@ pub fn analyzeContainer(mod: *Module, container_scope: *Scope.Container) !void { | ... | @@ -3340,7 +3348,6 @@ pub fn analyzeContainer(mod: *Module, container_scope: *Scope.Container) !void { |
| 3340 | &deleted_decls, | 3348 | &deleted_decls, |
| 3341 | &outdated_decls, | 3349 | &outdated_decls, |
| 3342 | decl_node, | 3350 | decl_node, |
| 3343 | decl_i, | ||
| 3344 | tree.*, | 3351 | tree.*, |
| 3345 | body, | 3352 | body, |
| 3346 | tree.fnProto(fn_proto), | 3353 | tree.fnProto(fn_proto), |
| ... | @@ -3355,7 +3362,6 @@ pub fn analyzeContainer(mod: *Module, container_scope: *Scope.Container) !void { | ... | @@ -3355,7 +3362,6 @@ pub fn analyzeContainer(mod: *Module, container_scope: *Scope.Container) !void { |
| 3355 | &deleted_decls, | 3362 | &deleted_decls, |
| 3356 | &outdated_decls, | 3363 | &outdated_decls, |
| 3357 | decl_node, | 3364 | decl_node, |
| 3358 | decl_i, | ||
| 3359 | tree.*, | 3365 | tree.*, |
| 3360 | 0, | 3366 | 0, |
| 3361 | tree.fnProtoSimple(&params, decl_node), | 3367 | tree.fnProtoSimple(&params, decl_node), |
| ... | @@ -3366,7 +3372,6 @@ pub fn analyzeContainer(mod: *Module, container_scope: *Scope.Container) !void { | ... | @@ -3366,7 +3372,6 @@ pub fn analyzeContainer(mod: *Module, container_scope: *Scope.Container) !void { |
| 3366 | &deleted_decls, | 3372 | &deleted_decls, |
| 3367 | &outdated_decls, | 3373 | &outdated_decls, |
| 3368 | decl_node, | 3374 | decl_node, |
| 3369 | decl_i, | ||
| 3370 | tree.*, | 3375 | tree.*, |
| 3371 | 0, | 3376 | 0, |
| 3372 | tree.fnProtoMulti(decl_node), | 3377 | tree.fnProtoMulti(decl_node), |
| ... | @@ -3378,7 +3383,6 @@ pub fn analyzeContainer(mod: *Module, container_scope: *Scope.Container) !void { | ... | @@ -3378,7 +3383,6 @@ pub fn analyzeContainer(mod: *Module, container_scope: *Scope.Container) !void { |
| 3378 | &deleted_decls, | 3383 | &deleted_decls, |
| 3379 | &outdated_decls, | 3384 | &outdated_decls, |
| 3380 | decl_node, | 3385 | decl_node, |
| 3381 | decl_i, | ||
| 3382 | tree.*, | 3386 | tree.*, |
| 3383 | 0, | 3387 | 0, |
| 3384 | tree.fnProtoOne(&params, decl_node), | 3388 | tree.fnProtoOne(&params, decl_node), |
| ... | @@ -3389,7 +3393,6 @@ pub fn analyzeContainer(mod: *Module, container_scope: *Scope.Container) !void { | ... | @@ -3389,7 +3393,6 @@ pub fn analyzeContainer(mod: *Module, container_scope: *Scope.Container) !void { |
| 3389 | &deleted_decls, | 3393 | &deleted_decls, |
| 3390 | &outdated_decls, | 3394 | &outdated_decls, |
| 3391 | decl_node, | 3395 | decl_node, |
| 3392 | decl_i, | ||
| 3393 | tree.*, | 3396 | tree.*, |
| 3394 | 0, | 3397 | 0, |
| 3395 | tree.fnProto(decl_node), | 3398 | tree.fnProto(decl_node), |
| ... | @@ -3400,7 +3403,6 @@ pub fn analyzeContainer(mod: *Module, container_scope: *Scope.Container) !void { | ... | @@ -3400,7 +3403,6 @@ pub fn analyzeContainer(mod: *Module, container_scope: *Scope.Container) !void { |
| 3400 | &deleted_decls, | 3403 | &deleted_decls, |
| 3401 | &outdated_decls, | 3404 | &outdated_decls, |
| 3402 | decl_node, | 3405 | decl_node, |
| 3403 | decl_i, | ||
| 3404 | tree.*, | 3406 | tree.*, |
| 3405 | tree.globalVarDecl(decl_node), | 3407 | tree.globalVarDecl(decl_node), |
| 3406 | ), | 3408 | ), |
| ... | @@ -3409,7 +3411,6 @@ pub fn analyzeContainer(mod: *Module, container_scope: *Scope.Container) !void { | ... | @@ -3409,7 +3411,6 @@ pub fn analyzeContainer(mod: *Module, container_scope: *Scope.Container) !void { |
| 3409 | &deleted_decls, | 3411 | &deleted_decls, |
| 3410 | &outdated_decls, | 3412 | &outdated_decls, |
| 3411 | decl_node, | 3413 | decl_node, |
| 3412 | decl_i, | ||
| 3413 | tree.*, | 3414 | tree.*, |
| 3414 | tree.localVarDecl(decl_node), | 3415 | tree.localVarDecl(decl_node), |
| 3415 | ), | 3416 | ), |
| ... | @@ -3418,7 +3419,6 @@ pub fn analyzeContainer(mod: *Module, container_scope: *Scope.Container) !void { | ... | @@ -3418,7 +3419,6 @@ pub fn analyzeContainer(mod: *Module, container_scope: *Scope.Container) !void { |
| 3418 | &deleted_decls, | 3419 | &deleted_decls, |
| 3419 | &outdated_decls, | 3420 | &outdated_decls, |
| 3420 | decl_node, | 3421 | decl_node, |
| 3421 | decl_i, | ||
| 3422 | tree.*, | 3422 | tree.*, |
| 3423 | tree.simpleVarDecl(decl_node), | 3423 | tree.simpleVarDecl(decl_node), |
| 3424 | ), | 3424 | ), |
| ... | @@ -3427,7 +3427,6 @@ pub fn analyzeContainer(mod: *Module, container_scope: *Scope.Container) !void { | ... | @@ -3427,7 +3427,6 @@ pub fn analyzeContainer(mod: *Module, container_scope: *Scope.Container) !void { |
| 3427 | &deleted_decls, | 3427 | &deleted_decls, |
| 3428 | &outdated_decls, | 3428 | &outdated_decls, |
| 3429 | decl_node, | 3429 | decl_node, |
| 3430 | decl_i, | ||
| 3431 | tree.*, | 3430 | tree.*, |
| 3432 | tree.alignedVarDecl(decl_node), | 3431 | tree.alignedVarDecl(decl_node), |
| 3433 | ), | 3432 | ), |
| ... | @@ -3440,38 +3439,21 @@ pub fn analyzeContainer(mod: *Module, container_scope: *Scope.Container) !void { | ... | @@ -3440,38 +3439,21 @@ pub fn analyzeContainer(mod: *Module, container_scope: *Scope.Container) !void { |
| 3440 | const name_hash = container_scope.fullyQualifiedNameHash(name); | 3439 | const name_hash = container_scope.fullyQualifiedNameHash(name); |
| 3441 | const contents_hash = std.zig.hashSrc(tree.getNodeSource(decl_node)); | 3440 | const contents_hash = std.zig.hashSrc(tree.getNodeSource(decl_node)); |
| 3442 | 3441 | ||
| 3443 | const new_decl = try mod.createNewDecl(&container_scope.base, name, decl_i, name_hash, contents_hash); | 3442 | const new_decl = try mod.createNewDecl(&container_scope.base, name, decl_node, name_hash, contents_hash); |
| 3444 | container_scope.decls.putAssumeCapacity(new_decl, {}); | 3443 | container_scope.decls.putAssumeCapacity(new_decl, {}); |
| 3445 | mod.comp.work_queue.writeItemAssumeCapacity(.{ .analyze_decl = new_decl }); | 3444 | mod.comp.work_queue.writeItemAssumeCapacity(.{ .analyze_decl = new_decl }); |
| 3446 | }, | 3445 | }, |
| 3447 | 3446 | ||
| 3448 | .container_field_init => try mod.semaContainerField( | 3447 | // Container fields are handled in AstGen. |
| 3449 | container_scope, | 3448 | .container_field_init, |
| 3450 | &deleted_decls, | 3449 | .container_field_align, |
| 3451 | decl_node, | 3450 | .container_field, |
| 3452 | decl_i, | 3451 | => continue, |
| 3453 | tree.*, | ||
| 3454 | tree.containerFieldInit(decl_node), | ||
| 3455 | ), | ||
| 3456 | .container_field_align => try mod.semaContainerField( | ||
| 3457 | container_scope, | ||
| 3458 | &deleted_decls, | ||
| 3459 | decl_node, | ||
| 3460 | decl_i, | ||
| 3461 | tree.*, | ||
| 3462 | tree.containerFieldAlign(decl_node), | ||
| 3463 | ), | ||
| 3464 | .container_field => try mod.semaContainerField( | ||
| 3465 | container_scope, | ||
| 3466 | &deleted_decls, | ||
| 3467 | decl_node, | ||
| 3468 | decl_i, | ||
| 3469 | tree.*, | ||
| 3470 | tree.containerField(decl_node), | ||
| 3471 | ), | ||
| 3472 | 3452 | ||
| 3473 | .test_decl => { | 3453 | .test_decl => { |
| 3474 | log.err("TODO: analyze test decl", .{}); | 3454 | if (mod.comp.bin_file.options.is_test) { |
| 3455 | log.err("TODO: analyze test decl", .{}); | ||
| 3456 | } | ||
| 3475 | }, | 3457 | }, |
| 3476 | .@"usingnamespace" => { | 3458 | .@"usingnamespace" => { |
| 3477 | log.err("TODO: analyze usingnamespace decl", .{}); | 3459 | log.err("TODO: analyze usingnamespace decl", .{}); |
| ... | @@ -3508,7 +3490,6 @@ fn semaContainerFn( | ... | @@ -3508,7 +3490,6 @@ fn semaContainerFn( |
| 3508 | deleted_decls: *std.AutoArrayHashMap(*Decl, void), | 3490 | deleted_decls: *std.AutoArrayHashMap(*Decl, void), |
| 3509 | outdated_decls: *std.AutoArrayHashMap(*Decl, void), | 3491 | outdated_decls: *std.AutoArrayHashMap(*Decl, void), |
| 3510 | decl_node: ast.Node.Index, | 3492 | decl_node: ast.Node.Index, |
| 3511 | decl_i: usize, | ||
| 3512 | tree: ast.Tree, | 3493 | tree: ast.Tree, |
| 3513 | body_node: ast.Node.Index, | 3494 | body_node: ast.Node.Index, |
| 3514 | fn_proto: ast.full.FnProto, | 3495 | fn_proto: ast.full.FnProto, |
| ... | @@ -3517,24 +3498,30 @@ fn semaContainerFn( | ... | @@ -3517,24 +3498,30 @@ fn semaContainerFn( |
| 3517 | defer tracy.end(); | 3498 | defer tracy.end(); |
| 3518 | 3499 | ||
| 3519 | // We will create a Decl for it regardless of analysis status. | 3500 | // We will create a Decl for it regardless of analysis status. |
| 3520 | const name_tok = fn_proto.name_token orelse { | 3501 | const name_token = fn_proto.name_token orelse { |
| 3521 | // This problem will go away with #1717. | 3502 | // This problem will go away with #1717. |
| 3522 | @panic("TODO missing function name"); | 3503 | @panic("TODO missing function name"); |
| 3523 | }; | 3504 | }; |
| 3524 | const name = tree.tokenSlice(name_tok); // TODO use identifierTokenString | 3505 | const name = tree.tokenSlice(name_token); // TODO use identifierTokenString |
| 3525 | const name_hash = container_scope.fullyQualifiedNameHash(name); | 3506 | const name_hash = container_scope.fullyQualifiedNameHash(name); |
| 3526 | const contents_hash = std.zig.hashSrc(tree.getNodeSource(decl_node)); | 3507 | const contents_hash = std.zig.hashSrc(tree.getNodeSource(decl_node)); |
| 3527 | if (mod.decl_table.get(name_hash)) |decl| { | 3508 | if (mod.decl_table.get(name_hash)) |decl| { |
| 3528 | // Update the AST Node index of the decl, even if its contents are unchanged, it may | 3509 | // Update the AST Node index of the decl, even if its contents are unchanged, it may |
| 3529 | // have been re-ordered. | 3510 | // have been re-ordered. |
| 3530 | decl.src_index = decl_i; | 3511 | const prev_src_node = decl.src_node; |
| 3512 | decl.src_node = decl_node; | ||
| 3531 | if (deleted_decls.swapRemove(decl) == null) { | 3513 | if (deleted_decls.swapRemove(decl) == null) { |
| 3532 | decl.analysis = .sema_failure; | 3514 | decl.analysis = .sema_failure; |
| 3533 | const msg = try ErrorMsg.create(mod.gpa, .{ | 3515 | const msg = try ErrorMsg.create(mod.gpa, .{ |
| 3534 | .container = .{ .file_scope = container_scope.file_scope }, | 3516 | .container = .{ .file_scope = container_scope.file_scope }, |
| 3535 | .lazy = .{ .token_abs = name_tok }, | 3517 | .lazy = .{ .token_abs = name_token }, |
| 3536 | }, "redefinition of '{s}'", .{decl.name}); | 3518 | }, "redefinition of '{s}'", .{decl.name}); |
| 3537 | errdefer msg.destroy(mod.gpa); | 3519 | errdefer msg.destroy(mod.gpa); |
| 3520 | const other_src_loc: SrcLoc = .{ | ||
| 3521 | .container = .{ .file_scope = decl.container.file_scope }, | ||
| 3522 | .lazy = .{ .node_abs = prev_src_node }, | ||
| 3523 | }; | ||
| 3524 | try mod.errNoteNonLazy(other_src_loc, msg, "previous definition here", .{}); | ||
| 3538 | try mod.failed_decls.putNoClobber(mod.gpa, decl, msg); | 3525 | try mod.failed_decls.putNoClobber(mod.gpa, decl, msg); |
| 3539 | } else { | 3526 | } else { |
| 3540 | if (!srcHashEql(decl.contents_hash, contents_hash)) { | 3527 | if (!srcHashEql(decl.contents_hash, contents_hash)) { |
| ... | @@ -3558,7 +3545,7 @@ fn semaContainerFn( | ... | @@ -3558,7 +3545,7 @@ fn semaContainerFn( |
| 3558 | } | 3545 | } |
| 3559 | } | 3546 | } |
| 3560 | } else { | 3547 | } else { |
| 3561 | const new_decl = try mod.createNewDecl(&container_scope.base, name, decl_i, name_hash, contents_hash); | 3548 | const new_decl = try mod.createNewDecl(&container_scope.base, name, decl_node, name_hash, contents_hash); |
| 3562 | container_scope.decls.putAssumeCapacity(new_decl, {}); | 3549 | container_scope.decls.putAssumeCapacity(new_decl, {}); |
| 3563 | if (fn_proto.extern_export_token) |maybe_export_token| { | 3550 | if (fn_proto.extern_export_token) |maybe_export_token| { |
| 3564 | const token_tags = tree.tokens.items(.tag); | 3551 | const token_tags = tree.tokens.items(.tag); |
| ... | @@ -3566,6 +3553,7 @@ fn semaContainerFn( | ... | @@ -3566,6 +3553,7 @@ fn semaContainerFn( |
| 3566 | mod.comp.work_queue.writeItemAssumeCapacity(.{ .analyze_decl = new_decl }); | 3553 | mod.comp.work_queue.writeItemAssumeCapacity(.{ .analyze_decl = new_decl }); |
| 3567 | } | 3554 | } |
| 3568 | } | 3555 | } |
| 3556 | new_decl.is_pub = fn_proto.visib_token != null; | ||
| 3569 | } | 3557 | } |
| 3570 | } | 3558 | } |
| 3571 | 3559 | ||
| ... | @@ -3575,7 +3563,6 @@ fn semaContainerVar( | ... | @@ -3575,7 +3563,6 @@ fn semaContainerVar( |
| 3575 | deleted_decls: *std.AutoArrayHashMap(*Decl, void), | 3563 | deleted_decls: *std.AutoArrayHashMap(*Decl, void), |
| 3576 | outdated_decls: *std.AutoArrayHashMap(*Decl, void), | 3564 | outdated_decls: *std.AutoArrayHashMap(*Decl, void), |
| 3577 | decl_node: ast.Node.Index, | 3565 | decl_node: ast.Node.Index, |
| 3578 | decl_i: usize, | ||
| 3579 | tree: ast.Tree, | 3566 | tree: ast.Tree, |
| 3580 | var_decl: ast.full.VarDecl, | 3567 | var_decl: ast.full.VarDecl, |
| 3581 | ) !void { | 3568 | ) !void { |
| ... | @@ -3589,21 +3576,27 @@ fn semaContainerVar( | ... | @@ -3589,21 +3576,27 @@ fn semaContainerVar( |
| 3589 | if (mod.decl_table.get(name_hash)) |decl| { | 3576 | if (mod.decl_table.get(name_hash)) |decl| { |
| 3590 | // Update the AST Node index of the decl, even if its contents are unchanged, it may | 3577 | // Update the AST Node index of the decl, even if its contents are unchanged, it may |
| 3591 | // have been re-ordered. | 3578 | // have been re-ordered. |
| 3592 | decl.src_index = decl_i; | 3579 | const prev_src_node = decl.src_node; |
| 3580 | decl.src_node = decl_node; | ||
| 3593 | if (deleted_decls.swapRemove(decl) == null) { | 3581 | if (deleted_decls.swapRemove(decl) == null) { |
| 3594 | decl.analysis = .sema_failure; | 3582 | decl.analysis = .sema_failure; |
| 3595 | const err_msg = try ErrorMsg.create(mod.gpa, .{ | 3583 | const msg = try ErrorMsg.create(mod.gpa, .{ |
| 3596 | .container = .{ .file_scope = container_scope.file_scope }, | 3584 | .container = .{ .file_scope = container_scope.file_scope }, |
| 3597 | .lazy = .{ .token_abs = name_token }, | 3585 | .lazy = .{ .token_abs = name_token }, |
| 3598 | }, "redefinition of '{s}'", .{decl.name}); | 3586 | }, "redefinition of '{s}'", .{decl.name}); |
| 3599 | errdefer err_msg.destroy(mod.gpa); | 3587 | errdefer msg.destroy(mod.gpa); |
| 3600 | try mod.failed_decls.putNoClobber(mod.gpa, decl, err_msg); | 3588 | const other_src_loc: SrcLoc = .{ |
| 3589 | .container = .{ .file_scope = decl.container.file_scope }, | ||
| 3590 | .lazy = .{ .node_abs = prev_src_node }, | ||
| 3591 | }; | ||
| 3592 | try mod.errNoteNonLazy(other_src_loc, msg, "previous definition here", .{}); | ||
| 3593 | try mod.failed_decls.putNoClobber(mod.gpa, decl, msg); | ||
| 3601 | } else if (!srcHashEql(decl.contents_hash, contents_hash)) { | 3594 | } else if (!srcHashEql(decl.contents_hash, contents_hash)) { |
| 3602 | try outdated_decls.put(decl, {}); | 3595 | try outdated_decls.put(decl, {}); |
| 3603 | decl.contents_hash = contents_hash; | 3596 | decl.contents_hash = contents_hash; |
| 3604 | } | 3597 | } |
| 3605 | } else { | 3598 | } else { |
| 3606 | const new_decl = try mod.createNewDecl(&container_scope.base, name, decl_i, name_hash, contents_hash); | 3599 | const new_decl = try mod.createNewDecl(&container_scope.base, name, decl_node, name_hash, contents_hash); |
| 3607 | container_scope.decls.putAssumeCapacity(new_decl, {}); | 3600 | container_scope.decls.putAssumeCapacity(new_decl, {}); |
| 3608 | if (var_decl.extern_export_token) |maybe_export_token| { | 3601 | if (var_decl.extern_export_token) |maybe_export_token| { |
| 3609 | const token_tags = tree.tokens.items(.tag); | 3602 | const token_tags = tree.tokens.items(.tag); |
| ... | @@ -3614,21 +3607,6 @@ fn semaContainerVar( | ... | @@ -3614,21 +3607,6 @@ fn semaContainerVar( |
| 3614 | } | 3607 | } |
| 3615 | } | 3608 | } |
| 3616 | 3609 | ||
| 3617 | fn semaContainerField( | ||
| 3618 | mod: *Module, | ||
| 3619 | container_scope: *Scope.Container, | ||
| 3620 | deleted_decls: *std.AutoArrayHashMap(*Decl, void), | ||
| 3621 | decl_node: ast.Node.Index, | ||
| 3622 | decl_i: usize, | ||
| 3623 | tree: ast.Tree, | ||
| 3624 | field: ast.full.ContainerField, | ||
| 3625 | ) !void { | ||
| 3626 | const tracy = trace(@src()); | ||
| 3627 | defer tracy.end(); | ||
| 3628 | |||
| 3629 | log.err("TODO: analyze container field", .{}); | ||
| 3630 | } | ||
| 3631 | |||
| 3632 | pub fn deleteDecl( | 3610 | pub fn deleteDecl( |
| 3633 | mod: *Module, | 3611 | mod: *Module, |
| 3634 | decl: *Decl, | 3612 | decl: *Decl, |
| ... | @@ -3811,7 +3789,7 @@ fn markOutdatedDecl(mod: *Module, decl: *Decl) !void { | ... | @@ -3811,7 +3789,7 @@ fn markOutdatedDecl(mod: *Module, decl: *Decl) !void { |
| 3811 | fn allocateNewDecl( | 3789 | fn allocateNewDecl( |
| 3812 | mod: *Module, | 3790 | mod: *Module, |
| 3813 | scope: *Scope, | 3791 | scope: *Scope, |
| 3814 | src_index: usize, | 3792 | src_node: ast.Node.Index, |
| 3815 | contents_hash: std.zig.SrcHash, | 3793 | contents_hash: std.zig.SrcHash, |
| 3816 | ) !*Decl { | 3794 | ) !*Decl { |
| 3817 | // If we have emit-h then we must allocate a bigger structure to store the emit-h state. | 3795 | // If we have emit-h then we must allocate a bigger structure to store the emit-h state. |
| ... | @@ -3827,7 +3805,7 @@ fn allocateNewDecl( | ... | @@ -3827,7 +3805,7 @@ fn allocateNewDecl( |
| 3827 | new_decl.* = .{ | 3805 | new_decl.* = .{ |
| 3828 | .name = "", | 3806 | .name = "", |
| 3829 | .container = scope.namespace(), | 3807 | .container = scope.namespace(), |
| 3830 | .src_index = src_index, | 3808 | .src_node = src_node, |
| 3831 | .typed_value = .{ .never_succeeded = {} }, | 3809 | .typed_value = .{ .never_succeeded = {} }, |
| 3832 | .analysis = .unreferenced, | 3810 | .analysis = .unreferenced, |
| 3833 | .deletion_flag = false, | 3811 | .deletion_flag = false, |
| ... | @@ -3858,12 +3836,12 @@ fn createNewDecl( | ... | @@ -3858,12 +3836,12 @@ fn createNewDecl( |
| 3858 | mod: *Module, | 3836 | mod: *Module, |
| 3859 | scope: *Scope, | 3837 | scope: *Scope, |
| 3860 | decl_name: []const u8, | 3838 | decl_name: []const u8, |
| 3861 | src_index: usize, | 3839 | src_node: ast.Node.Index, |
| 3862 | name_hash: Scope.NameHash, | 3840 | name_hash: Scope.NameHash, |
| 3863 | contents_hash: std.zig.SrcHash, | 3841 | contents_hash: std.zig.SrcHash, |
| 3864 | ) !*Decl { | 3842 | ) !*Decl { |
| 3865 | try mod.decl_table.ensureCapacity(mod.gpa, mod.decl_table.items().len + 1); | 3843 | try mod.decl_table.ensureCapacity(mod.gpa, mod.decl_table.items().len + 1); |
| 3866 | const new_decl = try mod.allocateNewDecl(scope, src_index, contents_hash); | 3844 | const new_decl = try mod.allocateNewDecl(scope, src_node, contents_hash); |
| 3867 | errdefer mod.gpa.destroy(new_decl); | 3845 | errdefer mod.gpa.destroy(new_decl); |
| 3868 | new_decl.name = try mem.dupeZ(mod.gpa, u8, decl_name); | 3846 | new_decl.name = try mem.dupeZ(mod.gpa, u8, decl_name); |
| 3869 | mod.decl_table.putAssumeCapacityNoClobber(name_hash, new_decl); | 3847 | mod.decl_table.putAssumeCapacityNoClobber(name_hash, new_decl); |
| ... | @@ -4076,7 +4054,7 @@ pub fn createAnonymousDecl( | ... | @@ -4076,7 +4054,7 @@ pub fn createAnonymousDecl( |
| 4076 | defer mod.gpa.free(name); | 4054 | defer mod.gpa.free(name); |
| 4077 | const name_hash = scope.namespace().fullyQualifiedNameHash(name); | 4055 | const name_hash = scope.namespace().fullyQualifiedNameHash(name); |
| 4078 | const src_hash: std.zig.SrcHash = undefined; | 4056 | const src_hash: std.zig.SrcHash = undefined; |
| 4079 | const new_decl = try mod.createNewDecl(scope, name, scope_decl.src_index, name_hash, src_hash); | 4057 | const new_decl = try mod.createNewDecl(scope, name, scope_decl.src_node, name_hash, src_hash); |
| 4080 | const decl_arena_state = try decl_arena.allocator.create(std.heap.ArenaAllocator.State); | 4058 | const decl_arena_state = try decl_arena.allocator.create(std.heap.ArenaAllocator.State); |
| 4081 | 4059 | ||
| 4082 | decl_arena_state.* = decl_arena.state; | 4060 | decl_arena_state.* = decl_arena.state; |
| ... | @@ -4112,7 +4090,7 @@ pub fn createContainerDecl( | ... | @@ -4112,7 +4090,7 @@ pub fn createContainerDecl( |
| 4112 | defer mod.gpa.free(name); | 4090 | defer mod.gpa.free(name); |
| 4113 | const name_hash = scope.namespace().fullyQualifiedNameHash(name); | 4091 | const name_hash = scope.namespace().fullyQualifiedNameHash(name); |
| 4114 | const src_hash: std.zig.SrcHash = undefined; | 4092 | const src_hash: std.zig.SrcHash = undefined; |
| 4115 | const new_decl = try mod.createNewDecl(scope, name, scope_decl.src_index, name_hash, src_hash); | 4093 | const new_decl = try mod.createNewDecl(scope, name, scope_decl.src_node, name_hash, src_hash); |
| 4116 | const decl_arena_state = try decl_arena.allocator.create(std.heap.ArenaAllocator.State); | 4094 | const decl_arena_state = try decl_arena.allocator.create(std.heap.ArenaAllocator.State); |
| 4117 | 4095 | ||
| 4118 | decl_arena_state.* = decl_arena.state; | 4096 | decl_arena_state.* = decl_arena.state; |
src/Package.zig+68-8| ... | @@ -4,18 +4,29 @@ const std = @import("std"); | ... | @@ -4,18 +4,29 @@ const std = @import("std"); |
| 4 | const fs = std.fs; | 4 | const fs = std.fs; |
| 5 | const mem = std.mem; | 5 | const mem = std.mem; |
| 6 | const Allocator = mem.Allocator; | 6 | const Allocator = mem.Allocator; |
| 7 | const assert = std.debug.assert; | ||
| 7 | 8 | ||
| 8 | const Compilation = @import("Compilation.zig"); | 9 | const Compilation = @import("Compilation.zig"); |
| 10 | const Module = @import("Module.zig"); | ||
| 9 | 11 | ||
| 10 | pub const Table = std.StringHashMapUnmanaged(*Package); | 12 | pub const Table = std.StringHashMapUnmanaged(*Package); |
| 11 | 13 | ||
| 14 | pub const root_namespace_hash: Module.Scope.NameHash = .{ | ||
| 15 | 0, 0, 6, 6, 6, 0, 0, 0, | ||
| 16 | 6, 9, 0, 0, 0, 4, 2, 0, | ||
| 17 | }; | ||
| 18 | |||
| 12 | root_src_directory: Compilation.Directory, | 19 | root_src_directory: Compilation.Directory, |
| 13 | /// Relative to `root_src_directory`. May contain path separators. | 20 | /// Relative to `root_src_directory`. May contain path separators. |
| 14 | root_src_path: []const u8, | 21 | root_src_path: []const u8, |
| 15 | table: Table = .{}, | 22 | table: Table = .{}, |
| 16 | parent: ?*Package = null, | 23 | parent: ?*Package = null, |
| 24 | namespace_hash: Module.Scope.NameHash, | ||
| 25 | /// Whether to free `root_src_directory` on `destroy`. | ||
| 26 | root_src_directory_owned: bool = false, | ||
| 17 | 27 | ||
| 18 | /// Allocate a Package. No references to the slices passed are kept. | 28 | /// Allocate a Package. No references to the slices passed are kept. |
| 29 | /// Don't forget to set `namespace_hash` later. | ||
| 19 | pub fn create( | 30 | pub fn create( |
| 20 | gpa: *Allocator, | 31 | gpa: *Allocator, |
| 21 | /// Null indicates the current working directory | 32 | /// Null indicates the current working directory |
| ... | @@ -38,27 +49,69 @@ pub fn create( | ... | @@ -38,27 +49,69 @@ pub fn create( |
| 38 | .handle = if (owned_dir_path) |p| try fs.cwd().openDir(p, .{}) else fs.cwd(), | 49 | .handle = if (owned_dir_path) |p| try fs.cwd().openDir(p, .{}) else fs.cwd(), |
| 39 | }, | 50 | }, |
| 40 | .root_src_path = owned_src_path, | 51 | .root_src_path = owned_src_path, |
| 52 | .root_src_directory_owned = true, | ||
| 53 | .namespace_hash = undefined, | ||
| 41 | }; | 54 | }; |
| 42 | 55 | ||
| 43 | return ptr; | 56 | return ptr; |
| 44 | } | 57 | } |
| 45 | 58 | ||
| 46 | /// Free all memory associated with this package and recursively call destroy | 59 | pub fn createWithDir( |
| 47 | /// on all packages in its table | 60 | gpa: *Allocator, |
| 61 | directory: Compilation.Directory, | ||
| 62 | /// Relative to `directory`. If null, means `directory` is the root src dir | ||
| 63 | /// and is owned externally. | ||
| 64 | root_src_dir_path: ?[]const u8, | ||
| 65 | /// Relative to root_src_dir_path | ||
| 66 | root_src_path: []const u8, | ||
| 67 | ) !*Package { | ||
| 68 | const ptr = try gpa.create(Package); | ||
| 69 | errdefer gpa.destroy(ptr); | ||
| 70 | |||
| 71 | const owned_src_path = try gpa.dupe(u8, root_src_path); | ||
| 72 | errdefer gpa.free(owned_src_path); | ||
| 73 | |||
| 74 | if (root_src_dir_path) |p| { | ||
| 75 | const owned_dir_path = try directory.join(gpa, &[1][]const u8{p}); | ||
| 76 | errdefer gpa.free(owned_dir_path); | ||
| 77 | |||
| 78 | ptr.* = .{ | ||
| 79 | .root_src_directory = .{ | ||
| 80 | .path = owned_dir_path, | ||
| 81 | .handle = try directory.handle.openDir(p, .{}), | ||
| 82 | }, | ||
| 83 | .root_src_directory_owned = true, | ||
| 84 | .root_src_path = owned_src_path, | ||
| 85 | .namespace_hash = undefined, | ||
| 86 | }; | ||
| 87 | } else { | ||
| 88 | ptr.* = .{ | ||
| 89 | .root_src_directory = directory, | ||
| 90 | .root_src_directory_owned = false, | ||
| 91 | .root_src_path = owned_src_path, | ||
| 92 | .namespace_hash = undefined, | ||
| 93 | }; | ||
| 94 | } | ||
| 95 | return ptr; | ||
| 96 | } | ||
| 97 | |||
| 98 | /// Free all memory associated with this package. It does not destroy any packages | ||
| 99 | /// inside its table; the caller is responsible for calling destroy() on them. | ||
| 48 | pub fn destroy(pkg: *Package, gpa: *Allocator) void { | 100 | pub fn destroy(pkg: *Package, gpa: *Allocator) void { |
| 49 | gpa.free(pkg.root_src_path); | 101 | gpa.free(pkg.root_src_path); |
| 50 | 102 | ||
| 51 | // If root_src_directory.path is null then the handle is the cwd() | 103 | if (pkg.root_src_directory_owned) { |
| 52 | // which shouldn't be closed. | 104 | // If root_src_directory.path is null then the handle is the cwd() |
| 53 | if (pkg.root_src_directory.path) |p| { | 105 | // which shouldn't be closed. |
| 54 | gpa.free(p); | 106 | if (pkg.root_src_directory.path) |p| { |
| 55 | pkg.root_src_directory.handle.close(); | 107 | gpa.free(p); |
| 108 | pkg.root_src_directory.handle.close(); | ||
| 109 | } | ||
| 56 | } | 110 | } |
| 57 | 111 | ||
| 58 | { | 112 | { |
| 59 | var it = pkg.table.iterator(); | 113 | var it = pkg.table.iterator(); |
| 60 | while (it.next()) |kv| { | 114 | while (it.next()) |kv| { |
| 61 | kv.value.destroy(gpa); | ||
| 62 | gpa.free(kv.key); | 115 | gpa.free(kv.key); |
| 63 | } | 116 | } |
| 64 | } | 117 | } |
| ... | @@ -72,3 +125,10 @@ pub fn add(pkg: *Package, gpa: *Allocator, name: []const u8, package: *Package) | ... | @@ -72,3 +125,10 @@ pub fn add(pkg: *Package, gpa: *Allocator, name: []const u8, package: *Package) |
| 72 | const name_dupe = try mem.dupe(gpa, u8, name); | 125 | const name_dupe = try mem.dupe(gpa, u8, name); |
| 73 | pkg.table.putAssumeCapacityNoClobber(name_dupe, package); | 126 | pkg.table.putAssumeCapacityNoClobber(name_dupe, package); |
| 74 | } | 127 | } |
| 128 | |||
| 129 | pub fn addAndAdopt(parent: *Package, gpa: *Allocator, name: []const u8, child: *Package) !void { | ||
| 130 | assert(child.parent == null); // make up your mind, who is the parent?? | ||
| 131 | child.parent = parent; | ||
| 132 | child.namespace_hash = std.zig.hashName(parent.namespace_hash, ":", name); | ||
| 133 | return parent.add(gpa, name, child); | ||
| 134 | } |
src/Sema.zig+135-36| ... | @@ -199,6 +199,7 @@ pub fn analyzeBody( | ... | @@ -199,6 +199,7 @@ pub fn analyzeBody( |
| 199 | .fn_type_cc => try sema.zirFnTypeCc(block, inst, false), | 199 | .fn_type_cc => try sema.zirFnTypeCc(block, inst, false), |
| 200 | .fn_type_cc_var_args => try sema.zirFnTypeCc(block, inst, true), | 200 | .fn_type_cc_var_args => try sema.zirFnTypeCc(block, inst, true), |
| 201 | .fn_type_var_args => try sema.zirFnType(block, inst, true), | 201 | .fn_type_var_args => try sema.zirFnType(block, inst, true), |
| 202 | .has_decl => try sema.zirHasDecl(block, inst), | ||
| 202 | .import => try sema.zirImport(block, inst), | 203 | .import => try sema.zirImport(block, inst), |
| 203 | .indexable_ptr_len => try sema.zirIndexablePtrLen(block, inst), | 204 | .indexable_ptr_len => try sema.zirIndexablePtrLen(block, inst), |
| 204 | .int => try sema.zirInt(block, inst), | 205 | .int => try sema.zirInt(block, inst), |
| ... | @@ -258,11 +259,14 @@ pub fn analyzeBody( | ... | @@ -258,11 +259,14 @@ pub fn analyzeBody( |
| 258 | .switch_capture_multi_ref => try sema.zirSwitchCapture(block, inst, true, true), | 259 | .switch_capture_multi_ref => try sema.zirSwitchCapture(block, inst, true, true), |
| 259 | .switch_capture_else => try sema.zirSwitchCaptureElse(block, inst, false), | 260 | .switch_capture_else => try sema.zirSwitchCaptureElse(block, inst, false), |
| 260 | .switch_capture_else_ref => try sema.zirSwitchCaptureElse(block, inst, true), | 261 | .switch_capture_else_ref => try sema.zirSwitchCaptureElse(block, inst, true), |
| 262 | .type_info => try sema.zirTypeInfo(block, inst), | ||
| 261 | .typeof => try sema.zirTypeof(block, inst), | 263 | .typeof => try sema.zirTypeof(block, inst), |
| 262 | .typeof_elem => try sema.zirTypeofElem(block, inst), | 264 | .typeof_elem => try sema.zirTypeofElem(block, inst), |
| 263 | .typeof_peer => try sema.zirTypeofPeer(block, inst), | 265 | .typeof_peer => try sema.zirTypeofPeer(block, inst), |
| 264 | .xor => try sema.zirBitwise(block, inst, .xor), | 266 | .xor => try sema.zirBitwise(block, inst, .xor), |
| 265 | .struct_init_empty => try sema.zirStructInitEmpty(block, inst), | 267 | .struct_init_empty => try sema.zirStructInitEmpty(block, inst), |
| 268 | .struct_init => try sema.zirStructInit(block, inst), | ||
| 269 | .field_type => try sema.zirFieldType(block, inst), | ||
| 266 | 270 | ||
| 267 | .struct_decl => try sema.zirStructDecl(block, inst, .Auto), | 271 | .struct_decl => try sema.zirStructDecl(block, inst, .Auto), |
| 268 | .struct_decl_packed => try sema.zirStructDecl(block, inst, .Packed), | 272 | .struct_decl_packed => try sema.zirStructDecl(block, inst, .Packed), |
| ... | @@ -342,6 +346,10 @@ pub fn analyzeBody( | ... | @@ -342,6 +346,10 @@ pub fn analyzeBody( |
| 342 | try sema.zirValidateStructInitPtr(block, inst); | 346 | try sema.zirValidateStructInitPtr(block, inst); |
| 343 | continue; | 347 | continue; |
| 344 | }, | 348 | }, |
| 349 | .@"export" => { | ||
| 350 | try sema.zirExport(block, inst); | ||
| 351 | continue; | ||
| 352 | }, | ||
| 345 | 353 | ||
| 346 | // Special case instructions to handle comptime control flow. | 354 | // Special case instructions to handle comptime control flow. |
| 347 | .repeat_inline => { | 355 | .repeat_inline => { |
| ... | @@ -593,6 +601,10 @@ fn zirStructDecl( | ... | @@ -593,6 +601,10 @@ fn zirStructDecl( |
| 593 | const struct_obj = try new_decl_arena.allocator.create(Module.Struct); | 601 | const struct_obj = try new_decl_arena.allocator.create(Module.Struct); |
| 594 | const struct_ty = try Type.Tag.@"struct".create(&new_decl_arena.allocator, struct_obj); | 602 | const struct_ty = try Type.Tag.@"struct".create(&new_decl_arena.allocator, struct_obj); |
| 595 | const struct_val = try Value.Tag.ty.create(&new_decl_arena.allocator, struct_ty); | 603 | const struct_val = try Value.Tag.ty.create(&new_decl_arena.allocator, struct_ty); |
| 604 | const new_decl = try sema.mod.createAnonymousDecl(&block.base, &new_decl_arena, .{ | ||
| 605 | .ty = Type.initTag(.type), | ||
| 606 | .val = struct_val, | ||
| 607 | }); | ||
| 596 | struct_obj.* = .{ | 608 | struct_obj.* = .{ |
| 597 | .owner_decl = sema.owner_decl, | 609 | .owner_decl = sema.owner_decl, |
| 598 | .fields = fields_map, | 610 | .fields = fields_map, |
| ... | @@ -600,12 +612,9 @@ fn zirStructDecl( | ... | @@ -600,12 +612,9 @@ fn zirStructDecl( |
| 600 | .container = .{ | 612 | .container = .{ |
| 601 | .ty = struct_ty, | 613 | .ty = struct_ty, |
| 602 | .file_scope = block.getFileScope(), | 614 | .file_scope = block.getFileScope(), |
| 615 | .parent_name_hash = new_decl.fullyQualifiedNameHash(), | ||
| 603 | }, | 616 | }, |
| 604 | }; | 617 | }; |
| 605 | const new_decl = try sema.mod.createAnonymousDecl(&block.base, &new_decl_arena, .{ | ||
| 606 | .ty = Type.initTag(.type), | ||
| 607 | .val = struct_val, | ||
| 608 | }); | ||
| 609 | return sema.analyzeDeclVal(block, src, new_decl); | 618 | return sema.analyzeDeclVal(block, src, new_decl); |
| 610 | } | 619 | } |
| 611 | 620 | ||
| ... | @@ -1333,6 +1342,28 @@ fn analyzeBlockBody( | ... | @@ -1333,6 +1342,28 @@ fn analyzeBlockBody( |
| 1333 | return &merges.block_inst.base; | 1342 | return &merges.block_inst.base; |
| 1334 | } | 1343 | } |
| 1335 | 1344 | ||
| 1345 | fn zirExport(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!void { | ||
| 1346 | const tracy = trace(@src()); | ||
| 1347 | defer tracy.end(); | ||
| 1348 | |||
| 1349 | const inst_data = sema.code.instructions.items(.data)[inst].pl_node; | ||
| 1350 | const extra = sema.code.extraData(zir.Inst.Bin, inst_data.payload_index).data; | ||
| 1351 | const src = inst_data.src(); | ||
| 1352 | const lhs_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node }; | ||
| 1353 | const rhs_src: LazySrcLoc = .{ .node_offset_builtin_call_arg1 = inst_data.src_node }; | ||
| 1354 | |||
| 1355 | // TODO (see corresponding TODO in AstGen) this is supposed to be a `decl_ref` | ||
| 1356 | // instruction, which could reference any decl, which is then supposed to get | ||
| 1357 | // exported, regardless of whether or not it is a function. | ||
| 1358 | const target_fn = try sema.resolveInstConst(block, lhs_src, extra.lhs); | ||
| 1359 | // TODO (see corresponding TODO in AstGen) this is supposed to be | ||
| 1360 | // `std.builtin.ExportOptions`, not a string. | ||
| 1361 | const export_name = try sema.resolveConstString(block, rhs_src, extra.rhs); | ||
| 1362 | |||
| 1363 | const actual_fn = target_fn.val.castTag(.function).?.data; | ||
| 1364 | try sema.mod.analyzeExport(&block.base, src, export_name, actual_fn.owner_decl); | ||
| 1365 | } | ||
| 1366 | |||
| 1336 | fn zirBreakpoint(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!void { | 1367 | fn zirBreakpoint(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!void { |
| 1337 | const tracy = trace(@src()); | 1368 | const tracy = trace(@src()); |
| 1338 | defer tracy.end(); | 1369 | defer tracy.end(); |
| ... | @@ -1402,9 +1433,6 @@ fn zirDbgStmtNode(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerE | ... | @@ -1402,9 +1433,6 @@ fn zirDbgStmtNode(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerE |
| 1402 | } | 1433 | } |
| 1403 | 1434 | ||
| 1404 | fn zirDeclRef(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!*Inst { | 1435 | fn zirDeclRef(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!*Inst { |
| 1405 | const tracy = trace(@src()); | ||
| 1406 | defer tracy.end(); | ||
| 1407 | |||
| 1408 | const inst_data = sema.code.instructions.items(.data)[inst].pl_node; | 1436 | const inst_data = sema.code.instructions.items(.data)[inst].pl_node; |
| 1409 | const src = inst_data.src(); | 1437 | const src = inst_data.src(); |
| 1410 | const decl = sema.owner_decl.dependencies.entries.items[inst_data.payload_index].key; | 1438 | const decl = sema.owner_decl.dependencies.entries.items[inst_data.payload_index].key; |
| ... | @@ -1412,9 +1440,6 @@ fn zirDeclRef(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError | ... | @@ -1412,9 +1440,6 @@ fn zirDeclRef(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError |
| 1412 | } | 1440 | } |
| 1413 | 1441 | ||
| 1414 | fn zirDeclVal(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!*Inst { | 1442 | fn zirDeclVal(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!*Inst { |
| 1415 | const tracy = trace(@src()); | ||
| 1416 | defer tracy.end(); | ||
| 1417 | |||
| 1418 | const inst_data = sema.code.instructions.items(.data)[inst].pl_node; | 1443 | const inst_data = sema.code.instructions.items(.data)[inst].pl_node; |
| 1419 | const src = inst_data.src(); | 1444 | const src = inst_data.src(); |
| 1420 | const decl = sema.owner_decl.dependencies.entries.items[inst_data.payload_index].key; | 1445 | const decl = sema.owner_decl.dependencies.entries.items[inst_data.payload_index].key; |
| ... | @@ -2543,7 +2568,10 @@ fn zirElemVal(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError | ... | @@ -2543,7 +2568,10 @@ fn zirElemVal(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError |
| 2543 | 2568 | ||
| 2544 | const bin_inst = sema.code.instructions.items(.data)[inst].bin; | 2569 | const bin_inst = sema.code.instructions.items(.data)[inst].bin; |
| 2545 | const array = try sema.resolveInst(bin_inst.lhs); | 2570 | const array = try sema.resolveInst(bin_inst.lhs); |
| 2546 | const array_ptr = try sema.analyzeRef(block, sema.src, array); | 2571 | const array_ptr = if (array.ty.zigTypeTag() == .Pointer) |
| 2572 | array | ||
| 2573 | else | ||
| 2574 | try sema.analyzeRef(block, sema.src, array); | ||
| 2547 | const elem_index = try sema.resolveInst(bin_inst.rhs); | 2575 | const elem_index = try sema.resolveInst(bin_inst.rhs); |
| 2548 | const result_ptr = try sema.elemPtr(block, sema.src, array_ptr, elem_index, sema.src); | 2576 | const result_ptr = try sema.elemPtr(block, sema.src, array_ptr, elem_index, sema.src); |
| 2549 | return sema.analyzeLoad(block, sema.src, result_ptr, sema.src); | 2577 | return sema.analyzeLoad(block, sema.src, result_ptr, sema.src); |
| ... | @@ -2558,7 +2586,10 @@ fn zirElemValNode(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerE | ... | @@ -2558,7 +2586,10 @@ fn zirElemValNode(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerE |
| 2558 | const elem_index_src: LazySrcLoc = .{ .node_offset_array_access_index = inst_data.src_node }; | 2586 | const elem_index_src: LazySrcLoc = .{ .node_offset_array_access_index = inst_data.src_node }; |
| 2559 | const extra = sema.code.extraData(zir.Inst.Bin, inst_data.payload_index).data; | 2587 | const extra = sema.code.extraData(zir.Inst.Bin, inst_data.payload_index).data; |
| 2560 | const array = try sema.resolveInst(extra.lhs); | 2588 | const array = try sema.resolveInst(extra.lhs); |
| 2561 | const array_ptr = try sema.analyzeRef(block, src, array); | 2589 | const array_ptr = if (array.ty.zigTypeTag() == .Pointer) |
| 2590 | array | ||
| 2591 | else | ||
| 2592 | try sema.analyzeRef(block, src, array); | ||
| 2562 | const elem_index = try sema.resolveInst(extra.rhs); | 2593 | const elem_index = try sema.resolveInst(extra.rhs); |
| 2563 | const result_ptr = try sema.elemPtr(block, src, array_ptr, elem_index, elem_index_src); | 2594 | const result_ptr = try sema.elemPtr(block, src, array_ptr, elem_index, elem_index_src); |
| 2564 | return sema.analyzeLoad(block, src, result_ptr, src); | 2595 | return sema.analyzeLoad(block, src, result_ptr, src); |
| ... | @@ -3595,6 +3626,34 @@ fn validateSwitchNoRange( | ... | @@ -3595,6 +3626,34 @@ fn validateSwitchNoRange( |
| 3595 | return sema.mod.failWithOwnedErrorMsg(&block.base, msg); | 3626 | return sema.mod.failWithOwnedErrorMsg(&block.base, msg); |
| 3596 | } | 3627 | } |
| 3597 | 3628 | ||
| 3629 | fn zirHasDecl(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!*Inst { | ||
| 3630 | const tracy = trace(@src()); | ||
| 3631 | defer tracy.end(); | ||
| 3632 | |||
| 3633 | const inst_data = sema.code.instructions.items(.data)[inst].pl_node; | ||
| 3634 | const extra = sema.code.extraData(zir.Inst.Bin, inst_data.payload_index).data; | ||
| 3635 | const src = inst_data.src(); | ||
| 3636 | const lhs_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node }; | ||
| 3637 | const rhs_src: LazySrcLoc = .{ .node_offset_builtin_call_arg1 = inst_data.src_node }; | ||
| 3638 | const container_type = try sema.resolveType(block, lhs_src, extra.lhs); | ||
| 3639 | const decl_name = try sema.resolveConstString(block, rhs_src, extra.rhs); | ||
| 3640 | const mod = sema.mod; | ||
| 3641 | const arena = sema.arena; | ||
| 3642 | |||
| 3643 | const container_scope = container_type.getContainerScope() orelse return mod.fail( | ||
| 3644 | &block.base, | ||
| 3645 | lhs_src, | ||
| 3646 | "expected struct, enum, union, or opaque, found '{}'", | ||
| 3647 | .{container_type}, | ||
| 3648 | ); | ||
| 3649 | if (mod.lookupDeclName(&container_scope.base, decl_name)) |decl| { | ||
| 3650 | // TODO if !decl.is_pub and inDifferentFiles() return false | ||
| 3651 | return mod.constBool(arena, src, true); | ||
| 3652 | } else { | ||
| 3653 | return mod.constBool(arena, src, false); | ||
| 3654 | } | ||
| 3655 | } | ||
| 3656 | |||
| 3598 | fn zirImport(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!*Inst { | 3657 | fn zirImport(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!*Inst { |
| 3599 | const tracy = trace(@src()); | 3658 | const tracy = trace(@src()); |
| 3600 | defer tracy.end(); | 3659 | defer tracy.end(); |
| ... | @@ -4021,6 +4080,12 @@ fn zirCmp( | ... | @@ -4021,6 +4080,12 @@ fn zirCmp( |
| 4021 | return block.addBinOp(src, bool_type, tag, casted_lhs, casted_rhs); | 4080 | return block.addBinOp(src, bool_type, tag, casted_lhs, casted_rhs); |
| 4022 | } | 4081 | } |
| 4023 | 4082 | ||
| 4083 | fn zirTypeInfo(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!*Inst { | ||
| 4084 | const inst_data = sema.code.instructions.items(.data)[inst].un_node; | ||
| 4085 | const src = inst_data.src(); | ||
| 4086 | return sema.mod.fail(&block.base, src, "TODO: implement Sema.zirTypeInfo", .{}); | ||
| 4087 | } | ||
| 4088 | |||
| 4024 | fn zirTypeof(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!*Inst { | 4089 | fn zirTypeof(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!*Inst { |
| 4025 | const inst_data = sema.code.instructions.items(.data)[inst].un_node; | 4090 | const inst_data = sema.code.instructions.items(.data)[inst].un_node; |
| 4026 | const src = inst_data.src(); | 4091 | const src = inst_data.src(); |
| ... | @@ -4438,6 +4503,18 @@ fn zirStructInitEmpty(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) In | ... | @@ -4438,6 +4503,18 @@ fn zirStructInitEmpty(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) In |
| 4438 | }); | 4503 | }); |
| 4439 | } | 4504 | } |
| 4440 | 4505 | ||
| 4506 | fn zirStructInit(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!*Inst { | ||
| 4507 | const inst_data = sema.code.instructions.items(.data)[inst].pl_node; | ||
| 4508 | const src = inst_data.src(); | ||
| 4509 | return sema.mod.fail(&block.base, src, "TODO: Sema.zirStructInit", .{}); | ||
| 4510 | } | ||
| 4511 | |||
| 4512 | fn zirFieldType(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!*Inst { | ||
| 4513 | const inst_data = sema.code.instructions.items(.data)[inst].pl_node; | ||
| 4514 | const src = inst_data.src(); | ||
| 4515 | return sema.mod.fail(&block.base, src, "TODO: Sema.zirFieldType", .{}); | ||
| 4516 | } | ||
| 4517 | |||
| 4441 | fn requireFunctionBlock(sema: *Sema, block: *Scope.Block, src: LazySrcLoc) !void { | 4518 | fn requireFunctionBlock(sema: *Sema, block: *Scope.Block, src: LazySrcLoc) !void { |
| 4442 | if (sema.func == null) { | 4519 | if (sema.func == null) { |
| 4443 | return sema.mod.fail(&block.base, src, "instruction illegal outside function body", .{}); | 4520 | return sema.mod.fail(&block.base, src, "instruction illegal outside function body", .{}); |
| ... | @@ -4632,7 +4709,8 @@ fn namedFieldPtr( | ... | @@ -4632,7 +4709,8 @@ fn namedFieldPtr( |
| 4632 | .Struct, .Opaque, .Union => { | 4709 | .Struct, .Opaque, .Union => { |
| 4633 | if (child_type.getContainerScope()) |container_scope| { | 4710 | if (child_type.getContainerScope()) |container_scope| { |
| 4634 | if (mod.lookupDeclName(&container_scope.base, field_name)) |decl| { | 4711 | if (mod.lookupDeclName(&container_scope.base, field_name)) |decl| { |
| 4635 | // TODO if !decl.is_pub and inDifferentFiles() "{} is private" | 4712 | if (!decl.is_pub and !(decl.container.file_scope == block.base.namespace().file_scope)) |
| 4713 | return mod.fail(&block.base, src, "'{s}' is private", .{field_name}); | ||
| 4636 | return sema.analyzeDeclRef(block, src, decl); | 4714 | return sema.analyzeDeclRef(block, src, decl); |
| 4637 | } | 4715 | } |
| 4638 | 4716 | ||
| ... | @@ -4660,7 +4738,8 @@ fn namedFieldPtr( | ... | @@ -4660,7 +4738,8 @@ fn namedFieldPtr( |
| 4660 | .Enum => { | 4738 | .Enum => { |
| 4661 | if (child_type.getContainerScope()) |container_scope| { | 4739 | if (child_type.getContainerScope()) |container_scope| { |
| 4662 | if (mod.lookupDeclName(&container_scope.base, field_name)) |decl| { | 4740 | if (mod.lookupDeclName(&container_scope.base, field_name)) |decl| { |
| 4663 | // TODO if !decl.is_pub and inDifferentFiles() "{} is private" | 4741 | if (!decl.is_pub and !(decl.container.file_scope == block.base.namespace().file_scope)) |
| 4742 | return mod.fail(&block.base, src, "'{s}' is private", .{field_name}); | ||
| 4664 | return sema.analyzeDeclRef(block, src, decl); | 4743 | return sema.analyzeDeclRef(block, src, decl); |
| 4665 | } | 4744 | } |
| 4666 | } | 4745 | } |
| ... | @@ -4731,37 +4810,51 @@ fn elemPtr( | ... | @@ -4731,37 +4810,51 @@ fn elemPtr( |
| 4731 | elem_index: *Inst, | 4810 | elem_index: *Inst, |
| 4732 | elem_index_src: LazySrcLoc, | 4811 | elem_index_src: LazySrcLoc, |
| 4733 | ) InnerError!*Inst { | 4812 | ) InnerError!*Inst { |
| 4734 | const elem_ty = switch (array_ptr.ty.zigTypeTag()) { | 4813 | const array_ty = switch (array_ptr.ty.zigTypeTag()) { |
| 4735 | .Pointer => array_ptr.ty.elemType(), | 4814 | .Pointer => array_ptr.ty.elemType(), |
| 4736 | else => return sema.mod.fail(&block.base, array_ptr.src, "expected pointer, found '{}'", .{array_ptr.ty}), | 4815 | else => return sema.mod.fail(&block.base, array_ptr.src, "expected pointer, found '{}'", .{array_ptr.ty}), |
| 4737 | }; | 4816 | }; |
| 4738 | if (!elem_ty.isIndexable()) { | 4817 | if (!array_ty.isIndexable()) { |
| 4739 | return sema.mod.fail(&block.base, src, "array access of non-array type '{}'", .{elem_ty}); | 4818 | return sema.mod.fail(&block.base, src, "array access of non-array type '{}'", .{array_ty}); |
| 4740 | } | 4819 | } |
| 4741 | 4820 | if (array_ty.isSinglePointer() and array_ty.elemType().zigTypeTag() == .Array) { | |
| 4742 | if (elem_ty.isSinglePointer() and elem_ty.elemType().zigTypeTag() == .Array) { | ||
| 4743 | // we have to deref the ptr operand to get the actual array pointer | 4821 | // we have to deref the ptr operand to get the actual array pointer |
| 4744 | const array_ptr_deref = try sema.analyzeLoad(block, src, array_ptr, array_ptr.src); | 4822 | const array_ptr_deref = try sema.analyzeLoad(block, src, array_ptr, array_ptr.src); |
| 4745 | if (array_ptr_deref.value()) |array_ptr_val| { | 4823 | return sema.elemPtrArray(block, src, array_ptr_deref, elem_index, elem_index_src); |
| 4746 | if (elem_index.value()) |index_val| { | 4824 | } |
| 4747 | // Both array pointer and index are compile-time known. | 4825 | if (array_ty.zigTypeTag() == .Array) { |
| 4748 | const index_u64 = index_val.toUnsignedInt(); | 4826 | return sema.elemPtrArray(block, src, array_ptr, elem_index, elem_index_src); |
| 4749 | // @intCast here because it would have been impossible to construct a value that | ||
| 4750 | // required a larger index. | ||
| 4751 | const elem_ptr = try array_ptr_val.elemPtr(sema.arena, @intCast(usize, index_u64)); | ||
| 4752 | const pointee_type = elem_ty.elemType().elemType(); | ||
| 4753 | |||
| 4754 | return sema.mod.constInst(sema.arena, src, .{ | ||
| 4755 | .ty = try Type.Tag.single_const_pointer.create(sema.arena, pointee_type), | ||
| 4756 | .val = elem_ptr, | ||
| 4757 | }); | ||
| 4758 | } | ||
| 4759 | } | ||
| 4760 | } | 4827 | } |
| 4761 | 4828 | ||
| 4762 | return sema.mod.fail(&block.base, src, "TODO implement more analyze elemptr", .{}); | 4829 | return sema.mod.fail(&block.base, src, "TODO implement more analyze elemptr", .{}); |
| 4763 | } | 4830 | } |
| 4764 | 4831 | ||
| 4832 | fn elemPtrArray( | ||
| 4833 | sema: *Sema, | ||
| 4834 | block: *Scope.Block, | ||
| 4835 | src: LazySrcLoc, | ||
| 4836 | array_ptr: *Inst, | ||
| 4837 | elem_index: *Inst, | ||
| 4838 | elem_index_src: LazySrcLoc, | ||
| 4839 | ) InnerError!*Inst { | ||
| 4840 | if (array_ptr.value()) |array_ptr_val| { | ||
| 4841 | if (elem_index.value()) |index_val| { | ||
| 4842 | // Both array pointer and index are compile-time known. | ||
| 4843 | const index_u64 = index_val.toUnsignedInt(); | ||
| 4844 | // @intCast here because it would have been impossible to construct a value that | ||
| 4845 | // required a larger index. | ||
| 4846 | const elem_ptr = try array_ptr_val.elemPtr(sema.arena, @intCast(usize, index_u64)); | ||
| 4847 | const pointee_type = array_ptr.ty.elemType().elemType(); | ||
| 4848 | |||
| 4849 | return sema.mod.constInst(sema.arena, src, .{ | ||
| 4850 | .ty = try Type.Tag.single_const_pointer.create(sema.arena, pointee_type), | ||
| 4851 | .val = elem_ptr, | ||
| 4852 | }); | ||
| 4853 | } | ||
| 4854 | } | ||
| 4855 | return sema.mod.fail(&block.base, src, "TODO implement more analyze elemptr for arrays", .{}); | ||
| 4856 | } | ||
| 4857 | |||
| 4765 | fn coerce( | 4858 | fn coerce( |
| 4766 | sema: *Sema, | 4859 | sema: *Sema, |
| 4767 | block: *Scope.Block, | 4860 | block: *Scope.Block, |
| ... | @@ -5244,9 +5337,9 @@ fn analyzeImport(sema: *Sema, block: *Scope.Block, src: LazySrcLoc, target_strin | ... | @@ -5244,9 +5337,9 @@ fn analyzeImport(sema: *Sema, block: *Scope.Block, src: LazySrcLoc, target_strin |
| 5244 | try std.fs.path.resolve(sema.gpa, &[_][]const u8{ cur_pkg_dir_path, target_string }); | 5337 | try std.fs.path.resolve(sema.gpa, &[_][]const u8{ cur_pkg_dir_path, target_string }); |
| 5245 | errdefer sema.gpa.free(resolved_path); | 5338 | errdefer sema.gpa.free(resolved_path); |
| 5246 | 5339 | ||
| 5247 | if (sema.mod.import_table.get(resolved_path)) |some| { | 5340 | if (sema.mod.import_table.get(resolved_path)) |cached_import| { |
| 5248 | sema.gpa.free(resolved_path); | 5341 | sema.gpa.free(resolved_path); |
| 5249 | return some; | 5342 | return cached_import; |
| 5250 | } | 5343 | } |
| 5251 | 5344 | ||
| 5252 | if (found_pkg == null) { | 5345 | if (found_pkg == null) { |
| ... | @@ -5264,6 +5357,11 @@ fn analyzeImport(sema: *Sema, block: *Scope.Block, src: LazySrcLoc, target_strin | ... | @@ -5264,6 +5357,11 @@ fn analyzeImport(sema: *Sema, block: *Scope.Block, src: LazySrcLoc, target_strin |
| 5264 | const struct_ty = try Type.Tag.empty_struct.create(sema.gpa, &file_scope.root_container); | 5357 | const struct_ty = try Type.Tag.empty_struct.create(sema.gpa, &file_scope.root_container); |
| 5265 | errdefer sema.gpa.destroy(struct_ty.castTag(.empty_struct).?); | 5358 | errdefer sema.gpa.destroy(struct_ty.castTag(.empty_struct).?); |
| 5266 | 5359 | ||
| 5360 | const container_name_hash: Scope.NameHash = if (found_pkg) |pkg| | ||
| 5361 | pkg.namespace_hash | ||
| 5362 | else | ||
| 5363 | std.zig.hashName(cur_pkg.namespace_hash, "/", resolved_path); | ||
| 5364 | |||
| 5267 | file_scope.* = .{ | 5365 | file_scope.* = .{ |
| 5268 | .sub_file_path = resolved_path, | 5366 | .sub_file_path = resolved_path, |
| 5269 | .source = .{ .unloaded = {} }, | 5367 | .source = .{ .unloaded = {} }, |
| ... | @@ -5274,6 +5372,7 @@ fn analyzeImport(sema: *Sema, block: *Scope.Block, src: LazySrcLoc, target_strin | ... | @@ -5274,6 +5372,7 @@ fn analyzeImport(sema: *Sema, block: *Scope.Block, src: LazySrcLoc, target_strin |
| 5274 | .file_scope = file_scope, | 5372 | .file_scope = file_scope, |
| 5275 | .decls = .{}, | 5373 | .decls = .{}, |
| 5276 | .ty = struct_ty, | 5374 | .ty = struct_ty, |
| 5375 | .parent_name_hash = container_name_hash, | ||
| 5277 | }, | 5376 | }, |
| 5278 | }; | 5377 | }; |
| 5279 | sema.mod.analyzeContainer(&file_scope.root_container) catch |err| switch (err) { | 5378 | sema.mod.analyzeContainer(&file_scope.root_container) catch |err| switch (err) { |
src/codegen.zig+1-1| ... | @@ -417,7 +417,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { | ... | @@ -417,7 +417,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { |
| 417 | const node_datas = tree.nodes.items(.data); | 417 | const node_datas = tree.nodes.items(.data); |
| 418 | const token_starts = tree.tokens.items(.start); | 418 | const token_starts = tree.tokens.items(.start); |
| 419 | 419 | ||
| 420 | const fn_decl = tree.rootDecls()[module_fn.owner_decl.src_index]; | 420 | const fn_decl = module_fn.owner_decl.src_node; |
| 421 | assert(node_tags[fn_decl] == .fn_decl); | 421 | assert(node_tags[fn_decl] == .fn_decl); |
| 422 | const block = node_datas[fn_decl].rhs; | 422 | const block = node_datas[fn_decl].rhs; |
| 423 | const lbrace_src = token_starts[tree.firstToken(block)]; | 423 | const lbrace_src = token_starts[tree.firstToken(block)]; |
src/link/Elf.zig+2-4| ... | @@ -2228,10 +2228,9 @@ pub fn updateDecl(self: *Elf, module: *Module, decl: *Module.Decl) !void { | ... | @@ -2228,10 +2228,9 @@ pub fn updateDecl(self: *Elf, module: *Module, decl: *Module.Decl) !void { |
| 2228 | const node_datas = tree.nodes.items(.data); | 2228 | const node_datas = tree.nodes.items(.data); |
| 2229 | const token_starts = tree.tokens.items(.start); | 2229 | const token_starts = tree.tokens.items(.start); |
| 2230 | 2230 | ||
| 2231 | const file_ast_decls = tree.rootDecls(); | ||
| 2232 | // TODO Look into improving the performance here by adding a token-index-to-line | 2231 | // TODO Look into improving the performance here by adding a token-index-to-line |
| 2233 | // lookup table. Currently this involves scanning over the source code for newlines. | 2232 | // lookup table. Currently this involves scanning over the source code for newlines. |
| 2234 | const fn_decl = file_ast_decls[decl.src_index]; | 2233 | const fn_decl = decl.src_node; |
| 2235 | assert(node_tags[fn_decl] == .fn_decl); | 2234 | assert(node_tags[fn_decl] == .fn_decl); |
| 2236 | const block = node_datas[fn_decl].rhs; | 2235 | const block = node_datas[fn_decl].rhs; |
| 2237 | const lbrace = tree.firstToken(block); | 2236 | const lbrace = tree.firstToken(block); |
| ... | @@ -2755,10 +2754,9 @@ pub fn updateDeclLineNumber(self: *Elf, module: *Module, decl: *const Module.Dec | ... | @@ -2755,10 +2754,9 @@ pub fn updateDeclLineNumber(self: *Elf, module: *Module, decl: *const Module.Dec |
| 2755 | const node_datas = tree.nodes.items(.data); | 2754 | const node_datas = tree.nodes.items(.data); |
| 2756 | const token_starts = tree.tokens.items(.start); | 2755 | const token_starts = tree.tokens.items(.start); |
| 2757 | 2756 | ||
| 2758 | const file_ast_decls = tree.rootDecls(); | ||
| 2759 | // TODO Look into improving the performance here by adding a token-index-to-line | 2757 | // TODO Look into improving the performance here by adding a token-index-to-line |
| 2760 | // lookup table. Currently this involves scanning over the source code for newlines. | 2758 | // lookup table. Currently this involves scanning over the source code for newlines. |
| 2761 | const fn_decl = file_ast_decls[decl.src_index]; | 2759 | const fn_decl = decl.src_node; |
| 2762 | assert(node_tags[fn_decl] == .fn_decl); | 2760 | assert(node_tags[fn_decl] == .fn_decl); |
| 2763 | const block = node_datas[fn_decl].rhs; | 2761 | const block = node_datas[fn_decl].rhs; |
| 2764 | const lbrace = tree.firstToken(block); | 2762 | const lbrace = tree.firstToken(block); |
src/link/MachO/DebugSymbols.zig+2-4| ... | @@ -909,10 +909,9 @@ pub fn updateDeclLineNumber(self: *DebugSymbols, module: *Module, decl: *const M | ... | @@ -909,10 +909,9 @@ pub fn updateDeclLineNumber(self: *DebugSymbols, module: *Module, decl: *const M |
| 909 | const node_datas = tree.nodes.items(.data); | 909 | const node_datas = tree.nodes.items(.data); |
| 910 | const token_starts = tree.tokens.items(.start); | 910 | const token_starts = tree.tokens.items(.start); |
| 911 | 911 | ||
| 912 | const file_ast_decls = tree.rootDecls(); | ||
| 913 | // TODO Look into improving the performance here by adding a token-index-to-line | 912 | // TODO Look into improving the performance here by adding a token-index-to-line |
| 914 | // lookup table. Currently this involves scanning over the source code for newlines. | 913 | // lookup table. Currently this involves scanning over the source code for newlines. |
| 915 | const fn_decl = file_ast_decls[decl.src_index]; | 914 | const fn_decl = decl.src_node; |
| 916 | assert(node_tags[fn_decl] == .fn_decl); | 915 | assert(node_tags[fn_decl] == .fn_decl); |
| 917 | const block = node_datas[fn_decl].rhs; | 916 | const block = node_datas[fn_decl].rhs; |
| 918 | const lbrace = tree.firstToken(block); | 917 | const lbrace = tree.firstToken(block); |
| ... | @@ -959,10 +958,9 @@ pub fn initDeclDebugBuffers( | ... | @@ -959,10 +958,9 @@ pub fn initDeclDebugBuffers( |
| 959 | const node_datas = tree.nodes.items(.data); | 958 | const node_datas = tree.nodes.items(.data); |
| 960 | const token_starts = tree.tokens.items(.start); | 959 | const token_starts = tree.tokens.items(.start); |
| 961 | 960 | ||
| 962 | const file_ast_decls = tree.rootDecls(); | ||
| 963 | // TODO Look into improving the performance here by adding a token-index-to-line | 961 | // TODO Look into improving the performance here by adding a token-index-to-line |
| 964 | // lookup table. Currently this involves scanning over the source code for newlines. | 962 | // lookup table. Currently this involves scanning over the source code for newlines. |
| 965 | const fn_decl = file_ast_decls[decl.src_index]; | 963 | const fn_decl = decl.src_node; |
| 966 | assert(node_tags[fn_decl] == .fn_decl); | 964 | assert(node_tags[fn_decl] == .fn_decl); |
| 967 | const block = node_datas[fn_decl].rhs; | 965 | const block = node_datas[fn_decl].rhs; |
| 968 | const lbrace = tree.firstToken(block); | 966 | const lbrace = tree.firstToken(block); |
src/main.zig+23-23| ... | @@ -505,7 +505,6 @@ fn buildOutputType( | ... | @@ -505,7 +505,6 @@ fn buildOutputType( |
| 505 | var emit_bin: EmitBin = .yes_default_path; | 505 | var emit_bin: EmitBin = .yes_default_path; |
| 506 | var emit_asm: Emit = .no; | 506 | var emit_asm: Emit = .no; |
| 507 | var emit_llvm_ir: Emit = .no; | 507 | var emit_llvm_ir: Emit = .no; |
| 508 | var emit_zir: Emit = .no; | ||
| 509 | var emit_docs: Emit = .no; | 508 | var emit_docs: Emit = .no; |
| 510 | var emit_analysis: Emit = .no; | 509 | var emit_analysis: Emit = .no; |
| 511 | var target_arch_os_abi: []const u8 = "native"; | 510 | var target_arch_os_abi: []const u8 = "native"; |
| ... | @@ -599,15 +598,15 @@ fn buildOutputType( | ... | @@ -599,15 +598,15 @@ fn buildOutputType( |
| 599 | var test_exec_args = std.ArrayList(?[]const u8).init(gpa); | 598 | var test_exec_args = std.ArrayList(?[]const u8).init(gpa); |
| 600 | defer test_exec_args.deinit(); | 599 | defer test_exec_args.deinit(); |
| 601 | 600 | ||
| 602 | const pkg_tree_root = try gpa.create(Package); | ||
| 603 | // This package only exists to clean up the code parsing --pkg-begin and | 601 | // This package only exists to clean up the code parsing --pkg-begin and |
| 604 | // --pkg-end flags. Use dummy values that are safe for the destroy call. | 602 | // --pkg-end flags. Use dummy values that are safe for the destroy call. |
| 605 | pkg_tree_root.* = .{ | 603 | var pkg_tree_root: Package = .{ |
| 606 | .root_src_directory = .{ .path = null, .handle = fs.cwd() }, | 604 | .root_src_directory = .{ .path = null, .handle = fs.cwd() }, |
| 607 | .root_src_path = &[0]u8{}, | 605 | .root_src_path = &[0]u8{}, |
| 606 | .namespace_hash = Package.root_namespace_hash, | ||
| 608 | }; | 607 | }; |
| 609 | defer pkg_tree_root.destroy(gpa); | 608 | defer freePkgTree(gpa, &pkg_tree_root, false); |
| 610 | var cur_pkg: *Package = pkg_tree_root; | 609 | var cur_pkg: *Package = &pkg_tree_root; |
| 611 | 610 | ||
| 612 | switch (arg_mode) { | 611 | switch (arg_mode) { |
| 613 | .build, .translate_c, .zig_test, .run => { | 612 | .build, .translate_c, .zig_test, .run => { |
| ... | @@ -658,8 +657,7 @@ fn buildOutputType( | ... | @@ -658,8 +657,7 @@ fn buildOutputType( |
| 658 | ) catch |err| { | 657 | ) catch |err| { |
| 659 | fatal("Failed to add package at path {s}: {s}", .{ pkg_path, @errorName(err) }); | 658 | fatal("Failed to add package at path {s}: {s}", .{ pkg_path, @errorName(err) }); |
| 660 | }; | 659 | }; |
| 661 | new_cur_pkg.parent = cur_pkg; | 660 | try cur_pkg.addAndAdopt(gpa, pkg_name, new_cur_pkg); |
| 662 | try cur_pkg.add(gpa, pkg_name, new_cur_pkg); | ||
| 663 | cur_pkg = new_cur_pkg; | 661 | cur_pkg = new_cur_pkg; |
| 664 | } else if (mem.eql(u8, arg, "--pkg-end")) { | 662 | } else if (mem.eql(u8, arg, "--pkg-end")) { |
| 665 | cur_pkg = cur_pkg.parent orelse | 663 | cur_pkg = cur_pkg.parent orelse |
| ... | @@ -924,12 +922,6 @@ fn buildOutputType( | ... | @@ -924,12 +922,6 @@ fn buildOutputType( |
| 924 | emit_bin = .{ .yes = arg["-femit-bin=".len..] }; | 922 | emit_bin = .{ .yes = arg["-femit-bin=".len..] }; |
| 925 | } else if (mem.eql(u8, arg, "-fno-emit-bin")) { | 923 | } else if (mem.eql(u8, arg, "-fno-emit-bin")) { |
| 926 | emit_bin = .no; | 924 | emit_bin = .no; |
| 927 | } else if (mem.eql(u8, arg, "-femit-zir")) { | ||
| 928 | emit_zir = .yes_default_path; | ||
| 929 | } else if (mem.startsWith(u8, arg, "-femit-zir=")) { | ||
| 930 | emit_zir = .{ .yes = arg["-femit-zir=".len..] }; | ||
| 931 | } else if (mem.eql(u8, arg, "-fno-emit-zir")) { | ||
| 932 | emit_zir = .no; | ||
| 933 | } else if (mem.eql(u8, arg, "-femit-h")) { | 925 | } else if (mem.eql(u8, arg, "-femit-h")) { |
| 934 | emit_h = .yes_default_path; | 926 | emit_h = .yes_default_path; |
| 935 | } else if (mem.startsWith(u8, arg, "-femit-h=")) { | 927 | } else if (mem.startsWith(u8, arg, "-femit-h=")) { |
| ... | @@ -1026,7 +1018,7 @@ fn buildOutputType( | ... | @@ -1026,7 +1018,7 @@ fn buildOutputType( |
| 1026 | .extra_flags = try arena.dupe([]const u8, extra_cflags.items), | 1018 | .extra_flags = try arena.dupe([]const u8, extra_cflags.items), |
| 1027 | }); | 1019 | }); |
| 1028 | }, | 1020 | }, |
| 1029 | .zig, .zir => { | 1021 | .zig => { |
| 1030 | if (root_src_file) |other| { | 1022 | if (root_src_file) |other| { |
| 1031 | fatal("found another zig file '{s}' after root source file '{s}'", .{ arg, other }); | 1023 | fatal("found another zig file '{s}' after root source file '{s}'", .{ arg, other }); |
| 1032 | } else { | 1024 | } else { |
| ... | @@ -1087,7 +1079,7 @@ fn buildOutputType( | ... | @@ -1087,7 +1079,7 @@ fn buildOutputType( |
| 1087 | .unknown, .shared_library, .object, .static_library => { | 1079 | .unknown, .shared_library, .object, .static_library => { |
| 1088 | try link_objects.append(it.only_arg); | 1080 | try link_objects.append(it.only_arg); |
| 1089 | }, | 1081 | }, |
| 1090 | .zig, .zir => { | 1082 | .zig => { |
| 1091 | if (root_src_file) |other| { | 1083 | if (root_src_file) |other| { |
| 1092 | fatal("found another zig file '{s}' after root source file '{s}'", .{ it.only_arg, other }); | 1084 | fatal("found another zig file '{s}' after root source file '{s}'", .{ it.only_arg, other }); |
| 1093 | } else { | 1085 | } else { |
| ... | @@ -1725,13 +1717,6 @@ fn buildOutputType( | ... | @@ -1725,13 +1717,6 @@ fn buildOutputType( |
| 1725 | var emit_docs_resolved = try emit_docs.resolve("docs"); | 1717 | var emit_docs_resolved = try emit_docs.resolve("docs"); |
| 1726 | defer emit_docs_resolved.deinit(); | 1718 | defer emit_docs_resolved.deinit(); |
| 1727 | 1719 | ||
| 1728 | switch (emit_zir) { | ||
| 1729 | .no => {}, | ||
| 1730 | .yes_default_path, .yes => { | ||
| 1731 | fatal("The -femit-zir implementation has been intentionally deleted so that it can be rewritten as a proper backend.", .{}); | ||
| 1732 | }, | ||
| 1733 | } | ||
| 1734 | |||
| 1735 | const root_pkg: ?*Package = if (root_src_file) |src_path| blk: { | 1720 | const root_pkg: ?*Package = if (root_src_file) |src_path| blk: { |
| 1736 | if (main_pkg_path) |p| { | 1721 | if (main_pkg_path) |p| { |
| 1737 | const rel_src_path = try fs.path.relative(gpa, p, src_path); | 1722 | const rel_src_path = try fs.path.relative(gpa, p, src_path); |
| ... | @@ -1747,6 +1732,7 @@ fn buildOutputType( | ... | @@ -1747,6 +1732,7 @@ fn buildOutputType( |
| 1747 | if (root_pkg) |pkg| { | 1732 | if (root_pkg) |pkg| { |
| 1748 | pkg.table = pkg_tree_root.table; | 1733 | pkg.table = pkg_tree_root.table; |
| 1749 | pkg_tree_root.table = .{}; | 1734 | pkg_tree_root.table = .{}; |
| 1735 | pkg.namespace_hash = pkg_tree_root.namespace_hash; | ||
| 1750 | } | 1736 | } |
| 1751 | 1737 | ||
| 1752 | const self_exe_path = try fs.selfExePathAlloc(arena); | 1738 | const self_exe_path = try fs.selfExePathAlloc(arena); |
| ... | @@ -2155,6 +2141,18 @@ fn updateModule(gpa: *Allocator, comp: *Compilation, hook: AfterUpdateHook) !voi | ... | @@ -2155,6 +2141,18 @@ fn updateModule(gpa: *Allocator, comp: *Compilation, hook: AfterUpdateHook) !voi |
| 2155 | } | 2141 | } |
| 2156 | } | 2142 | } |
| 2157 | 2143 | ||
| 2144 | fn freePkgTree(gpa: *Allocator, pkg: *Package, free_parent: bool) void { | ||
| 2145 | { | ||
| 2146 | var it = pkg.table.iterator(); | ||
| 2147 | while (it.next()) |kv| { | ||
| 2148 | freePkgTree(gpa, kv.value, true); | ||
| 2149 | } | ||
| 2150 | } | ||
| 2151 | if (free_parent) { | ||
| 2152 | pkg.destroy(gpa); | ||
| 2153 | } | ||
| 2154 | } | ||
| 2155 | |||
| 2158 | fn cmdTranslateC(comp: *Compilation, arena: *Allocator, enable_cache: bool) !void { | 2156 | fn cmdTranslateC(comp: *Compilation, arena: *Allocator, enable_cache: bool) !void { |
| 2159 | if (!build_options.have_llvm) | 2157 | if (!build_options.have_llvm) |
| 2160 | fatal("cannot translate-c: compiler built without LLVM extensions", .{}); | 2158 | fatal("cannot translate-c: compiler built without LLVM extensions", .{}); |
| ... | @@ -2509,6 +2507,7 @@ pub fn cmdBuild(gpa: *Allocator, arena: *Allocator, args: []const []const u8) !v | ... | @@ -2509,6 +2507,7 @@ pub fn cmdBuild(gpa: *Allocator, arena: *Allocator, args: []const []const u8) !v |
| 2509 | .handle = try zig_lib_directory.handle.openDir(std_special, .{}), | 2507 | .handle = try zig_lib_directory.handle.openDir(std_special, .{}), |
| 2510 | }, | 2508 | }, |
| 2511 | .root_src_path = "build_runner.zig", | 2509 | .root_src_path = "build_runner.zig", |
| 2510 | .namespace_hash = Package.root_namespace_hash, | ||
| 2512 | }; | 2511 | }; |
| 2513 | defer root_pkg.root_src_directory.handle.close(); | 2512 | defer root_pkg.root_src_directory.handle.close(); |
| 2514 | 2513 | ||
| ... | @@ -2554,8 +2553,9 @@ pub fn cmdBuild(gpa: *Allocator, arena: *Allocator, args: []const []const u8) !v | ... | @@ -2554,8 +2553,9 @@ pub fn cmdBuild(gpa: *Allocator, arena: *Allocator, args: []const []const u8) !v |
| 2554 | var build_pkg: Package = .{ | 2553 | var build_pkg: Package = .{ |
| 2555 | .root_src_directory = build_directory, | 2554 | .root_src_directory = build_directory, |
| 2556 | .root_src_path = build_zig_basename, | 2555 | .root_src_path = build_zig_basename, |
| 2556 | .namespace_hash = undefined, | ||
| 2557 | }; | 2557 | }; |
| 2558 | try root_pkg.table.put(arena, "@build", &build_pkg); | 2558 | try root_pkg.addAndAdopt(arena, "@build", &build_pkg); |
| 2559 | 2559 | ||
| 2560 | var global_cache_directory: Compilation.Directory = l: { | 2560 | var global_cache_directory: Compilation.Directory = l: { |
| 2561 | const p = override_global_cache_dir orelse try introspect.resolveGlobalCacheDir(arena); | 2561 | const p = override_global_cache_dir orelse try introspect.resolveGlobalCacheDir(arena); |
src/stage1/codegen.cpp+1| ... | @@ -9137,6 +9137,7 @@ Buf *codegen_generate_builtin_source(CodeGen *g) { | ... | @@ -9137,6 +9137,7 @@ Buf *codegen_generate_builtin_source(CodeGen *g) { |
| 9137 | buf_appendf(contents, "pub const position_independent_executable = %s;\n", bool_to_str(g->have_pie)); | 9137 | buf_appendf(contents, "pub const position_independent_executable = %s;\n", bool_to_str(g->have_pie)); |
| 9138 | buf_appendf(contents, "pub const strip_debug_info = %s;\n", bool_to_str(g->strip_debug_symbols)); | 9138 | buf_appendf(contents, "pub const strip_debug_info = %s;\n", bool_to_str(g->strip_debug_symbols)); |
| 9139 | buf_appendf(contents, "pub const code_model = CodeModel.default;\n"); | 9139 | buf_appendf(contents, "pub const code_model = CodeModel.default;\n"); |
| 9140 | buf_appendf(contents, "pub const zig_is_stage2 = false;\n"); | ||
| 9140 | 9141 | ||
| 9141 | { | 9142 | { |
| 9142 | TargetSubsystem detected_subsystem = detect_subsystem(g); | 9143 | TargetSubsystem detected_subsystem = detect_subsystem(g); |
src/test.zig+21-42| ... | @@ -122,11 +122,6 @@ pub const TestContext = struct { | ... | @@ -122,11 +122,6 @@ pub const TestContext = struct { |
| 122 | path: []const u8, | 122 | path: []const u8, |
| 123 | }; | 123 | }; |
| 124 | 124 | ||
| 125 | pub const Extension = enum { | ||
| 126 | Zig, | ||
| 127 | ZIR, | ||
| 128 | }; | ||
| 129 | |||
| 130 | /// A `Case` consists of a list of `Update`. The same `Compilation` is used for each | 125 | /// A `Case` consists of a list of `Update`. The same `Compilation` is used for each |
| 131 | /// update, so each update's source is treated as a single file being | 126 | /// update, so each update's source is treated as a single file being |
| 132 | /// updated by the test harness and incrementally compiled. | 127 | /// updated by the test harness and incrementally compiled. |
| ... | @@ -141,7 +136,6 @@ pub const TestContext = struct { | ... | @@ -141,7 +136,6 @@ pub const TestContext = struct { |
| 141 | /// to Executable. | 136 | /// to Executable. |
| 142 | output_mode: std.builtin.OutputMode, | 137 | output_mode: std.builtin.OutputMode, |
| 143 | updates: std.ArrayList(Update), | 138 | updates: std.ArrayList(Update), |
| 144 | extension: Extension, | ||
| 145 | object_format: ?std.builtin.ObjectFormat = null, | 139 | object_format: ?std.builtin.ObjectFormat = null, |
| 146 | emit_h: bool = false, | 140 | emit_h: bool = false, |
| 147 | llvm_backend: bool = false, | 141 | llvm_backend: bool = false, |
| ... | @@ -238,14 +232,12 @@ pub const TestContext = struct { | ... | @@ -238,14 +232,12 @@ pub const TestContext = struct { |
| 238 | ctx: *TestContext, | 232 | ctx: *TestContext, |
| 239 | name: []const u8, | 233 | name: []const u8, |
| 240 | target: CrossTarget, | 234 | target: CrossTarget, |
| 241 | extension: Extension, | ||
| 242 | ) *Case { | 235 | ) *Case { |
| 243 | ctx.cases.append(Case{ | 236 | ctx.cases.append(Case{ |
| 244 | .name = name, | 237 | .name = name, |
| 245 | .target = target, | 238 | .target = target, |
| 246 | .updates = std.ArrayList(Update).init(ctx.cases.allocator), | 239 | .updates = std.ArrayList(Update).init(ctx.cases.allocator), |
| 247 | .output_mode = .Exe, | 240 | .output_mode = .Exe, |
| 248 | .extension = extension, | ||
| 249 | .files = std.ArrayList(File).init(ctx.cases.allocator), | 241 | .files = std.ArrayList(File).init(ctx.cases.allocator), |
| 250 | }) catch @panic("out of memory"); | 242 | }) catch @panic("out of memory"); |
| 251 | return &ctx.cases.items[ctx.cases.items.len - 1]; | 243 | return &ctx.cases.items[ctx.cases.items.len - 1]; |
| ... | @@ -253,7 +245,7 @@ pub const TestContext = struct { | ... | @@ -253,7 +245,7 @@ pub const TestContext = struct { |
| 253 | 245 | ||
| 254 | /// Adds a test case for Zig input, producing an executable | 246 | /// Adds a test case for Zig input, producing an executable |
| 255 | pub fn exe(ctx: *TestContext, name: []const u8, target: CrossTarget) *Case { | 247 | pub fn exe(ctx: *TestContext, name: []const u8, target: CrossTarget) *Case { |
| 256 | return ctx.addExe(name, target, .Zig); | 248 | return ctx.addExe(name, target); |
| 257 | } | 249 | } |
| 258 | 250 | ||
| 259 | /// Adds a test case for ZIR input, producing an executable | 251 | /// Adds a test case for ZIR input, producing an executable |
| ... | @@ -269,7 +261,6 @@ pub const TestContext = struct { | ... | @@ -269,7 +261,6 @@ pub const TestContext = struct { |
| 269 | .target = target, | 261 | .target = target, |
| 270 | .updates = std.ArrayList(Update).init(ctx.cases.allocator), | 262 | .updates = std.ArrayList(Update).init(ctx.cases.allocator), |
| 271 | .output_mode = .Exe, | 263 | .output_mode = .Exe, |
| 272 | .extension = .Zig, | ||
| 273 | .object_format = .c, | 264 | .object_format = .c, |
| 274 | .files = std.ArrayList(File).init(ctx.cases.allocator), | 265 | .files = std.ArrayList(File).init(ctx.cases.allocator), |
| 275 | }) catch @panic("out of memory"); | 266 | }) catch @panic("out of memory"); |
| ... | @@ -284,7 +275,6 @@ pub const TestContext = struct { | ... | @@ -284,7 +275,6 @@ pub const TestContext = struct { |
| 284 | .target = target, | 275 | .target = target, |
| 285 | .updates = std.ArrayList(Update).init(ctx.cases.allocator), | 276 | .updates = std.ArrayList(Update).init(ctx.cases.allocator), |
| 286 | .output_mode = .Exe, | 277 | .output_mode = .Exe, |
| 287 | .extension = .Zig, | ||
| 288 | .files = std.ArrayList(File).init(ctx.cases.allocator), | 278 | .files = std.ArrayList(File).init(ctx.cases.allocator), |
| 289 | .llvm_backend = true, | 279 | .llvm_backend = true, |
| 290 | }) catch @panic("out of memory"); | 280 | }) catch @panic("out of memory"); |
| ... | @@ -295,14 +285,12 @@ pub const TestContext = struct { | ... | @@ -295,14 +285,12 @@ pub const TestContext = struct { |
| 295 | ctx: *TestContext, | 285 | ctx: *TestContext, |
| 296 | name: []const u8, | 286 | name: []const u8, |
| 297 | target: CrossTarget, | 287 | target: CrossTarget, |
| 298 | extension: Extension, | ||
| 299 | ) *Case { | 288 | ) *Case { |
| 300 | ctx.cases.append(Case{ | 289 | ctx.cases.append(Case{ |
| 301 | .name = name, | 290 | .name = name, |
| 302 | .target = target, | 291 | .target = target, |
| 303 | .updates = std.ArrayList(Update).init(ctx.cases.allocator), | 292 | .updates = std.ArrayList(Update).init(ctx.cases.allocator), |
| 304 | .output_mode = .Obj, | 293 | .output_mode = .Obj, |
| 305 | .extension = extension, | ||
| 306 | .files = std.ArrayList(File).init(ctx.cases.allocator), | 294 | .files = std.ArrayList(File).init(ctx.cases.allocator), |
| 307 | }) catch @panic("out of memory"); | 295 | }) catch @panic("out of memory"); |
| 308 | return &ctx.cases.items[ctx.cases.items.len - 1]; | 296 | return &ctx.cases.items[ctx.cases.items.len - 1]; |
| ... | @@ -310,7 +298,7 @@ pub const TestContext = struct { | ... | @@ -310,7 +298,7 @@ pub const TestContext = struct { |
| 310 | 298 | ||
| 311 | /// Adds a test case for Zig input, producing an object file. | 299 | /// Adds a test case for Zig input, producing an object file. |
| 312 | pub fn obj(ctx: *TestContext, name: []const u8, target: CrossTarget) *Case { | 300 | pub fn obj(ctx: *TestContext, name: []const u8, target: CrossTarget) *Case { |
| 313 | return ctx.addObj(name, target, .Zig); | 301 | return ctx.addObj(name, target); |
| 314 | } | 302 | } |
| 315 | 303 | ||
| 316 | /// Adds a test case for ZIR input, producing an object file. | 304 | /// Adds a test case for ZIR input, producing an object file. |
| ... | @@ -319,13 +307,12 @@ pub const TestContext = struct { | ... | @@ -319,13 +307,12 @@ pub const TestContext = struct { |
| 319 | } | 307 | } |
| 320 | 308 | ||
| 321 | /// Adds a test case for Zig or ZIR input, producing C code. | 309 | /// Adds a test case for Zig or ZIR input, producing C code. |
| 322 | pub fn addC(ctx: *TestContext, name: []const u8, target: CrossTarget, ext: Extension) *Case { | 310 | pub fn addC(ctx: *TestContext, name: []const u8, target: CrossTarget) *Case { |
| 323 | ctx.cases.append(Case{ | 311 | ctx.cases.append(Case{ |
| 324 | .name = name, | 312 | .name = name, |
| 325 | .target = target, | 313 | .target = target, |
| 326 | .updates = std.ArrayList(Update).init(ctx.cases.allocator), | 314 | .updates = std.ArrayList(Update).init(ctx.cases.allocator), |
| 327 | .output_mode = .Obj, | 315 | .output_mode = .Obj, |
| 328 | .extension = ext, | ||
| 329 | .object_format = .c, | 316 | .object_format = .c, |
| 330 | .files = std.ArrayList(File).init(ctx.cases.allocator), | 317 | .files = std.ArrayList(File).init(ctx.cases.allocator), |
| 331 | }) catch @panic("out of memory"); | 318 | }) catch @panic("out of memory"); |
| ... | @@ -333,21 +320,20 @@ pub const TestContext = struct { | ... | @@ -333,21 +320,20 @@ pub const TestContext = struct { |
| 333 | } | 320 | } |
| 334 | 321 | ||
| 335 | pub fn c(ctx: *TestContext, name: []const u8, target: CrossTarget, src: [:0]const u8, comptime out: [:0]const u8) void { | 322 | pub fn c(ctx: *TestContext, name: []const u8, target: CrossTarget, src: [:0]const u8, comptime out: [:0]const u8) void { |
| 336 | ctx.addC(name, target, .Zig).addCompareObjectFile(src, zig_h ++ out); | 323 | ctx.addC(name, target).addCompareObjectFile(src, zig_h ++ out); |
| 337 | } | 324 | } |
| 338 | 325 | ||
| 339 | pub fn h(ctx: *TestContext, name: []const u8, target: CrossTarget, src: [:0]const u8, comptime out: [:0]const u8) void { | 326 | pub fn h(ctx: *TestContext, name: []const u8, target: CrossTarget, src: [:0]const u8, comptime out: [:0]const u8) void { |
| 340 | ctx.addC(name, target, .Zig).addHeader(src, zig_h ++ out); | 327 | ctx.addC(name, target).addHeader(src, zig_h ++ out); |
| 341 | } | 328 | } |
| 342 | 329 | ||
| 343 | pub fn addCompareOutput( | 330 | pub fn addCompareOutput( |
| 344 | ctx: *TestContext, | 331 | ctx: *TestContext, |
| 345 | name: []const u8, | 332 | name: []const u8, |
| 346 | extension: Extension, | ||
| 347 | src: [:0]const u8, | 333 | src: [:0]const u8, |
| 348 | expected_stdout: []const u8, | 334 | expected_stdout: []const u8, |
| 349 | ) void { | 335 | ) void { |
| 350 | ctx.addExe(name, .{}, extension).addCompareOutput(src, expected_stdout); | 336 | ctx.addExe(name, .{}).addCompareOutput(src, expected_stdout); |
| 351 | } | 337 | } |
| 352 | 338 | ||
| 353 | /// Adds a test case that compiles the Zig source given in `src`, executes | 339 | /// Adds a test case that compiles the Zig source given in `src`, executes |
| ... | @@ -358,7 +344,7 @@ pub const TestContext = struct { | ... | @@ -358,7 +344,7 @@ pub const TestContext = struct { |
| 358 | src: [:0]const u8, | 344 | src: [:0]const u8, |
| 359 | expected_stdout: []const u8, | 345 | expected_stdout: []const u8, |
| 360 | ) void { | 346 | ) void { |
| 361 | return ctx.addCompareOutput(name, .Zig, src, expected_stdout); | 347 | return ctx.addCompareOutput(name, src, expected_stdout); |
| 362 | } | 348 | } |
| 363 | 349 | ||
| 364 | /// Adds a test case that compiles the ZIR source given in `src`, executes | 350 | /// Adds a test case that compiles the ZIR source given in `src`, executes |
| ... | @@ -376,11 +362,10 @@ pub const TestContext = struct { | ... | @@ -376,11 +362,10 @@ pub const TestContext = struct { |
| 376 | ctx: *TestContext, | 362 | ctx: *TestContext, |
| 377 | name: []const u8, | 363 | name: []const u8, |
| 378 | target: CrossTarget, | 364 | target: CrossTarget, |
| 379 | extension: Extension, | ||
| 380 | src: [:0]const u8, | 365 | src: [:0]const u8, |
| 381 | result: [:0]const u8, | 366 | result: [:0]const u8, |
| 382 | ) void { | 367 | ) void { |
| 383 | ctx.addObj(name, target, extension).addTransform(src, result); | 368 | ctx.addObj(name, target).addTransform(src, result); |
| 384 | } | 369 | } |
| 385 | 370 | ||
| 386 | /// Adds a test case that compiles the Zig given in `src` to ZIR and tests | 371 | /// Adds a test case that compiles the Zig given in `src` to ZIR and tests |
| ... | @@ -392,7 +377,7 @@ pub const TestContext = struct { | ... | @@ -392,7 +377,7 @@ pub const TestContext = struct { |
| 392 | src: [:0]const u8, | 377 | src: [:0]const u8, |
| 393 | result: [:0]const u8, | 378 | result: [:0]const u8, |
| 394 | ) void { | 379 | ) void { |
| 395 | ctx.addTransform(name, target, .Zig, src, result); | 380 | ctx.addTransform(name, target, src, result); |
| 396 | } | 381 | } |
| 397 | 382 | ||
| 398 | /// Adds a test case that cleans up the ZIR source given in `src`, and | 383 | /// Adds a test case that cleans up the ZIR source given in `src`, and |
| ... | @@ -411,11 +396,10 @@ pub const TestContext = struct { | ... | @@ -411,11 +396,10 @@ pub const TestContext = struct { |
| 411 | ctx: *TestContext, | 396 | ctx: *TestContext, |
| 412 | name: []const u8, | 397 | name: []const u8, |
| 413 | target: CrossTarget, | 398 | target: CrossTarget, |
| 414 | extension: Extension, | ||
| 415 | src: [:0]const u8, | 399 | src: [:0]const u8, |
| 416 | expected_errors: []const []const u8, | 400 | expected_errors: []const []const u8, |
| 417 | ) void { | 401 | ) void { |
| 418 | ctx.addObj(name, target, extension).addError(src, expected_errors); | 402 | ctx.addObj(name, target).addError(src, expected_errors); |
| 419 | } | 403 | } |
| 420 | 404 | ||
| 421 | /// Adds a test case that ensures that the Zig given in `src` fails to | 405 | /// Adds a test case that ensures that the Zig given in `src` fails to |
| ... | @@ -428,7 +412,7 @@ pub const TestContext = struct { | ... | @@ -428,7 +412,7 @@ pub const TestContext = struct { |
| 428 | src: [:0]const u8, | 412 | src: [:0]const u8, |
| 429 | expected_errors: []const []const u8, | 413 | expected_errors: []const []const u8, |
| 430 | ) void { | 414 | ) void { |
| 431 | ctx.addError(name, target, .Zig, src, expected_errors); | 415 | ctx.addError(name, target, src, expected_errors); |
| 432 | } | 416 | } |
| 433 | 417 | ||
| 434 | /// Adds a test case that ensures that the ZIR given in `src` fails to | 418 | /// Adds a test case that ensures that the ZIR given in `src` fails to |
| ... | @@ -448,10 +432,9 @@ pub const TestContext = struct { | ... | @@ -448,10 +432,9 @@ pub const TestContext = struct { |
| 448 | ctx: *TestContext, | 432 | ctx: *TestContext, |
| 449 | name: []const u8, | 433 | name: []const u8, |
| 450 | target: CrossTarget, | 434 | target: CrossTarget, |
| 451 | extension: Extension, | ||
| 452 | src: [:0]const u8, | 435 | src: [:0]const u8, |
| 453 | ) void { | 436 | ) void { |
| 454 | ctx.addObj(name, target, extension).compiles(src); | 437 | ctx.addObj(name, target).compiles(src); |
| 455 | } | 438 | } |
| 456 | 439 | ||
| 457 | /// Adds a test case that asserts that the Zig given in `src` compiles | 440 | /// Adds a test case that asserts that the Zig given in `src` compiles |
| ... | @@ -462,7 +445,7 @@ pub const TestContext = struct { | ... | @@ -462,7 +445,7 @@ pub const TestContext = struct { |
| 462 | target: CrossTarget, | 445 | target: CrossTarget, |
| 463 | src: [:0]const u8, | 446 | src: [:0]const u8, |
| 464 | ) void { | 447 | ) void { |
| 465 | ctx.addCompiles(name, target, .Zig, src); | 448 | ctx.addCompiles(name, target, src); |
| 466 | } | 449 | } |
| 467 | 450 | ||
| 468 | /// Adds a test case that asserts that the ZIR given in `src` compiles | 451 | /// Adds a test case that asserts that the ZIR given in `src` compiles |
| ... | @@ -489,7 +472,7 @@ pub const TestContext = struct { | ... | @@ -489,7 +472,7 @@ pub const TestContext = struct { |
| 489 | expected_errors: []const []const u8, | 472 | expected_errors: []const []const u8, |
| 490 | fixed_src: [:0]const u8, | 473 | fixed_src: [:0]const u8, |
| 491 | ) void { | 474 | ) void { |
| 492 | var case = ctx.addObj(name, target, .Zig); | 475 | var case = ctx.addObj(name, target); |
| 493 | case.addError(src, expected_errors); | 476 | case.addError(src, expected_errors); |
| 494 | case.compiles(fixed_src); | 477 | case.compiles(fixed_src); |
| 495 | } | 478 | } |
| ... | @@ -614,15 +597,14 @@ pub const TestContext = struct { | ... | @@ -614,15 +597,14 @@ pub const TestContext = struct { |
| 614 | .path = try std.fs.path.join(arena, &[_][]const u8{ tmp_dir_path, "zig-cache" }), | 597 | .path = try std.fs.path.join(arena, &[_][]const u8{ tmp_dir_path, "zig-cache" }), |
| 615 | }; | 598 | }; |
| 616 | 599 | ||
| 617 | const tmp_src_path = switch (case.extension) { | 600 | const tmp_src_path = "test_case.zig"; |
| 618 | .Zig => "test_case.zig", | ||
| 619 | .ZIR => "test_case.zir", | ||
| 620 | }; | ||
| 621 | 601 | ||
| 622 | var root_pkg: Package = .{ | 602 | var root_pkg: Package = .{ |
| 623 | .root_src_directory = .{ .path = tmp_dir_path, .handle = tmp.dir }, | 603 | .root_src_directory = .{ .path = tmp_dir_path, .handle = tmp.dir }, |
| 624 | .root_src_path = tmp_src_path, | 604 | .root_src_path = tmp_src_path, |
| 605 | .namespace_hash = Package.root_namespace_hash, | ||
| 625 | }; | 606 | }; |
| 607 | defer root_pkg.table.deinit(allocator); | ||
| 626 | 608 | ||
| 627 | const bin_name = try std.zig.binNameAlloc(arena, .{ | 609 | const bin_name = try std.zig.binNameAlloc(arena, .{ |
| 628 | .root_name = "test_case", | 610 | .root_name = "test_case", |
| ... | @@ -639,13 +621,10 @@ pub const TestContext = struct { | ... | @@ -639,13 +621,10 @@ pub const TestContext = struct { |
| 639 | .directory = emit_directory, | 621 | .directory = emit_directory, |
| 640 | .basename = bin_name, | 622 | .basename = bin_name, |
| 641 | }; | 623 | }; |
| 642 | const emit_h: ?Compilation.EmitLoc = if (case.emit_h) | 624 | const emit_h: ?Compilation.EmitLoc = if (case.emit_h) .{ |
| 643 | .{ | 625 | .directory = emit_directory, |
| 644 | .directory = emit_directory, | 626 | .basename = "test_case.h", |
| 645 | .basename = "test_case.h", | 627 | } else null; |
| 646 | } | ||
| 647 | else | ||
| 648 | null; | ||
| 649 | const comp = try Compilation.create(allocator, .{ | 628 | const comp = try Compilation.create(allocator, .{ |
| 650 | .local_cache_directory = zig_cache_directory, | 629 | .local_cache_directory = zig_cache_directory, |
| 651 | .global_cache_directory = global_cache_directory, | 630 | .global_cache_directory = global_cache_directory, |
src/zir.zig+43| ... | @@ -328,6 +328,9 @@ pub const Inst = struct { | ... | @@ -328,6 +328,9 @@ pub const Inst = struct { |
| 328 | error_union_type, | 328 | error_union_type, |
| 329 | /// `error.Foo` syntax. Uses the `str_tok` field of the Data union. | 329 | /// `error.Foo` syntax. Uses the `str_tok` field of the Data union. |
| 330 | error_value, | 330 | error_value, |
| 331 | /// Implements the `@export` builtin function. | ||
| 332 | /// Uses the `pl_node` union field. Payload is `Bin`. | ||
| 333 | @"export", | ||
| 331 | /// Given a pointer to a struct or object that contains virtual fields, returns a pointer | 334 | /// Given a pointer to a struct or object that contains virtual fields, returns a pointer |
| 332 | /// to the named field. The field name is stored in string_bytes. Used by a.b syntax. | 335 | /// to the named field. The field name is stored in string_bytes. Used by a.b syntax. |
| 333 | /// Uses `pl_node` field. The AST node is the a.b syntax. Payload is Field. | 336 | /// Uses `pl_node` field. The AST node is the a.b syntax. Payload is Field. |
| ... | @@ -360,6 +363,9 @@ pub const Inst = struct { | ... | @@ -360,6 +363,9 @@ pub const Inst = struct { |
| 360 | fn_type_cc, | 363 | fn_type_cc, |
| 361 | /// Same as `fn_type_cc` but the function is variadic. | 364 | /// Same as `fn_type_cc` but the function is variadic. |
| 362 | fn_type_cc_var_args, | 365 | fn_type_cc_var_args, |
| 366 | /// Implements the `@hasDecl` builtin. | ||
| 367 | /// Uses the `pl_node` union field. Payload is `Bin`. | ||
| 368 | has_decl, | ||
| 363 | /// `@import(operand)`. | 369 | /// `@import(operand)`. |
| 364 | /// Uses the `un_node` field. | 370 | /// Uses the `un_node` field. |
| 365 | import, | 371 | import, |
| ... | @@ -668,12 +674,21 @@ pub const Inst = struct { | ... | @@ -668,12 +674,21 @@ pub const Inst = struct { |
| 668 | /// A struct literal with a specified type, with no fields. | 674 | /// A struct literal with a specified type, with no fields. |
| 669 | /// Uses the `un_node` field. | 675 | /// Uses the `un_node` field. |
| 670 | struct_init_empty, | 676 | struct_init_empty, |
| 677 | /// Given a struct, union, enum, or opaque and a field name, returns the field type. | ||
| 678 | /// Uses the `pl_node` field. Payload is `FieldType`. | ||
| 679 | field_type, | ||
| 680 | /// Finalizes a typed struct initialization, performs validation, and returns the | ||
| 681 | /// struct value. | ||
| 682 | /// Uses the `pl_node` field. Payload is `StructInit`. | ||
| 683 | struct_init, | ||
| 671 | /// Converts an integer into an enum value. | 684 | /// Converts an integer into an enum value. |
| 672 | /// Uses `pl_node` with payload `Bin`. `lhs` is enum type, `rhs` is operand. | 685 | /// Uses `pl_node` with payload `Bin`. `lhs` is enum type, `rhs` is operand. |
| 673 | int_to_enum, | 686 | int_to_enum, |
| 674 | /// Converts an enum value into an integer. Resulting type will be the tag type | 687 | /// Converts an enum value into an integer. Resulting type will be the tag type |
| 675 | /// of the enum. Uses `un_node`. | 688 | /// of the enum. Uses `un_node`. |
| 676 | enum_to_int, | 689 | enum_to_int, |
| 690 | /// Implements the `@typeInfo` builtin. Uses `un_node`. | ||
| 691 | type_info, | ||
| 677 | 692 | ||
| 678 | /// Returns whether the instruction is one of the control flow "noreturn" types. | 693 | /// Returns whether the instruction is one of the control flow "noreturn" types. |
| 679 | /// Function calls do not count. | 694 | /// Function calls do not count. |
| ... | @@ -737,6 +752,7 @@ pub const Inst = struct { | ... | @@ -737,6 +752,7 @@ pub const Inst = struct { |
| 737 | .elem_val_node, | 752 | .elem_val_node, |
| 738 | .ensure_result_used, | 753 | .ensure_result_used, |
| 739 | .ensure_result_non_error, | 754 | .ensure_result_non_error, |
| 755 | .@"export", | ||
| 740 | .floatcast, | 756 | .floatcast, |
| 741 | .field_ptr, | 757 | .field_ptr, |
| 742 | .field_val, | 758 | .field_val, |
| ... | @@ -746,6 +762,7 @@ pub const Inst = struct { | ... | @@ -746,6 +762,7 @@ pub const Inst = struct { |
| 746 | .fn_type_var_args, | 762 | .fn_type_var_args, |
| 747 | .fn_type_cc, | 763 | .fn_type_cc, |
| 748 | .fn_type_cc_var_args, | 764 | .fn_type_cc_var_args, |
| 765 | .has_decl, | ||
| 749 | .int, | 766 | .int, |
| 750 | .float, | 767 | .float, |
| 751 | .float128, | 768 | .float128, |
| ... | @@ -831,8 +848,11 @@ pub const Inst = struct { | ... | @@ -831,8 +848,11 @@ pub const Inst = struct { |
| 831 | .switch_block_ref_under_multi, | 848 | .switch_block_ref_under_multi, |
| 832 | .validate_struct_init_ptr, | 849 | .validate_struct_init_ptr, |
| 833 | .struct_init_empty, | 850 | .struct_init_empty, |
| 851 | .struct_init, | ||
| 852 | .field_type, | ||
| 834 | .int_to_enum, | 853 | .int_to_enum, |
| 835 | .enum_to_int, | 854 | .enum_to_int, |
| 855 | .type_info, | ||
| 836 | => false, | 856 | => false, |
| 837 | 857 | ||
| 838 | .@"break", | 858 | .@"break", |
| ... | @@ -1543,6 +1563,24 @@ pub const Inst = struct { | ... | @@ -1543,6 +1563,24 @@ pub const Inst = struct { |
| 1543 | return @bitCast(f128, int_bits); | 1563 | return @bitCast(f128, int_bits); |
| 1544 | } | 1564 | } |
| 1545 | }; | 1565 | }; |
| 1566 | |||
| 1567 | /// Trailing is an item per field. | ||
| 1568 | pub const StructInit = struct { | ||
| 1569 | fields_len: u32, | ||
| 1570 | |||
| 1571 | pub const Item = struct { | ||
| 1572 | /// The `field_type` ZIR instruction for this field init. | ||
| 1573 | field_type: Index, | ||
| 1574 | /// The field init expression to be used as the field value. | ||
| 1575 | init: Ref, | ||
| 1576 | }; | ||
| 1577 | }; | ||
| 1578 | |||
| 1579 | pub const FieldType = struct { | ||
| 1580 | container_type: Ref, | ||
| 1581 | /// Offset into `string_bytes`, null terminated. | ||
| 1582 | name_start: u32, | ||
| 1583 | }; | ||
| 1546 | }; | 1584 | }; |
| 1547 | 1585 | ||
| 1548 | pub const SpecialProng = enum { none, @"else", under }; | 1586 | pub const SpecialProng = enum { none, @"else", under }; |
| ... | @@ -1617,6 +1655,7 @@ const Writer = struct { | ... | @@ -1617,6 +1655,7 @@ const Writer = struct { |
| 1617 | .typeof_elem, | 1655 | .typeof_elem, |
| 1618 | .struct_init_empty, | 1656 | .struct_init_empty, |
| 1619 | .enum_to_int, | 1657 | .enum_to_int, |
| 1658 | .type_info, | ||
| 1620 | => try self.writeUnNode(stream, inst), | 1659 | => try self.writeUnNode(stream, inst), |
| 1621 | 1660 | ||
| 1622 | .ref, | 1661 | .ref, |
| ... | @@ -1657,6 +1696,8 @@ const Writer = struct { | ... | @@ -1657,6 +1696,8 @@ const Writer = struct { |
| 1657 | .union_decl, | 1696 | .union_decl, |
| 1658 | .enum_decl, | 1697 | .enum_decl, |
| 1659 | .enum_decl_nonexhaustive, | 1698 | .enum_decl_nonexhaustive, |
| 1699 | .struct_init, | ||
| 1700 | .field_type, | ||
| 1660 | => try self.writePlNode(stream, inst), | 1701 | => try self.writePlNode(stream, inst), |
| 1661 | 1702 | ||
| 1662 | .add, | 1703 | .add, |
| ... | @@ -1676,12 +1717,14 @@ const Writer = struct { | ... | @@ -1676,12 +1717,14 @@ const Writer = struct { |
| 1676 | .cmp_gt, | 1717 | .cmp_gt, |
| 1677 | .cmp_neq, | 1718 | .cmp_neq, |
| 1678 | .div, | 1719 | .div, |
| 1720 | .has_decl, | ||
| 1679 | .mod_rem, | 1721 | .mod_rem, |
| 1680 | .shl, | 1722 | .shl, |
| 1681 | .shr, | 1723 | .shr, |
| 1682 | .xor, | 1724 | .xor, |
| 1683 | .store_node, | 1725 | .store_node, |
| 1684 | .error_union_type, | 1726 | .error_union_type, |
| 1727 | .@"export", | ||
| 1685 | .merge_error_sets, | 1728 | .merge_error_sets, |
| 1686 | .bit_and, | 1729 | .bit_and, |
| 1687 | .bit_or, | 1730 | .bit_or, |
test/stack_traces.zig+3-3| ... | @@ -282,10 +282,10 @@ pub fn addCases(cases: *tests.StackTracesContext) void { | ... | @@ -282,10 +282,10 @@ pub fn addCases(cases: *tests.StackTracesContext) void { |
| 282 | \\source.zig:10:8: [address] in main (test) | 282 | \\source.zig:10:8: [address] in main (test) |
| 283 | \\ foo(); | 283 | \\ foo(); |
| 284 | \\ ^ | 284 | \\ ^ |
| 285 | \\start.zig:342:29: [address] in std.start.posixCallMainAndExit (test) | 285 | \\start.zig:404:29: [address] in std.start.posixCallMainAndExit (test) |
| 286 | \\ return root.main(); | 286 | \\ return root.main(); |
| 287 | \\ ^ | 287 | \\ ^ |
| 288 | \\start.zig:163:5: [address] in std.start._start (test) | 288 | \\start.zig:225:5: [address] in std.start._start (test) |
| 289 | \\ @call(.{ .modifier = .never_inline }, posixCallMainAndExit, .{}); | 289 | \\ @call(.{ .modifier = .never_inline }, posixCallMainAndExit, .{}); |
| 290 | \\ ^ | 290 | \\ ^ |
| 291 | \\ | 291 | \\ |
| ... | @@ -294,7 +294,7 @@ pub fn addCases(cases: *tests.StackTracesContext) void { | ... | @@ -294,7 +294,7 @@ pub fn addCases(cases: *tests.StackTracesContext) void { |
| 294 | switch (std.Target.current.cpu.arch) { | 294 | switch (std.Target.current.cpu.arch) { |
| 295 | .aarch64 => "", // TODO disabled; results in segfault | 295 | .aarch64 => "", // TODO disabled; results in segfault |
| 296 | else => | 296 | else => |
| 297 | \\start.zig:163:5: [address] in std.start._start (test) | 297 | \\start.zig:225:5: [address] in std.start._start (test) |
| 298 | \\ @call(.{ .modifier = .never_inline }, posixCallMainAndExit, .{}); | 298 | \\ @call(.{ .modifier = .never_inline }, posixCallMainAndExit, .{}); |
| 299 | \\ ^ | 299 | \\ ^ |
| 300 | \\ | 300 | \\ |
test/stage2/test.zig+78-2| ... | @@ -941,6 +941,32 @@ pub fn addCases(ctx: *TestContext) !void { | ... | @@ -941,6 +941,32 @@ pub fn addCases(ctx: *TestContext) !void { |
| 941 | "", | 941 | "", |
| 942 | ); | 942 | ); |
| 943 | 943 | ||
| 944 | // Array access to a global array. | ||
| 945 | case.addCompareOutput( | ||
| 946 | \\const hello = "hello".*; | ||
| 947 | \\export fn _start() noreturn { | ||
| 948 | \\ assert(hello[1] == 'e'); | ||
| 949 | \\ | ||
| 950 | \\ exit(); | ||
| 951 | \\} | ||
| 952 | \\ | ||
| 953 | \\pub fn assert(ok: bool) void { | ||
| 954 | \\ if (!ok) unreachable; // assertion failure | ||
| 955 | \\} | ||
| 956 | \\ | ||
| 957 | \\fn exit() noreturn { | ||
| 958 | \\ asm volatile ("syscall" | ||
| 959 | \\ : | ||
| 960 | \\ : [number] "{rax}" (231), | ||
| 961 | \\ [arg1] "{rdi}" (0) | ||
| 962 | \\ : "rcx", "r11", "memory" | ||
| 963 | \\ ); | ||
| 964 | \\ unreachable; | ||
| 965 | \\} | ||
| 966 | , | ||
| 967 | "", | ||
| 968 | ); | ||
| 969 | |||
| 944 | // 64bit set stack | 970 | // 64bit set stack |
| 945 | case.addCompareOutput( | 971 | case.addCompareOutput( |
| 946 | \\export fn _start() noreturn { | 972 | \\export fn _start() noreturn { |
| ... | @@ -1022,7 +1048,7 @@ pub fn addCases(ctx: *TestContext) !void { | ... | @@ -1022,7 +1048,7 @@ pub fn addCases(ctx: *TestContext) !void { |
| 1022 | "Hello, World!\n", | 1048 | "Hello, World!\n", |
| 1023 | ); | 1049 | ); |
| 1024 | try case.files.append(.{ | 1050 | try case.files.append(.{ |
| 1025 | .src = | 1051 | .src = |
| 1026 | \\pub fn print() void { | 1052 | \\pub fn print() void { |
| 1027 | \\ asm volatile ("syscall" | 1053 | \\ asm volatile ("syscall" |
| 1028 | \\ : | 1054 | \\ : |
| ... | @@ -1038,11 +1064,61 @@ pub fn addCases(ctx: *TestContext) !void { | ... | @@ -1038,11 +1064,61 @@ pub fn addCases(ctx: *TestContext) !void { |
| 1038 | .path = "print.zig", | 1064 | .path = "print.zig", |
| 1039 | }); | 1065 | }); |
| 1040 | } | 1066 | } |
| 1067 | { | ||
| 1068 | var case = ctx.exe("import private", linux_x64); | ||
| 1069 | case.addError( | ||
| 1070 | \\export fn _start() noreturn { | ||
| 1071 | \\ @import("print.zig").print(); | ||
| 1072 | \\ exit(); | ||
| 1073 | \\} | ||
| 1074 | \\ | ||
| 1075 | \\fn exit() noreturn { | ||
| 1076 | \\ asm volatile ("syscall" | ||
| 1077 | \\ : | ||
| 1078 | \\ : [number] "{rax}" (231), | ||
| 1079 | \\ [arg1] "{rdi}" (@as(usize, 0)) | ||
| 1080 | \\ : "rcx", "r11", "memory" | ||
| 1081 | \\ ); | ||
| 1082 | \\ unreachable; | ||
| 1083 | \\} | ||
| 1084 | , | ||
| 1085 | &.{":2:25: error: 'print' is private"}, | ||
| 1086 | ); | ||
| 1087 | try case.files.append(.{ | ||
| 1088 | .src = | ||
| 1089 | \\fn print() void { | ||
| 1090 | \\ asm volatile ("syscall" | ||
| 1091 | \\ : | ||
| 1092 | \\ : [number] "{rax}" (@as(usize, 1)), | ||
| 1093 | \\ [arg1] "{rdi}" (@as(usize, 1)), | ||
| 1094 | \\ [arg2] "{rsi}" (@ptrToInt("Hello, World!\n")), | ||
| 1095 | \\ [arg3] "{rdx}" (@as(usize, 14)) | ||
| 1096 | \\ : "rcx", "r11", "memory" | ||
| 1097 | \\ ); | ||
| 1098 | \\ return; | ||
| 1099 | \\} | ||
| 1100 | , | ||
| 1101 | .path = "print.zig", | ||
| 1102 | }); | ||
| 1103 | } | ||
| 1041 | 1104 | ||
| 1042 | ctx.compileError("function redefinition", linux_x64, | 1105 | ctx.compileError("function redefinition", linux_x64, |
| 1106 | \\// dummy comment | ||
| 1043 | \\fn entry() void {} | 1107 | \\fn entry() void {} |
| 1044 | \\fn entry() void {} | 1108 | \\fn entry() void {} |
| 1045 | , &[_][]const u8{":2:4: error: redefinition of 'entry'"}); | 1109 | , &[_][]const u8{ |
| 1110 | ":3:4: error: redefinition of 'entry'", | ||
| 1111 | ":2:1: note: previous definition here", | ||
| 1112 | }); | ||
| 1113 | |||
| 1114 | ctx.compileError("global variable redefinition", linux_x64, | ||
| 1115 | \\// dummy comment | ||
| 1116 | \\var foo = false; | ||
| 1117 | \\var foo = true; | ||
| 1118 | , &[_][]const u8{ | ||
| 1119 | ":3:5: error: redefinition of 'foo'", | ||
| 1120 | ":2:1: note: previous definition here", | ||
| 1121 | }); | ||
| 1046 | 1122 | ||
| 1047 | ctx.compileError("compileError", linux_x64, | 1123 | ctx.compileError("compileError", linux_x64, |
| 1048 | \\export fn _start() noreturn { | 1124 | \\export fn _start() noreturn { |