r183292 - Implement SparcV9ABIInfo::EmitVAArg.
Jakob Stoklund Olesen
stoklund at 2pi.dk
Tue Jun 4 20:00:18 PDT 2013
Author: stoklund
Date: Tue Jun 4 22:00:18 2013
New Revision: 183292
URL: http://llvm.org/viewvc/llvm-project?rev=183292&view=rev
Log:
Implement SparcV9ABIInfo::EmitVAArg.
This could actually be implemented with the LLVM IR va_arg instruction,
but it doesn't seem to offer any advantages over accessing the va_list
pointer directly.
Using the va_list pointer directly makes it possible to perform type
coercion directly from the argument array, and the va_list updates are
exposed to the optimizers.
Modified:
cfe/trunk/lib/CodeGen/TargetInfo.cpp
cfe/trunk/test/CodeGen/sparcv9-abi.c
Modified: cfe/trunk/lib/CodeGen/TargetInfo.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/TargetInfo.cpp?rev=183292&r1=183291&r2=183292&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/TargetInfo.cpp (original)
+++ cfe/trunk/lib/CodeGen/TargetInfo.cpp Tue Jun 4 22:00:18 2013
@@ -5332,8 +5332,52 @@ SparcV9ABIInfo::classifyType(QualType Ty
llvm::Value *SparcV9ABIInfo::EmitVAArg(llvm::Value *VAListAddr, QualType Ty,
CodeGenFunction &CGF) const {
- // FIXME: Implement with va_arg.
- return 0;
+ ABIArgInfo AI = classifyType(Ty, 16 * 8);
+ llvm::Type *ArgTy = CGT.ConvertType(Ty);
+ if (AI.canHaveCoerceToType() && !AI.getCoerceToType())
+ AI.setCoerceToType(ArgTy);
+
+ 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");
+ llvm::Type *ArgPtrTy = llvm::PointerType::getUnqual(ArgTy);
+ llvm::Value *ArgAddr;
+ unsigned Stride;
+
+ switch (AI.getKind()) {
+ case ABIArgInfo::Expand:
+ llvm_unreachable("Unsupported ABI kind for va_arg");
+
+ case ABIArgInfo::Extend:
+ Stride = 8;
+ ArgAddr = Builder
+ .CreateConstGEP1_32(Addr, 8 - getDataLayout().getTypeAllocSize(ArgTy),
+ "extend");
+ break;
+
+ case ABIArgInfo::Direct:
+ Stride = getDataLayout().getTypeAllocSize(AI.getCoerceToType());
+ ArgAddr = Addr;
+ break;
+
+ case ABIArgInfo::Indirect:
+ Stride = 8;
+ ArgAddr = Builder.CreateBitCast(Addr,
+ llvm::PointerType::getUnqual(ArgPtrTy),
+ "indirect");
+ ArgAddr = Builder.CreateLoad(ArgAddr, "indirect.arg");
+ break;
+
+ case ABIArgInfo::Ignore:
+ return llvm::UndefValue::get(ArgPtrTy);
+ }
+
+ // Update VAList.
+ Addr = Builder.CreateConstGEP1_32(Addr, Stride, "ap.next");
+ Builder.CreateStore(Addr, VAListAddrAsBPP);
+
+ return Builder.CreatePointerCast(ArgAddr, ArgPtrTy, "arg.addr");
}
void SparcV9ABIInfo::computeInfo(CGFunctionInfo &FI) const {
Modified: cfe/trunk/test/CodeGen/sparcv9-abi.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/sparcv9-abi.c?rev=183292&r1=183291&r2=183292&view=diff
==============================================================================
--- cfe/trunk/test/CodeGen/sparcv9-abi.c (original)
+++ cfe/trunk/test/CodeGen/sparcv9-abi.c Tue Jun 4 22:00:18 2013
@@ -1,4 +1,5 @@
-// RUN: %clang_cc1 -triple sparcv9-unknown-linux -emit-llvm %s -o - | FileCheck %s
+// RUN: %clang_cc1 -triple sparcv9-unknown-unknown -emit-llvm %s -o - | FileCheck %s
+#include <stdarg.h>
// CHECK: define void @f_void()
void f_void(void) {}
@@ -115,3 +116,66 @@ void call_tiny() {
struct tiny x = { 1 };
f_tiny(x);
}
+
+// CHECK: define signext i32 @f_variable(i8* %f, ...)
+// CHECK: %ap = alloca i8*
+// CHECK: call void @llvm.va_start
+//
+int f_variable(char *f, ...) {
+ int s = 0;
+ char c;
+ va_list ap;
+ va_start(ap, f);
+ while ((c = *f++)) switch (c) {
+
+// CHECK: %[[CUR:[^ ]+]] = load i8** %ap
+// CHECK-DAG: %[[NXT:[^ ]+]] = getelementptr i8* %[[CUR]], i32 8
+// CHECK-DAG: store i8* %[[NXT]], i8** %ap
+// CHECK-DAG: %[[EXT:[^ ]+]] = getelementptr i8* %[[CUR]], i32 4
+// CHECK-DAG: %[[ADR:[^ ]+]] = bitcast i8* %[[EXT]] to i32*
+// CHECK-DAG: load i32* %[[ADR]]
+// CHECK: br
+ case 'i':
+ s += va_arg(ap, int);
+ break;
+
+// CHECK: %[[CUR:[^ ]+]] = load i8** %ap
+// CHECK-DAG: %[[NXT:[^ ]+]] = getelementptr i8* %[[CUR]], i32 8
+// CHECK-DAG: store i8* %[[NXT]], i8** %ap
+// CHECK-DAG: %[[ADR:[^ ]+]] = bitcast i8* %[[CUR]] to i64*
+// CHECK-DAG: load i64* %[[ADR]]
+// CHECK: br
+ case 'l':
+ s += va_arg(ap, long);
+ break;
+
+// CHECK: %[[CUR:[^ ]+]] = load i8** %ap
+// CHECK-DAG: %[[NXT:[^ ]+]] = getelementptr i8* %[[CUR]], i32 8
+// CHECK-DAG: store i8* %[[NXT]], i8** %ap
+// CHECK-DAG: %[[ADR:[^ ]+]] = bitcast i8* %[[CUR]] to %struct.tiny*
+// CHECK: br
+ case 't':
+ s += va_arg(ap, struct tiny).a;
+ break;
+
+// CHECK: %[[CUR:[^ ]+]] = load i8** %ap
+// CHECK-DAG: %[[NXT:[^ ]+]] = getelementptr i8* %[[CUR]], i32 16
+// CHECK-DAG: store i8* %[[NXT]], i8** %ap
+// CHECK-DAG: %[[ADR:[^ ]+]] = bitcast i8* %[[CUR]] to %struct.small*
+// CHECK: br
+ case 's':
+ s += *va_arg(ap, struct small).a;
+ break;
+
+// CHECK: %[[CUR:[^ ]+]] = load i8** %ap
+// CHECK-DAG: %[[NXT:[^ ]+]] = getelementptr i8* %[[CUR]], i32 8
+// CHECK-DAG: store i8* %[[NXT]], i8** %ap
+// CHECK-DAG: %[[IND:[^ ]+]] = bitcast i8* %[[CUR]] to %struct.medium**
+// CHECK-DAG: %[[ADR:[^ ]+]] = load %struct.medium** %[[IND]]
+// CHECK: br
+ case 'm':
+ s += *va_arg(ap, struct medium).a;
+ break;
+ }
+ return s;
+}
More information about the cfe-commits
mailing list