Author: Timm Baeder Date: 2026-06-10T10:10:57+02:00 New Revision: be1f53f568394ee7c1976a9a5785c8127dbcdf39
URL: https://github.com/llvm/llvm-project/commit/be1f53f568394ee7c1976a9a5785c8127dbcdf39 DIFF: https://github.com/llvm/llvm-project/commit/be1f53f568394ee7c1976a9a5785c8127dbcdf39.diff LOG: [clang][bytecode] Save a `Type*` in integral pointers instead of a descriptor (#202835) This way we don't need to allocate a descriptor via the `Program`, which is for global data. Added: Modified: clang/lib/AST/ByteCode/Compiler.cpp clang/lib/AST/ByteCode/Interp.cpp clang/lib/AST/ByteCode/Interp.h clang/lib/AST/ByteCode/MemberPointer.h clang/lib/AST/ByteCode/Opcodes.td clang/lib/AST/ByteCode/Pointer.cpp clang/lib/AST/ByteCode/Pointer.h Removed: ################################################################################ diff --git a/clang/lib/AST/ByteCode/Compiler.cpp b/clang/lib/AST/ByteCode/Compiler.cpp index b89849b6983d8..8ea42fea03bee 100644 --- a/clang/lib/AST/ByteCode/Compiler.cpp +++ b/clang/lib/AST/ByteCode/Compiler.cpp @@ -434,18 +434,9 @@ bool Compiler<Emitter>::VisitCastExpr(const CastExpr *E) { case CK_NullToMemberPointer: { if (!this->discard(SubExpr)) return false; - const Descriptor *Desc = nullptr; - const QualType PointeeType = E->getType()->getPointeeType(); - if (!PointeeType.isNull()) { - if (OptPrimType T = classify(PointeeType)) - Desc = P.createDescriptor(SubExpr, *T); - else - Desc = P.createDescriptor(SubExpr, PointeeType.getTypePtr(), - std::nullopt, /*IsConst=*/true); - } - uint64_t Val = Ctx.getASTContext().getTargetNullPointerValue(E->getType()); - return this->emitNull(classifyPrim(E->getType()), Val, Desc, E); + return this->emitNull(classifyPrim(E->getType()), Val, + E->getType().getTypePtr(), E); } case CK_PointerToIntegral: { @@ -481,19 +472,10 @@ bool Compiler<Emitter>::VisitCastExpr(const CastExpr *E) { // FIXME: I think the discard is wrong since the int->ptr cast might cause a // diagnostic. PrimType T = classifyPrim(IntType); - QualType PtrType = E->getType(); - const Descriptor *Desc; - if (OptPrimType T = classify(PtrType->getPointeeType())) - Desc = P.createDescriptor(SubExpr, *T); - else if (PtrType->getPointeeType()->isVoidType()) - Desc = nullptr; - else - Desc = P.createDescriptor(E, PtrType->getPointeeType().getTypePtr(), - Descriptor::InlineDescMD, /*IsConst=*/true); - - if (!this->emitGetIntPtr(T, Desc, E)) + if (!this->emitGetIntPtr(T, E->getType().getTypePtr(), E)) return false; + QualType PtrType = E->getType(); PrimType DestPtrT = classifyPrim(PtrType); if (DestPtrT == PT_Ptr) return true; diff --git a/clang/lib/AST/ByteCode/Interp.cpp b/clang/lib/AST/ByteCode/Interp.cpp index f6cac7aeb9fb5..f21dbb3d5246c 100644 --- a/clang/lib/AST/ByteCode/Interp.cpp +++ b/clang/lib/AST/ByteCode/Interp.cpp @@ -1489,7 +1489,7 @@ static bool getField(InterpState &S, CodePtr OpPC, const Pointer &Ptr, if (Ptr.isIntegralPointer()) { if (std::optional<IntPointer> IntPtr = - Ptr.asIntPointer().atOffset(S.getASTContext(), Off)) { + Ptr.asIntPointer().atOffset(S.Ctx, Off)) { S.Stk.push<Pointer>(std::move(*IntPtr)); return true; } @@ -1535,7 +1535,7 @@ static bool getBase(InterpState &S, CodePtr OpPC, const Pointer &Ptr, if (!Ptr.isBlockPointer()) { if (!Ptr.isIntegralPointer()) return false; - S.Stk.push<Pointer>(Ptr.asIntPointer().baseCast(S.getASTContext(), Off)); + S.Stk.push<Pointer>(Ptr.asIntPointer().baseCast(S.Ctx, Off)); return true; } @@ -1895,7 +1895,7 @@ static bool getDynamicDecl(InterpState &S, CodePtr OpPC, Pointer TypePtr, QualType DynamicType = TypePtr.getType(); if (TypePtr.isStatic() || TypePtr.isConst()) { - if (const VarDecl *VD = TypePtr.getDeclDesc()->asVarDecl(); + if (const VarDecl *VD = TypePtr.getRootVarDecl(); VD && !VD->isConstexpr()) { const Expr *E = S.Current->getExpr(OpPC); APValue V = TypePtr.toAPValue(S.getASTContext()); diff --git a/clang/lib/AST/ByteCode/Interp.h b/clang/lib/AST/ByteCode/Interp.h index 4c0a7040f46aa..9d3d3b449bea3 100644 --- a/clang/lib/AST/ByteCode/Interp.h +++ b/clang/lib/AST/ByteCode/Interp.h @@ -2503,11 +2503,16 @@ std::optional<Pointer> OffsetHelper(InterpState &S, CodePtr OpPC, // This is much simpler for integral pointers, so handle them first. if (Ptr.isIntegralPointer()) { uint64_t V = Ptr.getIntegerRepresentation(); - uint64_t O = static_cast<uint64_t>(Offset) * Ptr.elemSize(); - if constexpr (Op == ArithOp::Add) - return Pointer(V + O, Ptr.asIntPointer().Desc); - else - return Pointer(V - O, Ptr.asIntPointer().Desc); + QualType ElemType = Ptr.asIntPointer().getPointeeType(); + uint64_t ElemSize = + (ElemType.isNull() || ElemType->isVoidType()) + ? 1u + : S.getASTContext().getTypeSizeInChars(ElemType).getQuantity(); + uint64_t O = static_cast<uint64_t>(Offset) * ElemSize; + if constexpr (Op == ArithOp::Add) { + return Pointer(V + O, Ptr.asIntPointer().Ty); + } else + return Pointer(V - O, Ptr.asIntPointer().Ty); } else if (Ptr.isFunctionPointer()) { uint64_t O = static_cast<uint64_t>(Offset); uint64_t N; @@ -3119,11 +3124,10 @@ static inline bool ZeroIntAPS(InterpState &S, CodePtr OpPC, uint32_t BitWidth) { } template <PrimType Name, class T = typename PrimConv<Name>::T> -inline bool Null(InterpState &S, CodePtr OpPC, uint64_t Value, - const Descriptor *Desc) { +inline bool Null(InterpState &S, CodePtr OpPC, uint64_t Value, const Type *Ty) { // FIXME(perf): This is a somewhat often-used function and the value of a // null pointer is almost always 0. - S.Stk.push<T>(Value, Desc); + S.Stk.push<T>(Value, Ty); return true; } @@ -3563,7 +3567,7 @@ inline bool GetFnPtr(InterpState &S, CodePtr OpPC, const Function *Func) { } template <PrimType Name, class T = typename PrimConv<Name>::T> -inline bool GetIntPtr(InterpState &S, CodePtr OpPC, const Descriptor *Desc) { +inline bool GetIntPtr(InterpState &S, CodePtr OpPC, const Type *Ty) { const T &IntVal = S.Stk.pop<T>(); S.CCEDiag(S.Current->getSource(OpPC), diag::note_constexpr_invalid_cast) @@ -3588,10 +3592,10 @@ inline bool GetIntPtr(InterpState &S, CodePtr OpPC, const Descriptor *Desc) { S.P.getFunction((const FunctionDecl *)IntVal.getPtr()); S.Stk.push<Pointer>(F, IntVal.getOffset()); } else { - S.Stk.push<Pointer>(static_cast<uint64_t>(IntVal), Desc); + S.Stk.push<Pointer>(static_cast<uint64_t>(IntVal), Ty); } } else { - S.Stk.push<Pointer>(static_cast<uint64_t>(IntVal), Desc); + S.Stk.push<Pointer>(static_cast<uint64_t>(IntVal), Ty); } return true; @@ -3872,7 +3876,7 @@ inline bool AllocN(InterpState &S, CodePtr OpPC, PrimType T, const Expr *Source, return false; // If this failed and is nothrow, just return a null ptr. - S.Stk.push<Pointer>(0, nullptr); + S.Stk.push<Pointer>(); return true; } if (NumElements.isNegative()) { @@ -3881,7 +3885,7 @@ inline bool AllocN(InterpState &S, CodePtr OpPC, PrimType T, const Expr *Source, << NumElements.toDiagnosticString(S.getASTContext()); return false; } - S.Stk.push<Pointer>(0, nullptr); + S.Stk.push<Pointer>(); return true; } @@ -3915,7 +3919,7 @@ inline bool AllocCN(InterpState &S, CodePtr OpPC, const Descriptor *ElementDesc, return false; // If this failed and is nothrow, just return a null ptr. - S.Stk.push<Pointer>(0, ElementDesc); + S.Stk.push<Pointer>(0, ElementDesc->getType().getTypePtr()); return true; } if (NumElements.isNegative()) { @@ -3924,7 +3928,7 @@ inline bool AllocCN(InterpState &S, CodePtr OpPC, const Descriptor *ElementDesc, << NumElements.toDiagnosticString(S.getASTContext()); return false; } - S.Stk.push<Pointer>(0, nullptr); + S.Stk.push<Pointer>(); return true; } diff --git a/clang/lib/AST/ByteCode/MemberPointer.h b/clang/lib/AST/ByteCode/MemberPointer.h index dbbf1fe85bada..b23acf7befc67 100644 --- a/clang/lib/AST/ByteCode/MemberPointer.h +++ b/clang/lib/AST/ByteCode/MemberPointer.h @@ -44,7 +44,7 @@ class MemberPointer final { MemberPointer() = default; MemberPointer(Pointer Base, const ValueDecl *Dcl) : Base(Base), DeclAndIsDerivedMember(Dcl) {} - MemberPointer(uint32_t Address, const Descriptor *D) { + MemberPointer(uint32_t Address, const Type *) { // We only reach this for Address == 0, when creating a null member pointer. assert(Address == 0); } diff --git a/clang/lib/AST/ByteCode/Opcodes.td b/clang/lib/AST/ByteCode/Opcodes.td index 4bd61cdce658d..09c616aa2ff1d 100644 --- a/clang/lib/AST/ByteCode/Opcodes.td +++ b/clang/lib/AST/ByteCode/Opcodes.td @@ -311,7 +311,7 @@ def ZeroIntAPS : Opcode { // [] -> [Pointer] def Null : Opcode { let Types = [PtrTypeClass]; - let Args = [ArgUint64, ArgDesc]; + let Args = [ArgUint64, ArgTypePtr]; let HasGroup = 1; } @@ -596,7 +596,7 @@ def GetFnPtr : Opcode { def GetIntPtr : Opcode { let Types = [AluTypeClass]; - let Args = [ArgDesc]; + let Args = [ArgTypePtr]; let HasGroup = 1; } diff --git a/clang/lib/AST/ByteCode/Pointer.cpp b/clang/lib/AST/ByteCode/Pointer.cpp index 96409faeb6929..1b15c59c9fbff 100644 --- a/clang/lib/AST/ByteCode/Pointer.cpp +++ b/clang/lib/AST/ByteCode/Pointer.cpp @@ -337,9 +337,7 @@ void Pointer::print(llvm::raw_ostream &OS) const { OS << "}"; } break; case Storage::Int: - OS << "(Int) {"; - OS << Int.Value << " + " << Offset << ", " << Int.Desc; - OS << "}"; + OS << "(Int) {" << Int.Value << " + " << Offset << ", " << Int.Ty << "}"; break; case Storage::Fn: OS << "(Fn) { " << Fn.Func << " + " << Offset << " }"; @@ -994,11 +992,19 @@ std::optional<APValue> Pointer::toRValue(const Context &Ctx, return Result; } -std::optional<IntPointer> IntPointer::atOffset(const ASTContext &ASTCtx, +const VarDecl *Pointer::getRootVarDecl() const { + if (isBlockPointer()) + return getDeclDesc()->asVarDecl(); + return nullptr; +} + +std::optional<IntPointer> IntPointer::atOffset(const interp::Context &Ctx, unsigned Offset) const { - if (!this->Desc) - return *this; - const Record *R = this->Desc->ElemRecord; + QualType CurType = getPointeeType(); + if (CurType.isNull() || !CurType->isRecordType()) + return std::nullopt; + + const Record *R = Ctx.getRecord(CurType->getAsRecordDecl()); if (!R) return *this; @@ -1016,21 +1022,26 @@ std::optional<IntPointer> IntPointer::atOffset(const ASTContext &ASTCtx, if (FD->getParent()->isInvalidDecl()) return std::nullopt; + const ASTContext &ASTCtx = Ctx.getASTContext(); const ASTRecordLayout &Layout = ASTCtx.getASTRecordLayout(FD->getParent()); unsigned FieldIndex = FD->getFieldIndex(); uint64_t FieldOffset = ASTCtx.toCharUnitsFromBits(Layout.getFieldOffset(FieldIndex)) .getQuantity(); - return IntPointer{F->Desc, this->Value + FieldOffset}; + + return IntPointer{FD->getType().getTypePtr(), this->Value + FieldOffset}; } -IntPointer IntPointer::baseCast(const ASTContext &ASTCtx, +IntPointer IntPointer::baseCast(const interp::Context &Ctx, unsigned BaseOffset) const { - if (!Desc) { - assert(Value == 0); + if (!Ty) return *this; - } - const Record *R = Desc->ElemRecord; + + QualType CurType = getPointeeType(); + if (CurType.isNull() || !CurType->isRecordType()) + return *this; + + const Record *R = Ctx.getRecord(CurType->getAsRecordDecl()); const Descriptor *BaseDesc = nullptr; // This iterates over bases and checks for the proper offset. That's @@ -1044,9 +1055,13 @@ IntPointer IntPointer::baseCast(const ASTContext &ASTCtx, assert(BaseDesc); // Adjust the offset value based on the information from the record layout. + const ASTContext &ASTCtx = Ctx.getASTContext(); const ASTRecordLayout &Layout = ASTCtx.getASTRecordLayout(R->getDecl()); CharUnits BaseLayoutOffset = Layout.getBaseClassOffset(cast<CXXRecordDecl>(BaseDesc->asDecl())); - return {BaseDesc, Value + BaseLayoutOffset.getQuantity()}; + const RecordDecl *RD = BaseDesc->ElemRecord->getDecl(); + QualType T = RD->getASTContext().getTagType(ElaboratedTypeKeyword::None, + std::nullopt, RD, false); + return {T.getTypePtr(), Value + BaseLayoutOffset.getQuantity()}; } diff --git a/clang/lib/AST/ByteCode/Pointer.h b/clang/lib/AST/ByteCode/Pointer.h index a77918f667fd3..2b455ebc5efb5 100644 --- a/clang/lib/AST/ByteCode/Pointer.h +++ b/clang/lib/AST/ByteCode/Pointer.h @@ -45,12 +45,24 @@ struct BlockPointer { }; struct IntPointer { - const Descriptor *Desc; + const Type *Ty; uint64_t Value; - std::optional<IntPointer> atOffset(const ASTContext &ASTCtx, - unsigned Offset) const; - IntPointer baseCast(const ASTContext &ASTCtx, unsigned BaseOffset) const; + std::optional<IntPointer> atOffset(const Context &Ctx, unsigned Offset) const; + IntPointer baseCast(const Context &Ctx, unsigned BaseOffset) const; + + QualType getPointeeType() const { + if (!Ty) + return QualType(); + + QualType QT(Ty, 0); + if (QT->isPointerOrReferenceType()) + QT = QT->getPointeeType(); + else if (QT->isArrayType()) + QT = QT->getAsArrayTypeUnsafe()->getElementType(); + + return QT.IgnoreParens(); + } }; struct FunctionPointer { @@ -107,8 +119,8 @@ class Pointer { Pointer(Block *B, uint64_t BaseAndOffset); Pointer(const Pointer &P); Pointer(Pointer &&P); - Pointer(uint64_t Address, const Descriptor *Desc, uint64_t Offset = 0) - : Offset(Offset), StorageKind(Storage::Int), Int{Desc, Address} {} + Pointer(uint64_t Address, const Type *Ty, uint64_t Offset = 0) + : Offset(Offset), StorageKind(Storage::Int), Int{Ty, Address} {} Pointer(const Function *F, uint64_t Offset = 0) : Offset(Offset), StorageKind(Storage::Fn), Fn{F} {} Pointer(const Type *TypePtr, const Type *TypeInfoType, uint64_t Offset = 0) @@ -127,7 +139,7 @@ class Pointer { if (P.StorageKind != StorageKind) return false; if (isIntegralPointer()) - return P.Int.Value == Int.Value && P.Int.Desc == Int.Desc && + return P.Int.Value == Int.Value && P.Int.Ty == Int.Ty && P.Offset == Offset; if (isFunctionPointer()) @@ -161,7 +173,7 @@ class Pointer { /// Offsets a pointer inside an array. [[nodiscard]] Pointer atIndex(uint64_t Idx) const { if (isIntegralPointer()) - return Pointer(Int.Value, Int.Desc, Idx); + return Pointer(Int.Value, Int.Ty, Idx); if (isFunctionPointer()) return Pointer(Fn.Func, Idx); @@ -290,9 +302,7 @@ class Pointer { /// Accessor for information about the declaration site. const Descriptor *getDeclDesc() const { - if (isIntegralPointer()) - return Int.Desc; - if (isFunctionPointer() || isTypeidPointer()) + if (!isBlockPointer()) return nullptr; assert(isBlockPointer()); @@ -309,8 +319,8 @@ class Pointer { const Function *F = Fn.Func; return F ? F->getDecl() : DeclTy(); } - assert(isIntegralPointer()); - return Int.Desc ? Int.Desc->getSource() : DeclTy(); + llvm_unreachable("Unsupported pointer type in getSource()"); + return DeclTy(); } /// Returns a pointer to the object of which this pointer is a field. @@ -335,7 +345,7 @@ class Pointer { /// Accessors for information about the innermost field. const Descriptor *getFieldDesc() const { if (isIntegralPointer()) - return Int.Desc; + return nullptr; if (isRoot()) return getDeclDesc(); @@ -348,6 +358,8 @@ class Pointer { return QualType(Typeid.TypeInfoType, 0); if (isFunctionPointer()) return Fn.Func->getDecl()->getType(); + if (isIntegralPointer()) + return Int.getPointeeType(); if (isRoot() && BS.Base == Offset) { // If this pointer points to the root of a declaration, try to consult @@ -372,14 +384,15 @@ class Pointer { return getFieldDesc()->getType(); } + const VarDecl *getRootVarDecl() const; + [[nodiscard]] Pointer getDeclPtr() const { return Pointer(BS.Pointee); } /// Returns the element size of the innermost field. size_t elemSize() const { if (isIntegralPointer()) { - if (!Int.Desc) - return 1; - return Int.Desc->getElemDataSize(); + // FIXME: Remove this and handle int ptrs specially? + return 1; } if (BS.Base == RootPtrMark) _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
