Skip to content

Commit 05865a4

Browse files
committed
Fix array of object construction, and IO ctors
1 parent 637af71 commit 05865a4

6 files changed

Lines changed: 209 additions & 89 deletions

File tree

core/meta/src/TClass.cxx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5349,6 +5349,7 @@ TClass::ObjectPtr TClass::NewObjectArray(Long_t nElements, ENewType defConstruct
53495349
Error("NewArray", "cannot create object of class %s version %d", GetName(), fClassVersion);
53505350
}
53515351
} else if (HasInterpreterInfo()) {
5352+
// assert(nElements < 1 && "nelements used in TClass");
53525353
// We have the dictionary but do not have the
53535354
// constructor wrapper, so the dictionary was
53545355
// not generated by rootcint. Let's try to
@@ -5450,6 +5451,8 @@ TClass::ObjectPtr TClass::NewObjectArray(Long_t nElements, void *arena, ENewType
54505451
Error("NewArray with placement", "cannot create object of class %s version %d at address %p", GetName(), fClassVersion, arena);
54515452
}
54525453
} else if (HasInterpreterInfo()) {
5454+
// check what nelements is
5455+
// assert(nElements < 1 && "nelements used in TClass");
54535456
// We have the dictionary but do not have the constructor wrapper,
54545457
// so the dictionary was not generated by rootcint (it was made either
54555458
// by cint or by some external mechanism). Let's try to create the

core/metacling/src/TClingCallFunc.cxx

Lines changed: 32 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ C++ interpreter and the Clang C++ compiler, not CINT.
7070
#include <map>
7171
#include <string>
7272
#include <sstream>
73+
#include <iostream>
7374

7475
using namespace ROOT;
7576
using namespace llvm;
@@ -1071,6 +1072,17 @@ tcling_callfunc_ctor_Wrapper_t TClingCallFunc::make_ctor_wrapper(const TClingCla
10711072
{
10721073
// Make a code string that follows this pattern:
10731074
//
1075+
// This can be a single line if nary and arena are not passed.
1076+
// TODO : split this into map with 4 wrappers per decl:
1077+
// *ret = new ClassName;
1078+
// *ret = new ClassName[nary];
1079+
// *ret = new (arena) ClassName;
1080+
// *ret = new (arena) ClassName[nary];
1081+
// Based on the incoming request
1082+
1083+
// Use https://llvm.org/doxygen/classllvm_1_1PointerIntPair.html
1084+
1085+
10741086
// void
10751087
// unique_wrapper_ddd(void** ret, void* arena, unsigned long nary)
10761088
// {
@@ -1611,25 +1623,33 @@ void *TClingCallFunc::ExecDefaultConstructor(const TClingClassInfo *info,
16111623
::Error("TClingCallFunc::ExecDefaultConstructor", "Invalid class info!");
16121624
return nullptr;
16131625
}
1614-
auto D = info->GetDecl();
1615-
// bool is_rec = ;
1616-
if (Cpp::IsClass(D)) {
1617-
auto FD = Cpp::GetDefaultConstructorConst(D);
1618-
fJitCall = std::make_unique<Cpp::JitCall>(Cpp::MakeFunctionCallable(FD));
1626+
// Triage cases when nary is not 0, that is used for construction of multiple objects
1627+
// use Cpp::Construct
1628+
1629+
if (nary) {
1630+
// std::cout<<"NARY used: "<<nary<<"\n";
16191631
}
1620-
else if (Cpp::IsConstructor(D))
1621-
fJitCall = std::make_unique<Cpp::JitCall>(Cpp::MakeFunctionCallable(D));
16221632

1623-
else return nullptr;
1633+
const clang::Decl* D = info->GetDecl();
1634+
if (Cpp::IsClass(D))
1635+
D = (clang::Decl *)Cpp::GetDefaultConstructorConst(D);
1636+
if (!Cpp::IsConstructor(D))
1637+
return nullptr;
1638+
1639+
Cpp::JitCall JC = Cpp::MakeFunctionCallable(D);
16241640

1625-
if(fJitCall->getKind() == Cpp::JitCall::kUnknown) return nullptr;
1641+
if(JC.getKind() == Cpp::JitCall::kUnknown) return nullptr;
16261642

1643+
if(address) {
1644+
JC.Invoke(&address, {}, (void*)~0, nary);
1645+
return address;
1646+
}
1647+
else {
16271648
// Invoke:
16281649
void *obj = nullptr;
1629-
fJitCall->Invoke(&obj);
1630-
// (*wrapper)(&obj, address, nary);
1650+
JC.Invoke(&obj);
16311651
return obj;
1632-
1652+
}
16331653
// ::Error("TClingCallFunc::ExecDefaultConstructor", "Called with no wrapper, not implemented!");
16341654
// return nullptr;
16351655
}

interpreter/CppInterOp/include/clang/Interpreter/CppInterOp.h

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -88,13 +88,17 @@ namespace Cpp {
8888

8989
enum OperatorArity { kUnary = 1, kBinary, kBoth };
9090

91+
// enum CtorCallType : short
92+
// { kArena = 0, kArray = 2
93+
// };
94+
9195
/// A class modeling function calls for functions produced by the interpreter
9296
/// in compiled code. It provides an information if we are calling a standard
9397
/// function, constructor or destructor.
9498
class JitCall {
9599
public:
96100
friend CPPINTEROP_API JitCall
97-
MakeFunctionCallable(TInterp_t I, TCppConstFunction_t func);
101+
MakeFunctionCallable(TInterp_t I, TCppConstFunction_t func, bool is_arena, bool is_array);
98102
enum Kind : char {
99103
kUnknown = 0,
100104
kGenericCall,
@@ -111,7 +115,8 @@ namespace Cpp {
111115
// FIXME: Figure out how to unify the wrapper signatures.
112116
// FIXME: Hide these implementation details by moving wrapper generation in
113117
// this class.
114-
using GenericCall = void (*)(void*, int, void**, void*);
118+
// (self, nargs, args, result, n_objs)
119+
using GenericCall = void (*)(void*, int, void**, void*, unsigned long);
115120
using DestructorCall = void (*)(void*, unsigned long, int);
116121
private:
117122
union {
@@ -156,7 +161,7 @@ namespace Cpp {
156161
// self can go in the end and be nullptr by default; result can be a nullptr
157162
// by default. These changes should be synchronized with the wrapper if we
158163
// decide to directly.
159-
void Invoke(void* result, ArgList args = {}, void* self = nullptr) const {
164+
void Invoke(void* result, ArgList args = {}, void* self = nullptr, size_t n_objs = 0UL) const {
160165
// Forward if we intended to call a dtor with only 1 parameter.
161166
if (m_Kind == kDestructorCall && result && !args.m_Args)
162167
return InvokeDestructor(result, /*nary=*/0UL, /*withFree=*/true);
@@ -165,7 +170,7 @@ namespace Cpp {
165170
assert(AreArgumentsValid(result, args, self) && "Invalid args!");
166171
ReportInvokeStart(result, args, self);
167172
#endif // NDEBUG
168-
m_GenericCall(self, args.m_ArgSize, args.m_Args, result);
173+
m_GenericCall(self, args.m_ArgSize, args.m_Args, result, n_objs);
169174
}
170175
/// Makes a call to a destructor.
171176
///\param[in] object - the pointer of the object whose destructor we call.
@@ -566,10 +571,10 @@ namespace Cpp {
566571

567572
/// Creates a trampoline function by using the interpreter and returns a
568573
/// uniform interface to call it from compiled code.
569-
CPPINTEROP_API JitCall MakeFunctionCallable(TCppConstFunction_t func);
574+
CPPINTEROP_API JitCall MakeFunctionCallable(TCppConstFunction_t func, bool is_arena = false, bool is_array = false);
570575

571576
CPPINTEROP_API JitCall MakeFunctionCallable(TInterp_t I,
572-
TCppConstFunction_t func);
577+
TCppConstFunction_t func, bool is_arena = false, bool is_array = false);
573578

574579
/// Checks if a function declared is of const type or not.
575580
CPPINTEROP_API bool IsConstMethod(TCppFunction_t method);
@@ -757,15 +762,15 @@ namespace Cpp {
757762
CPPINTEROP_API std::vector<long int> GetDimensions(TCppType_t type);
758763

759764
/// Allocates memory for a given class.
760-
CPPINTEROP_API TCppObject_t Allocate(TCppScope_t scope);
765+
CPPINTEROP_API TCppObject_t Allocate(TCppScope_t scope, int n = 1);
761766

762767
/// Deallocates memory for a given class.
763768
CPPINTEROP_API void Deallocate(TCppScope_t scope, TCppObject_t address);
764769

765770
/// Creates an object of class \c scope and calls its default constructor. If
766771
/// \c arena is set it uses placement new.
767772
CPPINTEROP_API TCppObject_t Construct(TCppScope_t scope,
768-
void* arena = nullptr);
773+
void* arena = nullptr, unsigned long n_objs = 0UL);
769774

770775
/// Calls the destructor of object of type \c type. When withFree is true it
771776
/// calls operator delete/free.

interpreter/CppInterOp/lib/Interpreter/CXCppInterOp.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -591,9 +591,10 @@ void clang_deallocate(CXObject address) { ::operator delete(address); }
591591

592592
namespace Cpp {
593593
void* Construct(compat::Interpreter& interp, TCppScope_t scope,
594-
void* arena /*=nullptr*/);
594+
void* arena /*=nullptr*/, unsigned long n_objs = 0UL);
595595
} // namespace Cpp
596596

597+
597598
CXObject clang_construct(CXScope scope, void* arena) {
598599
return Cpp::Construct(*getInterpreter(scope),
599600
static_cast<void*>(getDecl(scope)), arena);

0 commit comments

Comments
 (0)