Skip to content

Commit 56d0cf8

Browse files
committed
Sema: catch invalid asm input operands
Fixes #7843
1 parent 6bc9c4f commit 56d0cf8

File tree

4 files changed

+120
-2
lines changed

4 files changed

+120
-2
lines changed

src/Module.zig

+20
Original file line numberDiff line numberDiff line change
@@ -2385,6 +2385,14 @@ pub const SrcLoc = struct {
23852385
const node_datas = tree.nodes.items(.data);
23862386
return nodeToSpan(tree, node_datas[asm_output].lhs);
23872387
},
2388+
.asm_input_op => |asm_input_op| {
2389+
const tree = try src_loc.file_scope.getTree(gpa);
2390+
const node = src_loc.declRelativeToNodeIndex(asm_input_op.asm_node_offset);
2391+
const full = tree.fullAsm(node).?;
2392+
const asm_input = full.inputs[asm_input_op.input_index];
2393+
const node_datas = tree.nodes.items(.data);
2394+
return nodeToSpan(tree, node_datas[asm_input].lhs);
2395+
},
23882396

23892397
.node_offset_if_cond => |node_off| {
23902398
const tree = try src_loc.file_scope.getTree(gpa);
@@ -2988,6 +2996,17 @@ pub const LazySrcLoc = union(enum) {
29882996
/// to the return type expression.
29892997
/// The Decl is determined contextually.
29902998
node_offset_asm_ret_ty: i32,
2999+
/// The source location points to the operand of an input of an inline assembly
3000+
/// expression, found by taking this AST node index offset from the containing
3001+
/// Decl AST node, which points to inline assembly AST node. Next, navigate
3002+
/// to the input operand expression.
3003+
/// The Decl is determined contextually.
3004+
asm_input_op: struct {
3005+
/// Points to the asm AST node.
3006+
asm_node_offset: i32,
3007+
/// Picks one of the inputs from the asm.
3008+
input_index: u32,
3009+
},
29913010
/// The source location points to the condition expression of an if
29923011
/// expression, found by taking this AST node index offset from the containing
29933012
/// Decl AST node, which points to an if expression AST node. Next, navigate
@@ -3196,6 +3215,7 @@ pub const LazySrcLoc = union(enum) {
31963215
.node_offset_deref_ptr,
31973216
.node_offset_asm_source,
31983217
.node_offset_asm_ret_ty,
3218+
.asm_input_op,
31993219
.node_offset_if_cond,
32003220
.node_offset_bin_op,
32013221
.node_offset_bin_lhs,

src/Sema.zig

+30
Original file line numberDiff line numberDiff line change
@@ -15833,6 +15833,36 @@ fn zirAsm(
1583315833
.ComptimeInt => arg.* = try sema.coerce(block, Type.usize, uncasted_arg, src),
1583415834
.ComptimeFloat => arg.* = try sema.coerce(block, Type.f64, uncasted_arg, src),
1583515835
else => {
15836+
const input_op_src: LazySrcLoc = .{
15837+
.asm_input_op = .{
15838+
.asm_node_offset = extra.data.src_node,
15839+
.input_index = @intCast(arg_i),
15840+
},
15841+
};
15842+
if (uncasted_arg_ty.comptimeOnly(mod)) {
15843+
return sema.fail(
15844+
block,
15845+
input_op_src,
15846+
"type '{}' is comptime-only and cannot be used for an asm input operand",
15847+
.{uncasted_arg_ty.fmt(mod)},
15848+
);
15849+
}
15850+
if (!uncasted_arg_ty.hasRuntimeBits(mod)) {
15851+
return sema.fail(
15852+
block,
15853+
input_op_src,
15854+
"type '{}' does not have runtime bits and cannot be used for an asm input operand",
15855+
.{uncasted_arg_ty.fmt(mod)},
15856+
);
15857+
}
15858+
if (!uncasted_arg_ty.hasWellDefinedLayout(mod)) {
15859+
return sema.fail(
15860+
block,
15861+
input_op_src,
15862+
"type '{}' does not have a well-defined memory layout and cannot be used for an asm input operand",
15863+
.{uncasted_arg_ty.fmt(mod)},
15864+
);
15865+
}
1583615866
arg.* = uncasted_arg;
1583715867
try sema.queueFullTypeResolution(uncasted_arg_ty);
1583815868
},

test/behavior/asm.zig

+2-2
Original file line numberDiff line numberDiff line change
@@ -149,11 +149,11 @@ test "struct/array/union types as input values" {
149149
); // fails
150150
asm volatile (""
151151
:
152-
: [_] "m" (@as(struct { x: u32, y: u8 }, undefined)),
152+
: [_] "m" (@as(packed struct { x: u32, y: u8 }, undefined)),
153153
); // fails
154154
asm volatile (""
155155
:
156-
: [_] "m" (@as(union { x: u32, y: u8 }, undefined)),
156+
: [_] "m" (@as(packed union { x: u32, y: u8 }, undefined)),
157157
); // fails
158158
}
159159

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
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+
// :28:23: error: type 'tmp.d.A' does not have a well-defined memory layout and cannot be used for an asm input operand
65+
// :35:36: error: type '[2]*const type' is comptime-only and cannot be used for an asm input operand
66+
// :41:22: error: type '@TypeOf(undefined)' is comptime-only and cannot be used for an asm input operand
67+
// :47:22: error: type 'void' does not have runtime bits and cannot be used for an asm input operand
68+
// :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)