This is the mail archive of the gcc@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

Re: kernel-2.2.1-undefined references.


>In article <19990212031118.4271.qmail@deer>,  <craig@jcb-sc.com> wrote:
>>
>>The buglet in gcc has, I gather, already been fixed.
>
>Yes. 
>
>The sad part is that the bug was fixed several months ago. It was just
>re-introduced _again_ last week.
>
>>						  I haven't
>>gotten the impression the underlying bug(s) in Linux have, or
>>will, get fixed.
>
>Craig, have you actually bothered to look at the Linux use of "inline"
>at all? I don't think you have, and you're just spouting sh*t on the
>list. 

I realize you think that.  That's because you're rather uninformed,
or intentionally forgetful, about what has really been going on here,
and prefer to insult others than to take responsibility for mistakes
committed (repeatedly) on your end.

>It's not at all buggy, it just assumes that the compiler does something
>reasonable. 

No, it assumes that the compiler does something *some* people consider
reasonable, but others don't, and which is not *documented* by the
compiler to do any particular thing, implementation-wise.

>In particular, there are two kinds of "inline" in the kernel.  There's
>the "oh, I'd like to get this inlined" kind of inline, and there's the
>"consider this a macro" kind of inline. 

In other words, the kernel makes two uses of "inline", one that is
correct, the other that is incorrect.

>Please go and actually look at the sources you complain about.  I'm not
>an unreasonable person, I just get DAMN irritated when the same bug
>shows up twice in gcc, and people have a hard time even admitting it is
>a bug (I think the post by you is the first one that actually calls it a
>"buglet", finally - it's a bug, and yes, it was small, but by golly it
>was HARD to get people to even acknowledge it as one). 

First, I based my comments on what *you* were saying when *you* were
slinging mud at the egcs developers, the decisions they were making,
and the help they were offering you.

If you had wanted us to look at any sources, *you* should have posted
the relevant bits here first, perhaps in place of mud-slinging, which
you continue to prefer to engage in.

>Basically, Linux _does_ already use the "inline as hint" mentality: we
>have tons of functions that are marked "static inline" or just "inline". 
>Some of those functions are quite large, and some of them actually only
>make sense inlining on an alpha or other sane architecture that has tons
>of registers: and I'd be very happy if gcc actually decides at some
>point that "oh, this function just adds too much register pressure to
>make sense to inline on an x86". 

Fine and dandy.

>There's another class of "inline" usage, though - the "use as macro"
>class, because inline functions are often a _lot_ more readable than
>macros are, and you get tons of other advantages (the compiler does the
>argument copy so you don't have side effect problems, and often most
>importantly you get argument type-checking with good error messages with
>inline functions that you wouldn't get with a macro).  Those "use as a
>macro" inlines are marked, for the edification of gcc, as "extern
>inline". 

Which is incorrect, if the code actually *depends* on inlining
actually happening, as the documentation should have made clearer,
but most everyone already knew.

>Guess what? A lot of them _used_ to be "static inline", because "static
>inline" is safer (it works as expected in the presense of the address-of
>operator, and yes, if the compiler refuses to inline the thing because
>it's not optimizing, it will still create the function for you).  Most
>of them were _changed_ to "extern inline" mostly due to the gcc
>documentation.

Mostly due to an *incorrect reading* of the gcc documentation, which
didn't help things.

>So Craig, go and look at some of those "extern inline" functions. 
>Instead of just spouting crap on the mailing list without obvously never
>having even _looked_ at the problem.  All of them are _extremely_
>reasonable as far as I can tell - feel free to look for yourself.

More below on your continuing attack on my efforts to educate you
as to proper use of gcc extensions.

>The ones that were bitten by the egcs bug (let's just be honest and call
>it what it really was)

I have concluded that *you* wouldn't know "honesty" if it bit
you in the ass.  You have lied about this before, and you are
continuing to lie about it now.  egcs not inlining an "extern inline"
function is not, never has been, and never will be a bug.  The
*developers* might consider it a bug, in that they'd prefer some
cases be inlined for performance reasons, but to the user, it is
*never* a bug in the sense of violating the "contract" the compiler
makes with its users, in the form of an explicit language
specification.

In that sense, it's what I call a "buglet", meaning, not necessarily
a high-priority bug -- not a violation of the "contract", or
specification, of how the compiler behaves in terms of implementing
the language it compiles.

In writing the g77 documentation, I tried to make the distinction
between promises made on behalf of the GNU Fortran *language* and
the behavior of the current GNU Fortran *compiler* as clear as I could.

If, as a programmer, I don't see that clear a distinction in a product's
documentation, I assume *fuzziness*.

It's been *your* error that you've assumed that any behavior you observe
and which the gcc documentation doesn't clearly say might change will
therefore be promised for all of eternity.  That's a *very* frequent
error, but rare is the person who insists on insulting those who
try and point it out to him, especially as repeatedly and as nastily
as you've done.

>were so small that it would have been completely
>unreasonable for any good compiler to not inline them.  They were
>essentially two assignments and a copy, they just happened to have the
>address-of-label thing in some debugging code (because all other gcc
>methods of getting the current PC have been buggy at various points). 

The only reasons it should have mattered to you that inlining did
not happen are that you didn't get the performance you want, or
the generated code was actually wrong.  Neither was the case.  Therefore,
if the overall result was that *your* code broke, it was not *egcs*
that broke it -- it was a change to egcs that triggered a long-hidden
bug in your code.  Please stop saying things like "this change broke
egcs", as that's a lie.

>Basically, Craig, just come down from your ivory tower and look at the
>code, and I'd be surprised if you didn't agree with me that Linux
>"extern inline" usage actually makes sense if you were to just spend a
>_small_ amount of time actually looking at it instead of spouting off
>without knowing what's up.

Okay, Linus, now that you've *totally* destroyed any and all credibility
you've *ever* had with me, and converted me from promoting your
abilities, and Linux, to friends and neighbors to warning them away
from anything you touch, I'll enclose a copy of some emails sent *six
months* ago on a closely-related issue.

I want you to read these emails *very* carefully, and then come back and
explain exactly how you still believe I'm simply up in an "ivory tower",
have never had a "look" at code *you* have not (to my knowledge)
offered here, and how I should still agree that Linux' use of
"extern inline" as "guarantee me inlining" makes sense.

(For *other* readers, who *are* allowed to not bother reading the
emails quoted below: the summary is, this problem came up before,
was specified as being related to Linux, and was *thoroughly* and
*completely* explained as being the result of a combination of
poorly-specified extensions, inadequate documentation, and Linux'
inappropriate reliance on the behavior of extensions.  Further,
viable alternatives were proposed.  Apparently that did no good
then, though I'm willing to take the blame for not fixing the
gcc docs myself, and there is plenty of reason to assume all this
verbage will do no good now.)

        tq vm, (burley)

P.S. Yes, folks, I realize that Linus almost certainly won't bother
actually reading the below, as he's already cast my posts on this
topic as "silly" and so on.  I'm writing all this for the public
record, basically: I want it clearly on record that Linux developers
(which I assume included David Miller, involved in the emails below)
were *warned* about this problem, told to change their code and
how to properly read the documentation *months* ago, that Linus
himself continually and repeatedly ignores the same advice given
now and insists on continuing to tell the lie that egcs is the
source of the problem.  It does *not* matter to me whether Linus
ever "gets" it, all things considered.


>Date: Tue, 28 Jul 1998 11:36:27 -0400 (EDT)
>From: Craig Burley <burley@gnu.org>
>To: davem@dm.cobaltmicro.com
>CC: kenner@vlsi1.ultra.nyu.edu, egcs-patches@cygnus.com, gcc2@cygnus.com,
>        rth@cygnus.com
>Cc: burley@gnu.org
>In-reply-to: <199807281242.FAA31050@dm.cobaltmicro.com>
>	(davem@dm.cobaltmicro.com)
>Subject: Re: inline functions and local labels
>
>>   Date: Tue, 28 Jul 98 08:36:39 EDT
>>   From: kenner@vlsi1.ultra.nyu.edu (Richard Kenner)
>>
>>   Inlining tells the compiler "for efficiency reasons, I'd like you to
>>   do your best to inline this function", not "even if you do it wrong, I'd 
>>   like you to inline it".
>>
>>Then what does "extern inline" say?
>
>It says "if you can inline this function, great, but even if you can't,
>don't compile it as a separate function".  E.g. if you compile without
>optimization, it doesn't get inlined.
>
>>Forget for a moment what you know about C and compiler implementation
>>details, and all of the issues surrounding this topic.  And pretend
>>for a moment you are a programmer using GNU C to accomplish some task
>>and you wish to express something, and you find that GNU C allows you
>>to express this by saying:
>>
>>extern __inline__ check_a(int a)
>>{
>>	__label__ here;
>>
>>	if(my_test(a) != 0)
>>		printf("Assertion on 'a' failed at %p\n", &here);
>
>(I think that should be `, &&here'.)
>
>>&&here:
>
>(I think that should be "here:".)
>
>>}
>>
>>Can you tell me that this does not seem like a useful construct or
>>feature?  Can you also tell me that this is hard for the person
>>writing such code to understand?  Which behavior of the above function
>>do you deem would be correct in any case?
>
>I'm confused -- what are the choices?  I've already tried to construct
>an example showing the differences, and can't do so without resorting
>to bogosities like having some external code somehow depend upon
>the uniqueness, or value, of labels passed to it as `void *' arguments.
>(See below for an example.)
>
>>It depends, for standard C constructs, I can understand this
>>completely.  For GNU C extensions, we can say whatever we like about
>>semantics wrt. inline functions, and in fact document them.
>
>I think we should first figure out whether the proposed semantics
>make good linguistic sense in the first place.  When I first looked
>into this as a result of this discussion, I *thought* there were some
>very interesting issues here, but so far all I can find is places
>in the gcc docs where we could do a better job clarifying stuff
>most programmers would regard as "natural" for them (and perhaps
>in disagreement with each other).
>
>>This issue is different from most others, because it is an issue of
>>semantics when two different GNU C extensions are used together, so we
>>can define the semantics any way we wish to in such cases.  I contend
>>that the current behavior makes the most sense and is the most useful
>>for users of GNU C (the fact that this behavior has been in known
>>active use for 4 or 5 years is a testament to this!).
>
>I'm still confused as to what the current behavior *is* that is
>being depended upon.
>
>My *guess* is that the current behavior is to try and inline functions,
>which is not always done.  That's what the docs say (especially if you
>read carefully, and between the lines -- they could stand improving
>though).
>
>What exactly *breaks* when code like the examples you post aren't
>actually inlined by gcc?  If it's just that you get unresolved
>references to the externals, well, that's what is *supposed* to happen,
>based on my reading of what `extern inline' means in gcc.
>
>If it's just that when the code doesn't get inlined, the application
>(Linux?) goes slower, well, that's not a linguistic or semantic
>issue -- even if the decision revolves around whether a construct
>like `&&foo' is present.
>
>If that's the case, then it's just a matter of the application no
>longer using `&&foo', or teaching gcc to change that decision again
>(but only when it's safe to do so, to preserve the semantics of
>the function), or teaching gcc a new construct meaning "*inline* this,
>dammit!", such as __force_inline__.  Programmers would be responsible
>for any code-generation bugs resulting from their combining this
>specification with features gcc normally would detect as "I can't
>safely inline this".
>
>
>As far as how hard it is to tell what labels should really "mean",
>here's a contrived example:
>
>#include <stdio.h>
>
>void *
>f (void *arg)
>{
>  static void *x = NULL;
>  void *y;
>
>  if (x == NULL)
>    {
>      x = arg;
>      return arg;
>    }
>
>  y = x;
>  x = arg;
>  return y;
>}
>
>inline int
>myjump ()
>{
>  __label__ bar;
>  void *f();
>  void *foo;
>  static int myval = 1;
>
>  foo = f(&&bar);
>  goto *foo;
>
>bar:
>  return myval++;
>}
>
>int
>main()
>{
>  int i;
>  int j;
>  int k;
>
>  i = myjump();
>  j = myjump();
>  k = myjump();
>  printf ("%d %d %d\n", i, j, k);
>  return 0;
>}
>
>Compiled using gcc 2.8.1 or egcs, without optimization, it prints
>"1 2 3", but with enough optimization to cause inlining, it prints
>"2 4 5" on my RH 4.2 Linux system, probably because the label
>feature is being abused (which gcc doesn't detect, but it does
>print "interesting" warnings about `i' and `j' when inlining, so
>perhaps it could detect this?).
>
>So, depending on the nature of code labels, vis-a-vis whether they're
>static a la variables, or static on a per-copy-of-function basis, seems
>to be unwise.  Even though the gcc docs don't seem to explicitly disallow
>such use, they don't allow it either, and wise programmers wouldn't
>depend on such behavior.  (Not only does the code above not work,
>but neither would depending on the equality of a `void *'-passed label
>determining whether the calling function was the same as some previous
>caller, or some such thing, be wise.)
>
>I suggest we revise the gcc docs regarding labels to clarify that
>any addresses of labels taken within a function during its invocation
>become invalid as soon as the function returns, just as is the case
>for passing `&a' given `int a;' within a function.
>
>We probably also should specify that comparing labels as addresses is
>not a reliable way to determine whether they refer to the same, or
>different, addresses.  That is, &&foo and &&bar, even within a single
>function invocation with foo and bar being labels on different chunks
>of code, could evaluate to equal (gcc could place the generated code
>in the same place in memory, and use state info to disambiguate the
>code at run time), and perhaps even &&foo and another &&foo could
>yield different addresses within the same function (gcc could "flatten"
>programmer-visible state info into distinct code sequences, as long
>as it preserves the correctness of "goto *label;" following each
>corresponding "label = &&foo;").
>
>I think it's okay to allow passing &&label to another procedure, though,
>as long as the lifetime of that argument is the calling function
>invocation's lifetime, and the only use of the argument is to return
>the value back to the function or to print it out (or otherwise make
>it available) for debugging/logging purposes.
>
>Also, perhaps we should clarify the text on "inline" so readers know
>it is never safe to depend on inlining of any given function always
>happening.  It's already said, but perhaps not clearly enough --
>some of the verbage seems to suggest otherwise in a few places, and
>not everyone reads the entire description before jumping to
>conclusions.
>
>In summary, I haven't seen any clear description of the semantic
>lossage being complained about, and can only guess that the problem
>is that gcc has decided to stop inlining something it used to inline,
>which is not great, but not a semantic problem, just an optimization
>issue that bare-to-the-metal coders must deal with on an ongoing
>basis.  (To wit: if these functions hadn't *previously* been inlined
>due to their using &&foo, would the programmers have nevertheless
>used that feature, and given up the inlining, or given up &&foo?
>Either way, that's what they *can* do now, although ideally they
>shouldn't be made to choose.  And they can macro-ize their way out
>of relying on &&foo, if they like.)
>
>I do wonder if a "pointer to `here'" feature might be useful in
>place of what I gather is a kludge to get some kind of pointer
>useful for debugging, logging, and so on.  Perhaps `&& .' or
>`&& __label_here__' or similar could be reserved for that purpose,
>and be valid *only* as a `void *' that can be copied, printed, written
>to a file, etc., but not as the target of a `goto *x;' or any
>other pointer-like operation (++, +, -, ==, unary *, etc.).
>
>        tq vm, (burley)


>Date: Tue, 28 Jul 1998 20:00:13 -0700
>From: "David S. Miller" <davem@dm.cobaltmicro.com>
>To: burley@gnu.org
>CC: kenner@vlsi1.ultra.nyu.edu, egcs-patches@cygnus.com, gcc2@cygnus.com,
>        rth@cygnus.com, burley@gnu.org
>In-reply-to: <199807281536.LAA11100@melange.gnu.org> (message from Craig
>	Burley on Tue, 28 Jul 1998 11:36:27 -0400 (EDT))
>Subject: Re: inline functions and local labels
>References:  <199807281536.LAA11100@melange.gnu.org>
>
>   Date: Tue, 28 Jul 1998 11:36:27 -0400 (EDT)
>   From: Craig Burley <burley@gnu.org>
>
>   I'm confused -- what are the choices?  I've already tried to
>   construct an example showing the differences, and can't do so
>   without resorting to bogosities like having some external code
>   somehow depend upon the uniqueness, or value, of labels passed to
>   it as `void *' arguments.  (See below for an example.)
>
>Craig, I apologize, I should have posted the code which behaves
>differently if not inlined (due to kenners patch) so that the behavior
>issue in question is more clear.  There is a performance concern, but
>this is secondary compared to the loss in functionality change:
>
>extern __inline__ unsigned char *skb_put(struct sk_buff *skb, unsigned int len)
>{
>	unsigned char *tmp=skb->tail;
>	skb->tail+=len;
>	skb->len+=len;
>	if(skb->tail>skb->end)
>	{
>		__label__ here; 
>		skb_over_panic(skb, len, &&here); 
>here:		;
>	}
>	return tmp;
>}
>
>We use this for debugging, and the debugging information becomes
>useless if the procedure is not inlined.
>
>Later,
>David S. Miller
>davem@dm.cobaltmicro.com


>Date: Wed, 29 Jul 1998 12:33:49 -0400 (EDT)
>From: Craig Burley <burley@gnu.org>
>To: davem@dm.cobaltmicro.com
>CC: kenner@vlsi1.ultra.nyu.edu, egcs-patches@cygnus.com, gcc2@cygnus.com,
>        rth@cygnus.com
>Cc: burley@gnu.org
>In-reply-to: <199807290300.UAA05668@dm.cobaltmicro.com>
>	(davem@dm.cobaltmicro.com)
>Subject: Re: inline functions and local labels
>
>>Craig, I apologize, I should have posted the code which behaves
>>differently if not inlined (due to kenners patch) so that the behavior
>>issue in question is more clear.  There is a performance concern, but
>>this is secondary compared to the loss in functionality change:
>[...]
>>We use this for debugging, and the debugging information becomes
>>useless if the procedure is not inlined.
>
>Ah, I think I get it now.
>
>What you *want* is to "dump" the address of the caller's reference
>to the current function, so the ability to quickly localize the
>cause of the problem is improved somewhat.
>
>What you're *using* to get this is something different, which sometimes
>amounts to the same thing (e.g. when the code is inlined), but
>sometimes doesn't (e.g. when it isn't).
>
>A new notation added to gcc might be handy here (a notation that
>would basically be of roughly the same class as __PRETTY_FUNCTION__,
>though it'd involve lower-level code-gen issues than that).
>
>But it seems to me it'd be more worthwhile to consider implementing
>a general way to print a limited stack backtrace, which is an issue
>outside the language definition, and would require less cruft in
>your code overall.
>
>        tq vm, (burley)


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]