From 17d3029331a65ea54ad1bdbf79add03d5a71dcd4 Mon Sep 17 00:00:00 2001 From: Timm Baeder Date: Wed, 16 Jul 2025 09:03:33 +0200 Subject: [clang][bytecode] Make union activation more granular (#148835) Only activate things if the syntactical structure suggests so. This adds a bunch of new opcodes to control whether to activate in stores, etc. Fixes #134789 --- clang/lib/AST/ByteCode/Pointer.cpp | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) (limited to 'clang/lib/AST/ByteCode/Pointer.cpp') diff --git a/clang/lib/AST/ByteCode/Pointer.cpp b/clang/lib/AST/ByteCode/Pointer.cpp index 159b4238a6a0..2f9ecf98e558 100644 --- a/clang/lib/AST/ByteCode/Pointer.cpp +++ b/clang/lib/AST/ByteCode/Pointer.cpp @@ -502,8 +502,17 @@ void Pointer::activate() const { if (!getInlineDesc()->InUnion) return; - auto activate = [](Pointer &P) -> void { + std::function activate; + activate = [&activate](Pointer &P) -> void { P.getInlineDesc()->IsActive = true; + if (const Record *R = P.getRecord(); R && !R->isUnion()) { + for (const Record::Field &F : R->fields()) { + Pointer FieldPtr = P.atField(F.Offset); + if (!FieldPtr.getInlineDesc()->IsActive) + activate(FieldPtr); + } + // FIXME: Bases? + } }; std::function deactivate; -- cgit v1.2.3 From 5b0935f1f05c7aa9d315463c17ff85e7d846d237 Mon Sep 17 00:00:00 2001 From: Timm Baeder Date: Sun, 20 Jul 2025 10:59:50 +0200 Subject: [clang][bytecode] Reintroduce Pointer::elem() (#149693) As a way of writing atIndex(I).deref(), which creates an intermediate Pointer, which in turn adds (and removes) that pointer from the pointer list of the Block. This way we can avoid that. --- clang/lib/AST/ByteCode/Pointer.cpp | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) (limited to 'clang/lib/AST/ByteCode/Pointer.cpp') diff --git a/clang/lib/AST/ByteCode/Pointer.cpp b/clang/lib/AST/ByteCode/Pointer.cpp index 2f9ecf98e558..c4d06d6a430d 100644 --- a/clang/lib/AST/ByteCode/Pointer.cpp +++ b/clang/lib/AST/ByteCode/Pointer.cpp @@ -760,14 +760,14 @@ std::optional Pointer::toRValue(const Context &Ctx, std::optional ElemT = Ctx.classify(ElemTy); assert(ElemT); INT_TYPE_SWITCH(*ElemT, { - auto V1 = Ptr.atIndex(0).deref(); - auto V2 = Ptr.atIndex(1).deref(); + auto V1 = Ptr.elem(0); + auto V2 = Ptr.elem(1); R = APValue(V1.toAPSInt(), V2.toAPSInt()); return true; }); } else if (ElemTy->isFloatingType()) { - R = APValue(Ptr.atIndex(0).deref().getAPFloat(), - Ptr.atIndex(1).deref().getAPFloat()); + R = APValue(Ptr.elem(0).getAPFloat(), + Ptr.elem(1).getAPFloat()); return true; } return false; @@ -782,9 +782,8 @@ std::optional Pointer::toRValue(const Context &Ctx, SmallVector Values; Values.reserve(VT->getNumElements()); for (unsigned I = 0; I != VT->getNumElements(); ++I) { - TYPE_SWITCH(ElemT, { - Values.push_back(Ptr.atIndex(I).deref().toAPValue(ASTCtx)); - }); + TYPE_SWITCH(ElemT, + { Values.push_back(Ptr.elem(I).toAPValue(ASTCtx)); }); } assert(Values.size() == VT->getNumElements()); -- cgit v1.2.3 From e39ee62c5bdbe71b9f191bc5da7d47577e2099a9 Mon Sep 17 00:00:00 2001 From: Timm Baeder Date: Mon, 21 Jul 2025 17:16:13 +0200 Subject: [clang][bytecode] Use OptPrimType instead of std::optional (#149812) We use this construct a lot. Use something similar to clang's UnsignedOrNone. This results in some slighy compile time improvements: https://llvm-compile-time-tracker.com/compare.php?from=17a4b0399d161a3b89d8f0ce82add1638f23f5d4&to=a251d81ecd0ed45dd190462663155fdb303ef04d&stat=instructions:u --- clang/lib/AST/ByteCode/Pointer.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'clang/lib/AST/ByteCode/Pointer.cpp') diff --git a/clang/lib/AST/ByteCode/Pointer.cpp b/clang/lib/AST/ByteCode/Pointer.cpp index c4d06d6a430d..4019b7466928 100644 --- a/clang/lib/AST/ByteCode/Pointer.cpp +++ b/clang/lib/AST/ByteCode/Pointer.cpp @@ -665,7 +665,7 @@ std::optional Pointer::toRValue(const Context &Ctx, return false; // Primitive values. - if (std::optional T = Ctx.classify(Ty)) { + if (OptPrimType T = Ctx.classify(Ty)) { TYPE_SWITCH(*T, R = Ptr.deref().toAPValue(ASTCtx)); return true; } @@ -682,7 +682,7 @@ std::optional Pointer::toRValue(const Context &Ctx, const Pointer &FP = Ptr.atField(F.Offset); QualType FieldTy = F.Decl->getType(); if (FP.isActive()) { - if (std::optional T = Ctx.classify(FieldTy)) { + if (OptPrimType T = Ctx.classify(FieldTy)) { TYPE_SWITCH(*T, Value = FP.deref().toAPValue(ASTCtx)); } else { Ok &= Composite(FieldTy, FP, Value); @@ -705,7 +705,7 @@ std::optional Pointer::toRValue(const Context &Ctx, const Pointer &FP = Ptr.atField(FD->Offset); APValue &Value = R.getStructField(I); - if (std::optional T = Ctx.classify(FieldTy)) { + if (OptPrimType T = Ctx.classify(FieldTy)) { TYPE_SWITCH(*T, Value = FP.deref().toAPValue(ASTCtx)); } else { Ok &= Composite(FieldTy, FP, Value); @@ -743,7 +743,7 @@ std::optional Pointer::toRValue(const Context &Ctx, for (unsigned I = 0; I < NumElems; ++I) { APValue &Slot = R.getArrayInitializedElt(I); const Pointer &EP = Ptr.atIndex(I); - if (std::optional T = Ctx.classify(ElemTy)) { + if (OptPrimType T = Ctx.classify(ElemTy)) { TYPE_SWITCH(*T, Slot = EP.deref().toAPValue(ASTCtx)); } else { Ok &= Composite(ElemTy, EP.narrow(), Slot); @@ -757,7 +757,7 @@ std::optional Pointer::toRValue(const Context &Ctx, QualType ElemTy = CT->getElementType(); if (ElemTy->isIntegerType()) { - std::optional ElemT = Ctx.classify(ElemTy); + OptPrimType ElemT = Ctx.classify(ElemTy); assert(ElemT); INT_TYPE_SWITCH(*ElemT, { auto V1 = Ptr.elem(0); @@ -803,7 +803,7 @@ std::optional Pointer::toRValue(const Context &Ctx, return toAPValue(ASTCtx); // Just load primitive types. - if (std::optional T = Ctx.classify(ResultType)) { + if (OptPrimType T = Ctx.classify(ResultType)) { TYPE_SWITCH(*T, return this->deref().toAPValue(ASTCtx)); } -- cgit v1.2.3