diff --git a/src/Sema.zig b/src/Sema.zig index b8dcd0a1a5..f66b505e5c 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -16614,6 +16614,7 @@ fn zirAsm( const clobbers_len: u5 = @truncate(extended.small >> 10); const is_volatile = @as(u1, @truncate(extended.small >> 15)) != 0; const is_global_assembly = sema.func_index == .none; + const zir_tags = sema.code.instructions.items(.tag); const asm_source: []const u8 = if (tmpl_is_expr) blk: { const tmpl: Zir.Inst.Ref = @enumFromInt(@intFromEnum(extra.data.asm_source)); @@ -16674,6 +16675,13 @@ fn zirAsm( const name = sema.code.nullTerminatedString(output.data.name); needed_capacity += (constraint.len + name.len + (2 + 3)) / 4; + if (output.data.operand.toIndex()) |index| { + if (zir_tags[@intFromEnum(index)] == .ref) { + // TODO: better error location; it would be even nicer if there were notes that pointed at the output and the variable definition + return sema.fail(block, src, "asm cannot output to const local '{s}'", .{name}); + } + } + outputs[out_i] = .{ .c = constraint, .n = name }; } diff --git a/test/cases/compile_errors/asm_output_to_const.zig b/test/cases/compile_errors/asm_output_to_const.zig new file mode 100644 index 0000000000..aa20a489aa --- /dev/null +++ b/test/cases/compile_errors/asm_output_to_const.zig @@ -0,0 +1,14 @@ +export fn foo() void { + const f: i64 = 1000; + + asm volatile ( + \\ movq $10, %[f] + : [f] "=r" (f), + ); +} + +// error +// backend=llvm +// target=native +// +// :4:5: error: asm cannot output to const local 'f'