aboutsummaryrefslogtreecommitdiff
path: root/clang/lib/AST/ByteCode/InterpBuiltin.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib/AST/ByteCode/InterpBuiltin.cpp')
-rw-r--r--clang/lib/AST/ByteCode/InterpBuiltin.cpp60
1 files changed, 60 insertions, 0 deletions
diff --git a/clang/lib/AST/ByteCode/InterpBuiltin.cpp b/clang/lib/AST/ByteCode/InterpBuiltin.cpp
index b7b6d65..64962ee 100644
--- a/clang/lib/AST/ByteCode/InterpBuiltin.cpp
+++ b/clang/lib/AST/ByteCode/InterpBuiltin.cpp
@@ -2914,6 +2914,48 @@ static bool interp__builtin_elementwise_triop(
return true;
}
+static bool interp__builtin_x86_insert_subvector(InterpState &S, CodePtr OpPC,
+ const CallExpr *Call,
+ unsigned ID) {
+ assert(Call->getNumArgs() == 3);
+
+ APSInt ImmAPS = popToAPSInt(S, Call->getArg(2));
+ uint64_t Index = ImmAPS.getZExtValue();
+
+ const Pointer &SubVec = S.Stk.pop<Pointer>();
+ if (!SubVec.getFieldDesc()->isPrimitiveArray())
+ return false;
+
+ const Pointer &BaseVec = S.Stk.pop<Pointer>();
+ if (!BaseVec.getFieldDesc()->isPrimitiveArray())
+ return false;
+
+ const Pointer &Dst = S.Stk.peek<Pointer>();
+
+ unsigned BaseElements = BaseVec.getNumElems();
+ unsigned SubElements = SubVec.getNumElems();
+
+ assert(SubElements != 0 && BaseElements != 0 &&
+ (BaseElements % SubElements) == 0);
+
+ unsigned NumLanes = BaseElements / SubElements;
+ unsigned Lane = static_cast<unsigned>(Index % NumLanes);
+ unsigned InsertPos = Lane * SubElements;
+
+ PrimType ElemPT = BaseVec.getFieldDesc()->getPrimType();
+
+ TYPE_SWITCH(ElemPT, {
+ for (unsigned I = 0; I != BaseElements; ++I)
+ Dst.elem<T>(I) = BaseVec.elem<T>(I);
+ for (unsigned I = 0; I != SubElements; ++I)
+ Dst.elem<T>(InsertPos + I) = SubVec.elem<T>(I);
+ });
+
+ Dst.initializeAllElements();
+
+ return true;
+}
+
bool InterpretBuiltin(InterpState &S, CodePtr OpPC, const CallExpr *Call,
uint32_t BuiltinID) {
if (!S.getASTContext().BuiltinInfo.isConstantEvaluated(BuiltinID))
@@ -3572,6 +3614,24 @@ bool InterpretBuiltin(InterpState &S, CodePtr OpPC, const CallExpr *Call,
return interp__builtin_elementwise_triop(S, OpPC, Call,
llvm::APIntOps::fshr);
+ case X86::BI__builtin_ia32_insertf32x4_256:
+ case X86::BI__builtin_ia32_inserti32x4_256:
+ case X86::BI__builtin_ia32_insertf64x2_256:
+ case X86::BI__builtin_ia32_inserti64x2_256:
+ case X86::BI__builtin_ia32_insertf32x4:
+ case X86::BI__builtin_ia32_inserti32x4:
+ case X86::BI__builtin_ia32_insertf64x2_512:
+ case X86::BI__builtin_ia32_inserti64x2_512:
+ case X86::BI__builtin_ia32_insertf32x8:
+ case X86::BI__builtin_ia32_inserti32x8:
+ case X86::BI__builtin_ia32_insertf64x4:
+ case X86::BI__builtin_ia32_inserti64x4:
+ case X86::BI__builtin_ia32_vinsertf128_ps256:
+ case X86::BI__builtin_ia32_vinsertf128_pd256:
+ case X86::BI__builtin_ia32_vinsertf128_si256:
+ case X86::BI__builtin_ia32_insert128i256:
+ return interp__builtin_x86_insert_subvector(S, OpPC, Call, BuiltinID);
+
default:
S.FFDiag(S.Current->getLocation(OpPC),
diag::note_invalid_subexpr_in_const_expr)