diff --git a/clang/lib/AST/ByteCode/Context.cpp b/clang/lib/AST/ByteCode/Context.cpp index c70a5259b77e2..6b8f4e31e4ff9 100644 --- a/clang/lib/AST/ByteCode/Context.cpp +++ b/clang/lib/AST/ByteCode/Context.cpp @@ -21,7 +21,12 @@ using namespace clang; using namespace clang::interp; -Context::Context(ASTContext &Ctx) : Ctx(Ctx), P(new Program(*this)) {} +Context::Context(ASTContext &Ctx) : Ctx(Ctx), P(new Program(*this)) { + this->IntWidth = Ctx.getTargetInfo().getIntWidth(); + this->LongWidth = Ctx.getTargetInfo().getLongWidth(); + assert(Ctx.getTargetInfo().getCharWidth() == 8 && + "We're assuming 8 bit chars"); +} Context::~Context() {} @@ -216,55 +221,91 @@ bool Context::evaluateCharRange(State &Parent, const Expr *SizeExpr, const LangOptions &Context::getLangOpts() const { return Ctx.getLangOpts(); } -std::optional Context::classify(QualType T) const { - if (T->isBooleanType()) - return PT_Bool; - - if (T->isSignedIntegerOrEnumerationType()) { - switch (Ctx.getIntWidth(T)) { - case 64: - return PT_Sint64; - case 32: - return PT_Sint32; - case 16: - return PT_Sint16; - case 8: - return PT_Sint8; - default: - return PT_IntAPS; - } +static PrimType integralTypeToPrimTypeS(unsigned BitWidth) { + switch (BitWidth) { + case 64: + return PT_Sint64; + case 32: + return PT_Sint32; + case 16: + return PT_Sint16; + case 8: + return PT_Sint8; + default: + return PT_IntAPS; } + llvm_unreachable("Unhandled BitWidth"); +} + +static PrimType integralTypeToPrimTypeU(unsigned BitWidth) { + switch (BitWidth) { + case 64: + return PT_Uint64; + case 32: + return PT_Uint32; + case 16: + return PT_Uint16; + case 8: + return PT_Uint8; + default: + return PT_IntAP; + } + llvm_unreachable("Unhandled BitWidth"); +} + +std::optional Context::classify(QualType T) const { - if (T->isUnsignedIntegerOrEnumerationType()) { - switch (Ctx.getIntWidth(T)) { - case 64: - return PT_Uint64; - case 32: - return PT_Uint32; - case 16: - return PT_Uint16; - case 8: - return PT_Uint8; - case 1: - // Might happen for enum types. + if (const auto *BT = dyn_cast(T.getCanonicalType())) { + auto Kind = BT->getKind(); + if (Kind == BuiltinType::Bool) return PT_Bool; - default: - return PT_IntAP; - } + if (Kind == BuiltinType::NullPtr) + return PT_Ptr; + if (Kind == BuiltinType::BoundMember) + return PT_MemberPtr; + + // Just trying to avoid the ASTContext::getIntWidth call below. + if (Kind == BuiltinType::Int) + return integralTypeToPrimTypeS(this->IntWidth); + if (Kind == BuiltinType::UInt) + return integralTypeToPrimTypeU(this->IntWidth); + if (Kind == BuiltinType::Long) + return integralTypeToPrimTypeS(this->LongWidth); + if (Kind == BuiltinType::ULong) + return integralTypeToPrimTypeU(this->LongWidth); + if (Kind == BuiltinType::SChar || Kind == BuiltinType::Char_S) + return integralTypeToPrimTypeS(8); + if (Kind == BuiltinType::UChar || Kind == BuiltinType::Char_U || + Kind == BuiltinType::Char8) + return integralTypeToPrimTypeU(8); + + if (BT->isSignedInteger()) + return integralTypeToPrimTypeS(Ctx.getIntWidth(T)); + if (BT->isUnsignedInteger()) + return integralTypeToPrimTypeU(Ctx.getIntWidth(T)); + + if (BT->isFloatingPoint()) + return PT_Float; } - if (T->isNullPtrType()) + if (T->isPointerOrReferenceType()) return PT_Ptr; - if (T->isRealFloatingType()) - return PT_Float; + if (T->isMemberPointerType()) + return PT_MemberPtr; - if (T->isFunctionPointerType() || T->isFunctionReferenceType() || - T->isFunctionType() || T->isBlockPointerType()) - return PT_Ptr; + if (const auto *BT = T->getAs()) { + if (BT->isSigned()) + return integralTypeToPrimTypeS(BT->getNumBits()); + return integralTypeToPrimTypeU(BT->getNumBits()); + } - if (T->isPointerOrReferenceType() || T->isObjCObjectPointerType()) - return PT_Ptr; + if (const auto *ET = T->getAs()) { + const auto *D = ET->getDecl(); + if (!D->isComplete()) + return std::nullopt; + return classify(D->getIntegerType()); + } if (const auto *AT = T->getAs()) return classify(AT->getValueType()); @@ -272,9 +313,8 @@ std::optional Context::classify(QualType T) const { if (const auto *DT = dyn_cast(T)) return classify(DT->getUnderlyingType()); - if (T->isSpecificBuiltinType(BuiltinType::BoundMember) || - T->isMemberPointerType()) - return PT_MemberPtr; + if (T->isObjCObjectPointerType() || T->isBlockPointerType()) + return PT_Ptr; if (T->isFixedPointType()) return PT_FixedPoint; diff --git a/clang/lib/AST/ByteCode/Context.h b/clang/lib/AST/ByteCode/Context.h index fc778f9796a79..9a604ce8ebbe9 100644 --- a/clang/lib/AST/ByteCode/Context.h +++ b/clang/lib/AST/ByteCode/Context.h @@ -137,6 +137,9 @@ class Context final { std::unique_ptr P; /// ID identifying an evaluation. unsigned EvalID = 0; + /// Cached widths (in bits) of common types, for a faster classify(). + unsigned IntWidth; + unsigned LongWidth; }; } // namespace interp