mirror of
https://github.com/ziglang/zig.git
synced 2025-12-26 08:03:08 +00:00
spirv: construct error union at runtime
This commit is contained in:
parent
ced8a2c3a6
commit
ece52640eb
@ -1021,9 +1021,10 @@ pub const DeclGen = struct {
|
||||
}
|
||||
|
||||
/// This function generates a load for a constant in direct (ie, non-memory) representation.
|
||||
/// When the constant is simple, it can be generated directly using OpConstant instructions. When
|
||||
/// the constant is more complicated however, it needs to be lowered to an indirect constant, which
|
||||
/// is then loaded using OpLoad. Such values are loaded into the UniformConstant storage class by default.
|
||||
/// When the constant is simple, it can be generated directly using OpConstant instructions.
|
||||
/// When the constant is more complicated however, it needs to be constructed using multiple values. This
|
||||
/// is done by emitting a sequence of instructions that initialize the value.
|
||||
//
|
||||
/// This function should only be called during function code generation.
|
||||
fn constant(self: *DeclGen, ty: Type, arg_val: Value, repr: Repr) !IdRef {
|
||||
const mod = self.module;
|
||||
@ -1037,7 +1038,7 @@ pub const DeclGen = struct {
|
||||
}
|
||||
|
||||
log.debug("constant: ty = {}, val = {}", .{ ty.fmt(self.module), val.fmtValue(ty, self.module) });
|
||||
if (val.isUndef(mod)) {
|
||||
if (val.isUndefDeep(mod)) {
|
||||
return self.spv.constUndef(result_ty_ref);
|
||||
}
|
||||
|
||||
@ -1060,8 +1061,7 @@ pub const DeclGen = struct {
|
||||
.inferred_error_set_type,
|
||||
=> unreachable, // types, not values
|
||||
|
||||
.undef => unreachable, // handled above
|
||||
.runtime_value => unreachable, // ???
|
||||
.undef, .runtime_value => unreachable, // handled above
|
||||
|
||||
.variable,
|
||||
.extern_func,
|
||||
@ -1103,6 +1103,49 @@ pub const DeclGen = struct {
|
||||
const value = try mod.getErrorValue(err.name);
|
||||
return try self.spv.constInt(result_ty_ref, value);
|
||||
},
|
||||
.error_union => |error_union| {
|
||||
// TODO: Error unions may be constructed with constant instructions if the payload type
|
||||
// allows it. For now, just generate it here regardless.
|
||||
const err_ty = switch (error_union.val) {
|
||||
.err_name => ty.errorUnionSet(mod),
|
||||
.payload => Type.err_int,
|
||||
};
|
||||
const err_val = switch (error_union.val) {
|
||||
.err_name => |err_name| (try mod.intern(.{ .err = .{
|
||||
.ty = ty.errorUnionSet(mod).toIntern(),
|
||||
.name = err_name,
|
||||
} })).toValue(),
|
||||
.payload => try mod.intValue(Type.err_int, 0),
|
||||
};
|
||||
const payload_ty = ty.errorUnionPayload(mod);
|
||||
const eu_layout = self.errorUnionLayout(payload_ty);
|
||||
if (!eu_layout.payload_has_bits) {
|
||||
// We use the error type directly as the type.
|
||||
return try self.constant(err_ty, err_val, .indirect);
|
||||
}
|
||||
|
||||
const payload_val = switch (error_union.val) {
|
||||
.err_name => try mod.intern(.{ .undef = payload_ty.toIntern() }),
|
||||
.payload => |payload| payload,
|
||||
}.toValue();
|
||||
|
||||
var constituents: [2]IdRef = undefined;
|
||||
if (eu_layout.error_first) {
|
||||
constituents[0] = try self.constant(err_ty, err_val, .indirect);
|
||||
constituents[1] = try self.constant(payload_ty, payload_val, .indirect);
|
||||
} else {
|
||||
constituents[0] = try self.constant(payload_ty, payload_val, .indirect);
|
||||
constituents[1] = try self.constant(err_ty, err_val, .indirect);
|
||||
}
|
||||
|
||||
const result_id = self.spv.allocId();
|
||||
try self.func.body.emit(self.spv.gpa, .OpCompositeConstruct, .{
|
||||
.id_result_type = self.typeId(result_ty_ref),
|
||||
.id_result = result_id,
|
||||
.constituents = &constituents,
|
||||
});
|
||||
return result_id;
|
||||
},
|
||||
// TODO: We can handle most pointers here (decl refs etc), because now they emit an extra
|
||||
// OpVariable that is not really required.
|
||||
else => {
|
||||
@ -1316,7 +1359,6 @@ pub const DeclGen = struct {
|
||||
const entry = try self.type_map.getOrPut(self.gpa, ty.toIntern());
|
||||
if (entry.found_existing) return entry.value_ptr.ty_ref;
|
||||
|
||||
const ip = &mod.intern_pool;
|
||||
const fn_info = mod.typeToFunc(ty).?;
|
||||
// TODO: Put this somewhere in Sema.zig
|
||||
if (fn_info.is_var_args)
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user