@@ -702,7 +702,7 @@ enum class IncDecOp {
702702
703703template <typename T, IncDecOp Op, PushVal DoPush>
704704bool IncDecHelper (InterpState &S, CodePtr OpPC, const Pointer &Ptr,
705- bool CanOverflow) {
705+ bool CanOverflow, UnsignedOrNone BitWidth = std:: nullopt ) {
706706 assert (!Ptr.isDummy ());
707707
708708 if (!S.inConstantContext ()) {
@@ -725,12 +725,18 @@ bool IncDecHelper(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
725725
726726 if constexpr (Op == IncDecOp::Inc) {
727727 if (!T::increment (Value, &Result) || !CanOverflow) {
728- Ptr.deref <T>() = Result;
728+ if (BitWidth)
729+ Ptr.deref <T>() = Result.truncate (*BitWidth);
730+ else
731+ Ptr.deref <T>() = Result;
729732 return true ;
730733 }
731734 } else {
732735 if (!T::decrement (Value, &Result) || !CanOverflow) {
733- Ptr.deref <T>() = Result;
736+ if (BitWidth)
737+ Ptr.deref <T>() = Result.truncate (*BitWidth);
738+ else
739+ Ptr.deref <T>() = Result;
734740 return true ;
735741 }
736742 }
@@ -774,6 +780,17 @@ bool Inc(InterpState &S, CodePtr OpPC, bool CanOverflow) {
774780 CanOverflow);
775781}
776782
783+ template <PrimType Name, class T = typename PrimConv<Name>::T>
784+ bool IncBitfield (InterpState &S, CodePtr OpPC, bool CanOverflow,
785+ unsigned BitWidth) {
786+ const Pointer &Ptr = S.Stk .pop <Pointer>();
787+ if (!CheckLoad (S, OpPC, Ptr, AK_Increment))
788+ return false ;
789+
790+ return IncDecHelper<T, IncDecOp::Inc, PushVal::Yes>(S, OpPC, Ptr, CanOverflow,
791+ BitWidth);
792+ }
793+
777794// / 1) Pops a pointer from the stack
778795// / 2) Load the value from the pointer
779796// / 3) Writes the value increased by one back to the pointer
@@ -786,6 +803,17 @@ bool IncPop(InterpState &S, CodePtr OpPC, bool CanOverflow) {
786803 return IncDecHelper<T, IncDecOp::Inc, PushVal::No>(S, OpPC, Ptr, CanOverflow);
787804}
788805
806+ template <PrimType Name, class T = typename PrimConv<Name>::T>
807+ bool IncPopBitfield (InterpState &S, CodePtr OpPC, bool CanOverflow,
808+ uint32_t BitWidth) {
809+ const Pointer &Ptr = S.Stk .pop <Pointer>();
810+ if (!CheckLoad (S, OpPC, Ptr, AK_Increment))
811+ return false ;
812+
813+ return IncDecHelper<T, IncDecOp::Inc, PushVal::No>(S, OpPC, Ptr, CanOverflow,
814+ BitWidth);
815+ }
816+
789817template <PrimType Name, class T = typename PrimConv<Name>::T>
790818bool PreInc (InterpState &S, CodePtr OpPC, bool CanOverflow) {
791819 const Pointer &Ptr = S.Stk .peek <Pointer>();
@@ -795,6 +823,17 @@ bool PreInc(InterpState &S, CodePtr OpPC, bool CanOverflow) {
795823 return IncDecHelper<T, IncDecOp::Inc, PushVal::No>(S, OpPC, Ptr, CanOverflow);
796824}
797825
826+ template <PrimType Name, class T = typename PrimConv<Name>::T>
827+ bool PreIncBitfield (InterpState &S, CodePtr OpPC, bool CanOverflow,
828+ uint32_t BitWidth) {
829+ const Pointer &Ptr = S.Stk .peek <Pointer>();
830+ if (!CheckLoad (S, OpPC, Ptr, AK_Increment))
831+ return false ;
832+
833+ return IncDecHelper<T, IncDecOp::Inc, PushVal::No>(S, OpPC, Ptr, CanOverflow,
834+ BitWidth);
835+ }
836+
798837// / 1) Pops a pointer from the stack
799838// / 2) Load the value from the pointer
800839// / 3) Writes the value decreased by one back to the pointer
@@ -808,6 +847,16 @@ bool Dec(InterpState &S, CodePtr OpPC, bool CanOverflow) {
808847 return IncDecHelper<T, IncDecOp::Dec, PushVal::Yes>(S, OpPC, Ptr,
809848 CanOverflow);
810849}
850+ template <PrimType Name, class T = typename PrimConv<Name>::T>
851+ bool DecBitfield (InterpState &S, CodePtr OpPC, bool CanOverflow,
852+ uint32_t BitWidth) {
853+ const Pointer &Ptr = S.Stk .pop <Pointer>();
854+ if (!CheckLoad (S, OpPC, Ptr, AK_Decrement))
855+ return false ;
856+
857+ return IncDecHelper<T, IncDecOp::Dec, PushVal::Yes>(S, OpPC, Ptr, CanOverflow,
858+ BitWidth);
859+ }
811860
812861// / 1) Pops a pointer from the stack
813862// / 2) Load the value from the pointer
@@ -821,6 +870,17 @@ bool DecPop(InterpState &S, CodePtr OpPC, bool CanOverflow) {
821870 return IncDecHelper<T, IncDecOp::Dec, PushVal::No>(S, OpPC, Ptr, CanOverflow);
822871}
823872
873+ template <PrimType Name, class T = typename PrimConv<Name>::T>
874+ bool DecPopBitfield (InterpState &S, CodePtr OpPC, bool CanOverflow,
875+ uint32_t BitWidth) {
876+ const Pointer &Ptr = S.Stk .pop <Pointer>();
877+ if (!CheckLoad (S, OpPC, Ptr, AK_Decrement))
878+ return false ;
879+
880+ return IncDecHelper<T, IncDecOp::Dec, PushVal::No>(S, OpPC, Ptr, CanOverflow,
881+ BitWidth);
882+ }
883+
824884template <PrimType Name, class T = typename PrimConv<Name>::T>
825885bool PreDec (InterpState &S, CodePtr OpPC, bool CanOverflow) {
826886 const Pointer &Ptr = S.Stk .peek <Pointer>();
@@ -829,6 +889,16 @@ bool PreDec(InterpState &S, CodePtr OpPC, bool CanOverflow) {
829889 return IncDecHelper<T, IncDecOp::Dec, PushVal::No>(S, OpPC, Ptr, CanOverflow);
830890}
831891
892+ template <PrimType Name, class T = typename PrimConv<Name>::T>
893+ bool PreDecBitfield (InterpState &S, CodePtr OpPC, bool CanOverflow,
894+ uint32_t BitWidth) {
895+ const Pointer &Ptr = S.Stk .peek <Pointer>();
896+ if (!CheckLoad (S, OpPC, Ptr, AK_Decrement))
897+ return false ;
898+ return IncDecHelper<T, IncDecOp::Dec, PushVal::No>(S, OpPC, Ptr, CanOverflow,
899+ BitWidth);
900+ }
901+
832902template <IncDecOp Op, PushVal DoPush>
833903bool IncDecFloatHelper (InterpState &S, CodePtr OpPC, const Pointer &Ptr,
834904 uint32_t FPOI) {
0 commit comments