Skip to content

Commit 22e4c0c

Browse files
committed
Implement ConstructorCall in JitCall, disentangled from generics
1 parent 1405afe commit 22e4c0c

File tree

5 files changed

+68
-21
lines changed

5 files changed

+68
-21
lines changed

include/CppInterOp/CppInterOp.h

Lines changed: 51 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,7 @@ class JitCall {
103103
enum Kind : char {
104104
kUnknown = 0,
105105
kGenericCall,
106+
kConstructorCall,
106107
kDestructorCall,
107108
};
108109
struct ArgList {
@@ -116,20 +117,25 @@ class JitCall {
116117
// FIXME: Hide these implementation details by moving wrapper generation in
117118
// this class.
118119
// (self, nargs, args, result, nary)
119-
using GenericCall = void (*)(void*, size_t, void**, void*, size_t);
120+
using GenericCall = void (*)(void*, size_t, void**, void*);
121+
// (result, nary, nargs, args, is_arena)
122+
using ConstructorCall = void (*)(void*, size_t, size_t, void**, void*);
120123
// (self, nary, withFree)
121124
using DestructorCall = void (*)(void*, size_t, int);
122125

123126
private:
124127
union {
125128
GenericCall m_GenericCall;
129+
ConstructorCall m_ConstructorCall;
126130
DestructorCall m_DestructorCall;
127131
};
128132
Kind m_Kind;
129133
TCppConstFunction_t m_FD;
130134
JitCall() : m_GenericCall(nullptr), m_Kind(kUnknown), m_FD(nullptr) {}
131135
JitCall(Kind K, GenericCall C, TCppConstFunction_t FD)
132136
: m_GenericCall(C), m_Kind(K), m_FD(FD) {}
137+
JitCall(Kind K, ConstructorCall C, TCppConstFunction_t Ctor)
138+
: m_ConstructorCall(C), m_Kind(K), m_FD(Ctor) {}
133139
JitCall(Kind K, DestructorCall C, TCppConstFunction_t Dtor)
134140
: m_DestructorCall(C), m_Kind(K), m_FD(Dtor) {}
135141

@@ -164,20 +170,36 @@ class JitCall {
164170
// self can go in the end and be nullptr by default; result can be a nullptr
165171
// by default. These changes should be synchronized with the wrapper if we
166172
// decide to directly.
167-
void Invoke(void* result, ArgList args = {}, void* self = nullptr,
168-
size_t nary = 0UL) const {
173+
void Invoke(void* result, ArgList args = {}, void* self = nullptr) const {
169174
// NOLINTBEGIN(*-type-union-access)
170-
// Forward if we intended to call a dtor with only 1 parameter.
171-
if (m_Kind == kDestructorCall && result && !args.m_Args) {
172-
InvokeDestructor(result, nary, /*withFree=*/true);
173-
return;
174-
}
175+
// Its possible the JitCall object deals with structor decls but went
176+
// through Invoke
177+
178+
switch (m_Kind) {
179+
case kUnknown:
180+
assert(0 && "Attempted to call an invalid function declaration");
181+
break;
175182

183+
case kGenericCall:
176184
#ifndef NDEBUG
177-
assert(AreArgumentsValid(result, args, self) && "Invalid args!");
178-
ReportInvokeStart(result, args, self);
185+
// We pass 1UL to nary which is only relevant for structors
186+
assert(AreArgumentsValid(result, args, self, 1UL) && "Invalid args!");
187+
ReportInvokeStart(result, args, self);
179188
#endif // NDEBUG
180-
m_GenericCall(self, args.m_ArgSize, args.m_Args, result, nary);
189+
m_GenericCall(self, args.m_ArgSize, args.m_Args, result);
190+
break;
191+
192+
case kConstructorCall:
193+
// Forward if we intended to call a constructor (nary cannot be inferred,
194+
// so we stick to constructing a single object)
195+
InvokeConstructor(result, /*nary=*/1UL, args, self);
196+
break;
197+
case kDestructorCall:
198+
// Forward if we intended to call a dtor with only 1 parameter.
199+
assert(!args.m_Args && "Destructor called with arguments");
200+
InvokeDestructor(result, /*nary=*/0UL, /*withFree=*/true);
201+
break;
202+
}
181203
// NOLINTEND(*-type-union-access)
182204
}
183205
/// Makes a call to a destructor.
@@ -195,6 +217,24 @@ class JitCall {
195217
#endif // NDEBUG
196218
m_DestructorCall(object, nary, withFree);
197219
}
220+
221+
/// Makes a call to a constructor.
222+
///\param[in] result - the memory address at which we construct the object
223+
/// (placement new).
224+
///\param[in] nary - Use array new if we have to construct an array of
225+
/// objects (nary > 1).
226+
///\param[in] args - a pointer to a argument list and argument size.
227+
// FIXME: Change the type of withFree from int to bool in the wrapper code.
228+
void InvokeConstructor(void* result, unsigned long nary = 1,
229+
ArgList args = {}, void* is_arena = nullptr) const {
230+
assert(m_Kind == kConstructorCall && "Wrong overload!");
231+
#ifndef NDEBUG
232+
assert(AreArgumentsValid(result, args, /*self=*/nullptr, nary) &&
233+
"Invalid args!");
234+
ReportInvokeStart(result, args, nullptr);
235+
#endif // NDEBUG
236+
m_ConstructorCall(result, nary, args.m_ArgSize, args.m_Args, is_arena);
237+
}
198238
};
199239

200240
///\returns the version string information of the library.

include/clang-c/CXCppInterOp.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -333,7 +333,7 @@ CINDEX_LINKAGE void clang_deallocate(CXObject address);
333333
* arena is set it uses placement new.
334334
*/
335335
CINDEX_LINKAGE CXObject clang_construct(CXScope scope, void* arena,
336-
size_t count);
336+
size_t count = 1UL);
337337

338338
/**
339339
* Creates a trampoline function and makes a call to a generic function or
@@ -350,7 +350,7 @@ CINDEX_LINKAGE CXObject clang_construct(CXScope scope, void* arena,
350350
* \param self The 'this pointer' of the object.
351351
*/
352352
CINDEX_LINKAGE void clang_invoke(CXScope func, void* result, void** args,
353-
size_t n, size_t nary, void* self);
353+
size_t n, void* self);
354354

355355
/**
356356
* Calls the destructor of object of type \c type. When withFree is true it

lib/CppInterOp/CXCppInterOp.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -607,9 +607,9 @@ CXObject clang_construct(CXScope scope, void* arena, size_t count) {
607607
}
608608

609609
void clang_invoke(CXScope func, void* result, void** args, size_t n,
610-
size_t nary, void* self) {
610+
void* self) {
611611
Cpp::MakeFunctionCallable(getInterpreter(func), getDecl(func))
612-
.Invoke(result, {args, n}, self, nary);
612+
.Invoke(result, {args, n}, self);
613613
}
614614

615615
namespace Cpp {

lib/CppInterOp/CppInterOp.cpp

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2976,6 +2976,13 @@ CPPINTEROP_API JitCall MakeFunctionCallable(TInterp_t I,
29762976
return {};
29772977
}
29782978

2979+
if (const auto* Ctor = dyn_cast<CXXConstructorDecl>(D)) {
2980+
if (auto Wrapper = make_wrapper(*interp, cast<FunctionDecl>(D)))
2981+
return {JitCall::kConstructorCall, Wrapper, Ctor};
2982+
// FIXME: else error we failed to compile the wrapper.
2983+
return {};
2984+
}
2985+
29792986
if (auto Wrapper = make_wrapper(*interp, cast<FunctionDecl>(D))) {
29802987
return {JitCall::kGenericCall, Wrapper, cast<FunctionDecl>(D)};
29812988
}
@@ -3741,13 +3748,13 @@ TCppObject_t Construct(compat::Interpreter& interp, TCppScope_t scope,
37413748
auto* const Ctor = GetDefaultConstructor(interp, Class);
37423749
if (JitCall JC = MakeFunctionCallable(&interp, Ctor)) {
37433750
if (arena) {
3744-
JC.Invoke(&arena, {}, (void*)~0,
3745-
count); // Tell Invoke to use placement new.
3751+
JC.InvokeConstructor(&arena, count, {},
3752+
(void*)~0); // Tell Invoke to use placement new.
37463753
return arena;
37473754
}
37483755

37493756
void* obj = nullptr;
3750-
JC.Invoke(&obj);
3757+
JC.InvokeConstructor(&obj, count, {}, nullptr);
37513758
return obj;
37523759
}
37533760
return nullptr;

unittests/CppInterOp/FunctionReflectionTest.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1483,7 +1483,7 @@ TEST(FunctionReflectionTest, JitCallAdvanced) {
14831483
auto* I = clang_createInterpreterFromRawPtr(Cpp::GetInterpreter());
14841484
auto S = clang_getDefaultConstructor(make_scope(Decls[0], I));
14851485
void* object_c = nullptr;
1486-
clang_invoke(S, &object_c, nullptr, 0, 0UL, nullptr);
1486+
clang_invoke(S, &object_c, nullptr, 0, nullptr);
14871487
EXPECT_TRUE(object_c) << "Failed to call the ctor.";
14881488
clang_destruct(object_c, make_scope(Decls[1], I), true);
14891489
// Clean up resources
@@ -2034,7 +2034,7 @@ TEST(FunctionReflectionTest, Construct) {
20342034
testing::internal::CaptureStdout();
20352035
auto* I = clang_createInterpreterFromRawPtr(Cpp::GetInterpreter());
20362036
auto scope_c = make_scope(static_cast<clang::Decl*>(scope), I);
2037-
auto object_c = clang_construct(scope_c, nullptr, 0UL);
2037+
auto object_c = clang_construct(scope_c, nullptr, 1UL);
20382038
EXPECT_TRUE(object_c != nullptr);
20392039
output = testing::internal::GetCapturedStdout();
20402040
EXPECT_EQ(output, "Constructor Executed");
@@ -2157,7 +2157,7 @@ TEST(FunctionReflectionTest, Destruct) {
21572157
testing::internal::CaptureStdout();
21582158
auto* I = clang_createInterpreterFromRawPtr(Cpp::GetInterpreter());
21592159
auto scope_c = make_scope(static_cast<clang::Decl*>(scope), I);
2160-
auto object_c = clang_construct(scope_c, nullptr, 0UL);
2160+
auto object_c = clang_construct(scope_c, nullptr, 1UL);
21612161
clang_destruct(object_c, scope_c, true);
21622162
output = testing::internal::GetCapturedStdout();
21632163
EXPECT_EQ(output, "Destructor Executed");

0 commit comments

Comments
 (0)