Page 1 of 2

Size of function arguments

Posted: Wed Jun 12, 2013 11:55 pm
by BMW
Is it a good idea to make arguments of a function 32 bits even if it only needs an 8-bit number? Because it will still take the same amount of space on the stack, and the CPU has to waste time padding the argument with zeros if you use a 1-byte argument as opposed to a 4-byte argument.

Or would the compiler do this for you anyway?

BTW I am talking about an OS running in 32-bit mode.

Re: Size of function arguments

Posted: Thu Jun 13, 2013 1:19 am
by Combuster
Well, the only thing you end up doing is lying to the compiler about the actual types of your arguments, which makes it harder for you to diagnose bugs. You're not going to save on instruction counts.

Re: Size of function arguments

Posted: Thu Jun 13, 2013 1:55 am
by iansjack
Why would the compiler have to waste time padding the argument? It can just use the 8-bit push immediate instruction or the movsx instruction if not an immediate value.

Re: Size of function arguments

Posted: Thu Jun 13, 2013 2:15 am
by AJ
HI,

In addition to the above responses, if you use the correct types as function arguments then you leave the compiler free to optimise where possible.

Cheers,
Adam

Re: Size of function arguments

Posted: Thu Jun 13, 2013 8:16 am
by Gigasoft
Unused locations between the parameters are undefined and not required to be zero. Therefore, no zero extension is needed.

Re: Size of function arguments

Posted: Thu Jun 13, 2013 11:15 am
by bluemoon
BMW wrote:Is it a good idea to make arguments of a function 32 bits even if it only needs an 8-bit number?
Declare your variable with standard int type unless it is required to be an exact N-bit number, on these case use fixed-width integers, and pass it to function without lying (casting).

Re: Size of function arguments

Posted: Sat Jun 15, 2013 12:46 am
by Mikemk
bluemoon wrote:Declare your variable with standard int type unless it is required to be an exact N-bit number.
This is such bad advise, I don't even know where to start. [-X

The exact length fields are their in order to ensure an exact length (duh), increasing portability to other platforms (not so duh). If a program uses different field sizes on different platforms, then there are quite a few more bugs to fix when porting to a new platform.
Besides, it's just general good practice to use clear code rather than vague trash.

Code: Select all

#include <stdint.h>
int32_t pagemap
is far clearer than

Code: Select all

#include <limits.h>
#if INT_MAX==2147483647
int pagemap
#elif LONG_MAX==2147483647
long pagemap
#else
long long pagemap // let's hope this is four bytes!
#endif
BMW wrote:Is it a good idea to make arguments of a function 32 bits even if it only needs an 8-bit number? Because it will still take the same amount of space on the stack, and the CPU has to waste time padding the argument with zeros if you use a 1-byte argument as opposed to a 4-byte argument.
CPU performance wise, yes. It's also easier to interface with assembly. However, it uses more ram, and as others have said, results in less optimized code.
Or would the compiler do this for you anyway?
It depends on the compiler. I believe gcc does (correct me if I'm wrong), other compilers might not.
BTW I am talking about an OS running in 32-bit mode.
I would hope so.

Re: Size of function arguments

Posted: Sat Jun 15, 2013 1:34 am
by FallenAvatar
m12 wrote:...
please read what others have said before you reply. However in response to your "answer", just no. Flat out wrong in so many ways. Please learn what you are talking about before you lead others astray.
m12 wrote:
bluemoon wrote: BTW I am talking about an OS running in 32-bit mode.
I would hope so.
And why would you hope that? 32-bit is very VERY old news at this point, not necessarily for hobbyist OS Dev, but why would you hope so? That's yet another misleading comment...

- Monk

Re: Size of function arguments

Posted: Sat Jun 15, 2013 1:52 am
by Mikemk
tjmonk15 wrote:
m12 wrote:
bluemoon wrote: BTW I am talking about an OS running in 32-bit mode.
I would hope so.
And why would you hope that? 32-bit is very VERY old news at this point, not necessarily for hobbyist OS Dev, but why would you hope so? That's yet another misleading comment...
The OP is about padding arguments to 32 bits to save processor time padding them to 32 bits. I would hope that this is being done on a 32-bit processor, otherwise it's somewhat pointless.

Re: Size of function arguments

Posted: Sat Jun 15, 2013 3:48 am
by bluemoon
m12 wrote:
bluemoon wrote:Declare your variable with standard int type unless it is required to be an exact N-bit number.
This is such bad advise, I don't even know where to start. [-X
For example, a function that take a counter N as parameter and print N *, you would do

Code: Select all

int print_star(int count);
Now if you make a design choice that impose artificial limitation like count < 256, and do this:

Code: Select all

int print_star(uint8_t count);
Let's see the consequence:
When calling print_star with:

Code: Select all

print_star(num);
1. num must be the type of uint8_t, or you'll get conversion warning
2. the compiler may generate 8-bit instruction(if available in architecture), but this wouldn't save instruction count. Also, 8 bit instruction would not run faster than 32-bit instruction.
3. the compiler push full 32-bit on stack anyway
4. it get worst when the type is uint16_t

In the above case, it's just easier to maintain, and out-weight any optimization gain (if any):

Code: Select all

int print_star(int count) {
  if ( count >= 256 ) return -1;
  ...
}
So, if you don't care the parameter width, just use the native integer.
You normally would care the width only on a serializer.

Re: Size of function arguments

Posted: Sat Jun 15, 2013 5:22 am
by Griwes
m12 wrote:
bluemoon wrote:Declare your variable with standard int type unless it is required to be an exact N-bit number.
This is such bad advise, I don't even know where to start. [-X
D'oh.
The exact length fields are their in order to ensure an exact length (duh), increasing portability to other platforms (not so duh).
D'oh.

`uintXX_t` and `intXX_t` are not portable. Go grep the C and C++ standards for them, they are optional - they obviously will be available on all sane platforms (using 8 bit bytes), but they are still less portable than anything else.
If a program uses different field sizes on different platforms, then there are quite a few more bugs to fix when porting to a new platform.
If you have serious bugs related to integer size (and I do mean serious), then your code is broken. Every type has defined the required range; you generally just use the one that fits (well, I personally do not follow this one, but since I am not expecting my code to be executed on 7 or 9 or 10 or whatever-bit machines, I am fine with lack of portability).
Besides, it's just general good practice to use clear code rather than vague trash.

Code: Select all

#include <stdint.h>
int32_t pagemap
is far clearer than

Code: Select all

#include <limits.h>
#if INT_MAX==2147483647
int pagemap
#elif LONG_MAX==2147483647
long pagemap
#else
long long pagemap // let's hope this is four bytes!
#endif
WTF is this shite. This is hardware dependent piece of variable, which must be 32 bit long, so you use uint32_t. Seems you've mistaken "not overuse fixed width integers" with "never use fixed width integers", which is just plain retarded.

I think bluemoon already addressed the rest of bullshit in that post.

Re: Size of function arguments

Posted: Sat Jun 15, 2013 5:35 am
by sortie
Griwes wrote:
m12 wrote:
bluemoon wrote:Declare your variable with standard int type unless it is required to be an exact N-bit number.
This is such bad advise, I don't even know where to start. [-X
D'oh.
The exact length fields are their in order to ensure an exact length (duh), increasing portability to other platforms (not so duh).
D'oh.

`uintXX_t` and `intXX_t` are not portable. Go grep the C and C++ standards for them, they are optional - they obviously will be available on all sane platforms (using 8 bit bytes), but they are still less portable than anything else.
Don't worry about portability to other platforms when doing operating systems development. You are writing that other platform! If you demand the compiler provide stdint.h, then you are in your right to make that part of your system API. (Unless you want to want parts of your OS on another OS, but that's kinda a special case regardless.)

You guys are likely micro-optimizing. I recommend looking at the function and its domain and then selecting suitable data types from that. For instance, a function that accepts a buffer should get a pointer and a size_t, unless there is any built-in limits in what the function does that means an unsigned int or a signed int will do. There is only no reason to artificially limit the domain of the function (the input must not be higher than some value) unless it would main the function much easier to write and maintain.

Re: Size of function arguments

Posted: Sat Jun 15, 2013 6:02 am
by bluemoon
sortie wrote:Don't worry about portability to other platforms when doing operating systems development. You are writing that other platform!
You realized many of us targeting multi-platform (e.g. i386 and x86_64, or even ARM)?
If coded carefully, 90%+ code-base of a kernel is platform/architecture independent.

While writing portability code is not a requirement (in case you decided to lock yourself onto one specific platform), it however make your code look more elegant.

Re: Size of function arguments

Posted: Sat Jun 15, 2013 6:10 am
by Griwes
sortie wrote:Don't worry about portability to other platforms when doing operating systems development. You are writing that other platform! If you demand the compiler provide stdint.h, then you are in your right to make that part of your system API. (Unless you want to want parts of your OS on another OS, but that's kinda a special case regardless.)
1) This was posted in general programming, assume this is a general thread.
2) stdint.h is required since C99, cstdint is required since C++11; I call every environment not providing either of them utterly broken and outdated.
3) As I said, (u)intXX_t is *not* portable, not because stdint may not exist, but because it is optional.
You guys are likely micro-optimizing. I recommend looking at the function and its domain and then selecting suitable data types from that. For instance, a function that accepts a buffer should get a pointer and a size_t, unless there is any built-in limits in what the function does that means an unsigned int or a signed int will do. There is only no reason to artificially limit the domain of the function (the input must not be higher than some value) unless it would main the function much easier to write and maintain.
Not agreed. Always choose whichever type fits semantically. If the value will never be higher than 255, just use uint8_t - you know, that's why C++ uses sane data type for characters - char - and why C's "'a' is an int!" is broken.

Those differences will be most probably optimized out anyway.

Re: Size of function arguments

Posted: Sat Jun 15, 2013 7:24 am
by sortie
bluemoon wrote:
sortie wrote:Don't worry about portability to other platforms when doing operating systems development. You are writing that other platform!
You realized many of us targeting multi-platform (e.g. i386 and x86_64, or even ARM)?
If coded carefully, 90%+ code-base of a kernel is platform/architecture independent.

While writing portability code is not a requirement (in case you decided to lock yourself onto one specific platform), it however make your code look more elegant.
I'm sorry, I shouldn't post in the forums before breakfast. My point is that you get to choose the API and ABI when you write an operating system. For that reason it's useless to think too much about "What if <stdfoo.h> isn't available?" or "What if the compiler doesn't support feature X?" or "What if the calling conventions are totally weird and complicated?" - because you get to choose the answer to those questions by defining the API and ABI. You should figure out what you want in your programming environment and embrace that, rather than worrying that if you port your 'ls' program to NetBSD for <whatever-weird-cpu> from 1997, then it won't work because of <silly-reason>. It's important to be architecture-independent for maintenance reasons, but it's perfectly good to build in assumptions in your OS if you do this as a conscious decision. The same thing applies to programs where it is okay to be non-portable if it eases maintenance and the non-portable assumptions in the program isn't too bad.
Griwes wrote:Not agreed. Always choose whichever type fits semantically. If the value will never be higher than 255, just use uint8_t - you know, that's why C++ uses sane data type for characters - char - and why C's "'a' is an int!" is broken.

Those differences will be most probably optimized out anyway.
Exactly my point, we agree. :-) I must've poorly phrased the part you responded to.
Griwes wrote:This was posted in general programming, assume this is a general thread.
Whoops, I missed that. Sorry.