diff options
Diffstat (limited to 'test/Feature')
-rw-r--r-- | test/Feature/VarArgAlignment.c | 118 |
1 files changed, 118 insertions, 0 deletions
diff --git a/test/Feature/VarArgAlignment.c b/test/Feature/VarArgAlignment.c new file mode 100644 index 00000000..a048336f --- /dev/null +++ b/test/Feature/VarArgAlignment.c @@ -0,0 +1,118 @@ +/* This test is for the alignment of variadic arguments. In + particular, on x86 arguments > 8 bytes (long double arguments in + test1) should be 16-byte aligned, unless they are passed byval with + specified alignment */ + +// RUN: %clang %s -emit-llvm %O0opt -c -g -o %t1.bc +// RUN: rm -rf %t.klee-out +// RUN: %klee --exit-on-error --output-dir=%t.klee-out %t1.bc | FileCheck %s + +#include <stdarg.h> +#include <assert.h> +#include <stdio.h> + +void test1(int x, ...) { + va_list ap; + va_start(ap, x); + int i1 = va_arg(ap, int); + int i2 = va_arg(ap, int); + int i3 = va_arg(ap, int); + printf("i1, i2, i3: %d, %d, %d\n", i1, i2, i3); + // CHECK: i1, i2, i3: 1, 2, 3 + + long long int l1 = va_arg(ap, long long int); + printf("l1: %lld\n", l1); + // CHECK: l1: 4 + + int i4 = va_arg(ap, int); + printf("i4: %d\n", i4); + // CHECK: i4: 5 + + long double ld1 = va_arg(ap, long double); + printf("ld1: %Lf\n", ld1); + // CHECK: ld1: 6.000000 + + long double ld2 = va_arg(ap, long double); + printf("ld2: %Lf\n", ld2); + // CHECK: ld2: 7.000000 + + + va_end(ap); +} + +struct mix { + long long int first; + char second; +}; + + +void test2(int x, ...) { + va_list ap; + va_start(ap, x); + int i1 = va_arg(ap, int); + int i2 = va_arg(ap, int); + int i3 = va_arg(ap, int); + printf("i1, i2, i3: %d, %d, %d\n", i1, i2, i3); + // CHECK: i1, i2, i3: 1, 2, 3 + + long long int l1 = va_arg(ap, long long int); + printf("l1: %lld\n", l1); + // CHECK: l1: 4 + + int i4 = va_arg(ap, int); + printf("i4: %d\n", i4); + // CHECK: i4: 5 + + struct mix m1 = va_arg(ap, struct mix); + printf("m1: (%lld, %d)\n", m1.first, m1.second); + // CHECK: m1: (7, 8) + + struct mix m2 = va_arg(ap, struct mix); + printf("m2: (%lld, %d)\n", m2.first, m2.second); + // CHECK: m2: (9, 10) + + va_end(ap); +} + +struct baz { + long double ll; +}; + +/* ld needs to be 16-byte aligned (checked with LLVM 9) */ +void foo(int x, ...) { + va_list ap; + va_start(ap, x); + int a = va_arg(ap, int); + long double ld = va_arg(ap, long double); + printf("ld: %Lf\n", ld); + // CHECK: ld: 1.000000 +} + +/* b needs to be 8-byte aligned as specified via the align + attribute (checked with LLVM 9) */ +void bar(int x, ...) { + va_list ap; + va_start(ap, x); + int a = va_arg(ap, int); + struct baz b = va_arg(ap, struct baz); + printf("b.ll: %Lf\n", b.ll); + // CHECK: b.ll: 1.000000 +} + +int main() { + int i1 = 1, i2 = 2, i3 = 3; + long long int l1 = 4; + int i4 = 5; + long double ld1 = 6.0, ld2 = 7.0; + struct mix m1 = { 7, 8 }; + struct mix m2 = { 9, 10 }; + test1(-1, i1, i2, i3, l1, i4, ld1, ld2); + test2(-1, i1, i2, i3, l1, i4, m1, m2); + + long double ll = 1.0; + struct baz s = { 1.0 }; + foo(1, 2, ll); + bar(1, 3, s); + + return 0; +} |