Skip to content

Commit

Permalink
Sema: catch invalid asm input operands
Browse files Browse the repository at this point in the history
Fixes #7843
  • Loading branch information
r00ster91 committed Jul 11, 2023
1 parent 6bc9c4f commit c3d96b7
Show file tree
Hide file tree
Showing 3 changed files with 116 additions and 0 deletions.
20 changes: 20 additions & 0 deletions src/Module.zig
Original file line number Diff line number Diff line change
Expand Up @@ -2385,6 +2385,14 @@ pub const SrcLoc = struct {
const node_datas = tree.nodes.items(.data);
return nodeToSpan(tree, node_datas[asm_output].lhs);
},
.asm_input_op => |asm_input_op| {
const tree = try src_loc.file_scope.getTree(gpa);
const node = src_loc.declRelativeToNodeIndex(asm_input_op.asm_node_offset);
const full = tree.fullAsm(node).?;
const asm_input = full.inputs[asm_input_op.input_index];
const node_datas = tree.nodes.items(.data);
return nodeToSpan(tree, node_datas[asm_input].lhs);
},

.node_offset_if_cond => |node_off| {
const tree = try src_loc.file_scope.getTree(gpa);
Expand Down Expand Up @@ -2988,6 +2996,17 @@ pub const LazySrcLoc = union(enum) {
/// to the return type expression.
/// The Decl is determined contextually.
node_offset_asm_ret_ty: i32,
/// The source location points to the operand of an input of an inline assembly
/// expression, found by taking this AST node index offset from the containing
/// Decl AST node, which points to inline assembly AST node. Next, navigate
/// to the input operand expression.
/// The Decl is determined contextually.
asm_input_op: struct {
/// Points to the asm AST node.
asm_node_offset: i32,
/// Picks one of the inputs from the asm.
input_index: u32,
},
/// The source location points to the condition expression of an if
/// expression, found by taking this AST node index offset from the containing
/// Decl AST node, which points to an if expression AST node. Next, navigate
Expand Down Expand Up @@ -3196,6 +3215,7 @@ pub const LazySrcLoc = union(enum) {
.node_offset_deref_ptr,
.node_offset_asm_source,
.node_offset_asm_ret_ty,
.asm_input_op,
.node_offset_if_cond,
.node_offset_bin_op,
.node_offset_bin_lhs,
Expand Down
30 changes: 30 additions & 0 deletions src/Sema.zig
Original file line number Diff line number Diff line change
Expand Up @@ -15833,6 +15833,36 @@ fn zirAsm(
.ComptimeInt => arg.* = try sema.coerce(block, Type.usize, uncasted_arg, src),
.ComptimeFloat => arg.* = try sema.coerce(block, Type.f64, uncasted_arg, src),
else => {
const input_op_src: LazySrcLoc = .{
.asm_input_op = .{
.asm_node_offset = extra.data.src_node,
.input_index = @intCast(arg_i),
},
};
if (uncasted_arg_ty.comptimeOnly(mod)) {
return sema.fail(
block,
input_op_src,
"type '{}' is comptime-only and cannot be used for an asm input operand",
.{uncasted_arg_ty.fmt(mod)},
);
}
if (!uncasted_arg_ty.hasRuntimeBits(mod)) {
return sema.fail(
block,
input_op_src,
"type '{}' does not have runtime bits and cannot be used for an asm input operand",
.{uncasted_arg_ty.fmt(mod)},
);
}
if (!uncasted_arg_ty.hasWellDefinedLayout(mod)) {
return sema.fail(
block,
input_op_src,
"type '{}' does not have a well-defined memory layout and cannot be used for an asm input operand",
.{uncasted_arg_ty.fmt(mod)},
);
}
arg.* = uncasted_arg;
try sema.queueFullTypeResolution(uncasted_arg_ty);
},
Expand Down
66 changes: 66 additions & 0 deletions test/cases/compile_errors/bad_asm_input_operands.zig
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
export fn a() void {
asm volatile (""
:
: [_] "{al}" (u8),
);
}
export fn b() void {
asm volatile (""
:
: [_] "{a}" (0),
[_] "{x}" (&&void),
);
}
export fn c() void {
asm volatile (""
:
: [_] "{x}" (1),
[_] "{x}" (struct {}{}),
);
}
export fn d() void {
asm volatile (""
:
: [_] "{x}" (((packed struct { x: u8 }){ .x = 1 })),
[_] "{x}" (extern struct { x: u8 }{ .x = 1 }),
[_] "{x}" (struct { x: u8 }{ .x = 1 }),
);
}
export fn e() void {
asm volatile (""
:
: [_] "{x}" (@Vector(3, u8){ 1, 2, 3 }),
[_] "{x}" ([2]*const type{ &u8, &u8 }),
);
}
export fn f() void {
asm volatile (""
:
: [_] "{x}" (undefined),
);
}
export fn g() void {
asm volatile (""
:
: [_] "{x}" ({}),
);
}
export fn h() void {
asm volatile (""
:
: [_] "{x}" (@as([]const u8, "hello")),
);
}

// error
// backend=stage2
// target=native
//
// :4:23: error: type 'type' is comptime-only and cannot be used for an asm input operand
// :11:22: error: type '*const *const type' is comptime-only and cannot be used for an asm input operand
// :18:31: error: type 'tmp.c__struct_1046' does not have runtime bits and cannot be used for an asm input operand
// :26:38: error: type 'tmp.d__struct_1049' does not have well-defined memory layout and cannot be used for an asm input operand
// :33:36: error: type '[2]*const type' is comptime-only and cannot be used for an asm input operand
// :39:22: error: type '@TypeOf(undefined)' is comptime-only and cannot be used for an asm input operand
// :45:22: error: type 'void' does not have runtime bits and cannot be used for an asm input operand
// :51:22: error: type '[]const u8' does not have well-defined memory layout and cannot be used for an asm input operand

0 comments on commit c3d96b7

Please sign in to comment.