Skip to content

Commit f706d8c

Browse files
committed
Add array new for ctor codegen in JitCall
1 parent 8dbfc8a commit f706d8c

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
@@ -1892,42 +1892,51 @@ void collect_type_info(const FunctionDecl* FD, QualType& QT,
18921892

18931893
void make_narg_ctor(const FunctionDecl* FD, const unsigned N,
18941894
std::ostringstream& typedefbuf, std::ostringstream& callbuf,
1895-
const std::string& class_name, int indent_level) {
1895+
const std::string& class_name, int indent_level,
1896+
bool array = false) {
18961897
// Make a code string that follows this pattern:
18971898
//
18981899
// ClassName(args...)
1900+
// OR
1901+
// ClassName[nary] // array of objects
18991902
//
19001903

1901-
callbuf << class_name << "(";
1902-
for (unsigned i = 0U; i < N; ++i) {
1903-
const ParmVarDecl* PVD = FD->getParamDecl(i);
1904-
QualType Ty = PVD->getType();
1905-
QualType QT = Ty.getCanonicalType();
1906-
std::string type_name;
1907-
EReferenceType refType = kNotReference;
1908-
bool isPointer = false;
1909-
collect_type_info(FD, QT, typedefbuf, callbuf, type_name, refType,
1910-
isPointer, indent_level, true);
1911-
if (i) {
1912-
callbuf << ',';
1913-
if (i % 2) {
1914-
callbuf << ' ';
1904+
if (array)
1905+
callbuf << class_name << "[nary]";
1906+
else
1907+
callbuf << class_name;
1908+
if (N) {
1909+
callbuf << "(";
1910+
for (unsigned i = 0U; i < N; ++i) {
1911+
const ParmVarDecl* PVD = FD->getParamDecl(i);
1912+
QualType Ty = PVD->getType();
1913+
QualType QT = Ty.getCanonicalType();
1914+
std::string type_name;
1915+
EReferenceType refType = kNotReference;
1916+
bool isPointer = false;
1917+
collect_type_info(FD, QT, typedefbuf, callbuf, type_name, refType,
1918+
isPointer, indent_level, true);
1919+
if (i) {
1920+
callbuf << ',';
1921+
if (i % 2) {
1922+
callbuf << ' ';
1923+
} else {
1924+
callbuf << "\n";
1925+
indent(callbuf, indent_level);
1926+
}
1927+
}
1928+
if (refType != kNotReference) {
1929+
callbuf << "(" << type_name.c_str()
1930+
<< (refType == kLValueReference ? "&" : "&&") << ")*("
1931+
<< type_name.c_str() << "*)args[" << i << "]";
1932+
} else if (isPointer) {
1933+
callbuf << "*(" << type_name.c_str() << "**)args[" << i << "]";
19151934
} else {
1916-
callbuf << "\n";
1917-
indent(callbuf, indent_level + 1);
1935+
callbuf << "*(" << type_name.c_str() << "*)args[" << i << "]";
19181936
}
19191937
}
1920-
if (refType != kNotReference) {
1921-
callbuf << "(" << type_name.c_str()
1922-
<< (refType == kLValueReference ? "&" : "&&") << ")*("
1923-
<< type_name.c_str() << "*)args[" << i << "]";
1924-
} else if (isPointer) {
1925-
callbuf << "*(" << type_name.c_str() << "**)args[" << i << "]";
1926-
} else {
1927-
callbuf << "*(" << type_name.c_str() << "*)args[" << i << "]";
1928-
}
1938+
callbuf << ")";
19291939
}
1930-
callbuf << ")";
19311940
}
19321941

19331942
const DeclContext* get_non_transparent_decl_context(const FunctionDecl* FD) {
@@ -2085,18 +2094,59 @@ void make_narg_ctor_with_return(const FunctionDecl* FD, const unsigned N,
20852094
std::ostringstream& buf, int indent_level) {
20862095
// Make a code string that follows this pattern:
20872096
//
2088-
// (*(ClassName**)ret) = (obj) ?
2089-
// new (*(ClassName**)ret) ClassName(args...) : new ClassName(args...);
2090-
//
2097+
// Array new if nary has been passed, and nargs is 0 (must be default ctor)
2098+
// if (nary) {
2099+
// (*(ClassName**)ret) = (obj) ? new (*(ClassName**)ret) ClassName[nary] :
2100+
// new ClassName[nary];
2101+
// }
2102+
// else {
2103+
// (*(ClassName**)ret) = (obj) ? new (*(ClassName**)ret) ClassName(args...)
2104+
// : new ClassName(args...);
2105+
// }
20912106
{
20922107
std::ostringstream typedefbuf;
20932108
std::ostringstream callbuf;
20942109
//
20952110
// Write the return value assignment part.
20962111
//
20972112
indent(callbuf, indent_level);
2113+
auto* CD = dyn_cast<CXXConstructorDecl>(FD);
2114+
2115+
// Activate this block only if array new is possible
2116+
// if (nary) {
2117+
// (*(ClassName**)ret) = (obj) ? new (*(ClassName**)ret) ClassName[nary]
2118+
// : new ClassName[nary];
2119+
// }
2120+
// else {
2121+
if (!CD->isDefaultConstructor() && CD->getNumParams() == 0) {
2122+
callbuf << "if (nary > 1) {\n";
2123+
indent(callbuf, indent_level);
2124+
callbuf << "(*(" << class_name << "**)ret) = ";
2125+
callbuf << "(is_arena) ? new (*(" << class_name << "**)ret) ";
2126+
make_narg_ctor(FD, N, typedefbuf, callbuf, class_name, indent_level,
2127+
true);
2128+
2129+
callbuf << ": new ";
2130+
//
2131+
// Write the actual expression.
2132+
//
2133+
make_narg_ctor(FD, N, typedefbuf, callbuf, class_name, indent_level,
2134+
true);
2135+
//
2136+
// End the new expression statement.
2137+
//
2138+
callbuf << ";\n";
2139+
indent(callbuf, indent_level);
2140+
callbuf << "}\n";
2141+
callbuf << "else {\n";
2142+
}
2143+
2144+
// Standard branch:
2145+
// (*(ClassName**)ret) = (obj) ? new (*(ClassName**)ret) ClassName(args...)
2146+
// : new ClassName(args...);
2147+
indent(callbuf, indent_level);
20982148
callbuf << "(*(" << class_name << "**)ret) = ";
2099-
callbuf << "(obj) ? new (*(" << class_name << "**)ret) ";
2149+
callbuf << "(is_arena) ? new (*(" << class_name << "**)ret) ";
21002150
make_narg_ctor(FD, N, typedefbuf, callbuf, class_name, indent_level);
21012151

21022152
callbuf << ": new ";
@@ -2108,6 +2158,10 @@ void make_narg_ctor_with_return(const FunctionDecl* FD, const unsigned N,
21082158
// End the new expression statement.
21092159
//
21102160
callbuf << ";\n";
2161+
indent(callbuf, --indent_level);
2162+
if (!CD->isDefaultConstructor() && CD->getNumParams() == 0)
2163+
callbuf << "}\n";
2164+
21112165
//
21122166
// Output the whole new expression and return statement.
21132167
//
@@ -2620,8 +2674,14 @@ int get_wrapper_code(compat::Interpreter& I, const FunctionDecl* FD,
26202674
"__attribute__((annotate(\"__cling__ptrcheck(off)\")))\n"
26212675
"extern \"C\" void ";
26222676
buf << wrapper_name;
2623-
buf << "(void* obj, int nargs, void** args, void* ret)\n"
2624-
"{\n";
2677+
if (Cpp::IsConstructor(FD)) {
2678+
buf << "(void* ret, unsigned long nary, unsigned long nargs, void** args, "
2679+
"void* is_arena)\n"
2680+
"{\n";
2681+
} else
2682+
buf << "(void* obj, unsigned long nargs, void** args, void* ret)\n"
2683+
"{\n";
2684+
26252685
++indent_level;
26262686
if (min_args == num_params) {
26272687
// No parameters with defaults.

0 commit comments

Comments
 (0)