From 8d0d6743bf1d703a0bebad799d8975677b0e693b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dalibor=20Van=C4=9Bk?= Date: Fri, 7 Aug 2026 10:44:43 +0200 Subject: [PATCH] implement asm output operand handling in symbolReferences and add related tests --- src/features/references.zig | 35 +++++++++++++++++++++++++ tests/lsp_features/references.zig | 43 +++++++++++++++++++++++++++++++ 2 files changed, 78 insertions(+) diff --git a/src/features/references.zig b/src/features/references.zig index 4838cc61e..eea2aad98 100644 --- a/src/features/references.zig +++ b/src/features/references.zig @@ -208,6 +208,41 @@ const Builder = struct { const candidate, _ = try builder.analyser.getSymbolEnumLiteral(handle, tree.tokenStart(name_token), name) orelse return; break :candidate .{ candidate, name_token }; }, + .asm_simple, + .@"asm", + => { + // An asm output operand without `->` is a bare identifier token + // with no corresponding AST node, so it is invisible to the + // child iteration above. + const full_asm = ast.fullAsm(tree, node).?; + for (full_asm.outputs) |output_node| { + const name_token = tree.nodeMainToken(output_node) + 4; + if (tree.tokenTag(name_token) != .identifier) continue; // `(-> T)` operand + const name = offsets.identifierTokenToNameSlice(tree, name_token); + const is_escaped_identifier = tree.source[tree.tokenStart(name_token)] == '@'; + + if (!is_escaped_identifier) { + if (std.mem.eql(u8, name, "_")) continue; + if (std.zig.isPrimitive(name)) continue; + } + + if (!std.mem.eql(u8, name, target_symbol_name)) continue; + + var candidate = try builder.analyser.lookupSymbolGlobal( + handle, + name, + tree.tokenStart(name_token), + ) orelse continue; + + if (builder.resolve_aliases) { + candidate = try builder.analyser.resolveVarDeclAlias(candidate) orelse candidate; + } + if (builder.target_symbol.eql(candidate)) { + try builder.add(handle, name_token); + } + } + return; + }, .global_var_decl, .local_var_decl, .aligned_var_decl, diff --git a/tests/lsp_features/references.zig b/tests/lsp_features/references.zig index 961db2333..4c20117da 100644 --- a/tests/lsp_features/references.zig +++ b/tests/lsp_features/references.zig @@ -259,6 +259,49 @@ test "asm" { \\ ); \\} ); + try testSymbolReferences( + \\fn foo() void { + \\ var <0>: u32 = 0; + \\ asm volatile ("bogus" + \\ : [ret] "={rax}" (<0>), + \\ ); + \\} + ); + try testSymbolReferences( + \\fn foo() void { + \\ var <0>: u32 = 0; + \\ asm volatile ("bogus" + \\ : [a] "={rax}" (<0>), + \\ [b] "={rdx}" (<0>), + \\ ); + \\} + ); + try testSymbolReferences( + \\fn foo() void { + \\ var <0>: u32 = 0; + \\ asm volatile ("bogus" + \\ : [ret] "={rax}" (-> u32), + \\ [out] "={rdx}" (<0>), + \\ ); + \\} + ); + try testSymbolReferences( + \\var <0>: u32 = 0; + \\fn foo() void { + \\ var <1>: u32 = 0; + \\ asm volatile ("bogus" + \\ : [ret] "={rax}" (<1>), + \\ ); + \\} + ); + try testSimpleReferences( + \\const @"i32" = undefined; + \\fn foo() void { + \\ asm volatile ("bogus" + \\ : [ret] "={rax}" (i32), + \\ ); + \\} + ); } test "function header" {