diff options
author | Jakob Stoklund Olesen <stoklund@2pi.dk> | 2013-06-05 03:00:18 +0000 |
---|---|---|
committer | Jakob Stoklund Olesen <stoklund@2pi.dk> | 2013-06-05 03:00:18 +0000 |
commit | 303caedd4b41f6dcfa994abfc7dc59d39e6cd346 (patch) | |
tree | 850c3d970aed29491c914e924bbb74662b52d2c5 /clang/test | |
parent | 36af2529ee81efc8fca98ad65a3a9fadc9e6e45e (diff) | |
download | bcm5719-llvm-303caedd4b41f6dcfa994abfc7dc59d39e6cd346.tar.gz bcm5719-llvm-303caedd4b41f6dcfa994abfc7dc59d39e6cd346.zip |
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.
llvm-svn: 183292
Diffstat (limited to 'clang/test')
-rw-r--r-- | clang/test/CodeGen/sparcv9-abi.c | 66 |
1 files changed, 65 insertions, 1 deletions
diff --git a/clang/test/CodeGen/sparcv9-abi.c b/clang/test/CodeGen/sparcv9-abi.c index b58c84689ad..22803a6d4c4 100644 --- a/clang/test/CodeGen/sparcv9-abi.c +++ b/clang/test/CodeGen/sparcv9-abi.c @@ -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; +} |