Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
As a beginning OS developer, I face a dilemma:
should I exploit GCC's features, or should I do things by hand?
Examples:
using builtins such as __SIZE_TYPE__, __INT32_TYPE__, __INT32_MAX__ etc. instead of old fashioned typedefs and numeric constants in base 16
using builtins such as __builtin_va_list and family, instead of #define'ing the macros oneself
to use or not to use GCC'isms such as __attribute__((packed))
I know everyone has their own needs, and will do things their own way (including myself), but I'd like to read cons and pros for "targeting a compiler", to help me make an early decision. Thanks.
Your OS should not use builtins, your C library should. Headers like <limits.h> and <stdarg.h> provide proper, standard-compliant wrapping of such features, so they shouldn't leak into mainline OS code.
With GCC, even a freestanding cross-compiler build provides these headers, so you can use them even without a C library in place. Much preferable.
Personally, I would shun even __attribute__((packed)) in code, and rather use -fpack-struct on the command line. Keeps the code itself compiler-independent, and easier to read.
Every good solution is obvious once you've found it.
Solar wrote:Look into ${PREFIX}/lib/gcc/${TARGET}/${VERSION}/include. Since the freestanding environmen does not include any executable code, but only definitions and macros depending on the compiler / target machine anyway, GCC provides these "for free".
So if one wanted to use them, would this be the right way? Otherwise copy/link those headers?
There is nothing to link, as those headers are (by definition) typedefs / macros only. They might even be in the standard include path, but as -nostdinc forbids GCC to search that, the explicit stating of the directory would be necessary. (You want the GCC headers, but you don't want /usr/include...)
Every good solution is obvious once you've found it.
Civillian wrote:[*]using builtins such as __SIZE_TYPE__, __INT32_TYPE__, __INT32_MAX__ etc. instead of old fashioned typedefs and numeric constants in base 16
I suggest to use compiler's header. As problems stated in previous thread.
Civillian wrote:[*]using builtins such as __builtin_va_list and family, instead of #define'ing the macros oneself
I would avoid va_list in kernel space, it seems convenient at first, but you cannot verify number of parameters and do type-check that way.
bluemoon wrote:I would avoid va_list in kernel space, it seems convenient at first, but you cannot verify number of parameters and do type-check that way.
Not necessarily bad per se. Just don't do it with any kind of userspace input...
Every good solution is obvious once you've found it.
Solar wrote:They might even be in the standard include path, but as -nostdinc forbids GCC to search that, the explicit stating of the directory would be necessary. (You want the GCC headers, but you don't want /usr/include...)
bluemoon wrote:I suggest to use compiler's header.
... and indeed it works. Now a minor problem is that I have this in the Makefile:
The alternative would be to get rid of -nostdinc while making sure it doesn't drag in /usr/include. Some trial & error should do the trick. Don't forget to addyour findings to the tutorial.
Every good solution is obvious once you've found it.
From what I read the implicit -isysroot would be /usr/include, so it makes sense to change it.
Next, using -ffreestandingwithout-nostdinc will allow GCC to search its freestanding headers directory.
Thanks for the inspiration Solar, this turned out cleaner than I thought.
Solar wrote:The alternative would be to get rid of -nostdinc while making sure it doesn't drag in /usr/include. Some trial & error should do the trick. Don't forget to addyour findings to the tutorial.
The better alternative is to use "-nostdlibinc" instead of -nostdinc, which keeps the compiler headers on the path but removes the C library headers.
Personally, I would shun even __attribute__((packed)) in code, and rather use -fpack-struct on the command line. Keeps the code itself compiler-independent, and easier to read.
But breaks platform PCS compliance. It will only run correctly on x86 as it will inadvertently pack all your structs, not just the ones you need packed for device interaction. So it'd cause unaligned accesses on platforms like ARM.
That's why I personally would mark every struct you need packed manually, as packed.
Personally, I would shun even __attribute__((packed)) in code, and rather use -fpack-struct on the command line.
It will only run correctly on x86 as it will inadvertently pack all your structs, not just the ones you need packed for device interaction. So it'd cause unaligned accesses on platforms like ARM.
I admit I never worked on the ARM, so I am ignorant of its alignment requirements. But wouldn't it suffice to design any such structs with padding in mind (i.e., descending order of datatype sizes)?
Every good solution is obvious once you've found it.
Personally, I would shun even __attribute__((packed)) in code, and rather use -fpack-struct on the command line.
It will only run correctly on x86 as it will inadvertently pack all your structs, not just the ones you need packed for device interaction. So it'd cause unaligned accesses on platforms like ARM.
I admit I never worked on the ARM, so I am ignorant of its alignment requirements. But wouldn't it suffice to design any such structs with padding in mind (i.e., descending order of datatype sizes)?
You're still second-guessing a procedure call standard, which (a) exists for a reason and (b) may be changed/adherance quality altered in a revision of the compiler.
JamesM wrote:That's why I personally would mark every struct you need packed manually, as packed.
The problem is that there's no portable way to do that, (even with defines thanks to pragma pack).
Then again, packed structs are only valid for architecture-specific code and portability is not an issue. If you need them on the second best candidate - files - you stink for not dealing with endianness.
"Certainly avoid yourself. He is a newbie and might not realize it. You'll hate his code deeply a few years down the road." - Sortie
[ My OS ] [ VDisk/SFS ]