Skip to content

Commit bc23372

Browse files
wooster0andrewrk
authored andcommitted
Sema: catch invalid asm input operands
Fixes #7843
1 parent e69caaa commit bc23372

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
@@ -519,6 +519,17 @@ pub const LazySrcLoc = union(enum) {
519519
/// to the return type expression.
520520
/// The Decl is determined contextually.
521521
node_offset_asm_ret_ty: i32,
522+
/// The source location points to the operand of an input of an inline assembly
523+
/// expression, found by taking this AST node index offset from the containing
524+
/// Decl AST node, which points to inline assembly AST node. Next, navigate
525+
/// to the input operand expression.
526+
/// The Decl is determined contextually.
527+
asm_input_op: struct {
528+
/// Points to the asm AST node.
529+
asm_node_offset: i32,
530+
/// Picks one of the inputs from the asm.
531+
input_index: u32,
532+
},
522533
/// The source location points to the condition expression of an if
523534
/// expression, found by taking this AST node index offset from the containing
524535
/// 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
@@ -593,6 +593,7 @@ pub const Decl = struct {
593593
.node_offset_deref_ptr,
594594
.node_offset_asm_source,
595595
.node_offset_asm_ret_ty,
596+
.asm_input_op,
596597
.node_offset_if_cond,
597598
.node_offset_bin_op,
598599
.node_offset_bin_lhs,
@@ -1384,6 +1385,14 @@ pub const SrcLoc = struct {
13841385
const node_datas = tree.nodes.items(.data);
13851386
return tree.nodeToSpan(node_datas[asm_output].lhs);
13861387
},
1388+
.asm_input_op => |asm_input_op| {
1389+
const tree = try src_loc.file_scope.getTree(gpa);
1390+
const node = src_loc.declRelativeToNodeIndex(asm_input_op.asm_node_offset);
1391+
const full = tree.fullAsm(node).?;
1392+
const asm_input = full.inputs[asm_input_op.input_index];
1393+
const node_datas = tree.nodes.items(.data);
1394+
return tree.nodeToSpan(node_datas[asm_input].lhs);
1395+
},
13871396

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

src/Sema.zig

+30
Original file line numberDiff line numberDiff line change
@@ -17105,6 +17105,36 @@ fn zirAsm(
1710517105
.ComptimeInt => arg.* = try sema.coerce(block, Type.usize, uncasted_arg, src),
1710617106
.ComptimeFloat => arg.* = try sema.coerce(block, Type.f64, uncasted_arg, src),
1710717107
else => {
17108+
const input_op_src: LazySrcLoc = .{
17109+
.asm_input_op = .{
17110+
.asm_node_offset = extra.data.src_node,
17111+
.input_index = @intCast(arg_i),
17112+
},
17113+
};
17114+
if (try sema.typeRequiresComptime(uncasted_arg_ty)) {
17115+
return sema.fail(
17116+
block,
17117+
input_op_src,
17118+
"type '{}' is comptime-only and cannot be used for an asm input operand",
17119+
.{uncasted_arg_ty.fmt(mod)},
17120+
);
17121+
}
17122+
if (!uncasted_arg_ty.hasRuntimeBitsIgnoreComptime(mod)) {
17123+
return sema.fail(
17124+
block,
17125+
input_op_src,
17126+
"type '{}' does not have runtime bits and cannot be used for an asm input operand",
17127+
.{uncasted_arg_ty.fmt(mod)},
17128+
);
17129+
}
17130+
if (!uncasted_arg_ty.hasWellDefinedLayout(mod)) {
17131+
return sema.fail(
17132+
block,
17133+
input_op_src,
17134+
"type '{}' does not have a well-defined memory layout and cannot be used for an asm input operand",
17135+
.{uncasted_arg_ty.fmt(mod)},
17136+
);
17137+
}
1710817138
arg.* = uncasted_arg;
1710917139
try sema.queueFullTypeResolution(uncasted_arg_ty);
1711017140
},

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)