Skip to content

Commit

Permalink
Add C API for printing UR objects
Browse files Browse the repository at this point in the history
Add an /include header for printing Unified Runtime objects with a C API.
  • Loading branch information
PatKamin committed Jan 22, 2024
1 parent 92f44da commit cc1e0da
Show file tree
Hide file tree
Showing 13 changed files with 6,261 additions and 398 deletions.
3,037 changes: 3,037 additions & 0 deletions include/ur_print.h

Large diffs are not rendered by default.

5 changes: 4 additions & 1 deletion scripts/core/INTRO.rst
Original file line number Diff line number Diff line change
Expand Up @@ -148,9 +148,12 @@ This allows the Unified Runtime shared library to be updated with additional sym
Printing API
------------
## --validate=off
The header "${x}_print.hpp" contains the "${x}::print" namespace with the output stream operator (<<) overloads for Unified Runtime objects.
The header "${x}_print.hpp" contains output stream operator (<<) overloads for Unified Runtime objects.
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
a given function.

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>,
ie. for printing ur_result_t use urPrintResult.
## --validate=on

Tracing
Expand Down
40 changes: 40 additions & 0 deletions scripts/generate_code.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,44 @@ def _mako_ddi_h(path, namespace, tags, version, revision, specs, meta):
specs=specs,
meta=meta)

"""
generates c/c++ files from the mako template
"""
def _mako_print_h(path, namespace, tags, version, specs, meta):
template = "print.h.mako"
fin = os.path.join("templates", template)

filename = "%s_print.h"%(namespace)
fout = os.path.join(path, filename)

print("Generating %s..."%fout)
return util.makoWrite(
fin, fout,
ver=version,
namespace=namespace,
tags=tags,
specs=specs,
meta=meta)

"""
generates c/c++ files from the mako template
"""
def _mako_print_cpp(path, namespace, tags, version, specs, meta):
template = "print.cpp.mako"
fin = os.path.join("templates", template)

filename = "%s_print.cpp"%(namespace)
fout = os.path.join(path, filename)

print("Generating %s..."%fout)
return util.makoWrite(
fin, fout,
ver=version,
namespace=namespace,
tags=tags,
specs=specs,
meta=meta)

"""
generates c/c++ files from the specification documents
"""
Expand All @@ -90,6 +128,7 @@ def generate_api(incpath, srcpath, namespace, tags, version, revision, specs, me
util.makePath(srcpath)

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

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

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

"""
Expand Down
11 changes: 11 additions & 0 deletions scripts/templates/helper.py
Original file line number Diff line number Diff line change
Expand Up @@ -937,6 +937,17 @@ def make_func_name(namespace, tags, obj):
cname = ''
return subt(namespace, tags, "%s%s"%(cname, obj['name']))

"""
Public:
returns the name of a function from a given name with prefix
"""
def make_func_name_with_prefix(prefix, name):
func_name = re.sub(r'^[^_]+_', '', name)
func_name = re.sub('_t$', '', func_name).capitalize()
func_name = re.sub(r'_([a-z])', lambda match: match.group(1).upper(), func_name)
func_name = f'{prefix}{func_name}'
return func_name

"""
Public:
returns the etor of a function
Expand Down
96 changes: 96 additions & 0 deletions scripts/templates/print.cpp.mako
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
<%!
import re
from templates import helper as th
%><%
n=namespace
N=n.upper()
x=tags['$x']
X=x.upper()
%>/*
*
* Copyright (C) 2023 Intel Corporation
*
* Part of the Unified-Runtime Project, under the Apache License v2.0 with LLVM Exceptions.
* See LICENSE.TXT
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
*
* @file ${n}_print.cpp
*
*/

#include "${n}_print.h"
#include "${n}_print.hpp"

#include <algorithm>
#include <sstream>
#include <string.h>

<%def name="ss_copy(item_name)">\
std::stringstream ss;
ss << ${item_name};
return str_copy(&ss, buffer, buff_size, out_size);
</%def>

${x}_result_t str_copy(std::stringstream *ss, char *buff, const size_t buff_size, size_t *out_size) {
size_t c_str_size = strlen(ss->str().c_str()) + 1;
if (out_size) {
*out_size = c_str_size;
}

if (buff) {
if (buff_size < c_str_size) {
return ${X}_RESULT_ERROR_INVALID_SIZE;
}

#if defined(_WIN32)
strncpy_s(buff, buff_size, ss->str().c_str(), c_str_size);
#else
strncpy(buff, ss->str().c_str(), std::min(buff_size, c_str_size));
#endif
}
return ${X}_RESULT_SUCCESS;
}

%for spec in specs:
%for obj in spec['objects']:
## ENUM #######################################################################
%if re.match(r"enum", obj['type']):
${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) {
${ss_copy("value")}
}

## STRUCT #####################################################################
%elif re.match(r"struct", obj['type']):
${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) {
${ss_copy("params")}
}

%endif
%endfor # obj in spec['objects']
%endfor

%for tbl in th.get_pfncbtables(specs, meta, n, tags):
%for obj in tbl['functions']:
<%
name = th.make_pfncb_param_type(n, tags, obj)
%>\
${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) {
${ss_copy("params")}
}

%endfor
%endfor

${x}_result_t ${x}PrintFunctionParams(enum ${x}_function_t function, const void *params, char *buffer, const size_t buff_size, size_t *out_size) {
if (!params) {
return ${X}_RESULT_ERROR_INVALID_NULL_POINTER;
}

std::stringstream ss;
${x}_result_t result = ${x}::extras::printFunctionParams(ss, function, params);
if (result != ${X}_RESULT_SUCCESS) {
return result;
}
return str_copy(&ss, buffer, buff_size, out_size);
}
92 changes: 92 additions & 0 deletions scripts/templates/print.h.mako
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
<%!
import re
from templates import helper as th
%><%
n=namespace
N=n.upper()
x=tags['$x']
X=x.upper()
%>/*
*
* Copyright (C) 2023 Intel Corporation
*
* Part of the Unified-Runtime Project, under the Apache License v2.0 with LLVM Exceptions.
* See LICENSE.TXT
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
*
* @file ${n}_print.h
*
*/
#ifndef ${X}_PRINT_H
#define ${X}_PRINT_H 1

#include "${x}_api.h"

#if defined(__cplusplus)
extern "C" {
#endif

## Declarations ###############################################################
%for spec in specs:
%for obj in spec['objects']:
%if re.match(r"enum", obj['type']):
///////////////////////////////////////////////////////////////////////////////
/// @brief Print ${th.make_enum_name(n, tags, obj)} enum
/// @returns
/// - ::${X}_RESULT_SUCCESS
/// - ::${X}_RESULT_ERROR_INVALID_NULL_POINTER
/// - `NULL == buffer`
/// - ::${X}_RESULT_ERROR_INVALID_SIZE
/// - `buff_size < out_size`
${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);

%elif re.match(r"struct", obj['type']):
///////////////////////////////////////////////////////////////////////////////
/// @brief Print ${th.make_type_name(n, tags, obj)} struct
/// @returns
/// - ::${X}_RESULT_SUCCESS
/// - ::${X}_RESULT_ERROR_INVALID_NULL_POINTER
/// - `NULL == buffer`
/// - ::${X}_RESULT_ERROR_INVALID_SIZE
/// - `buff_size < out_size`
${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);

%endif
%endfor # obj in spec['objects']
%endfor

%for tbl in th.get_pfncbtables(specs, meta, n, tags):
%for obj in tbl['functions']:
<%
name = th.make_pfncb_param_type(n, tags, obj)
%>
///////////////////////////////////////////////////////////////////////////////
/// @brief Print ${th.make_pfncb_param_type(n, tags, obj)} params struct
/// @returns
/// - ::${X}_RESULT_SUCCESS
/// - ::${X}_RESULT_ERROR_INVALID_NULL_POINTER
/// - `NULL == buffer`
/// - ::${X}_RESULT_ERROR_INVALID_SIZE
/// - `buff_size < out_size`
${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);
%endfor
%endfor

///////////////////////////////////////////////////////////////////////////////
/// @brief Print function parameters
/// @returns
/// - ::${X}_RESULT_SUCCESS
/// - ::${X}_RESULT_ERROR_INVALID_ENUMERATION
/// - ::${X}_RESULT_ERROR_INVALID_NULL_POINTER
/// - `NULL == params`
/// - `NULL == buffer`
/// - ::${X}_RESULT_ERROR_INVALID_SIZE
/// - `buff_size < out_size`
${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);

#if defined(__cplusplus)
} // extern "C"
#endif

#endif /* ${X}_PRINT_H */
1 change: 1 addition & 0 deletions source/loader/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ target_sources(ur_loader
${CMAKE_CURRENT_SOURCE_DIR}/ur_lib.hpp
${CMAKE_CURRENT_SOURCE_DIR}/ur_lib.cpp
${CMAKE_CURRENT_SOURCE_DIR}/ur_codeloc.hpp
${CMAKE_CURRENT_SOURCE_DIR}/ur_print.cpp
${CMAKE_CURRENT_SOURCE_DIR}/layers/validation/ur_valddi.cpp
${CMAKE_CURRENT_SOURCE_DIR}/layers/validation/ur_validation_layer.cpp
)
Expand Down
Loading

0 comments on commit cc1e0da

Please sign in to comment.