authorgravatar for robin@voetter.nlRobin Voetter <robin@voetter.nl> 2023-09-16 02:06:42+02:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2023-09-23 12:36:44-07:00
log001d76a4129da9998ebe25edc2583c8f3c75798a
tree456b55b3dfee848e0baf441ddacde2f72a46c7de
parentae17831cc060840c881c9514ef98c0637c446760

spirv: lower array aggregate at runtime


1 files changed, 44 insertions(+), 27 deletions(-)

src/codegen/spirv.zig+44-27
......@@ -1066,9 +1066,10 @@ pub const DeclGen = struct {
10661066 const mod = self.module;
10671067 const target = self.getTarget();
10681068 const result_ty_ref = try self.resolveType(ty, repr);
1069 const ip = &mod.intern_pool;
10691070
10701071 var val = arg_val;
1071 switch (mod.intern_pool.indexToKey(val.toIntern())) {
1072 switch (ip.indexToKey(val.toIntern())) {
10721073 .runtime_value => |rt| val = rt.val.toValue(),
10731074 else => {},
10741075 }
......@@ -1078,7 +1079,7 @@ pub const DeclGen = struct {
10781079 return self.spv.constUndef(result_ty_ref);
10791080 }
10801081
1081 switch (mod.intern_pool.indexToKey(val.toIntern())) {
1082 switch (ip.indexToKey(val.toIntern())) {
10821083 .int_type,
10831084 .ptr_type,
10841085 .array_type,
......@@ -1174,13 +1175,7 @@ pub const DeclGen = struct {
11741175 constituents[1] = try self.constant(err_ty, err_val, .indirect);
11751176 }
11761177
1177 const result_id = self.spv.allocId();
1178 try self.func.body.emit(self.spv.gpa, .OpCompositeConstruct, .{
1179 .id_result_type = self.typeId(result_ty_ref),
1180 .id_result = result_id,
1181 .constituents = &constituents,
1182 });
1183 return result_id;
1178 return try self.constructStruct(result_ty_ref, &constituents);
11841179 },
11851180 .enum_tag => {
11861181 const int_val = try val.intFromEnum(ty, mod);
......@@ -1215,13 +1210,7 @@ pub const DeclGen = struct {
12151210 }
12161211
12171212 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;
1213 return try self.constructStruct(result_ty_ref, &.{ ptr_id, len_id });
12251214 },
12261215 .opt => {
12271216 const payload_ty = ty.optionalChild(mod);
......@@ -1242,23 +1231,51 @@ pub const DeclGen = struct {
12421231 // Optional representation is a structure.
12431232 // { Payload, Bool }
12441233
1234 const has_pl_id = try self.constBool(maybe_payload_val != null, .indirect);
12451235 const payload_id = if (maybe_payload_val) |payload_val|
12461236 try self.constant(payload_ty, payload_val, .indirect)
12471237 else
12481238 try self.spv.constUndef(try self.resolveType(payload_ty, .indirect));
12491239
1250 const has_pl_id = try self.constBool(maybe_payload_val != null, .indirect);
1251
1252 const result_id = self.spv.allocId();
1253 try self.func.body.emit(self.spv.gpa, .OpCompositeConstruct, .{
1254 .id_result_type = self.typeId(result_ty_ref),
1255 .id_result = result_id,
1256 .constituents = &.{ payload_id, has_pl_id },
1257 });
1258 return result_id;
1240 return try self.constructStruct(result_ty_ref, &.{ payload_id, has_pl_id });
1241 },
1242 .aggregate => |aggregate| switch (ip.indexToKey(ty.ip_index)) {
1243 .array_type => |array_type| {
1244 const elem_ty = array_type.child.toType();
1245 const elem_ty_ref = try self.resolveType(elem_ty, .indirect);
1246
1247 var constituents = try self.gpa.alloc(IdRef, ty.arrayLenIncludingSentinel(mod));
1248 defer self.gpa.free(constituents);
1249
1250 switch (aggregate.storage) {
1251 .bytes => |bytes| {
1252 // TODO: This is really space inefficient, perhaps there is a better
1253 // way to do it?
1254 for (bytes, 0..) |byte, i| {
1255 constituents[i] = try self.spv.constInt(elem_ty_ref, byte);
1256 }
1257 },
1258 .elems => |elems| {
1259 for (0..@as(usize, @intCast(array_type.len))) |i| {
1260 constituents[i] = try self.constant(elem_ty, elems[i].toValue(), .indirect);
1261 }
1262 },
1263 .repeated_elem => |elem| {
1264 const val_id = try self.constant(elem_ty, elem.toValue(), .indirect);
1265 for (0..@as(usize, @intCast(array_type.len))) |i| {
1266 constituents[i] = val_id;
1267 }
1268 },
1269 }
1270 if (array_type.sentinel != .none) {
1271 constituents[constituents.len - 1] = try self.constant(elem_ty, array_type.sentinel.toValue(), .indirect);
1272 }
1273 return try self.constructStruct(result_ty_ref, constituents);
1274 },
1275 .vector_type => return self.todo("constant aggregate of type {}", .{ty.fmt(mod)}),
1276 .anon_struct_type => unreachable, // TODO
1277 else => unreachable,
12591278 },
1260 // TODO: We can handle most pointers here (decl refs etc), because now they emit an extra
1261 // OpVariable that is not really required.
12621279 else => {
12631280 // The value cannot be generated directly, so generate it as an indirect constant,
12641281 // and then perform an OpLoad.