This is an archive of the discontinued LLVM Phabricator instance.

Do not register incompatible C++ destructors with __cxa_atexit
ClosedPublic

Authored by dschuff on Apr 19 2016, 11:16 AM.

Details

Summary

For a static object with a nontrivial destructor, clang generates an
initializer function (__cxx_global_var_init) which registers that
object's destructor using __cxa_atexit. However some ABIs (ARM,
WebAssembly) use destructors that return 'this' instead of having void
return (which does not match the signature of function pointers passed
to __cxa_atexit). WebAssembly requires that all function signatures
of indirect calls exactly match the called function, so it raises an error
when the destructors are called.

This patch introduces CGCXXABI::canCalMismatchedFunctionType()
to specify whether this mismatch is allowed, and disables the direct
registration of destructors for ABIs that have this-returning destructors
on platforms which cannot tolerate the mismatch.

Diff Detail

Repository
rL LLVM

Event Timeline

dschuff updated this revision to Diff 54228.Apr 19 2016, 11:16 AM
dschuff retitled this revision from to Do not register incompatible C++ destructors with __cxa_atexit.
dschuff updated this object.
dschuff added a subscriber: cfe-commits.

Will want a reviewer who's involved with ARM too, still looking.

dschuff updated this object.Apr 19 2016, 11:18 AM
jfb added inline comments.Apr 19 2016, 11:25 AM
lib/CodeGen/CGDeclCXX.cpp
94 ↗(On Diff #54228)

This assignment is looking pretty ugly now, would be better to move out of line.

97 ↗(On Diff #54228)

Could you also pull out these conditions into their own bool? I find the ands and ors hard to follow!

test/CodeGenCXX/static-destructor.cpp
6 ↗(On Diff #54228)

You mention ARM but don't test ARM here.

dschuff updated this revision to Diff 54260.Apr 19 2016, 2:08 PM
dschuff marked 3 inline comments as done.
  • Clean up condition, add ARM to test
jfb added inline comments.Apr 19 2016, 2:24 PM
lib/CodeGen/CGDeclCXX.cpp
92 ↗(On Diff #54260)

Can you do that unconditionally? Or do you have to test for dtorKind == QualType::DK_cxx_destructor first? It looks like the function already does a dyncast_or_null so the previous code was doing a check it didn't need to.

95 ↗(On Diff #54260)

Comment on why you can't register dtor when has this return (ABI mismatch).

97 ↗(On Diff #54260)

Do you need to check Record here? Doesn't it also imply dtorKind == QualType::DK_cxx_destructor?

98 ↗(On Diff #54260)

|| !CGM.getCodeGenOpts().CXAAtExit seems wrong here. Shouldn't the condition be CanRegisterDestructor && CGM.getCodeGenOpts().CXAAtExit? I may be misunderstanding...

dschuff updated this revision to Diff 54264.Apr 19 2016, 2:44 PM
  • Clarify condition, remove redundant check
lib/CodeGen/CGDeclCXX.cpp
92 ↗(On Diff #54260)

Yes, that's why I made it unconditional. And actually I just noticed that the switch statement above returns from the function if dtorKind != DK_cxx_destructor anyway, so I removed the check here too.

95 ↗(On Diff #54260)

Doesn't the new text in the comment right above on line 98 cover that?

97 ↗(On Diff #54260)

Yes, there can be a case where Record is nullptr and CGM.getCodeGenOpts().CXAAtExit is false.

98 ↗(On Diff #54260)

I split and expanded the comment and made a variable with a name. See if it makes more sense now.

jfb added a comment.Apr 19 2016, 2:55 PM

lgtm besides two nits. Would be good to get a review from @t.p.northover or someone from ARM.

lib/CodeGen/CGDeclCXX.cpp
95 ↗(On Diff #54264)

Connecting the dots between "the right signature" and "has this return" isn't obvious IMO.

100 ↗(On Diff #54264)

clang-format

dschuff updated this revision to Diff 54274.Apr 19 2016, 3:10 PM
dschuff marked 2 inline comments as done.
  • Clean up condition, add ARM to test
  • Clarify condition, remove redundant check
  • more cleanup

any comments from @t.p.northover or perhaps @rengolin ?
(This does have a potential new cost on ARM, as it requires one thunk (which is just a tail call) per static initializer on ARM and WebAssembly)

I'm opposed to the changes on ARM. It would be undefined behaviour if the user wrote it at the C level, but not LLVM IR I think, which means Clang is perfectly entitled to emit calls like that.

Tim.

jfb added a comment.Apr 27 2016, 10:21 AM

@t.p.northover: would an acceptable solution be to add a new trait such as CGM.getCXXABI().CanCallMismatchedFunctionType() or something of the sort? ARM would set it to true, wasm to false.

rnk added a subscriber: rnk.Apr 27 2016, 10:32 AM

+1 for canCallMismatchedFunctionType.

I guess there's a more general issue here which is that LLVM appears to be more permissive about prototype mismatch than wasm. Specifically, I'm thinking about how swifterror relies on being able to pass extra parameters to a function that doesn't expect them and not get UB. I guess as long as LLVM doesn't introduce any prototype mismatch during optimization, that's OK, but this seems like it would be a real problem if we ever wanted to port swift to wasm.

Yep, that sounds about perfect to me. Exactly what the different CXXABI classes are for, really.

Tim.

jfb added a subscriber: pcc.Apr 27 2016, 10:44 AM

I guess there's a more general issue here which is that LLVM appears to be more permissive about prototype mismatch than wasm. Specifically, I'm thinking about how swifterror relies on being able to pass extra parameters to a function that doesn't expect them and not get UB. I guess as long as LLVM doesn't introduce any prototype mismatch during optimization, that's OK, but this seems like it would be a real problem if we ever wanted to port swift to wasm.

Yeah @dschuff, @sunfish and I were also talking about __cxa_pure_virtual being in the same signature-type-mismatch category. I wonder if this also makes CFI sad, /cc @pcc.

dschuff updated this revision to Diff 56218.May 4 2016, 4:17 PM
  • Introduce CGCXXABI::canCallMismatchedFunctionType
dschuff updated this object.May 4 2016, 4:22 PM

Thanks for the feedback, PTAL

jfb accepted this revision.May 10 2016, 9:29 AM
jfb added a reviewer: jfb.

lgtm

This revision is now accepted and ready to land.May 10 2016, 9:29 AM
rnk accepted this revision.May 10 2016, 9:45 AM
rnk added a reviewer: rnk.

lgtm

This revision was automatically updated to reflect the committed changes.

Well, I forgot to squash my local commits before landing, so this is r269085 thru r269089 :(