@@ -71,25 +71,68 @@ static void swapBytes(std::byte *M, size_t N) {
7171// / All offsets are in bits.
7272struct BitTracker {
7373 llvm::BitVector Initialized;
74+ llvm::BitVector Data_;
7475 std::vector<std::byte> Data;
7576
7677 BitTracker () = default ;
7778
7879 size_t size () const {
7980 assert (Initialized.size () == Data.size ());
81+ assert (Initialized.size () == Data_.size ());
8082 return Initialized.size ();
8183 }
8284
83- std::byte *getBytes (size_t Offset) { return Data.data () + Offset; }
85+ std::byte *getBytes (size_t Offset) {
86+ assert (false );
87+ return Data.data () + Offset;
88+ }
89+
90+ const std::byte *getBytes (size_t BitOffset, int a) {
91+ assert (BitOffset % 8 == 0 );
92+ return reinterpret_cast <const std::byte *>(Data_.getData ().data ()) +
93+ (BitOffset / 8 );
94+ }
95+
8496 bool allInitialized (size_t Offset, size_t Size) const {
85- for (size_t I = Offset; I != (Size + Offset); ++I) {
86- if (!Initialized[I])
87- return false ;
97+ return Initialized.find_first_unset_in (Offset, Offset + Size) == -1 ;
98+ }
99+
100+ void pushData (const std::byte *data, size_t BitOffset, size_t BitWidth) {
101+ assert (BitOffset >= Data_.size ());
102+ // First, fill up the bit vector until BitOffset. The bits are all 0
103+ // but we record them as indeterminate.
104+ {
105+ Data_.resize (BitOffset, false );
106+ Initialized.resize (BitOffset, false );
88107 }
89- return true ;
108+
109+ size_t BitsHandled = 0 ;
110+ // Read all full bytes first
111+ for (size_t I = 0 ; I != BitWidth / 8 ; ++I) {
112+ for (unsigned X = 0 ; X != 8 ; ++X) {
113+ Data_.push_back ((data[I] & std::byte (1 << X)) != std::byte{0 });
114+ Initialized.push_back (true );
115+ ++BitsHandled;
116+ }
117+ }
118+
119+ // Rest of the bits.
120+ assert ((BitWidth - BitsHandled) < 8 );
121+ for (size_t I = 0 , E = (BitWidth - BitsHandled); I != E; ++I) {
122+ Data_.push_back ((data[BitWidth / 8 ] & std::byte (1 << I)) != std::byte{0 });
123+ Initialized.push_back (true );
124+ ++BitsHandled;
125+ }
126+ }
127+
128+ void pushZeroes (size_t Amount) {
129+ Data_.resize (Data_.size () + Amount, false );
130+ Initialized.resize (Data_.size () + Amount, true );
90131 }
91132
133+ #if 0
92134 std::byte *getWritableBytes(size_t Offset, size_t Size, bool InitValue) {
135+ assert(false);
93136 assert(Offset >= Data.size());
94137 assert(Size > 0);
95138
@@ -104,17 +147,17 @@ struct BitTracker {
104147
105148 return Data.data() + Offset;
106149 }
150+ #endif
107151
108152 void markUninitializedUntil (size_t Offset) {
109- assert (Offset >= Data.size ());
110-
111- size_t NBytes = Offset - Data.size ();
112- for (size_t I = 0 ; I != NBytes; ++I)
113- Initialized.push_back (false );
114- Data.resize (Offset);
153+ assert (Offset >= Data_.size ());
154+ Data_.resize (Offset, false );
155+ Initialized.resize (Offset, false );
156+ return ;
115157 }
116158
117159 void zeroUntil (size_t Offset) {
160+ assert (false );
118161 assert (Offset >= Data.size ());
119162
120163 assert (Data.size () == Initialized.size ());
@@ -330,6 +373,7 @@ bool DoBitCast(InterpState &S, CodePtr OpPC, const Pointer &P, std::byte *Buff,
330373
331374 const Context &Ctx = S.getContext ();
332375 const ASTContext &ASTCtx = Ctx.getASTContext ();
376+ bool BigEndian = ASTCtx.getTargetInfo ().isBigEndian ();
333377 uint64_t PointerSizeInBits =
334378 ASTCtx.getTargetInfo ().getPointerWidth (LangAS::Default);
335379
@@ -353,9 +397,13 @@ bool DoBitCast(InterpState &S, CodePtr OpPC, const Pointer &P, std::byte *Buff,
353397
354398 BITCAST_TYPE_SWITCH_WITH_FLOAT (T, {
355399 T Val = Ptr.deref <T>();
356- std::byte Buff[sizeof (T)];
400+ std::byte *Buff = (std::byte *)std::malloc (
401+ ObjectReprChars.getQuantity ()); // [sizeof(T)];
357402 Val.bitcastToMemory (Buff);
403+ if (BigEndian)
404+ swapBytes (Buff, ObjectReprChars.getQuantity ());
358405 F.pushData (Buff, BitOffset, BitWidth);
406+ std::free (Buff);
359407 });
360408 return true ;
361409 });
@@ -366,6 +414,8 @@ bool DoBitCast(InterpState &S, CodePtr OpPC, const Pointer &P, std::byte *Buff,
366414 assert (F.Data .size () == BuffSize * 8 );
367415 std::memcpy (Buff, F.Data .getData ().data (), BuffSize);
368416
417+ if (BigEndian)
418+ swapBytes (Buff, BuffSize);
369419 return Success;
370420}
371421
@@ -392,68 +442,87 @@ bool DoBitCastToPtr(InterpState &S, const Pointer &P, Pointer &DestPtr,
392442
393443 const Context &Ctx = S.getContext ();
394444 const ASTContext &ASTCtx = Ctx.getASTContext ();
395- uint64_t PointerSize =
396- ASTCtx
397- .toCharUnitsFromBits (
398- ASTCtx.getTargetInfo ().getPointerWidth (LangAS::Default))
399- .getQuantity ();
445+ uint64_t PointerSizeInBits =
446+ ASTCtx.getTargetInfo ().getPointerWidth (LangAS::Default);
400447 bool BigEndian = ASTCtx.getTargetInfo ().isBigEndian ();
401448
402449 BitTracker Bytes;
403450 enumeratePointerFields (
404451 P, S.getContext (),
405- [&](const Pointer &P, PrimType T, size_t ByteOffset) -> bool {
406- ByteOffset /= 8 ;
452+ [&](const Pointer &P, PrimType T, size_t BitOffset) -> bool {
407453 bool PtrInitialized = P.isInitialized ();
408454 if (!PtrInitialized) {
409- Bytes.markUninitializedUntil (ByteOffset + primSize (T));
455+ Bytes.markUninitializedUntil (BitOffset + ( primSize (T) * 8 ));
410456 return true ;
411457 }
412458
413459 assert (P.isInitialized ());
414460 // nullptr_t is a PT_Ptr for us, but it's still not std::is_pointer_v.
415461 if (T == PT_Ptr) {
416- assert (P.getType ()->isNullPtrType ());
417- std::byte *M = Bytes.getWritableBytes (ByteOffset, PointerSize,
418- /* InitValue=*/ true );
419- std::memset (M, 0 , PointerSize);
462+ Bytes.pushZeroes (PointerSizeInBits);
420463 return true ;
421464 }
422465 BITCAST_TYPE_SWITCH_WITH_FLOAT (T, {
423466 T Val = P.deref <T>();
424467 unsigned ObjectReprBytes =
425468 ASTCtx.getTypeSizeInChars (P.getType ()).getQuantity ();
469+
470+ CharUnits ObjectReprChars = ASTCtx.getTypeSizeInChars (P.getType ());
471+ unsigned BitWidth;
472+ if (const FieldDecl *FD = P.getField (); FD && FD->isBitField ())
473+ BitWidth = FD->getBitWidthValue (ASTCtx);
474+ else
475+ BitWidth = ASTCtx.toBits (ObjectReprChars);
476+
426477 unsigned ValueReprBytes = Val.valueReprBytes (ASTCtx);
427478 assert (ObjectReprBytes >= ValueReprBytes);
428479
429- std::byte *Dest = Bytes. getWritableBytes (ByteOffset, ValueReprBytes,
430- PtrInitialized) ;
431- Val. bitcastToMemory (Dest) ;
432- Bytes. zeroUntil (ByteOffset + ObjectReprBytes );
480+ std::byte *Buff = (std::byte *) std::malloc (
481+ ObjectReprChars. getQuantity ()); // [sizeof(T)] ;
482+ // std::byte Buff[sizeof(T)] ;
483+ Val. bitcastToMemory (Buff );
433484
434485 if (BigEndian)
435- swapBytes (Dest, ValueReprBytes);
486+ swapBytes (Buff, BitWidth / 8 );
487+ // if (BigEndian) XXX
488+ // swapBytes(Dest, ValueReprBytes);
489+ Bytes.pushData (Buff, BitOffset, BitWidth);
490+ std::free (Buff);
436491 });
437492 return true ;
438493 });
439494
440495 bool Success = enumeratePointerFields (
441496 DestPtr, S.getContext (),
442- [&](const Pointer &P, PrimType T, size_t ByteOffset) -> bool {
443- ByteOffset /= 8 ;
497+ [&](const Pointer &P, PrimType T, size_t BitOffset) -> bool {
444498 if (T == PT_Float) {
445499 const QualType FloatType = P.getFieldDesc ()->getType ();
446500 const auto &Sem = ASTCtx.getFloatTypeSemantics (FloatType);
447- size_t ValueReprBytes =
448- ASTCtx.toCharUnitsFromBits (APFloat::semanticsSizeInBits (Sem))
449- .getQuantity ();
501+ size_t ValueReprBits = ASTCtx.getTypeSize (FloatType);
502+
503+ CharUnits ObjectReprChars = ASTCtx.getTypeSizeInChars (P.getType ());
504+ const std::byte *M = Bytes.getBytes (BitOffset, 1234 );
505+ std::byte *Buff = (std::byte *)std::malloc (
506+ ObjectReprChars.getQuantity ()); // [sizeof(T)];
507+ std::memcpy (Buff, M, ObjectReprChars.getQuantity ());
508+ // Val.bitcastToMemory(Buff);
509+ if (BigEndian)
510+ swapBytes (Buff, ObjectReprChars.getQuantity ());
450511
451- std::byte *M = Bytes. getBytes (ByteOffset );
512+ // F.pushData(Buff, BitOffset, BitWidth );
452513
453- if (BigEndian)
454- swapBytes (M, ValueReprBytes);
455- P.deref <Floating>() = Floating::bitcastFromMemory (M, Sem);
514+ // const std::byte *M = Bytes.getBytes(BitOffset, 1234);
515+ // size_t ValueReprBytes =
516+ // ASTCtx.toCharUnitsFromBits(APFloat::semanticsSizeInBits(Sem))
517+ // .getQuantity();
518+
519+ // std::byte *M = Bytes.getBytes(ByteOffset);
520+
521+ // if (BigEndian)
522+ // swapBytes(M, ValueReprBytes);
523+ P.deref <Floating>() = Floating::bitcastFromMemory (Buff, Sem);
456524 P.initialize ();
525+ std::free (Buff);
457526 return true ;
458527 }
459528 if (T == PT_Ptr) {
@@ -467,19 +536,19 @@ bool DoBitCastToPtr(InterpState &S, const Pointer &P, Pointer &DestPtr,
467536 BITCAST_TYPE_SWITCH (T, {
468537 T &Val = P.deref <T>();
469538
470- size_t ValueReprBytes = T::valueReprBytes (ASTCtx);
539+ // size_t ValueReprBytes = T::valueReprBytes(ASTCtx);
540+ size_t ValueReprBits = T::valueReprBits (ASTCtx);
471541 // Check if any of the bits we're about to read are uninitialized.
472- bool HasIndeterminateBytes =
473- !Bytes.allInitialized (ByteOffset, ValueReprBytes );
542+ bool HasIndeterminateBits =
543+ !Bytes.allInitialized (BitOffset, ValueReprBits );
474544
475- if (HasIndeterminateBytes ) {
545+ if (HasIndeterminateBits ) {
476546 // Always an error, unless the type of the field we're reading is
477547 // either unsigned char or std::byte.
478548 bool TargetIsUCharOrBytes =
479- (ValueReprBytes == 1 &&
480- (P.getType ()->isSpecificBuiltinType (BuiltinType::UChar) ||
481- P.getType ()->isSpecificBuiltinType (BuiltinType::Char_U) ||
482- P.getType ()->isStdByteType ()));
549+ (P.getType ()->isSpecificBuiltinType (BuiltinType::UChar) ||
550+ P.getType ()->isSpecificBuiltinType (BuiltinType::Char_U) ||
551+ P.getType ()->isStdByteType ());
483552
484553 if (!TargetIsUCharOrBytes) {
485554 const Expr *E = S.Current ->getExpr (OpPC);
@@ -491,12 +560,20 @@ bool DoBitCastToPtr(InterpState &S, const Pointer &P, Pointer &DestPtr,
491560 }
492561 }
493562
494- std::byte *M = Bytes.getBytes (ByteOffset);
495- if (BigEndian)
496- swapBytes (M, ValueReprBytes);
497- Val = T::bitcastFromMemory (M);
563+ assert (!P.getField ()->isBitField ());
564+
565+ std::byte *Copy = (std::byte *)std::malloc (ValueReprBits / 8 );
566+ const std::byte *M = Bytes.getBytes (BitOffset, 1234 );
567+
568+ std::memcpy (Copy, M, ValueReprBits / 8 );
569+
570+ if (BigEndian) {
571+ swapBytes (Copy, ValueReprBits / 8 );
572+ }
573+ Val = T::bitcastFromMemory (Copy);
574+ std::free (Copy);
498575
499- if (!HasIndeterminateBytes )
576+ if (!HasIndeterminateBits )
500577 P.initialize ();
501578 });
502579 return true ;
0 commit comments