]> granicus.if.org Git - clang/commitdiff
XCore target: Add target specific EmitVAArg
authorRobert Lytton <robert@xmos.com>
Mon, 19 Aug 2013 09:46:39 +0000 (09:46 +0000)
committerRobert Lytton <robert@xmos.com>
Mon, 19 Aug 2013 09:46:39 +0000 (09:46 +0000)
This is so aggregates can be passed as var args too.

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

lib/CodeGen/TargetInfo.cpp
test/CodeGen/xcore-abi.c

index bab77e6a45b2957f282827b7bb0973b531854d2c..4b1c56599f4a7ef2311426f286e973b7d2f96a57 100644 (file)
@@ -5370,13 +5370,53 @@ public:
 // Xcore ABI Implementation
 //===----------------------------------------------------------------------===//
 namespace {
+class XCoreABIInfo : public DefaultABIInfo {
+public:
+  XCoreABIInfo(CodeGen::CodeGenTypes &CGT) : DefaultABIInfo(CGT) {}
+  virtual llvm::Value *EmitVAArg(llvm::Value *VAListAddr, QualType Ty,
+                                 CodeGenFunction &CGF) const;
+};
+
 class XcoreTargetCodeGenInfo : public TargetCodeGenInfo {
 public:
   XcoreTargetCodeGenInfo(CodeGenTypes &CGT)
-    :TargetCodeGenInfo(new DefaultABIInfo(CGT)) {}
+    :TargetCodeGenInfo(new XCoreABIInfo(CGT)) {}
 };
 } // end anonymous namespace
 
+llvm::Value *XCoreABIInfo::EmitVAArg(llvm::Value *VAListAddr, QualType Ty,
+                                     CodeGenFunction &CGF) const {
+  ABIArgInfo AI = classifyArgumentType(Ty);
+  CGBuilderTy &Builder = CGF.Builder;
+  llvm::Type *ArgTy = CGT.ConvertType(Ty);
+  if (AI.canHaveCoerceToType() && !AI.getCoerceToType())
+    AI.setCoerceToType(ArgTy);
+
+  // handle the VAList
+  llvm::Value *VAListAddrAsBPP = Builder.CreateBitCast(VAListAddr,
+                                                       CGF.Int8PtrPtrTy);
+  llvm::Value *AP = Builder.CreateLoad(VAListAddrAsBPP);
+  llvm::Value *APN = Builder.CreateConstGEP1_32(AP, 4);
+  Builder.CreateStore(APN, VAListAddrAsBPP);
+
+  // handle the argument
+  llvm::Type *ArgPtrTy = llvm::PointerType::getUnqual(ArgTy);
+  switch (AI.getKind()) {
+  default:
+  case ABIArgInfo::Expand:
+    llvm_unreachable("Unsupported ABI kind for va_arg");
+  case ABIArgInfo::Ignore:
+    return llvm::UndefValue::get(ArgPtrTy);
+  case ABIArgInfo::Extend:
+  case ABIArgInfo::Direct:
+    return Builder.CreatePointerCast(AP, ArgPtrTy);
+  case ABIArgInfo::Indirect:
+    llvm::Value *ArgAddr;
+    ArgAddr = Builder.CreateBitCast(AP, llvm::PointerType::getUnqual(ArgPtrTy));
+    ArgAddr = Builder.CreateLoad(ArgAddr);
+    return Builder.CreatePointerCast(ArgAddr, ArgPtrTy);
+  }
+}
 
 //===----------------------------------------------------------------------===//
 // Driver code
index 6c325262dc8fb5747fe905241c550d48632bff1a..16cf55d170b53126760d61c7840a5e6ea7234618 100644 (file)
@@ -9,22 +9,86 @@ int g1;
 int g2 __attribute__((common));
 
 #include <stdarg.h>
-struct x { int a; };
+struct x { int a[5]; };
+void f(void*);
 void testva (int n, ...) {
+  // CHECK-LABEL: testva
   va_list ap;
+  va_start(ap,n);
   // CHECK: [[AP:%[a-z0-9]+]] = alloca i8*, align 4
+  // CHECK: [[AP1:%[a-z0-9]+]] = bitcast i8** [[AP]] to i8*
+  // CHECK: call void @llvm.va_start(i8* [[AP1]])
 
   char* v1 = va_arg (ap, char*);
-  // CHECK: va_arg i8** [[AP]], i8*
+  f(v1);
+  // CHECK: [[I:%[a-z0-9]+]] = load i8** [[AP]]
+  // CHECK: [[IN:%[a-z0-9]+]] = getelementptr i8* [[I]], i32 4
+  // CHECK: store i8* [[IN]], i8** [[AP]]
+  // CHECK: [[P:%[a-z0-9]+]] = bitcast i8* [[I]] to i8**
+  // CHECK: [[V1:%[a-z0-9]+]] = load i8** [[P]]
+  // CHECK: store i8* [[V1]], i8** [[V:%[a-z0-9]+]], align 4
+  // CHECK: [[V2:%[a-z0-9]+]] = load i8** [[V]], align 4
+  // CHECK: call void @f(i8* [[V2]])
 
-  int v2 = va_arg (ap, int);
-  // CHECK: va_arg i8** [[AP]], i32
+  char v2 = va_arg (ap, char);
+  f(&v2);
+  // CHECK: [[I:%[a-z0-9]+]] = load i8** [[AP]]
+  // CHECK: [[IN:%[a-z0-9]+]] = getelementptr i8* [[I]], i32 4
+  // CHECK: store i8* [[IN]], i8** [[AP]]
+  // CHECK: [[V1:%[a-z0-9]+]] = load i8* [[I]]
+  // CHECK: store i8 [[V1]], i8* [[V:%[a-z0-9]+]], align 1
+  // CHECK: call void @f(i8* [[V]])
 
-  long long int v3 = va_arg (ap, long long int);
-  // CHECK: va_arg i8** [[AP]], i64
+  int v3 = va_arg (ap, int);
+  f(&v3);
+  // CHECK: [[I:%[a-z0-9]+]] = load i8** [[AP]]
+  // CHECK: [[IN:%[a-z0-9]+]] = getelementptr i8* [[I]], i32 4
+  // CHECK: store i8* [[IN]], i8** [[AP]]
+  // CHECK: [[P:%[a-z0-9]+]] = bitcast i8* [[I]] to i32*
+  // CHECK: [[V1:%[a-z0-9]+]] = load i32* [[P]]
+  // CHECK: store i32 [[V1]], i32* [[V:%[a-z0-9]+]], align 4
+  // CHECK: [[V2:%[a-z0-9]+]] = bitcast i32* [[V]] to i8*
+  // CHECK: call void @f(i8* [[V2]])
 
-  //struct x t = va_arg (ap, struct x);
-  //cannot compile aggregate va_arg expressions yet
+  long long int v4 = va_arg (ap, long long int);
+  f(&v4);
+  // CHECK: [[I:%[a-z0-9]+]] = load i8** [[AP]]
+  // CHECK: [[IN:%[a-z0-9]+]] = getelementptr i8* [[I]], i32 4
+  // CHECK: store i8* [[IN]], i8** [[AP]]
+  // CHECK: [[P:%[a-z0-9]+]] = bitcast i8* [[I]] to i64*
+  // CHECK: [[V1:%[a-z0-9]+]] = load i64* [[P]]
+  // CHECK: store i64 [[V1]], i64* [[V:%[a-z0-9]+]], align 8
+  // CHECK:[[V2:%[a-z0-9]+]] = bitcast i64* [[V]] to i8*
+  // CHECK: call void @f(i8* [[V2]])
+
+  struct x v5 = va_arg (ap, struct x);  // typical agregate type
+  f(&v5);
+  // CHECK: [[I:%[a-z0-9]+]] = load i8** [[AP]]
+  // CHECK: [[IN:%[a-z0-9]+]] = getelementptr i8* [[I]], i32 4
+  // CHECK: store i8* [[IN]], i8** [[AP]]
+  // CHECK: [[I2:%[a-z0-9]+]] = bitcast i8* [[I]] to %struct.x**
+  // CHECK: [[P:%[a-z0-9]+]] = load %struct.x** [[I2]]
+  // CHECK: [[V1:%[a-z0-9]+]] = bitcast %struct.x* [[V:%[a-z0-9]+]] to i8*
+  // CHECK: [[P1:%[a-z0-9]+]] = bitcast %struct.x* [[P]] to i8*
+  // CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[V1]], i8* [[P1]], i32 20, i32 4, i1 false)
+  // CHECK: [[V2:%[a-z0-9]+]] = bitcast %struct.x* [[V]] to i8*
+  // CHECK: call void @f(i8* [[V2]])
+
+  int* v6 = va_arg (ap, int[4]);  // an unusual agregate type
+  f(v6);
+  // CHECK: [[I:%[a-z0-9]+]] = load i8** [[AP]]
+  // CHECK: [[IN:%[a-z0-9]+]] = getelementptr i8* [[I]], i32 4
+  // CHECK: store i8* [[IN]], i8** [[AP]]
+  // CHECK: [[I2:%[a-z0-9]+]] = bitcast i8* [[I]] to [4 x i32]**
+  // CHECK: [[P:%[a-z0-9]+]] = load [4 x i32]** [[I2]]
+  // CHECK: [[V1:%[a-z0-9]+]] = bitcast [4 x i32]* [[V0:%[a-z0-9]+]] to i8*
+  // CHECK: [[P1:%[a-z0-9]+]] = bitcast [4 x i32]* [[P]] to i8*
+  // CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[V1]], i8* [[P1]], i32 16, i32 4, i1 false)
+  // CHECK: [[V2:%[a-z0-9]+]] = getelementptr inbounds [4 x i32]* [[V0]], i32 0, i32 0
+  // CHECK: store i32* [[V2]], i32** [[V:%[a-z0-9]+]], align 4
+  // CHECK: [[V3:%[a-z0-9]+]] = load i32** [[V]], align 4
+  // CHECK: [[V4:%[a-z0-9]+]] = bitcast i32* [[V3]] to i8*
+  // CHECK: call void @f(i8* [[V4]])
 }
 
 void testbuiltin (void) {