summaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
authorBruno Cardoso Lopes <bruno.cardoso@gmail.com>2011-03-09 19:22:22 +0000
committerBruno Cardoso Lopes <bruno.cardoso@gmail.com>2011-03-09 19:22:22 +0000
commit954dac0f88bcb27c06ce467c43e913ff0aa511bb (patch)
treecebad824b2a6383b7c8548f11d468cd18b11951c /test
parent5d332e0c3e217e946532dd06f3e3bc6a7fd2a457 (diff)
downloadllvm-954dac0f88bcb27c06ce467c43e913ff0aa511bb.tar.gz
llvm-954dac0f88bcb27c06ce467c43e913ff0aa511bb.tar.bz2
llvm-954dac0f88bcb27c06ce467c43e913ff0aa511bb.tar.xz
Improve varags handling, with testcases. Patch by Sasa Stankovic
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@127349 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'test')
-rw-r--r--test/CodeGen/Mips/o32_cc_vararg.ll277
1 files changed, 277 insertions, 0 deletions
diff --git a/test/CodeGen/Mips/o32_cc_vararg.ll b/test/CodeGen/Mips/o32_cc_vararg.ll
new file mode 100644
index 0000000000..50b43b486c
--- /dev/null
+++ b/test/CodeGen/Mips/o32_cc_vararg.ll
@@ -0,0 +1,277 @@
+; RUN: llc -march=mipsel -mcpu=mips2 < %s | FileCheck %s
+
+
+; All test functions do the same thing - they return the first variable
+; argument.
+
+; All CHECK's do the same thing - they check whether variable arguments from
+; registers are placed on correct stack locations, and whether the first
+; variable argument is returned from the correct stack location.
+
+
+declare void @llvm.va_start(i8*) nounwind
+declare void @llvm.va_end(i8*) nounwind
+
+; return int
+define i32 @va1(i32 %a, ...) nounwind {
+entry:
+ %a.addr = alloca i32, align 4
+ %ap = alloca i8*, align 4
+ %b = alloca i32, align 4
+ store i32 %a, i32* %a.addr, align 4
+ %ap1 = bitcast i8** %ap to i8*
+ call void @llvm.va_start(i8* %ap1)
+ %0 = va_arg i8** %ap, i32
+ store i32 %0, i32* %b, align 4
+ %ap2 = bitcast i8** %ap to i8*
+ call void @llvm.va_end(i8* %ap2)
+ %tmp = load i32* %b, align 4
+ ret i32 %tmp
+
+; CHECK: va1:
+; CHECK: addiu $sp, $sp, -32
+; CHECK: sw $5, 36($sp)
+; CHECK: sw $6, 40($sp)
+; CHECK: sw $7, 44($sp)
+; CHECK: lw $2, 36($sp)
+}
+
+; check whether the variable double argument will be accessed from the 8-byte
+; aligned location (i.e. whether the address is computed by adding 7 and
+; clearing lower 3 bits)
+define double @va2(i32 %a, ...) nounwind {
+entry:
+ %a.addr = alloca i32, align 4
+ %ap = alloca i8*, align 4
+ %b = alloca double, align 8
+ store i32 %a, i32* %a.addr, align 4
+ %ap1 = bitcast i8** %ap to i8*
+ call void @llvm.va_start(i8* %ap1)
+ %0 = va_arg i8** %ap, double
+ store double %0, double* %b, align 8
+ %ap2 = bitcast i8** %ap to i8*
+ call void @llvm.va_end(i8* %ap2)
+ %tmp = load double* %b, align 8
+ ret double %tmp
+
+; CHECK: va2:
+; CHECK: addiu $sp, $sp, -40
+; CHECK: addiu $2, $sp, 44
+; CHECK: sw $5, 44($sp)
+; CHECK: sw $6, 48($sp)
+; CHECK: sw $7, 52($sp)
+; CHECK: addiu $3, $2, 7
+; CHECK: addiu $5, $zero, -8
+; CHECK: and $3, $3, $5
+; CHECK: ldc1 $f0, 0($3)
+}
+
+; int
+define i32 @va3(double %a, ...) nounwind {
+entry:
+ %a.addr = alloca double, align 8
+ %ap = alloca i8*, align 4
+ %b = alloca i32, align 4
+ store double %a, double* %a.addr, align 8
+ %ap1 = bitcast i8** %ap to i8*
+ call void @llvm.va_start(i8* %ap1)
+ %0 = va_arg i8** %ap, i32
+ store i32 %0, i32* %b, align 4
+ %ap2 = bitcast i8** %ap to i8*
+ call void @llvm.va_end(i8* %ap2)
+ %tmp = load i32* %b, align 4
+ ret i32 %tmp
+
+; CHECK: va3:
+; CHECK: addiu $sp, $sp, -40
+; CHECK: sw $6, 48($sp)
+; CHECK: sw $7, 52($sp)
+; CHECK: lw $2, 48($sp)
+}
+
+; double
+define double @va4(double %a, ...) nounwind {
+entry:
+ %a.addr = alloca double, align 8
+ %ap = alloca i8*, align 4
+ %b = alloca double, align 8
+ store double %a, double* %a.addr, align 8
+ %ap1 = bitcast i8** %ap to i8*
+ call void @llvm.va_start(i8* %ap1)
+ %0 = va_arg i8** %ap, double
+ store double %0, double* %b, align 8
+ %ap2 = bitcast i8** %ap to i8*
+ call void @llvm.va_end(i8* %ap2)
+ %tmp = load double* %b, align 8
+ ret double %tmp
+
+; CHECK: va4:
+; CHECK: addiu $sp, $sp, -48
+; CHECK: sw $6, 56($sp)
+; CHECK: sw $7, 60($sp)
+; CHECK: addiu $3, $sp, 56
+; CHECK: addiu $6, $3, 7
+; CHECK: addiu $7, $zero, -8
+; CHECK: and $2, $6, $7
+; CHECK: ldc1 $f0, 0($2)
+}
+
+; int
+define i32 @va5(i32 %a, i32 %b, i32 %c, ...) nounwind {
+entry:
+ %a.addr = alloca i32, align 4
+ %b.addr = alloca i32, align 4
+ %c.addr = alloca i32, align 4
+ %ap = alloca i8*, align 4
+ %d = alloca i32, align 4
+ store i32 %a, i32* %a.addr, align 4
+ store i32 %b, i32* %b.addr, align 4
+ store i32 %c, i32* %c.addr, align 4
+ %ap1 = bitcast i8** %ap to i8*
+ call void @llvm.va_start(i8* %ap1)
+ %0 = va_arg i8** %ap, i32
+ store i32 %0, i32* %d, align 4
+ %ap2 = bitcast i8** %ap to i8*
+ call void @llvm.va_end(i8* %ap2)
+ %tmp = load i32* %d, align 4
+ ret i32 %tmp
+
+; CHECK: va5:
+; CHECK: addiu $sp, $sp, -40
+; CHECK: sw $7, 52($sp)
+; CHECK: lw $2, 52($sp)
+}
+
+; double
+define double @va6(i32 %a, i32 %b, i32 %c, ...) nounwind {
+entry:
+ %a.addr = alloca i32, align 4
+ %b.addr = alloca i32, align 4
+ %c.addr = alloca i32, align 4
+ %ap = alloca i8*, align 4
+ %d = alloca double, align 8
+ store i32 %a, i32* %a.addr, align 4
+ store i32 %b, i32* %b.addr, align 4
+ store i32 %c, i32* %c.addr, align 4
+ %ap1 = bitcast i8** %ap to i8*
+ call void @llvm.va_start(i8* %ap1)
+ %0 = va_arg i8** %ap, double
+ store double %0, double* %d, align 8
+ %ap2 = bitcast i8** %ap to i8*
+ call void @llvm.va_end(i8* %ap2)
+ %tmp = load double* %d, align 8
+ ret double %tmp
+
+; CHECK: va6:
+; CHECK: addiu $sp, $sp, -48
+; CHECK: sw $7, 60($sp)
+; CHECK: addiu $2, $sp, 60
+; CHECK: addiu $3, $2, 7
+; CHECK: addiu $4, $zero, -8
+; CHECK: and $3, $3, $4
+; CHECK: ldc1 $f0, 0($3)
+}
+
+; int
+define i32 @va7(i32 %a, double %b, ...) nounwind {
+entry:
+ %a.addr = alloca i32, align 4
+ %b.addr = alloca double, align 8
+ %ap = alloca i8*, align 4
+ %c = alloca i32, align 4
+ store i32 %a, i32* %a.addr, align 4
+ store double %b, double* %b.addr, align 8
+ %ap1 = bitcast i8** %ap to i8*
+ call void @llvm.va_start(i8* %ap1)
+ %0 = va_arg i8** %ap, i32
+ store i32 %0, i32* %c, align 4
+ %ap2 = bitcast i8** %ap to i8*
+ call void @llvm.va_end(i8* %ap2)
+ %tmp = load i32* %c, align 4
+ ret i32 %tmp
+
+; CHECK: va7:
+; CHECK: addiu $sp, $sp, -40
+; CHECK: lw $2, 56($sp)
+}
+
+; double
+define double @va8(i32 %a, double %b, ...) nounwind {
+entry:
+ %a.addr = alloca i32, align 4
+ %b.addr = alloca double, align 8
+ %ap = alloca i8*, align 4
+ %c = alloca double, align 8
+ store i32 %a, i32* %a.addr, align 4
+ store double %b, double* %b.addr, align 8
+ %ap1 = bitcast i8** %ap to i8*
+ call void @llvm.va_start(i8* %ap1)
+ %0 = va_arg i8** %ap, double
+ store double %0, double* %c, align 8
+ %ap2 = bitcast i8** %ap to i8*
+ call void @llvm.va_end(i8* %ap2)
+ %tmp = load double* %c, align 8
+ ret double %tmp
+
+; CHECK: va8:
+; CHECK: addiu $sp, $sp, -48
+; CHECK: addiu $3, $sp, 64
+; CHECK: addiu $4, $3, 7
+; CHECK: addiu $5, $zero, -8
+; CHECK: and $2, $4, $5
+; CHECK: ldc1 $f0, 0($2)
+}
+
+; int
+define i32 @va9(double %a, double %b, i32 %c, ...) nounwind {
+entry:
+ %a.addr = alloca double, align 8
+ %b.addr = alloca double, align 8
+ %c.addr = alloca i32, align 4
+ %ap = alloca i8*, align 4
+ %d = alloca i32, align 4
+ store double %a, double* %a.addr, align 8
+ store double %b, double* %b.addr, align 8
+ store i32 %c, i32* %c.addr, align 4
+ %ap1 = bitcast i8** %ap to i8*
+ call void @llvm.va_start(i8* %ap1)
+ %0 = va_arg i8** %ap, i32
+ store i32 %0, i32* %d, align 4
+ %ap2 = bitcast i8** %ap to i8*
+ call void @llvm.va_end(i8* %ap2)
+ %tmp = load i32* %d, align 4
+ ret i32 %tmp
+
+; CHECK: va9:
+; CHECK: addiu $sp, $sp, -56
+; CHECK: lw $2, 76($sp)
+}
+
+; double
+define double @va10(double %a, double %b, i32 %c, ...) nounwind {
+entry:
+ %a.addr = alloca double, align 8
+ %b.addr = alloca double, align 8
+ %c.addr = alloca i32, align 4
+ %ap = alloca i8*, align 4
+ %d = alloca double, align 8
+ store double %a, double* %a.addr, align 8
+ store double %b, double* %b.addr, align 8
+ store i32 %c, i32* %c.addr, align 4
+ %ap1 = bitcast i8** %ap to i8*
+ call void @llvm.va_start(i8* %ap1)
+ %0 = va_arg i8** %ap, double
+ store double %0, double* %d, align 8
+ %ap2 = bitcast i8** %ap to i8*
+ call void @llvm.va_end(i8* %ap2)
+ %tmp = load double* %d, align 8
+ ret double %tmp
+
+; CHECK: va10:
+; CHECK: addiu $sp, $sp, -56
+; CHECK: addiu $3, $sp, 76
+; CHECK: addiu $2, $3, 7
+; CHECK: addiu $4, $zero, -8
+; CHECK: and $2, $2, $4
+; CHECK: ldc1 $f0, 0($2)
+}