Author: Timm Baeder Date: 2025-08-28T10:06:04+02:00 New Revision: 168308325d00b4de1c7a9c648d9f4f1f3e4c3866
URL: https://github.com/llvm/llvm-project/commit/168308325d00b4de1c7a9c648d9f4f1f3e4c3866 DIFF: https://github.com/llvm/llvm-project/commit/168308325d00b4de1c7a9c648d9f4f1f3e4c3866.diff LOG: [clang][bytecode] Simplify and optimize EvaluationResult (#155772) Remove support for saving a `Pointer` in the `EvaluationResult` since that was unused. Add `stealAPValue()` which moves the `APValue` out of the `EvaluationResult` to avoid a copy at the end of the evaluation. Added: Modified: clang/lib/AST/ByteCode/Context.cpp clang/lib/AST/ByteCode/Disasm.cpp clang/lib/AST/ByteCode/EvaluationResult.cpp clang/lib/AST/ByteCode/EvaluationResult.h Removed: ################################################################################ diff --git a/clang/lib/AST/ByteCode/Context.cpp b/clang/lib/AST/ByteCode/Context.cpp index fbbb508ed226c..8598996681466 100644 --- a/clang/lib/AST/ByteCode/Context.cpp +++ b/clang/lib/AST/ByteCode/Context.cpp @@ -91,7 +91,7 @@ bool Context::evaluateAsRValue(State &Parent, const Expr *E, APValue &Result) { #endif } - Result = Res.toAPValue(); + Result = Res.stealAPValue(); return true; } @@ -121,7 +121,7 @@ bool Context::evaluate(State &Parent, const Expr *E, APValue &Result, #endif } - Result = Res.toAPValue(); + Result = Res.stealAPValue(); return true; } @@ -153,7 +153,7 @@ bool Context::evaluateAsInitializer(State &Parent, const VarDecl *VD, #endif } - Result = Res.toAPValue(); + Result = Res.stealAPValue(); return true; } diff --git a/clang/lib/AST/ByteCode/Disasm.cpp b/clang/lib/AST/ByteCode/Disasm.cpp index 4ea47eac2150c..6ca6e93c46177 100644 --- a/clang/lib/AST/ByteCode/Disasm.cpp +++ b/clang/lib/AST/ByteCode/Disasm.cpp @@ -551,37 +551,13 @@ LLVM_DUMP_METHOD void Block::dump(llvm::raw_ostream &OS) const { LLVM_DUMP_METHOD void EvaluationResult::dump() const { assert(Ctx); auto &OS = llvm::errs(); - const ASTContext &ASTCtx = Ctx->getASTContext(); - switch (Kind) { - case Empty: + if (empty()) { OS << "Empty\n"; - break; - case RValue: - OS << "RValue: "; - std::get<APValue>(Value).dump(OS, ASTCtx); - break; - case LValue: { - assert(Source); - QualType SourceType; - if (const auto *D = dyn_cast<const Decl *>(Source)) { - if (const auto *VD = dyn_cast<ValueDecl>(D)) - SourceType = VD->getType(); - } else if (const auto *E = dyn_cast<const Expr *>(Source)) { - SourceType = E->getType(); - } - - OS << "LValue: "; - if (const auto *P = std::get_if<Pointer>(&Value)) - P->toAPValue(ASTCtx).printPretty(OS, ASTCtx, SourceType); - OS << "\n"; - break; - } - case Invalid: + } else if (isInvalid()) { OS << "Invalid\n"; - break; - case Valid: - OS << "Valid\n"; - break; + } else { + OS << "Value: "; + Value.dump(OS, Ctx->getASTContext()); } } diff --git a/clang/lib/AST/ByteCode/EvaluationResult.cpp b/clang/lib/AST/ByteCode/EvaluationResult.cpp index 773d9f96e5fd9..ba818788d7026 100644 --- a/clang/lib/AST/ByteCode/EvaluationResult.cpp +++ b/clang/lib/AST/ByteCode/EvaluationResult.cpp @@ -8,6 +8,7 @@ #include "EvaluationResult.h" #include "InterpState.h" +#include "Pointer.h" #include "Record.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SetVector.h" @@ -16,37 +17,6 @@ namespace clang { namespace interp { -APValue EvaluationResult::toAPValue() const { - assert(!empty()); - switch (Kind) { - case LValue: - // Either a pointer or a function pointer. - if (const auto *P = std::get_if<Pointer>(&Value)) - return P->toAPValue(Ctx->getASTContext()); - else - llvm_unreachable("Unhandled LValue type"); - break; - case RValue: - return std::get<APValue>(Value); - case Valid: - return APValue(); - default: - llvm_unreachable("Unhandled result kind?"); - } -} - -std::optional<APValue> EvaluationResult::toRValue() const { - if (Kind == RValue) - return toAPValue(); - - assert(Kind == LValue); - - // We have a pointer and want an RValue. - if (const auto *P = std::get_if<Pointer>(&Value)) - return P->toRValue(*Ctx, getSourceType()); - llvm_unreachable("Unhandled lvalue kind"); -} - static void DiagnoseUninitializedSubobject(InterpState &S, SourceLocation Loc, const FieldDecl *SubObjDecl) { assert(SubObjDecl && "Subobject declaration does not exist"); diff --git a/clang/lib/AST/ByteCode/EvaluationResult.h b/clang/lib/AST/ByteCode/EvaluationResult.h index 9785ec564d76e..d00b9ca02a48d 100644 --- a/clang/lib/AST/ByteCode/EvaluationResult.h +++ b/clang/lib/AST/ByteCode/EvaluationResult.h @@ -9,7 +9,6 @@ #ifndef LLVM_CLANG_AST_INTERP_EVALUATION_RESULT_H #define LLVM_CLANG_AST_INTERP_EVALUATION_RESULT_H -#include "Pointer.h" #include "clang/AST/APValue.h" #include "clang/AST/Decl.h" #include "clang/AST/Expr.h" @@ -20,6 +19,9 @@ namespace clang { namespace interp { class EvalEmitter; class Context; +class Pointer; +class SourceInfo; +class InterpState; /// Defines the result of an evaluation. /// @@ -32,8 +34,6 @@ class EvaluationResult final { public: enum ResultKind { Empty, // Initial state. - LValue, // Result is an lvalue/pointer. - RValue, // Result is an rvalue. Invalid, // Result is invalid. Valid, // Result is valid and empty. }; @@ -42,7 +42,7 @@ class EvaluationResult final { private: const Context *Ctx = nullptr; - std::variant<std::monostate, Pointer, APValue> Value; + APValue Value; ResultKind Kind = Empty; DeclTy Source = nullptr; // Currently only needed for dump(). @@ -55,10 +55,8 @@ class EvaluationResult final { void setSource(DeclTy D) { Source = D; } void takeValue(APValue &&V) { - // V could still be an LValue. assert(empty()); Value = std::move(V); - Kind = RValue; } void setInvalid() { // We are NOT asserting empty() here, since setting it to invalid @@ -75,18 +73,15 @@ class EvaluationResult final { bool empty() const { return Kind == Empty; } bool isInvalid() const { return Kind == Invalid; } - bool isLValue() const { return Kind == LValue; } - bool isRValue() const { return Kind == RValue; } - bool isPointer() const { return std::holds_alternative<Pointer>(Value); } - - /// Returns an APValue for the evaluation result. The returned - /// APValue might be an LValue or RValue. - APValue toAPValue() const; - - /// If the result is an LValue, convert that to an RValue - /// and return it. This may fail, e.g. if the result is an - /// LValue and we can't read from it. - std::optional<APValue> toRValue() const; + + /// Returns an APValue for the evaluation result. + APValue toAPValue() const { + assert(!empty()); + assert(!isInvalid()); + return Value; + } + + APValue stealAPValue() { return std::move(Value); } /// Check that all subobjects of the given pointer have been initialized. bool checkFullyInitialized(InterpState &S, const Pointer &Ptr) const; _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits