Skip to content

Commit 79ad08a

Browse files
committed
Update the tracing of APIs in the validation layer with params
Signed-off-by: Neil R. Spruit <[email protected]>
1 parent 02b7655 commit 79ad08a

File tree

13 files changed

+15730
-2164
lines changed

13 files changed

+15730
-2164
lines changed

scripts/generate_code.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,7 @@ def _mako_loader_cpp(path, namespace, tags, version, specs, meta):
182182
'handle_lifetime.h.mako' : ('handle_lifetime_tracking', 'handle_lifetime.h'),
183183
'handle_lifetime.cpp.mako' : ('handle_lifetime_tracking', 'handle_lifetime.cpp'),
184184
'certification.h.mako' : ('checkers/certification/generated', 'certification.h'),
185+
'to_string.h.mako' : ('../../utils', 'to_string.h'),
185186
}
186187

187188
def _mako_validation_layer_cpp(path, namespace, tags, version, specs, meta):
Lines changed: 171 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,171 @@
1+
<%!
2+
import re
3+
from templates import helper as th
4+
%><%
5+
n=namespace
6+
N=n.upper()
7+
8+
x=tags['$x']
9+
X=x.upper()
10+
%>/*
11+
* ***THIS FILE IS GENERATED. ***
12+
* See to_string.h.mako for modifications
13+
*
14+
* Copyright (C) 2025 Intel Corporation
15+
*
16+
* SPDX-License-Identifier: MIT
17+
*
18+
* @file ${name}
19+
*
20+
* to_string functions for Level Zero types
21+
*/
22+
23+
#ifndef _${N}_TO_STRING_H
24+
#define _${N}_TO_STRING_H
25+
26+
#include "${x}_api.h"
27+
#include <string>
28+
#include <sstream>
29+
#include <iomanip>
30+
31+
%if n == 'ze':
32+
namespace loader {
33+
34+
// Forward declarations
35+
std::string to_string(const ${x}_result_t result);
36+
37+
// Pointer to_string
38+
template<typename T>
39+
inline std::string to_string(const T* ptr) {
40+
if (ptr == nullptr) {
41+
return "nullptr";
42+
}
43+
std::ostringstream oss;
44+
oss << "0x" << std::hex << reinterpret_cast<uintptr_t>(ptr);
45+
return oss.str();
46+
}
47+
48+
%else:
49+
// Include ze_to_string.h for common definitions
50+
#include "ze_to_string.h"
51+
52+
namespace loader {
53+
%endif
54+
%if n == 'ze':
55+
// Handle to_string functions
56+
%for obj in th.extract_objs(specs, r"handle"):
57+
inline std::string to_string(${th.make_type_name(n, tags, obj)} handle) {
58+
return to_string(reinterpret_cast<const void*>(handle));
59+
}
60+
61+
%endfor
62+
%endif
63+
%if n == 'ze':
64+
// For primitive types and Level Zero typedef'd types
65+
// Since most Level Zero types are typedef'd to uint32_t, we can't distinguish them by type
66+
inline std::string to_string(uint32_t value) { return std::to_string(value); }
67+
inline std::string to_string(uint64_t value) { return std::to_string(value); }
68+
inline std::string to_string(uint8_t value) { return std::to_string(static_cast<unsigned>(value)); }
69+
inline std::string to_string(uint16_t value) { return std::to_string(value); }
70+
inline std::string to_string(int32_t value) { return std::to_string(value); }
71+
inline std::string to_string(int64_t value) { return std::to_string(value); }
72+
#if SIZE_MAX != UINT64_MAX
73+
inline std::string to_string(size_t value) { return std::to_string(value); }
74+
#endif
75+
inline std::string to_string(double value) { return std::to_string(value); }
76+
inline std::string to_string(const char* str) {
77+
if (!str) return "nullptr";
78+
return std::string("\"") + str + "\"";
79+
}
80+
81+
// Pointer to primitive types - dereference and print value
82+
inline std::string to_string(const uint32_t* ptr) {
83+
if (!ptr) return "nullptr";
84+
return to_string(*ptr);
85+
}
86+
inline std::string to_string(const uint64_t* ptr) {
87+
if (!ptr) return "nullptr";
88+
return to_string(*ptr);
89+
}
90+
inline std::string to_string(const uint8_t* ptr) {
91+
if (!ptr) return "nullptr";
92+
return to_string(*ptr);
93+
}
94+
inline std::string to_string(const uint16_t* ptr) {
95+
if (!ptr) return "nullptr";
96+
return to_string(*ptr);
97+
}
98+
inline std::string to_string(const int32_t* ptr) {
99+
if (!ptr) return "nullptr";
100+
return to_string(*ptr);
101+
}
102+
inline std::string to_string(const int64_t* ptr) {
103+
if (!ptr) return "nullptr";
104+
return to_string(*ptr);
105+
}
106+
#if SIZE_MAX != UINT64_MAX
107+
inline std::string to_string(const size_t* ptr) {
108+
if (!ptr) return "nullptr";
109+
return to_string(*ptr);
110+
}
111+
#endif
112+
inline std::string to_string(const double* ptr) {
113+
if (!ptr) return "nullptr";
114+
return to_string(*ptr);
115+
}
116+
117+
%endif
118+
// Struct to_string functions
119+
%for obj in th.extract_objs(specs, r"struct"):
120+
<%
121+
struct_name = th.make_type_name(n, tags, obj)
122+
%>\
123+
inline std::string to_string(const ${struct_name}* desc) {
124+
if (!desc) return "nullptr";
125+
std::ostringstream oss;
126+
oss << "{";
127+
%for idx, member in enumerate(obj['members']):
128+
%if member['name'] != 'pNext':
129+
<%
130+
# Extract the actual member name without array brackets
131+
member_name_full = member['name']
132+
member_name = member_name_full.split('[')[0] if '[' in member_name_full else member_name_full
133+
is_array = '[' in member_name_full
134+
135+
# Check if member is a pointer or regular value
136+
member_type = member.get('type', '')
137+
if is_array:
138+
# For arrays, just pass the array name (decays to pointer)
139+
member_access = f"desc->{member_name}"
140+
elif '*' in member_type:
141+
# It's already a pointer - pass directly
142+
member_access = f"desc->{member_name}"
143+
else:
144+
# Check if it's a struct type by looking at the type name
145+
# If it contains a struct typename pattern, take its address
146+
if '_t' in member_type and 'uint' not in member_type and 'int' not in member_type and 'size_t' not in member_type:
147+
member_access = f"&desc->{member_name}"
148+
else:
149+
member_access = f"desc->{member_name}"
150+
%>\
151+
%if idx == 0 and member['name'] == 'stype':
152+
oss << "stype=" << to_string(${member_access});
153+
%elif idx == 0:
154+
oss << "${member_name}=" << to_string(${member_access});
155+
%else:
156+
oss << ", ${member_name}=" << to_string(${member_access});
157+
%endif
158+
%endif
159+
%endfor
160+
oss << "}";
161+
return oss.str();
162+
}
163+
164+
inline std::string to_string(const ${struct_name}& desc) {
165+
return to_string(&desc);
166+
}
167+
168+
%endfor
169+
} // namespace loader
170+
171+
#endif // _${N}_TO_STRING_H

scripts/templates/validation/valddi.cpp.mako

Lines changed: 70 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ from templates import helper as th
1919
*
2020
*/
2121
#include "${x}_validation_layer.h"
22+
#include <sstream>
2223

2324
namespace validation_layer
2425
{
@@ -33,12 +34,68 @@ namespace validation_layer
3334
);
3435

3536
%endif
36-
static ze_result_t logAndPropagateResult(const char* fname, ze_result_t result) {
37-
if (result != ${X}_RESULT_SUCCESS) {
38-
context.logger->log_trace("Error (" + loader::to_string(result) + ") in " + std::string(fname));
39-
}
37+
// Generate specific logAndPropagateResult functions for each API function
38+
%for obj in th.extract_objs(specs, r"function"):
39+
<%
40+
func_name = th.make_func_name(n, tags, obj)
41+
param_lines = [line for line in th.make_param_lines(n, tags, obj, format=['name','delim'])]
42+
param_names = [line for line in th.make_param_lines(n, tags, obj, format=['name'])]
43+
is_void_params = len(param_lines) == 0
44+
%>\
45+
%if 'condition' in obj:
46+
#if ${th.subt(n, tags, obj['condition'])}
47+
%endif
48+
__attribute__((unused)) static ze_result_t logAndPropagateResult_${func_name}(
49+
ze_result_t result\
50+
%if not is_void_params:
51+
,
52+
%for line in th.make_param_lines(n, tags, obj):
53+
${line}
54+
%endfor
55+
%endif
56+
) {
57+
std::string status = (result == ${X}_RESULT_SUCCESS) ? "SUCCESS" : "ERROR";
58+
%if is_void_params:
59+
context.logger->log_trace(status + " (" + loader::to_string(result) + ") in ${func_name}()");
60+
%else:
61+
std::ostringstream oss;
62+
oss << status << " (" << loader::to_string(result) << ") in ${func_name}(";
63+
%for i, param in enumerate([p for p in th.make_param_lines(n, tags, obj, format=['name'])]):
64+
%if i > 0:
65+
oss << ", ";
66+
%endif
67+
oss << "${param}=" << loader::to_string(${param});
68+
%endfor
69+
oss << ")";
70+
context.logger->log_trace(oss.str());
71+
%endif
4072
return result;
4173
}
74+
%if 'condition' in obj:
75+
#endif // ${th.subt(n, tags, obj['condition'])}
76+
%endif
77+
%endfor
78+
\
79+
%if n == 'ze':
80+
// Special function for zexCounterBasedEventCreate2
81+
__attribute__((unused)) static ze_result_t logAndPropagateResult_zexCounterBasedEventCreate2(
82+
ze_result_t result,
83+
ze_context_handle_t hContext,
84+
ze_device_handle_t hDevice,
85+
const void* desc,
86+
ze_event_handle_t* phEvent
87+
) {
88+
std::string status = (result == ${X}_RESULT_SUCCESS) ? "SUCCESS" : "ERROR";
89+
std::ostringstream oss;
90+
oss << status << " (" << loader::to_string(result) << ") in zexCounterBasedEventCreate2("
91+
<< "hContext=" << static_cast<const void*>(hContext) << ", "
92+
<< "hDevice=" << static_cast<const void*>(hDevice) << ", "
93+
<< "desc=" << desc << ", "
94+
<< "phEvent=" << static_cast<const void*>(phEvent) << ")";
95+
context.logger->log_trace(oss.str());
96+
return result;
97+
}
98+
%endif
4299

43100
%for obj in th.extract_objs(specs, r"function"):
44101
<%
@@ -66,7 +123,7 @@ namespace validation_layer
66123

67124
if( nullptr == ${th.make_pfn_name(n, tags, obj)} )
68125
%if ret_type == "ze_result_t":
69-
return logAndPropagateResult("${th.make_func_name(n, tags, obj)}", ${X}_RESULT_ERROR_UNSUPPORTED_FEATURE);
126+
return logAndPropagateResult_${th.make_func_name(n, tags, obj)}(${X}_RESULT_ERROR_UNSUPPORTED_FEATURE${', ' if not is_void_params else ''}${', '.join(th.make_param_lines(n, tags, obj, format=["name"]))});
70127
%else:
71128
return ${failure_return};
72129
%endif
@@ -80,7 +137,7 @@ ${line} \
80137
);
81138
if(result!=${X}_RESULT_SUCCESS) \
82139
%if ret_type == "ze_result_t":
83-
return logAndPropagateResult("${th.make_func_name(n, tags, obj)}", result);
140+
return logAndPropagateResult_${th.make_func_name(n, tags, obj)}(result${', ' if not is_void_params else ''}${', '.join(th.make_param_lines(n, tags, obj, format=["name"]))});
84141
%else:
85142
return ${failure_return};
86143
%endif
@@ -103,7 +160,7 @@ ${line} \
103160
);
104161
if(result!=${X}_RESULT_SUCCESS) \
105162
%if ret_type == "ze_result_t":
106-
return logAndPropagateResult("${th.make_func_name(n, tags, obj)}", result);
163+
return logAndPropagateResult_${th.make_func_name(n, tags, obj)}(result${', ' if not is_void_params else ''}${', '.join(th.make_param_lines(n, tags, obj, format=["name"]))});
107164
%else:
108165
return ${failure_return};
109166
%endif
@@ -134,7 +191,7 @@ driver_result );
134191
%endif
135192
if(result!=${X}_RESULT_SUCCESS) \
136193
%if ret_type == "ze_result_t":
137-
return logAndPropagateResult("${th.make_func_name(n, tags, obj)}", result);
194+
return logAndPropagateResult_${th.make_func_name(n, tags, obj)}(result${', ' if not is_void_params else ''}${', '.join(th.make_param_lines(n, tags, obj, format=["name"]))});
138195
%else:
139196
return ${failure_return};
140197
%endif
@@ -173,7 +230,7 @@ return ${failure_return};
173230
}
174231
%endif
175232
%if ret_type == "ze_result_t":
176-
return logAndPropagateResult("${th.make_func_name(n, tags, obj)}", driver_result);
233+
return logAndPropagateResult_${th.make_func_name(n, tags, obj)}(driver_result${', ' if not is_void_params else ''}${', '.join(th.make_param_lines(n, tags, obj, format=["name"]))});
177234
%else:
178235
return driver_result;
179236
%endif
@@ -203,7 +260,7 @@ return ${failure_return};
203260
auto numValHandlers = context.validationHandlers.size();
204261
for (size_t i = 0; i < numValHandlers; i++) {
205262
auto result = context.validationHandlers[i]->zeValidation->zexCounterBasedEventCreate2Prologue( hContext, hDevice, desc, phEvent );
206-
if(result!=ZE_RESULT_SUCCESS) return logAndPropagateResult("zexCounterBasedEventCreate2", result);
263+
if(result!=ZE_RESULT_SUCCESS) return logAndPropagateResult_zexCounterBasedEventCreate2(result, hContext, hDevice, desc, phEvent);
207264
}
208265

209266
if(context.enableThreadingValidation){
@@ -212,7 +269,7 @@ return ${failure_return};
212269

213270
if(context.enableHandleLifetime){
214271
auto result = context.handleLifetime->zeHandleLifetime.zexCounterBasedEventCreate2Prologue( hContext, hDevice, desc, phEvent );
215-
if(result!=ZE_RESULT_SUCCESS) return logAndPropagateResult("zexCounterBasedEventCreate2", result);
272+
if(result!=ZE_RESULT_SUCCESS) return logAndPropagateResult_zexCounterBasedEventCreate2(result, hContext, hDevice, desc, phEvent);
216273
}
217274

218275
// This is an experimental function that must be accessed through the extension mechanism
@@ -254,7 +311,7 @@ return ${failure_return};
254311

255312
for (size_t i = 0; i < numValHandlers; i++) {
256313
auto result = context.validationHandlers[i]->zeValidation->zexCounterBasedEventCreate2Epilogue( hContext, hDevice, desc, phEvent, driver_result);
257-
if(result!=ZE_RESULT_SUCCESS) return logAndPropagateResult("zexCounterBasedEventCreate2", result);
314+
if(result!=ZE_RESULT_SUCCESS) return logAndPropagateResult_zexCounterBasedEventCreate2(result, hContext, hDevice, desc, phEvent);
258315
}
259316

260317
if(driver_result == ZE_RESULT_SUCCESS && context.enableHandleLifetime){
@@ -263,7 +320,7 @@ return ${failure_return};
263320
// Note: counter-based events may not have a traditional event pool dependency
264321
}
265322
}
266-
return logAndPropagateResult("zexCounterBasedEventCreate2", driver_result);
323+
return logAndPropagateResult_zexCounterBasedEventCreate2(driver_result, hContext, hDevice, desc, phEvent);
267324
}
268325
%endif
269326
} // namespace validation_layer

0 commit comments

Comments
 (0)