[libc-commits] [libc] 5561ab3 - [libc] Add holder class for va_lists

Michael Jones via libc-commits libc-commits at lists.llvm.org
Tue Apr 5 11:40:02 PDT 2022


Author: Michael Jones
Date: 2022-04-05T11:39:57-07:00
New Revision: 5561ab3495a42fddbc251bec6bef46a1cae9c559

URL: https://github.com/llvm/llvm-project/commit/5561ab3495a42fddbc251bec6bef46a1cae9c559
DIFF: https://github.com/llvm/llvm-project/commit/5561ab3495a42fddbc251bec6bef46a1cae9c559.diff

LOG: [libc] Add holder class for va_lists

This class is intended to be used in cases where a class is being used
on a va_list. It provides destruction and copy semantics with small
overhead. This is intended to be used in printf.

Reviewed By: sivachandra, lntue

Differential Revision: https://reviews.llvm.org/D123061

Added: 
    libc/src/__support/arg_list.h
    libc/test/src/__support/arg_list_test.cpp

Modified: 
    libc/src/__support/CMakeLists.txt
    libc/test/src/__support/CMakeLists.txt

Removed: 
    


################################################################################
diff  --git a/libc/src/__support/CMakeLists.txt b/libc/src/__support/CMakeLists.txt
index 8ac10d26ffca7..284d4ae5ca65c 100644
--- a/libc/src/__support/CMakeLists.txt
+++ b/libc/src/__support/CMakeLists.txt
@@ -54,6 +54,12 @@ add_header_library(
     integer_operations.h
 )
 
+add_header_library(
+  arg_list
+  HDRS
+    arg_list.h
+)
+
 # Thread support is used by other support libraries. So, we add the "threads"
 # before other directories.
 add_subdirectory(threads)

diff  --git a/libc/src/__support/arg_list.h b/libc/src/__support/arg_list.h
new file mode 100644
index 0000000000000..3a885df6495ea
--- /dev/null
+++ b/libc/src/__support/arg_list.h
@@ -0,0 +1,31 @@
+//===-- Holder Class for manipulating va_lists ------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SRC_SUPPORT_ARG_LIST_H
+#define LLVM_LIBC_SRC_SUPPORT_ARG_LIST_H
+
+#include <stdarg.h>
+
+namespace __llvm_libc {
+namespace internal {
+
+class ArgList {
+  va_list vlist;
+
+public:
+  ArgList(va_list vlist) { va_copy(this->vlist, vlist); }
+  ArgList(ArgList &other) { va_copy(this->vlist, other.vlist); }
+  ~ArgList() { va_end(this->vlist); }
+
+  template <class T> T inline next_var() { return va_arg(vlist, T); }
+};
+
+} // namespace internal
+} // namespace __llvm_libc
+
+#endif // LLVM_LIBC_SRC_SUPPORT_ARG_LIST_H

diff  --git a/libc/test/src/__support/CMakeLists.txt b/libc/test/src/__support/CMakeLists.txt
index 2bb125bc7c6a2..10a1c6c90e433 100644
--- a/libc/test/src/__support/CMakeLists.txt
+++ b/libc/test/src/__support/CMakeLists.txt
@@ -30,6 +30,16 @@ add_libc_unittest(
     libc.src.__support.str_to_float
 )
 
+add_libc_unittest(
+  arg_list_test
+  SUITE
+    libc_support_unittests
+  SRCS
+    arg_list_test.cpp
+  DEPENDS
+    libc.src.__support.arg_list
+)
+
 add_executable(
   libc_str_to_float_comparison_test
   str_to_float_comparison_test.cpp

diff  --git a/libc/test/src/__support/arg_list_test.cpp b/libc/test/src/__support/arg_list_test.cpp
new file mode 100644
index 0000000000000..70d4835bd32ff
--- /dev/null
+++ b/libc/test/src/__support/arg_list_test.cpp
@@ -0,0 +1,58 @@
+//===-- Unittests for ArgList ---------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "src/__support/arg_list.h"
+
+#include "utils/UnitTest/Test.h"
+
+int get_nth_int(int n, ...) {
+  va_list vlist;
+  va_start(vlist, n);
+  __llvm_libc::internal::ArgList v(vlist);
+  va_end(vlist);
+
+  for (int i = 0; i < n; ++i) {
+    v.next_var<int>();
+  }
+  return v.next_var<int>();
+}
+
+TEST(LlvmLibcArgListTest, BasicUsage) {
+  ASSERT_EQ(get_nth_int(5, 0, 10, 20, 30, 40, 50, 60, 70, 80, 90), 50);
+}
+
+int sum_two_nums(int first, int second, ...) {
+  va_list vlist;
+  va_start(vlist, second);
+  __llvm_libc::internal::ArgList v1(vlist);
+  va_end(vlist);
+
+  __llvm_libc::internal::ArgList v2 = v1;
+
+  int first_val;
+  for (int i = 0; i < first; ++i) {
+    v1.next_var<int>();
+  }
+  first_val = v1.next_var<int>();
+
+  int second_val;
+  for (int i = 0; i < second; ++i) {
+    v2.next_var<int>();
+  }
+  second_val = v2.next_var<int>();
+
+  return first_val + second_val;
+}
+
+TEST(LlvmLibcArgListTest, CopyConstructor) {
+  ASSERT_EQ(sum_two_nums(3, 1, 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024),
+            10);
+
+  ASSERT_EQ(sum_two_nums(3, 5, 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024),
+            40);
+}


        


More information about the libc-commits mailing list