| author | |
| committer | |
| log | f75cdd1acd0929792c33766bd1d093d897c65113 |
| tree | 4f67752f34d4d3d8b78631b48d48fb971000c7a1 |
| parent | 952032b40cd6e3dbffc5642d17a7a05fa7c83895 |
| parent | afe5862111034ea4100b0eea5971e181d70ffc39 |
| signature |
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 | |
| 8 | 8 | const root = @import("root"); |
| 9 | 9 | const std = @import("std.zig"); |
| 10 | const builtin = std.builtin; | |
| 10 | const builtin = @import("builtin"); | |
| 11 | 11 | const assert = std.debug.assert; |
| 12 | 12 | const uefi = std.os.uefi; |
| 13 | 13 | const tlcsprng = @import("crypto/tlcsprng.zig"); |
| ... | ... | @@ -17,39 +17,101 @@ var argc_argv_ptr: [*]usize = undefined; |
| 17 | 17 | const start_sym_name = if (builtin.arch.isMIPS()) "__start" else "_start"; |
| 18 | 18 | |
| 19 | 19 | comptime { |
| 20 | if (builtin.output_mode == .Lib and builtin.link_mode == .Dynamic) { | |
| 21 | if (builtin.os.tag == .windows and !@hasDecl(root, "_DllMainCRTStartup")) { | |
| 22 | @export(_DllMainCRTStartup, .{ .name = "_DllMainCRTStartup" }); | |
| 20 | // The self-hosted compiler is not fully capable of handling all of this start.zig file. | |
| 21 | // Until then, we have simplified logic here for self-hosted. TODO remove this once | |
| 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")) { | |
| 25 | if (builtin.link_libc and @hasDecl(root, "main")) { | |
| 26 | if (@typeInfo(@TypeOf(root.main)).Fn.calling_convention != .C) { | |
| 27 | @export(main, .{ .name = "main", .linkage = .Weak }); | |
| 35 | } else { | |
| 36 | if (builtin.output_mode == .Lib and builtin.link_mode == .Dynamic) { | |
| 37 | if (builtin.os.tag == .windows and !@hasDecl(root, "_DllMainCRTStartup")) { | |
| 38 | @export(_DllMainCRTStartup, .{ .name = "_DllMainCRTStartup" }); | |
| 28 | 39 | } |
| 29 | } else if (builtin.os.tag == .windows) { | |
| 30 | if (!@hasDecl(root, "WinMain") and !@hasDecl(root, "WinMainCRTStartup") and | |
| 31 | !@hasDecl(root, "wWinMain") and !@hasDecl(root, "wWinMainCRTStartup")) | |
| 32 | { | |
| 33 | @export(WinStartup, .{ .name = "wWinMainCRTStartup" }); | |
| 34 | } else if (@hasDecl(root, "WinMain") and !@hasDecl(root, "WinMainCRTStartup") and | |
| 35 | !@hasDecl(root, "wWinMain") and !@hasDecl(root, "wWinMainCRTStartup")) | |
| 36 | { | |
| 37 | @compileError("WinMain not supported; declare wWinMain or main instead"); | |
| 38 | } else if (@hasDecl(root, "wWinMain") and !@hasDecl(root, "wWinMainCRTStartup") and | |
| 39 | !@hasDecl(root, "WinMain") and !@hasDecl(root, "WinMainCRTStartup")) | |
| 40 | { | |
| 41 | @export(wWinMainCRTStartup, .{ .name = "wWinMainCRTStartup" }); | |
| 40 | } else if (builtin.output_mode == .Exe or @hasDecl(root, "main")) { | |
| 41 | if (builtin.link_libc and @hasDecl(root, "main")) { | |
| 42 | if (@typeInfo(@TypeOf(root.main)).Fn.calling_convention != .C) { | |
| 43 | @export(main, .{ .name = "main", .linkage = .Weak }); | |
| 44 | } | |
| 45 | } else if (builtin.os.tag == .windows) { | |
| 46 | if (!@hasDecl(root, "WinMain") and !@hasDecl(root, "WinMainCRTStartup") and | |
| 47 | !@hasDecl(root, "wWinMain") and !@hasDecl(root, "wWinMainCRTStartup")) | |
| 48 | { | |
| 49 | @export(WinStartup, .{ .name = "wWinMainCRTStartup" }); | |
| 50 | } else if (@hasDecl(root, "WinMain") and !@hasDecl(root, "WinMainCRTStartup") and | |
| 51 | !@hasDecl(root, "wWinMain") and !@hasDecl(root, "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 | 115 | fn _DllMainCRTStartup( |
| 54 | 116 | hinstDLL: std.os.windows.HINSTANCE, |
| 55 | 117 | fdwReason: std.os.windows.DWORD, |
lib/std/std.zig+1-1| ... | ... | @@ -92,7 +92,7 @@ pub const zig = @import("zig.zig"); |
| 92 | 92 | pub const start = @import("start.zig"); |
| 93 | 93 | |
| 94 | 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 | 96 | comptime { |
| 97 | 97 | _ = start; |
| 98 | 98 | } |
lib/std/zig.zig+11-8| ... | ... | @@ -18,16 +18,19 @@ pub const CrossTarget = @import("zig/cross_target.zig").CrossTarget; |
| 18 | 18 | |
| 19 | 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 | 21 | pub fn hashSrc(src: []const u8) SrcHash { |
| 24 | 22 | var out: SrcHash = undefined; |
| 25 | if (src.len <= @typeInfo(SrcHash).Array.len) { | |
| 26 | std.mem.copy(u8, &out, src); | |
| 27 | std.mem.set(u8, out[src.len..], 0); | |
| 28 | } else { | |
| 29 | std.crypto.hash.Blake3.hash(src, &out, .{}); | |
| 30 | } | |
| 23 | std.crypto.hash.Blake3.hash(src, &out, .{}); | |
| 24 | return out; | |
| 25 | } | |
| 26 | ||
| 27 | pub fn hashName(parent_hash: SrcHash, sep: []const u8, name: []const u8) SrcHash { | |
| 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 | 34 | return out; |
| 32 | 35 | } |
| 33 | 36 |
src/AstGen.zig+61-5| ... | ... | @@ -823,7 +823,31 @@ pub fn structInitExpr( |
| 823 | 823 | .none, .none_or_ref => return mod.failNode(scope, node, "TODO implement structInitExpr none", .{}), |
| 824 | 824 | .ref => unreachable, // struct literal not valid as l-value |
| 825 | 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 | 852 | .ptr => |ptr_inst| { |
| 829 | 853 | const field_ptr_list = try gpa.alloc(zir.Inst.Index, struct_init.ast.fields.len); |
| ... | ... | @@ -1245,6 +1269,7 @@ fn blockExprStmts( |
| 1245 | 1269 | .fn_type_var_args, |
| 1246 | 1270 | .fn_type_cc, |
| 1247 | 1271 | .fn_type_cc_var_args, |
| 1272 | .has_decl, | |
| 1248 | 1273 | .int, |
| 1249 | 1274 | .float, |
| 1250 | 1275 | .float128, |
| ... | ... | @@ -1320,6 +1345,8 @@ fn blockExprStmts( |
| 1320 | 1345 | .switch_capture_else, |
| 1321 | 1346 | .switch_capture_else_ref, |
| 1322 | 1347 | .struct_init_empty, |
| 1348 | .struct_init, | |
| 1349 | .field_type, | |
| 1323 | 1350 | .struct_decl, |
| 1324 | 1351 | .struct_decl_packed, |
| 1325 | 1352 | .struct_decl_extern, |
| ... | ... | @@ -1329,6 +1356,7 @@ fn blockExprStmts( |
| 1329 | 1356 | .opaque_decl, |
| 1330 | 1357 | .int_to_enum, |
| 1331 | 1358 | .enum_to_int, |
| 1359 | .type_info, | |
| 1332 | 1360 | => break :b false, |
| 1333 | 1361 | |
| 1334 | 1362 | // ZIR instructions that are always either `noreturn` or `void`. |
| ... | ... | @@ -1336,6 +1364,7 @@ fn blockExprStmts( |
| 1336 | 1364 | .dbg_stmt_node, |
| 1337 | 1365 | .ensure_result_used, |
| 1338 | 1366 | .ensure_result_non_error, |
| 1367 | .@"export", | |
| 1339 | 1368 | .set_eval_branch_quota, |
| 1340 | 1369 | .compile_log, |
| 1341 | 1370 | .ensure_err_payload_void, |
| ... | ... | @@ -2347,7 +2376,7 @@ fn arrayAccess( |
| 2347 | 2376 | ), |
| 2348 | 2377 | else => return rvalue(gz, scope, rl, try gz.addBin( |
| 2349 | 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 | 2380 | try expr(gz, scope, .{ .ty = .usize_type }, node_datas[node].rhs), |
| 2352 | 2381 | ), node), |
| 2353 | 2382 | } |
| ... | ... | @@ -4146,6 +4175,36 @@ fn builtinCall( |
| 4146 | 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 | 4208 | .add_with_overflow, |
| 4150 | 4209 | .align_cast, |
| 4151 | 4210 | .align_of, |
| ... | ... | @@ -4175,11 +4234,9 @@ fn builtinCall( |
| 4175 | 4234 | .error_name, |
| 4176 | 4235 | .error_return_trace, |
| 4177 | 4236 | .err_set_cast, |
| 4178 | .@"export", | |
| 4179 | 4237 | .fence, |
| 4180 | 4238 | .field_parent_ptr, |
| 4181 | 4239 | .float_to_int, |
| 4182 | .has_decl, | |
| 4183 | 4240 | .has_field, |
| 4184 | 4241 | .int_to_float, |
| 4185 | 4242 | .int_to_ptr, |
| ... | ... | @@ -4224,7 +4281,6 @@ fn builtinCall( |
| 4224 | 4281 | .This, |
| 4225 | 4282 | .truncate, |
| 4226 | 4283 | .Type, |
| 4227 | .type_info, | |
| 4228 | 4284 | .type_name, |
| 4229 | 4285 | .union_init, |
| 4230 | 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 | 932 | artifact_sub_dir, |
| 933 | 933 | }; |
| 934 | 934 | |
| 935 | // TODO when we implement serialization and deserialization of incremental compilation metadata, | |
| 936 | // this is where we would load it. We have open a handle to the directory where | |
| 937 | // the output either already is, or will be. | |
| 935 | // If we rely on stage1, we must not redundantly add these packages. | |
| 936 | const use_stage1 = build_options.is_stage1 and use_llvm; | |
| 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 | 965 | // However we currently do not have serialization of such metadata, so for now |
| 939 | 966 | // we set up an empty Module that does the entire compilation fresh. |
| 940 | 967 | |
| 941 | const root_scope = rs: { | |
| 942 | if (mem.endsWith(u8, root_pkg.root_src_path, ".zig")) { | |
| 943 | const root_scope = try gpa.create(Module.Scope.File); | |
| 944 | const struct_ty = try Type.Tag.empty_struct.create( | |
| 945 | gpa, | |
| 946 | &root_scope.root_container, | |
| 947 | ); | |
| 948 | root_scope.* = .{ | |
| 949 | // TODO this is duped so it can be freed in Container.deinit | |
| 950 | .sub_file_path = try gpa.dupe(u8, root_pkg.root_src_path), | |
| 951 | .source = .{ .unloaded = {} }, | |
| 952 | .tree = undefined, | |
| 953 | .status = .never_loaded, | |
| 954 | .pkg = root_pkg, | |
| 955 | .root_container = .{ | |
| 956 | .file_scope = root_scope, | |
| 957 | .decls = .{}, | |
| 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 | } | |
| 968 | const root_scope = try gpa.create(Module.Scope.File); | |
| 969 | errdefer gpa.destroy(root_scope); | |
| 970 | ||
| 971 | const struct_ty = try Type.Tag.empty_struct.create(gpa, &root_scope.root_container); | |
| 972 | root_scope.* = .{ | |
| 973 | // TODO this is duped so it can be freed in Container.deinit | |
| 974 | .sub_file_path = try gpa.dupe(u8, root_pkg.root_src_path), | |
| 975 | .source = .{ .unloaded = {} }, | |
| 976 | .tree = undefined, | |
| 977 | .status = .never_loaded, | |
| 978 | .pkg = root_pkg, | |
| 979 | .root_container = .{ | |
| 980 | .file_scope = root_scope, | |
| 981 | .decls = .{}, | |
| 982 | .ty = struct_ty, | |
| 983 | .parent_name_hash = root_pkg.namespace_hash, | |
| 984 | }, | |
| 967 | 985 | }; |
| 968 | 986 | |
| 969 | 987 | const module = try arena.create(Module); |
| ... | ... | @@ -1365,7 +1383,8 @@ pub fn update(self: *Compilation) !void { |
| 1365 | 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 | 1388 | if (!use_stage1) { |
| 1370 | 1389 | if (self.bin_file.options.module) |module| { |
| 1371 | 1390 | module.compile_log_text.shrinkAndFree(module.gpa, 0); |
| ... | ... | @@ -2490,7 +2509,7 @@ pub fn addCCArgs( |
| 2490 | 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 | 2514 | if (out_dep_path) |p| { |
| 2496 | 2515 | try argv.appendSlice(&[_][]const u8{ "-MD", "-MV", "-MF", p }); |
| ... | ... | @@ -2564,7 +2583,6 @@ pub const FileExt = enum { |
| 2564 | 2583 | object, |
| 2565 | 2584 | static_library, |
| 2566 | 2585 | zig, |
| 2567 | zir, | |
| 2568 | 2586 | unknown, |
| 2569 | 2587 | |
| 2570 | 2588 | pub fn clangSupportsDepFile(ext: FileExt) bool { |
| ... | ... | @@ -2578,7 +2596,6 @@ pub const FileExt = enum { |
| 2578 | 2596 | .object, |
| 2579 | 2597 | .static_library, |
| 2580 | 2598 | .zig, |
| 2581 | .zir, | |
| 2582 | 2599 | .unknown, |
| 2583 | 2600 | => false, |
| 2584 | 2601 | }; |
| ... | ... | @@ -2650,8 +2667,6 @@ pub fn classifyFileExt(filename: []const u8) FileExt { |
| 2650 | 2667 | return .h; |
| 2651 | 2668 | } else if (mem.endsWith(u8, filename, ".zig")) { |
| 2652 | 2669 | return .zig; |
| 2653 | } else if (mem.endsWith(u8, filename, ".zir")) { | |
| 2654 | return .zir; | |
| 2655 | 2670 | } else if (hasSharedLibraryExt(filename)) { |
| 2656 | 2671 | return .shared_library; |
| 2657 | 2672 | } else if (hasStaticLibraryExt(filename)) { |
| ... | ... | @@ -2672,7 +2687,6 @@ test "classifyFileExt" { |
| 2672 | 2687 | std.testing.expectEqual(FileExt.shared_library, classifyFileExt("foo.so.1.2.3")); |
| 2673 | 2688 | std.testing.expectEqual(FileExt.unknown, classifyFileExt("foo.so.1.2.3~")); |
| 2674 | 2689 | std.testing.expectEqual(FileExt.zig, classifyFileExt("foo.zig")); |
| 2675 | std.testing.expectEqual(FileExt.zir, classifyFileExt("foo.zir")); | |
| 2676 | 2690 | } |
| 2677 | 2691 | |
| 2678 | 2692 | fn haveFramePointer(comp: *const Compilation) bool { |
| ... | ... | @@ -2867,6 +2881,8 @@ pub fn generateBuiltinZigSource(comp: *Compilation, allocator: *Allocator) ![]u8 |
| 2867 | 2881 | |
| 2868 | 2882 | const target = comp.getTarget(); |
| 2869 | 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 | 2887 | @setEvalBranchQuota(4000); |
| 2872 | 2888 | try buffer.writer().print( |
| ... | ... | @@ -2879,6 +2895,7 @@ pub fn generateBuiltinZigSource(comp: *Compilation, allocator: *Allocator) ![]u8 |
| 2879 | 2895 | \\/// Zig version. When writing code that supports multiple versions of Zig, prefer |
| 2880 | 2896 | \\/// feature detection (i.e. with `@hasDecl` or `@hasField`) over version checks. |
| 2881 | 2897 | \\pub const zig_version = try @import("std").SemanticVersion.parse("{s}"); |
| 2898 | \\pub const zig_is_stage2 = {}; | |
| 2882 | 2899 | \\ |
| 2883 | 2900 | \\pub const output_mode = OutputMode.{}; |
| 2884 | 2901 | \\pub const link_mode = LinkMode.{}; |
| ... | ... | @@ -2892,6 +2909,7 @@ pub fn generateBuiltinZigSource(comp: *Compilation, allocator: *Allocator) ![]u8 |
| 2892 | 2909 | \\ |
| 2893 | 2910 | , .{ |
| 2894 | 2911 | build_options.version, |
| 2912 | !use_stage1, | |
| 2895 | 2913 | std.zig.fmtId(@tagName(comp.bin_file.options.output_mode)), |
| 2896 | 2914 | std.zig.fmtId(@tagName(comp.bin_file.options.link_mode)), |
| 2897 | 2915 | comp.bin_file.options.is_test, |
| ... | ... | @@ -3101,6 +3119,7 @@ fn buildOutputFromZig( |
| 3101 | 3119 | .handle = special_dir, |
| 3102 | 3120 | }, |
| 3103 | 3121 | .root_src_path = src_basename, |
| 3122 | .namespace_hash = Package.root_namespace_hash, | |
| 3104 | 3123 | }; |
| 3105 | 3124 | const root_name = src_basename[0 .. src_basename.len - std.fs.path.extension(src_basename).len]; |
| 3106 | 3125 | const target = comp.getTarget(); |
src/Module.zig+68-90| ... | ... | @@ -150,9 +150,15 @@ pub const Decl = struct { |
| 150 | 150 | /// The direct parent container of the Decl. |
| 151 | 151 | /// Reference to externally owned memory. |
| 152 | 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 | 159 | /// Must be recomputed when the corresponding source file is modified. |
| 155 | src_index: usize, | |
| 160 | src_node: ast.Node.Index, | |
| 161 | ||
| 156 | 162 | /// The most recent value of the Decl after a successful semantic analysis. |
| 157 | 163 | typed_value: union(enum) { |
| 158 | 164 | never_succeeded: void, |
| ... | ... | @@ -198,11 +204,6 @@ pub const Decl = struct { |
| 198 | 204 | /// Whether the corresponding AST decl has a `pub` keyword. |
| 199 | 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 | 207 | /// Represents the position of the code in the output file. |
| 207 | 208 | /// This is populated regardless of semantic analysis and code generation. |
| 208 | 209 | link: link.File.LinkBlock, |
| ... | ... | @@ -249,11 +250,11 @@ pub const Decl = struct { |
| 249 | 250 | } |
| 250 | 251 | |
| 251 | 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 | 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 | 260 | pub fn tokSrcLoc(decl: Decl, token_index: ast.TokenIndex) LazySrcLoc { |
| ... | ... | @@ -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 | 275 | pub fn srcToken(decl: Decl) u32 { |
| 280 | 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 | 280 | pub fn srcByteOffset(decl: Decl) u32 { |
| ... | ... | @@ -678,6 +674,7 @@ pub const Scope = struct { |
| 678 | 674 | base: Scope = Scope{ .tag = base_tag }, |
| 679 | 675 | |
| 680 | 676 | file_scope: *Scope.File, |
| 677 | parent_name_hash: NameHash, | |
| 681 | 678 | |
| 682 | 679 | /// Direct children of the file. |
| 683 | 680 | decls: std.AutoArrayHashMapUnmanaged(*Decl, void) = .{}, |
| ... | ... | @@ -696,8 +693,7 @@ pub const Scope = struct { |
| 696 | 693 | } |
| 697 | 694 | |
| 698 | 695 | pub fn fullyQualifiedNameHash(cont: *Container, name: []const u8) NameHash { |
| 699 | // TODO container scope qualified names. | |
| 700 | return std.zig.hashSrc(name); | |
| 696 | return std.zig.hashName(cont.parent_name_hash, ".", name); | |
| 701 | 697 | } |
| 702 | 698 | |
| 703 | 699 | pub fn renderFullyQualifiedName(cont: Container, name: []const u8, writer: anytype) !void { |
| ... | ... | @@ -2296,6 +2292,20 @@ pub const InnerError = error{ OutOfMemory, AnalysisFail }; |
| 2296 | 2292 | pub fn deinit(mod: *Module) void { |
| 2297 | 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 | 2309 | mod.compile_log_text.deinit(gpa); |
| 2300 | 2310 | |
| 2301 | 2311 | mod.zig_cache_artifact_directory.handle.close(); |
| ... | ... | @@ -2458,7 +2468,7 @@ fn astgenAndSemaDecl(mod: *Module, decl: *Decl) !bool { |
| 2458 | 2468 | const tree = try mod.getAstTree(decl.container.file_scope); |
| 2459 | 2469 | const node_tags = tree.nodes.items(.tag); |
| 2460 | 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 | 2472 | switch (node_tags[decl_node]) { |
| 2463 | 2473 | .fn_decl => { |
| 2464 | 2474 | const fn_proto = node_datas[decl_node].lhs; |
| ... | ... | @@ -2513,6 +2523,7 @@ fn astgenAndSemaDecl(mod: *Module, decl: *Decl) !bool { |
| 2513 | 2523 | |
| 2514 | 2524 | const block_expr = node_datas[decl_node].lhs; |
| 2515 | 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 | 2528 | const code = try gen_scope.finish(); |
| 2518 | 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 | 3305 | var outdated_decls = std.AutoArrayHashMap(*Decl, void).init(mod.gpa); |
| 3295 | 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 | 3309 | .fn_decl => { |
| 3299 | 3310 | const fn_proto = node_datas[decl_node].lhs; |
| 3300 | 3311 | const body = node_datas[decl_node].rhs; |
| ... | ... | @@ -3306,7 +3317,6 @@ pub fn analyzeContainer(mod: *Module, container_scope: *Scope.Container) !void { |
| 3306 | 3317 | &deleted_decls, |
| 3307 | 3318 | &outdated_decls, |
| 3308 | 3319 | decl_node, |
| 3309 | decl_i, | |
| 3310 | 3320 | tree.*, |
| 3311 | 3321 | body, |
| 3312 | 3322 | tree.fnProtoSimple(&params, fn_proto), |
| ... | ... | @@ -3317,7 +3327,6 @@ pub fn analyzeContainer(mod: *Module, container_scope: *Scope.Container) !void { |
| 3317 | 3327 | &deleted_decls, |
| 3318 | 3328 | &outdated_decls, |
| 3319 | 3329 | decl_node, |
| 3320 | decl_i, | |
| 3321 | 3330 | tree.*, |
| 3322 | 3331 | body, |
| 3323 | 3332 | tree.fnProtoMulti(fn_proto), |
| ... | ... | @@ -3329,7 +3338,6 @@ pub fn analyzeContainer(mod: *Module, container_scope: *Scope.Container) !void { |
| 3329 | 3338 | &deleted_decls, |
| 3330 | 3339 | &outdated_decls, |
| 3331 | 3340 | decl_node, |
| 3332 | decl_i, | |
| 3333 | 3341 | tree.*, |
| 3334 | 3342 | body, |
| 3335 | 3343 | tree.fnProtoOne(&params, fn_proto), |
| ... | ... | @@ -3340,7 +3348,6 @@ pub fn analyzeContainer(mod: *Module, container_scope: *Scope.Container) !void { |
| 3340 | 3348 | &deleted_decls, |
| 3341 | 3349 | &outdated_decls, |
| 3342 | 3350 | decl_node, |
| 3343 | decl_i, | |
| 3344 | 3351 | tree.*, |
| 3345 | 3352 | body, |
| 3346 | 3353 | tree.fnProto(fn_proto), |
| ... | ... | @@ -3355,7 +3362,6 @@ pub fn analyzeContainer(mod: *Module, container_scope: *Scope.Container) !void { |
| 3355 | 3362 | &deleted_decls, |
| 3356 | 3363 | &outdated_decls, |
| 3357 | 3364 | decl_node, |
| 3358 | decl_i, | |
| 3359 | 3365 | tree.*, |
| 3360 | 3366 | 0, |
| 3361 | 3367 | tree.fnProtoSimple(&params, decl_node), |
| ... | ... | @@ -3366,7 +3372,6 @@ pub fn analyzeContainer(mod: *Module, container_scope: *Scope.Container) !void { |
| 3366 | 3372 | &deleted_decls, |
| 3367 | 3373 | &outdated_decls, |
| 3368 | 3374 | decl_node, |
| 3369 | decl_i, | |
| 3370 | 3375 | tree.*, |
| 3371 | 3376 | 0, |
| 3372 | 3377 | tree.fnProtoMulti(decl_node), |
| ... | ... | @@ -3378,7 +3383,6 @@ pub fn analyzeContainer(mod: *Module, container_scope: *Scope.Container) !void { |
| 3378 | 3383 | &deleted_decls, |
| 3379 | 3384 | &outdated_decls, |
| 3380 | 3385 | decl_node, |
| 3381 | decl_i, | |
| 3382 | 3386 | tree.*, |
| 3383 | 3387 | 0, |
| 3384 | 3388 | tree.fnProtoOne(&params, decl_node), |
| ... | ... | @@ -3389,7 +3393,6 @@ pub fn analyzeContainer(mod: *Module, container_scope: *Scope.Container) !void { |
| 3389 | 3393 | &deleted_decls, |
| 3390 | 3394 | &outdated_decls, |
| 3391 | 3395 | decl_node, |
| 3392 | decl_i, | |
| 3393 | 3396 | tree.*, |
| 3394 | 3397 | 0, |
| 3395 | 3398 | tree.fnProto(decl_node), |
| ... | ... | @@ -3400,7 +3403,6 @@ pub fn analyzeContainer(mod: *Module, container_scope: *Scope.Container) !void { |
| 3400 | 3403 | &deleted_decls, |
| 3401 | 3404 | &outdated_decls, |
| 3402 | 3405 | decl_node, |
| 3403 | decl_i, | |
| 3404 | 3406 | tree.*, |
| 3405 | 3407 | tree.globalVarDecl(decl_node), |
| 3406 | 3408 | ), |
| ... | ... | @@ -3409,7 +3411,6 @@ pub fn analyzeContainer(mod: *Module, container_scope: *Scope.Container) !void { |
| 3409 | 3411 | &deleted_decls, |
| 3410 | 3412 | &outdated_decls, |
| 3411 | 3413 | decl_node, |
| 3412 | decl_i, | |
| 3413 | 3414 | tree.*, |
| 3414 | 3415 | tree.localVarDecl(decl_node), |
| 3415 | 3416 | ), |
| ... | ... | @@ -3418,7 +3419,6 @@ pub fn analyzeContainer(mod: *Module, container_scope: *Scope.Container) !void { |
| 3418 | 3419 | &deleted_decls, |
| 3419 | 3420 | &outdated_decls, |
| 3420 | 3421 | decl_node, |
| 3421 | decl_i, | |
| 3422 | 3422 | tree.*, |
| 3423 | 3423 | tree.simpleVarDecl(decl_node), |
| 3424 | 3424 | ), |
| ... | ... | @@ -3427,7 +3427,6 @@ pub fn analyzeContainer(mod: *Module, container_scope: *Scope.Container) !void { |
| 3427 | 3427 | &deleted_decls, |
| 3428 | 3428 | &outdated_decls, |
| 3429 | 3429 | decl_node, |
| 3430 | decl_i, | |
| 3431 | 3430 | tree.*, |
| 3432 | 3431 | tree.alignedVarDecl(decl_node), |
| 3433 | 3432 | ), |
| ... | ... | @@ -3440,38 +3439,21 @@ pub fn analyzeContainer(mod: *Module, container_scope: *Scope.Container) !void { |
| 3440 | 3439 | const name_hash = container_scope.fullyQualifiedNameHash(name); |
| 3441 | 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 | 3443 | container_scope.decls.putAssumeCapacity(new_decl, {}); |
| 3445 | 3444 | mod.comp.work_queue.writeItemAssumeCapacity(.{ .analyze_decl = new_decl }); |
| 3446 | 3445 | }, |
| 3447 | 3446 | |
| 3448 | .container_field_init => try mod.semaContainerField( | |
| 3449 | container_scope, | |
| 3450 | &deleted_decls, | |
| 3451 | decl_node, | |
| 3452 | decl_i, | |
| 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 | ), | |
| 3447 | // Container fields are handled in AstGen. | |
| 3448 | .container_field_init, | |
| 3449 | .container_field_align, | |
| 3450 | .container_field, | |
| 3451 | => continue, | |
| 3472 | 3452 | |
| 3473 | 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 | 3458 | .@"usingnamespace" => { |
| 3477 | 3459 | log.err("TODO: analyze usingnamespace decl", .{}); |
| ... | ... | @@ -3508,7 +3490,6 @@ fn semaContainerFn( |
| 3508 | 3490 | deleted_decls: *std.AutoArrayHashMap(*Decl, void), |
| 3509 | 3491 | outdated_decls: *std.AutoArrayHashMap(*Decl, void), |
| 3510 | 3492 | decl_node: ast.Node.Index, |
| 3511 | decl_i: usize, | |
| 3512 | 3493 | tree: ast.Tree, |
| 3513 | 3494 | body_node: ast.Node.Index, |
| 3514 | 3495 | fn_proto: ast.full.FnProto, |
| ... | ... | @@ -3517,24 +3498,30 @@ fn semaContainerFn( |
| 3517 | 3498 | defer tracy.end(); |
| 3518 | 3499 | |
| 3519 | 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 | 3502 | // This problem will go away with #1717. |
| 3522 | 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 | 3506 | const name_hash = container_scope.fullyQualifiedNameHash(name); |
| 3526 | 3507 | const contents_hash = std.zig.hashSrc(tree.getNodeSource(decl_node)); |
| 3527 | 3508 | if (mod.decl_table.get(name_hash)) |decl| { |
| 3528 | 3509 | // Update the AST Node index of the decl, even if its contents are unchanged, it may |
| 3529 | 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 | 3513 | if (deleted_decls.swapRemove(decl) == null) { |
| 3532 | 3514 | decl.analysis = .sema_failure; |
| 3533 | 3515 | const msg = try ErrorMsg.create(mod.gpa, .{ |
| 3534 | 3516 | .container = .{ .file_scope = container_scope.file_scope }, |
| 3535 | .lazy = .{ .token_abs = name_tok }, | |
| 3517 | .lazy = .{ .token_abs = name_token }, | |
| 3536 | 3518 | }, "redefinition of '{s}'", .{decl.name}); |
| 3537 | 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 | 3525 | try mod.failed_decls.putNoClobber(mod.gpa, decl, msg); |
| 3539 | 3526 | } else { |
| 3540 | 3527 | if (!srcHashEql(decl.contents_hash, contents_hash)) { |
| ... | ... | @@ -3558,7 +3545,7 @@ fn semaContainerFn( |
| 3558 | 3545 | } |
| 3559 | 3546 | } |
| 3560 | 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 | 3549 | container_scope.decls.putAssumeCapacity(new_decl, {}); |
| 3563 | 3550 | if (fn_proto.extern_export_token) |maybe_export_token| { |
| 3564 | 3551 | const token_tags = tree.tokens.items(.tag); |
| ... | ... | @@ -3566,6 +3553,7 @@ fn semaContainerFn( |
| 3566 | 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 | 3563 | deleted_decls: *std.AutoArrayHashMap(*Decl, void), |
| 3576 | 3564 | outdated_decls: *std.AutoArrayHashMap(*Decl, void), |
| 3577 | 3565 | decl_node: ast.Node.Index, |
| 3578 | decl_i: usize, | |
| 3579 | 3566 | tree: ast.Tree, |
| 3580 | 3567 | var_decl: ast.full.VarDecl, |
| 3581 | 3568 | ) !void { |
| ... | ... | @@ -3589,21 +3576,27 @@ fn semaContainerVar( |
| 3589 | 3576 | if (mod.decl_table.get(name_hash)) |decl| { |
| 3590 | 3577 | // Update the AST Node index of the decl, even if its contents are unchanged, it may |
| 3591 | 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 | 3581 | if (deleted_decls.swapRemove(decl) == null) { |
| 3594 | 3582 | decl.analysis = .sema_failure; |
| 3595 | const err_msg = try ErrorMsg.create(mod.gpa, .{ | |
| 3583 | const msg = try ErrorMsg.create(mod.gpa, .{ | |
| 3596 | 3584 | .container = .{ .file_scope = container_scope.file_scope }, |
| 3597 | 3585 | .lazy = .{ .token_abs = name_token }, |
| 3598 | 3586 | }, "redefinition of '{s}'", .{decl.name}); |
| 3599 | errdefer err_msg.destroy(mod.gpa); | |
| 3600 | try mod.failed_decls.putNoClobber(mod.gpa, decl, err_msg); | |
| 3587 | errdefer msg.destroy(mod.gpa); | |
| 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 | 3594 | } else if (!srcHashEql(decl.contents_hash, contents_hash)) { |
| 3602 | 3595 | try outdated_decls.put(decl, {}); |
| 3603 | 3596 | decl.contents_hash = contents_hash; |
| 3604 | 3597 | } |
| 3605 | 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 | 3600 | container_scope.decls.putAssumeCapacity(new_decl, {}); |
| 3608 | 3601 | if (var_decl.extern_export_token) |maybe_export_token| { |
| 3609 | 3602 | const token_tags = tree.tokens.items(.tag); |
| ... | ... | @@ -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 | 3610 | pub fn deleteDecl( |
| 3633 | 3611 | mod: *Module, |
| 3634 | 3612 | decl: *Decl, |
| ... | ... | @@ -3811,7 +3789,7 @@ fn markOutdatedDecl(mod: *Module, decl: *Decl) !void { |
| 3811 | 3789 | fn allocateNewDecl( |
| 3812 | 3790 | mod: *Module, |
| 3813 | 3791 | scope: *Scope, |
| 3814 | src_index: usize, | |
| 3792 | src_node: ast.Node.Index, | |
| 3815 | 3793 | contents_hash: std.zig.SrcHash, |
| 3816 | 3794 | ) !*Decl { |
| 3817 | 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 | 3805 | new_decl.* = .{ |
| 3828 | 3806 | .name = "", |
| 3829 | 3807 | .container = scope.namespace(), |
| 3830 | .src_index = src_index, | |
| 3808 | .src_node = src_node, | |
| 3831 | 3809 | .typed_value = .{ .never_succeeded = {} }, |
| 3832 | 3810 | .analysis = .unreferenced, |
| 3833 | 3811 | .deletion_flag = false, |
| ... | ... | @@ -3858,12 +3836,12 @@ fn createNewDecl( |
| 3858 | 3836 | mod: *Module, |
| 3859 | 3837 | scope: *Scope, |
| 3860 | 3838 | decl_name: []const u8, |
| 3861 | src_index: usize, | |
| 3839 | src_node: ast.Node.Index, | |
| 3862 | 3840 | name_hash: Scope.NameHash, |
| 3863 | 3841 | contents_hash: std.zig.SrcHash, |
| 3864 | 3842 | ) !*Decl { |
| 3865 | 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 | 3845 | errdefer mod.gpa.destroy(new_decl); |
| 3868 | 3846 | new_decl.name = try mem.dupeZ(mod.gpa, u8, decl_name); |
| 3869 | 3847 | mod.decl_table.putAssumeCapacityNoClobber(name_hash, new_decl); |
| ... | ... | @@ -4076,7 +4054,7 @@ pub fn createAnonymousDecl( |
| 4076 | 4054 | defer mod.gpa.free(name); |
| 4077 | 4055 | const name_hash = scope.namespace().fullyQualifiedNameHash(name); |
| 4078 | 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 | 4058 | const decl_arena_state = try decl_arena.allocator.create(std.heap.ArenaAllocator.State); |
| 4081 | 4059 | |
| 4082 | 4060 | decl_arena_state.* = decl_arena.state; |
| ... | ... | @@ -4112,7 +4090,7 @@ pub fn createContainerDecl( |
| 4112 | 4090 | defer mod.gpa.free(name); |
| 4113 | 4091 | const name_hash = scope.namespace().fullyQualifiedNameHash(name); |
| 4114 | 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 | 4094 | const decl_arena_state = try decl_arena.allocator.create(std.heap.ArenaAllocator.State); |
| 4117 | 4095 | |
| 4118 | 4096 | decl_arena_state.* = decl_arena.state; |
src/Package.zig+68-8| ... | ... | @@ -4,18 +4,29 @@ const std = @import("std"); |
| 4 | 4 | const fs = std.fs; |
| 5 | 5 | const mem = std.mem; |
| 6 | 6 | const Allocator = mem.Allocator; |
| 7 | const assert = std.debug.assert; | |
| 7 | 8 | |
| 8 | 9 | const Compilation = @import("Compilation.zig"); |
| 10 | const Module = @import("Module.zig"); | |
| 9 | 11 | |
| 10 | 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 | 19 | root_src_directory: Compilation.Directory, |
| 13 | 20 | /// Relative to `root_src_directory`. May contain path separators. |
| 14 | 21 | root_src_path: []const u8, |
| 15 | 22 | table: Table = .{}, |
| 16 | 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 | 28 | /// Allocate a Package. No references to the slices passed are kept. |
| 29 | /// Don't forget to set `namespace_hash` later. | |
| 19 | 30 | pub fn create( |
| 20 | 31 | gpa: *Allocator, |
| 21 | 32 | /// Null indicates the current working directory |
| ... | ... | @@ -38,27 +49,69 @@ pub fn create( |
| 38 | 49 | .handle = if (owned_dir_path) |p| try fs.cwd().openDir(p, .{}) else fs.cwd(), |
| 39 | 50 | }, |
| 40 | 51 | .root_src_path = owned_src_path, |
| 52 | .root_src_directory_owned = true, | |
| 53 | .namespace_hash = undefined, | |
| 41 | 54 | }; |
| 42 | 55 | |
| 43 | 56 | return ptr; |
| 44 | 57 | } |
| 45 | 58 | |
| 46 | /// Free all memory associated with this package and recursively call destroy | |
| 47 | /// on all packages in its table | |
| 59 | pub fn createWithDir( | |
| 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 | 100 | pub fn destroy(pkg: *Package, gpa: *Allocator) void { |
| 49 | 101 | gpa.free(pkg.root_src_path); |
| 50 | 102 | |
| 51 | // If root_src_directory.path is null then the handle is the cwd() | |
| 52 | // which shouldn't be closed. | |
| 53 | if (pkg.root_src_directory.path) |p| { | |
| 54 | gpa.free(p); | |
| 55 | pkg.root_src_directory.handle.close(); | |
| 103 | if (pkg.root_src_directory_owned) { | |
| 104 | // If root_src_directory.path is null then the handle is the cwd() | |
| 105 | // which shouldn't be closed. | |
| 106 | if (pkg.root_src_directory.path) |p| { | |
| 107 | gpa.free(p); | |
| 108 | pkg.root_src_directory.handle.close(); | |
| 109 | } | |
| 56 | 110 | } |
| 57 | 111 | |
| 58 | 112 | { |
| 59 | 113 | var it = pkg.table.iterator(); |
| 60 | 114 | while (it.next()) |kv| { |
| 61 | kv.value.destroy(gpa); | |
| 62 | 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 | 125 | const name_dupe = try mem.dupe(gpa, u8, name); |
| 73 | 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 | 199 | .fn_type_cc => try sema.zirFnTypeCc(block, inst, false), |
| 200 | 200 | .fn_type_cc_var_args => try sema.zirFnTypeCc(block, inst, true), |
| 201 | 201 | .fn_type_var_args => try sema.zirFnType(block, inst, true), |
| 202 | .has_decl => try sema.zirHasDecl(block, inst), | |
| 202 | 203 | .import => try sema.zirImport(block, inst), |
| 203 | 204 | .indexable_ptr_len => try sema.zirIndexablePtrLen(block, inst), |
| 204 | 205 | .int => try sema.zirInt(block, inst), |
| ... | ... | @@ -258,11 +259,14 @@ pub fn analyzeBody( |
| 258 | 259 | .switch_capture_multi_ref => try sema.zirSwitchCapture(block, inst, true, true), |
| 259 | 260 | .switch_capture_else => try sema.zirSwitchCaptureElse(block, inst, false), |
| 260 | 261 | .switch_capture_else_ref => try sema.zirSwitchCaptureElse(block, inst, true), |
| 262 | .type_info => try sema.zirTypeInfo(block, inst), | |
| 261 | 263 | .typeof => try sema.zirTypeof(block, inst), |
| 262 | 264 | .typeof_elem => try sema.zirTypeofElem(block, inst), |
| 263 | 265 | .typeof_peer => try sema.zirTypeofPeer(block, inst), |
| 264 | 266 | .xor => try sema.zirBitwise(block, inst, .xor), |
| 265 | 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 | 271 | .struct_decl => try sema.zirStructDecl(block, inst, .Auto), |
| 268 | 272 | .struct_decl_packed => try sema.zirStructDecl(block, inst, .Packed), |
| ... | ... | @@ -342,6 +346,10 @@ pub fn analyzeBody( |
| 342 | 346 | try sema.zirValidateStructInitPtr(block, inst); |
| 343 | 347 | continue; |
| 344 | 348 | }, |
| 349 | .@"export" => { | |
| 350 | try sema.zirExport(block, inst); | |
| 351 | continue; | |
| 352 | }, | |
| 345 | 353 | |
| 346 | 354 | // Special case instructions to handle comptime control flow. |
| 347 | 355 | .repeat_inline => { |
| ... | ... | @@ -593,6 +601,10 @@ fn zirStructDecl( |
| 593 | 601 | const struct_obj = try new_decl_arena.allocator.create(Module.Struct); |
| 594 | 602 | const struct_ty = try Type.Tag.@"struct".create(&new_decl_arena.allocator, struct_obj); |
| 595 | 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 | 608 | struct_obj.* = .{ |
| 597 | 609 | .owner_decl = sema.owner_decl, |
| 598 | 610 | .fields = fields_map, |
| ... | ... | @@ -600,12 +612,9 @@ fn zirStructDecl( |
| 600 | 612 | .container = .{ |
| 601 | 613 | .ty = struct_ty, |
| 602 | 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 | 618 | return sema.analyzeDeclVal(block, src, new_decl); |
| 610 | 619 | } |
| 611 | 620 | |
| ... | ... | @@ -1333,6 +1342,28 @@ fn analyzeBlockBody( |
| 1333 | 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 | 1367 | fn zirBreakpoint(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!void { |
| 1337 | 1368 | const tracy = trace(@src()); |
| 1338 | 1369 | defer tracy.end(); |
| ... | ... | @@ -1402,9 +1433,6 @@ fn zirDbgStmtNode(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerE |
| 1402 | 1433 | } |
| 1403 | 1434 | |
| 1404 | 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 | 1436 | const inst_data = sema.code.instructions.items(.data)[inst].pl_node; |
| 1409 | 1437 | const src = inst_data.src(); |
| 1410 | 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 | 1440 | } |
| 1413 | 1441 | |
| 1414 | 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 | 1443 | const inst_data = sema.code.instructions.items(.data)[inst].pl_node; |
| 1419 | 1444 | const src = inst_data.src(); |
| 1420 | 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 | 2568 | |
| 2544 | 2569 | const bin_inst = sema.code.instructions.items(.data)[inst].bin; |
| 2545 | 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 | 2575 | const elem_index = try sema.resolveInst(bin_inst.rhs); |
| 2548 | 2576 | const result_ptr = try sema.elemPtr(block, sema.src, array_ptr, elem_index, sema.src); |
| 2549 | 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 | 2586 | const elem_index_src: LazySrcLoc = .{ .node_offset_array_access_index = inst_data.src_node }; |
| 2559 | 2587 | const extra = sema.code.extraData(zir.Inst.Bin, inst_data.payload_index).data; |
| 2560 | 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 | 2593 | const elem_index = try sema.resolveInst(extra.rhs); |
| 2563 | 2594 | const result_ptr = try sema.elemPtr(block, src, array_ptr, elem_index, elem_index_src); |
| 2564 | 2595 | return sema.analyzeLoad(block, src, result_ptr, src); |
| ... | ... | @@ -3595,6 +3626,34 @@ fn validateSwitchNoRange( |
| 3595 | 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 | 3657 | fn zirImport(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!*Inst { |
| 3599 | 3658 | const tracy = trace(@src()); |
| 3600 | 3659 | defer tracy.end(); |
| ... | ... | @@ -4021,6 +4080,12 @@ fn zirCmp( |
| 4021 | 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 | 4089 | fn zirTypeof(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!*Inst { |
| 4025 | 4090 | const inst_data = sema.code.instructions.items(.data)[inst].un_node; |
| 4026 | 4091 | const src = inst_data.src(); |
| ... | ... | @@ -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 | 4518 | fn requireFunctionBlock(sema: *Sema, block: *Scope.Block, src: LazySrcLoc) !void { |
| 4442 | 4519 | if (sema.func == null) { |
| 4443 | 4520 | return sema.mod.fail(&block.base, src, "instruction illegal outside function body", .{}); |
| ... | ... | @@ -4632,7 +4709,8 @@ fn namedFieldPtr( |
| 4632 | 4709 | .Struct, .Opaque, .Union => { |
| 4633 | 4710 | if (child_type.getContainerScope()) |container_scope| { |
| 4634 | 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 | 4714 | return sema.analyzeDeclRef(block, src, decl); |
| 4637 | 4715 | } |
| 4638 | 4716 | |
| ... | ... | @@ -4660,7 +4738,8 @@ fn namedFieldPtr( |
| 4660 | 4738 | .Enum => { |
| 4661 | 4739 | if (child_type.getContainerScope()) |container_scope| { |
| 4662 | 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 | 4743 | return sema.analyzeDeclRef(block, src, decl); |
| 4665 | 4744 | } |
| 4666 | 4745 | } |
| ... | ... | @@ -4731,37 +4810,51 @@ fn elemPtr( |
| 4731 | 4810 | elem_index: *Inst, |
| 4732 | 4811 | elem_index_src: LazySrcLoc, |
| 4733 | 4812 | ) InnerError!*Inst { |
| 4734 | const elem_ty = switch (array_ptr.ty.zigTypeTag()) { | |
| 4813 | const array_ty = switch (array_ptr.ty.zigTypeTag()) { | |
| 4735 | 4814 | .Pointer => array_ptr.ty.elemType(), |
| 4736 | 4815 | else => return sema.mod.fail(&block.base, array_ptr.src, "expected pointer, found '{}'", .{array_ptr.ty}), |
| 4737 | 4816 | }; |
| 4738 | if (!elem_ty.isIndexable()) { | |
| 4739 | return sema.mod.fail(&block.base, src, "array access of non-array type '{}'", .{elem_ty}); | |
| 4817 | if (!array_ty.isIndexable()) { | |
| 4818 | return sema.mod.fail(&block.base, src, "array access of non-array type '{}'", .{array_ty}); | |
| 4740 | 4819 | } |
| 4741 | ||
| 4742 | if (elem_ty.isSinglePointer() and elem_ty.elemType().zigTypeTag() == .Array) { | |
| 4820 | if (array_ty.isSinglePointer() and array_ty.elemType().zigTypeTag() == .Array) { | |
| 4743 | 4821 | // we have to deref the ptr operand to get the actual array pointer |
| 4744 | 4822 | const array_ptr_deref = try sema.analyzeLoad(block, src, array_ptr, array_ptr.src); |
| 4745 | if (array_ptr_deref.value()) |array_ptr_val| { | |
| 4746 | if (elem_index.value()) |index_val| { | |
| 4747 | // Both array pointer and index are compile-time known. | |
| 4748 | const index_u64 = index_val.toUnsignedInt(); | |
| 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 | } | |
| 4823 | return sema.elemPtrArray(block, src, array_ptr_deref, elem_index, elem_index_src); | |
| 4824 | } | |
| 4825 | if (array_ty.zigTypeTag() == .Array) { | |
| 4826 | return sema.elemPtrArray(block, src, array_ptr, elem_index, elem_index_src); | |
| 4760 | 4827 | } |
| 4761 | 4828 | |
| 4762 | 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 | 4858 | fn coerce( |
| 4766 | 4859 | sema: *Sema, |
| 4767 | 4860 | block: *Scope.Block, |
| ... | ... | @@ -5244,9 +5337,9 @@ fn analyzeImport(sema: *Sema, block: *Scope.Block, src: LazySrcLoc, target_strin |
| 5244 | 5337 | try std.fs.path.resolve(sema.gpa, &[_][]const u8{ cur_pkg_dir_path, target_string }); |
| 5245 | 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 | 5341 | sema.gpa.free(resolved_path); |
| 5249 | return some; | |
| 5342 | return cached_import; | |
| 5250 | 5343 | } |
| 5251 | 5344 | |
| 5252 | 5345 | if (found_pkg == null) { |
| ... | ... | @@ -5264,6 +5357,11 @@ fn analyzeImport(sema: *Sema, block: *Scope.Block, src: LazySrcLoc, target_strin |
| 5264 | 5357 | const struct_ty = try Type.Tag.empty_struct.create(sema.gpa, &file_scope.root_container); |
| 5265 | 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 | 5365 | file_scope.* = .{ |
| 5268 | 5366 | .sub_file_path = resolved_path, |
| 5269 | 5367 | .source = .{ .unloaded = {} }, |
| ... | ... | @@ -5274,6 +5372,7 @@ fn analyzeImport(sema: *Sema, block: *Scope.Block, src: LazySrcLoc, target_strin |
| 5274 | 5372 | .file_scope = file_scope, |
| 5275 | 5373 | .decls = .{}, |
| 5276 | 5374 | .ty = struct_ty, |
| 5375 | .parent_name_hash = container_name_hash, | |
| 5277 | 5376 | }, |
| 5278 | 5377 | }; |
| 5279 | 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 | 417 | const node_datas = tree.nodes.items(.data); |
| 418 | 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 | 421 | assert(node_tags[fn_decl] == .fn_decl); |
| 422 | 422 | const block = node_datas[fn_decl].rhs; |
| 423 | 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 | 2228 | const node_datas = tree.nodes.items(.data); |
| 2229 | 2229 | const token_starts = tree.tokens.items(.start); |
| 2230 | 2230 | |
| 2231 | const file_ast_decls = tree.rootDecls(); | |
| 2232 | 2231 | // TODO Look into improving the performance here by adding a token-index-to-line |
| 2233 | 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 | 2234 | assert(node_tags[fn_decl] == .fn_decl); |
| 2236 | 2235 | const block = node_datas[fn_decl].rhs; |
| 2237 | 2236 | const lbrace = tree.firstToken(block); |
| ... | ... | @@ -2755,10 +2754,9 @@ pub fn updateDeclLineNumber(self: *Elf, module: *Module, decl: *const Module.Dec |
| 2755 | 2754 | const node_datas = tree.nodes.items(.data); |
| 2756 | 2755 | const token_starts = tree.tokens.items(.start); |
| 2757 | 2756 | |
| 2758 | const file_ast_decls = tree.rootDecls(); | |
| 2759 | 2757 | // TODO Look into improving the performance here by adding a token-index-to-line |
| 2760 | 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 | 2760 | assert(node_tags[fn_decl] == .fn_decl); |
| 2763 | 2761 | const block = node_datas[fn_decl].rhs; |
| 2764 | 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 | 909 | const node_datas = tree.nodes.items(.data); |
| 910 | 910 | const token_starts = tree.tokens.items(.start); |
| 911 | 911 | |
| 912 | const file_ast_decls = tree.rootDecls(); | |
| 913 | 912 | // TODO Look into improving the performance here by adding a token-index-to-line |
| 914 | 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 | 915 | assert(node_tags[fn_decl] == .fn_decl); |
| 917 | 916 | const block = node_datas[fn_decl].rhs; |
| 918 | 917 | const lbrace = tree.firstToken(block); |
| ... | ... | @@ -959,10 +958,9 @@ pub fn initDeclDebugBuffers( |
| 959 | 958 | const node_datas = tree.nodes.items(.data); |
| 960 | 959 | const token_starts = tree.tokens.items(.start); |
| 961 | 960 | |
| 962 | const file_ast_decls = tree.rootDecls(); | |
| 963 | 961 | // TODO Look into improving the performance here by adding a token-index-to-line |
| 964 | 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 | 964 | assert(node_tags[fn_decl] == .fn_decl); |
| 967 | 965 | const block = node_datas[fn_decl].rhs; |
| 968 | 966 | const lbrace = tree.firstToken(block); |
src/main.zig+23-23| ... | ... | @@ -505,7 +505,6 @@ fn buildOutputType( |
| 505 | 505 | var emit_bin: EmitBin = .yes_default_path; |
| 506 | 506 | var emit_asm: Emit = .no; |
| 507 | 507 | var emit_llvm_ir: Emit = .no; |
| 508 | var emit_zir: Emit = .no; | |
| 509 | 508 | var emit_docs: Emit = .no; |
| 510 | 509 | var emit_analysis: Emit = .no; |
| 511 | 510 | var target_arch_os_abi: []const u8 = "native"; |
| ... | ... | @@ -599,15 +598,15 @@ fn buildOutputType( |
| 599 | 598 | var test_exec_args = std.ArrayList(?[]const u8).init(gpa); |
| 600 | 599 | defer test_exec_args.deinit(); |
| 601 | 600 | |
| 602 | const pkg_tree_root = try gpa.create(Package); | |
| 603 | 601 | // This package only exists to clean up the code parsing --pkg-begin and |
| 604 | 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 | 604 | .root_src_directory = .{ .path = null, .handle = fs.cwd() }, |
| 607 | 605 | .root_src_path = &[0]u8{}, |
| 606 | .namespace_hash = Package.root_namespace_hash, | |
| 608 | 607 | }; |
| 609 | defer pkg_tree_root.destroy(gpa); | |
| 610 | var cur_pkg: *Package = pkg_tree_root; | |
| 608 | defer freePkgTree(gpa, &pkg_tree_root, false); | |
| 609 | var cur_pkg: *Package = &pkg_tree_root; | |
| 611 | 610 | |
| 612 | 611 | switch (arg_mode) { |
| 613 | 612 | .build, .translate_c, .zig_test, .run => { |
| ... | ... | @@ -658,8 +657,7 @@ fn buildOutputType( |
| 658 | 657 | ) catch |err| { |
| 659 | 658 | fatal("Failed to add package at path {s}: {s}", .{ pkg_path, @errorName(err) }); |
| 660 | 659 | }; |
| 661 | new_cur_pkg.parent = cur_pkg; | |
| 662 | try cur_pkg.add(gpa, pkg_name, new_cur_pkg); | |
| 660 | try cur_pkg.addAndAdopt(gpa, pkg_name, new_cur_pkg); | |
| 663 | 661 | cur_pkg = new_cur_pkg; |
| 664 | 662 | } else if (mem.eql(u8, arg, "--pkg-end")) { |
| 665 | 663 | cur_pkg = cur_pkg.parent orelse |
| ... | ... | @@ -924,12 +922,6 @@ fn buildOutputType( |
| 924 | 922 | emit_bin = .{ .yes = arg["-femit-bin=".len..] }; |
| 925 | 923 | } else if (mem.eql(u8, arg, "-fno-emit-bin")) { |
| 926 | 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 | 925 | } else if (mem.eql(u8, arg, "-femit-h")) { |
| 934 | 926 | emit_h = .yes_default_path; |
| 935 | 927 | } else if (mem.startsWith(u8, arg, "-femit-h=")) { |
| ... | ... | @@ -1026,7 +1018,7 @@ fn buildOutputType( |
| 1026 | 1018 | .extra_flags = try arena.dupe([]const u8, extra_cflags.items), |
| 1027 | 1019 | }); |
| 1028 | 1020 | }, |
| 1029 | .zig, .zir => { | |
| 1021 | .zig => { | |
| 1030 | 1022 | if (root_src_file) |other| { |
| 1031 | 1023 | fatal("found another zig file '{s}' after root source file '{s}'", .{ arg, other }); |
| 1032 | 1024 | } else { |
| ... | ... | @@ -1087,7 +1079,7 @@ fn buildOutputType( |
| 1087 | 1079 | .unknown, .shared_library, .object, .static_library => { |
| 1088 | 1080 | try link_objects.append(it.only_arg); |
| 1089 | 1081 | }, |
| 1090 | .zig, .zir => { | |
| 1082 | .zig => { | |
| 1091 | 1083 | if (root_src_file) |other| { |
| 1092 | 1084 | fatal("found another zig file '{s}' after root source file '{s}'", .{ it.only_arg, other }); |
| 1093 | 1085 | } else { |
| ... | ... | @@ -1725,13 +1717,6 @@ fn buildOutputType( |
| 1725 | 1717 | var emit_docs_resolved = try emit_docs.resolve("docs"); |
| 1726 | 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 | 1720 | const root_pkg: ?*Package = if (root_src_file) |src_path| blk: { |
| 1736 | 1721 | if (main_pkg_path) |p| { |
| 1737 | 1722 | const rel_src_path = try fs.path.relative(gpa, p, src_path); |
| ... | ... | @@ -1747,6 +1732,7 @@ fn buildOutputType( |
| 1747 | 1732 | if (root_pkg) |pkg| { |
| 1748 | 1733 | pkg.table = pkg_tree_root.table; |
| 1749 | 1734 | pkg_tree_root.table = .{}; |
| 1735 | pkg.namespace_hash = pkg_tree_root.namespace_hash; | |
| 1750 | 1736 | } |
| 1751 | 1737 | |
| 1752 | 1738 | const self_exe_path = try fs.selfExePathAlloc(arena); |
| ... | ... | @@ -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 | 2156 | fn cmdTranslateC(comp: *Compilation, arena: *Allocator, enable_cache: bool) !void { |
| 2159 | 2157 | if (!build_options.have_llvm) |
| 2160 | 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 | 2507 | .handle = try zig_lib_directory.handle.openDir(std_special, .{}), |
| 2510 | 2508 | }, |
| 2511 | 2509 | .root_src_path = "build_runner.zig", |
| 2510 | .namespace_hash = Package.root_namespace_hash, | |
| 2512 | 2511 | }; |
| 2513 | 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 | 2553 | var build_pkg: Package = .{ |
| 2555 | 2554 | .root_src_directory = build_directory, |
| 2556 | 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 | 2560 | var global_cache_directory: Compilation.Directory = l: { |
| 2561 | 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 | 9137 | buf_appendf(contents, "pub const position_independent_executable = %s;\n", bool_to_str(g->have_pie)); |
| 9138 | 9138 | buf_appendf(contents, "pub const strip_debug_info = %s;\n", bool_to_str(g->strip_debug_symbols)); |
| 9139 | 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 | 9143 | TargetSubsystem detected_subsystem = detect_subsystem(g); |
src/test.zig+21-42| ... | ... | @@ -122,11 +122,6 @@ pub const TestContext = struct { |
| 122 | 122 | path: []const u8, |
| 123 | 123 | }; |
| 124 | 124 | |
| 125 | pub const Extension = enum { | |
| 126 | Zig, | |
| 127 | ZIR, | |
| 128 | }; | |
| 129 | ||
| 130 | 125 | /// A `Case` consists of a list of `Update`. The same `Compilation` is used for each |
| 131 | 126 | /// update, so each update's source is treated as a single file being |
| 132 | 127 | /// updated by the test harness and incrementally compiled. |
| ... | ... | @@ -141,7 +136,6 @@ pub const TestContext = struct { |
| 141 | 136 | /// to Executable. |
| 142 | 137 | output_mode: std.builtin.OutputMode, |
| 143 | 138 | updates: std.ArrayList(Update), |
| 144 | extension: Extension, | |
| 145 | 139 | object_format: ?std.builtin.ObjectFormat = null, |
| 146 | 140 | emit_h: bool = false, |
| 147 | 141 | llvm_backend: bool = false, |
| ... | ... | @@ -238,14 +232,12 @@ pub const TestContext = struct { |
| 238 | 232 | ctx: *TestContext, |
| 239 | 233 | name: []const u8, |
| 240 | 234 | target: CrossTarget, |
| 241 | extension: Extension, | |
| 242 | 235 | ) *Case { |
| 243 | 236 | ctx.cases.append(Case{ |
| 244 | 237 | .name = name, |
| 245 | 238 | .target = target, |
| 246 | 239 | .updates = std.ArrayList(Update).init(ctx.cases.allocator), |
| 247 | 240 | .output_mode = .Exe, |
| 248 | .extension = extension, | |
| 249 | 241 | .files = std.ArrayList(File).init(ctx.cases.allocator), |
| 250 | 242 | }) catch @panic("out of memory"); |
| 251 | 243 | return &ctx.cases.items[ctx.cases.items.len - 1]; |
| ... | ... | @@ -253,7 +245,7 @@ pub const TestContext = struct { |
| 253 | 245 | |
| 254 | 246 | /// Adds a test case for Zig input, producing an executable |
| 255 | 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 | 251 | /// Adds a test case for ZIR input, producing an executable |
| ... | ... | @@ -269,7 +261,6 @@ pub const TestContext = struct { |
| 269 | 261 | .target = target, |
| 270 | 262 | .updates = std.ArrayList(Update).init(ctx.cases.allocator), |
| 271 | 263 | .output_mode = .Exe, |
| 272 | .extension = .Zig, | |
| 273 | 264 | .object_format = .c, |
| 274 | 265 | .files = std.ArrayList(File).init(ctx.cases.allocator), |
| 275 | 266 | }) catch @panic("out of memory"); |
| ... | ... | @@ -284,7 +275,6 @@ pub const TestContext = struct { |
| 284 | 275 | .target = target, |
| 285 | 276 | .updates = std.ArrayList(Update).init(ctx.cases.allocator), |
| 286 | 277 | .output_mode = .Exe, |
| 287 | .extension = .Zig, | |
| 288 | 278 | .files = std.ArrayList(File).init(ctx.cases.allocator), |
| 289 | 279 | .llvm_backend = true, |
| 290 | 280 | }) catch @panic("out of memory"); |
| ... | ... | @@ -295,14 +285,12 @@ pub const TestContext = struct { |
| 295 | 285 | ctx: *TestContext, |
| 296 | 286 | name: []const u8, |
| 297 | 287 | target: CrossTarget, |
| 298 | extension: Extension, | |
| 299 | 288 | ) *Case { |
| 300 | 289 | ctx.cases.append(Case{ |
| 301 | 290 | .name = name, |
| 302 | 291 | .target = target, |
| 303 | 292 | .updates = std.ArrayList(Update).init(ctx.cases.allocator), |
| 304 | 293 | .output_mode = .Obj, |
| 305 | .extension = extension, | |
| 306 | 294 | .files = std.ArrayList(File).init(ctx.cases.allocator), |
| 307 | 295 | }) catch @panic("out of memory"); |
| 308 | 296 | return &ctx.cases.items[ctx.cases.items.len - 1]; |
| ... | ... | @@ -310,7 +298,7 @@ pub const TestContext = struct { |
| 310 | 298 | |
| 311 | 299 | /// Adds a test case for Zig input, producing an object file. |
| 312 | 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 | 304 | /// Adds a test case for ZIR input, producing an object file. |
| ... | ... | @@ -319,13 +307,12 @@ pub const TestContext = struct { |
| 319 | 307 | } |
| 320 | 308 | |
| 321 | 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 | 311 | ctx.cases.append(Case{ |
| 324 | 312 | .name = name, |
| 325 | 313 | .target = target, |
| 326 | 314 | .updates = std.ArrayList(Update).init(ctx.cases.allocator), |
| 327 | 315 | .output_mode = .Obj, |
| 328 | .extension = ext, | |
| 329 | 316 | .object_format = .c, |
| 330 | 317 | .files = std.ArrayList(File).init(ctx.cases.allocator), |
| 331 | 318 | }) catch @panic("out of memory"); |
| ... | ... | @@ -333,21 +320,20 @@ pub const TestContext = struct { |
| 333 | 320 | } |
| 334 | 321 | |
| 335 | 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 | 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 | 330 | pub fn addCompareOutput( |
| 344 | 331 | ctx: *TestContext, |
| 345 | 332 | name: []const u8, |
| 346 | extension: Extension, | |
| 347 | 333 | src: [:0]const u8, |
| 348 | 334 | expected_stdout: []const u8, |
| 349 | 335 | ) void { |
| 350 | ctx.addExe(name, .{}, extension).addCompareOutput(src, expected_stdout); | |
| 336 | ctx.addExe(name, .{}).addCompareOutput(src, expected_stdout); | |
| 351 | 337 | } |
| 352 | 338 | |
| 353 | 339 | /// Adds a test case that compiles the Zig source given in `src`, executes |
| ... | ... | @@ -358,7 +344,7 @@ pub const TestContext = struct { |
| 358 | 344 | src: [:0]const u8, |
| 359 | 345 | expected_stdout: []const u8, |
| 360 | 346 | ) void { |
| 361 | return ctx.addCompareOutput(name, .Zig, src, expected_stdout); | |
| 347 | return ctx.addCompareOutput(name, src, expected_stdout); | |
| 362 | 348 | } |
| 363 | 349 | |
| 364 | 350 | /// Adds a test case that compiles the ZIR source given in `src`, executes |
| ... | ... | @@ -376,11 +362,10 @@ pub const TestContext = struct { |
| 376 | 362 | ctx: *TestContext, |
| 377 | 363 | name: []const u8, |
| 378 | 364 | target: CrossTarget, |
| 379 | extension: Extension, | |
| 380 | 365 | src: [:0]const u8, |
| 381 | 366 | result: [:0]const u8, |
| 382 | 367 | ) void { |
| 383 | ctx.addObj(name, target, extension).addTransform(src, result); | |
| 368 | ctx.addObj(name, target).addTransform(src, result); | |
| 384 | 369 | } |
| 385 | 370 | |
| 386 | 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 | 377 | src: [:0]const u8, |
| 393 | 378 | result: [:0]const u8, |
| 394 | 379 | ) void { |
| 395 | ctx.addTransform(name, target, .Zig, src, result); | |
| 380 | ctx.addTransform(name, target, src, result); | |
| 396 | 381 | } |
| 397 | 382 | |
| 398 | 383 | /// Adds a test case that cleans up the ZIR source given in `src`, and |
| ... | ... | @@ -411,11 +396,10 @@ pub const TestContext = struct { |
| 411 | 396 | ctx: *TestContext, |
| 412 | 397 | name: []const u8, |
| 413 | 398 | target: CrossTarget, |
| 414 | extension: Extension, | |
| 415 | 399 | src: [:0]const u8, |
| 416 | 400 | expected_errors: []const []const u8, |
| 417 | 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 | 405 | /// Adds a test case that ensures that the Zig given in `src` fails to |
| ... | ... | @@ -428,7 +412,7 @@ pub const TestContext = struct { |
| 428 | 412 | src: [:0]const u8, |
| 429 | 413 | expected_errors: []const []const u8, |
| 430 | 414 | ) void { |
| 431 | ctx.addError(name, target, .Zig, src, expected_errors); | |
| 415 | ctx.addError(name, target, src, expected_errors); | |
| 432 | 416 | } |
| 433 | 417 | |
| 434 | 418 | /// Adds a test case that ensures that the ZIR given in `src` fails to |
| ... | ... | @@ -448,10 +432,9 @@ pub const TestContext = struct { |
| 448 | 432 | ctx: *TestContext, |
| 449 | 433 | name: []const u8, |
| 450 | 434 | target: CrossTarget, |
| 451 | extension: Extension, | |
| 452 | 435 | src: [:0]const u8, |
| 453 | 436 | ) void { |
| 454 | ctx.addObj(name, target, extension).compiles(src); | |
| 437 | ctx.addObj(name, target).compiles(src); | |
| 455 | 438 | } |
| 456 | 439 | |
| 457 | 440 | /// Adds a test case that asserts that the Zig given in `src` compiles |
| ... | ... | @@ -462,7 +445,7 @@ pub const TestContext = struct { |
| 462 | 445 | target: CrossTarget, |
| 463 | 446 | src: [:0]const u8, |
| 464 | 447 | ) void { |
| 465 | ctx.addCompiles(name, target, .Zig, src); | |
| 448 | ctx.addCompiles(name, target, src); | |
| 466 | 449 | } |
| 467 | 450 | |
| 468 | 451 | /// Adds a test case that asserts that the ZIR given in `src` compiles |
| ... | ... | @@ -489,7 +472,7 @@ pub const TestContext = struct { |
| 489 | 472 | expected_errors: []const []const u8, |
| 490 | 473 | fixed_src: [:0]const u8, |
| 491 | 474 | ) void { |
| 492 | var case = ctx.addObj(name, target, .Zig); | |
| 475 | var case = ctx.addObj(name, target); | |
| 493 | 476 | case.addError(src, expected_errors); |
| 494 | 477 | case.compiles(fixed_src); |
| 495 | 478 | } |
| ... | ... | @@ -614,15 +597,14 @@ pub const TestContext = struct { |
| 614 | 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) { | |
| 618 | .Zig => "test_case.zig", | |
| 619 | .ZIR => "test_case.zir", | |
| 620 | }; | |
| 600 | const tmp_src_path = "test_case.zig"; | |
| 621 | 601 | |
| 622 | 602 | var root_pkg: Package = .{ |
| 623 | 603 | .root_src_directory = .{ .path = tmp_dir_path, .handle = tmp.dir }, |
| 624 | 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 | 609 | const bin_name = try std.zig.binNameAlloc(arena, .{ |
| 628 | 610 | .root_name = "test_case", |
| ... | ... | @@ -639,13 +621,10 @@ pub const TestContext = struct { |
| 639 | 621 | .directory = emit_directory, |
| 640 | 622 | .basename = bin_name, |
| 641 | 623 | }; |
| 642 | const emit_h: ?Compilation.EmitLoc = if (case.emit_h) | |
| 643 | .{ | |
| 644 | .directory = emit_directory, | |
| 645 | .basename = "test_case.h", | |
| 646 | } | |
| 647 | else | |
| 648 | null; | |
| 624 | const emit_h: ?Compilation.EmitLoc = if (case.emit_h) .{ | |
| 625 | .directory = emit_directory, | |
| 626 | .basename = "test_case.h", | |
| 627 | } else null; | |
| 649 | 628 | const comp = try Compilation.create(allocator, .{ |
| 650 | 629 | .local_cache_directory = zig_cache_directory, |
| 651 | 630 | .global_cache_directory = global_cache_directory, |
src/zir.zig+43| ... | ... | @@ -328,6 +328,9 @@ pub const Inst = struct { |
| 328 | 328 | error_union_type, |
| 329 | 329 | /// `error.Foo` syntax. Uses the `str_tok` field of the Data union. |
| 330 | 330 | error_value, |
| 331 | /// Implements the `@export` builtin function. | |
| 332 | /// Uses the `pl_node` union field. Payload is `Bin`. | |
| 333 | @"export", | |
| 331 | 334 | /// Given a pointer to a struct or object that contains virtual fields, returns a pointer |
| 332 | 335 | /// to the named field. The field name is stored in string_bytes. Used by a.b syntax. |
| 333 | 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 | 363 | fn_type_cc, |
| 361 | 364 | /// Same as `fn_type_cc` but the function is variadic. |
| 362 | 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 | 369 | /// `@import(operand)`. |
| 364 | 370 | /// Uses the `un_node` field. |
| 365 | 371 | import, |
| ... | ... | @@ -668,12 +674,21 @@ pub const Inst = struct { |
| 668 | 674 | /// A struct literal with a specified type, with no fields. |
| 669 | 675 | /// Uses the `un_node` field. |
| 670 | 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 | 684 | /// Converts an integer into an enum value. |
| 672 | 685 | /// Uses `pl_node` with payload `Bin`. `lhs` is enum type, `rhs` is operand. |
| 673 | 686 | int_to_enum, |
| 674 | 687 | /// Converts an enum value into an integer. Resulting type will be the tag type |
| 675 | 688 | /// of the enum. Uses `un_node`. |
| 676 | 689 | enum_to_int, |
| 690 | /// Implements the `@typeInfo` builtin. Uses `un_node`. | |
| 691 | type_info, | |
| 677 | 692 | |
| 678 | 693 | /// Returns whether the instruction is one of the control flow "noreturn" types. |
| 679 | 694 | /// Function calls do not count. |
| ... | ... | @@ -737,6 +752,7 @@ pub const Inst = struct { |
| 737 | 752 | .elem_val_node, |
| 738 | 753 | .ensure_result_used, |
| 739 | 754 | .ensure_result_non_error, |
| 755 | .@"export", | |
| 740 | 756 | .floatcast, |
| 741 | 757 | .field_ptr, |
| 742 | 758 | .field_val, |
| ... | ... | @@ -746,6 +762,7 @@ pub const Inst = struct { |
| 746 | 762 | .fn_type_var_args, |
| 747 | 763 | .fn_type_cc, |
| 748 | 764 | .fn_type_cc_var_args, |
| 765 | .has_decl, | |
| 749 | 766 | .int, |
| 750 | 767 | .float, |
| 751 | 768 | .float128, |
| ... | ... | @@ -831,8 +848,11 @@ pub const Inst = struct { |
| 831 | 848 | .switch_block_ref_under_multi, |
| 832 | 849 | .validate_struct_init_ptr, |
| 833 | 850 | .struct_init_empty, |
| 851 | .struct_init, | |
| 852 | .field_type, | |
| 834 | 853 | .int_to_enum, |
| 835 | 854 | .enum_to_int, |
| 855 | .type_info, | |
| 836 | 856 | => false, |
| 837 | 857 | |
| 838 | 858 | .@"break", |
| ... | ... | @@ -1543,6 +1563,24 @@ pub const Inst = struct { |
| 1543 | 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 | 1586 | pub const SpecialProng = enum { none, @"else", under }; |
| ... | ... | @@ -1617,6 +1655,7 @@ const Writer = struct { |
| 1617 | 1655 | .typeof_elem, |
| 1618 | 1656 | .struct_init_empty, |
| 1619 | 1657 | .enum_to_int, |
| 1658 | .type_info, | |
| 1620 | 1659 | => try self.writeUnNode(stream, inst), |
| 1621 | 1660 | |
| 1622 | 1661 | .ref, |
| ... | ... | @@ -1657,6 +1696,8 @@ const Writer = struct { |
| 1657 | 1696 | .union_decl, |
| 1658 | 1697 | .enum_decl, |
| 1659 | 1698 | .enum_decl_nonexhaustive, |
| 1699 | .struct_init, | |
| 1700 | .field_type, | |
| 1660 | 1701 | => try self.writePlNode(stream, inst), |
| 1661 | 1702 | |
| 1662 | 1703 | .add, |
| ... | ... | @@ -1676,12 +1717,14 @@ const Writer = struct { |
| 1676 | 1717 | .cmp_gt, |
| 1677 | 1718 | .cmp_neq, |
| 1678 | 1719 | .div, |
| 1720 | .has_decl, | |
| 1679 | 1721 | .mod_rem, |
| 1680 | 1722 | .shl, |
| 1681 | 1723 | .shr, |
| 1682 | 1724 | .xor, |
| 1683 | 1725 | .store_node, |
| 1684 | 1726 | .error_union_type, |
| 1727 | .@"export", | |
| 1685 | 1728 | .merge_error_sets, |
| 1686 | 1729 | .bit_and, |
| 1687 | 1730 | .bit_or, |
test/stack_traces.zig+3-3| ... | ... | @@ -282,10 +282,10 @@ pub fn addCases(cases: *tests.StackTracesContext) void { |
| 282 | 282 | \\source.zig:10:8: [address] in main (test) |
| 283 | 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 | 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 | 289 | \\ @call(.{ .modifier = .never_inline }, posixCallMainAndExit, .{}); |
| 290 | 290 | \\ ^ |
| 291 | 291 | \\ |
| ... | ... | @@ -294,7 +294,7 @@ pub fn addCases(cases: *tests.StackTracesContext) void { |
| 294 | 294 | switch (std.Target.current.cpu.arch) { |
| 295 | 295 | .aarch64 => "", // TODO disabled; results in segfault |
| 296 | 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 | 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 | 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 | 970 | // 64bit set stack |
| 945 | 971 | case.addCompareOutput( |
| 946 | 972 | \\export fn _start() noreturn { |
| ... | ... | @@ -1022,7 +1048,7 @@ pub fn addCases(ctx: *TestContext) !void { |
| 1022 | 1048 | "Hello, World!\n", |
| 1023 | 1049 | ); |
| 1024 | 1050 | try case.files.append(.{ |
| 1025 | .src = | |
| 1051 | .src = | |
| 1026 | 1052 | \\pub fn print() void { |
| 1027 | 1053 | \\ asm volatile ("syscall" |
| 1028 | 1054 | \\ : |
| ... | ... | @@ -1038,11 +1064,61 @@ pub fn addCases(ctx: *TestContext) !void { |
| 1038 | 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 | 1105 | ctx.compileError("function redefinition", linux_x64, |
| 1106 | \\// dummy comment | |
| 1043 | 1107 | \\fn entry() void {} |
| 1044 | 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 | 1123 | ctx.compileError("compileError", linux_x64, |
| 1048 | 1124 | \\export fn _start() noreturn { |