aboutsummaryrefslogtreecommitdiff
path: root/clang/lib/AST/ByteCode
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib/AST/ByteCode')
-rw-r--r--clang/lib/AST/ByteCode/Compiler.cpp2
-rw-r--r--clang/lib/AST/ByteCode/Interp.cpp3
-rw-r--r--clang/lib/AST/ByteCode/Interp.h8
-rw-r--r--clang/lib/AST/ByteCode/InterpBlock.cpp13
-rw-r--r--clang/lib/AST/ByteCode/InterpBlock.h2
-rw-r--r--clang/lib/AST/ByteCode/InterpBuiltin.cpp53
-rw-r--r--clang/lib/AST/ByteCode/InterpState.h2
-rw-r--r--clang/lib/AST/ByteCode/Pointer.cpp2
-rw-r--r--clang/lib/AST/ByteCode/Program.cpp6
9 files changed, 72 insertions, 19 deletions
diff --git a/clang/lib/AST/ByteCode/Compiler.cpp b/clang/lib/AST/ByteCode/Compiler.cpp
index c71fd22..74cae03 100644
--- a/clang/lib/AST/ByteCode/Compiler.cpp
+++ b/clang/lib/AST/ByteCode/Compiler.cpp
@@ -4660,7 +4660,7 @@ const RecordType *Compiler<Emitter>::getRecordTy(QualType Ty) {
template <class Emitter> Record *Compiler<Emitter>::getRecord(QualType Ty) {
if (const auto *RecordTy = getRecordTy(Ty))
- return getRecord(RecordTy->getOriginalDecl()->getDefinitionOrSelf());
+ return getRecord(RecordTy->getDecl()->getDefinitionOrSelf());
return nullptr;
}
diff --git a/clang/lib/AST/ByteCode/Interp.cpp b/clang/lib/AST/ByteCode/Interp.cpp
index 8904396..a72282c 100644
--- a/clang/lib/AST/ByteCode/Interp.cpp
+++ b/clang/lib/AST/ByteCode/Interp.cpp
@@ -1358,9 +1358,6 @@ bool Free(InterpState &S, CodePtr OpPC, bool DeleteIsArrayForm,
void diagnoseEnumValue(InterpState &S, CodePtr OpPC, const EnumDecl *ED,
const APSInt &Value) {
- if (S.EvaluatingDecl && !S.EvaluatingDecl->isConstexpr())
- return;
-
llvm::APInt Min;
llvm::APInt Max;
ED->getValueRange(Max, Min);
diff --git a/clang/lib/AST/ByteCode/Interp.h b/clang/lib/AST/ByteCode/Interp.h
index 57cc705..2f7e2d9 100644
--- a/clang/lib/AST/ByteCode/Interp.h
+++ b/clang/lib/AST/ByteCode/Interp.h
@@ -2258,6 +2258,8 @@ std::optional<Pointer> OffsetHelper(InterpState &S, CodePtr OpPC,
S.CCEDiag(S.Current->getSource(OpPC), diag::note_constexpr_array_index)
<< N << /*non-array*/ true << 0;
return Pointer(Ptr.asFunctionPointer().getFunction(), N);
+ } else if (!Ptr.isBlockPointer()) {
+ return std::nullopt;
}
assert(Ptr.isBlockPointer());
@@ -3096,7 +3098,8 @@ inline bool ArrayElemPtr(InterpState &S, CodePtr OpPC) {
}
if (Offset.isZero()) {
- if (Ptr.getFieldDesc()->isArray() && Ptr.getIndex() == 0) {
+ if (const Descriptor *Desc = Ptr.getFieldDesc();
+ Desc && Desc->isArray() && Ptr.getIndex() == 0) {
S.Stk.push<Pointer>(Ptr.atIndex(0).narrow());
return true;
}
@@ -3126,7 +3129,8 @@ inline bool ArrayElemPtrPop(InterpState &S, CodePtr OpPC) {
}
if (Offset.isZero()) {
- if (Ptr.getFieldDesc()->isArray() && Ptr.getIndex() == 0) {
+ if (const Descriptor *Desc = Ptr.getFieldDesc();
+ Desc && Desc->isArray() && Ptr.getIndex() == 0) {
S.Stk.push<Pointer>(Ptr.atIndex(0).narrow());
return true;
}
diff --git a/clang/lib/AST/ByteCode/InterpBlock.cpp b/clang/lib/AST/ByteCode/InterpBlock.cpp
index ac6f01f..24825ad 100644
--- a/clang/lib/AST/ByteCode/InterpBlock.cpp
+++ b/clang/lib/AST/ByteCode/InterpBlock.cpp
@@ -100,6 +100,19 @@ bool Block::hasPointer(const Pointer *P) const {
}
#endif
+void Block::movePointersTo(Block *B) {
+ assert(B != this);
+
+ while (Pointers) {
+ Pointer *P = Pointers;
+
+ this->removePointer(P);
+ P->BS.Pointee = B;
+ B->addPointer(P);
+ }
+ assert(!this->hasPointers());
+}
+
DeadBlock::DeadBlock(DeadBlock *&Root, Block *Blk)
: Root(Root), B(~0u, Blk->Desc, Blk->isExtern(), Blk->IsStatic,
Blk->isWeak(), Blk->isDummy(), /*IsDead=*/true) {
diff --git a/clang/lib/AST/ByteCode/InterpBlock.h b/clang/lib/AST/ByteCode/InterpBlock.h
index 9b3dadc..73fdc8d 100644
--- a/clang/lib/AST/ByteCode/InterpBlock.h
+++ b/clang/lib/AST/ByteCode/InterpBlock.h
@@ -92,6 +92,8 @@ public:
bool isInitialized() const { return IsInitialized; }
/// The Evaluation ID this block was created in.
unsigned getEvalID() const { return EvalID; }
+ /// Move all pointers from this block to \param B.
+ void movePointersTo(Block *B);
/// Returns a pointer to the stored data.
/// You are allowed to read Desc->getSize() bytes from this address.
diff --git a/clang/lib/AST/ByteCode/InterpBuiltin.cpp b/clang/lib/AST/ByteCode/InterpBuiltin.cpp
index b69f360..0cb4910 100644
--- a/clang/lib/AST/ByteCode/InterpBuiltin.cpp
+++ b/clang/lib/AST/ByteCode/InterpBuiltin.cpp
@@ -23,7 +23,7 @@
namespace clang {
namespace interp {
-LLVM_ATTRIBUTE_UNUSED static bool isNoopBuiltin(unsigned ID) {
+[[maybe_unused]] static bool isNoopBuiltin(unsigned ID) {
switch (ID) {
case Builtin::BIas_const:
case Builtin::BIforward:
@@ -3101,6 +3101,33 @@ static bool interp__builtin_vec_set(InterpState &S, CodePtr OpPC,
return true;
}
+static bool interp__builtin_ia32_vpconflict(InterpState &S, CodePtr OpPC,
+ const CallExpr *Call) {
+ assert(Call->getNumArgs() == 1);
+
+ QualType Arg0Type = Call->getArg(0)->getType();
+ const auto *VecT = Arg0Type->castAs<VectorType>();
+ PrimType ElemT = *S.getContext().classify(VecT->getElementType());
+ unsigned NumElems = VecT->getNumElements();
+ bool DestUnsigned = Call->getType()->isUnsignedIntegerOrEnumerationType();
+ const Pointer &Src = S.Stk.pop<Pointer>();
+ const Pointer &Dst = S.Stk.peek<Pointer>();
+
+ for (unsigned I = 0; I != NumElems; ++I) {
+ INT_TYPE_SWITCH_NO_BOOL(ElemT, {
+ APSInt ElemI = Src.elem<T>(I).toAPSInt();
+ APInt ConflictMask(ElemI.getBitWidth(), 0);
+ for (unsigned J = 0; J != I; ++J) {
+ APSInt ElemJ = Src.elem<T>(J).toAPSInt();
+ ConflictMask.setBitVal(J, ElemI == ElemJ);
+ }
+ Dst.elem<T>(I) = static_cast<T>(APSInt(ConflictMask, DestUnsigned));
+ });
+ }
+ Dst.initializeAllElements();
+ return true;
+}
+
bool InterpretBuiltin(InterpState &S, CodePtr OpPC, const CallExpr *Call,
uint32_t BuiltinID) {
if (!S.getASTContext().BuiltinInfo.isConstantEvaluated(BuiltinID))
@@ -3258,14 +3285,14 @@ bool InterpretBuiltin(InterpState &S, CodePtr OpPC, const CallExpr *Call,
case Builtin::BI__builtin_parityl:
case Builtin::BI__builtin_parityll:
return interp__builtin_elementwise_int_unaryop(
- S, OpPC, Call, [](const APSInt &Val) -> APInt {
+ S, OpPC, Call, [](const APSInt &Val) {
return APInt(Val.getBitWidth(), Val.popcount() % 2);
});
case Builtin::BI__builtin_clrsb:
case Builtin::BI__builtin_clrsbl:
case Builtin::BI__builtin_clrsbll:
return interp__builtin_elementwise_int_unaryop(
- S, OpPC, Call, [](const APSInt &Val) -> APInt {
+ S, OpPC, Call, [](const APSInt &Val) {
return APInt(Val.getBitWidth(),
Val.getBitWidth() - Val.getSignificantBits());
});
@@ -3274,8 +3301,7 @@ bool InterpretBuiltin(InterpState &S, CodePtr OpPC, const CallExpr *Call,
case Builtin::BI__builtin_bitreverse32:
case Builtin::BI__builtin_bitreverse64:
return interp__builtin_elementwise_int_unaryop(
- S, OpPC, Call,
- [](const APSInt &Val) -> APInt { return Val.reverseBits(); });
+ S, OpPC, Call, [](const APSInt &Val) { return Val.reverseBits(); });
case Builtin::BI__builtin_classify_type:
return interp__builtin_classify_type(S, OpPC, Frame, Call);
@@ -3595,6 +3621,15 @@ bool InterpretBuiltin(InterpState &S, CodePtr OpPC, const CallExpr *Call,
return LHS.isSigned() ? LHS.ssub_sat(RHS) : LHS.usub_sat(RHS);
});
+ case clang::X86::BI__builtin_ia32_pmulhrsw128:
+ case clang::X86::BI__builtin_ia32_pmulhrsw256:
+ case clang::X86::BI__builtin_ia32_pmulhrsw512:
+ return interp__builtin_elementwise_int_binop(
+ S, OpPC, Call, [](const APSInt &LHS, const APSInt &RHS) {
+ return (llvm::APIntOps::mulsExtended(LHS, RHS).ashr(14) + 1)
+ .extractBits(16, 1);
+ });
+
case clang::X86::BI__builtin_ia32_pavgb128:
case clang::X86::BI__builtin_ia32_pavgw128:
case clang::X86::BI__builtin_ia32_pavgb256:
@@ -3891,7 +3926,13 @@ bool InterpretBuiltin(InterpState &S, CodePtr OpPC, const CallExpr *Call,
[](const APSInt &Lo, const APSInt &Hi, const APSInt &Amt) {
return llvm::APIntOps::fshr(Hi, Lo, Amt);
});
-
+ case X86::BI__builtin_ia32_vpconflictsi_128:
+ case X86::BI__builtin_ia32_vpconflictsi_256:
+ case X86::BI__builtin_ia32_vpconflictsi_512:
+ case X86::BI__builtin_ia32_vpconflictdi_128:
+ case X86::BI__builtin_ia32_vpconflictdi_256:
+ case X86::BI__builtin_ia32_vpconflictdi_512:
+ return interp__builtin_ia32_vpconflict(S, OpPC, Call);
case clang::X86::BI__builtin_ia32_blendpd:
case clang::X86::BI__builtin_ia32_blendpd256:
case clang::X86::BI__builtin_ia32_blendps:
diff --git a/clang/lib/AST/ByteCode/InterpState.h b/clang/lib/AST/ByteCode/InterpState.h
index a13244b..e2e4d5c 100644
--- a/clang/lib/AST/ByteCode/InterpState.h
+++ b/clang/lib/AST/ByteCode/InterpState.h
@@ -114,7 +114,7 @@ public:
Alloc = std::make_unique<DynamicAllocator>();
}
- return *Alloc.get();
+ return *Alloc;
}
/// Diagnose any dynamic allocations that haven't been freed yet.
diff --git a/clang/lib/AST/ByteCode/Pointer.cpp b/clang/lib/AST/ByteCode/Pointer.cpp
index 663134c..e417bdf 100644
--- a/clang/lib/AST/ByteCode/Pointer.cpp
+++ b/clang/lib/AST/ByteCode/Pointer.cpp
@@ -751,7 +751,7 @@ std::optional<APValue> Pointer::toRValue(const Context &Ctx,
assert(Record && "Missing record descriptor");
bool Ok = true;
- if (RT->getOriginalDecl()->isUnion()) {
+ if (RT->getDecl()->isUnion()) {
const FieldDecl *ActiveField = nullptr;
APValue Value;
for (const auto &F : Record->fields()) {
diff --git a/clang/lib/AST/ByteCode/Program.cpp b/clang/lib/AST/ByteCode/Program.cpp
index 75bfd9f..e653782 100644
--- a/clang/lib/AST/ByteCode/Program.cpp
+++ b/clang/lib/AST/ByteCode/Program.cpp
@@ -226,11 +226,7 @@ UnsignedOrNone Program::createGlobal(const ValueDecl *VD, const Expr *Init) {
Globals[PIdx] = NewGlobal;
// All pointers pointing to the previous extern decl now point to the
// new decl.
- for (Pointer *Ptr = RedeclBlock->Pointers; Ptr; Ptr = Ptr->BS.Next) {
- RedeclBlock->removePointer(Ptr);
- Ptr->BS.Pointee = NewGlobal->block();
- NewGlobal->block()->addPointer(Ptr);
- }
+ RedeclBlock->movePointersTo(NewGlobal->block());
}
}
PIdx = *Idx;