Author: Timm Baeder
Date: 2026-01-30T10:07:23+01:00
New Revision: afb2e4f2e2b04a34522376e6bbf39237499c745b

URL: 
https://github.com/llvm/llvm-project/commit/afb2e4f2e2b04a34522376e6bbf39237499c745b
DIFF: 
https://github.com/llvm/llvm-project/commit/afb2e4f2e2b04a34522376e6bbf39237499c745b.diff

LOG: [clang][bytecode] Clean up `interp::Function` parameter handling (#178621)

Replace the multiple data structures with a vector + a map holding all
`ParamDescriptor`s. Update docs.

Added: 
    

Modified: 
    clang/lib/AST/ByteCode/ByteCodeEmitter.cpp
    clang/lib/AST/ByteCode/Context.cpp
    clang/lib/AST/ByteCode/Function.cpp
    clang/lib/AST/ByteCode/Function.h
    clang/lib/AST/ByteCode/Interp.cpp
    clang/lib/AST/ByteCode/InterpFrame.cpp

Removed: 
    


################################################################################
diff  --git a/clang/lib/AST/ByteCode/ByteCodeEmitter.cpp 
b/clang/lib/AST/ByteCode/ByteCodeEmitter.cpp
index 5dc6eca582ad9..35821085ff49b 100644
--- a/clang/lib/AST/ByteCode/ByteCodeEmitter.cpp
+++ b/clang/lib/AST/ByteCode/ByteCodeEmitter.cpp
@@ -32,15 +32,15 @@ void ByteCodeEmitter::compileFunc(const FunctionDecl 
*FuncDecl,
     return;
 
   // Set up lambda captures.
-  if (const auto *MD = dyn_cast<CXXMethodDecl>(FuncDecl);
-      MD && isLambdaCallOperator(MD)) {
+  if (Func->isLambdaCallOperator()) {
     // Set up lambda capture to closure record field mapping.
-    const Record *R = P.getOrCreateRecord(MD->getParent());
+    const CXXRecordDecl *ParentDecl = Func->getParentDecl();
+    const Record *R = P.getOrCreateRecord(ParentDecl);
     assert(R);
     llvm::DenseMap<const ValueDecl *, FieldDecl *> LC;
     FieldDecl *LTC;
 
-    MD->getParent()->getCaptureFields(LC, LTC);
+    ParentDecl->getCaptureFields(LC, LTC);
 
     for (auto Cap : LC) {
       unsigned Offset = R->getField(Cap.second)->Offset;
@@ -59,12 +59,13 @@ void ByteCodeEmitter::compileFunc(const FunctionDecl 
*FuncDecl,
   unsigned ParamIndex = 0;
   unsigned Drop = Func->hasRVO() +
                   (Func->hasThisPointer() && !Func->isThisPointerExplicit());
-  for (auto ParamOffset : llvm::drop_begin(Func->ParamOffsets, Drop)) {
-    const ParmVarDecl *PD = FuncDecl->parameters()[ParamIndex];
+
+  for (const auto &ParamDesc : llvm::drop_begin(Func->ParamDescriptors, Drop)) 
{
+    const ParmVarDecl *PD = FuncDecl->getParamDecl(ParamIndex);
     if (PD->isInvalidDecl())
       IsValid = false;
-    OptPrimType T = Ctx.classify(PD->getType());
-    this->Params.insert({PD, {ParamOffset, T != std::nullopt}});
+    this->Params.insert(
+        {PD, {ParamDesc.Offset, Ctx.canClassify(PD->getType())}});
     ++ParamIndex;
   }
 

diff  --git a/clang/lib/AST/ByteCode/Context.cpp 
b/clang/lib/AST/ByteCode/Context.cpp
index 5d5816eb02cd2..d6fdf581baaec 100644
--- a/clang/lib/AST/ByteCode/Context.cpp
+++ b/clang/lib/AST/ByteCode/Context.cpp
@@ -520,9 +520,7 @@ const Function *Context::getOrCreateFunction(const 
FunctionDecl *FuncDecl) {
   }
   // Set up argument indices.
   unsigned ParamOffset = 0;
-  SmallVector<PrimType, 8> ParamTypes;
-  SmallVector<unsigned, 8> ParamOffsets;
-  llvm::DenseMap<unsigned, Function::ParamDescriptor> ParamDescriptors;
+  llvm::SmallVector<Function::ParamDescriptor> ParamDescriptors;
 
   // If the return is not a primitive, a pointer to the storage where the
   // value is initialized in is passed as the first argument. See 'RVO'
@@ -531,8 +529,7 @@ const Function *Context::getOrCreateFunction(const 
FunctionDecl *FuncDecl) {
   bool HasRVO = false;
   if (!Ty->isVoidType() && !canClassify(Ty)) {
     HasRVO = true;
-    ParamTypes.push_back(PT_Ptr);
-    ParamOffsets.push_back(ParamOffset);
+    ParamDescriptors.emplace_back(nullptr, ParamOffset, PT_Ptr);
     ParamOffset += align(primSize(PT_Ptr));
   }
 
@@ -544,8 +541,7 @@ const Function *Context::getOrCreateFunction(const 
FunctionDecl *FuncDecl) {
     if (!IsLambdaStaticInvoker) {
       HasThisPointer = MD->isInstance();
       if (MD->isImplicitObjectMemberFunction()) {
-        ParamTypes.push_back(PT_Ptr);
-        ParamOffsets.push_back(ParamOffset);
+        ParamDescriptors.emplace_back(nullptr, ParamOffset, PT_Ptr);
         ParamOffset += align(primSize(PT_Ptr));
       }
     }
@@ -584,18 +580,15 @@ const Function *Context::getOrCreateFunction(const 
FunctionDecl *FuncDecl) {
     Descriptor *Desc = P->createDescriptor(PD, PT, nullptr, std::nullopt,
                                            IsConst, /*IsTemporary=*/false,
                                            /*IsMutable=*/false, IsVolatile);
-
-    ParamDescriptors.insert({ParamOffset, {PT, Desc}});
-    ParamOffsets.push_back(ParamOffset);
+    ParamDescriptors.emplace_back(Desc, ParamOffset, PT);
     ParamOffset += align(primSize(PT));
-    ParamTypes.push_back(PT);
   }
 
   // Create a handle over the emitted code.
   assert(!P->getFunction(FuncDecl));
-  const Function *Func = P->createFunction(
-      FuncDecl, ParamOffset, std::move(ParamTypes), 
std::move(ParamDescriptors),
-      std::move(ParamOffsets), HasThisPointer, HasRVO, IsLambdaStaticInvoker);
+  const Function *Func =
+      P->createFunction(FuncDecl, ParamOffset, std::move(ParamDescriptors),
+                        HasThisPointer, HasRVO, IsLambdaStaticInvoker);
   return Func;
 }
 
@@ -603,9 +596,7 @@ const Function *Context::getOrCreateObjCBlock(const 
BlockExpr *E) {
   const BlockDecl *BD = E->getBlockDecl();
   // Set up argument indices.
   unsigned ParamOffset = 0;
-  SmallVector<PrimType, 8> ParamTypes;
-  SmallVector<unsigned, 8> ParamOffsets;
-  llvm::DenseMap<unsigned, Function::ParamDescriptor> ParamDescriptors;
+  llvm::SmallVector<Function::ParamDescriptor> ParamDescriptors;
 
   // Assign descriptors to all parameters.
   // Composite objects are lowered to pointers.
@@ -618,10 +609,8 @@ const Function *Context::getOrCreateObjCBlock(const 
BlockExpr *E) {
     Descriptor *Desc = P->createDescriptor(PD, PT, nullptr, std::nullopt,
                                            IsConst, /*IsTemporary=*/false,
                                            /*IsMutable=*/false, IsVolatile);
-    ParamDescriptors.insert({ParamOffset, {PT, Desc}});
-    ParamOffsets.push_back(ParamOffset);
+    ParamDescriptors.emplace_back(Desc, ParamOffset, PT);
     ParamOffset += align(primSize(PT));
-    ParamTypes.push_back(PT);
   }
 
   if (BD->hasCaptures())
@@ -629,8 +618,7 @@ const Function *Context::getOrCreateObjCBlock(const 
BlockExpr *E) {
 
   // Create a handle over the emitted code.
   Function *Func =
-      P->createFunction(E, ParamOffset, std::move(ParamTypes),
-                        std::move(ParamDescriptors), std::move(ParamOffsets),
+      P->createFunction(E, ParamOffset, std::move(ParamDescriptors),
                         /*HasThisPointer=*/false, /*HasRVO=*/false,
                         /*IsLambdaStaticInvoker=*/false);
 
@@ -638,6 +626,7 @@ const Function *Context::getOrCreateObjCBlock(const 
BlockExpr *E) {
   Func->setDefined(true);
   // We don't compile the BlockDecl code at all right now.
   Func->setIsFullyCompiled(true);
+
   return Func;
 }
 

diff  --git a/clang/lib/AST/ByteCode/Function.cpp 
b/clang/lib/AST/ByteCode/Function.cpp
index 4c7872b19dcdf..56d08a64d1024 100644
--- a/clang/lib/AST/ByteCode/Function.cpp
+++ b/clang/lib/AST/ByteCode/Function.cpp
@@ -16,15 +16,17 @@ using namespace clang;
 using namespace clang::interp;
 
 Function::Function(Program &P, FunctionDeclTy Source, unsigned ArgSize,
-                   llvm::SmallVectorImpl<PrimType> &&ParamTypes,
-                   llvm::DenseMap<unsigned, ParamDescriptor> &&Params,
-                   llvm::SmallVectorImpl<unsigned> &&ParamOffsets,
+                   llvm::SmallVectorImpl<ParamDescriptor> &&ParamDescriptors,
                    bool HasThisPointer, bool HasRVO, bool 
IsLambdaStaticInvoker)
     : P(P), Kind(FunctionKind::Normal), Source(Source), ArgSize(ArgSize),
-      ParamTypes(std::move(ParamTypes)), Params(std::move(Params)),
-      ParamOffsets(std::move(ParamOffsets)), IsValid(false),
+      ParamDescriptors(std::move(ParamDescriptors)), IsValid(false),
       IsFullyCompiled(false), HasThisPointer(HasThisPointer), HasRVO(HasRVO),
       HasBody(false), Defined(false) {
+  for (ParamDescriptor PD : this->ParamDescriptors) {
+    Params.insert({PD.Offset, PD});
+  }
+  assert(Params.size() == this->ParamDescriptors.size());
+
   if (const auto *F = dyn_cast<const FunctionDecl *>(Source)) {
     Variadic = F->isVariadic();
     Immediate = F->isImmediateFunction();

diff  --git a/clang/lib/AST/ByteCode/Function.h 
b/clang/lib/AST/ByteCode/Function.h
index a086682d4ce21..544172b7e0c26 100644
--- a/clang/lib/AST/ByteCode/Function.h
+++ b/clang/lib/AST/ByteCode/Function.h
@@ -85,6 +85,17 @@ using FunctionDeclTy =
 /// After the function has been called, it will remove all arguments,
 /// including RVO and This pointer, from the stack.
 ///
+/// The parameters saved in a clang::intepr::Function include both the
+/// instance pointer as well as the RVO pointer.
+///
+/// \verbatim
+///    Stack position when calling  ─────┐
+///    this Function                     │
+///                                      ▼
+/// ┌─────┬──────┬────────┬────────┬─────┬────────────────────┐
+/// │ RVO │ This │ Param1 │ Param2 │ ... │                    │
+/// └─────┴──────┴────────┴────────┴─────┴────────────────────┘
+/// \endverbatim
 class Function final {
 public:
   enum class FunctionKind {
@@ -95,7 +106,14 @@ class Function final {
     LambdaCallOperator,
     CopyOrMoveOperator,
   };
-  using ParamDescriptor = std::pair<PrimType, Descriptor *>;
+
+  struct ParamDescriptor {
+    const Descriptor *Desc;
+    unsigned Offset;
+    PrimType T;
+    ParamDescriptor(const Descriptor *Desc, unsigned Offset, PrimType T)
+        : Desc(Desc), Offset(Offset), T(T) {}
+  };
 
   /// Returns the size of the function's local stack.
   unsigned getFrameSize() const { return FrameSize; }
@@ -140,9 +158,9 @@ class Function final {
 
   /// Range over argument types.
   using arg_reverse_iterator =
-      SmallVectorImpl<PrimType>::const_reverse_iterator;
+      SmallVectorImpl<ParamDescriptor>::const_reverse_iterator;
   llvm::iterator_range<arg_reverse_iterator> args_reverse() const {
-    return llvm::reverse(ParamTypes);
+    return llvm::reverse(ParamDescriptors);
   }
 
   /// Returns a specific scope.
@@ -202,7 +220,7 @@ class Function final {
 
   bool isVariadic() const { return Variadic; }
 
-  unsigned getNumParams() const { return ParamTypes.size(); }
+  unsigned getNumParams() const { return ParamDescriptors.size(); }
 
   /// Returns the number of parameter this function takes when it's called,
   /// i.e excluding the instance pointer and the RVO pointer.
@@ -222,20 +240,18 @@ class Function final {
   }
 
   unsigned getParamOffset(unsigned ParamIndex) const {
-    return ParamOffsets[ParamIndex];
+    return ParamDescriptors[ParamIndex].Offset;
   }
 
   PrimType getParamType(unsigned ParamIndex) const {
-    return ParamTypes[ParamIndex];
+    return ParamDescriptors[ParamIndex].T;
   }
 
 private:
   /// Construct a function representing an actual function.
   Function(Program &P, FunctionDeclTy Source, unsigned ArgSize,
-           llvm::SmallVectorImpl<PrimType> &&ParamTypes,
-           llvm::DenseMap<unsigned, ParamDescriptor> &&Params,
-           llvm::SmallVectorImpl<unsigned> &&ParamOffsets, bool HasThisPointer,
-           bool HasRVO, bool IsLambdaStaticInvoker);
+           llvm::SmallVectorImpl<ParamDescriptor> &&ParamDescriptors,
+           bool HasThisPointer, bool HasRVO, bool IsLambdaStaticInvoker);
 
   /// Sets the code of a function.
   void setCode(FunctionDeclTy Source, unsigned NewFrameSize,
@@ -275,12 +291,10 @@ class Function final {
   SourceMap SrcMap;
   /// List of block descriptors.
   llvm::SmallVector<Scope, 2> Scopes;
-  /// List of argument types.
-  llvm::SmallVector<PrimType, 8> ParamTypes;
-  /// Map from byte offset to parameter descriptor.
+  /// List of all parameters, including RVO and instance pointer.
+  llvm::SmallVector<ParamDescriptor> ParamDescriptors;
+  /// Map from Parameter offset to parameter descriptor.
   llvm::DenseMap<unsigned, ParamDescriptor> Params;
-  /// List of parameter offsets.
-  llvm::SmallVector<unsigned, 8> ParamOffsets;
   /// Flag to indicate if the function is valid.
   LLVM_PREFERRED_TYPE(bool)
   unsigned IsValid : 1;

diff  --git a/clang/lib/AST/ByteCode/Interp.cpp 
b/clang/lib/AST/ByteCode/Interp.cpp
index 2a495a475c378..d095e6f862fc5 100644
--- a/clang/lib/AST/ByteCode/Interp.cpp
+++ b/clang/lib/AST/ByteCode/Interp.cpp
@@ -296,8 +296,8 @@ void cleanupAfterFunctionCall(InterpState &S, CodePtr OpPC,
 
   // And in any case, remove the fixed parameters (the non-variadic ones)
   // at the end.
-  for (PrimType Ty : Func->args_reverse())
-    TYPE_SWITCH(Ty, S.Stk.discard<T>());
+  for (const Function::ParamDescriptor &PDesc : Func->args_reverse())
+    TYPE_SWITCH(PDesc.T, S.Stk.discard<T>());
 }
 
 bool isConstexprUnknown(const Pointer &P) {

diff  --git a/clang/lib/AST/ByteCode/InterpFrame.cpp 
b/clang/lib/AST/ByteCode/InterpFrame.cpp
index ef70d9526c194..3c185a0ad661a 100644
--- a/clang/lib/AST/ByteCode/InterpFrame.cpp
+++ b/clang/lib/AST/ByteCode/InterpFrame.cpp
@@ -252,14 +252,14 @@ Pointer InterpFrame::getParamPointer(unsigned Off) {
   assert(!isBottomFrame());
 
   // Allocate memory to store the parameter and the block metadata.
-  const auto &Desc = Func->getParamDescriptor(Off);
-  size_t BlockSize = sizeof(Block) + Desc.second->getAllocSize();
+  const auto &PDesc = Func->getParamDescriptor(Off);
+  size_t BlockSize = sizeof(Block) + PDesc.Desc->getAllocSize();
   auto Memory = std::make_unique<char[]>(BlockSize);
-  auto *B = new (Memory.get()) Block(S.Ctx.getEvalID(), Desc.second);
+  auto *B = new (Memory.get()) Block(S.Ctx.getEvalID(), PDesc.Desc);
   B->invokeCtor();
 
   // Copy the initial value.
-  TYPE_SWITCH(Desc.first, new (B->data()) T(stackRef<T>(Off)));
+  TYPE_SWITCH(PDesc.T, new (B->data()) T(stackRef<T>(Off)));
 
   // Record the param.
   Params.insert({Off, std::move(Memory)});


        
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to