llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-clang Author: Timm Baeder (tbaederr) <details> <summary>Changes</summary> As a way of writing atIndex(I).deref<T>(), which creates an intermediate Pointer, which in turn adds (and removes) that pointer from the pointer list of the Block. This way we can avoid that. --- Full diff: https://github.com/llvm/llvm-project/pull/149693.diff 8 Files Affected: - (modified) clang/lib/AST/ByteCode/Context.cpp (+1-1) - (modified) clang/lib/AST/ByteCode/EvaluationResult.cpp (+1-1) - (modified) clang/lib/AST/ByteCode/Interp.h (+26-26) - (modified) clang/lib/AST/ByteCode/InterpBuiltin.cpp (+10-11) - (modified) clang/lib/AST/ByteCode/Pointer.cpp (+6-7) - (modified) clang/lib/AST/ByteCode/Pointer.h (+19) - (modified) clang/lib/AST/ByteCode/Program.cpp (+4-6) - (modified) clang/lib/AST/ExprConstant.cpp (+3-12) ``````````diff diff --git a/clang/lib/AST/ByteCode/Context.cpp b/clang/lib/AST/ByteCode/Context.cpp index 9e683d71f83bc..12b8ab5da1d1d 100644 --- a/clang/lib/AST/ByteCode/Context.cpp +++ b/clang/lib/AST/ByteCode/Context.cpp @@ -254,7 +254,7 @@ bool Context::evaluateStrlen(State &Parent, const Expr *E, uint64_t &Result) { Result = 0; for (unsigned I = Ptr.getIndex(); I != N; ++I) { INT_TYPE_SWITCH(ElemT, { - auto Elem = Ptr.atIndex(I).deref<T>(); + auto Elem = Ptr.elem<T>(I); if (Elem.isZero()) return true; ++Result; diff --git a/clang/lib/AST/ByteCode/EvaluationResult.cpp b/clang/lib/AST/ByteCode/EvaluationResult.cpp index f59612bf00015..b11531f4296a2 100644 --- a/clang/lib/AST/ByteCode/EvaluationResult.cpp +++ b/clang/lib/AST/ByteCode/EvaluationResult.cpp @@ -204,7 +204,7 @@ static void collectBlocks(const Pointer &Ptr, } else if (Desc->isPrimitiveArray() && Desc->getPrimType() == PT_Ptr) { for (unsigned I = 0; I != Desc->getNumElems(); ++I) { - const Pointer &ElemPointee = Ptr.atIndex(I).deref<Pointer>(); + const Pointer &ElemPointee = Ptr.elem<Pointer>(I); if (isUsefulPtr(ElemPointee) && !Blocks.contains(ElemPointee.block())) collectBlocks(ElemPointee, Blocks); } diff --git a/clang/lib/AST/ByteCode/Interp.h b/clang/lib/AST/ByteCode/Interp.h index 7ba6e21bd5d82..7f29200f8617f 100644 --- a/clang/lib/AST/ByteCode/Interp.h +++ b/clang/lib/AST/ByteCode/Interp.h @@ -468,10 +468,10 @@ inline bool Mulc(InterpState &S, CodePtr OpPC) { const Pointer &Result = S.Stk.peek<Pointer>(); if constexpr (std::is_same_v<T, Floating>) { - APFloat A = LHS.atIndex(0).deref<Floating>().getAPFloat(); - APFloat B = LHS.atIndex(1).deref<Floating>().getAPFloat(); - APFloat C = RHS.atIndex(0).deref<Floating>().getAPFloat(); - APFloat D = RHS.atIndex(1).deref<Floating>().getAPFloat(); + APFloat A = LHS.elem<Floating>(0).getAPFloat(); + APFloat B = LHS.elem<Floating>(1).getAPFloat(); + APFloat C = RHS.elem<Floating>(0).getAPFloat(); + APFloat D = RHS.elem<Floating>(1).getAPFloat(); APFloat ResR(A.getSemantics()); APFloat ResI(A.getSemantics()); @@ -480,20 +480,20 @@ inline bool Mulc(InterpState &S, CodePtr OpPC) { // Copy into the result. Floating RA = S.allocFloat(A.getSemantics()); RA.copy(ResR); - Result.atIndex(0).deref<Floating>() = RA; // Floating(ResR); + Result.elem<Floating>(0) = RA; // Floating(ResR); Result.atIndex(0).initialize(); Floating RI = S.allocFloat(A.getSemantics()); RI.copy(ResI); - Result.atIndex(1).deref<Floating>() = RI; // Floating(ResI); + Result.elem<Floating>(1) = RI; // Floating(ResI); Result.atIndex(1).initialize(); Result.initialize(); } else { // Integer element type. - const T &LHSR = LHS.atIndex(0).deref<T>(); - const T &LHSI = LHS.atIndex(1).deref<T>(); - const T &RHSR = RHS.atIndex(0).deref<T>(); - const T &RHSI = RHS.atIndex(1).deref<T>(); + const T &LHSR = LHS.elem<T>(0); + const T &LHSI = LHS.elem<T>(1); + const T &RHSR = RHS.elem<T>(0); + const T &RHSI = RHS.elem<T>(1); unsigned Bits = LHSR.bitWidth(); // real(Result) = (real(LHS) * real(RHS)) - (imag(LHS) * imag(RHS)) @@ -503,7 +503,7 @@ inline bool Mulc(InterpState &S, CodePtr OpPC) { T B; if (T::mul(LHSI, RHSI, Bits, &B)) return false; - if (T::sub(A, B, Bits, &Result.atIndex(0).deref<T>())) + if (T::sub(A, B, Bits, &Result.elem<T>(0))) return false; Result.atIndex(0).initialize(); @@ -512,7 +512,7 @@ inline bool Mulc(InterpState &S, CodePtr OpPC) { return false; if (T::mul(LHSI, RHSR, Bits, &B)) return false; - if (T::add(A, B, Bits, &Result.atIndex(1).deref<T>())) + if (T::add(A, B, Bits, &Result.elem<T>(1))) return false; Result.atIndex(1).initialize(); Result.initialize(); @@ -528,10 +528,10 @@ inline bool Divc(InterpState &S, CodePtr OpPC) { const Pointer &Result = S.Stk.peek<Pointer>(); if constexpr (std::is_same_v<T, Floating>) { - APFloat A = LHS.atIndex(0).deref<Floating>().getAPFloat(); - APFloat B = LHS.atIndex(1).deref<Floating>().getAPFloat(); - APFloat C = RHS.atIndex(0).deref<Floating>().getAPFloat(); - APFloat D = RHS.atIndex(1).deref<Floating>().getAPFloat(); + APFloat A = LHS.elem<Floating>(0).getAPFloat(); + APFloat B = LHS.elem<Floating>(1).getAPFloat(); + APFloat C = RHS.elem<Floating>(0).getAPFloat(); + APFloat D = RHS.elem<Floating>(1).getAPFloat(); APFloat ResR(A.getSemantics()); APFloat ResI(A.getSemantics()); @@ -540,21 +540,21 @@ inline bool Divc(InterpState &S, CodePtr OpPC) { // Copy into the result. Floating RA = S.allocFloat(A.getSemantics()); RA.copy(ResR); - Result.atIndex(0).deref<Floating>() = RA; // Floating(ResR); + Result.elem<Floating>(0) = RA; // Floating(ResR); Result.atIndex(0).initialize(); Floating RI = S.allocFloat(A.getSemantics()); RI.copy(ResI); - Result.atIndex(1).deref<Floating>() = RI; // Floating(ResI); + Result.elem<Floating>(1) = RI; // Floating(ResI); Result.atIndex(1).initialize(); Result.initialize(); } else { // Integer element type. - const T &LHSR = LHS.atIndex(0).deref<T>(); - const T &LHSI = LHS.atIndex(1).deref<T>(); - const T &RHSR = RHS.atIndex(0).deref<T>(); - const T &RHSI = RHS.atIndex(1).deref<T>(); + const T &LHSR = LHS.elem<T>(0); + const T &LHSI = LHS.elem<T>(1); + const T &RHSR = RHS.elem<T>(0); + const T &RHSI = RHS.elem<T>(1); unsigned Bits = LHSR.bitWidth(); const T Zero = T::from(0, Bits); @@ -581,8 +581,8 @@ inline bool Divc(InterpState &S, CodePtr OpPC) { } // real(Result) = ((real(LHS) * real(RHS)) + (imag(LHS) * imag(RHS))) / Den - T &ResultR = Result.atIndex(0).deref<T>(); - T &ResultI = Result.atIndex(1).deref<T>(); + T &ResultR = Result.elem<T>(0); + T &ResultI = Result.elem<T>(1); if (T::mul(LHSR, RHSR, Bits, &A) || T::mul(LHSI, RHSI, Bits, &B)) return false; @@ -3103,7 +3103,7 @@ inline bool ArrayElem(InterpState &S, CodePtr OpPC, uint32_t Index) { return false; assert(Ptr.atIndex(Index).getFieldDesc()->getPrimType() == Name); - S.Stk.push<T>(Ptr.atIndex(Index).deref<T>()); + S.Stk.push<T>(Ptr.elem<T>(Index)); return true; } @@ -3115,7 +3115,7 @@ inline bool ArrayElemPop(InterpState &S, CodePtr OpPC, uint32_t Index) { return false; assert(Ptr.atIndex(Index).getFieldDesc()->getPrimType() == Name); - S.Stk.push<T>(Ptr.atIndex(Index).deref<T>()); + S.Stk.push<T>(Ptr.elem<T>(Index)); return true; } diff --git a/clang/lib/AST/ByteCode/InterpBuiltin.cpp b/clang/lib/AST/ByteCode/InterpBuiltin.cpp index 462b9a11e0a5c..f86d26edbb526 100644 --- a/clang/lib/AST/ByteCode/InterpBuiltin.cpp +++ b/clang/lib/AST/ByteCode/InterpBuiltin.cpp @@ -1098,9 +1098,9 @@ static bool interp__builtin_complex(InterpState &S, CodePtr OpPC, const Floating &Arg1 = S.Stk.pop<Floating>(); Pointer &Result = S.Stk.peek<Pointer>(); - Result.atIndex(0).deref<Floating>() = Arg1; + Result.elem<Floating>(0) = Arg1; Result.atIndex(0).initialize(); - Result.atIndex(1).deref<Floating>() = Arg2; + Result.elem<Floating>(1) = Arg2; Result.atIndex(1).initialize(); Result.initialize(); @@ -1644,10 +1644,10 @@ static bool interp__builtin_vector_reduce(InterpState &S, CodePtr OpPC, unsigned NumElems = Arg.getNumElems(); INT_TYPE_SWITCH_NO_BOOL(ElemT, { - T Result = Arg.atIndex(0).deref<T>(); + T Result = Arg.elem<T>(0); unsigned BitWidth = Result.bitWidth(); for (unsigned I = 1; I != NumElems; ++I) { - T Elem = Arg.atIndex(I).deref<T>(); + T Elem = Arg.elem<T>(I); T PrevResult = Result; if (ID == Builtin::BI__builtin_reduce_add) { @@ -1723,11 +1723,10 @@ static bool interp__builtin_elementwise_popcount(InterpState &S, CodePtr OpPC, for (unsigned I = 0; I != NumElems; ++I) { INT_TYPE_SWITCH_NO_BOOL(ElemT, { if (BuiltinID == Builtin::BI__builtin_elementwise_popcount) { - Dst.atIndex(I).deref<T>() = - T::from(Arg.atIndex(I).deref<T>().toAPSInt().popcount()); + Dst.elem<T>(I) = T::from(Arg.elem<T>(I).toAPSInt().popcount()); } else { - Dst.atIndex(I).deref<T>() = T::from( - Arg.atIndex(I).deref<T>().toAPSInt().reverseBits().getZExtValue()); + Dst.elem<T>(I) = + T::from(Arg.elem<T>(I).toAPSInt().reverseBits().getZExtValue()); } Dst.atIndex(I).initialize(); }); @@ -2296,8 +2295,8 @@ static bool interp__builtin_elementwise_sat(InterpState &S, CodePtr OpPC, APSInt Elem1; APSInt Elem2; INT_TYPE_SWITCH_NO_BOOL(ElemT, { - Elem1 = LHS.atIndex(I).deref<T>().toAPSInt(); - Elem2 = RHS.atIndex(I).deref<T>().toAPSInt(); + Elem1 = LHS.elem<T>(I).toAPSInt(); + Elem2 = RHS.elem<T>(I).toAPSInt(); }); APSInt Result; @@ -2942,7 +2941,7 @@ static bool copyComposite(InterpState &S, CodePtr OpPC, const Pointer &Src, for (unsigned I = 0, N = DestDesc->getNumElems(); I != N; ++I) { Pointer DestElem = Dest.atIndex(I); TYPE_SWITCH(ET, { - DestElem.deref<T>() = Src.atIndex(I).deref<T>(); + DestElem.deref<T>() = Src.elem<T>(I); DestElem.initialize(); }); } diff --git a/clang/lib/AST/ByteCode/Pointer.cpp b/clang/lib/AST/ByteCode/Pointer.cpp index 2f9ecf98e558e..c4d06d6a430d3 100644 --- a/clang/lib/AST/ByteCode/Pointer.cpp +++ b/clang/lib/AST/ByteCode/Pointer.cpp @@ -760,14 +760,14 @@ std::optional<APValue> Pointer::toRValue(const Context &Ctx, std::optional<PrimType> ElemT = Ctx.classify(ElemTy); assert(ElemT); INT_TYPE_SWITCH(*ElemT, { - auto V1 = Ptr.atIndex(0).deref<T>(); - auto V2 = Ptr.atIndex(1).deref<T>(); + auto V1 = Ptr.elem<T>(0); + auto V2 = Ptr.elem<T>(1); R = APValue(V1.toAPSInt(), V2.toAPSInt()); return true; }); } else if (ElemTy->isFloatingType()) { - R = APValue(Ptr.atIndex(0).deref<Floating>().getAPFloat(), - Ptr.atIndex(1).deref<Floating>().getAPFloat()); + R = APValue(Ptr.elem<Floating>(0).getAPFloat(), + Ptr.elem<Floating>(1).getAPFloat()); return true; } return false; @@ -782,9 +782,8 @@ std::optional<APValue> Pointer::toRValue(const Context &Ctx, SmallVector<APValue> Values; Values.reserve(VT->getNumElements()); for (unsigned I = 0; I != VT->getNumElements(); ++I) { - TYPE_SWITCH(ElemT, { - Values.push_back(Ptr.atIndex(I).deref<T>().toAPValue(ASTCtx)); - }); + TYPE_SWITCH(ElemT, + { Values.push_back(Ptr.elem<T>(I).toAPValue(ASTCtx)); }); } assert(Values.size() == VT->getNumElements()); diff --git a/clang/lib/AST/ByteCode/Pointer.h b/clang/lib/AST/ByteCode/Pointer.h index da74013cf83a6..d17eba5da9ca6 100644 --- a/clang/lib/AST/ByteCode/Pointer.h +++ b/clang/lib/AST/ByteCode/Pointer.h @@ -693,6 +693,25 @@ class Pointer { return *reinterpret_cast<T *>(asBlockPointer().Pointee->rawData() + Offset); } + /// Dereferences the element at index \p I. + /// This is equivalent to atIndex(I).deref<T>(). + template <typename T> T &elem(unsigned I) const { + assert(isLive() && "Invalid pointer"); + assert(isBlockPointer()); + assert(asBlockPointer().Pointee); + assert(isDereferencable()); + assert(getFieldDesc()->isPrimitiveArray()); + + unsigned ElemByteOffset = I * getFieldDesc()->getElemSize(); + if (isArrayRoot()) + return *reinterpret_cast<T *>(asBlockPointer().Pointee->rawData() + + asBlockPointer().Base + sizeof(InitMapPtr) + + ElemByteOffset); + + return *reinterpret_cast<T *>(asBlockPointer().Pointee->rawData() + Offset + + ElemByteOffset); + } + /// Whether this block can be read from at all. This is only true for /// block pointers that point to a valid location inside that block. bool isDereferencable() const { diff --git a/clang/lib/AST/ByteCode/Program.cpp b/clang/lib/AST/ByteCode/Program.cpp index 5ac0f59f32d4e..af6d7c7110629 100644 --- a/clang/lib/AST/ByteCode/Program.cpp +++ b/clang/lib/AST/ByteCode/Program.cpp @@ -74,27 +74,25 @@ unsigned Program::createGlobalString(const StringLiteral *S, const Expr *Base) { const Pointer Ptr(G->block()); if (CharWidth == 1) { - std::memcpy(&Ptr.atIndex(0).deref<char>(), S->getString().data(), - StringLength); + std::memcpy(&Ptr.elem<char>(0), S->getString().data(), StringLength); } else { // Construct the string in storage. for (unsigned I = 0; I <= StringLength; ++I) { - Pointer Field = Ptr.atIndex(I); const uint32_t CodePoint = I == StringLength ? 0 : S->getCodeUnit(I); switch (CharType) { case PT_Sint8: { using T = PrimConv<PT_Sint8>::T; - Field.deref<T>() = T::from(CodePoint, BitWidth); + Ptr.elem<T>(I) = T::from(CodePoint, BitWidth); break; } case PT_Uint16: { using T = PrimConv<PT_Uint16>::T; - Field.deref<T>() = T::from(CodePoint, BitWidth); + Ptr.elem<T>(I) = T::from(CodePoint, BitWidth); break; } case PT_Uint32: { using T = PrimConv<PT_Uint32>::T; - Field.deref<T>() = T::from(CodePoint, BitWidth); + Ptr.elem<T>(I) = T::from(CodePoint, BitWidth); break; } default: diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp index 0d12161756467..2ab94362f9aa5 100644 --- a/clang/lib/AST/ExprConstant.cpp +++ b/clang/lib/AST/ExprConstant.cpp @@ -9346,13 +9346,9 @@ bool LValueExprEvaluator::VisitUnaryDeref(const UnaryOperator *E) { // [C++26][expr.unary.op] // If the operand points to an object or function, the result // denotes that object or function; otherwise, the behavior is undefined. - // Because &(*(type*)0) is a common pattern, we do not fail the evaluation - // immediately. - if (!Success || !E->getType().getNonReferenceType()->isObjectType()) - return Success; - return bool(findCompleteObject(Info, E, AK_Dereference, Result, - E->getType())) || - Info.noteUndefinedBehavior(); + return Success && + (!E->getType().getNonReferenceType()->isObjectType() || + findCompleteObject(Info, E, AK_Dereference, Result, E->getType())); } bool LValueExprEvaluator::VisitUnaryReal(const UnaryOperator *E) { @@ -18022,11 +18018,6 @@ bool Expr::isPotentialConstantExprUnevaluated(Expr *E, Info.InConstantContext = true; Info.CheckingPotentialConstantExpression = true; - if (Info.EnableNewConstInterp) { - Info.Ctx.getInterpContext().isPotentialConstantExprUnevaluated(Info, E, FD); - return Diags.empty(); - } - // Fabricate a call stack frame to give the arguments a plausible cover story. CallStackFrame Frame(Info, SourceLocation(), FD, /*This=*/nullptr, /*CallExpr=*/nullptr, CallRef()); `````````` </details> https://github.com/llvm/llvm-project/pull/149693 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits