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 Sep 12, 2024
1 parent eccd06f commit 0bb0b0d
Show file tree
Hide file tree
Showing 4 changed files with 138 additions and 2 deletions.
36 changes: 36 additions & 0 deletions src/Sema.zig
Original file line number Diff line number Diff line change
Expand Up @@ -17629,6 +17629,42 @@ fn zirAsm(
.comptime_int => arg.* = try sema.coerce(block, Type.usize, uncasted_arg, src),
.comptime_float => arg.* = try sema.coerce(block, Type.f64, uncasted_arg, src),
else => {
const input_op_src = block.src(.{
.asm_input_op = .{
.asm_node_offset = extra.data.src_node,
.input_index = @intCast(arg_i),
},
});
if (try uncasted_arg_ty.comptimeOnlySema(pt)) {
const target = pt.zcu.getTarget();
const arch = target.cpu.arch;
const is_spirv = arch.isSpirV();
// SPIR-V is a typed language so we want to be able to pass types through.
if (uncasted_arg_ty.zigTypeTag(zcu) != .type or !is_spirv) {
return sema.fail(
block,
input_op_src,
"type '{}' is comptime-only and cannot be used for an assembly input operand",
.{uncasted_arg_ty.fmt(pt)},
);
}
}
if (!try uncasted_arg_ty.hasRuntimeBitsSema(pt)) {
return sema.fail(
block,
input_op_src,
"type '{}' does not have runtime bits and cannot be used for an assembly input operand",
.{uncasted_arg_ty.fmt(pt)},
);
}
if (!uncasted_arg_ty.hasWellDefinedLayout(zcu)) {
return sema.fail(
block,
input_op_src,
"type '{}' does not have a well-defined memory layout and cannot be used for an assembly input operand",
.{uncasted_arg_ty.fmt(pt)},
);
}
arg.* = uncasted_arg;
},
}
Expand Down
18 changes: 18 additions & 0 deletions src/Zcu.zig
Original file line number Diff line number Diff line change
Expand Up @@ -989,6 +989,14 @@ pub const SrcLoc = struct {
const node_datas = tree.nodes.items(.data);
return tree.nodeToSpan(node_datas[asm_output].lhs);
},
.asm_input_op => |asm_input_op| {
const tree = try src_loc.file_scope.getTree(gpa);
const node = src_loc.relativeToNodeIndex(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 tree.nodeToSpan(node_datas[asm_input].lhs);
},

.node_offset_if_cond => |node_off| {
const tree = try src_loc.file_scope.getTree(gpa);
Expand Down Expand Up @@ -1795,6 +1803,16 @@ pub const LazySrcLoc = struct {
/// base node, which points to inline assembly AST node. Next, navigate
/// to the return type expression.
node_offset_asm_ret_ty: i32,
/// The source location points to an input operand 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.
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
/// base node, which points to an if expression AST node. Next, navigate
Expand Down
16 changes: 14 additions & 2 deletions test/behavior/asm.zig
Original file line number Diff line number Diff line change
Expand Up @@ -150,12 +150,24 @@ test "struct/array/union types as input values" {
); // fails
asm volatile (""
:
: [_] "m" (@as(struct { x: u32, y: u8 }, undefined)),
: [_] "m" (@as(packed struct { x: u32, y: u8 }, undefined)),
); // fails
// TODO: CBE struggles with unions here
if (builtin.zig_backend != .stage2_c)
asm volatile (""
:
: [_] "m" (@as(packed union { x: u32, y: u8 }, undefined)),
); // fails
asm volatile (""
:
: [_] "m" (@as(union { x: u32, y: u8 }, undefined)),
: [_] "m" (@as(extern struct { x: u32, y: u8 }, undefined)),
); // fails
// TODO: CBE struggles with unions here
if (builtin.zig_backend != .stage2_c)
asm volatile (""
:
: [_] "m" (@as(extern union { x: u32, y: u8 }, undefined)),
); // fails
}

extern fn this_is_my_alias() i32;
Expand Down
70 changes: 70 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,70 @@
export fn a() void {
asm volatile (""
:
: [_] "{al}" (u8),
);
}
export fn b() void {
asm volatile (""
:
: [_] "{a}" (0),
[_] "{x}" (&&void),
);
}
export fn c() void {
const A = struct {};
asm volatile (""
:
: [_] "{x}" (1),
[_] "{x}" (A{}),
);
}
export fn d() void {
const A = struct { x: u8 };
asm volatile (""
:
: [_] "{x}" (((packed struct { x: u8 }){ .x = 1 })),
[_] "{x}" (extern struct { x: u8 }{ .x = 1 }),
[_] "{x}" (A{ .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 assembly input operand
// :11:22: error: type '*const *const type' is comptime-only and cannot be used for an assembly input operand
// :19:23: error: type 'tmp.c.A' does not have runtime bits and cannot be used for an assembly input operand
// :15:15: note: struct declared here
// :28:23: error: type 'tmp.d.A' does not have a well-defined memory layout and cannot be used for an assembly input operand
// :23:15: note: struct declared here
// :35:36: error: type '[2]*const type' is comptime-only and cannot be used for an assembly input operand
// :41:22: error: type '@TypeOf(undefined)' is comptime-only and cannot be used for an assembly input operand
// :47:22: error: type 'void' does not have runtime bits and cannot be used for an assembly input operand
// :53:22: error: type '[]const u8' does not have a well-defined memory layout and cannot be used for an assembly input operand

0 comments on commit 0bb0b0d

Please sign in to comment.