llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-clang Author: Timm Baeder (tbaederr) <details> <summary>Changes</summary> Quite a few opcode implementations don't ever report a diagnostic, so they don't need the `OpPC` at all. Add a tablegen bit to disable passing `OpPC` altogether. --- Full diff: https://github.com/llvm/llvm-project/pull/207479.diff 5 Files Affected: - (modified) clang/lib/AST/ByteCode/EvalEmitter.cpp (+2-2) - (modified) clang/lib/AST/ByteCode/Interp.cpp (+4-4) - (modified) clang/lib/AST/ByteCode/Interp.h (+27-28) - (modified) clang/lib/AST/ByteCode/Opcodes.td (+22-24) - (modified) clang/utils/TableGen/ClangOpcodesEmitter.cpp (+14-4) ``````````diff diff --git a/clang/lib/AST/ByteCode/EvalEmitter.cpp b/clang/lib/AST/ByteCode/EvalEmitter.cpp index dbec700c80d44..34c85c7c66bdd 100644 --- a/clang/lib/AST/ByteCode/EvalEmitter.cpp +++ b/clang/lib/AST/ByteCode/EvalEmitter.cpp @@ -209,8 +209,8 @@ bool EvalEmitter::speculate(const CallExpr *E, const LabelTy &EndLabel) { if (!isActive()) return true; - PushIgnoreDiags(S, OpPC); - auto _ = llvm::scope_exit([&]() { PopIgnoreDiags(S, OpPC); }); + PushIgnoreDiags(S); + auto _ = llvm::scope_exit([&]() { PopIgnoreDiags(S); }); size_t StackSizeBefore = S.Stk.size(); const Expr *Arg = E->getArg(0); diff --git a/clang/lib/AST/ByteCode/Interp.cpp b/clang/lib/AST/ByteCode/Interp.cpp index dc93cc4fd698c..6d9b8bc78668f 100644 --- a/clang/lib/AST/ByteCode/Interp.cpp +++ b/clang/lib/AST/ByteCode/Interp.cpp @@ -2891,7 +2891,7 @@ static void finishGlobalRecurse(InterpState &S, const Pointer &Ptr) { } } -bool FinishInitGlobal(InterpState &S, CodePtr OpPC) { +bool FinishInitGlobal(InterpState &S) { const Pointer &Ptr = S.Stk.pop<Pointer>(); finishGlobalRecurse(S, Ptr); @@ -3175,10 +3175,10 @@ PRESERVE_NONE static bool BCP(InterpState &S, CodePtr OpPC, int32_t Offset, assert(DepthBefore >= 1); #endif - auto SpeculativeInterp = [&S, OpPC]() -> bool { + auto SpeculativeInterp = [&S]() -> bool { // Ignore diagnostics during speculative execution. - PushIgnoreDiags(S, OpPC); - auto _ = llvm::scope_exit([&]() { PopIgnoreDiags(S, OpPC); }); + PushIgnoreDiags(S); + auto _ = llvm::scope_exit([&]() { PopIgnoreDiags(S); }); #if USE_TAILCALLS auto Op = S.PC.read<Opcode>(); diff --git a/clang/lib/AST/ByteCode/Interp.h b/clang/lib/AST/ByteCode/Interp.h index 61c2b0a5e5960..26cada1685186 100644 --- a/clang/lib/AST/ByteCode/Interp.h +++ b/clang/lib/AST/ByteCode/Interp.h @@ -1537,20 +1537,19 @@ bool GE(InterpState &S, CodePtr OpPC) { //===----------------------------------------------------------------------===// template <PrimType Name, class T = typename PrimConv<Name>::T> -bool Dup(InterpState &S, CodePtr OpPC) { +bool Dup(InterpState &S) { S.Stk.push<T>(S.Stk.peek<T>()); return true; } template <PrimType Name, class T = typename PrimConv<Name>::T> -bool Pop(InterpState &S, CodePtr OpPC) { +bool Pop(InterpState &S) { S.Stk.discard<T>(); return true; } /// [Value1, Value2] -> [Value2, Value1] -template <PrimType TopName, PrimType BottomName> -bool Flip(InterpState &S, CodePtr OpPC) { +template <PrimType TopName, PrimType BottomName> bool Flip(InterpState &S) { using TopT = typename PrimConv<TopName>::T; using BottomT = typename PrimConv<BottomName>::T; @@ -1568,7 +1567,7 @@ bool Flip(InterpState &S, CodePtr OpPC) { //===----------------------------------------------------------------------===// template <PrimType Name, class T = typename PrimConv<Name>::T> -bool Const(InterpState &S, CodePtr OpPC, const T &Arg) { +bool Const(InterpState &S, const T &Arg) { if constexpr (needsAlloc<T>()) { T Result = S.allocAP<T>(Arg.bitWidth()); Result.copy(Arg.toAPSInt()); @@ -1596,7 +1595,7 @@ bool Const(InterpState &S, CodePtr OpPC, const T &Arg) { return true; } -inline bool ConstFloat(InterpState &S, CodePtr OpPC, const Floating &F) { +inline bool ConstFloat(InterpState &S, const Floating &F) { Floating Result = S.allocFloat(F.getSemantics()); Result.copy(F.getAPFloat()); S.Stk.push<Floating>(Result); @@ -2120,21 +2119,21 @@ inline bool GetPtrThisBase(InterpState &S, CodePtr OpPC, uint32_t Off) { return true; } -inline bool FinishInitPop(InterpState &S, CodePtr OpPC) { +inline bool FinishInitPop(InterpState &S) { const Pointer &Ptr = S.Stk.pop<Pointer>(); if (Ptr.canBeInitialized()) Ptr.initialize(); return true; } -inline bool FinishInit(InterpState &S, CodePtr OpPC) { +inline bool FinishInit(InterpState &S) { const Pointer &Ptr = S.Stk.peek<Pointer>(); if (Ptr.canBeInitialized()) Ptr.initialize(); return true; } -inline bool FinishInitActivate(InterpState &S, CodePtr OpPC) { +inline bool FinishInitActivate(InterpState &S) { const Pointer &Ptr = S.Stk.peek<Pointer>(); if (Ptr.canBeInitialized()) { Ptr.initialize(); @@ -2143,7 +2142,7 @@ inline bool FinishInitActivate(InterpState &S, CodePtr OpPC) { return true; } -inline bool FinishInitActivatePop(InterpState &S, CodePtr OpPC) { +inline bool FinishInitActivatePop(InterpState &S) { const Pointer &Ptr = S.Stk.pop<Pointer>(); if (Ptr.canBeInitialized()) { Ptr.initialize(); @@ -2152,7 +2151,7 @@ inline bool FinishInitActivatePop(InterpState &S, CodePtr OpPC) { return true; } -bool FinishInitGlobal(InterpState &S, CodePtr OpPC); +bool FinishInitGlobal(InterpState &S); inline bool Dump(InterpState &S, CodePtr OpPC) { S.Stk.dump(); @@ -2261,14 +2260,14 @@ bool StorePop(InterpState &S, CodePtr OpPC) { return true; } -static inline bool Activate(InterpState &S, CodePtr OpPC) { +static inline bool Activate(InterpState &S) { const Pointer &Ptr = S.Stk.peek<Pointer>(); if (Ptr.canBeInitialized()) Ptr.activate(); return true; } -static inline bool ActivateThisField(InterpState &S, CodePtr OpPC, uint32_t I) { +static inline bool ActivateThisField(InterpState &S, uint32_t I) { if (S.checkingPotentialConstantExpression()) return false; if (!S.Current->hasThisPointer()) @@ -3139,12 +3138,12 @@ static inline bool PtrPtrCast(InterpState &S, CodePtr OpPC, bool SrcIsVoidPtr) { //===----------------------------------------------------------------------===// template <PrimType Name, class T = typename PrimConv<Name>::T> -bool Zero(InterpState &S, CodePtr OpPC) { +bool Zero(InterpState &S) { S.Stk.push<T>(T::zero()); return true; } -static inline bool ZeroIntAP(InterpState &S, CodePtr OpPC, uint32_t BitWidth) { +static inline bool ZeroIntAP(InterpState &S, uint32_t BitWidth) { auto Result = S.allocAP<IntegralAP<false>>(BitWidth); if (!Result.singleWord()) std::memset(Result.Memory, 0, Result.numWords() * sizeof(uint64_t)); @@ -3152,7 +3151,7 @@ static inline bool ZeroIntAP(InterpState &S, CodePtr OpPC, uint32_t BitWidth) { return true; } -static inline bool ZeroIntAPS(InterpState &S, CodePtr OpPC, uint32_t BitWidth) { +static inline bool ZeroIntAPS(InterpState &S, uint32_t BitWidth) { auto Result = S.allocAP<IntegralAP<true>>(BitWidth); if (!Result.singleWord()) std::memset(Result.Memory, 0, Result.numWords() * sizeof(uint64_t)); @@ -3161,7 +3160,7 @@ static inline bool ZeroIntAPS(InterpState &S, CodePtr OpPC, uint32_t BitWidth) { } template <PrimType Name, class T = typename PrimConv<Name>::T> -inline bool Null(InterpState &S, CodePtr OpPC, uint64_t Value, const Type *Ty) { +inline bool Null(InterpState &S, uint64_t Value, const Type *Ty) { // FIXME(perf): This is a somewhat often-used function and the value of a // null pointer is almost always 0. S.Stk.push<T>(Value, Ty); @@ -3433,13 +3432,13 @@ PRESERVE_NONE inline bool NoRet(InterpState &S, CodePtr OpPC) { // NarrowPtr, ExpandPtr //===----------------------------------------------------------------------===// -inline bool NarrowPtr(InterpState &S, CodePtr OpPC) { +inline bool NarrowPtr(InterpState &S) { const Pointer &Ptr = S.Stk.pop<Pointer>(); S.Stk.push<Pointer>(Ptr.narrow()); return true; } -inline bool ExpandPtr(InterpState &S, CodePtr OpPC) { +inline bool ExpandPtr(InterpState &S) { const Pointer &Ptr = S.Stk.pop<Pointer>(); if (Ptr.isBlockPointer()) S.Stk.push<Pointer>(Ptr.expand()); @@ -3654,7 +3653,7 @@ inline bool Unsupported(InterpState &S, CodePtr OpPC) { return false; } -inline bool PushIgnoreDiags(InterpState &S, CodePtr OpPC) { +inline bool PushIgnoreDiags(InterpState &S) { ++S.DiagIgnoreDepth; if (S.DiagIgnoreDepth != 1) return true; @@ -3666,7 +3665,7 @@ inline bool PushIgnoreDiags(InterpState &S, CodePtr OpPC) { return true; } -inline bool PopIgnoreDiags(InterpState &S, CodePtr OpPC) { +inline bool PopIgnoreDiags(InterpState &S) { assert(S.DiagIgnoreDepth != 0); --S.DiagIgnoreDepth; if (S.DiagIgnoreDepth == 0) { @@ -3677,20 +3676,20 @@ inline bool PopIgnoreDiags(InterpState &S, CodePtr OpPC) { return true; } -inline bool StartSpeculation(InterpState &S, CodePtr OpPC) { +inline bool StartSpeculation(InterpState &S) { #ifndef NDEBUG ++S.SpeculationDepth; #endif return true; } -inline bool StartInit(InterpState &S, CodePtr OpPC) { +inline bool StartInit(InterpState &S) { const Pointer &Ptr = S.Stk.peek<Pointer>(); S.InitializingPtrs.push_back(Ptr.view()); return true; } -inline bool EndInit(InterpState &S, CodePtr OpPC) { +inline bool EndInit(InterpState &S) { S.InitializingPtrs.pop_back(); return true; } @@ -3706,22 +3705,22 @@ PRESERVE_NONE inline bool EndSpeculation(InterpState &S) { return true; } -inline bool PushCC(InterpState &S, CodePtr OpPC, bool Value) { +inline bool PushCC(InterpState &S, bool Value) { S.ConstantContextOverride = Value; return true; } -inline bool PopCC(InterpState &S, CodePtr OpPC) { +inline bool PopCC(InterpState &S) { S.ConstantContextOverride = std::nullopt; return true; } -inline bool PushMSVCCE(InterpState &S, CodePtr OpPC) { +inline bool PushMSVCCE(InterpState &S) { // This is a per-frame property. ++S.Current->MSVCConstexprAllowed; return true; } -inline bool PopMSVCCE(InterpState &S, CodePtr OpPC) { +inline bool PopMSVCCE(InterpState &S) { assert(S.Current->MSVCConstexprAllowed >= 1); // This is a per-frame property. --S.Current->MSVCConstexprAllowed; diff --git a/clang/lib/AST/ByteCode/Opcodes.td b/clang/lib/AST/ByteCode/Opcodes.td index 8123ca7497335..cf99c1f056527 100644 --- a/clang/lib/AST/ByteCode/Opcodes.td +++ b/clang/lib/AST/ByteCode/Opcodes.td @@ -145,10 +145,12 @@ class Opcode { bit HasCustomEval = 0; bit HasGroup = 0; bit CanFail = 1; + bit NeedsOpPC = 1; } class SuccessOpcode : Opcode { let CanFail = 0; + let NeedsOpPC = 0; } class AluOpcode : Opcode { @@ -272,11 +274,10 @@ def EnableLocal : Opcode { // Constants //===----------------------------------------------------------------------===// -class ConstOpcode<Type Ty, ArgType ArgTy> : Opcode { +class ConstOpcode<Type Ty, ArgType ArgTy> : SuccessOpcode { let Types = [SingletonTypeClass<Ty>]; let Args = [ArgTy]; let Name = "Const"; - let CanFail = 0; } // [] -> [Integer] @@ -293,35 +294,29 @@ def ConstIntAPS : ConstOpcode<IntAPS, ArgIntAPS>; def ConstBool : ConstOpcode<Bool, ArgBool>; def ConstFixedPoint : ConstOpcode<FixedPoint, ArgFixedPoint>; -def ConstFloat : Opcode { +def ConstFloat : SuccessOpcode { let Args = [ArgFloat]; - let CanFail = 0; } // [] -> [Integer] -def Zero : Opcode { +def Zero : SuccessOpcode { let Types = [FixedSizeIntegralTypeClass]; let HasGroup = 1; - let CanFail = 0; - } -def ZeroIntAP : Opcode { +def ZeroIntAP : SuccessOpcode { let Args = [ArgUint32]; - let CanFail = 0; } -def ZeroIntAPS : Opcode { +def ZeroIntAPS : SuccessOpcode { let Args = [ArgUint32]; - let CanFail = 0; } // [] -> [Pointer] -def Null : Opcode { +def Null : SuccessOpcode { let Types = [PtrTypeClass]; let Args = [ArgUint64, ArgTypePtr]; let HasGroup = 1; - let CanFail = 0; } //===----------------------------------------------------------------------===// @@ -551,8 +546,13 @@ def StoreBitFieldPop : StoreBitFieldOpcode {} def StoreBitFieldActivate : StoreBitFieldOpcode {} def StoreBitFieldActivatePop : StoreBitFieldOpcode {} -def Activate : SuccessOpcode; -def ActivateThisField : Opcode { let Args = [ArgUint32]; } +def Activate : SuccessOpcode { + let NeedsOpPC = 0; +} +def ActivateThisField : Opcode { + let Args = [ArgUint32]; + let NeedsOpPC = 0; +} // [Pointer, Value] -> [] def Init : StoreOpcode {} @@ -846,23 +846,20 @@ def GE : ComparisonOpcode; //===----------------------------------------------------------------------===// // [Value] -> [] -def Pop : Opcode { +def Pop : SuccessOpcode { let Types = [AllTypeClass]; let HasGroup = 1; - let CanFail = 0; } // [Value] -> [Value, Value] -def Dup : Opcode { +def Dup : SuccessOpcode { let Types = [AllTypeClass]; let HasGroup = 1; - let CanFail = 0; } -def Flip : Opcode { +def Flip : SuccessOpcode { let Types = [AllTypeClass, AllTypeClass]; let HasGroup = 1; - let CanFail = 0; } // [] -> [] @@ -878,7 +875,9 @@ def DynamicCast : Opcode { } def InvalidStore : Opcode { let Args = [ArgTypePtr]; } -def CheckPseudoDtor : SuccessOpcode; +def CheckPseudoDtor : SuccessOpcode { + let NeedsOpPC = 1; +} def InvalidDeclRef : Opcode { let Args = [ArgDeclRef, ArgBool]; @@ -970,9 +969,8 @@ def CheckDestruction : Opcode; def CtorCheck : Opcode; -def PushCC : Opcode { +def PushCC : SuccessOpcode { let Args = [ArgBool]; - let CanFail = 0; } def PopCC : SuccessOpcode; def PushMSVCCE : SuccessOpcode; diff --git a/clang/utils/TableGen/ClangOpcodesEmitter.cpp b/clang/utils/TableGen/ClangOpcodesEmitter.cpp index 13a99900bc9ec..4a3c901d2de7f 100644 --- a/clang/utils/TableGen/ClangOpcodesEmitter.cpp +++ b/clang/utils/TableGen/ClangOpcodesEmitter.cpp @@ -126,6 +126,7 @@ void ClangOpcodesEmitter::EmitInterpFnDispatchers(raw_ostream &OS, StringRef N, bool CanReturn = R->getValueAsBit("CanReturn"); const auto &Args = R->getValueAsListOfDefs("Args"); bool CanFail = R->getValueAsBit("CanFail"); + bool PassOpPC = R->getValueAsBit("NeedsOpPC"); if (Args.empty()) { if (CanReturn) { @@ -142,7 +143,11 @@ void ClangOpcodesEmitter::EmitInterpFnDispatchers(raw_ostream &OS, StringRef N, OS << N; PrintTypes(OS, TS); - OS << "(S, S.PC)"; + OS << "(S"; + if (PassOpPC) + OS << ", S.PC)"; + else + OS << ")"; if (CanFail) OS << ") return false"; @@ -160,7 +165,8 @@ void ClangOpcodesEmitter::EmitInterpFnDispatchers(raw_ostream &OS, StringRef N, OS << " {\n"; - OS << " CodePtr OpPC = S.PC;\n"; + if (PassOpPC) + OS << " CodePtr OpPC = S.PC;\n"; // Emit calls to read arguments. for (size_t I = 0, N = Args.size(); I < N; ++I) { @@ -182,7 +188,8 @@ void ClangOpcodesEmitter::EmitInterpFnDispatchers(raw_ostream &OS, StringRef N, OS << N; PrintTypes(OS, TS); OS << "(S"; - OS << ", OpPC"; + if (PassOpPC) + OS << ", OpPC"; for (size_t I = 0, N = Args.size(); I < N; ++I) OS << ", V" << I; @@ -431,10 +438,13 @@ void ClangOpcodesEmitter::EmitEval(raw_ostream &OS, StringRef N, if (N == "EndSpeculation") { OS << "return EndSpeculation(S);\n"; } else { + bool PassOpPC = R->getValueAsBit("NeedsOpPC"); OS << " return " << N; PrintTypes(OS, TS); - OS << "(S, OpPC"; + OS << "(S"; + if (PassOpPC) + OS << ", OpPC"; for (size_t I = 0, N = Args.size(); I < N; ++I) OS << ", A" << I; OS << ");\n"; `````````` </details> https://github.com/llvm/llvm-project/pull/207479 _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
