authorgravatar for robin@voetter.nlRobin Voetter <robin@voetter.nl> 2023-09-16 01:31:21+02:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2023-09-23 12:36:44-07:00
log3e2553c7123e914f34bdd0c29dcb2683ad3a6726
treed20f19e92bdc6d17070f9ed68c6cac21df281c3e
parentcc13864dfbeeebab7dff6ef0d38195c44005caba

spirv: lower ptr constants


1 files changed, 72 insertions(+), 0 deletions(-)

src/codegen/spirv.zig+72
...@@ -450,6 +450,42 @@ pub const DeclGen = struct {...@@ -450,6 +450,42 @@ pub const DeclGen = struct {
450 return result_id;450 return result_id;
451 }451 }
452452
453 fn constructDeclRef(self: *DeclGen, ty: Type, decl_index: Decl.Index) !IdRef {
454 const mod = self.module;
455 const ty_ref = try self.resolveType(ty, .direct);
456 const ty_id = self.typeId(ty_ref);
457 const decl = mod.declPtr(decl_index);
458 const spv_decl_index = try self.resolveDecl(decl_index);
459 switch (mod.intern_pool.indexToKey(decl.val.ip_index)) {
460 .func => {
461 // TODO: Properly lower function pointers. For now we are going to hack around it and
462 // just generate an empty pointer. Function pointers are represented by usize for now,
463 // though.
464 // TODO: Add dependency
465 return try self.spv.constInt(ty_ref, 0);
466 },
467 .extern_func => unreachable, // TODO
468 else => {
469 const decl_id = self.spv.declPtr(spv_decl_index).result_id;
470 try self.func.decl_deps.put(self.spv.gpa, spv_decl_index, {});
471
472 switch (decl.@"addrspace") {
473 .generic => {
474 // Pointer should be generic, but is actually placed in CrossWorkgroup.
475 const result_id = self.spv.allocId();
476 try self.func.body.emit(self.spv.gpa, .OpPtrCastToGeneric, .{
477 .id_result_type = ty_id,
478 .id_result = result_id,
479 .pointer = decl_id,
480 });
481 return result_id;
482 },
483 else => return decl_id, // Variable is already correct, probably. Maybe needs a bitcast?
484 }
485 },
486 }
487 }
488
453 const IndirectConstantLowering = struct {489 const IndirectConstantLowering = struct {
454 const undef = 0xAA;490 const undef = 0xAA;
455491
...@@ -1151,6 +1187,42 @@ pub const DeclGen = struct {...@@ -1151,6 +1187,42 @@ pub const DeclGen = struct {
1151 const int_ty = ty.intTagType(mod);1187 const int_ty = ty.intTagType(mod);
1152 return try self.constant(int_ty, int_val, repr);1188 return try self.constant(int_ty, int_val, repr);
1153 },1189 },
1190 .ptr => |ptr| {
1191 const ptr_ty = switch (ptr.len) {
1192 .none => ty,
1193 else => ty.slicePtrFieldType(mod),
1194 };
1195 const ptr_id = switch (ptr.addr) {
1196 .decl => |decl| try self.constructDeclRef(ptr_ty, decl),
1197 .mut_decl => |mut_decl| try self.constructDeclRef(ptr_ty, mut_decl.decl), // TODO
1198 .int => |int| blk: {
1199 const ptr_id = self.spv.allocId();
1200 // TODO: This can probably be an OpSpecConstantOp Bitcast, but
1201 // that is not implemented by Mesa yet. Therefore, just generate it
1202 // as a runtime operation.
1203 try self.func.body.emit(self.spv.gpa, .OpConvertUToPtr, .{
1204 .id_result_type = try self.resolveTypeId(ptr_ty),
1205 .id_result = ptr_id,
1206 .integer_value = try self.constant(Type.usize, int.toValue(), .direct),
1207 });
1208 break :blk ptr_id;
1209 },
1210 .comptime_field => unreachable,
1211 else => |tag| return self.todo("pointer value of type {s}", .{@tagName(tag)}),
1212 };
1213 if (ptr.len == .none) {
1214 return ptr_id;
1215 }
1216
1217 const len_id = try self.constant(Type.usize, ptr.len.toValue(), .indirect);
1218 const result_id = self.spv.allocId();
1219 try self.func.body.emit(self.spv.gpa, .OpCompositeConstruct, .{
1220 .id_result_type = self.typeId(result_ty_ref),
1221 .id_result = result_id,
1222 .constituents = &.{ ptr_id, len_id },
1223 });
1224 return result_id;
1225 },
1154 // TODO: We can handle most pointers here (decl refs etc), because now they emit an extra1226 // TODO: We can handle most pointers here (decl refs etc), because now they emit an extra
1155 // OpVariable that is not really required.1227 // OpVariable that is not really required.
1156 else => {1228 else => {