diff --git a/clang/lib/AST/Interp/InterpBuiltin.cpp b/clang/lib/AST/Interp/InterpBuiltin.cpp index deba38e4e9ddc..b55b1569a2598 100644 --- a/clang/lib/AST/Interp/InterpBuiltin.cpp +++ b/clang/lib/AST/Interp/InterpBuiltin.cpp @@ -602,6 +602,17 @@ static bool interp__builtin_rotate(InterpState &S, CodePtr OpPC, return true; } +static bool interp__builtin_ffs(InterpState &S, CodePtr OpPC, + const InterpFrame *Frame, const Function *Func, + const CallExpr *Call) { + PrimType ArgT = *S.getContext().classify(Call->getArg(0)->getType()); + APSInt Value = peekToAPSInt(S.Stk, ArgT); + + uint64_t N = Value.countr_zero(); + pushInt(S, N == Value.getBitWidth() ? 0 : N + 1); + return true; +} + bool InterpretBuiltin(InterpState &S, CodePtr OpPC, const Function *F, const CallExpr *Call) { InterpFrame *Frame = S.Current; @@ -803,6 +814,13 @@ bool InterpretBuiltin(InterpState &S, CodePtr OpPC, const Function *F, return false; break; + case Builtin::BI__builtin_ffs: + case Builtin::BI__builtin_ffsl: + case Builtin::BI__builtin_ffsll: + if (!interp__builtin_ffs(S, OpPC, Frame, F, Call)) + return false; + break; + default: return false; } diff --git a/clang/test/AST/Interp/builtin-functions.cpp b/clang/test/AST/Interp/builtin-functions.cpp index 62fe9b081c78f..ce7c8bd357908 100644 --- a/clang/test/AST/Interp/builtin-functions.cpp +++ b/clang/test/AST/Interp/builtin-functions.cpp @@ -353,3 +353,13 @@ namespace rotateright { char rotateright3[__builtin_rotateright32(0x76543210, 22) == 0x50C841D9 ? 1 : -1]; char rotateright4[__builtin_rotateright64(0xFEDCBA9876543210ULL, 55) == 0xB97530ECA86421FDULL ? 1 : -1]; } + +namespace ffs { + char ffs1[__builtin_ffs(0) == 0 ? 1 : -1]; + char ffs2[__builtin_ffs(1) == 1 ? 1 : -1]; + char ffs3[__builtin_ffs(0xfbe71) == 1 ? 1 : -1]; + char ffs4[__builtin_ffs(0xfbe70) == 5 ? 1 : -1]; + char ffs5[__builtin_ffs(1U << (BITSIZE(int) - 1)) == BITSIZE(int) ? 1 : -1]; + char ffs6[__builtin_ffsl(0x10L) == 5 ? 1 : -1]; + char ffs7[__builtin_ffsll(0x100LL) == 9 ? 1 : -1]; +}