38 #if __cplusplus >= 201703L
48 #include <type_traits>
49 #include <unordered_map>
50 #include <unordered_set>
53 #ifdef ENABLE_TOSTRING_RAPIDJSON
54 #if __has_include(<rapidjson/document.h> )
55 #include <rapidjson/document.h>
56 #include <rapidjson/stringbuffer.h>
57 #include <rapidjson/writer.h>
59 #undefine ENABLE_TOSTRING_RAPIDJSON
63 #ifdef ENABLE_TOSTRING_LLVM
64 #if __has_include(<llvm/Support/raw_os_ostream.h> )
65 #include <llvm/IR/Value.h>
66 #include <llvm/Support/raw_os_ostream.h>
67 #include "llvm/IR/Function.h"
68 #include "llvm/IR/Module.h"
70 #undefine ENABLE_TOSTRING_LLVM
75 std::cout << __func__ << "#" << __LINE__ << ": " #EXPR "=" << ::toString(EXPR) \
79 std::string typeName(
const T* v) {
80 std::stringstream stream;
82 char* demangled = abi::__cxa_demangle(
typeid(
T).
name(), 0, 0, &status);
83 stream << std::string(demangled);
90 template <
typename T,
typename =
void>
91 struct has_toString : std::false_type {};
93 struct has_toString<
T, decltype(std::declval<T>().
toString(), void())> : std::true_type {
96 inline constexpr
bool has_toString_v = has_toString<T>::value;
98 template <
typename T,
typename =
void>
99 struct get_has_toString : std::false_type {};
100 template <
typename T>
101 struct get_has_toString<
T, decltype(std::declval<T>().get()->
toString(), void())>
104 inline constexpr
bool get_has_toString_v = get_has_toString<T>::value;
106 #ifdef ENABLE_TOSTRING_to_string
107 template <
typename T,
typename =
void>
108 struct has_to_string : std::false_type {};
109 template <
typename T>
110 struct has_to_string<
T, decltype(std::declval<T>().
to_string(), void())>
113 inline constexpr
bool has_to_string_v = has_to_string<T>::value;
116 #ifdef ENABLE_TOSTRING_str
117 template <
typename T,
typename =
void>
118 struct has_str : std::false_type {};
119 template <
typename T>
120 struct has_str<
T, decltype(std::declval<T>().str(), void())> : std::true_type {};
122 inline constexpr
bool has_str_v = has_str<T>::value;
127 template <
typename T>
129 if constexpr (std::is_same_v<T, std::string>) {
130 return "\"" + v +
"\"";
131 #ifdef ENABLE_TOSTRING_RAPIDJSON
132 }
else if constexpr (std::is_same_v<T, rapidjson::Value>) {
133 rapidjson::StringBuffer buffer;
134 rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
136 return buffer.GetString();
138 #ifdef ENABLE_TOSTRING_LLVM
139 }
else if constexpr (std::is_same_v<T, llvm::Module>) {
140 std::string type_str;
141 llvm::raw_string_ostream rso(type_str);
142 v.print(rso,
nullptr);
143 return "(" + rso.str() +
")";
144 }
else if constexpr (std::is_same_v<T, llvm::Function>) {
145 std::string type_str;
146 llvm::raw_string_ostream rso(type_str);
147 v.print(rso,
nullptr);
148 return "(" + rso.str() +
")";
149 }
else if constexpr (std::is_same_v<T, llvm::Value>) {
150 std::string type_str;
151 llvm::raw_string_ostream rso(type_str);
153 return "(" + rso.str() +
")";
154 }
else if constexpr (std::is_same_v<T, llvm::Type>) {
155 std::string type_str;
156 llvm::raw_string_ostream rso(type_str);
158 return "(" + rso.str() +
")";
159 }
else if constexpr (std::is_same_v<T, llvm::Triple>) {
162 }
else if constexpr (std::is_same_v<T, bool>) {
163 return v ?
"True" :
"False";
164 }
else if constexpr (std::is_arithmetic_v<T>) {
166 #ifdef ENABLE_TOSTRING_str
167 }
else if constexpr (has_str_v<T>) {
170 #ifdef ENABLE_TOSTRING_to_string
171 }
else if constexpr (has_to_string_v<T>) {
172 return v.to_string();
174 }
else if constexpr (has_toString_v<T>) {
176 }
else if constexpr (get_has_toString_v<T>) {
178 return (ptr == NULL ?
"NULL" :
"&" + ptr->toString());
179 }
else if constexpr (std::is_same_v<T, void*>) {
180 std::ostringstream ss;
181 ss << std::hex << (uintptr_t)v;
182 return "0x" + ss.str();
183 }
else if constexpr (std::is_same_v<
185 std::chrono::time_point<std::chrono::system_clock>>) {
186 std::string s(30,
'\0');
187 auto converted_v = (std::chrono::time_point<std::chrono::system_clock>)v;
188 std::time_t ts = std::chrono::system_clock::to_time_t(v);
189 std::strftime(&s[0], s.size(),
"%Y-%m-%d %H:%M:%S", std::localtime(&ts));
191 std::to_string((converted_v.time_since_epoch().count() / 1000) % 1000000);
192 }
else if constexpr (std::is_pointer_v<T>) {
193 return (v == NULL ?
"NULL" :
"&" +
toString(*v));
199 template <
typename T1,
typename T2>
200 std::string
toString(
const std::pair<T1, T2>& v) {
204 template <
typename T>
205 std::string
toString(
const std::vector<T>& v) {
206 auto result = std::string(
"[");
207 for (
size_t i = 0;
i < v.size(); ++
i) {
217 template <
typename T1,
typename T2>
218 std::string
toString(
const std::unordered_map<T1, T2>& v) {
219 auto result = std::string(
"{");
221 for (
const auto& p : v) {
232 template <
typename T>
233 std::string
toString(
const std::list<T>& v) {
234 auto result = std::string(
"[");
236 for (
const auto& p : v) {
247 template <
typename T>
248 std::string
toString(
const std::unordered_set<T>& v) {
249 auto result = std::string(
"{");
251 for (
const auto& p : v) {
262 template <
typename T>
263 std::string
toString(
const std::set<T>& v) {
264 auto result = std::string(
"{");
266 for (
const auto& p : v) {
277 template <
typename T>
278 std::string
toString(
const std::tuple<T, T>& v) {
280 std::tie(left, right) = v;
284 #endif // __cplusplus >= 201703L
std::string toString(const ExtArgumentType &sig_type)