[LLVMdev] Named register variables GNU-style

Renato Golin
2014-03-27T20:15:45Z

On 27 March 2014 19:35, Krzysztof Parzyszek <kparzysz at codeaurora.org>
wrote:
> Is there any sane reason to actually implement it?

Bare metal code is never sane, but that's not an excuse not to write
it. C is a very complete language, especially modern variations like
C11, but there's still a lot that can't be done in C and for good
reasons. Kernel code and optimal libraries can stretch the compiler a
lot more than user code, and often enough, there's simply no way to
represent ideas in C. One of these examples is unwind code.

Then you ask...

> Are there any cases when inline asm would work well enough?

Well, assembly is very powerful and so, but it's also very hard to
understand what's going on. Inline assembly is an extension to the
language, and because of that, different compilers implement them in
different ways. Most of GCC's implementation is hidden in layers upon
layers of legacy code that not many people dare to touch, but that
compiles code that can't stop being compiled, nor easily migrated (for
technical and legal reasons).

The interaction between inline assembly and C is, therefore, not easy
to implement, and it's even harder to get it "right" (ie. similar
to
the "other" compiler). The most you could write in C the better for
*compilers*, and minimising the exposure by using register variables
is actually not a bad idea.

But mostly, the __builtin_stack_frame is, in essence, a special case
of the generic pattern of named registers, and gives us the same level
of guarantees, so, in the end, there isn't much *technical* difference
in doing one and the other, with the added benefit that named
registers are already widely used and you won't need to add ifdefs for
new compilers.


> We have the
> __builtin_stack_pointer now, which is somewhat questionable[1], however
this
> should not serve a precedent to implement further "extensions"
like this.

No we don't. Not yet. ;)

I was about to commit when I thought I should get a point of view from
all sides, including (and especially) GCC.

The first issue here is that, if GCC doesn't "buy in", having a
__builtin_stack_pointer in Clang is as good as not having it.

The second issue is that, if we're going to implement an extension,
and there is already a technically equivalent solution in existence,
there's no reason to create a different one.

Lastly, and (much) more importantly, their technical arguments were
significantly better than mine.


> Argument against it..? "Why?"

Why? Because the less asm and more C code we have, the better. Because
inline asm semantics is a lot more obtuse than named registers.
Because builtins are just special cases of named registers. Because
target-independence is not possible in that kind of code.

Some arguments...

** With builtins, we don't need ifdefs, if all compilers implement it.
-- Yes, we do, for old compilers (GCC and Clang), and kernel/glibc
will need it for decades to come

** Builtins make the code target-intependent
-- No they don't, only the register part. The rest of the code
surrounding is highly target-specific. That's because you only need
that level of detail on code that is very target specific. That kind
of code is normally in separate files.

** Builtins remove the need for named registers
-- No they don't. glibc uses other registers for special purpose code.

** Builtins would work on all targets
-- No they won't. What do you do in targets that the compiler doesn't
implement the builtin because there is no equivalent of a stack
pointer?

Other arguments in favour of named registers:

-- Without this extension, it is e.g. hard to force some input or output
arguments of inline asm into specific machine registers, the only other way
is to use constraints, but most targets don't have constraints for every
specific register

-- The guarantees that a builtin would give us are very little more
than the ones by
named registers, and not enough value to justify the implementation of
yet-another
extension that other compilers won't implement.

You see, I'm not a big fan of extensions, nor I think we should
blindly follow GCC on whatever they do, but in this particular case,
we don't have a strong enough case to make. Even taking the legacy
argument off the table, the technical arguments comparing named
registers and specially crafted builtins are still in favour of named
registers, at least IMHO.

cheers,
--renato