urnathan added inline comments.

================
Comment at: clang/test/CXX/modules-ts/basic/basic.def.odr/p4/module.cpp:5
 // CHECK-DAG: @extern_var_exported = external {{(dso_local )?}}global
-// CHECK-DAG: @inline_var_exported = linkonce_odr {{(dso_local )?}}global
+// CHECK-DAG: @inline_var_exported = available_externally {{(dso_local 
)?}}global
 // CHECK-DAG: @const_var_exported = available_externally {{(dso_local 
)?}}constant i32 3,
----------------
ChuanqiXu wrote:
> urnathan wrote:
> > ChuanqiXu wrote:
> > > dblaikie wrote:
> > > > ChuanqiXu wrote:
> > > > > ChuanqiXu wrote:
> > > > > > urnathan wrote:
> > > > > > > ChuanqiXu wrote:
> > > > > > > > urnathan wrote:
> > > > > > > > > ChuanqiXu wrote:
> > > > > > > > > > urnathan wrote:
> > > > > > > > > > > I don;t think this is correct.  That should still be a 
> > > > > > > > > > > linkonce odr, otherwise you'll get conflicts with other 
> > > > > > > > > > > module implementation units.
> > > > > > > > > > It is still linkonce_odr in the module it get defined. See 
> > > > > > > > > > the new added test case: inline-variable-in-module.cpp for 
> > > > > > > > > > example. The attribute `available_externally` is equivalent 
> > > > > > > > > > to external from the perspective of linker. See 
> > > > > > > > > > https://llvm.org/docs/LangRef.html#linkage-types. According 
> > > > > > > > > > to [dcl.inline]p7, inline variable attached to named module 
> > > > > > > > > > should be defined in that domain. Note that the variable 
> > > > > > > > > > attached to global module fragment and private module 
> > > > > > > > > > fragment shouldn't be accessed outside the module, so it 
> > > > > > > > > > implies that all the variable defined in the module could 
> > > > > > > > > > only be defined in the module unit itself.
> > > > > > > > > There's a couple of issues with this.  module.cppm is 
> > > > > > > > > emitting a (linkonce) definition of inlne_var_exported, but 
> > > > > > > > > only because it itself is ODR-using that variable.  If you 
> > > > > > > > > take out the ODR-use in noninline_exported, there is no 
> > > > > > > > > longer a symbol emitted.
> > > > > > > > > 
> > > > > > > > > But, even if you forced inline vars to be emitted in their 
> > > > > > > > > defining-module's interface unit, that would be an ABI 
> > > > > > > > > change.  inline vars are emitted whereever ODR-used.  They 
> > > > > > > > > have no fixed home TU.  Now, we could alter the ABI and allow 
> > > > > > > > > interface units to define a home location for inline vars and 
> > > > > > > > > similar entities (eg, vtables for keyless classes).  But we'd 
> > > > > > > > > need buy-in from other compilers to do that.
> > > > > > > > > 
> > > > > > > > > FWIW such a discussion did come up early in implementing 
> > > > > > > > > modules-ts, but we decided there was enough going on just 
> > > > > > > > > getting the TS implemented.  I'm fine with revisiting that, 
> > > > > > > > > but it is a more significant change.
> > > > > > > > > 
> > > > > > > > > And it wouldn't apply to (eg) templated variables, which of 
> > > > > > > > > course could be instantiated anywhere.
> > > > > > > > Oh, now the key point here is what the correct behavior is 
> > > > > > > > instead of the patch. Let's discuss it first.
> > > > > > > > 
> > > > > > > > According to [[ http://eel.is/c++draft/dcl.inline#7 | 
> > > > > > > > [dcl.inline]p7 ]], 
> > > > > > > > > If an inline function or variable that is attached to a named 
> > > > > > > > > module is declared in a definition domain, it shall be 
> > > > > > > > > defined in that domain.
> > > > > > > > 
> > > > > > > > I think the intention of the sentence is to define inline 
> > > > > > > > variable in the module interface. So if it is required by the 
> > > > > > > > standard, I think other compiler need to follow up. As I 
> > > > > > > > described in the summary, it might be a difference between 
> > > > > > > > C++20 module and ModuleTS. Do you think it is necessary to send 
> > > > > > > > the question to WG21? (I get the behavior from reading the 
> > > > > > > > words. Maybe I misread or the word is not intentional).
> > > > > > > > 
> > > > > > > > Maybe the ABI standard group need to discuss what the linkage 
> > > > > > > > should be. Now it may be weak_odr or linkonce_odr. It depends 
> > > > > > > > on how we compile the file. If we compile the .cppm file 
> > > > > > > > directly, it would be linkonce_odr. And if we compile it to 
> > > > > > > > *.pcm file first, it would be weak_odr. I have registered an 
> > > > > > > > issue for this: 
> > > > > > > > https://github.com/llvm/llvm-project/issues/53838.
> > > > > > > > Oh, now the key point here is what the correct behavior is 
> > > > > > > > instead of the patch. Let's discuss it first.
> > > > > > > > 
> > > > > > > > According to [[ http://eel.is/c++draft/dcl.inline#7 | 
> > > > > > > > [dcl.inline]p7 ]], 
> > > > > > > > > If an inline function or variable that is attached to a named 
> > > > > > > > > module is declared in a definition domain, it shall be 
> > > > > > > > > defined in that domain.
> > > > > > > > 
> > > > > > > > I think the intention of the sentence is to define inline 
> > > > > > > > variable in the module interface. So if it is required by the 
> > > > > > > > standard, I think other compiler need to follow up. As I 
> > > > > > > > described in the summary, it might be a difference between 
> > > > > > > > C++20 module and ModuleTS. Do you think it is necessary to send 
> > > > > > > > the question to WG21? (I get the behavior from reading the 
> > > > > > > > words. Maybe I misread or the word is not intentional).
> > > > > > > 
> > > > > > > You are reading more into the std than it says.  The std 
> > > > > > > specifies what /source code/ is meaningful.  It says nothing 
> > > > > > > about how a computation system might represent the program in 
> > > > > > > another form.  Most of the latter, for ahead-of-time translation, 
> > > > > > > is at the discretion of compiler implementors.  Part of that is 
> > > > > > > the domain of the ABI, which specifies an interface to which 
> > > > > > > different compilers may target, and then have compatibility at 
> > > > > > > the object-file boundary. 
> > > > > > > 
> > > > > > > > Maybe the ABI standard group need to discuss what the linkage 
> > > > > > > > should be. 
> > > > > > > 
> > > > > > > Correct. And right now there is no consensus to do anything 
> > > > > > > different with such entities.
> > > > > > > The ABI (http://itanium-cxx-abi.github.io/cxx-abi/abi.html) 5.2 
> > > > > > > documents such vague-linkage entities.  That section would need 
> > > > > > > changes to bless what you are trying to do.
> > > > > > > 
> > > > > > > 
> > > > > > > You are reading more into the std than it says. The std specifies 
> > > > > > > what /source code/ is meaningful. It says nothing about how a 
> > > > > > > computation system might represent the program in another form. 
> > > > > > > Most of the latter, for ahead-of-time translation, is at the 
> > > > > > > discretion of compiler implementors. Part of that is the domain 
> > > > > > > of the ABI, which specifies an interface to which different 
> > > > > > > compilers may target, and then have compatibility at the 
> > > > > > > object-file boundary.
> > > > > > 
> > > > > > OK, your words make sense. In fact, I don't care much about whether 
> > > > > > or not could we define `inline variable` in the module unit. The 
> > > > > > problem I tried to solve is about `the definition static variable 
> > > > > > in module`. We couldn't run a simple hello world example if we 
> > > > > > don't solve it.
> > > > > > 
> > > > > > What I care about is where should we define inline function. I want 
> > > > > > to define inline function in the module unit it get declared. And 
> > > > > > my theory comes from [dcl.inline]p7. And our experiments show that 
> > > > > > it is the key reason why module could speed up compilation. Our 
> > > > > > data shows that the compilation could speed up about 40% for the 
> > > > > > feature. Since most of the time consumed in compilation spent on 
> > > > > > the middle end, it is really not significant to save the time in 
> > > > > > frontend. So it matters a lot if we could avoid compiling same 
> > > > > > functions in middle end.
> > > > > > 
> > > > > > Originally, I thought I am doing right. But from your words, we 
> > > > > > couldn't do this until the ABI standard group get in consensus, 
> > > > > > right?
> > > > > > 
> > > > > > Finally, I feel it is odd about [dcl.inline]p7. Since if it is not 
> > > > > > for implementors, I feel it is meaningless for users.
> > > > > Or given that the CXXABI doesn't discuss the case about inline 
> > > > > function in named module. Could we think it is a free space? Another 
> > > > > question maybe where could we ask for opinion? WG21 or Itanium CXXABI 
> > > > > group?
> > > > > Finally, I feel it is odd about [dcl.inline]p7. Since if it is not 
> > > > > for implementors, I feel it is meaningless for users.
> > > > 
> > > > Presumably that means that a user can't declare an inline function in a 
> > > > module, and define it somewhere else (like in a private implementation 
> > > > unit) - they must define it in the same definition domain it is 
> > > > declared. That's a concrete requirement for the user, irrespective of 
> > > > what object-file-level implementation strategy (where the definition 
> > > > gets emitted, what linkage is used, etc) is used.
> > > > Presumably that means that a user can't declare an inline function in a 
> > > > module, and define it somewhere else (like in a private implementation 
> > > > unit) - they must define it in the same definition domain it is 
> > > > declared. That's a concrete requirement for the user, irrespective of 
> > > > what object-file-level implementation strategy (where the definition 
> > > > gets emitted, what linkage is used, etc) is used.
> > > 
> > > Oh, I get it. Thanks.
> > yes, I understand the problem you are trying to solve  (had the same in 
> > GCC).  The issue is with internal-linkage entities in global module 
> > fragments.  Let's consider 3 separate cases.
> > a) the GMF is a header-unit.
> > 
> > 1)  We could either emit it in a header-unit-specific object file (if 
> > ODR-used when building that header unit).  This would surprise users as now 
> > we have a thing that is morally a header-file, but comes with an object 
> > file.  That is likely to break build flow and is not what GCC does.  There 
> > is of course a trade off here, in that it's either emitted exactly once, or 
> > emitted into every TU that ODR uses it.  But is that a significant  extra 
> > burden?  The only variable case I came across was _ioinit.  (There are many 
> > static inline functions, due to C compatibility, but for those you want to 
> > inline them anyway.)
> > 
> > 2) Or we could emit it in every TU that directly or indirectly imports the 
> > header unit and ODR uses the entity.  This is what GCC does.  in the case 
> > of _ioinit that means making sure to call its dynamic constructor from the 
> > TU's initialization function.
> > 
> > 3) Note we do not clone the internal entity within a single TU, once for 
> > each header or module that we import that itself ODR uses the entity.
> > 
> > b) textual inclusion in the GMF of a module.  If the module ODR-uses the 
> > entity, it needs to be emitted into the object file.
> > 
> > c) Both textual inclusion AND importing of a header-unit. We could emit 2 
> > copies, or we could merge these two definitions.  Merging is better (and 
> > what GCC does).
> > 
> > The std allows all the alternatives considered above.  Does that help?
> Thanks for the explanation. It really helps. Since I didn't touch header-unit 
> before (I mainly focus on named module), I don't have an opinion for (a) and 
> (c). For the (b), it might not be the case. I think we need to emit it all 
> the time. Here is the pattern of <iostream> in libstdc++:
> ```
> extern istream cin;
> // ...
> static ios_base::Init __ioinit;
> ``` 
> 
> And after including, `__ioinit` is not used in the module unit, but we 
> couldn't erase it. Otherwise the problem might met segfault. You could find 
> the example in the issue I linked.
> 
> ---
> 
> In fact, I care more about whether or not should we emit `inline` function 
> body in module purview to the module unit. But given that this is not the 
> intention of the patch, let's talk it in other places.
> Thanks for the explanation. It really helps. Since I didn't touch header-unit 
> before (I mainly focus on named module), I don't have an opinion for (a) and 
> (c). For the (b), it might not be the case. I think we need to emit it all 
> the time. Here is the pattern of <iostream> in libstdc++:
> ```
> extern istream cin;
> // ...
> static ios_base::Init __ioinit;
> ``` 
> 
> And after including, `__ioinit` is not used in the module unit, but we 
> couldn't erase it. Otherwise the problem might met segfault. You could find 
> the example in the issue I linked.

Hehe, I remember having to look this up. __ioinit /is/ used, because it has a 
dynamic initializer: [basic.start.dynamic]

there is no need for the compiler to emit unused internal-linkage variables 
with static initialization.


> In fact, I care more about whether or not should we emit `inline` function 
> body in module purview to the module unit. But given that this is not the 
> intention of the patch, let's talk it in other places.

Again, that's ABI.  While we could emit externally-visible out-of-line-bodies 
into the module's object file (and have importers of the module not emit such 
out-of-line bodies as needed), that would require the same ABI change as the 
variable case.  I notice that the ABI 
http://itanium-cxx-abi.github.io/cxx-abi/abi.html#vague speficially coveres 
inline function bodies (5.2.1), but not inline variables, because it was never 
updated when those became a feature.  But inline variables are just like 
keyless vtables, which it does cover, and that's what implementations do.)




CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D119409/new/

https://reviews.llvm.org/D119409

_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to