@@ -1830,6 +1830,7 @@ static bool interp__builtin_elementwise_popcount(InterpState &S, CodePtr OpPC,
18301830
18311831 return true ;
18321832}
1833+
18331834static bool interp__builtin_memcpy (InterpState &S, CodePtr OpPC,
18341835 const InterpFrame *Frame,
18351836 const Function *Func, const CallExpr *Call) {
@@ -1900,6 +1901,51 @@ static bool interp__builtin_memcpy(InterpState &S, CodePtr OpPC,
19001901 return true ;
19011902}
19021903
1904+ static bool interp__builtin_memcmp (InterpState &S, CodePtr OpPC,
1905+ const InterpFrame *Frame,
1906+ const Function *Func, const CallExpr *Call) {
1907+ assert (Call->getNumArgs () == 3 );
1908+ unsigned ID = Func->getBuiltinID ();
1909+ Pointer PtrA = getParam<Pointer>(Frame, 0 );
1910+ const Pointer &PtrB = getParam<Pointer>(Frame, 1 );
1911+ const APSInt &Size =
1912+ peekToAPSInt (S.Stk , *S.getContext ().classify (Call->getArg (2 )));
1913+
1914+ if (ID == Builtin::BImemcmp)
1915+ diagnoseNonConstexprBuiltin (S, OpPC, ID);
1916+
1917+ if (Size.isZero ()) {
1918+ pushInteger (S, 0 , Call->getType ());
1919+ return true ;
1920+ }
1921+
1922+ if (PtrA.isDummy () || PtrB.isDummy ())
1923+ return false ;
1924+
1925+ // Now, read both pointers to a buffer and compare those.
1926+
1927+ BitcastBuffer BufferA (
1928+ Bits (S.getASTContext ().getTypeSize (PtrA.getFieldDesc ()->getType ())));
1929+ readPointerToBuffer (S.getContext (), PtrA, BufferA, false );
1930+
1931+ BitcastBuffer BufferB (
1932+ Bits (S.getASTContext ().getTypeSize (PtrB.getFieldDesc ()->getType ())));
1933+ readPointerToBuffer (S.getContext (), PtrB, BufferB, false );
1934+
1935+ size_t MinBufferSize = std::min (BufferA.byteSize ().getQuantity (),
1936+ BufferB.byteSize ().getQuantity ());
1937+ size_t CmpSize = std::min (MinBufferSize, Size.getZExtValue ());
1938+ int Result = std::memcmp (BufferA.Data .get (), BufferB.Data .get (), CmpSize);
1939+ if (Result == 0 )
1940+ pushInteger (S, 0 , Call->getType ());
1941+ else if (Result < 0 )
1942+ pushInteger (S, -1 , Call->getType ());
1943+ else
1944+ pushInteger (S, 1 , Call->getType ());
1945+
1946+ return true ;
1947+ }
1948+
19031949bool InterpretBuiltin (InterpState &S, CodePtr OpPC, const Function *F,
19041950 const CallExpr *Call, uint32_t BuiltinID) {
19051951 const InterpFrame *Frame = S.Current ;
@@ -2373,6 +2419,12 @@ bool InterpretBuiltin(InterpState &S, CodePtr OpPC, const Function *F,
23732419 return false ;
23742420 break ;
23752421
2422+ case Builtin::BI__builtin_memcmp:
2423+ case Builtin::BImemcmp:
2424+ if (!interp__builtin_memcmp (S, OpPC, Frame, F, Call))
2425+ return false ;
2426+ break ;
2427+
23762428 default :
23772429 S.FFDiag (S.Current ->getLocation (OpPC),
23782430 diag::note_invalid_subexpr_in_const_expr)
0 commit comments