authorgravatar for alichraghi@proton.meAli Chraghi <alichraghi@proton.me> 2026-06-30 07:06:22+03:30
committergravatar for alichraghi@proton.meAli Chraghi <alichraghi@proton.me> 2026-06-30 07:06:47+03:30
logbac1ea6548073707a0a7d7740ce7987ffd710184
tree21f851e9a0eff548690561ca7c40e4b8766e86a3
parent199f8603ed3b6c9fb600c6f4feb380c995dd6b40

Sema: disallow input/output pointer params for shader functions


1 files changed, 15 insertions(+), 20 deletions(-)

src/Sema.zig+15-20
...@@ -8629,6 +8629,20 @@ fn checkParamType(...@@ -8629,6 +8629,20 @@ fn checkParamType(
8629 if (param_is_noalias and !param_ty.isGenericPoison() and !param_ty.isPtrAtRuntime(zcu) and !param_ty.isSliceAtRuntime(zcu)) {8629 if (param_is_noalias and !param_ty.isGenericPoison() and !param_ty.isPtrAtRuntime(zcu) and !param_ty.isSliceAtRuntime(zcu)) {
8630 return sema.fail(block, param_src, "non-pointer parameter declared noalias", .{});8630 return sema.fail(block, param_src, "non-pointer parameter declared noalias", .{});
8631 }8631 }
8632 switch (target.os.tag) {
8633 .vulkan, .opengl => if (cc != .@"inline" and param_ty.isPtrAtRuntime(zcu)) {
8634 switch (param_ty.ptrAddressSpace(zcu)) {
8635 .input, .output => |as| return sema.failWithOwnedErrorMsg(block, msg: {
8636 const msg = try sema.errMsg(param_src, "function parameter cannot be a pointer in '{s}' address space", .{@tagName(as)});
8637 errdefer msg.destroy(sema.gpa);
8638 try sema.errNote(param_src, msg, "mark the function as 'inline' so the parameter is substituted at call sites", .{});
8639 break :msg msg;
8640 }),
8641 else => {},
8642 }
8643 },
8644 else => {},
8645 }
8632}8646}
86338647
8634fn checkReturnTypeAndCallConv(8648fn checkReturnTypeAndCallConv(
...@@ -20530,10 +20544,6 @@ fn zirReifySpirvType(...@@ -20530,10 +20544,6 @@ fn zirReifySpirvType(
20530 return sema.failWithUseOfUndef(block, operand_src, null);20544 return sema.failWithUseOfUndef(block, operand_src, null);
20531 }20545 }
2053220546
20533 // TODO: use a longer hash!
20534 var hasher = std.hash.Wyhash.init(0);
20535 std.hash.autoHash(&hasher, union_val.tag);
20536
20537 const name = try ip.getOrPutStringFmt(20547 const name = try ip.getOrPutStringFmt(
20538 gpa,20548 gpa,
20539 io,20549 io,
...@@ -20640,20 +20650,11 @@ fn zirReifySpirvType(...@@ -20640,20 +20650,11 @@ fn zirReifySpirvType(
20640 else => {},20650 else => {},
20641 }20651 }
2064220652
20643 std.hash.autoHash(&hasher, usage_tag);
20644 std.hash.autoHash(&hasher, format);
20645 std.hash.autoHash(&hasher, dim);
20646 std.hash.autoHash(&hasher, depth);
20647 std.hash.autoHash(&hasher, access);
20648 std.hash.autoHash(&hasher, arrayed);
20649 std.hash.autoHash(&hasher, multisampled);
20650
20651 break :ip_data .{20653 break :ip_data .{
20652 .name = name,20654 .name = name,
20653 .zir_index = tracked_inst,20655 .zir_index = tracked_inst,
20654 .ty = blk: {20656 .ty = blk: {
20655 const sampled_type = usage_val.unionPayload(zcu).toType();20657 const sampled_type = usage_val.unionPayload(zcu).toType();
20656 std.hash.autoHash(&hasher, sampled_type.toIntern());
2065720658
20658 if (target.os.tag != .opencl and sampled_type.toIntern() == .void_type) {20659 if (target.os.tag != .opencl and sampled_type.toIntern() == .void_type) {
20659 return sema.fail(block, operand_src, "'void' type for '{t}' field is only valid under the 'opencl' os", .{usage_tag});20660 return sema.fail(block, operand_src, "'void' type for '{t}' field is only valid under the 'opencl' os", .{usage_tag});
...@@ -20726,7 +20727,6 @@ fn zirReifySpirvType(...@@ -20726,7 +20727,6 @@ fn zirReifySpirvType(
20726 if (image_info.usage != .sampled) {20727 if (image_info.usage != .sampled) {
20727 return sema.fail(block, operand_src, "'sampled_image' element must be an image with 'usage = .sampled'", .{});20728 return sema.fail(block, operand_src, "'sampled_image' element must be an image with 'usage = .sampled'", .{});
20728 }20729 }
20729 std.hash.autoHash(&hasher, union_val.val);
20730 break :blk .{20730 break :blk .{
20731 .name = name,20731 .name = name,
20732 .zir_index = tracked_inst,20732 .zir_index = tracked_inst,
...@@ -20754,7 +20754,6 @@ fn zirReifySpirvType(...@@ -20754,7 +20754,6 @@ fn zirReifySpirvType(
20754 {20754 {
20755 return sema.fail(block, operand_src, "'runtime_array' of 'runtime_array' is not allowed under the 'vulkan' os", .{});20755 return sema.fail(block, operand_src, "'runtime_array' of 'runtime_array' is not allowed under the 'vulkan' os", .{});
20756 }20756 }
20757 std.hash.autoHash(&hasher, union_val.val);
20758 break :blk .{20757 break :blk .{
20759 .name = name,20758 .name = name,
20760 .zir_index = tracked_inst,20759 .zir_index = tracked_inst,
...@@ -20773,11 +20772,7 @@ fn zirReifySpirvType(...@@ -20773,11 +20772,7 @@ fn zirReifySpirvType(
20773 },20772 },
20774 };20773 };
2077520774
20776 return .fromIntern(try ip.getReifiedSpirvType(gpa, io, pt.tid, .{20775 return .fromIntern(try ip.getReifiedSpirvType(gpa, io, pt.tid, ip_data));
20777 .zir_index = tracked_inst,
20778 .type_hash = hasher.final(),
20779 .type_spirv = ip_data,
20780 }));
20781}20776}
2078220777
20783fn resolveVaListRef(sema: *Sema, block: *Block, src: LazySrcLoc, zir_ref: Zir.Inst.Ref) CompileError!Air.Inst.Ref {20778fn resolveVaListRef(sema: *Sema, block: *Block, src: LazySrcLoc, zir_ref: Zir.Inst.Ref) CompileError!Air.Inst.Ref {