| ... | @@ -143,6 +143,13 @@ pub const DeclGen = struct { | ... | @@ -143,6 +143,13 @@ pub const DeclGen = struct { |
| 143 | 32; | 143 | 32; |
| 144 | } | 144 | } |
| 145 | | 145 | |
| | 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 | } |
| 165 | | 203 | |
| ... | @@ -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) orelse | 221 | 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 | }; |
| 185 | | 225 | |
| 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 operations | 278 | // 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. |
| 242 | | 282 | |
| 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 them | 350 | // 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(), |