diff options
Diffstat (limited to 'clang/lib/AST/ByteCode/InterpBuiltin.cpp')
| -rw-r--r-- | clang/lib/AST/ByteCode/InterpBuiltin.cpp | 63 |
1 files changed, 63 insertions, 0 deletions
diff --git a/clang/lib/AST/ByteCode/InterpBuiltin.cpp b/clang/lib/AST/ByteCode/InterpBuiltin.cpp index 8c2b71160f7f..ff6ef5a1f686 100644 --- a/clang/lib/AST/ByteCode/InterpBuiltin.cpp +++ b/clang/lib/AST/ByteCode/InterpBuiltin.cpp @@ -2829,6 +2829,65 @@ static bool interp__builtin_select(InterpState &S, CodePtr OpPC, return true; } +static bool interp__builtin_elementwise_fsh(InterpState &S, CodePtr OpPC, + const CallExpr *Call, + unsigned BuiltinID) { + assert(Call->getNumArgs() == 3); + + QualType Arg0Type = Call->getArg(0)->getType(); + QualType Arg1Type = Call->getArg(1)->getType(); + QualType Arg2Type = Call->getArg(2)->getType(); + + // Non-vector integer types. + if (!Arg0Type->isVectorType()) { + const APSInt &Shift = + popToAPSInt(S.Stk, *S.getContext().classify(Arg2Type)); + const APSInt &Lo = popToAPSInt(S.Stk, *S.getContext().classify(Arg1Type)); + const APSInt &Hi = popToAPSInt(S.Stk, *S.getContext().classify(Arg0Type)); + APSInt Result; + if (BuiltinID == Builtin::BI__builtin_elementwise_fshl) + Result = APSInt(llvm::APIntOps::fshl(Hi, Lo, Shift), Hi.isUnsigned()); + else if (BuiltinID == Builtin::BI__builtin_elementwise_fshr) + Result = APSInt(llvm::APIntOps::fshr(Hi, Lo, Shift), Hi.isUnsigned()); + else + llvm_unreachable("Wrong builtin ID"); + pushInteger(S, Result, Call->getType()); + return true; + } + + // Vector type. + const auto *VecT = Arg0Type->castAs<VectorType>(); + const PrimType &ElemT = *S.getContext().classify(VecT->getElementType()); + unsigned NumElems = VecT->getNumElements(); + + const Pointer &VecShift = S.Stk.pop<Pointer>(); + const Pointer &VecLo = S.Stk.pop<Pointer>(); + const Pointer &VecHi = S.Stk.pop<Pointer>(); + const Pointer &Dst = S.Stk.peek<Pointer>(); + for (unsigned I = 0; I != NumElems; ++I) { + APSInt Hi; + APSInt Lo; + APSInt Shift; + INT_TYPE_SWITCH_NO_BOOL(ElemT, { + Hi = VecHi.elem<T>(I).toAPSInt(); + Lo = VecLo.elem<T>(I).toAPSInt(); + Shift = VecShift.elem<T>(I).toAPSInt(); + }); + APSInt Result; + if (BuiltinID == Builtin::BI__builtin_elementwise_fshl) + Result = APSInt(llvm::APIntOps::fshl(Hi, Lo, Shift), Hi.isUnsigned()); + else if (BuiltinID == Builtin::BI__builtin_elementwise_fshr) + Result = APSInt(llvm::APIntOps::fshr(Hi, Lo, Shift), Hi.isUnsigned()); + else + llvm_unreachable("Wrong builtin ID"); + INT_TYPE_SWITCH_NO_BOOL(ElemT, + { Dst.elem<T>(I) = static_cast<T>(Result); }); + } + Dst.initializeAllElements(); + + return true; +} + bool InterpretBuiltin(InterpState &S, CodePtr OpPC, const CallExpr *Call, uint32_t BuiltinID) { if (!S.getASTContext().BuiltinInfo.isConstantEvaluated(BuiltinID)) @@ -3393,6 +3452,10 @@ bool InterpretBuiltin(InterpState &S, CodePtr OpPC, const CallExpr *Call, case X86::BI__builtin_ia32_selectpd_512: return interp__builtin_select(S, OpPC, Call); + case Builtin::BI__builtin_elementwise_fshl: + case Builtin::BI__builtin_elementwise_fshr: + return interp__builtin_elementwise_fsh(S, OpPC, Call, BuiltinID); + default: S.FFDiag(S.Current->getLocation(OpPC), diag::note_invalid_subexpr_in_const_expr) |
