1 | //===-- Unittests for ArgList ---------------------------------------------===// |
2 | // |
3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
4 | // See https://llvm.org/LICENSE.txt for license information. |
5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
6 | // |
7 | //===----------------------------------------------------------------------===// |
8 | |
9 | #include "src/__support/arg_list.h" |
10 | |
11 | #include "test/UnitTest/Test.h" |
12 | |
13 | int get_nth_int(int n, ...) { |
14 | va_list vlist; |
15 | va_start(vlist, n); |
16 | LIBC_NAMESPACE::internal::ArgList v(vlist); |
17 | va_end(vlist); |
18 | |
19 | for (int i = 0; i < n; ++i) { |
20 | v.next_var<int>(); |
21 | } |
22 | return v.next_var<int>(); |
23 | } |
24 | |
25 | TEST(LlvmLibcArgListTest, BasicUsage) { |
26 | ASSERT_EQ(get_nth_int(5, 0, 10, 20, 30, 40, 50, 60, 70, 80, 90), 50); |
27 | } |
28 | |
29 | int sum_two_nums(int first, int second, ...) { |
30 | va_list vlist; |
31 | va_start(vlist, second); |
32 | LIBC_NAMESPACE::internal::ArgList v1(vlist); |
33 | va_end(vlist); |
34 | |
35 | LIBC_NAMESPACE::internal::ArgList v2 = v1; |
36 | |
37 | int first_val; |
38 | for (int i = 0; i < first; ++i) { |
39 | v1.next_var<int>(); |
40 | } |
41 | first_val = v1.next_var<int>(); |
42 | |
43 | int second_val; |
44 | for (int i = 0; i < second; ++i) { |
45 | v2.next_var<int>(); |
46 | } |
47 | second_val = v2.next_var<int>(); |
48 | |
49 | return first_val + second_val; |
50 | } |
51 | |
52 | TEST(LlvmLibcArgListTest, CopyConstructor) { |
53 | ASSERT_EQ(sum_two_nums(3, 1, 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024), |
54 | 10); |
55 | |
56 | ASSERT_EQ(sum_two_nums(3, 5, 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024), |
57 | 40); |
58 | } |
59 | |
60 | long int check_primitives(int first, ...) { |
61 | va_list vlist; |
62 | va_start(vlist, first); |
63 | LIBC_NAMESPACE::internal::ArgList args(vlist); |
64 | va_end(vlist); |
65 | |
66 | long int count = 0; |
67 | count += args.next_var<int>(); |
68 | count += args.next_var<int>(); |
69 | count += args.next_var<int>(); |
70 | count += args.next_var<long>(); |
71 | count += args.next_var<unsigned long>(); |
72 | count += args.next_var<long long>(); |
73 | count += args.next_var<unsigned long long>(); |
74 | count += args.next_var<double>(); |
75 | count += args.next_var<double>(); |
76 | count += args.next_var<long double>(); |
77 | count += *args.next_var<int *>(); |
78 | return count; |
79 | } |
80 | |
81 | TEST(LlvmLibcArgListTest, TestPrimitiveTypes) { |
82 | char c = '\x01'; |
83 | short s = 2; |
84 | int i = 3; |
85 | long l = 4l; |
86 | unsigned long ul = 5ul; |
87 | long long ll = 6ll; |
88 | unsigned long long ull = 7ull; |
89 | float f = 8.0f; |
90 | double d = 9.0; |
91 | long double ld = 10.0L; |
92 | long v = 11; |
93 | void *p = &v; |
94 | ASSERT_EQ(check_primitives(0, c, s, i, l, ul, ll, ull, f, d, ld, p), 66l); |
95 | } |
96 | |
97 | struct S { |
98 | char c; |
99 | short s; |
100 | int i; |
101 | long l; |
102 | float f; |
103 | double d; |
104 | }; |
105 | |
106 | long int check_struct_type(int first, ...) { |
107 | va_list vlist; |
108 | va_start(vlist, first); |
109 | LIBC_NAMESPACE::internal::ArgList args(vlist); |
110 | va_end(vlist); |
111 | |
112 | S s = args.next_var<S>(); |
113 | int last = args.next_var<int>(); |
114 | return s.c + s.s + s.i + s.l + s.f + s.d + last; |
115 | } |
116 | |
117 | TEST(LlvmLibcArgListTest, TestStructTypes) { |
118 | S s{.c: '\x1', .s: 2, .i: 3, .l: 4l, .f: 5.0f, .d: 6.0}; |
119 | ASSERT_EQ(check_struct_type(0, s, 1), 22l); |
120 | } |
121 | |
122 | // Test vector extensions from clang. |
123 | #if __has_attribute(ext_vector_type) |
124 | |
125 | using int1 = int __attribute__((ext_vector_type(1))); |
126 | using int2 = int __attribute__((ext_vector_type(2))); |
127 | using int3 = int __attribute__((ext_vector_type(3))); |
128 | using int4 = int __attribute__((ext_vector_type(4))); |
129 | |
130 | int check_vector_type(int first, ...) { |
131 | va_list vlist; |
132 | va_start(vlist, first); |
133 | LIBC_NAMESPACE::internal::ArgList args(vlist); |
134 | va_end(vlist); |
135 | |
136 | int1 v1 = args.next_var<int1>(); |
137 | int2 v2 = args.next_var<int2>(); |
138 | int3 v3 = args.next_var<int3>(); |
139 | int4 v4 = args.next_var<int4>(); |
140 | |
141 | return v1.x + v2.x + v2.y + v3.x + v3.y + v3.z + v4.x + v4.y + v4.z + v4.w; |
142 | } |
143 | |
144 | TEST(LlvmLibcArgListTest, TestVectorTypes) { |
145 | int1 v1 = {1}; |
146 | int2 v2 = {1, 2}; |
147 | int3 v3 = {1, 2, 3}; |
148 | int4 v4 = {1, 2, 3, 4}; |
149 | ASSERT_EQ(check_vector_type(0, v1, v2, v3, v4), 20); |
150 | } |
151 | |
152 | #endif |
153 | |