| ... | @@ -373,8 +373,9 @@ const DeclGen = struct { | ... | @@ -373,8 +373,9 @@ const DeclGen = struct { |
| 373 | /// For `composite_integer` this is 0 (TODO) | 373 | /// For `composite_integer` this is 0 (TODO) |
| 374 | backing_bits: u16, | 374 | backing_bits: u16, |
| 375 | | 375 | |
| 376 | /// Whether the type is a vector. | 376 | /// Null if this type is a scalar, or the length |
| 377 | is_vector: bool, | 377 | /// of the vector otherwise. |
| | 378 | vector_len: ?u32, |
| 378 | | 379 | |
| 379 | /// Whether the inner type is signed. Only relevant for integers. | 380 | /// Whether the inner type is signed. Only relevant for integers. |
| 380 | signedness: std.builtin.Signedness, | 381 | signedness: std.builtin.Signedness, |
| ... | @@ -597,32 +598,37 @@ const DeclGen = struct { | ... | @@ -597,32 +598,37 @@ const DeclGen = struct { |
| 597 | return self.backingIntBits(ty) == null; | 598 | return self.backingIntBits(ty) == null; |
| 598 | } | 599 | } |
| 599 | | 600 | |
| 600 | fn arithmeticTypeInfo(self: *DeclGen, ty: Type) !ArithmeticTypeInfo { | 601 | fn arithmeticTypeInfo(self: *DeclGen, ty: Type) ArithmeticTypeInfo { |
| 601 | const mod = self.module; | 602 | const mod = self.module; |
| 602 | const target = self.getTarget(); | 603 | const target = self.getTarget(); |
| 603 | return switch (ty.zigTypeTag(mod)) { | 604 | var scalar_ty = ty.scalarType(mod); |
| | 605 | if (scalar_ty.zigTypeTag(mod) == .Enum) { |
| | 606 | scalar_ty = scalar_ty.intTagType(mod); |
| | 607 | } |
| | 608 | const vector_len = if (ty.isVector(mod)) ty.vectorLen(mod) else null; |
| | 609 | return switch (scalar_ty.zigTypeTag(mod)) { |
| 604 | .Bool => ArithmeticTypeInfo{ | 610 | .Bool => ArithmeticTypeInfo{ |
| 605 | .bits = 1, // Doesn't matter for this class. | 611 | .bits = 1, // Doesn't matter for this class. |
| 606 | .backing_bits = self.backingIntBits(1).?, | 612 | .backing_bits = self.backingIntBits(1).?, |
| 607 | .is_vector = false, | 613 | .vector_len = vector_len, |
| 608 | .signedness = .unsigned, // Technically, but doesn't matter for this class. | 614 | .signedness = .unsigned, // Technically, but doesn't matter for this class. |
| 609 | .class = .bool, | 615 | .class = .bool, |
| 610 | }, | 616 | }, |
| 611 | .Float => ArithmeticTypeInfo{ | 617 | .Float => ArithmeticTypeInfo{ |
| 612 | .bits = ty.floatBits(target), | 618 | .bits = scalar_ty.floatBits(target), |
| 613 | .backing_bits = ty.floatBits(target), // TODO: F80? | 619 | .backing_bits = scalar_ty.floatBits(target), // TODO: F80? |
| 614 | .is_vector = false, | 620 | .vector_len = vector_len, |
| 615 | .signedness = .signed, // Technically, but doesn't matter for this class. | 621 | .signedness = .signed, // Technically, but doesn't matter for this class. |
| 616 | .class = .float, | 622 | .class = .float, |
| 617 | }, | 623 | }, |
| 618 | .Int => blk: { | 624 | .Int => blk: { |
| 619 | const int_info = ty.intInfo(mod); | 625 | const int_info = scalar_ty.intInfo(mod); |
| 620 | // TODO: Maybe it's useful to also return this value. | 626 | // TODO: Maybe it's useful to also return this value. |
| 621 | const maybe_backing_bits = self.backingIntBits(int_info.bits); | 627 | const maybe_backing_bits = self.backingIntBits(int_info.bits); |
| 622 | break :blk ArithmeticTypeInfo{ | 628 | break :blk ArithmeticTypeInfo{ |
| 623 | .bits = int_info.bits, | 629 | .bits = int_info.bits, |
| 624 | .backing_bits = maybe_backing_bits orelse 0, | 630 | .backing_bits = maybe_backing_bits orelse 0, |
| 625 | .is_vector = false, | 631 | .vector_len = vector_len, |
| 626 | .signedness = int_info.signedness, | 632 | .signedness = int_info.signedness, |
| 627 | .class = if (maybe_backing_bits) |backing_bits| | 633 | .class = if (maybe_backing_bits) |backing_bits| |
| 628 | if (backing_bits == int_info.bits) | 634 | if (backing_bits == int_info.bits) |
| ... | @@ -633,22 +639,9 @@ const DeclGen = struct { | ... | @@ -633,22 +639,9 @@ const DeclGen = struct { |
| 633 | .composite_integer, | 639 | .composite_integer, |
| 634 | }; | 640 | }; |
| 635 | }, | 641 | }, |
| 636 | .Enum => return self.arithmeticTypeInfo(ty.intTagType(mod)), | 642 | .Enum => unreachable, |
| 637 | // As of yet, there is no vector support in the self-hosted compiler. | 643 | .Vector => unreachable, |
| 638 | .Vector => blk: { | 644 | else => unreachable, // Unhandled arithmetic type |
| 639 | const child_type = ty.childType(mod); | | |
| 640 | const child_ty_info = try self.arithmeticTypeInfo(child_type); | | |
| 641 | break :blk ArithmeticTypeInfo{ | | |
| 642 | .bits = child_ty_info.bits, | | |
| 643 | .backing_bits = child_ty_info.backing_bits, | | |
| 644 | .is_vector = true, | | |
| 645 | .signedness = child_ty_info.signedness, | | |
| 646 | .class = child_ty_info.class, | | |
| 647 | }; | | |
| 648 | }, | | |
| 649 | // TODO: For which types is this the case? | | |
| 650 | // else => self.todo("implement arithmeticTypeInfo for {}", .{ty.fmt(self.module)}), | | |
| 651 | else => unreachable, | | |
| 652 | }; | 645 | }; |
| 653 | } | 646 | } |
| 654 | | 647 | |
| ... | @@ -2336,7 +2329,7 @@ const DeclGen = struct { | ... | @@ -2336,7 +2329,7 @@ const DeclGen = struct { |
| 2336 | const shift_ty = self.typeOf(bin_op.rhs); | 2329 | const shift_ty = self.typeOf(bin_op.rhs); |
| 2337 | const scalar_shift_ty_ref = try self.resolveType(shift_ty.scalarType(mod), .direct); | 2330 | const scalar_shift_ty_ref = try self.resolveType(shift_ty.scalarType(mod), .direct); |
| 2338 | | 2331 | |
| 2339 | const info = try self.arithmeticTypeInfo(result_ty); | 2332 | const info = self.arithmeticTypeInfo(result_ty); |
| 2340 | switch (info.class) { | 2333 | switch (info.class) { |
| 2341 | .composite_integer => return self.todo("shift ops for composite integers", .{}), | 2334 | .composite_integer => return self.todo("shift ops for composite integers", .{}), |
| 2342 | .integer, .strange_integer => {}, | 2335 | .integer, .strange_integer => {}, |
| ... | @@ -2393,7 +2386,7 @@ const DeclGen = struct { | ... | @@ -2393,7 +2386,7 @@ const DeclGen = struct { |
| 2393 | | 2386 | |
| 2394 | fn minMax(self: *DeclGen, result_ty: Type, op: std.math.CompareOperator, lhs_id: IdRef, rhs_id: IdRef) !IdRef { | 2387 | fn minMax(self: *DeclGen, result_ty: Type, op: std.math.CompareOperator, lhs_id: IdRef, rhs_id: IdRef) !IdRef { |
| 2395 | const result_ty_ref = try self.resolveType(result_ty, .direct); | 2388 | const result_ty_ref = try self.resolveType(result_ty, .direct); |
| 2396 | const info = try self.arithmeticTypeInfo(result_ty); | 2389 | const info = self.arithmeticTypeInfo(result_ty); |
| 2397 | | 2390 | |
| 2398 | // TODO: Use fmin for OpenCL | 2391 | // TODO: Use fmin for OpenCL |
| 2399 | const cmp_id = try self.cmp(op, Type.bool, result_ty, lhs_id, rhs_id); | 2392 | const cmp_id = try self.cmp(op, Type.bool, result_ty, lhs_id, rhs_id); |
| ... | @@ -2516,7 +2509,7 @@ const DeclGen = struct { | ... | @@ -2516,7 +2509,7 @@ const DeclGen = struct { |
| 2516 | ) !IdRef { | 2509 | ) !IdRef { |
| 2517 | // Binary operations are generally applicable to both scalar and vector operations | 2510 | // Binary operations are generally applicable to both scalar and vector operations |
| 2518 | // in SPIR-V, but int and float versions of operations require different opcodes. | 2511 | // in SPIR-V, but int and float versions of operations require different opcodes. |
| 2519 | const info = try self.arithmeticTypeInfo(ty); | 2512 | const info = self.arithmeticTypeInfo(ty); |
| 2520 | | 2513 | |
| 2521 | const opcode_index: usize = switch (info.class) { | 2514 | const opcode_index: usize = switch (info.class) { |
| 2522 | .composite_integer => { | 2515 | .composite_integer => { |
| ... | @@ -2579,7 +2572,7 @@ const DeclGen = struct { | ... | @@ -2579,7 +2572,7 @@ const DeclGen = struct { |
| 2579 | | 2572 | |
| 2580 | const bool_ty_ref = try self.resolveType(Type.bool, .direct); | 2573 | const bool_ty_ref = try self.resolveType(Type.bool, .direct); |
| 2581 | | 2574 | |
| 2582 | const info = try self.arithmeticTypeInfo(operand_ty); | 2575 | const info = self.arithmeticTypeInfo(operand_ty); |
| 2583 | switch (info.class) { | 2576 | switch (info.class) { |
| 2584 | .composite_integer => return self.todo("overflow ops for composite integers", .{}), | 2577 | .composite_integer => return self.todo("overflow ops for composite integers", .{}), |
| 2585 | .strange_integer, .integer => {}, | 2578 | .strange_integer, .integer => {}, |
| ... | @@ -2693,7 +2686,7 @@ const DeclGen = struct { | ... | @@ -2693,7 +2686,7 @@ const DeclGen = struct { |
| 2693 | | 2686 | |
| 2694 | const bool_ty_ref = try self.resolveType(Type.bool, .direct); | 2687 | const bool_ty_ref = try self.resolveType(Type.bool, .direct); |
| 2695 | | 2688 | |
| 2696 | const info = try self.arithmeticTypeInfo(operand_ty); | 2689 | const info = self.arithmeticTypeInfo(operand_ty); |
| 2697 | switch (info.class) { | 2690 | switch (info.class) { |
| 2698 | .composite_integer => return self.todo("overflow shift for composite integers", .{}), | 2691 | .composite_integer => return self.todo("overflow shift for composite integers", .{}), |
| 2699 | .integer, .strange_integer => {}, | 2692 | .integer, .strange_integer => {}, |
| ... | @@ -2777,7 +2770,7 @@ const DeclGen = struct { | ... | @@ -2777,7 +2770,7 @@ const DeclGen = struct { |
| 2777 | const scalar_ty_ref = try self.resolveType(scalar_ty, .direct); | 2770 | const scalar_ty_ref = try self.resolveType(scalar_ty, .direct); |
| 2778 | const scalar_ty_id = self.typeId(scalar_ty_ref); | 2771 | const scalar_ty_id = self.typeId(scalar_ty_ref); |
| 2779 | | 2772 | |
| 2780 | const info = try self.arithmeticTypeInfo(operand_ty); | 2773 | const info = self.arithmeticTypeInfo(operand_ty); |
| 2781 | | 2774 | |
| 2782 | var result_id = try self.extractField(scalar_ty, operand, 0); | 2775 | var result_id = try self.extractField(scalar_ty, operand, 0); |
| 2783 | const len = operand_ty.vectorLen(mod); | 2776 | const len = operand_ty.vectorLen(mod); |
| ... | @@ -3093,7 +3086,7 @@ const DeclGen = struct { | ... | @@ -3093,7 +3086,7 @@ const DeclGen = struct { |
| 3093 | }; | 3086 | }; |
| 3094 | | 3087 | |
| 3095 | const opcode: Opcode = opcode: { | 3088 | const opcode: Opcode = opcode: { |
| 3096 | const info = try self.arithmeticTypeInfo(op_ty); | 3089 | const info = self.arithmeticTypeInfo(op_ty); |
| 3097 | const signedness = switch (info.class) { | 3090 | const signedness = switch (info.class) { |
| 3098 | .composite_integer => { | 3091 | .composite_integer => { |
| 3099 | return self.todo("binary operations for composite integers", .{}); | 3092 | return self.todo("binary operations for composite integers", .{}); |
| ... | @@ -3245,8 +3238,8 @@ const DeclGen = struct { | ... | @@ -3245,8 +3238,8 @@ const DeclGen = struct { |
| 3245 | const dst_ty = self.typeOfIndex(inst); | 3238 | const dst_ty = self.typeOfIndex(inst); |
| 3246 | const dst_ty_ref = try self.resolveType(dst_ty, .direct); | 3239 | const dst_ty_ref = try self.resolveType(dst_ty, .direct); |
| 3247 | | 3240 | |
| 3248 | const src_info = try self.arithmeticTypeInfo(src_ty); | 3241 | const src_info = self.arithmeticTypeInfo(src_ty); |
| 3249 | const dst_info = try self.arithmeticTypeInfo(dst_ty); | 3242 | const dst_info = self.arithmeticTypeInfo(dst_ty); |
| 3250 | | 3243 | |
| 3251 | if (src_info.backing_bits == dst_info.backing_bits) { | 3244 | if (src_info.backing_bits == dst_info.backing_bits) { |
| 3252 | return operand_id; | 3245 | return operand_id; |
| ... | @@ -3302,7 +3295,7 @@ const DeclGen = struct { | ... | @@ -3302,7 +3295,7 @@ const DeclGen = struct { |
| 3302 | const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; | 3295 | const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; |
| 3303 | const operand_ty = self.typeOf(ty_op.operand); | 3296 | const operand_ty = self.typeOf(ty_op.operand); |
| 3304 | const operand_id = try self.resolve(ty_op.operand); | 3297 | const operand_id = try self.resolve(ty_op.operand); |
| 3305 | const operand_info = try self.arithmeticTypeInfo(operand_ty); | 3298 | const operand_info = self.arithmeticTypeInfo(operand_ty); |
| 3306 | const dest_ty = self.typeOfIndex(inst); | 3299 | const dest_ty = self.typeOfIndex(inst); |
| 3307 | const dest_ty_id = try self.resolveTypeId(dest_ty); | 3300 | const dest_ty_id = try self.resolveTypeId(dest_ty); |
| 3308 | | 3301 | |
| ... | @@ -3328,7 +3321,7 @@ const DeclGen = struct { | ... | @@ -3328,7 +3321,7 @@ const DeclGen = struct { |
| 3328 | const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; | 3321 | const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; |
| 3329 | const operand_id = try self.resolve(ty_op.operand); | 3322 | const operand_id = try self.resolve(ty_op.operand); |
| 3330 | const dest_ty = self.typeOfIndex(inst); | 3323 | const dest_ty = self.typeOfIndex(inst); |
| 3331 | const dest_info = try self.arithmeticTypeInfo(dest_ty); | 3324 | const dest_info = self.arithmeticTypeInfo(dest_ty); |
| 3332 | const dest_ty_id = try self.resolveTypeId(dest_ty); | 3325 | const dest_ty_id = try self.resolveTypeId(dest_ty); |
| 3333 | | 3326 | |
| 3334 | const result_id = self.spv.allocId(); | 3327 | const result_id = self.spv.allocId(); |
| ... | @@ -3369,7 +3362,7 @@ const DeclGen = struct { | ... | @@ -3369,7 +3362,7 @@ const DeclGen = struct { |
| 3369 | const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; | 3362 | const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; |
| 3370 | const operand_id = try self.resolve(ty_op.operand); | 3363 | const operand_id = try self.resolve(ty_op.operand); |
| 3371 | const result_ty = self.typeOfIndex(inst); | 3364 | const result_ty = self.typeOfIndex(inst); |
| 3372 | const info = try self.arithmeticTypeInfo(result_ty); | 3365 | const info = self.arithmeticTypeInfo(result_ty); |
| 3373 | | 3366 | |
| 3374 | var wip = try self.elementWise(result_ty); | 3367 | var wip = try self.elementWise(result_ty); |
| 3375 | defer wip.deinit(); | 3368 | defer wip.deinit(); |