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