Skip to content

Commit 125dba7

Browse files
committed
Merge "merge main into amd-staging" into amd-staging
2 parents 430aaf3 + 77dc5a5 commit 125dba7

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

56 files changed

+848
-513
lines changed

clang/include/clang/Tooling/Inclusions/StandardLibrary.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
#include "llvm/Support/raw_ostream.h"
2222
#include <optional>
2323
#include <string>
24+
#include <vector>
2425

2526
namespace clang {
2627
class Decl;

clang/lib/AST/ByteCode/ByteCodeEmitter.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ class ByteCodeEmitter {
4646

4747
/// Methods implemented by the compiler.
4848
virtual bool visitFunc(const FunctionDecl *E) = 0;
49-
virtual bool visitExpr(const Expr *E) = 0;
49+
virtual bool visitExpr(const Expr *E, bool DestroyToplevelScope) = 0;
5050
virtual bool visitDeclAndReturn(const VarDecl *E, bool ConstantContext) = 0;
5151

5252
/// Emits jumps.

clang/lib/AST/ByteCode/Compiler.cpp

Lines changed: 67 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1874,8 +1874,12 @@ bool Compiler<Emitter>::VisitMemberExpr(const MemberExpr *E) {
18741874
return false;
18751875
}
18761876

1877-
if (!isa<FieldDecl>(Member))
1878-
return this->discard(Base) && this->visitDeclRef(Member, E);
1877+
if (!isa<FieldDecl>(Member)) {
1878+
if (!this->discard(Base) && !this->emitSideEffect(E))
1879+
return false;
1880+
1881+
return this->visitDeclRef(Member, E);
1882+
}
18791883

18801884
if (Initializing) {
18811885
if (!this->delegate(Base))
@@ -2579,8 +2583,15 @@ bool Compiler<Emitter>::VisitCXXReinterpretCastExpr(
25792583
const CXXReinterpretCastExpr *E) {
25802584
const Expr *SubExpr = E->getSubExpr();
25812585

2582-
bool TypesMatch = classify(E) == classify(SubExpr);
2583-
if (!this->emitInvalidCast(CastKind::Reinterpret, /*Fatal=*/!TypesMatch, E))
2586+
bool Fatal = false;
2587+
std::optional<PrimType> FromT = classify(SubExpr);
2588+
std::optional<PrimType> ToT = classify(E);
2589+
if (!FromT || !ToT)
2590+
Fatal = true;
2591+
else
2592+
Fatal = (ToT != FromT);
2593+
2594+
if (!this->emitInvalidCast(CastKind::Reinterpret, Fatal, E))
25842595
return false;
25852596

25862597
return this->delegate(SubExpr);
@@ -2666,8 +2677,14 @@ bool Compiler<Emitter>::VisitCXXConstructExpr(const CXXConstructExpr *E) {
26662677
if (!this->emitCallVar(Func, VarArgSize, E))
26672678
return false;
26682679
} else {
2669-
if (!this->emitCall(Func, 0, E))
2680+
if (!this->emitCall(Func, 0, E)) {
2681+
// When discarding, we don't need the result anyway, so clean up
2682+
// the instance dup we did earlier in case surrounding code wants
2683+
// to keep evaluating.
2684+
if (DiscardResult)
2685+
(void)this->emitPopPtr(E);
26702686
return false;
2687+
}
26712688
}
26722689

26732690
if (DiscardResult)
@@ -3716,20 +3733,29 @@ const Function *Compiler<Emitter>::getFunction(const FunctionDecl *FD) {
37163733
return Ctx.getOrCreateFunction(FD);
37173734
}
37183735

3719-
template <class Emitter> bool Compiler<Emitter>::visitExpr(const Expr *E) {
3736+
template <class Emitter>
3737+
bool Compiler<Emitter>::visitExpr(const Expr *E, bool DestroyToplevelScope) {
37203738
LocalScope<Emitter> RootScope(this);
3739+
3740+
auto maybeDestroyLocals = [&]() -> bool {
3741+
if (DestroyToplevelScope)
3742+
return RootScope.destroyLocals();
3743+
return true;
3744+
};
3745+
37213746
// Void expressions.
37223747
if (E->getType()->isVoidType()) {
37233748
if (!visit(E))
37243749
return false;
3725-
return this->emitRetVoid(E) && RootScope.destroyLocals();
3750+
return this->emitRetVoid(E) && maybeDestroyLocals();
37263751
}
37273752

37283753
// Expressions with a primitive return type.
37293754
if (std::optional<PrimType> T = classify(E)) {
37303755
if (!visit(E))
37313756
return false;
3732-
return this->emitRet(*T, E) && RootScope.destroyLocals();
3757+
3758+
return this->emitRet(*T, E) && maybeDestroyLocals();
37333759
}
37343760

37353761
// Expressions with a composite return type.
@@ -3747,10 +3773,10 @@ template <class Emitter> bool Compiler<Emitter>::visitExpr(const Expr *E) {
37473773
// We are destroying the locals AFTER the Ret op.
37483774
// The Ret op needs to copy the (alive) values, but the
37493775
// destructors may still turn the entire expression invalid.
3750-
return this->emitRetValue(E) && RootScope.destroyLocals();
3776+
return this->emitRetValue(E) && maybeDestroyLocals();
37513777
}
37523778

3753-
RootScope.destroyLocals();
3779+
(void)maybeDestroyLocals();
37543780
return false;
37553781
}
37563782

@@ -4044,18 +4070,18 @@ bool Compiler<Emitter>::visitAPValueInitializer(const APValue &Val,
40444070
}
40454071

40464072
template <class Emitter>
4047-
bool Compiler<Emitter>::VisitBuiltinCallExpr(const CallExpr *E) {
4073+
bool Compiler<Emitter>::VisitBuiltinCallExpr(const CallExpr *E,
4074+
unsigned BuiltinID) {
40484075
const Function *Func = getFunction(E->getDirectCallee());
40494076
if (!Func)
40504077
return false;
40514078

40524079
// For these, we're expected to ultimately return an APValue pointing
40534080
// to the CallExpr. This is needed to get the correct codegen.
4054-
unsigned Builtin = E->getBuiltinCallee();
4055-
if (Builtin == Builtin::BI__builtin___CFStringMakeConstantString ||
4056-
Builtin == Builtin::BI__builtin___NSStringMakeConstantString ||
4057-
Builtin == Builtin::BI__builtin_ptrauth_sign_constant ||
4058-
Builtin == Builtin::BI__builtin_function_start) {
4081+
if (BuiltinID == Builtin::BI__builtin___CFStringMakeConstantString ||
4082+
BuiltinID == Builtin::BI__builtin___NSStringMakeConstantString ||
4083+
BuiltinID == Builtin::BI__builtin_ptrauth_sign_constant ||
4084+
BuiltinID == Builtin::BI__builtin_function_start) {
40594085
if (std::optional<unsigned> GlobalOffset = P.createGlobal(E)) {
40604086
if (!this->emitGetPtrGlobal(*GlobalOffset, E))
40614087
return false;
@@ -4087,7 +4113,7 @@ bool Compiler<Emitter>::VisitBuiltinCallExpr(const CallExpr *E) {
40874113
}
40884114
}
40894115

4090-
if (!this->emitCallBI(Func, E, E))
4116+
if (!this->emitCallBI(Func, E, BuiltinID, E))
40914117
return false;
40924118

40934119
if (DiscardResult && !ReturnType->isVoidType()) {
@@ -4100,13 +4126,24 @@ bool Compiler<Emitter>::VisitBuiltinCallExpr(const CallExpr *E) {
41004126

41014127
template <class Emitter>
41024128
bool Compiler<Emitter>::VisitCallExpr(const CallExpr *E) {
4103-
if (E->getBuiltinCallee())
4104-
return VisitBuiltinCallExpr(E);
4129+
if (unsigned BuiltinID = E->getBuiltinCallee())
4130+
return VisitBuiltinCallExpr(E, BuiltinID);
4131+
4132+
const FunctionDecl *FuncDecl = E->getDirectCallee();
4133+
// Calls to replaceable operator new/operator delete.
4134+
if (FuncDecl && FuncDecl->isReplaceableGlobalAllocationFunction()) {
4135+
if (FuncDecl->getDeclName().getCXXOverloadedOperator() == OO_New ||
4136+
FuncDecl->getDeclName().getCXXOverloadedOperator() == OO_Array_New) {
4137+
return VisitBuiltinCallExpr(E, Builtin::BI__builtin_operator_new);
4138+
} else {
4139+
assert(FuncDecl->getDeclName().getCXXOverloadedOperator() == OO_Delete);
4140+
return VisitBuiltinCallExpr(E, Builtin::BI__builtin_operator_delete);
4141+
}
4142+
}
41054143

41064144
QualType ReturnType = E->getCallReturnType(Ctx.getASTContext());
41074145
std::optional<PrimType> T = classify(ReturnType);
41084146
bool HasRVO = !ReturnType->isVoidType() && !T;
4109-
const FunctionDecl *FuncDecl = E->getDirectCallee();
41104147

41114148
if (HasRVO) {
41124149
if (DiscardResult) {
@@ -5608,11 +5645,18 @@ bool Compiler<Emitter>::visitDeclRef(const ValueDecl *D, const Expr *E) {
56085645
if (isa<DecompositionDecl>(VD))
56095646
return revisit(VD);
56105647

5611-
// Visit local const variables like normal.
5612-
if ((VD->hasGlobalStorage() || VD->isLocalVarDecl() ||
5613-
VD->isStaticDataMember()) &&
5648+
if ((VD->hasGlobalStorage() || VD->isStaticDataMember()) &&
56145649
typeShouldBeVisited(VD->getType()))
56155650
return revisit(VD);
5651+
5652+
// FIXME: The evaluateValue() check here is a little ridiculous, since
5653+
// it will ultimately call into Context::evaluateAsInitializer(). In
5654+
// other words, we're evaluating the initializer, just to know if we can
5655+
// evaluate the initializer.
5656+
if (VD->isLocalVarDecl() && typeShouldBeVisited(VD->getType()) &&
5657+
VD->getInit() && !VD->getInit()->isValueDependent() &&
5658+
VD->evaluateValue())
5659+
return revisit(VD);
56165660
}
56175661
} else {
56185662
if (const auto *VD = dyn_cast<VarDecl>(D);

clang/lib/AST/ByteCode/Compiler.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,7 @@ class Compiler : public ConstStmtVisitor<Compiler<Emitter>, bool>,
133133
bool VisitVectorBinOp(const BinaryOperator *E);
134134
bool VisitCXXDefaultArgExpr(const CXXDefaultArgExpr *E);
135135
bool VisitCallExpr(const CallExpr *E);
136-
bool VisitBuiltinCallExpr(const CallExpr *E);
136+
bool VisitBuiltinCallExpr(const CallExpr *E, unsigned BuiltinID);
137137
bool VisitCXXDefaultInitExpr(const CXXDefaultInitExpr *E);
138138
bool VisitCXXBoolLiteralExpr(const CXXBoolLiteralExpr *E);
139139
bool VisitCXXNullPtrLiteralExpr(const CXXNullPtrLiteralExpr *E);
@@ -222,7 +222,7 @@ class Compiler : public ConstStmtVisitor<Compiler<Emitter>, bool>,
222222

223223
protected:
224224
bool visitStmt(const Stmt *S);
225-
bool visitExpr(const Expr *E) override;
225+
bool visitExpr(const Expr *E, bool DestroyToplevelScope) override;
226226
bool visitFunc(const FunctionDecl *F) override;
227227

228228
bool visitDeclAndReturn(const VarDecl *VD, bool ConstantContext) override;

clang/lib/AST/ByteCode/Context.cpp

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -44,13 +44,14 @@ bool Context::isPotentialConstantExpr(State &Parent, const FunctionDecl *FD) {
4444
bool Context::evaluateAsRValue(State &Parent, const Expr *E, APValue &Result) {
4545
++EvalID;
4646
bool Recursing = !Stk.empty();
47+
size_t StackSizeBefore = Stk.size();
4748
Compiler<EvalEmitter> C(*this, *P, Parent, Stk);
4849

4950
auto Res = C.interpretExpr(E, /*ConvertResultToRValue=*/E->isGLValue());
5051

5152
if (Res.isInvalid()) {
5253
C.cleanup();
53-
Stk.clear();
54+
Stk.clearTo(StackSizeBefore);
5455
return false;
5556
}
5657

@@ -60,7 +61,7 @@ bool Context::evaluateAsRValue(State &Parent, const Expr *E, APValue &Result) {
6061
#ifndef NDEBUG
6162
// Make sure we don't rely on some value being still alive in
6263
// InterpStack memory.
63-
Stk.clear();
64+
Stk.clearTo(StackSizeBefore);
6465
#endif
6566
}
6667

@@ -69,15 +70,19 @@ bool Context::evaluateAsRValue(State &Parent, const Expr *E, APValue &Result) {
6970
return true;
7071
}
7172

72-
bool Context::evaluate(State &Parent, const Expr *E, APValue &Result) {
73+
bool Context::evaluate(State &Parent, const Expr *E, APValue &Result,
74+
ConstantExprKind Kind) {
7375
++EvalID;
7476
bool Recursing = !Stk.empty();
77+
size_t StackSizeBefore = Stk.size();
7578
Compiler<EvalEmitter> C(*this, *P, Parent, Stk);
7679

77-
auto Res = C.interpretExpr(E);
80+
auto Res = C.interpretExpr(E, /*ConvertResultToRValue=*/false,
81+
/*DestroyToplevelScope=*/Kind ==
82+
ConstantExprKind::ClassTemplateArgument);
7883
if (Res.isInvalid()) {
7984
C.cleanup();
80-
Stk.clear();
85+
Stk.clearTo(StackSizeBefore);
8186
return false;
8287
}
8388

@@ -87,7 +92,7 @@ bool Context::evaluate(State &Parent, const Expr *E, APValue &Result) {
8792
#ifndef NDEBUG
8893
// Make sure we don't rely on some value being still alive in
8994
// InterpStack memory.
90-
Stk.clear();
95+
Stk.clearTo(StackSizeBefore);
9196
#endif
9297
}
9398

@@ -99,6 +104,7 @@ bool Context::evaluateAsInitializer(State &Parent, const VarDecl *VD,
99104
APValue &Result) {
100105
++EvalID;
101106
bool Recursing = !Stk.empty();
107+
size_t StackSizeBefore = Stk.size();
102108
Compiler<EvalEmitter> C(*this, *P, Parent, Stk);
103109

104110
bool CheckGlobalInitialized =
@@ -107,7 +113,8 @@ bool Context::evaluateAsInitializer(State &Parent, const VarDecl *VD,
107113
auto Res = C.interpretDecl(VD, CheckGlobalInitialized);
108114
if (Res.isInvalid()) {
109115
C.cleanup();
110-
Stk.clear();
116+
Stk.clearTo(StackSizeBefore);
117+
111118
return false;
112119
}
113120

@@ -117,7 +124,7 @@ bool Context::evaluateAsInitializer(State &Parent, const VarDecl *VD,
117124
#ifndef NDEBUG
118125
// Make sure we don't rely on some value being still alive in
119126
// InterpStack memory.
120-
Stk.clear();
127+
Stk.clearTo(StackSizeBefore);
121128
#endif
122129
}
123130

clang/lib/AST/ByteCode/Context.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,8 @@ class Context final {
5252
bool evaluateAsRValue(State &Parent, const Expr *E, APValue &Result);
5353

5454
/// Like evaluateAsRvalue(), but does no implicit lvalue-to-rvalue conversion.
55-
bool evaluate(State &Parent, const Expr *E, APValue &Result);
55+
bool evaluate(State &Parent, const Expr *E, APValue &Result,
56+
ConstantExprKind Kind);
5657

5758
/// Evaluates a toplevel initializer.
5859
bool evaluateAsInitializer(State &Parent, const VarDecl *VD, APValue &Result);

clang/lib/AST/ByteCode/DynamicAllocator.cpp

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -40,27 +40,30 @@ void DynamicAllocator::cleanup() {
4040
}
4141

4242
Block *DynamicAllocator::allocate(const Expr *Source, PrimType T,
43-
size_t NumElements, unsigned EvalID) {
43+
size_t NumElements, unsigned EvalID,
44+
Form AllocForm) {
4445
// Create a new descriptor for an array of the specified size and
4546
// element type.
4647
const Descriptor *D = allocateDescriptor(
4748
Source, T, Descriptor::InlineDescMD, NumElements, /*IsConst=*/false,
4849
/*IsTemporary=*/false, /*IsMutable=*/false);
4950

50-
return allocate(D, EvalID);
51+
return allocate(D, EvalID, AllocForm);
5152
}
5253

5354
Block *DynamicAllocator::allocate(const Descriptor *ElementDesc,
54-
size_t NumElements, unsigned EvalID) {
55+
size_t NumElements, unsigned EvalID,
56+
Form AllocForm) {
5557
// Create a new descriptor for an array of the specified size and
5658
// element type.
5759
const Descriptor *D = allocateDescriptor(
5860
ElementDesc->asExpr(), ElementDesc, Descriptor::InlineDescMD, NumElements,
5961
/*IsConst=*/false, /*IsTemporary=*/false, /*IsMutable=*/false);
60-
return allocate(D, EvalID);
62+
return allocate(D, EvalID, AllocForm);
6163
}
6264

63-
Block *DynamicAllocator::allocate(const Descriptor *D, unsigned EvalID) {
65+
Block *DynamicAllocator::allocate(const Descriptor *D, unsigned EvalID,
66+
Form AllocForm) {
6467
assert(D);
6568
assert(D->asExpr());
6669

@@ -84,7 +87,7 @@ Block *DynamicAllocator::allocate(const Descriptor *D, unsigned EvalID) {
8487
It->second.Allocations.emplace_back(std::move(Memory));
8588
else
8689
AllocationSites.insert(
87-
{D->asExpr(), AllocationSite(std::move(Memory), D->isArray())});
90+
{D->asExpr(), AllocationSite(std::move(Memory), AllocForm)});
8891
return B;
8992
}
9093

0 commit comments

Comments
 (0)