https://github.com/tbaederr created 
https://github.com/llvm/llvm-project/pull/218911

Just emit pointers to bytecode as uintptr_t. This avoids a vector and a 
DenseMap in Program. We used to emit the ID as uint32_t, but since all 
arguments are pointer-aligned in bytecode anyway, switching to uint64_t 
shouldn't cause a memory regression.

>From fd954c3d9a926f9e9f8fc9298442ce8dbe938a47 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Timm=20B=C3=A4der?= <[email protected]>
Date: Wed, 26 Aug 2026 13:14:36 +0200
Subject: [PATCH] [clang][bytecode] Remove native pointer marshalling

Just emit pointers to bytecode as uintptr_t. This avoids a vector and a
DenseMap in Program. We used to emit the ID as uint32_t, but since all
arguments are pointer-aligned in bytecode anyway, switching to uint64_t
shouldn't cause a memory regression.
---
 clang/lib/AST/ByteCode/ByteCodeEmitter.cpp   |  5 ++---
 clang/lib/AST/ByteCode/Disasm.cpp            | 22 ++++++++------------
 clang/lib/AST/ByteCode/Function.cpp          |  4 ++--
 clang/lib/AST/ByteCode/Function.h            |  5 +----
 clang/lib/AST/ByteCode/Interp.h              |  8 +++----
 clang/lib/AST/ByteCode/Program.cpp           | 13 ------------
 clang/lib/AST/ByteCode/Program.h             | 15 ++-----------
 clang/utils/TableGen/ClangOpcodesEmitter.cpp |  2 +-
 8 files changed, 20 insertions(+), 54 deletions(-)

diff --git a/clang/lib/AST/ByteCode/ByteCodeEmitter.cpp 
b/clang/lib/AST/ByteCode/ByteCodeEmitter.cpp
index f04478eb6ac16..c3dfec70134c0 100644
--- a/clang/lib/AST/ByteCode/ByteCodeEmitter.cpp
+++ b/clang/lib/AST/ByteCode/ByteCodeEmitter.cpp
@@ -138,7 +138,7 @@ static void emit(Program &P, 
llvm::SmallVectorImpl<std::byte> &Code,
   size_t Size;
 
   if constexpr (std::is_pointer_v<T>)
-    Size = align(sizeof(uint32_t));
+    Size = align(sizeof(uintptr_t));
   else
     Size = align(sizeof(T));
 
@@ -155,8 +155,7 @@ static void emit(Program &P, 
llvm::SmallVectorImpl<std::byte> &Code,
   if constexpr (!std::is_pointer_v<T>) {
     new (Code.data() + ValPos) T(Val);
   } else {
-    uint32_t ID = P.getOrCreateNativePointer(Val);
-    new (Code.data() + ValPos) uint32_t(ID);
+    new (Code.data() + ValPos) uintptr_t(reinterpret_cast<uintptr_t>(Val));
   }
 }
 
diff --git a/clang/lib/AST/ByteCode/Disasm.cpp 
b/clang/lib/AST/ByteCode/Disasm.cpp
index 9499d3a246706..611d64a2f1f54 100644
--- a/clang/lib/AST/ByteCode/Disasm.cpp
+++ b/clang/lib/AST/ByteCode/Disasm.cpp
@@ -33,13 +33,12 @@
 using namespace clang;
 using namespace clang::interp;
 
-template <typename T>
-inline static std::string printArg(Program &P, CodePtr &OpPC) {
+template <typename T> inline static std::string printArg(CodePtr &OpPC) {
   if constexpr (std::is_pointer_v<T>) {
-    uint32_t ID = OpPC.read<uint32_t>();
+    uintptr_t Ptr = OpPC.read<uintptr_t>();
     std::string Result;
     llvm::raw_string_ostream SS(Result);
-    SS << reinterpret_cast<T>(P.getNativePointer(ID));
+    SS << reinterpret_cast<void *>(Ptr);
     return Result;
   } else {
     std::string Result;
@@ -63,7 +62,7 @@ inline static std::string printArg(Program &P, CodePtr &OpPC) 
{
   }
 }
 
-template <> inline std::string printArg<Floating>(Program &P, CodePtr &OpPC) {
+template <> inline std::string printArg<Floating>(CodePtr &OpPC) {
   auto Sem = Floating::deserializeSemantics(*OpPC);
 
   unsigned BitWidth = llvm::APFloatBase::semanticsSizeInBits(
@@ -81,8 +80,7 @@ template <> inline std::string printArg<Floating>(Program &P, 
CodePtr &OpPC) {
   return S;
 }
 
-template <>
-inline std::string printArg<IntegralAP<false>>(Program &P, CodePtr &OpPC) {
+template <> inline std::string printArg<IntegralAP<false>>(CodePtr &OpPC) {
   using T = IntegralAP<false>;
   uint32_t BitWidth = T::deserializeSize(*OpPC);
   auto Memory =
@@ -99,8 +97,7 @@ inline std::string printArg<IntegralAP<false>>(Program &P, 
CodePtr &OpPC) {
   return Str;
 }
 
-template <>
-inline std::string printArg<IntegralAP<true>>(Program &P, CodePtr &OpPC) {
+template <> inline std::string printArg<IntegralAP<true>>(CodePtr &OpPC) {
   using T = IntegralAP<true>;
   uint32_t BitWidth = T::deserializeSize(*OpPC);
   auto Memory =
@@ -117,7 +114,7 @@ inline std::string printArg<IntegralAP<true>>(Program &P, 
CodePtr &OpPC) {
   return Str;
 }
 
-template <> inline std::string printArg<FixedPoint>(Program &P, CodePtr &OpPC) 
{
+template <> inline std::string printArg<FixedPoint>(CodePtr &OpPC) {
   auto F = FixedPoint::deserialize(*OpPC);
   OpPC += align(F.bytesToSerialize());
 
@@ -152,9 +149,8 @@ LLVM_DUMP_METHOD void Function::dump(llvm::raw_ostream &OS,
   {
     ColorScope SC(OS, true, {llvm::raw_ostream::BRIGHT_GREEN, true});
     if (const FunctionDecl *FD = getDecl()) {
-      FD->getNameForDiagnostic(
-          OS, P.getContext().getASTContext().getPrintingPolicy(),
-          /*Qualified=*/true);
+      FD->getNameForDiagnostic(OS, FD->getASTContext().getPrintingPolicy(),
+                               /*Qualified=*/true);
     } else {
       OS << getName();
     }
diff --git a/clang/lib/AST/ByteCode/Function.cpp 
b/clang/lib/AST/ByteCode/Function.cpp
index 49282c9dc7a33..a609af5828d92 100644
--- a/clang/lib/AST/ByteCode/Function.cpp
+++ b/clang/lib/AST/ByteCode/Function.cpp
@@ -15,10 +15,10 @@
 using namespace clang;
 using namespace clang::interp;
 
-Function::Function(Program &P, FunctionDeclTy Source, unsigned ArgSize,
+Function::Function(FunctionDeclTy Source, unsigned ArgSize,
                    llvm::SmallVectorImpl<ParamDescriptor> &&ParamDescriptors,
                    bool HasThisPointer, bool HasRVO, bool 
IsLambdaStaticInvoker)
-    : P(P), Kind(FunctionKind::Normal), Source(Source), ArgSize(ArgSize),
+    : Kind(FunctionKind::Normal), Source(Source), ArgSize(ArgSize),
       ParamDescriptors(std::move(ParamDescriptors)), IsValid(false),
       IsFullyCompiled(false), HasThisPointer(HasThisPointer), HasRVO(HasRVO),
       HasBody(false), Defined(false) {
diff --git a/clang/lib/AST/ByteCode/Function.h 
b/clang/lib/AST/ByteCode/Function.h
index 9742a16b50f2c..5dec1a0eee8ca 100644
--- a/clang/lib/AST/ByteCode/Function.h
+++ b/clang/lib/AST/ByteCode/Function.h
@@ -25,7 +25,6 @@
 
 namespace clang {
 namespace interp {
-class Program;
 class ByteCodeEmitter;
 class Pointer;
 enum PrimType : uint8_t;
@@ -254,7 +253,7 @@ class Function final {
 
 private:
   /// Construct a function representing an actual function.
-  Function(Program &P, FunctionDeclTy Source, unsigned ArgSize,
+  Function(FunctionDeclTy Source, unsigned ArgSize,
            llvm::SmallVectorImpl<ParamDescriptor> &&ParamDescriptors,
            bool HasThisPointer, bool HasRVO, bool IsLambdaStaticInvoker);
 
@@ -280,8 +279,6 @@ class Function final {
   friend class ByteCodeEmitter;
   friend class Context;
 
-  /// Program reference.
-  Program &P;
   /// Function Kind.
   FunctionKind Kind;
   /// Declaration this function was compiled from.
diff --git a/clang/lib/AST/ByteCode/Interp.h b/clang/lib/AST/ByteCode/Interp.h
index 2fe62fd511ea3..d58f3ce46d41a 100644
--- a/clang/lib/AST/ByteCode/Interp.h
+++ b/clang/lib/AST/ByteCode/Interp.h
@@ -4088,12 +4088,10 @@ inline bool IsBaseClass(InterpState &S) {
 
//===----------------------------------------------------------------------===//
 
 template <typename T> inline T ReadArg(InterpState &S, CodePtr &OpPC) {
-  if constexpr (std::is_pointer<T>::value) {
-    uint32_t ID = OpPC.read<uint32_t>();
-    return reinterpret_cast<T>(S.P.getNativePointer(ID));
-  } else {
+  if constexpr (std::is_pointer<T>::value)
+    return reinterpret_cast<T>(OpPC.read<uintptr_t>());
+  else
     return OpPC.read<T>();
-  }
 }
 
 template <> inline Floating ReadArg<Floating>(InterpState &S, CodePtr &OpPC) {
diff --git a/clang/lib/AST/ByteCode/Program.cpp 
b/clang/lib/AST/ByteCode/Program.cpp
index af2f108ef6970..257fa9214076e 100644
--- a/clang/lib/AST/ByteCode/Program.cpp
+++ b/clang/lib/AST/ByteCode/Program.cpp
@@ -17,19 +17,6 @@
 using namespace clang;
 using namespace clang::interp;
 
-unsigned Program::getOrCreateNativePointer(const void *Ptr) {
-  auto [It, Inserted] =
-      NativePointerIndices.try_emplace(Ptr, NativePointers.size());
-  if (Inserted)
-    NativePointers.push_back(Ptr);
-
-  return It->second;
-}
-
-const void *Program::getNativePointer(unsigned Idx) const {
-  return NativePointers[Idx];
-}
-
 Pointer Program::getPtrGlobal(unsigned Idx) const {
   assert(Idx < Globals.size());
   return Pointer(Globals[Idx]->block());
diff --git a/clang/lib/AST/ByteCode/Program.h b/clang/lib/AST/ByteCode/Program.h
index ea9e5b6bead72..19c64f8e914e7 100644
--- a/clang/lib/AST/ByteCode/Program.h
+++ b/clang/lib/AST/ByteCode/Program.h
@@ -57,12 +57,6 @@ class Program final {
 
   const Context &getContext() const { return Ctx; }
 
-  /// Marshals a native pointer to an ID for embedding in bytecode.
-  unsigned getOrCreateNativePointer(const void *Ptr);
-
-  /// Returns the value of a marshalled native pointer.
-  const void *getNativePointer(unsigned Idx) const;
-
   /// Returns a pointer to a global.
   Pointer getPtrGlobal(unsigned Idx) const;
 
@@ -98,13 +92,13 @@ class Program final {
   template <typename... Ts>
   Function *createFunction(const FunctionDecl *Def, Ts &&...Args) {
     Def = Def->getCanonicalDecl();
-    auto *Func = new Function(*this, Def, std::forward<Ts>(Args)...);
+    auto *Func = new Function(Def, std::forward<Ts>(Args)...);
     Funcs.insert({Def, std::unique_ptr<Function>(Func)});
     return Func;
   }
   /// Creates an anonymous function.
   template <typename... Ts> Function *createFunction(Ts &&...Args) {
-    auto *Func = new Function(*this, std::forward<Ts>(Args)...);
+    auto *Func = new Function(std::forward<Ts>(Args)...);
     AnonFuncs.emplace_back(Func);
     return Func;
   }
@@ -175,11 +169,6 @@ class Program final {
   /// List of anonymous functions.
   std::vector<std::unique_ptr<Function>> AnonFuncs;
 
-  /// Native pointers referenced by bytecode.
-  std::vector<const void *> NativePointers;
-  /// Cached native pointer indices.
-  llvm::DenseMap<const void *, unsigned> NativePointerIndices;
-
   /// Custom allocator for global storage.
   using PoolAllocTy = llvm::BumpPtrAllocator;
 
diff --git a/clang/utils/TableGen/ClangOpcodesEmitter.cpp 
b/clang/utils/TableGen/ClangOpcodesEmitter.cpp
index 8e70a070696ea..8165dd7547712 100644
--- a/clang/utils/TableGen/ClangOpcodesEmitter.cpp
+++ b/clang/utils/TableGen/ClangOpcodesEmitter.cpp
@@ -232,7 +232,7 @@ void ClangOpcodesEmitter::EmitDisasm(raw_ostream &OS, 
StringRef N,
     OS << "  Text.Op = PrintName(\"" << ID << "\");\n";
     for (const auto *Arg : R->getValueAsListOfDefs("Args"))
       OS << "  Text.Args.push_back(printArg<" << Arg->getValueAsString("Name")
-         << ">(P, PC));\n";
+         << ">(PC));\n";
 
     OS << "  break;\n";
   });

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

Reply via email to