authorgravatar for pentuppup@noreply.codeberg.orgpentuppup <pentuppup@noreply.codeberg.org> 2026-02-17 13:38:00-05:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2026-03-15 22:37:38+01:00
log23837094312763ffe6e598df80fdc2ef63f73ab5
treee7a96a114864fd2ecdba938b23579a88129227b0
parent43d5bea7af8933723a457da45714b144d95e2c70

coerce assembly clobbers in sema


3 files changed, 22 insertions(+), 3 deletions(-)

src/Sema.zig+7-3
...@@ -15649,11 +15649,15 @@ fn zirAsm(...@@ -15649,11 +15649,15 @@ fn zirAsm(
15649 inputs[arg_i] = .{ .c = constraint, .n = name };15649 inputs[arg_i] = .{ .c = constraint, .n = name };
15650 }15650 }
1565115651
15652 const clobbers_src = block.src(.{ .asm_clobbers = src.offset.node_offset.x });
15653 const clobbers_ty = try sema.getBuiltinType(src, .@"assembly.Clobbers");
15652 const clobbers = if (extra.data.clobbers == .none) empty: {15654 const clobbers = if (extra.data.clobbers == .none) empty: {
15653 const clobbers_ty = try sema.getBuiltinType(src, .@"assembly.Clobbers");
15654 break :empty try sema.structInitEmpty(block, clobbers_ty, src, src);15655 break :empty try sema.structInitEmpty(block, clobbers_ty, src, src);
15655 } else sema.resolveInst(extra.data.clobbers); // Already coerced by AstGen.15656 } else clobbers: {
15656 const clobbers_val = try sema.resolveConstDefinedValue(block, src, clobbers, .{ .simple = .clobber });15657 const uncoerced = sema.resolveInst(extra.data.clobbers);
15658 break :clobbers try sema.coerce(block, clobbers_ty, uncoerced, clobbers_src);
15659 };
15660 const clobbers_val = try sema.resolveConstDefinedValue(block, clobbers_src, clobbers, .{ .simple = .clobber });
15657 needed_capacity += asm_source.len / 4 + 1;15661 needed_capacity += asm_source.len / 4 + 1;
1565815662
15659 try sema.air_extra.ensureUnusedCapacity(gpa, needed_capacity);15663 try sema.air_extra.ensureUnusedCapacity(gpa, needed_capacity);
src/Zcu.zig+8
...@@ -1602,6 +1602,12 @@ pub const SrcLoc = struct {...@@ -1602,6 +1602,12 @@ pub const SrcLoc = struct {
1602 // token points to the ')'1602 // token points to the ')'
1603 tree.tokenToSpan(data[1] - 1);1603 tree.tokenToSpan(data[1] - 1);
1604 },1604 },
1605 .asm_clobbers => |offset| {
1606 const tree = try src_loc.file_scope.getTree(zcu);
1607 const node = offset.toAbsolute(src_loc.base_node);
1608 const full = tree.fullAsm(node).?;
1609 return tree.nodeToSpan(full.ast.clobbers.unwrap().?); // this should only be reachable if the clobbers are written in the source
1610 },
1605 .for_input => |for_input| {1611 .for_input => |for_input| {
1606 const tree = try src_loc.file_scope.getTree(zcu);1612 const tree = try src_loc.file_scope.getTree(zcu);
1607 const node = for_input.for_node_offset.toAbsolute(src_loc.base_node);1613 const node = for_input.for_node_offset.toAbsolute(src_loc.base_node);
...@@ -2552,6 +2558,8 @@ pub const LazySrcLoc = struct {...@@ -2552,6 +2558,8 @@ pub const LazySrcLoc = struct {
2552 offset: Ast.Node.Offset,2558 offset: Ast.Node.Offset,
2553 output_index: u32,2559 output_index: u32,
2554 },2560 },
2561 /// Points to the assembly node
2562 asm_clobbers: Ast.Node.Offset,
2555 /// The source location points to a for loop input.2563 /// The source location points to a for loop input.
2556 for_input: struct {2564 for_input: struct {
2557 /// Points to the for loop AST node.2565 /// Points to the for loop AST node.
test/cases/compile_errors/undefined_assembly_clobbers.zig created+7
...@@ -0,0 +1,7 @@
1export fn foo() void {
2 asm volatile("" ::: undefined);
3}
4
5// error
6//
7// :2:25: error: use of undefined value here causes illegal behavior