Author: Timm Baeder
Date: 2026-08-30T09:45:48+02:00
New Revision: 95473a6cc68b44aed2ee0622d0bb2e60313caad9

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

LOG: [clang][bytecode] Remove native pointer marshalling (#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.

Added: 
    

Modified: 
    clang/lib/AST/ByteCode/ByteCodeEmitter.cpp
    clang/lib/AST/ByteCode/Disasm.cpp
    clang/lib/AST/ByteCode/Function.cpp
    clang/lib/AST/ByteCode/Function.h
    clang/lib/AST/ByteCode/Interp.h
    clang/lib/AST/ByteCode/Program.cpp
    clang/lib/AST/ByteCode/Program.h
    clang/utils/TableGen/ClangOpcodesEmitter.cpp

Removed: 
    


################################################################################
diff  --git a/clang/lib/AST/ByteCode/ByteCodeEmitter.cpp 
b/clang/lib/AST/ByteCode/ByteCodeEmitter.cpp
index f04478eb6ac16..81f5fe25fcc35 100644
--- a/clang/lib/AST/ByteCode/ByteCodeEmitter.cpp
+++ b/clang/lib/AST/ByteCode/ByteCodeEmitter.cpp
@@ -130,7 +130,6 @@ int32_t ByteCodeEmitter::getOffset(LabelTy Label) {
 }
 
 /// Helper to write bytecode and bail out if 32-bit offsets become invalid.
-/// Pointers will be automatically marshalled as 32-bit IDs.
 template <typename T>
 static void emit(Program &P, llvm::SmallVectorImpl<std::byte> &Code,
                  const T &Val, bool &Success) {
@@ -138,7 +137,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));
 
@@ -152,12 +151,10 @@ static void emit(Program &P, 
llvm::SmallVectorImpl<std::byte> &Code,
   assert(aligned(ValPos + Size));
   Code.resize_for_overwrite(ValPos + Size);
 
-  if constexpr (!std::is_pointer_v<T>) {
+  if constexpr (std::is_pointer_v<T>)
+    new (Code.data() + ValPos) uintptr_t(reinterpret_cast<uintptr_t>(Val));
+  else
     new (Code.data() + ValPos) T(Val);
-  } else {
-    uint32_t ID = P.getOrCreateNativePointer(Val);
-    new (Code.data() + ValPos) uint32_t(ID);
-  }
 }
 
 /// Emits a serializable value. These usually (potentially) contain

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