Skip to content

Commit 4f80080

Browse files
authored
Merge pull request #930 from PatKamin/expose-serialization-c-api
[ur] Create printing C API
2 parents 2a82754 + cc1e0da commit 4f80080

File tree

13 files changed

+6261
-398
lines changed

13 files changed

+6261
-398
lines changed

include/ur_print.h

Lines changed: 3037 additions & 0 deletions
Large diffs are not rendered by default.

scripts/core/INTRO.rst

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -148,9 +148,12 @@ This allows the Unified Runtime shared library to be updated with additional sym
148148
Printing API
149149
------------
150150
## --validate=off
151-
The header "${x}_print.hpp" contains the "${x}::print" namespace with the output stream operator (<<) overloads for Unified Runtime objects.
151+
The header "${x}_print.hpp" contains output stream operator (<<) overloads for Unified Runtime objects.
152152
There is also the "${x}::extras::printFunctionParams" function for printing function parameters. These parameters have to be provided in a \*params_t struct format suitable for
153153
a given function.
154+
155+
The ${x}_print.h header provides the same functionality with a C interface. Each object has a print function named urPrint<object name without both prefix and suffix>,
156+
ie. for printing ur_result_t use urPrintResult.
154157
## --validate=on
155158

156159
Tracing

scripts/generate_code.py

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,44 @@ def _mako_ddi_h(path, namespace, tags, version, revision, specs, meta):
7070
specs=specs,
7171
meta=meta)
7272

73+
"""
74+
generates c/c++ files from the mako template
75+
"""
76+
def _mako_print_h(path, namespace, tags, version, specs, meta):
77+
template = "print.h.mako"
78+
fin = os.path.join("templates", template)
79+
80+
filename = "%s_print.h"%(namespace)
81+
fout = os.path.join(path, filename)
82+
83+
print("Generating %s..."%fout)
84+
return util.makoWrite(
85+
fin, fout,
86+
ver=version,
87+
namespace=namespace,
88+
tags=tags,
89+
specs=specs,
90+
meta=meta)
91+
92+
"""
93+
generates c/c++ files from the mako template
94+
"""
95+
def _mako_print_cpp(path, namespace, tags, version, specs, meta):
96+
template = "print.cpp.mako"
97+
fin = os.path.join("templates", template)
98+
99+
filename = "%s_print.cpp"%(namespace)
100+
fout = os.path.join(path, filename)
101+
102+
print("Generating %s..."%fout)
103+
return util.makoWrite(
104+
fin, fout,
105+
ver=version,
106+
namespace=namespace,
107+
tags=tags,
108+
specs=specs,
109+
meta=meta)
110+
73111
"""
74112
generates c/c++ files from the specification documents
75113
"""
@@ -90,6 +128,7 @@ def generate_api(incpath, srcpath, namespace, tags, version, revision, specs, me
90128
util.makePath(srcpath)
91129

92130
loc = 0
131+
loc += _mako_print_h(incpath, namespace, tags, version, specs, meta)
93132
loc += _generate_api_cpp(incpath, srcpath, namespace, tags, version, revision, specs, meta)
94133
print("Generated %s lines of code.\n"%loc)
95134

@@ -330,6 +369,7 @@ def generate_loader(path, section, namespace, tags, version, specs, meta):
330369

331370
loc = 0
332371
loc += _mako_loader_cpp(dstpath, namespace, tags, version, specs, meta)
372+
loc += _mako_print_cpp(dstpath, namespace, tags, version, specs, meta)
333373
print("Generated %s lines of code.\n"%loc)
334374

335375
"""

scripts/templates/helper.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -951,6 +951,17 @@ def make_func_name(namespace, tags, obj):
951951
cname = ''
952952
return subt(namespace, tags, "%s%s"%(cname, obj['name']))
953953

954+
"""
955+
Public:
956+
returns the name of a function from a given name with prefix
957+
"""
958+
def make_func_name_with_prefix(prefix, name):
959+
func_name = re.sub(r'^[^_]+_', '', name)
960+
func_name = re.sub('_t$', '', func_name).capitalize()
961+
func_name = re.sub(r'_([a-z])', lambda match: match.group(1).upper(), func_name)
962+
func_name = f'{prefix}{func_name}'
963+
return func_name
964+
954965
"""
955966
Public:
956967
returns the etor of a function

scripts/templates/print.cpp.mako

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
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+
*
12+
* Copyright (C) 2023 Intel Corporation
13+
*
14+
* Part of the Unified-Runtime Project, under the Apache License v2.0 with LLVM Exceptions.
15+
* See LICENSE.TXT
16+
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
17+
*
18+
* @file ${n}_print.cpp
19+
*
20+
*/
21+
22+
#include "${n}_print.h"
23+
#include "${n}_print.hpp"
24+
25+
#include <algorithm>
26+
#include <sstream>
27+
#include <string.h>
28+
29+
<%def name="ss_copy(item_name)">\
30+
std::stringstream ss;
31+
ss << ${item_name};
32+
return str_copy(&ss, buffer, buff_size, out_size);
33+
</%def>
34+
35+
${x}_result_t str_copy(std::stringstream *ss, char *buff, const size_t buff_size, size_t *out_size) {
36+
size_t c_str_size = strlen(ss->str().c_str()) + 1;
37+
if (out_size) {
38+
*out_size = c_str_size;
39+
}
40+
41+
if (buff) {
42+
if (buff_size < c_str_size) {
43+
return ${X}_RESULT_ERROR_INVALID_SIZE;
44+
}
45+
46+
#if defined(_WIN32)
47+
strncpy_s(buff, buff_size, ss->str().c_str(), c_str_size);
48+
#else
49+
strncpy(buff, ss->str().c_str(), std::min(buff_size, c_str_size));
50+
#endif
51+
}
52+
return ${X}_RESULT_SUCCESS;
53+
}
54+
55+
%for spec in specs:
56+
%for obj in spec['objects']:
57+
## ENUM #######################################################################
58+
%if re.match(r"enum", obj['type']):
59+
${x}_result_t ${th.make_func_name_with_prefix(f'{x}Print', obj['name'])}(enum ${th.make_enum_name(n, tags, obj)} value, char *buffer, const size_t buff_size, size_t *out_size) {
60+
${ss_copy("value")}
61+
}
62+
63+
## STRUCT #####################################################################
64+
%elif re.match(r"struct", obj['type']):
65+
${x}_result_t ${th.make_func_name_with_prefix(f'{x}Print', obj['name'])}(const ${obj['type']} ${th.make_type_name(n, tags, obj)} params, char *buffer, const size_t buff_size, size_t *out_size) {
66+
${ss_copy("params")}
67+
}
68+
69+
%endif
70+
%endfor # obj in spec['objects']
71+
%endfor
72+
73+
%for tbl in th.get_pfncbtables(specs, meta, n, tags):
74+
%for obj in tbl['functions']:
75+
<%
76+
name = th.make_pfncb_param_type(n, tags, obj)
77+
%>\
78+
${x}_result_t ${th.make_func_name_with_prefix(f'{x}Print', name)}(const struct ${th.make_pfncb_param_type(n, tags, obj)} *params, char *buffer, const size_t buff_size, size_t *out_size) {
79+
${ss_copy("params")}
80+
}
81+
82+
%endfor
83+
%endfor
84+
85+
${x}_result_t ${x}PrintFunctionParams(enum ${x}_function_t function, const void *params, char *buffer, const size_t buff_size, size_t *out_size) {
86+
if (!params) {
87+
return ${X}_RESULT_ERROR_INVALID_NULL_POINTER;
88+
}
89+
90+
std::stringstream ss;
91+
${x}_result_t result = ${x}::extras::printFunctionParams(ss, function, params);
92+
if (result != ${X}_RESULT_SUCCESS) {
93+
return result;
94+
}
95+
return str_copy(&ss, buffer, buff_size, out_size);
96+
}

scripts/templates/print.h.mako

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
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+
*
12+
* Copyright (C) 2023 Intel Corporation
13+
*
14+
* Part of the Unified-Runtime Project, under the Apache License v2.0 with LLVM Exceptions.
15+
* See LICENSE.TXT
16+
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
17+
*
18+
* @file ${n}_print.h
19+
*
20+
*/
21+
#ifndef ${X}_PRINT_H
22+
#define ${X}_PRINT_H 1
23+
24+
#include "${x}_api.h"
25+
26+
#if defined(__cplusplus)
27+
extern "C" {
28+
#endif
29+
30+
## Declarations ###############################################################
31+
%for spec in specs:
32+
%for obj in spec['objects']:
33+
%if re.match(r"enum", obj['type']):
34+
///////////////////////////////////////////////////////////////////////////////
35+
/// @brief Print ${th.make_enum_name(n, tags, obj)} enum
36+
/// @returns
37+
/// - ::${X}_RESULT_SUCCESS
38+
/// - ::${X}_RESULT_ERROR_INVALID_NULL_POINTER
39+
/// - `NULL == buffer`
40+
/// - ::${X}_RESULT_ERROR_INVALID_SIZE
41+
/// - `buff_size < out_size`
42+
${X}_APIEXPORT ${x}_result_t ${X}_APICALL ${th.make_func_name_with_prefix(f'{x}Print', obj['name'])}(enum ${th.make_enum_name(n, tags, obj)} value, char *buffer, const size_t buff_size, size_t *out_size);
43+
44+
%elif re.match(r"struct", obj['type']):
45+
///////////////////////////////////////////////////////////////////////////////
46+
/// @brief Print ${th.make_type_name(n, tags, obj)} struct
47+
/// @returns
48+
/// - ::${X}_RESULT_SUCCESS
49+
/// - ::${X}_RESULT_ERROR_INVALID_NULL_POINTER
50+
/// - `NULL == buffer`
51+
/// - ::${X}_RESULT_ERROR_INVALID_SIZE
52+
/// - `buff_size < out_size`
53+
${X}_APIEXPORT ${x}_result_t ${X}_APICALL ${th.make_func_name_with_prefix(f'{x}Print', obj['name'])}(const ${obj['type']} ${th.make_type_name(n, tags, obj)} params, char *buffer, const size_t buff_size, size_t *out_size);
54+
55+
%endif
56+
%endfor # obj in spec['objects']
57+
%endfor
58+
59+
%for tbl in th.get_pfncbtables(specs, meta, n, tags):
60+
%for obj in tbl['functions']:
61+
<%
62+
name = th.make_pfncb_param_type(n, tags, obj)
63+
%>
64+
///////////////////////////////////////////////////////////////////////////////
65+
/// @brief Print ${th.make_pfncb_param_type(n, tags, obj)} params struct
66+
/// @returns
67+
/// - ::${X}_RESULT_SUCCESS
68+
/// - ::${X}_RESULT_ERROR_INVALID_NULL_POINTER
69+
/// - `NULL == buffer`
70+
/// - ::${X}_RESULT_ERROR_INVALID_SIZE
71+
/// - `buff_size < out_size`
72+
${X}_APIEXPORT ${x}_result_t ${X}_APICALL ${th.make_func_name_with_prefix(f'{x}Print', name)}(const struct ${th.make_pfncb_param_type(n, tags, obj)} *params, char *buffer, const size_t buff_size, size_t *out_size);
73+
%endfor
74+
%endfor
75+
76+
///////////////////////////////////////////////////////////////////////////////
77+
/// @brief Print function parameters
78+
/// @returns
79+
/// - ::${X}_RESULT_SUCCESS
80+
/// - ::${X}_RESULT_ERROR_INVALID_ENUMERATION
81+
/// - ::${X}_RESULT_ERROR_INVALID_NULL_POINTER
82+
/// - `NULL == params`
83+
/// - `NULL == buffer`
84+
/// - ::${X}_RESULT_ERROR_INVALID_SIZE
85+
/// - `buff_size < out_size`
86+
${X}_APIEXPORT ${x}_result_t ${X}_APICALL ${x}PrintFunctionParams(enum ${x}_function_t function, const void *params, char *buffer, const size_t buff_size, size_t *out_size);
87+
88+
#if defined(__cplusplus)
89+
} // extern "C"
90+
#endif
91+
92+
#endif /* ${X}_PRINT_H */

source/loader/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,7 @@ target_sources(ur_loader
8989
${CMAKE_CURRENT_SOURCE_DIR}/ur_lib.hpp
9090
${CMAKE_CURRENT_SOURCE_DIR}/ur_lib.cpp
9191
${CMAKE_CURRENT_SOURCE_DIR}/ur_codeloc.hpp
92+
${CMAKE_CURRENT_SOURCE_DIR}/ur_print.cpp
9293
${CMAKE_CURRENT_SOURCE_DIR}/layers/validation/ur_valddi.cpp
9394
${CMAKE_CURRENT_SOURCE_DIR}/layers/validation/ur_validation_layer.cpp
9495
)

0 commit comments

Comments
 (0)