Skip to content

Commit 7b6c652

Browse files
authored
Allow StoredIntegerElement to use full storage when necessary. (#61726)
* Allow StoredIntegerElement to use full storage when necessary. This way we will be able to store whole 64-bit number when we store only a single value, or two 32-bit numbers or 3 16-bit. Fixes #61723
1 parent beefd4b commit 7b6c652

File tree

2 files changed

+38
-6
lines changed

2 files changed

+38
-6
lines changed

include/swift/Sema/ConstraintLocator.h

Lines changed: 26 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -508,6 +508,26 @@ public: \
508508
/// A base class for custom path elements that store numeric values.
509509
template <unsigned NumValues>
510510
class StoredIntegerElement: public LocatorPathElt {
511+
static constexpr unsigned valueWidth() {
512+
switch (NumValues) {
513+
default:
514+
return 16;
515+
case 1:
516+
return 64;
517+
case 2:
518+
return 32;
519+
}
520+
}
521+
522+
template <unsigned Index = 0,
523+
typename = typename std::enable_if<(Index < NumValues)>::type>
524+
static uint64_t packValue(unsigned value) {
525+
return uint64_t(value) << (valueWidth() * (NumValues - Index - 1));
526+
}
527+
528+
static constexpr uint64_t valueMask =
529+
valueWidth() < 64 ? (1ULL << valueWidth()) - 1 : -1ULL;
530+
511531
public:
512532
template <unsigned NumNumericInputs = NumValues,
513533
typename = typename std::enable_if<NumNumericInputs == 1>::type>
@@ -519,7 +539,7 @@ class StoredIntegerElement: public LocatorPathElt {
519539
template <unsigned NumNumericInputs = NumValues,
520540
typename = typename std::enable_if<NumNumericInputs == 2>::type>
521541
StoredIntegerElement(ConstraintLocator::PathElementKind kind, unsigned value0, unsigned value1)
522-
: LocatorPathElt(kind, (value0 << 16 | value1)) {
542+
: LocatorPathElt(kind, packValue<0>(value0) | packValue<1>(value1)) {
523543
assert(value0 == getValue<0>() && "value0 truncated");
524544
assert(value1 == getValue<1>() && "value1 truncated");
525545
}
@@ -528,7 +548,7 @@ class StoredIntegerElement: public LocatorPathElt {
528548
typename = typename std::enable_if<NumNumericInputs == 3>::type>
529549
StoredIntegerElement(ConstraintLocator::PathElementKind kind, unsigned value0,
530550
unsigned value1, unsigned value2)
531-
: LocatorPathElt(kind, uint64_t(value0) << 32 | uint64_t(value1) << 16 | uint64_t(value2)) {
551+
: LocatorPathElt(kind, packValue<0>(value0) | packValue<1>(value1) | packValue<2>(value2)) {
532552
assert(value0 == getValue<0>() && "value0 truncated");
533553
assert(value1 == getValue<1>() && "value1 truncated");
534554
assert(value2 == getValue<2>() && "value2 truncated");
@@ -537,13 +557,13 @@ class StoredIntegerElement: public LocatorPathElt {
537557
/// Retrieve a value associated with the path element.
538558
template <unsigned Index = 0,
539559
typename = typename std::enable_if<(Index < NumValues)>::type>
540-
unsigned getValue() const {
541-
// We pack values into 16 bit components of the storage, with value0
560+
uint64_t getValue() const {
561+
// We pack values into equally-sized components of the storage, with value0
542562
// being stored in the upper bits, valueN in the lower bits. Therefore we
543563
// need to shift out any extra values in the lower bits.
544564
auto extraValues = NumValues - Index - 1;
545-
auto value = getRawStorage() >> (extraValues * 16);
546-
return value & 0xFFFF;
565+
auto value = getRawStorage() >> (extraValues * valueWidth());
566+
return value & valueMask;
547567
}
548568
};
549569

test/Sema/large_int_array.swift.gyb

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
// RUN: %empty-directory(%t)
2+
// RUN: %gyb %s -o %t/large_int_array.swift
3+
// RUN: %target-swift-frontend -typecheck -verify %t/large_int_array.swift
4+
5+
% num_elements = 65537
6+
7+
let v = 0
8+
let _ : [Int] = [
9+
% for i in range(num_elements):
10+
v,
11+
% end
12+
]

0 commit comments

Comments
 (0)