Skip to content

Commit c3d96b7

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

File tree

3 files changed

+116
-0
lines changed

3 files changed

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

0 commit comments

Comments
 (0)