CppInterOp
C++ Language Interoperability Layer
Loading...
Searching...
No Matches
CppInterOp.h
Go to the documentation of this file.
1//===--- CppInterOp.h - A layer for language interoperability ---*- C++ -*-===//
2//
3// Part of the compiler-research project, under the Apache License v2.0 with
4// LLVM Exceptions.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This file defines API for introspection which enables language
10// interoperability.
11//
12//===----------------------------------------------------------------------===//
13
14#ifndef CPPINTEROP_CPPINTEROP_H
15#define CPPINTEROP_CPPINTEROP_H
16
17#ifdef CPPINTEROP_DISPATCH_H
18#error "CppInterOp.h and Dispatch.h are mutually exclusive — include only one."
19#endif
20
22// Cpp::Box must be visible before the tablegen-generated declarations
23// below, since Evaluate (and future Value-returning APIs) reference it.
24#include "CppInterOp/Box.h"
25
26#include <initializer_list>
27#include <memory>
28#include <utility>
29#include <vector>
30
31namespace Cpp {
32
33// Public API function declarations. Generated by cppinterop-tblgen
34// from CppInterOp.td. Do not edit this section by hand.
35#include "CppInterOp/CppInterOpDecl.inc"
36
37namespace detail {
38// Total slots before the published vtable's address point in an overlay
39// block: the ABI prefix of the underlying class (1 on MSVC --
40// complete-object-locator; 2 on Itanium -- offset-to-top + type_info)
41// plus 1 hidden slot CppInterOp interposes for the dtor-hook
42// self-pointer. Exposed only so the inline VTableOverlayExtraSlot helper
43// below can compile the offset; users should not read or write any slots
44// directly.
45// static (not inline) so the reproducer-as-TU compiles under C++14;
46// inline-variable is a C++17 extension and the JIT-compiled reproducer
47// is fed back through the interpreter at its default language standard.
48#ifdef _WIN32
49static constexpr int kVTableOverlayPrefixSize = 1 + 1;
50#else
51static constexpr int kVTableOverlayPrefixSize = 2 + 1;
52#endif
53} // namespace detail
54
55/// Address of the i-th extra-prefix slot of an instance with an overlay
56/// installed via MakeVTableOverlay(..., n_extra_prefix_slots = N, ...).
57/// Returns a void*& so callers read and write through the same expression;
58/// this is the canonical access path -- bindings should not synthesize the
59/// vptr arithmetic themselves. Behavior is undefined if \c inst has no
60/// overlay or i >= N.
61inline void*& VTableOverlayExtraSlot(void* inst, std::size_t i) {
62 void** vptr = *reinterpret_cast<void***>(inst);
63 return vptr[-(detail::kVTableOverlayPrefixSize + 1 + static_cast<int>(i))];
64}
65
67 void operator()(VTableOverlay* o) const noexcept { DestroyVTableOverlay(o); }
68};
70 std::unique_ptr<VTableOverlay, VTableOverlayDeleter>;
71
72/// Owning wrapper over MakeVTableOverlay: each pair maps a virtual method
73/// of polymorphic class \c base to its replacement function pointer. The
74/// overlay is installed on construction and the original vptr restored when
75/// the handle is destroyed. The caller works in reflected methods, not
76/// ABI-specific slot indices -- the common path for language bindings.
77/// \c n_extra_prefix_slots reserves nullptr-initialized slots immediately
78/// before the ABI prefix for the caller to write per-instance data into.
79/// \c on_destroy, when non-null, is invoked once after the C++ destructor
80/// of \c inst runs (operator-delete path). It receives the original \c
81/// inst pointer (which may be dangling at that point -- do not deref) and
82/// \c cleanup_data verbatim; bindings use it to release any per-instance
83/// state (Python handles, closures) tied to the object's lifetime. The
84/// callback must not throw: it runs inside a C++ destructor, so an
85/// escaping exception is undefined behavior.
87 void* inst, DeclRef base,
88 std::initializer_list<std::pair<ConstFuncRef, void*>> overrides,
89 std::size_t n_extra_prefix_slots = 0,
90 VTableOverlayDtorHook on_destroy = nullptr, void* cleanup_data = nullptr) {
91 std::vector<ConstFuncRef> methods;
92 std::vector<void*> fns;
93 methods.reserve(overrides.size());
94 fns.reserve(overrides.size());
95 for (const auto& p : overrides) {
96 methods.push_back(p.first);
97 fns.push_back(p.second);
98 }
100 inst, base, methods.data(), fns.data(), methods.size(),
101 n_extra_prefix_slots, on_destroy, cleanup_data)};
102}
103
104} // namespace Cpp
105
106#endif // CPPINTEROP_CPPINTEROP_H
static constexpr int kVTableOverlayPrefixSize
Definition CppInterOp.h:51
Definition Box.h:70
std::unique_ptr< VTableOverlay, VTableOverlayDeleter > UniqueVTableOverlay
Definition CppInterOp.h:70
void *& VTableOverlayExtraSlot(void *inst, std::size_t i)
Address of the i-th extra-prefix slot of an instance with an overlay installed via MakeVTableOverlay(...
Definition CppInterOp.h:61
void DestroyVTableOverlay(VTableOverlay *overlay)
UniqueVTableOverlay MakeUniqueVTableOverlay(void *inst, DeclRef base, std::initializer_list< std::pair< ConstFuncRef, void * > > overrides, std::size_t n_extra_prefix_slots=0, VTableOverlayDtorHook on_destroy=nullptr, void *cleanup_data=nullptr)
Owning wrapper over MakeVTableOverlay: each pair maps a virtual method of polymorphic class base to i...
Definition CppInterOp.h:86
VTableOverlay * MakeVTableOverlay(void *inst, ConstDeclRef base, const ConstFuncRef *methods, void *const *overlay_fns, std::size_t n_overlays, std::size_t n_extra_prefix_slots, VTableOverlayDtorHook on_destroy, void *cleanup_data)
void operator()(VTableOverlay *o) const noexcept
Definition CppInterOp.h:67