From 01d8f1c5f2a96277cc9451118fa59416c3d1570d Mon Sep 17 00:00:00 2001 From: Mark Seaborn Date: Wed, 22 Jan 2014 20:11:01 +0000 Subject: [PATCH] Handle va_arg on struct types for the le32 target (PNaCl and Emscripten) PNaCl and Emscripten can both handle va_arg IR instructions with struct type. Also add a test to cover generating a va_arg IR instruction from va_arg in C on le32 (as already handled by VisitVAArgExpr() in CGExprScalar.cpp), which was not covered by a test before. (This fixes https://code.google.com/p/nativeclient/issues/detail?id=2381) Differential Revision: http://llvm-reviews.chandlerc.com/D2539 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@199830 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/CGExprAgg.cpp | 6 +++++- test/CodeGen/le32-vaarg.c | 28 ++++++++++++++++++++++++++++ 2 files changed, 33 insertions(+), 1 deletion(-) create mode 100644 test/CodeGen/le32-vaarg.c diff --git a/lib/CodeGen/CGExprAgg.cpp b/lib/CodeGen/CGExprAgg.cpp index 3395bd7d33..ef56c0b06f 100644 --- a/lib/CodeGen/CGExprAgg.cpp +++ b/lib/CodeGen/CGExprAgg.cpp @@ -935,7 +935,11 @@ void AggExprEmitter::VisitVAArgExpr(VAArgExpr *VE) { llvm::Value *ArgPtr = CGF.EmitVAArg(ArgValue, VE->getType()); if (!ArgPtr) { - CGF.ErrorUnsupported(VE, "aggregate va_arg expression"); + // If EmitVAArg fails, we fall back to the LLVM instruction. + llvm::Value *Val = + Builder.CreateVAArg(ArgValue, CGF.ConvertType(VE->getType())); + if (!Dest.isIgnored()) + Builder.CreateStore(Val, Dest.getAddr()); return; } diff --git a/test/CodeGen/le32-vaarg.c b/test/CodeGen/le32-vaarg.c new file mode 100644 index 0000000000..51bbb02968 --- /dev/null +++ b/test/CodeGen/le32-vaarg.c @@ -0,0 +1,28 @@ +// RUN: %clang_cc1 -triple le32-unknown-nacl -emit-llvm -o - %s | FileCheck %s +#include + +int get_int(va_list *args) { + return va_arg(*args, int); +} +// CHECK: define i32 @get_int +// CHECK: [[RESULT:%[a-z_0-9]+]] = va_arg {{.*}}, i32{{$}} +// CHECK: ret i32 [[RESULT]] + +struct Foo { + int x; +}; + +struct Foo dest; + +void get_struct(va_list *args) { + dest = va_arg(*args, struct Foo); +} +// CHECK: define void @get_struct +// CHECK: [[RESULT:%[a-z_0-9]+]] = va_arg {{.*}}, %struct.Foo{{$}} +// CHECK: store %struct.Foo [[RESULT]], %struct.Foo* @dest + +void skip_struct(va_list *args) { + va_arg(*args, struct Foo); +} +// CHECK: define void @skip_struct +// CHECK: va_arg {{.*}}, %struct.Foo{{$}} -- 2.40.0