| ... | @@ -1066,9 +1066,10 @@ pub const DeclGen = struct { | ... | @@ -1066,9 +1066,10 @@ pub const DeclGen = struct { |
| 1066 | const mod = self.module; | 1066 | const mod = self.module; |
| 1067 | const target = self.getTarget(); | 1067 | const target = self.getTarget(); |
| 1068 | const result_ty_ref = try self.resolveType(ty, repr); | 1068 | const result_ty_ref = try self.resolveType(ty, repr); |
| | 1069 | const ip = &mod.intern_pool; |
| 1069 | | 1070 | |
| 1070 | var val = arg_val; | 1071 | var val = arg_val; |
| 1071 | switch (mod.intern_pool.indexToKey(val.toIntern())) { | 1072 | switch (ip.indexToKey(val.toIntern())) { |
| 1072 | .runtime_value => |rt| val = rt.val.toValue(), | 1073 | .runtime_value => |rt| val = rt.val.toValue(), |
| 1073 | else => {}, | 1074 | else => {}, |
| 1074 | } | 1075 | } |
| ... | @@ -1078,7 +1079,7 @@ pub const DeclGen = struct { | ... | @@ -1078,7 +1079,7 @@ pub const DeclGen = struct { |
| 1078 | return self.spv.constUndef(result_ty_ref); | 1079 | return self.spv.constUndef(result_ty_ref); |
| 1079 | } | 1080 | } |
| 1080 | | 1081 | |
| 1081 | switch (mod.intern_pool.indexToKey(val.toIntern())) { | 1082 | switch (ip.indexToKey(val.toIntern())) { |
| 1082 | .int_type, | 1083 | .int_type, |
| 1083 | .ptr_type, | 1084 | .ptr_type, |
| 1084 | .array_type, | 1085 | .array_type, |
| ... | @@ -1174,13 +1175,7 @@ pub const DeclGen = struct { | ... | @@ -1174,13 +1175,7 @@ pub const DeclGen = struct { |
| 1174 | constituents[1] = try self.constant(err_ty, err_val, .indirect); | 1175 | constituents[1] = try self.constant(err_ty, err_val, .indirect); |
| 1175 | } | 1176 | } |
| 1176 | | 1177 | |
| 1177 | const result_id = self.spv.allocId(); | 1178 | return try self.constructStruct(result_ty_ref, &constituents); |
| 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; | | |
| 1184 | }, | 1179 | }, |
| 1185 | .enum_tag => { | 1180 | .enum_tag => { |
| 1186 | const int_val = try val.intFromEnum(ty, mod); | 1181 | const int_val = try val.intFromEnum(ty, mod); |
| ... | @@ -1215,13 +1210,7 @@ pub const DeclGen = struct { | ... | @@ -1215,13 +1210,7 @@ pub const DeclGen = struct { |
| 1215 | } | 1210 | } |
| 1216 | | 1211 | |
| 1217 | const len_id = try self.constant(Type.usize, ptr.len.toValue(), .indirect); | 1212 | const len_id = try self.constant(Type.usize, ptr.len.toValue(), .indirect); |
| 1218 | const result_id = self.spv.allocId(); | 1213 | return try self.constructStruct(result_ty_ref, &.{ ptr_id, len_id }); |
| 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 | }, | 1214 | }, |
| 1226 | .opt => { | 1215 | .opt => { |
| 1227 | const payload_ty = ty.optionalChild(mod); | 1216 | const payload_ty = ty.optionalChild(mod); |
| ... | @@ -1242,23 +1231,51 @@ pub const DeclGen = struct { | ... | @@ -1242,23 +1231,51 @@ pub const DeclGen = struct { |
| 1242 | // Optional representation is a structure. | 1231 | // Optional representation is a structure. |
| 1243 | // { Payload, Bool } | 1232 | // { Payload, Bool } |
| 1244 | | 1233 | |
| | 1234 | const has_pl_id = try self.constBool(maybe_payload_val != null, .indirect); |
| 1245 | const payload_id = if (maybe_payload_val) |payload_val| | 1235 | const payload_id = if (maybe_payload_val) |payload_val| |
| 1246 | try self.constant(payload_ty, payload_val, .indirect) | 1236 | try self.constant(payload_ty, payload_val, .indirect) |
| 1247 | else | 1237 | else |
| 1248 | try self.spv.constUndef(try self.resolveType(payload_ty, .indirect)); | 1238 | try self.spv.constUndef(try self.resolveType(payload_ty, .indirect)); |
| 1249 | | 1239 | |
| 1250 | const has_pl_id = try self.constBool(maybe_payload_val != null, .indirect); | 1240 | return try self.constructStruct(result_ty_ref, &.{ payload_id, has_pl_id }); |
| 1251 | | 1241 | }, |
| 1252 | const result_id = self.spv.allocId(); | 1242 | .aggregate => |aggregate| switch (ip.indexToKey(ty.ip_index)) { |
| 1253 | try self.func.body.emit(self.spv.gpa, .OpCompositeConstruct, .{ | 1243 | .array_type => |array_type| { |
| 1254 | .id_result_type = self.typeId(result_ty_ref), | 1244 | const elem_ty = array_type.child.toType(); |
| 1255 | .id_result = result_id, | 1245 | const elem_ty_ref = try self.resolveType(elem_ty, .indirect); |
| 1256 | .constituents = &.{ payload_id, has_pl_id }, | 1246 | |
| 1257 | }); | 1247 | var constituents = try self.gpa.alloc(IdRef, ty.arrayLenIncludingSentinel(mod)); |
| 1258 | return result_id; | 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, |
| 1259 | }, | 1278 | }, |
| 1260 | // TODO: We can handle most pointers here (decl refs etc), because now they emit an extra | | |
| 1261 | // OpVariable that is not really required. | | |
| 1262 | else => { | 1279 | else => { |
| 1263 | // The value cannot be generated directly, so generate it as an indirect constant, | 1280 | // The value cannot be generated directly, so generate it as an indirect constant, |
| 1264 | // and then perform an OpLoad. | 1281 | // and then perform an OpLoad. |