[clang] 95473a6 - [clang][bytecode] Remove native pointer marshalling (#218911)
via cfe-commits
cfe-commits at lists.llvm.org
Sun Aug 30 00:45:53 PDT 2026
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";
});
More information about the cfe-commits
mailing list