chore: import upstream snapshot with attribution

This commit is contained in:
wehub-resource-sync
2026-07-13 12:40:42 +08:00
commit e25996e7db
15472 changed files with 3536181 additions and 0 deletions
@@ -0,0 +1,20 @@
// Copyright (c) 2025 PaddlePaddle 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.
#pragma once
#include <c10/util/Optional.h>
#include <torch/cuda.h>
#include <torch/sparse.h>
#include <torch/types.h>
@@ -0,0 +1,60 @@
// Copyright (c) 2025 PaddlePaddle 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 <c10/cuda/CUDAFunctions.h>
#if defined(PADDLE_WITH_CUDA) || defined(PADDLE_WITH_HIP)
#include <c10/cuda/CUDAGuard.h>
#endif
#include <c10/util/Exception.h>
#include <torch/cuda.h>
#include "paddle/phi/backends/gpu/gpu_info.h"
#include "paddle/phi/core/platform/device/gpu/gpu_info.h"
#include "paddle/phi/core/platform/device_event_base.h"
namespace torch::cuda {
c10::DeviceIndex device_count() {
#if defined(PADDLE_WITH_CUDA) || defined(PADDLE_WITH_HIP)
return phi::backends::gpu::GetGPUDeviceCount();
#else
// Match PyTorch c10::cuda::device_count(): return 0 in CPU-only builds so
// that is_available() and the pre-checks of synchronize() degrade gracefully
// through a single, consistent "No CUDA GPUs are available" error path.
return 0;
#endif
}
bool is_available() { return cuda::device_count() > 0; }
void synchronize(int64_t device_index) {
TORCH_CHECK(is_available(), "No CUDA GPUs are available");
auto num_gpus = cuda::device_count();
TORCH_CHECK(
device_index == -1 || (device_index >= 0 && device_index < num_gpus),
"Device index out of range: ",
device_index);
#if defined(PADDLE_WITH_CUDA) || defined(PADDLE_WITH_HIP)
// Match PyTorch semantics:
// 1. `device_index == -1` means "current CUDA device".
// 2. Explicit device synchronization must not leak a changed current device
// to the caller after returning.
const c10::cuda::CUDAGuard device_guard(c10::Device(
c10::DeviceType::CUDA, static_cast<c10::DeviceIndex>(device_index)));
c10::cuda::device_synchronize();
#endif
// CPU-only builds are already rejected above by the is_available() check.
}
} // namespace torch::cuda
@@ -0,0 +1,32 @@
// Copyright (c) 2025 PaddlePaddle 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.
#pragma once
#include <c10/core/Device.h>
#include <cstdint>
#include "paddle/common/macros.h"
namespace torch::cuda {
PADDLE_API c10::DeviceIndex device_count();
PADDLE_API bool is_available();
PADDLE_API void synchronize(int64_t device_index = -1);
} // namespace torch::cuda
namespace at::cuda {
using torch::cuda::synchronize;
} // namespace at::cuda
@@ -0,0 +1,19 @@
// Copyright (c) 2025 PaddlePaddle 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.
// The file has been adapted from pytorch project
// Licensed under BSD-style license -
// https://github.com/pytorch/pytorch/blob/main/LICENSE
#pragma once
@@ -0,0 +1,50 @@
// Copyright (c) 2025 PaddlePaddle 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.
// The file has been adapted from pytorch project
// Licensed under BSD-style license -
// https://github.com/pytorch/pytorch/blob/main/LICENSE
#pragma once
#include <ATen/Device.h>
#include <ATen/ops/arange.h>
#include <ATen/ops/empty_strided.h>
#include <c10/util/Exception.h>
#include <torch/types.h>
#include <utils/scalar_type_conversion.h>
#if !defined(PADDLE_ON_INFERENCE) && !defined(PADDLE_NO_PYTHON)
// Python bindings for the C++ frontend (includes Python.h)
#include "paddle/utils/pybind.h"
#endif
namespace torch::python {
namespace detail {
inline Dtype py_object_to_dtype(py::object object) {
PyObject* obj = object.ptr();
return *reinterpret_cast<Dtype*>(obj);
}
inline PyObject* getTHPDtype(c10::ScalarType dtype) {
return paddle::pybind::ToPyObject(
compat::_PD_AtenScalarTypeToPhiDataType(dtype));
}
} // namespace detail
} // namespace torch::python
namespace torch {
using torch::python::detail::getTHPDtype;
} // namespace torch
@@ -0,0 +1,17 @@
// Copyright (c) 2025 PaddlePaddle 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.
#pragma once
#include <ATen/ATen.h>
@@ -0,0 +1,22 @@
// Copyright (c) 2026 PaddlePaddle 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.
// The file has been adapted from pytorch project
// Licensed under BSD-style license -
// https://github.com/pytorch/pytorch/blob/main/LICENSE
#pragma once
#include <torch/all.h>
#include <torch/extension.h>
@@ -0,0 +1,60 @@
// Copyright (c) 2025 PaddlePaddle 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.
// The file has been adapted from pytorch project
// Licensed under BSD-style license -
// https://github.com/pytorch/pytorch/blob/main/LICENSE
#pragma once
#include <ATen/ATen.h>
#include <ATen/Functions.h>
#include <ATen/core/TensorBody.h>
#include <c10/core/ScalarType.h>
#include <c10/util/OptionalArrayRef.h>
namespace torch {
using namespace at; // NOLINT
using std::nullopt; // NOLINT
using std::optional; // NOLINT
using Dtype = at::ScalarType;
constexpr auto kUInt8 = at::kByte;
constexpr auto kInt8 = at::kChar;
constexpr auto kInt16 = at::kShort;
constexpr auto kInt32 = at::kInt;
constexpr auto kInt64 = at::kLong;
constexpr auto kUInt16 = at::kUInt16;
constexpr auto kUInt32 = at::kUInt32;
constexpr auto kFloat16 = at::kHalf;
constexpr auto kFloat32 = at::kFloat;
constexpr auto kFloat64 = at::kDouble;
constexpr auto kBFloat16 = at::kBFloat16;
constexpr auto kU8 = kUInt8;
constexpr auto kU16 = kUInt16;
constexpr auto kU32 = kUInt32;
constexpr auto kI8 = kInt8;
constexpr auto kI16 = kInt16;
constexpr auto kI32 = kInt32;
constexpr auto kI64 = kInt64;
constexpr auto kF16 = kFloat16;
constexpr auto kF32 = kFloat32;
constexpr auto kF64 = kFloat64;
} // namespace torch
@@ -0,0 +1,39 @@
// Copyright (c) 2026 PaddlePaddle 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.
#pragma once
/// Indicates the major version of LibTorch.
#define TORCH_VERSION_MAJOR 2
/// Indicates the minor version of LibTorch.
#define TORCH_VERSION_MINOR 10
/// Indicates the patch version of LibTorch.
#define TORCH_VERSION_PATCH 0
/// Indicates the ABI version tag of LibTorch.
#define TORCH_VERSION_ABI_TAG 0
/// Indicates the version of LibTorch as a string literal.
#define TORCH_VERSION "2.10.0"
/// Indicates the ABI version of LibTorch as a single uint64.
/// [ byte ][ byte ][ byte ][ byte ][ byte ][ byte ][ byte ][ byte ]
/// [ MAJ ][ MIN ][ PATCH][ ABI TAG ]
#define TORCH_ABI_VERSION \
(((0ULL + TORCH_VERSION_MAJOR) << 56) | \
((0ULL + TORCH_VERSION_MINOR) << 48) | /* NOLINT(whitespace/indent) */ \
((0ULL + TORCH_VERSION_PATCH) << 40) | /* NOLINT(whitespace/indent) */ \
((0ULL + TORCH_VERSION_ABI_TAG) << 0)) /* NOLINT(whitespace/indent) */
@@ -0,0 +1,583 @@
// Copyright (c) 2026 PaddlePaddle 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.
// The file has been adapted from pytorch project
// Licensed under BSD-style license -
// https://github.com/pytorch/pytorch/blob/main/LICENSE
#include "torch/csrc/jit/function_schema_parser.h"
#include "glog/logging.h"
#include "torch/csrc/jit/schema_parser_defs.h"
#include "torch/csrc/jit/schema_type_parser.h"
namespace torch::jit {
namespace {
std::string parsedDeclarationToDebugString(
const std::variant<std::string, c10::FunctionSchema>& parsed) {
// Used only in parser debug logs so we can see whether we parsed
// an operator name or a full function schema.
std::ostringstream os;
if (std::holds_alternative<std::string>(parsed)) {
os << "name(" << std::get<std::string>(parsed) << ")";
} else {
os << "schema" << std::get<c10::FunctionSchema>(parsed);
}
return os.str();
}
std::string schemaTypeRuntimeClassName(const c10::Type& type) {
if (dynamic_cast<const c10::detail::SchemaAtomicType*>(&type)) {
return "c10::detail::SchemaAtomicType";
}
if (dynamic_cast<const c10::detail::SchemaOptionalType*>(&type)) {
return "c10::detail::SchemaOptionalType";
}
if (dynamic_cast<const c10::detail::SchemaTupleType*>(&type)) {
return "c10::detail::SchemaTupleType";
}
return typeid(type).name();
}
const char* schemaTypeKindName(c10::TypeKind kind) {
switch (kind) {
#define TORCH_SCHEMA_KIND_CASE(T) \
case c10::TypeKind::T: \
return #T;
C10_FORALL_TYPES(TORCH_SCHEMA_KIND_CASE)
#undef TORCH_SCHEMA_KIND_CASE
default:
return "UnknownTypeKind";
}
}
void appendTypeTree(std::ostringstream& os,
const c10::TypePtr& type,
int depth) {
// Recursively dump the parsed type tree (e.g. Optional[Tuple[...]])
// for verbose parser tracing.
const std::string indent(static_cast<size_t>(depth) * 2, ' ');
if (!type) {
os << "\n" << indent << "- <null type>";
return;
}
os << "\n"
<< indent << "- str=`" << type->str()
<< "`, kind=" << schemaTypeKindName(type->kind())
<< ", class=" << schemaTypeRuntimeClassName(*type);
const auto children = type->containedTypes();
for (const auto& child : children) {
appendTypeTree(os, child, depth + 1);
}
}
std::string buildFunctionSchemaTypeTreeDebugString(
const c10::FunctionSchema& schema) {
std::ostringstream os;
os << "schema_type_tree";
for (size_t i = 0; i < schema.arguments().size(); ++i) {
const auto& arg = schema.arguments()[i];
os << "\narg[" << i << "] `" << arg.name() << "`";
appendTypeTree(os, arg.type(), 1);
}
for (size_t i = 0; i < schema.returns().size(); ++i) {
const auto& ret = schema.returns()[i];
os << "\nret[" << i << "] `" << ret.name() << "`";
appendTypeTree(os, ret.type(), 1);
}
return os.str();
}
class SchemaParser final {
public:
explicit SchemaParser(const std::string& schema) : schema_(schema) {}
std::variant<std::string, c10::FunctionSchema> parseExactlyOneDeclaration() {
// Parse exactly one declaration and reject trailing characters so callers
// can treat a successful parse as fully validated schema text.
skipWhitespace();
if (atEnd()) {
return std::string();
}
auto result = parseDeclaration();
skipWhitespace();
TORCH_CHECK(atEnd(), "Unexpected trailing content", posInfo());
return result;
}
private:
std::variant<std::string, c10::FunctionSchema> parseDeclaration() {
// Declarations are either:
// 1) operator name only
// 2) full schema: name(args) -> returns
const std::string name = parseOperatorName();
skipWhitespace();
if (atEnd() || peek() != TORCH_SCHEMA_CH_LPAREN) {
return name;
}
std::vector<c10::Argument> arguments;
std::vector<c10::Argument> returns;
bool kwarg_only = false;
bool is_vararg = false;
bool is_varret = false;
size_t idx = 0;
parseDelimitedList(TORCH_SCHEMA_CH_LPAREN, TORCH_SCHEMA_CH_RPAREN, [&] {
skipWhitespace();
if (consumeLiteral(TORCH_SCHEMA_LIT_VARARG)) {
TORCH_CHECK(
!is_vararg, "Duplicate vararg (...) declaration", posInfo());
is_vararg = true;
return;
}
if (consumeChar(TORCH_SCHEMA_CH_STAR)) {
kwarg_only = true;
return;
}
TORCH_CHECK(!is_vararg,
"... must be the last element of the argument list",
posInfo());
arguments.push_back(
parseArgument(idx++, /*is_return=*/false, /*kwarg_only=*/kwarg_only));
});
if (is_vararg) {
for (const auto& arg : arguments) {
TORCH_CHECK(!arg.default_value().has_value(),
"Schemas with vararg (...) cannot have default arguments");
}
}
skipWhitespace();
expectLiteral(TORCH_SCHEMA_LIT_ARROW);
skipWhitespace();
// In FunctionSchema, `-> (T1, T2)` means two return slots. It is not a
// single Tuple type return unless the schema explicitly encodes that type.
if (consumeLiteral(TORCH_SCHEMA_LIT_VARARG)) {
is_varret = true;
} else if (consumeChar(TORCH_SCHEMA_CH_LPAREN)) {
skipWhitespace();
if (!consumeChar(TORCH_SCHEMA_CH_RPAREN)) {
size_t return_idx = 0;
while (true) {
skipWhitespace();
if (consumeLiteral(TORCH_SCHEMA_LIT_VARARG)) {
TORCH_CHECK(
!is_varret, "Duplicate varret (...) declaration", posInfo());
is_varret = true;
skipWhitespace();
TORCH_CHECK(peek() == TORCH_SCHEMA_CH_RPAREN,
"... must be the last element of the return list",
posInfo());
} else {
TORCH_CHECK(!is_varret,
"... must be the last element of the return list",
posInfo());
returns.push_back(parseArgument(
return_idx++, /*is_return=*/true, /*kwarg_only=*/false));
}
skipWhitespace();
if (consumeChar(TORCH_SCHEMA_CH_COMMA)) {
continue;
}
expectChar(TORCH_SCHEMA_CH_RPAREN);
break;
}
}
} else {
returns.push_back(
parseArgument(0, /*is_return=*/true, /*kwarg_only=*/false));
}
return c10::FunctionSchema(
std::move(arguments), std::move(returns), is_vararg, is_varret);
}
c10::Argument parseArgument(size_t /*idx*/, bool is_return, bool kwarg_only) {
// Type and alias syntax is parsed by SchemaTypeParser. This method handles
// argument-level decorations such as fixed-size list suffixes, names and
// defaults.
SchemaTypeParser type_parser(schema_, &pos_, &next_fresh_alias_id_);
ParsedType parsed = type_parser.parseType();
std::optional<int32_t> N;
std::optional<torch::IValue> default_value;
std::string name;
skipWhitespace();
if (!is_return && consumeChar(TORCH_SCHEMA_CH_LBRACKET)) {
skipWhitespace();
const std::string n_str = parseUnsignedNumber();
int64_t n64 = 0;
try {
n64 = std::stoll(n_str);
} catch (const std::exception&) {
TORCH_CHECK(false, "Invalid fixed-size list length", posInfo());
}
TORCH_CHECK(n64 >= 0 && n64 <= std::numeric_limits<int32_t>::max(),
"Fixed-size list length out of range",
posInfo());
N = static_cast<int32_t>(n64);
skipWhitespace();
expectChar(TORCH_SCHEMA_CH_RBRACKET);
skipWhitespace();
if (consumeChar(TORCH_SCHEMA_CH_QMARK)) {
parsed.type = c10::makeSchemaOptionalType(parsed.type);
}
// Container alias annotation belongs to the outer list-like container.
// Element alias information is kept as contained type alias metadata.
auto container_alias = type_parser.parseAliasAnnotation();
if (container_alias.has_value() && parsed.alias_info.has_value()) {
container_alias->addContainedType(std::move(*parsed.alias_info));
}
if (container_alias.has_value()) {
parsed.alias_info = std::move(container_alias);
}
}
if (is_return) {
skipWhitespace();
if (!atEnd() && isIdentifierStart(peek())) {
name = parseIdentifier("return field name");
} else {
name = "";
}
} else {
name = parseIdentifier("argument name");
skipWhitespace();
if (consumeChar(TORCH_SCHEMA_CH_EQUAL)) {
default_value = parseDefaultValue(*parsed.type);
}
}
return c10::Argument(std::move(name),
parsed.type,
parsed.type,
N,
std::move(default_value),
!is_return && kwarg_only,
std::move(parsed.alias_info));
}
torch::IValue parseDefaultValue(const c10::Type& arg_type) {
skipWhitespace();
TORCH_CHECK(!atEnd(), "Missing default value", posInfo());
if (consumeKeyword(TORCH_SCHEMA_KW_NONE)) {
return torch::IValue();
}
if (consumeKeyword(TORCH_SCHEMA_KW_TRUE)) {
return torch::IValue(true);
}
if (consumeKeyword(TORCH_SCHEMA_KW_FALSE)) {
return torch::IValue(false);
}
if (peek() == TORCH_SCHEMA_CH_DQUOTE || peek() == TORCH_SCHEMA_CH_SQUOTE) {
return torch::IValue(parseStringLiteral());
}
if (peek() == TORCH_SCHEMA_CH_PLUS || peek() == TORCH_SCHEMA_CH_MINUS ||
std::isdigit(peekAsUnsigned())) {
return parseNumericLiteral();
}
if (isIdentifierStart(peek())) {
const std::string ident = parseIdentifier("default value");
TORCH_CHECK(arg_type.kind() == c10::TypeKind::StringType,
"Unsupported identifier default value `",
ident,
"`",
posInfo());
return torch::IValue(ident);
}
TORCH_CHECK(false, "Unsupported default value", posInfo());
}
torch::IValue parseNumericLiteral() {
skipWhitespace();
const size_t start = pos_;
bool seen_digit = false;
bool is_float = false;
if (peek() == TORCH_SCHEMA_CH_PLUS || peek() == TORCH_SCHEMA_CH_MINUS) {
++pos_;
}
while (!atEnd() && std::isdigit(peekAsUnsigned())) {
++pos_;
seen_digit = true;
}
if (!atEnd() && peek() == TORCH_SCHEMA_CH_DOT) {
is_float = true;
++pos_;
while (!atEnd() && std::isdigit(peekAsUnsigned())) {
++pos_;
seen_digit = true;
}
}
if (!atEnd() && (peek() == TORCH_SCHEMA_CH_EXP_LOWER ||
peek() == TORCH_SCHEMA_CH_EXP_UPPER)) {
is_float = true;
++pos_;
if (!atEnd() &&
(peek() == TORCH_SCHEMA_CH_PLUS || peek() == TORCH_SCHEMA_CH_MINUS)) {
++pos_;
}
bool has_exp_digit = false;
while (!atEnd() && std::isdigit(peekAsUnsigned())) {
++pos_;
has_exp_digit = true;
}
TORCH_CHECK(has_exp_digit, "Malformed numeric literal", posInfo());
}
TORCH_CHECK(seen_digit, "Malformed numeric literal", posInfo());
const std::string literal = schema_.substr(start, pos_ - start);
try {
if (is_float) {
return torch::IValue(std::stod(literal));
}
return torch::IValue(static_cast<int64_t>(std::stoll(literal)));
} catch (const std::exception&) {
TORCH_CHECK(
false, "Failed to parse numeric literal `", literal, "`", posInfo());
}
}
std::string parseStringLiteral() {
skipWhitespace();
TORCH_CHECK(!atEnd() && (peek() == TORCH_SCHEMA_CH_DQUOTE ||
peek() == TORCH_SCHEMA_CH_SQUOTE),
"Expected string literal",
posInfo());
const char quote = peek();
++pos_;
std::string out;
while (!atEnd()) {
char c = schema_[pos_++];
if (c == quote) {
return out;
}
if (c == TORCH_SCHEMA_CH_BACKSLASH) {
TORCH_CHECK(!atEnd(), "Unterminated escape sequence", posInfo());
const char escaped = schema_[pos_++];
switch (escaped) {
case TORCH_SCHEMA_CH_N:
out.push_back('\n');
break;
case TORCH_SCHEMA_CH_T:
out.push_back('\t');
break;
case TORCH_SCHEMA_CH_R:
out.push_back('\r');
break;
case TORCH_SCHEMA_CH_BACKSLASH:
out.push_back('\\');
break;
case TORCH_SCHEMA_CH_SQUOTE:
out.push_back('\'');
break;
case TORCH_SCHEMA_CH_DQUOTE:
out.push_back('"');
break;
default:
out.push_back(escaped);
break;
}
} else {
out.push_back(c);
}
}
TORCH_CHECK(false, "Unterminated string literal", posInfo());
}
template <typename Callback>
void parseDelimitedList(char begin, char end, Callback&& callback) {
// Shared list parser for "(...)" sections with comma-separated elements.
skipWhitespace();
expectChar(begin);
skipWhitespace();
if (consumeChar(end)) {
return;
}
while (true) {
callback();
skipWhitespace();
if (consumeChar(TORCH_SCHEMA_CH_COMMA)) {
continue;
}
expectChar(end);
return;
}
}
std::string parseOperatorName() {
skipWhitespace();
const size_t start = pos_;
while (!atEnd()) {
const char c = peek();
if (std::isspace(peekAsUnsigned()) || c == TORCH_SCHEMA_CH_LPAREN) {
break;
}
++pos_;
}
TORCH_CHECK(start != pos_, "Expected operator name", posInfo());
return schema_.substr(start, pos_ - start);
}
std::string parseIdentifier(const char* desc) {
skipWhitespace();
TORCH_CHECK(
!atEnd() && isIdentifierStart(peek()), "Expected ", desc, posInfo());
const size_t start = pos_++;
while (!atEnd() && isIdentifierChar(peek())) {
++pos_;
}
return schema_.substr(start, pos_ - start);
}
std::string parseUnsignedNumber() {
skipWhitespace();
TORCH_CHECK(!atEnd() && std::isdigit(peekAsUnsigned()),
"Expected an unsigned number",
posInfo());
const size_t start = pos_++;
while (!atEnd() && std::isdigit(peekAsUnsigned())) {
++pos_;
}
return schema_.substr(start, pos_ - start);
}
bool consumeKeyword(const char* kw) {
skipWhitespace();
const size_t len = std::char_traits<char>::length(kw);
if (schema_.compare(pos_, len, kw) != 0) {
return false;
}
const size_t next = pos_ + len;
if (next < schema_.size() && isIdentifierChar(schema_[next])) {
return false;
}
pos_ = next;
return true;
}
bool consumeLiteral(const char* literal) {
const size_t len = std::char_traits<char>::length(literal);
if (schema_.compare(pos_, len, literal) == 0) {
pos_ += len;
return true;
}
return false;
}
void expectLiteral(const char* literal) {
TORCH_CHECK(consumeLiteral(literal), "Expected `", literal, "`", posInfo());
}
bool consumeChar(char c) {
if (!atEnd() && schema_[pos_] == c) {
++pos_;
return true;
}
return false;
}
void expectChar(char c) {
TORCH_CHECK(
!atEnd() && schema_[pos_] == c, "Expected `", c, "`", posInfo());
++pos_;
}
char peek() const {
TORCH_INTERNAL_ASSERT(!atEnd());
return schema_[pos_];
}
unsigned char peekAsUnsigned() const {
return static_cast<unsigned char>(peek());
}
bool atEnd() const { return pos_ >= schema_.size(); }
void skipWhitespace() {
while (!atEnd() && std::isspace(peekAsUnsigned())) {
++pos_;
}
}
static bool isIdentifierStart(char c) {
const auto uc = static_cast<unsigned char>(c);
return std::isalpha(uc) || c == '_';
}
static bool isIdentifierChar(char c) {
const auto uc = static_cast<unsigned char>(c);
return std::isalnum(uc) || c == '_';
}
std::string posInfo() const {
std::ostringstream os;
os << " at position " << pos_ << " in schema `" << schema_ << "`";
return os.str();
}
const std::string& schema_;
size_t pos_{0};
size_t next_fresh_alias_id_{0};
};
} // namespace
std::variant<std::string, c10::FunctionSchema> parseSchemaOrName(
const std::string& schemaOrName) {
auto parsed = SchemaParser(schemaOrName).parseExactlyOneDeclaration();
VLOG(3) << "parseSchemaOrName input=`" << schemaOrName
<< "` parsed=" << parsedDeclarationToDebugString(parsed);
if (VLOG_IS_ON(4) && std::holds_alternative<c10::FunctionSchema>(parsed)) {
VLOG(4) << buildFunctionSchemaTypeTreeDebugString(
std::get<c10::FunctionSchema>(parsed));
}
return parsed;
}
c10::FunctionSchema parseSchema(const std::string& schema) {
auto parsed = parseSchemaOrName(schema);
TORCH_CHECK(
std::holds_alternative<c10::FunctionSchema>(parsed),
"Tried to parse a function schema but only the operator name was given");
VLOG(3) << "parseSchema input=`" << schema
<< "` output=" << std::get<c10::FunctionSchema>(parsed);
return std::get<c10::FunctionSchema>(std::move(parsed));
}
std::string parseName(const std::string& name) {
auto parsed = parseSchemaOrName(name);
TORCH_CHECK(
std::holds_alternative<std::string>(parsed),
"Tried to parse an operator name but a function schema was given");
VLOG(3) << "parseName input=`" << name
<< "` output=" << std::get<std::string>(parsed);
return std::get<std::string>(std::move(parsed));
}
std::string schemaTypeTreeToDebugString(const c10::FunctionSchema& schema) {
return buildFunctionSchemaTypeTreeDebugString(schema);
}
} // namespace torch::jit
@@ -0,0 +1,39 @@
// Copyright (c) 2026 PaddlePaddle 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.
// The file has been adapted from pytorch project
// Licensed under BSD-style license -
// https://github.com/pytorch/pytorch/blob/main/LICENSE
#pragma once
#include <ATen/core/function_schema.h>
#include <c10/macros/Macros.h>
#include <string>
#include <variant>
namespace torch::jit {
// allow_typevars: If true, we assume that lowercase types that we don't
// understand are type variables. This is only needed for TorchScript (and not
// not needed for custom ops).
// If false, we disallow typevars, except in certain cases for BC reason (i.e.
// your op is in the aten or prim namespace).
PADDLE_API std::variant<std::string, c10::FunctionSchema> parseSchemaOrName(
const std::string& schemaOrName);
PADDLE_API c10::FunctionSchema parseSchema(const std::string& schema);
PADDLE_API std::string parseName(const std::string& name);
PADDLE_API std::string schemaTypeTreeToDebugString(
const c10::FunctionSchema& schema);
} // namespace torch::jit
@@ -0,0 +1,86 @@
// Copyright (c) 2026 PaddlePaddle 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.
#pragma once
// Common literals
#define TORCH_SCHEMA_LIT_VARARG "..."
#define TORCH_SCHEMA_LIT_ARROW "->"
// Common keywords
#define TORCH_SCHEMA_KW_NONE "None"
#define TORCH_SCHEMA_KW_TRUE "true"
#define TORCH_SCHEMA_KW_FALSE "false"
// Common characters
#define TORCH_SCHEMA_CH_LPAREN '('
#define TORCH_SCHEMA_CH_RPAREN ')'
#define TORCH_SCHEMA_CH_LBRACKET '['
#define TORCH_SCHEMA_CH_RBRACKET ']'
#define TORCH_SCHEMA_CH_COMMA ','
#define TORCH_SCHEMA_CH_STAR '*'
#define TORCH_SCHEMA_CH_BANG '!'
#define TORCH_SCHEMA_CH_PIPE '|'
#define TORCH_SCHEMA_CH_QMARK '?'
#define TORCH_SCHEMA_CH_EQUAL '='
#define TORCH_SCHEMA_CH_DOT '.'
#define TORCH_SCHEMA_CH_PLUS '+'
#define TORCH_SCHEMA_CH_MINUS '-'
#define TORCH_SCHEMA_CH_EXP_LOWER 'e'
#define TORCH_SCHEMA_CH_EXP_UPPER 'E'
#define TORCH_SCHEMA_CH_DQUOTE '"'
#define TORCH_SCHEMA_CH_SQUOTE '\''
#define TORCH_SCHEMA_CH_BACKSLASH '\\'
#define TORCH_SCHEMA_CH_N 'n'
#define TORCH_SCHEMA_CH_T 't'
#define TORCH_SCHEMA_CH_R 'r'
// Alias syntax literals
#define TORCH_SCHEMA_ALIAS_WILDCARD "*"
#define TORCH_SCHEMA_ALIAS_FRESH_PREFIX "$"
// Type spellings in schema text
#define TORCH_SCHEMA_TYPE_CPP_DOUBLE "double"
#define TORCH_SCHEMA_TYPE_CPP_INT64_T "int64_t"
#define TORCH_SCHEMA_TYPE_TENSOR "Tensor"
#define TORCH_SCHEMA_TYPE_STR "str"
#define TORCH_SCHEMA_TYPE_STRING "string"
#define TORCH_SCHEMA_TYPE_INT "int"
#define TORCH_SCHEMA_TYPE_FLOAT "float"
#define TORCH_SCHEMA_TYPE_BOOL "bool"
#define TORCH_SCHEMA_TYPE_NONE "None"
#define TORCH_SCHEMA_TYPE_NONE_TYPE "NoneType"
#define TORCH_SCHEMA_TYPE_DEVICE "Device"
#define TORCH_SCHEMA_TYPE_SCALAR "Scalar"
#define TORCH_SCHEMA_TYPE_NUMBER "number"
// Base type conversion table for schema text -> TypeKind + canonical repr.
// Entry shape:
// _(input_text_literal, type_kind_enum_member, canonical_repr_literal)
// Notes:
// - Some entries intentionally map aliases to the same canonical repr.
// - This table only covers atomic/base types; tuple/optional are parsed
// structurally in SchemaTypeParser::parseType().
#define TORCH_SCHEMA_BASE_TYPE_CONVERSION_TABLE(_) \
_(TORCH_SCHEMA_TYPE_TENSOR, TensorType, TORCH_SCHEMA_TYPE_TENSOR) \
_(TORCH_SCHEMA_TYPE_STR, StringType, TORCH_SCHEMA_TYPE_STR) \
_(TORCH_SCHEMA_TYPE_STRING, StringType, TORCH_SCHEMA_TYPE_STR) \
_(TORCH_SCHEMA_TYPE_INT, IntType, TORCH_SCHEMA_TYPE_INT) \
_(TORCH_SCHEMA_TYPE_FLOAT, FloatType, TORCH_SCHEMA_TYPE_FLOAT) \
_(TORCH_SCHEMA_TYPE_BOOL, BoolType, TORCH_SCHEMA_TYPE_BOOL) \
_(TORCH_SCHEMA_TYPE_NONE, NoneType, TORCH_SCHEMA_TYPE_NONE_TYPE) \
_(TORCH_SCHEMA_TYPE_NONE_TYPE, NoneType, TORCH_SCHEMA_TYPE_NONE_TYPE) \
_(TORCH_SCHEMA_TYPE_DEVICE, DeviceObjType, TORCH_SCHEMA_TYPE_DEVICE) \
_(TORCH_SCHEMA_TYPE_SCALAR, NumberType, TORCH_SCHEMA_TYPE_SCALAR) \
_(TORCH_SCHEMA_TYPE_NUMBER, NumberType, TORCH_SCHEMA_TYPE_SCALAR)
@@ -0,0 +1,240 @@
// Copyright (c) 2026 PaddlePaddle 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 "torch/csrc/jit/schema_type_parser.h"
#include "torch/csrc/jit/schema_parser_defs.h"
#include <cctype>
#include <set>
#include <sstream>
#include <string>
#include <utility>
#include <vector>
namespace torch::jit {
size_t& SchemaTypeParser::refFromPtr(size_t* ptr, const char* name) {
TORCH_CHECK(ptr != nullptr, name, " must not be null");
return *ptr;
}
c10::TypePtr SchemaTypeParser::parseBaseType() {
// Map textual schema type names to compat lightweight type objects.
std::string type_name = parseDottedIdentifier("type");
if (type_name == TORCH_SCHEMA_TYPE_CPP_DOUBLE) {
TORCH_CHECK(false,
"Use `float` instead of `double` in schema declarations",
posInfo());
}
if (type_name == TORCH_SCHEMA_TYPE_CPP_INT64_T) {
TORCH_CHECK(false,
"Use `int` instead of `int64_t` in schema declarations",
posInfo());
}
#define TORCH_SCHEMA_BASE_TYPE_CASE(TEXT, KIND, REPR) \
if (type_name == TEXT) { \
return c10::makeSchemaAtomicType(c10::TypeKind::KIND, (REPR)); \
}
TORCH_SCHEMA_BASE_TYPE_CONVERSION_TABLE(TORCH_SCHEMA_BASE_TYPE_CASE)
#undef TORCH_SCHEMA_BASE_TYPE_CASE
TORCH_CHECK(false, "Unsupported type specifier `", type_name, "`", posInfo());
}
std::optional<c10::AliasInfo> SchemaTypeParser::parseAliasAnnotation() {
// Supported alias forms:
// (a), (a!), (a! -> b|c), !
// where bare '!' creates a fresh write alias set.
skipWhitespace();
if (consumeChar(TORCH_SCHEMA_CH_LPAREN)) {
std::set<std::string> before_sets;
parseAliasSetList(&before_sets);
skipWhitespace();
const bool is_write = consumeChar(TORCH_SCHEMA_CH_BANG);
std::set<std::string> after_sets = before_sets;
skipWhitespace();
if (consumeLiteral(TORCH_SCHEMA_LIT_ARROW)) {
after_sets.clear();
parseAliasSetList(&after_sets);
}
skipWhitespace();
TORCH_CHECK(!atEnd() && peek() == TORCH_SCHEMA_CH_RPAREN,
"Expected `)`",
posInfo());
consumeChar(TORCH_SCHEMA_CH_RPAREN);
return c10::AliasInfo(is_write, before_sets, after_sets);
}
if (consumeChar(TORCH_SCHEMA_CH_BANG)) {
std::set<std::string> fresh_set{
std::string(TORCH_SCHEMA_ALIAS_FRESH_PREFIX) +
std::to_string(next_fresh_alias_id_++)};
return c10::AliasInfo(true, fresh_set, fresh_set);
}
return std::nullopt;
}
ParsedType SchemaTypeParser::parseType() {
// Parse a full type expression including:
// - tuple forms: (T1, T2, ...)
// - alias suffixes
// - optional suffix '?'
skipWhitespace();
ParsedType out;
if (consumeChar(TORCH_SCHEMA_CH_LPAREN)) {
std::vector<c10::TypePtr> elements;
std::vector<std::optional<c10::AliasInfo>> element_aliases;
skipWhitespace();
if (!consumeChar(TORCH_SCHEMA_CH_RPAREN)) {
while (true) {
ParsedType elem = parseType();
elements.push_back(elem.type);
element_aliases.push_back(std::move(elem.alias_info));
skipWhitespace();
if (consumeChar(TORCH_SCHEMA_CH_COMMA)) {
continue;
}
TORCH_CHECK(!atEnd() && peek() == TORCH_SCHEMA_CH_RPAREN,
"Expected `)`",
posInfo());
consumeChar(TORCH_SCHEMA_CH_RPAREN);
break;
}
}
out.type = c10::makeSchemaTupleType(std::move(elements));
out.alias_info = parseAliasAnnotation();
// If tuple elements carry alias info, attach them as contained aliases
// of the tuple-level alias metadata.
bool has_contained_alias = false;
for (const auto& alias : element_aliases) {
if (alias.has_value()) {
has_contained_alias = true;
break;
}
}
if (has_contained_alias) {
if (!out.alias_info.has_value()) {
out.alias_info.emplace();
}
for (auto& alias : element_aliases) {
if (alias.has_value()) {
out.alias_info->addContainedType(std::move(*alias));
}
}
}
} else {
out.type = parseBaseType();
out.alias_info = parseAliasAnnotation();
}
skipWhitespace();
if (consumeChar(TORCH_SCHEMA_CH_QMARK)) {
out.type = c10::makeSchemaOptionalType(out.type);
}
return out;
}
void SchemaTypeParser::parseAliasSetList(std::set<std::string>* sets) {
TORCH_CHECK(sets != nullptr, "Alias set output must not be null");
// Parse alias set unions: a|b|*.
skipWhitespace();
while (true) {
if (consumeChar(TORCH_SCHEMA_CH_STAR)) {
sets->insert(TORCH_SCHEMA_ALIAS_WILDCARD);
} else {
sets->insert(parseIdentifier("alias set"));
}
skipWhitespace();
if (!consumeChar(TORCH_SCHEMA_CH_PIPE)) {
break;
}
skipWhitespace();
}
TORCH_CHECK(!sets->empty(), "Empty alias set annotation", posInfo());
}
std::string SchemaTypeParser::parseIdentifier(const char* desc) {
skipWhitespace();
TORCH_CHECK(
!atEnd() && isIdentifierStart(peek()), "Expected ", desc, posInfo());
const size_t start = pos_++;
while (!atEnd() && isIdentifierChar(peek())) {
++pos_;
}
return schema_.substr(start, pos_ - start);
}
std::string SchemaTypeParser::parseDottedIdentifier(const char* desc) {
std::string ident = parseIdentifier(desc);
skipWhitespace();
while (consumeChar(TORCH_SCHEMA_CH_DOT)) {
ident.push_back(TORCH_SCHEMA_CH_DOT);
ident += parseIdentifier(desc);
skipWhitespace();
}
return ident;
}
void SchemaTypeParser::skipWhitespace() {
while (!atEnd() && std::isspace(peekAsUnsigned())) {
++pos_;
}
}
bool SchemaTypeParser::consumeLiteral(const char* literal) {
const size_t len = std::char_traits<char>::length(literal);
if (schema_.compare(pos_, len, literal) == 0) {
pos_ += len;
return true;
}
return false;
}
bool SchemaTypeParser::consumeChar(char c) {
if (!atEnd() && schema_[pos_] == c) {
++pos_;
return true;
}
return false;
}
char SchemaTypeParser::peek() const {
TORCH_INTERNAL_ASSERT(!atEnd());
return schema_[pos_];
}
unsigned char SchemaTypeParser::peekAsUnsigned() const {
return static_cast<unsigned char>(peek());
}
bool SchemaTypeParser::atEnd() const { return pos_ >= schema_.size(); }
std::string SchemaTypeParser::posInfo() const {
std::ostringstream os;
os << " at position " << pos_ << " in schema `" << schema_ << "`";
return os.str();
}
bool SchemaTypeParser::isIdentifierStart(char c) {
const auto uc = static_cast<unsigned char>(c);
return std::isalpha(uc) || c == '_';
}
bool SchemaTypeParser::isIdentifierChar(char c) {
const auto uc = static_cast<unsigned char>(c);
return std::isalnum(uc) || c == '_';
}
} // namespace torch::jit
@@ -0,0 +1,67 @@
// Copyright (c) 2026 PaddlePaddle 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.
#pragma once
#include <ATen/core/alias_info.h>
#include <ATen/core/jit_type.h>
#include <c10/macros/Macros.h>
#include <cstddef>
#include <optional>
#include <set>
#include <string>
namespace torch::jit {
struct ParsedType {
c10::TypePtr type;
std::optional<c10::AliasInfo> alias_info;
};
class PADDLE_API SchemaTypeParser {
public:
SchemaTypeParser(const std::string& schema,
size_t* pos,
size_t* next_fresh_alias_id)
: schema_(schema),
pos_(refFromPtr(pos, "pos")),
next_fresh_alias_id_(
refFromPtr(next_fresh_alias_id, "next_fresh_alias_id")) {}
c10::TypePtr parseBaseType();
std::optional<c10::AliasInfo> parseAliasAnnotation();
ParsedType parseType();
private:
void parseAliasSetList(std::set<std::string>* sets);
std::string parseIdentifier(const char* desc);
std::string parseDottedIdentifier(const char* desc);
void skipWhitespace();
bool consumeLiteral(const char* literal);
bool consumeChar(char c);
char peek() const;
unsigned char peekAsUnsigned() const;
bool atEnd() const;
std::string posInfo() const;
static bool isIdentifierStart(char c);
static bool isIdentifierChar(char c);
static size_t& refFromPtr(size_t* ptr, const char* name);
const std::string& schema_;
size_t& pos_;
size_t& next_fresh_alias_id_;
};
} // namespace torch::jit