Skip to content

Commit ce9b420

Browse files
committed
Don't enforce (normal) emission for pragma(inline, true) function templates
Debugging failing fail_compilation/ice19762.d (stack overflow in LDC) was a trip down the rabbit hole. By the looks of it, the root of all evil is again the frontend not properly validating IndexExpressions - this time, for structs with fwd- referencing errors (analogous to the problem for opaque structs with compilable/ice20044.d, see https://issues.dlang.org/show_bug.cgi?id=20959). The stack overflow happens in LLVM when trying to create a GEP for core.internal.array.equality.at(), when checking the struct element type (with cycles, i.e., containing a field of itself) for sizedness. This little function now uses `pragma(inline, true)`, so it was newly codegen'd although needsCodegen() returns false. With the new available_externally emission into each referencing CU, I think this enforced regular emission from the module members tree shouldn't be required anymore, allowing to work around the test regression and possibly more issues with speculative instantiations. After adapting the codegen/inlining_templates.d lit-test accordingly (no IR definitions anymore in .ll file, because available_externally doesn't make it there), I've noticed that a lambda in imported and inlined call_enforce_with_default_template_params() wasn't emitted - it got culled by alreadyOrWillBeDefined(). Function/delegate literals aren't culled anymore.
1 parent 3e1dcc5 commit ce9b420

File tree

3 files changed

+19
-27
lines changed

3 files changed

+19
-27
lines changed

gen/declarations.cpp

+12-21
Original file line numberDiff line numberDiff line change
@@ -371,28 +371,19 @@ class CodegenVisitor : public Visitor {
371371
return;
372372
}
373373

374-
// Force codegen if this is a templated function with pragma(inline, true).
375-
if ((decl->members->length == 1) &&
376-
((*decl->members)[0]->isFuncDeclaration()) &&
377-
((*decl->members)[0]->isFuncDeclaration()->inlining == PINLINEalways)) {
378-
Logger::println("needsCodegen() == false, but function is marked with "
379-
"pragma(inline, true), so it really does need "
380-
"codegen.");
381-
} else {
382-
// FIXME: This is #673 all over again.
383-
if (!decl->needsCodegen()) {
384-
Logger::println("Does not need codegen, skipping.");
385-
return;
386-
}
374+
// FIXME: This is #673 all over again.
375+
if (!decl->needsCodegen()) {
376+
Logger::println("Does not need codegen, skipping.");
377+
return;
378+
}
387379

388-
if (irs->dcomputetarget && (decl->tempdecl == Type::rtinfo ||
389-
decl->tempdecl == Type::rtinfoImpl)) {
390-
// Emitting object.RTInfo(Impl) template instantiations in dcompute
391-
// modules would require dcompute support for global variables.
392-
Logger::println("Skipping object.RTInfo(Impl) template instantiations "
393-
"in dcompute modules.");
394-
return;
395-
}
380+
if (irs->dcomputetarget && (decl->tempdecl == Type::rtinfo ||
381+
decl->tempdecl == Type::rtinfoImpl)) {
382+
// Emitting object.RTInfo(Impl) template instantiations in dcompute
383+
// modules would require dcompute support for global variables.
384+
Logger::println("Skipping object.RTInfo(Impl) template instantiations "
385+
"in dcompute modules.");
386+
return;
396387
}
397388

398389
for (auto &m : *decl->members) {

gen/function-inlining.cpp

+3
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,9 @@ bool isInlineCandidate(FuncDeclaration &fdecl) {
7373
} // end anonymous namespace
7474

7575
bool alreadyOrWillBeDefined(FuncDeclaration &fdecl) {
76+
if (fdecl.isFuncLiteralDeclaration()) // emitted into each referencing CU
77+
return true;
78+
7679
for (FuncDeclaration *f = &fdecl; f;) {
7780
if (!f->isInstantiated() && f->inNonRoot()) {
7881
return false;

tests/codegen/inlining_templates.d

+4-6
Original file line numberDiff line numberDiff line change
@@ -31,10 +31,8 @@ void main()
3131
{
3232
}
3333

34-
// CHECK-NOT: declare{{.*}}_D6inputs10inlinables__T12template_fooTiZQrUNaNbNiNfiZi
35-
// CHECK-NOT: declare{{.*}}_D3std9exception__T7enforce
34+
// CHECK-NOT: declare {{.*}}template_foo
3635

37-
// CHECK-DAG: define{{.*}}_D6inputs10inlinables__T12template_fooTiZQrUNaNbNiNfiZi{{.*}}) #[[ATTR:[0-9]+]]
38-
// CHECK-DAG: define{{.*}}_D3std9exception__T7enforce{{.*}}) #[[ATTR]]
39-
40-
// CHECK-DAG: attributes #[[ATTR]] ={{.*}} alwaysinline
36+
// CHECK-NOT: declare {{.*}}call_enforce_with_default_template_params
37+
// CHECK-NOT: declare {{.*}}__lambda
38+
// CHECK-NOT: declare {{.*}}_D3std9exception__T7enforce

0 commit comments

Comments
 (0)