]> granicus.if.org Git - clang/commitdiff
[mips] Defer va_arg expansion to the backend.
authorDaniel Sanders <daniel.sanders@imgtec.com>
Fri, 1 Aug 2014 10:29:21 +0000 (10:29 +0000)
committerDaniel Sanders <daniel.sanders@imgtec.com>
Fri, 1 Aug 2014 10:29:21 +0000 (10:29 +0000)
Summary:
This patch causes clang to emit va_arg instructions to the backend instead of
expanding them into an implementation itself. The backend already implements
va_arg since this is necessary for NaCl so this patch is removing redundant
code.

Together with the llvm patch (D4556) that accounts for the effect of endianness
on the expansion of va_arg, this fixes PR19612.

Depends on D4556

Reviewers: sstankovic, dsanders

Reviewed By: dsanders

Subscribers: rnk, cfe-commits

Differential Revision: http://reviews.llvm.org/D4742

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@214497 91177308-0d34-0410-b5e6-96231b3b80d8

lib/CodeGen/TargetInfo.cpp
test/CodeGen/mips-vaarg.c [new file with mode: 0644]

index ca99ba580a57ff5766964d039874d4f2c460a0f0..3870f72487d9ff811748e58242057d1bc5af2e02 100644 (file)
@@ -5560,39 +5560,7 @@ void MipsABIInfo::computeInfo(CGFunctionInfo &FI) const {
 
 llvm::Value* MipsABIInfo::EmitVAArg(llvm::Value *VAListAddr, QualType Ty,
                                     CodeGenFunction &CGF) const {
-  llvm::Type *BP = CGF.Int8PtrTy;
-  llvm::Type *BPP = CGF.Int8PtrPtrTy;
-  CGBuilderTy &Builder = CGF.Builder;
-  llvm::Value *VAListAddrAsBPP = Builder.CreateBitCast(VAListAddr, BPP, "ap");
-  llvm::Value *Addr = Builder.CreateLoad(VAListAddrAsBPP, "ap.cur");
-  int64_t TypeAlign = getContext().getTypeAlign(Ty) / 8;
-  llvm::Type *PTy = llvm::PointerType::getUnqual(CGF.ConvertType(Ty));
-  llvm::Value *AddrTyped;
-  unsigned PtrWidth = getTarget().getPointerWidth(0);
-  llvm::IntegerType *IntTy = (PtrWidth == 32) ? CGF.Int32Ty : CGF.Int64Ty;
-
-  if (TypeAlign > MinABIStackAlignInBytes) {
-    llvm::Value *AddrAsInt = CGF.Builder.CreatePtrToInt(Addr, IntTy);
-    llvm::Value *Inc = llvm::ConstantInt::get(IntTy, TypeAlign - 1);
-    llvm::Value *Mask = llvm::ConstantInt::get(IntTy, -TypeAlign);
-    llvm::Value *Add = CGF.Builder.CreateAdd(AddrAsInt, Inc);
-    llvm::Value *And = CGF.Builder.CreateAnd(Add, Mask);
-    AddrTyped = CGF.Builder.CreateIntToPtr(And, PTy);
-  }
-  else
-    AddrTyped = Builder.CreateBitCast(Addr, PTy);  
-
-  llvm::Value *AlignedAddr = Builder.CreateBitCast(AddrTyped, BP);
-  TypeAlign = std::max((unsigned)TypeAlign, MinABIStackAlignInBytes);
-  uint64_t Offset =
-    llvm::RoundUpToAlignment(CGF.getContext().getTypeSize(Ty) / 8, TypeAlign);
-  llvm::Value *NextAddr =
-    Builder.CreateGEP(AlignedAddr, llvm::ConstantInt::get(IntTy, Offset),
-                      "ap.next");
-  Builder.CreateStore(NextAddr, VAListAddrAsBPP);
-  
-  return AddrTyped;
+  return nullptr;
 }
 
 bool
diff --git a/test/CodeGen/mips-vaarg.c b/test/CodeGen/mips-vaarg.c
new file mode 100644 (file)
index 0000000..f685ed8
--- /dev/null
@@ -0,0 +1,29 @@
+// RUN: %clang -target mips-unknown-linux     -S -o - -emit-llvm %s | FileCheck --check-prefix=ALL --check-prefix=O32 %s
+// RUN: %clang -target mipsel-unknown-linux   -S -o - -emit-llvm %s | FileCheck --check-prefix=ALL --check-prefix=O32 %s
+// RUN: %clang -target mips64-unknown-linux   -S -o - -emit-llvm %s -mabi=n32 | FileCheck --check-prefix=ALL --check-prefix=N32 %s
+// RUN: %clang -target mips64el-unknown-linux -S -o - -emit-llvm %s -mabi=n32 | FileCheck --check-prefix=ALL --check-prefix=N32 %s
+// RUN: %clang -target mips64-unknown-linux   -S -o - -emit-llvm %s -mabi=64  | FileCheck --check-prefix=ALL --check-prefix=N64 %s
+// RUN: %clang -target mips64el-unknown-linux -S -o - -emit-llvm %s -mabi=64  | FileCheck --check-prefix=ALL --check-prefix=N64 %s
+
+int foo (int a, ...)
+{
+    // ALL-LABEL: define i32 @foo(i32 %a, ...)
+
+    __builtin_va_list va;
+    // O32: %va = alloca i8*, align 4
+    // N32: %va = alloca i8*, align 4
+    // N64: %va = alloca i8*, align 8
+
+    __builtin_va_start (va, a);
+    // ALL: %va1 = bitcast i8** %va to i8*
+    // ALL: call void @llvm.va_start(i8* %va1)
+
+    int n = __builtin_va_arg (va, int);
+    // ALL: %{{[0-9]+}} = va_arg i8** %va, i32
+    
+    __builtin_va_end (va);
+    // ALL: %va2 = bitcast i8** %va to i8*
+    // ALL: call void @llvm.va_end(i8* %va2)
+
+    return n;
+}