chore: import upstream snapshot with attribution
cffconvert / validate (push) Has been skipped
License Check / license-check (push) Failing after 2s

This commit is contained in:
wehub-resource-sync
2026-07-13 12:14:16 +08:00
commit 8a852e4b4e
36502 changed files with 9277225 additions and 0 deletions
+165
View File
@@ -0,0 +1,165 @@
load("//tensorflow:tensorflow.default.bzl", "filegroup")
load("//tensorflow/core/platform:rules_cc.bzl", "cc_library")
# Experimental ops. These will eventually be replaced by machine-generated versions.
package(
# copybara:uncomment default_applicable_licenses = ["//tensorflow:license"],
licenses = ["notice"],
)
cc_library(
name = "array_ops",
srcs = [
"array_ops.cc",
],
hdrs = [
"array_ops.h",
],
visibility = [
"//tensorflow:internal",
],
deps = [
"//tensorflow/c/eager:abstract_context",
"//tensorflow/c/eager:abstract_operation",
"//tensorflow/c/eager:abstract_tensor_handle",
"//tensorflow/c/eager:tracing_utils",
"//tensorflow/core:framework_types_hdr",
"//tensorflow/core:protos_all_cc",
"//tensorflow/core/platform:errors",
"@com_google_absl//absl/status",
"@com_google_absl//absl/types:span",
],
)
cc_library(
name = "io_ops",
srcs = [
"io_ops.cc",
],
hdrs = [
"io_ops.h",
],
visibility = [
"//tensorflow:internal",
],
deps = [
"//tensorflow/c/eager:abstract_context",
"//tensorflow/c/eager:abstract_operation",
"//tensorflow/c/eager:abstract_tensor_handle",
"//tensorflow/c/eager:tracing_utils",
"//tensorflow/core:framework_types_hdr",
"//tensorflow/core:protos_all_cc",
"//tensorflow/core/platform:errors",
"@com_google_absl//absl/status",
"@com_google_absl//absl/types:span",
],
)
cc_library(
name = "math_ops",
srcs = [
"math_ops.cc",
],
hdrs = [
"math_ops.h",
],
visibility = [
"//tensorflow:internal",
],
deps = [
"//tensorflow/c/eager:abstract_context",
"//tensorflow/c/eager:abstract_operation",
"//tensorflow/c/eager:abstract_tensor_handle",
"//tensorflow/c/eager:tracing_utils",
"//tensorflow/core:framework_types_hdr",
"//tensorflow/core/platform:errors",
"@com_google_absl//absl/status",
"@com_google_absl//absl/types:span",
],
)
cc_library(
name = "nn_ops",
srcs = [
"nn_ops.cc",
],
hdrs = [
"nn_ops.h",
],
visibility = [
"//tensorflow:internal",
],
deps = [
"//tensorflow/c/eager:abstract_context",
"//tensorflow/c/eager:abstract_operation",
"//tensorflow/c/eager:abstract_tensor_handle",
"//tensorflow/c/eager:tracing_utils",
"//tensorflow/core:framework_types_hdr",
"//tensorflow/core/platform:errors",
"@com_google_absl//absl/status",
"@com_google_absl//absl/types:span",
],
)
cc_library(
name = "resource_variable_ops",
srcs = [
"resource_variable_ops.cc",
],
hdrs = [
"resource_variable_ops.h",
],
visibility = [
"//tensorflow:internal",
],
deps = [
"//tensorflow/c/eager:abstract_context",
"//tensorflow/c/eager:abstract_operation",
"//tensorflow/c/eager:abstract_tensor_handle",
"//tensorflow/c/eager:tracing_utils",
"//tensorflow/core:framework",
"//tensorflow/core:protos_all_cc",
"//tensorflow/core/platform:errors",
"@com_google_absl//absl/status",
"@com_google_absl//absl/types:span",
],
)
cc_library(
name = "ops",
hdrs = [
"array_ops.h",
"io_ops.h",
"math_ops.h",
"nn_ops.h",
"resource_variable_ops.h",
],
visibility = [
"//tensorflow:internal",
],
deps = [
":array_ops",
":io_ops",
":math_ops",
":nn_ops",
":resource_variable_ops",
"//tensorflow/c/eager:abstract_context",
"//tensorflow/c/eager:abstract_tensor_handle",
"//tensorflow/core:framework",
"//tensorflow/core:protos_all_cc",
"@com_google_absl//absl/status",
"@com_google_absl//absl/types:span",
],
)
filegroup(
name = "pywrap_required_hdrs",
srcs = [
"array_ops.h",
"io_ops.h",
"math_ops.h",
"nn_ops.h",
"resource_variable_ops.h",
],
visibility = ["//tensorflow/python:__subpackages__"],
)
+20
View File
@@ -0,0 +1,20 @@
# Experimental C++ Ops
The C++ files in this directory (***\*_ops.h*** and ***\*_ops.cc***) are
autogenerated from the registered Op and API definitions.
To regenerate them, run the script in this directory, `update_cpp_ops.sh`, with
no arguments. This script will overwrite the existing ops in-place at
***tensorflow/c/experimental/ops/\*_ops.{cc,h}***.
Run this `update_cpp_ops.sh` script when Op definitions change in the registry.
To generate additional operators, extend the lists in this script. Note that
category names correspond to generated source file names, and should be
consistent with the original source files registering each operator. For example
since `REGISTER_OP("MatMul")` appears in ***core/math_ops.cc***, the "MatMul"
operator in the script should be in the "math" category, and it will be
generated in the output file `c/experimental/ops/math_ops.cc`.
Running this script should be a no-op, generating identical code other than
formatting (i.e., line wrapping).
+210
View File
@@ -0,0 +1,210 @@
/* Copyright 2021 The TensorFlow Authors. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/
// This file is MACHINE GENERATED! Do not edit.
#include "tensorflow/c/experimental/ops/array_ops.h"
#include "absl/status/status.h"
#include "absl/types/span.h"
#include "tensorflow/c/eager/abstract_context.h"
#include "tensorflow/c/eager/abstract_operation.h"
#include "tensorflow/c/eager/abstract_tensor_handle.h"
#include "tensorflow/c/eager/tracing_utils.h"
#include "tensorflow/core/framework/types.h" // NOLINT
#include "tensorflow/core/framework/types.pb.h"
#include "tensorflow/core/platform/errors.h" // NOLINT
using tensorflow::tracing::MaybeSetOpName;
namespace tensorflow {
namespace ops {
// Op: Identity()
// Summary: Return a tensor with the same shape and contents as the input tensor
// or value.
//
// Description:
absl::Status Identity(AbstractContext* ctx, AbstractTensorHandle* const input,
AbstractTensorHandle** output, const char* name,
const char* raw_device_name) {
AbstractOperationPtr op_ptr(ctx->CreateOperation());
TF_RETURN_IF_ERROR(op_ptr->Reset("Identity", raw_device_name));
TF_RETURN_IF_ERROR(MaybeSetOpName(op_ptr.get(), name));
TF_RETURN_IF_ERROR(op_ptr->AddInput(input));
int num_retvals = 1;
TF_RETURN_IF_ERROR(op_ptr->Execute(absl::MakeSpan(output, 1), &num_retvals));
if (num_retvals != 1) {
return absl::InternalError("Identity: unexpected number of outputs");
}
return absl::OkStatus();
}
// Op: IdentityN()
// Summary: Returns a list of tensors with the same shapes and contents as the
// input
//
// Description:
// tensors.
//
// This op can be used to override the gradient for complicated functions. For
// example, suppose y = f(x) and we wish to apply a custom function g for
// backprop such that dx = g(dy). In Python,
//
// ```python
// with tf.get_default_graph().gradient_override_map(
// {'IdentityN': 'OverrideGradientWithG'}):
// y, _ = identity_n([f(x), x])
//
// @tf.RegisterGradient('OverrideGradientWithG')
// def ApplyG(op, dy, _):
// return [None, g(dy)] # Do not backprop to f(x).
// ```
absl::Status IdentityN(AbstractContext* ctx,
absl::Span<AbstractTensorHandle* const> input,
absl::Span<AbstractTensorHandle*> output,
const char* name, const char* raw_device_name) {
AbstractOperationPtr op_ptr(ctx->CreateOperation());
TF_RETURN_IF_ERROR(op_ptr->Reset("IdentityN", raw_device_name));
TF_RETURN_IF_ERROR(MaybeSetOpName(op_ptr.get(), name));
TF_RETURN_IF_ERROR(op_ptr->AddInputList(input));
int num_retvals = output.size();
TF_RETURN_IF_ERROR(op_ptr->Execute(output, &num_retvals));
if (num_retvals != output.size()) {
return absl::InternalError("IdentityN: unexpected number of outputs");
}
return absl::OkStatus();
}
// Op: ZerosLike()
// Summary: Returns a tensor of zeros with the same shape and type as x.
//
// Description:
absl::Status ZerosLike(AbstractContext* ctx, AbstractTensorHandle* const x,
AbstractTensorHandle** y, const char* name,
const char* raw_device_name) {
AbstractOperationPtr op_ptr(ctx->CreateOperation());
TF_RETURN_IF_ERROR(op_ptr->Reset("ZerosLike", raw_device_name));
TF_RETURN_IF_ERROR(MaybeSetOpName(op_ptr.get(), name));
TF_RETURN_IF_ERROR(op_ptr->AddInput(x));
int num_retvals = 1;
TF_RETURN_IF_ERROR(op_ptr->Execute(absl::MakeSpan(y, 1), &num_retvals));
if (num_retvals != 1) {
return absl::InternalError("ZerosLike: unexpected number of outputs");
}
return absl::OkStatus();
}
// Op: Shape()
// Summary: Returns the shape of a tensor.
//
// Description:
// This operation returns a 1-D integer tensor representing the shape of
// `input`.
//
// For example:
//
// ```
// # 't' is [[[1, 1, 1], [2, 2, 2]], [[3, 3, 3], [4, 4, 4]]]
// shape(t) ==> [2, 2, 3]
// ```
absl::Status Shape(AbstractContext* ctx, AbstractTensorHandle* const input,
AbstractTensorHandle** output, DataType out_type,
const char* name, const char* raw_device_name) {
AbstractOperationPtr op_ptr(ctx->CreateOperation());
TF_RETURN_IF_ERROR(op_ptr->Reset("Shape", raw_device_name));
TF_RETURN_IF_ERROR(MaybeSetOpName(op_ptr.get(), name));
TF_RETURN_IF_ERROR(op_ptr->AddInput(input));
TF_RETURN_IF_ERROR(op_ptr->SetAttrType("out_type", out_type));
int num_retvals = 1;
TF_RETURN_IF_ERROR(op_ptr->Execute(absl::MakeSpan(output, 1), &num_retvals));
if (num_retvals != 1) {
return absl::InternalError("Shape: unexpected number of outputs");
}
return absl::OkStatus();
}
// Op: ExpandDims()
// Summary: Inserts a dimension of 1 into a tensor's shape.
//
// Description:
// Given a tensor `input`, this operation inserts a dimension of 1 at the
// dimension index `axis` of `input`'s shape. The dimension index `axis`
// starts at zero; if you specify a negative number for `axis` it is counted
// backward from the end.
//
// This operation is useful if you want to add a batch dimension to a single
// element. For example, if you have a single image of shape `[height, width,
// channels]`, you can make it a batch of 1 image with `expand_dims(image,
// 0)`, which will make the shape `[1, height, width, channels]`.
//
// Other examples:
//
// ```
// # 't' is a tensor of shape [2]
// shape(expand_dims(t, 0)) ==> [1, 2]
// shape(expand_dims(t, 1)) ==> [2, 1]
// shape(expand_dims(t, -1)) ==> [2, 1]
//
// # 't2' is a tensor of shape [2, 3, 5]
// shape(expand_dims(t2, 0)) ==> [1, 2, 3, 5]
// shape(expand_dims(t2, 2)) ==> [2, 3, 1, 5]
// shape(expand_dims(t2, 3)) ==> [2, 3, 5, 1]
// ```
//
// This operation requires that:
//
// `-1-input.dims() <= dim <= input.dims()`
//
// This operation is related to `squeeze()`, which removes dimensions of
// size 1.
absl::Status ExpandDims(AbstractContext* ctx, AbstractTensorHandle* const input,
AbstractTensorHandle* const dim,
AbstractTensorHandle** output, const char* name,
const char* raw_device_name) {
AbstractOperationPtr op_ptr(ctx->CreateOperation());
TF_RETURN_IF_ERROR(op_ptr->Reset("ExpandDims", raw_device_name));
TF_RETURN_IF_ERROR(MaybeSetOpName(op_ptr.get(), name));
TF_RETURN_IF_ERROR(op_ptr->AddInput(input));
TF_RETURN_IF_ERROR(op_ptr->AddInput(dim));
int num_retvals = 1;
TF_RETURN_IF_ERROR(op_ptr->Execute(absl::MakeSpan(output, 1), &num_retvals));
if (num_retvals != 1) {
return absl::InternalError("ExpandDims: unexpected number of outputs");
}
return absl::OkStatus();
}
// Op: OnesLike()
// Summary: Returns a tensor of ones with the same shape and type as x.
//
// Description:
absl::Status OnesLike(AbstractContext* ctx, AbstractTensorHandle* const x,
AbstractTensorHandle** y, const char* name,
const char* raw_device_name) {
AbstractOperationPtr op_ptr(ctx->CreateOperation());
TF_RETURN_IF_ERROR(op_ptr->Reset("OnesLike", raw_device_name));
TF_RETURN_IF_ERROR(MaybeSetOpName(op_ptr.get(), name));
TF_RETURN_IF_ERROR(op_ptr->AddInput(x));
int num_retvals = 1;
TF_RETURN_IF_ERROR(op_ptr->Execute(absl::MakeSpan(y, 1), &num_retvals));
if (num_retvals != 1) {
return absl::InternalError("OnesLike: unexpected number of outputs");
}
return absl::OkStatus();
}
} // namespace ops
} // namespace tensorflow
+70
View File
@@ -0,0 +1,70 @@
/* Copyright 2021 The TensorFlow Authors. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/
// This file is MACHINE GENERATED! Do not edit.
#ifndef TENSORFLOW_C_EXPERIMENTAL_OPS_ARRAY_OPS_H_
#define TENSORFLOW_C_EXPERIMENTAL_OPS_ARRAY_OPS_H_
#include "absl/status/status.h"
#include "absl/types/span.h"
#include "tensorflow/c/eager/abstract_context.h"
#include "tensorflow/c/eager/abstract_tensor_handle.h"
#include "tensorflow/core/framework/types.h" // NOLINT
#include "tensorflow/core/framework/types.pb.h"
namespace tensorflow {
namespace ops {
// Return a tensor with the same shape and contents as the input tensor or
// value.
absl::Status Identity(AbstractContext* ctx, AbstractTensorHandle* const input,
AbstractTensorHandle** output, const char* name = nullptr,
const char* raw_device_name = nullptr);
// Returns a list of tensors with the same shapes and contents as the input
absl::Status IdentityN(AbstractContext* ctx,
absl::Span<AbstractTensorHandle* const> input,
absl::Span<AbstractTensorHandle*> output,
const char* name = nullptr,
const char* raw_device_name = nullptr);
// Returns a tensor of zeros with the same shape and type as x.
absl::Status ZerosLike(AbstractContext* ctx, AbstractTensorHandle* const x,
AbstractTensorHandle** y, const char* name = nullptr,
const char* raw_device_name = nullptr);
// Returns the shape of a tensor.
absl::Status Shape(AbstractContext* ctx, AbstractTensorHandle* const input,
AbstractTensorHandle** output, DataType out_type = DT_INT32,
const char* name = nullptr,
const char* raw_device_name = nullptr);
// Inserts a dimension of 1 into a tensor's shape.
absl::Status ExpandDims(AbstractContext* ctx, AbstractTensorHandle* const input,
AbstractTensorHandle* const dim,
AbstractTensorHandle** output,
const char* name = nullptr,
const char* raw_device_name = nullptr);
// Returns a tensor of ones with the same shape and type as x.
absl::Status OnesLike(AbstractContext* ctx, AbstractTensorHandle* const x,
AbstractTensorHandle** y, const char* name = nullptr,
const char* raw_device_name = nullptr);
} // namespace ops
} // namespace tensorflow
#endif // TENSORFLOW_C_EXPERIMENTAL_OPS_ARRAY_OPS_H_
+36
View File
@@ -0,0 +1,36 @@
load("@rules_cc//cc:cc_library.bzl", "cc_library")
load(
"//tensorflow:tensorflow.bzl",
"tf_cc_binary",
)
package(
# copybara:uncomment default_applicable_licenses = ["//tensorflow:license"],
default_visibility = ["//visibility:public"],
licenses = ["notice"],
)
cc_library(
name = "generate_cpp_main",
srcs = ["generate_cpp_main.cc"],
deps = [
"@com_google_absl//absl/log",
"@com_google_absl//absl/log:check",
"@com_google_absl//absl/strings",
"//tensorflow/c/experimental/ops/gen/common",
"//tensorflow/c/experimental/ops/gen/cpp/renderers",
"//tensorflow/core:framework",
"//tensorflow/core:framework_internal",
"//tensorflow/c/experimental/ops/gen/cpp",
"//tensorflow/c/experimental/ops/gen/model",
"//tensorflow/core:lib",
# Without this line to link in ops, the global registry will be empty:
"//tensorflow/core:ops",
],
)
tf_cc_binary(
name = "generate_cpp",
args = ["--stderrthreshold=1"], # Warnings and errors to stderr.
deps = [":generate_cpp_main"],
)
+116
View File
@@ -0,0 +1,116 @@
# TensorFlow Op CodeGen Machinery (Experimental)
## Usage
```
usage: generate_cpp [flags] OpName1 [OpName2 ...]
Flags:
--help=false bool Print this help message.
--category="" string Category for generated ops (e.g. 'math', 'array').
--namespace="" string Compact C++ namespace, default is 'tensorflow::ops'.
--output_dir="" string Directory into which output files will be generated.
--source_dir="" string The tensorflow root directory, e.g. 'tensorflow/' for in-source include paths. Any path underneath the tensorflow root is also accepted.
--api_dirs="" string Comma-separated list of directories containing API definitions.
```
## Design
### Generator Framework
The generator framework is a loose Model/View/Controller arrangement:
The *Model* classes live in the ***model/*** directory. They are representations
of the `OpDef` and `ApiDef` protos, normalized and resolved.
> _For example, an `OpDef` proto's `ArgDef` members contain a type string, which
> must be dereferenced to an `AttrDef` by name to determine its type. This
> `AttrDef` proto message in turn contains a type string which may need to be
> parsed as "list(type)". Other `AttrDef` messages are not types, but instead
> argument-like modifiers. In contrast, the generator model `ArgSpec` contains a
> resolved `ArgType` which provides a boolean `is_list()` method directly, and
> the model `OpSpec` provides a list of only the argument-like attributes. In
> addition to convenience, this should aid consistency between generated code in
> each target language._
The *Controller* is in the ***common/*** directory. It is the workhorse used by
the language generators; it digests the Op registry and API definitions to build
the model and provides utilities for the language generators.
The *View* and rendering classes map the language-independent Model classes
(`OpSpec`, `ArgSpec`, `AttrSpec`, etc.) to language-specific `SourceCode`. The
framework does not impose any design on the language-specific generators, but
provides some utilities, and the C++ generator is a complete example.
### C++ Generator
The `CppGenerator` class is the interface to the `cpp/` language directory.
Given a config, it can generate source code for a .cc or .h file as a string or
write it to a target file.
The `CppFileRenderer` is the main renderer used by the generator; it renders an
entire file. The `CppConfig` defines if it is operating in header or source
mode.
"Views" are stateless and intended to be low-level building blocks: a direct
language-specific representation of the model classes. For example, an `ArgView`
is initialized from an `ArgSpec` (which was created initially from an `ArgDef`
proto message). Where they may have some similar methods between the model and
view, the view methods are language-specific.
For instance, the C++ generator's `ArgView::VariableName()` method is an
language-formatted name usable as a variable representing the model `ArgSpec`
object. In contrast, the `ArgSpec::name()` method in the model refers to the
canonical name of the object in the proto.
Where views are a representation of the *input* model, in the C++ generator,
"renderers" then use these views to build the *output* `SourceCode`; Renderers
understand the language at the statement/directive level and target a functional
section of the output, such as a block comment or an entire method or file.
Other differences between views and renderers:
* Renderers are stateful, modifying a referenced SourceCode. Views are
stateless and their public methods are all const, returning strings.
* Renderers are context-dependent, e.g. a method signature will include
default values when in "declaration" mode but not "definition" mode. A view
of some argument object simply knows its default value and does not care the
context.
* In terms of dependencies, `Renderers` use `Views` and other `Renderers`.
However, `Renderers` do **not** reference the model directly (e.g.
`OpSpec`). This is because if a renderer needs to reference part of the
model, it should get a language specific representation.
### Extending to Additional Languages
The design for the C++ generator should apply to other languages, and the
underlying generator framework (the model and controller) try to be agnostic. In
fact, some elements of the C++ design could be formalized (such as the
rendering/view framework) or re-used (e.g. `cpp:Renderer` could likely be shared
with C and Java as a common C-style language renderer base class).
Abstracted and condensed from the C++ generator, the overall control flow could
be described as follows:
From main() in *generate_lang_main.cc*:
* Call `tensorflow::port::InitMain` and parse any flags
* Initialize config objects (e.g. `PathConfig`, `LangConfig` from flags)
* Initialize a new `LangGenerator` from these config objects
* Call this generator to create/write `SourceCode` to a file
In class `LangGenerator` in *lang_generator.cc*:
* Initialize a new `Controller` from the config objects
* Call this controller to build the Op models (`OpSpec`)
* Initialize a new language-specific `View` for each model object
* Create a blank `SourceCode` rendering target (for each output file)
* Initialize a new `LangFileRenderer` from this target source code, the model
`View` objects, and config objects
* Call this renderer to generate the target `SourceCode`
The dependencies are as follows:
* `lang::Generator` depends on `Controller`, `Model`, `lang::Renderers`,
`lang::Views`
* `lang::Renderer` depends on `lang::View` (and `lang::Renderer` peers)
* `lang::View` depends on the model (e.g. `OpSpec`) (and `lang::View` peers)
@@ -0,0 +1,49 @@
load("@rules_cc//cc:cc_library.bzl", "cc_library")
load(
"//tensorflow:tensorflow.bzl",
"tf_cc_tests",
)
package(
# copybara:uncomment default_applicable_licenses = ["//tensorflow:license"],
default_visibility = ["//visibility:public"],
licenses = ["notice"],
)
cc_library(
name = "common",
srcs = glob(
["*.cc"],
exclude = ["*_test.cc"],
),
hdrs = glob(["*.h"]),
deps = [
"//tensorflow/c/experimental/ops/gen/model",
"//tensorflow/core:framework",
"//tensorflow/core:framework_internal",
"//tensorflow/core:lib",
"//tensorflow/core:lib_internal",
"//tensorflow/core:op_gen_lib",
"//tensorflow/core:protos_all_cc",
"//tensorflow/core/platform:str_util",
"@com_google_absl//absl/log",
"@com_google_absl//absl/log:check",
"@com_google_absl//absl/strings",
],
alwayslink = 1,
)
tf_cc_tests(
name = "all_tests",
size = "small",
srcs = glob(["*_test.cc"]),
deps = [
":common",
"//tensorflow/core:core_cpu",
"//tensorflow/core:framework",
"//tensorflow/core:test",
"//tensorflow/core:test_main",
"//tensorflow/core:testlib",
"//tensorflow/core/platform:types",
],
)
@@ -0,0 +1,107 @@
/* Copyright 2021 The TensorFlow Authors. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/
#include "tensorflow/c/experimental/ops/gen/common/case_format.h"
#include <string>
#include "absl/strings/ascii.h"
#include "tensorflow/core/platform/types.h"
namespace tensorflow {
namespace generator {
namespace {
enum CaseFormatType {
LOWER_CAMEL,
UPPER_CAMEL,
LOWER_SNAKE,
UPPER_SNAKE,
};
std::string FormatStringCase(const std::string& str, CaseFormatType to,
const char delimiter = '_') {
const bool from_snake = (str == absl::AsciiStrToUpper(str)) ||
(str == absl::AsciiStrToLower(str));
const bool toUpper = (to == UPPER_CAMEL || to == UPPER_SNAKE);
const bool toSnake = (to == LOWER_SNAKE || to == UPPER_SNAKE);
std::string result;
bool inputStart = true;
bool wordStart = true;
for (const char c : str) {
// Find a word start.
if (c == delimiter) {
// Repeated cases of wordStart means explicit delimiter usage.
if (wordStart) {
result.push_back(delimiter);
}
wordStart = true;
continue;
}
if (!from_snake && absl::ascii_isupper(c)) {
wordStart = true;
}
// add delimiter
if (wordStart && toSnake && !inputStart) {
result.push_back(delimiter);
}
// add the next letter from the input string (choosing upper/lower case)
const bool shouldCapIfSnake = toUpper;
const bool shouldCapIfCamel = wordStart && (toUpper || !inputStart);
if ((toSnake && shouldCapIfSnake) || (!toSnake && shouldCapIfCamel)) {
result += absl::ascii_toupper(c);
} else {
result += absl::ascii_tolower(c);
}
// at this point we are no longer at the start of a word:
wordStart = false;
// .. or the input:
inputStart = false;
}
if (wordStart) {
// This only happens with a trailing delimiter, which should remain.
result.push_back(delimiter);
}
return result;
}
} // namespace
//
// Public interface
//
std::string toLowerCamel(const std::string& s, const char delimiter) {
return FormatStringCase(s, LOWER_CAMEL, delimiter);
}
std::string toLowerSnake(const std::string& s, const char delimiter) {
return FormatStringCase(s, LOWER_SNAKE, delimiter);
}
std::string toUpperCamel(const std::string& s, const char delimiter) {
return FormatStringCase(s, UPPER_CAMEL, delimiter);
}
std::string toUpperSnake(const std::string& s, const char delimiter) {
return FormatStringCase(s, UPPER_SNAKE, delimiter);
}
} // namespace generator
} // namespace tensorflow
@@ -0,0 +1,46 @@
/* Copyright 2021 The TensorFlow Authors. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/
#ifndef TENSORFLOW_C_EXPERIMENTAL_OPS_GEN_COMMON_CASE_FORMAT_H_
#define TENSORFLOW_C_EXPERIMENTAL_OPS_GEN_COMMON_CASE_FORMAT_H_
#include "tensorflow/core/platform/str_util.h"
#include "tensorflow/core/platform/types.h"
namespace tensorflow {
namespace generator {
// Conversion routines between upper/lower camel/snake case formats, e.g.:
// "lowerCamelCase"
// "lower_snake_case"
// "UpperCamelCase"
// "UPPER_SNAKE_CASE"
//
// The input format is automatically detected.
// The delimiter must be specified if it is other than an underscore ('_')
// for conversion either *to* or *from* snake case.
//
// Leading and trailing delimiters are supported, e.g.:
// "__OneTwo__" (in camel case) <==> "__ONE_TWO__" (in snake case)
//
// Note: performance not yet tested.
std::string toLowerCamel(const std::string& s, const char delimiter = '_');
std::string toLowerSnake(const std::string& s, const char delimiter = '_');
std::string toUpperCamel(const std::string& s, const char delimiter = '_');
std::string toUpperSnake(const std::string& s, const char delimiter = '_');
} // namespace generator
} // namespace tensorflow
#endif // TENSORFLOW_C_EXPERIMENTAL_OPS_GEN_COMMON_CASE_FORMAT_H_
@@ -0,0 +1,128 @@
/* Copyright 2021 The TensorFlow Authors. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/
#include "tensorflow/c/experimental/ops/gen/common/case_format.h"
#include <string>
#include "tensorflow/core/platform/test.h"
#include "tensorflow/core/platform/types.h"
namespace tensorflow {
namespace generator {
namespace {
// For each test case, we manually construct the 4 variations in string case and
// test all 16 conversions: from and to each of the 4 string case variations.
struct Variations {
std::string lower_camel;
std::string lower_snake;
std::string upper_camel;
std::string upper_snake;
};
void TestSingleVariation(const std::string& str, Variations expected,
char delimiter = '_') {
EXPECT_EQ(expected.lower_camel, toLowerCamel(str, delimiter));
EXPECT_EQ(expected.lower_snake, toLowerSnake(str, delimiter));
EXPECT_EQ(expected.upper_camel, toUpperCamel(str, delimiter));
EXPECT_EQ(expected.upper_snake, toUpperSnake(str, delimiter));
}
void TestAllVariations(Variations variations, char delimiter = '_') {
TestSingleVariation(variations.lower_camel, variations, delimiter);
TestSingleVariation(variations.lower_snake, variations, delimiter);
TestSingleVariation(variations.upper_camel, variations, delimiter);
TestSingleVariation(variations.upper_snake, variations, delimiter);
}
TEST(CppOpGenCaseFormat, test_single_word) {
TestAllVariations(Variations{
"three",
"three",
"Three",
"THREE",
});
}
TEST(CppOpGenCaseFormat, test_complex_string) {
TestAllVariations(Variations{
"threeNTest33Words",
"three_n_test33_words",
"ThreeNTest33Words",
"THREE_N_TEST33_WORDS",
});
}
TEST(CppOpGenCaseFormat, test_hyphen_delimiter) {
TestAllVariations(
Variations{
"threeNTest33Words",
"three-n-test33-words",
"ThreeNTest33Words",
"THREE-N-TEST33-WORDS",
},
'-');
}
TEST(CppOpGenCaseFormat, test_trailing_underscore) {
TestAllVariations(Variations{
"threeNTest33Words_",
"three_n_test33_words_",
"ThreeNTest33Words_",
"THREE_N_TEST33_WORDS_",
});
}
TEST(CppOpGenCaseFormat, test_double_trailing_underscores) {
TestAllVariations(Variations{
"xxY__",
"xx_y__",
"XxY__",
"XX_Y__",
});
}
TEST(CppOpGenCaseFormat, test_leading_underscore) {
TestAllVariations(Variations{
"_threeNTest33Words",
"_three_n_test33_words",
"_ThreeNTest33Words",
"_THREE_N_TEST33_WORDS",
});
}
TEST(CppOpGenCaseFormat, test_double_leading_underscores) {
TestAllVariations(Variations{
"__threeNTest33Words",
"__three_n_test33_words",
"__ThreeNTest33Words",
"__THREE_N_TEST33_WORDS",
});
}
TEST(CppOpGenCaseFormat, test_leading_and_trailing_underscores) {
TestAllVariations(Variations{
"__threeNTest33Words____",
"__three_n_test33_words____",
"__ThreeNTest33Words____",
"__THREE_N_TEST33_WORDS____",
});
}
} // namespace
} // namespace generator
} // namespace tensorflow
@@ -0,0 +1,94 @@
/* Copyright 2021 The TensorFlow Authors. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/
#include "tensorflow/c/experimental/ops/gen/common/controller.h"
#include <string>
#include <vector>
#include "absl/log/check.h"
#include "absl/strings/substitute.h"
#include "tensorflow/c/experimental/ops/gen/common/path_config.h"
#include "tensorflow/c/experimental/ops/gen/common/source_code.h"
#include "tensorflow/c/experimental/ops/gen/model/op_spec.h"
#include "xla/tsl/platform/status.h"
#include "tensorflow/core/framework/api_def.pb.h"
#include "tensorflow/core/framework/op.h"
#include "tensorflow/core/framework/op_def.pb.h"
#include "tensorflow/core/framework/op_gen_lib.h"
#include "tensorflow/core/platform/env.h"
#include "tensorflow/core/platform/logging.h"
#include "tensorflow/core/platform/path.h"
namespace tensorflow {
namespace generator {
Controller::Controller(PathConfig path_config, Env* env)
: env_(env), path_config_(path_config) {
// Load the Op and API definitions
InitializeOpApi();
// Convert the Op and API definitions to the internal data model
BuildModel();
}
Controller::~Controller() { delete api_def_map_; }
const void Controller::WriteFile(const std::string& file_path,
const SourceCode& code) const {
TF_CHECK_OK(WriteStringToFile(env_, file_path, code.Render())) << file_path;
}
const std::vector<OpSpec>& Controller::GetModelOps() const {
return operators_;
}
void Controller::InitializeOpApi() {
OpRegistry::Global()->Export(false, &op_list_);
// Load matching API defs for each Op. Paths are visited in order, allowing
// python/api_def_Xyz.pbtxt to override base/api_def_Xyz.pbtxt, for example.
api_def_map_ = new ApiDefMap(op_list_);
for (const auto& op : op_list_.op()) {
for (const auto& dir : path_config_.api_dirs) {
const std::string file_name =
absl::Substitute("api_def_$0.pbtxt", op.name());
const std::string file_path = io::JoinPath(dir, file_name);
if (env_->FileExists(file_path).ok()) {
TF_CHECK_OK(api_def_map_->LoadFile(env_, file_path)) << file_path;
} else {
// API defs are currently used for only optional pieces.
}
}
}
// Doc strings (summary, description) typically come from the API def.
api_def_map_->UpdateDocs();
}
void Controller::BuildModel() {
// Build the internal data model for the requested ops
for (const auto& op_name : path_config_.op_names) {
const OpDef* op_def = nullptr;
TF_CHECK_OK(OpRegistry::Global()->LookUpOpDef(op_name, &op_def));
CHECK(op_def != nullptr); // Crash OK
const ApiDef* api_def = api_def_map_->GetApiDef(op_name);
CHECK(api_def != nullptr); // Crash OK
operators_.push_back(OpSpec::Create(*op_def, *api_def));
}
}
} // namespace generator
} // namespace tensorflow
@@ -0,0 +1,58 @@
/* Copyright 2021 The TensorFlow Authors. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/
#ifndef TENSORFLOW_C_EXPERIMENTAL_OPS_GEN_COMMON_CONTROLLER_H_
#define TENSORFLOW_C_EXPERIMENTAL_OPS_GEN_COMMON_CONTROLLER_H_
#include <vector>
#include "tensorflow/c/experimental/ops/gen/common/path_config.h"
#include "tensorflow/c/experimental/ops/gen/common/source_code.h"
#include "tensorflow/c/experimental/ops/gen/model/op_spec.h"
#include "tensorflow/core/framework/op_def.pb.h"
#include "tensorflow/core/framework/op_gen_lib.h"
#include "tensorflow/core/platform/env.h"
#include "tensorflow/core/platform/types.h"
namespace tensorflow {
namespace generator {
class Controller {
public:
explicit Controller(PathConfig path_config, Env* env = Env::Default());
virtual ~Controller();
const void WriteFile(const std::string& file_path,
const SourceCode& code) const;
const std::vector<OpSpec>& GetModelOps() const;
private:
void InitializeOpApi();
void BuildModel();
// Data model: Ops to generate
std::vector<OpSpec> operators_;
// Configuration
Env* env_;
PathConfig path_config_;
// Initialized TensorFlow Op/API definitions
OpList op_list_;
ApiDefMap* api_def_map_;
};
} // namespace generator
} // namespace tensorflow
#endif // TENSORFLOW_C_EXPERIMENTAL_OPS_GEN_COMMON_CONTROLLER_H_
@@ -0,0 +1,69 @@
/* Copyright 2021 The TensorFlow Authors. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/
#include "tensorflow/c/experimental/ops/gen/common/path_config.h"
#include <algorithm>
#include <string>
#include <vector>
#include "absl/strings/str_join.h"
#include "tensorflow/core/lib/strings/str_util.h"
#include "tensorflow/core/platform/types.h"
namespace tensorflow {
namespace generator {
PathConfig::PathConfig(const std::string& output_dir,
const std::string& source_dir,
const std::string& api_dir_list,
const std::vector<std::string> op_names)
: output_path(output_dir), op_names(op_names) {
api_dirs = str_util::Split(api_dir_list, ",", str_util::SkipEmpty());
// Decompose the directory components given the output/source directories.
//
// Be flexible; accept any path string with a "tensorflow" directory name.
// (It's hard to construct a location-agnostic include path string using the
// build system, so we accept an example, such as the source build target.)
tf_root_dir = "tensorflow";
// Prefix, e.g. "third_party" given root_dir "third_party/tensorflow/...."
std::vector<std::string> source_path_components =
tensorflow::str_util::Split(source_dir, "/");
auto source_tfroot_pos = std::find(source_path_components.begin(),
source_path_components.end(), tf_root_dir);
if (source_tfroot_pos != source_path_components.end()) {
tf_prefix_dir =
absl::StrJoin(source_path_components.begin(), source_tfroot_pos, "/");
} else {
tf_prefix_dir = source_dir;
}
// TF subdir, e.g. "c/ops" given output_dir "blah/blah/tensorflow/c/ops"
std::vector<std::string> output_path_components =
tensorflow::str_util::Split(output_dir, "/");
auto output_tfroot_pos = std::find(output_path_components.begin(),
output_path_components.end(), tf_root_dir);
if (output_tfroot_pos != output_path_components.end()) {
tf_output_dir =
absl::StrJoin(output_tfroot_pos + 1, output_path_components.end(), "/");
} else {
tf_output_dir = output_dir;
}
}
} // namespace generator
} // namespace tensorflow
@@ -0,0 +1,43 @@
/* Copyright 2021 The TensorFlow Authors. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/
#ifndef TENSORFLOW_C_EXPERIMENTAL_OPS_GEN_COMMON_PATH_CONFIG_H_
#define TENSORFLOW_C_EXPERIMENTAL_OPS_GEN_COMMON_PATH_CONFIG_H_
#include <vector>
#include "tensorflow/core/platform/types.h"
namespace tensorflow {
namespace generator {
struct PathConfig {
std::string output_path;
std::vector<std::string> op_names;
std::vector<std::string> api_dirs;
std::string tf_prefix_dir;
std::string tf_root_dir;
std::string tf_output_dir;
explicit PathConfig() = default;
explicit PathConfig(const std::string& output_dir,
const std::string& source_dir,
const std::string& api_dir_list,
const std::vector<std::string> op_names);
};
} // namespace generator
} // namespace tensorflow
#endif // TENSORFLOW_C_EXPERIMENTAL_OPS_GEN_COMMON_PATH_CONFIG_H_
@@ -0,0 +1,68 @@
/* Copyright 2021 The TensorFlow Authors. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/
#include "tensorflow/c/experimental/ops/gen/common/source_code.h"
#include <string>
#include "absl/log/log.h"
#include "absl/strings/ascii.h"
#include "absl/strings/match.h"
#include "absl/strings/str_cat.h"
#include "absl/strings/string_view.h"
#include "absl/strings/strip.h"
#include "tensorflow/core/platform/logging.h"
#include "tensorflow/core/platform/stringpiece.h"
namespace tensorflow {
namespace generator {
std::string SourceCode::Render() const {
std::string code;
for (const Line& line : lines_) {
absl::StrAppend(&code, std::string(line.indent * spaces_per_indent_, ' '),
line.text, "\n");
}
return code;
}
void SourceCode::AddLineWithIndent(const std::string& line) {
ValidateAndAddLine(current_indent_, line);
}
void SourceCode::AddLineWithoutIndent(const std::string& line) {
ValidateAndAddLine(0, line);
}
void SourceCode::AddBlankLine() { ValidateAndAddLine(0, ""); }
void SourceCode::IncreaseIndent() { current_indent_++; }
void SourceCode::DecreaseIndent() { current_indent_--; }
void SourceCode::ValidateAndAddLine(int indent, const std::string& raw_line) {
absl::string_view line(raw_line);
bool had_trailing_newline = absl::ConsumeSuffix(&line, "\n");
if (absl::StrContains(line, '\n')) {
LOG(ERROR) << "Attempt to add multiple lines; bad formatting is likely.";
} else if (had_trailing_newline) {
LOG(WARNING) << "Superfluous trailing newline in '" << line << "'";
}
lines_.push_back(
{indent, std::string(absl::StripTrailingAsciiWhitespace(line))});
}
} // namespace generator
} // namespace tensorflow
@@ -0,0 +1,54 @@
/* Copyright 2021 The TensorFlow Authors. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/
#ifndef TENSORFLOW_C_EXPERIMENTAL_OPS_GEN_COMMON_SOURCE_CODE_H_
#define TENSORFLOW_C_EXPERIMENTAL_OPS_GEN_COMMON_SOURCE_CODE_H_
#include <vector>
#include "tensorflow/core/platform/types.h"
namespace tensorflow {
namespace generator {
class SourceCode {
public:
std::string Render() const;
void SetSpacesPerIndent(int spaces_per_indent) {
spaces_per_indent_ = spaces_per_indent;
}
void AddLineWithIndent(const std::string& line);
void AddLineWithoutIndent(const std::string& line);
void AddBlankLine();
void IncreaseIndent();
void DecreaseIndent();
private:
struct Line {
int indent;
std::string text;
};
void ValidateAndAddLine(int indent_level, const std::string& raw_line);
int spaces_per_indent_ = 2;
int current_indent_ = 0;
std::vector<Line> lines_;
};
} // namespace generator
} // namespace tensorflow
#endif // TENSORFLOW_C_EXPERIMENTAL_OPS_GEN_COMMON_SOURCE_CODE_H_
@@ -0,0 +1,43 @@
/* Copyright 2021 The TensorFlow Authors. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/
#include "tensorflow/c/experimental/ops/gen/common/view_util.h"
#include <string>
#include <vector>
#include "absl/strings/str_join.h"
#include "absl/strings/substitute.h"
#include "tensorflow/core/platform/types.h"
namespace tensorflow {
namespace generator {
std::string Call(const std::string& object, const std::string& method,
std::vector<std::string> arguments, const char* oper) {
return absl::Substitute("$0$1$2($3)", object, oper, method,
absl::StrJoin(arguments, ", "));
}
std::string Call(const std::string& function,
std::vector<std::string> arguments) {
return absl::Substitute("$0($1)", function, absl::StrJoin(arguments, ", "));
}
std::string Quoted(const std::string& s) {
return absl::Substitute("\"$0\"", s);
}
} // namespace generator
} // namespace tensorflow
@@ -0,0 +1,34 @@
/* Copyright 2021 The TensorFlow Authors. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/
#ifndef TENSORFLOW_C_EXPERIMENTAL_OPS_GEN_COMMON_VIEW_UTIL_H_
#define TENSORFLOW_C_EXPERIMENTAL_OPS_GEN_COMMON_VIEW_UTIL_H_
#include <vector>
#include "tensorflow/core/platform/types.h"
namespace tensorflow {
namespace generator {
std::string Call(const std::string& function,
std::vector<std::string> arguments);
std::string Call(const std::string& object, const std::string& method,
std::vector<std::string> arguments, const char* oper = "->");
std::string Quoted(const std::string& s);
} // namespace generator
} // namespace tensorflow
#endif // TENSORFLOW_C_EXPERIMENTAL_OPS_GEN_COMMON_VIEW_UTIL_H_
@@ -0,0 +1,53 @@
load("@rules_cc//cc:cc_library.bzl", "cc_library")
load(
"//tensorflow:tensorflow.bzl",
"tf_cc_test",
)
package(
# copybara:uncomment default_applicable_licenses = ["//tensorflow:license"],
default_visibility = ["//visibility:private"],
licenses = ["notice"],
)
cc_library(
name = "cpp",
srcs = glob(
["*.cc"],
exclude = ["*_test.cc"],
),
hdrs = glob(["*.h"]),
visibility = ["//tensorflow/c/experimental/ops/gen:__pkg__"],
deps = [
"//tensorflow/c/experimental/ops/gen/common",
"//tensorflow/c/experimental/ops/gen/cpp/renderers",
"//tensorflow/c/experimental/ops/gen/cpp/views",
"//tensorflow/c/experimental/ops/gen/model",
"//tensorflow/core:framework",
"//tensorflow/core:lib",
"//tensorflow/core:lib_internal",
"//tensorflow/core:op_gen_lib",
"//tensorflow/core:protos_all_cc",
"@com_google_absl//absl/strings",
],
alwayslink = 1,
)
tf_cc_test(
name = "cpp_generator_test",
size = "small",
srcs = ["cpp_generator_test.cc"],
data = ["//tensorflow/c/experimental/ops/gen/cpp/golden"],
deps = [
":cpp",
"//tensorflow/c/experimental/ops/gen/common",
"//tensorflow/c/experimental/ops/gen/cpp/renderers",
"//tensorflow/core:core_cpu",
"//tensorflow/core:framework",
"//tensorflow/core:lib",
"//tensorflow/core:test",
"//tensorflow/core:test_main",
"//tensorflow/core:testlib",
"@xla//xla/tsl/platform:status",
],
)
@@ -0,0 +1,73 @@
/* Copyright 2021 The TensorFlow Authors. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/
#include "tensorflow/c/experimental/ops/gen/cpp/cpp_generator.h"
#include <string>
#include <vector>
#include "tensorflow/c/experimental/ops/gen/common/path_config.h"
#include "tensorflow/c/experimental/ops/gen/common/source_code.h"
#include "tensorflow/c/experimental/ops/gen/cpp/renderers/cpp_config.h"
#include "tensorflow/c/experimental/ops/gen/cpp/renderers/cpp_file_renderer.h"
#include "tensorflow/c/experimental/ops/gen/cpp/renderers/renderer_context.h"
#include "tensorflow/c/experimental/ops/gen/cpp/views/op_view.h"
#include "tensorflow/c/experimental/ops/gen/model/op_spec.h"
#include "tensorflow/core/platform/path.h"
#include "tensorflow/core/platform/types.h"
namespace tensorflow {
namespace generator {
CppGenerator::CppGenerator(cpp::CppConfig cpp_config, PathConfig path_config)
: controller_(path_config),
cpp_config_(cpp_config),
path_config_(path_config) {}
SourceCode CppGenerator::GenerateOneFile(
cpp::RendererContext::Mode mode) const {
SourceCode generated_code;
const std::vector<OpSpec> ops(controller_.GetModelOps());
std::vector<cpp::OpView> views(ops.begin(), ops.end());
cpp::RendererContext context{mode, generated_code, cpp_config_, path_config_};
cpp::CppFileRenderer(context, views).Render();
return generated_code;
}
SourceCode CppGenerator::HeaderFileContents() const {
return GenerateOneFile(cpp::RendererContext::kHeader);
}
SourceCode CppGenerator::SourceFileContents() const {
return GenerateOneFile(cpp::RendererContext::kSource);
}
std::string CppGenerator::HeaderFileName() const {
return io::JoinPath(path_config_.output_path, cpp_config_.unit + "_ops.h");
}
std::string CppGenerator::SourceFileName() const {
return io::JoinPath(path_config_.output_path, cpp_config_.unit + "_ops.cc");
}
void CppGenerator::WriteHeaderFile() const {
controller_.WriteFile(HeaderFileName(), HeaderFileContents());
}
void CppGenerator::WriteSourceFile() const {
controller_.WriteFile(SourceFileName(), SourceFileContents());
}
} // namespace generator
} // namespace tensorflow
@@ -0,0 +1,49 @@
/* Copyright 2021 The TensorFlow Authors. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/
#ifndef TENSORFLOW_C_EXPERIMENTAL_OPS_GEN_CPP_CPP_GENERATOR_H_
#define TENSORFLOW_C_EXPERIMENTAL_OPS_GEN_CPP_CPP_GENERATOR_H_
#include "tensorflow/c/experimental/ops/gen/common/controller.h"
#include "tensorflow/c/experimental/ops/gen/common/path_config.h"
#include "tensorflow/c/experimental/ops/gen/common/source_code.h"
#include "tensorflow/c/experimental/ops/gen/cpp/renderers/cpp_config.h"
#include "tensorflow/c/experimental/ops/gen/cpp/renderers/renderer_context.h"
#include "tensorflow/core/platform/types.h"
namespace tensorflow {
namespace generator {
class CppGenerator {
public:
explicit CppGenerator(cpp::CppConfig cpp_config, PathConfig path_config);
SourceCode HeaderFileContents() const;
SourceCode SourceFileContents() const;
std::string HeaderFileName() const;
std::string SourceFileName() const;
void WriteHeaderFile() const;
void WriteSourceFile() const;
private:
SourceCode GenerateOneFile(cpp::RendererContext::Mode mode) const;
Controller controller_;
cpp::CppConfig cpp_config_;
PathConfig path_config_;
};
} // namespace generator
} // namespace tensorflow
#endif // TENSORFLOW_C_EXPERIMENTAL_OPS_GEN_CPP_CPP_GENERATOR_H_
@@ -0,0 +1,83 @@
/* Copyright 2021 The TensorFlow Authors. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/
#include "tensorflow/c/experimental/ops/gen/cpp/cpp_generator.h"
#include <algorithm>
#include <string>
#include <vector>
#include "tensorflow/c/experimental/ops/gen/common/path_config.h"
#include "tensorflow/c/experimental/ops/gen/cpp/renderers/cpp_config.h"
#include "xla/tsl/platform/status.h"
#include "tensorflow/core/platform/env.h"
#include "tensorflow/core/platform/path.h"
#include "tensorflow/core/platform/test.h"
#include "tensorflow/core/platform/types.h"
namespace tensorflow {
namespace generator {
namespace {
TEST(CppGeneratorTest, typical_usage) {
std::string category = "testing";
std::string name_space = "tensorflow::ops";
std::string output_dir = "tensorflow/c/experimental/ops/gen/cpp/golden";
std::string source_dir = "tensorflow";
std::string api_dirs = "";
std::vector<std::string> ops = {
"Neg", // Simple unary Op
"MatMul", // 2 inputs & attrs with default values
"IdentityN", // Variadic input+output
"SparseSoftmaxCrossEntropyWithLogits", // 2 outputs
"AccumulatorApplyGradient", // 0 outputs
"VarHandleOp", // type, shape, list(string) attrs
"RestoreV2", // Variadic output-only, list(type) attr
};
cpp::CppConfig cpp_config(category, name_space);
PathConfig controller_config(output_dir, source_dir, api_dirs, ops);
CppGenerator generator(cpp_config, controller_config);
Env *env = Env::Default();
std::string golden_dir = io::JoinPath(testing::TensorFlowSrcRoot(),
controller_config.tf_output_dir);
std::string generated_header = generator.HeaderFileContents().Render();
std::string generated_source = generator.SourceFileContents().Render();
std::string expected_header;
std::string header_file_name =
io::JoinPath(golden_dir, "testing_ops.h.golden");
TF_CHECK_OK(ReadFileToString(env, header_file_name, &expected_header));
std::string expected_source;
std::string source_file_name =
io::JoinPath(golden_dir, "testing_ops.cc.golden");
TF_CHECK_OK(ReadFileToString(env, source_file_name, &expected_source));
// Remove carriage returns (for Windows)
expected_header.erase(
std::remove(expected_header.begin(), expected_header.end(), '\r'),
expected_header.end());
expected_source.erase(
std::remove(expected_source.begin(), expected_source.end(), '\r'),
expected_source.end());
EXPECT_EQ(expected_header, generated_header);
EXPECT_EQ(expected_source, generated_source);
}
} // namespace
} // namespace generator
} // namespace tensorflow
@@ -0,0 +1,10 @@
package(
# copybara:uncomment default_applicable_licenses = ["//tensorflow:license"],
default_visibility = ["//visibility:public"],
licenses = ["notice"],
)
filegroup(
name = "golden",
data = glob(["*.golden"]),
)
@@ -0,0 +1,150 @@
/* Copyright 2021 The TensorFlow Authors. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/
// This file is MACHINE GENERATED! Do not edit.
#include "tensorflow/c/experimental/ops/gen/cpp/golden/testing_ops.h"
#include "absl/status/status.h"
#include "absl/types/span.h"
#include "tensorflow/c/eager/abstract_context.h"
#include "tensorflow/c/eager/abstract_tensor_handle.h"
#include "tensorflow/core/framework/types.h" // NOLINT
#include <cstring> // NOLINT
#include "tensorflow/c/eager/abstract_operation.h"
#include "tensorflow/c/eager/tracing_utils.h"
#include "tensorflow/core/platform/errors.h" // NOLINT
using tensorflow::tracing::MaybeSetOpName;
namespace tensorflow {
namespace ops {
// Op: Neg()
// Summary:
//
// Description:
absl::Status Neg(AbstractContext* ctx, AbstractTensorHandle* const x, AbstractTensorHandle** y, const char* name, const char* raw_device_name) {
AbstractOperationPtr op_ptr(ctx->CreateOperation());
TF_RETURN_IF_ERROR(op_ptr->Reset("Neg", raw_device_name));
TF_RETURN_IF_ERROR(MaybeSetOpName(op_ptr.get(), name));
TF_RETURN_IF_ERROR(op_ptr->AddInput(x));
int num_retvals = 1;
return op_ptr->Execute(absl::MakeSpan(y, 1), &num_retvals);
}
// Op: MatMul()
// Summary:
//
// Description:
absl::Status MatMul(AbstractContext* ctx, AbstractTensorHandle* const a, AbstractTensorHandle* const b, AbstractTensorHandle** product, bool transpose_a, bool transpose_b, bool grad_a, bool grad_b, const char* name, const char* raw_device_name) {
AbstractOperationPtr op_ptr(ctx->CreateOperation());
TF_RETURN_IF_ERROR(op_ptr->Reset("MatMul", raw_device_name));
TF_RETURN_IF_ERROR(MaybeSetOpName(op_ptr.get(), name));
TF_RETURN_IF_ERROR(op_ptr->AddInput(a));
TF_RETURN_IF_ERROR(op_ptr->AddInput(b));
TF_RETURN_IF_ERROR(op_ptr->SetAttrBool("transpose_a", transpose_a));
TF_RETURN_IF_ERROR(op_ptr->SetAttrBool("transpose_b", transpose_b));
TF_RETURN_IF_ERROR(op_ptr->SetAttrBool("grad_a", grad_a));
TF_RETURN_IF_ERROR(op_ptr->SetAttrBool("grad_b", grad_b));
int num_retvals = 1;
return op_ptr->Execute(absl::MakeSpan(product, 1), &num_retvals);
}
// Op: IdentityN()
// Summary:
//
// Description:
absl::Status IdentityN(AbstractContext* ctx, absl::Span<AbstractTensorHandle* const> input, absl::Span<AbstractTensorHandle*> output, const char* name, const char* raw_device_name) {
AbstractOperationPtr op_ptr(ctx->CreateOperation());
TF_RETURN_IF_ERROR(op_ptr->Reset("IdentityN", raw_device_name));
TF_RETURN_IF_ERROR(MaybeSetOpName(op_ptr.get(), name));
TF_RETURN_IF_ERROR(op_ptr->AddInputList(input));
int num_retvals = output.size();
return op_ptr->Execute(output, &num_retvals);
}
// Op: SparseSoftmaxCrossEntropyWithLogits()
// Summary:
//
// Description:
absl::Status SparseSoftmaxCrossEntropyWithLogits(AbstractContext* ctx, AbstractTensorHandle* const features, AbstractTensorHandle* const labels, AbstractTensorHandle** loss, AbstractTensorHandle** backprop, const char* name, const char* raw_device_name) {
AbstractOperationPtr op_ptr(ctx->CreateOperation());
TF_RETURN_IF_ERROR(op_ptr->Reset("SparseSoftmaxCrossEntropyWithLogits", raw_device_name));
TF_RETURN_IF_ERROR(MaybeSetOpName(op_ptr.get(), name));
TF_RETURN_IF_ERROR(op_ptr->AddInput(features));
TF_RETURN_IF_ERROR(op_ptr->AddInput(labels));
int num_retvals = 2;
AbstractTensorHandle* temp_outputs[2] = {nullptr};
absl::Status status = op_ptr->Execute(temp_outputs, &num_retvals);
if (status.ok()) {
*loss = temp_outputs[0];
*backprop = temp_outputs[1];
}
return status;
}
// Op: AccumulatorApplyGradient()
// Summary:
//
// Description:
absl::Status AccumulatorApplyGradient(AbstractContext* ctx, AbstractTensorHandle** handle, AbstractTensorHandle* const local_step, AbstractTensorHandle* const gradient, const char* name, const char* raw_device_name) {
AbstractOperationPtr op_ptr(ctx->CreateOperation());
TF_RETURN_IF_ERROR(op_ptr->Reset("AccumulatorApplyGradient", raw_device_name));
TF_RETURN_IF_ERROR(MaybeSetOpName(op_ptr.get(), name));
TF_RETURN_IF_ERROR(op_ptr->AddInput(handle));
TF_RETURN_IF_ERROR(op_ptr->AddInput(local_step));
TF_RETURN_IF_ERROR(op_ptr->AddInput(gradient));
int num_retvals = 0;
std::vector<AbstractTensorHandle*> dummy_outputs;
return op_ptr->Execute(absl::MakeSpan(dummy_outputs), &num_retvals);
}
// Op: VarHandleOp()
// Summary:
//
// Description:
absl::Status VarHandleOp(AbstractContext* ctx, AbstractTensorHandle** resource, DataType dtype, const PartialTensorShape shape, const char* container, const char* shared_name, const char* debug_name, absl::Span<std::string const> allowed_devices, const char* name, const char* raw_device_name) {
AbstractOperationPtr op_ptr(ctx->CreateOperation());
TF_RETURN_IF_ERROR(op_ptr->Reset("VarHandleOp", raw_device_name));
TF_RETURN_IF_ERROR(MaybeSetOpName(op_ptr.get(), name));
TF_RETURN_IF_ERROR(op_ptr->SetAttrString("container", container, strlen(container)));
TF_RETURN_IF_ERROR(op_ptr->SetAttrString("shared_name", shared_name, strlen(shared_name)));
TF_RETURN_IF_ERROR(op_ptr->SetAttrString("debug_name", debug_name, strlen(debug_name)));
TF_RETURN_IF_ERROR(op_ptr->SetAttrType("dtype", dtype));
TF_RETURN_IF_ERROR(op_ptr->SetAttrShape("shape", shape));
TF_RETURN_IF_ERROR(op_ptr->SetAttrStringList("allowed_devices", allowed_devices));
int num_retvals = 1;
return op_ptr->Execute(absl::MakeSpan(resource, 1), &num_retvals);
}
// Op: RestoreV2()
// Summary:
//
// Description:
absl::Status RestoreV2(AbstractContext* ctx, AbstractTensorHandle* const prefix, AbstractTensorHandle* const tensor_names, AbstractTensorHandle* const shape_and_slices, absl::Span<AbstractTensorHandle*> tensors, absl::Span<DataType> dtypes, const char* name, const char* raw_device_name) {
AbstractOperationPtr op_ptr(ctx->CreateOperation());
TF_RETURN_IF_ERROR(op_ptr->Reset("RestoreV2", raw_device_name));
TF_RETURN_IF_ERROR(MaybeSetOpName(op_ptr.get(), name));
TF_RETURN_IF_ERROR(op_ptr->AddInput(prefix));
TF_RETURN_IF_ERROR(op_ptr->AddInput(tensor_names));
TF_RETURN_IF_ERROR(op_ptr->AddInput(shape_and_slices));
TF_RETURN_IF_ERROR(op_ptr->SetAttrTypeList("dtypes", dtypes.data(), dtypes.length()));
int num_retvals = tensors.size();
return op_ptr->Execute(tensors, &num_retvals);
}
} // namespace ops
} // namespace tensorflow
@@ -0,0 +1,54 @@
/* Copyright 2021 The TensorFlow Authors. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/
// This file is MACHINE GENERATED! Do not edit.
#ifndef TENSORFLOW_C_EXPERIMENTAL_OPS_GEN_CPP_GOLDEN_TESTING_OPS_H_
#define TENSORFLOW_C_EXPERIMENTAL_OPS_GEN_CPP_GOLDEN_TESTING_OPS_H_
#include "absl/status/status.h"
#include "absl/types/span.h"
#include "tensorflow/c/eager/abstract_context.h"
#include "tensorflow/c/eager/abstract_tensor_handle.h"
#include "tensorflow/core/framework/types.h" // NOLINT
namespace tensorflow {
namespace ops {
//
absl::Status Neg(AbstractContext* ctx, AbstractTensorHandle* const x, AbstractTensorHandle** y, const char* name = nullptr, const char* raw_device_name = nullptr);
//
absl::Status MatMul(AbstractContext* ctx, AbstractTensorHandle* const a, AbstractTensorHandle* const b, AbstractTensorHandle** product, bool transpose_a = false, bool transpose_b = false, bool grad_a = false, bool grad_b = false, const char* name = nullptr, const char* raw_device_name = nullptr);
//
absl::Status IdentityN(AbstractContext* ctx, absl::Span<AbstractTensorHandle* const> input, absl::Span<AbstractTensorHandle*> output, const char* name = nullptr, const char* raw_device_name = nullptr);
//
absl::Status SparseSoftmaxCrossEntropyWithLogits(AbstractContext* ctx, AbstractTensorHandle* const features, AbstractTensorHandle* const labels, AbstractTensorHandle** loss, AbstractTensorHandle** backprop, const char* name = nullptr, const char* raw_device_name = nullptr);
//
absl::Status AccumulatorApplyGradient(AbstractContext* ctx, AbstractTensorHandle** handle, AbstractTensorHandle* const local_step, AbstractTensorHandle* const gradient, const char* name = nullptr, const char* raw_device_name = nullptr);
//
absl::Status VarHandleOp(AbstractContext* ctx, AbstractTensorHandle** resource, DataType dtype, const PartialTensorShape shape, const char* container = "", const char* shared_name = "", const char* debug_name = "", absl::Span<std::string const> allowed_devices = {}, const char* name = nullptr, const char* raw_device_name = nullptr);
//
absl::Status RestoreV2(AbstractContext* ctx, AbstractTensorHandle* const prefix, AbstractTensorHandle* const tensor_names, AbstractTensorHandle* const shape_and_slices, absl::Span<AbstractTensorHandle*> tensors, absl::Span<DataType> dtypes, const char* name = nullptr, const char* raw_device_name = nullptr);
} // namespace ops
} // namespace tensorflow
#endif // TENSORFLOW_C_EXPERIMENTAL_OPS_GEN_CPP_GOLDEN_TESTING_OPS_H_
@@ -0,0 +1,52 @@
load("@rules_cc//cc:cc_library.bzl", "cc_library")
load(
"//tensorflow:tensorflow.bzl",
"tf_cc_tests",
)
package(
# copybara:uncomment default_applicable_licenses = ["//tensorflow:license"],
default_visibility = ["//visibility:private"],
licenses = ["notice"],
)
cc_library(
name = "renderers",
srcs = glob(
["*.cc"],
exclude = ["*_test.cc"],
),
hdrs = glob(["*.h"]),
visibility = [
"//tensorflow/c/experimental/ops/gen:__pkg__",
"//tensorflow/c/experimental/ops/gen/cpp:__pkg__",
],
deps = [
"//tensorflow/c/experimental/ops/gen/common",
"//tensorflow/c/experimental/ops/gen/cpp/views",
"//tensorflow/core:framework_internal",
"//tensorflow/core:lib",
"//tensorflow/core:lib_internal",
"@com_google_absl//absl/log",
"@com_google_absl//absl/strings",
],
alwayslink = 1,
)
tf_cc_tests(
name = "renderer_tests",
size = "small",
srcs = glob(
["*_test.cc"],
),
deps = [
":renderers",
"//tensorflow/c/experimental/ops/gen/common",
"//tensorflow/core:core_cpu",
"//tensorflow/core:framework",
"//tensorflow/core:test",
"//tensorflow/core:test_main",
"//tensorflow/core:testlib",
"//tensorflow/core/platform:types",
],
)
@@ -0,0 +1,34 @@
/* Copyright 2021 The TensorFlow Authors. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/
#include "tensorflow/c/experimental/ops/gen/cpp/renderers/cpp_config.h"
#include <string>
#include "absl/strings/ascii.h"
#include "absl/strings/str_split.h"
#include "tensorflow/core/platform/types.h"
namespace tensorflow {
namespace generator {
namespace cpp {
CppConfig::CppConfig(const std::string& category, const std::string& name_space)
: category(category),
unit(absl::AsciiStrToLower(category)),
namespaces(absl::StrSplit(name_space, "::")) {}
} // namespace cpp
} // namespace generator
} // namespace tensorflow
@@ -0,0 +1,40 @@
/* Copyright 2021 The TensorFlow Authors. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/
#ifndef TENSORFLOW_C_EXPERIMENTAL_OPS_GEN_CPP_RENDERERS_CPP_CONFIG_H_
#define TENSORFLOW_C_EXPERIMENTAL_OPS_GEN_CPP_RENDERERS_CPP_CONFIG_H_
#include <vector>
#include "tensorflow/core/platform/types.h"
namespace tensorflow {
namespace generator {
namespace cpp {
struct CppConfig {
std::string category;
std::string unit;
std::vector<std::string> namespaces;
explicit CppConfig() = default;
explicit CppConfig(const std::string& category,
const std::string& name_space = "tensorflow::ops");
};
} // namespace cpp
} // namespace generator
} // namespace tensorflow
#endif // TENSORFLOW_C_EXPERIMENTAL_OPS_GEN_CPP_RENDERERS_CPP_CONFIG_H_
@@ -0,0 +1,85 @@
/* Copyright 2021 The TensorFlow Authors. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/
#include "tensorflow/c/experimental/ops/gen/cpp/renderers/cpp_file_renderer.h"
#include <vector>
#include "tensorflow/c/experimental/ops/gen/cpp/renderers/op_renderer.h"
#include "tensorflow/c/experimental/ops/gen/cpp/renderers/renderer.h"
#include "tensorflow/c/experimental/ops/gen/cpp/renderers/renderer_context.h"
#include "tensorflow/c/experimental/ops/gen/cpp/views/op_view.h"
namespace tensorflow {
namespace generator {
namespace cpp {
static const char *copyright =
R"(
/* Copyright 2021 The TensorFlow Authors. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/
)";
static const char *machine_generated =
"// This file is MACHINE GENERATED! Do not edit.";
CppFileRenderer::CppFileRenderer(RendererContext context,
const std::vector<OpView> &ops)
: Renderer(context),
guard_(context),
name_space_(context),
includes_(context),
ops_(ops) {}
void CppFileRenderer::Render() {
CodeLines(copyright);
BlankLine();
CodeLine(machine_generated);
BlankLine();
if (context_.mode == RendererContext::kHeader) {
guard_.Open();
} else {
includes_.SelfHeader();
}
includes_.Headers(ops_);
name_space_.Open();
BlankLine();
for (const OpView &op : ops_) {
OpRenderer(context_, op).Render();
}
name_space_.Close();
if (context_.mode == RendererContext::kHeader) {
guard_.Close();
}
}
} // namespace cpp
} // namespace generator
} // namespace tensorflow
@@ -0,0 +1,48 @@
/* Copyright 2021 The TensorFlow Authors. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/
#ifndef TENSORFLOW_C_EXPERIMENTAL_OPS_GEN_CPP_RENDERERS_CPP_FILE_RENDERER_H_
#define TENSORFLOW_C_EXPERIMENTAL_OPS_GEN_CPP_RENDERERS_CPP_FILE_RENDERER_H_
#include <vector>
#include "tensorflow/c/experimental/ops/gen/cpp/renderers/guard_renderer.h"
#include "tensorflow/c/experimental/ops/gen/cpp/renderers/include_renderer.h"
#include "tensorflow/c/experimental/ops/gen/cpp/renderers/namespace_renderer.h"
#include "tensorflow/c/experimental/ops/gen/cpp/renderers/renderer.h"
#include "tensorflow/c/experimental/ops/gen/cpp/renderers/renderer_context.h"
#include "tensorflow/c/experimental/ops/gen/cpp/views/op_view.h"
namespace tensorflow {
namespace generator {
namespace cpp {
class CppFileRenderer : public Renderer {
public:
explicit CppFileRenderer(RendererContext context,
const std::vector<OpView> &ops);
void Render();
private:
GuardRenderer guard_;
NamespaceRenderer name_space_;
IncludeRenderer includes_;
std::vector<OpView> ops_;
};
} // namespace cpp
} // namespace generator
} // namespace tensorflow
#endif // TENSORFLOW_C_EXPERIMENTAL_OPS_GEN_CPP_RENDERERS_CPP_FILE_RENDERER_H_
@@ -0,0 +1,53 @@
/* Copyright 2021 The TensorFlow Authors. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/
#include "tensorflow/c/experimental/ops/gen/cpp/renderers/guard_renderer.h"
#include <algorithm>
#include <string>
#include "tensorflow/c/experimental/ops/gen/common/case_format.h"
#include "tensorflow/c/experimental/ops/gen/cpp/renderers/renderer.h"
#include "tensorflow/c/experimental/ops/gen/cpp/renderers/renderer_context.h"
#include "tensorflow/core/platform/path.h"
#include "tensorflow/core/platform/types.h"
namespace tensorflow {
namespace generator {
namespace cpp {
GuardRenderer::GuardRenderer(RendererContext context) : Renderer(context) {
std::string self_path = io::JoinPath(context_.path_config.tf_root_dir,
context_.path_config.tf_output_dir,
context_.cpp_config.unit + "_ops.h");
std::string with_underscores(self_path);
std::replace(with_underscores.begin(), with_underscores.end(), '/', '_');
std::replace(with_underscores.begin(), with_underscores.end(), '.', '_');
guard_ = toUpperSnake(with_underscores) + "_";
}
void GuardRenderer::Open() {
CodeLine("#ifndef $0", guard_);
CodeLine("#define $0", guard_);
BlankLine();
}
void GuardRenderer::Close() {
BlankLine();
CodeLine("#endif // $0", guard_);
}
} // namespace cpp
} // namespace generator
} // namespace tensorflow
@@ -0,0 +1,41 @@
/* Copyright 2021 The TensorFlow Authors. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/
#ifndef TENSORFLOW_C_EXPERIMENTAL_OPS_GEN_CPP_RENDERERS_GUARD_RENDERER_H_
#define TENSORFLOW_C_EXPERIMENTAL_OPS_GEN_CPP_RENDERERS_GUARD_RENDERER_H_
#include "tensorflow/c/experimental/ops/gen/cpp/renderers/renderer.h"
#include "tensorflow/c/experimental/ops/gen/cpp/renderers/renderer_context.h"
#include "tensorflow/core/platform/types.h"
namespace tensorflow {
namespace generator {
namespace cpp {
class GuardRenderer : public Renderer {
public:
explicit GuardRenderer(RendererContext context);
void Open();
void Close();
private:
std::string guard_;
};
} // namespace cpp
} // namespace generator
} // namespace tensorflow
#endif // TENSORFLOW_C_EXPERIMENTAL_OPS_GEN_CPP_RENDERERS_GUARD_RENDERER_H_
@@ -0,0 +1,98 @@
/* Copyright 2021 The TensorFlow Authors. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/
#include "tensorflow/c/experimental/ops/gen/cpp/renderers/include_renderer.h"
#include <string>
#include <vector>
#include "absl/strings/match.h"
#include "tensorflow/c/experimental/ops/gen/cpp/renderers/renderer.h"
#include "tensorflow/c/experimental/ops/gen/cpp/renderers/renderer_context.h"
#include "tensorflow/c/experimental/ops/gen/cpp/views/op_argument_view.h"
#include "tensorflow/c/experimental/ops/gen/cpp/views/op_view.h"
#include "tensorflow/core/platform/path.h"
namespace tensorflow {
namespace generator {
namespace cpp {
IncludeRenderer::IncludeRenderer(RendererContext context) : Renderer(context) {}
void IncludeRenderer::SelfHeader() {
Include(SelfHeaderPath());
BlankLine();
}
std::string IncludeRenderer::SelfHeaderPath() const {
return io::JoinPath(context_.path_config.tf_root_dir,
context_.path_config.tf_output_dir,
context_.cpp_config.unit + "_ops.h");
}
void IncludeRenderer::Include(const std::string& tf_file_path) {
CodeLine("#include \"$0\"",
io::JoinPath(context_.path_config.tf_prefix_dir, tf_file_path));
}
void IncludeRenderer::Headers(const std::vector<OpView>& ops) {
Include(
"absl"
"/status/status.h");
bool needs_span = false;
if (context_.mode == RendererContext::kSource) {
needs_span = true;
} else {
for (const OpView& op : ops) {
for (const OpArgumentView& arg : op.AllArguments()) {
if (absl::StrContains(arg.Declaration(), "absl::Span")) {
needs_span = true;
break;
}
}
if (needs_span) break;
}
}
if (needs_span) {
Include(
"absl"
"/types/span.h");
}
Include("tensorflow/c/eager/abstract_context.h");
Include("tensorflow/c/eager/abstract_tensor_handle.h");
if (context_.cpp_config.unit == "resource_variable") {
Include("tensorflow/core/framework/tensor_shape.h");
}
CodeLine("#include \"$0\" // NOLINT",
io::JoinPath(context_.path_config.tf_prefix_dir,
"tensorflow/core/framework/types.h"));
if (context_.cpp_config.unit == "resource_variable") {
CodeLine("#include <string>");
}
if (context_.mode == RendererContext::kSource) {
CodeLine("#include <cstring> // NOLINT");
Include("tensorflow/c/eager/abstract_operation.h");
Include("tensorflow/c/eager/tracing_utils.h");
CodeLine("#include \"$0\" // NOLINT",
io::JoinPath(context_.path_config.tf_prefix_dir,
"tensorflow/core/platform/errors.h"));
BlankLine();
Statement("using tensorflow::tracing::MaybeSetOpName");
}
BlankLine();
}
} // namespace cpp
} // namespace generator
} // namespace tensorflow
@@ -0,0 +1,45 @@
/* Copyright 2021 The TensorFlow Authors. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/
#ifndef TENSORFLOW_C_EXPERIMENTAL_OPS_GEN_CPP_RENDERERS_INCLUDE_RENDERER_H_
#define TENSORFLOW_C_EXPERIMENTAL_OPS_GEN_CPP_RENDERERS_INCLUDE_RENDERER_H_
#include <vector>
#include "tensorflow/c/experimental/ops/gen/cpp/renderers/renderer.h"
#include "tensorflow/c/experimental/ops/gen/cpp/renderers/renderer_context.h"
#include "tensorflow/c/experimental/ops/gen/cpp/views/op_view.h"
#include "tensorflow/core/platform/types.h"
namespace tensorflow {
namespace generator {
namespace cpp {
class IncludeRenderer : public Renderer {
public:
explicit IncludeRenderer(RendererContext context);
std::string SelfHeaderPath() const;
void SelfHeader();
void Headers(const std::vector<OpView>& ops);
private:
void Include(const std::string& tf_file_path);
};
} // namespace cpp
} // namespace generator
} // namespace tensorflow
#endif // TENSORFLOW_C_EXPERIMENTAL_OPS_GEN_CPP_RENDERERS_INCLUDE_RENDERER_H_
@@ -0,0 +1,45 @@
/* Copyright 2021 The TensorFlow Authors. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/
#include "tensorflow/c/experimental/ops/gen/cpp/renderers/namespace_renderer.h"
#include <string>
#include "tensorflow/c/experimental/ops/gen/cpp/renderers/renderer.h"
#include "tensorflow/c/experimental/ops/gen/cpp/renderers/renderer_context.h"
#include "tensorflow/core/platform/types.h"
namespace tensorflow {
namespace generator {
namespace cpp {
NamespaceRenderer::NamespaceRenderer(RendererContext context)
: Renderer(context) {}
void NamespaceRenderer::Open() {
for (const std::string& ns : context_.cpp_config.namespaces) {
CodeLine("namespace " + ns + " {");
}
}
void NamespaceRenderer::Close() {
for (auto it = context_.cpp_config.namespaces.rbegin();
it != context_.cpp_config.namespaces.rend(); ++it) {
CodeLine("} // namespace " + *it);
}
}
} // namespace cpp
} // namespace generator
} // namespace tensorflow
@@ -0,0 +1,40 @@
/* Copyright 2021 The TensorFlow Authors. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/
#ifndef TENSORFLOW_C_EXPERIMENTAL_OPS_GEN_CPP_RENDERERS_NAMESPACE_RENDERER_H_
#define TENSORFLOW_C_EXPERIMENTAL_OPS_GEN_CPP_RENDERERS_NAMESPACE_RENDERER_H_
#include <vector>
#include "tensorflow/c/experimental/ops/gen/cpp/renderers/renderer.h"
#include "tensorflow/c/experimental/ops/gen/cpp/renderers/renderer_context.h"
#include "tensorflow/core/platform/types.h"
namespace tensorflow {
namespace generator {
namespace cpp {
class NamespaceRenderer : public Renderer {
public:
explicit NamespaceRenderer(RendererContext context);
void Open();
void Close();
};
} // namespace cpp
} // namespace generator
} // namespace tensorflow
#endif // TENSORFLOW_C_EXPERIMENTAL_OPS_GEN_CPP_RENDERERS_NAMESPACE_RENDERER_H_
@@ -0,0 +1,46 @@
/* Copyright 2021 The TensorFlow Authors. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/
#include "tensorflow/c/experimental/ops/gen/cpp/renderers/op_comment_renderer.h"
#include "tensorflow/c/experimental/ops/gen/cpp/renderers/renderer.h"
#include "tensorflow/c/experimental/ops/gen/cpp/renderers/renderer_context.h"
#include "tensorflow/c/experimental/ops/gen/cpp/views/op_view.h"
namespace tensorflow {
namespace generator {
namespace cpp {
OpCommentRenderer::OpCommentRenderer(RendererContext context, OpView op)
: Renderer(context), op_(op) {}
void OpCommentRenderer::Render() {
if (context_.mode == RendererContext::kHeader) {
// Add a short 1-line comment to the header files.
CommentLine(op_.Summary());
return;
}
CommentLine("Op: $0()", op_.FunctionName());
CommentLine("Summary: $0", op_.Summary());
CommentLine("");
CommentLine("Description:");
for (const auto& line : op_.Description()) {
CommentLine(" $0", line);
}
}
} // namespace cpp
} // namespace generator
} // namespace tensorflow
@@ -0,0 +1,40 @@
/* Copyright 2021 The TensorFlow Authors. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/
#ifndef TENSORFLOW_C_EXPERIMENTAL_OPS_GEN_CPP_RENDERERS_OP_COMMENT_RENDERER_H_
#define TENSORFLOW_C_EXPERIMENTAL_OPS_GEN_CPP_RENDERERS_OP_COMMENT_RENDERER_H_
#include "tensorflow/c/experimental/ops/gen/cpp/renderers/renderer.h"
#include "tensorflow/c/experimental/ops/gen/cpp/renderers/renderer_context.h"
#include "tensorflow/c/experimental/ops/gen/cpp/views/op_view.h"
namespace tensorflow {
namespace generator {
namespace cpp {
class OpCommentRenderer : public Renderer {
public:
explicit OpCommentRenderer(RendererContext context, OpView op);
void Render();
private:
OpView op_;
};
} // namespace cpp
} // namespace generator
} // namespace tensorflow
#endif // TENSORFLOW_C_EXPERIMENTAL_OPS_GEN_CPP_RENDERERS_OP_COMMENT_RENDERER_H_
@@ -0,0 +1,102 @@
/* Copyright 2021 The TensorFlow Authors. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/
#include "tensorflow/c/experimental/ops/gen/cpp/renderers/op_implementation_renderer.h"
#include "tensorflow/c/experimental/ops/gen/common/view_util.h"
#include "tensorflow/c/experimental/ops/gen/cpp/renderers/renderer.h"
#include "tensorflow/c/experimental/ops/gen/cpp/renderers/renderer_context.h"
#include "tensorflow/c/experimental/ops/gen/cpp/views/arg_view.h"
#include "tensorflow/c/experimental/ops/gen/cpp/views/attr_view.h"
#include "tensorflow/c/experimental/ops/gen/cpp/views/op_view.h"
namespace tensorflow {
namespace generator {
namespace cpp {
OpImplementationRenderer::OpImplementationRenderer(RendererContext context,
OpView op)
: Renderer(context), op_(op) {}
void OpImplementationRenderer::Render() {
RenderInitialization();
if (op_.IsListOp()) {
RenderExecutionListOp();
} else if (op_.NumOutputs() == 0) {
RenderExecutionZeroOutputs();
} else if (op_.NumOutputs() == 1) {
RenderExecutionSingleOutput();
} else {
RenderExecutionMultipleOutputs();
}
}
void OpImplementationRenderer::RenderInitialization() {
// Create Op variable and initialize it
Statement("AbstractOperationPtr $0(ctx->CreateOperation())",
op_.VariableName());
TFStatement(Call(op_.VariableName(), "Reset",
{op_.OpNameString(), "raw_device_name"}));
TFStatement(Call("MaybeSetOpName", {op_.VariableName() + ".get()", "name"}));
// Set each input
for (const ArgView& ar : op_.Inputs()) {
TFStatement(Call(op_.VariableName(), ar.SetterMethod(), ar.SetterArgs()));
}
// Set each attribute
for (const AttrView& ar : op_.Attributes()) {
TFStatement(Call(op_.VariableName(), ar.SetterMethod(), ar.SetterArgs()));
}
}
void OpImplementationRenderer::RenderExecutionListOp() {
ArgView output_arg = op_.OnlyOutput();
Statement("int num_retvals = $0.size()", output_arg.VariableName());
Statement("return " + Call(op_.VariableName(), "Execute",
{output_arg.VariableName(), "&num_retvals"}));
}
void OpImplementationRenderer::RenderExecutionSingleOutput() {
ArgView output_arg = op_.OnlyOutput();
Statement("int num_retvals = 1");
Statement("return $0->Execute(absl::MakeSpan($1, 1), &num_retvals)",
op_.VariableName(), output_arg.VariableName());
}
void OpImplementationRenderer::RenderExecutionMultipleOutputs() {
Statement("int num_retvals = $0", op_.NumOutputs());
Statement("AbstractTensorHandle* temp_outputs[$0] = {nullptr}",
op_.NumOutputs());
Statement("absl::Status status = $0->Execute(temp_outputs, &num_retvals)",
op_.VariableName());
BlockOpen("if (status.ok())");
for (const ArgView& arg : op_.Outputs()) {
Statement("*$0 = temp_outputs[$1]", arg.VariableName(), arg.Position());
}
BlockClose();
Statement("return status");
}
void OpImplementationRenderer::RenderExecutionZeroOutputs() {
Statement("int num_retvals = 0");
Statement("std::vector<AbstractTensorHandle*> dummy_outputs");
Statement("return $0->Execute(absl::MakeSpan(dummy_outputs), &num_retvals)",
op_.VariableName());
}
} // namespace cpp
} // namespace generator
} // namespace tensorflow
@@ -0,0 +1,45 @@
/* Copyright 2021 The TensorFlow Authors. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/
#ifndef TENSORFLOW_C_EXPERIMENTAL_OPS_GEN_CPP_RENDERERS_OP_IMPLEMENTATION_RENDERER_H_
#define TENSORFLOW_C_EXPERIMENTAL_OPS_GEN_CPP_RENDERERS_OP_IMPLEMENTATION_RENDERER_H_
#include "tensorflow/c/experimental/ops/gen/cpp/renderers/renderer.h"
#include "tensorflow/c/experimental/ops/gen/cpp/renderers/renderer_context.h"
#include "tensorflow/c/experimental/ops/gen/cpp/views/op_view.h"
namespace tensorflow {
namespace generator {
namespace cpp {
class OpImplementationRenderer : public Renderer {
public:
explicit OpImplementationRenderer(RendererContext context, OpView op);
void Render();
private:
void RenderInitialization();
void RenderExecutionListOp();
void RenderExecutionMultipleOutputs();
void RenderExecutionZeroOutputs();
void RenderExecutionSingleOutput();
OpView op_;
};
} // namespace cpp
} // namespace generator
} // namespace tensorflow
#endif // TENSORFLOW_C_EXPERIMENTAL_OPS_GEN_CPP_RENDERERS_OP_IMPLEMENTATION_RENDERER_H_
@@ -0,0 +1,79 @@
/* Copyright 2021 The TensorFlow Authors. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/
#include "tensorflow/c/experimental/ops/gen/cpp/renderers/op_renderer.h"
#include <iterator>
#include <string>
#include <vector>
#include "absl/strings/str_cat.h"
#include "absl/strings/str_join.h"
#include "absl/strings/substitute.h"
#include "tensorflow/c/experimental/ops/gen/cpp/renderers/op_implementation_renderer.h"
#include "tensorflow/c/experimental/ops/gen/cpp/renderers/renderer.h"
#include "tensorflow/c/experimental/ops/gen/cpp/renderers/renderer_context.h"
#include "tensorflow/c/experimental/ops/gen/cpp/views/op_argument_view.h"
#include "tensorflow/c/experimental/ops/gen/cpp/views/op_view.h"
namespace tensorflow {
namespace generator {
namespace cpp {
std::string OpRenderer::Signature() const {
std::vector<std::string> args_with_default_val;
std::vector<std::string> args_without_default_val;
for (OpArgumentView const& argument : op_.AllArguments()) {
bool is_header = (context_.mode == RendererContext::kHeader);
std::string text = argument.Declaration(is_header);
if (is_header) {
absl::StrAppend(&text, argument.Initializer());
}
if (argument.HasDefaultValue()) {
args_with_default_val.push_back(text);
} else {
args_without_default_val.push_back(text);
}
}
std::vector<std::string> arguments;
arguments.reserve(args_without_default_val.size() +
args_with_default_val.size());
arguments.insert(arguments.end(),
std::make_move_iterator(args_without_default_val.begin()),
std::make_move_iterator(args_without_default_val.end()));
arguments.insert(arguments.end(),
std::make_move_iterator(args_with_default_val.begin()),
std::make_move_iterator(args_with_default_val.end()));
return absl::Substitute("$0 $1($2)", "absl::Status", op_.FunctionName(),
absl::StrJoin(arguments, ", "));
}
OpRenderer::OpRenderer(RendererContext context, OpView op)
: Renderer(context), op_(op), comment_(context, op) {}
void OpRenderer::Render() {
comment_.Render();
if (context_.mode == RendererContext::kHeader) {
Statement(Signature());
} else {
BlockOpen(Signature());
OpImplementationRenderer(context_, op_).Render();
BlockClose();
}
BlankLine();
}
} // namespace cpp
} // namespace generator
} // namespace tensorflow
@@ -0,0 +1,44 @@
/* Copyright 2021 The TensorFlow Authors. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/
#ifndef TENSORFLOW_C_EXPERIMENTAL_OPS_GEN_CPP_RENDERERS_OP_RENDERER_H_
#define TENSORFLOW_C_EXPERIMENTAL_OPS_GEN_CPP_RENDERERS_OP_RENDERER_H_
#include "tensorflow/c/experimental/ops/gen/cpp/renderers/op_comment_renderer.h"
#include "tensorflow/c/experimental/ops/gen/cpp/renderers/renderer.h"
#include "tensorflow/c/experimental/ops/gen/cpp/renderers/renderer_context.h"
#include "tensorflow/c/experimental/ops/gen/cpp/views/op_view.h"
#include "tensorflow/core/platform/types.h"
namespace tensorflow {
namespace generator {
namespace cpp {
class OpRenderer : public Renderer {
public:
explicit OpRenderer(RendererContext context, OpView op);
void Render();
private:
OpView op_;
OpCommentRenderer comment_;
std::string Signature() const;
};
} // namespace cpp
} // namespace generator
} // namespace tensorflow
#endif // TENSORFLOW_C_EXPERIMENTAL_OPS_GEN_CPP_RENDERERS_OP_RENDERER_H_
@@ -0,0 +1,87 @@
/* Copyright 2021 The TensorFlow Authors. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/
#include "tensorflow/c/experimental/ops/gen/cpp/renderers/renderer.h"
#include <string>
#include "absl/log/log.h"
#include "absl/strings/match.h"
#include "absl/strings/str_cat.h"
#include "absl/strings/string_view.h"
#include "absl/strings/substitute.h"
#include "tensorflow/c/experimental/ops/gen/cpp/renderers/renderer_context.h"
#include "tensorflow/core/lib/strings/str_util.h"
#include "tensorflow/core/platform/logging.h"
#include "tensorflow/core/platform/stringpiece.h"
namespace tensorflow {
namespace generator {
namespace cpp {
Renderer::Renderer(RendererContext context) : context_(context) {}
Renderer& Renderer::BlankLine() {
context_.code.AddLineWithoutIndent("");
return *this;
}
Renderer& Renderer::CodeLine(const std::string& text) {
context_.code.AddLineWithoutIndent(text);
return *this;
}
Renderer& Renderer::CodeLines(const std::string& text) {
absl::string_view trimmed_text(text);
str_util::RemoveWhitespaceContext(&trimmed_text);
for (const std::string& line : str_util::Split(trimmed_text, '\n')) {
context_.code.AddLineWithoutIndent(line);
}
return *this;
}
Renderer& Renderer::Statement(const std::string& text) {
if (absl::EndsWith(text, ";")) {
LOG(WARNING) << "Superfluous terminating ';' in '" << text << "'";
context_.code.AddLineWithIndent(text);
} else {
context_.code.AddLineWithIndent(absl::StrCat(text, ";"));
}
return *this;
}
Renderer& Renderer::TFStatement(const std::string& text) {
return Statement(absl::Substitute("TF_RETURN_IF_ERROR($0)", text));
}
Renderer& Renderer::CommentLine(const std::string& text) {
context_.code.AddLineWithIndent(absl::StrCat("// ", text));
return *this;
}
Renderer& Renderer::BlockOpen(const std::string& text) {
context_.code.AddLineWithIndent(absl::StrCat(text, " {"));
context_.code.IncreaseIndent();
return *this;
}
Renderer& Renderer::BlockClose(const std::string& text) {
context_.code.DecreaseIndent();
context_.code.AddLineWithIndent(absl::StrCat("}", text));
return *this;
}
} // namespace cpp
} // namespace generator
} // namespace tensorflow
@@ -0,0 +1,100 @@
/* Copyright 2021 The TensorFlow Authors. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/
#ifndef TENSORFLOW_C_EXPERIMENTAL_OPS_GEN_CPP_RENDERERS_RENDERER_H_
#define TENSORFLOW_C_EXPERIMENTAL_OPS_GEN_CPP_RENDERERS_RENDERER_H_
#include "absl/strings/string_view.h"
#include "absl/strings/substitute.h"
#include "tensorflow/c/experimental/ops/gen/cpp/renderers/renderer_context.h"
#include "tensorflow/core/platform/types.h"
namespace tensorflow {
namespace generator {
namespace cpp {
class Renderer {
public:
explicit Renderer(RendererContext context);
protected:
// Append a blank line.
Renderer &BlankLine();
// Append a line of source code, left-justified (not indented).
// Use for preprocessors directives ("#include"), namespaces, etc.
Renderer& CodeLine(const std::string& text);
template <typename... Args>
Renderer CodeLine(absl::string_view text, const Args &...args) {
return CodeLine(absl::Substitute(text, args...));
}
// Append a multiline string of source code, left-justified (not indented).
// Note: Trims leading/trailing whitespace including newlines, making this
// method convenient for multiline raw strings.
// Newlines ('\n') are allowed/expected.
Renderer& CodeLines(const std::string& text);
template <typename... Args>
Renderer CodeLines(absl::string_view text, const Args &...args) {
return CodeLines(absl::Substitute(text, args...));
}
// Indent and append a C++ statement.
// Note: do *not* include a trailing semicolon in the statement text.
Renderer& Statement(const std::string& text);
template <typename... Args>
Renderer Statement(absl::string_view text, const Args &...args) {
return Statement(absl::Substitute(text, args...));
}
// Indent and append a call to a TF method returning a Status to check.
// Note: do *not* include a trailing semicolon in the statement text.
Renderer& TFStatement(const std::string& text);
template <typename... Args>
Renderer TFStatement(absl::string_view text, const Args &...args) {
return TFStatement(absl::Substitute(text, args...));
}
// Indent and append a C++ single-line style comment (using '//').
Renderer& CommentLine(const std::string& text = "");
template <typename... Args>
Renderer CommentLine(absl::string_view text, const Args &...args) {
return CommentLine(absl::Substitute(text, args...));
}
// Append a line of code which starts a new block: trailing with '{') and
// indenting.
Renderer& BlockOpen(const std::string& text);
template <typename... Args>
Renderer BlockOpen(absl::string_view text, const Args &...args) {
return BlockOpen(absl::Substitute(text, args...));
}
// Append a line of code ending a block: unindenting and adding '}'.
// Note: optional trailing text is often a comment, e.g. '// namespace xyz'.
Renderer& BlockClose(const std::string& text = "");
template <typename... Args>
Renderer BlockClose(absl::string_view text, const Args &...args) {
return BlockClose(absl::Substitute(text, args...));
}
protected:
RendererContext context_;
};
} // namespace cpp
} // namespace generator
} // namespace tensorflow
#endif // TENSORFLOW_C_EXPERIMENTAL_OPS_GEN_CPP_RENDERERS_RENDERER_H_
@@ -0,0 +1,39 @@
/* Copyright 2021 The TensorFlow Authors. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/
#ifndef TENSORFLOW_C_EXPERIMENTAL_OPS_GEN_CPP_RENDERERS_RENDERER_CONTEXT_H_
#define TENSORFLOW_C_EXPERIMENTAL_OPS_GEN_CPP_RENDERERS_RENDERER_CONTEXT_H_
#include "tensorflow/c/experimental/ops/gen/common/path_config.h"
#include "tensorflow/c/experimental/ops/gen/common/source_code.h"
#include "tensorflow/c/experimental/ops/gen/cpp/renderers/cpp_config.h"
namespace tensorflow {
namespace generator {
namespace cpp {
struct RendererContext {
enum Mode { kHeader = 0, kSource };
Mode mode;
SourceCode &code;
CppConfig cpp_config;
PathConfig path_config;
};
} // namespace cpp
} // namespace generator
} // namespace tensorflow
#endif // TENSORFLOW_C_EXPERIMENTAL_OPS_GEN_CPP_RENDERERS_RENDERER_CONTEXT_H_
@@ -0,0 +1,84 @@
/* Copyright 2021 The TensorFlow Authors. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/
#include "tensorflow/c/experimental/ops/gen/cpp/renderers/renderer.h"
#include <string>
#include "tensorflow/c/experimental/ops/gen/common/path_config.h"
#include "tensorflow/c/experimental/ops/gen/common/source_code.h"
#include "tensorflow/c/experimental/ops/gen/cpp/renderers/cpp_config.h"
#include "tensorflow/c/experimental/ops/gen/cpp/renderers/renderer_context.h"
#include "tensorflow/core/platform/test.h"
#include "tensorflow/core/platform/types.h"
namespace tensorflow {
namespace generator {
namespace cpp {
namespace {
TEST(Renderer, typical_usage) {
class TestRenderer : Renderer {
public:
explicit TestRenderer(SourceCode& code)
: Renderer(
{RendererContext::kSource, code, CppConfig(), PathConfig()}) {}
void Render() {
CommentLine("File level comment.");
CodeLine("#include \"header.h\"");
BlankLine();
BlockOpen("void TestFunction()");
{
Statement("int i = 1");
BlankLine();
BlockOpen("while (i == 1)");
{
CommentLine("Do nothing, really....");
CodeLine("#if 0");
Statement("call()");
CodeLine("#endif");
BlockClose();
}
BlockClose(" // comment ending TestFunction");
}
}
};
SourceCode code;
TestRenderer(code).Render();
std::string expected = R"(// File level comment.
#include "header.h"
void TestFunction() {
int i = 1;
while (i == 1) {
// Do nothing, really....
#if 0
call();
#endif
}
} // comment ending TestFunction
)";
code.SetSpacesPerIndent(3);
EXPECT_EQ(expected, code.Render());
}
} // namespace
} // namespace cpp
} // namespace generator
} // namespace tensorflow
@@ -0,0 +1,31 @@
load("@rules_cc//cc:cc_library.bzl", "cc_library")
package(
# copybara:uncomment default_applicable_licenses = ["//tensorflow:license"],
default_visibility = ["//visibility:private"],
licenses = ["notice"],
)
cc_library(
name = "views",
srcs = glob(
["*.cc"],
exclude = ["*_test.cc"],
),
hdrs = glob(["*.h"]),
visibility = [
"//tensorflow/c/experimental/ops/gen/cpp:__pkg__",
"//tensorflow/c/experimental/ops/gen/cpp/renderers:__pkg__",
],
deps = [
"//tensorflow/c/experimental/ops/gen/common",
"//tensorflow/c/experimental/ops/gen/model",
"//tensorflow/core:lib",
"//tensorflow/core:lib_internal",
"//tensorflow/core:protos_all_cc",
"@com_google_absl//absl/log",
"@com_google_absl//absl/log:check",
"@com_google_absl//absl/strings",
],
alwayslink = 1,
)
@@ -0,0 +1,47 @@
/* Copyright 2021 The TensorFlow Authors. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/
#include "tensorflow/c/experimental/ops/gen/cpp/views/arg_type_view.h"
#include <string>
#include "tensorflow/c/experimental/ops/gen/model/arg_type.h"
#include "tensorflow/core/framework/types.pb.h"
#include "tensorflow/core/platform/types.h"
namespace tensorflow {
namespace generator {
namespace cpp {
ArgTypeView::ArgTypeView(ArgType arg_type) : arg_type_(arg_type) {}
std::string ArgTypeView::TypeName() const {
if (arg_type_.is_read_only()) {
if (arg_type_.is_list()) {
return "absl::Span<AbstractTensorHandle* const>";
} else {
return "AbstractTensorHandle* const";
}
} else {
if (arg_type_.is_list()) {
return "absl::Span<AbstractTensorHandle*>";
} else {
return "AbstractTensorHandle**";
}
}
}
} // namespace cpp
} // namespace generator
} // namespace tensorflow
@@ -0,0 +1,39 @@
/* Copyright 2021 The TensorFlow Authors. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/
#ifndef TENSORFLOW_C_EXPERIMENTAL_OPS_GEN_CPP_VIEWS_ARG_TYPE_VIEW_H_
#define TENSORFLOW_C_EXPERIMENTAL_OPS_GEN_CPP_VIEWS_ARG_TYPE_VIEW_H_
#include "tensorflow/c/experimental/ops/gen/model/arg_type.h"
#include "tensorflow/core/platform/types.h"
namespace tensorflow {
namespace generator {
namespace cpp {
class ArgTypeView {
public:
explicit ArgTypeView(ArgType arg_type);
std::string TypeName() const;
private:
ArgType arg_type_;
};
} // namespace cpp
} // namespace generator
} // namespace tensorflow
#endif // TENSORFLOW_C_EXPERIMENTAL_OPS_GEN_CPP_VIEWS_ARG_TYPE_VIEW_H_
@@ -0,0 +1,49 @@
/* Copyright 2021 The TensorFlow Authors. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/
#include "tensorflow/c/experimental/ops/gen/cpp/views/arg_view.h"
#include <string>
#include <vector>
#include "tensorflow/c/experimental/ops/gen/model/arg_spec.h"
#include "tensorflow/core/platform/types.h"
namespace tensorflow {
namespace generator {
namespace cpp {
ArgView::ArgView(ArgSpec arg) : arg_(arg) {}
std::string ArgView::VariableName() const { return arg_.name(); }
std::string ArgView::SetterMethod() const {
if (IsList()) {
return "AddInputList";
} else {
return "AddInput";
}
}
std::vector<std::string> ArgView::SetterArgs() const {
return {VariableName()};
}
bool ArgView::IsList() const { return arg_.arg_type().is_list(); }
int ArgView::Position() const { return arg_.position(); }
} // namespace cpp
} // namespace generator
} // namespace tensorflow
@@ -0,0 +1,47 @@
/* Copyright 2021 The TensorFlow Authors. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/
#ifndef TENSORFLOW_C_EXPERIMENTAL_OPS_GEN_CPP_VIEWS_ARG_VIEW_H_
#define TENSORFLOW_C_EXPERIMENTAL_OPS_GEN_CPP_VIEWS_ARG_VIEW_H_
#include <vector>
#include "tensorflow/c/experimental/ops/gen/cpp/views/arg_type_view.h"
#include "tensorflow/c/experimental/ops/gen/model/arg_spec.h"
#include "tensorflow/core/platform/types.h"
namespace tensorflow {
namespace generator {
namespace cpp {
class ArgView {
public:
explicit ArgView(ArgSpec arg);
std::string VariableName() const;
std::string SetterMethod() const;
std::vector<std::string> SetterArgs() const;
int Position() const;
bool IsList() const;
private:
ArgSpec arg_;
};
} // namespace cpp
} // namespace generator
} // namespace tensorflow
#endif // TENSORFLOW_C_EXPERIMENTAL_OPS_GEN_CPP_VIEWS_ARG_VIEW_H_
@@ -0,0 +1,137 @@
/* Copyright 2021 The TensorFlow Authors. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/
#include "tensorflow/c/experimental/ops/gen/cpp/views/attr_view.h"
#include <string>
#include <vector>
#include "absl/log/log.h"
#include "absl/strings/str_cat.h"
#include "absl/strings/substitute.h"
#include "tensorflow/c/experimental/ops/gen/common/case_format.h"
#include "tensorflow/c/experimental/ops/gen/common/view_util.h"
#include "tensorflow/core/framework/attr_value.pb.h"
#include "tensorflow/core/framework/types.pb.h"
namespace tensorflow {
namespace generator {
namespace cpp {
std::string AttrView::VariableName() const { return attr_.name(); }
std::string AttrView::VariableType() const {
// Completely special cases (e.g. strings are different when lists)
if (attr_.full_type() == "string") {
return "const char*";
}
if (attr_.full_type() == "list(string)") {
return "absl::Span<std::string const>";
}
// Normal path: translate base type to C++ ...
std::string c_base_type = attr_.base_type();
if (attr_.base_type() == "type") {
c_base_type = "DataType";
} else if (attr_.base_type() == "shape") {
c_base_type = "const PartialTensorShape";
}
// ... and wrap in a Span<> if it's a list.
if (attr_.is_list()) {
return absl::Substitute("absl::Span<$0>", c_base_type);
} else {
return c_base_type;
}
return attr_.full_type();
}
std::string AttrView::AttrNameString() const { return Quoted(attr_.name()); }
std::string AttrView::DefaultValue() const {
const AttrValue &attr_value = attr_.default_value();
switch (attr_value.value_case()) {
case AttrValue::VALUE_NOT_SET:
return "";
case AttrValue::kType:
return DataType_Name(attr_value.type());
case AttrValue::kS:
return "\"" + attr_value.s() + "\"";
case AttrValue::kI:
return std::to_string(attr_value.i());
case AttrValue::kF:
return std::to_string(attr_value.f());
case AttrValue::kB:
return attr_value.b() ? "true" : "false";
case AttrValue::kList:
if (attr_.full_type() == "list(string)" &&
attr_value.list().s_size() == 0) {
return "{}";
}
LOG(WARNING) << "Unimplemented: default value of list-typed attribute.";
return "/* UNIMPLEMENTED */";
case AttrValue::kShape:
case AttrValue::kTensor:
case AttrValue::kFunc:
case AttrValue::kPlaceholder:
LOG(ERROR) << "Unexpected non-primitive attribute value.";
return "/* ERROR */";
}
}
std::string AttrView::VariableStrLen() const {
return Call("strlen", {VariableName()});
}
std::string AttrView::VariableSpanData() const {
return Call(VariableName(), "data", {}, ".");
}
std::string AttrView::VariableSpanLen() const {
return Call(VariableName(), "length", {}, ".");
}
std::string AttrView::InputArg(bool with_default_value) const {
std::string default_value = DefaultValue();
if (!with_default_value || default_value.empty()) {
return absl::Substitute("$0 $1", VariableType(), attr_.name());
}
return absl::Substitute("$0 $1 = $2", VariableType(), attr_.name(),
default_value);
}
std::string AttrView::SetterMethod() const {
if (!attr_.is_list()) {
return absl::StrCat("SetAttr", toUpperCamel(attr_.full_type()));
} else {
return absl::StrCat("SetAttr", toUpperCamel(attr_.base_type()), "List");
}
}
std::vector<std::string> AttrView::SetterArgs() const {
if (attr_.full_type() == "string") {
return {AttrNameString(), VariableName(), VariableStrLen()};
} else if (attr_.full_type() == "list(string)") {
return {AttrNameString(), VariableName()}; // accepts span directly
} else if (attr_.is_list()) {
return {AttrNameString(), VariableSpanData(), VariableSpanLen()};
} else {
return {AttrNameString(), VariableName()};
}
}
} // namespace cpp
} // namespace generator
} // namespace tensorflow
@@ -0,0 +1,50 @@
/* Copyright 2021 The TensorFlow Authors. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/
#ifndef TENSORFLOW_C_EXPERIMENTAL_OPS_GEN_CPP_VIEWS_ATTR_VIEW_H_
#define TENSORFLOW_C_EXPERIMENTAL_OPS_GEN_CPP_VIEWS_ATTR_VIEW_H_
#include <vector>
#include "tensorflow/c/experimental/ops/gen/model/attr_spec.h"
#include "tensorflow/core/platform/types.h"
namespace tensorflow {
namespace generator {
namespace cpp {
class AttrView {
public:
explicit AttrView(AttrSpec attr) : attr_(attr) {}
std::string VariableName() const;
std::string VariableType() const;
std::string AttrNameString() const;
std::string VariableStrLen() const;
std::string VariableSpanData() const;
std::string VariableSpanLen() const;
std::string DefaultValue() const;
std::string InputArg(bool with_default_value) const;
std::string SetterMethod() const;
std::vector<std::string> SetterArgs() const;
private:
AttrSpec attr_;
};
} // namespace cpp
} // namespace generator
} // namespace tensorflow
#endif // TENSORFLOW_C_EXPERIMENTAL_OPS_GEN_CPP_VIEWS_ATTR_VIEW_H_
@@ -0,0 +1,58 @@
/* Copyright 2021 The TensorFlow Authors. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/
#include "tensorflow/c/experimental/ops/gen/cpp/views/op_argument_view.h"
#include <string>
#include "absl/strings/substitute.h"
#include "tensorflow/c/experimental/ops/gen/cpp/views/arg_type_view.h"
#include "tensorflow/c/experimental/ops/gen/cpp/views/arg_view.h"
#include "tensorflow/c/experimental/ops/gen/cpp/views/attr_view.h"
#include "tensorflow/c/experimental/ops/gen/model/arg_spec.h"
#include "tensorflow/c/experimental/ops/gen/model/attr_spec.h"
namespace tensorflow {
namespace generator {
namespace cpp {
std::string OpArgumentView::Declaration(bool is_header) const {
return absl::Substitute("$0 $1", type_name_, variable_name_);
}
std::string OpArgumentView::Initializer() const {
if (default_value_.empty()) {
return "";
}
return absl::Substitute(" = $0", default_value_);
}
bool OpArgumentView::HasDefaultValue() const { return !default_value_.empty(); }
OpArgumentView::OpArgumentView(std::string type, std::string var,
std::string def)
: type_name_(type), variable_name_(var), default_value_(def) {}
OpArgumentView::OpArgumentView(ArgSpec arg)
: type_name_(ArgTypeView(arg.arg_type()).TypeName()),
variable_name_(ArgView(arg).VariableName()) {}
OpArgumentView::OpArgumentView(AttrSpec attr)
: type_name_(AttrView(attr).VariableType()),
variable_name_(AttrView(attr).VariableName()),
default_value_(AttrView(attr).DefaultValue()) {}
} // namespace cpp
} // namespace generator
} // namespace tensorflow
@@ -0,0 +1,47 @@
/* Copyright 2021 The TensorFlow Authors. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/
#ifndef TENSORFLOW_C_EXPERIMENTAL_OPS_GEN_CPP_VIEWS_OP_ARGUMENT_VIEW_H_
#define TENSORFLOW_C_EXPERIMENTAL_OPS_GEN_CPP_VIEWS_OP_ARGUMENT_VIEW_H_
#include "tensorflow/c/experimental/ops/gen/model/arg_spec.h"
#include "tensorflow/c/experimental/ops/gen/model/attr_spec.h"
#include "tensorflow/core/platform/types.h"
namespace tensorflow {
namespace generator {
namespace cpp {
class OpArgumentView {
public:
explicit OpArgumentView(ArgSpec arg);
explicit OpArgumentView(AttrSpec attr);
explicit OpArgumentView(std::string type, std::string var,
std::string def = "");
std::string Declaration(bool is_header = false) const;
std::string Initializer() const;
bool HasDefaultValue() const;
private:
std::string type_name_;
std::string variable_name_;
std::string default_value_;
};
} // namespace cpp
} // namespace generator
} // namespace tensorflow
#endif // TENSORFLOW_C_EXPERIMENTAL_OPS_GEN_CPP_VIEWS_OP_ARGUMENT_VIEW_H_
@@ -0,0 +1,99 @@
/* Copyright 2021 The TensorFlow Authors. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/
#include "tensorflow/c/experimental/ops/gen/cpp/views/op_view.h"
#include <string>
#include <vector>
#include "absl/log/check.h"
#include "tensorflow/c/experimental/ops/gen/common/view_util.h"
#include "tensorflow/c/experimental/ops/gen/cpp/views/arg_view.h"
#include "tensorflow/c/experimental/ops/gen/cpp/views/attr_view.h"
#include "tensorflow/c/experimental/ops/gen/cpp/views/op_argument_view.h"
#include "tensorflow/c/experimental/ops/gen/model/op_spec.h"
#include "tensorflow/core/lib/strings/str_util.h"
#include "tensorflow/core/platform/logging.h"
namespace tensorflow {
namespace generator {
namespace cpp {
OpView::OpView(OpSpec op)
: op_(op),
input_args_(op_.Inputs().begin(), op_.Inputs().end()),
output_args_(op_.Outputs().begin(), op_.Outputs().end()),
argument_attrs_(op_.Attributes().begin(), op_.Attributes().end()) {
// Initialize function arguments
all_arguments_.push_back(OpArgumentView("AbstractContext*", "ctx"));
for (const auto& arg : op_.Inputs()) {
all_arguments_.push_back(OpArgumentView(arg));
}
for (const auto& arg : op_.Outputs()) {
all_arguments_.push_back(OpArgumentView(arg));
}
for (const auto& attr : op.Attributes()) {
all_arguments_.push_back(OpArgumentView(attr));
}
all_arguments_.push_back(OpArgumentView("const char*", "name", "nullptr"));
all_arguments_.push_back(
OpArgumentView("const char*", "raw_device_name", "nullptr"));
}
const std::vector<ArgView>& OpView::Inputs() const { return input_args_; }
const std::vector<ArgView>& OpView::Outputs() const { return output_args_; }
const std::vector<AttrView>& OpView::Attributes() const {
return argument_attrs_;
}
const std::vector<OpArgumentView>& OpView::AllArguments() const {
return all_arguments_;
}
int OpView::NumInputs() const { return input_args_.size(); }
int OpView::NumOutputs() const { return output_args_.size(); }
ArgView OpView::OnlyInput() const {
CHECK_EQ(input_args_.size(), 1); // Crash OK
return input_args_.front();
}
ArgView OpView::OnlyOutput() const {
CHECK_EQ(output_args_.size(), 1); // Crash OK
return output_args_.front();
}
std::string OpView::FunctionName() const { return op_.name(); }
std::string OpView::OpNameString() const { return Quoted(op_.name()); }
std::string OpView::VariableName() const { return "op_ptr"; }
std::vector<std::string> OpView::Description() const {
return str_util::Split(op_.description(), "\n");
}
std::string OpView::Summary() const { return op_.summary(); }
// Context
bool OpView::IsListOp() const {
return NumOutputs() == 1 && OnlyOutput().IsList();
}
} // namespace cpp
} // namespace generator
} // namespace tensorflow
@@ -0,0 +1,63 @@
/* Copyright 2021 The TensorFlow Authors. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/
#ifndef TENSORFLOW_C_EXPERIMENTAL_OPS_GEN_CPP_VIEWS_OP_VIEW_H_
#define TENSORFLOW_C_EXPERIMENTAL_OPS_GEN_CPP_VIEWS_OP_VIEW_H_
#include <vector>
#include "tensorflow/c/experimental/ops/gen/cpp/views/arg_view.h"
#include "tensorflow/c/experimental/ops/gen/cpp/views/attr_view.h"
#include "tensorflow/c/experimental/ops/gen/cpp/views/op_argument_view.h"
#include "tensorflow/c/experimental/ops/gen/model/op_spec.h"
#include "tensorflow/core/platform/types.h"
namespace tensorflow {
namespace generator {
namespace cpp {
class OpView {
public:
explicit OpView(OpSpec op);
const std::vector<ArgView> &Inputs() const;
const std::vector<ArgView> &Outputs() const;
const std::vector<AttrView> &Attributes() const;
const std::vector<OpArgumentView> &AllArguments() const;
int NumInputs() const;
int NumOutputs() const;
ArgView OnlyInput() const;
ArgView OnlyOutput() const;
std::string FunctionName() const;
std::string VariableName() const;
std::string OpNameString() const;
std::string Summary() const;
std::vector<std::string> Description() const;
bool IsListOp() const;
private:
OpSpec op_;
std::vector<ArgView> input_args_;
std::vector<ArgView> output_args_;
std::vector<AttrView> argument_attrs_;
std::vector<OpArgumentView> all_arguments_;
};
} // namespace cpp
} // namespace generator
} // namespace tensorflow
#endif // TENSORFLOW_C_EXPERIMENTAL_OPS_GEN_CPP_VIEWS_OP_VIEW_H_
@@ -0,0 +1,107 @@
/* Copyright 2021 The TensorFlow Authors. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/
#include <vector>
#include "absl/log/check.h"
#include "absl/log/log.h"
#include "absl/strings/str_cat.h"
#include "tensorflow/c/experimental/ops/gen/common/path_config.h"
#include "tensorflow/c/experimental/ops/gen/cpp/cpp_generator.h"
#include "tensorflow/c/experimental/ops/gen/cpp/renderers/cpp_config.h"
#include "tensorflow/core/platform/init_main.h"
#include "tensorflow/core/platform/logging.h"
#include "tensorflow/core/util/command_line_flags.h"
using tensorflow::string;
namespace generator = tensorflow::generator;
namespace {
class MainConfig {
public:
void InitMain(int* argc, char*** argv) {
std::vector<tensorflow::Flag> flags = Flags();
// Parse known flags
string usage = tensorflow::Flags::Usage(
absl::StrCat(*argv[0], " Op1 [Op2 ...]"), flags);
QCHECK(tensorflow::Flags::Parse(argc, *argv, flags)) << usage; // Crash OK
// Initialize any TensorFlow support, parsing boilerplate flags (e.g. logs)
tensorflow::port::InitMain(usage.c_str(), argc, argv);
// Validate flags
if (help_) {
LOG(QFATAL) << usage; // Crash OK
}
QCHECK(!source_dir_.empty()) << usage; // Crash OK
QCHECK(!output_dir_.empty()) << usage; // Crash OK
QCHECK(!category_.empty()) << usage; // Crash OK
// Remaining arguments (i.e. the positional args) are the requested Op names
op_names_.assign((*argv) + 1, (*argv) + (*argc));
}
generator::cpp::CppConfig CppConfig() {
return generator::cpp::CppConfig(category_);
}
generator::PathConfig PathConfig() {
return generator::PathConfig(output_dir_, source_dir_, api_dirs_,
op_names_);
}
private:
std::vector<tensorflow::Flag> Flags() {
return {
tensorflow::Flag("help", &help_, "Print this help message."),
tensorflow::Flag("category", &category_,
"Category for generated ops (e.g. 'math', 'array')."),
tensorflow::Flag(
"namespace", &name_space_,
"Compact C++ namespace, default is 'tensorflow::ops'."),
tensorflow::Flag(
"output_dir", &output_dir_,
"Directory into which output files will be generated."),
tensorflow::Flag(
"source_dir", &source_dir_,
"The tensorflow root directory, e.g. 'tensorflow/' for "
"in-source include paths. Any path underneath the "
"tensorflow root is also accepted."),
tensorflow::Flag(
"api_dirs", &api_dirs_,
"Comma-separated list of directories containing API definitions.")};
}
bool help_ = false;
string category_;
string name_space_;
string output_dir_;
string source_dir_;
string api_dirs_;
std::vector<string> op_names_;
};
} // namespace
int main(int argc, char* argv[]) {
MainConfig config;
config.InitMain(&argc, &argv);
generator::CppGenerator generator(config.CppConfig(), config.PathConfig());
generator.WriteHeaderFile();
generator.WriteSourceFile();
return 0;
}
@@ -0,0 +1,22 @@
load("@rules_cc//cc:cc_library.bzl", "cc_library")
package(
# copybara:uncomment default_applicable_licenses = ["//tensorflow:license"],
default_visibility = ["//tensorflow/c/experimental/ops/gen:__subpackages__"],
licenses = ["notice"],
)
cc_library(
name = "model",
srcs = glob(["*.cc"]),
hdrs = glob(["*.h"]),
deps = [
"//tensorflow/core:framework_internal",
"//tensorflow/core:lib",
"//tensorflow/core:lib_internal",
"//tensorflow/core:protos_all_cc",
"@com_google_absl//absl/container:flat_hash_set",
"@com_google_absl//absl/strings",
],
alwayslink = 1,
)
@@ -0,0 +1,42 @@
/* Copyright 2021 The TensorFlow Authors. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/
#include "tensorflow/c/experimental/ops/gen/model/arg_spec.h"
#include "tensorflow/c/experimental/ops/gen/model/arg_type.h"
#include "tensorflow/core/framework/op_def.pb.h"
namespace tensorflow {
namespace generator {
ArgSpec::ArgSpec(const OpDef::ArgDef& arg_def, ArgType arg_type, int position)
: name_(arg_def.name()),
description_(arg_def.description()),
arg_type_(arg_type),
position_(position) {}
ArgSpec ArgSpec::CreateInput(const OpDef::ArgDef& arg_def, int position) {
if (arg_def.is_ref()) {
return ArgSpec(arg_def, ArgType::CreateInputRef(arg_def), position);
} else {
return ArgSpec(arg_def, ArgType::CreateInput(arg_def), position);
}
}
ArgSpec ArgSpec::CreateOutput(const OpDef::ArgDef& arg_def, int position) {
return ArgSpec(arg_def, ArgType::CreateOutput(arg_def), position);
}
} // namespace generator
} // namespace tensorflow
@@ -0,0 +1,53 @@
/* Copyright 2021 The TensorFlow Authors. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/
#ifndef TENSORFLOW_C_EXPERIMENTAL_OPS_GEN_MODEL_ARG_SPEC_H_
#define TENSORFLOW_C_EXPERIMENTAL_OPS_GEN_MODEL_ARG_SPEC_H_
#include "tensorflow/c/experimental/ops/gen/model/arg_type.h"
#include "tensorflow/core/framework/op_def.pb.h"
#include "tensorflow/core/platform/types.h"
namespace tensorflow {
namespace generator {
// An input or output argument to an Op.
//
// Essentially, this represents an OpDef::ArgDef and its context within the Op.
class ArgSpec {
public:
ArgSpec() = default;
ArgSpec(const ArgSpec& other) = default;
static ArgSpec CreateInput(const OpDef::ArgDef& arg_def, int position);
static ArgSpec CreateOutput(const OpDef::ArgDef& arg_def, int position);
const std::string& name() const { return name_; }
const std::string& description() const { return description_; }
const ArgType arg_type() const { return arg_type_; }
const int position() const { return position_; }
private:
explicit ArgSpec(const OpDef::ArgDef& arg_def, ArgType arg_type,
int position);
std::string name_;
std::string description_;
ArgType arg_type_;
int position_;
};
} // namespace generator
} // namespace tensorflow
#endif // TENSORFLOW_C_EXPERIMENTAL_OPS_GEN_MODEL_ARG_SPEC_H_
@@ -0,0 +1,47 @@
/* Copyright 2021 The TensorFlow Authors. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/
#include "tensorflow/c/experimental/ops/gen/model/arg_type.h"
#include "tensorflow/core/framework/op_def.pb.h"
namespace tensorflow {
namespace generator {
ArgType ArgType::CreateInput(const OpDef::ArgDef& arg_def) {
return ArgType(arg_def, kInput);
}
ArgType ArgType::CreateInputRef(const OpDef::ArgDef& arg_def) {
return ArgType(arg_def, kInputRef);
}
ArgType ArgType::CreateOutput(const OpDef::ArgDef& arg_def) {
return ArgType(arg_def, kOutput);
}
ArgType::ArgType(const OpDef::ArgDef& arg_def, Kind kind)
: kind_(kind), data_type_(arg_def.type()) {
if (!arg_def.type_attr().empty()) {
type_attr_name_ = arg_def.type_attr();
}
if (!arg_def.type_list_attr().empty()) {
type_attr_name_ = arg_def.type_list_attr();
}
is_list_ =
!arg_def.type_list_attr().empty() || !arg_def.number_attr().empty();
}
} // namespace generator
} // namespace tensorflow
@@ -0,0 +1,55 @@
/* Copyright 2021 The TensorFlow Authors. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/
#ifndef TENSORFLOW_C_EXPERIMENTAL_OPS_GEN_MODEL_ARG_TYPE_H_
#define TENSORFLOW_C_EXPERIMENTAL_OPS_GEN_MODEL_ARG_TYPE_H_
#include "tensorflow/core/framework/op_def.pb.h"
#include "tensorflow/core/platform/types.h"
namespace tensorflow {
namespace generator {
// Type information of an Op argument (ArgSpec)..
//
// This represents the type information with OpDef::ArgDef and any type-related
// context.
class ArgType {
public:
ArgType() = default;
ArgType(const ArgType& other) = default;
static ArgType CreateInput(const OpDef::ArgDef& arg_def);
static ArgType CreateInputRef(const OpDef::ArgDef& arg_def);
static ArgType CreateOutput(const OpDef::ArgDef& arg_def);
const tensorflow::DataType data_type() const { return data_type_; }
const std::string type_attr_name() const { return type_attr_name_; }
const bool is_read_only() const { return kind_ == kInput; }
const bool is_list() const { return is_list_; }
private:
enum Kind { kInput = 0, kInputRef, kOutput };
explicit ArgType(const OpDef::ArgDef& arg_def, Kind kind);
Kind kind_;
tensorflow::DataType data_type_;
std::string type_attr_name_;
bool is_list_;
};
} // namespace generator
} // namespace tensorflow
#endif // TENSORFLOW_C_EXPERIMENTAL_OPS_GEN_MODEL_ARG_TYPE_H_
@@ -0,0 +1,43 @@
/* Copyright 2021 The TensorFlow Authors. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/
#include "tensorflow/c/experimental/ops/gen/model/attr_spec.h"
#include "absl/strings/match.h"
#include "tensorflow/core/framework/op_def.pb.h"
namespace tensorflow {
namespace generator {
AttrSpec AttrSpec::Create(const OpDef::AttrDef& attr_def) {
return AttrSpec(attr_def);
}
AttrSpec::AttrSpec(const OpDef::AttrDef& attr_def) {
name_ = attr_def.name();
description_ = attr_def.description();
full_type_ = attr_def.type();
default_value_ = attr_def.default_value();
if (absl::StartsWith(full_type_, "list(")) {
is_list_ = true;
// strip surrounding "list(%s)"
base_type_ = full_type_.substr(5, full_type_.length() - 6);
} else {
is_list_ = false;
base_type_ = full_type_;
}
}
} // namespace generator
} // namespace tensorflow
@@ -0,0 +1,55 @@
/* Copyright 2021 The TensorFlow Authors. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/
#ifndef TENSORFLOW_C_EXPERIMENTAL_OPS_GEN_MODEL_ATTR_SPEC_H_
#define TENSORFLOW_C_EXPERIMENTAL_OPS_GEN_MODEL_ATTR_SPEC_H_
#include "tensorflow/core/framework/attr_value.pb.h"
#include "tensorflow/core/framework/op_def.pb.h"
#include "tensorflow/core/platform/types.h"
namespace tensorflow {
namespace generator {
// An attribute for an Op, such as an input/output type or for passing options.
//
// Essentially, this represents an OpDef::AttrDef and its context within the Op.
class AttrSpec {
public:
AttrSpec() = default;
AttrSpec(const AttrSpec& other) = default;
static AttrSpec Create(const OpDef::AttrDef& attr_def);
const std::string& name() const { return name_; }
const std::string& description() const { return description_; }
const std::string& full_type() const { return full_type_; }
const std::string& base_type() const { return base_type_; }
const AttrValue& default_value() const { return default_value_; }
const bool is_list() const { return is_list_; }
private:
explicit AttrSpec(const OpDef::AttrDef& attr_def);
std::string name_;
std::string description_;
std::string full_type_;
std::string base_type_;
AttrValue default_value_;
bool is_list_;
};
} // namespace generator
} // namespace tensorflow
#endif // TENSORFLOW_C_EXPERIMENTAL_OPS_GEN_MODEL_ATTR_SPEC_H_
@@ -0,0 +1,66 @@
/* Copyright 2021 The TensorFlow Authors. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/
#include "tensorflow/c/experimental/ops/gen/model/op_spec.h"
#include <string>
#include "absl/container/flat_hash_set.h"
#include "tensorflow/c/experimental/ops/gen/model/arg_spec.h"
#include "tensorflow/c/experimental/ops/gen/model/attr_spec.h"
#include "tensorflow/core/framework/api_def.pb.h"
#include "tensorflow/core/framework/op_def.pb.h"
#include "tensorflow/core/platform/types.h"
namespace tensorflow {
namespace generator {
OpSpec OpSpec::Create(const OpDef& op_def, const ApiDef& api_def) {
return OpSpec(op_def, api_def);
}
OpSpec::OpSpec(const OpDef& op_def, const ApiDef& api_def)
: name_(op_def.name()),
summary_(api_def.summary()),
description_(api_def.description()) {
absl::flat_hash_set<std::string> inferred_attrs;
// Parse the arguments
for (const OpDef::ArgDef& arg_def : op_def.input_arg()) {
ArgSpec arg = ArgSpec::CreateInput(arg_def, input_args_.size());
input_args_.push_back(arg);
if (!arg_def.type_attr().empty()) {
inferred_attrs.insert(arg_def.type_attr());
if (!arg_def.number_attr().empty()) {
inferred_attrs.insert(arg_def.number_attr());
}
} else if (!arg_def.type_list_attr().empty()) {
inferred_attrs.insert(arg_def.type_list_attr());
}
}
for (const OpDef::ArgDef& arg_def : op_def.output_arg()) {
ArgSpec arg = ArgSpec::CreateOutput(arg_def, output_args_.size());
output_args_.push_back(arg);
}
// Parse the attributes.
for (const OpDef::AttrDef& attr_def : op_def.attr()) {
AttrSpec attr = AttrSpec::Create(attr_def);
// Only non-inferred args are added as arguments.
if (inferred_attrs.find(attr_def.name()) == inferred_attrs.end()) {
argument_attrs_.push_back(attr);
}
}
}
} // namespace generator
} // namespace tensorflow
@@ -0,0 +1,60 @@
/* Copyright 2021 The TensorFlow Authors. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/
#ifndef TENSORFLOW_C_EXPERIMENTAL_OPS_GEN_MODEL_OP_SPEC_H_
#define TENSORFLOW_C_EXPERIMENTAL_OPS_GEN_MODEL_OP_SPEC_H_
#include <map>
#include <vector>
#include "tensorflow/c/experimental/ops/gen/model/arg_spec.h"
#include "tensorflow/c/experimental/ops/gen/model/attr_spec.h"
#include "tensorflow/core/framework/api_def.pb.h"
#include "tensorflow/core/framework/op_def.pb.h"
#include "tensorflow/core/platform/types.h"
namespace tensorflow {
namespace generator {
// An Op.
//
// Essentially, this represents an OpDef and any necessary context (e.g ApiDef).
class OpSpec {
public:
static OpSpec Create(const OpDef& op_def, const ApiDef& api_def);
const std::string& name() const { return name_; }
const std::string& summary() const { return summary_; }
const std::string& description() const { return description_; }
const std::vector<ArgSpec>& Inputs() const { return input_args_; }
const std::vector<ArgSpec>& Outputs() const { return output_args_; }
const std::vector<AttrSpec>& Attributes() const { return argument_attrs_; }
private:
explicit OpSpec(const OpDef& op_def, const ApiDef& api_def);
private:
std::string name_;
std::string summary_;
std::string description_;
std::vector<ArgSpec> input_args_;
std::vector<ArgSpec> output_args_;
std::vector<AttrSpec> argument_attrs_;
std::map<std::string, AttrSpec> type_attrs_;
};
} // namespace generator
} // namespace tensorflow
#endif // TENSORFLOW_C_EXPERIMENTAL_OPS_GEN_MODEL_OP_SPEC_H_
+99
View File
@@ -0,0 +1,99 @@
/* Copyright 2021 The TensorFlow Authors. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/
// This file is MACHINE GENERATED! Do not edit.
#include "tensorflow/c/experimental/ops/io_ops.h"
#include <vector>
#include "absl/status/status.h"
#include "absl/types/span.h"
#include "tensorflow/c/eager/abstract_context.h"
#include "tensorflow/c/eager/abstract_operation.h"
#include "tensorflow/c/eager/abstract_tensor_handle.h"
#include "tensorflow/c/eager/tracing_utils.h"
#include "tensorflow/core/framework/types.h" // NOLINT
#include "tensorflow/core/framework/types.pb.h"
#include "tensorflow/core/platform/errors.h" // NOLINT
using tensorflow::tracing::MaybeSetOpName;
namespace tensorflow {
namespace ops {
// Op: RestoreV2()
// Summary: Restores tensors from a V2 checkpoint.
//
// Description:
// For backward compatibility with the V1 format, this Op currently allows
// restoring from a V1 checkpoint as well:
// - This Op first attempts to find the V2 index file pointed to by
// "prefix", and
// if found proceed to read it as a V2 checkpoint;
// - Otherwise the V1 read path is invoked.
// Relying on this behavior is not recommended, as the ability to fall back to
// read V1 might be deprecated and eventually removed.
//
// By default, restores the named tensors in full. If the caller wishes to
// restore specific slices of stored tensors, "shape_and_slices" should be
// non-empty strings and correspondingly well-formed.
//
// Callers must ensure all the named tensors are indeed stored in the
// checkpoint.
absl::Status RestoreV2(AbstractContext* ctx, AbstractTensorHandle* const prefix,
AbstractTensorHandle* const tensor_names,
AbstractTensorHandle* const shape_and_slices,
absl::Span<AbstractTensorHandle*> tensors,
absl::Span<DataType> dtypes, const char* name,
const char* raw_device_name) {
AbstractOperationPtr op_ptr(ctx->CreateOperation());
TF_RETURN_IF_ERROR(op_ptr->Reset("RestoreV2", raw_device_name));
TF_RETURN_IF_ERROR(MaybeSetOpName(op_ptr.get(), name));
TF_RETURN_IF_ERROR(op_ptr->AddInput(prefix));
TF_RETURN_IF_ERROR(op_ptr->AddInput(tensor_names));
TF_RETURN_IF_ERROR(op_ptr->AddInput(shape_and_slices));
TF_RETURN_IF_ERROR(
op_ptr->SetAttrTypeList("dtypes", dtypes.data(), dtypes.length()));
int num_retvals = tensors.size();
return op_ptr->Execute(tensors, &num_retvals);
}
// Op: SaveV2()
// Summary: Saves tensors in V2 checkpoint format.
//
// Description:
// By default, saves the named tensors in full. If the caller wishes to save
// specific slices of full tensors, "shape_and_slices" should be non-empty
// strings and correspondingly well-formed.
absl::Status SaveV2(AbstractContext* ctx, AbstractTensorHandle* const prefix,
AbstractTensorHandle* const tensor_names,
AbstractTensorHandle* const shape_and_slices,
absl::Span<AbstractTensorHandle* const> tensors,
const char* name, const char* raw_device_name) {
AbstractOperationPtr op_ptr(ctx->CreateOperation());
TF_RETURN_IF_ERROR(op_ptr->Reset("SaveV2", raw_device_name));
TF_RETURN_IF_ERROR(MaybeSetOpName(op_ptr.get(), name));
TF_RETURN_IF_ERROR(op_ptr->AddInput(prefix));
TF_RETURN_IF_ERROR(op_ptr->AddInput(tensor_names));
TF_RETURN_IF_ERROR(op_ptr->AddInput(shape_and_slices));
TF_RETURN_IF_ERROR(op_ptr->AddInputList(tensors));
int num_retvals = 0;
std::vector<AbstractTensorHandle*> dummy_outputs;
return op_ptr->Execute(absl::MakeSpan(dummy_outputs), &num_retvals);
}
} // namespace ops
} // namespace tensorflow
+50
View File
@@ -0,0 +1,50 @@
/* Copyright 2021 The TensorFlow Authors. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/
// This file is MACHINE GENERATED! Do not edit.
#ifndef TENSORFLOW_C_EXPERIMENTAL_OPS_IO_OPS_H_
#define TENSORFLOW_C_EXPERIMENTAL_OPS_IO_OPS_H_
#include "absl/status/status.h"
#include "absl/types/span.h"
#include "tensorflow/c/eager/abstract_context.h"
#include "tensorflow/c/eager/abstract_tensor_handle.h"
#include "tensorflow/core/framework/types.h" // NOLINT
#include "tensorflow/core/framework/types.pb.h"
namespace tensorflow {
namespace ops {
// Restores tensors from a V2 checkpoint.
absl::Status RestoreV2(AbstractContext* ctx, AbstractTensorHandle* const prefix,
AbstractTensorHandle* const tensor_names,
AbstractTensorHandle* const shape_and_slices,
absl::Span<AbstractTensorHandle*> tensors,
absl::Span<DataType> dtypes, const char* name = nullptr,
const char* raw_device_name = nullptr);
// Saves tensors in V2 checkpoint format.
absl::Status SaveV2(AbstractContext* ctx, AbstractTensorHandle* const prefix,
AbstractTensorHandle* const tensor_names,
AbstractTensorHandle* const shape_and_slices,
absl::Span<AbstractTensorHandle* const> tensors,
const char* name = nullptr,
const char* raw_device_name = nullptr);
} // namespace ops
} // namespace tensorflow
#endif // TENSORFLOW_C_EXPERIMENTAL_OPS_IO_OPS_H_
+321
View File
@@ -0,0 +1,321 @@
/* Copyright 2021 The TensorFlow Authors. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/
// This file is MACHINE GENERATED! Do not edit.
#include "tensorflow/c/experimental/ops/math_ops.h"
#include "absl/status/status.h"
#include "absl/types/span.h"
#include "tensorflow/c/eager/abstract_context.h"
#include "tensorflow/c/eager/abstract_operation.h"
#include "tensorflow/c/eager/abstract_tensor_handle.h"
#include "tensorflow/c/eager/tracing_utils.h"
#include "tensorflow/core/framework/types.h" // NOLINT
#include "tensorflow/core/platform/errors.h" // NOLINT
using tensorflow::tracing::MaybeSetOpName;
namespace tensorflow {
namespace ops {
// Op: Mul()
// Summary: Returns x * y element-wise.
//
// Description:
// *NOTE*: `Multiply` supports broadcasting. More about broadcasting
// [here](http://docs.scipy.org/doc/numpy/user/basics.broadcasting.html)
absl::Status Mul(AbstractContext* ctx, AbstractTensorHandle* const x,
AbstractTensorHandle* const y, AbstractTensorHandle** z,
const char* name, const char* raw_device_name) {
AbstractOperationPtr op_ptr(ctx->CreateOperation());
TF_RETURN_IF_ERROR(op_ptr->Reset("Mul", raw_device_name));
TF_RETURN_IF_ERROR(MaybeSetOpName(op_ptr.get(), name));
TF_RETURN_IF_ERROR(op_ptr->AddInput(x));
TF_RETURN_IF_ERROR(op_ptr->AddInput(y));
int num_retvals = 1;
return op_ptr->Execute(absl::MakeSpan(z, 1), &num_retvals);
}
// Op: Conj()
// Summary: Returns the complex conjugate of a complex number.
//
// Description:
// Given a tensor `input` of complex numbers, this operation returns a tensor
// of complex numbers that are the complex conjugate of each element in
// `input`. The complex numbers in `input` must be of the form \\(a + bj\\),
// where *a* is the real part and *b* is the imaginary part.
//
// The complex conjugate returned by this operation is of the form \\(a -
// bj\\).
//
// For example:
//
// ```
// # tensor 'input' is [-2.25 + 4.75j, 3.25 + 5.75j]
// tf.conj(input) ==> [-2.25 - 4.75j, 3.25 - 5.75j]
// ```
absl::Status Conj(AbstractContext* ctx, AbstractTensorHandle* const input,
AbstractTensorHandle** output, const char* name,
const char* raw_device_name) {
AbstractOperationPtr op_ptr(ctx->CreateOperation());
TF_RETURN_IF_ERROR(op_ptr->Reset("Conj", raw_device_name));
TF_RETURN_IF_ERROR(MaybeSetOpName(op_ptr.get(), name));
TF_RETURN_IF_ERROR(op_ptr->AddInput(input));
int num_retvals = 1;
return op_ptr->Execute(absl::MakeSpan(output, 1), &num_retvals);
}
// Op: AddV2()
// Summary: Returns x + y element-wise.
//
// Description:
// *NOTE*: `Add` supports broadcasting. `AddN` does not. More about
// broadcasting
// [here](http://docs.scipy.org/doc/numpy/user/basics.broadcasting.html)
absl::Status AddV2(AbstractContext* ctx, AbstractTensorHandle* const x,
AbstractTensorHandle* const y, AbstractTensorHandle** z,
const char* name, const char* raw_device_name) {
AbstractOperationPtr op_ptr(ctx->CreateOperation());
TF_RETURN_IF_ERROR(op_ptr->Reset("AddV2", raw_device_name));
TF_RETURN_IF_ERROR(MaybeSetOpName(op_ptr.get(), name));
TF_RETURN_IF_ERROR(op_ptr->AddInput(x));
TF_RETURN_IF_ERROR(op_ptr->AddInput(y));
int num_retvals = 1;
return op_ptr->Execute(absl::MakeSpan(z, 1), &num_retvals);
}
// Op: MatMul()
// Summary: Multiply the matrix "a" by the matrix "b".
//
// Description:
// The inputs must be two-dimensional matrices and the inner dimension of
// "a" (after being transposed if transpose_a is true) must match the
// outer dimension of "b" (after being transposed if transposed_b is
// true).
//
// *Note*: The default kernel implementation for MatMul on GPUs uses
// cublas.
absl::Status MatMul(AbstractContext* ctx, AbstractTensorHandle* const a,
AbstractTensorHandle* const b,
AbstractTensorHandle** product, bool transpose_a,
bool transpose_b, bool grad_a, bool grad_b,
const char* name, const char* raw_device_name) {
AbstractOperationPtr op_ptr(ctx->CreateOperation());
TF_RETURN_IF_ERROR(op_ptr->Reset("MatMul", raw_device_name));
TF_RETURN_IF_ERROR(MaybeSetOpName(op_ptr.get(), name));
TF_RETURN_IF_ERROR(op_ptr->AddInput(a));
TF_RETURN_IF_ERROR(op_ptr->AddInput(b));
TF_RETURN_IF_ERROR(op_ptr->SetAttrBool("transpose_a", transpose_a));
TF_RETURN_IF_ERROR(op_ptr->SetAttrBool("transpose_b", transpose_b));
TF_RETURN_IF_ERROR(op_ptr->SetAttrBool("grad_a", grad_a));
TF_RETURN_IF_ERROR(op_ptr->SetAttrBool("grad_b", grad_b));
int num_retvals = 1;
return op_ptr->Execute(absl::MakeSpan(product, 1), &num_retvals);
}
// Op: Neg()
// Summary: Computes numerical negative value element-wise.
//
// Description:
// I.e., \\(y = -x\\).
absl::Status Neg(AbstractContext* ctx, AbstractTensorHandle* const x,
AbstractTensorHandle** y, const char* name,
const char* raw_device_name) {
AbstractOperationPtr op_ptr(ctx->CreateOperation());
TF_RETURN_IF_ERROR(op_ptr->Reset("Neg", raw_device_name));
TF_RETURN_IF_ERROR(MaybeSetOpName(op_ptr.get(), name));
TF_RETURN_IF_ERROR(op_ptr->AddInput(x));
int num_retvals = 1;
return op_ptr->Execute(absl::MakeSpan(y, 1), &num_retvals);
}
// Op: Sum()
// Summary: Computes the sum of elements across dimensions of a tensor.
//
// Description:
// Reduces `input` along the dimensions given in `axis`. Unless
// `keep_dims` is true, the rank of the tensor is reduced by 1 for each entry
// in `axis`. If `keep_dims` is true, the reduced dimensions are retained with
// length 1.
absl::Status Sum(AbstractContext* ctx, AbstractTensorHandle* const input,
AbstractTensorHandle* const reduction_indices,
AbstractTensorHandle** output, bool keep_dims,
const char* name, const char* raw_device_name) {
AbstractOperationPtr op_ptr(ctx->CreateOperation());
TF_RETURN_IF_ERROR(op_ptr->Reset("Sum", raw_device_name));
TF_RETURN_IF_ERROR(MaybeSetOpName(op_ptr.get(), name));
TF_RETURN_IF_ERROR(op_ptr->AddInput(input));
TF_RETURN_IF_ERROR(op_ptr->AddInput(reduction_indices));
TF_RETURN_IF_ERROR(op_ptr->SetAttrBool("keep_dims", keep_dims));
int num_retvals = 1;
return op_ptr->Execute(absl::MakeSpan(output, 1), &num_retvals);
}
// Op: Sub()
// Summary: Returns x - y element-wise.
//
// Description:
// *NOTE*: `Subtract` supports broadcasting. More about broadcasting
// [here](http://docs.scipy.org/doc/numpy/user/basics.broadcasting.html)
absl::Status Sub(AbstractContext* ctx, AbstractTensorHandle* const x,
AbstractTensorHandle* const y, AbstractTensorHandle** z,
const char* name, const char* raw_device_name) {
AbstractOperationPtr op_ptr(ctx->CreateOperation());
TF_RETURN_IF_ERROR(op_ptr->Reset("Sub", raw_device_name));
TF_RETURN_IF_ERROR(MaybeSetOpName(op_ptr.get(), name));
TF_RETURN_IF_ERROR(op_ptr->AddInput(x));
TF_RETURN_IF_ERROR(op_ptr->AddInput(y));
int num_retvals = 1;
return op_ptr->Execute(absl::MakeSpan(z, 1), &num_retvals);
}
// Op: Div()
// Summary: Returns x / y element-wise.
//
// Description:
// *NOTE*: `Div` supports broadcasting. More about broadcasting
// [here](http://docs.scipy.org/doc/numpy/user/basics.broadcasting.html)
absl::Status Div(AbstractContext* ctx, AbstractTensorHandle* const x,
AbstractTensorHandle* const y, AbstractTensorHandle** z,
const char* name, const char* raw_device_name) {
AbstractOperationPtr op_ptr(ctx->CreateOperation());
TF_RETURN_IF_ERROR(op_ptr->Reset("Div", raw_device_name));
TF_RETURN_IF_ERROR(MaybeSetOpName(op_ptr.get(), name));
TF_RETURN_IF_ERROR(op_ptr->AddInput(x));
TF_RETURN_IF_ERROR(op_ptr->AddInput(y));
int num_retvals = 1;
return op_ptr->Execute(absl::MakeSpan(z, 1), &num_retvals);
}
// Op: DivNoNan()
// Summary: Returns 0 if the denominator is zero.
//
// Description:
//
// *NOTE*: `DivNoNan` supports broadcasting. More about broadcasting
// [here](http://docs.scipy.org/doc/numpy/user/basics.broadcasting.html)
absl::Status DivNoNan(AbstractContext* ctx, AbstractTensorHandle* const x,
AbstractTensorHandle* const y, AbstractTensorHandle** z,
const char* name, const char* raw_device_name) {
AbstractOperationPtr op_ptr(ctx->CreateOperation());
TF_RETURN_IF_ERROR(op_ptr->Reset("DivNoNan", raw_device_name));
TF_RETURN_IF_ERROR(MaybeSetOpName(op_ptr.get(), name));
TF_RETURN_IF_ERROR(op_ptr->AddInput(x));
TF_RETURN_IF_ERROR(op_ptr->AddInput(y));
int num_retvals = 1;
return op_ptr->Execute(absl::MakeSpan(z, 1), &num_retvals);
}
// Op: Exp()
// Summary: Computes exponential of x element-wise. \\(y = e^x\\).
//
// Description:
// This function computes the exponential of every element in the input
// tensor. i.e. `exp(x)` or `e^(x)`, where `x` is the input tensor. `e`
// denotes Euler's number and is approximately equal to 2.718281. Output is
// positive for any real input.
//
// ```python
// x = tf.constant(2.0)
// tf.math.exp(x) ==> 7.389056
//
// x = tf.constant([2.0, 8.0])
// tf.math.exp(x) ==> array([7.389056, 2980.958], dtype=float32)
// ```
//
// For complex numbers, the exponential value is calculated as follows:
//
// ```
// e^(x+iy) = e^x * e^iy = e^x * (cos y + i sin y)
// ```
//
// Let's consider complex number 1+1j as an example.
// e^1 * (cos 1 + i sin 1) = 2.7182818284590 * (0.54030230586+0.8414709848j)
//
// ```python
// x = tf.constant(1 + 1j)
// tf.math.exp(x) ==> 1.4686939399158851+2.2873552871788423j
// ```
absl::Status Exp(AbstractContext* ctx, AbstractTensorHandle* const x,
AbstractTensorHandle** y, const char* name,
const char* raw_device_name) {
AbstractOperationPtr op_ptr(ctx->CreateOperation());
TF_RETURN_IF_ERROR(op_ptr->Reset("Exp", raw_device_name));
TF_RETURN_IF_ERROR(MaybeSetOpName(op_ptr.get(), name));
TF_RETURN_IF_ERROR(op_ptr->AddInput(x));
int num_retvals = 1;
return op_ptr->Execute(absl::MakeSpan(y, 1), &num_retvals);
}
// Op: Sqrt()
// Summary: Computes square root of x element-wise.
//
// Description:
// I.e., \\(y = \sqrt{x} = x^{1/2}\\).
absl::Status Sqrt(AbstractContext* ctx, AbstractTensorHandle* const x,
AbstractTensorHandle** y, const char* name,
const char* raw_device_name) {
AbstractOperationPtr op_ptr(ctx->CreateOperation());
TF_RETURN_IF_ERROR(op_ptr->Reset("Sqrt", raw_device_name));
TF_RETURN_IF_ERROR(MaybeSetOpName(op_ptr.get(), name));
TF_RETURN_IF_ERROR(op_ptr->AddInput(x));
int num_retvals = 1;
return op_ptr->Execute(absl::MakeSpan(y, 1), &num_retvals);
}
// Op: SqrtGrad()
// Summary: Computes the gradient for the sqrt of `x` wrt its input.
//
// Description:
// Specifically, `grad = dy * 0.5 / y`, where `y = sqrt(x)`, and `dy`
// is the corresponding input gradient.
absl::Status SqrtGrad(AbstractContext* ctx, AbstractTensorHandle* const y,
AbstractTensorHandle* const dy, AbstractTensorHandle** z,
const char* name, const char* raw_device_name) {
AbstractOperationPtr op_ptr(ctx->CreateOperation());
TF_RETURN_IF_ERROR(op_ptr->Reset("SqrtGrad", raw_device_name));
TF_RETURN_IF_ERROR(MaybeSetOpName(op_ptr.get(), name));
TF_RETURN_IF_ERROR(op_ptr->AddInput(y));
TF_RETURN_IF_ERROR(op_ptr->AddInput(dy));
int num_retvals = 1;
return op_ptr->Execute(absl::MakeSpan(z, 1), &num_retvals);
}
// Op: Log1p()
// Summary: Computes natural logarithm of (1 + x) element-wise.
//
// Description:
// I.e., \\(y = \log_e (1 + x)\\).
//
// Example:
//
// ```python
// x = tf.constant([0, 0.5, 1, 5])
// tf.math.log1p(x) ==> [0., 0.4054651, 0.6931472, 1.7917595]
// ```
absl::Status Log1p(AbstractContext* ctx, AbstractTensorHandle* const x,
AbstractTensorHandle** y, const char* name,
const char* raw_device_name) {
AbstractOperationPtr op_ptr(ctx->CreateOperation());
TF_RETURN_IF_ERROR(op_ptr->Reset("Log1p", raw_device_name));
TF_RETURN_IF_ERROR(MaybeSetOpName(op_ptr.get(), name));
TF_RETURN_IF_ERROR(op_ptr->AddInput(x));
int num_retvals = 1;
return op_ptr->Execute(absl::MakeSpan(y, 1), &num_retvals);
}
} // namespace ops
} // namespace tensorflow
+108
View File
@@ -0,0 +1,108 @@
/* Copyright 2021 The TensorFlow Authors. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/
// This file is MACHINE GENERATED! Do not edit.
#ifndef TENSORFLOW_C_EXPERIMENTAL_OPS_MATH_OPS_H_
#define TENSORFLOW_C_EXPERIMENTAL_OPS_MATH_OPS_H_
#include "absl/status/status.h"
#include "tensorflow/c/eager/abstract_context.h"
#include "tensorflow/c/eager/abstract_tensor_handle.h"
#include "tensorflow/core/framework/types.h" // NOLINT
namespace tensorflow {
namespace ops {
// Returns x * y element-wise.
absl::Status Mul(AbstractContext* ctx, AbstractTensorHandle* const x,
AbstractTensorHandle* const y, AbstractTensorHandle** z,
const char* name = nullptr,
const char* raw_device_name = nullptr);
// Returns the complex conjugate of a complex number.
absl::Status Conj(AbstractContext* ctx, AbstractTensorHandle* const input,
AbstractTensorHandle** output, const char* name = nullptr,
const char* raw_device_name = nullptr);
// Returns x + y element-wise.
absl::Status AddV2(AbstractContext* ctx, AbstractTensorHandle* const x,
AbstractTensorHandle* const y, AbstractTensorHandle** z,
const char* name = nullptr,
const char* raw_device_name = nullptr);
// Multiply the matrix "a" by the matrix "b".
absl::Status MatMul(AbstractContext* ctx, AbstractTensorHandle* const a,
AbstractTensorHandle* const b,
AbstractTensorHandle** product, bool transpose_a = false,
bool transpose_b = false, bool grad_a = false,
bool grad_b = false, const char* name = nullptr,
const char* raw_device_name = nullptr);
// Computes numerical negative value element-wise.
absl::Status Neg(AbstractContext* ctx, AbstractTensorHandle* const x,
AbstractTensorHandle** y, const char* name = nullptr,
const char* raw_device_name = nullptr);
// Computes the sum of elements across dimensions of a tensor.
absl::Status Sum(AbstractContext* ctx, AbstractTensorHandle* const input,
AbstractTensorHandle* const reduction_indices,
AbstractTensorHandle** output, bool keep_dims = false,
const char* name = nullptr,
const char* raw_device_name = nullptr);
// Returns x - y element-wise.
absl::Status Sub(AbstractContext* ctx, AbstractTensorHandle* const x,
AbstractTensorHandle* const y, AbstractTensorHandle** z,
const char* name = nullptr,
const char* raw_device_name = nullptr);
// Returns x / y element-wise.
absl::Status Div(AbstractContext* ctx, AbstractTensorHandle* const x,
AbstractTensorHandle* const y, AbstractTensorHandle** z,
const char* name = nullptr,
const char* raw_device_name = nullptr);
// Returns 0 if the denominator is zero.
absl::Status DivNoNan(AbstractContext* ctx, AbstractTensorHandle* const x,
AbstractTensorHandle* const y, AbstractTensorHandle** z,
const char* name = nullptr,
const char* raw_device_name = nullptr);
// Computes exponential of x element-wise. \\(y = e^x\\).
absl::Status Exp(AbstractContext* ctx, AbstractTensorHandle* const x,
AbstractTensorHandle** y, const char* name = nullptr,
const char* raw_device_name = nullptr);
// Computes square root of x element-wise.
absl::Status Sqrt(AbstractContext* ctx, AbstractTensorHandle* const x,
AbstractTensorHandle** y, const char* name = nullptr,
const char* raw_device_name = nullptr);
// Computes the gradient for the sqrt of `x` wrt its input.
absl::Status SqrtGrad(AbstractContext* ctx, AbstractTensorHandle* const y,
AbstractTensorHandle* const dy, AbstractTensorHandle** z,
const char* name = nullptr,
const char* raw_device_name = nullptr);
// Computes natural logarithm of (1 + x) element-wise.
absl::Status Log1p(AbstractContext* ctx, AbstractTensorHandle* const x,
AbstractTensorHandle** y, const char* name = nullptr,
const char* raw_device_name = nullptr);
} // namespace ops
} // namespace tensorflow
#endif // TENSORFLOW_C_EXPERIMENTAL_OPS_MATH_OPS_H_
+170
View File
@@ -0,0 +1,170 @@
/* Copyright 2021 The TensorFlow Authors. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/
// This file is MACHINE GENERATED! Do not edit.
#include "tensorflow/c/experimental/ops/nn_ops.h"
#include <cstring> // NOLINT
#include "absl/status/status.h"
#include "absl/types/span.h"
#include "tensorflow/c/eager/abstract_context.h"
#include "tensorflow/c/eager/abstract_operation.h"
#include "tensorflow/c/eager/abstract_tensor_handle.h"
#include "tensorflow/c/eager/tracing_utils.h"
#include "tensorflow/core/framework/types.h" // NOLINT
#include "tensorflow/core/platform/errors.h" // NOLINT
using tensorflow::tracing::MaybeSetOpName;
namespace tensorflow {
namespace ops {
// Op: SparseSoftmaxCrossEntropyWithLogits()
// Summary: Computes softmax cross entropy cost and gradients to backpropagate.
//
// Description:
// Unlike `SoftmaxCrossEntropyWithLogits`, this operation does not accept
// a matrix of label probabilities, but rather a single label per row
// of features. This label is considered to have probability 1.0 for the
// given row.
//
// Inputs are the logits, not probabilities.
absl::Status SparseSoftmaxCrossEntropyWithLogits(
AbstractContext* ctx, AbstractTensorHandle* const features,
AbstractTensorHandle* const labels, AbstractTensorHandle** loss,
AbstractTensorHandle** backprop, const char* name,
const char* raw_device_name) {
AbstractOperationPtr op_ptr(ctx->CreateOperation());
TF_RETURN_IF_ERROR(
op_ptr->Reset("SparseSoftmaxCrossEntropyWithLogits", raw_device_name));
TF_RETURN_IF_ERROR(MaybeSetOpName(op_ptr.get(), name));
TF_RETURN_IF_ERROR(op_ptr->AddInput(features));
TF_RETURN_IF_ERROR(op_ptr->AddInput(labels));
int num_retvals = 2;
AbstractTensorHandle* temp_outputs[2] = {nullptr};
absl::Status status = op_ptr->Execute(temp_outputs, &num_retvals);
TF_RETURN_IF_ERROR(status);
if (num_retvals != 2) {
return absl::InternalError(
"SparseSoftmaxCrossEntropyWithLogits: unexpected number of outputs");
}
if (status.ok()) {
*loss = temp_outputs[0];
*backprop = temp_outputs[1];
}
return status;
}
// Op: ReluGrad()
// Summary: Computes rectified linear gradients for a Relu operation.
//
// Description:
absl::Status ReluGrad(AbstractContext* ctx,
AbstractTensorHandle* const gradients,
AbstractTensorHandle* const features,
AbstractTensorHandle** backprops, const char* name,
const char* raw_device_name) {
AbstractOperationPtr op_ptr(ctx->CreateOperation());
TF_RETURN_IF_ERROR(op_ptr->Reset("ReluGrad", raw_device_name));
TF_RETURN_IF_ERROR(MaybeSetOpName(op_ptr.get(), name));
TF_RETURN_IF_ERROR(op_ptr->AddInput(gradients));
TF_RETURN_IF_ERROR(op_ptr->AddInput(features));
int num_retvals = 1;
TF_RETURN_IF_ERROR(
op_ptr->Execute(absl::MakeSpan(backprops, 1), &num_retvals));
if (num_retvals != 1) {
return absl::InternalError("ReluGrad: unexpected number of outputs");
}
return absl::OkStatus();
}
// Op: Relu()
// Summary: Computes rectified linear: `max(features, 0)`.
//
// Description:
// See: https://en.wikipedia.org/wiki/Rectifier_(neural_networks)
// Example usage:
// >>> tf.nn.relu([-2., 0., 3.]).numpy()
// array([0., 0., 3.], dtype=float32)
absl::Status Relu(AbstractContext* ctx, AbstractTensorHandle* const features,
AbstractTensorHandle** activations, const char* name,
const char* raw_device_name) {
AbstractOperationPtr op_ptr(ctx->CreateOperation());
TF_RETURN_IF_ERROR(op_ptr->Reset("Relu", raw_device_name));
TF_RETURN_IF_ERROR(MaybeSetOpName(op_ptr.get(), name));
TF_RETURN_IF_ERROR(op_ptr->AddInput(features));
int num_retvals = 1;
TF_RETURN_IF_ERROR(
op_ptr->Execute(absl::MakeSpan(activations, 1), &num_retvals));
if (num_retvals != 1) {
return absl::InternalError("Relu: unexpected number of outputs");
}
return absl::OkStatus();
}
// Op: BiasAdd()
// Summary: Adds `bias` to `value`.
//
// Description:
// This is a special case of `tf.add` where `bias` is restricted to be 1-D.
// Broadcasting is supported, so `value` may have any number of dimensions.
absl::Status BiasAdd(AbstractContext* ctx, AbstractTensorHandle* const value,
AbstractTensorHandle* const bias,
AbstractTensorHandle** output, const char* data_format,
const char* name, const char* raw_device_name) {
AbstractOperationPtr op_ptr(ctx->CreateOperation());
TF_RETURN_IF_ERROR(op_ptr->Reset("BiasAdd", raw_device_name));
TF_RETURN_IF_ERROR(MaybeSetOpName(op_ptr.get(), name));
TF_RETURN_IF_ERROR(op_ptr->AddInput(value));
TF_RETURN_IF_ERROR(op_ptr->AddInput(bias));
TF_RETURN_IF_ERROR(
op_ptr->SetAttrString("data_format", data_format, strlen(data_format)));
int num_retvals = 1;
TF_RETURN_IF_ERROR(op_ptr->Execute(absl::MakeSpan(output, 1), &num_retvals));
if (num_retvals != 1) {
return absl::InternalError("BiasAdd: unexpected number of outputs");
}
return absl::OkStatus();
}
// Op: BiasAddGrad()
// Summary: The backward operation for "BiasAdd" on the "bias" tensor.
//
// Description:
// It accumulates all the values from out_backprop into the feature dimension.
// For NHWC data format, the feature dimension is the last. For NCHW data
// format, the feature dimension is the third-to-last.
absl::Status BiasAddGrad(AbstractContext* ctx,
AbstractTensorHandle* const out_backprop,
AbstractTensorHandle** output, const char* data_format,
const char* name, const char* raw_device_name) {
AbstractOperationPtr op_ptr(ctx->CreateOperation());
TF_RETURN_IF_ERROR(op_ptr->Reset("BiasAddGrad", raw_device_name));
TF_RETURN_IF_ERROR(MaybeSetOpName(op_ptr.get(), name));
TF_RETURN_IF_ERROR(op_ptr->AddInput(out_backprop));
TF_RETURN_IF_ERROR(
op_ptr->SetAttrString("data_format", data_format, strlen(data_format)));
int num_retvals = 1;
TF_RETURN_IF_ERROR(op_ptr->Execute(absl::MakeSpan(output, 1), &num_retvals));
if (num_retvals != 1) {
return absl::InternalError("BiasAddGrad: unexpected number of outputs");
}
return absl::OkStatus();
}
} // namespace ops
} // namespace tensorflow
+69
View File
@@ -0,0 +1,69 @@
/* Copyright 2021 The TensorFlow Authors. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/
// This file is MACHINE GENERATED! Do not edit.
#ifndef TENSORFLOW_C_EXPERIMENTAL_OPS_NN_OPS_H_
#define TENSORFLOW_C_EXPERIMENTAL_OPS_NN_OPS_H_
#include "absl/status/status.h"
#include "tensorflow/c/eager/abstract_context.h"
#include "tensorflow/c/eager/abstract_tensor_handle.h"
#include "tensorflow/core/framework/types.h" // NOLINT
namespace tensorflow {
namespace ops {
// Computes softmax cross entropy cost and gradients to backpropagate.
absl::Status SparseSoftmaxCrossEntropyWithLogits(
AbstractContext* ctx, AbstractTensorHandle* const features,
AbstractTensorHandle* const labels, AbstractTensorHandle** loss,
AbstractTensorHandle** backprop, const char* name = nullptr,
const char* raw_device_name = nullptr);
// Computes rectified linear gradients for a Relu operation.
absl::Status ReluGrad(AbstractContext* ctx,
AbstractTensorHandle* const gradients,
AbstractTensorHandle* const features,
AbstractTensorHandle** backprops,
const char* name = nullptr,
const char* raw_device_name = nullptr);
// Computes rectified linear: `max(features, 0)`.
absl::Status Relu(AbstractContext* ctx, AbstractTensorHandle* const features,
AbstractTensorHandle** activations,
const char* name = nullptr,
const char* raw_device_name = nullptr);
// Adds `bias` to `value`.
absl::Status BiasAdd(AbstractContext* ctx, AbstractTensorHandle* const value,
AbstractTensorHandle* const bias,
AbstractTensorHandle** output,
const char* data_format = "NHWC",
const char* name = nullptr,
const char* raw_device_name = nullptr);
// The backward operation for "BiasAdd" on the "bias" tensor.
absl::Status BiasAddGrad(AbstractContext* ctx,
AbstractTensorHandle* const out_backprop,
AbstractTensorHandle** output,
const char* data_format = "NHWC",
const char* name = nullptr,
const char* raw_device_name = nullptr);
} // namespace ops
} // namespace tensorflow
#endif // TENSORFLOW_C_EXPERIMENTAL_OPS_NN_OPS_H_
@@ -0,0 +1,134 @@
/* Copyright 2021 The TensorFlow Authors. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/
// This file is MACHINE GENERATED! Do not edit.
#include "tensorflow/c/experimental/ops/resource_variable_ops.h"
#include <cstring> // NOLINT
#include <string>
#include <vector>
#include "absl/status/status.h"
#include "absl/types/span.h"
#include "tensorflow/c/eager/abstract_context.h"
#include "tensorflow/c/eager/abstract_operation.h"
#include "tensorflow/c/eager/abstract_tensor_handle.h"
#include "tensorflow/c/eager/tracing_utils.h"
#include "tensorflow/core/framework/tensor_shape.h"
#include "tensorflow/core/framework/types.h" // NOLINT
#include "tensorflow/core/framework/types.pb.h"
#include "tensorflow/core/platform/errors.h" // NOLINT
using tensorflow::tracing::MaybeSetOpName;
namespace tensorflow {
namespace ops {
// Op: VarHandleOp()
// Summary: Creates a handle to a Variable resource.
//
// Description:
absl::Status VarHandleOp(AbstractContext* ctx, AbstractTensorHandle** resource,
DataType dtype, const PartialTensorShape shape,
const char* container, const char* shared_name,
const char* debug_name,
absl::Span<std::string const> allowed_devices,
const char* name, const char* raw_device_name) {
AbstractOperationPtr op_ptr(ctx->CreateOperation());
TF_RETURN_IF_ERROR(op_ptr->Reset("VarHandleOp", raw_device_name));
TF_RETURN_IF_ERROR(MaybeSetOpName(op_ptr.get(), name));
TF_RETURN_IF_ERROR(
op_ptr->SetAttrString("container", container, strlen(container)));
TF_RETURN_IF_ERROR(
op_ptr->SetAttrString("shared_name", shared_name, strlen(shared_name)));
TF_RETURN_IF_ERROR(
op_ptr->SetAttrString("debug_name", debug_name, strlen(debug_name)));
TF_RETURN_IF_ERROR(op_ptr->SetAttrType("dtype", dtype));
TF_RETURN_IF_ERROR(op_ptr->SetAttrShape("shape", shape));
TF_RETURN_IF_ERROR(
op_ptr->SetAttrStringList("allowed_devices", allowed_devices));
int num_retvals = 1;
return op_ptr->Execute(absl::MakeSpan(resource, 1), &num_retvals);
}
// Op: ReadVariableOp()
// Summary: Reads the value of a variable.
//
// Description:
// The tensor returned by this operation is immutable.
//
// The value returned by this operation is guaranteed to be influenced by all
// the writes on which this operation depends directly or indirectly, and to
// not be influenced by any of the writes which depend directly or indirectly
// on this operation.
absl::Status ReadVariableOp(AbstractContext* ctx,
AbstractTensorHandle* const resource,
AbstractTensorHandle** value, DataType dtype,
const char* name, const char* raw_device_name) {
AbstractOperationPtr op_ptr(ctx->CreateOperation());
TF_RETURN_IF_ERROR(op_ptr->Reset("ReadVariableOp", raw_device_name));
TF_RETURN_IF_ERROR(MaybeSetOpName(op_ptr.get(), name));
TF_RETURN_IF_ERROR(op_ptr->AddInput(resource));
TF_RETURN_IF_ERROR(op_ptr->SetAttrType("dtype", dtype));
int num_retvals = 1;
return op_ptr->Execute(absl::MakeSpan(value, 1), &num_retvals);
}
// Op: AssignVariableOp()
// Summary: Assigns a new value to a variable.
//
// Description:
// Any ReadVariableOp with a control dependency on this op is guaranteed to
// return this value or a subsequent newer value of the variable.
absl::Status AssignVariableOp(AbstractContext* ctx,
AbstractTensorHandle* const resource,
AbstractTensorHandle* const value,
bool validate_shape, const char* name,
const char* raw_device_name) {
AbstractOperationPtr op_ptr(ctx->CreateOperation());
TF_RETURN_IF_ERROR(op_ptr->Reset("AssignVariableOp", raw_device_name));
TF_RETURN_IF_ERROR(MaybeSetOpName(op_ptr.get(), name));
TF_RETURN_IF_ERROR(op_ptr->AddInput(resource));
TF_RETURN_IF_ERROR(op_ptr->AddInput(value));
TF_RETURN_IF_ERROR(op_ptr->SetAttrBool("validate_shape", validate_shape));
int num_retvals = 0;
std::vector<AbstractTensorHandle*> dummy_outputs;
return op_ptr->Execute(absl::MakeSpan(dummy_outputs), &num_retvals);
}
// Op: DestroyResourceOp()
// Summary: Deletes the resource specified by the handle.
//
// Description:
// All subsequent operations using the resource will result in a NotFound
// error status.
absl::Status DestroyResourceOp(AbstractContext* ctx,
AbstractTensorHandle* const resource,
bool ignore_lookup_error, const char* name,
const char* raw_device_name) {
AbstractOperationPtr op_ptr(ctx->CreateOperation());
TF_RETURN_IF_ERROR(op_ptr->Reset("DestroyResourceOp", raw_device_name));
TF_RETURN_IF_ERROR(MaybeSetOpName(op_ptr.get(), name));
TF_RETURN_IF_ERROR(op_ptr->AddInput(resource));
TF_RETURN_IF_ERROR(
op_ptr->SetAttrBool("ignore_lookup_error", ignore_lookup_error));
int num_retvals = 0;
std::vector<AbstractTensorHandle*> dummy_outputs;
return op_ptr->Execute(absl::MakeSpan(dummy_outputs), &num_retvals);
}
} // namespace ops
} // namespace tensorflow
@@ -0,0 +1,69 @@
/* Copyright 2021 The TensorFlow Authors. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/
// This file is MACHINE GENERATED! Do not edit.
#ifndef TENSORFLOW_C_EXPERIMENTAL_OPS_RESOURCE_VARIABLE_OPS_H_
#define TENSORFLOW_C_EXPERIMENTAL_OPS_RESOURCE_VARIABLE_OPS_H_
#include <string>
#include "absl/status/status.h"
#include "absl/types/span.h"
#include "tensorflow/c/eager/abstract_context.h"
#include "tensorflow/c/eager/abstract_tensor_handle.h"
#include "tensorflow/core/framework/tensor_shape.h"
#include "tensorflow/core/framework/types.h" // NOLINT
#include "tensorflow/core/framework/types.pb.h"
namespace tensorflow {
namespace ops {
// Creates a handle to a Variable resource.
absl::Status VarHandleOp(AbstractContext* ctx, AbstractTensorHandle** resource,
DataType dtype, const PartialTensorShape shape,
const char* container = "",
const char* shared_name = "",
const char* debug_name = "",
absl::Span<std::string const> allowed_devices = {},
const char* name = nullptr,
const char* raw_device_name = nullptr);
// Reads the value of a variable.
absl::Status ReadVariableOp(AbstractContext* ctx,
AbstractTensorHandle* const resource,
AbstractTensorHandle** value, DataType dtype,
const char* name = nullptr,
const char* raw_device_name = nullptr);
// Assigns a new value to a variable.
absl::Status AssignVariableOp(AbstractContext* ctx,
AbstractTensorHandle* const resource,
AbstractTensorHandle* const value,
bool validate_shape = false,
const char* name = nullptr,
const char* raw_device_name = nullptr);
// Deletes the resource specified by the handle.
absl::Status DestroyResourceOp(AbstractContext* ctx,
AbstractTensorHandle* const resource,
bool ignore_lookup_error = true,
const char* name = nullptr,
const char* raw_device_name = nullptr);
} // namespace ops
} // namespace tensorflow
#endif // TENSORFLOW_C_EXPERIMENTAL_OPS_RESOURCE_VARIABLE_OPS_H_
+75
View File
@@ -0,0 +1,75 @@
#!/bin/bash
# Copyright 2021 The TensorFlow Authors. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# ==============================================================================
# Script to manually generate the C++ ops.
set -e
current_file="$(readlink -f "$0")"
current_dir="$(dirname "$current_file")"
api_dir="${current_dir}/../../../core/api_def/base_api"
generate="bazel run \
--test_output=all \
//tensorflow/c/experimental/ops/gen:generate_cpp -- \
--output_dir="${current_dir}" \
--api_dirs="${api_dir}" \
--source_dir=third_party/tensorflow"
${generate} \
--category=array \
Identity \
IdentityN \
ZerosLike \
Shape \
ExpandDims \
OnesLike
${generate} \
--category=math \
Mul \
Conj \
AddV2 \
MatMul \
Neg \
Sum \
Sub \
Div \
DivNoNan \
Exp \
Sqrt \
SqrtGrad \
Log1p
${generate} \
--category=nn \
SparseSoftmaxCrossEntropyWithLogits \
ReluGrad \
Relu \
BiasAdd \
BiasAddGrad
${generate} \
--category=resource_variable \
VarHandleOp \
ReadVariableOp \
AssignVariableOp \
DestroyResourceOp
${generate} \
--category=io \
RestoreV2 \
SaveV2