Page 2 of 3

Re: better registers representation in C?

Posted: Mon Aug 01, 2011 5:54 am
by Solar
Love4Boobies wrote:
XenOS wrote:I'm really not too worried about portability across different compilers. I decided to use GCC for my project just because it fits my needs and it targets a lot of different architectures.
And what if you someday wish to port it to some architecture that GCC doesn't support but other compilers do? There are plenty of useful things that GCC can't output, such as EFI Byte Code (not that you'd want to port your OS to EFI, I'm just pointing out that GCC's not perfect).
Or what if GCC changes its internals? Doesn't happen too often, but it has happened before. Writing "unsigned int" carries no information that you had any specific size in mind. Relying on it having a specific size is relying on unspecified behaviour. It doesn't crash your app as certainly as de-referencing an uninitialized pointer, but it is perfectly allowed to. 8) And the poor sod who comes after you in maintaining your code has to deduce what you meant by "unsigned int" from the rest of the code...

Re: better registers representation in C?

Posted: Mon Aug 01, 2011 9:30 am
by Fanael
Solar wrote:Relying on it having a specific size is relying on unspecified behaviour. It doesn't crash your app as certainly as de-referencing an uninitialized pointer, but it is perfectly allowed to. 8)
No, it's not, because it's unspecified (C99, 3.4.4/1 says "[...] behavior where this International Standard provides two or more possibilities and imposes no further requirements on which is chosen in any instance"), not undefined (anything can happen).

Re: better registers representation in C?

Posted: Mon Aug 01, 2011 9:41 am
by Love4Boobies
Fix your tags, I didn't say that :) Also, you basically agree with what Solar was trying to say (i.e., that it's a bug but still legal), except you misinterpreted him.

Re: better registers representation in C?

Posted: Mon Aug 01, 2011 9:55 am
by xenos
Love4Boobies wrote:Freestanding C++03 (with or without TR1) implementations must provide fewer headers: <cstddef>, <limits>, <cstdlib> (see Combuster's comments), <new>, <typeinfo>, <exception>, and <cstdarg>. Perhaps passing -std=c++0x fixes things; I don't know how complete GCC's C++0x support is.
I already tried -std=c++0x before, but unfortunately it didn't change anything. It seems that I need to install (a freestanding version of) libstdc++-v3 along with my cross compiler. At least the libstdc++-v3 docs suggest that I should configure my cross compiler with "--disable-hosted-libstdcxx" and run "make all-target-libstdc++-v3 install-target-libstdc++-v3". However, even though this make command intends to install only the freestanding headers, it nevertheless tries to build the complete hosted library, which of course fails. I could not find a suitable workaround yet.
And what if you someday wish to port it to some architecture that GCC doesn't support but other compilers do? There are plenty of useful things that GCC can't output, such as EFI Byte Code (not that you'd want to port your OS to EFI, I'm just pointing out that GCC's not perfect).
In that case I'd have to port all the architecture dependent code to the new architecture in a way that the new compiler understands. Well, since it's a completely different and new architecture, "porting" here really means that I need to write completely new code anyway - I cannot "port" x86 CPU startup code to ARM. So it really doesn't matter to me what the existing architecture dependent code looks like - I won't reuse it for the new architecture.

But of course the architecture independent code (such as scheduler / memory manager algorithms, process and thread management...) must be ported, and this part of my kernel is indeed written completely in C++ without any architecture or compiler dependent stuff, inline assembly or whatever.
Learning calling conventions wasn't my point. My point was that changing the ABI at some point (e.g., by passing some argument to your compiler) can cause subtle bugs regardless of how you wish to write your assembly, in case inline assembly created some false sense of security. But I take it that wasn't it...
Good point.
Solar wrote:Or what if GCC changes its internals? Doesn't happen too often, but it has happened before. Writing "unsigned int" carries no information that you had any specific size in mind. Relying on it having a specific size is relying on unspecified behaviour. It doesn't crash your app as certainly as de-referencing an uninitialized pointer, but it is perfectly allowed to. 8) And the poor sod who comes after you in maintaining your code has to deduce what you meant by "unsigned int" from the rest of the code...
I totally agree with you. That's why I intend to change all those nasty "unsigned int"s to "uint32_t"s as soon as I managed to properly integrate the freestanding C++0x headers into my cross compiler toolchain :)

Re: better registers representation in C?

Posted: Mon Aug 01, 2011 10:32 am
by Love4Boobies
XenOS wrote:
Love4Boobies wrote:Freestanding C++03 (with or without TR1) implementations must provide fewer headers: <cstddef>, <limits>, <cstdlib> (see Combuster's comments), <new>, <typeinfo>, <exception>, and <cstdarg>. Perhaps passing -std=c++0x fixes things; I don't know how complete GCC's C++0x support is.
I already tried -std=c++0x before, but unfortunately it didn't change anything. It seems that I need to install (a freestanding version of) libstdc++-v3 along with my cross compiler. At least the libstdc++-v3 docs suggest that I should configure my cross compiler with "--disable-hosted-libstdcxx" and run "make all-target-libstdc++-v3 install-target-libstdc++-v3". However, even though this make command intends to install only the freestanding headers, it nevertheless tries to build the complete hosted library, which of course fails. I could not find a suitable workaround yet.
Maybe that will work, maybe it won't. Or maybe the code just isn't there yet. Perhaps someone with more knowledge of GCC can help you here.
XenOS wrote:
And what if you someday wish to port it to some architecture that GCC doesn't support but other compilers do? There are plenty of useful things that GCC can't output, such as EFI Byte Code (not that you'd want to port your OS to EFI, I'm just pointing out that GCC's not perfect).
In that case I'd have to port all the architecture dependent code to the new architecture in a way that the new compiler understands. Well, since it's a completely different and new architecture, "porting" here really means that I need to write completely new code anyway - I cannot "port" x86 CPU startup code to ARM. So it really doesn't matter to me what the existing architecture dependent code looks like - I won't reuse it for the new architecture.
That's the thing---with proper coding standards and design, a lot of the seemingly unportable code can actually become portable. The secret is to come up with good abstractions and use those in the code shared between architectures. Since you've mentioned bootstrap code, check out GRUB's source code; a lot of the code is common to all supported architectures. In the scenario we were talking about, having all sorts of compiler-specific things in the code will make it much harder to port the code.

Anyway, while I agree that this little rant doesn't apply to (inline) assembly, new architectures isn't the only reason for switching compilers---that was merely an example. Other examples: compiler X is better at optimizing, the compiler's vendor stopped developing your compiler, etc.

Re: better registers representation in C?

Posted: Mon Aug 01, 2011 11:22 am
by Owen
Love4Boobies wrote:
XenOS wrote:
Using inline assembly is dangerous because it ties your code to a single compiler---you don't really want that.
Of course this is true. However, I'm really not too worried about portability across different compilers. I decided to use GCC for my project just because it fits my needs and it targets a lot of different architectures.
And what if you someday wish to port it to some architecture that GCC doesn't support but other compilers do? There are plenty of useful things that GCC can't output, such as EFI Byte Code (not that you'd want to port your OS to EFI, I'm just pointing out that GCC's not perfect).
You're changing architecture. Your inline assembly is useless anyway!

Re: better registers representation in C?

Posted: Mon Aug 01, 2011 11:58 am
by Love4Boobies
Owen wrote:You're changing architecture. Your inline assembly is useless anyway!
I guess you didn't read everything? Happens to me too :lol:
Love4Boobies wrote:Anyway, while I agree that this little rant doesn't apply to (inline) assembly, new architectures isn't the only reason for switching compilers---that was merely an example. Other examples: compiler X is better at optimizing, the compiler's vendor stopped developing your compiler, etc.

Re: better registers representation in C?

Posted: Mon Aug 01, 2011 12:34 pm
by Fanael
Love4Boobies wrote:Fix your tags, I didn't say that :)
Oh well. Sorry for that.
Love4Boobies wrote:Also, you basically agree with what Solar was trying to say (i.e., that it's a bug but still legal), except you misinterpreted him.
Darn it. English (or German, or French, or any other natural language) is so ambiguous :P

Re: better registers representation in C?

Posted: Sun Sep 04, 2011 1:44 pm
by miker00lz
this reminds me of the old Borland Turbo C++ 3.0 compiler. it had an excellent way to work with registers, treating them as 16 or 8 bit variables.

for example _AX, _AH, _AL, _DI, _ES, _FLAGS, etc... i wish Borland were still around, they made the best compilers overall back in the day. imo, anyway.

Re: better registers representation in C?

Posted: Sun Sep 04, 2011 3:14 pm
by Owen
GCC/Clang:

Code: Select all

    register uint64_t myVariable asm("rax");

Re: better registers representation in C?

Posted: Sun Sep 04, 2011 3:29 pm
by Love4Boobies
Note that the register keyword isn't required to actually store variables in registers---in fact, good compilers will ignore this optimization hint and use more optimal register allocation. The real usefulness of this keyword comes from the fact that it stops people from dereferencing things that shouldn't be dereferenced.

Re: better registers representation in C?

Posted: Sun Sep 04, 2011 3:59 pm
by Owen
In the case of the GCC extension I just mentioned, it is required to disambiguate:

Code: Select all

// At global scope
int myVar asm("..."); // A
register int myVar asm("..."); // B
A specifies a global variable allocated in memory with the specified name, which will be identical to that if the symbol was defined as an assembler label. The second says "myVar is an alias for the specified register." The second must be used with care, and exists to enable better optimization of interpreters.

[This disambiguation is of course not necessary for local variables, but maintains consistent syntax. Also note that this extension could be useful as an optimized implementation of something like <iohw.h>]

Re: better registers representation in C?

Posted: Sun Sep 04, 2011 4:05 pm
by Love4Boobies
Owen wrote:The second must be used with care, and exists to enable better optimization of interpreters.
Which interpreters? GCC doesn't have any C interpreter...
Owen wrote:Also note that this extension could be useful as an optimized implementation of something like <iohw.h>]
Could you elaborate?

Re: better registers representation in C?

Posted: Sun Sep 04, 2011 4:22 pm
by Owen
Love4Boobies wrote:
Owen wrote:The second must be used with care, and exists to enable better optimization of interpreters.
Which interpreters? GCC doesn't have any C interpreter...
Who said GCC had an interpreter? I said it was to enable better optimization of interpreters in general.
Owen wrote:Also note that this extension could be useful as an optimized implementation of something like <iohw.h>]
Could you elaborate?
It does occur to me that it wouldn't be useful for my original thought. That said, it is useful on some embedded systems, and for fast system call implementations (particularly on architectures like ARM and AMD64 where not all the registers are cleanly exposed to the inline assembly syntax).

Re: better registers representation in C?

Posted: Sun Sep 04, 2011 7:39 pm
by Love4Boobies
Owen wrote:
Love4Boobies wrote:
Owen wrote:The second must be used with care, and exists to enable better optimization of interpreters.
Which interpreters? GCC doesn't have any C interpreter...
Who said GCC had an interpreter? I said it was to enable better optimization of interpreters in general.
Not sure how valid a reason to adding a compiler extension that is. I maintain my original position that the only reason for which C programmers would have direct access to registers is a poor register allocator in the compiler.