]> granicus.if.org Git - clang/commitdiff
Handle va_arg on struct types for the le32 target (PNaCl and Emscripten)
authorMark Seaborn <mseaborn@chromium.org>
Wed, 22 Jan 2014 20:11:01 +0000 (20:11 +0000)
committerMark Seaborn <mseaborn@chromium.org>
Wed, 22 Jan 2014 20:11:01 +0000 (20:11 +0000)
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
test/CodeGen/le32-vaarg.c [new file with mode: 0644]

index 3395bd7d33b03a2c475a50c7b3b8faf9815839f9..ef56c0b06f2e2bdf1f7da1c6957e2ee500343f50 100644 (file)
@@ -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 (file)
index 0000000..51bbb02
--- /dev/null
@@ -0,0 +1,28 @@
+// RUN: %clang_cc1 -triple le32-unknown-nacl -emit-llvm -o - %s | FileCheck %s
+#include <stdarg.h>
+
+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{{$}}