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

Reply via email to