authorgravatar for robin@voetter.nlRobin Voetter <robin@voetter.nl> 2021-05-15 14:04:41+02:00
committergravatar for robin@voetter.nlRobin Voetter <robin@voetter.nl> 2021-05-16 14:13:23+02:00
logae2e21639a958b0bc8c085c8eac6733aaa933457
treefd828ba3d5f399b0e01c90eafc96b001d8e0f904
parentcbf5280f54509e7aa58d8fd14258274a12efeee1

SPIR-V: Some initial floating point constant generation


1 files changed, 43 insertions(+), 4 deletions(-)

src/codegen/spirv.zig+43-4
...@@ -143,6 +143,13 @@ pub const DeclGen = struct {...@@ -143,6 +143,13 @@ pub const DeclGen = struct {
143 32;143 32;
144 }144 }
145145
146 /// Checks whether the type is "composite int", an integer consisting of multiple native integers. These are represented by
147 /// arrays of largestSupportedIntBits().
148 /// Asserts `ty` is an integer.
149 fn isCompositeInt(self: *DeclGen, ty: Type) bool {
150 return self.backingIntBits(ty) == null;
151 }
152
146 /// Generate a constant representing `val`.153 /// Generate a constant representing `val`.
147 /// TODO: Deduplication?154 /// TODO: Deduplication?
148 fn genConstant(self: *DeclGen, ty: Type, val: Value) Error!u32 {155 fn genConstant(self: *DeclGen, ty: Type, val: Value) Error!u32 {
...@@ -160,6 +167,37 @@ pub const DeclGen = struct {...@@ -160,6 +167,37 @@ pub const DeclGen = struct {
160 const opcode: spec.Opcode = if (val.toBool()) .OpConstantTrue else .OpConstantFalse;167 const opcode: spec.Opcode = if (val.toBool()) .OpConstantTrue else .OpConstantFalse;
161 try writeInstruction(code, opcode, &[_]u32{ result_type_id, result_id });168 try writeInstruction(code, opcode, &[_]u32{ result_type_id, result_id });
162 },169 },
170 .Float => {
171 // At this point we are guaranteed that the target floating point type is supported, otherwise the function
172 // would have exited at getOrGenType(ty).
173
174 // f16 and f32 require one word of storage. f64 requires 2, low-order first.
175
176 switch (val.tag()) {
177 .float_16 => try writeInstruction(code, .OpConstant, &[_]u32{
178 result_type_id,
179 result_id,
180 @bitCast(u16, val.castTag(.float_16).?.data)
181 }),
182 .float_32 => try writeInstruction(code, .OpConstant, &[_]u32{
183 result_type_id,
184 result_id,
185 @bitCast(u32, val.castTag(.float_32).?.data)
186 }),
187 .float_64 => {
188 const float_bits = @bitCast(u64, val.castTag(.float_64).?.data);
189 try writeInstruction(code, .OpConstant, &[_]u32{
190 result_type_id,
191 result_id,
192 @truncate(u32, float_bits),
193 @truncate(u32, float_bits >> 32),
194 });
195 },
196 .float_128 => unreachable, // Filtered out in the call to getOrGenType.
197 // TODO: What tags do we need to handle here anyway?
198 else => return self.fail(.{.node_offset = 0}, "TODO: SPIR-V backend: float constant generation of value {s}\n", .{ val.tag() }),
199 }
200 },
163 else => return self.fail(.{.node_offset = 0}, "TODO: SPIR-V backend: constant generation of type {s}\n", .{ ty.zigTypeTag() }),201 else => return self.fail(.{.node_offset = 0}, "TODO: SPIR-V backend: constant generation of type {s}\n", .{ ty.zigTypeTag() }),
164 }202 }
165203
...@@ -180,8 +218,10 @@ pub const DeclGen = struct {...@@ -180,8 +218,10 @@ pub const DeclGen = struct {
180 .Void => try writeInstruction(code, .OpTypeVoid, &[_]u32{ result_id }),218 .Void => try writeInstruction(code, .OpTypeVoid, &[_]u32{ result_id }),
181 .Bool => try writeInstruction(code, .OpTypeBool, &[_]u32{ result_id }),219 .Bool => try writeInstruction(code, .OpTypeBool, &[_]u32{ result_id }),
182 .Int => {220 .Int => {
183 const backing_bits = self.backingIntBits(ty) orelse221 const backing_bits = self.backingIntBits(ty) orelse {
184 return self.fail(.{.node_offset = 0}, "TODO: SPIR-V backend: implement fallback for {}", .{ ty });222 // Integers too big for any native type are represented as "composite integers": An array of largestSupportedIntBits.
223 return self.fail(.{.node_offset = 0}, "TODO: SPIR-V backend: implement composite ints {}", .{ ty });
224 };
185225
186 // TODO: If backing_bits != int_info.bits, a duplicate type might be generated here.226 // TODO: If backing_bits != int_info.bits, a duplicate type might be generated here.
187 try writeInstruction(code, .OpTypeInt, &[_]u32{227 try writeInstruction(code, .OpTypeInt, &[_]u32{
...@@ -238,7 +278,7 @@ pub const DeclGen = struct {...@@ -238,7 +278,7 @@ pub const DeclGen = struct {
238 // Although not 100% the same, Zig vectors map quite neatly to SPIR-V vectors (including many integer and float operations278 // Although not 100% the same, Zig vectors map quite neatly to SPIR-V vectors (including many integer and float operations
239 // which work on them), so simply use those.279 // which work on them), so simply use those.
240 // Note: SPIR-V vectors only support bools, ints and floats, so pointer vectors need to be supported another way.280 // Note: SPIR-V vectors only support bools, ints and floats, so pointer vectors need to be supported another way.
241 // "big integers" (larger than the largest supported native type) can probably be represented by an array of vectors.281 // "composite integers" (larger than the largest supported native type) can probably be represented by an array of vectors.
242282
243 // TODO: Vectors are not yet supported by the self-hosted compiler itself it seems.283 // TODO: Vectors are not yet supported by the self-hosted compiler itself it seems.
244 return self.fail(.{.node_offset = 0}, "TODO: SPIR-V backend: implement type Vector", .{});284 return self.fail(.{.node_offset = 0}, "TODO: SPIR-V backend: implement type Vector", .{});
...@@ -310,7 +350,6 @@ pub const DeclGen = struct {...@@ -310,7 +350,6 @@ pub const DeclGen = struct {
310 // TODO: Breakpoints won't be supported in SPIR-V, but the compiler seems to insert them350 // TODO: Breakpoints won't be supported in SPIR-V, but the compiler seems to insert them
311 // throughout the IR.351 // throughout the IR.
312 .breakpoint => null,352 .breakpoint => null,
313 // TODO: What does this entail?
314 .dbg_stmt => null,353 .dbg_stmt => null,
315 .ret => self.genRet(inst.castTag(.ret).?),354 .ret => self.genRet(inst.castTag(.ret).?),
316 .retvoid => self.genRetVoid(),355 .retvoid => self.genRetVoid(),