| ... | ... | @@ -143,6 +143,13 @@ pub const DeclGen = struct { |
| 143 | 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 | 153 | /// Generate a constant representing `val`. |
| 147 | 154 | /// TODO: Deduplication? |
| 148 | 155 | fn genConstant(self: *DeclGen, ty: Type, val: Value) Error!u32 { |
| ... | ... | @@ -160,6 +167,37 @@ pub const DeclGen = struct { |
| 160 | 167 | const opcode: spec.Opcode = if (val.toBool()) .OpConstantTrue else .OpConstantFalse; |
| 161 | 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 | 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 | 218 | .Void => try writeInstruction(code, .OpTypeVoid, &[_]u32{ result_id }), |
| 181 | 219 | .Bool => try writeInstruction(code, .OpTypeBool, &[_]u32{ result_id }), |
| 182 | 220 | .Int => { |
| 183 | | const backing_bits = self.backingIntBits(ty) orelse |
| 184 | | return self.fail(.{.node_offset = 0}, "TODO: SPIR-V backend: implement fallback for {}", .{ ty }); |
| 221 | const backing_bits = self.backingIntBits(ty) orelse { |
| 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 | 226 | // TODO: If backing_bits != int_info.bits, a duplicate type might be generated here. |
| 187 | 227 | try writeInstruction(code, .OpTypeInt, &[_]u32{ |
| ... | ... | @@ -238,7 +278,7 @@ pub const DeclGen = struct { |
| 238 | 278 | // Although not 100% the same, Zig vectors map quite neatly to SPIR-V vectors (including many integer and float operations |
| 239 | 279 | // which work on them), so simply use those. |
| 240 | 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 | 283 | // TODO: Vectors are not yet supported by the self-hosted compiler itself it seems. |
| 244 | 284 | return self.fail(.{.node_offset = 0}, "TODO: SPIR-V backend: implement type Vector", .{}); |
| ... | ... | @@ -310,7 +350,6 @@ pub const DeclGen = struct { |
| 310 | 350 | // TODO: Breakpoints won't be supported in SPIR-V, but the compiler seems to insert them |
| 311 | 351 | // throughout the IR. |
| 312 | 352 | .breakpoint => null, |
| 313 | | // TODO: What does this entail? |
| 314 | 353 | .dbg_stmt => null, |
| 315 | 354 | .ret => self.genRet(inst.castTag(.ret).?), |
| 316 | 355 | .retvoid => self.genRetVoid(), |