authorgravatar for alichraghi@proton.meAli Chraghi <alichraghi@proton.me> 2025-08-03 11:14:10+03:30
committergravatar for alichraghi@proton.meAli Chraghi <alichraghi@proton.me> 2025-08-03 12:10:23+03:30
log58b9200106c0eb721a13aea13e4ce55c4c0e340b
tree2655ca20b6cd6cee165700e37cff50b29c679072
parentd15a7b1b219b7f0b9ab9b870fb051005e3890a37
signaturelock-open Commit is signed but in an unrecognized format.

spirv: use packed struct's backing int type for shift value


2 files changed, 207 insertions(+), 328 deletions(-)

src/arch/spirv/CodeGen.zig+202-326
......@@ -431,15 +431,12 @@ fn resolveUav(cg: *CodeGen, val: InternPool.Index) !Id {
431431 const zcu = cg.module.zcu;
432432 const ty: Type = .fromInterned(zcu.intern_pool.typeOf(val));
433433 const ty_id = try cg.resolveType(ty, .indirect);
434 const decl_ptr_ty_id = try cg.module.ptrType(ty_id, cg.module.storageClass(.generic));
435434
436435 const spv_decl_index = blk: {
437436 const entry = try cg.module.uav_link.getOrPut(cg.module.gpa, .{ val, .function });
438437 if (entry.found_existing) {
439438 try cg.addFunctionDep(entry.value_ptr.*, .function);
440
441 const result_id = cg.module.declPtr(entry.value_ptr.*).result_id;
442 return try cg.castToGeneric(decl_ptr_ty_id, result_id);
439 return cg.module.declPtr(entry.value_ptr.*).result_id;
443440 }
444441
445442 const spv_decl_index = try cg.module.allocDecl(.invocation_global);
......@@ -520,7 +517,7 @@ fn resolveUav(cg: *CodeGen, val: InternPool.Index) !Id {
520517 });
521518 }
522519
523 return try cg.castToGeneric(decl_ptr_ty_id, result_id);
520 return result_id;
524521}
525522
526523fn addFunctionDep(cg: *CodeGen, decl_index: Module.Decl.Index, storage_class: StorageClass) !void {
......@@ -535,21 +532,6 @@ fn addFunctionDep(cg: *CodeGen, decl_index: Module.Decl.Index, storage_class: St
535532 }
536533}
537534
538fn castToGeneric(cg: *CodeGen, type_id: Id, ptr_id: Id) !Id {
539 const target = cg.module.zcu.getTarget();
540 if (target.cpu.has(.spirv, .generic_pointer)) {
541 const result_id = cg.module.allocId();
542 try cg.body.emit(cg.module.gpa, .OpPtrCastToGeneric, .{
543 .id_result_type = type_id,
544 .id_result = result_id,
545 .pointer = ptr_id,
546 });
547 return result_id;
548 }
549
550 return ptr_id;
551}
552
553535/// Start a new SPIR-V block, Emits the label of the new block, and stores which
554536/// block we are currently generating.
555537/// Note that there is no such thing as nested blocks like in ZIR or AIR, so we don't need to
......@@ -1209,11 +1191,7 @@ fn constantNavRef(cg: *CodeGen, ty: Type, nav_index: InternPool.Nav.Index) !Id {
12091191
12101192 const spv_decl_index = try cg.module.resolveNav(ip, nav_index);
12111193 const spv_decl = cg.module.declPtr(spv_decl_index);
1212
1213 const decl_id = switch (spv_decl.kind) {
1214 .func => unreachable, // TODO: Is this possible?
1215 .global, .invocation_global => spv_decl.result_id,
1216 };
1194 assert(spv_decl.kind != .func);
12171195
12181196 const storage_class = cg.module.storageClass(nav.getAddrspace());
12191197 try cg.addFunctionDep(spv_decl_index, storage_class);
......@@ -1221,23 +1199,18 @@ fn constantNavRef(cg: *CodeGen, ty: Type, nav_index: InternPool.Nav.Index) !Id {
12211199 const nav_ty_id = try cg.resolveType(nav_ty, .indirect);
12221200 const decl_ptr_ty_id = try cg.module.ptrType(nav_ty_id, storage_class);
12231201
1224 const ptr_id = switch (storage_class) {
1225 .generic => try cg.castToGeneric(decl_ptr_ty_id, decl_id),
1226 else => decl_id,
1227 };
1228
12291202 if (decl_ptr_ty_id != ty_id) {
12301203 // Differing pointer types, insert a cast.
12311204 const casted_ptr_id = cg.module.allocId();
12321205 try cg.body.emit(cg.module.gpa, .OpBitcast, .{
12331206 .id_result_type = ty_id,
12341207 .id_result = casted_ptr_id,
1235 .operand = ptr_id,
1208 .operand = spv_decl.result_id,
12361209 });
12371210 return casted_ptr_id;
1238 } else {
1239 return ptr_id;
12401211 }
1212
1213 return spv_decl.result_id;
12411214}
12421215
12431216// Turn a Zig type's name into a cache reference.
......@@ -2120,28 +2093,7 @@ fn buildSelect(cg: *CodeGen, condition: Temporary, lhs: Temporary, rhs: Temporar
21202093 return v.finalize(result_ty, results);
21212094}
21222095
2123const CmpPredicate = enum {
2124 l_eq,
2125 l_ne,
2126 i_ne,
2127 i_eq,
2128 s_lt,
2129 s_gt,
2130 s_le,
2131 s_ge,
2132 u_lt,
2133 u_gt,
2134 u_le,
2135 u_ge,
2136 f_oeq,
2137 f_une,
2138 f_olt,
2139 f_ole,
2140 f_ogt,
2141 f_oge,
2142};
2143
2144fn buildCmp(cg: *CodeGen, pred: CmpPredicate, lhs: Temporary, rhs: Temporary) !Temporary {
2096fn buildCmp(cg: *CodeGen, opcode: Opcode, lhs: Temporary, rhs: Temporary) !Temporary {
21452097 const v = cg.vectorization(.{ lhs, rhs });
21462098 const ops = v.components();
21472099 const results = cg.module.allocIds(ops);
......@@ -2153,27 +2105,6 @@ fn buildCmp(cg: *CodeGen, pred: CmpPredicate, lhs: Temporary, rhs: Temporary) !T
21532105 const op_lhs = try v.prepare(cg, lhs);
21542106 const op_rhs = try v.prepare(cg, rhs);
21552107
2156 const opcode: Opcode = switch (pred) {
2157 .l_eq => .OpLogicalEqual,
2158 .l_ne => .OpLogicalNotEqual,
2159 .i_eq => .OpIEqual,
2160 .i_ne => .OpINotEqual,
2161 .s_lt => .OpSLessThan,
2162 .s_gt => .OpSGreaterThan,
2163 .s_le => .OpSLessThanEqual,
2164 .s_ge => .OpSGreaterThanEqual,
2165 .u_lt => .OpULessThan,
2166 .u_gt => .OpUGreaterThan,
2167 .u_le => .OpULessThanEqual,
2168 .u_ge => .OpUGreaterThanEqual,
2169 .f_oeq => .OpFOrdEqual,
2170 .f_une => .OpFUnordNotEqual,
2171 .f_olt => .OpFOrdLessThan,
2172 .f_ole => .OpFOrdLessThanEqual,
2173 .f_ogt => .OpFOrdGreaterThan,
2174 .f_oge => .OpFOrdGreaterThanEqual,
2175 };
2176
21772108 for (0..ops) |i| {
21782109 try cg.body.emitRaw(cg.module.gpa, opcode, 4);
21792110 cg.body.writeOperand(Id, op_result_ty_id);
......@@ -2278,7 +2209,10 @@ fn buildUnary(cg: *CodeGen, op: UnaryOp, operand: Temporary) !Temporary {
22782209 .log,
22792210 .log2,
22802211 .log10,
2281 => return cg.todo("implement unary operation '{s}' for {s} os", .{ @tagName(op), @tagName(target.os.tag) }),
2212 => return cg.todo(
2213 "implement unary operation '{s}' for {s} os",
2214 .{ @tagName(op), @tagName(target.os.tag) },
2215 ),
22822216 else => unreachable,
22832217 },
22842218 else => unreachable,
......@@ -2298,40 +2232,8 @@ fn buildUnary(cg: *CodeGen, op: UnaryOp, operand: Temporary) !Temporary {
22982232 return v.finalize(result_ty, results);
22992233}
23002234
2301const BinaryOp = enum {
2302 i_add,
2303 f_add,
2304 i_sub,
2305 f_sub,
2306 i_mul,
2307 f_mul,
2308 s_div,
2309 u_div,
2310 f_div,
2311 s_rem,
2312 f_rem,
2313 s_mod,
2314 u_mod,
2315 f_mod,
2316 srl,
2317 sra,
2318 sll,
2319 bit_and,
2320 bit_or,
2321 bit_xor,
2322 f_max,
2323 s_max,
2324 u_max,
2325 f_min,
2326 s_min,
2327 u_min,
2328 l_and,
2329 l_or,
2330};
2331
2332fn buildBinary(cg: *CodeGen, op: BinaryOp, lhs: Temporary, rhs: Temporary) !Temporary {
2235fn buildBinary(cg: *CodeGen, opcode: Opcode, lhs: Temporary, rhs: Temporary) !Temporary {
23332236 const zcu = cg.module.zcu;
2334 const target = cg.module.zcu.getTarget();
23352237
23362238 const v = cg.vectorization(.{ lhs, rhs });
23372239 const ops = v.components();
......@@ -2344,73 +2246,12 @@ fn buildBinary(cg: *CodeGen, op: BinaryOp, lhs: Temporary, rhs: Temporary) !Temp
23442246 const op_lhs = try v.prepare(cg, lhs);
23452247 const op_rhs = try v.prepare(cg, rhs);
23462248
2347 if (switch (op) {
2348 .i_add => .OpIAdd,
2349 .f_add => .OpFAdd,
2350 .i_sub => .OpISub,
2351 .f_sub => .OpFSub,
2352 .i_mul => .OpIMul,
2353 .f_mul => .OpFMul,
2354 .s_div => .OpSDiv,
2355 .u_div => .OpUDiv,
2356 .f_div => .OpFDiv,
2357 .s_rem => .OpSRem,
2358 .f_rem => .OpFRem,
2359 .s_mod => .OpSMod,
2360 .u_mod => .OpUMod,
2361 .f_mod => .OpFMod,
2362 .srl => .OpShiftRightLogical,
2363 .sra => .OpShiftRightArithmetic,
2364 .sll => .OpShiftLeftLogical,
2365 .bit_and => .OpBitwiseAnd,
2366 .bit_or => .OpBitwiseOr,
2367 .bit_xor => .OpBitwiseXor,
2368 .l_and => .OpLogicalAnd,
2369 .l_or => .OpLogicalOr,
2370 else => @as(?Opcode, null),
2371 }) |opcode| {
2372 for (0..ops) |i| {
2373 try cg.body.emitRaw(cg.module.gpa, opcode, 4);
2374 cg.body.writeOperand(Id, op_result_ty_id);
2375 cg.body.writeOperand(Id, results.at(i));
2376 cg.body.writeOperand(Id, op_lhs.at(i));
2377 cg.body.writeOperand(Id, op_rhs.at(i));
2378 }
2379 } else {
2380 const set = try cg.importExtendedSet();
2381
2382 // TODO: Put these numbers in some definition
2383 const extinst: u32 = switch (target.os.tag) {
2384 .opencl => switch (op) {
2385 .f_max => 27, // fmax
2386 .s_max => 156, // s_max
2387 .u_max => 157, // u_max
2388 .f_min => 28, // fmin
2389 .s_min => 158, // s_min
2390 .u_min => 159, // u_min
2391 else => unreachable,
2392 },
2393 .vulkan, .opengl => switch (op) {
2394 .f_max => 40, // FMax
2395 .s_max => 42, // SMax
2396 .u_max => 41, // UMax
2397 .f_min => 37, // FMin
2398 .s_min => 39, // SMin
2399 .u_min => 38, // UMin
2400 else => unreachable,
2401 },
2402 else => unreachable,
2403 };
2404
2405 for (0..ops) |i| {
2406 try cg.body.emit(cg.module.gpa, .OpExtInst, .{
2407 .id_result_type = op_result_ty_id,
2408 .id_result = results.at(i),
2409 .set = set,
2410 .instruction = .{ .inst = extinst },
2411 .id_ref_4 = &.{ op_lhs.at(i), op_rhs.at(i) },
2412 });
2413 }
2249 for (0..ops) |i| {
2250 try cg.body.emitRaw(cg.module.gpa, opcode, 4);
2251 cg.body.writeOperand(Id, op_result_ty_id);
2252 cg.body.writeOperand(Id, results.at(i));
2253 cg.body.writeOperand(Id, op_lhs.at(i));
2254 cg.body.writeOperand(Id, op_rhs.at(i));
24142255 }
24152256
24162257 return v.finalize(result_ty, results);
......@@ -2420,10 +2261,7 @@ fn buildBinary(cg: *CodeGen, op: BinaryOp, lhs: Temporary, rhs: Temporary) !Temp
24202261/// or OpIMul and s_mul_hi or u_mul_hi on OpenCL.
24212262fn buildWideMul(
24222263 cg: *CodeGen,
2423 op: enum {
2424 s_mul_extended,
2425 u_mul_extended,
2426 },
2264 signedness: std.builtin.Signedness,
24272265 lhs: Temporary,
24282266 rhs: Temporary,
24292267) !struct { Temporary, Temporary } {
......@@ -2450,9 +2288,9 @@ fn buildWideMul(
24502288 // OpUMulExtended. For these we will use the OpenCL s_mul_hi to compute the high-order bits
24512289 // instead.
24522290 const set = try cg.importExtendedSet();
2453 const overflow_inst: u32 = switch (op) {
2454 .s_mul_extended => 160, // s_mul_hi
2455 .u_mul_extended => 203, // u_mul_hi
2291 const overflow_inst: u32 = switch (signedness) {
2292 .signed => 160, // s_mul_hi
2293 .unsigned => 203, // u_mul_hi
24562294 };
24572295
24582296 for (0..ops) |i| {
......@@ -2481,9 +2319,9 @@ fn buildWideMul(
24812319 }));
24822320 const op_result_ty_id = try cg.resolveType(op_result_ty, .direct);
24832321
2484 const opcode: Opcode = switch (op) {
2485 .s_mul_extended => .OpSMulExtended,
2486 .u_mul_extended => .OpUMulExtended,
2322 const opcode: Opcode = switch (signedness) {
2323 .signed => .OpSMulExtended,
2324 .unsigned => .OpUMulExtended,
24872325 };
24882326
24892327 for (0..ops) |i| {
......@@ -2718,7 +2556,7 @@ fn convertToDirect(cg: *CodeGen, ty: Type, operand_id: Id) !Id {
27182556 };
27192557
27202558 const result = try cg.buildCmp(
2721 .i_ne,
2559 .OpINotEqual,
27222560 Temporary.init(operand_ty, operand_id),
27232561 Temporary.init(.u1, false_id),
27242562 );
......@@ -2817,9 +2655,9 @@ fn genInst(cg: *CodeGen, inst: Air.Inst.Index) Error!void {
28172655 const air_tags = cg.air.instructions.items(.tag);
28182656 const maybe_result_id: ?Id = switch (air_tags[@intFromEnum(inst)]) {
28192657 // zig fmt: off
2820 .add, .add_wrap, .add_optimized => try cg.airArithOp(inst, .f_add, .i_add, .i_add),
2821 .sub, .sub_wrap, .sub_optimized => try cg.airArithOp(inst, .f_sub, .i_sub, .i_sub),
2822 .mul, .mul_wrap, .mul_optimized => try cg.airArithOp(inst, .f_mul, .i_mul, .i_mul),
2658 .add, .add_wrap, .add_optimized => try cg.airArithOp(inst, .OpFAdd, .OpIAdd, .OpIAdd),
2659 .sub, .sub_wrap, .sub_optimized => try cg.airArithOp(inst, .OpFSub, .OpISub, .OpISub),
2660 .mul, .mul_wrap, .mul_optimized => try cg.airArithOp(inst, .OpFMul, .OpIMul, .OpIMul),
28232661
28242662 .sqrt => try cg.airUnOpSimple(inst, .sqrt),
28252663 .sin => try cg.airUnOpSimple(inst, .sin),
......@@ -2837,15 +2675,15 @@ fn genInst(cg: *CodeGen, inst: Air.Inst.Index) Error!void {
28372675 .trunc_float => try cg.airUnOpSimple(inst, .trunc),
28382676 .neg, .neg_optimized => try cg.airUnOpSimple(inst, .f_neg),
28392677
2840 .div_float, .div_float_optimized => try cg.airArithOp(inst, .f_div, .s_div, .u_div),
2678 .div_float, .div_float_optimized => try cg.airArithOp(inst, .OpFDiv, .OpSDiv, .OpUDiv),
28412679 .div_floor, .div_floor_optimized => try cg.airDivFloor(inst),
28422680 .div_trunc, .div_trunc_optimized => try cg.airDivTrunc(inst),
28432681
2844 .rem, .rem_optimized => try cg.airArithOp(inst, .f_rem, .s_rem, .u_mod),
2845 .mod, .mod_optimized => try cg.airArithOp(inst, .f_mod, .s_mod, .u_mod),
2682 .rem, .rem_optimized => try cg.airArithOp(inst, .OpFRem, .OpSRem, .OpUMod),
2683 .mod, .mod_optimized => try cg.airArithOp(inst, .OpFMod, .OpSMod, .OpUMod),
28462684
2847 .add_with_overflow => try cg.airAddSubOverflow(inst, .i_add, .u_lt, .s_lt),
2848 .sub_with_overflow => try cg.airAddSubOverflow(inst, .i_sub, .u_gt, .s_gt),
2685 .add_with_overflow => try cg.airAddSubOverflow(inst, .OpIAdd, .OpULessThan, .OpSLessThan),
2686 .sub_with_overflow => try cg.airAddSubOverflow(inst, .OpISub, .OpUGreaterThan, .OpSGreaterThan),
28492687 .mul_with_overflow => try cg.airMulOverflow(inst),
28502688 .shl_with_overflow => try cg.airShlOverflow(inst),
28512689
......@@ -2864,14 +2702,14 @@ fn genInst(cg: *CodeGen, inst: Air.Inst.Index) Error!void {
28642702 .ptr_add => try cg.airPtrAdd(inst),
28652703 .ptr_sub => try cg.airPtrSub(inst),
28662704
2867 .bit_and => try cg.airBinOpSimple(inst, .bit_and),
2868 .bit_or => try cg.airBinOpSimple(inst, .bit_or),
2869 .xor => try cg.airBinOpSimple(inst, .bit_xor),
2870 .bool_and => try cg.airBinOpSimple(inst, .l_and),
2871 .bool_or => try cg.airBinOpSimple(inst, .l_or),
2705 .bit_and => try cg.airBinOpSimple(inst, .OpBitwiseAnd),
2706 .bit_or => try cg.airBinOpSimple(inst, .OpBitwiseOr),
2707 .xor => try cg.airBinOpSimple(inst, .OpBitwiseXor),
2708 .bool_and => try cg.airBinOpSimple(inst, .OpLogicalAnd),
2709 .bool_or => try cg.airBinOpSimple(inst, .OpLogicalOr),
28722710
2873 .shl, .shl_exact => try cg.airShift(inst, .sll, .sll),
2874 .shr, .shr_exact => try cg.airShift(inst, .srl, .sra),
2711 .shl, .shl_exact => try cg.airShift(inst, .OpShiftLeftLogical, .OpShiftLeftLogical),
2712 .shr, .shr_exact => try cg.airShift(inst, .OpShiftRightLogical, .OpShiftRightArithmetic),
28752713
28762714 .min => try cg.airMinMax(inst, .min),
28772715 .max => try cg.airMinMax(inst, .max),
......@@ -2983,7 +2821,7 @@ fn genInst(cg: *CodeGen, inst: Air.Inst.Index) Error!void {
29832821 try cg.inst_results.putNoClobber(gpa, inst, result_id);
29842822}
29852823
2986fn airBinOpSimple(cg: *CodeGen, inst: Air.Inst.Index, op: BinaryOp) !?Id {
2824fn airBinOpSimple(cg: *CodeGen, inst: Air.Inst.Index, op: Opcode) !?Id {
29872825 const bin_op = cg.air.instructions.items(.data)[@intFromEnum(inst)].bin_op;
29882826 const lhs = try cg.temporary(bin_op.lhs);
29892827 const rhs = try cg.temporary(bin_op.rhs);
......@@ -2992,7 +2830,7 @@ fn airBinOpSimple(cg: *CodeGen, inst: Air.Inst.Index, op: BinaryOp) !?Id {
29922830 return try result.materialize(cg);
29932831}
29942832
2995fn airShift(cg: *CodeGen, inst: Air.Inst.Index, unsigned: BinaryOp, signed: BinaryOp) !?Id {
2833fn airShift(cg: *CodeGen, inst: Air.Inst.Index, unsigned: Opcode, signed: Opcode) !?Id {
29962834 const zcu = cg.module.zcu;
29972835 const bin_op = cg.air.instructions.items(.data)[@intFromEnum(inst)].bin_op;
29982836
......@@ -3042,28 +2880,77 @@ fn airMinMax(cg: *CodeGen, inst: Air.Inst.Index, op: MinMax) !?Id {
30422880}
30432881
30442882fn minMax(cg: *CodeGen, lhs: Temporary, rhs: Temporary, op: MinMax) !Temporary {
2883 const zcu = cg.module.zcu;
2884 const target = zcu.getTarget();
30452885 const info = cg.arithmeticTypeInfo(lhs.ty);
30462886
3047 const binop: BinaryOp = switch (info.class) {
3048 .float => switch (op) {
3049 .min => .f_min,
3050 .max => .f_max,
2887 const v = cg.vectorization(.{ lhs, rhs });
2888 const ops = v.components();
2889 const results = cg.module.allocIds(ops);
2890
2891 const op_result_ty = lhs.ty.scalarType(zcu);
2892 const op_result_ty_id = try cg.resolveType(op_result_ty, .direct);
2893 const result_ty = try v.resultType(cg, lhs.ty);
2894
2895 const op_lhs = try v.prepare(cg, lhs);
2896 const op_rhs = try v.prepare(cg, rhs);
2897
2898 const ext_inst: u32 = switch (target.os.tag) {
2899 .opencl => switch (info.class) {
2900 .float => switch (op) {
2901 .min => 28, // fmin
2902 .max => 27, // fmax
2903 },
2904 .integer,
2905 .strange_integer,
2906 .composite_integer,
2907 => switch (info.signedness) {
2908 .signed => switch (op) {
2909 .min => 158, // s_min
2910 .max => 156, // s_max
2911 },
2912 .unsigned => switch (op) {
2913 .min => 159, // u_min
2914 .max => 157, // u_max
2915 },
2916 },
2917 .bool => unreachable,
30512918 },
3052 .integer, .strange_integer => switch (info.signedness) {
3053 .signed => switch (op) {
3054 .min => .s_min,
3055 .max => .s_max,
2919 .vulkan, .opengl => switch (info.class) {
2920 .float => switch (op) {
2921 .min => 37, // FMin
2922 .max => 40, // FMax
30562923 },
3057 .unsigned => switch (op) {
3058 .min => .u_min,
3059 .max => .u_max,
2924 .integer,
2925 .strange_integer,
2926 .composite_integer,
2927 => switch (info.signedness) {
2928 .signed => switch (op) {
2929 .min => 39, // SMin
2930 .max => 42, // SMax
2931 },
2932 .unsigned => switch (op) {
2933 .min => 38, // UMin
2934 .max => 41, // UMax
2935 },
30602936 },
2937 .bool => unreachable,
30612938 },
3062 .composite_integer => unreachable, // TODO
3063 .bool => unreachable,
2939 else => unreachable,
30642940 };
30652941
3066 return try cg.buildBinary(binop, lhs, rhs);
2942 const set = try cg.importExtendedSet();
2943 for (0..ops) |i| {
2944 try cg.body.emit(cg.module.gpa, .OpExtInst, .{
2945 .id_result_type = op_result_ty_id,
2946 .id_result = results.at(i),
2947 .set = set,
2948 .instruction = .{ .inst = ext_inst },
2949 .id_ref_4 = &.{ op_lhs.at(i), op_rhs.at(i) },
2950 });
2951 }
2952
2953 return v.finalize(result_ty, results);
30672954}
30682955
30692956/// This function normalizes values to a canonical representation
......@@ -3083,14 +2970,14 @@ fn normalize(cg: *CodeGen, value: Temporary, info: ArithmeticTypeInfo) !Temporar
30832970 .unsigned => {
30842971 const mask_value = if (info.bits == 64) 0xFFFF_FFFF_FFFF_FFFF else (@as(u64, 1) << @as(u6, @intCast(info.bits))) - 1;
30852972 const mask_id = try cg.constInt(ty.scalarType(zcu), mask_value);
3086 return try cg.buildBinary(.bit_and, value, Temporary.init(ty.scalarType(zcu), mask_id));
2973 return try cg.buildBinary(.OpBitwiseAnd, value, Temporary.init(ty.scalarType(zcu), mask_id));
30872974 },
30882975 .signed => {
30892976 // Shift left and right so that we can copy the sight bit that way.
30902977 const shift_amt_id = try cg.constInt(ty.scalarType(zcu), info.backing_bits - info.bits);
30912978 const shift_amt: Temporary = .init(ty.scalarType(zcu), shift_amt_id);
3092 const left = try cg.buildBinary(.sll, value, shift_amt);
3093 return try cg.buildBinary(.sra, left, shift_amt);
2979 const left = try cg.buildBinary(.OpShiftLeftLogical, value, shift_amt);
2980 return try cg.buildBinary(.OpShiftRightArithmetic, left, shift_amt);
30942981 },
30952982 },
30962983 }
......@@ -3108,7 +2995,7 @@ fn airDivFloor(cg: *CodeGen, inst: Air.Inst.Index) !?Id {
31082995 .integer, .strange_integer => {
31092996 switch (info.signedness) {
31102997 .unsigned => {
3111 const result = try cg.buildBinary(.u_div, lhs, rhs);
2998 const result = try cg.buildBinary(.OpUDiv, lhs, rhs);
31122999 return try result.materialize(cg);
31133000 },
31143001 .signed => {},
......@@ -3118,26 +3005,26 @@ fn airDivFloor(cg: *CodeGen, inst: Air.Inst.Index) !?Id {
31183005 // (a / b) - (a % b != 0 && a < 0 != b < 0);
31193006 // There shouldn't be any overflow issues.
31203007
3121 const div = try cg.buildBinary(.s_div, lhs, rhs);
3122 const rem = try cg.buildBinary(.s_rem, lhs, rhs);
3008 const div = try cg.buildBinary(.OpSDiv, lhs, rhs);
3009 const rem = try cg.buildBinary(.OpSRem, lhs, rhs);
31233010
31243011 const zero: Temporary = .init(lhs.ty, try cg.constInt(lhs.ty, 0));
31253012
3126 const rem_is_not_zero = try cg.buildCmp(.i_ne, rem, zero);
3013 const rem_is_not_zero = try cg.buildCmp(.OpINotEqual, rem, zero);
31273014
31283015 const result_negative = try cg.buildCmp(
3129 .l_ne,
3130 try cg.buildCmp(.s_lt, lhs, zero),
3131 try cg.buildCmp(.s_lt, rhs, zero),
3016 .OpLogicalNotEqual,
3017 try cg.buildCmp(.OpSLessThan, lhs, zero),
3018 try cg.buildCmp(.OpSLessThan, rhs, zero),
31323019 );
31333020 const rem_is_not_zero_and_result_is_negative = try cg.buildBinary(
3134 .l_and,
3021 .OpLogicalAnd,
31353022 rem_is_not_zero,
31363023 result_negative,
31373024 );
31383025
31393026 const result = try cg.buildBinary(
3140 .i_sub,
3027 .OpISub,
31413028 div,
31423029 try cg.intFromBool2(rem_is_not_zero_and_result_is_negative, div.ty),
31433030 );
......@@ -3145,7 +3032,7 @@ fn airDivFloor(cg: *CodeGen, inst: Air.Inst.Index) !?Id {
31453032 return try result.materialize(cg);
31463033 },
31473034 .float => {
3148 const div = try cg.buildBinary(.f_div, lhs, rhs);
3035 const div = try cg.buildBinary(.OpFDiv, lhs, rhs);
31493036 const result = try cg.buildUnary(.floor, div);
31503037 return try result.materialize(cg);
31513038 },
......@@ -3164,16 +3051,16 @@ fn airDivTrunc(cg: *CodeGen, inst: Air.Inst.Index) !?Id {
31643051 .composite_integer => unreachable, // TODO
31653052 .integer, .strange_integer => switch (info.signedness) {
31663053 .unsigned => {
3167 const result = try cg.buildBinary(.u_div, lhs, rhs);
3054 const result = try cg.buildBinary(.OpUDiv, lhs, rhs);
31683055 return try result.materialize(cg);
31693056 },
31703057 .signed => {
3171 const result = try cg.buildBinary(.s_div, lhs, rhs);
3058 const result = try cg.buildBinary(.OpSDiv, lhs, rhs);
31723059 return try result.materialize(cg);
31733060 },
31743061 },
31753062 .float => {
3176 const div = try cg.buildBinary(.f_div, lhs, rhs);
3063 const div = try cg.buildBinary(.OpFDiv, lhs, rhs);
31773064 const result = try cg.buildUnary(.trunc, div);
31783065 return try result.materialize(cg);
31793066 },
......@@ -3191,9 +3078,9 @@ fn airUnOpSimple(cg: *CodeGen, inst: Air.Inst.Index, op: UnaryOp) !?Id {
31913078fn airArithOp(
31923079 cg: *CodeGen,
31933080 inst: Air.Inst.Index,
3194 comptime fop: BinaryOp,
3195 comptime sop: BinaryOp,
3196 comptime uop: BinaryOp,
3081 comptime fop: Opcode,
3082 comptime sop: Opcode,
3083 comptime uop: Opcode,
31973084) !?Id {
31983085 const bin_op = cg.air.instructions.items(.data)[@intFromEnum(inst)].bin_op;
31993086
......@@ -3253,11 +3140,11 @@ fn abs(cg: *CodeGen, result_ty: Type, value: Temporary) !Temporary {
32533140fn airAddSubOverflow(
32543141 cg: *CodeGen,
32553142 inst: Air.Inst.Index,
3256 comptime add: BinaryOp,
3257 comptime ucmp: CmpPredicate,
3258 comptime scmp: CmpPredicate,
3143 comptime add: Opcode,
3144 u_opcode: Opcode,
3145 s_opcode: Opcode,
32593146) !?Id {
3260 _ = scmp;
3147 _ = s_opcode;
32613148 // Note: OpIAddCarry and OpISubBorrow are not really useful here: For unsigned numbers,
32623149 // there is in both cases only one extra operation required. For signed operations,
32633150 // the overflow bit is set then going from 0x80.. to 0x00.., but this doesn't actually
......@@ -3285,7 +3172,7 @@ fn airAddSubOverflow(
32853172 const overflowed = switch (info.signedness) {
32863173 // Overflow happened if the result is smaller than either of the operands. It doesn't matter which.
32873174 // For subtraction the conditions need to be swapped.
3288 .unsigned => try cg.buildCmp(ucmp, result, lhs),
3175 .unsigned => try cg.buildCmp(u_opcode, result, lhs),
32893176 // For signed operations, we check the signs of the operands and the result.
32903177 .signed => blk: {
32913178 // Signed overflow detection using the sign bits of the operands and the result.
......@@ -3297,19 +3184,19 @@ fn airAddSubOverflow(
32973184 // (sign(a) != sign(b)) && (sign(a) != sign(result))
32983185 const zero: Temporary = .init(rhs.ty, try cg.constInt(rhs.ty, 0));
32993186
3300 const lhs_is_neg = try cg.buildCmp(.s_lt, lhs, zero);
3301 const rhs_is_neg = try cg.buildCmp(.s_lt, rhs, zero);
3302 const result_is_neg = try cg.buildCmp(.s_lt, result, zero);
3187 const lhs_is_neg = try cg.buildCmp(.OpSLessThan, lhs, zero);
3188 const rhs_is_neg = try cg.buildCmp(.OpSLessThan, rhs, zero);
3189 const result_is_neg = try cg.buildCmp(.OpSLessThan, result, zero);
33033190
3304 const signs_match = try cg.buildCmp(.l_eq, lhs_is_neg, rhs_is_neg);
3305 const result_sign_differs = try cg.buildCmp(.l_ne, lhs_is_neg, result_is_neg);
3191 const signs_match = try cg.buildCmp(.OpLogicalEqual, lhs_is_neg, rhs_is_neg);
3192 const result_sign_differs = try cg.buildCmp(.OpLogicalNotEqual, lhs_is_neg, result_is_neg);
33063193
3307 const overflow_condition = if (add == .i_add)
3194 const overflow_condition = if (add == .OpIAdd)
33083195 signs_match
3309 else // .i_sub
3196 else // .OpISub
33103197 try cg.buildUnary(.l_not, signs_match);
33113198
3312 break :blk try cg.buildBinary(.l_and, overflow_condition, result_sign_differs);
3199 break :blk try cg.buildCmp(.OpLogicalAnd, overflow_condition, result_sign_differs);
33133200 },
33143201 };
33153202
......@@ -3361,23 +3248,23 @@ fn airMulOverflow(cg: *CodeGen, inst: Air.Inst.Index) !?Id {
33613248 const casted_lhs = try cg.buildConvert(op_ty, lhs);
33623249 const casted_rhs = try cg.buildConvert(op_ty, rhs);
33633250
3364 const full_result = try cg.buildBinary(.i_mul, casted_lhs, casted_rhs);
3251 const full_result = try cg.buildBinary(.OpIMul, casted_lhs, casted_rhs);
33653252
33663253 const low_bits = try cg.buildConvert(lhs.ty, full_result);
33673254 const result = try cg.normalize(low_bits, info);
33683255
33693256 // Shift the result bits away to get the overflow bits.
33703257 const shift: Temporary = .init(full_result.ty, try cg.constInt(full_result.ty, info.bits));
3371 const overflow = try cg.buildBinary(.srl, full_result, shift);
3258 const overflow = try cg.buildBinary(.OpShiftRightLogical, full_result, shift);
33723259
33733260 // Directly check if its zero in the op_ty without converting first.
33743261 const zero: Temporary = .init(full_result.ty, try cg.constInt(full_result.ty, 0));
3375 const overflowed = try cg.buildCmp(.i_ne, zero, overflow);
3262 const overflowed = try cg.buildCmp(.OpINotEqual, zero, overflow);
33763263
33773264 break :blk .{ result, overflowed };
33783265 }
33793266
3380 const low_bits, const high_bits = try cg.buildWideMul(.u_mul_extended, lhs, rhs);
3267 const low_bits, const high_bits = try cg.buildWideMul(.unsigned, lhs, rhs);
33813268
33823269 // Truncate the result, if required.
33833270 const result = try cg.normalize(low_bits, info);
......@@ -3386,17 +3273,17 @@ fn airMulOverflow(cg: *CodeGen, inst: Air.Inst.Index) !?Id {
33863273 // high bits of the low word of the result (those outside the range of the
33873274 // int) are nonzero.
33883275 const zero: Temporary = .init(lhs.ty, try cg.constInt(lhs.ty, 0));
3389 const high_overflowed = try cg.buildCmp(.i_ne, zero, high_bits);
3276 const high_overflowed = try cg.buildCmp(.OpINotEqual, zero, high_bits);
33903277
33913278 // If no overflow bits in low_bits, no extra work needs to be done.
33923279 if (info.backing_bits == info.bits) break :blk .{ result, high_overflowed };
33933280
33943281 // Shift the result bits away to get the overflow bits.
33953282 const shift: Temporary = .init(lhs.ty, try cg.constInt(lhs.ty, info.bits));
3396 const low_overflow = try cg.buildBinary(.srl, low_bits, shift);
3397 const low_overflowed = try cg.buildCmp(.i_ne, zero, low_overflow);
3283 const low_overflow = try cg.buildBinary(.OpShiftRightLogical, low_bits, shift);
3284 const low_overflowed = try cg.buildCmp(.OpINotEqual, zero, low_overflow);
33983285
3399 const overflowed = try cg.buildBinary(.l_or, low_overflowed, high_overflowed);
3286 const overflowed = try cg.buildCmp(.OpLogicalOr, low_overflowed, high_overflowed);
34003287
34013288 break :blk .{ result, overflowed };
34023289 },
......@@ -3412,16 +3299,16 @@ fn airMulOverflow(cg: *CodeGen, inst: Air.Inst.Index) !?Id {
34123299 // (lhs > 0 && rhs < 0) || (lhs < 0 && rhs > 0)
34133300
34143301 const zero: Temporary = .init(lhs.ty, try cg.constInt(lhs.ty, 0));
3415 const lhs_negative = try cg.buildCmp(.s_lt, lhs, zero);
3416 const rhs_negative = try cg.buildCmp(.s_lt, rhs, zero);
3417 const lhs_positive = try cg.buildCmp(.s_gt, lhs, zero);
3418 const rhs_positive = try cg.buildCmp(.s_gt, rhs, zero);
3302 const lhs_negative = try cg.buildCmp(.OpSLessThan, lhs, zero);
3303 const rhs_negative = try cg.buildCmp(.OpSLessThan, rhs, zero);
3304 const lhs_positive = try cg.buildCmp(.OpSGreaterThan, lhs, zero);
3305 const rhs_positive = try cg.buildCmp(.OpSGreaterThan, rhs, zero);
34193306
34203307 // Set to `true` if we expect -1.
34213308 const expected_overflow_bit = try cg.buildBinary(
3422 .l_or,
3423 try cg.buildBinary(.l_and, lhs_positive, rhs_negative),
3424 try cg.buildBinary(.l_and, lhs_negative, rhs_positive),
3309 .OpLogicalOr,
3310 try cg.buildCmp(.OpLogicalAnd, lhs_positive, rhs_negative),
3311 try cg.buildCmp(.OpLogicalAnd, lhs_negative, rhs_positive),
34253312 );
34263313
34273314 if (maybe_op_ty_bits) |op_ty_bits| {
......@@ -3430,7 +3317,7 @@ fn airMulOverflow(cg: *CodeGen, inst: Air.Inst.Index) !?Id {
34303317 const casted_lhs = try cg.buildConvert(op_ty, lhs);
34313318 const casted_rhs = try cg.buildConvert(op_ty, rhs);
34323319
3433 const full_result = try cg.buildBinary(.i_mul, casted_lhs, casted_rhs);
3320 const full_result = try cg.buildBinary(.OpIMul, casted_lhs, casted_rhs);
34343321
34353322 // Truncate to the result type.
34363323 const low_bits = try cg.buildConvert(lhs.ty, full_result);
......@@ -3443,18 +3330,18 @@ fn airMulOverflow(cg: *CodeGen, inst: Air.Inst.Index) !?Id {
34433330 const shift: Temporary = .init(full_result.ty, try cg.constInt(full_result.ty, info.bits - 1));
34443331 // Use SRA so that any sign bits are duplicated. Now we can just check if ALL bits are set
34453332 // for negative cases.
3446 const overflow = try cg.buildBinary(.sra, full_result, shift);
3333 const overflow = try cg.buildBinary(.OpShiftRightArithmetic, full_result, shift);
34473334
34483335 const long_all_set: Temporary = .init(full_result.ty, try cg.constInt(full_result.ty, -1));
34493336 const long_zero: Temporary = .init(full_result.ty, try cg.constInt(full_result.ty, 0));
34503337 const mask = try cg.buildSelect(expected_overflow_bit, long_all_set, long_zero);
34513338
3452 const overflowed = try cg.buildCmp(.i_ne, mask, overflow);
3339 const overflowed = try cg.buildCmp(.OpINotEqual, mask, overflow);
34533340
34543341 break :blk .{ result, overflowed };
34553342 }
34563343
3457 const low_bits, const high_bits = try cg.buildWideMul(.s_mul_extended, lhs, rhs);
3344 const low_bits, const high_bits = try cg.buildWideMul(.signed, lhs, rhs);
34583345
34593346 // Truncate result if required.
34603347 const result = try cg.normalize(low_bits, info);
......@@ -3465,7 +3352,7 @@ fn airMulOverflow(cg: *CodeGen, inst: Air.Inst.Index) !?Id {
34653352 // Like with unsigned, overflow happened if high_bits are not the ones we expect,
34663353 // and we also need to check some ones from the low bits.
34673354
3468 const high_overflowed = try cg.buildCmp(.i_ne, mask, high_bits);
3355 const high_overflowed = try cg.buildCmp(.OpINotEqual, mask, high_bits);
34693356
34703357 // If no overflow bits in low_bits, no extra work needs to be done.
34713358 // Careful, we still have to check the sign bit, so this branch
......@@ -3476,10 +3363,10 @@ fn airMulOverflow(cg: *CodeGen, inst: Air.Inst.Index) !?Id {
34763363 const shift: Temporary = .init(lhs.ty, try cg.constInt(lhs.ty, info.bits - 1));
34773364 // Use SRA so that any sign bits are duplicated. Now we can just check if ALL bits are set
34783365 // for negative cases.
3479 const low_overflow = try cg.buildBinary(.sra, low_bits, shift);
3480 const low_overflowed = try cg.buildCmp(.i_ne, mask, low_overflow);
3366 const low_overflow = try cg.buildBinary(.OpShiftRightArithmetic, low_bits, shift);
3367 const low_overflowed = try cg.buildCmp(.OpINotEqual, mask, low_overflow);
34813368
3482 const overflowed = try cg.buildBinary(.l_or, low_overflowed, high_overflowed);
3369 const overflowed = try cg.buildCmp(.OpLogicalOr, low_overflowed, high_overflowed);
34833370
34843371 break :blk .{ result, overflowed };
34853372 },
......@@ -3517,15 +3404,15 @@ fn airShlOverflow(cg: *CodeGen, inst: Air.Inst.Index) !?Id {
35173404 // so just manually upcast it if required.
35183405 const casted_shift = try cg.buildConvert(base.ty.scalarType(zcu), shift);
35193406
3520 const left = try cg.buildBinary(.sll, base, casted_shift);
3407 const left = try cg.buildBinary(.OpShiftLeftLogical, base, casted_shift);
35213408 const result = try cg.normalize(left, info);
35223409
35233410 const right = switch (info.signedness) {
3524 .unsigned => try cg.buildBinary(.srl, result, casted_shift),
3525 .signed => try cg.buildBinary(.sra, result, casted_shift),
3411 .unsigned => try cg.buildBinary(.OpShiftRightLogical, result, casted_shift),
3412 .signed => try cg.buildBinary(.OpShiftRightArithmetic, result, casted_shift),
35263413 };
35273414
3528 const overflowed = try cg.buildCmp(.i_ne, base, right);
3415 const overflowed = try cg.buildCmp(.OpINotEqual, base, right);
35293416 const ov = try cg.intFromBool(overflowed);
35303417
35313418 const result_ty_id = try cg.resolveType(result_ty, .direct);
......@@ -3957,19 +3844,19 @@ fn cmp(
39573844
39583845 return switch (op) {
39593846 .eq => try cg.buildBinary(
3960 .l_and,
3847 .OpLogicalAnd,
39613848 try cg.cmp(.eq, lhs_valid, rhs_valid),
39623849 try cg.buildBinary(
3963 .l_or,
3850 .OpLogicalOr,
39643851 try cg.buildUnary(.l_not, lhs_valid),
39653852 try cg.cmp(.eq, lhs_pl, rhs_pl),
39663853 ),
39673854 ),
39683855 .neq => try cg.buildBinary(
3969 .l_or,
3856 .OpLogicalOr,
39703857 try cg.cmp(.neq, lhs_valid, rhs_valid),
39713858 try cg.buildBinary(
3972 .l_and,
3859 .OpLogicalAnd,
39733860 lhs_valid,
39743861 try cg.cmp(.neq, lhs_pl, rhs_pl),
39753862 ),
......@@ -3981,37 +3868,37 @@ fn cmp(
39813868 }
39823869
39833870 const info = cg.arithmeticTypeInfo(scalar_ty);
3984 const pred: CmpPredicate = switch (info.class) {
3871 const pred: Opcode = switch (info.class) {
39853872 .composite_integer => unreachable, // TODO
39863873 .float => switch (op) {
3987 .eq => .f_oeq,
3988 .neq => .f_une,
3989 .lt => .f_olt,
3990 .lte => .f_ole,
3991 .gt => .f_ogt,
3992 .gte => .f_oge,
3874 .eq => .OpFOrdEqual,
3875 .neq => .OpFUnordNotEqual,
3876 .lt => .OpFOrdLessThan,
3877 .lte => .OpFOrdLessThanEqual,
3878 .gt => .OpFOrdGreaterThan,
3879 .gte => .OpFOrdGreaterThanEqual,
39933880 },
39943881 .bool => switch (op) {
3995 .eq => .l_eq,
3996 .neq => .l_ne,
3882 .eq => .OpLogicalEqual,
3883 .neq => .OpLogicalNotEqual,
39973884 else => unreachable,
39983885 },
39993886 .integer, .strange_integer => switch (info.signedness) {
40003887 .signed => switch (op) {
4001 .eq => .i_eq,
4002 .neq => .i_ne,
4003 .lt => .s_lt,
4004 .lte => .s_le,
4005 .gt => .s_gt,
4006 .gte => .s_ge,
3888 .eq => .OpIEqual,
3889 .neq => .OpINotEqual,
3890 .lt => .OpSLessThan,
3891 .lte => .OpSLessThanEqual,
3892 .gt => .OpSGreaterThan,
3893 .gte => .OpSGreaterThanEqual,
40073894 },
40083895 .unsigned => switch (op) {
4009 .eq => .i_eq,
4010 .neq => .i_ne,
4011 .lt => .u_lt,
4012 .lte => .u_le,
4013 .gt => .u_gt,
4014 .gte => .u_ge,
3896 .eq => .OpIEqual,
3897 .neq => .OpINotEqual,
3898 .lt => .OpULessThan,
3899 .lte => .OpULessThanEqual,
3900 .gt => .OpUGreaterThan,
3901 .gte => .OpUGreaterThanEqual,
40153902 },
40163903 },
40173904 };
......@@ -4312,12 +4199,12 @@ fn airAggregateInit(cg: *CodeGen, inst: Air.Inst.Index) !?Id {
43124199 .ty = field_int_ty,
43134200 .value = .{ .singleton = field_int_id },
43144201 });
4315 const shifted = try cg.buildBinary(.sll, extended_int_conv, .{
4202 const shifted = try cg.buildBinary(.OpShiftLeftLogical, extended_int_conv, .{
43164203 .ty = backing_int_ty,
43174204 .value = .{ .singleton = shift_rhs },
43184205 });
43194206 const running_int_tmp = try cg.buildBinary(
4320 .bit_or,
4207 .OpBitwiseOr,
43214208 .{ .ty = backing_int_ty, .value = .{ .singleton = running_int_id } },
43224209 shifted,
43234210 );
......@@ -4770,17 +4657,20 @@ fn airStructFieldVal(cg: *CodeGen, inst: Air.Inst.Index) !?Id {
47704657 .@"struct" => switch (object_ty.containerLayout(zcu)) {
47714658 .@"packed" => {
47724659 const struct_ty = zcu.typeToPackedStruct(object_ty).?;
4660 const struct_backing_int_bits = cg.module.backingIntBits(@intCast(object_ty.bitSize(zcu))).@"0";
47734661 const bit_offset = zcu.structPackedFieldBitOffset(struct_ty, field_index);
4774 const bit_offset_id = try cg.constInt(.u16, bit_offset);
4662 // We use the same int type the packed struct is backed by, because even though it would
4663 // be valid SPIR-V to use an smaller type like u16, some implementations like PoCL will complain.
4664 const bit_offset_id = try cg.constInt(object_ty, bit_offset);
47754665 const signedness = if (field_ty.isInt(zcu)) field_ty.intInfo(zcu).signedness else .unsigned;
47764666 const field_bit_size: u16 = @intCast(field_ty.bitSize(zcu));
47774667 const field_int_ty = try pt.intType(signedness, field_bit_size);
47784668 const shift_lhs: Temporary = .{ .ty = object_ty, .value = .{ .singleton = object_id } };
4779 const shift = try cg.buildBinary(.srl, shift_lhs, .{ .ty = .u16, .value = .{ .singleton = bit_offset_id } });
4669 const shift = try cg.buildBinary(.OpShiftRightLogical, shift_lhs, .{ .ty = object_ty, .value = .{ .singleton = bit_offset_id } });
47804670 const mask_id = try cg.constInt(object_ty, (@as(u64, 1) << @as(u6, @intCast(field_bit_size))) - 1);
4781 const masked = try cg.buildBinary(.bit_and, shift, .{ .ty = object_ty, .value = .{ .singleton = mask_id } });
4671 const masked = try cg.buildBinary(.OpBitwiseAnd, shift, .{ .ty = object_ty, .value = .{ .singleton = mask_id } });
47824672 const result_id = blk: {
4783 if (cg.module.backingIntBits(field_bit_size).@"0" == cg.module.backingIntBits(@intCast(object_ty.bitSize(zcu))).@"0")
4673 if (cg.module.backingIntBits(field_bit_size).@"0" == struct_backing_int_bits)
47844674 break :blk try cg.bitCast(field_int_ty, object_ty, try masked.materialize(cg));
47854675 const trunc = try cg.buildConvert(field_int_ty, masked);
47864676 break :blk try trunc.materialize(cg);
......@@ -4799,7 +4689,7 @@ fn airStructFieldVal(cg: *CodeGen, inst: Air.Inst.Index) !?Id {
47994689 const int_ty = try pt.intType(signedness, field_bit_size);
48004690 const mask_id = try cg.constInt(backing_int_ty, (@as(u64, 1) << @as(u6, @intCast(field_bit_size))) - 1);
48014691 const masked = try cg.buildBinary(
4802 .bit_and,
4692 .OpBitwiseAnd,
48034693 .{ .ty = backing_int_ty, .value = .{ .singleton = object_id } },
48044694 .{ .ty = backing_int_ty, .value = .{ .singleton = mask_id } },
48054695 );
......@@ -4858,7 +4748,7 @@ fn airFieldParentPtr(cg: *CodeGen, inst: Air.Inst.Index) !?Id {
48584748 const field_offset_id = try cg.constInt(.usize, field_offset);
48594749 const field_ptr_tmp: Temporary = .init(.usize, field_ptr_int);
48604750 const field_offset_tmp: Temporary = .init(.usize, field_offset_id);
4861 const result = try cg.buildBinary(.i_sub, field_ptr_tmp, field_offset_tmp);
4751 const result = try cg.buildBinary(.OpISub, field_ptr_tmp, field_offset_tmp);
48624752 break :base_ptr_int try result.materialize(cg);
48634753 };
48644754
......@@ -4947,7 +4837,6 @@ fn alloc(
49474837 ty: Type,
49484838 options: AllocOptions,
49494839) !Id {
4950 const target = cg.module.zcu.getTarget();
49514840 const ty_id = try cg.resolveType(ty, .indirect);
49524841 const ptr_fn_ty_id = try cg.module.ptrType(ty_id, .function);
49534842
......@@ -4961,20 +4850,7 @@ fn alloc(
49614850 .initializer = options.initializer,
49624851 });
49634852
4964 switch (target.os.tag) {
4965 .vulkan, .opengl => return var_id,
4966 else => {},
4967 }
4968
4969 switch (options.storage_class) {
4970 .generic => {
4971 const ptr_gn_ty_id = try cg.module.ptrType(ty_id, .generic);
4972 // Convert to a generic pointer
4973 return cg.castToGeneric(ptr_gn_ty_id, var_id);
4974 },
4975 .function => return var_id,
4976 else => unreachable,
4977 }
4853 return var_id;
49784854}
49794855
49804856fn airAlloc(cg: *CodeGen, inst: Air.Inst.Index) !?Id {
src/arch/spirv/Module.zig+5-2
......@@ -368,7 +368,10 @@ pub fn finalize(module: *Module, gpa: Allocator) ![]Word {
368368 }
369369 if (target.cpu.arch == .spirv64) try module.addCapability(.int64);
370370 if (target.cpu.has(.spirv, .int64)) try module.addCapability(.int64);
371 if (target.cpu.has(.spirv, .float16)) try module.addCapability(.float16);
371 if (target.cpu.has(.spirv, .float16)) {
372 if (target.os.tag == .opencl) try module.addExtension("cl_khr_fp16");
373 try module.addCapability(.float16);
374 }
372375 if (target.cpu.has(.spirv, .float64)) try module.addCapability(.float64);
373376 if (target.cpu.has(.spirv, .generic_pointer)) try module.addCapability(.generic_pointer);
374377 if (target.cpu.has(.spirv, .vector16)) try module.addCapability(.vector16);
......@@ -920,7 +923,7 @@ pub fn debugString(module: *Module, string: []const u8) !Id {
920923pub fn storageClass(module: *Module, as: std.builtin.AddressSpace) spec.StorageClass {
921924 const target = module.zcu.getTarget();
922925 return switch (as) {
923 .generic => if (target.cpu.has(.spirv, .generic_pointer)) .generic else .function,
926 .generic => .function,
924927 .global => switch (target.os.tag) {
925928 .opencl, .amdhsa => .cross_workgroup,
926929 else => .storage_buffer,