OSDev.org

The Place to Start for Operating System Developers
It is currently Thu Mar 28, 2024 9:13 am

All times are UTC - 6 hours




Post new topic Reply to topic  [ 9 posts ] 
Author Message
 Post subject: GCC arguments passing and optimizations
PostPosted: Fri Aug 16, 2019 4:26 am 
Offline
Member
Member

Joined: Mon Jun 04, 2018 8:10 am
Posts: 44
Hi, I have a problem with passing arguments to a function.

Here is the function:


Code:
void test(uint32_t a, uint32_t b)
{
   uint32_t *arg = &a;

   for (uint32_t i = 0; i < 4; ++i) {
      printf("%h: %h\n", arg + i, *(arg + i));
   }
}


and the call to that function:
Code:

test(0, 1);



This code is part of my kernel and the stack is setup at 0x20000 when the kernel is loaded. I ran this code with different levels of optimization and here are the outputs:


With O1 or no optimization:
0x0001ffe0: 0x00000000
0x0001ffe4: 0x00000001

Here the second argument is passed correctly.


With O2 or O3 optimization:
0x0001ffec: 0x00000000
0x0001fff0: 0x000025bc

Here the second argument is not passed and 0x25bc is just some random stuff.

It seems that with O2/O3 optimization GCC notices that I am not using the second argument in the function and just does not pass it. The reason I am using the pointer to access arguments is that I further would like to use a variable number of arguments.
Is there any kind of attribute to use on the function or another trick to force GCC to pass arguments even if there are not used? I would of course like to keep optimizations.

Regards


Top
 Profile  
 
 Post subject: Re: GCC arguments passing and optimizations
PostPosted: Fri Aug 16, 2019 4:56 am 
Offline
Member
Member

Joined: Mon Mar 25, 2013 7:01 pm
Posts: 5099
Attempting to access one object from a pointer to another object is undefined behavior.

If you want to pass a variable number of arguments, you can use stdarg.h in your kernel.


Top
 Profile  
 
 Post subject: Re: GCC arguments passing and optimizations
PostPosted: Fri Aug 16, 2019 9:23 am 
Offline
Member
Member

Joined: Wed Aug 30, 2017 8:24 am
Posts: 1593
To expand on Octo's answer: arg points to an array of only one element (namely a). Thus it is not permissible to calculate the pointer "arg + i" for i >= 2, and it is not permissible to dereference that pointer even for i >= 1. You are allowed to calculate the pointer to "one element past the end" of the array, but not to dereference it.

I also find it weird that you only get two lines of output. Should be four lines, according to the program. And "%h" is not a valid format string. I think you mean "%x".

_________________
Carpe diem!


Top
 Profile  
 
 Post subject: Re: GCC arguments passing and optimizations
PostPosted: Sun Aug 18, 2019 4:24 am 
Offline
Member
Member

Joined: Mon Jun 04, 2018 8:10 am
Posts: 44
Hi and thanks for your replies. I get indeed get 4 lines of output but I only wrote 2 in my post as the last two ones were just random numbers and the printf function I use is a printf function I coded myself, that's why I am using "%h" and not "%x".

How can I use a variable number of arguments without using any library then?

Here is what I did for my "printf" function and it works fine...

Code:

extern void printf(const char *format, ...)
{
   uint32_t *curr_arg = (uint32_t *)&format + 1;

   while (*format) {
      // despecialization
      if (*format == '\\') {
         screen_putc(*(++format));
      }

      // special format
      else if (*format == '%') {
         switch (*(++format)) {
            case 'i':
            case 'd':
               printi(*curr_arg++);
               break;

            case 'h':
               printh(*curr_arg++);
               break;

            case 'c':
               screen_putc(*(char *)(curr_arg++));
               break;

            case 's':
               print(*(char **)(curr_arg++));
               break;

            case 'k':
               screen_set_attr(*(uchar_t *)(curr_arg++));
               break;

            default:
               screen_putc('?');
         }
      }

      // normal character
      else {
         screen_putc(*format);
      }

      format++;
   }
}



Why does it work with the printf function and not with my test function?

Regards


Top
 Profile  
 
 Post subject: Re: GCC arguments passing and optimizations
PostPosted: Sun Aug 18, 2019 4:54 am 
Offline
Member
Member
User avatar

Joined: Sat Mar 31, 2012 3:07 am
Posts: 4591
Location: Chichester, UK
LIC wrote:
How can I use a variable number of arguments without using any library then?

"stdarg.h" is a header file, not a library. Why wouldn't you want to use it?


Top
 Profile  
 
 Post subject: Re: GCC arguments passing and optimizations
PostPosted: Sun Aug 18, 2019 4:12 pm 
Offline
Member
Member

Joined: Mon Jun 04, 2018 8:10 am
Posts: 44
Okay, I tried to understand stdarg.h, are variable arguments management built into the compiler?
Also why is my "printf" function working correctly?

Thanks for your replies


Top
 Profile  
 
 Post subject: Re: GCC arguments passing and optimizations
PostPosted: Sun Aug 18, 2019 4:45 pm 
Offline
Member
Member
User avatar

Joined: Thu Nov 16, 2006 12:01 pm
Posts: 7612
Location: Germany
LIC wrote:
Okay, I tried to understand stdarg.h, are variable arguments management built into the compiler?


For x86_64, it is not possible to implement <stdarg.h> functionality with pure C code. The first couple of parameters of a function are passed in registers. So you'll have to rely on the compiler to support you. G++ and clang do this via the following list of builtin functions:

  • __builtin_va_arg( ap, type )
  • __builtin_va_copy( dest, src )
  • __builtin_va_end( ap )
  • __builtin_va_start( ap, parmN )

and the typedef

  • __builtin_va_list

Besides, implementing a function "printf()" (i.e., a function with a name reserved by the standard) and then implementing non-standard behavior (%h) is a very bad idea. If you don't want to stick to the standard (why not?), then please use function names distinct from the ISO/IEC 9899 standard functions ("principle of least surprise").

And finally, have you considered adapting one of the existing standard libraries, instead of rolling your own? No offense intended, but the way you attempted to brute-force your variable argument list through undefined behavior makes me doubt you have the wherewithal to make a homegrown standard library fly. Actually, it's usually best to achieve quite some competence in user space programming before trying to tackle something like printf() (easily one of the most complex functions in the standard), or kernel-space programming...

_________________
Every good solution is obvious once you've found it.


Last edited by Solar on Tue Aug 20, 2019 7:52 am, edited 2 times in total.

Top
 Profile  
 
 Post subject: Re: GCC arguments passing and optimizations
PostPosted: Sun Aug 18, 2019 10:15 pm 
Offline
Member
Member

Joined: Wed Aug 30, 2017 8:24 am
Posts: 1593
LIC wrote:
Here is what I did for my "printf" function and it works fine...
Code:
uint32_t *curr_arg = (uint32_t *)&format + 1;


Well, then you are very lucky indeed. That pointer is invalid. On AMD64, as well as most other archs, the arguments are passed in the registers, so the only way to have their address is for the compiler to spill them to stack. So the address will just be some random stuff somewhere on the stack. So just use va_arg(), please.

To answer your question, it worked because you were lucky, and the precise conditions applied that made it work. But it was fragile, and next compiler release might have already broken it. The likely difference between the working example here and the non-working one you posted first is the ellipsis.

_________________
Carpe diem!


Top
 Profile  
 
 Post subject: Re: GCC arguments passing and optimizations
PostPosted: Tue Aug 20, 2019 3:29 am 
Offline
Member
Member

Joined: Mon Jun 04, 2018 8:10 am
Posts: 44
Ok, thank you for your replies and advice!


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 9 posts ] 

All times are UTC - 6 hours


Who is online

Users browsing this forum: No registered users and 32 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group