Skip to content

Commit f8b0879

Browse files
committed
Sema: catch invalid asm input operands
Fixes #7843
1 parent 17bad9f commit f8b0879

File tree

5 files changed

+130
-2
lines changed

5 files changed

+130
-2
lines changed

lib/std/zig.zig

+11
Original file line numberDiff line numberDiff line change
@@ -518,6 +518,17 @@ pub const LazySrcLoc = union(enum) {
518518
/// to the return type expression.
519519
/// The Decl is determined contextually.
520520
node_offset_asm_ret_ty: i32,
521+
/// The source location points to the operand of an input of an inline assembly
522+
/// expression, found by taking this AST node index offset from the containing
523+
/// Decl AST node, which points to inline assembly AST node. Next, navigate
524+
/// to the input operand expression.
525+
/// The Decl is determined contextually.
526+
asm_input_op: struct {
527+
/// Points to the asm AST node.
528+
asm_node_offset: i32,
529+
/// Picks one of the inputs from the asm.
530+
input_index: u32,
531+
},
521532
/// The source location points to the condition expression of an if
522533
/// expression, found by taking this AST node index offset from the containing
523534
/// Decl AST node, which points to an if expression AST node. Next, navigate

src/Module.zig

+9
Original file line numberDiff line numberDiff line change
@@ -673,6 +673,7 @@ pub const Decl = struct {
673673
.node_offset_deref_ptr,
674674
.node_offset_asm_source,
675675
.node_offset_asm_ret_ty,
676+
.asm_input_op,
676677
.node_offset_if_cond,
677678
.node_offset_bin_op,
678679
.node_offset_bin_lhs,
@@ -1452,6 +1453,14 @@ pub const SrcLoc = struct {
14521453
const node_datas = tree.nodes.items(.data);
14531454
return tree.nodeToSpan(node_datas[asm_output].lhs);
14541455
},
1456+
.asm_input_op => |asm_input_op| {
1457+
const tree = try src_loc.file_scope.getTree(gpa);
1458+
const node = src_loc.declRelativeToNodeIndex(asm_input_op.asm_node_offset);
1459+
const full = tree.fullAsm(node).?;
1460+
const asm_input = full.inputs[asm_input_op.input_index];
1461+
const node_datas = tree.nodes.items(.data);
1462+
return tree.nodeToSpan(node_datas[asm_input].lhs);
1463+
},
14551464

14561465
.node_offset_if_cond => |node_off| {
14571466
const tree = try src_loc.file_scope.getTree(gpa);

src/Sema.zig

+30
Original file line numberDiff line numberDiff line change
@@ -16854,6 +16854,36 @@ fn zirAsm(
1685416854
.ComptimeInt => arg.* = try sema.coerce(block, Type.usize, uncasted_arg, src),
1685516855
.ComptimeFloat => arg.* = try sema.coerce(block, Type.f64, uncasted_arg, src),
1685616856
else => {
16857+
const input_op_src: LazySrcLoc = .{
16858+
.asm_input_op = .{
16859+
.asm_node_offset = extra.data.src_node,
16860+
.input_index = @intCast(arg_i),
16861+
},
16862+
};
16863+
if (try sema.typeRequiresComptime(uncasted_arg_ty)) {
16864+
return sema.fail(
16865+
block,
16866+
input_op_src,
16867+
"type '{}' is comptime-only and cannot be used for an asm input operand",
16868+
.{uncasted_arg_ty.fmt(mod)},
16869+
);
16870+
}
16871+
if (!uncasted_arg_ty.hasRuntimeBitsIgnoreComptime(mod)) {
16872+
return sema.fail(
16873+
block,
16874+
input_op_src,
16875+
"type '{}' does not have runtime bits and cannot be used for an asm input operand",
16876+
.{uncasted_arg_ty.fmt(mod)},
16877+
);
16878+
}
16879+
if (!uncasted_arg_ty.hasWellDefinedLayout(mod)) {
16880+
return sema.fail(
16881+
block,
16882+
input_op_src,
16883+
"type '{}' does not have a well-defined memory layout and cannot be used for an asm input operand",
16884+
.{uncasted_arg_ty.fmt(mod)},
16885+
);
16886+
}
1685716887
arg.* = uncasted_arg;
1685816888
try sema.queueFullTypeResolution(uncasted_arg_ty);
1685916889
},

test/behavior/asm.zig

+10-2
Original file line numberDiff line numberDiff line change
@@ -146,11 +146,19 @@ test "struct/array/union types as input values" {
146146
); // fails
147147
asm volatile (""
148148
:
149-
: [_] "m" (@as(struct { x: u32, y: u8 }, undefined)),
149+
: [_] "m" (@as(packed struct { x: u32, y: u8 }, undefined)),
150150
); // fails
151151
asm volatile (""
152152
:
153-
: [_] "m" (@as(union { x: u32, y: u8 }, undefined)),
153+
: [_] "m" (@as(packed union { x: u32, y: u8 }, undefined)),
154+
); // fails
155+
asm volatile (""
156+
:
157+
: [_] "m" (@as(extern struct { x: u32, y: u8 }, undefined)),
158+
); // fails
159+
asm volatile (""
160+
:
161+
: [_] "m" (@as(extern union { x: u32, y: u8 }, undefined)),
154162
); // fails
155163
}
156164

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
export fn a() void {
2+
asm volatile (""
3+
:
4+
: [_] "{al}" (u8),
5+
);
6+
}
7+
export fn b() void {
8+
asm volatile (""
9+
:
10+
: [_] "{a}" (0),
11+
[_] "{x}" (&&void),
12+
);
13+
}
14+
export fn c() void {
15+
const A = struct {};
16+
asm volatile (""
17+
:
18+
: [_] "{x}" (1),
19+
[_] "{x}" (A{}),
20+
);
21+
}
22+
export fn d() void {
23+
const A = struct { x: u8 };
24+
asm volatile (""
25+
:
26+
: [_] "{x}" (((packed struct { x: u8 }){ .x = 1 })),
27+
[_] "{x}" (extern struct { x: u8 }{ .x = 1 }),
28+
[_] "{x}" (A{ .x = 1 }),
29+
);
30+
}
31+
export fn e() void {
32+
asm volatile (""
33+
:
34+
: [_] "{x}" (@Vector(3, u8){ 1, 2, 3 }),
35+
[_] "{x}" ([2]*const type{ &u8, &u8 }),
36+
);
37+
}
38+
export fn f() void {
39+
asm volatile (""
40+
:
41+
: [_] "{x}" (undefined),
42+
);
43+
}
44+
export fn g() void {
45+
asm volatile (""
46+
:
47+
: [_] "{x}" ({}),
48+
);
49+
}
50+
export fn h() void {
51+
asm volatile (""
52+
:
53+
: [_] "{x}" (@as([]const u8, "hello")),
54+
);
55+
}
56+
57+
// error
58+
// backend=stage2
59+
// target=native
60+
//
61+
// :4:23: error: type 'type' is comptime-only and cannot be used for an asm input operand
62+
// :11:22: error: type '*const *const type' is comptime-only and cannot be used for an asm input operand
63+
// :19:23: error: type 'tmp.c.A' does not have runtime bits and cannot be used for an asm input operand
64+
// :15:15: note: struct declared here
65+
// :28:23: error: type 'tmp.d.A' does not have a well-defined memory layout and cannot be used for an asm input operand
66+
// :23:15: note: struct declared here
67+
// :35:36: error: type '[2]*const type' is comptime-only and cannot be used for an asm input operand
68+
// :41:22: error: type '@TypeOf(undefined)' is comptime-only and cannot be used for an asm input operand
69+
// :47:22: error: type 'void' does not have runtime bits and cannot be used for an asm input operand
70+
// :53:22: error: type '[]const u8' does not have a well-defined memory layout and cannot be used for an asm input operand

0 commit comments

Comments
 (0)