| ... | @@ -1137,6 +1137,42 @@ fn constBool(cg: *CodeGen, value: bool, repr: Repr) !Id { | ... | @@ -1137,6 +1137,42 @@ fn constBool(cg: *CodeGen, value: bool, repr: Repr) !Id { |
| 1137 | } | 1137 | } |
| 1138 | } | 1138 | } |
| 1139 | | 1139 | |
| | 1140 | /// Returns the OpSwitch literal int corresponding to ref (case of the switch), |
| | 1141 | /// where ty is the type we switch on and words is the width of the literal |
| | 1142 | /// (words = 1 means up to 32 bits, and 2 means 64 bits). |
| | 1143 | fn literalInt(cg: *CodeGen, ty: Type, words: u32, ref: Air.Inst.Ref) spec.LiteralContextDependentNumber { |
| | 1144 | const zcu = cg.zcu; |
| | 1145 | const target = cg.zcu.getTarget(); |
| | 1146 | |
| | 1147 | var int_ty: Type = ty; |
| | 1148 | var value: Value = .fromInterned(ref.toInterned().?); |
| | 1149 | const int_val: u64 = blk: switch (int_ty.zigTypeTag(zcu)) { |
| | 1150 | .bool, .int => if (int_ty.isSignedInt(zcu)) switch (target.os.tag) { |
| | 1151 | // Kernel only supports unsigned ints, so use the unsigned backing type. |
| | 1152 | .opencl, .amdhsa => switch (cg.backingIntBits(int_ty.intInfo(zcu).bits).@"0") { |
| | 1153 | inline 8, 16, 32, 64 => |bits| @as(@Int(.unsigned, bits), @truncate(@as(u64, @bitCast(value.toSignedInt(zcu))))), |
| | 1154 | else => unreachable, |
| | 1155 | }, |
| | 1156 | else => @bitCast(value.toSignedInt(zcu)), |
| | 1157 | } else value.toUnsignedInt(zcu), |
| | 1158 | .@"enum" => { |
| | 1159 | // Handle proper backingInt conversion in the .int case. |
| | 1160 | int_ty = int_ty.backingIntType(zcu); |
| | 1161 | value = value.backingInt(zcu); |
| | 1162 | continue :blk .int; |
| | 1163 | }, |
| | 1164 | .error_set => value.getErrorInt(zcu), |
| | 1165 | .pointer => value.toUnsignedInt(zcu), |
| | 1166 | else => unreachable, |
| | 1167 | }; |
| | 1168 | |
| | 1169 | return switch (words) { |
| | 1170 | 1 => .{ .uint32 = @truncate(int_val) }, |
| | 1171 | 2 => .{ .uint64 = int_val }, |
| | 1172 | else => unreachable, |
| | 1173 | }; |
| | 1174 | } |
| | 1175 | |
| 1140 | /// Emits an integer constant. | 1176 | /// Emits an integer constant. |
| 1141 | /// This function, unlike cg.constInt, takes care to bitcast | 1177 | /// This function, unlike cg.constInt, takes care to bitcast |
| 1142 | /// the value to an unsigned int first for Kernels. | 1178 | /// the value to an unsigned int first for Kernels. |
| ... | @@ -7864,19 +7900,7 @@ fn airSwitchBr(cg: *CodeGen, inst: Air.Inst.Index) !void { | ... | @@ -7864,19 +7900,7 @@ fn airSwitchBr(cg: *CodeGen, inst: Air.Inst.Index) !void { |
| 7864 | const label = case_labels.at(case.idx); | 7900 | const label = case_labels.at(case.idx); |
| 7865 | | 7901 | |
| 7866 | for (case.items) |item| { | 7902 | for (case.items) |item| { |
| 7867 | const value: Value = .fromInterned(item.toInterned().?); | 7903 | const int_lit = cg.literalInt(cond_ty, cond_words, item); |
| 7868 | const int_val: u64 = switch (cond_ty.zigTypeTag(zcu)) { | | |
| 7869 | .bool, .int => if (cond_ty.isSignedInt(zcu)) @bitCast(value.toSignedInt(zcu)) else value.toUnsignedInt(zcu), | | |
| 7870 | .@"enum" => value.backingInt(zcu).toUnsignedInt(zcu), | | |
| 7871 | .error_set => value.getErrorInt(zcu), | | |
| 7872 | .pointer => value.toUnsignedInt(zcu), | | |
| 7873 | else => unreachable, | | |
| 7874 | }; | | |
| 7875 | const int_lit: spec.LiteralContextDependentNumber = switch (cond_words) { | | |
| 7876 | 1 => .{ .uint32 = @intCast(int_val) }, | | |
| 7877 | 2 => .{ .uint64 = int_val }, | | |
| 7878 | else => unreachable, | | |
| 7879 | }; | | |
| 7880 | cg.body.writeOperand(spec.LiteralContextDependentNumber, int_lit); | 7904 | cg.body.writeOperand(spec.LiteralContextDependentNumber, int_lit); |
| 7881 | cg.body.writeOperand(Id, label); | 7905 | cg.body.writeOperand(Id, label); |
| 7882 | } | 7906 | } |
| ... | @@ -8098,25 +8122,16 @@ fn airLoopSwitchBr(cg: *CodeGen, inst: Air.Inst.Index) !void { | ... | @@ -8098,25 +8122,16 @@ fn airLoopSwitchBr(cg: *CodeGen, inst: Air.Inst.Index) !void { |
| 8098 | cg.body.writeOperand(Id, cond_indirect); | 8122 | cg.body.writeOperand(Id, cond_indirect); |
| 8099 | cg.body.writeOperand(Id, switch_default); | 8123 | cg.body.writeOperand(Id, switch_default); |
| 8100 | | 8124 | |
| | 8125 | // Emit the non-range cases into the OpSwitch. |
| | 8126 | // Cases with ranges are handled by the conditional chain below. |
| 8101 | { | 8127 | { |
| 8102 | var it = switch_br.iterateCases(); | 8128 | var it = switch_br.iterateCases(); |
| 8103 | while (it.next()) |case| { | 8129 | while (it.next()) |case| { |
| 8104 | if (case.ranges.len > 0) continue; | 8130 | if (case.ranges.len > 0) continue; |
| 8105 | const label = case_labels.at(case.idx); | 8131 | const label = case_labels.at(case.idx); |
| | 8132 | |
| 8106 | for (case.items) |item| { | 8133 | for (case.items) |item| { |
| 8107 | const value: Value = .fromInterned(item.toInterned().?); | 8134 | const int_lit = cg.literalInt(cond_ty, cond_words, item); |
| 8108 | const int_val: u64 = switch (cond_ty.zigTypeTag(zcu)) { | | |
| 8109 | .bool, .int => if (cond_ty.isSignedInt(zcu)) @bitCast(value.toSignedInt(zcu)) else value.toUnsignedInt(zcu), | | |
| 8110 | .@"enum" => value.backingInt(zcu).toUnsignedInt(zcu), | | |
| 8111 | .error_set => value.getErrorInt(zcu), | | |
| 8112 | .pointer => value.toUnsignedInt(zcu), | | |
| 8113 | else => unreachable, | | |
| 8114 | }; | | |
| 8115 | const int_lit: spec.LiteralContextDependentNumber = switch (cond_words) { | | |
| 8116 | 1 => .{ .uint32 = @intCast(int_val) }, | | |
| 8117 | 2 => .{ .uint64 = int_val }, | | |
| 8118 | else => unreachable, | | |
| 8119 | }; | | |
| 8120 | cg.body.writeOperand(spec.LiteralContextDependentNumber, int_lit); | 8135 | cg.body.writeOperand(spec.LiteralContextDependentNumber, int_lit); |
| 8121 | cg.body.writeOperand(Id, label); | 8136 | cg.body.writeOperand(Id, label); |
| 8122 | } | 8137 | } |