This is an archive of the discontinued LLVM Phabricator instance.

Defer codegen of dllexport/attribute(used) inline method definitions
ClosedPublic

Authored by hans on Jun 5 2014, 4:16 PM.

Details

Summary

We would previously fail to emit a definition of bar() for the following code:

struct __declspec(dllexport) S {
  void foo() {
    t->bar();
  }
  struct T {
    void bar() {}
  };
  T *t;
};

Note that foo() is an exported method, but bar() is not. However, foo() refers to bar() so we need to emit its definition. To make this work, we need to delay the codegen of foo() until the bodies of all the other inline methods have been parsed.

The same problem applies to inline methods that are marked used.

Diff Detail

Repository
rL LLVM

Event Timeline

hans updated this revision to Diff 10159.Jun 5 2014, 4:16 PM
hans retitled this revision from to Defer codegen of dllexport/attribute(used) inline method definitions.
hans updated this object.
hans edited the test plan for this revision. (Show Details)
hans added reviewers: rnk, rsmith.
hans added subscribers: Unknown Object (MLST), hansw.
hans updated this revision to Diff 10160.Jun 5 2014, 5:35 PM

Simplify things. Let ModuleBuilder defer method definitions, and then consider them at the next top level decl. At that point, it's safe to calculate the GVA linkage, so we can just call into EmitTopLevelDecl and let that figure out if the method needs to be emitted in the usual way - no special cases.

rsmith added inline comments.Jun 5 2014, 6:24 PM
lib/CodeGen/ModuleBuilder.cpp
92 ↗(On Diff #10160)

An alternative fix would be to check D->isUsed() instead of checking for UsedAttr here. That'd avoid the locality degradation and memory allocation here.

Or just remove this check and unconditionally call EmitTopLevelDecl? That would better match what we do for out-of-line method definitions, and would avoid duplicating this between here and ASTContext::DeclMustBeEmitted.

test/CodeGenCXX/attr-used.cpp
21 ↗(On Diff #10160)

Typo "othersie"

hans added inline comments.Jun 5 2014, 6:48 PM
lib/CodeGen/ModuleBuilder.cpp
92 ↗(On Diff #10160)

Checking D->isUsed() certainly sounds simpler :-) I'll try that out.

We can't unconditionally call EmitTopLevelDecl, because it will call DeclMustBeEmitted, which might calculate the gva linkage, and then we fail this test from SemaCXX/undefined-internal.cpp :(

namespace test7 {
  typedef struct {
    void bar();
    void foo() { bar(); }
  } A;
}

I suspect that test doesn't work well with the "used" attribute either.

test/CodeGenCXX/attr-used.cpp
21 ↗(On Diff #10160)

Done.

rsmith accepted this revision.Jun 5 2014, 7:12 PM
rsmith edited edge metadata.

LGTM

lib/CodeGen/ModuleBuilder.cpp
92 ↗(On Diff #10160)

Arrgh! That's horrible, but it does justify delaying the emission to end of TU. The existing code is wrong for this case even without checking 'used'. A comment here mentioning this case would be useful for future archaeologists.

This revision is now accepted and ready to land.Jun 5 2014, 7:12 PM
hans added inline comments.Jun 5 2014, 10:11 PM
lib/CodeGen/ModuleBuilder.cpp
92 ↗(On Diff #10160)

The current patch delays emission to the end of the current top level declaration. Is that OK, or are you saying we need to delay all the way to the end of the TU?

hans closed this revision.Jun 6 2014, 10:44 AM
hans updated this revision to Diff 10183.

Closed by commit rL210356 (authored by @hans).