<div dir="ltr">va_arg of struct types is not implemented in the x86_64 backend:<div><br></div><div><div>  // Decide which area this value should be read from.</div><div>  // TODO: Implement the AMD64 ABI in its entirety. This simple</div>
<div>  // selection mechanism works only for the basic types.</div><div>  if (ArgVT == MVT::f80) {</div><div>    llvm_unreachable("va_arg for f80 not yet implemented");</div><div>  } else if (ArgVT.isFloatingPoint() && ArgSize <= 16 /*bytes*/) {</div>
<div>    ArgMode = 2;  // Argument passed in XMM register. Use fp_offset.</div><div>  } else if (ArgVT.isInteger() && ArgSize <= 32 /*bytes*/) {</div><div>    ArgMode = 1;  // Argument passed in GPR64 register(s). Use gp_offset.</div>
<div>  } else {</div><div>    llvm_unreachable("Unhandled argument type in LowerVAARG");</div><div>  }</div><div><br></div></div><div>So Clang lowers it manually.</div><div><br></div><div>If you only use builtin types such as integers, pointers, floats, and doubles, then va_arg works.</div>
</div><div class="gmail_extra"><br><br><div class="gmail_quote">On Tue, Aug 26, 2014 at 2:36 PM, Ramkumar Ramachandra <span dir="ltr"><<a href="mailto:artagnon@gmail.com" target="_blank">artagnon@gmail.com</a>></span> wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">So I've written out this sample based on what Clang emitted:<br>
<br>
-- 8< --<br>
%struct.__va_list_tag = type { i32, i32, i8*, i8* }<br>
<div class=""><br>
define i32 @test(i32 %X, ...) {<br>
  ; Initialize variable argument processing<br>
</div>  %ap = alloca %struct.__va_list_tag<br>
  %ap2 = bitcast %struct.__va_list_tag* %ap to i8*<br>
  %retptr = alloca i32<br>
<div class="">  call void @llvm.va_start(i8* %ap2)<br>
<br>
  ; Read a single integer argument<br>
</div>  %idxptr = getelementptr inbounds %struct.__va_list_tag* %ap, i32 0, i32 0<br>
  %idx = load i32* %idxptr<br>
  %tmp = getelementptr inbounds %struct.__va_list_tag* %ap, i32 0, i32 3<br>
  %extract = load i8** %tmp<br>
  %rawel = getelementptr i8* %extract, i32 %idx<br>
  %elptr = bitcast i8* %rawel to i32*<br>
  %newidx = add i32 %idx, 8<br>
  store i32 %idx, i32* %idxptr<br>
<br>
  ; Store that argument in el<br>
  %el = load i32* %elptr<br>
  store i32 %el, i32* %retptr<br>
  %ret = load i32* %retptr<br>
<div class=""><br>
  ; Stop processing of arguments.<br>
  call void @llvm.va_end(i8* %ap2)<br>
</div>  ret i32 %ret<br>
<div class="">}<br>
<br>
define i32 @main() {<br>
  %call = call i32 (i32, ...)* @test(i32 1, i32 3)<br>
  ret i32 %call<br>
}<br>
<br>
declare void @llvm.va_start(i8*)<br>
declare void @llvm.va_copy(i8*, i8*)<br>
declare void @llvm.va_end(i8*)<br>
-- 8< --<br>
<br>
</div>Can we include (a neater version of) this in the LangRef? Can it not<br>
be simplified?<br>
<br>
I understand that %struct.__va_list_tag will be different for each<br>
platform, so the user can't gep into the structure in a<br>
platform-independent manner, but what's the problem with this?<br>
<br>
%ap = alloca_va_list<br>
%ap2 = bitcast %struct.__va_list_tag* %ap to i8*<br>
call void @llvm.va_start(i8* %ap2)<br>
va_arg %ap i32<br>
call void @llvm.va_end(i8* %ap2)<br>
<br>
All we need is a sort of global %struct.__va_list_tag, right?<br>
</blockquote></div><br></div>