Skip to content

Commit 710a964

Browse files
committed
Add array new for ctor codegen in JitCall
1 parent d7153e9 commit 710a964

File tree

1 file changed

+93
-33
lines changed

1 file changed

+93
-33
lines changed

lib/CppInterOp/CppInterOp.cpp

Lines changed: 93 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1885,42 +1885,51 @@ void collect_type_info(const FunctionDecl* FD, QualType& QT,
18851885

18861886
void make_narg_ctor(const FunctionDecl* FD, const unsigned N,
18871887
std::ostringstream& typedefbuf, std::ostringstream& callbuf,
1888-
const std::string& class_name, int indent_level) {
1888+
const std::string& class_name, int indent_level,
1889+
bool array = false) {
18891890
// Make a code string that follows this pattern:
18901891
//
18911892
// ClassName(args...)
1893+
// OR
1894+
// ClassName[nary] // array of objects
18921895
//
18931896

1894-
callbuf << class_name << "(";
1895-
for (unsigned i = 0U; i < N; ++i) {
1896-
const ParmVarDecl* PVD = FD->getParamDecl(i);
1897-
QualType Ty = PVD->getType();
1898-
QualType QT = Ty.getCanonicalType();
1899-
std::string type_name;
1900-
EReferenceType refType = kNotReference;
1901-
bool isPointer = false;
1902-
collect_type_info(FD, QT, typedefbuf, callbuf, type_name, refType,
1903-
isPointer, indent_level, true);
1904-
if (i) {
1905-
callbuf << ',';
1906-
if (i % 2) {
1907-
callbuf << ' ';
1897+
if (array)
1898+
callbuf << class_name << "[nary]";
1899+
else
1900+
callbuf << class_name;
1901+
if (N) {
1902+
callbuf << "(";
1903+
for (unsigned i = 0U; i < N; ++i) {
1904+
const ParmVarDecl* PVD = FD->getParamDecl(i);
1905+
QualType Ty = PVD->getType();
1906+
QualType QT = Ty.getCanonicalType();
1907+
std::string type_name;
1908+
EReferenceType refType = kNotReference;
1909+
bool isPointer = false;
1910+
collect_type_info(FD, QT, typedefbuf, callbuf, type_name, refType,
1911+
isPointer, indent_level, true);
1912+
if (i) {
1913+
callbuf << ',';
1914+
if (i % 2) {
1915+
callbuf << ' ';
1916+
} else {
1917+
callbuf << "\n";
1918+
indent(callbuf, indent_level);
1919+
}
1920+
}
1921+
if (refType != kNotReference) {
1922+
callbuf << "(" << type_name.c_str()
1923+
<< (refType == kLValueReference ? "&" : "&&") << ")*("
1924+
<< type_name.c_str() << "*)args[" << i << "]";
1925+
} else if (isPointer) {
1926+
callbuf << "*(" << type_name.c_str() << "**)args[" << i << "]";
19081927
} else {
1909-
callbuf << "\n";
1910-
indent(callbuf, indent_level + 1);
1928+
callbuf << "*(" << type_name.c_str() << "*)args[" << i << "]";
19111929
}
19121930
}
1913-
if (refType != kNotReference) {
1914-
callbuf << "(" << type_name.c_str()
1915-
<< (refType == kLValueReference ? "&" : "&&") << ")*("
1916-
<< type_name.c_str() << "*)args[" << i << "]";
1917-
} else if (isPointer) {
1918-
callbuf << "*(" << type_name.c_str() << "**)args[" << i << "]";
1919-
} else {
1920-
callbuf << "*(" << type_name.c_str() << "*)args[" << i << "]";
1921-
}
1931+
callbuf << ")";
19221932
}
1923-
callbuf << ")";
19241933
}
19251934

19261935
const DeclContext* get_non_transparent_decl_context(const FunctionDecl* FD) {
@@ -2072,18 +2081,59 @@ void make_narg_ctor_with_return(const FunctionDecl* FD, const unsigned N,
20722081
std::ostringstream& buf, int indent_level) {
20732082
// Make a code string that follows this pattern:
20742083
//
2075-
// (*(ClassName**)ret) = (obj) ?
2076-
// new (*(ClassName**)ret) ClassName(args...) : new ClassName(args...);
2077-
//
2084+
// Array new if nary has been passed, and nargs is 0 (must be default ctor)
2085+
// if (nary) {
2086+
// (*(ClassName**)ret) = (obj) ? new (*(ClassName**)ret) ClassName[nary] :
2087+
// new ClassName[nary];
2088+
// }
2089+
// else {
2090+
// (*(ClassName**)ret) = (obj) ? new (*(ClassName**)ret) ClassName(args...)
2091+
// : new ClassName(args...);
2092+
// }
20782093
{
20792094
std::ostringstream typedefbuf;
20802095
std::ostringstream callbuf;
20812096
//
20822097
// Write the return value assignment part.
20832098
//
20842099
indent(callbuf, indent_level);
2100+
auto* CD = dyn_cast<CXXConstructorDecl>(FD);
2101+
2102+
// Activate this block only if array new is possible
2103+
// if (nary) {
2104+
// (*(ClassName**)ret) = (obj) ? new (*(ClassName**)ret) ClassName[nary]
2105+
// : new ClassName[nary];
2106+
// }
2107+
// else {
2108+
if (!CD->isDefaultConstructor() && CD->getNumParams() == 0) {
2109+
callbuf << "if (nary > 1) {\n";
2110+
indent(callbuf, indent_level);
2111+
callbuf << "(*(" << class_name << "**)ret) = ";
2112+
callbuf << "(is_arena) ? new (*(" << class_name << "**)ret) ";
2113+
make_narg_ctor(FD, N, typedefbuf, callbuf, class_name, indent_level,
2114+
true);
2115+
2116+
callbuf << ": new ";
2117+
//
2118+
// Write the actual expression.
2119+
//
2120+
make_narg_ctor(FD, N, typedefbuf, callbuf, class_name, indent_level,
2121+
true);
2122+
//
2123+
// End the new expression statement.
2124+
//
2125+
callbuf << ";\n";
2126+
indent(callbuf, indent_level);
2127+
callbuf << "}\n";
2128+
callbuf << "else {\n";
2129+
}
2130+
2131+
// Standard branch:
2132+
// (*(ClassName**)ret) = (obj) ? new (*(ClassName**)ret) ClassName(args...)
2133+
// : new ClassName(args...);
2134+
indent(callbuf, indent_level);
20852135
callbuf << "(*(" << class_name << "**)ret) = ";
2086-
callbuf << "(obj) ? new (*(" << class_name << "**)ret) ";
2136+
callbuf << "(is_arena) ? new (*(" << class_name << "**)ret) ";
20872137
make_narg_ctor(FD, N, typedefbuf, callbuf, class_name, indent_level);
20882138

20892139
callbuf << ": new ";
@@ -2095,6 +2145,10 @@ void make_narg_ctor_with_return(const FunctionDecl* FD, const unsigned N,
20952145
// End the new expression statement.
20962146
//
20972147
callbuf << ";\n";
2148+
indent(callbuf, --indent_level);
2149+
if (!CD->isDefaultConstructor() && CD->getNumParams() == 0)
2150+
callbuf << "}\n";
2151+
20982152
//
20992153
// Output the whole new expression and return statement.
21002154
//
@@ -2607,8 +2661,14 @@ int get_wrapper_code(compat::Interpreter& I, const FunctionDecl* FD,
26072661
"__attribute__((annotate(\"__cling__ptrcheck(off)\")))\n"
26082662
"extern \"C\" void ";
26092663
buf << wrapper_name;
2610-
buf << "(void* obj, int nargs, void** args, void* ret)\n"
2611-
"{\n";
2664+
if (Cpp::IsConstructor(FD)) {
2665+
buf << "(void* ret, unsigned long nary, unsigned long nargs, void** args, "
2666+
"void* is_arena)\n"
2667+
"{\n";
2668+
} else
2669+
buf << "(void* obj, unsigned long nargs, void** args, void* ret)\n"
2670+
"{\n";
2671+
26122672
++indent_level;
26132673
if (min_args == num_params) {
26142674
// No parameters with defaults.

0 commit comments

Comments
 (0)