| author | |
| committer | |
| log | 332eafeb7f3d866556ab767b960a04661bc43bc7 |
| tree | d299cbc233ca756ca42885e66f54e2b08f2a3d9a |
| parent | c05a20fc8c36742dab8792d15e79716da1a55759 |
Ran into a design flaw here which will need to get solved by having
AstGen annotate ZIR with which instructions are closed over.18 files changed, 385 insertions(+), 243 deletions(-)
src/AstGen.zig+4-1| ... | ... | @@ -6416,6 +6416,9 @@ fn identifier( |
| 6416 | 6416 | }, |
| 6417 | 6417 | .top => break, |
| 6418 | 6418 | }; |
| 6419 | if (found_already == null) { | |
| 6420 | return astgen.failNode(ident, "use of undeclared identifier '{s}'", .{ident_name}); | |
| 6421 | } | |
| 6419 | 6422 | |
| 6420 | 6423 | // Decl references happen by name rather than ZIR index so that when unrelated |
| 6421 | 6424 | // decls are modified, ZIR code containing references to them can be unmodified. |
| ... | ... | @@ -10052,7 +10055,7 @@ fn isPrimitive(name: []const u8) bool { |
| 10052 | 10055 | } |
| 10053 | 10056 | } |
| 10054 | 10057 | |
| 10055 | /// Local variables shadowing detection, including function parameters and primitives. | |
| 10058 | /// Local variables shadowing detection, including function parameters. | |
| 10056 | 10059 | fn detectLocalShadowing( |
| 10057 | 10060 | astgen: *AstGen, |
| 10058 | 10061 | scope: *Scope, |
src/Module.zig+50-12| ... | ... | @@ -365,6 +365,8 @@ pub const Decl = struct { |
| 365 | 365 | /// Decl is marked alive, then it sends the Decl to the linker. Otherwise it |
| 366 | 366 | /// deletes the Decl on the spot. |
| 367 | 367 | alive: bool, |
| 368 | /// Whether the Decl is a `usingnamespace` declaration. | |
| 369 | is_usingnamespace: bool, | |
| 368 | 370 | |
| 369 | 371 | /// Represents the position of the code in the output file. |
| 370 | 372 | /// This is populated regardless of semantic analysis and code generation. |
| ... | ... | @@ -1008,6 +1010,11 @@ pub const Scope = struct { |
| 1008 | 1010 | |
| 1009 | 1011 | anon_decls: std.AutoArrayHashMapUnmanaged(*Decl, void) = .{}, |
| 1010 | 1012 | |
| 1013 | /// Key is usingnamespace Decl itself. To find the namespace being included, | |
| 1014 | /// the Decl Value has to be resolved as a Type which has a Namespace. | |
| 1015 | /// Value is whether the usingnamespace decl is marked `pub`. | |
| 1016 | usingnamespace_set: std.AutoHashMapUnmanaged(*Decl, bool) = .{}, | |
| 1017 | ||
| 1011 | 1018 | pub fn deinit(ns: *Namespace, mod: *Module) void { |
| 1012 | 1019 | ns.destroyDecls(mod); |
| 1013 | 1020 | ns.* = undefined; |
| ... | ... | @@ -3174,6 +3181,31 @@ fn semaDecl(mod: *Module, decl: *Decl) !bool { |
| 3174 | 3181 | errdefer decl_arena.deinit(); |
| 3175 | 3182 | const decl_arena_state = try decl_arena.allocator.create(std.heap.ArenaAllocator.State); |
| 3176 | 3183 | |
| 3184 | if (decl.is_usingnamespace) { | |
| 3185 | const ty_ty = Type.initTag(.type); | |
| 3186 | if (!decl_tv.ty.eql(ty_ty)) { | |
| 3187 | return mod.fail(&block_scope.base, src, "expected type, found {}", .{decl_tv.ty}); | |
| 3188 | } | |
| 3189 | var buffer: Value.ToTypeBuffer = undefined; | |
| 3190 | const ty = decl_tv.val.toType(&buffer); | |
| 3191 | if (ty.getNamespace() == null) { | |
| 3192 | return mod.fail(&block_scope.base, src, "type {} has no namespace", .{ty}); | |
| 3193 | } | |
| 3194 | ||
| 3195 | decl.ty = ty_ty; | |
| 3196 | decl.val = try Value.Tag.ty.create(&decl_arena.allocator, ty); | |
| 3197 | decl.align_val = Value.initTag(.null_value); | |
| 3198 | decl.linksection_val = Value.initTag(.null_value); | |
| 3199 | decl.has_tv = true; | |
| 3200 | decl.owns_tv = false; | |
| 3201 | decl_arena_state.* = decl_arena.state; | |
| 3202 | decl.value_arena = decl_arena_state; | |
| 3203 | decl.analysis = .complete; | |
| 3204 | decl.generation = mod.generation; | |
| 3205 | ||
| 3206 | return true; | |
| 3207 | } | |
| 3208 | ||
| 3177 | 3209 | if (decl_tv.val.castTag(.function)) |fn_payload| { |
| 3178 | 3210 | const func = fn_payload.data; |
| 3179 | 3211 | const owns_tv = func.owner_decl == decl; |
| ... | ... | @@ -3269,16 +3301,13 @@ fn semaDecl(mod: *Module, decl: *Decl) !bool { |
| 3269 | 3301 | if (type_changed and mod.emit_h != null) { |
| 3270 | 3302 | try mod.comp.work_queue.writeItem(.{ .emit_h_decl = decl }); |
| 3271 | 3303 | } |
| 3272 | } else if (decl_tv.ty.zigTypeTag() == .Type) { | |
| 3273 | // In case this Decl is a struct or union, we need to resolve the fields | |
| 3274 | // while we still have the `Sema` in scope, so that the field type expressions | |
| 3275 | // can use the resolved AIR instructions that they possibly reference. | |
| 3276 | // We do this after the decl is populated and set to `complete` so that a `Decl` | |
| 3277 | // may reference itself. | |
| 3278 | var buffer: Value.ToTypeBuffer = undefined; | |
| 3279 | const ty = decl.val.toType(&buffer); | |
| 3280 | try sema.resolveDeclFields(&block_scope, src, ty); | |
| 3281 | 3304 | } |
| 3305 | // In case this Decl is a struct or union, we need to resolve the fields | |
| 3306 | // while we still have the `Sema` in scope, so that the field type expressions | |
| 3307 | // can use the resolved AIR instructions that they possibly reference. | |
| 3308 | // We do this after the decl is populated and set to `complete` so that a `Decl` | |
| 3309 | // may reference itself. | |
| 3310 | try sema.resolvePendingTypes(&block_scope); | |
| 3282 | 3311 | |
| 3283 | 3312 | if (decl.is_exported) { |
| 3284 | 3313 | const export_src = src; // TODO point to the export token |
| ... | ... | @@ -3494,7 +3523,7 @@ fn scanDecl(iter: *ScanDeclIter, decl_sub_index: usize, flags: u4) SemaError!voi |
| 3494 | 3523 | |
| 3495 | 3524 | // zig fmt: off |
| 3496 | 3525 | const is_pub = (flags & 0b0001) != 0; |
| 3497 | const is_exported = (flags & 0b0010) != 0; | |
| 3526 | const export_bit = (flags & 0b0010) != 0; | |
| 3498 | 3527 | const has_align = (flags & 0b0100) != 0; |
| 3499 | 3528 | const has_linksection = (flags & 0b1000) != 0; |
| 3500 | 3529 | // zig fmt: on |
| ... | ... | @@ -3509,7 +3538,7 @@ fn scanDecl(iter: *ScanDeclIter, decl_sub_index: usize, flags: u4) SemaError!voi |
| 3509 | 3538 | var is_named_test = false; |
| 3510 | 3539 | const decl_name: [:0]const u8 = switch (decl_name_index) { |
| 3511 | 3540 | 0 => name: { |
| 3512 | if (is_exported) { | |
| 3541 | if (export_bit) { | |
| 3513 | 3542 | const i = iter.usingnamespace_index; |
| 3514 | 3543 | iter.usingnamespace_index += 1; |
| 3515 | 3544 | break :name try std.fmt.allocPrintZ(gpa, "usingnamespace_{d}", .{i}); |
| ... | ... | @@ -3535,11 +3564,17 @@ fn scanDecl(iter: *ScanDeclIter, decl_sub_index: usize, flags: u4) SemaError!voi |
| 3535 | 3564 | } |
| 3536 | 3565 | }, |
| 3537 | 3566 | }; |
| 3567 | const is_exported = export_bit and decl_name_index != 0; | |
| 3568 | const is_usingnamespace = export_bit and decl_name_index == 0; | |
| 3569 | if (is_usingnamespace) try namespace.usingnamespace_set.ensureUnusedCapacity(gpa, 1); | |
| 3538 | 3570 | |
| 3539 | 3571 | // We create a Decl for it regardless of analysis status. |
| 3540 | 3572 | const gop = try namespace.decls.getOrPut(gpa, decl_name); |
| 3541 | 3573 | if (!gop.found_existing) { |
| 3542 | 3574 | const new_decl = try mod.allocateNewDecl(namespace, decl_node); |
| 3575 | if (is_usingnamespace) { | |
| 3576 | namespace.usingnamespace_set.putAssumeCapacity(new_decl, is_pub); | |
| 3577 | } | |
| 3543 | 3578 | log.debug("scan new {*} ({s}) into {*}", .{ new_decl, decl_name, namespace }); |
| 3544 | 3579 | new_decl.src_line = line; |
| 3545 | 3580 | new_decl.name = decl_name; |
| ... | ... | @@ -3548,7 +3583,7 @@ fn scanDecl(iter: *ScanDeclIter, decl_sub_index: usize, flags: u4) SemaError!voi |
| 3548 | 3583 | // test decls if in test mode, get analyzed. |
| 3549 | 3584 | const decl_pkg = namespace.file_scope.pkg; |
| 3550 | 3585 | const want_analysis = is_exported or switch (decl_name_index) { |
| 3551 | 0 => true, // comptime decl | |
| 3586 | 0 => true, // comptime or usingnamespace decl | |
| 3552 | 3587 | 1 => blk: { |
| 3553 | 3588 | // test decl with no name. Skip the part where we check against |
| 3554 | 3589 | // the test name filter. |
| ... | ... | @@ -3571,6 +3606,7 @@ fn scanDecl(iter: *ScanDeclIter, decl_sub_index: usize, flags: u4) SemaError!voi |
| 3571 | 3606 | } |
| 3572 | 3607 | new_decl.is_pub = is_pub; |
| 3573 | 3608 | new_decl.is_exported = is_exported; |
| 3609 | new_decl.is_usingnamespace = is_usingnamespace; | |
| 3574 | 3610 | new_decl.has_align = has_align; |
| 3575 | 3611 | new_decl.has_linksection = has_linksection; |
| 3576 | 3612 | new_decl.zir_decl_index = @intCast(u32, decl_sub_index); |
| ... | ... | @@ -3587,6 +3623,7 @@ fn scanDecl(iter: *ScanDeclIter, decl_sub_index: usize, flags: u4) SemaError!voi |
| 3587 | 3623 | |
| 3588 | 3624 | decl.is_pub = is_pub; |
| 3589 | 3625 | decl.is_exported = is_exported; |
| 3626 | decl.is_usingnamespace = is_usingnamespace; | |
| 3590 | 3627 | decl.has_align = has_align; |
| 3591 | 3628 | decl.has_linksection = has_linksection; |
| 3592 | 3629 | decl.zir_decl_index = @intCast(u32, decl_sub_index); |
| ... | ... | @@ -3979,6 +4016,7 @@ pub fn allocateNewDecl(mod: *Module, namespace: *Scope.Namespace, src_node: ast. |
| 3979 | 4016 | .has_linksection = false, |
| 3980 | 4017 | .has_align = false, |
| 3981 | 4018 | .alive = false, |
| 4019 | .is_usingnamespace = false, | |
| 3982 | 4020 | }; |
| 3983 | 4021 | return new_decl; |
| 3984 | 4022 | } |
src/Sema.zig+99-16| ... | ... | @@ -58,6 +58,9 @@ comptime_args_fn_inst: Zir.Inst.Index = 0, |
| 58 | 58 | /// extra hash table lookup in the `monomorphed_funcs` set. |
| 59 | 59 | /// Sema will set this to null when it takes ownership. |
| 60 | 60 | preallocated_new_func: ?*Module.Fn = null, |
| 61 | /// Collects struct, union, enum, and opaque decls which need to have their | |
| 62 | /// fields resolved before this Sema is deinitialized. | |
| 63 | types_pending_resolution: std.ArrayListUnmanaged(Type) = .{}, | |
| 61 | 64 | |
| 62 | 65 | const std = @import("std"); |
| 63 | 66 | const mem = std.mem; |
| ... | ... | @@ -90,6 +93,7 @@ pub fn deinit(sema: *Sema) void { |
| 90 | 93 | sema.air_values.deinit(gpa); |
| 91 | 94 | sema.inst_map.deinit(gpa); |
| 92 | 95 | sema.decl_val_table.deinit(gpa); |
| 96 | sema.types_pending_resolution.deinit(gpa); | |
| 93 | 97 | sema.* = undefined; |
| 94 | 98 | } |
| 95 | 99 | |
| ... | ... | @@ -908,7 +912,9 @@ fn zirStructDecl( |
| 908 | 912 | &struct_obj.namespace, new_decl, new_decl.name, |
| 909 | 913 | }); |
| 910 | 914 | try sema.analyzeStructDecl(new_decl, inst, struct_obj); |
| 915 | try sema.types_pending_resolution.ensureUnusedCapacity(sema.gpa, 1); | |
| 911 | 916 | try new_decl.finalizeNewArena(&new_decl_arena); |
| 917 | sema.types_pending_resolution.appendAssumeCapacity(struct_ty); | |
| 912 | 918 | return sema.analyzeDeclVal(block, src, new_decl); |
| 913 | 919 | } |
| 914 | 920 | |
| ... | ... | @@ -1198,7 +1204,9 @@ fn zirUnionDecl( |
| 1198 | 1204 | |
| 1199 | 1205 | _ = try sema.mod.scanNamespace(&union_obj.namespace, extra_index, decls_len, new_decl); |
| 1200 | 1206 | |
| 1207 | try sema.types_pending_resolution.ensureUnusedCapacity(sema.gpa, 1); | |
| 1201 | 1208 | try new_decl.finalizeNewArena(&new_decl_arena); |
| 1209 | sema.types_pending_resolution.appendAssumeCapacity(union_ty); | |
| 1202 | 1210 | return sema.analyzeDeclVal(block, src, new_decl); |
| 1203 | 1211 | } |
| 1204 | 1212 | |
| ... | ... | @@ -2324,42 +2332,105 @@ fn zirDeclVal(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileErr |
| 2324 | 2332 | } |
| 2325 | 2333 | |
| 2326 | 2334 | fn lookupIdentifier(sema: *Sema, block: *Scope.Block, src: LazySrcLoc, name: []const u8) !*Decl { |
| 2327 | // TODO emit a compile error if more than one decl would be matched. | |
| 2328 | 2335 | var namespace = sema.namespace; |
| 2329 | 2336 | while (true) { |
| 2330 | if (try sema.lookupInNamespace(namespace, name)) |decl| { | |
| 2337 | if (try sema.lookupInNamespace(block, src, namespace, name, false)) |decl| { | |
| 2331 | 2338 | return decl; |
| 2332 | 2339 | } |
| 2333 | 2340 | namespace = namespace.parent orelse break; |
| 2334 | 2341 | } |
| 2335 | return sema.mod.fail(&block.base, src, "use of undeclared identifier '{s}'", .{name}); | |
| 2342 | unreachable; // AstGen detects use of undeclared identifier errors. | |
| 2336 | 2343 | } |
| 2337 | 2344 | |
| 2338 | 2345 | /// This looks up a member of a specific namespace. It is affected by `usingnamespace` but |
| 2339 | 2346 | /// only for ones in the specified namespace. |
| 2340 | 2347 | fn lookupInNamespace( |
| 2341 | 2348 | sema: *Sema, |
| 2349 | block: *Scope.Block, | |
| 2350 | src: LazySrcLoc, | |
| 2342 | 2351 | namespace: *Scope.Namespace, |
| 2343 | 2352 | ident_name: []const u8, |
| 2353 | observe_usingnamespace: bool, | |
| 2344 | 2354 | ) CompileError!?*Decl { |
| 2355 | const mod = sema.mod; | |
| 2356 | ||
| 2345 | 2357 | const namespace_decl = namespace.getDecl(); |
| 2346 | 2358 | if (namespace_decl.analysis == .file_failure) { |
| 2347 | try sema.mod.declareDeclDependency(sema.owner_decl, namespace_decl); | |
| 2359 | try mod.declareDeclDependency(sema.owner_decl, namespace_decl); | |
| 2348 | 2360 | return error.AnalysisFail; |
| 2349 | 2361 | } |
| 2350 | 2362 | |
| 2351 | // TODO implement usingnamespace | |
| 2352 | if (namespace.decls.get(ident_name)) |decl| { | |
| 2353 | try sema.mod.declareDeclDependency(sema.owner_decl, decl); | |
| 2363 | if (observe_usingnamespace and namespace.usingnamespace_set.count() != 0) { | |
| 2364 | const src_file = block.src_decl.namespace.file_scope; | |
| 2365 | ||
| 2366 | const gpa = sema.gpa; | |
| 2367 | var checked_namespaces: std.AutoArrayHashMapUnmanaged(*Scope.Namespace, void) = .{}; | |
| 2368 | defer checked_namespaces.deinit(gpa); | |
| 2369 | ||
| 2370 | // Keep track of name conflicts for error notes. | |
| 2371 | var candidates: std.ArrayListUnmanaged(*Decl) = .{}; | |
| 2372 | defer candidates.deinit(gpa); | |
| 2373 | ||
| 2374 | try checked_namespaces.put(gpa, namespace, {}); | |
| 2375 | var check_i: usize = 0; | |
| 2376 | ||
| 2377 | while (check_i < checked_namespaces.count()) : (check_i += 1) { | |
| 2378 | const check_ns = checked_namespaces.keys()[check_i]; | |
| 2379 | if (check_ns.decls.get(ident_name)) |decl| { | |
| 2380 | // Skip decls which are not marked pub, which are in a different | |
| 2381 | // file than the `a.b`/`@hasDecl` syntax. | |
| 2382 | if (decl.is_pub or src_file == decl.namespace.file_scope) { | |
| 2383 | try candidates.append(gpa, decl); | |
| 2384 | } | |
| 2385 | } | |
| 2386 | var it = check_ns.usingnamespace_set.iterator(); | |
| 2387 | while (it.next()) |entry| { | |
| 2388 | const sub_usingnamespace_decl = entry.key_ptr.*; | |
| 2389 | const sub_is_pub = entry.value_ptr.*; | |
| 2390 | if (!sub_is_pub and src_file != sub_usingnamespace_decl.namespace.file_scope) { | |
| 2391 | // Skip usingnamespace decls which are not marked pub, which are in | |
| 2392 | // a different file than the `a.b`/`@hasDecl` syntax. | |
| 2393 | continue; | |
| 2394 | } | |
| 2395 | try sema.ensureDeclAnalyzed(sub_usingnamespace_decl); | |
| 2396 | const ns_ty = sub_usingnamespace_decl.val.castTag(.ty).?.data; | |
| 2397 | const sub_ns = ns_ty.getNamespace().?; | |
| 2398 | try checked_namespaces.put(gpa, sub_ns, {}); | |
| 2399 | } | |
| 2400 | } | |
| 2401 | ||
| 2402 | switch (candidates.items.len) { | |
| 2403 | 0 => {}, | |
| 2404 | 1 => { | |
| 2405 | const decl = candidates.items[0]; | |
| 2406 | try mod.declareDeclDependency(sema.owner_decl, decl); | |
| 2407 | return decl; | |
| 2408 | }, | |
| 2409 | else => { | |
| 2410 | const msg = msg: { | |
| 2411 | const msg = try mod.errMsg(&block.base, src, "ambiguous reference", .{}); | |
| 2412 | errdefer msg.destroy(gpa); | |
| 2413 | for (candidates.items) |candidate| { | |
| 2414 | const src_loc = candidate.srcLoc(); | |
| 2415 | try mod.errNoteNonLazy(src_loc, msg, "declared here", .{}); | |
| 2416 | } | |
| 2417 | break :msg msg; | |
| 2418 | }; | |
| 2419 | return mod.failWithOwnedErrorMsg(&block.base, msg); | |
| 2420 | }, | |
| 2421 | } | |
| 2422 | } else if (namespace.decls.get(ident_name)) |decl| { | |
| 2423 | try mod.declareDeclDependency(sema.owner_decl, decl); | |
| 2354 | 2424 | return decl; |
| 2355 | 2425 | } |
| 2426 | ||
| 2356 | 2427 | log.debug("{*} ({s}) depends on non-existence of '{s}' in {*} ({s})", .{ |
| 2357 | 2428 | sema.owner_decl, sema.owner_decl.name, ident_name, namespace_decl, namespace_decl.name, |
| 2358 | 2429 | }); |
| 2359 | 2430 | // TODO This dependency is too strong. Really, it should only be a dependency |
| 2360 | 2431 | // on the non-existence of `ident_name` in the namespace. We can lessen the number of |
| 2361 | 2432 | // outdated declarations by making this dependency more sophisticated. |
| 2362 | try sema.mod.declareDeclDependency(sema.owner_decl, namespace_decl); | |
| 2433 | try mod.declareDeclDependency(sema.owner_decl, namespace_decl); | |
| 2363 | 2434 | return null; |
| 2364 | 2435 | } |
| 2365 | 2436 | |
| ... | ... | @@ -2727,10 +2798,7 @@ fn analyzeCall( |
| 2727 | 2798 | // we need to resolve the field type expressions right here, right now, while |
| 2728 | 2799 | // the child `Sema` is still available, with the AIR instruction map intact, |
| 2729 | 2800 | // because the field type expressions may reference into it. |
| 2730 | if (sema.typeOf(result).zigTypeTag() == .Type) { | |
| 2731 | const ty = try sema.analyzeAsType(&child_block, call_src, result); | |
| 2732 | try sema.resolveDeclFields(&child_block, call_src, ty); | |
| 2733 | } | |
| 2801 | try sema.resolvePendingTypes(&child_block); | |
| 2734 | 2802 | } |
| 2735 | 2803 | |
| 2736 | 2804 | break :res2 result; |
| ... | ... | @@ -5332,6 +5400,7 @@ fn zirHasField(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileEr |
| 5332 | 5400 | fn zirHasDecl(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { |
| 5333 | 5401 | const inst_data = sema.code.instructions.items(.data)[inst].pl_node; |
| 5334 | 5402 | const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data; |
| 5403 | const src = inst_data.src(); | |
| 5335 | 5404 | const lhs_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node }; |
| 5336 | 5405 | const rhs_src: LazySrcLoc = .{ .node_offset_builtin_call_arg1 = inst_data.src_node }; |
| 5337 | 5406 | const container_type = try sema.resolveType(block, lhs_src, extra.lhs); |
| ... | ... | @@ -5344,7 +5413,7 @@ fn zirHasDecl(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileErr |
| 5344 | 5413 | "expected struct, enum, union, or opaque, found '{}'", |
| 5345 | 5414 | .{container_type}, |
| 5346 | 5415 | ); |
| 5347 | if (try sema.lookupInNamespace(namespace, decl_name)) |decl| { | |
| 5416 | if (try sema.lookupInNamespace(block, src, namespace, decl_name, true)) |decl| { | |
| 5348 | 5417 | if (decl.is_pub or decl.namespace.file_scope == block.base.namespace().file_scope) { |
| 5349 | 5418 | return Air.Inst.Ref.bool_true; |
| 5350 | 5419 | } |
| ... | ... | @@ -8203,7 +8272,7 @@ fn namespaceLookup( |
| 8203 | 8272 | ) CompileError!?*Decl { |
| 8204 | 8273 | const mod = sema.mod; |
| 8205 | 8274 | const gpa = sema.gpa; |
| 8206 | if (try sema.lookupInNamespace(namespace, decl_name)) |decl| { | |
| 8275 | if (try sema.lookupInNamespace(block, src, namespace, decl_name, true)) |decl| { | |
| 8207 | 8276 | if (!decl.is_pub and decl.namespace.file_scope != block.getFileScope()) { |
| 8208 | 8277 | const msg = msg: { |
| 8209 | 8278 | const msg = try mod.errMsg(&block.base, src, "'{s}' is not marked 'pub'", .{ |
| ... | ... | @@ -8919,8 +8988,7 @@ fn analyzeDeclVal( |
| 8919 | 8988 | return result; |
| 8920 | 8989 | } |
| 8921 | 8990 | |
| 8922 | fn analyzeDeclRef(sema: *Sema, decl: *Decl) CompileError!Air.Inst.Ref { | |
| 8923 | try sema.mod.declareDeclDependency(sema.owner_decl, decl); | |
| 8991 | fn ensureDeclAnalyzed(sema: *Sema, decl: *Decl) CompileError!void { | |
| 8924 | 8992 | sema.mod.ensureDeclAnalyzed(decl) catch |err| { |
| 8925 | 8993 | if (sema.owner_func) |owner_func| { |
| 8926 | 8994 | owner_func.state = .dependency_failure; |
| ... | ... | @@ -8929,6 +8997,11 @@ fn analyzeDeclRef(sema: *Sema, decl: *Decl) CompileError!Air.Inst.Ref { |
| 8929 | 8997 | } |
| 8930 | 8998 | return err; |
| 8931 | 8999 | }; |
| 9000 | } | |
| 9001 | ||
| 9002 | fn analyzeDeclRef(sema: *Sema, decl: *Decl) CompileError!Air.Inst.Ref { | |
| 9003 | try sema.mod.declareDeclDependency(sema.owner_decl, decl); | |
| 9004 | try sema.ensureDeclAnalyzed(decl); | |
| 8932 | 9005 | |
| 8933 | 9006 | const decl_tv = try decl.typedValue(); |
| 8934 | 9007 | if (decl_tv.val.castTag(.variable)) |payload| { |
| ... | ... | @@ -9560,6 +9633,16 @@ pub fn resolveTypeLayout( |
| 9560 | 9633 | } |
| 9561 | 9634 | } |
| 9562 | 9635 | |
| 9636 | pub fn resolvePendingTypes(sema: *Sema, block: *Scope.Block) !void { | |
| 9637 | for (sema.types_pending_resolution.items) |ty| { | |
| 9638 | // If an error happens resolving the fields of a struct, it will be marked | |
| 9639 | // invalid and a proper compile error set up. But we should still look at the | |
| 9640 | // other types pending resolution. | |
| 9641 | const src: LazySrcLoc = .{ .node_offset = 0 }; | |
| 9642 | sema.resolveDeclFields(block, src, ty) catch continue; | |
| 9643 | } | |
| 9644 | } | |
| 9645 | ||
| 9563 | 9646 | /// `sema` and `block` are expected to be the same ones used for the `Decl`. |
| 9564 | 9647 | pub fn resolveDeclFields(sema: *Sema, block: *Scope.Block, src: LazySrcLoc, ty: Type) !void { |
| 9565 | 9648 | switch (ty.tag()) { |
src/codegen.zig+13-13| ... | ... | @@ -899,7 +899,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { |
| 899 | 899 | fn dbgSetPrologueEnd(self: *Self) InnerError!void { |
| 900 | 900 | switch (self.debug_output) { |
| 901 | 901 | .dwarf => |dbg_out| { |
| 902 | try dbg_out.dbg_line.append(DW.LNS_set_prologue_end); | |
| 902 | try dbg_out.dbg_line.append(DW.LNS.set_prologue_end); | |
| 903 | 903 | try self.dbgAdvancePCAndLine(self.prev_di_line, self.prev_di_column); |
| 904 | 904 | }, |
| 905 | 905 | .none => {}, |
| ... | ... | @@ -909,7 +909,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { |
| 909 | 909 | fn dbgSetEpilogueBegin(self: *Self) InnerError!void { |
| 910 | 910 | switch (self.debug_output) { |
| 911 | 911 | .dwarf => |dbg_out| { |
| 912 | try dbg_out.dbg_line.append(DW.LNS_set_epilogue_begin); | |
| 912 | try dbg_out.dbg_line.append(DW.LNS.set_epilogue_begin); | |
| 913 | 913 | try self.dbgAdvancePCAndLine(self.prev_di_line, self.prev_di_column); |
| 914 | 914 | }, |
| 915 | 915 | .none => {}, |
| ... | ... | @@ -925,13 +925,13 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { |
| 925 | 925 | // It lets you emit single-byte opcodes that add different numbers to |
| 926 | 926 | // both the PC and the line number at the same time. |
| 927 | 927 | try dbg_out.dbg_line.ensureUnusedCapacity(11); |
| 928 | dbg_out.dbg_line.appendAssumeCapacity(DW.LNS_advance_pc); | |
| 928 | dbg_out.dbg_line.appendAssumeCapacity(DW.LNS.advance_pc); | |
| 929 | 929 | leb128.writeULEB128(dbg_out.dbg_line.writer(), delta_pc) catch unreachable; |
| 930 | 930 | if (delta_line != 0) { |
| 931 | dbg_out.dbg_line.appendAssumeCapacity(DW.LNS_advance_line); | |
| 931 | dbg_out.dbg_line.appendAssumeCapacity(DW.LNS.advance_line); | |
| 932 | 932 | leb128.writeILEB128(dbg_out.dbg_line.writer(), delta_line) catch unreachable; |
| 933 | 933 | } |
| 934 | dbg_out.dbg_line.appendAssumeCapacity(DW.LNS_copy); | |
| 934 | dbg_out.dbg_line.appendAssumeCapacity(DW.LNS.copy); | |
| 935 | 935 | }, |
| 936 | 936 | .none => {}, |
| 937 | 937 | } |
| ... | ... | @@ -1010,7 +1010,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { |
| 1010 | 1010 | .dwarf => |dbg_out| { |
| 1011 | 1011 | assert(ty.hasCodeGenBits()); |
| 1012 | 1012 | const index = dbg_out.dbg_info.items.len; |
| 1013 | try dbg_out.dbg_info.resize(index + 4); // DW.AT_type, DW.FORM_ref4 | |
| 1013 | try dbg_out.dbg_info.resize(index + 4); // DW.AT.type, DW.FORM.ref4 | |
| 1014 | 1014 | |
| 1015 | 1015 | const gop = try dbg_out.dbg_info_type_relocs.getOrPut(self.gpa, ty); |
| 1016 | 1016 | if (!gop.found_existing) { |
| ... | ... | @@ -2438,13 +2438,13 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { |
| 2438 | 2438 | .dwarf => |dbg_out| { |
| 2439 | 2439 | try dbg_out.dbg_info.ensureCapacity(dbg_out.dbg_info.items.len + 3); |
| 2440 | 2440 | dbg_out.dbg_info.appendAssumeCapacity(link.File.Elf.abbrev_parameter); |
| 2441 | dbg_out.dbg_info.appendSliceAssumeCapacity(&[2]u8{ // DW.AT_location, DW.FORM_exprloc | |
| 2441 | dbg_out.dbg_info.appendSliceAssumeCapacity(&[2]u8{ // DW.AT.location, DW.FORM.exprloc | |
| 2442 | 2442 | 1, // ULEB128 dwarf expression length |
| 2443 | 2443 | reg.dwarfLocOp(), |
| 2444 | 2444 | }); |
| 2445 | 2445 | try dbg_out.dbg_info.ensureCapacity(dbg_out.dbg_info.items.len + 5 + name_with_null.len); |
| 2446 | try self.addDbgInfoTypeReloc(ty); // DW.AT_type, DW.FORM_ref4 | |
| 2447 | dbg_out.dbg_info.appendSliceAssumeCapacity(name_with_null); // DW.AT_name, DW.FORM_string | |
| 2446 | try self.addDbgInfoTypeReloc(ty); // DW.AT.type, DW.FORM.ref4 | |
| 2447 | dbg_out.dbg_info.appendSliceAssumeCapacity(name_with_null); // DW.AT.name, DW.FORM.string | |
| 2448 | 2448 | }, |
| 2449 | 2449 | .none => {}, |
| 2450 | 2450 | } |
| ... | ... | @@ -2467,15 +2467,15 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { |
| 2467 | 2467 | var counting_writer = std.io.countingWriter(std.io.null_writer); |
| 2468 | 2468 | leb128.writeILEB128(counting_writer.writer(), adjusted_stack_offset) catch unreachable; |
| 2469 | 2469 | |
| 2470 | // DW.AT_location, DW.FORM_exprloc | |
| 2470 | // DW.AT.location, DW.FORM.exprloc | |
| 2471 | 2471 | // ULEB128 dwarf expression length |
| 2472 | 2472 | try leb128.writeULEB128(dbg_out.dbg_info.writer(), counting_writer.bytes_written + 1); |
| 2473 | try dbg_out.dbg_info.append(DW.OP_breg11); | |
| 2473 | try dbg_out.dbg_info.append(DW.OP.breg11); | |
| 2474 | 2474 | try leb128.writeILEB128(dbg_out.dbg_info.writer(), adjusted_stack_offset); |
| 2475 | 2475 | |
| 2476 | 2476 | try dbg_out.dbg_info.ensureCapacity(dbg_out.dbg_info.items.len + 5 + name_with_null.len); |
| 2477 | try self.addDbgInfoTypeReloc(ty); // DW.AT_type, DW.FORM_ref4 | |
| 2478 | dbg_out.dbg_info.appendSliceAssumeCapacity(name_with_null); // DW.AT_name, DW.FORM_string | |
| 2477 | try self.addDbgInfoTypeReloc(ty); // DW.AT.type, DW.FORM.ref4 | |
| 2478 | dbg_out.dbg_info.appendSliceAssumeCapacity(name_with_null); // DW.AT.name, DW.FORM.string | |
| 2479 | 2479 | }, |
| 2480 | 2480 | else => {}, |
| 2481 | 2481 | } |
src/codegen/aarch64.zig+1-1| ... | ... | @@ -52,7 +52,7 @@ pub const Register = enum(u6) { |
| 52 | 52 | } |
| 53 | 53 | |
| 54 | 54 | pub fn dwarfLocOp(self: Register) u8 { |
| 55 | return @as(u8, self.id()) + DW.OP_reg0; | |
| 55 | return @as(u8, self.id()) + DW.OP.reg0; | |
| 56 | 56 | } |
| 57 | 57 | }; |
| 58 | 58 |
src/codegen/arm.zig+1-1| ... | ... | @@ -170,7 +170,7 @@ pub const Register = enum(u5) { |
| 170 | 170 | } |
| 171 | 171 | |
| 172 | 172 | pub fn dwarfLocOp(self: Register) u8 { |
| 173 | return @as(u8, self.id()) + DW.OP_reg0; | |
| 173 | return @as(u8, self.id()) + DW.OP.reg0; | |
| 174 | 174 | } |
| 175 | 175 | }; |
| 176 | 176 |
src/codegen/riscv64.zig+2-2| ... | ... | @@ -390,7 +390,7 @@ pub const RawRegister = enum(u5) { |
| 390 | 390 | x24, x25, x26, x27, x28, x29, x30, x31, |
| 391 | 391 | |
| 392 | 392 | pub fn dwarfLocOp(reg: RawRegister) u8 { |
| 393 | return @enumToInt(reg) + DW.OP_reg0; | |
| 393 | return @enumToInt(reg) + DW.OP.reg0; | |
| 394 | 394 | } |
| 395 | 395 | }; |
| 396 | 396 | |
| ... | ... | @@ -424,7 +424,7 @@ pub const Register = enum(u5) { |
| 424 | 424 | } |
| 425 | 425 | |
| 426 | 426 | pub fn dwarfLocOp(reg: Register) u8 { |
| 427 | return @as(u8, @enumToInt(reg)) + DW.OP_reg0; | |
| 427 | return @as(u8, @enumToInt(reg)) + DW.OP.reg0; | |
| 428 | 428 | } |
| 429 | 429 | }; |
| 430 | 430 |
src/codegen/x86.zig+8-8| ... | ... | @@ -59,14 +59,14 @@ pub const Register = enum(u8) { |
| 59 | 59 | |
| 60 | 60 | pub fn dwarfLocOp(reg: Register) u8 { |
| 61 | 61 | return switch (reg.to32()) { |
| 62 | .eax => DW.OP_reg0, | |
| 63 | .ecx => DW.OP_reg1, | |
| 64 | .edx => DW.OP_reg2, | |
| 65 | .ebx => DW.OP_reg3, | |
| 66 | .esp => DW.OP_reg4, | |
| 67 | .ebp => DW.OP_reg5, | |
| 68 | .esi => DW.OP_reg6, | |
| 69 | .edi => DW.OP_reg7, | |
| 62 | .eax => DW.OP.reg0, | |
| 63 | .ecx => DW.OP.reg1, | |
| 64 | .edx => DW.OP.reg2, | |
| 65 | .ebx => DW.OP.reg3, | |
| 66 | .esp => DW.OP.reg4, | |
| 67 | .ebp => DW.OP.reg5, | |
| 68 | .esi => DW.OP.reg6, | |
| 69 | .edi => DW.OP.reg7, | |
| 70 | 70 | else => unreachable, |
| 71 | 71 | }; |
| 72 | 72 | } |
src/codegen/x86_64.zig+17-17| ... | ... | @@ -115,23 +115,23 @@ pub const Register = enum(u8) { |
| 115 | 115 | |
| 116 | 116 | pub fn dwarfLocOp(self: Register) u8 { |
| 117 | 117 | return switch (self.to64()) { |
| 118 | .rax => DW.OP_reg0, | |
| 119 | .rdx => DW.OP_reg1, | |
| 120 | .rcx => DW.OP_reg2, | |
| 121 | .rbx => DW.OP_reg3, | |
| 122 | .rsi => DW.OP_reg4, | |
| 123 | .rdi => DW.OP_reg5, | |
| 124 | .rbp => DW.OP_reg6, | |
| 125 | .rsp => DW.OP_reg7, | |
| 126 | ||
| 127 | .r8 => DW.OP_reg8, | |
| 128 | .r9 => DW.OP_reg9, | |
| 129 | .r10 => DW.OP_reg10, | |
| 130 | .r11 => DW.OP_reg11, | |
| 131 | .r12 => DW.OP_reg12, | |
| 132 | .r13 => DW.OP_reg13, | |
| 133 | .r14 => DW.OP_reg14, | |
| 134 | .r15 => DW.OP_reg15, | |
| 118 | .rax => DW.OP.reg0, | |
| 119 | .rdx => DW.OP.reg1, | |
| 120 | .rcx => DW.OP.reg2, | |
| 121 | .rbx => DW.OP.reg3, | |
| 122 | .rsi => DW.OP.reg4, | |
| 123 | .rdi => DW.OP.reg5, | |
| 124 | .rbp => DW.OP.reg6, | |
| 125 | .rsp => DW.OP.reg7, | |
| 126 | ||
| 127 | .r8 => DW.OP.reg8, | |
| 128 | .r9 => DW.OP.reg9, | |
| 129 | .r10 => DW.OP.reg10, | |
| 130 | .r11 => DW.OP.reg11, | |
| 131 | .r12 => DW.OP.reg12, | |
| 132 | .r13 => DW.OP.reg13, | |
| 133 | .r14 => DW.OP.reg14, | |
| 134 | .r15 => DW.OP.reg15, | |
| 135 | 135 | |
| 136 | 136 | else => unreachable, |
| 137 | 137 | }; |
src/link.zig+1-1| ... | ... | @@ -179,7 +179,7 @@ pub const File = struct { |
| 179 | 179 | /// This is where the .debug_info tag for the type is. |
| 180 | 180 | off: u32, |
| 181 | 181 | /// Offset from `TextBlock.dbg_info_off` (the buffer that is local to a Decl). |
| 182 | /// List of DW.AT_type / DW.FORM_ref4 that points to the type. | |
| 182 | /// List of DW.AT.type / DW.FORM.ref4 that points to the type. | |
| 183 | 183 | relocs: std.ArrayListUnmanaged(u32), |
| 184 | 184 | }; |
| 185 | 185 |
src/link/Elf.zig+76-76| ... | ... | @@ -772,48 +772,48 @@ pub fn flushModule(self: *Elf, comp: *Compilation) !void { |
| 772 | 772 | // These are LEB encoded but since the values are all less than 127 |
| 773 | 773 | // we can simply append these bytes. |
| 774 | 774 | const abbrev_buf = [_]u8{ |
| 775 | abbrev_compile_unit, DW.TAG_compile_unit, DW.CHILDREN_yes, // header | |
| 776 | DW.AT_stmt_list, DW.FORM_sec_offset, DW.AT_low_pc, | |
| 777 | DW.FORM_addr, DW.AT_high_pc, DW.FORM_addr, | |
| 778 | DW.AT_name, DW.FORM_strp, DW.AT_comp_dir, | |
| 779 | DW.FORM_strp, DW.AT_producer, DW.FORM_strp, | |
| 780 | DW.AT_language, DW.FORM_data2, 0, | |
| 775 | abbrev_compile_unit, DW.TAG.compile_unit, DW.CHILDREN.yes, // header | |
| 776 | DW.AT.stmt_list, DW.FORM.sec_offset, DW.AT.low_pc, | |
| 777 | DW.FORM.addr, DW.AT.high_pc, DW.FORM.addr, | |
| 778 | DW.AT.name, DW.FORM.strp, DW.AT.comp_dir, | |
| 779 | DW.FORM.strp, DW.AT.producer, DW.FORM.strp, | |
| 780 | DW.AT.language, DW.FORM.data2, 0, | |
| 781 | 781 | 0, // table sentinel |
| 782 | 782 | abbrev_subprogram, |
| 783 | DW.TAG_subprogram, | |
| 784 | DW.CHILDREN_yes, // header | |
| 785 | DW.AT_low_pc, | |
| 786 | DW.FORM_addr, | |
| 787 | DW.AT_high_pc, | |
| 788 | DW.FORM_data4, | |
| 789 | DW.AT_type, | |
| 790 | DW.FORM_ref4, | |
| 791 | DW.AT_name, | |
| 792 | DW.FORM_string, | |
| 783 | DW.TAG.subprogram, | |
| 784 | DW.CHILDREN.yes, // header | |
| 785 | DW.AT.low_pc, | |
| 786 | DW.FORM.addr, | |
| 787 | DW.AT.high_pc, | |
| 788 | DW.FORM.data4, | |
| 789 | DW.AT.type, | |
| 790 | DW.FORM.ref4, | |
| 791 | DW.AT.name, | |
| 792 | DW.FORM.string, | |
| 793 | 793 | 0, 0, // table sentinel |
| 794 | 794 | abbrev_subprogram_retvoid, |
| 795 | DW.TAG_subprogram, DW.CHILDREN_yes, // header | |
| 796 | DW.AT_low_pc, DW.FORM_addr, | |
| 797 | DW.AT_high_pc, DW.FORM_data4, | |
| 798 | DW.AT_name, DW.FORM_string, | |
| 795 | DW.TAG.subprogram, DW.CHILDREN.yes, // header | |
| 796 | DW.AT.low_pc, DW.FORM.addr, | |
| 797 | DW.AT.high_pc, DW.FORM.data4, | |
| 798 | DW.AT.name, DW.FORM.string, | |
| 799 | 799 | 0, |
| 800 | 800 | 0, // table sentinel |
| 801 | 801 | abbrev_base_type, |
| 802 | DW.TAG_base_type, | |
| 803 | DW.CHILDREN_no, // header | |
| 804 | DW.AT_encoding, | |
| 805 | DW.FORM_data1, | |
| 806 | DW.AT_byte_size, | |
| 807 | DW.FORM_data1, | |
| 808 | DW.AT_name, | |
| 809 | DW.FORM_string, 0, 0, // table sentinel | |
| 810 | abbrev_pad1, DW.TAG_unspecified_type, DW.CHILDREN_no, // header | |
| 802 | DW.TAG.base_type, | |
| 803 | DW.CHILDREN.no, // header | |
| 804 | DW.AT.encoding, | |
| 805 | DW.FORM.data1, | |
| 806 | DW.AT.byte_size, | |
| 807 | DW.FORM.data1, | |
| 808 | DW.AT.name, | |
| 809 | DW.FORM.string, 0, 0, // table sentinel | |
| 810 | abbrev_pad1, DW.TAG.unspecified_type, DW.CHILDREN.no, // header | |
| 811 | 811 | 0, 0, // table sentinel |
| 812 | 812 | abbrev_parameter, |
| 813 | DW.TAG_formal_parameter, DW.CHILDREN_no, // header | |
| 814 | DW.AT_location, DW.FORM_exprloc, | |
| 815 | DW.AT_type, DW.FORM_ref4, | |
| 816 | DW.AT_name, DW.FORM_string, | |
| 813 | DW.TAG.formal_parameter, DW.CHILDREN.no, // header | |
| 814 | DW.AT.location, DW.FORM.exprloc, | |
| 815 | DW.AT.type, DW.FORM.ref4, | |
| 816 | DW.AT.name, DW.FORM.string, | |
| 817 | 817 | 0, |
| 818 | 818 | 0, // table sentinel |
| 819 | 819 | 0, |
| ... | ... | @@ -897,7 +897,7 @@ pub fn flushModule(self: *Elf, comp: *Compilation) !void { |
| 897 | 897 | const high_pc = text_phdr.p_vaddr + text_phdr.p_memsz; |
| 898 | 898 | |
| 899 | 899 | di_buf.appendAssumeCapacity(abbrev_compile_unit); |
| 900 | self.writeDwarfAddrAssumeCapacity(&di_buf, 0); // DW.AT_stmt_list, DW.FORM_sec_offset | |
| 900 | self.writeDwarfAddrAssumeCapacity(&di_buf, 0); // DW.AT.stmt_list, DW.FORM.sec_offset | |
| 901 | 901 | self.writeDwarfAddrAssumeCapacity(&di_buf, low_pc); |
| 902 | 902 | self.writeDwarfAddrAssumeCapacity(&di_buf, high_pc); |
| 903 | 903 | self.writeDwarfAddrAssumeCapacity(&di_buf, name_strp); |
| ... | ... | @@ -906,7 +906,7 @@ pub fn flushModule(self: *Elf, comp: *Compilation) !void { |
| 906 | 906 | // We are still waiting on dwarf-std.org to assign DW_LANG_Zig a number: |
| 907 | 907 | // http://dwarfstd.org/ShowIssue.php?issue=171115.1 |
| 908 | 908 | // Until then we say it is C99. |
| 909 | mem.writeInt(u16, di_buf.addManyAsArrayAssumeCapacity(2), DW.LANG_C99, target_endian); | |
| 909 | mem.writeInt(u16, di_buf.addManyAsArrayAssumeCapacity(2), DW.LANG.C99, target_endian); | |
| 910 | 910 | |
| 911 | 911 | if (di_buf.items.len > first_dbg_info_decl.dbg_info_off) { |
| 912 | 912 | // Move the first N decls to the end to make more padding for the header. |
| ... | ... | @@ -1030,7 +1030,7 @@ pub fn flushModule(self: *Elf, comp: *Compilation) !void { |
| 1030 | 1030 | di_buf.items.len += ptr_width_bytes; // We will come back and write this. |
| 1031 | 1031 | const after_header_len = di_buf.items.len; |
| 1032 | 1032 | |
| 1033 | const opcode_base = DW.LNS_set_isa + 1; | |
| 1033 | const opcode_base = DW.LNS.set_isa + 1; | |
| 1034 | 1034 | di_buf.appendSliceAssumeCapacity(&[_]u8{ |
| 1035 | 1035 | 1, // minimum_instruction_length |
| 1036 | 1036 | 1, // maximum_operations_per_instruction |
| ... | ... | @@ -1041,18 +1041,18 @@ pub fn flushModule(self: *Elf, comp: *Compilation) !void { |
| 1041 | 1041 | |
| 1042 | 1042 | // Standard opcode lengths. The number of items here is based on `opcode_base`. |
| 1043 | 1043 | // The value is the number of LEB128 operands the instruction takes. |
| 1044 | 0, // `DW.LNS_copy` | |
| 1045 | 1, // `DW.LNS_advance_pc` | |
| 1046 | 1, // `DW.LNS_advance_line` | |
| 1047 | 1, // `DW.LNS_set_file` | |
| 1048 | 1, // `DW.LNS_set_column` | |
| 1049 | 0, // `DW.LNS_negate_stmt` | |
| 1050 | 0, // `DW.LNS_set_basic_block` | |
| 1051 | 0, // `DW.LNS_const_add_pc` | |
| 1052 | 1, // `DW.LNS_fixed_advance_pc` | |
| 1053 | 0, // `DW.LNS_set_prologue_end` | |
| 1054 | 0, // `DW.LNS_set_epilogue_begin` | |
| 1055 | 1, // `DW.LNS_set_isa` | |
| 1044 | 0, // `DW.LNS.copy` | |
| 1045 | 1, // `DW.LNS.advance_pc` | |
| 1046 | 1, // `DW.LNS.advance_line` | |
| 1047 | 1, // `DW.LNS.set_file` | |
| 1048 | 1, // `DW.LNS.set_column` | |
| 1049 | 0, // `DW.LNS.negate_stmt` | |
| 1050 | 0, // `DW.LNS.set_basic_block` | |
| 1051 | 0, // `DW.LNS.const_add_pc` | |
| 1052 | 1, // `DW.LNS.fixed_advance_pc` | |
| 1053 | 0, // `DW.LNS.set_prologue_end` | |
| 1054 | 0, // `DW.LNS.set_epilogue_begin` | |
| 1055 | 1, // `DW.LNS.set_isa` | |
| 1056 | 1056 | 0, // include_directories (none except the compilation unit cwd) |
| 1057 | 1057 | }); |
| 1058 | 1058 | // file_names[0] |
| ... | ... | @@ -2053,7 +2053,7 @@ fn allocateTextBlock(self: *Elf, text_block: *TextBlock, new_block_size: u64, al |
| 2053 | 2053 | |
| 2054 | 2054 | // The .debug_info section has `low_pc` and `high_pc` values which is the virtual address |
| 2055 | 2055 | // range of the compilation unit. When we expand the text section, this range changes, |
| 2056 | // so the DW_TAG_compile_unit tag of the .debug_info section becomes dirty. | |
| 2056 | // so the DW_TAG.compile_unit tag of the .debug_info section becomes dirty. | |
| 2057 | 2057 | self.debug_info_header_dirty = true; |
| 2058 | 2058 | // This becomes dirty for the same reason. We could potentially make this more |
| 2059 | 2059 | // fine-grained with the addition of support for more compilation units. It is planned to |
| ... | ... | @@ -2303,22 +2303,22 @@ pub fn updateFunc(self: *Elf, module: *Module, func: *Module.Fn, air: Air, liven |
| 2303 | 2303 | |
| 2304 | 2304 | const ptr_width_bytes = self.ptrWidthBytes(); |
| 2305 | 2305 | dbg_line_buffer.appendSliceAssumeCapacity(&[_]u8{ |
| 2306 | DW.LNS_extended_op, | |
| 2306 | DW.LNS.extended_op, | |
| 2307 | 2307 | ptr_width_bytes + 1, |
| 2308 | DW.LNE_set_address, | |
| 2308 | DW.LNE.set_address, | |
| 2309 | 2309 | }); |
| 2310 | 2310 | // This is the "relocatable" vaddr, corresponding to `code_buffer` index `0`. |
| 2311 | 2311 | assert(dbg_line_vaddr_reloc_index == dbg_line_buffer.items.len); |
| 2312 | 2312 | dbg_line_buffer.items.len += ptr_width_bytes; |
| 2313 | 2313 | |
| 2314 | dbg_line_buffer.appendAssumeCapacity(DW.LNS_advance_line); | |
| 2314 | dbg_line_buffer.appendAssumeCapacity(DW.LNS.advance_line); | |
| 2315 | 2315 | // This is the "relocatable" relative line offset from the previous function's end curly |
| 2316 | 2316 | // to this function's begin curly. |
| 2317 | 2317 | assert(self.getRelocDbgLineOff() == dbg_line_buffer.items.len); |
| 2318 | 2318 | // Here we use a ULEB128-fixed-4 to make sure this field can be overwritten later. |
| 2319 | 2319 | leb128.writeUnsignedFixed(4, dbg_line_buffer.addManyAsArrayAssumeCapacity(4), line_off); |
| 2320 | 2320 | |
| 2321 | dbg_line_buffer.appendAssumeCapacity(DW.LNS_set_file); | |
| 2321 | dbg_line_buffer.appendAssumeCapacity(DW.LNS.set_file); | |
| 2322 | 2322 | assert(self.getRelocDbgFileIndex() == dbg_line_buffer.items.len); |
| 2323 | 2323 | // Once we support more than one source file, this will have the ability to be more |
| 2324 | 2324 | // than one possible value. |
| ... | ... | @@ -2327,7 +2327,7 @@ pub fn updateFunc(self: *Elf, module: *Module, func: *Module.Fn, air: Air, liven |
| 2327 | 2327 | |
| 2328 | 2328 | // Emit a line for the begin curly with prologue_end=false. The codegen will |
| 2329 | 2329 | // do the work of setting prologue_end=true and epilogue_begin=true. |
| 2330 | dbg_line_buffer.appendAssumeCapacity(DW.LNS_copy); | |
| 2330 | dbg_line_buffer.appendAssumeCapacity(DW.LNS.copy); | |
| 2331 | 2331 | |
| 2332 | 2332 | // .debug_info subprogram |
| 2333 | 2333 | const decl_name_with_null = decl.name[0 .. mem.lenZ(decl.name) + 1]; |
| ... | ... | @@ -2344,9 +2344,9 @@ pub fn updateFunc(self: *Elf, module: *Module, func: *Module.Fn, air: Air, liven |
| 2344 | 2344 | // "relocations" and have to be in this fixed place so that functions can be |
| 2345 | 2345 | // moved in virtual address space. |
| 2346 | 2346 | assert(dbg_info_low_pc_reloc_index == dbg_info_buffer.items.len); |
| 2347 | dbg_info_buffer.items.len += ptr_width_bytes; // DW.AT_low_pc, DW.FORM_addr | |
| 2347 | dbg_info_buffer.items.len += ptr_width_bytes; // DW.AT.low_pc, DW.FORM.addr | |
| 2348 | 2348 | assert(self.getRelocDbgInfoSubprogramHighPC() == dbg_info_buffer.items.len); |
| 2349 | dbg_info_buffer.items.len += 4; // DW.AT_high_pc, DW.FORM_data4 | |
| 2349 | dbg_info_buffer.items.len += 4; // DW.AT.high_pc, DW.FORM.data4 | |
| 2350 | 2350 | if (fn_ret_has_bits) { |
| 2351 | 2351 | const gop = try dbg_info_type_relocs.getOrPut(self.base.allocator, fn_ret_type); |
| 2352 | 2352 | if (!gop.found_existing) { |
| ... | ... | @@ -2356,9 +2356,9 @@ pub fn updateFunc(self: *Elf, module: *Module, func: *Module.Fn, air: Air, liven |
| 2356 | 2356 | }; |
| 2357 | 2357 | } |
| 2358 | 2358 | try gop.value_ptr.relocs.append(self.base.allocator, @intCast(u32, dbg_info_buffer.items.len)); |
| 2359 | dbg_info_buffer.items.len += 4; // DW.AT_type, DW.FORM_ref4 | |
| 2359 | dbg_info_buffer.items.len += 4; // DW.AT.type, DW.FORM.ref4 | |
| 2360 | 2360 | } |
| 2361 | dbg_info_buffer.appendSliceAssumeCapacity(decl_name_with_null); // DW.AT_name, DW.FORM_string | |
| 2361 | dbg_info_buffer.appendSliceAssumeCapacity(decl_name_with_null); // DW.AT.name, DW.FORM.string | |
| 2362 | 2362 | |
| 2363 | 2363 | const res = try codegen.generateFunction(&self.base, decl.srcLoc(), func, air, liveness, &code_buffer, .{ |
| 2364 | 2364 | .dwarf = .{ |
| ... | ... | @@ -2409,7 +2409,7 @@ pub fn updateFunc(self: *Elf, module: *Module, func: *Module.Fn, air: Air, liven |
| 2409 | 2409 | mem.writeInt(u32, ptr, @intCast(u32, local_sym.st_size), target_endian); |
| 2410 | 2410 | } |
| 2411 | 2411 | |
| 2412 | try dbg_line_buffer.appendSlice(&[_]u8{ DW.LNS_extended_op, 1, DW.LNE_end_sequence }); | |
| 2412 | try dbg_line_buffer.appendSlice(&[_]u8{ DW.LNS.extended_op, 1, DW.LNE.end_sequence }); | |
| 2413 | 2413 | |
| 2414 | 2414 | // Now we have the full contents and may allocate a region to store it. |
| 2415 | 2415 | |
| ... | ... | @@ -2493,7 +2493,7 @@ pub fn updateFunc(self: *Elf, module: *Module, func: *Module.Fn, air: Air, liven |
| 2493 | 2493 | const file_pos = debug_line_sect.sh_offset + src_fn.off; |
| 2494 | 2494 | try self.pwriteDbgLineNops(prev_padding_size, dbg_line_buffer.items, next_padding_size, file_pos); |
| 2495 | 2495 | |
| 2496 | // .debug_info - End the TAG_subprogram children. | |
| 2496 | // .debug_info - End the TAG.subprogram children. | |
| 2497 | 2497 | try dbg_info_buffer.append(0); |
| 2498 | 2498 | |
| 2499 | 2499 | return self.finishUpdateDecl(module, decl, &dbg_info_type_relocs, &dbg_info_buffer); |
| ... | ... | @@ -2566,34 +2566,34 @@ fn addDbgInfoType(self: *Elf, ty: Type, dbg_info_buffer: *std.ArrayList(u8)) !vo |
| 2566 | 2566 | .Bool => { |
| 2567 | 2567 | try dbg_info_buffer.appendSlice(&[_]u8{ |
| 2568 | 2568 | abbrev_base_type, |
| 2569 | DW.ATE_boolean, // DW.AT_encoding , DW.FORM_data1 | |
| 2570 | 1, // DW.AT_byte_size, DW.FORM_data1 | |
| 2571 | 'b', 'o', 'o', 'l', 0, // DW.AT_name, DW.FORM_string | |
| 2569 | DW.ATE.boolean, // DW.AT.encoding , DW.FORM.data1 | |
| 2570 | 1, // DW.AT.byte_size, DW.FORM.data1 | |
| 2571 | 'b', 'o', 'o', 'l', 0, // DW.AT.name, DW.FORM.string | |
| 2572 | 2572 | }); |
| 2573 | 2573 | }, |
| 2574 | 2574 | .Int => { |
| 2575 | 2575 | const info = ty.intInfo(self.base.options.target); |
| 2576 | 2576 | try dbg_info_buffer.ensureCapacity(dbg_info_buffer.items.len + 12); |
| 2577 | 2577 | dbg_info_buffer.appendAssumeCapacity(abbrev_base_type); |
| 2578 | // DW.AT_encoding, DW.FORM_data1 | |
| 2578 | // DW.AT.encoding, DW.FORM.data1 | |
| 2579 | 2579 | dbg_info_buffer.appendAssumeCapacity(switch (info.signedness) { |
| 2580 | .signed => DW.ATE_signed, | |
| 2581 | .unsigned => DW.ATE_unsigned, | |
| 2580 | .signed => DW.ATE.signed, | |
| 2581 | .unsigned => DW.ATE.unsigned, | |
| 2582 | 2582 | }); |
| 2583 | // DW.AT_byte_size, DW.FORM_data1 | |
| 2583 | // DW.AT.byte_size, DW.FORM.data1 | |
| 2584 | 2584 | dbg_info_buffer.appendAssumeCapacity(@intCast(u8, ty.abiSize(self.base.options.target))); |
| 2585 | // DW.AT_name, DW.FORM_string | |
| 2585 | // DW.AT.name, DW.FORM.string | |
| 2586 | 2586 | try dbg_info_buffer.writer().print("{}\x00", .{ty}); |
| 2587 | 2587 | }, |
| 2588 | 2588 | .Optional => { |
| 2589 | 2589 | if (ty.isPtrLikeOptional()) { |
| 2590 | 2590 | try dbg_info_buffer.ensureCapacity(dbg_info_buffer.items.len + 12); |
| 2591 | 2591 | dbg_info_buffer.appendAssumeCapacity(abbrev_base_type); |
| 2592 | // DW.AT_encoding, DW.FORM_data1 | |
| 2593 | dbg_info_buffer.appendAssumeCapacity(DW.ATE_address); | |
| 2594 | // DW.AT_byte_size, DW.FORM_data1 | |
| 2592 | // DW.AT.encoding, DW.FORM.data1 | |
| 2593 | dbg_info_buffer.appendAssumeCapacity(DW.ATE.address); | |
| 2594 | // DW.AT.byte_size, DW.FORM.data1 | |
| 2595 | 2595 | dbg_info_buffer.appendAssumeCapacity(@intCast(u8, ty.abiSize(self.base.options.target))); |
| 2596 | // DW.AT_name, DW.FORM_string | |
| 2596 | // DW.AT.name, DW.FORM.string | |
| 2597 | 2597 | try dbg_info_buffer.writer().print("{}\x00", .{ty}); |
| 2598 | 2598 | } else { |
| 2599 | 2599 | log.err("TODO implement .debug_info for type '{}'", .{ty}); |
| ... | ... | @@ -3034,7 +3034,7 @@ fn archPtrWidthBytes(self: Elf) u8 { |
| 3034 | 3034 | /// The reloc offset for the virtual address of a function in its Line Number Program. |
| 3035 | 3035 | /// Size is a virtual address integer. |
| 3036 | 3036 | const dbg_line_vaddr_reloc_index = 3; |
| 3037 | /// The reloc offset for the virtual address of a function in its .debug_info TAG_subprogram. | |
| 3037 | /// The reloc offset for the virtual address of a function in its .debug_info TAG.subprogram. | |
| 3038 | 3038 | /// Size is a virtual address integer. |
| 3039 | 3039 | const dbg_info_low_pc_reloc_index = 1; |
| 3040 | 3040 | |
| ... | ... | @@ -3060,7 +3060,7 @@ fn dbgLineNeededHeaderBytes(self: Elf) u32 { |
| 3060 | 3060 | const root_src_dir_path_len = if (self.base.options.module.?.root_pkg.root_src_directory.path) |p| p.len else 1; // "." |
| 3061 | 3061 | return @intCast(u32, 53 + directory_entry_format_count * 2 + file_name_entry_format_count * 2 + |
| 3062 | 3062 | directory_count * 8 + file_name_count * 8 + |
| 3063 | // These are encoded as DW.FORM_string rather than DW.FORM_strp as we would like | |
| 3063 | // These are encoded as DW.FORM.string rather than DW.FORM.strp as we would like | |
| 3064 | 3064 | // because of a workaround for readelf and gdb failing to understand DWARFv5 correctly. |
| 3065 | 3065 | root_src_dir_path_len + |
| 3066 | 3066 | self.base.options.module.?.root_pkg.root_src_path.len); |
| ... | ... | @@ -3088,8 +3088,8 @@ fn pwriteDbgLineNops( |
| 3088 | 3088 | const tracy = trace(@src()); |
| 3089 | 3089 | defer tracy.end(); |
| 3090 | 3090 | |
| 3091 | const page_of_nops = [1]u8{DW.LNS_negate_stmt} ** 4096; | |
| 3092 | const three_byte_nop = [3]u8{ DW.LNS_advance_pc, 0b1000_0000, 0 }; | |
| 3091 | const page_of_nops = [1]u8{DW.LNS.negate_stmt} ** 4096; | |
| 3092 | const three_byte_nop = [3]u8{ DW.LNS.advance_pc, 0b1000_0000, 0 }; | |
| 3093 | 3093 | var vecs: [512]std.os.iovec_const = undefined; |
| 3094 | 3094 | var vec_index: usize = 0; |
| 3095 | 3095 | { |
src/link/MachO/DebugSymbols.zig+70-70| ... | ... | @@ -93,7 +93,7 @@ const abbrev_parameter = 6; |
| 93 | 93 | /// The reloc offset for the virtual address of a function in its Line Number Program. |
| 94 | 94 | /// Size is a virtual address integer. |
| 95 | 95 | const dbg_line_vaddr_reloc_index = 3; |
| 96 | /// The reloc offset for the virtual address of a function in its .debug_info TAG_subprogram. | |
| 96 | /// The reloc offset for the virtual address of a function in its .debug_info TAG.subprogram. | |
| 97 | 97 | /// Size is a virtual address integer. |
| 98 | 98 | const dbg_info_low_pc_reloc_index = 1; |
| 99 | 99 | |
| ... | ... | @@ -299,40 +299,40 @@ pub fn flushModule(self: *DebugSymbols, allocator: *Allocator, options: link.Opt |
| 299 | 299 | // These are LEB encoded but since the values are all less than 127 |
| 300 | 300 | // we can simply append these bytes. |
| 301 | 301 | const abbrev_buf = [_]u8{ |
| 302 | abbrev_compile_unit, DW.TAG_compile_unit, DW.CHILDREN_yes, // header | |
| 303 | DW.AT_stmt_list, DW.FORM_sec_offset, // offset | |
| 304 | DW.AT_low_pc, DW.FORM_addr, | |
| 305 | DW.AT_high_pc, DW.FORM_addr, | |
| 306 | DW.AT_name, DW.FORM_strp, | |
| 307 | DW.AT_comp_dir, DW.FORM_strp, | |
| 308 | DW.AT_producer, DW.FORM_strp, | |
| 309 | DW.AT_language, DW.FORM_data2, | |
| 302 | abbrev_compile_unit, DW.TAG.compile_unit, DW.CHILDREN.yes, // header | |
| 303 | DW.AT.stmt_list, DW.FORM.sec_offset, // offset | |
| 304 | DW.AT.low_pc, DW.FORM.addr, | |
| 305 | DW.AT.high_pc, DW.FORM.addr, | |
| 306 | DW.AT.name, DW.FORM.strp, | |
| 307 | DW.AT.comp_dir, DW.FORM.strp, | |
| 308 | DW.AT.producer, DW.FORM.strp, | |
| 309 | DW.AT.language, DW.FORM.data2, | |
| 310 | 310 | 0, 0, // table sentinel |
| 311 | abbrev_subprogram, DW.TAG_subprogram, DW.CHILDREN_yes, // header | |
| 312 | DW.AT_low_pc, DW.FORM_addr, // start VM address | |
| 313 | DW.AT_high_pc, DW.FORM_data4, | |
| 314 | DW.AT_type, DW.FORM_ref4, | |
| 315 | DW.AT_name, DW.FORM_string, | |
| 316 | DW.AT_decl_line, DW.FORM_data4, | |
| 317 | DW.AT_decl_file, DW.FORM_data1, | |
| 311 | abbrev_subprogram, DW.TAG.subprogram, DW.CHILDREN.yes, // header | |
| 312 | DW.AT.low_pc, DW.FORM.addr, // start VM address | |
| 313 | DW.AT.high_pc, DW.FORM.data4, | |
| 314 | DW.AT.type, DW.FORM.ref4, | |
| 315 | DW.AT.name, DW.FORM.string, | |
| 316 | DW.AT.decl_line, DW.FORM.data4, | |
| 317 | DW.AT.decl_file, DW.FORM.data1, | |
| 318 | 318 | 0, 0, // table sentinel |
| 319 | 319 | abbrev_subprogram_retvoid, |
| 320 | DW.TAG_subprogram, DW.CHILDREN_yes, // header | |
| 321 | DW.AT_low_pc, DW.FORM_addr, | |
| 322 | DW.AT_high_pc, DW.FORM_data4, | |
| 323 | DW.AT_name, DW.FORM_string, | |
| 324 | DW.AT_decl_line, DW.FORM_data4, | |
| 325 | DW.AT_decl_file, DW.FORM_data1, | |
| 320 | DW.TAG.subprogram, DW.CHILDREN.yes, // header | |
| 321 | DW.AT.low_pc, DW.FORM.addr, | |
| 322 | DW.AT.high_pc, DW.FORM.data4, | |
| 323 | DW.AT.name, DW.FORM.string, | |
| 324 | DW.AT.decl_line, DW.FORM.data4, | |
| 325 | DW.AT.decl_file, DW.FORM.data1, | |
| 326 | 326 | 0, 0, // table sentinel |
| 327 | abbrev_base_type, DW.TAG_base_type, DW.CHILDREN_no, // header | |
| 328 | DW.AT_encoding, DW.FORM_data1, DW.AT_byte_size, | |
| 329 | DW.FORM_data1, DW.AT_name, DW.FORM_string, | |
| 327 | abbrev_base_type, DW.TAG.base_type, DW.CHILDREN.no, // header | |
| 328 | DW.AT.encoding, DW.FORM.data1, DW.AT.byte_size, | |
| 329 | DW.FORM.data1, DW.AT.name, DW.FORM.string, | |
| 330 | 330 | 0, 0, // table sentinel |
| 331 | abbrev_pad1, DW.TAG_unspecified_type, DW.CHILDREN_no, // header | |
| 331 | abbrev_pad1, DW.TAG.unspecified_type, DW.CHILDREN.no, // header | |
| 332 | 332 | 0, 0, // table sentinel |
| 333 | abbrev_parameter, DW.TAG_formal_parameter, DW.CHILDREN_no, // header | |
| 334 | DW.AT_location, DW.FORM_exprloc, DW.AT_type, | |
| 335 | DW.FORM_ref4, DW.AT_name, DW.FORM_string, | |
| 333 | abbrev_parameter, DW.TAG.formal_parameter, DW.CHILDREN.no, // header | |
| 334 | DW.AT.location, DW.FORM.exprloc, DW.AT.type, | |
| 335 | DW.FORM.ref4, DW.AT.name, DW.FORM.string, | |
| 336 | 336 | 0, 0, // table sentinel |
| 337 | 337 | 0, 0, 0, // section sentinel |
| 338 | 338 | }; |
| ... | ... | @@ -397,7 +397,7 @@ pub fn flushModule(self: *DebugSymbols, allocator: *Allocator, options: link.Opt |
| 397 | 397 | const high_pc = text_section.addr + text_section.size; |
| 398 | 398 | |
| 399 | 399 | di_buf.appendAssumeCapacity(abbrev_compile_unit); |
| 400 | mem.writeIntLittle(u32, di_buf.addManyAsArrayAssumeCapacity(4), 0); // DW.AT_stmt_list, DW.FORM_sec_offset | |
| 400 | mem.writeIntLittle(u32, di_buf.addManyAsArrayAssumeCapacity(4), 0); // DW.AT.stmt_list, DW.FORM.sec_offset | |
| 401 | 401 | mem.writeIntLittle(u64, di_buf.addManyAsArrayAssumeCapacity(8), low_pc); |
| 402 | 402 | mem.writeIntLittle(u64, di_buf.addManyAsArrayAssumeCapacity(8), high_pc); |
| 403 | 403 | mem.writeIntLittle(u32, di_buf.addManyAsArrayAssumeCapacity(4), @intCast(u32, name_strp)); |
| ... | ... | @@ -406,7 +406,7 @@ pub fn flushModule(self: *DebugSymbols, allocator: *Allocator, options: link.Opt |
| 406 | 406 | // We are still waiting on dwarf-std.org to assign DW_LANG_Zig a number: |
| 407 | 407 | // http://dwarfstd.org/ShowIssue.php?issue=171115.1 |
| 408 | 408 | // Until then we say it is C99. |
| 409 | mem.writeIntLittle(u16, di_buf.addManyAsArrayAssumeCapacity(2), DW.LANG_C99); | |
| 409 | mem.writeIntLittle(u16, di_buf.addManyAsArrayAssumeCapacity(2), DW.LANG.C99); | |
| 410 | 410 | |
| 411 | 411 | if (di_buf.items.len > first_dbg_info_decl.dbg_info_off) { |
| 412 | 412 | // Move the first N decls to the end to make more padding for the header. |
| ... | ... | @@ -514,7 +514,7 @@ pub fn flushModule(self: *DebugSymbols, allocator: *Allocator, options: link.Opt |
| 514 | 514 | di_buf.items.len += @sizeOf(u32); // We will come back and write this. |
| 515 | 515 | const after_header_len = di_buf.items.len; |
| 516 | 516 | |
| 517 | const opcode_base = DW.LNS_set_isa + 1; | |
| 517 | const opcode_base = DW.LNS.set_isa + 1; | |
| 518 | 518 | di_buf.appendSliceAssumeCapacity(&[_]u8{ |
| 519 | 519 | 1, // minimum_instruction_length |
| 520 | 520 | 1, // maximum_operations_per_instruction |
| ... | ... | @@ -525,18 +525,18 @@ pub fn flushModule(self: *DebugSymbols, allocator: *Allocator, options: link.Opt |
| 525 | 525 | |
| 526 | 526 | // Standard opcode lengths. The number of items here is based on `opcode_base`. |
| 527 | 527 | // The value is the number of LEB128 operands the instruction takes. |
| 528 | 0, // `DW.LNS_copy` | |
| 529 | 1, // `DW.LNS_advance_pc` | |
| 530 | 1, // `DW.LNS_advance_line` | |
| 531 | 1, // `DW.LNS_set_file` | |
| 532 | 1, // `DW.LNS_set_column` | |
| 533 | 0, // `DW.LNS_negate_stmt` | |
| 534 | 0, // `DW.LNS_set_basic_block` | |
| 535 | 0, // `DW.LNS_const_add_pc` | |
| 536 | 1, // `DW.LNS_fixed_advance_pc` | |
| 537 | 0, // `DW.LNS_set_prologue_end` | |
| 538 | 0, // `DW.LNS_set_epilogue_begin` | |
| 539 | 1, // `DW.LNS_set_isa` | |
| 528 | 0, // `DW.LNS.copy` | |
| 529 | 1, // `DW.LNS.advance_pc` | |
| 530 | 1, // `DW.LNS.advance_line` | |
| 531 | 1, // `DW.LNS.set_file` | |
| 532 | 1, // `DW.LNS.set_column` | |
| 533 | 0, // `DW.LNS.negate_stmt` | |
| 534 | 0, // `DW.LNS.set_basic_block` | |
| 535 | 0, // `DW.LNS.const_add_pc` | |
| 536 | 1, // `DW.LNS.fixed_advance_pc` | |
| 537 | 0, // `DW.LNS.set_prologue_end` | |
| 538 | 0, // `DW.LNS.set_epilogue_begin` | |
| 539 | 1, // `DW.LNS.set_isa` | |
| 540 | 540 | 0, // include_directories (none except the compilation unit cwd) |
| 541 | 541 | }); |
| 542 | 542 | // file_names[0] |
| ... | ... | @@ -876,22 +876,22 @@ pub fn initDeclDebugBuffers( |
| 876 | 876 | const line_off = @intCast(u28, decl.src_line + func.lbrace_line); |
| 877 | 877 | |
| 878 | 878 | dbg_line_buffer.appendSliceAssumeCapacity(&[_]u8{ |
| 879 | DW.LNS_extended_op, | |
| 879 | DW.LNS.extended_op, | |
| 880 | 880 | @sizeOf(u64) + 1, |
| 881 | DW.LNE_set_address, | |
| 881 | DW.LNE.set_address, | |
| 882 | 882 | }); |
| 883 | 883 | // This is the "relocatable" vaddr, corresponding to `code_buffer` index `0`. |
| 884 | 884 | assert(dbg_line_vaddr_reloc_index == dbg_line_buffer.items.len); |
| 885 | 885 | dbg_line_buffer.items.len += @sizeOf(u64); |
| 886 | 886 | |
| 887 | dbg_line_buffer.appendAssumeCapacity(DW.LNS_advance_line); | |
| 887 | dbg_line_buffer.appendAssumeCapacity(DW.LNS.advance_line); | |
| 888 | 888 | // This is the "relocatable" relative line offset from the previous function's end curly |
| 889 | 889 | // to this function's begin curly. |
| 890 | 890 | assert(getRelocDbgLineOff() == dbg_line_buffer.items.len); |
| 891 | 891 | // Here we use a ULEB128-fixed-4 to make sure this field can be overwritten later. |
| 892 | 892 | leb.writeUnsignedFixed(4, dbg_line_buffer.addManyAsArrayAssumeCapacity(4), line_off); |
| 893 | 893 | |
| 894 | dbg_line_buffer.appendAssumeCapacity(DW.LNS_set_file); | |
| 894 | dbg_line_buffer.appendAssumeCapacity(DW.LNS.set_file); | |
| 895 | 895 | assert(getRelocDbgFileIndex() == dbg_line_buffer.items.len); |
| 896 | 896 | // Once we support more than one source file, this will have the ability to be more |
| 897 | 897 | // than one possible value. |
| ... | ... | @@ -900,7 +900,7 @@ pub fn initDeclDebugBuffers( |
| 900 | 900 | |
| 901 | 901 | // Emit a line for the begin curly with prologue_end=false. The codegen will |
| 902 | 902 | // do the work of setting prologue_end=true and epilogue_begin=true. |
| 903 | dbg_line_buffer.appendAssumeCapacity(DW.LNS_copy); | |
| 903 | dbg_line_buffer.appendAssumeCapacity(DW.LNS.copy); | |
| 904 | 904 | |
| 905 | 905 | // .debug_info subprogram |
| 906 | 906 | const decl_name_with_null = decl.name[0 .. mem.lenZ(decl.name) + 1]; |
| ... | ... | @@ -917,9 +917,9 @@ pub fn initDeclDebugBuffers( |
| 917 | 917 | // "relocations" and have to be in this fixed place so that functions can be |
| 918 | 918 | // moved in virtual address space. |
| 919 | 919 | assert(dbg_info_low_pc_reloc_index == dbg_info_buffer.items.len); |
| 920 | dbg_info_buffer.items.len += @sizeOf(u64); // DW.AT_low_pc, DW.FORM_addr | |
| 920 | dbg_info_buffer.items.len += @sizeOf(u64); // DW.AT.low_pc, DW.FORM.addr | |
| 921 | 921 | assert(getRelocDbgInfoSubprogramHighPC() == dbg_info_buffer.items.len); |
| 922 | dbg_info_buffer.items.len += 4; // DW.AT_high_pc, DW.FORM_data4 | |
| 922 | dbg_info_buffer.items.len += 4; // DW.AT.high_pc, DW.FORM.data4 | |
| 923 | 923 | if (fn_ret_has_bits) { |
| 924 | 924 | const gop = try dbg_info_type_relocs.getOrPut(allocator, fn_ret_type); |
| 925 | 925 | if (!gop.found_existing) { |
| ... | ... | @@ -929,11 +929,11 @@ pub fn initDeclDebugBuffers( |
| 929 | 929 | }; |
| 930 | 930 | } |
| 931 | 931 | try gop.value_ptr.relocs.append(allocator, @intCast(u32, dbg_info_buffer.items.len)); |
| 932 | dbg_info_buffer.items.len += 4; // DW.AT_type, DW.FORM_ref4 | |
| 932 | dbg_info_buffer.items.len += 4; // DW.AT.type, DW.FORM.ref4 | |
| 933 | 933 | } |
| 934 | dbg_info_buffer.appendSliceAssumeCapacity(decl_name_with_null); // DW.AT_name, DW.FORM_string | |
| 935 | mem.writeIntLittle(u32, dbg_info_buffer.addManyAsArrayAssumeCapacity(4), line_off + 1); // DW.AT_decl_line, DW.FORM_data4 | |
| 936 | dbg_info_buffer.appendAssumeCapacity(file_index); // DW.AT_decl_file, DW.FORM_data1 | |
| 934 | dbg_info_buffer.appendSliceAssumeCapacity(decl_name_with_null); // DW.AT.name, DW.FORM.string | |
| 935 | mem.writeIntLittle(u32, dbg_info_buffer.addManyAsArrayAssumeCapacity(4), line_off + 1); // DW.AT.decl_line, DW.FORM.data4 | |
| 936 | dbg_info_buffer.appendAssumeCapacity(file_index); // DW.AT.decl_file, DW.FORM.data1 | |
| 937 | 937 | }, |
| 938 | 938 | else => { |
| 939 | 939 | // TODO implement .debug_info for global variables |
| ... | ... | @@ -985,16 +985,16 @@ pub fn commitDeclDebugInfo( |
| 985 | 985 | { |
| 986 | 986 | // Advance line and PC. |
| 987 | 987 | // TODO encapsulate logic in a helper function. |
| 988 | try dbg_line_buffer.append(DW.LNS_advance_pc); | |
| 988 | try dbg_line_buffer.append(DW.LNS.advance_pc); | |
| 989 | 989 | try leb.writeULEB128(dbg_line_buffer.writer(), text_block.size); |
| 990 | 990 | |
| 991 | try dbg_line_buffer.append(DW.LNS_advance_line); | |
| 991 | try dbg_line_buffer.append(DW.LNS.advance_line); | |
| 992 | 992 | const func = decl.val.castTag(.function).?.data; |
| 993 | 993 | const line_off = @intCast(u28, func.rbrace_line - func.lbrace_line); |
| 994 | 994 | try leb.writeULEB128(dbg_line_buffer.writer(), line_off); |
| 995 | 995 | } |
| 996 | 996 | |
| 997 | try dbg_line_buffer.appendSlice(&[_]u8{ DW.LNS_extended_op, 1, DW.LNE_end_sequence }); | |
| 997 | try dbg_line_buffer.appendSlice(&[_]u8{ DW.LNS.extended_op, 1, DW.LNE.end_sequence }); | |
| 998 | 998 | |
| 999 | 999 | // Now we have the full contents and may allocate a region to store it. |
| 1000 | 1000 | |
| ... | ... | @@ -1075,7 +1075,7 @@ pub fn commitDeclDebugInfo( |
| 1075 | 1075 | const file_pos = debug_line_sect.offset + src_fn.off; |
| 1076 | 1076 | try self.pwriteDbgLineNops(prev_padding_size, dbg_line_buffer.items, next_padding_size, file_pos); |
| 1077 | 1077 | |
| 1078 | // .debug_info - End the TAG_subprogram children. | |
| 1078 | // .debug_info - End the TAG.subprogram children. | |
| 1079 | 1079 | try dbg_info_buffer.append(0); |
| 1080 | 1080 | }, |
| 1081 | 1081 | else => {}, |
| ... | ... | @@ -1128,27 +1128,27 @@ fn addDbgInfoType( |
| 1128 | 1128 | .Bool => { |
| 1129 | 1129 | try dbg_info_buffer.appendSlice(&[_]u8{ |
| 1130 | 1130 | abbrev_base_type, |
| 1131 | DW.ATE_boolean, // DW.AT_encoding , DW.FORM_data1 | |
| 1132 | 1, // DW.AT_byte_size, DW.FORM_data1 | |
| 1131 | DW.ATE.boolean, // DW.AT.encoding , DW.FORM.data1 | |
| 1132 | 1, // DW.AT.byte_size, DW.FORM.data1 | |
| 1133 | 1133 | 'b', |
| 1134 | 1134 | 'o', |
| 1135 | 1135 | 'o', |
| 1136 | 1136 | 'l', |
| 1137 | 0, // DW.AT_name, DW.FORM_string | |
| 1137 | 0, // DW.AT.name, DW.FORM.string | |
| 1138 | 1138 | }); |
| 1139 | 1139 | }, |
| 1140 | 1140 | .Int => { |
| 1141 | 1141 | const info = ty.intInfo(target); |
| 1142 | 1142 | try dbg_info_buffer.ensureCapacity(dbg_info_buffer.items.len + 12); |
| 1143 | 1143 | dbg_info_buffer.appendAssumeCapacity(abbrev_base_type); |
| 1144 | // DW.AT_encoding, DW.FORM_data1 | |
| 1144 | // DW.AT.encoding, DW.FORM.data1 | |
| 1145 | 1145 | dbg_info_buffer.appendAssumeCapacity(switch (info.signedness) { |
| 1146 | .signed => DW.ATE_signed, | |
| 1147 | .unsigned => DW.ATE_unsigned, | |
| 1146 | .signed => DW.ATE.signed, | |
| 1147 | .unsigned => DW.ATE.unsigned, | |
| 1148 | 1148 | }); |
| 1149 | // DW.AT_byte_size, DW.FORM_data1 | |
| 1149 | // DW.AT.byte_size, DW.FORM.data1 | |
| 1150 | 1150 | dbg_info_buffer.appendAssumeCapacity(@intCast(u8, ty.abiSize(target))); |
| 1151 | // DW.AT_name, DW.FORM_string | |
| 1151 | // DW.AT.name, DW.FORM.string | |
| 1152 | 1152 | try dbg_info_buffer.writer().print("{}\x00", .{ty}); |
| 1153 | 1153 | }, |
| 1154 | 1154 | else => { |
| ... | ... | @@ -1306,7 +1306,7 @@ fn dbgLineNeededHeaderBytes(self: DebugSymbols, module: *Module) u32 { |
| 1306 | 1306 | const root_src_dir_path_len = if (module.root_pkg.root_src_directory.path) |p| p.len else 1; // "." |
| 1307 | 1307 | return @intCast(u32, 53 + directory_entry_format_count * 2 + file_name_entry_format_count * 2 + |
| 1308 | 1308 | directory_count * 8 + file_name_count * 8 + |
| 1309 | // These are encoded as DW.FORM_string rather than DW.FORM_strp as we would like | |
| 1309 | // These are encoded as DW.FORM.string rather than DW.FORM.strp as we would like | |
| 1310 | 1310 | // because of a workaround for readelf and gdb failing to understand DWARFv5 correctly. |
| 1311 | 1311 | root_src_dir_path_len + |
| 1312 | 1312 | module.root_pkg.root_src_path.len); |
| ... | ... | @@ -1332,8 +1332,8 @@ fn pwriteDbgLineNops( |
| 1332 | 1332 | const tracy = trace(@src()); |
| 1333 | 1333 | defer tracy.end(); |
| 1334 | 1334 | |
| 1335 | const page_of_nops = [1]u8{DW.LNS_negate_stmt} ** 4096; | |
| 1336 | const three_byte_nop = [3]u8{ DW.LNS_advance_pc, 0b1000_0000, 0 }; | |
| 1335 | const page_of_nops = [1]u8{DW.LNS.negate_stmt} ** 4096; | |
| 1336 | const three_byte_nop = [3]u8{ DW.LNS.advance_pc, 0b1000_0000, 0 }; | |
| 1337 | 1337 | var vecs: [32]std.os.iovec_const = undefined; |
| 1338 | 1338 | var vec_index: usize = 0; |
| 1339 | 1339 | { |
src/link/MachO/Object.zig+2-2| ... | ... | @@ -836,8 +836,8 @@ pub fn parseDebugInfo(self: *Object, allocator: *Allocator) !void { |
| 836 | 836 | }, |
| 837 | 837 | else => |e| return e, |
| 838 | 838 | }; |
| 839 | const name = try compile_unit.die.getAttrString(&debug_info.inner, dwarf.AT_name); | |
| 840 | const comp_dir = try compile_unit.die.getAttrString(&debug_info.inner, dwarf.AT_comp_dir); | |
| 839 | const name = try compile_unit.die.getAttrString(&debug_info.inner, dwarf.AT.name); | |
| 840 | const comp_dir = try compile_unit.die.getAttrString(&debug_info.inner, dwarf.AT.comp_dir); | |
| 841 | 841 | |
| 842 | 842 | self.debug_info = debug_info; |
| 843 | 843 | self.tu_name = try allocator.dupe(u8, name); |
test/behavior.zig+2-1| ... | ... | @@ -10,6 +10,7 @@ test { |
| 10 | 10 | _ = @import("behavior/if.zig"); |
| 11 | 11 | _ = @import("behavior/cast.zig"); |
| 12 | 12 | _ = @import("behavior/array.zig"); |
| 13 | _ = @import("behavior/usingnamespace.zig"); | |
| 13 | 14 | |
| 14 | 15 | if (!builtin.zig_is_stage2) { |
| 15 | 16 | // Tests that only pass for stage1. |
| ... | ... | @@ -148,7 +149,7 @@ test { |
| 148 | 149 | _ = @import("behavior/undefined.zig"); |
| 149 | 150 | _ = @import("behavior/underscore.zig"); |
| 150 | 151 | _ = @import("behavior/union.zig"); |
| 151 | _ = @import("behavior/usingnamespace.zig"); | |
| 152 | _ = @import("behavior/usingnamespace_stage1.zig"); | |
| 152 | 153 | _ = @import("behavior/var_args.zig"); |
| 153 | 154 | _ = @import("behavior/vector.zig"); |
| 154 | 155 | _ = @import("behavior/void.zig"); |
test/behavior/eval.zig-6| ... | ... | @@ -125,12 +125,6 @@ test "pointer to type" { |
| 125 | 125 | } |
| 126 | 126 | } |
| 127 | 127 | |
| 128 | test "no undeclared identifier error in unanalyzed branches" { | |
| 129 | if (false) { | |
| 130 | lol_this_doesnt_exist = nonsense; | |
| 131 | } | |
| 132 | } | |
| 133 | ||
| 134 | 128 | test "a type constructed in a global expression" { |
| 135 | 129 | var l: List = undefined; |
| 136 | 130 | l.array[0] = 10; |
test/behavior/usingnamespace.zig+7-16| ... | ... | @@ -1,22 +1,13 @@ |
| 1 | 1 | const std = @import("std"); |
| 2 | 2 | |
| 3 | fn Foo(comptime T: type) type { | |
| 4 | return struct { | |
| 5 | usingnamespace T; | |
| 6 | }; | |
| 7 | } | |
| 8 | ||
| 9 | test "usingnamespace inside a generic struct" { | |
| 10 | const std2 = Foo(std); | |
| 11 | const testing2 = Foo(std.testing); | |
| 12 | try std2.testing.expect(true); | |
| 13 | try testing2.expect(true); | |
| 14 | } | |
| 3 | const A = struct { | |
| 4 | pub const B = bool; | |
| 5 | }; | |
| 15 | 6 | |
| 16 | usingnamespace struct { | |
| 17 | pub const foo = 42; | |
| 7 | const C = struct { | |
| 8 | usingnamespace A; | |
| 18 | 9 | }; |
| 19 | 10 | |
| 20 | test "usingnamespace does not redeclare an imported variable" { | |
| 21 | comptime try std.testing.expect(foo == 42); | |
| 11 | test "basic usingnamespace" { | |
| 12 | try std.testing.expect(C.B == bool); | |
| 22 | 13 | } |
test/behavior/usingnamespace_stage1.zig created+22| ... | ... | @@ -0,0 +1,22 @@ |
| 1 | const std = @import("std"); | |
| 2 | ||
| 3 | fn Foo(comptime T: type) type { | |
| 4 | return struct { | |
| 5 | usingnamespace T; | |
| 6 | }; | |
| 7 | } | |
| 8 | ||
| 9 | test "usingnamespace inside a generic struct" { | |
| 10 | const std2 = Foo(std); | |
| 11 | const testing2 = Foo(std.testing); | |
| 12 | try std2.testing.expect(true); | |
| 13 | try testing2.expect(true); | |
| 14 | } | |
| 15 | ||
| 16 | usingnamespace struct { | |
| 17 | pub const foo = 42; | |
| 18 | }; | |
| 19 | ||
| 20 | test "usingnamespace does not redeclare an imported variable" { | |
| 21 | comptime try std.testing.expect(foo == 42); | |
| 22 | } |
test/compile_errors.zig+10| ... | ... | @@ -8846,4 +8846,14 @@ pub fn addCases(ctx: *TestContext) !void { |
| 8846 | 8846 | , &[_][]const u8{ |
| 8847 | 8847 | "error: invalid operands to binary expression: 'f32' and 'f32'", |
| 8848 | 8848 | }); |
| 8849 | ||
| 8850 | ctx.objErrStage1("undeclared identifier in unanalyzed branch", | |
| 8851 | \\export fn a() void { | |
| 8852 | \\ if (false) { | |
| 8853 | \\ lol_this_doesnt_exist = nonsense; | |
| 8854 | \\ } | |
| 8855 | \\} | |
| 8856 | , &[_][]const u8{ | |
| 8857 | "tmp.zig:3:9: error: use of undeclared identifier 'lol_this_doesnt_exist'", | |
| 8858 | }); | |
| 8849 | 8859 | } |