| ... | ... | @@ -1300,16 +1300,16 @@ pub const Value = extern union { |
| 1300 | 1300 | for (fields) |field, i| { |
| 1301 | 1301 | const field_val = field_vals[i]; |
| 1302 | 1302 | const field_bigint_const = switch (field.ty.zigTypeTag()) { |
| 1303 | | .Float => switch (field.ty.floatBits(target)) { |
| 1304 | | 16 => bitcastFloatToBigInt(f16, field_val.toFloat(f16), &field_buf), |
| 1305 | | 32 => bitcastFloatToBigInt(f32, field_val.toFloat(f32), &field_buf), |
| 1306 | | 64 => bitcastFloatToBigInt(f64, field_val.toFloat(f64), &field_buf), |
| 1307 | | 80 => bitcastFloatToBigInt(f80, field_val.toFloat(f80), &field_buf), |
| 1308 | | 128 => bitcastFloatToBigInt(f128, field_val.toFloat(f128), &field_buf), |
| 1309 | | else => unreachable, |
| 1303 | .Void => continue, |
| 1304 | .Float => floatToBigInt(field_val, field.ty, target, &field_buf), |
| 1305 | .Int, .Bool => intOrBoolToBigInt(field_val, field.ty, target, &field_buf, &field_space), |
| 1306 | .Struct => switch (field.ty.containerLayout()) { |
| 1307 | .Auto, .Extern => unreachable, // Sema should have error'd before this. |
| 1308 | .Packed => packedStructToInt(field_val, field.ty, target, &field_buf), |
| 1310 | 1309 | }, |
| 1311 | | .Int, .Bool => field_val.toBigInt(&field_space, target), |
| 1312 | | .Struct => packedStructToInt(field_val, field.ty, target, &field_buf), |
| 1310 | .Vector => vectorToBigInt(field_val, field.ty, target, &field_buf), |
| 1311 | .Enum => enumToBigInt(field_val, field.ty, target, &field_space), |
| 1312 | .Union => unreachable, // TODO: packed structs support packed unions |
| 1313 | 1313 | else => unreachable, |
| 1314 | 1314 | }; |
| 1315 | 1315 | var field_bigint = BigIntMutable.init(&field_buf2, 0); |
| ... | ... | @@ -1320,6 +1320,61 @@ pub const Value = extern union { |
| 1320 | 1320 | return bigint.toConst(); |
| 1321 | 1321 | } |
| 1322 | 1322 | |
| 1323 | fn intOrBoolToBigInt(val: Value, ty: Type, target: Target, buf: []std.math.big.Limb, space: *BigIntSpace) BigIntConst { |
| 1324 | const big_int_const = val.toBigInt(space, target); |
| 1325 | if (big_int_const.positive) return big_int_const; |
| 1326 | |
| 1327 | var big_int = BigIntMutable.init(buf, 0); |
| 1328 | big_int.bitNotWrap(big_int_const.negate(), .unsigned, @intCast(u32, ty.bitSize(target))); |
| 1329 | big_int.addScalar(big_int.toConst(), 1); |
| 1330 | return big_int.toConst(); |
| 1331 | } |
| 1332 | |
| 1333 | fn vectorToBigInt(val: Value, ty: Type, target: Target, buf: []std.math.big.Limb) BigIntConst { |
| 1334 | const endian = target.cpu.arch.endian(); |
| 1335 | var vec_bitint = BigIntMutable.init(buf, 0); |
| 1336 | const vec_len = @intCast(usize, ty.arrayLen()); |
| 1337 | const elem_ty = ty.childType(); |
| 1338 | const elem_size = @intCast(usize, elem_ty.bitSize(target)); |
| 1339 | |
| 1340 | var elem_buf: [16]std.math.big.Limb = undefined; |
| 1341 | var elem_space: BigIntSpace = undefined; |
| 1342 | var elem_buf2: [16]std.math.big.Limb = undefined; |
| 1343 | |
| 1344 | var elem_i: usize = 0; |
| 1345 | while (elem_i < vec_len) : (elem_i += 1) { |
| 1346 | const elem_i_target = if (endian == .Big) vec_len - elem_i - 1 else elem_i; |
| 1347 | const elem_val = val.indexVectorlike(elem_i_target); |
| 1348 | const elem_bigint_const = switch (elem_ty.zigTypeTag()) { |
| 1349 | .Int, .Bool => intOrBoolToBigInt(elem_val, elem_ty, target, &elem_buf, &elem_space), |
| 1350 | .Float => floatToBigInt(elem_val, elem_ty, target, &elem_buf), |
| 1351 | .Pointer => unreachable, // TODO |
| 1352 | else => unreachable, // Sema should not let this happen |
| 1353 | }; |
| 1354 | var elem_bitint = BigIntMutable.init(&elem_buf2, 0); |
| 1355 | elem_bitint.shiftLeft(elem_bigint_const, elem_size * elem_i); |
| 1356 | vec_bitint.bitOr(vec_bitint.toConst(), elem_bitint.toConst()); |
| 1357 | } |
| 1358 | return vec_bitint.toConst(); |
| 1359 | } |
| 1360 | |
| 1361 | fn enumToBigInt(val: Value, ty: Type, target: Target, space: *BigIntSpace) BigIntConst { |
| 1362 | var enum_buf: Payload.U64 = undefined; |
| 1363 | const int_val = val.enumToInt(ty, &enum_buf); |
| 1364 | return int_val.toBigInt(space, target); |
| 1365 | } |
| 1366 | |
| 1367 | fn floatToBigInt(val: Value, ty: Type, target: Target, buf: []std.math.big.Limb) BigIntConst { |
| 1368 | return switch (ty.floatBits(target)) { |
| 1369 | 16 => bitcastFloatToBigInt(f16, val.toFloat(f16), buf), |
| 1370 | 32 => bitcastFloatToBigInt(f32, val.toFloat(f32), buf), |
| 1371 | 64 => bitcastFloatToBigInt(f64, val.toFloat(f64), buf), |
| 1372 | 80 => bitcastFloatToBigInt(f80, val.toFloat(f80), buf), |
| 1373 | 128 => bitcastFloatToBigInt(f128, val.toFloat(f128), buf), |
| 1374 | else => unreachable, |
| 1375 | }; |
| 1376 | } |
| 1377 | |
| 1323 | 1378 | fn bitcastFloatToBigInt(comptime F: type, f: F, buf: []std.math.big.Limb) BigIntConst { |
| 1324 | 1379 | const Int = @Type(.{ .Int = .{ |
| 1325 | 1380 | .signedness = .unsigned, |