mirror of
https://github.com/ziglang/zig.git
synced 2025-12-26 08:03:08 +00:00
SPIR-V: Compute backing integer bits
This commit is contained in:
parent
de6df2bc12
commit
458c338aeb
@ -2,6 +2,8 @@ const std = @import("std");
|
||||
const Allocator = std.mem.Allocator;
|
||||
const log = std.log.scoped(.codegen);
|
||||
|
||||
const Target = std.Target;
|
||||
|
||||
const spec = @import("spirv/spec.zig");
|
||||
const Module = @import("../Module.zig");
|
||||
const Decl = Module.Decl;
|
||||
@ -63,6 +65,43 @@ pub const DeclGen = struct {
|
||||
return error.AnalysisFail;
|
||||
}
|
||||
|
||||
/// SPIR-V requires enabling specific integer sizes through capabilities, and so if they are not enabled, we need
|
||||
/// to emulate them in other instructions/types. This function returns, given an integer bit width (signed or unsigned, sign
|
||||
/// included), the width of the underlying type which represents it, given the enabled features for the current target.
|
||||
/// If the result is `null`, the largest type the target platform supports natively is not able to perform computations using
|
||||
/// that size. In this case, multiple elements of the largest type should be used.
|
||||
/// The backing type will be chosen as the smallest supported integer larger or equal to it in number of bits.
|
||||
/// The result is valid to be used with OpTypeInt.
|
||||
/// TODO: The extension SPV_INTEL_arbitrary_precision_integers allows any integer size (at least up to 32 bits).
|
||||
/// TODO: This probably needs an ABI-version as well (especially in combination with SPV_INTEL_arbitrary_precision_integers).
|
||||
fn backingIntBits(self: *DeclGen, bits: u32) ?u32 {
|
||||
// TODO: Figure out what to do with u0/i0.
|
||||
std.debug.assert(bits != 0);
|
||||
|
||||
const target = self.module.getTarget();
|
||||
|
||||
// 8, 16 and 64-bit integers require the Int8, Int16 and Inr64 capabilities respectively.
|
||||
const ints = [_]struct{ bits: u32, feature: ?Target.spirv.Feature } {
|
||||
.{ .bits = 8, .feature = .Int8 },
|
||||
.{ .bits = 16, .feature = .Int16 },
|
||||
.{ .bits = 32, .feature = null },
|
||||
.{ .bits = 64, .feature = .Int64 },
|
||||
};
|
||||
|
||||
for (ints) |int| {
|
||||
const has_feature = if (int.feature) |feature|
|
||||
Target.spirv.featureSetHas(target.cpu.features, feature)
|
||||
else
|
||||
true;
|
||||
|
||||
if (bits <= int.bits and has_feature) {
|
||||
return int.bits;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
pub fn getOrGenType(self: *DeclGen, t: Type) !u32 {
|
||||
// We can't use getOrPut here so we can recursively generate types.
|
||||
if (self.types.get(t)) |already_generated| {
|
||||
@ -76,10 +115,12 @@ pub const DeclGen = struct {
|
||||
.Bool => try writeInstruction(&self.spv.types_and_globals, .OpTypeBool, &[_]u32{ result }),
|
||||
.Int => {
|
||||
const int_info = t.intInfo(self.module.getTarget());
|
||||
// TODO: Capabilities.
|
||||
const backing_bits = self.backingIntBits(int_info.bits) orelse
|
||||
return self.fail(.{.node_offset = 0}, "TODO: SPIR-V backend: implement fallback for integer of {} bits", .{ int_info.bits });
|
||||
|
||||
try writeInstruction(&self.spv.types_and_globals, .OpTypeInt, &[_]u32{
|
||||
result,
|
||||
int_info.bits,
|
||||
backing_bits,
|
||||
switch (int_info.signedness) {
|
||||
.unsigned => 0,
|
||||
.signed => 1,
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user