Skip to content

Commit ee541d8

Browse files
committed
Sema: catch invalid asm input operands
Fixes #7843
1 parent 9374725 commit ee541d8

File tree

4 files changed

+132
-2
lines changed

4 files changed

+132
-2
lines changed

src/Sema.zig

+30
Original file line numberDiff line numberDiff line change
@@ -17157,6 +17157,36 @@ fn zirAsm(
1715717157
.ComptimeInt => arg.* = try sema.coerce(block, Type.usize, uncasted_arg, src),
1715817158
.ComptimeFloat => arg.* = try sema.coerce(block, Type.f64, uncasted_arg, src),
1715917159
else => {
17160+
const input_op_src = block.src(.{
17161+
.asm_input_op = .{
17162+
.asm_node_offset = extra.data.src_node,
17163+
.input_index = @intCast(arg_i),
17164+
},
17165+
});
17166+
if (try sema.typeRequiresComptime(uncasted_arg_ty)) {
17167+
return sema.fail(
17168+
block,
17169+
input_op_src,
17170+
"type '{}' is comptime-only and cannot be used for an assembly input operand",
17171+
.{uncasted_arg_ty.fmt(pt)},
17172+
);
17173+
}
17174+
if (!try sema.typeHasRuntimeBits(uncasted_arg_ty)) {
17175+
return sema.fail(
17176+
block,
17177+
input_op_src,
17178+
"type '{}' does not have runtime bits and cannot be used for an assembly input operand",
17179+
.{uncasted_arg_ty.fmt(pt)},
17180+
);
17181+
}
17182+
if (!uncasted_arg_ty.hasWellDefinedLayout(mod)) {
17183+
return sema.fail(
17184+
block,
17185+
input_op_src,
17186+
"type '{}' does not have a well-defined memory layout and cannot be used for an assembly input operand",
17187+
.{uncasted_arg_ty.fmt(pt)},
17188+
);
17189+
}
1716017190
arg.* = uncasted_arg;
1716117191
},
1716217192
}

src/Zcu.zig

+18
Original file line numberDiff line numberDiff line change
@@ -989,6 +989,14 @@ pub const SrcLoc = struct {
989989
const node_datas = tree.nodes.items(.data);
990990
return tree.nodeToSpan(node_datas[asm_output].lhs);
991991
},
992+
.asm_input_op => |asm_input_op| {
993+
const tree = try src_loc.file_scope.getTree(gpa);
994+
const node = src_loc.relativeToNodeIndex(asm_input_op.asm_node_offset);
995+
const full = tree.fullAsm(node).?;
996+
const asm_input = full.inputs[asm_input_op.input_index];
997+
const node_datas = tree.nodes.items(.data);
998+
return tree.nodeToSpan(node_datas[asm_input].lhs);
999+
},
9921000

9931001
.node_offset_if_cond => |node_off| {
9941002
const tree = try src_loc.file_scope.getTree(gpa);
@@ -1795,6 +1803,16 @@ pub const LazySrcLoc = struct {
17951803
/// base node, which points to inline assembly AST node. Next, navigate
17961804
/// to the return type expression.
17971805
node_offset_asm_ret_ty: i32,
1806+
/// The source location points to an input operand of an inline assembly
1807+
/// expression, found by taking this AST node index offset from the containing
1808+
/// Decl AST node, which points to inline assembly AST node. Next, navigate
1809+
/// to the input operand expression.
1810+
asm_input_op: struct {
1811+
/// Points to the asm AST node.
1812+
asm_node_offset: i32,
1813+
/// Picks one of the inputs from the asm.
1814+
input_index: u32,
1815+
},
17981816
/// The source location points to the condition expression of an if
17991817
/// expression, found by taking this AST node index offset from the containing
18001818
/// base node, which points to an if expression AST node. Next, navigate

test/behavior/asm.zig

+14-2
Original file line numberDiff line numberDiff line change
@@ -150,12 +150,24 @@ test "struct/array/union types as input values" {
150150
); // fails
151151
asm volatile (""
152152
:
153-
: [_] "m" (@as(struct { x: u32, y: u8 }, undefined)),
153+
: [_] "m" (@as(packed struct { x: u32, y: u8 }, undefined)),
154154
); // fails
155+
// TODO: CBE struggles with unions here
156+
if (builtin.zig_backend != .stage2_c)
157+
asm volatile (""
158+
:
159+
: [_] "m" (@as(packed union { x: u32, y: u8 }, undefined)),
160+
); // fails
155161
asm volatile (""
156162
:
157-
: [_] "m" (@as(union { x: u32, y: u8 }, undefined)),
163+
: [_] "m" (@as(extern struct { x: u32, y: u8 }, undefined)),
158164
); // fails
165+
// TODO: CBE struggles with unions here
166+
if (builtin.zig_backend != .stage2_c)
167+
asm volatile (""
168+
:
169+
: [_] "m" (@as(extern union { x: u32, y: u8 }, undefined)),
170+
); // fails
159171
}
160172

161173
extern fn this_is_my_alias() i32;
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 assembly input operand
62+
// :11:22: error: type '*const *const type' is comptime-only and cannot be used for an assembly input operand
63+
// :19:23: error: type 'tmp.c.A' does not have runtime bits and cannot be used for an assembly 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 assembly 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 assembly input operand
68+
// :41:22: error: type '@TypeOf(undefined)' is comptime-only and cannot be used for an assembly input operand
69+
// :47:22: error: type 'void' does not have runtime bits and cannot be used for an assembly input operand
70+
// :53:22: error: type '[]const u8' does not have a well-defined memory layout and cannot be used for an assembly input operand

0 commit comments

Comments
 (0)