chore: import upstream snapshot with attribution
This commit is contained in:
@@ -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
|
||||
Reference in New Issue
Block a user