aboutsummaryrefslogtreecommitdiff
path: root/clang/lib/AST
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib/AST')
-rw-r--r--clang/lib/AST/ASTConcept.cpp31
-rw-r--r--clang/lib/AST/ASTImporter.cpp12
-rw-r--r--clang/lib/AST/ByteCode/InterpBuiltin.cpp137
-rw-r--r--clang/lib/AST/ExprConstant.cpp148
4 files changed, 315 insertions, 13 deletions
diff --git a/clang/lib/AST/ASTConcept.cpp b/clang/lib/AST/ASTConcept.cpp
index d658890..fd12bc4 100644
--- a/clang/lib/AST/ASTConcept.cpp
+++ b/clang/lib/AST/ASTConcept.cpp
@@ -24,13 +24,18 @@ static void
CreateUnsatisfiedConstraintRecord(const ASTContext &C,
const UnsatisfiedConstraintRecord &Detail,
UnsatisfiedConstraintRecord *TrailingObject) {
- if (auto *E = dyn_cast<Expr *>(Detail))
+ if (Detail.isNull())
+ new (TrailingObject) UnsatisfiedConstraintRecord(nullptr);
+ else if (const auto *E = llvm::dyn_cast<const Expr *>(Detail))
new (TrailingObject) UnsatisfiedConstraintRecord(E);
+ else if (const auto *Concept =
+ llvm::dyn_cast<const ConceptReference *>(Detail))
+ new (TrailingObject) UnsatisfiedConstraintRecord(Concept);
else {
auto &SubstitutionDiagnostic =
- *cast<std::pair<SourceLocation, StringRef> *>(Detail);
+ *cast<const clang::ConstraintSubstitutionDiagnostic *>(Detail);
StringRef Message = C.backupStr(SubstitutionDiagnostic.second);
- auto *NewSubstDiag = new (C) std::pair<SourceLocation, StringRef>(
+ auto *NewSubstDiag = new (C) clang::ConstraintSubstitutionDiagnostic(
SubstitutionDiagnostic.first, Message);
new (TrailingObject) UnsatisfiedConstraintRecord(NewSubstDiag);
}
@@ -74,9 +79,10 @@ ASTConstraintSatisfaction *ASTConstraintSatisfaction::Rebuild(
return new (Mem) ASTConstraintSatisfaction(C, Satisfaction);
}
-void ConstraintSatisfaction::Profile(
- llvm::FoldingSetNodeID &ID, const ASTContext &C,
- const NamedDecl *ConstraintOwner, ArrayRef<TemplateArgument> TemplateArgs) {
+void ConstraintSatisfaction::Profile(llvm::FoldingSetNodeID &ID,
+ const ASTContext &C,
+ const NamedDecl *ConstraintOwner,
+ ArrayRef<TemplateArgument> TemplateArgs) {
ID.AddPointer(ConstraintOwner);
ID.AddInteger(TemplateArgs.size());
for (auto &Arg : TemplateArgs)
@@ -116,6 +122,19 @@ void ConceptReference::print(llvm::raw_ostream &OS,
}
}
+const StreamingDiagnostic &clang::operator<<(const StreamingDiagnostic &DB,
+ const ConceptReference *C) {
+ std::string NameStr;
+ llvm::raw_string_ostream OS(NameStr);
+ LangOptions LO;
+ LO.CPlusPlus = true;
+ LO.Bool = true;
+ OS << '\'';
+ C->print(OS, PrintingPolicy(LO));
+ OS << '\'';
+ return DB << NameStr;
+}
+
concepts::ExprRequirement::ExprRequirement(
Expr *E, bool IsSimple, SourceLocation NoexceptLoc,
ReturnTypeRequirement Req, SatisfactionStatus Status,
diff --git a/clang/lib/AST/ASTImporter.cpp b/clang/lib/AST/ASTImporter.cpp
index 1c8fd83..f43fa8c 100644
--- a/clang/lib/AST/ASTImporter.cpp
+++ b/clang/lib/AST/ASTImporter.cpp
@@ -1069,22 +1069,22 @@ Error ASTNodeImporter::ImportConstraintSatisfaction(
ToSat.ContainsErrors = FromSat.ContainsErrors;
if (!ToSat.IsSatisfied) {
for (auto Record = FromSat.begin(); Record != FromSat.end(); ++Record) {
- if (Expr *E = Record->dyn_cast<Expr *>()) {
+ if (const Expr *E = Record->dyn_cast<const Expr *>()) {
ExpectedExpr ToSecondExpr = import(E);
if (!ToSecondExpr)
return ToSecondExpr.takeError();
ToSat.Details.emplace_back(ToSecondExpr.get());
} else {
- auto Pair = Record->dyn_cast<std::pair<SourceLocation, StringRef> *>();
+ auto Pair =
+ Record->dyn_cast<const ConstraintSubstitutionDiagnostic *>();
ExpectedSLoc ToPairFirst = import(Pair->first);
if (!ToPairFirst)
return ToPairFirst.takeError();
StringRef ToPairSecond = ImportASTStringRef(Pair->second);
- ToSat.Details.emplace_back(
- new (Importer.getToContext())
- ConstraintSatisfaction::SubstitutionDiagnostic{
- ToPairFirst.get(), ToPairSecond});
+ ToSat.Details.emplace_back(new (Importer.getToContext())
+ ConstraintSubstitutionDiagnostic{
+ ToPairFirst.get(), ToPairSecond});
}
}
}
diff --git a/clang/lib/AST/ByteCode/InterpBuiltin.cpp b/clang/lib/AST/ByteCode/InterpBuiltin.cpp
index a2e97fc..6053237 100644
--- a/clang/lib/AST/ByteCode/InterpBuiltin.cpp
+++ b/clang/lib/AST/ByteCode/InterpBuiltin.cpp
@@ -2773,6 +2773,50 @@ static bool interp__builtin_blend(InterpState &S, CodePtr OpPC,
return true;
}
+static bool interp__builtin_ia32_pshuf(InterpState &S, CodePtr OpPC,
+ const CallExpr *Call, bool IsShufHW) {
+ assert(Call->getNumArgs() == 2 && "masked forms handled via select*");
+ APSInt ControlImm = popToAPSInt(S, Call->getArg(1));
+ const Pointer &Src = S.Stk.pop<Pointer>();
+ const Pointer &Dst = S.Stk.peek<Pointer>();
+
+ unsigned NumElems = Dst.getNumElems();
+ PrimType ElemT = Dst.getFieldDesc()->getPrimType();
+
+ unsigned ElemBits = static_cast<unsigned>(primSize(ElemT) * 8);
+ if (ElemBits != 16 && ElemBits != 32)
+ return false;
+
+ unsigned LaneElts = 128u / ElemBits;
+ assert(LaneElts && (NumElems % LaneElts == 0));
+
+ uint8_t Ctl = static_cast<uint8_t>(ControlImm.getZExtValue());
+
+ for (unsigned Idx = 0; Idx != NumElems; Idx++) {
+ unsigned LaneBase = (Idx / LaneElts) * LaneElts;
+ unsigned LaneIdx = Idx % LaneElts;
+ unsigned SrcIdx = Idx;
+ unsigned Sel = (Ctl >> (2 * LaneIdx)) & 0x3;
+ if (ElemBits == 32) {
+ SrcIdx = LaneBase + Sel;
+ } else {
+ constexpr unsigned HalfSize = 4;
+ bool InHigh = LaneIdx >= HalfSize;
+ if (!IsShufHW && !InHigh) {
+ SrcIdx = LaneBase + Sel;
+ } else if (IsShufHW && InHigh) {
+ unsigned Rel = LaneIdx - HalfSize;
+ Sel = (Ctl >> (2 * Rel)) & 0x3;
+ SrcIdx = LaneBase + HalfSize + Sel;
+ }
+ }
+
+ INT_TYPE_SWITCH_NO_BOOL(ElemT, { Dst.elem<T>(Idx) = Src.elem<T>(SrcIdx); });
+ }
+ Dst.initializeAllElements();
+ return true;
+}
+
static bool interp__builtin_elementwise_triop(
InterpState &S, CodePtr OpPC, const CallExpr *Call,
llvm::function_ref<APInt(const APSInt &, const APSInt &, const APSInt &)>
@@ -2878,6 +2922,61 @@ static bool interp__builtin_x86_insert_subvector(InterpState &S, CodePtr OpPC,
return true;
}
+static bool interp__builtin_vec_ext(InterpState &S, CodePtr OpPC,
+ const CallExpr *Call, unsigned ID) {
+ assert(Call->getNumArgs() == 2);
+
+ APSInt ImmAPS = popToAPSInt(S, Call->getArg(1));
+ const Pointer &Vec = S.Stk.pop<Pointer>();
+ if (!Vec.getFieldDesc()->isPrimitiveArray())
+ return false;
+
+ unsigned NumElems = Vec.getNumElems();
+ unsigned Index =
+ static_cast<unsigned>(ImmAPS.getZExtValue() & (NumElems - 1));
+
+ PrimType ElemPT = Vec.getFieldDesc()->getPrimType();
+ // FIXME(#161685): Replace float+int split with a numeric-only type switch
+ if (ElemPT == PT_Float) {
+ S.Stk.push<Floating>(Vec.elem<Floating>(Index));
+ return true;
+ }
+ INT_TYPE_SWITCH_NO_BOOL(ElemPT, {
+ APSInt V = Vec.elem<T>(Index).toAPSInt();
+ pushInteger(S, V, Call->getType());
+ });
+
+ return true;
+}
+
+static bool interp__builtin_vec_set(InterpState &S, CodePtr OpPC,
+ const CallExpr *Call, unsigned ID) {
+ assert(Call->getNumArgs() == 3);
+
+ APSInt ImmAPS = popToAPSInt(S, Call->getArg(2));
+ APSInt ValAPS = popToAPSInt(S, Call->getArg(1));
+
+ const Pointer &Base = S.Stk.pop<Pointer>();
+ if (!Base.getFieldDesc()->isPrimitiveArray())
+ return false;
+
+ const Pointer &Dst = S.Stk.peek<Pointer>();
+
+ unsigned NumElems = Base.getNumElems();
+ unsigned Index =
+ static_cast<unsigned>(ImmAPS.getZExtValue() & (NumElems - 1));
+
+ PrimType ElemPT = Base.getFieldDesc()->getPrimType();
+ INT_TYPE_SWITCH_NO_BOOL(ElemPT, {
+ for (unsigned I = 0; I != NumElems; ++I)
+ Dst.elem<T>(I) = Base.elem<T>(I);
+ Dst.elem<T>(Index) = static_cast<T>(ValAPS);
+ });
+
+ Dst.initializeAllElements();
+ return true;
+}
+
bool InterpretBuiltin(InterpState &S, CodePtr OpPC, const CallExpr *Call,
uint32_t BuiltinID) {
if (!S.getASTContext().BuiltinInfo.isConstantEvaluated(BuiltinID))
@@ -3606,6 +3705,21 @@ bool InterpretBuiltin(InterpState &S, CodePtr OpPC, const CallExpr *Call,
case X86::BI__builtin_ia32_selectpd_512:
return interp__builtin_select(S, OpPC, Call);
+ case X86::BI__builtin_ia32_pshuflw:
+ case X86::BI__builtin_ia32_pshuflw256:
+ case X86::BI__builtin_ia32_pshuflw512:
+ return interp__builtin_ia32_pshuf(S, OpPC, Call, false);
+
+ case X86::BI__builtin_ia32_pshufhw:
+ case X86::BI__builtin_ia32_pshufhw256:
+ case X86::BI__builtin_ia32_pshufhw512:
+ return interp__builtin_ia32_pshuf(S, OpPC, Call, true);
+
+ case X86::BI__builtin_ia32_pshufd:
+ case X86::BI__builtin_ia32_pshufd256:
+ case X86::BI__builtin_ia32_pshufd512:
+ return interp__builtin_ia32_pshuf(S, OpPC, Call, false);
+
case X86::BI__builtin_ia32_kandqi:
case X86::BI__builtin_ia32_kandhi:
case X86::BI__builtin_ia32_kandsi:
@@ -3686,6 +3800,29 @@ bool InterpretBuiltin(InterpState &S, CodePtr OpPC, const CallExpr *Call,
case X86::BI__builtin_ia32_insert128i256:
return interp__builtin_x86_insert_subvector(S, OpPC, Call, BuiltinID);
+ case X86::BI__builtin_ia32_vec_ext_v4hi:
+ case X86::BI__builtin_ia32_vec_ext_v16qi:
+ case X86::BI__builtin_ia32_vec_ext_v8hi:
+ case X86::BI__builtin_ia32_vec_ext_v4si:
+ case X86::BI__builtin_ia32_vec_ext_v2di:
+ case X86::BI__builtin_ia32_vec_ext_v32qi:
+ case X86::BI__builtin_ia32_vec_ext_v16hi:
+ case X86::BI__builtin_ia32_vec_ext_v8si:
+ case X86::BI__builtin_ia32_vec_ext_v4di:
+ case X86::BI__builtin_ia32_vec_ext_v4sf:
+ return interp__builtin_vec_ext(S, OpPC, Call, BuiltinID);
+
+ case X86::BI__builtin_ia32_vec_set_v4hi:
+ case X86::BI__builtin_ia32_vec_set_v16qi:
+ case X86::BI__builtin_ia32_vec_set_v8hi:
+ case X86::BI__builtin_ia32_vec_set_v4si:
+ case X86::BI__builtin_ia32_vec_set_v2di:
+ case X86::BI__builtin_ia32_vec_set_v32qi:
+ case X86::BI__builtin_ia32_vec_set_v16hi:
+ case X86::BI__builtin_ia32_vec_set_v8si:
+ case X86::BI__builtin_ia32_vec_set_v4di:
+ return interp__builtin_vec_set(S, OpPC, Call, BuiltinID);
+
default:
S.FFDiag(S.Current->getLocation(OpPC),
diag::note_invalid_subexpr_in_const_expr)
diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp
index b706b14..7bf28d9 100644
--- a/clang/lib/AST/ExprConstant.cpp
+++ b/clang/lib/AST/ExprConstant.cpp
@@ -11615,6 +11615,60 @@ static bool evalPackBuiltin(const CallExpr *E, EvalInfo &Info, APValue &Result,
return true;
}
+static bool evalPshufBuiltin(EvalInfo &Info, const CallExpr *Call,
+ bool IsShufHW, APValue &Out) {
+ APValue Vec;
+ APSInt Imm;
+ if (!EvaluateAsRValue(Info, Call->getArg(0), Vec))
+ return false;
+ if (!EvaluateInteger(Call->getArg(1), Imm, Info))
+ return false;
+
+ const auto *VT = Call->getType()->getAs<VectorType>();
+ if (!VT)
+ return false;
+
+ QualType ElemT = VT->getElementType();
+ unsigned ElemBits = Info.Ctx.getTypeSize(ElemT);
+ unsigned NumElts = VT->getNumElements();
+
+ unsigned LaneBits = 128u;
+ unsigned LaneElts = LaneBits / ElemBits;
+ if (!LaneElts || (NumElts % LaneElts) != 0)
+ return false;
+
+ uint8_t Ctl = static_cast<uint8_t>(Imm.getZExtValue());
+
+ SmallVector<APValue, 32> ResultElements;
+ ResultElements.reserve(NumElts);
+
+ for (unsigned Idx = 0; Idx != NumElts; Idx++) {
+ unsigned LaneBase = (Idx / LaneElts) * LaneElts;
+ unsigned LaneIdx = Idx % LaneElts;
+ unsigned SrcIdx = Idx;
+ unsigned Sel = (Ctl >> (2 * LaneIdx)) & 0x3;
+
+ if (ElemBits == 32) {
+ SrcIdx = LaneBase + Sel;
+ } else {
+ constexpr unsigned HalfSize = 4;
+ bool InHigh = LaneIdx >= HalfSize;
+ if (!IsShufHW && !InHigh) {
+ SrcIdx = LaneBase + Sel;
+ } else if (IsShufHW && InHigh) {
+ unsigned Rel = LaneIdx - HalfSize;
+ Sel = (Ctl >> (2 * Rel)) & 0x3;
+ SrcIdx = LaneBase + HalfSize + Sel;
+ }
+ }
+
+ ResultElements.push_back(Vec.getVectorElt(SrcIdx));
+ }
+
+ Out = APValue(ResultElements.data(), ResultElements.size());
+ return true;
+}
+
bool VectorExprEvaluator::VisitCallExpr(const CallExpr *E) {
if (!IsConstantEvaluatedBuiltinCall(E))
return ExprEvaluatorBaseTy::VisitCallExpr(E);
@@ -11868,7 +11922,6 @@ bool VectorExprEvaluator::VisitCallExpr(const CallExpr *E) {
return Success(APValue(ResultElements.data(), ResultElements.size()), E);
}
-
case clang::X86::BI__builtin_ia32_vprotbi:
case clang::X86::BI__builtin_ia32_vprotdi:
case clang::X86::BI__builtin_ia32_vprotqi:
@@ -12087,6 +12140,34 @@ bool VectorExprEvaluator::VisitCallExpr(const CallExpr *E) {
return Success(APValue(ResultElements.data(), ResultElements.size()), E);
}
+
+ case X86::BI__builtin_ia32_pshuflw:
+ case X86::BI__builtin_ia32_pshuflw256:
+ case X86::BI__builtin_ia32_pshuflw512: {
+ APValue R;
+ if (!evalPshufBuiltin(Info, E, false, R))
+ return false;
+ return Success(R, E);
+ }
+
+ case X86::BI__builtin_ia32_pshufhw:
+ case X86::BI__builtin_ia32_pshufhw256:
+ case X86::BI__builtin_ia32_pshufhw512: {
+ APValue R;
+ if (!evalPshufBuiltin(Info, E, true, R))
+ return false;
+ return Success(R, E);
+ }
+
+ case X86::BI__builtin_ia32_pshufd:
+ case X86::BI__builtin_ia32_pshufd256:
+ case X86::BI__builtin_ia32_pshufd512: {
+ APValue R;
+ if (!evalPshufBuiltin(Info, E, false, R))
+ return false;
+ return Success(R, E);
+ }
+
case Builtin::BI__builtin_elementwise_clzg:
case Builtin::BI__builtin_elementwise_ctzg: {
APValue SourceLHS;
@@ -12235,6 +12316,41 @@ bool VectorExprEvaluator::VisitCallExpr(const CallExpr *E) {
return Success(APValue(ResultElements.data(), ResultElements.size()), E);
}
+
+ case clang::X86::BI__builtin_ia32_vec_set_v4hi:
+ case clang::X86::BI__builtin_ia32_vec_set_v16qi:
+ case clang::X86::BI__builtin_ia32_vec_set_v8hi:
+ case clang::X86::BI__builtin_ia32_vec_set_v4si:
+ case clang::X86::BI__builtin_ia32_vec_set_v2di:
+ case clang::X86::BI__builtin_ia32_vec_set_v32qi:
+ case clang::X86::BI__builtin_ia32_vec_set_v16hi:
+ case clang::X86::BI__builtin_ia32_vec_set_v8si:
+ case clang::X86::BI__builtin_ia32_vec_set_v4di: {
+ APValue VecVal;
+ APSInt Scalar, IndexAPS;
+ if (!EvaluateVector(E->getArg(0), VecVal, Info) ||
+ !EvaluateInteger(E->getArg(1), Scalar, Info) ||
+ !EvaluateInteger(E->getArg(2), IndexAPS, Info))
+ return false;
+
+ QualType ElemTy = E->getType()->castAs<VectorType>()->getElementType();
+ unsigned ElemWidth = Info.Ctx.getIntWidth(ElemTy);
+ bool ElemUnsigned = ElemTy->isUnsignedIntegerOrEnumerationType();
+ Scalar.setIsUnsigned(ElemUnsigned);
+ APSInt ElemAPS = Scalar.extOrTrunc(ElemWidth);
+ APValue ElemAV(ElemAPS);
+
+ unsigned NumElems = VecVal.getVectorLength();
+ unsigned Index =
+ static_cast<unsigned>(IndexAPS.getZExtValue() & (NumElems - 1));
+
+ SmallVector<APValue, 4> Elems;
+ Elems.reserve(NumElems);
+ for (unsigned ElemNum = 0; ElemNum != NumElems; ++ElemNum)
+ Elems.push_back(ElemNum == Index ? ElemAV : VecVal.getVectorElt(ElemNum));
+
+ return Success(APValue(Elems.data(), NumElems), E);
+ }
}
}
@@ -14822,6 +14938,25 @@ bool IntExprEvaluator::VisitBuiltinCallExpr(const CallExpr *E,
return HandleMaskBinOp(
[](const APSInt &LHS, const APSInt &RHS) { return LHS + RHS; });
}
+
+ case clang::X86::BI__builtin_ia32_vec_ext_v4hi:
+ case clang::X86::BI__builtin_ia32_vec_ext_v16qi:
+ case clang::X86::BI__builtin_ia32_vec_ext_v8hi:
+ case clang::X86::BI__builtin_ia32_vec_ext_v4si:
+ case clang::X86::BI__builtin_ia32_vec_ext_v2di:
+ case clang::X86::BI__builtin_ia32_vec_ext_v32qi:
+ case clang::X86::BI__builtin_ia32_vec_ext_v16hi:
+ case clang::X86::BI__builtin_ia32_vec_ext_v8si:
+ case clang::X86::BI__builtin_ia32_vec_ext_v4di: {
+ APValue Vec;
+ APSInt IdxAPS;
+ if (!EvaluateVector(E->getArg(0), Vec, Info) ||
+ !EvaluateInteger(E->getArg(1), IdxAPS, Info))
+ return false;
+ unsigned N = Vec.getVectorLength();
+ unsigned Idx = static_cast<unsigned>(IdxAPS.getZExtValue() & (N - 1));
+ return Success(Vec.getVectorElt(Idx).getInt(), E);
+ }
}
}
@@ -16638,6 +16773,17 @@ bool FloatExprEvaluator::VisitCallExpr(const CallExpr *E) {
(void)Result.fusedMultiplyAdd(SourceY, SourceZ, RM);
return true;
}
+
+ case clang::X86::BI__builtin_ia32_vec_ext_v4sf: {
+ APValue Vec;
+ APSInt IdxAPS;
+ if (!EvaluateVector(E->getArg(0), Vec, Info) ||
+ !EvaluateInteger(E->getArg(1), IdxAPS, Info))
+ return false;
+ unsigned N = Vec.getVectorLength();
+ unsigned Idx = static_cast<unsigned>(IdxAPS.getZExtValue() & (N - 1));
+ return Success(Vec.getVectorElt(Idx), E);
+ }
}
}