title: What prevents the usage of a function argument as hidden pointer?
body: <p>I try to understand the implication of <a href="https://stackoverflow.com/questions/18133812/where-is-the-x86-64-system-v-abi-documented">System V AMD64 - ABI's</a> <a href="https://en.wikipedia.org/wiki/X86_calling_conventions#System_V_AMD64_ABI" rel="nofollow noreferrer">calling convention</a> and looking at the following example:</p>
  
  <pre><code>struct Vec3{
      double x, y, z;
  };
  
  struct Vec3 do_something(void);
  
  void use(struct Vec3 * out){
      *out = do_something();
  }
  </code></pre>
  
  <p>A <code>Vec3</code>-variable is of type MEMORY and thus the caller (<code>use</code>) must allocate space for the returned variable and pass it as hidden pointer to the callee (i.e. <code>do_something</code>). Which is what we see in the resulting assembler (<a href="https://godbolt.org/z/DZoeHd" rel="nofollow noreferrer">on godbolt</a>, compiled with <code>-O2</code>):</p>
  
  <pre><code>use:
          pushq   %rbx
          movq    %rdi, %rbx           ;remember out
          subq    $32, %rsp            ;memory for returned object
          movq    %rsp, %rdi           ;hidden pointer to %rdi
          call    do_something
          movdqu  (%rsp), %xmm0        ;copy memory to out
          movq    16(%rsp), %rax
          movups  %xmm0, (%rbx)
          movq    %rax, 16(%rbx)
          addq    $32, %rsp            ;unwind/restore
          popq    %rbx
          ret
  </code></pre>
  
  <p>I understand, that an alias of  pointer <code>out</code> (e.g. as global variable) could be used in <code>do_something</code> and thus <code>out</code> cannot be passed as hidden pointer to <code>do_something</code>: if it would, <code>out</code> would be changed inside of <code>do_something</code> and not when <code>do_something</code> returns, thus some calculations might become faulty. For example this version of <code>do_something</code> would return faulty results:</p>
  
  <pre><code>struct Vec3 global; //initialized somewhere
  struct Vec3 do_something(void){
     struct Vec3 res;
     res.x = 2*global.x; 
     res.y = global.y+global.x; 
     res.z = 0; 
     return res;
  }
  </code></pre>
  
  <p>if <code>out</code> where an alias for the global variable <code>global</code> and were used as hidden pointer passed in <code>%rdi</code>, <code>res</code> were also an alias of <code>global</code>, because the compiler would use the memory pointed to by hidden pointer directly (a kind of RVO in C), without actually creating a temporary object and copying it when returned, then <code>res.y</code> would be <code>2*x+y</code>(if <code>x,y</code> are old values of <code>global</code>) and not <code>x+y</code> as for any other hidden pointer.</p>
  
  <p>It was suggested to me, that using <code>restrict</code> should solve the problem, i.e.</p>
  
  <pre><code>void use(struct Vec3 *restrict out){
      *out = do_something();
  }
  </code></pre>
  
  <p>because now, the compiler knows, that there are no aliases of <code>out</code> which could be used in <code>do_something</code>, so the assembler could be as simple as this:</p>
  
  <pre><code>use:
      jmp     do_something ; %rdi is now the hidden pointer
  </code></pre>
  
  <p>However, this is not the case neither for gcc nor for clang - the assembler stays unchanged (see on <a href="https://godbolt.org/z/kUPFox" rel="nofollow noreferrer">godbolt</a>).</p>
  
  <p>What prevents the usage of <code>out</code> as hidden pointer?</p>
  
  <hr>
  
  <p>NB: The desired (or very similar) behavior would be achieved for a slightly different function-signature:</p>
  
  <pre><code>struct Vec3 use_v2(){
      return do_something();
  }
  </code></pre>
  
  <p>which results in (see on <a href="https://godbolt.org/z/v1ESAZ" rel="nofollow noreferrer">godbolt</a>):</p>
  
  <pre><code>use_v2:
      pushq   %r12
      movq    %rdi, %r12
      call    do_something
      movq    %r12, %rax
      popq    %r12
      ret
  </code></pre>