| ... | @@ -1180,6 +1180,22 @@ const DeclGen = struct { | ... | @@ -1180,6 +1180,22 @@ const DeclGen = struct { |
| 1180 | return ty_ref; | 1180 | return ty_ref; |
| 1181 | } | 1181 | } |
| 1182 | | 1182 | |
| | 1183 | fn resolveFnReturnType(self: *DeclGen, ret_ty: Type) !CacheRef { |
| | 1184 | const mod = self.module; |
| | 1185 | if (!ret_ty.hasRuntimeBitsIgnoreComptime(mod)) { |
| | 1186 | // If the return type is an error set or an error union, then we make this |
| | 1187 | // anyerror return type instead, so that it can be coerced into a function |
| | 1188 | // pointer type which has anyerror as the return type. |
| | 1189 | if (ret_ty.isError(mod)) { |
| | 1190 | return self.resolveType(Type.anyerror, .direct); |
| | 1191 | } else { |
| | 1192 | return self.resolveType(Type.void, .direct); |
| | 1193 | } |
| | 1194 | } |
| | 1195 | |
| | 1196 | return try self.resolveType(ret_ty, .direct); |
| | 1197 | } |
| | 1198 | |
| 1183 | /// Turn a Zig type into a SPIR-V Type, and return a reference to it. | 1199 | /// Turn a Zig type into a SPIR-V Type, and return a reference to it. |
| 1184 | fn resolveType(self: *DeclGen, ty: Type, repr: Repr) Error!CacheRef { | 1200 | fn resolveType(self: *DeclGen, ty: Type, repr: Repr) Error!CacheRef { |
| 1185 | const mod = self.module; | 1201 | const mod = self.module; |
| ... | @@ -1260,7 +1276,7 @@ const DeclGen = struct { | ... | @@ -1260,7 +1276,7 @@ const DeclGen = struct { |
| 1260 | param_ty_refs[param_index] = try self.resolveType(param_ty, .direct); | 1276 | param_ty_refs[param_index] = try self.resolveType(param_ty, .direct); |
| 1261 | param_index += 1; | 1277 | param_index += 1; |
| 1262 | } | 1278 | } |
| 1263 | const return_ty_ref = try self.resolveType(fn_info.return_type.toType(), .direct); | 1279 | const return_ty_ref = try self.resolveFnReturnType(fn_info.return_type.toType()); |
| 1264 | | 1280 | |
| 1265 | const ty_ref = try self.spv.resolve(.{ .function_type = .{ | 1281 | const ty_ref = try self.spv.resolve(.{ .function_type = .{ |
| 1266 | .return_type = return_ty_ref, | 1282 | .return_type = return_ty_ref, |
| ... | @@ -1449,9 +1465,11 @@ const DeclGen = struct { | ... | @@ -1449,9 +1465,11 @@ const DeclGen = struct { |
| 1449 | return ty_ref; | 1465 | return ty_ref; |
| 1450 | }, | 1466 | }, |
| 1451 | .Opaque => { | 1467 | .Opaque => { |
| 1452 | return try self.spv.resolve(.{ .opaque_type = .{ | 1468 | return try self.spv.resolve(.{ |
| 1453 | .name = .none, // TODO | 1469 | .opaque_type = .{ |
| 1454 | } }); | 1470 | .name = .none, // TODO |
| | 1471 | }, |
| | 1472 | }); |
| 1455 | }, | 1473 | }, |
| 1456 | | 1474 | |
| 1457 | .Null, | 1475 | .Null, |
| ... | @@ -1677,16 +1695,17 @@ const DeclGen = struct { | ... | @@ -1677,16 +1695,17 @@ const DeclGen = struct { |
| 1677 | | 1695 | |
| 1678 | if (decl.val.getFunction(mod)) |_| { | 1696 | if (decl.val.getFunction(mod)) |_| { |
| 1679 | assert(decl.ty.zigTypeTag(mod) == .Fn); | 1697 | assert(decl.ty.zigTypeTag(mod) == .Fn); |
| | 1698 | const fn_info = mod.typeToFunc(decl.ty).?; |
| | 1699 | const return_ty_ref = try self.resolveFnReturnType(fn_info.return_type.toType()); |
| | 1700 | |
| 1680 | const prototype_id = try self.resolveTypeId(decl.ty); | 1701 | const prototype_id = try self.resolveTypeId(decl.ty); |
| 1681 | try self.func.prologue.emit(self.spv.gpa, .OpFunction, .{ | 1702 | try self.func.prologue.emit(self.spv.gpa, .OpFunction, .{ |
| 1682 | .id_result_type = try self.resolveTypeId(decl.ty.fnReturnType(mod)), | 1703 | .id_result_type = self.typeId(return_ty_ref), |
| 1683 | .id_result = decl_id, | 1704 | .id_result = decl_id, |
| 1684 | .function_control = .{}, // TODO: We can set inline here if the type requires it. | 1705 | .function_control = .{}, // TODO: We can set inline here if the type requires it. |
| 1685 | .function_type = prototype_id, | 1706 | .function_type = prototype_id, |
| 1686 | }); | 1707 | }); |
| 1687 | | 1708 | |
| 1688 | const fn_info = mod.typeToFunc(decl.ty).?; | | |
| 1689 | | | |
| 1690 | try self.args.ensureUnusedCapacity(self.gpa, fn_info.param_types.len); | 1709 | try self.args.ensureUnusedCapacity(self.gpa, fn_info.param_types.len); |
| 1691 | for (fn_info.param_types.get(ip)) |param_ty_index| { | 1710 | for (fn_info.param_types.get(ip)) |param_ty_index| { |
| 1692 | const param_ty = param_ty_index.toType(); | 1711 | const param_ty = param_ty_index.toType(); |
| ... | @@ -3385,15 +3404,25 @@ const DeclGen = struct { | ... | @@ -3385,15 +3404,25 @@ const DeclGen = struct { |
| 3385 | | 3404 | |
| 3386 | fn airRet(self: *DeclGen, inst: Air.Inst.Index) !void { | 3405 | fn airRet(self: *DeclGen, inst: Air.Inst.Index) !void { |
| 3387 | const operand = self.air.instructions.items(.data)[inst].un_op; | 3406 | const operand = self.air.instructions.items(.data)[inst].un_op; |
| 3388 | const operand_ty = self.typeOf(operand); | 3407 | const ret_ty = self.typeOf(operand); |
| 3389 | const mod = self.module; | 3408 | const mod = self.module; |
| 3390 | if (operand_ty.hasRuntimeBits(mod)) { | 3409 | if (!ret_ty.hasRuntimeBitsIgnoreComptime(mod)) { |
| 3391 | // TODO: If we return an empty struct, this branch is also hit incorrectly. | 3410 | const decl = mod.declPtr(self.decl_index); |
| 3392 | const operand_id = try self.resolve(operand); | 3411 | const fn_info = mod.typeToFunc(decl.ty).?; |
| 3393 | try self.func.body.emit(self.spv.gpa, .OpReturnValue, .{ .value = operand_id }); | 3412 | if (fn_info.return_type.toType().isError(mod)) { |
| 3394 | } else { | 3413 | // Functions with an empty error set are emitted with an error code |
| 3395 | try self.func.body.emit(self.spv.gpa, .OpReturn, {}); | 3414 | // return type and return zero so they can be function pointers coerced |
| | 3415 | // to functions that return anyerror. |
| | 3416 | const err_ty_ref = try self.resolveType(Type.anyerror, .direct); |
| | 3417 | const no_err_id = try self.constInt(err_ty_ref, 0); |
| | 3418 | return try self.func.body.emit(self.spv.gpa, .OpReturnValue, .{ .value = no_err_id }); |
| | 3419 | } else { |
| | 3420 | return try self.func.body.emit(self.spv.gpa, .OpReturn, {}); |
| | 3421 | } |
| 3396 | } | 3422 | } |
| | 3423 | |
| | 3424 | const operand_id = try self.resolve(operand); |
| | 3425 | try self.func.body.emit(self.spv.gpa, .OpReturnValue, .{ .value = operand_id }); |
| 3397 | } | 3426 | } |
| 3398 | | 3427 | |
| 3399 | fn airRetLoad(self: *DeclGen, inst: Air.Inst.Index) !void { | 3428 | fn airRetLoad(self: *DeclGen, inst: Air.Inst.Index) !void { |
| ... | @@ -3403,8 +3432,18 @@ const DeclGen = struct { | ... | @@ -3403,8 +3432,18 @@ const DeclGen = struct { |
| 3403 | const ret_ty = ptr_ty.childType(mod); | 3432 | const ret_ty = ptr_ty.childType(mod); |
| 3404 | | 3433 | |
| 3405 | if (!ret_ty.hasRuntimeBitsIgnoreComptime(mod)) { | 3434 | if (!ret_ty.hasRuntimeBitsIgnoreComptime(mod)) { |
| 3406 | try self.func.body.emit(self.spv.gpa, .OpReturn, {}); | 3435 | const decl = mod.declPtr(self.decl_index); |
| 3407 | return; | 3436 | const fn_info = mod.typeToFunc(decl.ty).?; |
| | 3437 | if (fn_info.return_type.toType().isError(mod)) { |
| | 3438 | // Functions with an empty error set are emitted with an error code |
| | 3439 | // return type and return zero so they can be function pointers coerced |
| | 3440 | // to functions that return anyerror. |
| | 3441 | const err_ty_ref = try self.resolveType(Type.anyerror, .direct); |
| | 3442 | const no_err_id = try self.constInt(err_ty_ref, 0); |
| | 3443 | return try self.func.body.emit(self.spv.gpa, .OpReturnValue, .{ .value = no_err_id }); |
| | 3444 | } else { |
| | 3445 | return try self.func.body.emit(self.spv.gpa, .OpReturn, {}); |
| | 3446 | } |
| 3408 | } | 3447 | } |
| 3409 | | 3448 | |
| 3410 | const ptr = try self.resolve(un_op); | 3449 | const ptr = try self.resolve(un_op); |
| ... | @@ -3991,7 +4030,7 @@ const DeclGen = struct { | ... | @@ -3991,7 +4030,7 @@ const DeclGen = struct { |
| 3991 | const fn_info = mod.typeToFunc(zig_fn_ty).?; | 4030 | const fn_info = mod.typeToFunc(zig_fn_ty).?; |
| 3992 | const return_type = fn_info.return_type; | 4031 | const return_type = fn_info.return_type; |
| 3993 | | 4032 | |
| 3994 | const result_type_id = try self.resolveTypeId(return_type.toType()); | 4033 | const result_type_ref = try self.resolveFnReturnType(return_type.toType()); |
| 3995 | const result_id = self.spv.allocId(); | 4034 | const result_id = self.spv.allocId(); |
| 3996 | const callee_id = try self.resolve(pl_op.operand); | 4035 | const callee_id = try self.resolve(pl_op.operand); |
| 3997 | | 4036 | |
| ... | @@ -4012,7 +4051,7 @@ const DeclGen = struct { | ... | @@ -4012,7 +4051,7 @@ const DeclGen = struct { |
| 4012 | } | 4051 | } |
| 4013 | | 4052 | |
| 4014 | try self.func.body.emit(self.spv.gpa, .OpFunctionCall, .{ | 4053 | try self.func.body.emit(self.spv.gpa, .OpFunctionCall, .{ |
| 4015 | .id_result_type = result_type_id, | 4054 | .id_result_type = self.typeId(result_type_ref), |
| 4016 | .id_result = result_id, | 4055 | .id_result = result_id, |
| 4017 | .function = callee_id, | 4056 | .function = callee_id, |
| 4018 | .id_ref_3 = params[0..n_params], | 4057 | .id_ref_3 = params[0..n_params], |