Skip to content

Commit 9da1db4

Browse files
committed
Array of objects in Construct/Destruct/Allocate/Deallocate
1 parent 49e6f4c commit 9da1db4

File tree

5 files changed

+67
-42
lines changed

5 files changed

+67
-42
lines changed

include/CppInterOp/CppInterOp.h

Lines changed: 35 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -115,8 +115,10 @@ class JitCall {
115115
// FIXME: Figure out how to unify the wrapper signatures.
116116
// FIXME: Hide these implementation details by moving wrapper generation in
117117
// this class.
118-
using GenericCall = void (*)(void*, size_t, void**, void*);
119-
using DestructorCall = void (*)(void*, unsigned long, int);
118+
// (self, nargs, args, result, nary)
119+
using GenericCall = void (*)(void*, size_t, void**, void*, size_t);
120+
// (self, nary, withFree)
121+
using DestructorCall = void (*)(void*, size_t, int);
120122

121123
private:
122124
union {
@@ -162,19 +164,20 @@ class JitCall {
162164
// self can go in the end and be nullptr by default; result can be a nullptr
163165
// by default. These changes should be synchronized with the wrapper if we
164166
// decide to directly.
165-
void Invoke(void* result, ArgList args = {}, void* self = nullptr) const {
167+
void Invoke(void* result, ArgList args = {}, void* self = nullptr,
168+
size_t nary = 0UL) const {
166169
// NOLINTBEGIN(*-type-union-access)
167170
// Forward if we intended to call a dtor with only 1 parameter.
168171
if (m_Kind == kDestructorCall && result && !args.m_Args) {
169-
InvokeDestructor(result, /*nary=*/0UL, /*withFree=*/true);
172+
InvokeDestructor(result, nary, /*withFree=*/true);
170173
return;
171174
}
172175

173176
#ifndef NDEBUG
174177
assert(AreArgumentsValid(result, args, self) && "Invalid args!");
175178
ReportInvokeStart(result, args, self);
176179
#endif // NDEBUG
177-
m_GenericCall(self, args.m_ArgSize, args.m_Args, result);
180+
m_GenericCall(self, args.m_ArgSize, args.m_Args, result, nary);
178181
// NOLINTEND(*-type-union-access)
179182
}
180183
/// Makes a call to a destructor.
@@ -792,20 +795,36 @@ enum : long int {
792795
/// Gets the size/dimensions of a multi-dimension array.
793796
CPPINTEROP_API std::vector<long int> GetDimensions(TCppType_t type);
794797

795-
/// Allocates memory for a given class.
796-
CPPINTEROP_API TCppObject_t Allocate(TCppScope_t scope);
798+
/// Allocates memory required by an object of a given class
799+
/// \c scope Given class for which to allocate memory for
800+
/// \c count is used to indicate the number of objects to allocate for.
801+
CPPINTEROP_API TCppObject_t Allocate(TCppScope_t scope,
802+
TCppIndex_t count = 1UL);
797803

798804
/// Deallocates memory for a given class.
799-
CPPINTEROP_API void Deallocate(TCppScope_t scope, TCppObject_t address);
800-
801-
/// Creates an object of class \c scope and calls its default constructor. If
802-
/// \c arena is set it uses placement new.
803-
CPPINTEROP_API TCppObject_t Construct(TCppScope_t scope, void* arena = nullptr);
804-
805-
/// Calls the destructor of object of type \c type. When withFree is true it
806-
/// calls operator delete/free.
805+
/// \c scope Class to indicate size of memory to deallocate
806+
/// \c count is used to indicate the number of objects to dallocate for
807+
CPPINTEROP_API void Deallocate(TCppScope_t scope, TCppObject_t address,
808+
TCppIndex_t count = 1UL);
809+
810+
/// Creates one or more objects of class \c scope by calling its default
811+
/// constructor.
812+
/// \param[in] scope Class to construct
813+
/// \param[in] arena If set, this API uses placement new to construct at this
814+
/// address.
815+
/// \param[in] is used to indicate the number of objects to construct.
816+
CPPINTEROP_API TCppObject_t Construct(TCppScope_t scope, void* arena = nullptr,
817+
TCppIndex_t count = 1UL);
818+
819+
/// Destroys one or more objects of a class
820+
/// \param[in] This this pointer of the object to destruct. Can also be the
821+
/// starting address of an array of objects
822+
/// \param[in] withFree if true, we call operator delete/free, else just the
823+
/// destructor
824+
/// \param[in] count indicate the number of objects to destruct, if \c This
825+
/// points to an array of objects
807826
CPPINTEROP_API void Destruct(TCppObject_t This, TCppScope_t type,
808-
bool withFree = true);
827+
bool withFree = true, TCppIndex_t count = 0UL);
809828

810829
/// @name Stream Redirection
811830
///

include/clang-c/CXCppInterOp.h

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -332,7 +332,8 @@ CINDEX_LINKAGE void clang_deallocate(CXObject address);
332332
* Creates an object of class \c scope and calls its default constructor. If \c
333333
* arena is set it uses placement new.
334334
*/
335-
CINDEX_LINKAGE CXObject clang_construct(CXScope scope, void* arena);
335+
CINDEX_LINKAGE CXObject clang_construct(CXScope scope, void* arena,
336+
size_t count);
336337

337338
/**
338339
* Creates a trampoline function and makes a call to a generic function or
@@ -349,7 +350,7 @@ CINDEX_LINKAGE CXObject clang_construct(CXScope scope, void* arena);
349350
* \param self The 'this pointer' of the object.
350351
*/
351352
CINDEX_LINKAGE void clang_invoke(CXScope func, void* result, void** args,
352-
size_t n, void* self);
353+
size_t n, size_t nary, void* self);
353354

354355
/**
355356
* Calls the destructor of object of type \c type. When withFree is true it
@@ -361,7 +362,8 @@ CINDEX_LINKAGE void clang_invoke(CXScope func, void* result, void** args,
361362
*
362363
* \param withFree Whether to call operator delete/free or not.
363364
*/
364-
CINDEX_LINKAGE void clang_destruct(CXObject This, CXScope S, bool withFree);
365+
CINDEX_LINKAGE void clang_destruct(CXObject This, CXScope S,
366+
bool withFree = true, size_t nary = 0UL);
365367

366368
/**
367369
* @}

lib/CppInterOp/CXCppInterOp.cpp

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -598,25 +598,25 @@ void clang_deallocate(CXObject address) { ::operator delete(address); }
598598

599599
namespace Cpp {
600600
void* Construct(compat::Interpreter& interp, TCppScope_t scope,
601-
void* arena /*=nullptr*/);
601+
void* arena /*=nullptr*/, TCppIndex_t count);
602602
} // namespace Cpp
603603

604-
CXObject clang_construct(CXScope scope, void* arena) {
604+
CXObject clang_construct(CXScope scope, void* arena, size_t count) {
605605
return Cpp::Construct(*getInterpreter(scope),
606-
static_cast<void*>(getDecl(scope)), arena);
606+
static_cast<void*>(getDecl(scope)), arena, count);
607607
}
608608

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

615615
namespace Cpp {
616616
void Destruct(compat::Interpreter& interp, TCppObject_t This,
617-
clang::Decl* Class, bool withFree);
617+
clang::Decl* Class, bool withFree, size_t nary);
618618
} // namespace Cpp
619619

620-
void clang_destruct(CXObject This, CXScope S, bool withFree) {
621-
Cpp::Destruct(*getInterpreter(S), This, getDecl(S), withFree);
620+
void clang_destruct(CXObject This, CXScope S, bool withFree, size_t nary) {
621+
Cpp::Destruct(*getInterpreter(S), This, getDecl(S), withFree, nary);
622622
}

lib/CppInterOp/CppInterOp.cpp

Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3653,17 +3653,18 @@ void GetOperator(TCppScope_t scope, Operator op,
36533653
}
36543654
}
36553655

3656-
TCppObject_t Allocate(TCppScope_t scope) {
3657-
return (TCppObject_t)::operator new(Cpp::SizeOf(scope));
3656+
TCppObject_t Allocate(TCppScope_t scope, TCppIndex_t count) {
3657+
return (TCppObject_t)::operator new(Cpp::SizeOf(scope) * count);
36583658
}
36593659

3660-
void Deallocate(TCppScope_t scope, TCppObject_t address) {
3661-
::operator delete(address);
3660+
void Deallocate(TCppScope_t scope, TCppObject_t address, TCppIndex_t count) {
3661+
size_t bytes = Cpp::SizeOf(scope) * count;
3662+
::operator delete(address, bytes);
36623663
}
36633664

36643665
// FIXME: Add optional arguments to the operator new.
36653666
TCppObject_t Construct(compat::Interpreter& interp, TCppScope_t scope,
3666-
void* arena /*=nullptr*/) {
3667+
void* arena /*=nullptr*/, TCppIndex_t count /*=1UL*/) {
36673668
auto* Class = (Decl*)scope;
36683669
// FIXME: Diagnose.
36693670
if (!HasDefaultConstructor(Class))
@@ -3672,7 +3673,8 @@ TCppObject_t Construct(compat::Interpreter& interp, TCppScope_t scope,
36723673
auto* const Ctor = GetDefaultConstructor(interp, Class);
36733674
if (JitCall JC = MakeFunctionCallable(&interp, Ctor)) {
36743675
if (arena) {
3675-
JC.Invoke(&arena, {}, (void*)~0); // Tell Invoke to use placement new.
3676+
JC.Invoke(&arena, {}, (void*)~0,
3677+
count); // Tell Invoke to use placement new.
36763678
return arena;
36773679
}
36783680

@@ -3683,22 +3685,24 @@ TCppObject_t Construct(compat::Interpreter& interp, TCppScope_t scope,
36833685
return nullptr;
36843686
}
36853687

3686-
TCppObject_t Construct(TCppScope_t scope, void* arena /*=nullptr*/) {
3687-
return Construct(getInterp(), scope, arena);
3688+
TCppObject_t Construct(TCppScope_t scope, void* arena /*=nullptr*/,
3689+
TCppIndex_t count /*=1UL*/) {
3690+
return Construct(getInterp(), scope, arena, count);
36883691
}
36893692

36903693
void Destruct(compat::Interpreter& interp, TCppObject_t This, Decl* Class,
3691-
bool withFree) {
3694+
bool withFree, TCppIndex_t nary) {
36923695
if (auto wrapper = make_dtor_wrapper(interp, Class)) {
3693-
(*wrapper)(This, /*nary=*/0, withFree);
3696+
(*wrapper)(This, nary, withFree);
36943697
return;
36953698
}
36963699
// FIXME: Diagnose.
36973700
}
36983701

3699-
void Destruct(TCppObject_t This, TCppScope_t scope, bool withFree /*=true*/) {
3702+
void Destruct(TCppObject_t This, TCppScope_t scope, bool withFree /*=true*/,
3703+
TCppIndex_t count /*=0UL*/) {
37003704
auto* Class = static_cast<Decl*>(scope);
3701-
Destruct(getInterp(), This, Class, withFree);
3705+
Destruct(getInterp(), This, Class, withFree, count);
37023706
}
37033707

37043708
class StreamCaptureInfo {

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, nullptr);
1486+
clang_invoke(S, &object_c, nullptr, 0, 0UL, 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);
2037+
auto object_c = clang_construct(scope_c, nullptr, 0UL);
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);
2160+
auto object_c = clang_construct(scope_c, nullptr, 0UL);
21612161
clang_destruct(object_c, scope_c, true);
21622162
output = testing::internal::GetCapturedStdout();
21632163
EXPECT_EQ(output, "Destructor Executed");

0 commit comments

Comments
 (0)