Re: [PATCH 0/4] -ffreestanding/-fno-builtin-* patches

From: Linus Torvalds
Date: Fri Aug 21 2020 - 13:55:22 EST


On Fri, Aug 21, 2020 at 10:29 AM Arvind Sankar <nivedita@xxxxxxxxxxxx> wrote:
>
> The no-builtin- options _don't_ disable
> __builtin_ functions. They remove the default definition of foo() as
> __builtin_foo().

Oh, ok, then it's fine.

> Take the problem that instigated this thread. __builtin_stpcpy() doesn't
> work in the kernel because the fallback, stpcpy(), isn't implemented.

Right.

The only problem is the - bogus - recognition of (or rewriting of)
code patterns that the compiler recohnmizes.

__builtin_stpcpy() itself is fine if somebody wants to use it - and
has the fallback.

But implicitly recognizing some code sequence and turning it into
something else is the problem.

> This is why I'm saying clang's no-builtin-foo option is useful for
> embedded: it doesn't prevent the programmer using __builtin_foo(), it
> prevents the _compiler_ using __builtin_foo() on its own.

And that's fine. But it's apparently not what gcc does.

> > So this is things like the compiler silently seeing "oh, you called
> > your function 'free()', so we know that the stores you did to it are
> > dead and we'll remove them".
> >
> > Or this is the compiler doing "Oh, you did four stores of zero in a
> > row, and and you asked for size optimizations, so we'll turn those
> > into a 'bzero()' call".
>
> This one is slightly different from the previous one. The first case is
> really a call to __builtin_free().

No, the first case is a disgrace and a compiler bug.

We've had a situation where gcc complained about a static function
called "free()", without any header file inclusion, and then
complained about it not matching its idea of what "free()" is.

Which is pure and utter garbage.

It's like you have a local variable "int free", and the compiler says
"hey, this doesn't match the prototype that I know this name should
have". It's BS. You just saw the user not just *use* that name, but
*define* it, and do it in a scope where the complaint is irrelevant
and stupid, and when we hadn't even included the header that would
have resulted in conflicts.

IOW, it's an example of a compiler that thinks "it knows better".

It's a broken compiler. And it's an example of the kind of breakage
that compilers absolutely shouldn't do.

The second example is from clang doesn't something horribly horribly stupid.

> This one is turning something that wasn't a function call into
> __builtin_bzero(), and I would hope that no-builtin-bzero would stop it
> as well. OTOH, the compiler is free to turn it into memset(), just like
> it could for structure/array initializers.

The whole "the compiler is free to do X" argument is pure BS. Stop
repeating that bogus argument.

Of COURSE a compiler can do whatever the hell it wants.

That doesn't change the fact that certain things are broken beyond
words and utterly stupid, and a compiler that does them is a *BAD*
compiler.

Turning four stores into a memset() is garbage. Just admit it, instead
of trying to say that it's allowed.

Technically a compiler can decode to simply not compile the kernel at
all, because we do things that are outside a lot of standards.

So the "technically allowed" is not an argument.

Linus