- Provides no piroirity supoort && disables three priority related attributes: init_priority, ctor attr, dtor attr;
- '-qunique' in XL compiler equivalent behavior of emitting sinit and sterm functions name using getUniqueModuleId() function in LLVM (currently no support for InternalLinkage and WeakODRLinkage symbols);
- Add testcases to emit IR sample with sinit80000000, dtor, and __sterm80000000
- Temporarily side-steps the need to implement the functionality of llvm.global_ctors and llvm.global_dtors arrays. The uses of that functionality in this patch (with respect to the name of the functions involved) are not representative of how the functionality will be used once implemented.
Details
Diff Detail
- Repository
- rG LLVM Github Monorepo
Event Timeline
clang/lib/Sema/SemaDeclAttr.cpp | ||
---|---|---|
6942–6946 | This change (and the others like it) should be done within Attr.td and not exposed here. You should make these attributes target-specific. You should also update AttrDocs.td for these attributes to document that they're not supported on AIX. | |
clang/test/CodeGen/aix-priority-attribute.cpp | ||
1–4 ↗ | (On Diff #261602) | I think this test file should live in SemaCXX instead, as this is not testing the codegen behavior, but testing the semantic checking behavior. |
clang/lib/CodeGen/CGDeclCXX.cpp | ||
---|---|---|
720 | I may be missing something but why do we need this now, as opposed to not needing it before? Why didn't we need to clear the CXXGlobalDtors after emitting the function function before? | |
clang/lib/CodeGen/ItaniumCXXABI.cpp | ||
4526 | Style guide now says no capitalization and no punctuation at the end for report_fatal_error messages. |
clang/lib/CodeGen/CGDeclCXX.cpp | ||
---|---|---|
720 | No, you didn't miss anything here. I just followed what EmitCXXGlobalInitFunc() does, which is to clear the std::vecotr once we are certain it's useless. | |
clang/lib/Sema/SemaDeclAttr.cpp | ||
6942–6946 | Thanks for your comments. As I mentioned in the below testcase, those three attributes actually will be supported by the follow-up patches for AIX. I will update them to report_fatal_error instead. | |
clang/test/CodeGen/aix-priority-attribute.cpp | ||
1–4 ↗ | (On Diff #261602) | Actually we will support those three attributes in the future, so the warning are placeholders waiting for the future upgrade where we do want to check the codegen results. I agree the warnings here are confusing, I will update them with report_fatal_error. |
clang/test/CodeGen/static-init.cpp | ||
---|---|---|
2 | Shouldn't this be internal? |
clang/lib/AST/ItaniumMangle.cpp | ||
---|---|---|
5243 | If I understand correctly, this function will come in pair with __cxx_global_var_init. | |
clang/lib/CodeGen/CGCXXABI.h | ||
113 | Do we need this isCXXGlobalInitAndDtorFuncInternal? Looks like it's always going to return ! useSinitAndSterm() result. | |
clang/lib/CodeGen/CGDeclCXX.cpp | ||
591 | const for UseSinitAndSterm variable? | |
643 | flip this for an early return? | |
696 | We might want to avoid this string copy construction if possible. | |
clang/lib/CodeGen/CodeGenModule.h | ||
20 | Is this Attr.h needed somewhere in this file? | |
401 | nit: UserSinitAndSterm -> UseSinitAndSterm? | |
clang/lib/CodeGen/ItaniumCXXABI.cpp | ||
4528 | In this implementation we do not seem to have __srterm functions. I think we should refer to __dtor instead. | |
4561 | Srterm is not used in this implementation. | |
4563 | I think we need a better naming for this and make it consistent with the end block below. | |
clang/test/CodeGen/static-init.cpp | ||
0 | Would it be better to test static init for at least two global variable? |
clang/lib/CodeGen/CGDeclCXX.cpp | ||
---|---|---|
304 | Is there a valid case that unatexit.getCallee() returns a type which could not be cast to llvm::Function? |
-fregister_global_dtors_with_atexit does not seem to work properly in current implementation.
We should consider somehow disabling/report_fatal_error it instead of letting it generate invalid code on AIX.
clang/lib/CodeGen/CGDeclCXX.cpp | ||
---|---|---|
599 | I think report_fatal_error is more appropriate here? Since we know some case will trigger this, and we do not want those case to silently pass in non-assertion mode? | |
clang/lib/CodeGen/ItaniumCXXABI.cpp | ||
4534 | This comment is confusing. | |
4550 | nit: this is not sterm function. |
Address the comments
clang/lib/AST/ItaniumMangle.cpp | ||
---|---|---|
5243 | This is somewhere I am kinda on the fence. Personally, I think embed decl name in the cxx_global_var_destruct_ / cxx_global_vat_init_ as mangleDynamicAtExitDestructor does is more helpful for the user to debug the static init. | |
clang/lib/CodeGen/CGCXXABI.h | ||
113 | AFAIK, not all platforms which use sinit and sterm have external linkage sinit/sterm functions. And also since for 7.2 AIX we are considering change sinit/sterm to internal linkage symbols, I seperate this query out. | |
clang/lib/CodeGen/CGDeclCXX.cpp | ||
304 | I used cast instead of dyn_cast before Diff 9 actually, and then I noticed that clang-tidy gave error and asked me to use dyn_cast instead. Cannot recall what the error says though... | |
clang/lib/CodeGen/CodeGenModule.h | ||
20 | Oops..this is something I forgot to remove. Good catch! | |
clang/lib/CodeGen/ItaniumCXXABI.cpp | ||
4563 | Thanks, I will try destruct.call instead. |
clang/lib/CodeGen/CGCXXABI.h | ||
---|---|---|
113 | I would prefer to create the query in the patch when we actually need it. With what we have right now, it seems redundant. | |
clang/lib/CodeGen/CGDeclCXX.cpp | ||
643 | It looks like one of the UseSinitAndSterm is redundant. We could have something like: UseSinitAndSterm ? llvm::twine("__sinit80000000_clang_") + GlobalUniqueModuleId : llvm::twine("_GLOBAL__sub_I_") + getTransformedFileName(getModule()) which minimize the use of std::string? | |
696 | Could we assert !GlobalUniqueModuleId.empty() here? | |
703 | This could go inside of the if (UseSinitAndSterm). | |
clang/lib/CodeGen/ItaniumCXXABI.cpp | ||
4561 | "guard.hasDtor" does not reflect what the meaning. Maybe matching with the variable name would make sense: "guard.needsDestruct" or just "needsDestruct"? | |
clang/test/CodeGen/static-init.cpp | ||
3 | #0 could be removed. |
clang/lib/CodeGen/ItaniumCXXABI.cpp | ||
---|---|---|
4528 | We should probably report_fatal_error if CXAAtExit (the option) is true before this line. This would imply driver changes to default AIX to using -fno-use-cxa-atexit. An associated test file is https://github.com/llvm/llvm-project/blame/master/clang/test/Driver/cxa-atexit.cpp. |
clang/lib/CodeGen/CGDeclCXX.cpp | ||
---|---|---|
567 | Consider having the SmallString<128> buffer passed in and returning a StringRef backed by that buffer. | |
clang/lib/CodeGen/CodeGenModule.h | ||
1066 | What is "the C++ global destructor function"? Based on the comment on CXXGlobalDtors it has something to do with termination of the program. The existing usage is limited and consistent: This is a facility used when even atexit is not available. | |
1068 | The description of CXXGlobalDtors is
| |
clang/lib/CodeGen/ItaniumCXXABI.cpp | ||
4582 | The purpose of the specific interface does not appear to match its usage here (see my other comment). This function is meant to be called on unloading a shared library. The usual termination path calls destructors via atexit. |
clang/include/clang/AST/Mangle.h | ||
---|---|---|
178 | I am not sure "destructor" is the right term here. This seems to be an analogue to the functions named using mangleDynamicAtExitDestructor, except that those rather directly perform destruction and are registered with atexit during initialization whereas these perform finalization and are "registered" by being called from an "sterm" function. What are the thoughts on mangleDynamicStermFinalizer? | |
clang/lib/AST/ItaniumMangle.cpp | ||
5243 | Not every dynamically initialized non-local variable of static storage duration requires non-trivial destruction. These don't actually pair with __cxx_global_var_init; rather, they pair with the calls to atexit and the functions whose addresses are passed to atexit. |
clang/lib/CodeGen/CGDeclCXX.cpp | ||
---|---|---|
304 | If we expect cast to be okay, then we should use it without the if. In Diff 8, an if is used with cast (thus a clang-tidy error make sense): if (llvm::Function *unatexitFn = cast<llvm::Function>(unatexit.getCallee())) |
Address another round of reviews;
clang/include/clang/AST/Mangle.h | ||
---|---|---|
178 | mangleDynamicDestructor is an analogue to mangleDynamicInitializer actually. From this perspective, I think mangleDynamicStermFinalizer is good. | |
clang/lib/CodeGen/CodeGenModule.h | ||
1068 | Currently, only Apple Kernal extension will use AddCXXDtorEntry to add variable destructor to CXXGlobalDtors. $cat test.cpp class test { int a; public: test(int c) {a = c;} ~test() {a = 0;} } t(1); $clang --driver-mode=g++ -target x86_64-apple-darwin10 -fapple-kext -flto -S -o - test.cpp ... define internal void @_GLOBAL__D_a() #0 { entry: call void @_ZN4testD1Ev(%class.test* @t) #~test() {a = 0;} ret void } Since the usage as you said below does not match with our sterm finalizer function __cxx_global_var_destruct, I am thinking we can either modify the name and the description of CXXGlobalDtors to make it also fit AIX or we can define a brand new CXXStermFinalizers vector and also related facility to GenerateCXXStermFinalizerFunc instead. An example of modification I have in mind is:
I would prefer the modification way to save a lot effort. Any thoughts on it? | |
clang/lib/CodeGen/ItaniumCXXABI.cpp | ||
4528 | Maybe we should add -fno-use-cxa-atexit to driver in a follow-up patch? | |
clang/test/CodeGen/static-init.cpp | ||
3 | Why I chose to keep this #0 is because to remove it, we would either remove the following { which I kinda feel makes the function look not nice or we need to match #0 with regex which I think is redundant. |
clang/lib/CodeGen/CGDeclCXX.cpp | ||
---|---|---|
292 | Please add a comment explaining the meaning of the zero and non-zero return values. | |
609 | I don't think we should capitalize "sinit" and "sterm" in comments. Indeed, there's a comment below where they are not capitalized. | |
642–643 | The first sentence does not apply unconditionally in the status quo of this patch. Perhaps keep the original comment completely with something like: // When not using sinit and sterm functions: // ... | |
644 | Can this part be committed in a separate patch? It does not appear to have dependencies on other parts of this patch and has the appearance of being a possible change for other platforms. | |
689–690 | Following from my previous comments on CXXGlobalDtors, I am not convinced that __sterm functions match the role. | |
720 | If this is another drive-by fix, can we put it in a separate patch? | |
832–842 | This change would not belong in this function if its scope remains the generation of a "GlobalDtorsFunc" (based on my understanding of the latter). | |
clang/lib/CodeGen/ItaniumCXXABI.cpp | ||
4526 | s/unimplemented on AIX yet/not yet implemented on AIX/; | |
4548 | Suggestion: | |
4561 | I don't think this is a real "guard variable". I think the comments need to explain this (including scare quotes for "guard variable". |
clang/lib/AST/ItaniumMangle.cpp | ||
---|---|---|
5239 | I believe these are actually paired with the __dtor_ functions. The prefix can be __finalize_. | |
clang/lib/CodeGen/CGDeclCXX.cpp | ||
567 | FileName should be a reference? | |
643 | The binding of the second sentence in relation to "not using sinit and sterm" is not clear in this new version. I still recommend introducing a "block" with a colon. | |
645 | Use a SmallString for FuncName. | |
646 | Move Storage into the else block and use it only for calling getTransformedFileName. |
clang/lib/CodeGen/CGDeclCXX.cpp | ||
---|---|---|
689–690 | This function is to be renamed. | |
699 | The called function is to be renamed. | |
clang/lib/CodeGen/CodeGenModule.h | ||
1067 | This function is to be renamed. | |
clang/lib/CodeGen/ItaniumCXXABI.cpp | ||
4541 | This function is to be renamed. | |
4553 | Term, being a short form for "termination", the variable name does not match the purpose based on the terminology within the Clang context. | |
4570 | This comment is not helpful. It does not say which action is associated with which state. | |
clang/test/CodeGen/aix-constructor-attribute.cpp | ||
3 | Please split on the | with the new line beginning with FileCheck indented two spaces in relation to the previous line. Apply throughout. |
clang/test/CodeGen/static-init.cpp | ||
---|---|---|
0 | Looks like the non-inline comments are easier to get ignored and missed, so I will copy paste the non-inlined comment I previously had: -fregister_global_dtors_with_atexit does not seem to work properly in current implementation. We should consider somehow disabling/report_fatal_error it instead of letting it generate invalid code on AIX. |
clang/test/CodeGen/static-init.cpp | ||
---|---|---|
0 | I suggest adding also one each of the following:
|
Address another round of reviews;
clang/lib/CodeGen/CGDeclCXX.cpp | ||
---|---|---|
644 | Sure. I will create a NFC patch for this part and try to commit it first. But so far, I think I can keep this part in this patch just for review purpose to make the patch look nicer? | |
699 | Any suggestions here about how to represent the functionality of __sterm and _GLOBAL__D_a into one word? Cannot think of a good name... Actually I am wondering do we need to rename the Destruct part? The __sterm and _GLOBAL__D_a do destruct the object by calling sterm finalizers and object destructors? | |
720 | Sure, I will put it in the above mentioned clean-up NFC patch as well. | |
816 | I will try GenerateCXXGlobalDestructFunc based on the thoughts as I also mentioned elsewhere that the __sterm and _GLOBAL__D_ function do destruct the object by calling sterm finalizers and object destructors. Any suggestions or concerns about this renaming? Or do we really need to rename this one? | |
clang/lib/CodeGen/ItaniumCXXABI.cpp | ||
4548 | I don't get your point, can you elaborate on this a little bit? | |
clang/test/CodeGen/static-init.cpp | ||
0 | Thanks for doing so! The semantic of global_dtors here on AIX is __sterm function, which we are never gonna register with __atexit. I am thinking we can disable it in a follow-up driver patch with the handling of -fno-use-cxa-atexit. |
clang/lib/CodeGen/CGDeclCXX.cpp | ||
---|---|---|
644 | Sure; you'd need the new patch to exist before rebasing on it anyway. We can leave the rebasing to the commit or later in the review. | |
699 | Being clear in the naming of the function helps to signal its purpose to future maintainers. The sterm finalizers are unlikely to be understood from Destruct (it implies plain destruction a bit too much). Maybe "cleanup"? | |
816 | I think "cleanup" works here too. | |
clang/lib/CodeGen/ItaniumCXXABI.cpp | ||
4548 | This is my suggestion for the comment (to replace "Create a variable destruction function"). |
clang/test/CodeGen/static-init.cpp | ||
---|---|---|
15 | Okay, the restricted scope of this patch seems to landed in a place where how the llvm.global_dtors array will be handled is not indicated... The backend should implement the semantics of the IR construct. When handling said array in the IR, it seems the method to handle the requisite semantics would be to generate an alias (with the appropriate linkage for the linker to pick it up) that is named using the __sinit/__sterm convention. Which is to say that at least some part of the naming should eventually move into the LLVM side and out of Clang. Please update the description of this patch to indicate that:
|
clang/test/CodeGen/static-init.cpp | ||
---|---|---|
0 | The semantic of global_dtors is not limited to the __sterm functions associated with C++ cleanup actions. With respect to user-declared __attribute__((__destructor__)) functions, the option could improve the interleaving of those cleanup actions with cleanup actions registered by user-declared __attribute__((__constructor__)) functions. This provides that rationale for separating the __sterm functions associated with the C++ cleanup actions from the other "destructor" functions. |
clang/lib/CodeGen/CGDeclCXX.cpp | ||
---|---|---|
276 | s/atexit has wrong parameter type/Argument to atexit has a wrong type/; | |
301 | s/unatexit has wrong parameter type/Argument to unatexit has a wrong type/; | |
645 | Replace the call to toNullTerminatedStringRef and the assignment with a call to toVector. | |
646 | CreateGlobalInitOrDestructFunction currently calls Create with llvm::GlobalValue::InternalLinkage and also calls SetInternalFunctionAttributes. Setting ExternalLinkage after-the-fact seems brittle. | |
653 | Replace the call to toNullTerminatedStringRef and the assignment with a call to toVector. | |
689–690 | I think "cleanup" works here too. | |
693–695 | s/Create our global destructor function/Create our global cleanup function/; | |
826–827 | s/dtors/cleanups/; | |
clang/lib/CodeGen/CodeGenModule.h | ||
472 | Near duplicate comment line. | |
473 | s/finalizers/finalizer/; | |
474 | s/instead that need to run/, which also run/; | |
1060 | s/a destructor/an sterm finalizer/; | |
1061 | s/Dtor/StermFinalizer/; | |
1463–1464 | s/destructs/performs cleanup associated with/; | |
clang/lib/CodeGen/ItaniumCXXABI.cpp | ||
4532 | There should not be period at the end of a report_fatal_error message. | |
4536 | s/and/and (as appropriate)/; | |
4561 | The "and the related [ ... ]" part is ambiguous in terms of describing unatexit versus the actions generated here. Suggestion: | |
4562 | Remove the "Otherwise [ ... ]". | |
4565 | Does this fit on one line? | |
4573 | Please add a test for a static local. Note the branch_weights. I do not believe the branch_weights associated with guarded initialization for a static local (what the called function is meant to deal with) is necessarily appropriate for a branch associated with finalization-on-unload. | |
clang/lib/Sema/SemaDeclAttr.cpp | ||
6944 | s/unsupported on AIX yet/is not yet supported on AIX/; | |
6953 | s/unsupported on AIX yet/is not yet supported on AIX/; | |
7151 | s/unsupported on AIX yet/is not yet supported on AIX/; |
clang/test/CodeGen/static-init.cpp | ||
---|---|---|
15 | I think the llvm.global_ctors usage is also more extensive here (and not symmetric on the finalization side): struct C { C(int) {} ~C() {} }; C c0 = 42; template <typename T> C c = 42; inline C c1 = 42; int main(void) { (void) &c<int>; } |
Renamed some functions;
Add one more test;
etc.
clang/lib/CodeGen/ItaniumCXXABI.cpp | ||
---|---|---|
4573 | Thank you for pointing this out. I will adjust the function name to EmitCXXGuardedInitOrDestructBranch later to match our usage. In terms of branch_weights, this is something I am not familiar with. So please correct me if I am wrong. Some of my superficial thoughts would be are we able to apply branch_weights on a branch associated with finalization-on-unload? Should it be set as nullptr, because we would not know how many times we will call __sterm(and each sterm finalizer contained)? BTW, I will add a testcase for a static local and we can update the branch_weights part later along with the reviews. | |
clang/test/CodeGen/static-init.cpp | ||
0 | Yeah, I agree that the semantic of global_dtors should contain both __sterm and __attribute__((__destructor__)) dtors. And we do need some rationale to separate __sterm and those other destructor functions out for AIX. However, I doubt the -fregister_global_dtors_with_atexit option is something we should use. Cuz dtors with __attribute__((__destructor__)) actually are equivalent to __dtor functions in AIX's semantic which need to be registered with __atexit. However, we shouldn't register __sterm with __atexit. So it seems this option does not work well for AIX either we set it to true or false, and we need to figure something else out when we start supporting __attribute__((__destructor__)) and __attribute__((__constructor__))? | |
15 | Yes, we should definitely test template variable(and other WeakODR linkage symbols) and inline variable. However, this patch hasn't covered these aspects yet. My plan was to set the basic frame using this patch, and have some small follow-up patches to clean up the implementation. Do you think we should cover these in this patch as well? I kinda feel it's already a bit big one.. |
clang/lib/CodeGen/ItaniumCXXABI.cpp | ||
---|---|---|
4573 | I don't think we want to generate branch_weights. We already expect __sterm to be called rarely. Just changing the function name is not going to help though. A caller would need to indicate which of "init" or "destruct" is intended. | |
clang/test/CodeGen/static-init.cpp | ||
0 | Yes, we should look further into this when __attribute__((__destructor__)) is supported. The difference between atexit-registered functions and __sterm functions is in whether or not they are run when unloading a module (which termination also does). Thanks for your observation re: the similarity between __attribute__((__destructor__)) functions and the __dtor functions. Thinking about it a bit, the level of similarity is rather tied to the option in question. If we choose to register using atexit, we need to consider introducing the corresponding unatexit. This means that even when the option in question is active, we will produce entries into the global_dtors array at the IR level. | |
15 | The patch is already limited in scope in such a way that covering the WeakODR linkage cases would not fit well. I'm fine with handling them later. There may be work specific for these with respect to the symmetry between the initialization and the finalization. |
clang/lib/CodeGen/CGDeclCXX.cpp | ||
---|---|---|
707 | Correct me if I'm wrong... | |
clang/lib/CodeGen/CodeGenModule.h | ||
471–473 | Word after ; should not be Capitalize. We should use small case, or change this to .. | |
clang/test/CodeGen/static-init.cpp | ||
126 | Is checking this Attrs necessary? | |
141 | I think we used to have dso_local marked on sinit and sterm function in previous diff. Now they are gone. What's the reason for removing them? |
Remove trailing spaces;
Update the testcase;
Adjust the EmitGuardedInitBranch function;
clang/lib/CodeGen/CGDeclCXX.cpp | ||
---|---|---|
707 | Actually GlobalUniqueModuleId will not always get “initialized" in EmitCXXGlobalInitFunc. In some cases, only __sterm will be generated for the var decl. struct Test4 { Test4(); ~Test4(); }; void f() { static Test4 staticLocal; } | |
clang/test/CodeGen/static-init.cpp | ||
126 | I missed to delete this line. Thanks for pointing it out. | |
141 | dso_local affects calls to the function in terms of how the compiler will do the optimization on the call. Since we won't be generating any calls to the function (the linker arranges for the calls to happen indirectly), marking them dso_local does not help any. So I think it doesn't really matter if we put dso_local here. |
clang/lib/CodeGen/CGDeclCXX.cpp | ||
---|---|---|
345 | Do we need to change/complicate the interface for this function, just to do a call to Builder.CreateCondBr()? | |
642–643 | This comment does not apply well on top of this early return for some platform. I think you could move it to current line 665? |
Removed a redundant header file;
Addressed comments;
clang/lib/CodeGen/CGDeclCXX.cpp | ||
---|---|---|
345 | Sure, we can. Thank you for your suggestion. I was hoping to use one function to synthesize the guarded init or destruct branch. But I think it seems better if we wait for further more usage of guarded destruct branch to do so and not complicate stuff in this patch. |
LGTM. But I suggest to wait for @hubert.reinterpretcast to have another scan at this before landing.
Thanks; LGTM with minor nit.
clang/lib/CodeGen/CodeGenModule.h | ||
---|---|---|
1060 | Minor nit: "a sterm" should be "an sterm" if "sterm" is pronounced like "es-term". | |
clang/test/CodeGenCXX/aix-static-init.cpp | ||
189 | Just a comment: The finalization order of static locals in relation to non-locals cannot (using the mechanisms available) be guaranteed to be consistent with the reverse order of initialization. I don't think that there is a clearly "correct" order, so "whatever falls out" is probably okay. |
FYI this diff appears to be breaking a ptrauth test on apple/swift/master-next (clang/test/CodeGenCXX/ptrauth-static-destructors.cpp).
Investigating this further.
I am not sure "destructor" is the right term here. This seems to be an analogue to the functions named using mangleDynamicAtExitDestructor, except that those rather directly perform destruction and are registered with atexit during initialization whereas these perform finalization and are "registered" by being called from an "sterm" function. What are the thoughts on mangleDynamicStermFinalizer?