1 //===-- Holder Class for manipulating va_lists ------------------*- C++ -*-===// 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 #ifndef LLVM_LIBC_SRC___SUPPORT_ARG_LIST_H 10 #define LLVM_LIBC_SRC___SUPPORT_ARG_LIST_H 11 12 #include "src/__support/common.h" 13 14 #include <stdarg.h> 15 #include <stddef.h> 16 #include <stdint.h> 17 18 namespace LIBC_NAMESPACE { 19 namespace internal { 20 21 class ArgList { 22 va_list vlist; 23 24 public: ArgList(va_list vlist)25 LIBC_INLINE ArgList(va_list vlist) { va_copy(this->vlist, vlist); } ArgList(ArgList & other)26 LIBC_INLINE ArgList(ArgList &other) { va_copy(this->vlist, other.vlist); } ~ArgList()27 LIBC_INLINE ~ArgList() { va_end(this->vlist); } 28 29 LIBC_INLINE ArgList &operator=(ArgList &rhs) { 30 va_copy(vlist, rhs.vlist); 31 return *this; 32 } 33 next_var()34 template <class T> LIBC_INLINE T next_var() { return va_arg(vlist, T); } 35 }; 36 37 // Used for testing things that use an ArgList when it's impossible to know what 38 // the arguments should be ahead of time. An example of this would be fuzzing, 39 // since a function passed a random input could request unpredictable arguments. 40 class MockArgList { 41 size_t arg_counter = 0; 42 43 public: 44 LIBC_INLINE MockArgList() = default; MockArgList(va_list)45 LIBC_INLINE MockArgList(va_list) { ; } MockArgList(MockArgList & other)46 LIBC_INLINE MockArgList(MockArgList &other) { 47 arg_counter = other.arg_counter; 48 } 49 LIBC_INLINE ~MockArgList() = default; 50 51 LIBC_INLINE MockArgList &operator=(MockArgList &rhs) { 52 arg_counter = rhs.arg_counter; 53 return *this; 54 } 55 next_var()56 template <class T> LIBC_INLINE T next_var() { 57 ++arg_counter; 58 return T(arg_counter); 59 } 60 read_count()61 size_t read_count() const { return arg_counter; } 62 }; 63 64 // Used for the GPU implementation of `printf`. This models a variadic list as a 65 // simple array of pointers that are built manually by the implementation. 66 class StructArgList { 67 void *ptr; 68 void *end; 69 70 public: StructArgList(void * ptr,size_t size)71 LIBC_INLINE StructArgList(void *ptr, size_t size) 72 : ptr(ptr), end(reinterpret_cast<unsigned char *>(ptr) + size) {} StructArgList(const StructArgList & other)73 LIBC_INLINE StructArgList(const StructArgList &other) { 74 ptr = other.ptr; 75 end = other.end; 76 } 77 LIBC_INLINE StructArgList() = default; 78 LIBC_INLINE ~StructArgList() = default; 79 80 LIBC_INLINE StructArgList &operator=(const StructArgList &rhs) { 81 ptr = rhs.ptr; 82 return *this; 83 } 84 get_ptr()85 LIBC_INLINE void *get_ptr() const { return ptr; } 86 next_var()87 template <class T> LIBC_INLINE T next_var() { 88 ptr = reinterpret_cast<void *>( 89 ((reinterpret_cast<uintptr_t>(ptr) + alignof(T) - 1) / alignof(T)) * 90 alignof(T)); 91 92 if (ptr >= end) 93 return T(-1); 94 95 T val = *reinterpret_cast<T *>(ptr); 96 ptr = reinterpret_cast<unsigned char *>(ptr) + sizeof(T); 97 return val; 98 } 99 }; 100 101 } // namespace internal 102 } // namespace LIBC_NAMESPACE 103 104 #endif // LLVM_LIBC_SRC___SUPPORT_ARG_LIST_H 105