1 // Licensed to the .NET Foundation under one or more agreements.
2 // The .NET Foundation licenses this file to you under the MIT license.
3 // See the LICENSE file in the project root for more information.
5 // A set of integers in the range [0..N], for some N defined by the "Env" (via "BitSetTraits").
7 // Represented as a pointer-sized item. If N bits can fit in this item, the representation is "direct"; otherwise,
8 // the item is a pointer to an array of K size_t's, where K is the number of size_t's necessary to hold N bits.
10 #ifndef bitSetAsShortLong_DEFINED
11 #define bitSetAsShortLong_DEFINED 1
14 #include "compilerbitsettraits.h"
16 typedef size_t* BitSetShortLongRep;
18 template <typename Env, typename BitSetTraits>
19 class BitSetOps</*BitSetType*/ BitSetShortLongRep,
20 /*Brand*/ BSShortLong,
22 /*BitSetTraits*/ BitSetTraits>
25 typedef BitSetShortLongRep Rep;
28 static const unsigned BitsInSizeT = sizeof(size_t) * BitSetSupport::BitsInByte;
30 inline static bool IsShort(Env env)
32 return BitSetTraits::GetArrSize(env, sizeof(size_t)) <= 1;
35 // The operations on the "long" (pointer-to-array-of-size_t) versions of the representation.
36 static void AssignLong(Env env, BitSetShortLongRep& lhs, BitSetShortLongRep rhs);
37 static BitSetShortLongRep MakeSingletonLong(Env env, unsigned bitNum);
38 static BitSetShortLongRep MakeCopyLong(Env env, BitSetShortLongRep bs);
39 static bool IsEmptyLong(Env env, BitSetShortLongRep bs);
40 static unsigned CountLong(Env env, BitSetShortLongRep bs);
41 static bool IsEmptyUnionLong(Env env, BitSetShortLongRep bs1, BitSetShortLongRep bs2);
42 static void UnionDLong(Env env, BitSetShortLongRep& bs1, BitSetShortLongRep bs2);
43 static void DiffDLong(Env env, BitSetShortLongRep& bs1, BitSetShortLongRep bs2);
44 static void AddElemDLong(Env env, BitSetShortLongRep& bs, unsigned i);
45 static void RemoveElemDLong(Env env, BitSetShortLongRep& bs, unsigned i);
46 static void ClearDLong(Env env, BitSetShortLongRep& bs);
47 static BitSetShortLongRep MakeUninitArrayBits(Env env);
48 static BitSetShortLongRep MakeEmptyArrayBits(Env env);
49 static BitSetShortLongRep MakeFullArrayBits(Env env);
50 static bool IsMemberLong(Env env, BitSetShortLongRep bs, unsigned i);
51 static bool EqualLong(Env env, BitSetShortLongRep bs1, BitSetShortLongRep bs2);
52 static bool IsSubsetLong(Env env, BitSetShortLongRep bs1, BitSetShortLongRep bs2);
53 static bool IsEmptyIntersectionLong(Env env, BitSetShortLongRep bs1, BitSetShortLongRep bs2);
54 static void IntersectionDLong(Env env, BitSetShortLongRep& bs1, BitSetShortLongRep bs2);
55 static void DataFlowDLong(Env env,
56 BitSetShortLongRep& out,
57 const BitSetShortLongRep gen,
58 const BitSetShortLongRep in);
59 static void LivenessDLong(Env env,
60 BitSetShortLongRep& in,
61 const BitSetShortLongRep def,
62 const BitSetShortLongRep use,
63 const BitSetShortLongRep out);
65 static const char* ToStringLong(Env env, BitSetShortLongRep bs);
69 inline static BitSetShortLongRep UninitVal()
74 static bool MayBeUninit(BitSetShortLongRep bs)
76 return bs == UninitVal();
79 static void Assign(Env env, BitSetShortLongRep& lhs, BitSetShortLongRep rhs)
81 // We can't assert that rhs != UninitVal in the Short case, because in that
82 // case it's a legal value.
88 else if (lhs == UninitVal())
90 assert(rhs != UninitVal());
91 lhs = MakeCopy(env, rhs);
95 AssignLong(env, lhs, rhs);
99 static void AssignAllowUninitRhs(Env env, BitSetShortLongRep& lhs, BitSetShortLongRep rhs)
106 else if (rhs == UninitVal())
110 else if (lhs == UninitVal())
112 lhs = MakeCopy(env, rhs);
116 AssignLong(env, lhs, rhs);
120 static void AssignNoCopy(Env env, BitSetShortLongRep& lhs, BitSetShortLongRep rhs)
125 static void ClearD(Env env, BitSetShortLongRep& bs)
129 bs = (BitSetShortLongRep) nullptr;
133 assert(bs != UninitVal());
138 static BitSetShortLongRep MakeSingleton(Env env, unsigned bitNum)
140 assert(bitNum < BitSetTraits::GetSize(env));
143 return BitSetShortLongRep(((size_t)1) << bitNum);
147 return MakeSingletonLong(env, bitNum);
151 static BitSetShortLongRep MakeCopy(Env env, BitSetShortLongRep bs)
159 return MakeCopyLong(env, bs);
163 static bool IsEmpty(Env env, BitSetShortLongRep bs)
167 return bs == nullptr;
171 assert(bs != UninitVal());
172 return IsEmptyLong(env, bs);
176 static unsigned Count(Env env, BitSetShortLongRep bs)
180 return BitSetSupport::CountBitsInIntegral(size_t(bs));
184 assert(bs != UninitVal());
185 return CountLong(env, bs);
189 static bool IsEmptyUnion(Env env, BitSetShortLongRep bs1, BitSetShortLongRep bs2)
193 return (((size_t)bs1) | ((size_t)bs2)) == 0;
197 return IsEmptyUnionLong(env, bs1, bs2);
201 static void UnionD(Env env, BitSetShortLongRep& bs1, BitSetShortLongRep bs2)
205 bs1 = (BitSetShortLongRep)(((size_t)bs1) | ((size_t)bs2));
209 UnionDLong(env, bs1, bs2);
212 static BitSetShortLongRep Union(Env env, BitSetShortLongRep bs1, BitSetShortLongRep bs2)
214 BitSetShortLongRep res = MakeCopy(env, bs1);
215 UnionD(env, res, bs2);
219 static void DiffD(Env env, BitSetShortLongRep& bs1, BitSetShortLongRep bs2)
223 bs1 = (BitSetShortLongRep)(((size_t)bs1) & (~(size_t)bs2));
227 DiffDLong(env, bs1, bs2);
230 static BitSetShortLongRep Diff(Env env, BitSetShortLongRep bs1, BitSetShortLongRep bs2)
232 BitSetShortLongRep res = MakeCopy(env, bs1);
233 DiffD(env, res, bs2);
237 static void RemoveElemD(Env env, BitSetShortLongRep& bs, unsigned i)
239 assert(i < BitSetTraits::GetSize(env));
242 size_t mask = ((size_t)1) << i;
244 bs = (BitSetShortLongRep)(((size_t)bs) & mask);
248 assert(bs != UninitVal());
249 RemoveElemDLong(env, bs, i);
252 static BitSetShortLongRep RemoveElem(Env env, BitSetShortLongRep bs, unsigned i)
254 BitSetShortLongRep res = MakeCopy(env, bs);
255 RemoveElemD(env, res, i);
259 static void AddElemD(Env env, BitSetShortLongRep& bs, unsigned i)
261 assert(i < BitSetTraits::GetSize(env));
264 size_t mask = ((size_t)1) << i;
265 bs = (BitSetShortLongRep)(((size_t)bs) | mask);
269 AddElemDLong(env, bs, i);
272 static BitSetShortLongRep AddElem(Env env, BitSetShortLongRep bs, unsigned i)
274 BitSetShortLongRep res = MakeCopy(env, bs);
275 AddElemD(env, res, i);
279 static bool IsMember(Env env, const BitSetShortLongRep bs, unsigned i)
281 assert(i < BitSetTraits::GetSize(env));
284 size_t mask = ((size_t)1) << i;
285 return (((size_t)bs) & mask) != 0;
289 assert(bs != UninitVal());
290 return IsMemberLong(env, bs, i);
294 static void IntersectionD(Env env, BitSetShortLongRep& bs1, BitSetShortLongRep bs2)
298 (size_t&)bs1 &= (size_t)bs2;
302 IntersectionDLong(env, bs1, bs2);
306 static BitSetShortLongRep Intersection(Env env, BitSetShortLongRep bs1, BitSetShortLongRep bs2)
308 BitSetShortLongRep res = MakeCopy(env, bs1);
309 IntersectionD(env, res, bs2);
312 static bool IsEmptyIntersection(Env env, BitSetShortLongRep bs1, BitSetShortLongRep bs2)
316 return (((size_t)bs1) & ((size_t)bs2)) == 0;
320 return IsEmptyIntersectionLong(env, bs1, bs2);
324 static void DataFlowD(Env env, BitSetShortLongRep& out, const BitSetShortLongRep gen, const BitSetShortLongRep in)
328 (size_t&)out = (size_t)out & ((size_t)gen | (size_t)in);
332 DataFlowDLong(env, out, gen, in);
336 static void LivenessD(Env env,
337 BitSetShortLongRep& in,
338 const BitSetShortLongRep def,
339 const BitSetShortLongRep use,
340 const BitSetShortLongRep out)
344 (size_t&)in = (size_t)use | ((size_t)out & ~(size_t)def);
348 LivenessDLong(env, in, def, use, out);
352 static bool IsSubset(Env env, BitSetShortLongRep bs1, BitSetShortLongRep bs2)
356 size_t u1 = (size_t)bs1;
357 size_t u2 = (size_t)bs2;
358 return (u1 & u2) == u1;
362 return IsSubsetLong(env, bs1, bs2);
366 static bool Equal(Env env, BitSetShortLongRep bs1, BitSetShortLongRep bs2)
370 return (size_t)bs1 == (size_t)bs2;
374 return EqualLong(env, bs1, bs2);
379 // Returns a string valid until the allocator releases the memory.
380 static const char* ToString(Env env, BitSetShortLongRep bs)
384 assert(sizeof(BitSetShortLongRep) == sizeof(size_t));
385 const int CharsForSizeT = sizeof(size_t) * 2;
387 const int ShortAllocSize = CharsForSizeT + 4;
388 res = (char*)BitSetTraits::DebugAlloc(env, ShortAllocSize);
389 size_t bits = (size_t)bs;
390 unsigned remaining = ShortAllocSize;
392 if (sizeof(size_t) == sizeof(int64_t))
394 sprintf_s(ptr, remaining, "%016llX", bits);
398 assert(sizeof(size_t) == sizeof(int));
399 sprintf_s(ptr, remaining, "%08X", bits);
405 return ToStringLong(env, bs);
410 static BitSetShortLongRep MakeEmpty(Env env)
418 return MakeEmptyArrayBits(env);
422 static BitSetShortLongRep MakeFull(Env env)
426 // Can't just shift by numBits+1, since that might be 32 (and (1 << 32( == 1, for an unsigned).
427 unsigned numBits = BitSetTraits::GetSize(env);
428 if (numBits == BitsInSizeT)
430 // Can't use the implementation below to get all 1's...
431 return BitSetShortLongRep(size_t(-1));
435 return BitSetShortLongRep((size_t(1) << numBits) - 1);
440 return MakeFullArrayBits(env);
446 // The BitSet that we're iterating over. This is updated to point at the current
447 // size_t set of bits.
448 BitSetShortLongRep m_bs;
450 // The end of the iteration.
451 BitSetShortLongRep m_bsEnd;
453 // The remaining bits to be iterated over in the current size_t set of bits.
454 // In the "short" case, these are all the remaining bits.
455 // In the "long" case, these are remaining bits in the current element;
456 // these and the bits in the remaining elements comprise the remaining bits.
459 // The number of bits that have already been iterated over (set or clear). If you
460 // add this to the bit number of the next bit in "m_bits", you get the proper bit number of that
461 // bit in "m_bs". This is only updated when we increment m_bs.
465 Iter(Env env, const BitSetShortLongRep& bs) : m_bs(bs), m_bitNum(0)
467 if (BitSetOps::IsShort(env))
471 // Set the iteration end condition, valid even though this is not a pointer in the short case.
476 assert(bs != BitSetOps::UninitVal());
479 unsigned len = BitSetTraits::GetArrSize(env, sizeof(size_t));
484 bool NextElem(unsigned* pElem)
486 #if BITSET_TRACK_OPCOUNTS
487 BitSetStaticsImpl::RecordOp(BitSetStaticsImpl::BSOP_NextBit);
494 static_assert_no_msg(sizeof(size_t) == 8);
495 hasBit = BitScanForward64(&nextBit, m_bits);
497 static_assert_no_msg(sizeof(size_t) == 4);
498 hasBit = BitScanForward(&nextBit, m_bits);
501 // If there's a bit, doesn't matter if we're short or long.
504 *pElem = m_bitNum + nextBit;
505 m_bits &= ~(((size_t)1) << nextBit); // clear bit we just found so we don't find it again
510 // Go to the next size_t bit element. For short bitsets, this will hit the end condition
518 // If we get here, it's not a short type, so get the next size_t element.
519 m_bitNum += sizeof(size_t) * BitSetSupport::BitsInByte;
526 typedef const BitSetShortLongRep& ValArgType;
527 typedef BitSetShortLongRep RetValType;
530 template <typename Env, typename BitSetTraits>
531 void BitSetOps</*BitSetType*/ BitSetShortLongRep,
532 /*Brand*/ BSShortLong,
534 /*BitSetTraits*/ BitSetTraits>::AssignLong(Env env, BitSetShortLongRep& lhs, BitSetShortLongRep rhs)
536 assert(!IsShort(env));
537 unsigned len = BitSetTraits::GetArrSize(env, sizeof(size_t));
538 for (unsigned i = 0; i < len; i++)
544 template <typename Env, typename BitSetTraits>
545 BitSetShortLongRep BitSetOps</*BitSetType*/ BitSetShortLongRep,
546 /*Brand*/ BSShortLong,
548 /*BitSetTraits*/ BitSetTraits>::MakeSingletonLong(Env env, unsigned bitNum)
550 assert(!IsShort(env));
551 BitSetShortLongRep res = MakeEmptyArrayBits(env);
552 unsigned index = bitNum / BitsInSizeT;
553 res[index] = ((size_t)1) << (bitNum % BitsInSizeT);
557 template <typename Env, typename BitSetTraits>
558 BitSetShortLongRep BitSetOps</*BitSetType*/ BitSetShortLongRep,
559 /*Brand*/ BSShortLong,
561 /*BitSetTraits*/ BitSetTraits>::MakeCopyLong(Env env, BitSetShortLongRep bs)
563 assert(!IsShort(env));
564 BitSetShortLongRep res = MakeUninitArrayBits(env);
565 unsigned len = BitSetTraits::GetArrSize(env, sizeof(size_t));
566 for (unsigned i = 0; i < len; i++)
573 template <typename Env, typename BitSetTraits>
574 bool BitSetOps</*BitSetType*/ BitSetShortLongRep,
575 /*Brand*/ BSShortLong,
577 /*BitSetTraits*/ BitSetTraits>::IsEmptyLong(Env env, BitSetShortLongRep bs)
579 assert(!IsShort(env));
580 unsigned len = BitSetTraits::GetArrSize(env, sizeof(size_t));
581 for (unsigned i = 0; i < len; i++)
591 template <typename Env, typename BitSetTraits>
592 unsigned BitSetOps</*BitSetType*/ BitSetShortLongRep,
593 /*Brand*/ BSShortLong,
595 /*BitSetTraits*/ BitSetTraits>::CountLong(Env env, BitSetShortLongRep bs)
597 assert(!IsShort(env));
598 unsigned len = BitSetTraits::GetArrSize(env, sizeof(size_t));
600 for (unsigned i = 0; i < len; i++)
602 res += BitSetSupport::CountBitsInIntegral(bs[i]);
607 template <typename Env, typename BitSetTraits>
608 void BitSetOps</*BitSetType*/ BitSetShortLongRep,
609 /*Brand*/ BSShortLong,
611 /*BitSetTraits*/ BitSetTraits>::UnionDLong(Env env, BitSetShortLongRep& bs1, BitSetShortLongRep bs2)
613 assert(!IsShort(env));
614 unsigned len = BitSetTraits::GetArrSize(env, sizeof(size_t));
615 for (unsigned i = 0; i < len; i++)
621 template <typename Env, typename BitSetTraits>
622 void BitSetOps</*BitSetType*/ BitSetShortLongRep,
623 /*Brand*/ BSShortLong,
625 /*BitSetTraits*/ BitSetTraits>::DiffDLong(Env env, BitSetShortLongRep& bs1, BitSetShortLongRep bs2)
627 assert(!IsShort(env));
628 unsigned len = BitSetTraits::GetArrSize(env, sizeof(size_t));
629 for (unsigned i = 0; i < len; i++)
635 template <typename Env, typename BitSetTraits>
636 void BitSetOps</*BitSetType*/ BitSetShortLongRep,
637 /*Brand*/ BSShortLong,
639 /*BitSetTraits*/ BitSetTraits>::AddElemDLong(Env env, BitSetShortLongRep& bs, unsigned i)
641 assert(!IsShort(env));
642 unsigned index = i / BitsInSizeT;
643 size_t mask = ((size_t)1) << (i % BitsInSizeT);
647 template <typename Env, typename BitSetTraits>
648 void BitSetOps</*BitSetType*/ BitSetShortLongRep,
649 /*Brand*/ BSShortLong,
651 /*BitSetTraits*/ BitSetTraits>::RemoveElemDLong(Env env, BitSetShortLongRep& bs, unsigned i)
653 assert(!IsShort(env));
654 unsigned index = i / BitsInSizeT;
655 size_t mask = ((size_t)1) << (i % BitsInSizeT);
660 template <typename Env, typename BitSetTraits>
661 void BitSetOps</*BitSetType*/ BitSetShortLongRep,
662 /*Brand*/ BSShortLong,
664 /*BitSetTraits*/ BitSetTraits>::ClearDLong(Env env, BitSetShortLongRep& bs)
666 assert(!IsShort(env));
667 unsigned len = BitSetTraits::GetArrSize(env, sizeof(size_t));
668 for (unsigned i = 0; i < len; i++)
674 template <typename Env, typename BitSetTraits>
675 BitSetShortLongRep BitSetOps</*BitSetType*/ BitSetShortLongRep,
676 /*Brand*/ BSShortLong,
678 /*BitSetTraits*/ BitSetTraits>::MakeUninitArrayBits(Env env)
680 assert(!IsShort(env));
681 unsigned len = BitSetTraits::GetArrSize(env, sizeof(size_t));
682 assert(len > 1); // Or else would not require an array.
683 return (BitSetShortLongRep)(BitSetTraits::Alloc(env, len * sizeof(size_t)));
686 template <typename Env, typename BitSetTraits>
687 BitSetShortLongRep BitSetOps</*BitSetType*/ BitSetShortLongRep,
688 /*Brand*/ BSShortLong,
690 /*BitSetTraits*/ BitSetTraits>::MakeEmptyArrayBits(Env env)
692 assert(!IsShort(env));
693 unsigned len = BitSetTraits::GetArrSize(env, sizeof(size_t));
694 assert(len > 1); // Or else would not require an array.
695 BitSetShortLongRep res = (BitSetShortLongRep)(BitSetTraits::Alloc(env, len * sizeof(size_t)));
696 for (unsigned i = 0; i < len; i++)
703 template <typename Env, typename BitSetTraits>
704 BitSetShortLongRep BitSetOps</*BitSetType*/ BitSetShortLongRep,
705 /*Brand*/ BSShortLong,
707 /*BitSetTraits*/ BitSetTraits>::MakeFullArrayBits(Env env)
709 assert(!IsShort(env));
710 unsigned len = BitSetTraits::GetArrSize(env, sizeof(size_t));
711 assert(len > 1); // Or else would not require an array.
712 BitSetShortLongRep res = (BitSetShortLongRep)(BitSetTraits::Alloc(env, len * sizeof(size_t)));
713 for (unsigned i = 0; i < len - 1; i++)
717 // Start with all ones, shift in zeros in the last elem.
718 unsigned lastElemBits = (BitSetTraits::GetSize(env) - 1) % BitsInSizeT + 1;
719 res[len - 1] = (size_t(-1) >> (BitsInSizeT - lastElemBits));
723 template <typename Env, typename BitSetTraits>
724 bool BitSetOps</*BitSetType*/ BitSetShortLongRep,
725 /*Brand*/ BSShortLong,
727 /*BitSetTraits*/ BitSetTraits>::IsMemberLong(Env env, BitSetShortLongRep bs, unsigned i)
729 assert(!IsShort(env));
730 unsigned index = i / BitsInSizeT;
731 unsigned bitInElem = (i % BitsInSizeT);
732 size_t mask = ((size_t)1) << bitInElem;
733 return (bs[index] & mask) != 0;
736 template <typename Env, typename BitSetTraits>
737 void BitSetOps</*BitSetType*/ BitSetShortLongRep,
738 /*Brand*/ BSShortLong,
740 /*BitSetTraits*/ BitSetTraits>::IntersectionDLong(Env env,
741 BitSetShortLongRep& bs1,
742 BitSetShortLongRep bs2)
744 assert(!IsShort(env));
745 unsigned len = BitSetTraits::GetArrSize(env, sizeof(size_t));
746 for (unsigned i = 0; i < len; i++)
752 template <typename Env, typename BitSetTraits>
753 bool BitSetOps</*BitSetType*/ BitSetShortLongRep,
754 /*Brand*/ BSShortLong,
756 /*BitSetTraits*/ BitSetTraits>::IsEmptyIntersectionLong(Env env,
757 BitSetShortLongRep bs1,
758 BitSetShortLongRep bs2)
760 assert(!IsShort(env));
761 unsigned len = BitSetTraits::GetArrSize(env, sizeof(size_t));
762 for (unsigned i = 0; i < len; i++)
764 if ((bs1[i] & bs2[i]) != 0)
772 template <typename Env, typename BitSetTraits>
773 bool BitSetOps</*BitSetType*/ BitSetShortLongRep,
774 /*Brand*/ BSShortLong,
776 /*BitSetTraits*/ BitSetTraits>::IsEmptyUnionLong(Env env, BitSetShortLongRep bs1, BitSetShortLongRep bs2)
778 assert(!IsShort(env));
779 unsigned len = BitSetTraits::GetArrSize(env, sizeof(size_t));
780 for (unsigned i = 0; i < len; i++)
782 if ((bs1[i] | bs2[i]) != 0)
790 template <typename Env, typename BitSetTraits>
791 void BitSetOps</*BitSetType*/ BitSetShortLongRep,
792 /*Brand*/ BSShortLong,
794 /*BitSetTraits*/ BitSetTraits>::DataFlowDLong(Env env,
795 BitSetShortLongRep& out,
796 const BitSetShortLongRep gen,
797 const BitSetShortLongRep in)
799 assert(!IsShort(env));
800 unsigned len = BitSetTraits::GetArrSize(env, sizeof(size_t));
801 for (unsigned i = 0; i < len; i++)
803 out[i] = out[i] & (gen[i] | in[i]);
807 template <typename Env, typename BitSetTraits>
808 void BitSetOps</*BitSetType*/ BitSetShortLongRep,
809 /*Brand*/ BSShortLong,
811 /*BitSetTraits*/ BitSetTraits>::LivenessDLong(Env env,
812 BitSetShortLongRep& in,
813 const BitSetShortLongRep def,
814 const BitSetShortLongRep use,
815 const BitSetShortLongRep out)
817 assert(!IsShort(env));
818 unsigned len = BitSetTraits::GetArrSize(env, sizeof(size_t));
819 for (unsigned i = 0; i < len; i++)
821 in[i] = use[i] | (out[i] & ~def[i]);
825 template <typename Env, typename BitSetTraits>
826 bool BitSetOps</*BitSetType*/ BitSetShortLongRep,
827 /*Brand*/ BSShortLong,
829 /*BitSetTraits*/ BitSetTraits>::EqualLong(Env env, BitSetShortLongRep bs1, BitSetShortLongRep bs2)
831 assert(!IsShort(env));
832 unsigned len = BitSetTraits::GetArrSize(env, sizeof(size_t));
833 for (unsigned i = 0; i < len; i++)
835 if (bs1[i] != bs2[i])
843 template <typename Env, typename BitSetTraits>
844 bool BitSetOps</*BitSetType*/ BitSetShortLongRep,
845 /*Brand*/ BSShortLong,
847 /*BitSetTraits*/ BitSetTraits>::IsSubsetLong(Env env, BitSetShortLongRep bs1, BitSetShortLongRep bs2)
849 assert(!IsShort(env));
850 unsigned len = BitSetTraits::GetArrSize(env, sizeof(size_t));
851 for (unsigned i = 0; i < len; i++)
853 if ((bs1[i] & bs2[i]) != bs1[i])
862 template <typename Env, typename BitSetTraits>
863 const char* BitSetOps</*BitSetType*/ BitSetShortLongRep,
864 /*Brand*/ BSShortLong,
866 /*BitSetTraits*/ BitSetTraits>::ToStringLong(Env env, BitSetShortLongRep bs)
868 assert(!IsShort(env));
869 unsigned len = BitSetTraits::GetArrSize(env, sizeof(size_t));
870 const int CharsForSizeT = sizeof(size_t) * 2;
871 unsigned allocSz = len * CharsForSizeT + 4;
872 unsigned remaining = allocSz;
873 char* res = (char*)BitSetTraits::DebugAlloc(env, allocSz);
875 for (unsigned i = len; 0 < i; i--)
877 size_t bits = bs[i - 1];
878 for (unsigned bytesDone = 0; bytesDone < sizeof(size_t); bytesDone += sizeof(unsigned))
880 unsigned bits0 = (unsigned)bits;
881 sprintf_s(temp, remaining, "%08X", bits0);
885 assert(sizeof(unsigned) == 4);
886 // Doing this twice by 16, rather than once by 32, avoids warnings when size_t == unsigned.
895 #endif // bitSetAsShortLong_DEFINED