Skip to content

Commit 1683083

Browse files
authored
[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.
1 parent 59befff commit 1683083

File tree

4 files changed

+22
-81
lines changed

4 files changed

+22
-81
lines changed

clang/lib/AST/ByteCode/Context.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ bool Context::evaluateAsRValue(State &Parent, const Expr *E, APValue &Result) {
9191
#endif
9292
}
9393

94-
Result = Res.toAPValue();
94+
Result = Res.stealAPValue();
9595

9696
return true;
9797
}
@@ -121,7 +121,7 @@ bool Context::evaluate(State &Parent, const Expr *E, APValue &Result,
121121
#endif
122122
}
123123

124-
Result = Res.toAPValue();
124+
Result = Res.stealAPValue();
125125
return true;
126126
}
127127

@@ -153,7 +153,7 @@ bool Context::evaluateAsInitializer(State &Parent, const VarDecl *VD,
153153
#endif
154154
}
155155

156-
Result = Res.toAPValue();
156+
Result = Res.stealAPValue();
157157
return true;
158158
}
159159

clang/lib/AST/ByteCode/Disasm.cpp

Lines changed: 5 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -551,37 +551,13 @@ LLVM_DUMP_METHOD void Block::dump(llvm::raw_ostream &OS) const {
551551
LLVM_DUMP_METHOD void EvaluationResult::dump() const {
552552
assert(Ctx);
553553
auto &OS = llvm::errs();
554-
const ASTContext &ASTCtx = Ctx->getASTContext();
555554

556-
switch (Kind) {
557-
case Empty:
555+
if (empty()) {
558556
OS << "Empty\n";
559-
break;
560-
case RValue:
561-
OS << "RValue: ";
562-
std::get<APValue>(Value).dump(OS, ASTCtx);
563-
break;
564-
case LValue: {
565-
assert(Source);
566-
QualType SourceType;
567-
if (const auto *D = dyn_cast<const Decl *>(Source)) {
568-
if (const auto *VD = dyn_cast<ValueDecl>(D))
569-
SourceType = VD->getType();
570-
} else if (const auto *E = dyn_cast<const Expr *>(Source)) {
571-
SourceType = E->getType();
572-
}
573-
574-
OS << "LValue: ";
575-
if (const auto *P = std::get_if<Pointer>(&Value))
576-
P->toAPValue(ASTCtx).printPretty(OS, ASTCtx, SourceType);
577-
OS << "\n";
578-
break;
579-
}
580-
case Invalid:
557+
} else if (isInvalid()) {
581558
OS << "Invalid\n";
582-
break;
583-
case Valid:
584-
OS << "Valid\n";
585-
break;
559+
} else {
560+
OS << "Value: ";
561+
Value.dump(OS, Ctx->getASTContext());
586562
}
587563
}

clang/lib/AST/ByteCode/EvaluationResult.cpp

Lines changed: 1 addition & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88

99
#include "EvaluationResult.h"
1010
#include "InterpState.h"
11+
#include "Pointer.h"
1112
#include "Record.h"
1213
#include "llvm/ADT/STLExtras.h"
1314
#include "llvm/ADT/SetVector.h"
@@ -16,37 +17,6 @@
1617
namespace clang {
1718
namespace interp {
1819

19-
APValue EvaluationResult::toAPValue() const {
20-
assert(!empty());
21-
switch (Kind) {
22-
case LValue:
23-
// Either a pointer or a function pointer.
24-
if (const auto *P = std::get_if<Pointer>(&Value))
25-
return P->toAPValue(Ctx->getASTContext());
26-
else
27-
llvm_unreachable("Unhandled LValue type");
28-
break;
29-
case RValue:
30-
return std::get<APValue>(Value);
31-
case Valid:
32-
return APValue();
33-
default:
34-
llvm_unreachable("Unhandled result kind?");
35-
}
36-
}
37-
38-
std::optional<APValue> EvaluationResult::toRValue() const {
39-
if (Kind == RValue)
40-
return toAPValue();
41-
42-
assert(Kind == LValue);
43-
44-
// We have a pointer and want an RValue.
45-
if (const auto *P = std::get_if<Pointer>(&Value))
46-
return P->toRValue(*Ctx, getSourceType());
47-
llvm_unreachable("Unhandled lvalue kind");
48-
}
49-
5020
static void DiagnoseUninitializedSubobject(InterpState &S, SourceLocation Loc,
5121
const FieldDecl *SubObjDecl) {
5222
assert(SubObjDecl && "Subobject declaration does not exist");

clang/lib/AST/ByteCode/EvaluationResult.h

Lines changed: 13 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@
99
#ifndef LLVM_CLANG_AST_INTERP_EVALUATION_RESULT_H
1010
#define LLVM_CLANG_AST_INTERP_EVALUATION_RESULT_H
1111

12-
#include "Pointer.h"
1312
#include "clang/AST/APValue.h"
1413
#include "clang/AST/Decl.h"
1514
#include "clang/AST/Expr.h"
@@ -20,6 +19,9 @@ namespace clang {
2019
namespace interp {
2120
class EvalEmitter;
2221
class Context;
22+
class Pointer;
23+
class SourceInfo;
24+
class InterpState;
2325

2426
/// Defines the result of an evaluation.
2527
///
@@ -32,8 +34,6 @@ class EvaluationResult final {
3234
public:
3335
enum ResultKind {
3436
Empty, // Initial state.
35-
LValue, // Result is an lvalue/pointer.
36-
RValue, // Result is an rvalue.
3737
Invalid, // Result is invalid.
3838
Valid, // Result is valid and empty.
3939
};
@@ -42,7 +42,7 @@ class EvaluationResult final {
4242

4343
private:
4444
const Context *Ctx = nullptr;
45-
std::variant<std::monostate, Pointer, APValue> Value;
45+
APValue Value;
4646
ResultKind Kind = Empty;
4747
DeclTy Source = nullptr; // Currently only needed for dump().
4848

@@ -55,10 +55,8 @@ class EvaluationResult final {
5555
void setSource(DeclTy D) { Source = D; }
5656

5757
void takeValue(APValue &&V) {
58-
// V could still be an LValue.
5958
assert(empty());
6059
Value = std::move(V);
61-
Kind = RValue;
6260
}
6361
void setInvalid() {
6462
// We are NOT asserting empty() here, since setting it to invalid
@@ -75,18 +73,15 @@ class EvaluationResult final {
7573

7674
bool empty() const { return Kind == Empty; }
7775
bool isInvalid() const { return Kind == Invalid; }
78-
bool isLValue() const { return Kind == LValue; }
79-
bool isRValue() const { return Kind == RValue; }
80-
bool isPointer() const { return std::holds_alternative<Pointer>(Value); }
81-
82-
/// Returns an APValue for the evaluation result. The returned
83-
/// APValue might be an LValue or RValue.
84-
APValue toAPValue() const;
85-
86-
/// If the result is an LValue, convert that to an RValue
87-
/// and return it. This may fail, e.g. if the result is an
88-
/// LValue and we can't read from it.
89-
std::optional<APValue> toRValue() const;
76+
77+
/// Returns an APValue for the evaluation result.
78+
APValue toAPValue() const {
79+
assert(!empty());
80+
assert(!isInvalid());
81+
return Value;
82+
}
83+
84+
APValue stealAPValue() { return std::move(Value); }
9085

9186
/// Check that all subobjects of the given pointer have been initialized.
9287
bool checkFullyInitialized(InterpState &S, const Pointer &Ptr) const;

0 commit comments

Comments
 (0)