Add files using upload-large-folder tool
Browse filesThis view is limited to 50 files because it contains too many changes.
See raw diff
- .gitattributes +7 -0
- phivenv/Lib/site-packages/torch/include/torch/csrc/profiler/unwind/communicate.h +73 -0
- phivenv/Lib/site-packages/torch/include/torch/csrc/profiler/unwind/debug_info.h +280 -0
- phivenv/Lib/site-packages/torch/include/torch/csrc/profiler/unwind/dwarf_enums.h +46 -0
- phivenv/Lib/site-packages/torch/include/torch/csrc/profiler/unwind/dwarf_symbolize_enums.h +179 -0
- phivenv/Lib/site-packages/torch/include/torch/csrc/profiler/unwind/eh_frame_hdr.h +100 -0
- phivenv/Lib/site-packages/torch/include/torch/csrc/profiler/unwind/fast_symbolizer.h +108 -0
- phivenv/Lib/site-packages/torch/include/torch/csrc/profiler/unwind/fde.h +411 -0
- phivenv/Lib/site-packages/torch/include/torch/csrc/profiler/unwind/lexer.h +159 -0
- phivenv/Lib/site-packages/torch/include/torch/csrc/profiler/unwind/line_number_program.h +328 -0
- phivenv/Lib/site-packages/torch/include/torch/csrc/profiler/unwind/mem_file.h +159 -0
- phivenv/Lib/site-packages/torch/include/torch/csrc/profiler/unwind/range_table.h +73 -0
- phivenv/Lib/site-packages/torch/include/torch/csrc/profiler/unwind/sections.h +120 -0
- phivenv/Lib/site-packages/torch/include/torch/csrc/profiler/unwind/unwind.h +43 -0
- phivenv/Lib/site-packages/torch/include/torch/csrc/profiler/unwind/unwind_error.h +29 -0
- phivenv/Lib/site-packages/torch/include/torch/csrc/profiler/unwind/unwinder.h +81 -0
- phivenv/Lib/site-packages/torch/include/torch/csrc/stable/library.h +356 -0
- phivenv/Lib/site-packages/torch/include/torch/csrc/stable/tensor.h +126 -0
- phivenv/Lib/site-packages/torch/include/torch/csrc/tensor/python_tensor.h +35 -0
- phivenv/Lib/site-packages/torch/include/torch/csrc/utils/byte_order.h +81 -0
- phivenv/Lib/site-packages/torch/include/torch/csrc/utils/cpp_stacktraces.h +9 -0
- phivenv/Lib/site-packages/torch/include/torch/csrc/utils/cuda_enabled.h +13 -0
- phivenv/Lib/site-packages/torch/include/torch/csrc/utils/device_lazy_init.h +87 -0
- phivenv/Lib/site-packages/torch/include/torch/csrc/utils/disable_torch_function.h +45 -0
- phivenv/Lib/site-packages/torch/include/torch/csrc/utils/generated_serialization_types.h +0 -0
- phivenv/Lib/site-packages/torch/include/torch/csrc/utils/init.h +9 -0
- phivenv/Lib/site-packages/torch/include/torch/csrc/utils/invalid_arguments.h +15 -0
- phivenv/Lib/site-packages/torch/include/torch/csrc/utils/nested.h +15 -0
- phivenv/Lib/site-packages/torch/include/torch/csrc/utils/numpy_stub.h +21 -0
- phivenv/Lib/site-packages/torch/include/torch/csrc/utils/object_ptr.h +81 -0
- phivenv/Lib/site-packages/torch/include/torch/csrc/utils/out_types.h +15 -0
- phivenv/Lib/site-packages/torch/include/torch/csrc/utils/pybind.h +420 -0
- phivenv/Lib/site-packages/torch/include/torch/csrc/utils/pycfunction_helpers.h +13 -0
- phivenv/Lib/site-packages/torch/include/torch/csrc/utils/pyobject_preservation.h +7 -0
- phivenv/Lib/site-packages/torch/include/torch/csrc/utils/python_arg_parser.h +1303 -0
- phivenv/Lib/site-packages/torch/include/torch/csrc/utils/python_compat.h +46 -0
- phivenv/Lib/site-packages/torch/include/torch/csrc/utils/python_dispatch.h +16 -0
- phivenv/Lib/site-packages/torch/include/torch/csrc/utils/python_numbers.h +204 -0
- phivenv/Lib/site-packages/torch/include/torch/csrc/utils/python_raii.h +84 -0
- phivenv/Lib/site-packages/torch/include/torch/csrc/utils/python_scalars.h +172 -0
- phivenv/Lib/site-packages/torch/include/torch/csrc/utils/python_strings.h +129 -0
- phivenv/Lib/site-packages/torch/include/torch/csrc/utils/python_stub.h +4 -0
- phivenv/Lib/site-packages/torch/include/torch/csrc/utils/python_symnode.h +328 -0
- phivenv/Lib/site-packages/torch/include/torch/csrc/utils/python_torch_function_mode.h +29 -0
- phivenv/Lib/site-packages/torch/include/torch/csrc/utils/python_tuples.h +27 -0
- phivenv/Lib/site-packages/torch/include/torch/csrc/utils/pythoncapi_compat.h +1520 -0
- phivenv/Lib/site-packages/torch/include/torch/csrc/utils/schema_info.h +116 -0
- phivenv/Lib/site-packages/torch/include/torch/csrc/utils/six.h +52 -0
- phivenv/Lib/site-packages/torch/include/torch/csrc/utils/structseq.h +9 -0
- phivenv/Lib/site-packages/torch/include/torch/csrc/utils/tensor_apply.h +19 -0
.gitattributes
CHANGED
|
@@ -105,3 +105,10 @@ phivenv/Lib/site-packages/torch/bin/fbgemm.dll filter=lfs diff=lfs merge=lfs -te
|
|
| 105 |
phivenv/Lib/site-packages/torch/bin/protoc.exe filter=lfs diff=lfs merge=lfs -text
|
| 106 |
phivenv/Lib/site-packages/torch/distributed/__pycache__/distributed_c10d.cpython-39.pyc filter=lfs diff=lfs merge=lfs -text
|
| 107 |
phivenv/Lib/site-packages/torch/fx/experimental/__pycache__/symbolic_shapes.cpython-39.pyc filter=lfs diff=lfs merge=lfs -text
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 105 |
phivenv/Lib/site-packages/torch/bin/protoc.exe filter=lfs diff=lfs merge=lfs -text
|
| 106 |
phivenv/Lib/site-packages/torch/distributed/__pycache__/distributed_c10d.cpython-39.pyc filter=lfs diff=lfs merge=lfs -text
|
| 107 |
phivenv/Lib/site-packages/torch/fx/experimental/__pycache__/symbolic_shapes.cpython-39.pyc filter=lfs diff=lfs merge=lfs -text
|
| 108 |
+
phivenv/Lib/site-packages/torch/lib/asmjit.lib filter=lfs diff=lfs merge=lfs -text
|
| 109 |
+
phivenv/Lib/site-packages/torch/lib/c10.lib filter=lfs diff=lfs merge=lfs -text
|
| 110 |
+
phivenv/Lib/site-packages/torch/lib/asmjit.dll filter=lfs diff=lfs merge=lfs -text
|
| 111 |
+
phivenv/Lib/site-packages/torch/lib/cpuinfo.lib filter=lfs diff=lfs merge=lfs -text
|
| 112 |
+
phivenv/Lib/site-packages/torch/lib/fbgemm.dll filter=lfs diff=lfs merge=lfs -text
|
| 113 |
+
phivenv/Lib/site-packages/torch/lib/c10.dll filter=lfs diff=lfs merge=lfs -text
|
| 114 |
+
phivenv/Lib/site-packages/torch/lib/fbgemm.lib filter=lfs diff=lfs merge=lfs -text
|
phivenv/Lib/site-packages/torch/include/torch/csrc/profiler/unwind/communicate.h
ADDED
|
@@ -0,0 +1,73 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#pragma once
|
| 2 |
+
#include <ext/stdio_filebuf.h>
|
| 3 |
+
#include <torch/csrc/profiler/unwind/unwind_error.h>
|
| 4 |
+
#include <unistd.h>
|
| 5 |
+
#include <array>
|
| 6 |
+
#include <memory>
|
| 7 |
+
|
| 8 |
+
namespace torch::unwind {
|
| 9 |
+
// helper to open a process with stdin/stdout/stderr streams.
|
| 10 |
+
struct Communicate {
|
| 11 |
+
Communicate(const char* command, const char** args) {
|
| 12 |
+
if (pipe(inpipe_.data()) < 0 || pipe(outpipe_.data()) < 0 ||
|
| 13 |
+
pipe(errpipe_.data()) < 0) {
|
| 14 |
+
throw UnwindError("pipe() failed");
|
| 15 |
+
}
|
| 16 |
+
pid_t pid = fork();
|
| 17 |
+
if (pid < 0) {
|
| 18 |
+
throw UnwindError("fork() failed");
|
| 19 |
+
} else if (pid == 0) { // child process
|
| 20 |
+
close(inpipe_[1]);
|
| 21 |
+
close(outpipe_[0]);
|
| 22 |
+
close(errpipe_[0]);
|
| 23 |
+
|
| 24 |
+
dup2(inpipe_[0], STDIN_FILENO);
|
| 25 |
+
dup2(outpipe_[1], STDOUT_FILENO);
|
| 26 |
+
dup2(errpipe_[1], STDERR_FILENO);
|
| 27 |
+
execvp(command, (char* const*)args);
|
| 28 |
+
throw UnwindError("failed execvp");
|
| 29 |
+
} else { // parent process
|
| 30 |
+
close(inpipe_[0]);
|
| 31 |
+
close(outpipe_[1]);
|
| 32 |
+
close(errpipe_[1]);
|
| 33 |
+
outbuf_ = std::make_unique<__gnu_cxx::stdio_filebuf<char>>(
|
| 34 |
+
inpipe_[1], std::ios::out);
|
| 35 |
+
inbuf_ = std::make_unique<__gnu_cxx::stdio_filebuf<char>>(
|
| 36 |
+
outpipe_[0], std::ios::in);
|
| 37 |
+
errbuf_ = std::make_unique<__gnu_cxx::stdio_filebuf<char>>(
|
| 38 |
+
errpipe_[0], std::ios::in);
|
| 39 |
+
in_ = std::make_unique<std::istream>(inbuf_.get());
|
| 40 |
+
out_ = std::make_unique<std::ostream>(outbuf_.get());
|
| 41 |
+
err_ = std::make_unique<std::ostream>(errbuf_.get());
|
| 42 |
+
}
|
| 43 |
+
}
|
| 44 |
+
Communicate(const Communicate&) = delete;
|
| 45 |
+
Communicate(Communicate&&) = delete;
|
| 46 |
+
Communicate& operator=(const Communicate&) = delete;
|
| 47 |
+
Communicate& operator=(Communicate&&) = delete;
|
| 48 |
+
~Communicate() {
|
| 49 |
+
close(inpipe_[1]);
|
| 50 |
+
close(outpipe_[0]);
|
| 51 |
+
close(errpipe_[0]);
|
| 52 |
+
}
|
| 53 |
+
std::ostream& out() {
|
| 54 |
+
return *out_;
|
| 55 |
+
}
|
| 56 |
+
std::ostream& err() {
|
| 57 |
+
return *err_;
|
| 58 |
+
}
|
| 59 |
+
std::istream& in() {
|
| 60 |
+
return *in_;
|
| 61 |
+
}
|
| 62 |
+
|
| 63 |
+
private:
|
| 64 |
+
std::array<int, 2> inpipe_{-1, -1};
|
| 65 |
+
std::array<int, 2> outpipe_{-1, -1};
|
| 66 |
+
std::array<int, 2> errpipe_{-1, -1};
|
| 67 |
+
std::unique_ptr<__gnu_cxx::stdio_filebuf<char>> outbuf_, inbuf_, errbuf_;
|
| 68 |
+
std::unique_ptr<std::istream> in_;
|
| 69 |
+
std::unique_ptr<std::ostream> out_;
|
| 70 |
+
std::unique_ptr<std::ostream> err_;
|
| 71 |
+
};
|
| 72 |
+
|
| 73 |
+
} // namespace torch::unwind
|
phivenv/Lib/site-packages/torch/include/torch/csrc/profiler/unwind/debug_info.h
ADDED
|
@@ -0,0 +1,280 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#pragma once
|
| 2 |
+
#include <torch/csrc/profiler/unwind/dwarf_enums.h>
|
| 3 |
+
#include <torch/csrc/profiler/unwind/dwarf_symbolize_enums.h>
|
| 4 |
+
#include <torch/csrc/profiler/unwind/lexer.h>
|
| 5 |
+
#include <torch/csrc/profiler/unwind/sections.h>
|
| 6 |
+
#include <torch/csrc/profiler/unwind/unwind_error.h>
|
| 7 |
+
#include <cstdint>
|
| 8 |
+
#include <optional>
|
| 9 |
+
|
| 10 |
+
namespace torch::unwind {
|
| 11 |
+
|
| 12 |
+
struct DebugInfo {
|
| 13 |
+
DebugInfo(Sections& s) : s_(s) {}
|
| 14 |
+
|
| 15 |
+
void parse(uint64_t offset) {
|
| 16 |
+
auto L = parseHeader(offset);
|
| 17 |
+
parseCompileUnit(L);
|
| 18 |
+
}
|
| 19 |
+
std::optional<uint64_t> lineNumberProgramOffset() {
|
| 20 |
+
return line_number_program_offset_;
|
| 21 |
+
}
|
| 22 |
+
uint64_t nextOffset() {
|
| 23 |
+
return end_ - s_.debug_info.data;
|
| 24 |
+
}
|
| 25 |
+
std::vector<std::pair<uint64_t, uint64_t>> ranges() {
|
| 26 |
+
if (range_ptr_) {
|
| 27 |
+
auto offset = range_ptr_->first;
|
| 28 |
+
if (range_ptr_->second == DW_FORM_rnglistx) {
|
| 29 |
+
UNWIND_CHECK(rnglists_base_, "rnglistx but not rnglists_base_ set");
|
| 30 |
+
LOG_INFO("index for rnglistx {:x} + {:x}\n", *rnglists_base_, offset);
|
| 31 |
+
CheckedLexer L = s_.debug_rnglists.lexer(
|
| 32 |
+
*rnglists_base_ + offset * sec_offset_size_);
|
| 33 |
+
auto read = readSegmentOffset(L);
|
| 34 |
+
offset = *rnglists_base_ + read;
|
| 35 |
+
}
|
| 36 |
+
return version_ == 4 ? readRanges4(offset) : readRanges5(offset);
|
| 37 |
+
}
|
| 38 |
+
if (!highpc_) {
|
| 39 |
+
return {};
|
| 40 |
+
}
|
| 41 |
+
return {{lowpc_, lowpc_ + *highpc_}};
|
| 42 |
+
}
|
| 43 |
+
|
| 44 |
+
bool is64bit() {
|
| 45 |
+
return is_64bit_;
|
| 46 |
+
}
|
| 47 |
+
|
| 48 |
+
private:
|
| 49 |
+
CheckedLexer parseHeader(uint64_t offset) {
|
| 50 |
+
offset_ = offset;
|
| 51 |
+
CheckedLexer L = s_.debug_info.lexer(offset_);
|
| 52 |
+
std::tie(length_, is_64bit_) = L.readSectionLength();
|
| 53 |
+
sec_offset_size_ = is_64bit_ ? 8 : 4;
|
| 54 |
+
end_ = (const char*)L.loc() + length_;
|
| 55 |
+
version_ = L.read<uint16_t>();
|
| 56 |
+
UNWIND_CHECK(
|
| 57 |
+
version_ == 5 || version_ == 4,
|
| 58 |
+
"unexpected dwarf version {}",
|
| 59 |
+
version_);
|
| 60 |
+
uint8_t address_size = 0;
|
| 61 |
+
if (version_ == 5) {
|
| 62 |
+
auto unit_type = L.read<uint8_t>();
|
| 63 |
+
UNWIND_CHECK(unit_type == 0x1, "unexpected unit type {}", unit_type);
|
| 64 |
+
address_size = L.read<uint8_t>();
|
| 65 |
+
debug_abbrev_offset_ =
|
| 66 |
+
is_64bit_ ? L.read<uint64_t>() : L.read<uint32_t>();
|
| 67 |
+
} else {
|
| 68 |
+
debug_abbrev_offset_ =
|
| 69 |
+
is_64bit_ ? L.read<uint64_t>() : L.read<uint32_t>();
|
| 70 |
+
address_size = L.read<uint8_t>();
|
| 71 |
+
}
|
| 72 |
+
LOG_INFO(
|
| 73 |
+
"compilation unit at offset {:x} with length {:x} and debug_abbrev_offset {:x}\n",
|
| 74 |
+
offset,
|
| 75 |
+
length_,
|
| 76 |
+
debug_abbrev_offset_);
|
| 77 |
+
UNWIND_CHECK(
|
| 78 |
+
address_size == 8,
|
| 79 |
+
"expected 64-bit dwarf but found address size {}",
|
| 80 |
+
address_size);
|
| 81 |
+
return L;
|
| 82 |
+
}
|
| 83 |
+
|
| 84 |
+
uint64_t readSegmentOffset(CheckedLexer& L) {
|
| 85 |
+
return s_.readSegmentOffset(L, is_64bit_);
|
| 86 |
+
}
|
| 87 |
+
|
| 88 |
+
uint64_t readEncoded(CheckedLexer& L, uint64_t encoding) {
|
| 89 |
+
switch (encoding) {
|
| 90 |
+
case DW_FORM_data8:
|
| 91 |
+
case DW_FORM_addr:
|
| 92 |
+
return L.read<uint64_t>();
|
| 93 |
+
case DW_FORM_data4:
|
| 94 |
+
return L.read<uint32_t>();
|
| 95 |
+
case DW_FORM_addrx: {
|
| 96 |
+
auto idx = L.readULEB128();
|
| 97 |
+
return s_.debug_addr.lexer(address_base_ + sizeof(uint64_t) * idx)
|
| 98 |
+
.read<uint64_t>();
|
| 99 |
+
}
|
| 100 |
+
case DW_FORM_sec_offset:
|
| 101 |
+
return readSegmentOffset(L);
|
| 102 |
+
case DW_FORM_rnglistx: {
|
| 103 |
+
return L.readULEB128();
|
| 104 |
+
}
|
| 105 |
+
default:
|
| 106 |
+
UNWIND_CHECK(false, "unexpected encoding");
|
| 107 |
+
}
|
| 108 |
+
}
|
| 109 |
+
|
| 110 |
+
void parseCompileUnit(CheckedLexer& L) {
|
| 111 |
+
auto entry = L.readULEB128();
|
| 112 |
+
auto A = findAbbrev(debug_abbrev_offset_, entry);
|
| 113 |
+
while (true) {
|
| 114 |
+
auto attr = A.readULEB128();
|
| 115 |
+
auto form = A.readULEB128();
|
| 116 |
+
if (attr == 0 && form == 0) {
|
| 117 |
+
break;
|
| 118 |
+
}
|
| 119 |
+
if (form == DW_FORM_implicit_const) {
|
| 120 |
+
A.readSLEB128();
|
| 121 |
+
}
|
| 122 |
+
if (attr == DW_AT_low_pc) {
|
| 123 |
+
lowpc_ = readEncoded(L, form);
|
| 124 |
+
LOG_INFO(" lowpc {:x}\n", lowpc_);
|
| 125 |
+
} else if (attr == DW_AT_high_pc) {
|
| 126 |
+
highpc_ = readEncoded(L, form);
|
| 127 |
+
range_ptr_ = std::nullopt;
|
| 128 |
+
LOG_INFO(" highpc {:x}\n", *highpc_);
|
| 129 |
+
} else if (attr == DW_AT_addr_base) {
|
| 130 |
+
UNWIND_CHECK(form == DW_FORM_sec_offset, "unexpected addr_base form");
|
| 131 |
+
address_base_ = readSegmentOffset(L);
|
| 132 |
+
LOG_INFO(" address base {:x}\n", address_base_);
|
| 133 |
+
} else if (attr == DW_AT_rnglists_base) {
|
| 134 |
+
UNWIND_CHECK(
|
| 135 |
+
form == DW_FORM_sec_offset, "unexpected rnglists_base form");
|
| 136 |
+
rnglists_base_ = readSegmentOffset(L);
|
| 137 |
+
LOG_INFO(" range base {:x}\n", *rnglists_base_);
|
| 138 |
+
} else if (form == DW_FORM_string) {
|
| 139 |
+
L.readCString();
|
| 140 |
+
} else if (attr == DW_AT_stmt_list) {
|
| 141 |
+
UNWIND_CHECK(form == DW_FORM_sec_offset, "unexpected stmt_list form");
|
| 142 |
+
LOG_INFO(" program table offset {:x}\n", *line_number_program_offset_);
|
| 143 |
+
line_number_program_offset_ = readSegmentOffset(L);
|
| 144 |
+
} else if (form == DW_FORM_exprloc) {
|
| 145 |
+
auto sz = L.readULEB128();
|
| 146 |
+
L.skip(int64_t(sz));
|
| 147 |
+
} else if (form == DW_FORM_block1) {
|
| 148 |
+
auto sz = L.read<uint8_t>();
|
| 149 |
+
L.skip(int64_t(sz));
|
| 150 |
+
} else if (attr == DW_AT_ranges) {
|
| 151 |
+
auto range_offset = readEncoded(L, form);
|
| 152 |
+
LOG_INFO("setting range_ptr to {:x} {:x}\n", range_offset, form);
|
| 153 |
+
range_ptr_.emplace(range_offset, form);
|
| 154 |
+
} else if (
|
| 155 |
+
form == DW_FORM_udata || form == DW_FORM_rnglistx ||
|
| 156 |
+
form == DW_FORM_strx || form == DW_FORM_loclistx ||
|
| 157 |
+
form == DW_FORM_addrx) {
|
| 158 |
+
L.readULEB128();
|
| 159 |
+
} else if (form == DW_FORM_sdata) {
|
| 160 |
+
L.readSLEB128();
|
| 161 |
+
} else {
|
| 162 |
+
auto sz = formSize(form, sec_offset_size_);
|
| 163 |
+
UNWIND_CHECK(sz, "unsupported form in compilation unit {:x}", form);
|
| 164 |
+
L.skip(int64_t(*sz));
|
| 165 |
+
}
|
| 166 |
+
}
|
| 167 |
+
}
|
| 168 |
+
|
| 169 |
+
std::vector<std::pair<uint64_t, uint64_t>> readRanges4(uint64_t offset) {
|
| 170 |
+
CheckedLexer L = s_.debug_ranges.lexer(offset);
|
| 171 |
+
std::vector<std::pair<uint64_t, uint64_t>> ranges;
|
| 172 |
+
uint64_t base = lowpc_;
|
| 173 |
+
while (true) {
|
| 174 |
+
auto start = L.read<uint64_t>();
|
| 175 |
+
auto end = L.read<uint64_t>();
|
| 176 |
+
if (start == 0 && end == 0) {
|
| 177 |
+
break;
|
| 178 |
+
}
|
| 179 |
+
if (start == std::numeric_limits<uint64_t>::max()) {
|
| 180 |
+
base = end;
|
| 181 |
+
} else {
|
| 182 |
+
ranges.emplace_back(base + start, base + end);
|
| 183 |
+
}
|
| 184 |
+
}
|
| 185 |
+
return ranges;
|
| 186 |
+
}
|
| 187 |
+
|
| 188 |
+
std::vector<std::pair<uint64_t, uint64_t>> readRanges5(uint64_t offset) {
|
| 189 |
+
CheckedLexer L = s_.debug_rnglists.lexer(offset);
|
| 190 |
+
uint64_t base = 0;
|
| 191 |
+
LOG_INFO("BEGIN RANGES {:x}\n", offset);
|
| 192 |
+
std::vector<std::pair<uint64_t, uint64_t>> ranges;
|
| 193 |
+
while (true) {
|
| 194 |
+
auto op = L.read<uint8_t>();
|
| 195 |
+
switch (op) {
|
| 196 |
+
case DW_RLE_end_of_list:
|
| 197 |
+
LOG_INFO("END RANGES\n");
|
| 198 |
+
return ranges;
|
| 199 |
+
case DW_RLE_base_addressx: {
|
| 200 |
+
base = readEncoded(L, DW_FORM_addrx);
|
| 201 |
+
LOG_INFO("BASE ADDRX {:x}\n", base);
|
| 202 |
+
} break;
|
| 203 |
+
case DW_RLE_startx_length: {
|
| 204 |
+
auto s = readEncoded(L, DW_FORM_addrx);
|
| 205 |
+
auto e = L.readULEB128();
|
| 206 |
+
LOG_INFO("startx_length {:x} {:x}\n", s, e);
|
| 207 |
+
ranges.emplace_back(s, s + e);
|
| 208 |
+
} break;
|
| 209 |
+
case DW_RLE_base_address:
|
| 210 |
+
base = L.read<uint64_t>();
|
| 211 |
+
LOG_INFO("BASE ADDR {:x}\n", base);
|
| 212 |
+
break;
|
| 213 |
+
case DW_RLE_offset_pair: {
|
| 214 |
+
auto s = L.readULEB128();
|
| 215 |
+
auto e = L.readULEB128();
|
| 216 |
+
LOG_INFO("offset_pair {:x} {:x}\n", s, e);
|
| 217 |
+
ranges.emplace_back(base + s, base + e);
|
| 218 |
+
} break;
|
| 219 |
+
case DW_RLE_start_length: {
|
| 220 |
+
auto s = L.read<uint64_t>();
|
| 221 |
+
auto e = L.readULEB128();
|
| 222 |
+
LOG_INFO("start_length {:x} {:x}\n", s, e);
|
| 223 |
+
ranges.emplace_back(s, s + e);
|
| 224 |
+
} break;
|
| 225 |
+
default:
|
| 226 |
+
UNWIND_CHECK(false, "unknown range op: {}", op);
|
| 227 |
+
}
|
| 228 |
+
}
|
| 229 |
+
}
|
| 230 |
+
|
| 231 |
+
CheckedLexer findAbbrev(uint64_t offset, uint64_t entry) {
|
| 232 |
+
CheckedLexer L = s_.debug_abbrev.lexer(offset);
|
| 233 |
+
while (true) {
|
| 234 |
+
auto abbrev_code = L.readULEB128();
|
| 235 |
+
UNWIND_CHECK(
|
| 236 |
+
abbrev_code != 0,
|
| 237 |
+
"could not find entry {} at offset {:x}",
|
| 238 |
+
entry,
|
| 239 |
+
offset);
|
| 240 |
+
auto tag = L.readULEB128();
|
| 241 |
+
L.read<uint8_t>(); // has children
|
| 242 |
+
if (abbrev_code == entry) {
|
| 243 |
+
UNWIND_CHECK(
|
| 244 |
+
tag == DW_TAG_compile_unit,
|
| 245 |
+
"first entry was not a compile unit but {}",
|
| 246 |
+
tag);
|
| 247 |
+
return L;
|
| 248 |
+
}
|
| 249 |
+
while (true) {
|
| 250 |
+
auto attr = L.readULEB128();
|
| 251 |
+
auto form = L.readULEB128();
|
| 252 |
+
if (attr == 0 && form == 0) {
|
| 253 |
+
break;
|
| 254 |
+
}
|
| 255 |
+
if (form == DW_FORM_implicit_const) {
|
| 256 |
+
L.readSLEB128();
|
| 257 |
+
}
|
| 258 |
+
}
|
| 259 |
+
}
|
| 260 |
+
}
|
| 261 |
+
|
| 262 |
+
// NOLINTNEXTLINE(cppcoreguidelines-avoid-const-or-ref-data-members)
|
| 263 |
+
Sections& s_;
|
| 264 |
+
std::optional<uint64_t> line_number_program_offset_;
|
| 265 |
+
uint64_t offset_ = 0;
|
| 266 |
+
uint8_t sec_offset_size_ = 0;
|
| 267 |
+
uint64_t length_ = 0;
|
| 268 |
+
const char* end_ = nullptr;
|
| 269 |
+
uint64_t debug_abbrev_offset_ = 0;
|
| 270 |
+
bool is_64bit_ = false;
|
| 271 |
+
|
| 272 |
+
std::optional<std::pair<uint64_t, uint8_t>> range_ptr_;
|
| 273 |
+
uint64_t lowpc_ = 0;
|
| 274 |
+
std::optional<uint64_t> highpc_;
|
| 275 |
+
uint16_t version_ = 0;
|
| 276 |
+
uint64_t address_base_ = 0;
|
| 277 |
+
std::optional<uint64_t> rnglists_base_;
|
| 278 |
+
};
|
| 279 |
+
|
| 280 |
+
} // namespace torch::unwind
|
phivenv/Lib/site-packages/torch/include/torch/csrc/profiler/unwind/dwarf_enums.h
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#pragma once
|
| 2 |
+
|
| 3 |
+
enum {
|
| 4 |
+
DW_EH_PE_absptr = 0x00,
|
| 5 |
+
DW_EH_PE_omit = 0xff,
|
| 6 |
+
/* FDE data encoding. */
|
| 7 |
+
DW_EH_PE_uleb128 = 0x01,
|
| 8 |
+
DW_EH_PE_udata2 = 0x02,
|
| 9 |
+
DW_EH_PE_udata4 = 0x03,
|
| 10 |
+
DW_EH_PE_udata8 = 0x04,
|
| 11 |
+
DW_EH_PE_sleb128 = 0x09,
|
| 12 |
+
DW_EH_PE_sdata2 = 0x0a,
|
| 13 |
+
DW_EH_PE_sdata4 = 0x0b,
|
| 14 |
+
DW_EH_PE_sdata8 = 0x0c,
|
| 15 |
+
DW_EH_PE_signed = 0x08,
|
| 16 |
+
/* FDE flags. */
|
| 17 |
+
DW_EH_PE_pcrel = 0x10,
|
| 18 |
+
DW_EH_PE_textrel = 0x20,
|
| 19 |
+
DW_EH_PE_datarel = 0x30,
|
| 20 |
+
DW_EH_PE_funcrel = 0x40,
|
| 21 |
+
DW_EH_PE_aligned = 0x50,
|
| 22 |
+
DW_EH_PE_indirect = 0x80,
|
| 23 |
+
};
|
| 24 |
+
|
| 25 |
+
enum {
|
| 26 |
+
DW_CFA_nop = 0x0,
|
| 27 |
+
DW_CFA_advance_loc = 0x01,
|
| 28 |
+
DW_CFA_offset = 0x02,
|
| 29 |
+
DW_CFA_restore = 0x03,
|
| 30 |
+
DW_CFA_advance_loc1 = 0x02,
|
| 31 |
+
DW_CFA_advance_loc2 = 0x03,
|
| 32 |
+
DW_CFA_advance_loc4 = 0x04,
|
| 33 |
+
DW_CFA_restore_extended = 0x06,
|
| 34 |
+
DW_CFA_undefined = 0x07,
|
| 35 |
+
DW_CFA_register = 0x09,
|
| 36 |
+
DW_CFA_remember_state = 0x0a,
|
| 37 |
+
DW_CFA_restore_state = 0x0b,
|
| 38 |
+
DW_CFA_def_cfa = 0x0c,
|
| 39 |
+
DW_CFA_def_cfa_register = 0x0d,
|
| 40 |
+
DW_CFA_def_cfa_offset = 0x0e,
|
| 41 |
+
DW_CFA_def_cfa_expression = 0xf,
|
| 42 |
+
DW_CFA_expression = 0x10,
|
| 43 |
+
DW_CFA_offset_extended_sf = 0x11,
|
| 44 |
+
DW_CFA_GNU_args_size = 0x2e,
|
| 45 |
+
DW_OP_deref = 0x6,
|
| 46 |
+
};
|
phivenv/Lib/site-packages/torch/include/torch/csrc/profiler/unwind/dwarf_symbolize_enums.h
ADDED
|
@@ -0,0 +1,179 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#pragma once
|
| 2 |
+
#include <torch/csrc/profiler/unwind/unwind_error.h>
|
| 3 |
+
#include <cstdint>
|
| 4 |
+
#include <optional>
|
| 5 |
+
|
| 6 |
+
enum {
|
| 7 |
+
DW_TAG_subprogram = 0x2e,
|
| 8 |
+
DW_TAG_inlined_subroutine = 0x1d,
|
| 9 |
+
DW_TAG_compile_unit = 0x11,
|
| 10 |
+
DW_AT_sibling = 0x1, // reference
|
| 11 |
+
DW_AT_name = 0x3, // string
|
| 12 |
+
DW_AT_stmt_list = 0x10, // lineptr
|
| 13 |
+
DW_AT_addr_base = 0x73, // sec_offset
|
| 14 |
+
DW_AT_rnglists_base = 0x74, // sec_offset
|
| 15 |
+
DW_AT_low_pc = 0x11, // address
|
| 16 |
+
DW_AT_high_pc = 0x12, // address
|
| 17 |
+
DW_AT_specification = 0x47, // reference
|
| 18 |
+
DW_AT_abstract_origin = 0x31, // reference
|
| 19 |
+
DW_AT_linkage_name = 0x6e, // string
|
| 20 |
+
DW_AT_ranges = 0x55, // rnglist
|
| 21 |
+
DW_AT_str_offsets_base = 0x72, // sec_offset
|
| 22 |
+
DW_FORM_addr = 0x01,
|
| 23 |
+
DW_FORM_block2 = 0x03,
|
| 24 |
+
DW_FORM_block4 = 0x04,
|
| 25 |
+
DW_FORM_data2 = 0x05,
|
| 26 |
+
DW_FORM_data4 = 0x06,
|
| 27 |
+
DW_FORM_data8 = 0x07,
|
| 28 |
+
DW_FORM_string = 0x08,
|
| 29 |
+
DW_FORM_block = 0x09,
|
| 30 |
+
DW_FORM_block1 = 0x0a,
|
| 31 |
+
DW_FORM_data1 = 0x0b,
|
| 32 |
+
DW_FORM_flag = 0x0c,
|
| 33 |
+
DW_FORM_sdata = 0x0d,
|
| 34 |
+
DW_FORM_strp = 0x0e,
|
| 35 |
+
DW_FORM_udata = 0x0f,
|
| 36 |
+
DW_FORM_ref_addr = 0x10,
|
| 37 |
+
DW_FORM_ref1 = 0x11,
|
| 38 |
+
DW_FORM_ref2 = 0x12,
|
| 39 |
+
DW_FORM_ref4 = 0x13,
|
| 40 |
+
DW_FORM_ref8 = 0x14,
|
| 41 |
+
DW_FORM_ref_udata = 0x15,
|
| 42 |
+
DW_FORM_indirect = 0x16,
|
| 43 |
+
DW_FORM_sec_offset = 0x17,
|
| 44 |
+
DW_FORM_exprloc = 0x18,
|
| 45 |
+
DW_FORM_flag_present = 0x19,
|
| 46 |
+
DW_FORM_strx = 0x1a,
|
| 47 |
+
DW_FORM_addrx = 0x1b,
|
| 48 |
+
DW_FORM_ref_sup4 = 0x1c,
|
| 49 |
+
DW_FORM_strp_sup = 0x1d,
|
| 50 |
+
DW_FORM_data16 = 0x1e,
|
| 51 |
+
DW_FORM_line_strp = 0x1f,
|
| 52 |
+
DW_FORM_ref_sig8 = 0x20,
|
| 53 |
+
DW_FORM_implicit_const = 0x21,
|
| 54 |
+
DW_FORM_loclistx = 0x22,
|
| 55 |
+
DW_FORM_rnglistx = 0x23,
|
| 56 |
+
DW_FORM_ref_sup8 = 0x24,
|
| 57 |
+
DW_FORM_strx1 = 0x25,
|
| 58 |
+
DW_FORM_strx2 = 0x26,
|
| 59 |
+
DW_FORM_strx3 = 0x27,
|
| 60 |
+
DW_FORM_strx4 = 0x28,
|
| 61 |
+
DW_FORM_addrx1 = 0x29,
|
| 62 |
+
DW_FORM_addrx2 = 0x2a,
|
| 63 |
+
DW_FORM_addrx3 = 0x2b,
|
| 64 |
+
DW_FORM_addrx4 = 0x2c,
|
| 65 |
+
/* GNU Debug Fission extensions. */
|
| 66 |
+
DW_FORM_GNU_addr_index = 0x1f01,
|
| 67 |
+
DW_FORM_GNU_str_index = 0x1f02,
|
| 68 |
+
DW_FORM_GNU_ref_alt = 0x1f20, /* offset in alternate .debuginfo. */
|
| 69 |
+
DW_FORM_GNU_strp_alt = 0x1f21, /* offset in alternate .debug_str. */
|
| 70 |
+
DW_LNCT_path = 0x1,
|
| 71 |
+
DW_LNCT_directory_index = 0x2,
|
| 72 |
+
DW_LNS_extended_op = 0x00,
|
| 73 |
+
DW_LNE_end_sequence = 0x01,
|
| 74 |
+
DW_LNE_set_address = 0x02,
|
| 75 |
+
DW_LNS_copy = 0x01,
|
| 76 |
+
DW_LNS_advance_pc = 0x02,
|
| 77 |
+
DW_LNS_advance_line = 0x03,
|
| 78 |
+
DW_LNS_set_file = 0x04,
|
| 79 |
+
DW_LNS_const_add_pc = 0x08,
|
| 80 |
+
DW_LNS_fixed_advance_pc = 0x09,
|
| 81 |
+
DW_RLE_end_of_list = 0x0,
|
| 82 |
+
DW_RLE_base_addressx = 0x1,
|
| 83 |
+
DW_RLE_startx_endx = 0x2,
|
| 84 |
+
DW_RLE_startx_length = 0x3,
|
| 85 |
+
DW_RLE_offset_pair = 0x4,
|
| 86 |
+
DW_RLE_base_address = 0x5,
|
| 87 |
+
DW_RLE_start_end = 0x6,
|
| 88 |
+
DW_RLE_start_length = 0x7
|
| 89 |
+
};
|
| 90 |
+
|
| 91 |
+
static std::optional<size_t> formSize(uint64_t form, uint8_t sec_offset_size) {
|
| 92 |
+
switch (form) {
|
| 93 |
+
case DW_FORM_addr:
|
| 94 |
+
return sizeof(void*);
|
| 95 |
+
case DW_FORM_block2:
|
| 96 |
+
case DW_FORM_block4:
|
| 97 |
+
return std::nullopt;
|
| 98 |
+
case DW_FORM_data2:
|
| 99 |
+
return 2;
|
| 100 |
+
case DW_FORM_data4:
|
| 101 |
+
return 4;
|
| 102 |
+
case DW_FORM_data8:
|
| 103 |
+
return 8;
|
| 104 |
+
case DW_FORM_string:
|
| 105 |
+
case DW_FORM_block:
|
| 106 |
+
case DW_FORM_block1:
|
| 107 |
+
return std::nullopt;
|
| 108 |
+
case DW_FORM_data1:
|
| 109 |
+
case DW_FORM_flag:
|
| 110 |
+
return 1;
|
| 111 |
+
case DW_FORM_sdata:
|
| 112 |
+
return std::nullopt;
|
| 113 |
+
case DW_FORM_strp:
|
| 114 |
+
return sec_offset_size;
|
| 115 |
+
case DW_FORM_udata:
|
| 116 |
+
return std::nullopt;
|
| 117 |
+
case DW_FORM_ref_addr:
|
| 118 |
+
return sec_offset_size;
|
| 119 |
+
case DW_FORM_ref1:
|
| 120 |
+
return 1;
|
| 121 |
+
case DW_FORM_ref2:
|
| 122 |
+
return 2;
|
| 123 |
+
case DW_FORM_ref4:
|
| 124 |
+
return 4;
|
| 125 |
+
case DW_FORM_ref8:
|
| 126 |
+
return 8;
|
| 127 |
+
case DW_FORM_ref_udata:
|
| 128 |
+
case DW_FORM_indirect:
|
| 129 |
+
return std::nullopt;
|
| 130 |
+
case DW_FORM_sec_offset:
|
| 131 |
+
return sec_offset_size;
|
| 132 |
+
case DW_FORM_exprloc:
|
| 133 |
+
return std::nullopt;
|
| 134 |
+
case DW_FORM_flag_present:
|
| 135 |
+
return 0;
|
| 136 |
+
case DW_FORM_strx:
|
| 137 |
+
case DW_FORM_addrx:
|
| 138 |
+
return std::nullopt;
|
| 139 |
+
case DW_FORM_ref_sup4:
|
| 140 |
+
return 4;
|
| 141 |
+
case DW_FORM_strp_sup:
|
| 142 |
+
return sec_offset_size;
|
| 143 |
+
case DW_FORM_data16:
|
| 144 |
+
return 16;
|
| 145 |
+
case DW_FORM_line_strp:
|
| 146 |
+
return sec_offset_size;
|
| 147 |
+
case DW_FORM_ref_sig8:
|
| 148 |
+
return 8;
|
| 149 |
+
case DW_FORM_implicit_const:
|
| 150 |
+
return 0;
|
| 151 |
+
case DW_FORM_loclistx:
|
| 152 |
+
case DW_FORM_rnglistx:
|
| 153 |
+
return std::nullopt;
|
| 154 |
+
case DW_FORM_ref_sup8:
|
| 155 |
+
return 8;
|
| 156 |
+
case DW_FORM_strx1:
|
| 157 |
+
return 1;
|
| 158 |
+
case DW_FORM_strx2:
|
| 159 |
+
return 2;
|
| 160 |
+
case DW_FORM_strx3:
|
| 161 |
+
return 3;
|
| 162 |
+
case DW_FORM_strx4:
|
| 163 |
+
return 4;
|
| 164 |
+
case DW_FORM_addrx1:
|
| 165 |
+
return 1;
|
| 166 |
+
case DW_FORM_addrx2:
|
| 167 |
+
return 2;
|
| 168 |
+
case DW_FORM_addrx3:
|
| 169 |
+
return 3;
|
| 170 |
+
case DW_FORM_addrx4:
|
| 171 |
+
return 4;
|
| 172 |
+
case DW_FORM_GNU_addr_index:
|
| 173 |
+
case DW_FORM_GNU_str_index:
|
| 174 |
+
case DW_FORM_GNU_ref_alt:
|
| 175 |
+
case DW_FORM_GNU_strp_alt:
|
| 176 |
+
default:
|
| 177 |
+
return std::nullopt;
|
| 178 |
+
}
|
| 179 |
+
}
|
phivenv/Lib/site-packages/torch/include/torch/csrc/profiler/unwind/eh_frame_hdr.h
ADDED
|
@@ -0,0 +1,100 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#pragma once
|
| 2 |
+
#include <cstdint>
|
| 3 |
+
#include <ostream>
|
| 4 |
+
|
| 5 |
+
#include <torch/csrc/profiler/unwind/lexer.h>
|
| 6 |
+
#include <torch/csrc/profiler/unwind/unwind_error.h>
|
| 7 |
+
|
| 8 |
+
// Overview of the format described in
|
| 9 |
+
// https://refspecs.linuxfoundation.org/LSB_1.3.0/gLSB/gLSB/ehframehdr.html
|
| 10 |
+
namespace torch::unwind {
|
| 11 |
+
|
| 12 |
+
struct EHFrameHdr {
|
| 13 |
+
EHFrameHdr(void* base) : base_(base) {
|
| 14 |
+
Lexer L(base, base);
|
| 15 |
+
version_ = L.read<uint8_t>();
|
| 16 |
+
eh_frame_ptr_enc_ = L.read<uint8_t>();
|
| 17 |
+
fde_count_enc_ = L.read<uint8_t>();
|
| 18 |
+
table_enc_ = L.read<uint8_t>();
|
| 19 |
+
if (table_enc_ == DW_EH_PE_omit) {
|
| 20 |
+
table_size_ = 0;
|
| 21 |
+
} else {
|
| 22 |
+
switch (table_enc_ & 0xF) {
|
| 23 |
+
case DW_EH_PE_udata2:
|
| 24 |
+
case DW_EH_PE_sdata2:
|
| 25 |
+
table_size_ = 2;
|
| 26 |
+
break;
|
| 27 |
+
case DW_EH_PE_udata4:
|
| 28 |
+
case DW_EH_PE_sdata4:
|
| 29 |
+
table_size_ = 4;
|
| 30 |
+
break;
|
| 31 |
+
case DW_EH_PE_udata8:
|
| 32 |
+
case DW_EH_PE_sdata8:
|
| 33 |
+
table_size_ = 8;
|
| 34 |
+
break;
|
| 35 |
+
case DW_EH_PE_uleb128:
|
| 36 |
+
case DW_EH_PE_sleb128:
|
| 37 |
+
throw UnwindError("uleb/sleb table encoding not supported");
|
| 38 |
+
break;
|
| 39 |
+
default:
|
| 40 |
+
throw UnwindError("unknown table encoding");
|
| 41 |
+
}
|
| 42 |
+
}
|
| 43 |
+
// NOLINTNEXTLINE(performance-no-int-to-ptr)
|
| 44 |
+
eh_frame_ = (void*)L.readEncodedOr(eh_frame_ptr_enc_, 0);
|
| 45 |
+
fde_count_ = L.readEncodedOr(fde_count_enc_, 0);
|
| 46 |
+
table_start_ = L.loc();
|
| 47 |
+
}
|
| 48 |
+
size_t nentries() const {
|
| 49 |
+
return fde_count_;
|
| 50 |
+
}
|
| 51 |
+
|
| 52 |
+
uint64_t lowpc(size_t i) const {
|
| 53 |
+
return Lexer(table_start_, base_)
|
| 54 |
+
.skip(2 * i * table_size_)
|
| 55 |
+
.readEncoded(table_enc_);
|
| 56 |
+
}
|
| 57 |
+
void* fde(size_t i) const {
|
| 58 |
+
// NOLINTNEXTLINE(performance-no-int-to-ptr)
|
| 59 |
+
return (void*)Lexer(table_start_, base_)
|
| 60 |
+
.skip((2 * i + 1) * table_size_)
|
| 61 |
+
.readEncoded(table_enc_);
|
| 62 |
+
}
|
| 63 |
+
|
| 64 |
+
void* entryForAddr(uint64_t addr) const {
|
| 65 |
+
if (!table_size_ || !nentries()) {
|
| 66 |
+
throw UnwindError("search table not present");
|
| 67 |
+
}
|
| 68 |
+
uint64_t low = 0;
|
| 69 |
+
uint64_t high = nentries();
|
| 70 |
+
while (low + 1 < high) {
|
| 71 |
+
auto mid = (low + high) / 2;
|
| 72 |
+
if (addr < lowpc(mid)) {
|
| 73 |
+
high = mid;
|
| 74 |
+
} else {
|
| 75 |
+
low = mid;
|
| 76 |
+
}
|
| 77 |
+
}
|
| 78 |
+
return fde(low);
|
| 79 |
+
}
|
| 80 |
+
|
| 81 |
+
friend std::ostream& operator<<(std::ostream& out, const EHFrameHdr& self) {
|
| 82 |
+
out << "EHFrameHeader(version=" << self.version_
|
| 83 |
+
<< ",table_size=" << self.table_size_
|
| 84 |
+
<< ",fde_count=" << self.fde_count_ << ")";
|
| 85 |
+
return out;
|
| 86 |
+
}
|
| 87 |
+
|
| 88 |
+
private:
|
| 89 |
+
void* base_;
|
| 90 |
+
void* table_start_;
|
| 91 |
+
uint8_t version_;
|
| 92 |
+
uint8_t eh_frame_ptr_enc_;
|
| 93 |
+
uint8_t fde_count_enc_;
|
| 94 |
+
uint8_t table_enc_;
|
| 95 |
+
void* eh_frame_ = nullptr;
|
| 96 |
+
int64_t fde_count_;
|
| 97 |
+
uint32_t table_size_;
|
| 98 |
+
};
|
| 99 |
+
|
| 100 |
+
} // namespace torch::unwind
|
phivenv/Lib/site-packages/torch/include/torch/csrc/profiler/unwind/fast_symbolizer.h
ADDED
|
@@ -0,0 +1,108 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#pragma once
|
| 2 |
+
|
| 3 |
+
#include <fmt/format.h>
|
| 4 |
+
#include <sys/types.h>
|
| 5 |
+
#include <torch/csrc/profiler/unwind/debug_info.h>
|
| 6 |
+
#include <torch/csrc/profiler/unwind/line_number_program.h>
|
| 7 |
+
#include <torch/csrc/profiler/unwind/sections.h>
|
| 8 |
+
#include <torch/csrc/profiler/unwind/unwind.h>
|
| 9 |
+
#include <torch/csrc/profiler/unwind/unwind_error.h>
|
| 10 |
+
#include <memory>
|
| 11 |
+
#include <unordered_map>
|
| 12 |
+
|
| 13 |
+
namespace torch::unwind {
|
| 14 |
+
|
| 15 |
+
#define UNWIND_WARN(w, ...) \
|
| 16 |
+
do { \
|
| 17 |
+
w.emplace_back(fmt::format(__VA_ARGS__)); \
|
| 18 |
+
LOG_INFO("WARNING: {}\n", w.back()); \
|
| 19 |
+
} while (0);
|
| 20 |
+
|
| 21 |
+
struct FastSymbolizer {
|
| 22 |
+
FastSymbolizer() = default;
|
| 23 |
+
Frame symbolize(const std::string& library, uint64_t offset) {
|
| 24 |
+
LOG_INFO("symbolizing {} + 0x{:x}\n", library, offset);
|
| 25 |
+
Frame frame;
|
| 26 |
+
frame.funcname = "??";
|
| 27 |
+
frame.filename = library;
|
| 28 |
+
frame.lineno = offset;
|
| 29 |
+
auto s = getOrCreateSections(library);
|
| 30 |
+
if (auto e = s->findSubprogramName(offset)) {
|
| 31 |
+
frame.funcname = *e;
|
| 32 |
+
} else {
|
| 33 |
+
UNWIND_WARN(
|
| 34 |
+
warnings_,
|
| 35 |
+
"failed to find subprogram name for {} 0x{:x}",
|
| 36 |
+
library,
|
| 37 |
+
offset);
|
| 38 |
+
}
|
| 39 |
+
if (auto e = findLine(s, offset)) {
|
| 40 |
+
frame.filename = e->first;
|
| 41 |
+
frame.lineno = e->second;
|
| 42 |
+
} else {
|
| 43 |
+
UNWIND_WARN(
|
| 44 |
+
warnings_, "failed to find file/line for {} 0x{:x}", library, offset);
|
| 45 |
+
}
|
| 46 |
+
return frame;
|
| 47 |
+
}
|
| 48 |
+
const std::vector<std::string>& warnings() {
|
| 49 |
+
return warnings_;
|
| 50 |
+
}
|
| 51 |
+
|
| 52 |
+
private:
|
| 53 |
+
void parseDebugInfo(Sections* s) {
|
| 54 |
+
uint64_t offset = 0;
|
| 55 |
+
while (offset < s->debug_info.size) {
|
| 56 |
+
DebugInfo info(*s);
|
| 57 |
+
info.parse(offset);
|
| 58 |
+
if (auto lnp_offset = info.lineNumberProgramOffset()) {
|
| 59 |
+
for (auto r : info.ranges()) {
|
| 60 |
+
s->addDebugInfoRange(r.first, r.second, line_number_programs_.size());
|
| 61 |
+
}
|
| 62 |
+
line_number_programs_.emplace_back(
|
| 63 |
+
std::make_unique<LineNumberProgram>(*s, *lnp_offset));
|
| 64 |
+
}
|
| 65 |
+
offset = info.nextOffset();
|
| 66 |
+
}
|
| 67 |
+
}
|
| 68 |
+
Sections* getOrCreateSections(const std::string& library) {
|
| 69 |
+
auto it = libraries_.find(library);
|
| 70 |
+
if (it == libraries_.end()) {
|
| 71 |
+
it = libraries_.insert({library, std::make_unique<Sections>()}).first;
|
| 72 |
+
try {
|
| 73 |
+
Sections* s = it->second.get();
|
| 74 |
+
s->parse(library.c_str());
|
| 75 |
+
parseDebugInfo(s);
|
| 76 |
+
} catch (UnwindError& err) {
|
| 77 |
+
UNWIND_WARN(
|
| 78 |
+
warnings_, "failed to parse library {}: {}", library, err.what());
|
| 79 |
+
}
|
| 80 |
+
}
|
| 81 |
+
return it->second.get();
|
| 82 |
+
}
|
| 83 |
+
std::optional<std::pair<std::string, int64_t>> findLine(
|
| 84 |
+
Sections* s,
|
| 85 |
+
uint64_t offset) {
|
| 86 |
+
if (auto idx = s->findDebugInfoOffset(offset)) {
|
| 87 |
+
auto r = line_number_programs_.at(*idx).get();
|
| 88 |
+
try {
|
| 89 |
+
r->parse();
|
| 90 |
+
} catch (UnwindError& err) {
|
| 91 |
+
UNWIND_WARN(
|
| 92 |
+
warnings_,
|
| 93 |
+
"failed to read line number program [{:x}] {}",
|
| 94 |
+
r->offset(),
|
| 95 |
+
err.what());
|
| 96 |
+
}
|
| 97 |
+
if (auto e = r->find(offset)) {
|
| 98 |
+
return std::make_pair(r->filename(e->file), e->line);
|
| 99 |
+
}
|
| 100 |
+
}
|
| 101 |
+
return std::nullopt;
|
| 102 |
+
}
|
| 103 |
+
std::unordered_map<std::string, std::unique_ptr<Sections>> libraries_;
|
| 104 |
+
std::vector<std::unique_ptr<LineNumberProgram>> line_number_programs_;
|
| 105 |
+
std::vector<std::string> warnings_;
|
| 106 |
+
};
|
| 107 |
+
|
| 108 |
+
} // namespace torch::unwind
|
phivenv/Lib/site-packages/torch/include/torch/csrc/profiler/unwind/fde.h
ADDED
|
@@ -0,0 +1,411 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#pragma once
|
| 2 |
+
#include <c10/util/Exception.h>
|
| 3 |
+
#include <c10/util/irange.h>
|
| 4 |
+
#include <torch/csrc/profiler/unwind/action.h>
|
| 5 |
+
#include <torch/csrc/profiler/unwind/lexer.h>
|
| 6 |
+
#include <array>
|
| 7 |
+
#include <iostream>
|
| 8 |
+
#include <sstream>
|
| 9 |
+
#include <vector>
|
| 10 |
+
|
| 11 |
+
namespace torch::unwind {
|
| 12 |
+
|
| 13 |
+
struct TableState {
|
| 14 |
+
Action cfa;
|
| 15 |
+
std::array<Action, D_REG_SIZE> registers;
|
| 16 |
+
friend std::ostream& operator<<(std::ostream& out, const TableState& self) {
|
| 17 |
+
out << "cfa = " << self.cfa << "; ";
|
| 18 |
+
for (auto r : c10::irange(self.registers.size())) {
|
| 19 |
+
if (self.registers.at(r).kind != A_UNDEFINED) {
|
| 20 |
+
out << "r" << r << " = " << self.registers.at(r) << "; ";
|
| 21 |
+
}
|
| 22 |
+
}
|
| 23 |
+
return out;
|
| 24 |
+
}
|
| 25 |
+
};
|
| 26 |
+
|
| 27 |
+
// FDE - Frame Description Entry (Concept in ELF spec)
|
| 28 |
+
// This format is explained well by
|
| 29 |
+
// https://www.airs.com/blog/archives/460
|
| 30 |
+
// Details of different dwarf actions are explained
|
| 31 |
+
// in the spec document:
|
| 32 |
+
// https://web.archive.org/web/20221129184704/https://dwarfstd.org/doc/DWARF4.doc
|
| 33 |
+
// An overview of how DWARF unwinding works is given in
|
| 34 |
+
// https://dl.acm.org/doi/pdf/10.1145/3360572
|
| 35 |
+
// A similar implementation written in rust is:
|
| 36 |
+
// https://github.com/mstange/framehop/
|
| 37 |
+
|
| 38 |
+
template <bool LOG = false>
|
| 39 |
+
struct FDE {
|
| 40 |
+
FDE(void* data, const char* library_name, uint64_t load_bias)
|
| 41 |
+
: library_name_(library_name), load_bias_(load_bias) {
|
| 42 |
+
Lexer L(data);
|
| 43 |
+
auto length = L.read4or8Length();
|
| 44 |
+
void* fde_start = L.loc();
|
| 45 |
+
// NOLINTNEXTLINE(performance-no-int-to-ptr)
|
| 46 |
+
void* cie_data = (void*)((int64_t)fde_start - L.read<uint32_t>());
|
| 47 |
+
Lexer LC(cie_data);
|
| 48 |
+
auto cie_length = LC.read4or8Length();
|
| 49 |
+
void* cie_start = LC.loc();
|
| 50 |
+
auto zero = LC.read<uint32_t>();
|
| 51 |
+
TORCH_INTERNAL_ASSERT(zero == 0, "expected 0 for CIE");
|
| 52 |
+
auto version = LC.read<uint8_t>();
|
| 53 |
+
TORCH_INTERNAL_ASSERT(
|
| 54 |
+
version == 1 || version == 3, "non-1 version for CIE");
|
| 55 |
+
augmentation_string_ = LC.readCString();
|
| 56 |
+
if (hasAugmentation("eh")) {
|
| 57 |
+
throw UnwindError("unsupported 'eh' augmentation string");
|
| 58 |
+
}
|
| 59 |
+
code_alignment_factor_ = static_cast<int64_t>(LC.readULEB128());
|
| 60 |
+
data_alignment_factor_ = static_cast<int64_t>(LC.readSLEB128());
|
| 61 |
+
if (version == 1) {
|
| 62 |
+
ra_register_ = LC.read<uint8_t>();
|
| 63 |
+
} else {
|
| 64 |
+
ra_register_ = static_cast<int64_t>(LC.readULEB128());
|
| 65 |
+
}
|
| 66 |
+
// we assume this in the state
|
| 67 |
+
TORCH_INTERNAL_ASSERT(ra_register_ == 16, "unexpected number of registers");
|
| 68 |
+
if (augmentation_string_ && *augmentation_string_ == 'z') {
|
| 69 |
+
augmentation_length_ = static_cast<int64_t>(LC.readULEB128());
|
| 70 |
+
Lexer A(LC.loc());
|
| 71 |
+
for (auto ap = augmentation_string_ + 1; *ap; ap++) {
|
| 72 |
+
switch (*ap) {
|
| 73 |
+
case 'L':
|
| 74 |
+
lsda_enc = A.read<uint8_t>();
|
| 75 |
+
break;
|
| 76 |
+
case 'R':
|
| 77 |
+
fde_enc = A.read<uint8_t>();
|
| 78 |
+
break;
|
| 79 |
+
case 'P': {
|
| 80 |
+
uint8_t personality_enc = A.read<uint8_t>();
|
| 81 |
+
A.readEncoded(personality_enc);
|
| 82 |
+
} break;
|
| 83 |
+
case 'S': {
|
| 84 |
+
// signal handler
|
| 85 |
+
} break;
|
| 86 |
+
default: {
|
| 87 |
+
throw UnwindError("unknown augmentation string");
|
| 88 |
+
} break;
|
| 89 |
+
}
|
| 90 |
+
}
|
| 91 |
+
}
|
| 92 |
+
LC.skip(augmentation_length_);
|
| 93 |
+
low_pc_ = L.readEncoded(fde_enc);
|
| 94 |
+
high_pc_ = low_pc_ + L.readEncodedValue(fde_enc);
|
| 95 |
+
|
| 96 |
+
if (hasAugmentation("z")) {
|
| 97 |
+
augmentation_length_fde_ = static_cast<int64_t>(L.readULEB128());
|
| 98 |
+
}
|
| 99 |
+
L.readEncodedOr(lsda_enc, 0);
|
| 100 |
+
|
| 101 |
+
cie_begin_ = LC.loc();
|
| 102 |
+
fde_begin_ = L.loc();
|
| 103 |
+
cie_end_ = (void*)((const char*)cie_start + cie_length);
|
| 104 |
+
fde_end_ = (void*)((const char*)fde_start + length);
|
| 105 |
+
}
|
| 106 |
+
|
| 107 |
+
// OP Code implementations
|
| 108 |
+
|
| 109 |
+
void advance_raw(int64_t amount) {
|
| 110 |
+
auto previous_pc = current_pc_;
|
| 111 |
+
current_pc_ += amount;
|
| 112 |
+
if (LOG) {
|
| 113 |
+
(*out_) << (void*)(previous_pc - load_bias_) << "-"
|
| 114 |
+
<< (void*)(current_pc_ - load_bias_) << ": " << state() << "\n";
|
| 115 |
+
}
|
| 116 |
+
}
|
| 117 |
+
|
| 118 |
+
void advance_loc(int64_t amount) {
|
| 119 |
+
if (LOG) {
|
| 120 |
+
(*out_) << "advance_loc " << amount << "\n";
|
| 121 |
+
}
|
| 122 |
+
advance_raw(amount * code_alignment_factor_);
|
| 123 |
+
}
|
| 124 |
+
|
| 125 |
+
void offset(int64_t reg, int64_t offset) {
|
| 126 |
+
if (LOG) {
|
| 127 |
+
(*out_) << "offset " << reg << " " << offset << "\n";
|
| 128 |
+
}
|
| 129 |
+
if (reg > (int64_t)state().registers.size()) {
|
| 130 |
+
if (LOG) {
|
| 131 |
+
(*out_) << "OFFSET OF BIG REGISTER " << reg << "ignored...\n";
|
| 132 |
+
}
|
| 133 |
+
return;
|
| 134 |
+
}
|
| 135 |
+
state().registers.at(reg) =
|
| 136 |
+
Action{A_LOAD_CFA_OFFSET, -1, offset * data_alignment_factor_};
|
| 137 |
+
}
|
| 138 |
+
|
| 139 |
+
void restore(int64_t reg) {
|
| 140 |
+
if (LOG) {
|
| 141 |
+
(*out_) << "restore " << reg << "\n";
|
| 142 |
+
}
|
| 143 |
+
if (reg > (int64_t)state().registers.size()) {
|
| 144 |
+
if (LOG) {
|
| 145 |
+
(*out_) << "RESTORE OF BIG REGISTER " << reg << "ignored...\n";
|
| 146 |
+
}
|
| 147 |
+
return;
|
| 148 |
+
}
|
| 149 |
+
state().registers.at(reg) = initial_state_.registers.at(reg);
|
| 150 |
+
}
|
| 151 |
+
|
| 152 |
+
void def_cfa(int64_t reg, int64_t off) {
|
| 153 |
+
if (LOG) {
|
| 154 |
+
(*out_) << "def_cfa " << reg << " " << off << "\n";
|
| 155 |
+
}
|
| 156 |
+
last_reg_ = reg;
|
| 157 |
+
last_offset_ = off;
|
| 158 |
+
state().cfa = Action::regPlusData(static_cast<int32_t>(reg), off);
|
| 159 |
+
}
|
| 160 |
+
void def_cfa_register(int64_t reg) {
|
| 161 |
+
def_cfa(reg, last_offset_);
|
| 162 |
+
}
|
| 163 |
+
void def_cfa_offset(int64_t off) {
|
| 164 |
+
def_cfa(last_reg_, off);
|
| 165 |
+
}
|
| 166 |
+
|
| 167 |
+
void remember_state() {
|
| 168 |
+
if (LOG) {
|
| 169 |
+
(*out_) << "remember_state\n";
|
| 170 |
+
}
|
| 171 |
+
state_stack_.push_back(state());
|
| 172 |
+
}
|
| 173 |
+
void restore_state() {
|
| 174 |
+
if (LOG) {
|
| 175 |
+
(*out_) << "restore_state\n";
|
| 176 |
+
}
|
| 177 |
+
state_stack_.pop_back();
|
| 178 |
+
}
|
| 179 |
+
|
| 180 |
+
void undefined(int64_t reg) {
|
| 181 |
+
if (LOG) {
|
| 182 |
+
(*out_) << "undefined " << reg << "\n";
|
| 183 |
+
}
|
| 184 |
+
state().registers.at(reg) = Action::undefined();
|
| 185 |
+
}
|
| 186 |
+
void register_(int64_t reg, int64_t rhs_reg) {
|
| 187 |
+
if (LOG) {
|
| 188 |
+
(*out_) << "register " << reg << " " << rhs_reg << "\n";
|
| 189 |
+
}
|
| 190 |
+
state().registers.at(reg) =
|
| 191 |
+
Action::regPlusData(static_cast<int32_t>(reg), 0);
|
| 192 |
+
}
|
| 193 |
+
|
| 194 |
+
TableState& state() {
|
| 195 |
+
return state_stack_.back();
|
| 196 |
+
}
|
| 197 |
+
|
| 198 |
+
void dump(std::ostream& out) {
|
| 199 |
+
out_ = &out;
|
| 200 |
+
out << "FDE(augmentation_string=" << augmentation_string_
|
| 201 |
+
<< ", low_pc=" << (void*)(low_pc_ - load_bias_)
|
| 202 |
+
<< ",high_pc=" << (void*)(high_pc_ - load_bias_)
|
| 203 |
+
<< ",code_alignment_factor=" << code_alignment_factor_
|
| 204 |
+
<< ", data_alignment_factor=" << data_alignment_factor_
|
| 205 |
+
<< ", ra_register_=" << ra_register_ << ")\n";
|
| 206 |
+
readUpTo(high_pc_);
|
| 207 |
+
out_ = &std::cout;
|
| 208 |
+
}
|
| 209 |
+
|
| 210 |
+
TableState readUpTo(uint64_t addr) {
|
| 211 |
+
if (addr < low_pc_ || addr > high_pc_) {
|
| 212 |
+
throw UnwindError("Address not in range");
|
| 213 |
+
}
|
| 214 |
+
if (LOG) {
|
| 215 |
+
// NOLINTNEXTLINE(performance-no-int-to-ptr)
|
| 216 |
+
(*out_) << "readUpTo " << (void*)addr << " for " << library_name_
|
| 217 |
+
<< " at " << (void*)load_bias_ << "\n";
|
| 218 |
+
}
|
| 219 |
+
state_stack_.emplace_back();
|
| 220 |
+
current_pc_ = low_pc_;
|
| 221 |
+
// parse instructions...
|
| 222 |
+
Lexer LC(cie_begin_);
|
| 223 |
+
while (LC.loc() < cie_end_ && current_pc_ <= addr) {
|
| 224 |
+
readInstruction(LC);
|
| 225 |
+
}
|
| 226 |
+
if (current_pc_ > addr) {
|
| 227 |
+
return state();
|
| 228 |
+
}
|
| 229 |
+
|
| 230 |
+
initial_state_ = state_stack_.back();
|
| 231 |
+
|
| 232 |
+
if (LOG) {
|
| 233 |
+
(*out_) << "--\n";
|
| 234 |
+
}
|
| 235 |
+
|
| 236 |
+
Lexer L(fde_begin_);
|
| 237 |
+
while (L.loc() < fde_end_ && current_pc_ <= addr) {
|
| 238 |
+
readInstruction(L);
|
| 239 |
+
}
|
| 240 |
+
// so that we print the full range in debugging
|
| 241 |
+
if (current_pc_ <= addr) {
|
| 242 |
+
advance_raw(addr - current_pc_);
|
| 243 |
+
}
|
| 244 |
+
return state();
|
| 245 |
+
}
|
| 246 |
+
|
| 247 |
+
void dumpAddr2Line() {
|
| 248 |
+
std::cout << "addr2line -f -e " << library_name_ << " "
|
| 249 |
+
<< (void*)(low_pc_ - load_bias_) << "\n";
|
| 250 |
+
}
|
| 251 |
+
|
| 252 |
+
void readInstruction(Lexer& L) {
|
| 253 |
+
uint8_t bc = L.read<uint8_t>();
|
| 254 |
+
auto op = bc >> 6;
|
| 255 |
+
auto lowbits = bc & 0x3F;
|
| 256 |
+
switch (op) {
|
| 257 |
+
case 0x0: {
|
| 258 |
+
switch (lowbits) {
|
| 259 |
+
case DW_CFA_nop: {
|
| 260 |
+
return; // nop
|
| 261 |
+
}
|
| 262 |
+
case DW_CFA_advance_loc1: {
|
| 263 |
+
auto delta = L.read<uint8_t>();
|
| 264 |
+
return advance_loc(delta);
|
| 265 |
+
}
|
| 266 |
+
case DW_CFA_advance_loc2: {
|
| 267 |
+
auto delta = L.read<uint16_t>();
|
| 268 |
+
return advance_loc(delta);
|
| 269 |
+
}
|
| 270 |
+
case DW_CFA_advance_loc4: {
|
| 271 |
+
auto delta = L.read<uint32_t>();
|
| 272 |
+
return advance_loc(delta);
|
| 273 |
+
}
|
| 274 |
+
case DW_CFA_restore_extended: {
|
| 275 |
+
auto reg = L.readULEB128();
|
| 276 |
+
return restore(reg);
|
| 277 |
+
}
|
| 278 |
+
case DW_CFA_undefined: {
|
| 279 |
+
auto reg = L.readULEB128();
|
| 280 |
+
return undefined(reg);
|
| 281 |
+
}
|
| 282 |
+
case DW_CFA_register: {
|
| 283 |
+
auto reg = L.readULEB128();
|
| 284 |
+
auto rhs_reg = L.readULEB128();
|
| 285 |
+
return register_(reg, rhs_reg);
|
| 286 |
+
}
|
| 287 |
+
case DW_CFA_def_cfa: {
|
| 288 |
+
auto reg = L.readULEB128();
|
| 289 |
+
auto off = L.readULEB128();
|
| 290 |
+
return def_cfa(reg, off);
|
| 291 |
+
}
|
| 292 |
+
case DW_CFA_def_cfa_register: {
|
| 293 |
+
auto reg = L.readULEB128();
|
| 294 |
+
return def_cfa_register(reg);
|
| 295 |
+
}
|
| 296 |
+
case DW_CFA_def_cfa_offset: {
|
| 297 |
+
auto off = L.readULEB128();
|
| 298 |
+
return def_cfa_offset(off);
|
| 299 |
+
}
|
| 300 |
+
case DW_CFA_offset_extended_sf: {
|
| 301 |
+
auto reg = L.readULEB128();
|
| 302 |
+
auto off = L.readSLEB128();
|
| 303 |
+
return offset(reg, off);
|
| 304 |
+
}
|
| 305 |
+
case DW_CFA_remember_state: {
|
| 306 |
+
return remember_state();
|
| 307 |
+
}
|
| 308 |
+
case DW_CFA_restore_state: {
|
| 309 |
+
return restore_state();
|
| 310 |
+
}
|
| 311 |
+
case DW_CFA_GNU_args_size: {
|
| 312 |
+
// GNU_args_size, we do not need to know it..
|
| 313 |
+
L.readULEB128();
|
| 314 |
+
return;
|
| 315 |
+
}
|
| 316 |
+
case DW_CFA_expression: {
|
| 317 |
+
auto reg = L.readULEB128();
|
| 318 |
+
auto len = L.readULEB128();
|
| 319 |
+
// NOLINTNEXTLINE(performance-no-int-to-ptr)
|
| 320 |
+
auto end = (void*)((uint64_t)L.loc() + len);
|
| 321 |
+
auto op = L.read<uint8_t>();
|
| 322 |
+
if ((op & 0xF0) == 0x70) { // DW_bregX
|
| 323 |
+
auto rhs_reg = (op & 0xF);
|
| 324 |
+
auto addend = L.readSLEB128();
|
| 325 |
+
if (L.loc() == end) {
|
| 326 |
+
state().registers.at(reg) =
|
| 327 |
+
Action::regPlusDataDeref(rhs_reg, addend);
|
| 328 |
+
return;
|
| 329 |
+
}
|
| 330 |
+
}
|
| 331 |
+
throw UnwindError("Unsupported dwarf expression");
|
| 332 |
+
}
|
| 333 |
+
case DW_CFA_def_cfa_expression: {
|
| 334 |
+
auto len = L.readULEB128();
|
| 335 |
+
// NOLINTNEXTLINE(performance-no-int-to-ptr)
|
| 336 |
+
auto end = (void*)((uint64_t)L.loc() + len);
|
| 337 |
+
auto op = L.read<uint8_t>();
|
| 338 |
+
if ((op & 0xF0) == 0x70) { // DW_bregX
|
| 339 |
+
auto rhs_reg = (op & 0xF);
|
| 340 |
+
auto addend = L.readSLEB128();
|
| 341 |
+
if (L.loc() != end) {
|
| 342 |
+
auto op2 = L.read<uint8_t>();
|
| 343 |
+
if (op2 == DW_OP_deref && L.loc() == end) { // deref
|
| 344 |
+
state().cfa = Action::regPlusDataDeref(rhs_reg, addend);
|
| 345 |
+
return;
|
| 346 |
+
}
|
| 347 |
+
}
|
| 348 |
+
}
|
| 349 |
+
throw UnwindError("Unsupported def_cfa dwarf expression");
|
| 350 |
+
}
|
| 351 |
+
default: {
|
| 352 |
+
std::stringstream ss;
|
| 353 |
+
// NOLINTNEXTLINE(performance-no-int-to-ptr)
|
| 354 |
+
ss << "unknown op code " << (void*)(uint64_t)lowbits;
|
| 355 |
+
throw UnwindError(ss.str());
|
| 356 |
+
}
|
| 357 |
+
}
|
| 358 |
+
}
|
| 359 |
+
case DW_CFA_advance_loc: {
|
| 360 |
+
return advance_loc(lowbits);
|
| 361 |
+
}
|
| 362 |
+
case DW_CFA_offset: {
|
| 363 |
+
auto off = L.readULEB128();
|
| 364 |
+
return offset(lowbits, off);
|
| 365 |
+
}
|
| 366 |
+
case DW_CFA_restore: {
|
| 367 |
+
return restore(lowbits);
|
| 368 |
+
}
|
| 369 |
+
}
|
| 370 |
+
}
|
| 371 |
+
// used for debug printing
|
| 372 |
+
const char* library_name_;
|
| 373 |
+
uint64_t load_bias_;
|
| 374 |
+
|
| 375 |
+
// parsed from the eh_string data structures:
|
| 376 |
+
const char* augmentation_string_ = nullptr;
|
| 377 |
+
int64_t augmentation_length_ = 0;
|
| 378 |
+
int64_t augmentation_length_fde_ = 0;
|
| 379 |
+
|
| 380 |
+
int64_t code_alignment_factor_;
|
| 381 |
+
int64_t data_alignment_factor_;
|
| 382 |
+
void* cie_data_{nullptr};
|
| 383 |
+
|
| 384 |
+
int64_t ra_register_;
|
| 385 |
+
uint8_t lsda_enc = DW_EH_PE_omit;
|
| 386 |
+
uint8_t fde_enc = DW_EH_PE_absptr;
|
| 387 |
+
uint64_t low_pc_ = UINT64_MAX;
|
| 388 |
+
uint64_t high_pc_ = UINT64_MAX;
|
| 389 |
+
|
| 390 |
+
void* cie_begin_;
|
| 391 |
+
void* fde_begin_;
|
| 392 |
+
void* cie_end_;
|
| 393 |
+
void* fde_end_;
|
| 394 |
+
|
| 395 |
+
// state accumulated while parsing instructions
|
| 396 |
+
int64_t last_reg_ = 0;
|
| 397 |
+
int64_t last_offset_ = 0;
|
| 398 |
+
uint64_t current_pc_ = 0;
|
| 399 |
+
|
| 400 |
+
TableState
|
| 401 |
+
initial_state_; // state after the initial instructions, used by restore
|
| 402 |
+
std::vector<TableState> state_stack_;
|
| 403 |
+
|
| 404 |
+
std::ostream* out_ = &std::cout; // for debug dumping
|
| 405 |
+
private:
|
| 406 |
+
bool hasAugmentation(const char* s) {
|
| 407 |
+
return strstr(augmentation_string_, s) != nullptr;
|
| 408 |
+
}
|
| 409 |
+
};
|
| 410 |
+
|
| 411 |
+
} // namespace torch::unwind
|
phivenv/Lib/site-packages/torch/include/torch/csrc/profiler/unwind/lexer.h
ADDED
|
@@ -0,0 +1,159 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#pragma once
|
| 2 |
+
#include <cstdint>
|
| 3 |
+
#include <cstring>
|
| 4 |
+
#include <utility>
|
| 5 |
+
|
| 6 |
+
#include <torch/csrc/profiler/unwind/dwarf_enums.h>
|
| 7 |
+
#include <torch/csrc/profiler/unwind/unwind_error.h>
|
| 8 |
+
|
| 9 |
+
namespace torch::unwind {
|
| 10 |
+
|
| 11 |
+
template <bool checked>
|
| 12 |
+
struct LexerImpl {
|
| 13 |
+
LexerImpl(void* data, void* base = nullptr, void* end = nullptr)
|
| 14 |
+
: next_((const char*)data),
|
| 15 |
+
base_((int64_t)base),
|
| 16 |
+
end_((const char*)end) {}
|
| 17 |
+
|
| 18 |
+
template <typename T>
|
| 19 |
+
T read() {
|
| 20 |
+
T result;
|
| 21 |
+
auto end = next_ + sizeof(T);
|
| 22 |
+
UNWIND_CHECK(
|
| 23 |
+
!checked || end <= end_,
|
| 24 |
+
"read out of bounds {} >= {}",
|
| 25 |
+
(void*)end,
|
| 26 |
+
(void*)end_);
|
| 27 |
+
memcpy(&result, next_, sizeof(T));
|
| 28 |
+
next_ = end;
|
| 29 |
+
return result;
|
| 30 |
+
}
|
| 31 |
+
|
| 32 |
+
// SLEB/ULEB code adapted from LLVM equivalents
|
| 33 |
+
int64_t readSLEB128() {
|
| 34 |
+
int64_t Value = 0;
|
| 35 |
+
unsigned Shift = 0;
|
| 36 |
+
uint8_t Byte = 0;
|
| 37 |
+
do {
|
| 38 |
+
Byte = read<uint8_t>();
|
| 39 |
+
uint64_t Slice = Byte & 0x7f;
|
| 40 |
+
if ((Shift >= 64 && Slice != (Value < 0 ? 0x7f : 0x00)) ||
|
| 41 |
+
(Shift == 63 && Slice != 0 && Slice != 0x7f)) {
|
| 42 |
+
throw UnwindError("sleb128 too big for int64");
|
| 43 |
+
}
|
| 44 |
+
Value |= int64_t(Slice << Shift);
|
| 45 |
+
Shift += 7;
|
| 46 |
+
} while (Byte >= 128);
|
| 47 |
+
// Sign extend negative numbers if needed.
|
| 48 |
+
if (Shift < 64 && (Byte & 0x40)) {
|
| 49 |
+
Value |= int64_t((-1ULL) << Shift);
|
| 50 |
+
}
|
| 51 |
+
return Value;
|
| 52 |
+
}
|
| 53 |
+
|
| 54 |
+
uint64_t readULEB128() {
|
| 55 |
+
uint64_t Value = 0;
|
| 56 |
+
unsigned Shift = 0;
|
| 57 |
+
uint8_t p = 0;
|
| 58 |
+
do {
|
| 59 |
+
p = read<uint8_t>();
|
| 60 |
+
uint64_t Slice = p & 0x7f;
|
| 61 |
+
if ((Shift >= 64 && Slice != 0) || Slice << Shift >> Shift != Slice) {
|
| 62 |
+
throw UnwindError("uleb128 too big for uint64");
|
| 63 |
+
}
|
| 64 |
+
Value += Slice << Shift;
|
| 65 |
+
Shift += 7;
|
| 66 |
+
} while (p >= 128);
|
| 67 |
+
return Value;
|
| 68 |
+
}
|
| 69 |
+
const char* readCString() {
|
| 70 |
+
auto result = next_;
|
| 71 |
+
if (!checked) {
|
| 72 |
+
next_ += strlen(next_) + 1;
|
| 73 |
+
return result;
|
| 74 |
+
}
|
| 75 |
+
while (next_ < end_) {
|
| 76 |
+
if (*next_++ == '\0') {
|
| 77 |
+
return result;
|
| 78 |
+
}
|
| 79 |
+
}
|
| 80 |
+
UNWIND_CHECK(
|
| 81 |
+
false, "string is out of bounds {} >= {}", (void*)next_, (void*)end_);
|
| 82 |
+
}
|
| 83 |
+
int64_t readEncoded(uint8_t enc) {
|
| 84 |
+
int64_t r = 0;
|
| 85 |
+
switch (enc & (~DW_EH_PE_indirect & 0xF0)) {
|
| 86 |
+
case DW_EH_PE_absptr:
|
| 87 |
+
break;
|
| 88 |
+
case DW_EH_PE_pcrel:
|
| 89 |
+
r = (int64_t)next_;
|
| 90 |
+
break;
|
| 91 |
+
case DW_EH_PE_datarel:
|
| 92 |
+
r = base_;
|
| 93 |
+
break;
|
| 94 |
+
default:
|
| 95 |
+
throw UnwindError("unknown encoding");
|
| 96 |
+
}
|
| 97 |
+
return r + readEncodedValue(enc);
|
| 98 |
+
}
|
| 99 |
+
int64_t readEncodedOr(uint8_t enc, int64_t orelse) {
|
| 100 |
+
if (enc == DW_EH_PE_omit) {
|
| 101 |
+
return orelse;
|
| 102 |
+
}
|
| 103 |
+
return readEncoded(enc);
|
| 104 |
+
}
|
| 105 |
+
|
| 106 |
+
int64_t read4or8Length() {
|
| 107 |
+
return readSectionLength().first;
|
| 108 |
+
}
|
| 109 |
+
|
| 110 |
+
std::pair<int64_t, bool> readSectionLength() {
|
| 111 |
+
int64_t length = read<uint32_t>();
|
| 112 |
+
if (length == 0xFFFFFFFF) {
|
| 113 |
+
return std::make_pair(read<int64_t>(), true);
|
| 114 |
+
}
|
| 115 |
+
return std::make_pair(length, false);
|
| 116 |
+
}
|
| 117 |
+
|
| 118 |
+
void* loc() const {
|
| 119 |
+
return (void*)next_;
|
| 120 |
+
}
|
| 121 |
+
LexerImpl& skip(size_t bytes) {
|
| 122 |
+
next_ += bytes;
|
| 123 |
+
return *this;
|
| 124 |
+
}
|
| 125 |
+
|
| 126 |
+
int64_t readEncodedValue(uint8_t enc) {
|
| 127 |
+
switch (enc & 0xF) {
|
| 128 |
+
case DW_EH_PE_udata2:
|
| 129 |
+
return read<uint16_t>();
|
| 130 |
+
case DW_EH_PE_sdata2:
|
| 131 |
+
return read<int16_t>();
|
| 132 |
+
case DW_EH_PE_udata4:
|
| 133 |
+
return read<uint32_t>();
|
| 134 |
+
case DW_EH_PE_sdata4:
|
| 135 |
+
return read<int32_t>();
|
| 136 |
+
case DW_EH_PE_udata8:
|
| 137 |
+
return read<uint64_t>();
|
| 138 |
+
case DW_EH_PE_sdata8:
|
| 139 |
+
return read<int64_t>();
|
| 140 |
+
case DW_EH_PE_uleb128:
|
| 141 |
+
return readULEB128();
|
| 142 |
+
case DW_EH_PE_sleb128:
|
| 143 |
+
return readSLEB128();
|
| 144 |
+
default:
|
| 145 |
+
throw UnwindError("not implemented");
|
| 146 |
+
}
|
| 147 |
+
}
|
| 148 |
+
|
| 149 |
+
private:
|
| 150 |
+
const char* next_;
|
| 151 |
+
int64_t base_;
|
| 152 |
+
const char* end_;
|
| 153 |
+
};
|
| 154 |
+
|
| 155 |
+
// using Lexer = LexerImpl<false>;
|
| 156 |
+
using CheckedLexer = LexerImpl<true>;
|
| 157 |
+
using Lexer = LexerImpl<false>;
|
| 158 |
+
|
| 159 |
+
} // namespace torch::unwind
|
phivenv/Lib/site-packages/torch/include/torch/csrc/profiler/unwind/line_number_program.h
ADDED
|
@@ -0,0 +1,328 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#include <c10/util/irange.h>
|
| 2 |
+
#include <torch/csrc/profiler/unwind/debug_info.h>
|
| 3 |
+
#include <torch/csrc/profiler/unwind/dwarf_enums.h>
|
| 4 |
+
#include <torch/csrc/profiler/unwind/dwarf_symbolize_enums.h>
|
| 5 |
+
#include <torch/csrc/profiler/unwind/lexer.h>
|
| 6 |
+
#include <torch/csrc/profiler/unwind/sections.h>
|
| 7 |
+
#include <torch/csrc/profiler/unwind/unwind_error.h>
|
| 8 |
+
#include <tuple>
|
| 9 |
+
|
| 10 |
+
namespace torch::unwind {
|
| 11 |
+
|
| 12 |
+
struct LineNumberProgram {
|
| 13 |
+
LineNumberProgram(Sections& s, uint64_t offset) : s_(s), offset_(offset) {}
|
| 14 |
+
|
| 15 |
+
uint64_t offset() {
|
| 16 |
+
return offset_;
|
| 17 |
+
}
|
| 18 |
+
void parse() {
|
| 19 |
+
if (parsed_) {
|
| 20 |
+
return;
|
| 21 |
+
}
|
| 22 |
+
parsed_ = true;
|
| 23 |
+
CheckedLexer L = s_.debug_line.lexer(offset_);
|
| 24 |
+
std::tie(length_, is_64bit_) = L.readSectionLength();
|
| 25 |
+
program_end_ = (char*)L.loc() + length_;
|
| 26 |
+
auto version = L.read<uint16_t>();
|
| 27 |
+
UNWIND_CHECK(
|
| 28 |
+
version == 5 || version == 4,
|
| 29 |
+
"expected version 4 or 5 but found {}",
|
| 30 |
+
version);
|
| 31 |
+
if (version == 5) {
|
| 32 |
+
auto address_size = L.read<uint8_t>();
|
| 33 |
+
UNWIND_CHECK(
|
| 34 |
+
address_size == 8,
|
| 35 |
+
"expected 64-bit dwarf but found address size {}",
|
| 36 |
+
address_size);
|
| 37 |
+
segment_selector_size_ = L.read<uint8_t>();
|
| 38 |
+
}
|
| 39 |
+
header_length_ = is_64bit_ ? L.read<uint64_t>() : L.read<uint32_t>();
|
| 40 |
+
program_ = L;
|
| 41 |
+
program_.skip(int64_t(header_length_));
|
| 42 |
+
minimum_instruction_length_ = L.read<uint8_t>();
|
| 43 |
+
maximum_operations_per_instruction_ = L.read<uint8_t>();
|
| 44 |
+
default_is_stmt_ = L.read<uint8_t>();
|
| 45 |
+
line_base_ = L.read<int8_t>();
|
| 46 |
+
line_range_ = L.read<uint8_t>();
|
| 47 |
+
opcode_base_ = L.read<uint8_t>();
|
| 48 |
+
UNWIND_CHECK(line_range_ != 0, "line_range_ must be non-zero");
|
| 49 |
+
standard_opcode_lengths_.resize(opcode_base_);
|
| 50 |
+
for (size_t i = 1; i < opcode_base_; i++) {
|
| 51 |
+
standard_opcode_lengths_[i] = L.read<uint8_t>();
|
| 52 |
+
}
|
| 53 |
+
// fmt::print("{:x} {:x} {} {} {} {} {}\n", offset_, header_length_,
|
| 54 |
+
// minimum_instruction_length_, maximum_operations_per_instruction_,
|
| 55 |
+
// line_base_, line_range_, opcode_base_);
|
| 56 |
+
uint8_t directory_entry_format_count = L.read<uint8_t>();
|
| 57 |
+
|
| 58 |
+
if (version == 5) {
|
| 59 |
+
struct Member {
|
| 60 |
+
uint64_t content_type;
|
| 61 |
+
uint64_t form;
|
| 62 |
+
};
|
| 63 |
+
std::vector<Member> directory_members;
|
| 64 |
+
directory_members.reserve(directory_entry_format_count);
|
| 65 |
+
for (size_t i = 0; i < directory_entry_format_count; i++) {
|
| 66 |
+
directory_members.push_back({L.readULEB128(), L.readULEB128()});
|
| 67 |
+
}
|
| 68 |
+
uint64_t directories_count = L.readULEB128();
|
| 69 |
+
for (size_t i = 0; i < directories_count; i++) {
|
| 70 |
+
for (auto& member : directory_members) {
|
| 71 |
+
switch (member.content_type) {
|
| 72 |
+
case DW_LNCT_path: {
|
| 73 |
+
include_directories_.emplace_back(
|
| 74 |
+
s_.readString(L, member.form, is_64bit_));
|
| 75 |
+
} break;
|
| 76 |
+
default: {
|
| 77 |
+
skipForm(L, member.form);
|
| 78 |
+
} break;
|
| 79 |
+
}
|
| 80 |
+
}
|
| 81 |
+
}
|
| 82 |
+
|
| 83 |
+
for (auto i : c10::irange(directories_count)) {
|
| 84 |
+
(void)i;
|
| 85 |
+
LOG_INFO("{} {}\n", i, include_directories_[i]);
|
| 86 |
+
}
|
| 87 |
+
auto file_name_entry_format_count = L.read<uint8_t>();
|
| 88 |
+
std::vector<Member> file_members;
|
| 89 |
+
file_members.reserve(file_name_entry_format_count);
|
| 90 |
+
for (size_t i = 0; i < file_name_entry_format_count; i++) {
|
| 91 |
+
file_members.push_back({L.readULEB128(), L.readULEB128()});
|
| 92 |
+
}
|
| 93 |
+
auto files_count = L.readULEB128();
|
| 94 |
+
for (size_t i = 0; i < files_count; i++) {
|
| 95 |
+
for (auto& member : file_members) {
|
| 96 |
+
switch (member.content_type) {
|
| 97 |
+
case DW_LNCT_path: {
|
| 98 |
+
file_names_.emplace_back(
|
| 99 |
+
s_.readString(L, member.form, is_64bit_));
|
| 100 |
+
} break;
|
| 101 |
+
case DW_LNCT_directory_index: {
|
| 102 |
+
file_directory_index_.emplace_back(readData(L, member.form));
|
| 103 |
+
UNWIND_CHECK(
|
| 104 |
+
file_directory_index_.back() < include_directories_.size(),
|
| 105 |
+
"directory index out of range");
|
| 106 |
+
} break;
|
| 107 |
+
default: {
|
| 108 |
+
skipForm(L, member.form);
|
| 109 |
+
} break;
|
| 110 |
+
}
|
| 111 |
+
}
|
| 112 |
+
}
|
| 113 |
+
for (auto i : c10::irange(files_count)) {
|
| 114 |
+
(void)i;
|
| 115 |
+
LOG_INFO("{} {} {}\n", i, file_names_[i], file_directory_index_[i]);
|
| 116 |
+
}
|
| 117 |
+
} else {
|
| 118 |
+
include_directories_.emplace_back(""); // implicit cwd
|
| 119 |
+
while (true) {
|
| 120 |
+
auto str = L.readCString();
|
| 121 |
+
if (*str == '\0') {
|
| 122 |
+
break;
|
| 123 |
+
}
|
| 124 |
+
include_directories_.emplace_back(str);
|
| 125 |
+
}
|
| 126 |
+
file_names_.emplace_back("");
|
| 127 |
+
file_directory_index_.emplace_back(0);
|
| 128 |
+
while (true) {
|
| 129 |
+
auto str = L.readCString();
|
| 130 |
+
if (*str == '\0') {
|
| 131 |
+
break;
|
| 132 |
+
}
|
| 133 |
+
auto directory_index = L.readULEB128();
|
| 134 |
+
L.readULEB128(); // mod_time
|
| 135 |
+
L.readULEB128(); // file_length
|
| 136 |
+
file_names_.emplace_back(str);
|
| 137 |
+
file_directory_index_.push_back(directory_index);
|
| 138 |
+
}
|
| 139 |
+
}
|
| 140 |
+
UNWIND_CHECK(
|
| 141 |
+
maximum_operations_per_instruction_ == 1,
|
| 142 |
+
"maximum_operations_per_instruction_ must be 1");
|
| 143 |
+
UNWIND_CHECK(
|
| 144 |
+
minimum_instruction_length_ == 1,
|
| 145 |
+
"minimum_instruction_length_ must be 1");
|
| 146 |
+
readProgram();
|
| 147 |
+
}
|
| 148 |
+
struct Entry {
|
| 149 |
+
uint32_t file = 1;
|
| 150 |
+
int64_t line = 1;
|
| 151 |
+
};
|
| 152 |
+
std::optional<Entry> find(uint64_t address) {
|
| 153 |
+
auto e = program_index_.find(address);
|
| 154 |
+
if (!e) {
|
| 155 |
+
return std::nullopt;
|
| 156 |
+
}
|
| 157 |
+
return all_programs_.at(*e).find(address);
|
| 158 |
+
}
|
| 159 |
+
std::string filename(uint64_t index) {
|
| 160 |
+
return fmt::format(
|
| 161 |
+
"{}/{}",
|
| 162 |
+
include_directories_.at(file_directory_index_.at(index)),
|
| 163 |
+
file_names_.at(index));
|
| 164 |
+
}
|
| 165 |
+
|
| 166 |
+
private:
|
| 167 |
+
void skipForm(CheckedLexer& L, uint64_t form) {
|
| 168 |
+
auto sz = formSize(form, is_64bit_ ? 8 : 4);
|
| 169 |
+
UNWIND_CHECK(sz, "unsupported form {}", form);
|
| 170 |
+
L.skip(int64_t(*sz));
|
| 171 |
+
}
|
| 172 |
+
|
| 173 |
+
uint64_t readData(CheckedLexer& L, uint64_t encoding) {
|
| 174 |
+
switch (encoding) {
|
| 175 |
+
case DW_FORM_data1:
|
| 176 |
+
return L.read<uint8_t>();
|
| 177 |
+
case DW_FORM_data2:
|
| 178 |
+
return L.read<uint16_t>();
|
| 179 |
+
case DW_FORM_data4:
|
| 180 |
+
return L.read<uint32_t>();
|
| 181 |
+
case DW_FORM_data8:
|
| 182 |
+
return L.read<uint64_t>();
|
| 183 |
+
case DW_FORM_udata:
|
| 184 |
+
return L.readULEB128();
|
| 185 |
+
default:
|
| 186 |
+
UNWIND_CHECK(false, "unsupported data encoding {}", encoding);
|
| 187 |
+
}
|
| 188 |
+
}
|
| 189 |
+
|
| 190 |
+
void produceEntry() {
|
| 191 |
+
if (shadow_) {
|
| 192 |
+
return;
|
| 193 |
+
}
|
| 194 |
+
if (ranges_.size() == 1) {
|
| 195 |
+
start_address_ = address_;
|
| 196 |
+
}
|
| 197 |
+
PRINT_LINE_TABLE(
|
| 198 |
+
"{:x}\t{}\t{}\n", address_, filename(entry_.file), entry_.line);
|
| 199 |
+
UNWIND_CHECK(
|
| 200 |
+
entry_.file < file_names_.size(),
|
| 201 |
+
"file index {} > {} entries",
|
| 202 |
+
entry_.file,
|
| 203 |
+
file_names_.size());
|
| 204 |
+
ranges_.add(address_, entry_, true);
|
| 205 |
+
}
|
| 206 |
+
void endSequence() {
|
| 207 |
+
if (shadow_) {
|
| 208 |
+
return;
|
| 209 |
+
}
|
| 210 |
+
PRINT_LINE_TABLE(
|
| 211 |
+
"{:x}\tEND\n", address_, filename(entry_.file), entry_.line);
|
| 212 |
+
program_index_.add(start_address_, all_programs_.size(), false);
|
| 213 |
+
program_index_.add(address_, std::nullopt, false);
|
| 214 |
+
all_programs_.emplace_back(std::move(ranges_));
|
| 215 |
+
ranges_ = RangeTable<Entry>();
|
| 216 |
+
}
|
| 217 |
+
void readProgram() {
|
| 218 |
+
while (program_.loc() < program_end_) {
|
| 219 |
+
PRINT_INST("{:x}: ", (char*)program_.loc() - (s_.debug_line.data));
|
| 220 |
+
uint8_t op = program_.read<uint8_t>();
|
| 221 |
+
if (op >= opcode_base_) {
|
| 222 |
+
auto op2 = int64_t(op - opcode_base_);
|
| 223 |
+
address_ += op2 / line_range_;
|
| 224 |
+
entry_.line += line_base_ + (op2 % line_range_);
|
| 225 |
+
PRINT_INST(
|
| 226 |
+
"address += {}, line += {}\n",
|
| 227 |
+
op2 / line_range_,
|
| 228 |
+
line_base_ + (op2 % line_range_));
|
| 229 |
+
produceEntry();
|
| 230 |
+
} else {
|
| 231 |
+
switch (op) {
|
| 232 |
+
case DW_LNS_extended_op: {
|
| 233 |
+
auto len = program_.readULEB128();
|
| 234 |
+
auto extended_op = program_.read<uint8_t>();
|
| 235 |
+
switch (extended_op) {
|
| 236 |
+
case DW_LNE_end_sequence: {
|
| 237 |
+
PRINT_INST("end_sequence\n");
|
| 238 |
+
endSequence();
|
| 239 |
+
entry_ = Entry{};
|
| 240 |
+
} break;
|
| 241 |
+
case DW_LNE_set_address: {
|
| 242 |
+
address_ = program_.read<uint64_t>();
|
| 243 |
+
if (!shadow_) {
|
| 244 |
+
PRINT_INST(
|
| 245 |
+
"set address {:x} {:x} {:x}\n",
|
| 246 |
+
address_,
|
| 247 |
+
min_address_,
|
| 248 |
+
max_address_);
|
| 249 |
+
}
|
| 250 |
+
shadow_ = address_ == 0;
|
| 251 |
+
} break;
|
| 252 |
+
default: {
|
| 253 |
+
PRINT_INST("skip extended op {}\n", extended_op);
|
| 254 |
+
program_.skip(int64_t(len - 1));
|
| 255 |
+
} break;
|
| 256 |
+
}
|
| 257 |
+
} break;
|
| 258 |
+
case DW_LNS_copy: {
|
| 259 |
+
PRINT_INST("copy\n");
|
| 260 |
+
produceEntry();
|
| 261 |
+
} break;
|
| 262 |
+
case DW_LNS_advance_pc: {
|
| 263 |
+
PRINT_INST("advance pc\n");
|
| 264 |
+
address_ += program_.readULEB128();
|
| 265 |
+
} break;
|
| 266 |
+
case DW_LNS_advance_line: {
|
| 267 |
+
entry_.line += program_.readSLEB128();
|
| 268 |
+
PRINT_INST("advance line {}\n", entry_.line);
|
| 269 |
+
|
| 270 |
+
} break;
|
| 271 |
+
case DW_LNS_set_file: {
|
| 272 |
+
PRINT_INST("set file\n");
|
| 273 |
+
entry_.file = program_.readULEB128();
|
| 274 |
+
} break;
|
| 275 |
+
case DW_LNS_const_add_pc: {
|
| 276 |
+
PRINT_INST("const add pc\n");
|
| 277 |
+
address_ += (255 - opcode_base_) / line_range_;
|
| 278 |
+
} break;
|
| 279 |
+
case DW_LNS_fixed_advance_pc: {
|
| 280 |
+
PRINT_INST("fixed advance pc\n");
|
| 281 |
+
address_ += program_.read<uint16_t>();
|
| 282 |
+
} break;
|
| 283 |
+
default: {
|
| 284 |
+
PRINT_INST("other {}\n", op);
|
| 285 |
+
auto n = standard_opcode_lengths_[op];
|
| 286 |
+
for (int i = 0; i < n; ++i) {
|
| 287 |
+
program_.readULEB128();
|
| 288 |
+
}
|
| 289 |
+
} break;
|
| 290 |
+
}
|
| 291 |
+
}
|
| 292 |
+
}
|
| 293 |
+
PRINT_INST(
|
| 294 |
+
"{:x}: end {:x}\n",
|
| 295 |
+
((char*)program_.loc() - s_.debug_line.data),
|
| 296 |
+
program_end_ - s_.debug_line.data);
|
| 297 |
+
}
|
| 298 |
+
|
| 299 |
+
uint64_t address_ = 0;
|
| 300 |
+
bool shadow_ = false;
|
| 301 |
+
bool parsed_ = false;
|
| 302 |
+
Entry entry_ = {};
|
| 303 |
+
std::vector<std::string> include_directories_;
|
| 304 |
+
std::vector<std::string> file_names_;
|
| 305 |
+
std::vector<uint64_t> file_directory_index_;
|
| 306 |
+
uint8_t segment_selector_size_ = 0;
|
| 307 |
+
uint8_t minimum_instruction_length_ = 0;
|
| 308 |
+
uint8_t maximum_operations_per_instruction_ = 0;
|
| 309 |
+
int8_t line_base_ = 0;
|
| 310 |
+
uint8_t line_range_ = 0;
|
| 311 |
+
uint8_t opcode_base_ = 0;
|
| 312 |
+
bool default_is_stmt_ = false;
|
| 313 |
+
CheckedLexer program_ = {nullptr};
|
| 314 |
+
char* program_end_ = nullptr;
|
| 315 |
+
uint64_t header_length_ = 0;
|
| 316 |
+
uint64_t length_ = 0;
|
| 317 |
+
bool is_64bit_ = false;
|
| 318 |
+
std::vector<uint8_t> standard_opcode_lengths_;
|
| 319 |
+
// NOLINTNEXTLINE(cppcoreguidelines-avoid-const-or-ref-data-members)
|
| 320 |
+
Sections& s_;
|
| 321 |
+
uint64_t offset_;
|
| 322 |
+
uint64_t start_address_ = 0;
|
| 323 |
+
RangeTable<uint64_t> program_index_;
|
| 324 |
+
std::vector<RangeTable<Entry>> all_programs_;
|
| 325 |
+
RangeTable<Entry> ranges_;
|
| 326 |
+
};
|
| 327 |
+
|
| 328 |
+
} // namespace torch::unwind
|
phivenv/Lib/site-packages/torch/include/torch/csrc/profiler/unwind/mem_file.h
ADDED
|
@@ -0,0 +1,159 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
| 2 |
+
// All rights reserved.
|
| 3 |
+
//
|
| 4 |
+
// This source code is licensed under the BSD-style license found in the
|
| 5 |
+
// LICENSE file in the root directory of this source tree.
|
| 6 |
+
|
| 7 |
+
#pragma once
|
| 8 |
+
|
| 9 |
+
#include <c10/util/error.h>
|
| 10 |
+
#include <elf.h>
|
| 11 |
+
#include <fcntl.h>
|
| 12 |
+
#include <fmt/format.h>
|
| 13 |
+
#include <sys/mman.h>
|
| 14 |
+
#include <sys/stat.h>
|
| 15 |
+
#include <torch/csrc/profiler/unwind/lexer.h>
|
| 16 |
+
#include <torch/csrc/profiler/unwind/unwind_error.h>
|
| 17 |
+
#include <unistd.h>
|
| 18 |
+
#include <cerrno>
|
| 19 |
+
#include <cstdio>
|
| 20 |
+
#include <cstring>
|
| 21 |
+
|
| 22 |
+
namespace torch::unwind {
|
| 23 |
+
|
| 24 |
+
struct Section {
|
| 25 |
+
char* data = nullptr;
|
| 26 |
+
size_t size = 0;
|
| 27 |
+
const char* string(size_t offset) {
|
| 28 |
+
return lexer(offset).readCString();
|
| 29 |
+
}
|
| 30 |
+
CheckedLexer lexer(size_t offset) {
|
| 31 |
+
return CheckedLexer(data + offset, data, data + size);
|
| 32 |
+
}
|
| 33 |
+
};
|
| 34 |
+
|
| 35 |
+
/// Memory maps a file into the address space read-only, and manages the
|
| 36 |
+
/// lifetime of the mapping. Here are a few use cases:
|
| 37 |
+
/// 1. Used in the loader to read in initial image, and to inspect
|
| 38 |
+
// ELF files for dependencies before calling dlopen.
|
| 39 |
+
///
|
| 40 |
+
/// 2. Used in unity to load the elf file.
|
| 41 |
+
struct MemFile {
|
| 42 |
+
explicit MemFile(const char* filename_)
|
| 43 |
+
: fd_(open(filename_, O_RDONLY)), name_(filename_) {
|
| 44 |
+
UNWIND_CHECK(
|
| 45 |
+
fd_ != -1,
|
| 46 |
+
"failed to open {}: {}",
|
| 47 |
+
filename_,
|
| 48 |
+
c10::utils::str_error(errno));
|
| 49 |
+
struct stat s{};
|
| 50 |
+
if (-1 == fstat(fd_, &s)) {
|
| 51 |
+
close(fd_); // destructors don't run during exceptions
|
| 52 |
+
UNWIND_CHECK(
|
| 53 |
+
false,
|
| 54 |
+
"failed to stat {}: {}",
|
| 55 |
+
filename_,
|
| 56 |
+
c10::utils::str_error(errno));
|
| 57 |
+
}
|
| 58 |
+
n_bytes_ = s.st_size;
|
| 59 |
+
UNWIND_CHECK(
|
| 60 |
+
n_bytes_ > sizeof(Elf64_Ehdr), "empty shared library: {}", filename_);
|
| 61 |
+
mem_ = (char*)mmap(nullptr, n_bytes_, PROT_READ, MAP_SHARED, fd_, 0);
|
| 62 |
+
if (MAP_FAILED == mem_) {
|
| 63 |
+
close(fd_);
|
| 64 |
+
UNWIND_CHECK(
|
| 65 |
+
false,
|
| 66 |
+
"failed to mmap {}: {}",
|
| 67 |
+
filename_,
|
| 68 |
+
c10::utils::str_error(errno));
|
| 69 |
+
}
|
| 70 |
+
ehdr_ = (Elf64_Ehdr*)mem_;
|
| 71 |
+
#define ELF_CHECK(cond) UNWIND_CHECK(cond, "not an ELF file: {}", filename_)
|
| 72 |
+
ELF_CHECK(ehdr_->e_ident[EI_MAG0] == ELFMAG0);
|
| 73 |
+
ELF_CHECK(ehdr_->e_ident[EI_MAG1] == ELFMAG1);
|
| 74 |
+
ELF_CHECK(ehdr_->e_ident[EI_MAG2] == ELFMAG2);
|
| 75 |
+
ELF_CHECK(ehdr_->e_ident[EI_MAG3] == ELFMAG3);
|
| 76 |
+
ELF_CHECK(ehdr_->e_ident[EI_CLASS] == ELFCLASS64);
|
| 77 |
+
ELF_CHECK(ehdr_->e_ident[EI_VERSION] == EV_CURRENT);
|
| 78 |
+
ELF_CHECK(ehdr_->e_version == EV_CURRENT);
|
| 79 |
+
ELF_CHECK(ehdr_->e_machine == EM_X86_64);
|
| 80 |
+
#undef ELF_CHECK
|
| 81 |
+
UNWIND_CHECK(
|
| 82 |
+
ehdr_->e_shoff + sizeof(Elf64_Shdr) * ehdr_->e_shnum <= n_bytes_,
|
| 83 |
+
"invalid section header table {} {} {}",
|
| 84 |
+
ehdr_->e_shoff + sizeof(Elf64_Shdr) * ehdr_->e_shnum,
|
| 85 |
+
n_bytes_,
|
| 86 |
+
ehdr_->e_shnum);
|
| 87 |
+
shdr_ = (Elf64_Shdr*)(mem_ + ehdr_->e_shoff);
|
| 88 |
+
UNWIND_CHECK(
|
| 89 |
+
ehdr_->e_shstrndx < ehdr_->e_shnum, "invalid strtab section offset");
|
| 90 |
+
auto& strtab_hdr = shdr_[ehdr_->e_shstrndx];
|
| 91 |
+
strtab_ = getSection(strtab_hdr);
|
| 92 |
+
}
|
| 93 |
+
|
| 94 |
+
MemFile(const MemFile&) = delete;
|
| 95 |
+
MemFile(MemFile&&) = delete;
|
| 96 |
+
MemFile& operator=(const MemFile&) = delete;
|
| 97 |
+
MemFile& operator=(MemFile&&) = delete;
|
| 98 |
+
[[nodiscard]] const char* data() const {
|
| 99 |
+
return (const char*)mem_;
|
| 100 |
+
}
|
| 101 |
+
|
| 102 |
+
/// Returns whether or not the file descriptor
|
| 103 |
+
/// of the underlying file is valid.
|
| 104 |
+
int valid() {
|
| 105 |
+
return fcntl(fd_, F_GETFD) != -1 || errno != EBADF;
|
| 106 |
+
}
|
| 107 |
+
|
| 108 |
+
~MemFile() {
|
| 109 |
+
if (mem_) {
|
| 110 |
+
munmap((void*)mem_, n_bytes_);
|
| 111 |
+
}
|
| 112 |
+
if (fd_ >= 0) {
|
| 113 |
+
close(fd_);
|
| 114 |
+
}
|
| 115 |
+
}
|
| 116 |
+
|
| 117 |
+
/// Returns the size of the underlying file defined by the `MemFile`
|
| 118 |
+
size_t size() {
|
| 119 |
+
return n_bytes_;
|
| 120 |
+
}
|
| 121 |
+
[[nodiscard]] int fd() const {
|
| 122 |
+
return fd_;
|
| 123 |
+
}
|
| 124 |
+
|
| 125 |
+
Section getSection(const Elf64_Shdr& shdr) {
|
| 126 |
+
UNWIND_CHECK(shdr.sh_offset + shdr.sh_size <= n_bytes_, "invalid section");
|
| 127 |
+
return Section{mem_ + shdr.sh_offset, shdr.sh_size};
|
| 128 |
+
}
|
| 129 |
+
|
| 130 |
+
Section getSection(const char* name, bool optional) {
|
| 131 |
+
for (int i = 0; i < ehdr_->e_shnum; i++) {
|
| 132 |
+
if (strcmp(strtab_.string(shdr_[i].sh_name), name) == 0) {
|
| 133 |
+
return getSection(shdr_[i]);
|
| 134 |
+
}
|
| 135 |
+
}
|
| 136 |
+
UNWIND_CHECK(optional, "{} has no section {}", name_, name);
|
| 137 |
+
return Section{nullptr, 0};
|
| 138 |
+
}
|
| 139 |
+
|
| 140 |
+
Section strtab() {
|
| 141 |
+
return strtab_;
|
| 142 |
+
}
|
| 143 |
+
|
| 144 |
+
private:
|
| 145 |
+
template <typename T>
|
| 146 |
+
T* load(size_t offset) {
|
| 147 |
+
UNWIND_CHECK(offset < n_bytes_, "out of range");
|
| 148 |
+
return (T*)(mem_ + offset);
|
| 149 |
+
}
|
| 150 |
+
int fd_;
|
| 151 |
+
char* mem_{nullptr};
|
| 152 |
+
size_t n_bytes_{0};
|
| 153 |
+
std::string name_;
|
| 154 |
+
Elf64_Ehdr* ehdr_;
|
| 155 |
+
Elf64_Shdr* shdr_;
|
| 156 |
+
Section strtab_ = {nullptr, 0};
|
| 157 |
+
};
|
| 158 |
+
|
| 159 |
+
} // namespace torch::unwind
|
phivenv/Lib/site-packages/torch/include/torch/csrc/profiler/unwind/range_table.h
ADDED
|
@@ -0,0 +1,73 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#pragma once
|
| 2 |
+
#include <torch/csrc/profiler/unwind/unwind_error.h>
|
| 3 |
+
#include <algorithm>
|
| 4 |
+
#include <memory>
|
| 5 |
+
#include <optional>
|
| 6 |
+
#include <vector>
|
| 7 |
+
|
| 8 |
+
namespace torch::unwind {
|
| 9 |
+
template <typename T>
|
| 10 |
+
struct RangeTable {
|
| 11 |
+
RangeTable() {
|
| 12 |
+
// guarantee that lower_bound[-1] is always valid
|
| 13 |
+
addresses_.push_back(0);
|
| 14 |
+
payloads_.emplace_back(std::nullopt);
|
| 15 |
+
}
|
| 16 |
+
void add(uint64_t address, std::optional<T> payload, bool sorted) {
|
| 17 |
+
if (addresses_.back() > address) {
|
| 18 |
+
UNWIND_CHECK(!sorted, "expected addresses to be sorted");
|
| 19 |
+
sorted_ = false;
|
| 20 |
+
}
|
| 21 |
+
addresses_.push_back(address);
|
| 22 |
+
payloads_.emplace_back(std::move(payload));
|
| 23 |
+
}
|
| 24 |
+
std::optional<T> find(uint64_t address) {
|
| 25 |
+
maybeSort();
|
| 26 |
+
auto it = std::upper_bound(addresses_.begin(), addresses_.end(), address);
|
| 27 |
+
return payloads_.at(it - addresses_.begin() - 1);
|
| 28 |
+
}
|
| 29 |
+
void dump() {
|
| 30 |
+
for (size_t i = 0; i < addresses_.size(); i++) {
|
| 31 |
+
fmt::print("{} {:x}: {}\n", i, addresses_[i], payloads_[i] ? "" : "END");
|
| 32 |
+
}
|
| 33 |
+
}
|
| 34 |
+
size_t size() const {
|
| 35 |
+
return addresses_.size();
|
| 36 |
+
}
|
| 37 |
+
uint64_t back() {
|
| 38 |
+
maybeSort();
|
| 39 |
+
return addresses_.back();
|
| 40 |
+
}
|
| 41 |
+
|
| 42 |
+
private:
|
| 43 |
+
void maybeSort() {
|
| 44 |
+
if (sorted_) {
|
| 45 |
+
return;
|
| 46 |
+
}
|
| 47 |
+
std::vector<uint64_t> indices;
|
| 48 |
+
indices.reserve(addresses_.size());
|
| 49 |
+
for (size_t i = 0; i < addresses_.size(); i++) {
|
| 50 |
+
indices.push_back(i);
|
| 51 |
+
}
|
| 52 |
+
std::sort(indices.begin(), indices.end(), [&](uint64_t a, uint64_t b) {
|
| 53 |
+
return addresses_[a] < addresses_[b] ||
|
| 54 |
+
(addresses_[a] == addresses_[b] &&
|
| 55 |
+
bool(payloads_[a]) < bool(payloads_[b]));
|
| 56 |
+
});
|
| 57 |
+
std::vector<uint64_t> addresses;
|
| 58 |
+
std::vector<std::optional<T>> payloads;
|
| 59 |
+
addresses.reserve(addresses_.size());
|
| 60 |
+
payloads.reserve(addresses_.size());
|
| 61 |
+
for (auto i : indices) {
|
| 62 |
+
addresses.push_back(addresses_[i]);
|
| 63 |
+
payloads.push_back(payloads_[i]);
|
| 64 |
+
}
|
| 65 |
+
addresses_ = std::move(addresses);
|
| 66 |
+
payloads_ = std::move(payloads);
|
| 67 |
+
sorted_ = true;
|
| 68 |
+
}
|
| 69 |
+
bool sorted_ = true;
|
| 70 |
+
std::vector<uint64_t> addresses_;
|
| 71 |
+
std::vector<std::optional<T>> payloads_;
|
| 72 |
+
};
|
| 73 |
+
} // namespace torch::unwind
|
phivenv/Lib/site-packages/torch/include/torch/csrc/profiler/unwind/sections.h
ADDED
|
@@ -0,0 +1,120 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#pragma once
|
| 2 |
+
#include <cxxabi.h>
|
| 3 |
+
#include <elf.h>
|
| 4 |
+
#include <torch/csrc/profiler/unwind/dwarf_enums.h>
|
| 5 |
+
#include <torch/csrc/profiler/unwind/dwarf_symbolize_enums.h>
|
| 6 |
+
#include <torch/csrc/profiler/unwind/mem_file.h>
|
| 7 |
+
#include <torch/csrc/profiler/unwind/range_table.h>
|
| 8 |
+
#include <torch/csrc/profiler/unwind/unwind_error.h>
|
| 9 |
+
#include <cstdint>
|
| 10 |
+
|
| 11 |
+
namespace torch::unwind {
|
| 12 |
+
|
| 13 |
+
static std::string demangle(const std::string& mangled_name) {
|
| 14 |
+
int status = 0;
|
| 15 |
+
char* realname =
|
| 16 |
+
abi::__cxa_demangle(mangled_name.c_str(), nullptr, nullptr, &status);
|
| 17 |
+
if (status == 0) {
|
| 18 |
+
std::string demangled_name(realname);
|
| 19 |
+
// NOLINTNEXTLINE(cppcoreguidelines-no-malloc)
|
| 20 |
+
free(realname);
|
| 21 |
+
return demangled_name;
|
| 22 |
+
} else {
|
| 23 |
+
return mangled_name;
|
| 24 |
+
}
|
| 25 |
+
}
|
| 26 |
+
|
| 27 |
+
struct Sections {
|
| 28 |
+
Sections() = default;
|
| 29 |
+
void parse(const char* name) {
|
| 30 |
+
library_ = std::make_unique<MemFile>(name);
|
| 31 |
+
strtab = library_->getSection(".strtab", false);
|
| 32 |
+
|
| 33 |
+
symtab = library_->getSection(".symtab", true);
|
| 34 |
+
debug_info = library_->getSection(".debug_info", true);
|
| 35 |
+
if (debug_info.size > 0) {
|
| 36 |
+
debug_abbrev = library_->getSection(".debug_abbrev", false);
|
| 37 |
+
debug_str = library_->getSection(".debug_str", false);
|
| 38 |
+
debug_line = library_->getSection(".debug_line", false);
|
| 39 |
+
// dwarf 5
|
| 40 |
+
debug_line_str = library_->getSection(".debug_line_str", true);
|
| 41 |
+
debug_rnglists = library_->getSection(".debug_rnglists", true);
|
| 42 |
+
debug_addr = library_->getSection(".debug_addr", true);
|
| 43 |
+
// dwarf 4
|
| 44 |
+
debug_ranges = library_->getSection(".debug_ranges", true);
|
| 45 |
+
}
|
| 46 |
+
parseSymtab();
|
| 47 |
+
}
|
| 48 |
+
|
| 49 |
+
Section debug_info;
|
| 50 |
+
Section debug_abbrev;
|
| 51 |
+
Section debug_str;
|
| 52 |
+
Section debug_line;
|
| 53 |
+
Section debug_line_str;
|
| 54 |
+
Section debug_rnglists;
|
| 55 |
+
Section debug_ranges;
|
| 56 |
+
Section debug_addr;
|
| 57 |
+
Section symtab;
|
| 58 |
+
Section strtab;
|
| 59 |
+
|
| 60 |
+
const char* readString(CheckedLexer& data, uint64_t encoding, bool is_64bit) {
|
| 61 |
+
switch (encoding) {
|
| 62 |
+
case DW_FORM_string: {
|
| 63 |
+
return data.readCString();
|
| 64 |
+
}
|
| 65 |
+
case DW_FORM_strp: {
|
| 66 |
+
return debug_str.string(readSegmentOffset(data, is_64bit));
|
| 67 |
+
}
|
| 68 |
+
case DW_FORM_line_strp: {
|
| 69 |
+
return debug_line_str.string(readSegmentOffset(data, is_64bit));
|
| 70 |
+
}
|
| 71 |
+
default:
|
| 72 |
+
UNWIND_CHECK(false, "unsupported string encoding {:x}", encoding);
|
| 73 |
+
}
|
| 74 |
+
}
|
| 75 |
+
|
| 76 |
+
uint64_t readSegmentOffset(CheckedLexer& data, bool is_64bit) {
|
| 77 |
+
return is_64bit ? data.read<uint64_t>() : data.read<uint32_t>();
|
| 78 |
+
}
|
| 79 |
+
|
| 80 |
+
std::optional<uint64_t> findDebugInfoOffset(uint64_t address) {
|
| 81 |
+
return debug_info_offsets_.find(address);
|
| 82 |
+
}
|
| 83 |
+
size_t compilationUnitCount() {
|
| 84 |
+
return debug_info_offsets_.size() / 2;
|
| 85 |
+
}
|
| 86 |
+
void addDebugInfoRange(
|
| 87 |
+
uint64_t start,
|
| 88 |
+
uint64_t end,
|
| 89 |
+
uint64_t debug_info_offset) {
|
| 90 |
+
debug_info_offsets_.add(start, debug_info_offset, false);
|
| 91 |
+
debug_info_offsets_.add(end, std::nullopt, false);
|
| 92 |
+
}
|
| 93 |
+
std::optional<std::string> findSubprogramName(uint64_t address) {
|
| 94 |
+
if (auto e = symbol_table_.find(address)) {
|
| 95 |
+
return demangle(strtab.string(*e));
|
| 96 |
+
}
|
| 97 |
+
return std::nullopt;
|
| 98 |
+
}
|
| 99 |
+
|
| 100 |
+
private:
|
| 101 |
+
void parseSymtab() {
|
| 102 |
+
auto L = symtab.lexer(0);
|
| 103 |
+
char* end = symtab.data + symtab.size;
|
| 104 |
+
while (L.loc() < end) {
|
| 105 |
+
auto symbol = L.read<Elf64_Sym>();
|
| 106 |
+
if (symbol.st_shndx == SHN_UNDEF ||
|
| 107 |
+
ELF64_ST_TYPE(symbol.st_info) != STT_FUNC) {
|
| 108 |
+
continue;
|
| 109 |
+
}
|
| 110 |
+
symbol_table_.add(symbol.st_value, symbol.st_name, false);
|
| 111 |
+
symbol_table_.add(symbol.st_value + symbol.st_size, std::nullopt, false);
|
| 112 |
+
}
|
| 113 |
+
}
|
| 114 |
+
|
| 115 |
+
std::unique_ptr<MemFile> library_;
|
| 116 |
+
RangeTable<uint64_t> debug_info_offsets_;
|
| 117 |
+
RangeTable<uint64_t> symbol_table_;
|
| 118 |
+
};
|
| 119 |
+
|
| 120 |
+
} // namespace torch::unwind
|
phivenv/Lib/site-packages/torch/include/torch/csrc/profiler/unwind/unwind.h
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#pragma once
|
| 2 |
+
#include <c10/macros/Export.h>
|
| 3 |
+
#include <cstdint>
|
| 4 |
+
#include <optional>
|
| 5 |
+
#include <string>
|
| 6 |
+
#include <vector>
|
| 7 |
+
|
| 8 |
+
namespace torch::unwind {
|
| 9 |
+
// gather current stack, relatively fast.
|
| 10 |
+
// gets faster once the cache of program counter locations is warm.
|
| 11 |
+
TORCH_API std::vector<void*> unwind();
|
| 12 |
+
|
| 13 |
+
struct Frame {
|
| 14 |
+
std::string filename;
|
| 15 |
+
std::string funcname;
|
| 16 |
+
uint64_t lineno;
|
| 17 |
+
};
|
| 18 |
+
|
| 19 |
+
enum class Mode { addr2line, fast, dladdr };
|
| 20 |
+
|
| 21 |
+
// note: symbolize is really slow
|
| 22 |
+
// it will launch an addr2line process that has to parse dwarf
|
| 23 |
+
// information from the libraries that frames point into.
|
| 24 |
+
// Callers should first batch up all the unique void* pointers
|
| 25 |
+
// across a number of unwind states and make a single call to
|
| 26 |
+
// symbolize.
|
| 27 |
+
TORCH_API std::vector<Frame> symbolize(
|
| 28 |
+
const std::vector<void*>& frames,
|
| 29 |
+
Mode mode);
|
| 30 |
+
|
| 31 |
+
// returns path to the library, and the offset of the addr inside the library
|
| 32 |
+
TORCH_API std::optional<std::pair<std::string, uint64_t>> libraryFor(
|
| 33 |
+
void* addr);
|
| 34 |
+
|
| 35 |
+
struct Stats {
|
| 36 |
+
size_t hits = 0;
|
| 37 |
+
size_t misses = 0;
|
| 38 |
+
size_t unsupported = 0;
|
| 39 |
+
size_t resets = 0;
|
| 40 |
+
};
|
| 41 |
+
Stats stats();
|
| 42 |
+
|
| 43 |
+
} // namespace torch::unwind
|
phivenv/Lib/site-packages/torch/include/torch/csrc/profiler/unwind/unwind_error.h
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#pragma once
|
| 2 |
+
#include <fmt/format.h>
|
| 3 |
+
#include <optional>
|
| 4 |
+
#include <stdexcept>
|
| 5 |
+
|
| 6 |
+
namespace torch::unwind {
|
| 7 |
+
|
| 8 |
+
struct UnwindError : public std::runtime_error {
|
| 9 |
+
using std::runtime_error::runtime_error;
|
| 10 |
+
};
|
| 11 |
+
|
| 12 |
+
#define UNWIND_CHECK(cond, fmtstring, ...) \
|
| 13 |
+
do { \
|
| 14 |
+
if (!(cond)) { \
|
| 15 |
+
throw unwind::UnwindError(fmt::format( \
|
| 16 |
+
"{}:{}: " fmtstring, __FILE__, __LINE__, ##__VA_ARGS__)); \
|
| 17 |
+
} \
|
| 18 |
+
} while (0)
|
| 19 |
+
|
| 20 |
+
// #define LOG_INFO(...) fmt::print(__VA_ARGS__)
|
| 21 |
+
#define LOG_INFO(...)
|
| 22 |
+
|
| 23 |
+
// #define PRINT_INST(...) LOG_INFO(__VA_ARGS__)
|
| 24 |
+
#define PRINT_INST(...)
|
| 25 |
+
|
| 26 |
+
// #define PRINT_LINE_TABLE(...) LOG_INFO(__VA_ARGS__)
|
| 27 |
+
#define PRINT_LINE_TABLE(...)
|
| 28 |
+
|
| 29 |
+
} // namespace torch::unwind
|
phivenv/Lib/site-packages/torch/include/torch/csrc/profiler/unwind/unwinder.h
ADDED
|
@@ -0,0 +1,81 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#pragma once
|
| 2 |
+
#include <torch/csrc/profiler/unwind/action.h>
|
| 3 |
+
#include <torch/csrc/profiler/unwind/unwind_error.h>
|
| 4 |
+
#include <cstdint>
|
| 5 |
+
#include <limits>
|
| 6 |
+
|
| 7 |
+
namespace torch::unwind {
|
| 8 |
+
|
| 9 |
+
struct UnwindState {
|
| 10 |
+
int64_t rip, rbp, rsp;
|
| 11 |
+
};
|
| 12 |
+
|
| 13 |
+
struct Unwinder {
|
| 14 |
+
Unwinder(Action rsp, Action rip, Action rbp)
|
| 15 |
+
: kind_(rip.kind == A_UNDEFINED ? END : STANDARD),
|
| 16 |
+
reg_(rsp.reg),
|
| 17 |
+
off_(rsp.data),
|
| 18 |
+
rip_off_(rip.data),
|
| 19 |
+
rbp_off_(
|
| 20 |
+
rbp.kind == A_UNDEFINED ? std::numeric_limits<int64_t>::max()
|
| 21 |
+
: rbp.data),
|
| 22 |
+
deref_(rsp.kind == A_REG_PLUS_DATA_DEREF) {
|
| 23 |
+
check(rsp.reg == D_RSP || rsp.reg == D_RBP);
|
| 24 |
+
check(rip.kind == A_UNDEFINED || rip.kind == A_LOAD_CFA_OFFSET);
|
| 25 |
+
if (rsp.kind == A_REG_PLUS_DATA) {
|
| 26 |
+
check(rbp.kind == A_LOAD_CFA_OFFSET || rbp.kind == A_UNDEFINED);
|
| 27 |
+
} else if (rsp.kind == A_REG_PLUS_DATA_DEREF) {
|
| 28 |
+
if (rbp.kind == A_REG_PLUS_DATA_DEREF) {
|
| 29 |
+
check(rbp.reg == rsp.reg);
|
| 30 |
+
rbp_off_ -= rsp.data;
|
| 31 |
+
} else {
|
| 32 |
+
check(rbp.kind == A_UNDEFINED);
|
| 33 |
+
}
|
| 34 |
+
} else {
|
| 35 |
+
check(false);
|
| 36 |
+
}
|
| 37 |
+
}
|
| 38 |
+
void check(bool cond) {
|
| 39 |
+
if (!cond) {
|
| 40 |
+
throw UnwindError("Unwinding actions do not follow supported patterns");
|
| 41 |
+
}
|
| 42 |
+
}
|
| 43 |
+
bool terminator() const {
|
| 44 |
+
return kind_ != STANDARD;
|
| 45 |
+
}
|
| 46 |
+
bool isUnknown() const {
|
| 47 |
+
return kind_ == UNKNOWN;
|
| 48 |
+
}
|
| 49 |
+
// unwinder representing some pattern unsupported in
|
| 50 |
+
// current implementation
|
| 51 |
+
static Unwinder unknown() {
|
| 52 |
+
return Unwinder();
|
| 53 |
+
}
|
| 54 |
+
UnwindState run(const UnwindState& cur) const {
|
| 55 |
+
UnwindState r = cur;
|
| 56 |
+
r.rsp = (reg_ == D_RSP ? cur.rsp : cur.rbp) + off_;
|
| 57 |
+
r.rbp = rbp_off_ == std::numeric_limits<int64_t>::max()
|
| 58 |
+
? cur.rbp
|
| 59 |
+
// NOLINTNEXTLINE(performance-no-int-to-ptr)
|
| 60 |
+
: *(int64_t*)(r.rsp + rbp_off_);
|
| 61 |
+
if (deref_) {
|
| 62 |
+
// NOLINTNEXTLINE(performance-no-int-to-ptr)
|
| 63 |
+
r.rsp = *(int64_t*)r.rsp;
|
| 64 |
+
}
|
| 65 |
+
// NOLINTNEXTLINE(performance-no-int-to-ptr)
|
| 66 |
+
r.rip = *(int64_t*)(r.rsp + rip_off_);
|
| 67 |
+
|
| 68 |
+
return r;
|
| 69 |
+
}
|
| 70 |
+
|
| 71 |
+
private:
|
| 72 |
+
Unwinder() : kind_(UNKNOWN), reg_(0), off_(0), rip_off_(0), rbp_off_(0) {}
|
| 73 |
+
enum Kind { STANDARD, END, UNKNOWN } kind_;
|
| 74 |
+
uint32_t reg_;
|
| 75 |
+
int64_t off_;
|
| 76 |
+
int64_t rip_off_;
|
| 77 |
+
int64_t rbp_off_;
|
| 78 |
+
bool deref_{false};
|
| 79 |
+
};
|
| 80 |
+
|
| 81 |
+
} // namespace torch::unwind
|
phivenv/Lib/site-packages/torch/include/torch/csrc/stable/library.h
ADDED
|
@@ -0,0 +1,356 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#pragma once
|
| 2 |
+
// this file can only have stable stuff! Akin to shim.h
|
| 3 |
+
// but unlike shim.h, this file can contain header-only C++
|
| 4 |
+
// code for better UX.
|
| 5 |
+
|
| 6 |
+
#include <torch/csrc/inductor/aoti_torch/c/shim.h>
|
| 7 |
+
#include <torch/csrc/stable/tensor.h>
|
| 8 |
+
|
| 9 |
+
#include <optional>
|
| 10 |
+
|
| 11 |
+
// use anonymous namespace to avoid collisions between differing
|
| 12 |
+
// versions of this file that may be included by different sources
|
| 13 |
+
namespace {
|
| 14 |
+
|
| 15 |
+
// =============================================================================
|
| 16 |
+
// helpers for converting between StableIValue and T
|
| 17 |
+
// =============================================================================
|
| 18 |
+
|
| 19 |
+
// forward declare so that from/to() calls in detail work
|
| 20 |
+
template <typename T>
|
| 21 |
+
StableIValue from(T val);
|
| 22 |
+
template <typename T>
|
| 23 |
+
T to(StableIValue val);
|
| 24 |
+
|
| 25 |
+
namespace detail {
|
| 26 |
+
|
| 27 |
+
// =============================================================================
|
| 28 |
+
// FROM CONVERSIONS (T -> StableIValue)
|
| 29 |
+
// =============================================================================
|
| 30 |
+
|
| 31 |
+
// Specialization for general copyable types (catch-all) => StableIValue
|
| 32 |
+
template <typename T>
|
| 33 |
+
struct FromImpl {
|
| 34 |
+
static StableIValue call(T val) {
|
| 35 |
+
static_assert(
|
| 36 |
+
sizeof(T) <= sizeof(StableIValue),
|
| 37 |
+
"StableLibrary stack does not support parameter types larger than 64 bits.");
|
| 38 |
+
static_assert(std::is_trivially_copyable_v<T>);
|
| 39 |
+
// Initialization should be cheap enough; let's give people well-specified
|
| 40 |
+
// reproducible behavior.
|
| 41 |
+
StableIValue result = 0;
|
| 42 |
+
// NOTE [ -Wclass-memaccess ]: reinterpret_cast to suppress
|
| 43 |
+
// overzealous -Wclass-memaccess. (see
|
| 44 |
+
// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=107361) We have a
|
| 45 |
+
// static_assert above that T is trivially copyable, which should be
|
| 46 |
+
// enough.
|
| 47 |
+
std::memcpy(&result, reinterpret_cast<const void*>(&val), sizeof(val));
|
| 48 |
+
return result;
|
| 49 |
+
}
|
| 50 |
+
};
|
| 51 |
+
|
| 52 |
+
// Specialization for std::nullopt_t => StableIValue
|
| 53 |
+
template <>
|
| 54 |
+
struct FromImpl<std::nullopt_t> {
|
| 55 |
+
static StableIValue call(std::nullopt_t val) {
|
| 56 |
+
return from(nullptr);
|
| 57 |
+
}
|
| 58 |
+
};
|
| 59 |
+
|
| 60 |
+
// Specialization for std::optional => StableIValue
|
| 61 |
+
// [Handling std::optional]
|
| 62 |
+
// When the schema is represented by an optional type, say int?, then we
|
| 63 |
+
// expect the custom extension representation to be a std::optional<int>
|
| 64 |
+
// (critically NOT int!). In order for all parameters to be stably parsed and
|
| 65 |
+
// handled by our dispatcher, we liaison custom extension parameters through
|
| 66 |
+
// boxed kernels, meaning that every value will make its way to be an IValue:
|
| 67 |
+
//
|
| 68 |
+
// custom extension value --(from)-> StableIValue --(to_ivalue)-> IValue
|
| 69 |
+
//
|
| 70 |
+
// When the custom extension value is a literal that can be trivially
|
| 71 |
+
// casted to StableIValue, e.g., an int, a float, a pointer, this route is
|
| 72 |
+
// ...trivial. The below specialization is for a case when the custom
|
| 73 |
+
// extension value would NOT fit within a StableIValue: a std::optional.
|
| 74 |
+
//
|
| 75 |
+
// If the std::optional has no value, it is treated as std::nullopt,
|
| 76 |
+
// whose StableIValue representation is from(nullptr). Otherwise, we:
|
| 77 |
+
// 1. unwrap the std::optional<T>
|
| 78 |
+
// 2. recursively convert its value of type T to a StableIValue
|
| 79 |
+
// 3. allocate heap space for said StableIValue
|
| 80 |
+
// 4. convert the resulting StableIValue* into a StableIValue
|
| 81 |
+
//
|
| 82 |
+
// note that this allocates heap memory! which we expect to be cleaned
|
| 83 |
+
// up in the to_ivalue() function defined in shim_common.cpp. We
|
| 84 |
+
// purposefully hide this implementation detail from the user so that
|
| 85 |
+
// all the user needs to know is:
|
| 86 |
+
//
|
| 87 |
+
// The schema requests an optional (T?) so I must call `from` on a
|
| 88 |
+
// std::optional<T> or a std::nullopt.
|
| 89 |
+
template <typename T>
|
| 90 |
+
struct FromImpl<std::optional<T>> {
|
| 91 |
+
static StableIValue call(const std::optional<T>& val) {
|
| 92 |
+
if (!val.has_value()) {
|
| 93 |
+
return from(std::nullopt);
|
| 94 |
+
}
|
| 95 |
+
StableIValue* heap_val = new StableIValue(from(val.value()));
|
| 96 |
+
return from(heap_val);
|
| 97 |
+
}
|
| 98 |
+
};
|
| 99 |
+
|
| 100 |
+
// Specialization for torch::stable::Tensor => StableIValue
|
| 101 |
+
// Returns a new owning reference of the underlying Tensor.
|
| 102 |
+
template <>
|
| 103 |
+
struct FromImpl<torch::stable::Tensor> {
|
| 104 |
+
static StableIValue call(const torch::stable::Tensor& val) {
|
| 105 |
+
AtenTensorHandle new_ath;
|
| 106 |
+
aoti_torch_new_tensor_handle(val.get(), &new_ath);
|
| 107 |
+
return from(new_ath);
|
| 108 |
+
}
|
| 109 |
+
};
|
| 110 |
+
|
| 111 |
+
// =============================================================================
|
| 112 |
+
// TO CONVERSIONS (StableIValue -> T)
|
| 113 |
+
// =============================================================================
|
| 114 |
+
|
| 115 |
+
// Specialization for StableIValue => general copyable types (catch-all)
|
| 116 |
+
template <typename T>
|
| 117 |
+
struct ToImpl {
|
| 118 |
+
static T call(StableIValue val) {
|
| 119 |
+
static_assert(std::is_trivially_copyable_v<T>);
|
| 120 |
+
// T may not have a default constructor. (For example, it might be
|
| 121 |
+
// c10::Device.) However, std::memcpy implicitly creates a T at the
|
| 122 |
+
// destination. So, we can use a union to work around this lack of
|
| 123 |
+
// default constructor.
|
| 124 |
+
union Result {
|
| 125 |
+
Result() {}
|
| 126 |
+
T t;
|
| 127 |
+
};
|
| 128 |
+
Result result;
|
| 129 |
+
// See NOTE[ -Wclass-memaccess ] above.
|
| 130 |
+
std::memcpy(reinterpret_cast<void*>(&result.t), &val, sizeof(result));
|
| 131 |
+
return result.t;
|
| 132 |
+
}
|
| 133 |
+
};
|
| 134 |
+
|
| 135 |
+
// Specialization for StableIValue => std::nullopt_t
|
| 136 |
+
template <>
|
| 137 |
+
struct ToImpl<std::nullopt_t> {
|
| 138 |
+
static std::nullopt_t call(StableIValue val) {
|
| 139 |
+
// val should be equivalent to from(nullptr)
|
| 140 |
+
return std::nullopt;
|
| 141 |
+
}
|
| 142 |
+
};
|
| 143 |
+
|
| 144 |
+
// Specialization for StableIValue => std::optional, see [Handling
|
| 145 |
+
// std::optional] as the semantic is the same but in reverse direction as we go
|
| 146 |
+
// from IValue --(from_ivalue)-> StableIValue --(to<T>)-> T in custom extension
|
| 147 |
+
template <typename T>
|
| 148 |
+
struct ToImpl<std::optional<T>> {
|
| 149 |
+
static std::optional<T> call(StableIValue val) {
|
| 150 |
+
auto sivp = to<StableIValue*>(val);
|
| 151 |
+
|
| 152 |
+
// sivp is either nullptr or a pointer to a StableIValue
|
| 153 |
+
if (sivp == nullptr) {
|
| 154 |
+
return {};
|
| 155 |
+
}
|
| 156 |
+
auto inner_val = to<T>(*sivp);
|
| 157 |
+
|
| 158 |
+
// free the memory associated with StableIValue* sivp
|
| 159 |
+
delete sivp;
|
| 160 |
+
|
| 161 |
+
return std::make_optional(inner_val);
|
| 162 |
+
}
|
| 163 |
+
};
|
| 164 |
+
|
| 165 |
+
// Specialization for StableIValue => torch::stable::Tensor
|
| 166 |
+
// The resulting stable::Tensor steals ownership of the input's
|
| 167 |
+
// underlying AtenTensorHandle.
|
| 168 |
+
template <>
|
| 169 |
+
struct ToImpl<torch::stable::Tensor> {
|
| 170 |
+
static torch::stable::Tensor call(StableIValue val) {
|
| 171 |
+
return torch::stable::Tensor(to<AtenTensorHandle>(val));
|
| 172 |
+
}
|
| 173 |
+
};
|
| 174 |
+
|
| 175 |
+
} // namespace detail
|
| 176 |
+
|
| 177 |
+
// Expose the partially templated class functions through single functions
|
| 178 |
+
template <typename T>
|
| 179 |
+
StableIValue from(T val) {
|
| 180 |
+
return detail::FromImpl<T>::call(val);
|
| 181 |
+
}
|
| 182 |
+
|
| 183 |
+
template <typename T>
|
| 184 |
+
StableIValue from(const std::optional<T>& val) {
|
| 185 |
+
return detail::FromImpl<std::optional<T>>::call(val);
|
| 186 |
+
}
|
| 187 |
+
|
| 188 |
+
// The below overload is used! See https://godbolt.org/z/859cshxrW
|
| 189 |
+
// We are suppressing the warning for versions clang12- and gcc11-
|
| 190 |
+
[[maybe_unused]] StableIValue from(const torch::stable::Tensor& val) {
|
| 191 |
+
return detail::FromImpl<torch::stable::Tensor>::call(val);
|
| 192 |
+
}
|
| 193 |
+
|
| 194 |
+
template <typename T>
|
| 195 |
+
T to(StableIValue val) {
|
| 196 |
+
return detail::ToImpl<T>::call(val);
|
| 197 |
+
}
|
| 198 |
+
|
| 199 |
+
// =============================================================================
|
| 200 |
+
// end to helpers for converting between StableIValue and T
|
| 201 |
+
// =============================================================================
|
| 202 |
+
|
| 203 |
+
class StableLibrary final {
|
| 204 |
+
private:
|
| 205 |
+
TorchLibraryHandle lib_;
|
| 206 |
+
|
| 207 |
+
public:
|
| 208 |
+
enum class Kind {
|
| 209 |
+
DEF,
|
| 210 |
+
IMPL,
|
| 211 |
+
FRAGMENT,
|
| 212 |
+
};
|
| 213 |
+
|
| 214 |
+
// constructor
|
| 215 |
+
/// \private
|
| 216 |
+
///
|
| 217 |
+
/// Use STABLE_TORCH_LIBRARY or STABLE_TORCH_LIBRARY_IMPL() instead of using
|
| 218 |
+
/// these constructors directly
|
| 219 |
+
StableLibrary(
|
| 220 |
+
Kind kind,
|
| 221 |
+
const char* ns,
|
| 222 |
+
const char* k,
|
| 223 |
+
const char* file,
|
| 224 |
+
uint32_t line) {
|
| 225 |
+
if (kind == Kind::IMPL) {
|
| 226 |
+
aoti_torch_library_init_impl(ns, k, file, line, &lib_);
|
| 227 |
+
} else if (kind == Kind::DEF) {
|
| 228 |
+
aoti_torch_library_init_def(ns, file, line, &lib_);
|
| 229 |
+
} else { // kind == FRAGMENT
|
| 230 |
+
aoti_torch_library_init_fragment(ns, file, line, &lib_);
|
| 231 |
+
}
|
| 232 |
+
}
|
| 233 |
+
|
| 234 |
+
// do not permit copy
|
| 235 |
+
StableLibrary(const StableLibrary&) = delete;
|
| 236 |
+
StableLibrary& operator=(const StableLibrary&) = delete;
|
| 237 |
+
|
| 238 |
+
// do not permit move
|
| 239 |
+
StableLibrary(StableLibrary&& other) = delete;
|
| 240 |
+
StableLibrary& operator=(StableLibrary&& other) = delete;
|
| 241 |
+
|
| 242 |
+
~StableLibrary() {
|
| 243 |
+
aoti_torch_delete_library_object(lib_);
|
| 244 |
+
}
|
| 245 |
+
|
| 246 |
+
// corresponds to a limited, stable version of torch::library::impl()
|
| 247 |
+
// Inputs:
|
| 248 |
+
// name: the name of the function to implement
|
| 249 |
+
// fn: a boxed function with schema
|
| 250 |
+
// (StableIValue* stack, uint64_t num_inputs, uint64_t num_outputs) ->
|
| 251 |
+
// void
|
| 252 |
+
// fn should follow the calling convention of our boxed kernels that convert
|
| 253 |
+
// to IValues. fn will be called with a StableIValue* array of length
|
| 254 |
+
// max(num_inputs, num_outputs), where the first num_inputs entries are
|
| 255 |
+
// populated with inputs. fn is responsible for stealing the memory of the
|
| 256 |
+
// inputs, in effect "popping" them off the stack, and then populating the
|
| 257 |
+
// stack with StableIValue outputs. Concretely, fn should:
|
| 258 |
+
// 1. read StableIValue inputs from the given stack
|
| 259 |
+
// 2. convert the inputs to the proper types
|
| 260 |
+
// 3. call the function corresponding to name with the inputs
|
| 261 |
+
// 4. convert the outputs to StableIValues
|
| 262 |
+
// 5. populate the now empty stack with StableIValue outputs
|
| 263 |
+
// If the operation corresponding to name takes in 4 inputs and returns 2
|
| 264 |
+
// outputs, fn should expect stack to contain 4 StableIValues:
|
| 265 |
+
// [stable_arg1, stable_arg2, stable_arg3, stable_arg4]
|
| 266 |
+
// to end, fn should fill the stack with 2 StableIValues representing outputs:
|
| 267 |
+
// [stable_ret1, stable_ret2, -, -]
|
| 268 |
+
StableLibrary& impl(
|
| 269 |
+
const char* name,
|
| 270 |
+
void (*fn)(StableIValue*, uint64_t, uint64_t)) {
|
| 271 |
+
aoti_torch_library_impl(lib_, name, fn);
|
| 272 |
+
return *this;
|
| 273 |
+
}
|
| 274 |
+
|
| 275 |
+
// corresponds to a limited, stable version of torch::library::def()
|
| 276 |
+
StableLibrary& def(const char* schema) {
|
| 277 |
+
aoti_torch_library_def(lib_, schema);
|
| 278 |
+
return *this;
|
| 279 |
+
}
|
| 280 |
+
};
|
| 281 |
+
|
| 282 |
+
class StableTorchLibraryInit final {
|
| 283 |
+
private:
|
| 284 |
+
using InitFn = void(StableLibrary&);
|
| 285 |
+
StableLibrary lib_;
|
| 286 |
+
|
| 287 |
+
public:
|
| 288 |
+
StableTorchLibraryInit(
|
| 289 |
+
StableLibrary::Kind kind,
|
| 290 |
+
InitFn* fn,
|
| 291 |
+
const char* ns,
|
| 292 |
+
const char* k,
|
| 293 |
+
const char* file,
|
| 294 |
+
uint32_t line)
|
| 295 |
+
: lib_(kind, ns, k, file, line) {
|
| 296 |
+
fn(lib_);
|
| 297 |
+
}
|
| 298 |
+
};
|
| 299 |
+
|
| 300 |
+
} // namespace
|
| 301 |
+
|
| 302 |
+
// macros copied from c10/macros/Macros.h
|
| 303 |
+
#ifdef __COUNTER__
|
| 304 |
+
#define STABLE_UID __COUNTER__
|
| 305 |
+
#else
|
| 306 |
+
#define STABLE_UID __LINE__
|
| 307 |
+
#endif
|
| 308 |
+
|
| 309 |
+
#define STABLE_CONCATENATE_IMPL(s1, s2) s1##s2
|
| 310 |
+
#define STABLE_CONCATENATE(s1, s2) STABLE_CONCATENATE_IMPL(s1, s2)
|
| 311 |
+
// end of macros copied from c10/macros/Macros.h
|
| 312 |
+
|
| 313 |
+
#define STABLE_TORCH_LIBRARY_IMPL(ns, k, m) \
|
| 314 |
+
_STABLE_TORCH_LIBRARY_IMPL(ns, k, m, STABLE_UID)
|
| 315 |
+
|
| 316 |
+
#define _STABLE_TORCH_LIBRARY_IMPL(ns, k, m, uid) \
|
| 317 |
+
static void STABLE_CONCATENATE( \
|
| 318 |
+
STABLE_TORCH_LIBRARY_IMPL_init_##ns##_##k##_, uid)(StableLibrary&); \
|
| 319 |
+
static const StableTorchLibraryInit STABLE_CONCATENATE( \
|
| 320 |
+
STABLE_TORCH_LIBRARY_IMPL_static_init_##ns##_##k##_, uid)( \
|
| 321 |
+
StableLibrary::Kind::IMPL, \
|
| 322 |
+
&STABLE_CONCATENATE(STABLE_TORCH_LIBRARY_IMPL_init_##ns##_##k##_, uid), \
|
| 323 |
+
#ns, \
|
| 324 |
+
#k, \
|
| 325 |
+
__FILE__, \
|
| 326 |
+
__LINE__); \
|
| 327 |
+
void STABLE_CONCATENATE( \
|
| 328 |
+
STABLE_TORCH_LIBRARY_IMPL_init_##ns##_##k##_, uid)(StableLibrary & m)
|
| 329 |
+
|
| 330 |
+
#define STABLE_TORCH_LIBRARY(ns, m) \
|
| 331 |
+
static void STABLE_TORCH_LIBRARY_init_##ns(StableLibrary&); \
|
| 332 |
+
static const StableTorchLibraryInit STABLE_TORCH_LIBRARY_static_init_##ns( \
|
| 333 |
+
StableLibrary::Kind::DEF, \
|
| 334 |
+
&STABLE_TORCH_LIBRARY_init_##ns, \
|
| 335 |
+
#ns, \
|
| 336 |
+
nullptr, \
|
| 337 |
+
__FILE__, \
|
| 338 |
+
__LINE__); \
|
| 339 |
+
void STABLE_TORCH_LIBRARY_init_##ns(StableLibrary& m)
|
| 340 |
+
|
| 341 |
+
#define STABLE_TORCH_LIBRARY_FRAGMENT(ns, m) \
|
| 342 |
+
_STABLE_TORCH_LIBRARY_FRAGMENT(ns, m, STABLE_UID)
|
| 343 |
+
|
| 344 |
+
#define _STABLE_TORCH_LIBRARY_FRAGMENT(ns, m, uid) \
|
| 345 |
+
static void STABLE_CONCATENATE( \
|
| 346 |
+
STABLE_TORCH_LIBRARY_FRAGMENT_init_##ns##_, uid)(StableLibrary&); \
|
| 347 |
+
static const StableTorchLibraryInit STABLE_CONCATENATE( \
|
| 348 |
+
STABLE_TORCH_LIBRARY_FRAGMENT_static_init_##ns##_, uid)( \
|
| 349 |
+
StableLibrary::Kind::FRAGMENT, \
|
| 350 |
+
&STABLE_CONCATENATE(STABLE_TORCH_LIBRARY_FRAGMENT_init_##ns##_, uid), \
|
| 351 |
+
#ns, \
|
| 352 |
+
nullptr, \
|
| 353 |
+
__FILE__, \
|
| 354 |
+
__LINE__); \
|
| 355 |
+
void STABLE_CONCATENATE( \
|
| 356 |
+
STABLE_TORCH_LIBRARY_FRAGMENT_init_##ns##_, uid)(StableLibrary & m)
|
phivenv/Lib/site-packages/torch/include/torch/csrc/stable/tensor.h
ADDED
|
@@ -0,0 +1,126 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#pragma once
|
| 2 |
+
|
| 3 |
+
// TODO ASAP: THIS FILE SHOULD BE HEADER ONLY BUT ISN'T ENFORCED:
|
| 4 |
+
// I only need it for AOTI_TORCH_ERROR_CODE_CHECK, see #154908
|
| 5 |
+
#include <torch/csrc/inductor/aoti_runtime/utils.h>
|
| 6 |
+
|
| 7 |
+
#include <torch/csrc/inductor/aoti_torch/c/shim.h>
|
| 8 |
+
|
| 9 |
+
namespace torch::stable {
|
| 10 |
+
|
| 11 |
+
using DeviceIndex =
|
| 12 |
+
int8_t; // this is from c10/core/Device.h and can be header only
|
| 13 |
+
|
| 14 |
+
// The torch::stable::Tensor class is a highlevel C++ wrapper around
|
| 15 |
+
// the C shim Tensor APIs. We've modeled this class after TensorBase, as custom
|
| 16 |
+
// op kernels only really need to interact with Tensor metadata (think sizes,
|
| 17 |
+
// strides, device, dtype). Other functions on Tensor (like empty_like) should
|
| 18 |
+
// live like the ATen op that they are and exist outside of this struct.
|
| 19 |
+
//
|
| 20 |
+
// There are several goals of this class over AtenTensorHandle and
|
| 21 |
+
// RAIIAtenTensorHandle:
|
| 22 |
+
// 1. torch::stable::Tensor is a nicer UX much closer to torch::Tensor than the
|
| 23 |
+
// C APIs with AtenTensorHandle. Under the hood we still call to these C shim
|
| 24 |
+
// APIs to preserve stability.
|
| 25 |
+
// 2. RAIIAtenTensorHandle boils down to a uniq_ptr that forces the user to pass
|
| 26 |
+
// around ownership. This makes it difficult to pass one input into 2
|
| 27 |
+
// different functions, e.g., doing something like c = a(t) + b(t) for
|
| 28 |
+
// stable::Tensor t. Thus, we use a shared_ptr here.
|
| 29 |
+
class Tensor {
|
| 30 |
+
private:
|
| 31 |
+
std::shared_ptr<AtenTensorOpaque> ath_;
|
| 32 |
+
|
| 33 |
+
public:
|
| 34 |
+
Tensor() = delete;
|
| 35 |
+
|
| 36 |
+
// Construct a stable::Tensor from an AtenTensorHandle (ATH)
|
| 37 |
+
// Steals ownership from the ATH
|
| 38 |
+
explicit Tensor(AtenTensorHandle ath)
|
| 39 |
+
: ath_(ath, [](AtenTensorHandle ath) {
|
| 40 |
+
AOTI_TORCH_ERROR_CODE_CHECK(aoti_torch_delete_tensor_object(ath));
|
| 41 |
+
}) {}
|
| 42 |
+
|
| 43 |
+
// Copy and move constructors can be default cuz the underlying handle is a
|
| 44 |
+
// shared_ptr
|
| 45 |
+
Tensor(const Tensor& other) = default;
|
| 46 |
+
Tensor(Tensor&& other) noexcept = default;
|
| 47 |
+
|
| 48 |
+
// Copy and move assignment operators can be default cuz the underlying handle
|
| 49 |
+
// is a shared_ptr
|
| 50 |
+
Tensor& operator=(const Tensor& other) = default;
|
| 51 |
+
Tensor& operator=(Tensor&& other) noexcept = default;
|
| 52 |
+
|
| 53 |
+
// Destructor can be default: shared ptr has custom deletion logic
|
| 54 |
+
~Tensor() = default;
|
| 55 |
+
|
| 56 |
+
// Returns a borrowed reference to the AtenTensorHandle
|
| 57 |
+
AtenTensorHandle get() const {
|
| 58 |
+
return ath_.get();
|
| 59 |
+
}
|
| 60 |
+
|
| 61 |
+
// =============================================================================
|
| 62 |
+
// C-shimified TensorBase APIs: the below APIs have the same signatures and
|
| 63 |
+
// semantics as their counterparts in TensorBase.h.
|
| 64 |
+
// =============================================================================
|
| 65 |
+
|
| 66 |
+
void* data_ptr() const {
|
| 67 |
+
void* data_ptr;
|
| 68 |
+
AOTI_TORCH_ERROR_CODE_CHECK(aoti_torch_get_data_ptr(ath_.get(), &data_ptr));
|
| 69 |
+
return data_ptr;
|
| 70 |
+
}
|
| 71 |
+
|
| 72 |
+
int64_t dim() const {
|
| 73 |
+
int64_t dim;
|
| 74 |
+
AOTI_TORCH_ERROR_CODE_CHECK(aoti_torch_get_dim(ath_.get(), &dim));
|
| 75 |
+
return dim;
|
| 76 |
+
}
|
| 77 |
+
|
| 78 |
+
int64_t numel() const {
|
| 79 |
+
int64_t numel;
|
| 80 |
+
AOTI_TORCH_ERROR_CODE_CHECK(aoti_torch_get_numel(ath_.get(), &numel));
|
| 81 |
+
return numel;
|
| 82 |
+
}
|
| 83 |
+
|
| 84 |
+
// note: this is a subset of the original TensorBase API. It takes no
|
| 85 |
+
// arguments whereas the original API takes in a kwarg of memory format.
|
| 86 |
+
// Here, we assume the default contiguous memory format.
|
| 87 |
+
bool is_contiguous() const {
|
| 88 |
+
bool is_contiguous;
|
| 89 |
+
AOTI_TORCH_ERROR_CODE_CHECK(
|
| 90 |
+
aoti_torch_is_contiguous(ath_.get(), &is_contiguous));
|
| 91 |
+
return is_contiguous;
|
| 92 |
+
}
|
| 93 |
+
|
| 94 |
+
int64_t stride(int64_t dim) const {
|
| 95 |
+
int64_t stride;
|
| 96 |
+
AOTI_TORCH_ERROR_CODE_CHECK(
|
| 97 |
+
aoti_torch_get_stride(ath_.get(), dim, &stride));
|
| 98 |
+
return stride;
|
| 99 |
+
}
|
| 100 |
+
|
| 101 |
+
DeviceIndex get_device() const {
|
| 102 |
+
int32_t device_index;
|
| 103 |
+
AOTI_TORCH_ERROR_CODE_CHECK(
|
| 104 |
+
aoti_torch_get_device_index(ath_.get(), &device_index));
|
| 105 |
+
return static_cast<DeviceIndex>(device_index);
|
| 106 |
+
}
|
| 107 |
+
|
| 108 |
+
bool is_cuda() const {
|
| 109 |
+
int32_t device_type;
|
| 110 |
+
AOTI_TORCH_ERROR_CODE_CHECK(
|
| 111 |
+
aoti_torch_get_device_type(ath_.get(), &device_type));
|
| 112 |
+
return device_type == aoti_torch_device_type_cuda();
|
| 113 |
+
}
|
| 114 |
+
|
| 115 |
+
int64_t size(int64_t dim) const {
|
| 116 |
+
int64_t size;
|
| 117 |
+
AOTI_TORCH_ERROR_CODE_CHECK(aoti_torch_get_size(ath_.get(), dim, &size));
|
| 118 |
+
return size;
|
| 119 |
+
}
|
| 120 |
+
|
| 121 |
+
// =============================================================================
|
| 122 |
+
// END of C-shimified TensorBase APIs
|
| 123 |
+
// =============================================================================
|
| 124 |
+
};
|
| 125 |
+
|
| 126 |
+
} // namespace torch::stable
|
phivenv/Lib/site-packages/torch/include/torch/csrc/tensor/python_tensor.h
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#pragma once
|
| 2 |
+
|
| 3 |
+
#include <c10/core/Device.h>
|
| 4 |
+
#include <c10/core/DispatchKey.h>
|
| 5 |
+
#include <c10/core/ScalarType.h>
|
| 6 |
+
#include <torch/csrc/Export.h>
|
| 7 |
+
#include <torch/csrc/python_headers.h>
|
| 8 |
+
|
| 9 |
+
namespace at {
|
| 10 |
+
class Tensor;
|
| 11 |
+
} // namespace at
|
| 12 |
+
|
| 13 |
+
namespace torch::tensors {
|
| 14 |
+
|
| 15 |
+
// Initializes the Python tensor type objects: torch.FloatTensor,
|
| 16 |
+
// torch.DoubleTensor, etc. and binds them in their containing modules.
|
| 17 |
+
TORCH_PYTHON_API void initialize_python_bindings();
|
| 18 |
+
|
| 19 |
+
// Same as set_default_tensor_type() but takes a PyObject*
|
| 20 |
+
TORCH_PYTHON_API void py_set_default_tensor_type(PyObject* type_obj);
|
| 21 |
+
|
| 22 |
+
// Same as py_set_default_tensor_type, but only changes the dtype (ScalarType).
|
| 23 |
+
TORCH_PYTHON_API void py_set_default_dtype(PyObject* dtype_obj);
|
| 24 |
+
|
| 25 |
+
// Gets the DispatchKey for the default tensor type.
|
| 26 |
+
//
|
| 27 |
+
// TODO: This is nuts! There is no reason to let the default tensor type id
|
| 28 |
+
// change. Probably only store ScalarType, as that's the only flex point
|
| 29 |
+
// we support.
|
| 30 |
+
TORCH_PYTHON_API c10::DispatchKey get_default_dispatch_key();
|
| 31 |
+
TORCH_PYTHON_API at::Device get_default_device();
|
| 32 |
+
|
| 33 |
+
// Gets the ScalarType for the default tensor type.
|
| 34 |
+
TORCH_PYTHON_API at::ScalarType get_default_scalar_type();
|
| 35 |
+
} // namespace torch::tensors
|
phivenv/Lib/site-packages/torch/include/torch/csrc/utils/byte_order.h
ADDED
|
@@ -0,0 +1,81 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#pragma once
|
| 2 |
+
|
| 3 |
+
#include <c10/util/BFloat16.h>
|
| 4 |
+
#include <c10/util/Float8_e4m3fn.h>
|
| 5 |
+
#include <c10/util/Float8_e4m3fnuz.h>
|
| 6 |
+
#include <c10/util/Float8_e5m2.h>
|
| 7 |
+
#include <c10/util/Float8_e5m2fnuz.h>
|
| 8 |
+
#include <c10/util/Half.h>
|
| 9 |
+
#include <torch/csrc/Export.h>
|
| 10 |
+
#include <cstddef>
|
| 11 |
+
#include <cstdint>
|
| 12 |
+
|
| 13 |
+
#ifdef __FreeBSD__
|
| 14 |
+
#include <sys/endian.h>
|
| 15 |
+
#include <sys/types.h>
|
| 16 |
+
#define thp_bswap16(x) bswap16(x)
|
| 17 |
+
#define thp_bswap32(x) bswap32(x)
|
| 18 |
+
#define thp_bswap64(x) bswap64(x)
|
| 19 |
+
#elif defined(__APPLE__)
|
| 20 |
+
#include <libkern/OSByteOrder.h>
|
| 21 |
+
#define thp_bswap16(x) OSSwapInt16(x)
|
| 22 |
+
#define thp_bswap32(x) OSSwapInt32(x)
|
| 23 |
+
#define thp_bswap64(x) OSSwapInt64(x)
|
| 24 |
+
#elif defined(__GNUC__) && !defined(__MINGW32__)
|
| 25 |
+
#include <byteswap.h>
|
| 26 |
+
#define thp_bswap16(x) bswap_16(x)
|
| 27 |
+
#define thp_bswap32(x) bswap_32(x)
|
| 28 |
+
#define thp_bswap64(x) bswap_64(x)
|
| 29 |
+
#elif defined _WIN32 || defined _WIN64
|
| 30 |
+
#define thp_bswap16(x) _byteswap_ushort(x)
|
| 31 |
+
#define thp_bswap32(x) _byteswap_ulong(x)
|
| 32 |
+
#define thp_bswap64(x) _byteswap_uint64(x)
|
| 33 |
+
#endif
|
| 34 |
+
|
| 35 |
+
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
|
| 36 |
+
#define to_be16(x) thp_bswap16(x)
|
| 37 |
+
#define from_be16(x) thp_bswap16(x)
|
| 38 |
+
#define to_be32(x) thp_bswap32(x)
|
| 39 |
+
#define from_be32(x) thp_bswap32(x)
|
| 40 |
+
#define to_be64(x) thp_bswap64(x)
|
| 41 |
+
#define from_be64(x) thp_bswap64(x)
|
| 42 |
+
#define to_le16(x) (x)
|
| 43 |
+
#define from_le16(x) (x)
|
| 44 |
+
#define to_le32(x) (x)
|
| 45 |
+
#define from_le32(x) (x)
|
| 46 |
+
#define to_le64(x) (x)
|
| 47 |
+
#define from_le64(x) (x)
|
| 48 |
+
#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
|
| 49 |
+
#define to_be16(x) (x)
|
| 50 |
+
#define from_be16(x) (x)
|
| 51 |
+
#define to_be32(x) (x)
|
| 52 |
+
#define from_be32(x) (x)
|
| 53 |
+
#define to_be64(x) (x)
|
| 54 |
+
#define from_be64(x) (x)
|
| 55 |
+
#define to_le16(x) thp_bswap16(x)
|
| 56 |
+
#define from_le16(x) thp_bswap16(x)
|
| 57 |
+
#define to_le32(x) thp_bswap32(x)
|
| 58 |
+
#define from_le32(x) thp_bswap32(x)
|
| 59 |
+
#define to_le64(x) thp_bswap64(x)
|
| 60 |
+
#define from_le64(x) thp_bswap64(x)
|
| 61 |
+
#else
|
| 62 |
+
#error Unexpected or undefined __BYTE_ORDER__
|
| 63 |
+
#endif
|
| 64 |
+
|
| 65 |
+
namespace torch::utils {
|
| 66 |
+
|
| 67 |
+
enum THPByteOrder { THP_LITTLE_ENDIAN = 0, THP_BIG_ENDIAN = 1 };
|
| 68 |
+
|
| 69 |
+
TORCH_API THPByteOrder THP_nativeByteOrder();
|
| 70 |
+
|
| 71 |
+
template <typename T, typename U>
|
| 72 |
+
TORCH_API void THP_decodeBuffer(T* dst, const uint8_t* src, U type, size_t len);
|
| 73 |
+
|
| 74 |
+
template <typename T>
|
| 75 |
+
TORCH_API void THP_encodeBuffer(
|
| 76 |
+
uint8_t* dst,
|
| 77 |
+
const T* src,
|
| 78 |
+
THPByteOrder order,
|
| 79 |
+
size_t len);
|
| 80 |
+
|
| 81 |
+
} // namespace torch::utils
|
phivenv/Lib/site-packages/torch/include/torch/csrc/utils/cpp_stacktraces.h
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#pragma once
|
| 2 |
+
|
| 3 |
+
#include <torch/csrc/Export.h>
|
| 4 |
+
#include <torch/csrc/profiler/unwind/unwind.h>
|
| 5 |
+
|
| 6 |
+
namespace torch {
|
| 7 |
+
TORCH_API bool get_cpp_stacktraces_enabled();
|
| 8 |
+
TORCH_API torch::unwind::Mode get_symbolize_mode();
|
| 9 |
+
} // namespace torch
|
phivenv/Lib/site-packages/torch/include/torch/csrc/utils/cuda_enabled.h
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#pragma once
|
| 2 |
+
|
| 3 |
+
namespace torch::utils {
|
| 4 |
+
|
| 5 |
+
inline constexpr bool cuda_enabled() {
|
| 6 |
+
#ifdef USE_CUDA
|
| 7 |
+
return true;
|
| 8 |
+
#else
|
| 9 |
+
return false;
|
| 10 |
+
#endif
|
| 11 |
+
}
|
| 12 |
+
|
| 13 |
+
} // namespace torch::utils
|
phivenv/Lib/site-packages/torch/include/torch/csrc/utils/device_lazy_init.h
ADDED
|
@@ -0,0 +1,87 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#pragma once
|
| 2 |
+
|
| 3 |
+
#include <c10/core/TensorOptions.h>
|
| 4 |
+
#include <torch/csrc/Export.h>
|
| 5 |
+
|
| 6 |
+
// device_lazy_init() is always compiled, even for CPU-only builds.
|
| 7 |
+
|
| 8 |
+
namespace torch::utils {
|
| 9 |
+
|
| 10 |
+
/**
|
| 11 |
+
* This mechanism of lazy initialization is designed for each device backend.
|
| 12 |
+
* Currently, CUDA and XPU follow this design. This function `device_lazy_init`
|
| 13 |
+
* MUST be called before you attempt to access any Type(CUDA or XPU) object
|
| 14 |
+
* from ATen, in any way. It guarantees that the device runtime status is lazily
|
| 15 |
+
* initialized when the first runtime API is requested.
|
| 16 |
+
*
|
| 17 |
+
* Here are some common ways that a device object may be retrieved:
|
| 18 |
+
* - You call getNonVariableType or getNonVariableTypeOpt
|
| 19 |
+
* - You call toBackend() on a Type
|
| 20 |
+
*
|
| 21 |
+
* It's important to do this correctly, because if you forget to add it you'll
|
| 22 |
+
* get an oblique error message seems like "Cannot initialize CUDA without
|
| 23 |
+
* ATen_cuda library" or "Cannot initialize XPU without ATen_xpu library" if you
|
| 24 |
+
* try to use CUDA or XPU functionality from a CPU-only build, which is not good
|
| 25 |
+
* UX.
|
| 26 |
+
*/
|
| 27 |
+
TORCH_PYTHON_API void device_lazy_init(at::DeviceType device_type);
|
| 28 |
+
TORCH_PYTHON_API void set_requires_device_init(
|
| 29 |
+
at::DeviceType device_type,
|
| 30 |
+
bool value);
|
| 31 |
+
|
| 32 |
+
inline bool is_device_lazy_init_supported(at::DeviceType device_type) {
|
| 33 |
+
// Add more devices here to enable lazy initialization.
|
| 34 |
+
return (
|
| 35 |
+
device_type == at::DeviceType::CUDA ||
|
| 36 |
+
device_type == at::DeviceType::XPU ||
|
| 37 |
+
device_type == at::DeviceType::HPU ||
|
| 38 |
+
device_type == at::DeviceType::MTIA ||
|
| 39 |
+
device_type == at::DeviceType::PrivateUse1);
|
| 40 |
+
}
|
| 41 |
+
|
| 42 |
+
inline void maybe_initialize_device(at::Device& device) {
|
| 43 |
+
if (is_device_lazy_init_supported(device.type())) {
|
| 44 |
+
device_lazy_init(device.type());
|
| 45 |
+
}
|
| 46 |
+
}
|
| 47 |
+
|
| 48 |
+
inline void maybe_initialize_device(std::optional<at::Device>& device) {
|
| 49 |
+
if (!device.has_value()) {
|
| 50 |
+
return;
|
| 51 |
+
}
|
| 52 |
+
maybe_initialize_device(device.value());
|
| 53 |
+
}
|
| 54 |
+
|
| 55 |
+
inline void maybe_initialize_device(const at::TensorOptions& options) {
|
| 56 |
+
auto device = options.device();
|
| 57 |
+
maybe_initialize_device(device);
|
| 58 |
+
}
|
| 59 |
+
|
| 60 |
+
inline void maybe_initialize_device(
|
| 61 |
+
std::optional<at::DeviceType>& device_type) {
|
| 62 |
+
if (!device_type.has_value()) {
|
| 63 |
+
return;
|
| 64 |
+
}
|
| 65 |
+
maybe_initialize_device(device_type.value());
|
| 66 |
+
}
|
| 67 |
+
|
| 68 |
+
bool is_device_initialized(at::DeviceType device_type);
|
| 69 |
+
|
| 70 |
+
TORCH_PYTHON_API bool is_device_in_bad_fork(at::DeviceType device_type);
|
| 71 |
+
|
| 72 |
+
TORCH_PYTHON_API void set_device_in_bad_fork(
|
| 73 |
+
at::DeviceType device_type,
|
| 74 |
+
bool value);
|
| 75 |
+
|
| 76 |
+
TORCH_PYTHON_API void register_fork_handler_for_device_init(
|
| 77 |
+
at::DeviceType device_type);
|
| 78 |
+
|
| 79 |
+
inline void maybe_register_fork_handler_for_device_init(
|
| 80 |
+
std::optional<at::DeviceType>& device_type) {
|
| 81 |
+
if (!device_type.has_value()) {
|
| 82 |
+
return;
|
| 83 |
+
}
|
| 84 |
+
register_fork_handler_for_device_init(device_type.value());
|
| 85 |
+
}
|
| 86 |
+
|
| 87 |
+
} // namespace torch::utils
|
phivenv/Lib/site-packages/torch/include/torch/csrc/utils/disable_torch_function.h
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#pragma once
|
| 2 |
+
#include <c10/core/DispatchKey.h>
|
| 3 |
+
#include <c10/core/impl/LocalDispatchKeySet.h>
|
| 4 |
+
#include <torch/csrc/python_headers.h>
|
| 5 |
+
|
| 6 |
+
namespace torch {
|
| 7 |
+
// Sometimes we don't want infinite recursion for subclasses,
|
| 8 |
+
// Or a way to achieve the old behaviour.
|
| 9 |
+
|
| 10 |
+
// This is an internal utility, not exposed to users.
|
| 11 |
+
bool torch_function_enabled();
|
| 12 |
+
PyObject* disabled_torch_function_impl();
|
| 13 |
+
PyObject* disabled_torch_dispatch_impl();
|
| 14 |
+
void set_disabled_torch_function_impl(PyObject* value);
|
| 15 |
+
void set_disabled_torch_dispatch_impl(PyObject* value);
|
| 16 |
+
// Set ignore_mode to true if you're trying to collect overloaded arguments;
|
| 17 |
+
// using mode here will improperly cause you to add ALL objects to the
|
| 18 |
+
// overloaded list even if they don't actually have __torch_function__
|
| 19 |
+
bool check_has_torch_function(PyObject* obj, bool ignore_mode = false);
|
| 20 |
+
|
| 21 |
+
struct DisableTorchDispatch {
|
| 22 |
+
DisableTorchDispatch()
|
| 23 |
+
: guard_(c10::DispatchKeySet(
|
| 24 |
+
{c10::DispatchKey::Python, c10::DispatchKey::PreDispatch})),
|
| 25 |
+
guard_tls_snapshot_(c10::DispatchKey::PythonTLSSnapshot) {}
|
| 26 |
+
c10::impl::ExcludeDispatchKeyGuard guard_;
|
| 27 |
+
c10::impl::ExcludeDispatchKeyGuard guard_tls_snapshot_;
|
| 28 |
+
};
|
| 29 |
+
|
| 30 |
+
} // namespace torch
|
| 31 |
+
|
| 32 |
+
PyObject* THPModule_isEnabledTorchFunction(PyObject* self, PyObject* unused);
|
| 33 |
+
PyObject* THPModule_isAllDisabledTorchFunction(
|
| 34 |
+
PyObject* self,
|
| 35 |
+
PyObject* unused);
|
| 36 |
+
PyObject* THPModule_DisableTorchFunctionType();
|
| 37 |
+
PyObject* THPModule_DisableTorchFunctionSubclassType();
|
| 38 |
+
PyObject* THPModule_disable_torch_function(PyObject* self, PyObject* args);
|
| 39 |
+
PyObject* THPModule_disable_torch_dispatch(PyObject* self, PyObject* args);
|
| 40 |
+
PyObject* THPModule_has_torch_function(PyObject*, PyObject* arg);
|
| 41 |
+
PyObject* THPModule_has_torch_function_unary(PyObject*, PyObject* obj);
|
| 42 |
+
PyObject* THPModule_has_torch_function_variadic(
|
| 43 |
+
PyObject*,
|
| 44 |
+
PyObject* const* args,
|
| 45 |
+
Py_ssize_t nargs);
|
phivenv/Lib/site-packages/torch/include/torch/csrc/utils/generated_serialization_types.h
ADDED
|
The diff for this file is too large to render.
See raw diff
|
|
|
phivenv/Lib/site-packages/torch/include/torch/csrc/utils/init.h
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#pragma once
|
| 2 |
+
|
| 3 |
+
#include <torch/csrc/utils/pybind.h>
|
| 4 |
+
|
| 5 |
+
namespace torch::throughput_benchmark {
|
| 6 |
+
|
| 7 |
+
void initThroughputBenchmarkBindings(PyObject* module);
|
| 8 |
+
|
| 9 |
+
} // namespace torch::throughput_benchmark
|
phivenv/Lib/site-packages/torch/include/torch/csrc/utils/invalid_arguments.h
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#pragma once
|
| 2 |
+
|
| 3 |
+
#include <torch/csrc/python_headers.h>
|
| 4 |
+
#include <string>
|
| 5 |
+
#include <vector>
|
| 6 |
+
|
| 7 |
+
namespace torch {
|
| 8 |
+
|
| 9 |
+
std::string format_invalid_args(
|
| 10 |
+
PyObject* given_args,
|
| 11 |
+
PyObject* given_kwargs,
|
| 12 |
+
const std::string& function_name,
|
| 13 |
+
const std::vector<std::string>& options);
|
| 14 |
+
|
| 15 |
+
} // namespace torch
|
phivenv/Lib/site-packages/torch/include/torch/csrc/utils/nested.h
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#pragma once
|
| 2 |
+
|
| 3 |
+
#include <torch/csrc/python_headers.h>
|
| 4 |
+
#include <torch/csrc/utils/python_arg_parser.h>
|
| 5 |
+
|
| 6 |
+
#include <ATen/core/Tensor.h>
|
| 7 |
+
|
| 8 |
+
namespace torch::utils {
|
| 9 |
+
|
| 10 |
+
at::Tensor nested_tensor_ctor(
|
| 11 |
+
c10::DispatchKey dispatch_key,
|
| 12 |
+
at::ScalarType scalar_type,
|
| 13 |
+
PythonArgs& r);
|
| 14 |
+
|
| 15 |
+
} // namespace torch::utils
|
phivenv/Lib/site-packages/torch/include/torch/csrc/utils/numpy_stub.h
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#pragma once
|
| 2 |
+
|
| 3 |
+
#include <torch/csrc/python_headers.h>
|
| 4 |
+
|
| 5 |
+
#ifdef USE_NUMPY
|
| 6 |
+
|
| 7 |
+
#if !defined(NO_IMPORT_ARRAY) && !defined(WITH_NUMPY_IMPORT_ARRAY)
|
| 8 |
+
#define NO_IMPORT_ARRAY
|
| 9 |
+
#endif
|
| 10 |
+
|
| 11 |
+
#ifndef PY_ARRAY_UNIQUE_SYMBOL
|
| 12 |
+
#define PY_ARRAY_UNIQUE_SYMBOL __numpy_array_api
|
| 13 |
+
#endif
|
| 14 |
+
|
| 15 |
+
#ifndef NPY_NO_DEPRECATED_API
|
| 16 |
+
#define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION
|
| 17 |
+
#endif
|
| 18 |
+
|
| 19 |
+
#include <numpy/arrayobject.h>
|
| 20 |
+
|
| 21 |
+
#endif // USE_NUMPY
|
phivenv/Lib/site-packages/torch/include/torch/csrc/utils/object_ptr.h
ADDED
|
@@ -0,0 +1,81 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#pragma once
|
| 2 |
+
|
| 3 |
+
#include <torch/csrc/Export.h>
|
| 4 |
+
#include <torch/csrc/python_headers.h>
|
| 5 |
+
#include <utility>
|
| 6 |
+
|
| 7 |
+
template <class T>
|
| 8 |
+
class TORCH_PYTHON_API THPPointer {
|
| 9 |
+
public:
|
| 10 |
+
THPPointer() : ptr(nullptr) {}
|
| 11 |
+
explicit THPPointer(T* ptr) noexcept : ptr(ptr) {}
|
| 12 |
+
THPPointer(THPPointer&& p) noexcept : ptr(std::exchange(p.ptr, nullptr)) {}
|
| 13 |
+
THPPointer(const THPPointer& p) = delete;
|
| 14 |
+
THPPointer& operator=(const THPPointer&) = delete;
|
| 15 |
+
|
| 16 |
+
~THPPointer() {
|
| 17 |
+
free();
|
| 18 |
+
}
|
| 19 |
+
T* get() {
|
| 20 |
+
return ptr;
|
| 21 |
+
}
|
| 22 |
+
const T* get() const {
|
| 23 |
+
return ptr;
|
| 24 |
+
}
|
| 25 |
+
THPPointer dup() const {
|
| 26 |
+
return dup(ptr);
|
| 27 |
+
}
|
| 28 |
+
static THPPointer dup(const T* ptr) {
|
| 29 |
+
Py_XINCREF(ptr);
|
| 30 |
+
return THPPointer(
|
| 31 |
+
const_cast<T*>(ptr)); // NOLINT(cppcoreguidelines-pro-type-const-cast)
|
| 32 |
+
}
|
| 33 |
+
static THPPointer none() {
|
| 34 |
+
Py_INCREF(Py_None);
|
| 35 |
+
return THPPointer(reinterpret_cast<T*>(Py_None));
|
| 36 |
+
}
|
| 37 |
+
T* release() {
|
| 38 |
+
T* tmp = ptr;
|
| 39 |
+
ptr = nullptr;
|
| 40 |
+
return tmp;
|
| 41 |
+
}
|
| 42 |
+
operator T*() {
|
| 43 |
+
return ptr;
|
| 44 |
+
}
|
| 45 |
+
THPPointer& operator=(T* new_ptr) noexcept {
|
| 46 |
+
free();
|
| 47 |
+
ptr = new_ptr;
|
| 48 |
+
return *this;
|
| 49 |
+
}
|
| 50 |
+
THPPointer& operator=(THPPointer&& p) noexcept {
|
| 51 |
+
free();
|
| 52 |
+
ptr = p.ptr;
|
| 53 |
+
p.ptr = nullptr;
|
| 54 |
+
return *this;
|
| 55 |
+
}
|
| 56 |
+
T* operator->() {
|
| 57 |
+
return ptr;
|
| 58 |
+
}
|
| 59 |
+
explicit operator bool() const {
|
| 60 |
+
return ptr != nullptr;
|
| 61 |
+
}
|
| 62 |
+
|
| 63 |
+
private:
|
| 64 |
+
void free();
|
| 65 |
+
T* ptr = nullptr;
|
| 66 |
+
};
|
| 67 |
+
|
| 68 |
+
/**
|
| 69 |
+
* An RAII-style, owning pointer to a PyObject. You must protect
|
| 70 |
+
* destruction of this object with the GIL.
|
| 71 |
+
*
|
| 72 |
+
* WARNING: Think twice before putting this as a field in a C++
|
| 73 |
+
* struct. This class does NOT take out the GIL on destruction,
|
| 74 |
+
* so if you will need to ensure that the destructor of your struct
|
| 75 |
+
* is either (a) always invoked when the GIL is taken or (b) takes
|
| 76 |
+
* out the GIL itself. Easiest way to avoid this problem is to
|
| 77 |
+
* not use THPPointer in this situation.
|
| 78 |
+
*/
|
| 79 |
+
using THPObjectPtr = THPPointer<PyObject>;
|
| 80 |
+
using THPCodeObjectPtr = THPPointer<PyCodeObject>;
|
| 81 |
+
using THPFrameObjectPtr = THPPointer<PyFrameObject>;
|
phivenv/Lib/site-packages/torch/include/torch/csrc/utils/out_types.h
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#pragma once
|
| 2 |
+
|
| 3 |
+
#include <ATen/core/Tensor.h>
|
| 4 |
+
|
| 5 |
+
namespace torch::utils {
|
| 6 |
+
|
| 7 |
+
TORCH_API void check_out_type_matches(
|
| 8 |
+
const at::Tensor& result,
|
| 9 |
+
std::optional<at::ScalarType> scalarType,
|
| 10 |
+
bool scalarType_is_none,
|
| 11 |
+
std::optional<at::Layout> layout,
|
| 12 |
+
std::optional<at::Device> device,
|
| 13 |
+
bool device_is_none);
|
| 14 |
+
|
| 15 |
+
}
|
phivenv/Lib/site-packages/torch/include/torch/csrc/utils/pybind.h
ADDED
|
@@ -0,0 +1,420 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#pragma once
|
| 2 |
+
|
| 3 |
+
#include <torch/csrc/python_headers.h>
|
| 4 |
+
#include <torch/csrc/utils/pythoncapi_compat.h>
|
| 5 |
+
|
| 6 |
+
#include <ATen/core/Tensor.h>
|
| 7 |
+
#include <ATen/core/jit_type_base.h>
|
| 8 |
+
#include <c10/util/irange.h>
|
| 9 |
+
#include <pybind11/pybind11.h>
|
| 10 |
+
#include <pybind11/stl.h>
|
| 11 |
+
|
| 12 |
+
#include <torch/csrc/Device.h>
|
| 13 |
+
#include <torch/csrc/Dtype.h>
|
| 14 |
+
#include <torch/csrc/DynamicTypes.h>
|
| 15 |
+
#include <torch/csrc/Generator.h>
|
| 16 |
+
#include <torch/csrc/MemoryFormat.h>
|
| 17 |
+
#include <torch/csrc/Stream.h>
|
| 18 |
+
#include <torch/csrc/utils/tensor_memoryformats.h>
|
| 19 |
+
|
| 20 |
+
namespace py = pybind11;
|
| 21 |
+
|
| 22 |
+
#define IS_PYBIND_2_13_PLUS PYBIND11_VERSION_HEX >= 0x020D0000
|
| 23 |
+
|
| 24 |
+
// This makes intrusive_ptr to be available as a custom pybind11 holder type,
|
| 25 |
+
// see
|
| 26 |
+
// https://pybind11.readthedocs.io/en/stable/advanced/smart_ptrs.html#custom-smart-pointers
|
| 27 |
+
PYBIND11_DECLARE_HOLDER_TYPE(T, c10::intrusive_ptr<T>, true)
|
| 28 |
+
|
| 29 |
+
PYBIND11_DECLARE_HOLDER_TYPE(T, c10::SingletonOrSharedTypePtr<T>)
|
| 30 |
+
PYBIND11_DECLARE_HOLDER_TYPE(T, c10::SingletonTypePtr<T>, true)
|
| 31 |
+
|
| 32 |
+
namespace pybind11::detail {
|
| 33 |
+
|
| 34 |
+
// torch.Tensor <-> at::Tensor conversions (without unwrapping)
|
| 35 |
+
template <>
|
| 36 |
+
struct TORCH_PYTHON_API type_caster<at::Tensor> {
|
| 37 |
+
public:
|
| 38 |
+
// NOLINTNEXTLINE(cppcoreguidelines-non-private-member-variables-in-classes)
|
| 39 |
+
PYBIND11_TYPE_CASTER(at::Tensor, _("torch.Tensor"));
|
| 40 |
+
|
| 41 |
+
bool load(handle src, bool);
|
| 42 |
+
|
| 43 |
+
static handle cast(
|
| 44 |
+
const at::Tensor& src,
|
| 45 |
+
return_value_policy /* policy */,
|
| 46 |
+
handle /* parent */);
|
| 47 |
+
};
|
| 48 |
+
|
| 49 |
+
// torch._StorageBase <-> at::Storage
|
| 50 |
+
template <>
|
| 51 |
+
struct type_caster<at::Storage> {
|
| 52 |
+
public:
|
| 53 |
+
// NOLINTNEXTLINE(cppcoreguidelines-non-private-member-variables-in-classes)
|
| 54 |
+
PYBIND11_TYPE_CASTER(at::Storage, _("torch.StorageBase"));
|
| 55 |
+
|
| 56 |
+
bool load(handle src, bool) {
|
| 57 |
+
PyObject* obj = src.ptr();
|
| 58 |
+
if (torch::isStorage(obj)) {
|
| 59 |
+
value = torch::createStorage(obj);
|
| 60 |
+
return true;
|
| 61 |
+
}
|
| 62 |
+
return false;
|
| 63 |
+
}
|
| 64 |
+
|
| 65 |
+
static handle cast(
|
| 66 |
+
const at::Storage& src,
|
| 67 |
+
return_value_policy /* policy */,
|
| 68 |
+
handle /* parent */) {
|
| 69 |
+
return handle(torch::createPyObject(src));
|
| 70 |
+
}
|
| 71 |
+
};
|
| 72 |
+
|
| 73 |
+
template <>
|
| 74 |
+
struct type_caster<at::Generator> {
|
| 75 |
+
public:
|
| 76 |
+
// NOLINTNEXTLINE(cppcoreguidelines-non-private-member-variables-in-classes)
|
| 77 |
+
PYBIND11_TYPE_CASTER(at::Generator, _("torch.Generator"));
|
| 78 |
+
|
| 79 |
+
bool load(handle src, bool) {
|
| 80 |
+
PyObject* obj = src.ptr();
|
| 81 |
+
if (THPGenerator_Check(obj)) {
|
| 82 |
+
value = reinterpret_cast<THPGenerator*>(obj)->cdata;
|
| 83 |
+
return true;
|
| 84 |
+
}
|
| 85 |
+
return false;
|
| 86 |
+
}
|
| 87 |
+
|
| 88 |
+
static handle cast(
|
| 89 |
+
const at::Generator& src,
|
| 90 |
+
return_value_policy /* policy */,
|
| 91 |
+
handle /* parent */) {
|
| 92 |
+
return handle(THPGenerator_Wrap(src));
|
| 93 |
+
}
|
| 94 |
+
};
|
| 95 |
+
|
| 96 |
+
template <>
|
| 97 |
+
struct TORCH_PYTHON_API type_caster<at::IntArrayRef> {
|
| 98 |
+
public:
|
| 99 |
+
// NOLINTNEXTLINE(cppcoreguidelines-non-private-member-variables-in-classes)
|
| 100 |
+
PYBIND11_TYPE_CASTER(at::IntArrayRef, _("Tuple[int, ...]"));
|
| 101 |
+
|
| 102 |
+
bool load(handle src, bool);
|
| 103 |
+
static handle cast(
|
| 104 |
+
at::IntArrayRef src,
|
| 105 |
+
return_value_policy /* policy */,
|
| 106 |
+
handle /* parent */);
|
| 107 |
+
|
| 108 |
+
private:
|
| 109 |
+
std::vector<int64_t> v_value;
|
| 110 |
+
};
|
| 111 |
+
|
| 112 |
+
template <>
|
| 113 |
+
struct TORCH_PYTHON_API type_caster<at::SymIntArrayRef> {
|
| 114 |
+
public:
|
| 115 |
+
// NOLINTNEXTLINE(cppcoreguidelines-non-private-member-variables-in-classes)
|
| 116 |
+
PYBIND11_TYPE_CASTER(at::SymIntArrayRef, _("List[int]"));
|
| 117 |
+
|
| 118 |
+
bool load(handle src, bool);
|
| 119 |
+
static handle cast(
|
| 120 |
+
at::SymIntArrayRef src,
|
| 121 |
+
return_value_policy /* policy */,
|
| 122 |
+
handle /* parent */);
|
| 123 |
+
|
| 124 |
+
private:
|
| 125 |
+
std::vector<c10::SymInt> v_value;
|
| 126 |
+
};
|
| 127 |
+
|
| 128 |
+
template <>
|
| 129 |
+
struct TORCH_PYTHON_API type_caster<at::ArrayRef<c10::SymNode>> {
|
| 130 |
+
public:
|
| 131 |
+
// NOLINTNEXTLINE(cppcoreguidelines-non-private-member-variables-in-classes)
|
| 132 |
+
PYBIND11_TYPE_CASTER(at::ArrayRef<c10::SymNode>, _("List[SymNode]"));
|
| 133 |
+
|
| 134 |
+
bool load(handle src, bool);
|
| 135 |
+
static handle cast(
|
| 136 |
+
at::ArrayRef<c10::SymNode> src,
|
| 137 |
+
return_value_policy /* policy */,
|
| 138 |
+
handle /* parent */);
|
| 139 |
+
|
| 140 |
+
private:
|
| 141 |
+
std::vector<c10::SymNode> v_value;
|
| 142 |
+
};
|
| 143 |
+
|
| 144 |
+
template <>
|
| 145 |
+
struct type_caster<at::MemoryFormat> {
|
| 146 |
+
public:
|
| 147 |
+
// NOLINTNEXTLINE(cppcoreguidelines-non-private-member-variables-in-classes)
|
| 148 |
+
PYBIND11_TYPE_CASTER(at::MemoryFormat, _("torch.memory_format"));
|
| 149 |
+
|
| 150 |
+
bool load(handle src, bool) {
|
| 151 |
+
PyObject* obj = src.ptr();
|
| 152 |
+
if (THPMemoryFormat_Check(obj)) {
|
| 153 |
+
value = reinterpret_cast<THPMemoryFormat*>(obj)->memory_format;
|
| 154 |
+
return true;
|
| 155 |
+
}
|
| 156 |
+
return false;
|
| 157 |
+
}
|
| 158 |
+
static handle cast(
|
| 159 |
+
at::MemoryFormat src,
|
| 160 |
+
return_value_policy /* policy */,
|
| 161 |
+
handle /* parent */) {
|
| 162 |
+
return handle(Py_NewRef(torch::utils::getTHPMemoryFormat(src)));
|
| 163 |
+
}
|
| 164 |
+
};
|
| 165 |
+
|
| 166 |
+
template <>
|
| 167 |
+
struct type_caster<at::Device> {
|
| 168 |
+
public:
|
| 169 |
+
// NOLINTNEXTLINE(cppcoreguidelines-non-private-member-variables-in-classes)
|
| 170 |
+
PYBIND11_TYPE_CASTER(at::Device, _("torch.device"));
|
| 171 |
+
|
| 172 |
+
// PYBIND11_TYPE_CASTER defines a member field called value. Since at::Device
|
| 173 |
+
// cannot be default-initialized, we provide this constructor to explicitly
|
| 174 |
+
// initialize that field. The value doesn't matter as it will be overwritten
|
| 175 |
+
// after a successful call to load.
|
| 176 |
+
type_caster() : value(c10::kCPU) {}
|
| 177 |
+
|
| 178 |
+
bool load(handle src, bool) {
|
| 179 |
+
PyObject* obj = src.ptr();
|
| 180 |
+
if (THPDevice_Check(obj)) {
|
| 181 |
+
value = reinterpret_cast<THPDevice*>(obj)->device;
|
| 182 |
+
return true;
|
| 183 |
+
}
|
| 184 |
+
return false;
|
| 185 |
+
}
|
| 186 |
+
|
| 187 |
+
static handle cast(
|
| 188 |
+
const at::Device& src,
|
| 189 |
+
return_value_policy /* policy */,
|
| 190 |
+
handle /* parent */) {
|
| 191 |
+
return handle(THPDevice_New(src));
|
| 192 |
+
}
|
| 193 |
+
};
|
| 194 |
+
|
| 195 |
+
template <>
|
| 196 |
+
struct type_caster<at::ScalarType> {
|
| 197 |
+
public:
|
| 198 |
+
// NOLINTNEXTLINE(cppcoreguidelines-non-private-member-variables-in-classes)
|
| 199 |
+
PYBIND11_TYPE_CASTER(at::ScalarType, _("torch.dtype"));
|
| 200 |
+
|
| 201 |
+
// PYBIND11_TYPE_CASTER defines a member field called value. at::ScalarType
|
| 202 |
+
// cannot be default-initialized, we provide this constructor to explicitly
|
| 203 |
+
// initialize that field. The value doesn't matter as it will be overwritten
|
| 204 |
+
// after a successful call to load.
|
| 205 |
+
type_caster() : value(at::kFloat) {}
|
| 206 |
+
|
| 207 |
+
bool load(handle src, bool) {
|
| 208 |
+
PyObject* obj = src.ptr();
|
| 209 |
+
if (THPDtype_Check(obj)) {
|
| 210 |
+
value = reinterpret_cast<THPDtype*>(obj)->scalar_type;
|
| 211 |
+
return true;
|
| 212 |
+
}
|
| 213 |
+
return false;
|
| 214 |
+
}
|
| 215 |
+
|
| 216 |
+
static handle cast(
|
| 217 |
+
const at::ScalarType& src,
|
| 218 |
+
return_value_policy /* policy */,
|
| 219 |
+
handle /* parent */) {
|
| 220 |
+
return Py_NewRef(torch::getTHPDtype(src));
|
| 221 |
+
}
|
| 222 |
+
};
|
| 223 |
+
|
| 224 |
+
template <>
|
| 225 |
+
struct type_caster<c10::Stream> {
|
| 226 |
+
public:
|
| 227 |
+
// NOLINTNEXTLINE(cppcoreguidelines-non-private-member-variables-in-classes)
|
| 228 |
+
PYBIND11_TYPE_CASTER(c10::Stream, _("torch.Stream"));
|
| 229 |
+
|
| 230 |
+
// PYBIND11_TYPE_CASTER defines a member field called value. Since c10::Stream
|
| 231 |
+
// cannot be default-initialized, we provide this constructor to explicitly
|
| 232 |
+
// initialize that field. The value doesn't matter as it will be overwritten
|
| 233 |
+
// after a successful call to load.
|
| 234 |
+
type_caster() : value(c10::Stream::DEFAULT, c10::Device(c10::kCPU, 0)) {}
|
| 235 |
+
|
| 236 |
+
bool load(handle src, bool) {
|
| 237 |
+
PyObject* obj = src.ptr();
|
| 238 |
+
if (THPStream_Check(obj)) {
|
| 239 |
+
value = c10::Stream::unpack3(
|
| 240 |
+
((THPStream*)obj)->stream_id,
|
| 241 |
+
static_cast<c10::DeviceIndex>(((THPStream*)obj)->device_index),
|
| 242 |
+
static_cast<c10::DeviceType>(((THPStream*)obj)->device_type));
|
| 243 |
+
return true;
|
| 244 |
+
}
|
| 245 |
+
return false;
|
| 246 |
+
}
|
| 247 |
+
|
| 248 |
+
static handle cast(
|
| 249 |
+
const c10::Stream& src,
|
| 250 |
+
return_value_policy /* policy */,
|
| 251 |
+
handle /* parent */) {
|
| 252 |
+
return handle(THPStream_Wrap(src));
|
| 253 |
+
}
|
| 254 |
+
};
|
| 255 |
+
|
| 256 |
+
template <>
|
| 257 |
+
struct type_caster<c10::DispatchKey>
|
| 258 |
+
: public type_caster_base<c10::DispatchKey> {
|
| 259 |
+
using base = type_caster_base<c10::DispatchKey>;
|
| 260 |
+
c10::DispatchKey tmp{};
|
| 261 |
+
|
| 262 |
+
public:
|
| 263 |
+
bool load(handle src, bool convert) {
|
| 264 |
+
if (base::load(src, convert)) {
|
| 265 |
+
return true;
|
| 266 |
+
} else if (py::isinstance(
|
| 267 |
+
src, py::module_::import("builtins").attr("str"))) {
|
| 268 |
+
tmp = c10::parseDispatchKey(py::cast<std::string>(src));
|
| 269 |
+
value = &tmp;
|
| 270 |
+
return true;
|
| 271 |
+
}
|
| 272 |
+
return false;
|
| 273 |
+
}
|
| 274 |
+
|
| 275 |
+
static handle cast(
|
| 276 |
+
c10::DispatchKey src,
|
| 277 |
+
return_value_policy policy,
|
| 278 |
+
handle parent) {
|
| 279 |
+
return base::cast(src, policy, parent);
|
| 280 |
+
}
|
| 281 |
+
};
|
| 282 |
+
|
| 283 |
+
template <>
|
| 284 |
+
struct TORCH_PYTHON_API type_caster<c10::Scalar> {
|
| 285 |
+
public:
|
| 286 |
+
PYBIND11_TYPE_CASTER(
|
| 287 |
+
c10::Scalar,
|
| 288 |
+
_("Union[Number, torch.SymInt, torch.SymFloat, torch.SymBool]"));
|
| 289 |
+
bool load(py::handle src, bool);
|
| 290 |
+
|
| 291 |
+
static py::handle cast(
|
| 292 |
+
const c10::Scalar& si,
|
| 293 |
+
return_value_policy /* policy */,
|
| 294 |
+
handle /* parent */);
|
| 295 |
+
};
|
| 296 |
+
|
| 297 |
+
template <>
|
| 298 |
+
struct TORCH_PYTHON_API type_caster<c10::SymInt> {
|
| 299 |
+
public:
|
| 300 |
+
PYBIND11_TYPE_CASTER(c10::SymInt, _("Union[int, torch.SymInt]"));
|
| 301 |
+
bool load(py::handle src, bool);
|
| 302 |
+
|
| 303 |
+
static py::handle cast(
|
| 304 |
+
const c10::SymInt& si,
|
| 305 |
+
return_value_policy /* policy */,
|
| 306 |
+
handle /* parent */);
|
| 307 |
+
};
|
| 308 |
+
|
| 309 |
+
template <>
|
| 310 |
+
struct TORCH_PYTHON_API type_caster<c10::SymFloat> {
|
| 311 |
+
public:
|
| 312 |
+
PYBIND11_TYPE_CASTER(c10::SymFloat, _("float"));
|
| 313 |
+
bool load(py::handle src, bool);
|
| 314 |
+
|
| 315 |
+
static py::handle cast(
|
| 316 |
+
const c10::SymFloat& si,
|
| 317 |
+
return_value_policy /* policy */,
|
| 318 |
+
handle /* parent */);
|
| 319 |
+
};
|
| 320 |
+
|
| 321 |
+
template <>
|
| 322 |
+
struct TORCH_PYTHON_API type_caster<c10::SymBool> {
|
| 323 |
+
public:
|
| 324 |
+
PYBIND11_TYPE_CASTER(c10::SymBool, _("Union[bool, torch.SymBool]"));
|
| 325 |
+
bool load(py::handle src, bool);
|
| 326 |
+
|
| 327 |
+
static py::handle cast(
|
| 328 |
+
const c10::SymBool& si,
|
| 329 |
+
return_value_policy /* policy */,
|
| 330 |
+
handle /* parent */);
|
| 331 |
+
};
|
| 332 |
+
|
| 333 |
+
template <typename T>
|
| 334 |
+
struct type_caster<c10::complex<T>> {
|
| 335 |
+
public:
|
| 336 |
+
// NOLINTNEXTLINE(cppcoreguidelines-non-private-member-variables-in-classes)
|
| 337 |
+
PYBIND11_TYPE_CASTER(c10::complex<T>, _("complex"));
|
| 338 |
+
|
| 339 |
+
bool load(handle src, bool) {
|
| 340 |
+
PyObject* obj = src.ptr();
|
| 341 |
+
|
| 342 |
+
// Referred from `THPUtils_unpackComplexDouble`
|
| 343 |
+
Py_complex py_complex = PyComplex_AsCComplex(obj);
|
| 344 |
+
if (py_complex.real == -1.0 && PyErr_Occurred()) {
|
| 345 |
+
return false;
|
| 346 |
+
}
|
| 347 |
+
|
| 348 |
+
// Python's Complex is always double precision.
|
| 349 |
+
value = c10::complex<double>(py_complex.real, py_complex.imag);
|
| 350 |
+
return true;
|
| 351 |
+
}
|
| 352 |
+
|
| 353 |
+
static handle cast(
|
| 354 |
+
const c10::complex<T>& complex,
|
| 355 |
+
return_value_policy /* policy */,
|
| 356 |
+
handle /* parent */) {
|
| 357 |
+
// Python only knows double precision complex.
|
| 358 |
+
return handle(PyComplex_FromDoubles(complex.real(), complex.imag()));
|
| 359 |
+
}
|
| 360 |
+
};
|
| 361 |
+
|
| 362 |
+
} // namespace pybind11::detail
|
| 363 |
+
|
| 364 |
+
namespace torch::impl {
|
| 365 |
+
|
| 366 |
+
// Use this function if you have a C++ object that is used from both C++
|
| 367 |
+
// and Python contexts, and you need its GIL to be released when you
|
| 368 |
+
// destruct it in the Python context.
|
| 369 |
+
//
|
| 370 |
+
// This function is a valid shared_ptr destructor and can be used to
|
| 371 |
+
// conveniently allocate a shared_ptr to an object whose destructor will be run
|
| 372 |
+
// without the GIL. Pass it as the second argument to shared_ptr, e.g.,
|
| 373 |
+
//
|
| 374 |
+
// shared_ptr<T>(new T(), destroy_without_gil<T>)
|
| 375 |
+
//
|
| 376 |
+
// Attaching the GIL release logic to the holder pointer rather than the
|
| 377 |
+
// actual destructor of T is helpful when T is Python-agnostic and
|
| 378 |
+
// shouldn't refer to the PYthon API.
|
| 379 |
+
//
|
| 380 |
+
// Note there are limitations to the correctness of code that makes use of this.
|
| 381 |
+
// In particular, if a shared_ptr is constructed from C++ code without this
|
| 382 |
+
// destructor and then passed to pybind11, pybind11 will happily take ownership
|
| 383 |
+
// of the shared_ptr (and be willing to destruct it from a context where it is
|
| 384 |
+
// holding the GIL). unique_ptr with a type branded deleter is less prone to
|
| 385 |
+
// this problem, because a stock deleter unique_ptr is not convertible with it.
|
| 386 |
+
// I plan to mitigate this problem by adding DEBUG-only asserts to the true C++
|
| 387 |
+
// destructors that the GIL is not held (using a virtual call to get to the
|
| 388 |
+
// Python interpreter); alternately, we could use a virtual call to simply
|
| 389 |
+
// ensure we release the GIL in the C++ destructor, however, this is a layering
|
| 390 |
+
// violation (why does code that is ostensibly Python agnostic calling into the
|
| 391 |
+
// GIL).
|
| 392 |
+
//
|
| 393 |
+
// Adapted from
|
| 394 |
+
// https://github.com/pybind/pybind11/issues/1446#issuecomment-406341510
|
| 395 |
+
template <typename T>
|
| 396 |
+
inline void destroy_without_gil(T* ptr) {
|
| 397 |
+
// Because the ownership of a shared_ptr is diffuse, it's not possible to
|
| 398 |
+
// necessarily predict whether or not the last reference to an object will
|
| 399 |
+
// be destructed from Python or C++. This means that in the destructor here,
|
| 400 |
+
// we don't necessarily know if we actually have the GIL or not; in fact,
|
| 401 |
+
// we don't even know if the Python interpreter still exists! Thus, we have
|
| 402 |
+
// to test for it before releasing the GIL.
|
| 403 |
+
//
|
| 404 |
+
// PyGILState_Check is hopefully self explanatory. But Py_IsInitialized or
|
| 405 |
+
// _PyIsFinalizing? Both get set at the same time during the Python
|
| 406 |
+
// destruction process:
|
| 407 |
+
// https://github.com/python/cpython/blob/d92513390a1a0da781bb08c284136f4d7abea36d/Python/pylifecycle.c#L1716-L1717
|
| 408 |
+
// so the operant question is whether or not you want to release the GIL after
|
| 409 |
+
// finalization has completed (and there is just no Python interpreter).
|
| 410 |
+
// Clearly there is no need to release GIL in that state, so we want
|
| 411 |
+
// Py_IsInitialized.
|
| 412 |
+
if (Py_IsInitialized() && PyGILState_Check()) {
|
| 413 |
+
pybind11::gil_scoped_release nogil;
|
| 414 |
+
delete ptr;
|
| 415 |
+
} else {
|
| 416 |
+
delete ptr;
|
| 417 |
+
}
|
| 418 |
+
}
|
| 419 |
+
|
| 420 |
+
} // namespace torch::impl
|
phivenv/Lib/site-packages/torch/include/torch/csrc/utils/pycfunction_helpers.h
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#pragma once
|
| 2 |
+
|
| 3 |
+
#include <c10/macros/Macros.h>
|
| 4 |
+
|
| 5 |
+
#include <Python.h>
|
| 6 |
+
|
| 7 |
+
inline PyCFunction castPyCFunctionWithKeywords(PyCFunctionWithKeywords func) {
|
| 8 |
+
C10_DIAGNOSTIC_PUSH_AND_IGNORED_IF_DEFINED("-Wcast-function-type")
|
| 9 |
+
C10_DIAGNOSTIC_PUSH_AND_IGNORED_IF_DEFINED("-Wcast-function-type-strict")
|
| 10 |
+
return reinterpret_cast<PyCFunction>(func);
|
| 11 |
+
C10_DIAGNOSTIC_POP()
|
| 12 |
+
C10_DIAGNOSTIC_POP()
|
| 13 |
+
}
|
phivenv/Lib/site-packages/torch/include/torch/csrc/utils/pyobject_preservation.h
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#pragma once
|
| 2 |
+
|
| 3 |
+
#include <torch/csrc/python_headers.h>
|
| 4 |
+
|
| 5 |
+
// This file contains utilities used for handling PyObject preservation
|
| 6 |
+
|
| 7 |
+
void clear_slots(PyTypeObject* type, PyObject* self);
|
phivenv/Lib/site-packages/torch/include/torch/csrc/utils/python_arg_parser.h
ADDED
|
@@ -0,0 +1,1303 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#pragma once
|
| 2 |
+
|
| 3 |
+
// Parse arguments to Python functions implemented in C++
|
| 4 |
+
// This is similar to PyArg_ParseTupleAndKeywords(), but specifically handles
|
| 5 |
+
// the types relevant to PyTorch and distinguishes between overloaded function
|
| 6 |
+
// signatures.
|
| 7 |
+
//
|
| 8 |
+
// Example:
|
| 9 |
+
//
|
| 10 |
+
// static PythonArgParser parser({
|
| 11 |
+
// "norm(Scalar p, int64_t dim, bool keepdim=False)",
|
| 12 |
+
// "norm(Scalar p=2)",
|
| 13 |
+
// });
|
| 14 |
+
// ParsedArgs<3> parsed_args;
|
| 15 |
+
// auto r = parser.parse(args, kwargs, parsed_args);
|
| 16 |
+
// if (r.idx == 0) {
|
| 17 |
+
// norm(r.scalar(0), r.int64(1), r.bool(0));
|
| 18 |
+
// } else {
|
| 19 |
+
// norm(r.scalar(0));
|
| 20 |
+
// }
|
| 21 |
+
//
|
| 22 |
+
// We auto-generate most uses of PythonArgParser; the generated files
|
| 23 |
+
// are torch/csrc/autograd/generated/python_*.cpp
|
| 24 |
+
//
|
| 25 |
+
// Some gotchas that you should watch out for:
|
| 26 |
+
//
|
| 27 |
+
// - Note [Order of overloads matters]
|
| 28 |
+
// Order of overloads matters. A set of input arguments may
|
| 29 |
+
// bind to multiple argument specs; we will always pick the
|
| 30 |
+
// first one in PythonArgParser. However, when you are writing
|
| 31 |
+
// overloads in, e.g., native_functions.yaml, you don't have to
|
| 32 |
+
// worry about what order you write them, because the code
|
| 33 |
+
// generation logic always gives the overloads a canonical
|
| 34 |
+
// order, where Tensor overloads come first, before Scalar overloads.
|
| 35 |
+
// This logic is in sort_declarations in
|
| 36 |
+
// tools/autograd/gen_python_functions.py
|
| 37 |
+
//
|
| 38 |
+
// - Zero-dim tensors (e.g., torch.tensor(2)) bind to both
|
| 39 |
+
// Scalar and Tensor, UNLESS they require grad (in which case
|
| 40 |
+
// they only bind to Tensor).
|
| 41 |
+
|
| 42 |
+
#include <pybind11/pytypes.h>
|
| 43 |
+
#include <torch/csrc/python_headers.h>
|
| 44 |
+
|
| 45 |
+
#include <torch/csrc/Device.h>
|
| 46 |
+
#include <torch/csrc/Dtype.h>
|
| 47 |
+
#include <torch/csrc/DynamicTypes.h>
|
| 48 |
+
#include <torch/csrc/Exceptions.h>
|
| 49 |
+
#include <torch/csrc/Export.h>
|
| 50 |
+
#include <torch/csrc/Generator.h>
|
| 51 |
+
#include <torch/csrc/Layout.h>
|
| 52 |
+
#include <torch/csrc/MemoryFormat.h>
|
| 53 |
+
#include <torch/csrc/QScheme.h>
|
| 54 |
+
#include <torch/csrc/Stream.h>
|
| 55 |
+
#include <torch/csrc/autograd/python_variable.h>
|
| 56 |
+
#include <torch/csrc/autograd/variable.h>
|
| 57 |
+
#include <torch/csrc/dynamo/eval_frame.h>
|
| 58 |
+
#include <torch/csrc/jit/frontend/tracer.h>
|
| 59 |
+
#include <torch/csrc/python_dimname.h>
|
| 60 |
+
#include <torch/csrc/tensor/python_tensor.h>
|
| 61 |
+
#include <torch/csrc/utils/disable_torch_function.h>
|
| 62 |
+
#include <torch/csrc/utils/object_ptr.h>
|
| 63 |
+
#include <torch/csrc/utils/pybind.h>
|
| 64 |
+
#include <torch/csrc/utils/python_numbers.h>
|
| 65 |
+
#include <torch/csrc/utils/python_strings.h>
|
| 66 |
+
#include <torch/csrc/utils/python_symnode.h>
|
| 67 |
+
#include <torch/csrc/utils/six.h>
|
| 68 |
+
|
| 69 |
+
#include <ATen/DeviceAccelerator.h>
|
| 70 |
+
#include <ATen/PythonTorchFunctionTLS.h>
|
| 71 |
+
#include <ATen/core/Tensor.h>
|
| 72 |
+
#include <c10/util/Exception.h>
|
| 73 |
+
#include <c10/util/irange.h>
|
| 74 |
+
|
| 75 |
+
#include <c10/core/SymFloat.h>
|
| 76 |
+
#include <c10/core/SymNodeImpl.h>
|
| 77 |
+
|
| 78 |
+
#include <c10/core/DispatchKeySet.h>
|
| 79 |
+
#include <array>
|
| 80 |
+
#include <cstddef>
|
| 81 |
+
#include <string>
|
| 82 |
+
#include <vector>
|
| 83 |
+
|
| 84 |
+
inline bool THPUtils_checkScalar(PyObject* obj) {
|
| 85 |
+
#ifdef USE_NUMPY
|
| 86 |
+
if (torch::utils::is_numpy_scalar(obj)) {
|
| 87 |
+
return true;
|
| 88 |
+
}
|
| 89 |
+
#endif
|
| 90 |
+
return PyFloat_Check(obj) || PyLong_Check(obj) || PyComplex_Check(obj) ||
|
| 91 |
+
torch::is_symint(py::handle(obj)) ||
|
| 92 |
+
torch::is_symfloat(py::handle(obj)) || torch::is_symbool(py::handle(obj));
|
| 93 |
+
}
|
| 94 |
+
|
| 95 |
+
namespace torch {
|
| 96 |
+
|
| 97 |
+
TORCH_PYTHON_API bool should_allow_numbers_as_tensors(const std::string& name);
|
| 98 |
+
|
| 99 |
+
enum class ParameterType {
|
| 100 |
+
TENSOR,
|
| 101 |
+
SCALAR,
|
| 102 |
+
INT64,
|
| 103 |
+
SYM_INT,
|
| 104 |
+
DOUBLE,
|
| 105 |
+
COMPLEX,
|
| 106 |
+
TENSOR_LIST,
|
| 107 |
+
INT_LIST,
|
| 108 |
+
GENERATOR,
|
| 109 |
+
BOOL,
|
| 110 |
+
STORAGE,
|
| 111 |
+
PYOBJECT,
|
| 112 |
+
SCALARTYPE,
|
| 113 |
+
LAYOUT,
|
| 114 |
+
MEMORY_FORMAT,
|
| 115 |
+
DEVICE,
|
| 116 |
+
STREAM,
|
| 117 |
+
STRING,
|
| 118 |
+
DIMNAME,
|
| 119 |
+
DIMNAME_LIST,
|
| 120 |
+
QSCHEME,
|
| 121 |
+
FLOAT_LIST,
|
| 122 |
+
SCALAR_LIST,
|
| 123 |
+
SYM_INT_LIST,
|
| 124 |
+
DISPATCH_KEY_SET
|
| 125 |
+
};
|
| 126 |
+
|
| 127 |
+
struct FunctionParameter;
|
| 128 |
+
struct FunctionSignature;
|
| 129 |
+
struct PythonArgs;
|
| 130 |
+
|
| 131 |
+
// Contains bound Python arguments in declaration order
|
| 132 |
+
template <int N>
|
| 133 |
+
struct ParsedArgs {
|
| 134 |
+
ParsedArgs() : args() {}
|
| 135 |
+
// NOLINTNEXTLINE(cppcoreguidelines-avoid-c-arrays,modernize-avoid-c-arrays)
|
| 136 |
+
PyObject* args[N];
|
| 137 |
+
};
|
| 138 |
+
|
| 139 |
+
// A PythonArgParser contains a list of valid signatures. Instances are
|
| 140 |
+
// typically global variables and should be immutable.
|
| 141 |
+
struct PYBIND11_EXPORT PythonArgParser {
|
| 142 |
+
explicit PythonArgParser(
|
| 143 |
+
const std::vector<std::string>& fmts,
|
| 144 |
+
bool traceable = false);
|
| 145 |
+
|
| 146 |
+
// meant only for `torch` functions.
|
| 147 |
+
template <int N>
|
| 148 |
+
inline PythonArgs parse(
|
| 149 |
+
PyObject* self,
|
| 150 |
+
PyObject* args,
|
| 151 |
+
PyObject* kwargs,
|
| 152 |
+
ParsedArgs<N>& dst);
|
| 153 |
+
|
| 154 |
+
template <int N>
|
| 155 |
+
inline PythonArgs parse(PyObject* args, PyObject* kwargs, ParsedArgs<N>& dst);
|
| 156 |
+
|
| 157 |
+
inline PythonArgs parse(PyObject* self, ParsedArgs<0>& dst);
|
| 158 |
+
|
| 159 |
+
// Formatted strings of non-hidden signatures
|
| 160 |
+
std::vector<std::string> get_signatures() const;
|
| 161 |
+
|
| 162 |
+
private:
|
| 163 |
+
[[noreturn]] void print_error(
|
| 164 |
+
PyObject* self,
|
| 165 |
+
PyObject* args,
|
| 166 |
+
PyObject* kwargs,
|
| 167 |
+
// NOLINTNEXTLINE(cppcoreguidelines-avoid-c-arrays,modernize-avoid-c-arrays)
|
| 168 |
+
PyObject* parsed_args[]);
|
| 169 |
+
void check_deprecated(const FunctionSignature& signature);
|
| 170 |
+
PythonArgs raw_parse(
|
| 171 |
+
PyObject* self,
|
| 172 |
+
PyObject* args,
|
| 173 |
+
PyObject* kwargs,
|
| 174 |
+
// NOLINTNEXTLINE(cppcoreguidelines-avoid-c-arrays,modernize-avoid-c-arrays)
|
| 175 |
+
PyObject* parsed_args[]);
|
| 176 |
+
|
| 177 |
+
std::vector<FunctionSignature> signatures_;
|
| 178 |
+
std::string function_name;
|
| 179 |
+
size_t max_args;
|
| 180 |
+
bool traceable;
|
| 181 |
+
};
|
| 182 |
+
|
| 183 |
+
// FunctionSignature represents a single valid signature for a Python function.
|
| 184 |
+
// It is immutable once constructed. The contained data can be concurrently
|
| 185 |
+
// accessed by multiple calls.
|
| 186 |
+
struct FunctionSignature {
|
| 187 |
+
explicit FunctionSignature(const std::string& fmt, int index);
|
| 188 |
+
|
| 189 |
+
bool parse(
|
| 190 |
+
PyObject* self,
|
| 191 |
+
PyObject* args,
|
| 192 |
+
PyObject* kwargs,
|
| 193 |
+
// NOLINTNEXTLINE(cppcoreguidelines-avoid-c-arrays,modernize-avoid-c-arrays)
|
| 194 |
+
PyObject* dst[],
|
| 195 |
+
std::vector<PyObject*>& overloaded_args,
|
| 196 |
+
bool raise_exception);
|
| 197 |
+
|
| 198 |
+
std::string toString() const;
|
| 199 |
+
|
| 200 |
+
std::string name;
|
| 201 |
+
std::vector<FunctionParameter> params;
|
| 202 |
+
size_t min_args;
|
| 203 |
+
size_t max_args;
|
| 204 |
+
size_t max_pos_args;
|
| 205 |
+
int index;
|
| 206 |
+
bool hidden;
|
| 207 |
+
bool deprecated;
|
| 208 |
+
};
|
| 209 |
+
|
| 210 |
+
// PythonArgs contains bound Python arguments for an actual invocation
|
| 211 |
+
// along with references to the matched signature.
|
| 212 |
+
struct TORCH_PYTHON_API PythonArgs {
|
| 213 |
+
PythonArgs(
|
| 214 |
+
bool traceable,
|
| 215 |
+
const FunctionSignature& signature,
|
| 216 |
+
PyObject** args,
|
| 217 |
+
std::vector<PyObject*> overloaded_args)
|
| 218 |
+
: idx(signature.index),
|
| 219 |
+
traceable(traceable),
|
| 220 |
+
signature(signature),
|
| 221 |
+
args(args),
|
| 222 |
+
overloaded_args(std::move(overloaded_args)) {}
|
| 223 |
+
|
| 224 |
+
int idx;
|
| 225 |
+
bool traceable;
|
| 226 |
+
// NOLINTNEXTLINE(cppcoreguidelines-avoid-const-or-ref-data-members)
|
| 227 |
+
const FunctionSignature& signature;
|
| 228 |
+
PyObject** args;
|
| 229 |
+
std::vector<PyObject*> overloaded_args; // NOTE: borrowed references
|
| 230 |
+
|
| 231 |
+
inline bool has_torch_function();
|
| 232 |
+
inline std::string get_func_name();
|
| 233 |
+
inline at::Tensor tensor(int i);
|
| 234 |
+
inline std::optional<at::Tensor> optionalTensor(int i);
|
| 235 |
+
inline at::Scalar scalar(int i);
|
| 236 |
+
inline at::Scalar scalarWithDefault(int i, const at::Scalar& default_scalar);
|
| 237 |
+
inline std::vector<at::Scalar> scalarlist(int i);
|
| 238 |
+
inline std::vector<at::Tensor> tensorlist(int i);
|
| 239 |
+
inline torch::List<std::optional<at::Tensor>> list_of_optional_tensors(int i);
|
| 240 |
+
template <int N>
|
| 241 |
+
inline std::array<at::Tensor, N> tensorlist_n(int i);
|
| 242 |
+
inline std::vector<int64_t> intlist(int i);
|
| 243 |
+
inline std::vector<c10::SymInt> symintlist(int i);
|
| 244 |
+
inline c10::OptionalArray<int64_t> intlistOptional(int i);
|
| 245 |
+
inline c10::OptionalArray<c10::SymInt> symintlistOptional(int i);
|
| 246 |
+
inline std::vector<int64_t> intlistWithDefault(
|
| 247 |
+
int i,
|
| 248 |
+
std::vector<int64_t> default_intlist);
|
| 249 |
+
inline std::optional<at::Generator> generator(int i);
|
| 250 |
+
inline at::Storage storage(int i);
|
| 251 |
+
inline at::Storage storage(
|
| 252 |
+
int i,
|
| 253 |
+
at::ScalarType& storage_scalar_type,
|
| 254 |
+
bool& is_typed_storage);
|
| 255 |
+
inline c10::Stream stream(int i);
|
| 256 |
+
inline at::ScalarType scalartype(int i);
|
| 257 |
+
inline at::ScalarType scalartypeWithDefault(
|
| 258 |
+
int i,
|
| 259 |
+
at::ScalarType default_scalartype);
|
| 260 |
+
inline std::optional<at::ScalarType> scalartypeOptional(int i);
|
| 261 |
+
inline std::optional<at::Scalar> scalarOptional(int i);
|
| 262 |
+
inline std::optional<int64_t> toInt64Optional(int i);
|
| 263 |
+
inline std::optional<c10::SymInt> toSymIntOptional(int i);
|
| 264 |
+
inline std::optional<bool> toBoolOptional(int i);
|
| 265 |
+
inline std::optional<double> toDoubleOptional(int i);
|
| 266 |
+
inline c10::OptionalArray<double> doublelistOptional(int i);
|
| 267 |
+
inline std::vector<double> doublelist(int i);
|
| 268 |
+
inline std::vector<double> getDoublelist(int i);
|
| 269 |
+
inline at::Layout layout(int i);
|
| 270 |
+
inline at::Layout layoutWithDefault(int i, at::Layout default_layout);
|
| 271 |
+
inline std::optional<at::Layout> layoutOptional(int i);
|
| 272 |
+
inline at::Device device(int i);
|
| 273 |
+
inline at::Device deviceWithDefault(int i, const at::Device& default_device);
|
| 274 |
+
inline std::optional<at::Device> deviceOptional(int i);
|
| 275 |
+
inline at::Dimname dimname(int i);
|
| 276 |
+
inline std::vector<at::Dimname> dimnamelist(int i);
|
| 277 |
+
inline std::optional<std::vector<at::Dimname>> toDimnameListOptional(int i);
|
| 278 |
+
inline at::MemoryFormat memoryformat(int i);
|
| 279 |
+
inline std::optional<at::MemoryFormat> memoryformatOptional(int i);
|
| 280 |
+
inline at::QScheme toQScheme(int i);
|
| 281 |
+
inline std::string string(int i);
|
| 282 |
+
inline std::string stringWithDefault(int i, const std::string& default_str);
|
| 283 |
+
inline std::optional<std::string> stringOptional(int i);
|
| 284 |
+
inline std::string_view stringView(int i);
|
| 285 |
+
inline std::string_view stringViewWithDefault(
|
| 286 |
+
int i,
|
| 287 |
+
const std::string_view default_str);
|
| 288 |
+
inline std::optional<std::string_view> stringViewOptional(int i);
|
| 289 |
+
inline PyObject* pyobject(int i);
|
| 290 |
+
inline int64_t toInt64(int i);
|
| 291 |
+
inline c10::SymInt toSymInt(int i);
|
| 292 |
+
inline c10::SymBool toSymBool(int i);
|
| 293 |
+
inline int64_t toInt64WithDefault(int i, int64_t default_int);
|
| 294 |
+
inline double toDouble(int i);
|
| 295 |
+
inline double toDoubleWithDefault(int i, double default_double);
|
| 296 |
+
inline c10::complex<double> toComplex(int i);
|
| 297 |
+
inline c10::complex<double> toComplexWithDefault(
|
| 298 |
+
int i,
|
| 299 |
+
c10::complex<double> default_complex);
|
| 300 |
+
inline bool toBool(int i);
|
| 301 |
+
inline bool toBoolWithDefault(int i, bool default_bool);
|
| 302 |
+
inline bool isNone(int i);
|
| 303 |
+
inline std::optional<c10::DispatchKeySet> toDispatchKeySetOptional(int i);
|
| 304 |
+
|
| 305 |
+
private:
|
| 306 |
+
// Non-inline functions' symbols are exposed to torch_python DLL
|
| 307 |
+
// via TORCH_PYTHON_API tag at struct level.
|
| 308 |
+
at::Tensor tensor_slow(int i);
|
| 309 |
+
at::Scalar scalar_slow(int i);
|
| 310 |
+
at::Scalar scalar_slow(PyObject* arg);
|
| 311 |
+
};
|
| 312 |
+
|
| 313 |
+
// FunctionParameter is a single formal parameter of a Python function.
|
| 314 |
+
// It is immutable once constructed.
|
| 315 |
+
struct FunctionParameter {
|
| 316 |
+
FunctionParameter(const std::string& fmt, bool keyword_only);
|
| 317 |
+
|
| 318 |
+
bool check(
|
| 319 |
+
PyObject* obj,
|
| 320 |
+
std::vector<PyObject*>& overloaded_args,
|
| 321 |
+
int argnum,
|
| 322 |
+
int64_t* failed_idx = nullptr);
|
| 323 |
+
|
| 324 |
+
void set_default_str(const std::string& str);
|
| 325 |
+
TORCH_PYTHON_API std::string type_name() const;
|
| 326 |
+
|
| 327 |
+
ParameterType type_;
|
| 328 |
+
bool optional;
|
| 329 |
+
bool allow_none;
|
| 330 |
+
bool keyword_only;
|
| 331 |
+
bool allow_numbers_as_tensors = false;
|
| 332 |
+
int size;
|
| 333 |
+
std::string name;
|
| 334 |
+
// having this as a raw PyObject * will presumably leak it, but these are only
|
| 335 |
+
// held by static objects anyway, and Py_Finalize can already be called when
|
| 336 |
+
// this is destructed.
|
| 337 |
+
PyObject* python_name;
|
| 338 |
+
// NOLINTNEXTLINE(cppcoreguidelines-avoid-magic-numbers)
|
| 339 |
+
at::SmallVector<PyObject*, 5> numpy_python_names;
|
| 340 |
+
at::Scalar default_scalar;
|
| 341 |
+
std::vector<int64_t> default_intlist;
|
| 342 |
+
std::string default_string;
|
| 343 |
+
union {
|
| 344 |
+
bool default_bool;
|
| 345 |
+
int64_t default_int;
|
| 346 |
+
double default_double;
|
| 347 |
+
// NOLINTNEXTLINE(cppcoreguidelines-avoid-c-arrays,modernize-avoid-c-arrays)
|
| 348 |
+
double default_complex[2]; // see Scalar
|
| 349 |
+
at::ScalarType default_scalartype;
|
| 350 |
+
at::Layout default_layout;
|
| 351 |
+
};
|
| 352 |
+
std::string default_value;
|
| 353 |
+
};
|
| 354 |
+
|
| 355 |
+
template <int N>
|
| 356 |
+
inline PythonArgs PythonArgParser::parse(
|
| 357 |
+
PyObject* self,
|
| 358 |
+
PyObject* args,
|
| 359 |
+
PyObject* kwargs,
|
| 360 |
+
ParsedArgs<N>& dst) {
|
| 361 |
+
TORCH_CHECK_VALUE(
|
| 362 |
+
N >= max_args,
|
| 363 |
+
"PythonArgParser: dst ParsedArgs buffer does not have enough capacity, expected ",
|
| 364 |
+
max_args,
|
| 365 |
+
" (got ",
|
| 366 |
+
N,
|
| 367 |
+
")");
|
| 368 |
+
return raw_parse(self, args, kwargs, dst.args);
|
| 369 |
+
}
|
| 370 |
+
|
| 371 |
+
template <int N>
|
| 372 |
+
inline PythonArgs PythonArgParser::parse(
|
| 373 |
+
PyObject* args,
|
| 374 |
+
PyObject* kwargs,
|
| 375 |
+
ParsedArgs<N>& dst) {
|
| 376 |
+
return parse(nullptr, args, kwargs, dst);
|
| 377 |
+
}
|
| 378 |
+
|
| 379 |
+
inline PythonArgs PythonArgParser::parse(PyObject* self, ParsedArgs<0>& dst) {
|
| 380 |
+
return parse(self, nullptr, nullptr, dst);
|
| 381 |
+
}
|
| 382 |
+
|
| 383 |
+
inline bool PythonArgs::has_torch_function() {
|
| 384 |
+
return !overloaded_args.empty() || at::impl::torch_function_mode_enabled();
|
| 385 |
+
}
|
| 386 |
+
|
| 387 |
+
inline std::string PythonArgs::get_func_name() {
|
| 388 |
+
return signature.name;
|
| 389 |
+
}
|
| 390 |
+
|
| 391 |
+
// TODO: this can return MaybeOwned
|
| 392 |
+
inline at::Tensor PythonArgs::tensor(int i) {
|
| 393 |
+
if (args[i] && THPVariable_CheckExact(args[i])) {
|
| 394 |
+
return THPVariable_Unpack(args[i]);
|
| 395 |
+
}
|
| 396 |
+
return tensor_slow(i);
|
| 397 |
+
}
|
| 398 |
+
|
| 399 |
+
inline std::optional<at::Tensor> PythonArgs::optionalTensor(int i) {
|
| 400 |
+
at::Tensor t = tensor(i);
|
| 401 |
+
// NOLINTNEXTLINE(bugprone-branch-clone)
|
| 402 |
+
if (t.defined()) {
|
| 403 |
+
return t;
|
| 404 |
+
} else {
|
| 405 |
+
return std::nullopt;
|
| 406 |
+
}
|
| 407 |
+
}
|
| 408 |
+
|
| 409 |
+
inline at::Scalar PythonArgs::scalar(int i) {
|
| 410 |
+
if (!args[i])
|
| 411 |
+
return signature.params[i].default_scalar;
|
| 412 |
+
return scalar_slow(i);
|
| 413 |
+
}
|
| 414 |
+
|
| 415 |
+
inline std::vector<at::Scalar> PythonArgs::scalarlist(int i) {
|
| 416 |
+
if (!args[i])
|
| 417 |
+
return std::vector<at::Scalar>();
|
| 418 |
+
auto tuple = six::isTuple(args[i]);
|
| 419 |
+
THPObjectPtr arg = six::maybeAsTuple(args[i]);
|
| 420 |
+
// NOLINTNEXTLINE(bugprone-branch-clone)
|
| 421 |
+
auto size = tuple ? PyTuple_GET_SIZE(arg.get()) : PyList_GET_SIZE(arg.get());
|
| 422 |
+
std::vector<at::Scalar> res(size);
|
| 423 |
+
for (const auto idx : c10::irange(size)) {
|
| 424 |
+
PyObject* obj = tuple ? PyTuple_GET_ITEM(arg.get(), idx)
|
| 425 |
+
: PyList_GET_ITEM(arg.get(), idx);
|
| 426 |
+
res[idx] = scalar_slow(obj);
|
| 427 |
+
}
|
| 428 |
+
return res;
|
| 429 |
+
}
|
| 430 |
+
|
| 431 |
+
inline at::Scalar PythonArgs::scalarWithDefault(
|
| 432 |
+
int i,
|
| 433 |
+
const at::Scalar& default_scalar) {
|
| 434 |
+
if (!args[i])
|
| 435 |
+
return default_scalar;
|
| 436 |
+
return scalar_slow(i);
|
| 437 |
+
}
|
| 438 |
+
|
| 439 |
+
inline std::optional<at::Scalar> PythonArgs::scalarOptional(int i) {
|
| 440 |
+
if (!args[i])
|
| 441 |
+
return std::nullopt;
|
| 442 |
+
return scalar_slow(i);
|
| 443 |
+
}
|
| 444 |
+
|
| 445 |
+
inline std::vector<at::Tensor> PythonArgs::tensorlist(int i) {
|
| 446 |
+
if (!args[i])
|
| 447 |
+
return std::vector<at::Tensor>();
|
| 448 |
+
auto tuple = six::isTuple(args[i]);
|
| 449 |
+
THPObjectPtr arg = six::maybeAsTuple(args[i]);
|
| 450 |
+
// NOLINTNEXTLINE(bugprone-branch-clone)
|
| 451 |
+
auto size = tuple ? PyTuple_GET_SIZE(arg.get()) : PyList_GET_SIZE(arg.get());
|
| 452 |
+
std::vector<at::Tensor> res(size);
|
| 453 |
+
for (const auto idx : c10::irange(size)) {
|
| 454 |
+
PyObject* obj = tuple ? PyTuple_GET_ITEM(arg.get(), idx)
|
| 455 |
+
: PyList_GET_ITEM(arg.get(), idx);
|
| 456 |
+
// This is checked by the argument parser so it's safe to cast without
|
| 457 |
+
// checking if this is a tensor first
|
| 458 |
+
res[idx] = THPVariable_Unpack(obj);
|
| 459 |
+
}
|
| 460 |
+
return res;
|
| 461 |
+
}
|
| 462 |
+
|
| 463 |
+
inline torch::List<std::optional<at::Tensor>> PythonArgs::
|
| 464 |
+
list_of_optional_tensors(int i) {
|
| 465 |
+
if (!args[i])
|
| 466 |
+
return torch::List<std::optional<at::Tensor>>();
|
| 467 |
+
auto tuple = six::isTuple(args[i]);
|
| 468 |
+
THPObjectPtr arg = six::maybeAsTuple(args[i]);
|
| 469 |
+
// NOLINTNEXTLINE(bugprone-branch-clone)
|
| 470 |
+
auto size = tuple ? PyTuple_GET_SIZE(arg.get()) : PyList_GET_SIZE(arg.get());
|
| 471 |
+
torch::List<std::optional<at::Tensor>> res;
|
| 472 |
+
res.reserve(size);
|
| 473 |
+
for (const auto idx : c10::irange(size)) {
|
| 474 |
+
PyObject* obj = tuple ? PyTuple_GET_ITEM(arg.get(), idx)
|
| 475 |
+
: PyList_GET_ITEM(arg.get(), idx);
|
| 476 |
+
// This is checked by the argument parser so it's safe to cast without
|
| 477 |
+
// checking if this is a tensor first
|
| 478 |
+
res.push_back(THPVariable_Unpack(obj));
|
| 479 |
+
}
|
| 480 |
+
return res;
|
| 481 |
+
}
|
| 482 |
+
|
| 483 |
+
template <int N>
|
| 484 |
+
inline std::array<at::Tensor, N> PythonArgs::tensorlist_n(int i) {
|
| 485 |
+
auto res = std::array<at::Tensor, N>();
|
| 486 |
+
if (!args[i])
|
| 487 |
+
return res;
|
| 488 |
+
auto tuple = six::isTuple(args[i]);
|
| 489 |
+
THPObjectPtr arg = six::maybeAsTuple(args[i]);
|
| 490 |
+
// NOLINTNEXTLINE(bugprone-branch-clone)
|
| 491 |
+
auto size = tuple ? PyTuple_GET_SIZE(arg.get()) : PyList_GET_SIZE(arg.get());
|
| 492 |
+
if (size != N) {
|
| 493 |
+
throw TypeError("expected tuple of %d elements but got %d", N, (int)size);
|
| 494 |
+
}
|
| 495 |
+
for (const auto idx : c10::irange(size)) {
|
| 496 |
+
PyObject* obj = tuple ? PyTuple_GET_ITEM(arg.get(), idx)
|
| 497 |
+
: PyList_GET_ITEM(arg.get(), idx);
|
| 498 |
+
// This is checked by the argument parser so it's safe to cast without
|
| 499 |
+
// checking if this is a tensor first
|
| 500 |
+
res[idx] = THPVariable_Unpack(obj);
|
| 501 |
+
}
|
| 502 |
+
return res;
|
| 503 |
+
}
|
| 504 |
+
|
| 505 |
+
inline std::vector<int64_t> PythonArgs::intlist(int i) {
|
| 506 |
+
return intlistWithDefault(i, signature.params[i].default_intlist);
|
| 507 |
+
}
|
| 508 |
+
|
| 509 |
+
inline PyObject* toPyObject(const c10::SymInt& symint) {
|
| 510 |
+
if (symint.is_symbolic()) {
|
| 511 |
+
auto r = py::cast(symint).release().ptr();
|
| 512 |
+
TORCH_INTERNAL_ASSERT(r);
|
| 513 |
+
return r;
|
| 514 |
+
} else {
|
| 515 |
+
auto m = symint.maybe_as_int();
|
| 516 |
+
// NOLINTNEXTLINE(bugprone-unchecked-optional-access)
|
| 517 |
+
return THPUtils_packInt64(m.value());
|
| 518 |
+
}
|
| 519 |
+
}
|
| 520 |
+
|
| 521 |
+
inline void throw_intlist_exception(
|
| 522 |
+
const torch::PythonArgs* args,
|
| 523 |
+
size_t i,
|
| 524 |
+
PyObject* obj,
|
| 525 |
+
size_t idx,
|
| 526 |
+
const std::exception& e = python_error()) {
|
| 527 |
+
std::string error = strlen(e.what())
|
| 528 |
+
? e.what()
|
| 529 |
+
: std::string("type must be ") + args->signature.params[i].type_name() +
|
| 530 |
+
",but got " + Py_TYPE(obj)->tp_name;
|
| 531 |
+
throw TypeError(
|
| 532 |
+
"%s(): argument '%s' failed to unpack the object at pos %zu with error \"%s\"",
|
| 533 |
+
args->signature.name.c_str(),
|
| 534 |
+
args->signature.params[i].name.c_str(),
|
| 535 |
+
idx + 1,
|
| 536 |
+
error.c_str());
|
| 537 |
+
}
|
| 538 |
+
|
| 539 |
+
inline std::vector<c10::SymInt> PythonArgs::symintlist(int i) {
|
| 540 |
+
if (!args[i]) {
|
| 541 |
+
return c10::fmap(signature.params[i].default_intlist, [](int64_t di) {
|
| 542 |
+
return c10::SymInt(di);
|
| 543 |
+
});
|
| 544 |
+
}
|
| 545 |
+
|
| 546 |
+
const auto size1 = signature.params[i].size;
|
| 547 |
+
if (size1 > 0 && THPUtils_checkLong(args[i])) {
|
| 548 |
+
return std::vector<c10::SymInt>(
|
| 549 |
+
size1, c10::SymInt(THPUtils_unpackLong(args[i])));
|
| 550 |
+
}
|
| 551 |
+
|
| 552 |
+
if (size1 > 0 && torch::is_symint(py::handle(args[i]))) {
|
| 553 |
+
auto si = py::handle(args[i]).cast<c10::SymInt>();
|
| 554 |
+
return std::vector<c10::SymInt>(size1, si);
|
| 555 |
+
}
|
| 556 |
+
|
| 557 |
+
PyObject* arg = args[i];
|
| 558 |
+
auto tuple = PyTuple_Check(arg);
|
| 559 |
+
// NOLINTNEXTLINE(bugprone-branch-clone)
|
| 560 |
+
const auto size2 = tuple ? PyTuple_GET_SIZE(arg) : PyList_GET_SIZE(arg);
|
| 561 |
+
std::vector<c10::SymInt> res;
|
| 562 |
+
res.reserve(size2);
|
| 563 |
+
for (const auto idx : c10::irange(size2)) {
|
| 564 |
+
PyObject* obj =
|
| 565 |
+
tuple ? PyTuple_GET_ITEM(arg, idx) : PyList_GET_ITEM(arg, idx);
|
| 566 |
+
|
| 567 |
+
// Elements of torch.Size are tensors during tracing, and we need to
|
| 568 |
+
// record extra information before they are turned into an IntArrayRef
|
| 569 |
+
if (traceable && jit::tracer::isTracing() && THPVariable_Check(obj)) {
|
| 570 |
+
auto& var = THPVariable_Unpack(obj);
|
| 571 |
+
jit::tracer::ArgumentStash::stashIntArrayRefElem(
|
| 572 |
+
signature.params[i].name, size2, idx, var);
|
| 573 |
+
try {
|
| 574 |
+
res.emplace_back(var.item<int64_t>());
|
| 575 |
+
continue;
|
| 576 |
+
} catch (std::exception& e) {
|
| 577 |
+
throw_intlist_exception(this, i, obj, idx, e);
|
| 578 |
+
}
|
| 579 |
+
continue;
|
| 580 |
+
} else {
|
| 581 |
+
// convert tensor to scalar outside of try / catch,
|
| 582 |
+
// so that Tensor subclass exceptions will not be caught.
|
| 583 |
+
if (THPUtils_checkLongExact(obj)) {
|
| 584 |
+
// Fast path for plain numbers
|
| 585 |
+
try {
|
| 586 |
+
res.emplace_back(THPUtils_unpackLong(obj));
|
| 587 |
+
} catch (std::exception& e) {
|
| 588 |
+
throw_intlist_exception(this, i, obj, idx, e);
|
| 589 |
+
}
|
| 590 |
+
} else if (THPVariable_Check(obj)) {
|
| 591 |
+
auto& var = THPVariable_Unpack(obj);
|
| 592 |
+
if (var.numel() != 1 ||
|
| 593 |
+
!at::isIntegralType(
|
| 594 |
+
var.dtype().toScalarType(), /*include_bool*/ true)) {
|
| 595 |
+
throw_intlist_exception(this, i, obj, idx);
|
| 596 |
+
}
|
| 597 |
+
auto scalar = var.item();
|
| 598 |
+
TORCH_CHECK(scalar.isIntegral(/*include bool*/ false));
|
| 599 |
+
res.push_back(scalar.toSymInt());
|
| 600 |
+
} else {
|
| 601 |
+
try {
|
| 602 |
+
if (is_symint(py::handle(obj))) {
|
| 603 |
+
res.push_back(py::handle(obj).cast<c10::SymInt>());
|
| 604 |
+
} else {
|
| 605 |
+
res.emplace_back(THPUtils_unpackIndex(obj));
|
| 606 |
+
}
|
| 607 |
+
} catch (std::exception& e) {
|
| 608 |
+
throw_intlist_exception(this, i, obj, idx, e);
|
| 609 |
+
}
|
| 610 |
+
}
|
| 611 |
+
}
|
| 612 |
+
}
|
| 613 |
+
|
| 614 |
+
return res;
|
| 615 |
+
}
|
| 616 |
+
|
| 617 |
+
inline std::vector<int64_t> PythonArgs::intlistWithDefault(
|
| 618 |
+
int i,
|
| 619 |
+
std::vector<int64_t> default_intlist) {
|
| 620 |
+
if (!args[i])
|
| 621 |
+
return default_intlist;
|
| 622 |
+
PyObject* arg = args[i];
|
| 623 |
+
const auto size1 = signature.params[i].size;
|
| 624 |
+
if (size1 > 0 && THPUtils_checkLong(arg)) {
|
| 625 |
+
return std::vector<int64_t>(size1, THPUtils_unpackLong(arg));
|
| 626 |
+
}
|
| 627 |
+
if (size1 > 0 && torch::is_symint(py::handle(arg))) {
|
| 628 |
+
return std::vector<int64_t>(
|
| 629 |
+
size1,
|
| 630 |
+
py::handle(arg).cast<c10::SymInt>().guard_int(__FILE__, __LINE__));
|
| 631 |
+
}
|
| 632 |
+
auto tuple = PyTuple_Check(arg);
|
| 633 |
+
// NOLINTNEXTLINE(bugprone-branch-clone)
|
| 634 |
+
const auto size2 = tuple ? PyTuple_GET_SIZE(arg) : PyList_GET_SIZE(arg);
|
| 635 |
+
std::vector<int64_t> res(size2);
|
| 636 |
+
for (const auto idx : c10::irange(size2)) {
|
| 637 |
+
PyObject* obj =
|
| 638 |
+
tuple ? PyTuple_GET_ITEM(arg, idx) : PyList_GET_ITEM(arg, idx);
|
| 639 |
+
// Elements of torch.Size are tensors during tracing, and we need to
|
| 640 |
+
// record extra information before they are turned into an IntArrayRef
|
| 641 |
+
if (traceable && jit::tracer::isTracing() && THPVariable_Check(obj)) {
|
| 642 |
+
auto& var = THPVariable_Unpack(obj);
|
| 643 |
+
jit::tracer::ArgumentStash::stashIntArrayRefElem(
|
| 644 |
+
signature.params[i].name, size2, idx, var);
|
| 645 |
+
try {
|
| 646 |
+
res[idx] = var.item<int64_t>();
|
| 647 |
+
continue;
|
| 648 |
+
} catch (std::exception& e) {
|
| 649 |
+
throw_intlist_exception(this, i, obj, idx, e);
|
| 650 |
+
}
|
| 651 |
+
} else {
|
| 652 |
+
// convert tensor to scalar outside of try / catch,
|
| 653 |
+
// so that Tensor subclass exceptions will not be caught.
|
| 654 |
+
if (THPUtils_checkLongExact(obj)) {
|
| 655 |
+
// Fast path for plain numbers
|
| 656 |
+
try {
|
| 657 |
+
res[idx] = THPUtils_unpackLong(obj);
|
| 658 |
+
} catch (std::exception& e) {
|
| 659 |
+
throw_intlist_exception(this, i, obj, idx, e);
|
| 660 |
+
}
|
| 661 |
+
} else if (torch::is_symint(py::handle(obj))) {
|
| 662 |
+
res[idx] = py::cast<c10::SymInt>(py::handle(obj))
|
| 663 |
+
.guard_int(__FILE__, __LINE__);
|
| 664 |
+
} else if (THPVariable_Check(obj)) {
|
| 665 |
+
auto& var = THPVariable_Unpack(obj);
|
| 666 |
+
if (var.numel() != 1 ||
|
| 667 |
+
!at::isIntegralType(
|
| 668 |
+
var.dtype().toScalarType(), /*include_bool*/ true)) {
|
| 669 |
+
throw_intlist_exception(this, i, obj, idx);
|
| 670 |
+
}
|
| 671 |
+
res[idx] = var.item<int64_t>();
|
| 672 |
+
} else {
|
| 673 |
+
try {
|
| 674 |
+
res[idx] = THPUtils_unpackIndex(obj);
|
| 675 |
+
} catch (std::exception& e) {
|
| 676 |
+
throw_intlist_exception(this, i, obj, idx, e);
|
| 677 |
+
}
|
| 678 |
+
}
|
| 679 |
+
}
|
| 680 |
+
}
|
| 681 |
+
return res;
|
| 682 |
+
}
|
| 683 |
+
|
| 684 |
+
inline c10::OptionalArray<int64_t> PythonArgs::intlistOptional(int i) {
|
| 685 |
+
if (!args[i]) {
|
| 686 |
+
return {};
|
| 687 |
+
}
|
| 688 |
+
return intlist(i);
|
| 689 |
+
}
|
| 690 |
+
|
| 691 |
+
inline c10::OptionalArray<c10::SymInt> PythonArgs::symintlistOptional(int i) {
|
| 692 |
+
if (!args[i]) {
|
| 693 |
+
return {};
|
| 694 |
+
}
|
| 695 |
+
return symintlist(i);
|
| 696 |
+
}
|
| 697 |
+
|
| 698 |
+
inline std::vector<double> PythonArgs::getDoublelist(int i) {
|
| 699 |
+
PyObject* arg = args[i];
|
| 700 |
+
auto tuple = PyTuple_Check(arg);
|
| 701 |
+
// NOLINTNEXTLINE(bugprone-branch-clone)
|
| 702 |
+
auto size = tuple ? PyTuple_GET_SIZE(arg) : PyList_GET_SIZE(arg);
|
| 703 |
+
std::vector<double> res(size);
|
| 704 |
+
for (const auto idx : c10::irange(size)) {
|
| 705 |
+
PyObject* obj =
|
| 706 |
+
tuple ? PyTuple_GET_ITEM(arg, idx) : PyList_GET_ITEM(arg, idx);
|
| 707 |
+
try {
|
| 708 |
+
if (torch::is_symfloat(py::handle(obj))) {
|
| 709 |
+
res[idx] = py::cast<c10::SymFloat>(py::handle(obj))
|
| 710 |
+
.guard_float(__FILE__, __LINE__);
|
| 711 |
+
} else {
|
| 712 |
+
res[idx] = THPUtils_unpackDouble(obj);
|
| 713 |
+
}
|
| 714 |
+
} catch (const std::exception&) {
|
| 715 |
+
throw TypeError(
|
| 716 |
+
"%s(): argument '%s' must be %s, but found element of type %s at pos %zu",
|
| 717 |
+
signature.name.c_str(),
|
| 718 |
+
signature.params[i].name.c_str(),
|
| 719 |
+
signature.params[i].type_name().c_str(),
|
| 720 |
+
Py_TYPE(obj)->tp_name,
|
| 721 |
+
idx + 1);
|
| 722 |
+
}
|
| 723 |
+
}
|
| 724 |
+
return res;
|
| 725 |
+
}
|
| 726 |
+
|
| 727 |
+
inline c10::OptionalArray<double> PythonArgs::doublelistOptional(int i) {
|
| 728 |
+
if (!args[i]) {
|
| 729 |
+
return {};
|
| 730 |
+
}
|
| 731 |
+
return this->getDoublelist(i);
|
| 732 |
+
}
|
| 733 |
+
|
| 734 |
+
inline std::vector<double> PythonArgs::doublelist(int i) {
|
| 735 |
+
if (!args[i]) {
|
| 736 |
+
return {};
|
| 737 |
+
}
|
| 738 |
+
return this->getDoublelist(i);
|
| 739 |
+
}
|
| 740 |
+
|
| 741 |
+
inline std::optional<c10::DispatchKeySet> PythonArgs::toDispatchKeySetOptional(
|
| 742 |
+
int i) {
|
| 743 |
+
if (!args[i]) {
|
| 744 |
+
return {};
|
| 745 |
+
}
|
| 746 |
+
return py::cast<c10::DispatchKeySet>(py::handle(args[i]));
|
| 747 |
+
}
|
| 748 |
+
|
| 749 |
+
inline at::ScalarType PythonArgs::scalartypeWithDefault(
|
| 750 |
+
int i,
|
| 751 |
+
at::ScalarType default_scalartype) {
|
| 752 |
+
if (!args[i])
|
| 753 |
+
return default_scalartype;
|
| 754 |
+
return scalartype(i);
|
| 755 |
+
}
|
| 756 |
+
|
| 757 |
+
inline at::ScalarType toScalarType(PyObject* obj) {
|
| 758 |
+
if (obj == (PyObject*)&PyFloat_Type) {
|
| 759 |
+
return at::ScalarType::Double;
|
| 760 |
+
}
|
| 761 |
+
if (obj == (PyObject*)&PyBool_Type) {
|
| 762 |
+
return at::ScalarType::Bool;
|
| 763 |
+
}
|
| 764 |
+
if (obj == (PyObject*)&PyLong_Type) {
|
| 765 |
+
return at::ScalarType::Long;
|
| 766 |
+
}
|
| 767 |
+
if (obj == (PyObject*)&PyComplex_Type) {
|
| 768 |
+
return at::ScalarType::ComplexDouble;
|
| 769 |
+
}
|
| 770 |
+
return reinterpret_cast<THPDtype*>(obj)->scalar_type;
|
| 771 |
+
}
|
| 772 |
+
|
| 773 |
+
inline at::ScalarType PythonArgs::scalartype(int i) {
|
| 774 |
+
if (!args[i]) {
|
| 775 |
+
auto scalartype = signature.params[i].default_scalartype;
|
| 776 |
+
return (scalartype == at::ScalarType::Undefined)
|
| 777 |
+
? torch::tensors::get_default_scalar_type()
|
| 778 |
+
: scalartype;
|
| 779 |
+
}
|
| 780 |
+
PyObject* obj = args[i];
|
| 781 |
+
return toScalarType(obj);
|
| 782 |
+
}
|
| 783 |
+
|
| 784 |
+
inline std::optional<at::ScalarType> PythonArgs::scalartypeOptional(int i) {
|
| 785 |
+
if (!args[i])
|
| 786 |
+
return std::nullopt;
|
| 787 |
+
return scalartype(i);
|
| 788 |
+
}
|
| 789 |
+
|
| 790 |
+
inline at::Layout toLayout(PyObject* obj) {
|
| 791 |
+
const auto layout = reinterpret_cast<THPLayout*>(obj);
|
| 792 |
+
return layout->layout;
|
| 793 |
+
}
|
| 794 |
+
|
| 795 |
+
inline at::Layout PythonArgs::layout(int i) {
|
| 796 |
+
if (!args[i])
|
| 797 |
+
return signature.params[i].default_layout;
|
| 798 |
+
return toLayout(args[i]);
|
| 799 |
+
}
|
| 800 |
+
|
| 801 |
+
inline at::Layout PythonArgs::layoutWithDefault(
|
| 802 |
+
int i,
|
| 803 |
+
at::Layout default_layout) {
|
| 804 |
+
if (!args[i])
|
| 805 |
+
return default_layout;
|
| 806 |
+
return layout(i);
|
| 807 |
+
}
|
| 808 |
+
|
| 809 |
+
inline std::optional<at::Layout> PythonArgs::layoutOptional(int i) {
|
| 810 |
+
if (!args[i])
|
| 811 |
+
return std::nullopt;
|
| 812 |
+
return layout(i);
|
| 813 |
+
}
|
| 814 |
+
|
| 815 |
+
inline at::Device deviceFromLong(int64_t device_index) {
|
| 816 |
+
TORCH_CHECK(device_index >= 0, "Device index must not be negative");
|
| 817 |
+
return at::Device(
|
| 818 |
+
// NOLINTNEXTLINE(bugprone-unchecked-optional-access)
|
| 819 |
+
at::getAccelerator(true).value(),
|
| 820 |
+
static_cast<c10::DeviceIndex>(device_index));
|
| 821 |
+
}
|
| 822 |
+
|
| 823 |
+
inline at::Device toDevice(PyObject* obj) {
|
| 824 |
+
if (THPDevice_Check(obj)) {
|
| 825 |
+
const auto device = reinterpret_cast<THPDevice*>(obj);
|
| 826 |
+
return device->device;
|
| 827 |
+
}
|
| 828 |
+
if (THPUtils_checkLong(obj)) {
|
| 829 |
+
return deviceFromLong(THPUtils_unpackLong(obj));
|
| 830 |
+
}
|
| 831 |
+
if (torch::is_symint(py::handle(obj))) {
|
| 832 |
+
auto device_index =
|
| 833 |
+
py::cast<c10::SymInt>(py::handle(obj)).guard_int(__FILE__, __LINE__);
|
| 834 |
+
return deviceFromLong(device_index);
|
| 835 |
+
}
|
| 836 |
+
const std::string& device_str = THPUtils_unpackString(obj);
|
| 837 |
+
return at::Device(device_str);
|
| 838 |
+
}
|
| 839 |
+
|
| 840 |
+
inline at::Device PythonArgs::device(int i) {
|
| 841 |
+
if (!args[i]) {
|
| 842 |
+
return torch::tensors::get_default_device();
|
| 843 |
+
}
|
| 844 |
+
return toDevice(args[i]);
|
| 845 |
+
}
|
| 846 |
+
|
| 847 |
+
inline at::Device PythonArgs::deviceWithDefault(
|
| 848 |
+
int i,
|
| 849 |
+
const at::Device& default_device) {
|
| 850 |
+
if (!args[i])
|
| 851 |
+
return default_device;
|
| 852 |
+
return device(i);
|
| 853 |
+
}
|
| 854 |
+
|
| 855 |
+
inline std::optional<at::Device> PythonArgs::deviceOptional(int i) {
|
| 856 |
+
if (!args[i])
|
| 857 |
+
return std::nullopt;
|
| 858 |
+
return device(i);
|
| 859 |
+
}
|
| 860 |
+
|
| 861 |
+
inline at::Dimname PythonArgs::dimname(int i) {
|
| 862 |
+
TORCH_INTERNAL_ASSERT(args[i] != nullptr);
|
| 863 |
+
return THPDimname_parse(args[i]);
|
| 864 |
+
}
|
| 865 |
+
|
| 866 |
+
inline std::vector<at::Dimname> parseDimnameList(PyObject* arg) {
|
| 867 |
+
auto tuple = PyTuple_Check(arg);
|
| 868 |
+
// NOLINTNEXTLINE(bugprone-branch-clone)
|
| 869 |
+
auto size = tuple ? PyTuple_GET_SIZE(arg) : PyList_GET_SIZE(arg);
|
| 870 |
+
std::vector<at::Dimname> res;
|
| 871 |
+
res.reserve(size);
|
| 872 |
+
for (const auto idx : c10::irange(size)) {
|
| 873 |
+
PyObject* obj =
|
| 874 |
+
tuple ? PyTuple_GET_ITEM(arg, idx) : PyList_GET_ITEM(arg, idx);
|
| 875 |
+
res.push_back(THPDimname_parse(obj));
|
| 876 |
+
}
|
| 877 |
+
return res;
|
| 878 |
+
}
|
| 879 |
+
|
| 880 |
+
inline std::optional<std::vector<at::Dimname>> PythonArgs::
|
| 881 |
+
toDimnameListOptional(int i) {
|
| 882 |
+
if (!args[i])
|
| 883 |
+
return std::nullopt;
|
| 884 |
+
return parseDimnameList(args[i]);
|
| 885 |
+
}
|
| 886 |
+
|
| 887 |
+
inline std::vector<at::Dimname> PythonArgs::dimnamelist(int i) {
|
| 888 |
+
TORCH_INTERNAL_ASSERT(args[i]);
|
| 889 |
+
PyObject* arg = args[i];
|
| 890 |
+
auto size = signature.params[i].size;
|
| 891 |
+
TORCH_INTERNAL_ASSERT(size == 0 || size == 1);
|
| 892 |
+
if (size == 1 && THPUtils_checkDimname(arg)) {
|
| 893 |
+
return {THPDimname_parse(arg)};
|
| 894 |
+
}
|
| 895 |
+
return parseDimnameList(arg);
|
| 896 |
+
}
|
| 897 |
+
|
| 898 |
+
inline at::MemoryFormat PythonArgs::memoryformat(int i) {
|
| 899 |
+
if (!args[i])
|
| 900 |
+
return at::MemoryFormat::Contiguous;
|
| 901 |
+
TORCH_CHECK(
|
| 902 |
+
THPMemoryFormat_Check(args[i]),
|
| 903 |
+
"memory_format arg must be an instance of the torch.memory_format");
|
| 904 |
+
const auto memory_format = reinterpret_cast<THPMemoryFormat*>(args[i]);
|
| 905 |
+
return memory_format->memory_format;
|
| 906 |
+
}
|
| 907 |
+
|
| 908 |
+
inline std::optional<at::MemoryFormat> PythonArgs::memoryformatOptional(int i) {
|
| 909 |
+
if (!args[i])
|
| 910 |
+
return std::nullopt;
|
| 911 |
+
return memoryformat(i);
|
| 912 |
+
}
|
| 913 |
+
|
| 914 |
+
inline at::QScheme PythonArgs::toQScheme(int i) {
|
| 915 |
+
if (!args[i])
|
| 916 |
+
return at::kPerTensorAffine;
|
| 917 |
+
TORCH_CHECK(
|
| 918 |
+
THPQScheme_Check(args[i]),
|
| 919 |
+
"qscheme arg must be an instance of the torch.qscheme");
|
| 920 |
+
const auto qscheme = reinterpret_cast<THPQScheme*>(args[i]);
|
| 921 |
+
return qscheme->qscheme;
|
| 922 |
+
}
|
| 923 |
+
|
| 924 |
+
inline std::string PythonArgs::string(int i) {
|
| 925 |
+
return stringWithDefault(i, signature.params[i].default_string);
|
| 926 |
+
}
|
| 927 |
+
|
| 928 |
+
inline std::string PythonArgs::stringWithDefault(
|
| 929 |
+
int i,
|
| 930 |
+
const std::string& default_str) {
|
| 931 |
+
if (!args[i])
|
| 932 |
+
return default_str;
|
| 933 |
+
return THPUtils_unpackString(args[i]);
|
| 934 |
+
}
|
| 935 |
+
|
| 936 |
+
inline std::optional<std::string> PythonArgs::stringOptional(int i) {
|
| 937 |
+
if (!args[i])
|
| 938 |
+
return std::nullopt;
|
| 939 |
+
return THPUtils_unpackString(args[i]);
|
| 940 |
+
}
|
| 941 |
+
|
| 942 |
+
inline std::string_view PythonArgs::stringView(int i) {
|
| 943 |
+
return stringViewWithDefault(i, signature.params[i].default_string);
|
| 944 |
+
}
|
| 945 |
+
|
| 946 |
+
inline std::string_view PythonArgs::stringViewWithDefault(
|
| 947 |
+
int i,
|
| 948 |
+
const std::string_view default_str) {
|
| 949 |
+
if (!args[i])
|
| 950 |
+
return default_str;
|
| 951 |
+
return THPUtils_unpackStringView(args[i]);
|
| 952 |
+
}
|
| 953 |
+
|
| 954 |
+
inline std::optional<std::string_view> PythonArgs::stringViewOptional(int i) {
|
| 955 |
+
if (!args[i])
|
| 956 |
+
return std::nullopt;
|
| 957 |
+
return THPUtils_unpackStringView(args[i]);
|
| 958 |
+
}
|
| 959 |
+
|
| 960 |
+
inline int64_t PythonArgs::toInt64(int i) {
|
| 961 |
+
if (!args[i])
|
| 962 |
+
return signature.params[i].default_int;
|
| 963 |
+
if (traceable && jit::tracer::isTracing() && THPVariable_Check(args[i])) {
|
| 964 |
+
auto& var = THPVariable_Unpack(args[i]);
|
| 965 |
+
jit::tracer::ArgumentStash::stashValue(
|
| 966 |
+
signature.params[i].name, idx, var, c10::IntType::get());
|
| 967 |
+
}
|
| 968 |
+
if (torch::is_symint(py::handle(args[i]))) {
|
| 969 |
+
return py::cast<c10::SymInt>(py::handle(args[i]))
|
| 970 |
+
.guard_int(__FILE__, __LINE__);
|
| 971 |
+
}
|
| 972 |
+
return THPUtils_unpackLong(args[i]);
|
| 973 |
+
}
|
| 974 |
+
|
| 975 |
+
inline c10::SymInt PythonArgs::toSymInt(int i) {
|
| 976 |
+
if (!args[i]) {
|
| 977 |
+
return c10::SymInt(signature.params[i].default_int);
|
| 978 |
+
}
|
| 979 |
+
|
| 980 |
+
if (traceable && jit::tracer::isTracing() && THPVariable_Check(args[i])) {
|
| 981 |
+
auto& var = THPVariable_Unpack(args[i]);
|
| 982 |
+
jit::tracer::ArgumentStash::stashValue(
|
| 983 |
+
signature.params[i].name, idx, var, c10::IntType::get());
|
| 984 |
+
}
|
| 985 |
+
|
| 986 |
+
return py::cast<c10::SymInt>(py::handle(args[i]));
|
| 987 |
+
}
|
| 988 |
+
|
| 989 |
+
inline c10::SymBool PythonArgs::toSymBool(int i) {
|
| 990 |
+
if (!args[i]) {
|
| 991 |
+
return c10::SymBool(signature.params[i].default_bool);
|
| 992 |
+
}
|
| 993 |
+
if (traceable && jit::tracer::isTracing() && THPVariable_Check(args[i])) {
|
| 994 |
+
auto& var = THPVariable_Unpack(args[i]);
|
| 995 |
+
jit::tracer::ArgumentStash::stashValue(
|
| 996 |
+
signature.params[i].name, idx, var, c10::BoolType::get());
|
| 997 |
+
}
|
| 998 |
+
|
| 999 |
+
return py::cast<c10::SymBool>(py::handle(args[i]));
|
| 1000 |
+
}
|
| 1001 |
+
|
| 1002 |
+
inline int64_t PythonArgs::toInt64WithDefault(int i, int64_t default_int) {
|
| 1003 |
+
if (!args[i])
|
| 1004 |
+
return default_int;
|
| 1005 |
+
return toInt64(i);
|
| 1006 |
+
}
|
| 1007 |
+
|
| 1008 |
+
inline std::optional<int64_t> PythonArgs::toInt64Optional(int i) {
|
| 1009 |
+
if (!args[i])
|
| 1010 |
+
return std::nullopt;
|
| 1011 |
+
return toInt64(i);
|
| 1012 |
+
}
|
| 1013 |
+
|
| 1014 |
+
inline std::optional<c10::SymInt> PythonArgs::toSymIntOptional(int i) {
|
| 1015 |
+
if (!args[i])
|
| 1016 |
+
return std::nullopt;
|
| 1017 |
+
return toSymInt(i);
|
| 1018 |
+
}
|
| 1019 |
+
|
| 1020 |
+
inline std::optional<bool> PythonArgs::toBoolOptional(int i) {
|
| 1021 |
+
if (!args[i]) {
|
| 1022 |
+
return std::nullopt;
|
| 1023 |
+
}
|
| 1024 |
+
return toBool(i);
|
| 1025 |
+
}
|
| 1026 |
+
|
| 1027 |
+
inline std::optional<double> PythonArgs::toDoubleOptional(int i) {
|
| 1028 |
+
if (!args[i]) {
|
| 1029 |
+
return std::nullopt;
|
| 1030 |
+
}
|
| 1031 |
+
return toDouble(i);
|
| 1032 |
+
}
|
| 1033 |
+
|
| 1034 |
+
inline double PythonArgs::toDouble(int i) {
|
| 1035 |
+
if (!args[i])
|
| 1036 |
+
return signature.params[i].default_double;
|
| 1037 |
+
if (torch::is_symfloat(py::handle(args[i]))) {
|
| 1038 |
+
return py::cast<c10::SymFloat>(py::handle(args[i]))
|
| 1039 |
+
.guard_float(__FILE__, __LINE__);
|
| 1040 |
+
}
|
| 1041 |
+
if (torch::is_symint(py::handle(args[i]))) {
|
| 1042 |
+
return static_cast<double>(py::cast<c10::SymInt>(py::handle(args[i]))
|
| 1043 |
+
.guard_int(__FILE__, __LINE__));
|
| 1044 |
+
}
|
| 1045 |
+
return THPUtils_unpackDouble(args[i]);
|
| 1046 |
+
}
|
| 1047 |
+
|
| 1048 |
+
inline bool PythonArgs::toBool(int i) {
|
| 1049 |
+
if (!args[i])
|
| 1050 |
+
return signature.params[i].default_bool;
|
| 1051 |
+
if (torch::is_symbool(py::handle(args[i]))) {
|
| 1052 |
+
return py::cast<c10::SymBool>(py::handle(args[i]))
|
| 1053 |
+
.guard_bool(__FILE__, __LINE__);
|
| 1054 |
+
}
|
| 1055 |
+
return args[i] == Py_True;
|
| 1056 |
+
}
|
| 1057 |
+
|
| 1058 |
+
inline double PythonArgs::toDoubleWithDefault(int i, double default_double) {
|
| 1059 |
+
if (!args[i])
|
| 1060 |
+
return default_double;
|
| 1061 |
+
return toDouble(i);
|
| 1062 |
+
}
|
| 1063 |
+
|
| 1064 |
+
inline c10::complex<double> PythonArgs::toComplex(int i) {
|
| 1065 |
+
if (!args[i])
|
| 1066 |
+
return *(reinterpret_cast<const c10::complex<double>*>(
|
| 1067 |
+
signature.params[i].default_complex));
|
| 1068 |
+
return THPUtils_unpackComplexDouble(args[i]);
|
| 1069 |
+
}
|
| 1070 |
+
|
| 1071 |
+
inline c10::complex<double> PythonArgs::toComplexWithDefault(
|
| 1072 |
+
int i,
|
| 1073 |
+
c10::complex<double> default_complex) {
|
| 1074 |
+
if (!args[i])
|
| 1075 |
+
return default_complex;
|
| 1076 |
+
return toComplex(i);
|
| 1077 |
+
}
|
| 1078 |
+
|
| 1079 |
+
inline bool PythonArgs::toBoolWithDefault(int i, bool default_bool) {
|
| 1080 |
+
if (!args[i])
|
| 1081 |
+
return default_bool;
|
| 1082 |
+
return toBool(i);
|
| 1083 |
+
}
|
| 1084 |
+
|
| 1085 |
+
inline bool PythonArgs::isNone(int i) {
|
| 1086 |
+
return args[i] == nullptr;
|
| 1087 |
+
}
|
| 1088 |
+
|
| 1089 |
+
inline std::optional<at::Generator> PythonArgs::generator(int i) {
|
| 1090 |
+
if (!args[i])
|
| 1091 |
+
return std::nullopt;
|
| 1092 |
+
return reinterpret_cast<THPGenerator*>(args[i])->cdata;
|
| 1093 |
+
}
|
| 1094 |
+
|
| 1095 |
+
inline at::Storage PythonArgs::storage(int i) {
|
| 1096 |
+
if (!args[i])
|
| 1097 |
+
return at::Storage();
|
| 1098 |
+
return createStorage(args[i]);
|
| 1099 |
+
}
|
| 1100 |
+
|
| 1101 |
+
inline at::Storage PythonArgs::storage(
|
| 1102 |
+
int i,
|
| 1103 |
+
at::ScalarType& storage_scalar_type,
|
| 1104 |
+
bool& is_typed_storage) {
|
| 1105 |
+
at::Storage storage;
|
| 1106 |
+
if (!args[i]) {
|
| 1107 |
+
storage = at::Storage();
|
| 1108 |
+
is_typed_storage = false;
|
| 1109 |
+
storage_scalar_type = at::ScalarType::Undefined;
|
| 1110 |
+
} else {
|
| 1111 |
+
std::tie(storage, storage_scalar_type, is_typed_storage) =
|
| 1112 |
+
createStorageGetType(args[i]);
|
| 1113 |
+
}
|
| 1114 |
+
return storage;
|
| 1115 |
+
}
|
| 1116 |
+
|
| 1117 |
+
inline c10::Stream PythonArgs::stream(int i) {
|
| 1118 |
+
if (!args[i])
|
| 1119 |
+
return c10::Stream(
|
| 1120 |
+
c10::Stream::Default::DEFAULT, c10::Device(c10::DeviceType::CPU, -1));
|
| 1121 |
+
if (!THPStream_Check(args[i])) {
|
| 1122 |
+
throw TypeError(
|
| 1123 |
+
"expected Stream object. Got '%s'", Py_TYPE(args[i])->tp_name);
|
| 1124 |
+
}
|
| 1125 |
+
return c10::Stream::unpack3(
|
| 1126 |
+
((THPStream*)args[i])->stream_id,
|
| 1127 |
+
static_cast<c10::DeviceIndex>(((THPStream*)args[i])->device_index),
|
| 1128 |
+
static_cast<c10::DeviceType>(((THPStream*)args[i])->device_type));
|
| 1129 |
+
}
|
| 1130 |
+
|
| 1131 |
+
inline PyObject* PythonArgs::pyobject(int i) {
|
| 1132 |
+
if (!args[i])
|
| 1133 |
+
return Py_None;
|
| 1134 |
+
return args[i];
|
| 1135 |
+
}
|
| 1136 |
+
|
| 1137 |
+
/*
|
| 1138 |
+
*
|
| 1139 |
+
* Handle __torch_function__ overrides if we know that there are overloaded
|
| 1140 |
+
* arguments. All objects stored in r.overloaded_args must have a
|
| 1141 |
+
* __torch_function__ implementation and the arguments must be ordered in order
|
| 1142 |
+
* of precedence. Precedence goes from left to right in the order of the
|
| 1143 |
+
* signature of the function the overloaded arguments were passed to, except
|
| 1144 |
+
* subclasses are always considered before superclasses.
|
| 1145 |
+
*
|
| 1146 |
+
* If the result of calling __torch_function__ is NotImplemented, the
|
| 1147 |
+
* next implementation in the precedence order is called. If all
|
| 1148 |
+
* arguments return NotImplemented from their __torch_function__
|
| 1149 |
+
* implementation, a TypeError is raised in Python.
|
| 1150 |
+
*
|
| 1151 |
+
* Assumes overloaded_args has at least one entry. All entries must have
|
| 1152 |
+
* a __torch_function__ attribute that resolves to a callable that
|
| 1153 |
+
* accepts a torch API function, a tuple of arguments, and a dict of
|
| 1154 |
+
* keyword arguments for the torch API function.
|
| 1155 |
+
*
|
| 1156 |
+
* It is sufficient to call PythonArgs::has_torch_function before
|
| 1157 |
+
* calling this function to verify that there are valid arguments
|
| 1158 |
+
* present. If that is not done then special care must be taken to
|
| 1159 |
+
* ensure there are arguments that are overloaded with
|
| 1160 |
+
* __torch_function__.
|
| 1161 |
+
*
|
| 1162 |
+
* See torch._overrides.handle_torch_function for the equivalent
|
| 1163 |
+
* code in the pure-python implementation.
|
| 1164 |
+
*
|
| 1165 |
+
* 'r' is a parsed PythonArgs instance, returned from
|
| 1166 |
+
* PythonArgParser::parse.
|
| 1167 |
+
*
|
| 1168 |
+
* 'args' is a reference to the python tuple of arguments to the torch
|
| 1169 |
+
* API function.
|
| 1170 |
+
*
|
| 1171 |
+
* 'kwargs' is a reference to the python dict of keyword arguments to
|
| 1172 |
+
* the torch API function.
|
| 1173 |
+
*
|
| 1174 |
+
* 'torch_api' is a reference to a python torch API namespace.
|
| 1175 |
+
*
|
| 1176 |
+
* 'torch_api_function' is the reference to the original torch method, usually,
|
| 1177 |
+
* we can use torch_api and func_name to get torch_api_function. In some cases,
|
| 1178 |
+
* e.g., torch custom op, we create the function in C++, if we still use
|
| 1179 |
+
* torch_api and func_name to fetch original api, a cyclic call will happen.
|
| 1180 |
+
*
|
| 1181 |
+
* 'overloaded_args' is the args which have overloaded __torch_function__.
|
| 1182 |
+
*
|
| 1183 |
+
* 'func_name' is the named of the original torch method.
|
| 1184 |
+
*
|
| 1185 |
+
* TODO: we could use different names for the following 'handle_torch_function'
|
| 1186 |
+
* instead of overloading.
|
| 1187 |
+
*
|
| 1188 |
+
*/
|
| 1189 |
+
// Used for Tensor methods with arguments.
|
| 1190 |
+
auto handle_torch_function(
|
| 1191 |
+
PythonArgs& r,
|
| 1192 |
+
PyObject* self,
|
| 1193 |
+
PyObject* args,
|
| 1194 |
+
PyObject* kwargs,
|
| 1195 |
+
PyObject* torch_api,
|
| 1196 |
+
const char* module_name,
|
| 1197 |
+
const char* func_name_override = nullptr) -> PyObject*;
|
| 1198 |
+
|
| 1199 |
+
// Used for functions which needs to parse python args.
|
| 1200 |
+
auto handle_torch_function(
|
| 1201 |
+
PythonArgs& r,
|
| 1202 |
+
PyObject* args,
|
| 1203 |
+
PyObject* kwargs,
|
| 1204 |
+
PyObject* torch_api,
|
| 1205 |
+
const char* module_name,
|
| 1206 |
+
const char* func_name_override = nullptr) -> PyObject*;
|
| 1207 |
+
|
| 1208 |
+
// Used for functions that have no argument parsing.
|
| 1209 |
+
auto handle_torch_function(
|
| 1210 |
+
PyObject* self,
|
| 1211 |
+
const std::string& func_name,
|
| 1212 |
+
PyObject* args = nullptr,
|
| 1213 |
+
PyObject* kwargs = nullptr,
|
| 1214 |
+
PyObject* torch_api = THPVariableClass,
|
| 1215 |
+
const std::string& module_name = "torch.Tensor") -> PyObject*;
|
| 1216 |
+
|
| 1217 |
+
// Used for functions created in C++, e.g., C++ custom op, which doesn't use
|
| 1218 |
+
// PythonArgParser to get overloaded_args.
|
| 1219 |
+
enum class TorchFunctionName { TorchFunction, TorchDispatch };
|
| 1220 |
+
|
| 1221 |
+
auto TORCH_PYTHON_API handle_torch_function_no_python_arg_parser(
|
| 1222 |
+
at::ArrayRef<PyObject*> overloaded_args,
|
| 1223 |
+
PyObject* args,
|
| 1224 |
+
PyObject* kwargs,
|
| 1225 |
+
const char* func_name,
|
| 1226 |
+
PyObject* torch_api_function,
|
| 1227 |
+
const char* module_name,
|
| 1228 |
+
TorchFunctionName torch_function_name = TorchFunctionName::TorchFunction)
|
| 1229 |
+
-> PyObject*;
|
| 1230 |
+
|
| 1231 |
+
// Used for getters of Tensor properties
|
| 1232 |
+
auto handle_torch_function_getter(
|
| 1233 |
+
THPVariable* self,
|
| 1234 |
+
const std::string& property_name) -> PyObject*;
|
| 1235 |
+
|
| 1236 |
+
// Used for setters of Tensor properties.
|
| 1237 |
+
auto handle_torch_function_setter(
|
| 1238 |
+
THPVariable* self,
|
| 1239 |
+
const std::string& property_name,
|
| 1240 |
+
PyObject* value) -> int;
|
| 1241 |
+
|
| 1242 |
+
// Used for __getitem__ and __setitem__
|
| 1243 |
+
auto handle_torch_function_indexing(
|
| 1244 |
+
PyObject* self,
|
| 1245 |
+
PyObject* index,
|
| 1246 |
+
PyObject* val = nullptr) -> PyObject*;
|
| 1247 |
+
|
| 1248 |
+
/*
|
| 1249 |
+
* Check if the input obj is Tensor type, including its subclass, or overloaded
|
| 1250 |
+
* type. If the type defines __torch_function__, it also returns true.
|
| 1251 |
+
* Otherwise returns false. If the class is not torch.Tensor, and it defines
|
| 1252 |
+
* __torch_function__, we append obj to overloaded_args.
|
| 1253 |
+
*
|
| 1254 |
+
* 'obj': the input argument to be checked
|
| 1255 |
+
* 'overloaded_args': the vector to append the overloaded args.
|
| 1256 |
+
*/
|
| 1257 |
+
bool is_tensor_and_append_overloaded(
|
| 1258 |
+
PyObject* obj,
|
| 1259 |
+
std::vector<PyObject*>* overloaded_args);
|
| 1260 |
+
|
| 1261 |
+
/*
|
| 1262 |
+
* Check if the input obj is Tensor List or Tensor Tuple type. First check
|
| 1263 |
+
* whether obj is Tuple or List type, if true, iterate over each element and
|
| 1264 |
+
* check whether it is Tensor type, including its subclass or overloaded type.
|
| 1265 |
+
* At the same time, the overloaded arg is appended to the overloaded_args.
|
| 1266 |
+
*
|
| 1267 |
+
* 'obj': the input argument to be checked
|
| 1268 |
+
* 'overloaded_args': the vector to append the overloaded args.
|
| 1269 |
+
* 'argnum': the number of total arguments of the function being checked.
|
| 1270 |
+
* 'throw_error': whether throw error if any element in the list or tuple is
|
| 1271 |
+
* not tensor type or overloaded.
|
| 1272 |
+
*/
|
| 1273 |
+
bool is_tensor_list_and_append_overloaded(
|
| 1274 |
+
PyObject* obj,
|
| 1275 |
+
std::vector<PyObject*>* overloaded_args,
|
| 1276 |
+
size_t argnum,
|
| 1277 |
+
bool throw_error);
|
| 1278 |
+
|
| 1279 |
+
/* Given an argument that is definitely a tensor and is definitely overloaded,
|
| 1280 |
+
* append it to the overloaded arguments list. Use this instead of
|
| 1281 |
+
* is_tensor_and_append_overloaded in situations where you have a PyObject
|
| 1282 |
+
* and you know it definitely is a Tensor and it is definitely overloaded.
|
| 1283 |
+
*
|
| 1284 |
+
* 'overloaded_args': the vector to append the overloaded args
|
| 1285 |
+
* 'obj': the input tensor that is overloaded
|
| 1286 |
+
*/
|
| 1287 |
+
void append_overloaded_tensor(
|
| 1288 |
+
std::vector<PyObject*>* overloaded_args,
|
| 1289 |
+
PyObject* obj);
|
| 1290 |
+
|
| 1291 |
+
/* Given an argument that is definitely a type and is definitely overloaded,
|
| 1292 |
+
* append it to the overloaded arguments list. Use this only with
|
| 1293 |
+
* __torch_dispatch__, where we operate on classes that have a
|
| 1294 |
+
* __torch_dispatch__ classmethod.
|
| 1295 |
+
*
|
| 1296 |
+
* 'overloaded_args': the vector to append the overloaded type
|
| 1297 |
+
* 'obj': the input class that has a __torch_dispatch__ classmethod.
|
| 1298 |
+
*/
|
| 1299 |
+
void append_overloaded_type(
|
| 1300 |
+
std::vector<PyObject*>* overloaded_args,
|
| 1301 |
+
PyObject* obj);
|
| 1302 |
+
|
| 1303 |
+
} // namespace torch
|
phivenv/Lib/site-packages/torch/include/torch/csrc/utils/python_compat.h
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#ifndef PYTHON_COMPAT
|
| 2 |
+
#define PYTHON_COMPAT
|
| 3 |
+
|
| 4 |
+
#include <torch/csrc/utils/pythoncapi_compat.h>
|
| 5 |
+
|
| 6 |
+
#ifdef __cplusplus
|
| 7 |
+
extern "C" {
|
| 8 |
+
#endif
|
| 9 |
+
|
| 10 |
+
// PyTorch-only compat functions
|
| 11 |
+
|
| 12 |
+
#define IS_PYTHON_3_11_PLUS PY_VERSION_HEX >= 0x030B00C1
|
| 13 |
+
#define IS_PYTHON_3_12_PLUS PY_VERSION_HEX >= 0x030C0000
|
| 14 |
+
#define IS_PYTHON_3_13_PLUS PY_VERSION_HEX >= 0x030D0000
|
| 15 |
+
#define IS_PYTHON_3_14_PLUS PY_VERSION_HEX >= 0x030E0000
|
| 16 |
+
|
| 17 |
+
static inline int PyCode_GetNCellvars(PyCodeObject* code) {
|
| 18 |
+
// gh-26364 added co_ncellvars to Python 3.11.0rc1
|
| 19 |
+
#if IS_PYTHON_3_11_PLUS
|
| 20 |
+
return code->co_ncellvars;
|
| 21 |
+
#else
|
| 22 |
+
return PyTuple_GET_SIZE(code->co_cellvars);
|
| 23 |
+
#endif
|
| 24 |
+
}
|
| 25 |
+
|
| 26 |
+
static inline int PyCode_GetNFreevars(PyCodeObject* code) {
|
| 27 |
+
// gh-26364 added co_nfreevars to Python 3.11.0rc1
|
| 28 |
+
#if IS_PYTHON_3_11_PLUS
|
| 29 |
+
return code->co_nfreevars;
|
| 30 |
+
#else
|
| 31 |
+
return PyTuple_GET_SIZE(code->co_freevars);
|
| 32 |
+
#endif
|
| 33 |
+
}
|
| 34 |
+
|
| 35 |
+
// Provided by CPython but getting the header for them is very hard
|
| 36 |
+
#if IS_PYTHON_3_11_PLUS
|
| 37 |
+
// NOLINTNEXTLINE(readability-redundant-declaration)
|
| 38 |
+
PyAPI_FUNC(void) _PyWeakref_ClearRef(PyWeakReference* self);
|
| 39 |
+
#else
|
| 40 |
+
extern void _PyWeakref_ClearRef(PyWeakReference* self);
|
| 41 |
+
#endif
|
| 42 |
+
|
| 43 |
+
#ifdef __cplusplus
|
| 44 |
+
}
|
| 45 |
+
#endif
|
| 46 |
+
#endif // PYTHON_COMPAT
|
phivenv/Lib/site-packages/torch/include/torch/csrc/utils/python_dispatch.h
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#include <pybind11/pybind11.h>
|
| 2 |
+
#include <torch/csrc/utils/pybind.h>
|
| 3 |
+
|
| 4 |
+
namespace torch::impl::dispatch {
|
| 5 |
+
|
| 6 |
+
void initDispatchBindings(PyObject* module);
|
| 7 |
+
|
| 8 |
+
void python_op_registration_trampoline_impl(
|
| 9 |
+
const c10::OperatorHandle& op,
|
| 10 |
+
c10::DispatchKey key,
|
| 11 |
+
c10::DispatchKeySet keyset,
|
| 12 |
+
torch::jit::Stack* stack,
|
| 13 |
+
bool with_keyset,
|
| 14 |
+
bool with_op);
|
| 15 |
+
|
| 16 |
+
} // namespace torch::impl::dispatch
|
phivenv/Lib/site-packages/torch/include/torch/csrc/utils/python_numbers.h
ADDED
|
@@ -0,0 +1,204 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#pragma once
|
| 2 |
+
|
| 3 |
+
#include <c10/core/Device.h>
|
| 4 |
+
#include <torch/csrc/Exceptions.h>
|
| 5 |
+
#include <torch/csrc/jit/frontend/tracer.h>
|
| 6 |
+
#include <torch/csrc/python_headers.h>
|
| 7 |
+
#include <torch/csrc/utils/object_ptr.h>
|
| 8 |
+
#include <torch/csrc/utils/tensor_numpy.h>
|
| 9 |
+
#include <cstdint>
|
| 10 |
+
#include <limits>
|
| 11 |
+
#include <stdexcept>
|
| 12 |
+
|
| 13 |
+
// largest integer that can be represented consecutively in a double
|
| 14 |
+
const int64_t DOUBLE_INT_MAX = 9007199254740992;
|
| 15 |
+
|
| 16 |
+
inline PyObject* THPUtils_packDeviceIndex(c10::DeviceIndex value) {
|
| 17 |
+
return PyLong_FromLong(value);
|
| 18 |
+
}
|
| 19 |
+
|
| 20 |
+
inline PyObject* THPUtils_packInt32(int32_t value) {
|
| 21 |
+
return PyLong_FromLong(value);
|
| 22 |
+
}
|
| 23 |
+
|
| 24 |
+
inline PyObject* THPUtils_packInt64(int64_t value) {
|
| 25 |
+
return PyLong_FromLongLong(value);
|
| 26 |
+
}
|
| 27 |
+
|
| 28 |
+
inline PyObject* THPUtils_packUInt32(uint32_t value) {
|
| 29 |
+
return PyLong_FromUnsignedLong(value);
|
| 30 |
+
}
|
| 31 |
+
|
| 32 |
+
inline PyObject* THPUtils_packUInt64(uint64_t value) {
|
| 33 |
+
return PyLong_FromUnsignedLongLong(value);
|
| 34 |
+
}
|
| 35 |
+
|
| 36 |
+
inline PyObject* THPUtils_packDoubleAsInt(double value) {
|
| 37 |
+
return PyLong_FromDouble(value);
|
| 38 |
+
}
|
| 39 |
+
|
| 40 |
+
inline bool THPUtils_checkLongExact(PyObject* obj) {
|
| 41 |
+
return PyLong_CheckExact(obj) && !PyBool_Check(obj);
|
| 42 |
+
}
|
| 43 |
+
|
| 44 |
+
inline bool THPUtils_checkLong(PyObject* obj) {
|
| 45 |
+
// Fast path
|
| 46 |
+
if (THPUtils_checkLongExact(obj)) {
|
| 47 |
+
return true;
|
| 48 |
+
}
|
| 49 |
+
|
| 50 |
+
#ifdef USE_NUMPY
|
| 51 |
+
if (torch::utils::is_numpy_int(obj)) {
|
| 52 |
+
return true;
|
| 53 |
+
}
|
| 54 |
+
#endif
|
| 55 |
+
|
| 56 |
+
return PyLong_Check(obj) && !PyBool_Check(obj);
|
| 57 |
+
}
|
| 58 |
+
|
| 59 |
+
inline int32_t THPUtils_unpackInt(PyObject* obj) {
|
| 60 |
+
int overflow = 0;
|
| 61 |
+
long value = PyLong_AsLongAndOverflow(obj, &overflow);
|
| 62 |
+
if (value == -1 && PyErr_Occurred()) {
|
| 63 |
+
throw python_error();
|
| 64 |
+
}
|
| 65 |
+
if (overflow != 0) {
|
| 66 |
+
throw std::runtime_error("Overflow when unpacking long");
|
| 67 |
+
}
|
| 68 |
+
if (value > std::numeric_limits<int32_t>::max() ||
|
| 69 |
+
value < std::numeric_limits<int32_t>::min()) {
|
| 70 |
+
throw std::runtime_error("Overflow when unpacking long");
|
| 71 |
+
}
|
| 72 |
+
return (int32_t)value;
|
| 73 |
+
}
|
| 74 |
+
|
| 75 |
+
inline int64_t THPUtils_unpackLong(PyObject* obj) {
|
| 76 |
+
int overflow = 0;
|
| 77 |
+
long long value = PyLong_AsLongLongAndOverflow(obj, &overflow);
|
| 78 |
+
if (value == -1 && PyErr_Occurred()) {
|
| 79 |
+
throw python_error();
|
| 80 |
+
}
|
| 81 |
+
if (overflow != 0) {
|
| 82 |
+
throw std::runtime_error("Overflow when unpacking long");
|
| 83 |
+
}
|
| 84 |
+
return (int64_t)value;
|
| 85 |
+
}
|
| 86 |
+
|
| 87 |
+
inline uint32_t THPUtils_unpackUInt32(PyObject* obj) {
|
| 88 |
+
unsigned long value = PyLong_AsUnsignedLong(obj);
|
| 89 |
+
if (PyErr_Occurred()) {
|
| 90 |
+
throw python_error();
|
| 91 |
+
}
|
| 92 |
+
if (value > std::numeric_limits<uint32_t>::max()) {
|
| 93 |
+
throw std::runtime_error("Overflow when unpacking unsigned long");
|
| 94 |
+
}
|
| 95 |
+
return (uint32_t)value;
|
| 96 |
+
}
|
| 97 |
+
|
| 98 |
+
inline uint64_t THPUtils_unpackUInt64(PyObject* obj) {
|
| 99 |
+
unsigned long long value = PyLong_AsUnsignedLongLong(obj);
|
| 100 |
+
if (PyErr_Occurred()) {
|
| 101 |
+
throw python_error();
|
| 102 |
+
}
|
| 103 |
+
return (uint64_t)value;
|
| 104 |
+
}
|
| 105 |
+
|
| 106 |
+
bool THPUtils_checkIndex(PyObject* obj);
|
| 107 |
+
|
| 108 |
+
inline int64_t THPUtils_unpackIndex(PyObject* obj) {
|
| 109 |
+
if (!THPUtils_checkLong(obj)) {
|
| 110 |
+
auto index = THPObjectPtr(PyNumber_Index(obj));
|
| 111 |
+
if (index == nullptr) {
|
| 112 |
+
throw python_error();
|
| 113 |
+
}
|
| 114 |
+
// NB: This needs to be called before `index` goes out of scope and the
|
| 115 |
+
// underlying object's refcount is decremented
|
| 116 |
+
return THPUtils_unpackLong(index.get());
|
| 117 |
+
}
|
| 118 |
+
return THPUtils_unpackLong(obj);
|
| 119 |
+
}
|
| 120 |
+
|
| 121 |
+
inline bool THPUtils_unpackBool(PyObject* obj) {
|
| 122 |
+
if (obj == Py_True) {
|
| 123 |
+
return true;
|
| 124 |
+
} else if (obj == Py_False) {
|
| 125 |
+
return false;
|
| 126 |
+
} else {
|
| 127 |
+
throw std::runtime_error("couldn't convert python object to boolean");
|
| 128 |
+
}
|
| 129 |
+
}
|
| 130 |
+
|
| 131 |
+
inline bool THPUtils_checkBool(PyObject* obj) {
|
| 132 |
+
#ifdef USE_NUMPY
|
| 133 |
+
if (torch::utils::is_numpy_bool(obj)) {
|
| 134 |
+
return true;
|
| 135 |
+
}
|
| 136 |
+
#endif
|
| 137 |
+
return PyBool_Check(obj);
|
| 138 |
+
}
|
| 139 |
+
|
| 140 |
+
inline bool THPUtils_checkDouble(PyObject* obj) {
|
| 141 |
+
#ifdef USE_NUMPY
|
| 142 |
+
if (torch::utils::is_numpy_scalar(obj)) {
|
| 143 |
+
return true;
|
| 144 |
+
}
|
| 145 |
+
#endif
|
| 146 |
+
return PyFloat_Check(obj) || PyLong_Check(obj);
|
| 147 |
+
}
|
| 148 |
+
|
| 149 |
+
inline double THPUtils_unpackDouble(PyObject* obj) {
|
| 150 |
+
if (PyFloat_Check(obj)) {
|
| 151 |
+
return PyFloat_AS_DOUBLE(obj);
|
| 152 |
+
}
|
| 153 |
+
double value = PyFloat_AsDouble(obj);
|
| 154 |
+
if (value == -1 && PyErr_Occurred()) {
|
| 155 |
+
throw python_error();
|
| 156 |
+
}
|
| 157 |
+
return value;
|
| 158 |
+
}
|
| 159 |
+
|
| 160 |
+
inline c10::complex<double> THPUtils_unpackComplexDouble(PyObject* obj) {
|
| 161 |
+
Py_complex value = PyComplex_AsCComplex(obj);
|
| 162 |
+
if (value.real == -1.0 && PyErr_Occurred()) {
|
| 163 |
+
throw python_error();
|
| 164 |
+
}
|
| 165 |
+
|
| 166 |
+
return c10::complex<double>(value.real, value.imag);
|
| 167 |
+
}
|
| 168 |
+
|
| 169 |
+
inline bool THPUtils_unpackNumberAsBool(PyObject* obj) {
|
| 170 |
+
if (PyFloat_Check(obj)) {
|
| 171 |
+
return (bool)PyFloat_AS_DOUBLE(obj);
|
| 172 |
+
}
|
| 173 |
+
|
| 174 |
+
if (PyComplex_Check(obj)) {
|
| 175 |
+
double real_val = PyComplex_RealAsDouble(obj);
|
| 176 |
+
double imag_val = PyComplex_ImagAsDouble(obj);
|
| 177 |
+
return !(real_val == 0 && imag_val == 0);
|
| 178 |
+
}
|
| 179 |
+
|
| 180 |
+
int overflow = 0;
|
| 181 |
+
long long value = PyLong_AsLongLongAndOverflow(obj, &overflow);
|
| 182 |
+
if (value == -1 && PyErr_Occurred()) {
|
| 183 |
+
throw python_error();
|
| 184 |
+
}
|
| 185 |
+
// No need to check overflow, because when overflow occurred, it should
|
| 186 |
+
// return true in order to keep the same behavior of numpy.
|
| 187 |
+
return (bool)value;
|
| 188 |
+
}
|
| 189 |
+
|
| 190 |
+
inline c10::DeviceIndex THPUtils_unpackDeviceIndex(PyObject* obj) {
|
| 191 |
+
int overflow = 0;
|
| 192 |
+
long value = PyLong_AsLongAndOverflow(obj, &overflow);
|
| 193 |
+
if (value == -1 && PyErr_Occurred()) {
|
| 194 |
+
throw python_error();
|
| 195 |
+
}
|
| 196 |
+
if (overflow != 0) {
|
| 197 |
+
throw std::runtime_error("Overflow when unpacking DeviceIndex");
|
| 198 |
+
}
|
| 199 |
+
if (value > std::numeric_limits<c10::DeviceIndex>::max() ||
|
| 200 |
+
value < std::numeric_limits<c10::DeviceIndex>::min()) {
|
| 201 |
+
throw std::runtime_error("Overflow when unpacking DeviceIndex");
|
| 202 |
+
}
|
| 203 |
+
return (c10::DeviceIndex)value;
|
| 204 |
+
}
|
phivenv/Lib/site-packages/torch/include/torch/csrc/utils/python_raii.h
ADDED
|
@@ -0,0 +1,84 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#include <torch/csrc/utils/pybind.h>
|
| 2 |
+
#include <optional>
|
| 3 |
+
#include <tuple>
|
| 4 |
+
|
| 5 |
+
namespace torch::impl {
|
| 6 |
+
|
| 7 |
+
template <typename GuardT, typename... Args>
|
| 8 |
+
struct RAIIContextManager {
|
| 9 |
+
explicit RAIIContextManager(Args&&... args)
|
| 10 |
+
: args_(std::forward<Args>(args)...) {}
|
| 11 |
+
|
| 12 |
+
void enter() {
|
| 13 |
+
auto emplace = [&](Args... args) {
|
| 14 |
+
guard_.emplace(std::forward<Args>(args)...);
|
| 15 |
+
};
|
| 16 |
+
std::apply(std::move(emplace), args_);
|
| 17 |
+
}
|
| 18 |
+
|
| 19 |
+
void exit() {
|
| 20 |
+
guard_ = std::nullopt;
|
| 21 |
+
}
|
| 22 |
+
|
| 23 |
+
private:
|
| 24 |
+
std::optional<GuardT> guard_;
|
| 25 |
+
std::tuple<Args...> args_;
|
| 26 |
+
};
|
| 27 |
+
|
| 28 |
+
// Turns a C++ RAII guard into a Python context manager.
|
| 29 |
+
// See _ExcludeDispatchKeyGuard in python_dispatch.cpp for example.
|
| 30 |
+
template <typename GuardT, typename... GuardArgs>
|
| 31 |
+
void py_context_manager(const py::module& m, const char* name) {
|
| 32 |
+
using ContextManagerT = RAIIContextManager<GuardT, GuardArgs...>;
|
| 33 |
+
py::class_<ContextManagerT>(m, name)
|
| 34 |
+
.def(py::init<GuardArgs...>())
|
| 35 |
+
.def("__enter__", [](ContextManagerT& guard) { guard.enter(); })
|
| 36 |
+
.def(
|
| 37 |
+
"__exit__",
|
| 38 |
+
[](ContextManagerT& guard,
|
| 39 |
+
const py::object& exc_type,
|
| 40 |
+
const py::object& exc_value,
|
| 41 |
+
const py::object& traceback) { guard.exit(); });
|
| 42 |
+
}
|
| 43 |
+
|
| 44 |
+
template <typename GuardT, typename... Args>
|
| 45 |
+
struct DeprecatedRAIIContextManager {
|
| 46 |
+
explicit DeprecatedRAIIContextManager(Args&&... args) {
|
| 47 |
+
guard_.emplace(std::forward<Args>(args)...);
|
| 48 |
+
}
|
| 49 |
+
|
| 50 |
+
void enter() {}
|
| 51 |
+
|
| 52 |
+
void exit() {
|
| 53 |
+
guard_ = std::nullopt;
|
| 54 |
+
}
|
| 55 |
+
|
| 56 |
+
private:
|
| 57 |
+
std::optional<GuardT> guard_;
|
| 58 |
+
std::tuple<Args...> args_;
|
| 59 |
+
};
|
| 60 |
+
|
| 61 |
+
// Definition: a "Python RAII guard" is an object in Python that acquires
|
| 62 |
+
// a resource on init and releases the resource on deletion.
|
| 63 |
+
//
|
| 64 |
+
// This API turns a C++ RAII guard into an object can be used either as a
|
| 65 |
+
// Python context manager or as a "Python RAII guard".
|
| 66 |
+
//
|
| 67 |
+
// Please prefer `py_context_manager` to this API if you are binding a new
|
| 68 |
+
// RAII guard into Python because "Python RAII guards" don't work as expected
|
| 69 |
+
// in Python (Python makes no guarantees about when an object gets deleted)
|
| 70 |
+
template <typename GuardT, typename... GuardArgs>
|
| 71 |
+
void py_context_manager_DEPRECATED(const py::module& m, const char* name) {
|
| 72 |
+
using ContextManagerT = DeprecatedRAIIContextManager<GuardT, GuardArgs...>;
|
| 73 |
+
py::class_<ContextManagerT>(m, name)
|
| 74 |
+
.def(py::init<GuardArgs...>())
|
| 75 |
+
.def("__enter__", [](ContextManagerT& guard) { guard.enter(); })
|
| 76 |
+
.def(
|
| 77 |
+
"__exit__",
|
| 78 |
+
[](ContextManagerT& guard,
|
| 79 |
+
const py::object& exc_type,
|
| 80 |
+
const py::object& exc_value,
|
| 81 |
+
const py::object& traceback) { guard.exit(); });
|
| 82 |
+
}
|
| 83 |
+
|
| 84 |
+
} // namespace torch::impl
|
phivenv/Lib/site-packages/torch/include/torch/csrc/utils/python_scalars.h
ADDED
|
@@ -0,0 +1,172 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#pragma once
|
| 2 |
+
|
| 3 |
+
#include <ATen/ATen.h>
|
| 4 |
+
#include <c10/util/TypeCast.h>
|
| 5 |
+
#include <torch/csrc/python_headers.h>
|
| 6 |
+
|
| 7 |
+
#include <torch/csrc/Exceptions.h>
|
| 8 |
+
#include <torch/csrc/utils/python_numbers.h>
|
| 9 |
+
|
| 10 |
+
namespace torch::utils {
|
| 11 |
+
|
| 12 |
+
template <typename T>
|
| 13 |
+
inline T unpackIntegral(PyObject* obj, const char* type) {
|
| 14 |
+
#if PY_VERSION_HEX >= 0x030a00f0
|
| 15 |
+
// In Python-3.10 floats can no longer be silently converted to integers
|
| 16 |
+
// Keep backward compatible behavior for now
|
| 17 |
+
if (PyFloat_Check(obj)) {
|
| 18 |
+
return c10::checked_convert<T>(THPUtils_unpackDouble(obj), type);
|
| 19 |
+
}
|
| 20 |
+
return c10::checked_convert<T>(THPUtils_unpackLong(obj), type);
|
| 21 |
+
#else
|
| 22 |
+
return static_cast<T>(THPUtils_unpackLong(obj));
|
| 23 |
+
#endif
|
| 24 |
+
}
|
| 25 |
+
|
| 26 |
+
inline void store_scalar(void* data, at::ScalarType scalarType, PyObject* obj) {
|
| 27 |
+
switch (scalarType) {
|
| 28 |
+
case at::kByte:
|
| 29 |
+
*(uint8_t*)data = unpackIntegral<uint8_t>(obj, "uint8");
|
| 30 |
+
break;
|
| 31 |
+
case at::kUInt16:
|
| 32 |
+
*(uint16_t*)data = unpackIntegral<uint16_t>(obj, "uint16");
|
| 33 |
+
break;
|
| 34 |
+
case at::kUInt32:
|
| 35 |
+
*(uint32_t*)data = unpackIntegral<uint32_t>(obj, "uint32");
|
| 36 |
+
break;
|
| 37 |
+
case at::kUInt64:
|
| 38 |
+
// NB: This doesn't allow implicit conversion of float to int
|
| 39 |
+
*(uint64_t*)data = THPUtils_unpackUInt64(obj);
|
| 40 |
+
break;
|
| 41 |
+
case at::kChar:
|
| 42 |
+
*(int8_t*)data = unpackIntegral<int8_t>(obj, "int8");
|
| 43 |
+
break;
|
| 44 |
+
case at::kShort:
|
| 45 |
+
*(int16_t*)data = unpackIntegral<int16_t>(obj, "int16");
|
| 46 |
+
break;
|
| 47 |
+
case at::kInt:
|
| 48 |
+
*(int32_t*)data = unpackIntegral<int32_t>(obj, "int32");
|
| 49 |
+
break;
|
| 50 |
+
case at::kLong:
|
| 51 |
+
*(int64_t*)data = unpackIntegral<int64_t>(obj, "int64");
|
| 52 |
+
break;
|
| 53 |
+
case at::kHalf:
|
| 54 |
+
*(at::Half*)data =
|
| 55 |
+
at::convert<at::Half, double>(THPUtils_unpackDouble(obj));
|
| 56 |
+
break;
|
| 57 |
+
case at::kFloat:
|
| 58 |
+
*(float*)data = (float)THPUtils_unpackDouble(obj);
|
| 59 |
+
break;
|
| 60 |
+
case at::kDouble:
|
| 61 |
+
*(double*)data = THPUtils_unpackDouble(obj);
|
| 62 |
+
break;
|
| 63 |
+
case at::kComplexHalf:
|
| 64 |
+
*(c10::complex<at::Half>*)data =
|
| 65 |
+
(c10::complex<at::Half>)static_cast<c10::complex<float>>(
|
| 66 |
+
THPUtils_unpackComplexDouble(obj));
|
| 67 |
+
break;
|
| 68 |
+
case at::kComplexFloat:
|
| 69 |
+
*(c10::complex<float>*)data =
|
| 70 |
+
(c10::complex<float>)THPUtils_unpackComplexDouble(obj);
|
| 71 |
+
break;
|
| 72 |
+
case at::kComplexDouble:
|
| 73 |
+
*(c10::complex<double>*)data = THPUtils_unpackComplexDouble(obj);
|
| 74 |
+
break;
|
| 75 |
+
case at::kBool:
|
| 76 |
+
*(bool*)data = THPUtils_unpackNumberAsBool(obj);
|
| 77 |
+
break;
|
| 78 |
+
case at::kBFloat16:
|
| 79 |
+
*(at::BFloat16*)data =
|
| 80 |
+
at::convert<at::BFloat16, double>(THPUtils_unpackDouble(obj));
|
| 81 |
+
break;
|
| 82 |
+
// TODO(#146647): simplify below with macros
|
| 83 |
+
case at::kFloat8_e5m2:
|
| 84 |
+
*(at::Float8_e5m2*)data =
|
| 85 |
+
at::convert<at::Float8_e5m2, double>(THPUtils_unpackDouble(obj));
|
| 86 |
+
break;
|
| 87 |
+
case at::kFloat8_e5m2fnuz:
|
| 88 |
+
*(at::Float8_e5m2fnuz*)data =
|
| 89 |
+
at::convert<at::Float8_e5m2fnuz, double>(THPUtils_unpackDouble(obj));
|
| 90 |
+
break;
|
| 91 |
+
case at::kFloat8_e4m3fn:
|
| 92 |
+
*(at::Float8_e4m3fn*)data =
|
| 93 |
+
at::convert<at::Float8_e4m3fn, double>(THPUtils_unpackDouble(obj));
|
| 94 |
+
break;
|
| 95 |
+
case at::kFloat8_e4m3fnuz:
|
| 96 |
+
*(at::Float8_e4m3fnuz*)data =
|
| 97 |
+
at::convert<at::Float8_e4m3fnuz, double>(THPUtils_unpackDouble(obj));
|
| 98 |
+
break;
|
| 99 |
+
case at::kFloat8_e8m0fnu:
|
| 100 |
+
*(at::Float8_e8m0fnu*)data =
|
| 101 |
+
at::convert<at::Float8_e8m0fnu, double>(THPUtils_unpackDouble(obj));
|
| 102 |
+
break;
|
| 103 |
+
default:
|
| 104 |
+
throw std::runtime_error("store_scalar: invalid type");
|
| 105 |
+
}
|
| 106 |
+
}
|
| 107 |
+
|
| 108 |
+
inline PyObject* load_scalar(const void* data, at::ScalarType scalarType) {
|
| 109 |
+
switch (scalarType) {
|
| 110 |
+
case at::kByte:
|
| 111 |
+
return THPUtils_packInt64(*(uint8_t*)data);
|
| 112 |
+
case at::kUInt16:
|
| 113 |
+
return THPUtils_packInt64(*(uint16_t*)data);
|
| 114 |
+
case at::kUInt32:
|
| 115 |
+
return THPUtils_packUInt32(*(uint32_t*)data);
|
| 116 |
+
case at::kUInt64:
|
| 117 |
+
return THPUtils_packUInt64(*(uint64_t*)data);
|
| 118 |
+
case at::kChar:
|
| 119 |
+
return THPUtils_packInt64(*(int8_t*)data);
|
| 120 |
+
case at::kShort:
|
| 121 |
+
return THPUtils_packInt64(*(int16_t*)data);
|
| 122 |
+
case at::kInt:
|
| 123 |
+
return THPUtils_packInt64(*(int32_t*)data);
|
| 124 |
+
case at::kLong:
|
| 125 |
+
return THPUtils_packInt64(*(int64_t*)data);
|
| 126 |
+
case at::kHalf:
|
| 127 |
+
return PyFloat_FromDouble(
|
| 128 |
+
at::convert<double, at::Half>(*(at::Half*)data));
|
| 129 |
+
case at::kFloat:
|
| 130 |
+
return PyFloat_FromDouble(*(float*)data);
|
| 131 |
+
case at::kDouble:
|
| 132 |
+
return PyFloat_FromDouble(*(double*)data);
|
| 133 |
+
case at::kComplexHalf: {
|
| 134 |
+
auto data_ = reinterpret_cast<const c10::complex<at::Half>*>(data);
|
| 135 |
+
return PyComplex_FromDoubles(data_->real(), data_->imag());
|
| 136 |
+
}
|
| 137 |
+
case at::kComplexFloat: {
|
| 138 |
+
auto data_ = reinterpret_cast<const c10::complex<float>*>(data);
|
| 139 |
+
return PyComplex_FromDoubles(data_->real(), data_->imag());
|
| 140 |
+
}
|
| 141 |
+
case at::kComplexDouble:
|
| 142 |
+
return PyComplex_FromCComplex(
|
| 143 |
+
*reinterpret_cast<Py_complex*>((c10::complex<double>*)data));
|
| 144 |
+
case at::kBool:
|
| 145 |
+
// Don't use bool*, since it may take out-of-range byte as bool.
|
| 146 |
+
// Instead, we cast explicitly to avoid ASAN error.
|
| 147 |
+
return PyBool_FromLong(static_cast<bool>(*(uint8_t*)data));
|
| 148 |
+
case at::kBFloat16:
|
| 149 |
+
return PyFloat_FromDouble(
|
| 150 |
+
at::convert<double, at::BFloat16>(*(at::BFloat16*)data));
|
| 151 |
+
// TODO(#146647): simplify below with macros
|
| 152 |
+
case at::kFloat8_e5m2:
|
| 153 |
+
return PyFloat_FromDouble(
|
| 154 |
+
at::convert<double, at::Float8_e5m2>(*(at::Float8_e5m2*)data));
|
| 155 |
+
case at::kFloat8_e4m3fn:
|
| 156 |
+
return PyFloat_FromDouble(
|
| 157 |
+
at::convert<double, at::Float8_e4m3fn>(*(at::Float8_e4m3fn*)data));
|
| 158 |
+
case at::kFloat8_e5m2fnuz:
|
| 159 |
+
return PyFloat_FromDouble(at::convert<double, at::Float8_e5m2fnuz>(
|
| 160 |
+
*(at::Float8_e5m2fnuz*)data));
|
| 161 |
+
case at::kFloat8_e4m3fnuz:
|
| 162 |
+
return PyFloat_FromDouble(at::convert<double, at::Float8_e4m3fnuz>(
|
| 163 |
+
*(at::Float8_e4m3fnuz*)data));
|
| 164 |
+
case at::kFloat8_e8m0fnu:
|
| 165 |
+
return PyFloat_FromDouble(
|
| 166 |
+
at::convert<double, at::Float8_e8m0fnu>(*(at::Float8_e8m0fnu*)data));
|
| 167 |
+
default:
|
| 168 |
+
throw std::runtime_error("load_scalar: invalid type");
|
| 169 |
+
}
|
| 170 |
+
}
|
| 171 |
+
|
| 172 |
+
} // namespace torch::utils
|
phivenv/Lib/site-packages/torch/include/torch/csrc/utils/python_strings.h
ADDED
|
@@ -0,0 +1,129 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#pragma once
|
| 2 |
+
|
| 3 |
+
#include <torch/csrc/python_headers.h>
|
| 4 |
+
#include <torch/csrc/utils/object_ptr.h>
|
| 5 |
+
#include <torch/csrc/utils/pybind.h>
|
| 6 |
+
#include <stdexcept>
|
| 7 |
+
#include <string>
|
| 8 |
+
|
| 9 |
+
// Utilities for handling Python strings. Note that PyString, when defined, is
|
| 10 |
+
// the same as PyBytes.
|
| 11 |
+
|
| 12 |
+
// Returns true if obj is a bytes/str or unicode object
|
| 13 |
+
// As of Python 3.6, this does not require the GIL
|
| 14 |
+
inline bool THPUtils_checkString(PyObject* obj) {
|
| 15 |
+
return PyBytes_Check(obj) || PyUnicode_Check(obj);
|
| 16 |
+
}
|
| 17 |
+
|
| 18 |
+
// Unpacks PyBytes (PyString) or PyUnicode as std::string
|
| 19 |
+
// PyBytes are unpacked as-is. PyUnicode is unpacked as UTF-8.
|
| 20 |
+
// NOTE: this method requires the GIL
|
| 21 |
+
inline std::string THPUtils_unpackString(PyObject* obj) {
|
| 22 |
+
if (PyBytes_Check(obj)) {
|
| 23 |
+
size_t size = PyBytes_GET_SIZE(obj);
|
| 24 |
+
return std::string(PyBytes_AS_STRING(obj), size);
|
| 25 |
+
}
|
| 26 |
+
if (PyUnicode_Check(obj)) {
|
| 27 |
+
Py_ssize_t size = 0;
|
| 28 |
+
const char* data = PyUnicode_AsUTF8AndSize(obj, &size);
|
| 29 |
+
if (!data) {
|
| 30 |
+
throw std::runtime_error("error unpacking string as utf-8");
|
| 31 |
+
}
|
| 32 |
+
return std::string(data, (size_t)size);
|
| 33 |
+
}
|
| 34 |
+
throw std::runtime_error("unpackString: expected bytes or unicode object");
|
| 35 |
+
}
|
| 36 |
+
|
| 37 |
+
// Unpacks PyBytes (PyString) or PyUnicode as std::string_view
|
| 38 |
+
// PyBytes are unpacked as-is. PyUnicode is unpacked as UTF-8.
|
| 39 |
+
// NOTE: If `obj` is destroyed, then the non-owning std::string_view will
|
| 40 |
+
// become invalid. If the string needs to be accessed at any point after
|
| 41 |
+
// `obj` is destroyed, then the std::string_view should be copied into
|
| 42 |
+
// a std::string, or another owning object, and kept alive. For an example,
|
| 43 |
+
// look at how IValue and autograd nodes handle std::string_view arguments.
|
| 44 |
+
// NOTE: this method requires the GIL
|
| 45 |
+
inline std::string_view THPUtils_unpackStringView(PyObject* obj) {
|
| 46 |
+
if (PyBytes_Check(obj)) {
|
| 47 |
+
size_t size = PyBytes_GET_SIZE(obj);
|
| 48 |
+
return std::string_view(PyBytes_AS_STRING(obj), size);
|
| 49 |
+
}
|
| 50 |
+
if (PyUnicode_Check(obj)) {
|
| 51 |
+
Py_ssize_t size = 0;
|
| 52 |
+
const char* data = PyUnicode_AsUTF8AndSize(obj, &size);
|
| 53 |
+
if (!data) {
|
| 54 |
+
throw std::runtime_error("error unpacking string as utf-8");
|
| 55 |
+
}
|
| 56 |
+
return std::string_view(data, (size_t)size);
|
| 57 |
+
}
|
| 58 |
+
throw std::runtime_error("unpackString: expected bytes or unicode object");
|
| 59 |
+
}
|
| 60 |
+
|
| 61 |
+
inline PyObject* THPUtils_packString(const char* str) {
|
| 62 |
+
return PyUnicode_FromString(str);
|
| 63 |
+
}
|
| 64 |
+
|
| 65 |
+
inline PyObject* THPUtils_packString(const std::string& str) {
|
| 66 |
+
return PyUnicode_FromStringAndSize(
|
| 67 |
+
str.c_str(), static_cast<Py_ssize_t>(str.size()));
|
| 68 |
+
}
|
| 69 |
+
|
| 70 |
+
inline PyObject* THPUtils_internString(const std::string& str) {
|
| 71 |
+
return PyUnicode_InternFromString(str.c_str());
|
| 72 |
+
}
|
| 73 |
+
|
| 74 |
+
// Precondition: THPUtils_checkString(obj) must be true
|
| 75 |
+
inline bool THPUtils_isInterned(PyObject* obj) {
|
| 76 |
+
return PyUnicode_CHECK_INTERNED(obj);
|
| 77 |
+
}
|
| 78 |
+
|
| 79 |
+
// Precondition: THPUtils_checkString(obj) must be true
|
| 80 |
+
inline void THPUtils_internStringInPlace(PyObject** obj) {
|
| 81 |
+
PyUnicode_InternInPlace(obj);
|
| 82 |
+
}
|
| 83 |
+
|
| 84 |
+
/*
|
| 85 |
+
* Reference:
|
| 86 |
+
* https://github.com/numpy/numpy/blob/f4c497c768e0646df740b647782df463825bfd27/numpy/core/src/common/get_attr_string.h#L42
|
| 87 |
+
*
|
| 88 |
+
* Stripped down version of PyObject_GetAttrString,
|
| 89 |
+
* avoids lookups for None, tuple, and List objects,
|
| 90 |
+
* and doesn't create a PyErr since this code ignores it.
|
| 91 |
+
*
|
| 92 |
+
* This can be much faster then PyObject_GetAttrString where
|
| 93 |
+
* exceptions are not used by caller.
|
| 94 |
+
*
|
| 95 |
+
* 'obj' is the object to search for attribute.
|
| 96 |
+
*
|
| 97 |
+
* 'name' is the attribute to search for.
|
| 98 |
+
*
|
| 99 |
+
* Returns a py::object wrapping the return value. If the attribute lookup
|
| 100 |
+
* failed the value will be NULL.
|
| 101 |
+
*
|
| 102 |
+
*/
|
| 103 |
+
|
| 104 |
+
inline py::object PyObject_FastGetAttrString(PyObject* obj, const char* name) {
|
| 105 |
+
PyTypeObject* tp = Py_TYPE(obj);
|
| 106 |
+
PyObject* res = (PyObject*)nullptr;
|
| 107 |
+
|
| 108 |
+
/* Attribute referenced by (char *)name */
|
| 109 |
+
if (tp->tp_getattr != nullptr) {
|
| 110 |
+
// This is OK per https://bugs.python.org/issue39620
|
| 111 |
+
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-const-cast)
|
| 112 |
+
res = (*tp->tp_getattr)(obj, const_cast<char*>(name));
|
| 113 |
+
if (res == nullptr) {
|
| 114 |
+
PyErr_Clear();
|
| 115 |
+
}
|
| 116 |
+
}
|
| 117 |
+
/* Attribute referenced by (PyObject *)name */
|
| 118 |
+
else if (tp->tp_getattro != nullptr) {
|
| 119 |
+
auto w = py::reinterpret_steal<py::object>(THPUtils_internString(name));
|
| 120 |
+
if (w.ptr() == nullptr) {
|
| 121 |
+
return py::object();
|
| 122 |
+
}
|
| 123 |
+
res = (*tp->tp_getattro)(obj, w.ptr());
|
| 124 |
+
if (res == nullptr) {
|
| 125 |
+
PyErr_Clear();
|
| 126 |
+
}
|
| 127 |
+
}
|
| 128 |
+
return py::reinterpret_steal<py::object>(res);
|
| 129 |
+
}
|
phivenv/Lib/site-packages/torch/include/torch/csrc/utils/python_stub.h
ADDED
|
@@ -0,0 +1,4 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#pragma once
|
| 2 |
+
|
| 3 |
+
struct _object;
|
| 4 |
+
using PyObject = _object;
|
phivenv/Lib/site-packages/torch/include/torch/csrc/utils/python_symnode.h
ADDED
|
@@ -0,0 +1,328 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#pragma once
|
| 2 |
+
|
| 3 |
+
#include <c10/core/SafePyObject.h>
|
| 4 |
+
#include <c10/core/SymNodeImpl.h>
|
| 5 |
+
|
| 6 |
+
#include <torch/csrc/PyInterpreter.h>
|
| 7 |
+
#include <torch/csrc/autograd/python_variable.h>
|
| 8 |
+
#include <torch/csrc/utils/pybind.h>
|
| 9 |
+
|
| 10 |
+
namespace torch {
|
| 11 |
+
|
| 12 |
+
TORCH_PYTHON_API py::handle get_symint_class();
|
| 13 |
+
TORCH_PYTHON_API py::handle get_symfloat_class();
|
| 14 |
+
TORCH_PYTHON_API py::handle get_symbool_class();
|
| 15 |
+
|
| 16 |
+
// NB: These functions must not be called too early, otherwise torch not setup.
|
| 17 |
+
// Alternate design is to have torch "register" the object to us
|
| 18 |
+
inline bool is_symint(py::handle obj) {
|
| 19 |
+
return py::isinstance(obj, get_symint_class());
|
| 20 |
+
}
|
| 21 |
+
inline bool is_symfloat(py::handle obj) {
|
| 22 |
+
return py::isinstance(obj, get_symfloat_class());
|
| 23 |
+
}
|
| 24 |
+
inline bool is_symbool(py::handle obj) {
|
| 25 |
+
return py::isinstance(obj, get_symbool_class());
|
| 26 |
+
}
|
| 27 |
+
|
| 28 |
+
namespace impl {
|
| 29 |
+
|
| 30 |
+
// This c10::SymNodeImpl simply backends to a Python object that
|
| 31 |
+
// implements the API. The Python object is the source of truth,
|
| 32 |
+
// this is just an adapter so C++ calls can get to the object.
|
| 33 |
+
class PythonSymNodeImpl : public c10::SymNodeImpl {
|
| 34 |
+
public:
|
| 35 |
+
PythonSymNodeImpl(py::object pyobj) : c10::SymNodeImpl() {
|
| 36 |
+
pyobj_ = std::make_shared<c10::SafePyObject>(
|
| 37 |
+
pyobj.release().ptr(), getPyInterpreter());
|
| 38 |
+
}
|
| 39 |
+
|
| 40 |
+
c10::SymNode wrap_int(int64_t num) override {
|
| 41 |
+
py::gil_scoped_acquire acquire;
|
| 42 |
+
auto r = getPyObj().attr("wrap_int")(num);
|
| 43 |
+
return c10::make_intrusive<PythonSymNodeImpl>(std::move(r));
|
| 44 |
+
}
|
| 45 |
+
|
| 46 |
+
c10::SymNode wrap_float(double num) override {
|
| 47 |
+
py::gil_scoped_acquire acquire;
|
| 48 |
+
auto r = getPyObj().attr("wrap_float")(num);
|
| 49 |
+
return c10::make_intrusive<PythonSymNodeImpl>(std::move(r));
|
| 50 |
+
}
|
| 51 |
+
|
| 52 |
+
c10::SymNode wrap_bool(bool num) override {
|
| 53 |
+
py::gil_scoped_acquire acquire;
|
| 54 |
+
auto r = getPyObj().attr("wrap_bool")(num);
|
| 55 |
+
return c10::make_intrusive<PythonSymNodeImpl>(std::move(r));
|
| 56 |
+
}
|
| 57 |
+
|
| 58 |
+
#define TORCH_SYMNODE_SIZES_STRIDES(n) \
|
| 59 |
+
c10::SymNode n( \
|
| 60 |
+
c10::ArrayRef<c10::SymNode> sizes, c10::ArrayRef<c10::SymNode> strides) \
|
| 61 |
+
override { \
|
| 62 |
+
py::gil_scoped_acquire acquire; \
|
| 63 |
+
auto r = getPyObj().attr(#n)(sizes, strides); \
|
| 64 |
+
return c10::make_intrusive<PythonSymNodeImpl>(std::move(r)); \
|
| 65 |
+
}
|
| 66 |
+
|
| 67 |
+
// clang-format off
|
| 68 |
+
TORCH_SYMNODE_SIZES_STRIDES(is_contiguous)
|
| 69 |
+
TORCH_SYMNODE_SIZES_STRIDES(is_channels_last_contiguous_2d)
|
| 70 |
+
TORCH_SYMNODE_SIZES_STRIDES(is_channels_last_contiguous_3d)
|
| 71 |
+
TORCH_SYMNODE_SIZES_STRIDES(is_channels_last_strides_2d)
|
| 72 |
+
TORCH_SYMNODE_SIZES_STRIDES(is_channels_last_strides_3d)
|
| 73 |
+
TORCH_SYMNODE_SIZES_STRIDES(is_non_overlapping_and_dense)
|
| 74 |
+
// clang-format on
|
| 75 |
+
|
| 76 |
+
#undef TORCH_SYMNODE_SIZES_STRIDES
|
| 77 |
+
|
| 78 |
+
bool bool_() override {
|
| 79 |
+
py::gil_scoped_acquire acquire;
|
| 80 |
+
return getPyObj().attr("bool_")().is(py::handle(Py_True));
|
| 81 |
+
}
|
| 82 |
+
|
| 83 |
+
bool is_int() override {
|
| 84 |
+
py::gil_scoped_acquire acquire;
|
| 85 |
+
return getPyObj().attr("is_int")().is(py::handle(Py_True));
|
| 86 |
+
}
|
| 87 |
+
|
| 88 |
+
bool is_float() override {
|
| 89 |
+
py::gil_scoped_acquire acquire;
|
| 90 |
+
return getPyObj().attr("is_float")().is(py::handle(Py_True));
|
| 91 |
+
}
|
| 92 |
+
|
| 93 |
+
bool is_bool() override {
|
| 94 |
+
py::gil_scoped_acquire acquire;
|
| 95 |
+
return getPyObj().attr("is_bool")().is(py::handle(Py_True));
|
| 96 |
+
}
|
| 97 |
+
|
| 98 |
+
bool is_nested_int() const override {
|
| 99 |
+
py::gil_scoped_acquire acquire;
|
| 100 |
+
return getPyObj().attr("is_nested_int")().is(py::handle(Py_True));
|
| 101 |
+
}
|
| 102 |
+
|
| 103 |
+
bool has_hint() override {
|
| 104 |
+
py::gil_scoped_acquire acquire;
|
| 105 |
+
return getPyObj().attr("has_hint")().is(py::handle(Py_True));
|
| 106 |
+
}
|
| 107 |
+
|
| 108 |
+
int64_t guard_int(const char* file, int64_t line) override {
|
| 109 |
+
py::gil_scoped_acquire acquire;
|
| 110 |
+
return getPyObj().attr("guard_int")(file, line).cast<int64_t>();
|
| 111 |
+
}
|
| 112 |
+
|
| 113 |
+
double guard_float(const char* file, int64_t line) override {
|
| 114 |
+
py::gil_scoped_acquire acquire;
|
| 115 |
+
return getPyObj().attr("guard_float")(file, line).cast<double>();
|
| 116 |
+
}
|
| 117 |
+
|
| 118 |
+
bool guard_bool(const char* file, int64_t line) override {
|
| 119 |
+
py::gil_scoped_acquire acquire;
|
| 120 |
+
return getPyObj().attr("guard_bool")(file, line).cast<bool>();
|
| 121 |
+
}
|
| 122 |
+
|
| 123 |
+
bool expect_true(const char* file, int64_t line) override {
|
| 124 |
+
py::gil_scoped_acquire acquire;
|
| 125 |
+
return getPyObj().attr("expect_true")(file, line).cast<bool>();
|
| 126 |
+
}
|
| 127 |
+
|
| 128 |
+
bool expect_size(const char* file, int64_t line) override {
|
| 129 |
+
py::gil_scoped_acquire acquire;
|
| 130 |
+
return getPyObj().attr("expect_size")(file, line).cast<bool>();
|
| 131 |
+
}
|
| 132 |
+
|
| 133 |
+
bool guard_size_oblivious(const char* file, int64_t line) override {
|
| 134 |
+
py::gil_scoped_acquire acquire;
|
| 135 |
+
return getPyObj().attr("guard_size_oblivious")(file, line).cast<bool>();
|
| 136 |
+
}
|
| 137 |
+
|
| 138 |
+
bool guard_or_false(const char* file, int64_t line) override {
|
| 139 |
+
py::gil_scoped_acquire acquire;
|
| 140 |
+
return getPyObj().attr("guard_or_false")(file, line).cast<bool>();
|
| 141 |
+
}
|
| 142 |
+
|
| 143 |
+
bool statically_known_true(const char* file, int64_t line) override {
|
| 144 |
+
py::gil_scoped_acquire acquire;
|
| 145 |
+
return getPyObj().attr("statically_known_true")(file, line).cast<bool>();
|
| 146 |
+
}
|
| 147 |
+
|
| 148 |
+
bool guard_or_true(const char* file, int64_t line) override {
|
| 149 |
+
py::gil_scoped_acquire acquire;
|
| 150 |
+
return getPyObj().attr("guard_or_true")(file, line).cast<bool>();
|
| 151 |
+
}
|
| 152 |
+
|
| 153 |
+
int64_t int_() override {
|
| 154 |
+
py::gil_scoped_acquire acquire;
|
| 155 |
+
return getPyObj().attr("int_")().cast<int64_t>();
|
| 156 |
+
}
|
| 157 |
+
|
| 158 |
+
std::optional<int64_t> maybe_as_int() override {
|
| 159 |
+
py::gil_scoped_acquire acquire;
|
| 160 |
+
const auto& r = getPyObj().attr("maybe_as_int")();
|
| 161 |
+
if (r.is_none()) {
|
| 162 |
+
return std::nullopt;
|
| 163 |
+
} else {
|
| 164 |
+
return r.cast<int64_t>();
|
| 165 |
+
}
|
| 166 |
+
}
|
| 167 |
+
|
| 168 |
+
std::string str() override {
|
| 169 |
+
py::gil_scoped_acquire acquire;
|
| 170 |
+
return getPyObj().attr("str")().cast<std::string>();
|
| 171 |
+
}
|
| 172 |
+
|
| 173 |
+
std::string _graph_repr() override {
|
| 174 |
+
py::gil_scoped_acquire acquire;
|
| 175 |
+
return getPyObj().attr("_graph_repr")().cast<std::string>();
|
| 176 |
+
}
|
| 177 |
+
|
| 178 |
+
c10::SymNode dispatch_sym_ite_(
|
| 179 |
+
const char* fname,
|
| 180 |
+
const c10::SymNode& other,
|
| 181 |
+
const c10::SymNode& third) {
|
| 182 |
+
auto pother = dynamic_cast<PythonSymNodeImpl*>(other.get());
|
| 183 |
+
auto pthird = dynamic_cast<PythonSymNodeImpl*>(third.get());
|
| 184 |
+
TORCH_CHECK(pother);
|
| 185 |
+
TORCH_CHECK(pthird);
|
| 186 |
+
py::gil_scoped_acquire acquire;
|
| 187 |
+
auto r = getPyObj().attr(fname)(pother->getPyObj(), pthird->getPyObj());
|
| 188 |
+
return c10::make_intrusive<PythonSymNodeImpl>(r);
|
| 189 |
+
}
|
| 190 |
+
|
| 191 |
+
c10::SymNode dispatch_common_(const char* fname, const c10::SymNode& other) {
|
| 192 |
+
auto pother = dynamic_cast<PythonSymNodeImpl*>(other.get());
|
| 193 |
+
TORCH_CHECK(pother);
|
| 194 |
+
py::gil_scoped_acquire acquire;
|
| 195 |
+
auto r = getPyObj().attr(fname)(pother->getPyObj());
|
| 196 |
+
return c10::make_intrusive<PythonSymNodeImpl>(r);
|
| 197 |
+
}
|
| 198 |
+
|
| 199 |
+
c10::SymNode dispatch_common_(const char* fname) {
|
| 200 |
+
py::gil_scoped_acquire acquire;
|
| 201 |
+
auto r = getPyObj().attr(fname)();
|
| 202 |
+
return c10::make_intrusive<PythonSymNodeImpl>(r);
|
| 203 |
+
}
|
| 204 |
+
|
| 205 |
+
c10::SymNode add(const c10::SymNode& other) override {
|
| 206 |
+
return dispatch_common_(__func__, other);
|
| 207 |
+
}
|
| 208 |
+
|
| 209 |
+
c10::SymNode sub(const c10::SymNode& other) override {
|
| 210 |
+
return dispatch_common_(__func__, other);
|
| 211 |
+
}
|
| 212 |
+
|
| 213 |
+
c10::SymNode mul(const c10::SymNode& other) override {
|
| 214 |
+
return dispatch_common_(__func__, other);
|
| 215 |
+
}
|
| 216 |
+
|
| 217 |
+
c10::SymNode truediv(const c10::SymNode& other) override {
|
| 218 |
+
return dispatch_common_(__func__, other);
|
| 219 |
+
}
|
| 220 |
+
|
| 221 |
+
c10::SymNode float_truediv(const c10::SymNode& other) override {
|
| 222 |
+
return dispatch_common_(__func__, other);
|
| 223 |
+
}
|
| 224 |
+
|
| 225 |
+
c10::SymNode int_truediv(const c10::SymNode& other) override {
|
| 226 |
+
return dispatch_common_(__func__, other);
|
| 227 |
+
}
|
| 228 |
+
|
| 229 |
+
c10::SymNode pow(const c10::SymNode& other) override {
|
| 230 |
+
return dispatch_common_(__func__, other);
|
| 231 |
+
}
|
| 232 |
+
|
| 233 |
+
c10::SymNode float_pow(const c10::SymNode& other) override {
|
| 234 |
+
return dispatch_common_(__func__, other);
|
| 235 |
+
}
|
| 236 |
+
|
| 237 |
+
c10::SymNode pow_by_natural(const c10::SymNode& other) override {
|
| 238 |
+
return dispatch_common_(__func__, other);
|
| 239 |
+
}
|
| 240 |
+
|
| 241 |
+
c10::SymNode floordiv(const c10::SymNode& other) override {
|
| 242 |
+
return dispatch_common_(__func__, other);
|
| 243 |
+
}
|
| 244 |
+
|
| 245 |
+
c10::SymNode int_floordiv(const c10::SymNode& other) override {
|
| 246 |
+
return dispatch_common_(__func__, other);
|
| 247 |
+
}
|
| 248 |
+
|
| 249 |
+
c10::SymNode mod(const c10::SymNode& other) override {
|
| 250 |
+
return dispatch_common_(__func__, other);
|
| 251 |
+
}
|
| 252 |
+
|
| 253 |
+
c10::SymNode eq(const c10::SymNode& other) override {
|
| 254 |
+
return dispatch_common_(__func__, other);
|
| 255 |
+
}
|
| 256 |
+
|
| 257 |
+
c10::SymNode ne(const c10::SymNode& other) override {
|
| 258 |
+
return dispatch_common_(__func__, other);
|
| 259 |
+
}
|
| 260 |
+
|
| 261 |
+
c10::SymNode gt(const c10::SymNode& other) override {
|
| 262 |
+
return dispatch_common_(__func__, other);
|
| 263 |
+
}
|
| 264 |
+
|
| 265 |
+
c10::SymNode lt(const c10::SymNode& other) override {
|
| 266 |
+
return dispatch_common_(__func__, other);
|
| 267 |
+
}
|
| 268 |
+
|
| 269 |
+
c10::SymNode le(const c10::SymNode& other) override {
|
| 270 |
+
return dispatch_common_(__func__, other);
|
| 271 |
+
}
|
| 272 |
+
|
| 273 |
+
c10::SymNode ge(const c10::SymNode& other) override {
|
| 274 |
+
return dispatch_common_(__func__, other);
|
| 275 |
+
}
|
| 276 |
+
|
| 277 |
+
c10::SymNode sym_min(const c10::SymNode& other) override {
|
| 278 |
+
return dispatch_common_(__func__, other);
|
| 279 |
+
}
|
| 280 |
+
c10::SymNode sym_max(const c10::SymNode& other) override {
|
| 281 |
+
return dispatch_common_(__func__, other);
|
| 282 |
+
}
|
| 283 |
+
|
| 284 |
+
c10::SymNode sym_and(const c10::SymNode& other) override {
|
| 285 |
+
return dispatch_common_(__func__, other);
|
| 286 |
+
}
|
| 287 |
+
|
| 288 |
+
c10::SymNode sym_or(const c10::SymNode& other) override {
|
| 289 |
+
return dispatch_common_(__func__, other);
|
| 290 |
+
}
|
| 291 |
+
|
| 292 |
+
c10::SymNode sym_ite(const c10::SymNode& other, const c10::SymNode& third)
|
| 293 |
+
override {
|
| 294 |
+
return dispatch_sym_ite_(__func__, other, third);
|
| 295 |
+
}
|
| 296 |
+
|
| 297 |
+
c10::SymNode sym_not() override {
|
| 298 |
+
return dispatch_common_(__func__);
|
| 299 |
+
}
|
| 300 |
+
|
| 301 |
+
c10::SymNode ceil() override {
|
| 302 |
+
return dispatch_common_(__func__);
|
| 303 |
+
}
|
| 304 |
+
|
| 305 |
+
c10::SymNode floor() override {
|
| 306 |
+
return dispatch_common_(__func__);
|
| 307 |
+
}
|
| 308 |
+
|
| 309 |
+
c10::SymNode neg() override {
|
| 310 |
+
return dispatch_common_(__func__);
|
| 311 |
+
}
|
| 312 |
+
|
| 313 |
+
c10::SymNode clone() override {
|
| 314 |
+
return dispatch_common_(__func__);
|
| 315 |
+
}
|
| 316 |
+
|
| 317 |
+
c10::SymNode sym_float() override {
|
| 318 |
+
return dispatch_common_(__func__);
|
| 319 |
+
}
|
| 320 |
+
|
| 321 |
+
py::handle getPyObj() const {
|
| 322 |
+
return py::handle(pyobj_->ptr(getPyInterpreter()));
|
| 323 |
+
}
|
| 324 |
+
std::shared_ptr<c10::SafePyObject> pyobj_ = nullptr;
|
| 325 |
+
};
|
| 326 |
+
|
| 327 |
+
} // namespace impl
|
| 328 |
+
} // namespace torch
|
phivenv/Lib/site-packages/torch/include/torch/csrc/utils/python_torch_function_mode.h
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#pragma once
|
| 2 |
+
|
| 3 |
+
#include <ATen/PythonTorchFunctionTLS.h>
|
| 4 |
+
|
| 5 |
+
namespace torch::overrides {
|
| 6 |
+
|
| 7 |
+
struct StashTorchFunctionModeGuard {
|
| 8 |
+
StashTorchFunctionModeGuard() {
|
| 9 |
+
cur_mode_ = at::impl::PythonTorchFunctionTLS::pop_stack();
|
| 10 |
+
}
|
| 11 |
+
~StashTorchFunctionModeGuard() {
|
| 12 |
+
at::impl::PythonTorchFunctionTLS::push_onto_stack(cur_mode_);
|
| 13 |
+
}
|
| 14 |
+
StashTorchFunctionModeGuard(const StashTorchFunctionModeGuard&) = delete;
|
| 15 |
+
StashTorchFunctionModeGuard(StashTorchFunctionModeGuard&&) = delete;
|
| 16 |
+
StashTorchFunctionModeGuard& operator=(const StashTorchFunctionModeGuard&) =
|
| 17 |
+
delete;
|
| 18 |
+
StashTorchFunctionModeGuard& operator=(StashTorchFunctionModeGuard&&) =
|
| 19 |
+
delete;
|
| 20 |
+
|
| 21 |
+
const std::shared_ptr<c10::SafePyObject>& get_cur_mode() {
|
| 22 |
+
return cur_mode_;
|
| 23 |
+
}
|
| 24 |
+
|
| 25 |
+
private:
|
| 26 |
+
std::shared_ptr<c10::SafePyObject> cur_mode_;
|
| 27 |
+
};
|
| 28 |
+
|
| 29 |
+
} // namespace torch::overrides
|
phivenv/Lib/site-packages/torch/include/torch/csrc/utils/python_tuples.h
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#pragma once
|
| 2 |
+
|
| 3 |
+
#include <torch/csrc/Exceptions.h>
|
| 4 |
+
#include <torch/csrc/python_headers.h>
|
| 5 |
+
#include <torch/csrc/utils/object_ptr.h>
|
| 6 |
+
#include <torch/csrc/utils/python_numbers.h>
|
| 7 |
+
|
| 8 |
+
inline void THPUtils_packInt64Array(
|
| 9 |
+
PyObject* tuple,
|
| 10 |
+
size_t size,
|
| 11 |
+
const int64_t* sizes) {
|
| 12 |
+
for (size_t i = 0; i != size; ++i) {
|
| 13 |
+
PyObject* i64 = THPUtils_packInt64(sizes[i]);
|
| 14 |
+
if (!i64) {
|
| 15 |
+
throw python_error();
|
| 16 |
+
}
|
| 17 |
+
PyTuple_SET_ITEM(tuple, i, i64);
|
| 18 |
+
}
|
| 19 |
+
}
|
| 20 |
+
|
| 21 |
+
inline PyObject* THPUtils_packInt64Array(size_t size, const int64_t* sizes) {
|
| 22 |
+
THPObjectPtr tuple(PyTuple_New(static_cast<Py_ssize_t>(size)));
|
| 23 |
+
if (!tuple)
|
| 24 |
+
throw python_error();
|
| 25 |
+
THPUtils_packInt64Array(tuple.get(), size, sizes);
|
| 26 |
+
return tuple.release();
|
| 27 |
+
}
|
phivenv/Lib/site-packages/torch/include/torch/csrc/utils/pythoncapi_compat.h
ADDED
|
@@ -0,0 +1,1520 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
// Header file providing new C API functions to old Python versions.
|
| 2 |
+
//
|
| 3 |
+
// File distributed under the Zero Clause BSD (0BSD) license.
|
| 4 |
+
// Copyright Contributors to the pythoncapi_compat project.
|
| 5 |
+
//
|
| 6 |
+
// Homepage:
|
| 7 |
+
// https://github.com/python/pythoncapi_compat
|
| 8 |
+
//
|
| 9 |
+
// Latest version:
|
| 10 |
+
// https://raw.githubusercontent.com/python/pythoncapi_compat/master/pythoncapi_compat.h
|
| 11 |
+
//
|
| 12 |
+
// SPDX-License-Identifier: 0BSD
|
| 13 |
+
|
| 14 |
+
#ifndef PYTHONCAPI_COMPAT
|
| 15 |
+
#define PYTHONCAPI_COMPAT
|
| 16 |
+
|
| 17 |
+
#ifdef __cplusplus
|
| 18 |
+
extern "C" {
|
| 19 |
+
#endif
|
| 20 |
+
|
| 21 |
+
#include <Python.h>
|
| 22 |
+
|
| 23 |
+
// Python 3.11.0b4 added PyFrame_Back() to Python.h
|
| 24 |
+
#if PY_VERSION_HEX < 0x030b00B4 && !defined(PYPY_VERSION)
|
| 25 |
+
# include "frameobject.h" // PyFrameObject, PyFrame_GetBack()
|
| 26 |
+
#endif
|
| 27 |
+
|
| 28 |
+
|
| 29 |
+
#ifndef _Py_CAST
|
| 30 |
+
# define _Py_CAST(type, expr) ((type)(expr))
|
| 31 |
+
#endif
|
| 32 |
+
|
| 33 |
+
// Static inline functions should use _Py_NULL rather than using directly NULL
|
| 34 |
+
// to prevent C++ compiler warnings. On C23 and newer and on C++11 and newer,
|
| 35 |
+
// _Py_NULL is defined as nullptr.
|
| 36 |
+
#if (defined (__STDC_VERSION__) && __STDC_VERSION__ > 201710L) \
|
| 37 |
+
|| (defined(__cplusplus) && __cplusplus >= 201103)
|
| 38 |
+
# define _Py_NULL nullptr
|
| 39 |
+
#else
|
| 40 |
+
# define _Py_NULL NULL
|
| 41 |
+
#endif
|
| 42 |
+
|
| 43 |
+
// Cast argument to PyObject* type.
|
| 44 |
+
#ifndef _PyObject_CAST
|
| 45 |
+
# define _PyObject_CAST(op) _Py_CAST(PyObject*, op)
|
| 46 |
+
#endif
|
| 47 |
+
|
| 48 |
+
|
| 49 |
+
// bpo-42262 added Py_NewRef() to Python 3.10.0a3
|
| 50 |
+
#if PY_VERSION_HEX < 0x030A00A3 && !defined(Py_NewRef)
|
| 51 |
+
static inline PyObject* _Py_NewRef(PyObject *obj)
|
| 52 |
+
{
|
| 53 |
+
Py_INCREF(obj);
|
| 54 |
+
return obj;
|
| 55 |
+
}
|
| 56 |
+
#define Py_NewRef(obj) _Py_NewRef(_PyObject_CAST(obj))
|
| 57 |
+
#endif
|
| 58 |
+
|
| 59 |
+
|
| 60 |
+
// bpo-42262 added Py_XNewRef() to Python 3.10.0a3
|
| 61 |
+
#if PY_VERSION_HEX < 0x030A00A3 && !defined(Py_XNewRef)
|
| 62 |
+
static inline PyObject* _Py_XNewRef(PyObject *obj)
|
| 63 |
+
{
|
| 64 |
+
Py_XINCREF(obj);
|
| 65 |
+
return obj;
|
| 66 |
+
}
|
| 67 |
+
#define Py_XNewRef(obj) _Py_XNewRef(_PyObject_CAST(obj))
|
| 68 |
+
#endif
|
| 69 |
+
|
| 70 |
+
|
| 71 |
+
// bpo-39573 added Py_SET_REFCNT() to Python 3.9.0a4
|
| 72 |
+
#if PY_VERSION_HEX < 0x030900A4 && !defined(Py_SET_REFCNT)
|
| 73 |
+
static inline void _Py_SET_REFCNT(PyObject *ob, Py_ssize_t refcnt)
|
| 74 |
+
{
|
| 75 |
+
ob->ob_refcnt = refcnt;
|
| 76 |
+
}
|
| 77 |
+
#define Py_SET_REFCNT(ob, refcnt) _Py_SET_REFCNT(_PyObject_CAST(ob), refcnt)
|
| 78 |
+
#endif
|
| 79 |
+
|
| 80 |
+
|
| 81 |
+
// Py_SETREF() and Py_XSETREF() were added to Python 3.5.2.
|
| 82 |
+
// It is excluded from the limited C API.
|
| 83 |
+
#if (PY_VERSION_HEX < 0x03050200 && !defined(Py_SETREF)) && !defined(Py_LIMITED_API)
|
| 84 |
+
#define Py_SETREF(dst, src) \
|
| 85 |
+
do { \
|
| 86 |
+
PyObject **_tmp_dst_ptr = _Py_CAST(PyObject**, &(dst)); \
|
| 87 |
+
PyObject *_tmp_dst = (*_tmp_dst_ptr); \
|
| 88 |
+
*_tmp_dst_ptr = _PyObject_CAST(src); \
|
| 89 |
+
Py_DECREF(_tmp_dst); \
|
| 90 |
+
} while (0)
|
| 91 |
+
|
| 92 |
+
#define Py_XSETREF(dst, src) \
|
| 93 |
+
do { \
|
| 94 |
+
PyObject **_tmp_dst_ptr = _Py_CAST(PyObject**, &(dst)); \
|
| 95 |
+
PyObject *_tmp_dst = (*_tmp_dst_ptr); \
|
| 96 |
+
*_tmp_dst_ptr = _PyObject_CAST(src); \
|
| 97 |
+
Py_XDECREF(_tmp_dst); \
|
| 98 |
+
} while (0)
|
| 99 |
+
#endif
|
| 100 |
+
|
| 101 |
+
|
| 102 |
+
// bpo-43753 added Py_Is(), Py_IsNone(), Py_IsTrue() and Py_IsFalse()
|
| 103 |
+
// to Python 3.10.0b1.
|
| 104 |
+
#if PY_VERSION_HEX < 0x030A00B1 && !defined(Py_Is)
|
| 105 |
+
# define Py_Is(x, y) ((x) == (y))
|
| 106 |
+
#endif
|
| 107 |
+
#if PY_VERSION_HEX < 0x030A00B1 && !defined(Py_IsNone)
|
| 108 |
+
# define Py_IsNone(x) Py_Is(x, Py_None)
|
| 109 |
+
#endif
|
| 110 |
+
#if (PY_VERSION_HEX < 0x030A00B1 || defined(PYPY_VERSION)) && !defined(Py_IsTrue)
|
| 111 |
+
# define Py_IsTrue(x) Py_Is(x, Py_True)
|
| 112 |
+
#endif
|
| 113 |
+
#if (PY_VERSION_HEX < 0x030A00B1 || defined(PYPY_VERSION)) && !defined(Py_IsFalse)
|
| 114 |
+
# define Py_IsFalse(x) Py_Is(x, Py_False)
|
| 115 |
+
#endif
|
| 116 |
+
|
| 117 |
+
|
| 118 |
+
// bpo-39573 added Py_SET_TYPE() to Python 3.9.0a4
|
| 119 |
+
#if PY_VERSION_HEX < 0x030900A4 && !defined(Py_SET_TYPE)
|
| 120 |
+
static inline void _Py_SET_TYPE(PyObject *ob, PyTypeObject *type)
|
| 121 |
+
{
|
| 122 |
+
ob->ob_type = type;
|
| 123 |
+
}
|
| 124 |
+
#define Py_SET_TYPE(ob, type) _Py_SET_TYPE(_PyObject_CAST(ob), type)
|
| 125 |
+
#endif
|
| 126 |
+
|
| 127 |
+
|
| 128 |
+
// bpo-39573 added Py_SET_SIZE() to Python 3.9.0a4
|
| 129 |
+
#if PY_VERSION_HEX < 0x030900A4 && !defined(Py_SET_SIZE)
|
| 130 |
+
static inline void _Py_SET_SIZE(PyVarObject *ob, Py_ssize_t size)
|
| 131 |
+
{
|
| 132 |
+
ob->ob_size = size;
|
| 133 |
+
}
|
| 134 |
+
#define Py_SET_SIZE(ob, size) _Py_SET_SIZE((PyVarObject*)(ob), size)
|
| 135 |
+
#endif
|
| 136 |
+
|
| 137 |
+
|
| 138 |
+
// bpo-40421 added PyFrame_GetCode() to Python 3.9.0b1
|
| 139 |
+
#if PY_VERSION_HEX < 0x030900B1 || defined(PYPY_VERSION)
|
| 140 |
+
static inline PyCodeObject* PyFrame_GetCode(PyFrameObject *frame)
|
| 141 |
+
{
|
| 142 |
+
assert(frame != _Py_NULL);
|
| 143 |
+
assert(frame->f_code != _Py_NULL);
|
| 144 |
+
return _Py_CAST(PyCodeObject*, Py_NewRef(frame->f_code));
|
| 145 |
+
}
|
| 146 |
+
#endif
|
| 147 |
+
|
| 148 |
+
static inline PyCodeObject* _PyFrame_GetCodeBorrow(PyFrameObject *frame)
|
| 149 |
+
{
|
| 150 |
+
PyCodeObject *code = PyFrame_GetCode(frame);
|
| 151 |
+
Py_DECREF(code);
|
| 152 |
+
return code;
|
| 153 |
+
}
|
| 154 |
+
|
| 155 |
+
|
| 156 |
+
// bpo-40421 added PyFrame_GetBack() to Python 3.9.0b1
|
| 157 |
+
#if PY_VERSION_HEX < 0x030900B1 && !defined(PYPY_VERSION)
|
| 158 |
+
static inline PyFrameObject* PyFrame_GetBack(PyFrameObject *frame)
|
| 159 |
+
{
|
| 160 |
+
assert(frame != _Py_NULL);
|
| 161 |
+
return _Py_CAST(PyFrameObject*, Py_XNewRef(frame->f_back));
|
| 162 |
+
}
|
| 163 |
+
#endif
|
| 164 |
+
|
| 165 |
+
#if !defined(PYPY_VERSION)
|
| 166 |
+
static inline PyFrameObject* _PyFrame_GetBackBorrow(PyFrameObject *frame)
|
| 167 |
+
{
|
| 168 |
+
PyFrameObject *back = PyFrame_GetBack(frame);
|
| 169 |
+
Py_XDECREF(back);
|
| 170 |
+
return back;
|
| 171 |
+
}
|
| 172 |
+
#endif
|
| 173 |
+
|
| 174 |
+
|
| 175 |
+
// bpo-40421 added PyFrame_GetLocals() to Python 3.11.0a7
|
| 176 |
+
#if PY_VERSION_HEX < 0x030B00A7 && !defined(PYPY_VERSION)
|
| 177 |
+
static inline PyObject* PyFrame_GetLocals(PyFrameObject *frame)
|
| 178 |
+
{
|
| 179 |
+
#if PY_VERSION_HEX >= 0x030400B1
|
| 180 |
+
if (PyFrame_FastToLocalsWithError(frame) < 0) {
|
| 181 |
+
return NULL;
|
| 182 |
+
}
|
| 183 |
+
#else
|
| 184 |
+
PyFrame_FastToLocals(frame);
|
| 185 |
+
#endif
|
| 186 |
+
return Py_NewRef(frame->f_locals);
|
| 187 |
+
}
|
| 188 |
+
#endif
|
| 189 |
+
|
| 190 |
+
|
| 191 |
+
// bpo-40421 added PyFrame_GetGlobals() to Python 3.11.0a7
|
| 192 |
+
#if PY_VERSION_HEX < 0x030B00A7 && !defined(PYPY_VERSION)
|
| 193 |
+
static inline PyObject* PyFrame_GetGlobals(PyFrameObject *frame)
|
| 194 |
+
{
|
| 195 |
+
return Py_NewRef(frame->f_globals);
|
| 196 |
+
}
|
| 197 |
+
#endif
|
| 198 |
+
|
| 199 |
+
|
| 200 |
+
// bpo-40421 added PyFrame_GetBuiltins() to Python 3.11.0a7
|
| 201 |
+
#if PY_VERSION_HEX < 0x030B00A7 && !defined(PYPY_VERSION)
|
| 202 |
+
static inline PyObject* PyFrame_GetBuiltins(PyFrameObject *frame)
|
| 203 |
+
{
|
| 204 |
+
return Py_NewRef(frame->f_builtins);
|
| 205 |
+
}
|
| 206 |
+
#endif
|
| 207 |
+
|
| 208 |
+
|
| 209 |
+
// bpo-40421 added PyFrame_GetLasti() to Python 3.11.0b1
|
| 210 |
+
#if PY_VERSION_HEX < 0x030B00B1 && !defined(PYPY_VERSION)
|
| 211 |
+
static inline int PyFrame_GetLasti(PyFrameObject *frame)
|
| 212 |
+
{
|
| 213 |
+
#if PY_VERSION_HEX >= 0x030A00A7
|
| 214 |
+
// bpo-27129: Since Python 3.10.0a7, f_lasti is an instruction offset,
|
| 215 |
+
// not a bytes offset anymore. Python uses 16-bit "wordcode" (2 bytes)
|
| 216 |
+
// instructions.
|
| 217 |
+
if (frame->f_lasti < 0) {
|
| 218 |
+
return -1;
|
| 219 |
+
}
|
| 220 |
+
return frame->f_lasti * 2;
|
| 221 |
+
#else
|
| 222 |
+
return frame->f_lasti;
|
| 223 |
+
#endif
|
| 224 |
+
}
|
| 225 |
+
#endif
|
| 226 |
+
|
| 227 |
+
|
| 228 |
+
// gh-91248 added PyFrame_GetVar() to Python 3.12.0a2
|
| 229 |
+
#if PY_VERSION_HEX < 0x030C00A2 && !defined(PYPY_VERSION)
|
| 230 |
+
static inline PyObject* PyFrame_GetVar(PyFrameObject *frame, PyObject *name)
|
| 231 |
+
{
|
| 232 |
+
PyObject *locals, *value;
|
| 233 |
+
|
| 234 |
+
locals = PyFrame_GetLocals(frame);
|
| 235 |
+
if (locals == NULL) {
|
| 236 |
+
return NULL;
|
| 237 |
+
}
|
| 238 |
+
#if PY_VERSION_HEX >= 0x03000000
|
| 239 |
+
value = PyDict_GetItemWithError(locals, name);
|
| 240 |
+
#else
|
| 241 |
+
value = _PyDict_GetItemWithError(locals, name);
|
| 242 |
+
#endif
|
| 243 |
+
Py_DECREF(locals);
|
| 244 |
+
|
| 245 |
+
if (value == NULL) {
|
| 246 |
+
if (PyErr_Occurred()) {
|
| 247 |
+
return NULL;
|
| 248 |
+
}
|
| 249 |
+
#if PY_VERSION_HEX >= 0x03000000
|
| 250 |
+
PyErr_Format(PyExc_NameError, "variable %R does not exist", name);
|
| 251 |
+
#else
|
| 252 |
+
PyErr_SetString(PyExc_NameError, "variable does not exist");
|
| 253 |
+
#endif
|
| 254 |
+
return NULL;
|
| 255 |
+
}
|
| 256 |
+
return Py_NewRef(value);
|
| 257 |
+
}
|
| 258 |
+
#endif
|
| 259 |
+
|
| 260 |
+
|
| 261 |
+
// gh-91248 added PyFrame_GetVarString() to Python 3.12.0a2
|
| 262 |
+
#if PY_VERSION_HEX < 0x030C00A2 && !defined(PYPY_VERSION)
|
| 263 |
+
static inline PyObject*
|
| 264 |
+
PyFrame_GetVarString(PyFrameObject *frame, const char *name)
|
| 265 |
+
{
|
| 266 |
+
PyObject *name_obj, *value;
|
| 267 |
+
#if PY_VERSION_HEX >= 0x03000000
|
| 268 |
+
name_obj = PyUnicode_FromString(name);
|
| 269 |
+
#else
|
| 270 |
+
name_obj = PyString_FromString(name);
|
| 271 |
+
#endif
|
| 272 |
+
if (name_obj == NULL) {
|
| 273 |
+
return NULL;
|
| 274 |
+
}
|
| 275 |
+
value = PyFrame_GetVar(frame, name_obj);
|
| 276 |
+
Py_DECREF(name_obj);
|
| 277 |
+
return value;
|
| 278 |
+
}
|
| 279 |
+
#endif
|
| 280 |
+
|
| 281 |
+
|
| 282 |
+
// bpo-39947 added PyThreadState_GetInterpreter() to Python 3.9.0a5
|
| 283 |
+
#if PY_VERSION_HEX < 0x030900A5 || defined(PYPY_VERSION)
|
| 284 |
+
static inline PyInterpreterState *
|
| 285 |
+
PyThreadState_GetInterpreter(PyThreadState *tstate)
|
| 286 |
+
{
|
| 287 |
+
assert(tstate != _Py_NULL);
|
| 288 |
+
return tstate->interp;
|
| 289 |
+
}
|
| 290 |
+
#endif
|
| 291 |
+
|
| 292 |
+
|
| 293 |
+
// bpo-40429 added PyThreadState_GetFrame() to Python 3.9.0b1
|
| 294 |
+
#if PY_VERSION_HEX < 0x030900B1 && !defined(PYPY_VERSION)
|
| 295 |
+
static inline PyFrameObject* PyThreadState_GetFrame(PyThreadState *tstate)
|
| 296 |
+
{
|
| 297 |
+
assert(tstate != _Py_NULL);
|
| 298 |
+
return _Py_CAST(PyFrameObject *, Py_XNewRef(tstate->frame));
|
| 299 |
+
}
|
| 300 |
+
#endif
|
| 301 |
+
|
| 302 |
+
#if !defined(PYPY_VERSION)
|
| 303 |
+
static inline PyFrameObject*
|
| 304 |
+
_PyThreadState_GetFrameBorrow(PyThreadState *tstate)
|
| 305 |
+
{
|
| 306 |
+
PyFrameObject *frame = PyThreadState_GetFrame(tstate);
|
| 307 |
+
Py_XDECREF(frame);
|
| 308 |
+
return frame;
|
| 309 |
+
}
|
| 310 |
+
#endif
|
| 311 |
+
|
| 312 |
+
|
| 313 |
+
// bpo-39947 added PyInterpreterState_Get() to Python 3.9.0a5
|
| 314 |
+
#if PY_VERSION_HEX < 0x030900A5 || defined(PYPY_VERSION)
|
| 315 |
+
static inline PyInterpreterState* PyInterpreterState_Get(void)
|
| 316 |
+
{
|
| 317 |
+
PyThreadState *tstate;
|
| 318 |
+
PyInterpreterState *interp;
|
| 319 |
+
|
| 320 |
+
tstate = PyThreadState_GET();
|
| 321 |
+
if (tstate == _Py_NULL) {
|
| 322 |
+
Py_FatalError("GIL released (tstate is NULL)");
|
| 323 |
+
}
|
| 324 |
+
interp = tstate->interp;
|
| 325 |
+
if (interp == _Py_NULL) {
|
| 326 |
+
Py_FatalError("no current interpreter");
|
| 327 |
+
}
|
| 328 |
+
return interp;
|
| 329 |
+
}
|
| 330 |
+
#endif
|
| 331 |
+
|
| 332 |
+
|
| 333 |
+
// bpo-39947 added PyInterpreterState_Get() to Python 3.9.0a6
|
| 334 |
+
#if 0x030700A1 <= PY_VERSION_HEX && PY_VERSION_HEX < 0x030900A6 && !defined(PYPY_VERSION)
|
| 335 |
+
static inline uint64_t PyThreadState_GetID(PyThreadState *tstate)
|
| 336 |
+
{
|
| 337 |
+
assert(tstate != _Py_NULL);
|
| 338 |
+
return tstate->id;
|
| 339 |
+
}
|
| 340 |
+
#endif
|
| 341 |
+
|
| 342 |
+
// bpo-43760 added PyThreadState_EnterTracing() to Python 3.11.0a2
|
| 343 |
+
#if PY_VERSION_HEX < 0x030B00A2 && !defined(PYPY_VERSION)
|
| 344 |
+
static inline void PyThreadState_EnterTracing(PyThreadState *tstate)
|
| 345 |
+
{
|
| 346 |
+
tstate->tracing++;
|
| 347 |
+
#if PY_VERSION_HEX >= 0x030A00A1
|
| 348 |
+
tstate->cframe->use_tracing = 0;
|
| 349 |
+
#else
|
| 350 |
+
tstate->use_tracing = 0;
|
| 351 |
+
#endif
|
| 352 |
+
}
|
| 353 |
+
#endif
|
| 354 |
+
|
| 355 |
+
// bpo-43760 added PyThreadState_LeaveTracing() to Python 3.11.0a2
|
| 356 |
+
#if PY_VERSION_HEX < 0x030B00A2 && !defined(PYPY_VERSION)
|
| 357 |
+
static inline void PyThreadState_LeaveTracing(PyThreadState *tstate)
|
| 358 |
+
{
|
| 359 |
+
int use_tracing = (tstate->c_tracefunc != _Py_NULL
|
| 360 |
+
|| tstate->c_profilefunc != _Py_NULL);
|
| 361 |
+
tstate->tracing--;
|
| 362 |
+
#if PY_VERSION_HEX >= 0x030A00A1
|
| 363 |
+
tstate->cframe->use_tracing = use_tracing;
|
| 364 |
+
#else
|
| 365 |
+
tstate->use_tracing = use_tracing;
|
| 366 |
+
#endif
|
| 367 |
+
}
|
| 368 |
+
#endif
|
| 369 |
+
|
| 370 |
+
|
| 371 |
+
// bpo-37194 added PyObject_CallNoArgs() to Python 3.9.0a1
|
| 372 |
+
// PyObject_CallNoArgs() added to PyPy 3.9.16-v7.3.11
|
| 373 |
+
#if !defined(PyObject_CallNoArgs) && PY_VERSION_HEX < 0x030900A1
|
| 374 |
+
static inline PyObject* PyObject_CallNoArgs(PyObject *func)
|
| 375 |
+
{
|
| 376 |
+
return PyObject_CallFunctionObjArgs(func, NULL);
|
| 377 |
+
}
|
| 378 |
+
#endif
|
| 379 |
+
|
| 380 |
+
|
| 381 |
+
// bpo-39245 made PyObject_CallOneArg() public (previously called
|
| 382 |
+
// _PyObject_CallOneArg) in Python 3.9.0a4
|
| 383 |
+
// PyObject_CallOneArg() added to PyPy 3.9.16-v7.3.11
|
| 384 |
+
#if !defined(PyObject_CallOneArg) && PY_VERSION_HEX < 0x030900A4
|
| 385 |
+
static inline PyObject* PyObject_CallOneArg(PyObject *func, PyObject *arg)
|
| 386 |
+
{
|
| 387 |
+
return PyObject_CallFunctionObjArgs(func, arg, NULL);
|
| 388 |
+
}
|
| 389 |
+
#endif
|
| 390 |
+
|
| 391 |
+
|
| 392 |
+
// bpo-1635741 added PyModule_AddObjectRef() to Python 3.10.0a3
|
| 393 |
+
#if PY_VERSION_HEX < 0x030A00A3
|
| 394 |
+
static inline int
|
| 395 |
+
PyModule_AddObjectRef(PyObject *module, const char *name, PyObject *value)
|
| 396 |
+
{
|
| 397 |
+
int res;
|
| 398 |
+
|
| 399 |
+
if (!value && !PyErr_Occurred()) {
|
| 400 |
+
// PyModule_AddObject() raises TypeError in this case
|
| 401 |
+
PyErr_SetString(PyExc_SystemError,
|
| 402 |
+
"PyModule_AddObjectRef() must be called "
|
| 403 |
+
"with an exception raised if value is NULL");
|
| 404 |
+
return -1;
|
| 405 |
+
}
|
| 406 |
+
|
| 407 |
+
Py_XINCREF(value);
|
| 408 |
+
res = PyModule_AddObject(module, name, value);
|
| 409 |
+
if (res < 0) {
|
| 410 |
+
Py_XDECREF(value);
|
| 411 |
+
}
|
| 412 |
+
return res;
|
| 413 |
+
}
|
| 414 |
+
#endif
|
| 415 |
+
|
| 416 |
+
|
| 417 |
+
// bpo-40024 added PyModule_AddType() to Python 3.9.0a5
|
| 418 |
+
#if PY_VERSION_HEX < 0x030900A5
|
| 419 |
+
static inline int PyModule_AddType(PyObject *module, PyTypeObject *type)
|
| 420 |
+
{
|
| 421 |
+
const char *name, *dot;
|
| 422 |
+
|
| 423 |
+
if (PyType_Ready(type) < 0) {
|
| 424 |
+
return -1;
|
| 425 |
+
}
|
| 426 |
+
|
| 427 |
+
// inline _PyType_Name()
|
| 428 |
+
name = type->tp_name;
|
| 429 |
+
assert(name != _Py_NULL);
|
| 430 |
+
dot = strrchr(name, '.');
|
| 431 |
+
if (dot != _Py_NULL) {
|
| 432 |
+
name = dot + 1;
|
| 433 |
+
}
|
| 434 |
+
|
| 435 |
+
return PyModule_AddObjectRef(module, name, _PyObject_CAST(type));
|
| 436 |
+
}
|
| 437 |
+
#endif
|
| 438 |
+
|
| 439 |
+
|
| 440 |
+
// bpo-40241 added PyObject_GC_IsTracked() to Python 3.9.0a6.
|
| 441 |
+
// bpo-4688 added _PyObject_GC_IS_TRACKED() to Python 2.7.0a2.
|
| 442 |
+
#if PY_VERSION_HEX < 0x030900A6 && !defined(PYPY_VERSION)
|
| 443 |
+
static inline int PyObject_GC_IsTracked(PyObject* obj)
|
| 444 |
+
{
|
| 445 |
+
return (PyObject_IS_GC(obj) && _PyObject_GC_IS_TRACKED(obj));
|
| 446 |
+
}
|
| 447 |
+
#endif
|
| 448 |
+
|
| 449 |
+
// bpo-40241 added PyObject_GC_IsFinalized() to Python 3.9.0a6.
|
| 450 |
+
// bpo-18112 added _PyGCHead_FINALIZED() to Python 3.4.0 final.
|
| 451 |
+
#if PY_VERSION_HEX < 0x030900A6 && PY_VERSION_HEX >= 0x030400F0 && !defined(PYPY_VERSION)
|
| 452 |
+
static inline int PyObject_GC_IsFinalized(PyObject *obj)
|
| 453 |
+
{
|
| 454 |
+
PyGC_Head *gc = _Py_CAST(PyGC_Head*, obj) - 1;
|
| 455 |
+
return (PyObject_IS_GC(obj) && _PyGCHead_FINALIZED(gc));
|
| 456 |
+
}
|
| 457 |
+
#endif
|
| 458 |
+
|
| 459 |
+
|
| 460 |
+
// bpo-39573 added Py_IS_TYPE() to Python 3.9.0a4
|
| 461 |
+
#if PY_VERSION_HEX < 0x030900A4 && !defined(Py_IS_TYPE)
|
| 462 |
+
static inline int _Py_IS_TYPE(PyObject *ob, PyTypeObject *type) {
|
| 463 |
+
return Py_TYPE(ob) == type;
|
| 464 |
+
}
|
| 465 |
+
#define Py_IS_TYPE(ob, type) _Py_IS_TYPE(_PyObject_CAST(ob), type)
|
| 466 |
+
#endif
|
| 467 |
+
|
| 468 |
+
|
| 469 |
+
// bpo-46906 added PyFloat_Pack2() and PyFloat_Unpack2() to Python 3.11a7.
|
| 470 |
+
// bpo-11734 added _PyFloat_Pack2() and _PyFloat_Unpack2() to Python 3.6.0b1.
|
| 471 |
+
// Python 3.11a2 moved _PyFloat_Pack2() and _PyFloat_Unpack2() to the internal
|
| 472 |
+
// C API: Python 3.11a2-3.11a6 versions are not supported.
|
| 473 |
+
#if 0x030600B1 <= PY_VERSION_HEX && PY_VERSION_HEX <= 0x030B00A1 && !defined(PYPY_VERSION)
|
| 474 |
+
static inline int PyFloat_Pack2(double x, char *p, int le)
|
| 475 |
+
{ return _PyFloat_Pack2(x, (unsigned char*)p, le); }
|
| 476 |
+
|
| 477 |
+
static inline double PyFloat_Unpack2(const char *p, int le)
|
| 478 |
+
{ return _PyFloat_Unpack2((const unsigned char *)p, le); }
|
| 479 |
+
#endif
|
| 480 |
+
|
| 481 |
+
|
| 482 |
+
// bpo-46906 added PyFloat_Pack4(), PyFloat_Pack8(), PyFloat_Unpack4() and
|
| 483 |
+
// PyFloat_Unpack8() to Python 3.11a7.
|
| 484 |
+
// Python 3.11a2 moved _PyFloat_Pack4(), _PyFloat_Pack8(), _PyFloat_Unpack4()
|
| 485 |
+
// and _PyFloat_Unpack8() to the internal C API: Python 3.11a2-3.11a6 versions
|
| 486 |
+
// are not supported.
|
| 487 |
+
#if PY_VERSION_HEX <= 0x030B00A1 && !defined(PYPY_VERSION)
|
| 488 |
+
static inline int PyFloat_Pack4(double x, char *p, int le)
|
| 489 |
+
{ return _PyFloat_Pack4(x, (unsigned char*)p, le); }
|
| 490 |
+
|
| 491 |
+
static inline int PyFloat_Pack8(double x, char *p, int le)
|
| 492 |
+
{ return _PyFloat_Pack8(x, (unsigned char*)p, le); }
|
| 493 |
+
|
| 494 |
+
static inline double PyFloat_Unpack4(const char *p, int le)
|
| 495 |
+
{ return _PyFloat_Unpack4((const unsigned char *)p, le); }
|
| 496 |
+
|
| 497 |
+
static inline double PyFloat_Unpack8(const char *p, int le)
|
| 498 |
+
{ return _PyFloat_Unpack8((const unsigned char *)p, le); }
|
| 499 |
+
#endif
|
| 500 |
+
|
| 501 |
+
|
| 502 |
+
// gh-92154 added PyCode_GetCode() to Python 3.11.0b1
|
| 503 |
+
#if PY_VERSION_HEX < 0x030B00B1 && !defined(PYPY_VERSION)
|
| 504 |
+
static inline PyObject* PyCode_GetCode(PyCodeObject *code)
|
| 505 |
+
{
|
| 506 |
+
return Py_NewRef(code->co_code);
|
| 507 |
+
}
|
| 508 |
+
#endif
|
| 509 |
+
|
| 510 |
+
|
| 511 |
+
// gh-95008 added PyCode_GetVarnames() to Python 3.11.0rc1
|
| 512 |
+
#if PY_VERSION_HEX < 0x030B00C1 && !defined(PYPY_VERSION)
|
| 513 |
+
static inline PyObject* PyCode_GetVarnames(PyCodeObject *code)
|
| 514 |
+
{
|
| 515 |
+
return Py_NewRef(code->co_varnames);
|
| 516 |
+
}
|
| 517 |
+
#endif
|
| 518 |
+
|
| 519 |
+
// gh-95008 added PyCode_GetFreevars() to Python 3.11.0rc1
|
| 520 |
+
#if PY_VERSION_HEX < 0x030B00C1 && !defined(PYPY_VERSION)
|
| 521 |
+
static inline PyObject* PyCode_GetFreevars(PyCodeObject *code)
|
| 522 |
+
{
|
| 523 |
+
return Py_NewRef(code->co_freevars);
|
| 524 |
+
}
|
| 525 |
+
#endif
|
| 526 |
+
|
| 527 |
+
// gh-95008 added PyCode_GetCellvars() to Python 3.11.0rc1
|
| 528 |
+
#if PY_VERSION_HEX < 0x030B00C1 && !defined(PYPY_VERSION)
|
| 529 |
+
static inline PyObject* PyCode_GetCellvars(PyCodeObject *code)
|
| 530 |
+
{
|
| 531 |
+
return Py_NewRef(code->co_cellvars);
|
| 532 |
+
}
|
| 533 |
+
#endif
|
| 534 |
+
|
| 535 |
+
|
| 536 |
+
// Py_UNUSED() was added to Python 3.4.0b2.
|
| 537 |
+
#if PY_VERSION_HEX < 0x030400B2 && !defined(Py_UNUSED)
|
| 538 |
+
# if defined(__GNUC__) || defined(__clang__)
|
| 539 |
+
# define Py_UNUSED(name) _unused_ ## name __attribute__((unused))
|
| 540 |
+
# else
|
| 541 |
+
# define Py_UNUSED(name) _unused_ ## name
|
| 542 |
+
# endif
|
| 543 |
+
#endif
|
| 544 |
+
|
| 545 |
+
|
| 546 |
+
// gh-105922 added PyImport_AddModuleRef() to Python 3.13.0a1
|
| 547 |
+
#if PY_VERSION_HEX < 0x030D00A0
|
| 548 |
+
static inline PyObject* PyImport_AddModuleRef(const char *name)
|
| 549 |
+
{
|
| 550 |
+
return Py_XNewRef(PyImport_AddModule(name));
|
| 551 |
+
}
|
| 552 |
+
#endif
|
| 553 |
+
|
| 554 |
+
|
| 555 |
+
// gh-105927 added PyWeakref_GetRef() to Python 3.13.0a1
|
| 556 |
+
#if PY_VERSION_HEX < 0x030D0000
|
| 557 |
+
static inline int PyWeakref_GetRef(PyObject *ref, PyObject **pobj)
|
| 558 |
+
{
|
| 559 |
+
PyObject *obj;
|
| 560 |
+
if (ref != NULL && !PyWeakref_Check(ref)) {
|
| 561 |
+
*pobj = NULL;
|
| 562 |
+
PyErr_SetString(PyExc_TypeError, "expected a weakref");
|
| 563 |
+
return -1;
|
| 564 |
+
}
|
| 565 |
+
obj = PyWeakref_GetObject(ref);
|
| 566 |
+
if (obj == NULL) {
|
| 567 |
+
// SystemError if ref is NULL
|
| 568 |
+
*pobj = NULL;
|
| 569 |
+
return -1;
|
| 570 |
+
}
|
| 571 |
+
if (obj == Py_None) {
|
| 572 |
+
*pobj = NULL;
|
| 573 |
+
return 0;
|
| 574 |
+
}
|
| 575 |
+
*pobj = Py_NewRef(obj);
|
| 576 |
+
return (*pobj != NULL);
|
| 577 |
+
}
|
| 578 |
+
#endif
|
| 579 |
+
|
| 580 |
+
|
| 581 |
+
// bpo-36974 added PY_VECTORCALL_ARGUMENTS_OFFSET to Python 3.8b1
|
| 582 |
+
#ifndef PY_VECTORCALL_ARGUMENTS_OFFSET
|
| 583 |
+
# define PY_VECTORCALL_ARGUMENTS_OFFSET (_Py_CAST(size_t, 1) << (8 * sizeof(size_t) - 1))
|
| 584 |
+
#endif
|
| 585 |
+
|
| 586 |
+
// bpo-36974 added PyVectorcall_NARGS() to Python 3.8b1
|
| 587 |
+
#if PY_VERSION_HEX < 0x030800B1
|
| 588 |
+
static inline Py_ssize_t PyVectorcall_NARGS(size_t n)
|
| 589 |
+
{
|
| 590 |
+
return n & ~PY_VECTORCALL_ARGUMENTS_OFFSET;
|
| 591 |
+
}
|
| 592 |
+
#endif
|
| 593 |
+
|
| 594 |
+
|
| 595 |
+
// gh-105922 added PyObject_Vectorcall() to Python 3.9.0a4
|
| 596 |
+
#if PY_VERSION_HEX < 0x030900A4
|
| 597 |
+
static inline PyObject*
|
| 598 |
+
PyObject_Vectorcall(PyObject *callable, PyObject *const *args,
|
| 599 |
+
size_t nargsf, PyObject *kwnames)
|
| 600 |
+
{
|
| 601 |
+
#if PY_VERSION_HEX >= 0x030800B1 && !defined(PYPY_VERSION)
|
| 602 |
+
// bpo-36974 added _PyObject_Vectorcall() to Python 3.8.0b1
|
| 603 |
+
return _PyObject_Vectorcall(callable, args, nargsf, kwnames);
|
| 604 |
+
#else
|
| 605 |
+
PyObject *posargs = NULL, *kwargs = NULL;
|
| 606 |
+
PyObject *res;
|
| 607 |
+
Py_ssize_t nposargs, nkwargs, i;
|
| 608 |
+
|
| 609 |
+
if (nargsf != 0 && args == NULL) {
|
| 610 |
+
PyErr_BadInternalCall();
|
| 611 |
+
goto error;
|
| 612 |
+
}
|
| 613 |
+
if (kwnames != NULL && !PyTuple_Check(kwnames)) {
|
| 614 |
+
PyErr_BadInternalCall();
|
| 615 |
+
goto error;
|
| 616 |
+
}
|
| 617 |
+
|
| 618 |
+
nposargs = (Py_ssize_t)PyVectorcall_NARGS(nargsf);
|
| 619 |
+
if (kwnames) {
|
| 620 |
+
nkwargs = PyTuple_GET_SIZE(kwnames);
|
| 621 |
+
}
|
| 622 |
+
else {
|
| 623 |
+
nkwargs = 0;
|
| 624 |
+
}
|
| 625 |
+
|
| 626 |
+
posargs = PyTuple_New(nposargs);
|
| 627 |
+
if (posargs == NULL) {
|
| 628 |
+
goto error;
|
| 629 |
+
}
|
| 630 |
+
if (nposargs) {
|
| 631 |
+
for (i=0; i < nposargs; i++) {
|
| 632 |
+
PyTuple_SET_ITEM(posargs, i, Py_NewRef(*args));
|
| 633 |
+
args++;
|
| 634 |
+
}
|
| 635 |
+
}
|
| 636 |
+
|
| 637 |
+
if (nkwargs) {
|
| 638 |
+
kwargs = PyDict_New();
|
| 639 |
+
if (kwargs == NULL) {
|
| 640 |
+
goto error;
|
| 641 |
+
}
|
| 642 |
+
|
| 643 |
+
for (i = 0; i < nkwargs; i++) {
|
| 644 |
+
PyObject *key = PyTuple_GET_ITEM(kwnames, i);
|
| 645 |
+
PyObject *value = *args;
|
| 646 |
+
args++;
|
| 647 |
+
if (PyDict_SetItem(kwargs, key, value) < 0) {
|
| 648 |
+
goto error;
|
| 649 |
+
}
|
| 650 |
+
}
|
| 651 |
+
}
|
| 652 |
+
else {
|
| 653 |
+
kwargs = NULL;
|
| 654 |
+
}
|
| 655 |
+
|
| 656 |
+
res = PyObject_Call(callable, posargs, kwargs);
|
| 657 |
+
Py_DECREF(posargs);
|
| 658 |
+
Py_XDECREF(kwargs);
|
| 659 |
+
return res;
|
| 660 |
+
|
| 661 |
+
error:
|
| 662 |
+
Py_DECREF(posargs);
|
| 663 |
+
Py_XDECREF(kwargs);
|
| 664 |
+
return NULL;
|
| 665 |
+
#endif
|
| 666 |
+
}
|
| 667 |
+
#endif
|
| 668 |
+
|
| 669 |
+
|
| 670 |
+
// gh-106521 added PyObject_GetOptionalAttr() and
|
| 671 |
+
// PyObject_GetOptionalAttrString() to Python 3.13.0a1
|
| 672 |
+
#if PY_VERSION_HEX < 0x030D00A1
|
| 673 |
+
static inline int
|
| 674 |
+
PyObject_GetOptionalAttr(PyObject *obj, PyObject *attr_name, PyObject **result)
|
| 675 |
+
{
|
| 676 |
+
// bpo-32571 added _PyObject_LookupAttr() to Python 3.7.0b1
|
| 677 |
+
#if PY_VERSION_HEX >= 0x030700B1 && !defined(PYPY_VERSION)
|
| 678 |
+
return _PyObject_LookupAttr(obj, attr_name, result);
|
| 679 |
+
#else
|
| 680 |
+
*result = PyObject_GetAttr(obj, attr_name);
|
| 681 |
+
if (*result != NULL) {
|
| 682 |
+
return 1;
|
| 683 |
+
}
|
| 684 |
+
if (!PyErr_Occurred()) {
|
| 685 |
+
return 0;
|
| 686 |
+
}
|
| 687 |
+
if (PyErr_ExceptionMatches(PyExc_AttributeError)) {
|
| 688 |
+
PyErr_Clear();
|
| 689 |
+
return 0;
|
| 690 |
+
}
|
| 691 |
+
return -1;
|
| 692 |
+
#endif
|
| 693 |
+
}
|
| 694 |
+
|
| 695 |
+
static inline int
|
| 696 |
+
PyObject_GetOptionalAttrString(PyObject *obj, const char *attr_name, PyObject **result)
|
| 697 |
+
{
|
| 698 |
+
PyObject *name_obj;
|
| 699 |
+
int rc;
|
| 700 |
+
#if PY_VERSION_HEX >= 0x03000000
|
| 701 |
+
name_obj = PyUnicode_FromString(attr_name);
|
| 702 |
+
#else
|
| 703 |
+
name_obj = PyString_FromString(attr_name);
|
| 704 |
+
#endif
|
| 705 |
+
if (name_obj == NULL) {
|
| 706 |
+
*result = NULL;
|
| 707 |
+
return -1;
|
| 708 |
+
}
|
| 709 |
+
rc = PyObject_GetOptionalAttr(obj, name_obj, result);
|
| 710 |
+
Py_DECREF(name_obj);
|
| 711 |
+
return rc;
|
| 712 |
+
}
|
| 713 |
+
#endif
|
| 714 |
+
|
| 715 |
+
|
| 716 |
+
// gh-106307 added PyObject_GetOptionalAttr() and
|
| 717 |
+
// PyMapping_GetOptionalItemString() to Python 3.13.0a1
|
| 718 |
+
#if PY_VERSION_HEX < 0x030D00A1
|
| 719 |
+
static inline int
|
| 720 |
+
PyMapping_GetOptionalItem(PyObject *obj, PyObject *key, PyObject **result)
|
| 721 |
+
{
|
| 722 |
+
*result = PyObject_GetItem(obj, key);
|
| 723 |
+
if (*result) {
|
| 724 |
+
return 1;
|
| 725 |
+
}
|
| 726 |
+
if (!PyErr_ExceptionMatches(PyExc_KeyError)) {
|
| 727 |
+
return -1;
|
| 728 |
+
}
|
| 729 |
+
PyErr_Clear();
|
| 730 |
+
return 0;
|
| 731 |
+
}
|
| 732 |
+
|
| 733 |
+
static inline int
|
| 734 |
+
PyMapping_GetOptionalItemString(PyObject *obj, const char *key, PyObject **result)
|
| 735 |
+
{
|
| 736 |
+
PyObject *key_obj;
|
| 737 |
+
int rc;
|
| 738 |
+
#if PY_VERSION_HEX >= 0x03000000
|
| 739 |
+
key_obj = PyUnicode_FromString(key);
|
| 740 |
+
#else
|
| 741 |
+
key_obj = PyString_FromString(key);
|
| 742 |
+
#endif
|
| 743 |
+
if (key_obj == NULL) {
|
| 744 |
+
*result = NULL;
|
| 745 |
+
return -1;
|
| 746 |
+
}
|
| 747 |
+
rc = PyMapping_GetOptionalItem(obj, key_obj, result);
|
| 748 |
+
Py_DECREF(key_obj);
|
| 749 |
+
return rc;
|
| 750 |
+
}
|
| 751 |
+
#endif
|
| 752 |
+
|
| 753 |
+
// gh-108511 added PyMapping_HasKeyWithError() and
|
| 754 |
+
// PyMapping_HasKeyStringWithError() to Python 3.13.0a1
|
| 755 |
+
#if PY_VERSION_HEX < 0x030D00A1
|
| 756 |
+
static inline int
|
| 757 |
+
PyMapping_HasKeyWithError(PyObject *obj, PyObject *key)
|
| 758 |
+
{
|
| 759 |
+
PyObject *res;
|
| 760 |
+
int rc = PyMapping_GetOptionalItem(obj, key, &res);
|
| 761 |
+
Py_XDECREF(res);
|
| 762 |
+
return rc;
|
| 763 |
+
}
|
| 764 |
+
|
| 765 |
+
static inline int
|
| 766 |
+
PyMapping_HasKeyStringWithError(PyObject *obj, const char *key)
|
| 767 |
+
{
|
| 768 |
+
PyObject *res;
|
| 769 |
+
int rc = PyMapping_GetOptionalItemString(obj, key, &res);
|
| 770 |
+
Py_XDECREF(res);
|
| 771 |
+
return rc;
|
| 772 |
+
}
|
| 773 |
+
#endif
|
| 774 |
+
|
| 775 |
+
|
| 776 |
+
// gh-108511 added PyObject_HasAttrWithError() and
|
| 777 |
+
// PyObject_HasAttrStringWithError() to Python 3.13.0a1
|
| 778 |
+
#if PY_VERSION_HEX < 0x030D00A1
|
| 779 |
+
static inline int
|
| 780 |
+
PyObject_HasAttrWithError(PyObject *obj, PyObject *attr)
|
| 781 |
+
{
|
| 782 |
+
PyObject *res;
|
| 783 |
+
int rc = PyObject_GetOptionalAttr(obj, attr, &res);
|
| 784 |
+
Py_XDECREF(res);
|
| 785 |
+
return rc;
|
| 786 |
+
}
|
| 787 |
+
|
| 788 |
+
static inline int
|
| 789 |
+
PyObject_HasAttrStringWithError(PyObject *obj, const char *attr)
|
| 790 |
+
{
|
| 791 |
+
PyObject *res;
|
| 792 |
+
int rc = PyObject_GetOptionalAttrString(obj, attr, &res);
|
| 793 |
+
Py_XDECREF(res);
|
| 794 |
+
return rc;
|
| 795 |
+
}
|
| 796 |
+
#endif
|
| 797 |
+
|
| 798 |
+
|
| 799 |
+
// gh-106004 added PyDict_GetItemRef() and PyDict_GetItemStringRef()
|
| 800 |
+
// to Python 3.13.0a1
|
| 801 |
+
#if PY_VERSION_HEX < 0x030D00A1
|
| 802 |
+
static inline int
|
| 803 |
+
PyDict_GetItemRef(PyObject *mp, PyObject *key, PyObject **result)
|
| 804 |
+
{
|
| 805 |
+
#if PY_VERSION_HEX >= 0x03000000
|
| 806 |
+
PyObject *item = PyDict_GetItemWithError(mp, key);
|
| 807 |
+
#else
|
| 808 |
+
PyObject *item = _PyDict_GetItemWithError(mp, key);
|
| 809 |
+
#endif
|
| 810 |
+
if (item != NULL) {
|
| 811 |
+
*result = Py_NewRef(item);
|
| 812 |
+
return 1; // found
|
| 813 |
+
}
|
| 814 |
+
if (!PyErr_Occurred()) {
|
| 815 |
+
*result = NULL;
|
| 816 |
+
return 0; // not found
|
| 817 |
+
}
|
| 818 |
+
*result = NULL;
|
| 819 |
+
return -1;
|
| 820 |
+
}
|
| 821 |
+
|
| 822 |
+
static inline int
|
| 823 |
+
PyDict_GetItemStringRef(PyObject *mp, const char *key, PyObject **result)
|
| 824 |
+
{
|
| 825 |
+
int res;
|
| 826 |
+
#if PY_VERSION_HEX >= 0x03000000
|
| 827 |
+
PyObject *key_obj = PyUnicode_FromString(key);
|
| 828 |
+
#else
|
| 829 |
+
PyObject *key_obj = PyString_FromString(key);
|
| 830 |
+
#endif
|
| 831 |
+
if (key_obj == NULL) {
|
| 832 |
+
*result = NULL;
|
| 833 |
+
return -1;
|
| 834 |
+
}
|
| 835 |
+
res = PyDict_GetItemRef(mp, key_obj, result);
|
| 836 |
+
Py_DECREF(key_obj);
|
| 837 |
+
return res;
|
| 838 |
+
}
|
| 839 |
+
#endif
|
| 840 |
+
|
| 841 |
+
|
| 842 |
+
// gh-106307 added PyModule_Add() to Python 3.13.0a1
|
| 843 |
+
#if PY_VERSION_HEX < 0x030D00A1
|
| 844 |
+
static inline int
|
| 845 |
+
PyModule_Add(PyObject *mod, const char *name, PyObject *value)
|
| 846 |
+
{
|
| 847 |
+
int res = PyModule_AddObjectRef(mod, name, value);
|
| 848 |
+
Py_XDECREF(value);
|
| 849 |
+
return res;
|
| 850 |
+
}
|
| 851 |
+
#endif
|
| 852 |
+
|
| 853 |
+
|
| 854 |
+
// gh-108014 added Py_IsFinalizing() to Python 3.13.0a1
|
| 855 |
+
// bpo-1856 added _Py_Finalizing to Python 3.2.1b1.
|
| 856 |
+
// _Py_IsFinalizing() was added to PyPy 7.3.0.
|
| 857 |
+
#if (0x030201B1 <= PY_VERSION_HEX && PY_VERSION_HEX < 0x030D00A1) \
|
| 858 |
+
&& (!defined(PYPY_VERSION_NUM) || PYPY_VERSION_NUM >= 0x7030000)
|
| 859 |
+
static inline int Py_IsFinalizing(void)
|
| 860 |
+
{
|
| 861 |
+
#if PY_VERSION_HEX >= 0x030700A1
|
| 862 |
+
// _Py_IsFinalizing() was added to Python 3.7.0a1.
|
| 863 |
+
return _Py_IsFinalizing();
|
| 864 |
+
#else
|
| 865 |
+
return (_Py_Finalizing != NULL);
|
| 866 |
+
#endif
|
| 867 |
+
}
|
| 868 |
+
#endif
|
| 869 |
+
|
| 870 |
+
|
| 871 |
+
// gh-108323 added PyDict_ContainsString() to Python 3.13.0a1
|
| 872 |
+
#if PY_VERSION_HEX < 0x030D00A1
|
| 873 |
+
static inline int PyDict_ContainsString(PyObject *op, const char *key)
|
| 874 |
+
{
|
| 875 |
+
PyObject *key_obj = PyUnicode_FromString(key);
|
| 876 |
+
if (key_obj == NULL) {
|
| 877 |
+
return -1;
|
| 878 |
+
}
|
| 879 |
+
int res = PyDict_Contains(op, key_obj);
|
| 880 |
+
Py_DECREF(key_obj);
|
| 881 |
+
return res;
|
| 882 |
+
}
|
| 883 |
+
#endif
|
| 884 |
+
|
| 885 |
+
|
| 886 |
+
// gh-108445 added PyLong_AsInt() to Python 3.13.0a1
|
| 887 |
+
#if PY_VERSION_HEX < 0x030D00A1
|
| 888 |
+
static inline int PyLong_AsInt(PyObject *obj)
|
| 889 |
+
{
|
| 890 |
+
#ifdef PYPY_VERSION
|
| 891 |
+
long value = PyLong_AsLong(obj);
|
| 892 |
+
if (value == -1 && PyErr_Occurred()) {
|
| 893 |
+
return -1;
|
| 894 |
+
}
|
| 895 |
+
if (value < (long)INT_MIN || (long)INT_MAX < value) {
|
| 896 |
+
PyErr_SetString(PyExc_OverflowError,
|
| 897 |
+
"Python int too large to convert to C int");
|
| 898 |
+
return -1;
|
| 899 |
+
}
|
| 900 |
+
return (int)value;
|
| 901 |
+
#else
|
| 902 |
+
return _PyLong_AsInt(obj);
|
| 903 |
+
#endif
|
| 904 |
+
}
|
| 905 |
+
#endif
|
| 906 |
+
|
| 907 |
+
|
| 908 |
+
// gh-107073 added PyObject_VisitManagedDict() to Python 3.13.0a1
|
| 909 |
+
#if PY_VERSION_HEX < 0x030D00A1
|
| 910 |
+
static inline int
|
| 911 |
+
PyObject_VisitManagedDict(PyObject *obj, visitproc visit, void *arg)
|
| 912 |
+
{
|
| 913 |
+
PyObject **dict = _PyObject_GetDictPtr(obj);
|
| 914 |
+
if (*dict == NULL) {
|
| 915 |
+
return -1;
|
| 916 |
+
}
|
| 917 |
+
Py_VISIT(*dict);
|
| 918 |
+
return 0;
|
| 919 |
+
}
|
| 920 |
+
|
| 921 |
+
static inline void
|
| 922 |
+
PyObject_ClearManagedDict(PyObject *obj)
|
| 923 |
+
{
|
| 924 |
+
PyObject **dict = _PyObject_GetDictPtr(obj);
|
| 925 |
+
if (*dict == NULL) {
|
| 926 |
+
return;
|
| 927 |
+
}
|
| 928 |
+
Py_CLEAR(*dict);
|
| 929 |
+
}
|
| 930 |
+
#endif
|
| 931 |
+
|
| 932 |
+
// gh-108867 added PyThreadState_GetUnchecked() to Python 3.13.0a1
|
| 933 |
+
// Python 3.5.2 added _PyThreadState_UncheckedGet().
|
| 934 |
+
#if PY_VERSION_HEX >= 0x03050200 && PY_VERSION_HEX < 0x030D00A1
|
| 935 |
+
static inline PyThreadState*
|
| 936 |
+
PyThreadState_GetUnchecked(void)
|
| 937 |
+
{
|
| 938 |
+
return _PyThreadState_UncheckedGet();
|
| 939 |
+
}
|
| 940 |
+
#endif
|
| 941 |
+
|
| 942 |
+
// gh-110289 added PyUnicode_EqualToUTF8() and PyUnicode_EqualToUTF8AndSize()
|
| 943 |
+
// to Python 3.13.0a1
|
| 944 |
+
#if PY_VERSION_HEX < 0x030D00A1
|
| 945 |
+
static inline int
|
| 946 |
+
PyUnicode_EqualToUTF8AndSize(PyObject *unicode, const char *str, Py_ssize_t str_len)
|
| 947 |
+
{
|
| 948 |
+
Py_ssize_t len;
|
| 949 |
+
const void *utf8;
|
| 950 |
+
PyObject *exc_type, *exc_value, *exc_tb;
|
| 951 |
+
int res;
|
| 952 |
+
|
| 953 |
+
// API cannot report errors so save/restore the exception
|
| 954 |
+
PyErr_Fetch(&exc_type, &exc_value, &exc_tb);
|
| 955 |
+
|
| 956 |
+
// Python 3.3.0a1 added PyUnicode_AsUTF8AndSize()
|
| 957 |
+
#if PY_VERSION_HEX >= 0x030300A1
|
| 958 |
+
if (PyUnicode_IS_ASCII(unicode)) {
|
| 959 |
+
utf8 = PyUnicode_DATA(unicode);
|
| 960 |
+
len = PyUnicode_GET_LENGTH(unicode);
|
| 961 |
+
}
|
| 962 |
+
else {
|
| 963 |
+
utf8 = PyUnicode_AsUTF8AndSize(unicode, &len);
|
| 964 |
+
if (utf8 == NULL) {
|
| 965 |
+
// Memory allocation failure. The API cannot report error,
|
| 966 |
+
// so ignore the exception and return 0.
|
| 967 |
+
res = 0;
|
| 968 |
+
goto done;
|
| 969 |
+
}
|
| 970 |
+
}
|
| 971 |
+
|
| 972 |
+
if (len != str_len) {
|
| 973 |
+
res = 0;
|
| 974 |
+
goto done;
|
| 975 |
+
}
|
| 976 |
+
res = (memcmp(utf8, str, (size_t)len) == 0);
|
| 977 |
+
#else
|
| 978 |
+
PyObject *bytes = PyUnicode_AsUTF8String(unicode);
|
| 979 |
+
if (bytes == NULL) {
|
| 980 |
+
// Memory allocation failure. The API cannot report error,
|
| 981 |
+
// so ignore the exception and return 0.
|
| 982 |
+
res = 0;
|
| 983 |
+
goto done;
|
| 984 |
+
}
|
| 985 |
+
|
| 986 |
+
#if PY_VERSION_HEX >= 0x03000000
|
| 987 |
+
len = PyBytes_GET_SIZE(bytes);
|
| 988 |
+
utf8 = PyBytes_AS_STRING(bytes);
|
| 989 |
+
#else
|
| 990 |
+
len = PyString_GET_SIZE(bytes);
|
| 991 |
+
utf8 = PyString_AS_STRING(bytes);
|
| 992 |
+
#endif
|
| 993 |
+
if (len != str_len) {
|
| 994 |
+
Py_DECREF(bytes);
|
| 995 |
+
res = 0;
|
| 996 |
+
goto done;
|
| 997 |
+
}
|
| 998 |
+
|
| 999 |
+
res = (memcmp(utf8, str, (size_t)len) == 0);
|
| 1000 |
+
Py_DECREF(bytes);
|
| 1001 |
+
#endif
|
| 1002 |
+
|
| 1003 |
+
done:
|
| 1004 |
+
PyErr_Restore(exc_type, exc_value, exc_tb);
|
| 1005 |
+
return res;
|
| 1006 |
+
}
|
| 1007 |
+
|
| 1008 |
+
static inline int
|
| 1009 |
+
PyUnicode_EqualToUTF8(PyObject *unicode, const char *str)
|
| 1010 |
+
{
|
| 1011 |
+
return PyUnicode_EqualToUTF8AndSize(unicode, str, (Py_ssize_t)strlen(str));
|
| 1012 |
+
}
|
| 1013 |
+
#endif
|
| 1014 |
+
|
| 1015 |
+
|
| 1016 |
+
// gh-111138 added PyList_Extend() and PyList_Clear() to Python 3.13.0a2
|
| 1017 |
+
#if PY_VERSION_HEX < 0x030D00A2
|
| 1018 |
+
static inline int
|
| 1019 |
+
PyList_Extend(PyObject *list, PyObject *iterable)
|
| 1020 |
+
{
|
| 1021 |
+
return PyList_SetSlice(list, PY_SSIZE_T_MAX, PY_SSIZE_T_MAX, iterable);
|
| 1022 |
+
}
|
| 1023 |
+
|
| 1024 |
+
static inline int
|
| 1025 |
+
PyList_Clear(PyObject *list)
|
| 1026 |
+
{
|
| 1027 |
+
return PyList_SetSlice(list, 0, PY_SSIZE_T_MAX, NULL);
|
| 1028 |
+
}
|
| 1029 |
+
#endif
|
| 1030 |
+
|
| 1031 |
+
// gh-111262 added PyDict_Pop() and PyDict_PopString() to Python 3.13.0a2
|
| 1032 |
+
#if PY_VERSION_HEX < 0x030D00A2
|
| 1033 |
+
static inline int
|
| 1034 |
+
PyDict_Pop(PyObject *dict, PyObject *key, PyObject **result)
|
| 1035 |
+
{
|
| 1036 |
+
PyObject *value;
|
| 1037 |
+
|
| 1038 |
+
if (!PyDict_Check(dict)) {
|
| 1039 |
+
PyErr_BadInternalCall();
|
| 1040 |
+
if (result) {
|
| 1041 |
+
*result = NULL;
|
| 1042 |
+
}
|
| 1043 |
+
return -1;
|
| 1044 |
+
}
|
| 1045 |
+
|
| 1046 |
+
// bpo-16991 added _PyDict_Pop() to Python 3.5.0b2.
|
| 1047 |
+
// Python 3.6.0b3 changed _PyDict_Pop() first argument type to PyObject*.
|
| 1048 |
+
// Python 3.13.0a1 removed _PyDict_Pop().
|
| 1049 |
+
#if defined(PYPY_VERSION) || PY_VERSION_HEX < 0x030500b2 || PY_VERSION_HEX >= 0x030D0000
|
| 1050 |
+
value = PyObject_CallMethod(dict, "pop", "O", key);
|
| 1051 |
+
#elif PY_VERSION_HEX < 0x030600b3
|
| 1052 |
+
value = _PyDict_Pop(_Py_CAST(PyDictObject*, dict), key, NULL);
|
| 1053 |
+
#else
|
| 1054 |
+
value = _PyDict_Pop(dict, key, NULL);
|
| 1055 |
+
#endif
|
| 1056 |
+
if (value == NULL) {
|
| 1057 |
+
if (result) {
|
| 1058 |
+
*result = NULL;
|
| 1059 |
+
}
|
| 1060 |
+
if (PyErr_Occurred() && !PyErr_ExceptionMatches(PyExc_KeyError)) {
|
| 1061 |
+
return -1;
|
| 1062 |
+
}
|
| 1063 |
+
PyErr_Clear();
|
| 1064 |
+
return 0;
|
| 1065 |
+
}
|
| 1066 |
+
if (result) {
|
| 1067 |
+
*result = value;
|
| 1068 |
+
}
|
| 1069 |
+
else {
|
| 1070 |
+
Py_DECREF(value);
|
| 1071 |
+
}
|
| 1072 |
+
return 1;
|
| 1073 |
+
}
|
| 1074 |
+
|
| 1075 |
+
static inline int
|
| 1076 |
+
PyDict_PopString(PyObject *dict, const char *key, PyObject **result)
|
| 1077 |
+
{
|
| 1078 |
+
PyObject *key_obj = PyUnicode_FromString(key);
|
| 1079 |
+
if (key_obj == NULL) {
|
| 1080 |
+
if (result != NULL) {
|
| 1081 |
+
*result = NULL;
|
| 1082 |
+
}
|
| 1083 |
+
return -1;
|
| 1084 |
+
}
|
| 1085 |
+
|
| 1086 |
+
int res = PyDict_Pop(dict, key_obj, result);
|
| 1087 |
+
Py_DECREF(key_obj);
|
| 1088 |
+
return res;
|
| 1089 |
+
}
|
| 1090 |
+
#endif
|
| 1091 |
+
|
| 1092 |
+
|
| 1093 |
+
#if PY_VERSION_HEX < 0x030200A4
|
| 1094 |
+
// Python 3.2.0a4 added Py_hash_t type
|
| 1095 |
+
typedef Py_ssize_t Py_hash_t;
|
| 1096 |
+
#endif
|
| 1097 |
+
|
| 1098 |
+
|
| 1099 |
+
// gh-111545 added Py_HashPointer() to Python 3.13.0a3
|
| 1100 |
+
#if PY_VERSION_HEX < 0x030D00A3
|
| 1101 |
+
static inline Py_hash_t Py_HashPointer(const void *ptr)
|
| 1102 |
+
{
|
| 1103 |
+
#if PY_VERSION_HEX >= 0x030900A4 && !defined(PYPY_VERSION)
|
| 1104 |
+
return _Py_HashPointer(ptr);
|
| 1105 |
+
#else
|
| 1106 |
+
return _Py_HashPointer(_Py_CAST(void*, ptr));
|
| 1107 |
+
#endif
|
| 1108 |
+
}
|
| 1109 |
+
#endif
|
| 1110 |
+
|
| 1111 |
+
|
| 1112 |
+
// Python 3.13a4 added a PyTime API.
|
| 1113 |
+
// Use the private API added to Python 3.5.
|
| 1114 |
+
#if PY_VERSION_HEX < 0x030D00A4 && PY_VERSION_HEX >= 0x03050000
|
| 1115 |
+
typedef _PyTime_t PyTime_t;
|
| 1116 |
+
#define PyTime_MIN _PyTime_MIN
|
| 1117 |
+
#define PyTime_MAX _PyTime_MAX
|
| 1118 |
+
|
| 1119 |
+
static inline double PyTime_AsSecondsDouble(PyTime_t t)
|
| 1120 |
+
{ return _PyTime_AsSecondsDouble(t); }
|
| 1121 |
+
|
| 1122 |
+
static inline int PyTime_Monotonic(PyTime_t *result)
|
| 1123 |
+
{ return _PyTime_GetMonotonicClockWithInfo(result, NULL); }
|
| 1124 |
+
|
| 1125 |
+
static inline int PyTime_Time(PyTime_t *result)
|
| 1126 |
+
{ return _PyTime_GetSystemClockWithInfo(result, NULL); }
|
| 1127 |
+
|
| 1128 |
+
static inline int PyTime_PerfCounter(PyTime_t *result)
|
| 1129 |
+
{
|
| 1130 |
+
#if PY_VERSION_HEX >= 0x03070000 && !defined(PYPY_VERSION)
|
| 1131 |
+
return _PyTime_GetPerfCounterWithInfo(result, NULL);
|
| 1132 |
+
#elif PY_VERSION_HEX >= 0x03070000
|
| 1133 |
+
// Call time.perf_counter_ns() and convert Python int object to PyTime_t.
|
| 1134 |
+
// Cache time.perf_counter_ns() function for best performance.
|
| 1135 |
+
static PyObject *func = NULL;
|
| 1136 |
+
if (func == NULL) {
|
| 1137 |
+
PyObject *mod = PyImport_ImportModule("time");
|
| 1138 |
+
if (mod == NULL) {
|
| 1139 |
+
return -1;
|
| 1140 |
+
}
|
| 1141 |
+
|
| 1142 |
+
func = PyObject_GetAttrString(mod, "perf_counter_ns");
|
| 1143 |
+
Py_DECREF(mod);
|
| 1144 |
+
if (func == NULL) {
|
| 1145 |
+
return -1;
|
| 1146 |
+
}
|
| 1147 |
+
}
|
| 1148 |
+
|
| 1149 |
+
PyObject *res = PyObject_CallNoArgs(func);
|
| 1150 |
+
if (res == NULL) {
|
| 1151 |
+
return -1;
|
| 1152 |
+
}
|
| 1153 |
+
long long value = PyLong_AsLongLong(res);
|
| 1154 |
+
Py_DECREF(res);
|
| 1155 |
+
|
| 1156 |
+
if (value == -1 && PyErr_Occurred()) {
|
| 1157 |
+
return -1;
|
| 1158 |
+
}
|
| 1159 |
+
|
| 1160 |
+
Py_BUILD_ASSERT(sizeof(value) >= sizeof(PyTime_t));
|
| 1161 |
+
*result = (PyTime_t)value;
|
| 1162 |
+
return 0;
|
| 1163 |
+
#else
|
| 1164 |
+
// Call time.perf_counter() and convert C double to PyTime_t.
|
| 1165 |
+
// Cache time.perf_counter() function for best performance.
|
| 1166 |
+
static PyObject *func = NULL;
|
| 1167 |
+
if (func == NULL) {
|
| 1168 |
+
PyObject *mod = PyImport_ImportModule("time");
|
| 1169 |
+
if (mod == NULL) {
|
| 1170 |
+
return -1;
|
| 1171 |
+
}
|
| 1172 |
+
|
| 1173 |
+
func = PyObject_GetAttrString(mod, "perf_counter");
|
| 1174 |
+
Py_DECREF(mod);
|
| 1175 |
+
if (func == NULL) {
|
| 1176 |
+
return -1;
|
| 1177 |
+
}
|
| 1178 |
+
}
|
| 1179 |
+
|
| 1180 |
+
PyObject *res = PyObject_CallNoArgs(func);
|
| 1181 |
+
if (res == NULL) {
|
| 1182 |
+
return -1;
|
| 1183 |
+
}
|
| 1184 |
+
double d = PyFloat_AsDouble(res);
|
| 1185 |
+
Py_DECREF(res);
|
| 1186 |
+
|
| 1187 |
+
if (d == -1.0 && PyErr_Occurred()) {
|
| 1188 |
+
return -1;
|
| 1189 |
+
}
|
| 1190 |
+
|
| 1191 |
+
// Avoid floor() to avoid having to link to libm
|
| 1192 |
+
*result = (PyTime_t)(d * 1e9);
|
| 1193 |
+
return 0;
|
| 1194 |
+
#endif
|
| 1195 |
+
}
|
| 1196 |
+
|
| 1197 |
+
#endif
|
| 1198 |
+
|
| 1199 |
+
// gh-111389 added hash constants to Python 3.13.0a5. These constants were
|
| 1200 |
+
// added first as private macros to Python 3.4.0b1 and PyPy 7.3.9.
|
| 1201 |
+
#if (!defined(PyHASH_BITS) \
|
| 1202 |
+
&& ((!defined(PYPY_VERSION) && PY_VERSION_HEX >= 0x030400B1) \
|
| 1203 |
+
|| (defined(PYPY_VERSION) && PY_VERSION_HEX >= 0x03070000 \
|
| 1204 |
+
&& PYPY_VERSION_NUM >= 0x07090000)))
|
| 1205 |
+
# define PyHASH_BITS _PyHASH_BITS
|
| 1206 |
+
# define PyHASH_MODULUS _PyHASH_MODULUS
|
| 1207 |
+
# define PyHASH_INF _PyHASH_INF
|
| 1208 |
+
# define PyHASH_IMAG _PyHASH_IMAG
|
| 1209 |
+
#endif
|
| 1210 |
+
|
| 1211 |
+
|
| 1212 |
+
// gh-111545 added Py_GetConstant() and Py_GetConstantBorrowed()
|
| 1213 |
+
// to Python 3.13.0a6
|
| 1214 |
+
#if PY_VERSION_HEX < 0x030D00A6 && !defined(Py_CONSTANT_NONE)
|
| 1215 |
+
|
| 1216 |
+
#define Py_CONSTANT_NONE 0
|
| 1217 |
+
#define Py_CONSTANT_FALSE 1
|
| 1218 |
+
#define Py_CONSTANT_TRUE 2
|
| 1219 |
+
#define Py_CONSTANT_ELLIPSIS 3
|
| 1220 |
+
#define Py_CONSTANT_NOT_IMPLEMENTED 4
|
| 1221 |
+
#define Py_CONSTANT_ZERO 5
|
| 1222 |
+
#define Py_CONSTANT_ONE 6
|
| 1223 |
+
#define Py_CONSTANT_EMPTY_STR 7
|
| 1224 |
+
#define Py_CONSTANT_EMPTY_BYTES 8
|
| 1225 |
+
#define Py_CONSTANT_EMPTY_TUPLE 9
|
| 1226 |
+
|
| 1227 |
+
static inline PyObject* Py_GetConstant(unsigned int constant_id)
|
| 1228 |
+
{
|
| 1229 |
+
static PyObject* constants[Py_CONSTANT_EMPTY_TUPLE + 1] = {NULL};
|
| 1230 |
+
|
| 1231 |
+
if (constants[Py_CONSTANT_NONE] == NULL) {
|
| 1232 |
+
constants[Py_CONSTANT_NONE] = Py_None;
|
| 1233 |
+
constants[Py_CONSTANT_FALSE] = Py_False;
|
| 1234 |
+
constants[Py_CONSTANT_TRUE] = Py_True;
|
| 1235 |
+
constants[Py_CONSTANT_ELLIPSIS] = Py_Ellipsis;
|
| 1236 |
+
constants[Py_CONSTANT_NOT_IMPLEMENTED] = Py_NotImplemented;
|
| 1237 |
+
|
| 1238 |
+
constants[Py_CONSTANT_ZERO] = PyLong_FromLong(0);
|
| 1239 |
+
if (constants[Py_CONSTANT_ZERO] == NULL) {
|
| 1240 |
+
goto fatal_error;
|
| 1241 |
+
}
|
| 1242 |
+
|
| 1243 |
+
constants[Py_CONSTANT_ONE] = PyLong_FromLong(1);
|
| 1244 |
+
if (constants[Py_CONSTANT_ONE] == NULL) {
|
| 1245 |
+
goto fatal_error;
|
| 1246 |
+
}
|
| 1247 |
+
|
| 1248 |
+
constants[Py_CONSTANT_EMPTY_STR] = PyUnicode_FromStringAndSize("", 0);
|
| 1249 |
+
if (constants[Py_CONSTANT_EMPTY_STR] == NULL) {
|
| 1250 |
+
goto fatal_error;
|
| 1251 |
+
}
|
| 1252 |
+
|
| 1253 |
+
constants[Py_CONSTANT_EMPTY_BYTES] = PyBytes_FromStringAndSize("", 0);
|
| 1254 |
+
if (constants[Py_CONSTANT_EMPTY_BYTES] == NULL) {
|
| 1255 |
+
goto fatal_error;
|
| 1256 |
+
}
|
| 1257 |
+
|
| 1258 |
+
constants[Py_CONSTANT_EMPTY_TUPLE] = PyTuple_New(0);
|
| 1259 |
+
if (constants[Py_CONSTANT_EMPTY_TUPLE] == NULL) {
|
| 1260 |
+
goto fatal_error;
|
| 1261 |
+
}
|
| 1262 |
+
// goto dance to avoid compiler warnings about Py_FatalError()
|
| 1263 |
+
goto init_done;
|
| 1264 |
+
|
| 1265 |
+
fatal_error:
|
| 1266 |
+
// This case should never happen
|
| 1267 |
+
Py_FatalError("Py_GetConstant() failed to get constants");
|
| 1268 |
+
}
|
| 1269 |
+
|
| 1270 |
+
init_done:
|
| 1271 |
+
if (constant_id <= Py_CONSTANT_EMPTY_TUPLE) {
|
| 1272 |
+
return Py_NewRef(constants[constant_id]);
|
| 1273 |
+
}
|
| 1274 |
+
else {
|
| 1275 |
+
PyErr_BadInternalCall();
|
| 1276 |
+
return NULL;
|
| 1277 |
+
}
|
| 1278 |
+
}
|
| 1279 |
+
|
| 1280 |
+
static inline PyObject* Py_GetConstantBorrowed(unsigned int constant_id)
|
| 1281 |
+
{
|
| 1282 |
+
PyObject *obj = Py_GetConstant(constant_id);
|
| 1283 |
+
Py_XDECREF(obj);
|
| 1284 |
+
return obj;
|
| 1285 |
+
}
|
| 1286 |
+
#endif
|
| 1287 |
+
|
| 1288 |
+
|
| 1289 |
+
// gh-114329 added PyList_GetItemRef() to Python 3.13.0a4
|
| 1290 |
+
#if PY_VERSION_HEX < 0x030D00A4
|
| 1291 |
+
static inline PyObject *
|
| 1292 |
+
PyList_GetItemRef(PyObject *op, Py_ssize_t index)
|
| 1293 |
+
{
|
| 1294 |
+
PyObject *item = PyList_GetItem(op, index);
|
| 1295 |
+
Py_XINCREF(item);
|
| 1296 |
+
return item;
|
| 1297 |
+
}
|
| 1298 |
+
#endif
|
| 1299 |
+
|
| 1300 |
+
|
| 1301 |
+
// gh-114329 added PyList_GetItemRef() to Python 3.13.0a4
|
| 1302 |
+
#if PY_VERSION_HEX < 0x030D00A4
|
| 1303 |
+
static inline int
|
| 1304 |
+
PyDict_SetDefaultRef(PyObject *d, PyObject *key, PyObject *default_value,
|
| 1305 |
+
PyObject **result)
|
| 1306 |
+
{
|
| 1307 |
+
PyObject *value;
|
| 1308 |
+
if (PyDict_GetItemRef(d, key, &value) < 0) {
|
| 1309 |
+
// get error
|
| 1310 |
+
if (result) {
|
| 1311 |
+
*result = NULL;
|
| 1312 |
+
}
|
| 1313 |
+
return -1;
|
| 1314 |
+
}
|
| 1315 |
+
if (value != NULL) {
|
| 1316 |
+
// present
|
| 1317 |
+
if (result) {
|
| 1318 |
+
*result = value;
|
| 1319 |
+
}
|
| 1320 |
+
else {
|
| 1321 |
+
Py_DECREF(value);
|
| 1322 |
+
}
|
| 1323 |
+
return 1;
|
| 1324 |
+
}
|
| 1325 |
+
|
| 1326 |
+
// missing: set the item
|
| 1327 |
+
if (PyDict_SetItem(d, key, default_value) < 0) {
|
| 1328 |
+
// set error
|
| 1329 |
+
if (result) {
|
| 1330 |
+
*result = NULL;
|
| 1331 |
+
}
|
| 1332 |
+
return -1;
|
| 1333 |
+
}
|
| 1334 |
+
if (result) {
|
| 1335 |
+
*result = Py_NewRef(default_value);
|
| 1336 |
+
}
|
| 1337 |
+
return 0;
|
| 1338 |
+
}
|
| 1339 |
+
#endif
|
| 1340 |
+
|
| 1341 |
+
#if PY_VERSION_HEX < 0x030D00B3
|
| 1342 |
+
# define Py_BEGIN_CRITICAL_SECTION(op) {
|
| 1343 |
+
# define Py_END_CRITICAL_SECTION() }
|
| 1344 |
+
# define Py_BEGIN_CRITICAL_SECTION2(a, b) {
|
| 1345 |
+
# define Py_END_CRITICAL_SECTION2() }
|
| 1346 |
+
#endif
|
| 1347 |
+
|
| 1348 |
+
#if PY_VERSION_HEX < 0x030E0000 && PY_VERSION_HEX >= 0x03060000 && !defined(PYPY_VERSION)
|
| 1349 |
+
typedef struct PyUnicodeWriter PyUnicodeWriter;
|
| 1350 |
+
|
| 1351 |
+
static inline void PyUnicodeWriter_Discard(PyUnicodeWriter *writer)
|
| 1352 |
+
{
|
| 1353 |
+
_PyUnicodeWriter_Dealloc((_PyUnicodeWriter*)writer);
|
| 1354 |
+
PyMem_Free(writer);
|
| 1355 |
+
}
|
| 1356 |
+
|
| 1357 |
+
static inline PyUnicodeWriter* PyUnicodeWriter_Create(Py_ssize_t length)
|
| 1358 |
+
{
|
| 1359 |
+
if (length < 0) {
|
| 1360 |
+
PyErr_SetString(PyExc_ValueError,
|
| 1361 |
+
"length must be positive");
|
| 1362 |
+
return NULL;
|
| 1363 |
+
}
|
| 1364 |
+
|
| 1365 |
+
const size_t size = sizeof(_PyUnicodeWriter);
|
| 1366 |
+
PyUnicodeWriter *pub_writer = (PyUnicodeWriter *)PyMem_Malloc(size);
|
| 1367 |
+
if (pub_writer == _Py_NULL) {
|
| 1368 |
+
PyErr_NoMemory();
|
| 1369 |
+
return _Py_NULL;
|
| 1370 |
+
}
|
| 1371 |
+
_PyUnicodeWriter *writer = (_PyUnicodeWriter *)pub_writer;
|
| 1372 |
+
|
| 1373 |
+
_PyUnicodeWriter_Init(writer);
|
| 1374 |
+
if (_PyUnicodeWriter_Prepare(writer, length, 127) < 0) {
|
| 1375 |
+
PyUnicodeWriter_Discard(pub_writer);
|
| 1376 |
+
return NULL;
|
| 1377 |
+
}
|
| 1378 |
+
writer->overallocate = 1;
|
| 1379 |
+
return pub_writer;
|
| 1380 |
+
}
|
| 1381 |
+
|
| 1382 |
+
static inline PyObject* PyUnicodeWriter_Finish(PyUnicodeWriter *writer)
|
| 1383 |
+
{
|
| 1384 |
+
PyObject *str = _PyUnicodeWriter_Finish((_PyUnicodeWriter*)writer);
|
| 1385 |
+
assert(((_PyUnicodeWriter*)writer)->buffer == NULL);
|
| 1386 |
+
PyMem_Free(writer);
|
| 1387 |
+
return str;
|
| 1388 |
+
}
|
| 1389 |
+
|
| 1390 |
+
static inline int
|
| 1391 |
+
PyUnicodeWriter_WriteChar(PyUnicodeWriter *writer, Py_UCS4 ch)
|
| 1392 |
+
{
|
| 1393 |
+
if (ch > 0x10ffff) {
|
| 1394 |
+
PyErr_SetString(PyExc_ValueError,
|
| 1395 |
+
"character must be in range(0x110000)");
|
| 1396 |
+
return -1;
|
| 1397 |
+
}
|
| 1398 |
+
|
| 1399 |
+
return _PyUnicodeWriter_WriteChar((_PyUnicodeWriter*)writer, ch);
|
| 1400 |
+
}
|
| 1401 |
+
|
| 1402 |
+
static inline int
|
| 1403 |
+
PyUnicodeWriter_WriteStr(PyUnicodeWriter *writer, PyObject *obj)
|
| 1404 |
+
{
|
| 1405 |
+
PyObject *str = PyObject_Str(obj);
|
| 1406 |
+
if (str == NULL) {
|
| 1407 |
+
return -1;
|
| 1408 |
+
}
|
| 1409 |
+
|
| 1410 |
+
int res = _PyUnicodeWriter_WriteStr((_PyUnicodeWriter*)writer, str);
|
| 1411 |
+
Py_DECREF(str);
|
| 1412 |
+
return res;
|
| 1413 |
+
}
|
| 1414 |
+
|
| 1415 |
+
static inline int
|
| 1416 |
+
PyUnicodeWriter_WriteRepr(PyUnicodeWriter *writer, PyObject *obj)
|
| 1417 |
+
{
|
| 1418 |
+
PyObject *str = PyObject_Repr(obj);
|
| 1419 |
+
if (str == NULL) {
|
| 1420 |
+
return -1;
|
| 1421 |
+
}
|
| 1422 |
+
|
| 1423 |
+
int res = _PyUnicodeWriter_WriteStr((_PyUnicodeWriter*)writer, str);
|
| 1424 |
+
Py_DECREF(str);
|
| 1425 |
+
return res;
|
| 1426 |
+
}
|
| 1427 |
+
|
| 1428 |
+
static inline int
|
| 1429 |
+
PyUnicodeWriter_WriteUTF8(PyUnicodeWriter *writer,
|
| 1430 |
+
const char *str, Py_ssize_t size)
|
| 1431 |
+
{
|
| 1432 |
+
if (size < 0) {
|
| 1433 |
+
size = (Py_ssize_t)strlen(str);
|
| 1434 |
+
}
|
| 1435 |
+
|
| 1436 |
+
PyObject *str_obj = PyUnicode_FromStringAndSize(str, size);
|
| 1437 |
+
if (str_obj == _Py_NULL) {
|
| 1438 |
+
return -1;
|
| 1439 |
+
}
|
| 1440 |
+
|
| 1441 |
+
int res = _PyUnicodeWriter_WriteStr((_PyUnicodeWriter*)writer, str_obj);
|
| 1442 |
+
Py_DECREF(str_obj);
|
| 1443 |
+
return res;
|
| 1444 |
+
}
|
| 1445 |
+
|
| 1446 |
+
static inline int
|
| 1447 |
+
PyUnicodeWriter_WriteWideChar(PyUnicodeWriter *writer,
|
| 1448 |
+
const wchar_t *str, Py_ssize_t size)
|
| 1449 |
+
{
|
| 1450 |
+
if (size < 0) {
|
| 1451 |
+
size = (Py_ssize_t)wcslen(str);
|
| 1452 |
+
}
|
| 1453 |
+
|
| 1454 |
+
PyObject *str_obj = PyUnicode_FromWideChar(str, size);
|
| 1455 |
+
if (str_obj == _Py_NULL) {
|
| 1456 |
+
return -1;
|
| 1457 |
+
}
|
| 1458 |
+
|
| 1459 |
+
int res = _PyUnicodeWriter_WriteStr((_PyUnicodeWriter*)writer, str_obj);
|
| 1460 |
+
Py_DECREF(str_obj);
|
| 1461 |
+
return res;
|
| 1462 |
+
}
|
| 1463 |
+
|
| 1464 |
+
static inline int
|
| 1465 |
+
PyUnicodeWriter_WriteSubstring(PyUnicodeWriter *writer, PyObject *str,
|
| 1466 |
+
Py_ssize_t start, Py_ssize_t end)
|
| 1467 |
+
{
|
| 1468 |
+
if (!PyUnicode_Check(str)) {
|
| 1469 |
+
PyErr_Format(PyExc_TypeError, "expect str, not %T", str);
|
| 1470 |
+
return -1;
|
| 1471 |
+
}
|
| 1472 |
+
if (start < 0 || start > end) {
|
| 1473 |
+
PyErr_Format(PyExc_ValueError, "invalid start argument");
|
| 1474 |
+
return -1;
|
| 1475 |
+
}
|
| 1476 |
+
if (end > PyUnicode_GET_LENGTH(str)) {
|
| 1477 |
+
PyErr_Format(PyExc_ValueError, "invalid end argument");
|
| 1478 |
+
return -1;
|
| 1479 |
+
}
|
| 1480 |
+
|
| 1481 |
+
return _PyUnicodeWriter_WriteSubstring((_PyUnicodeWriter*)writer, str,
|
| 1482 |
+
start, end);
|
| 1483 |
+
}
|
| 1484 |
+
|
| 1485 |
+
static inline int
|
| 1486 |
+
PyUnicodeWriter_Format(PyUnicodeWriter *writer, const char *format, ...)
|
| 1487 |
+
{
|
| 1488 |
+
va_list vargs;
|
| 1489 |
+
va_start(vargs, format);
|
| 1490 |
+
PyObject *str = PyUnicode_FromFormatV(format, vargs);
|
| 1491 |
+
va_end(vargs);
|
| 1492 |
+
if (str == _Py_NULL) {
|
| 1493 |
+
return -1;
|
| 1494 |
+
}
|
| 1495 |
+
|
| 1496 |
+
int res = _PyUnicodeWriter_WriteStr((_PyUnicodeWriter*)writer, str);
|
| 1497 |
+
Py_DECREF(str);
|
| 1498 |
+
return res;
|
| 1499 |
+
}
|
| 1500 |
+
#endif // PY_VERSION_HEX < 0x030E0000
|
| 1501 |
+
|
| 1502 |
+
// gh-116560 added PyLong_GetSign() to Python 3.14.0a0
|
| 1503 |
+
#if PY_VERSION_HEX < 0x030E00A0
|
| 1504 |
+
static inline int PyLong_GetSign(PyObject *obj, int *sign)
|
| 1505 |
+
{
|
| 1506 |
+
if (!PyLong_Check(obj)) {
|
| 1507 |
+
PyErr_Format(PyExc_TypeError, "expect int, got %s", Py_TYPE(obj)->tp_name);
|
| 1508 |
+
return -1;
|
| 1509 |
+
}
|
| 1510 |
+
|
| 1511 |
+
*sign = _PyLong_Sign(obj);
|
| 1512 |
+
return 0;
|
| 1513 |
+
}
|
| 1514 |
+
#endif
|
| 1515 |
+
|
| 1516 |
+
|
| 1517 |
+
#ifdef __cplusplus
|
| 1518 |
+
}
|
| 1519 |
+
#endif
|
| 1520 |
+
#endif // PYTHONCAPI_COMPAT
|
phivenv/Lib/site-packages/torch/include/torch/csrc/utils/schema_info.h
ADDED
|
@@ -0,0 +1,116 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#pragma once
|
| 2 |
+
|
| 3 |
+
#include <torch/csrc/jit/frontend/function_schema_parser.h>
|
| 4 |
+
#include <unordered_set>
|
| 5 |
+
|
| 6 |
+
namespace torch::utils {
|
| 7 |
+
|
| 8 |
+
using SchemaSpecialCasePair =
|
| 9 |
+
std::pair<c10::FunctionSchema, std::unordered_set<std::string>>;
|
| 10 |
+
/**
|
| 11 |
+
* class SchemaInfo
|
| 12 |
+
*
|
| 13 |
+
* FunctionSchema wrapper that publicizes argument value specific operator
|
| 14 |
+
* behavior (mutation, aliasing, special cases, etc...)
|
| 15 |
+
*/
|
| 16 |
+
|
| 17 |
+
struct TORCH_API SchemaInfo {
|
| 18 |
+
public:
|
| 19 |
+
explicit SchemaInfo(c10::FunctionSchema schema)
|
| 20 |
+
: schema_(std::move(schema)),
|
| 21 |
+
alias_maps_current_(false),
|
| 22 |
+
has_init_(false) {}
|
| 23 |
+
explicit SchemaInfo(const char* signature)
|
| 24 |
+
: schema_(torch::jit::parseSchema(signature)),
|
| 25 |
+
alias_maps_current_(false),
|
| 26 |
+
has_init_(false) {}
|
| 27 |
+
|
| 28 |
+
bool is_mutable();
|
| 29 |
+
|
| 30 |
+
bool is_mutable(const c10::SchemaArgument& argument);
|
| 31 |
+
|
| 32 |
+
bool is_mutable(std::string_view name);
|
| 33 |
+
|
| 34 |
+
bool has_argument(std::string_view name);
|
| 35 |
+
|
| 36 |
+
bool is_nondeterministic() const;
|
| 37 |
+
|
| 38 |
+
// Returns whether lhs and rhs may alias directly.
|
| 39 |
+
// This does not account for cases where lhs or rhs are a container that
|
| 40 |
+
// may contain elements that alias the other argument.
|
| 41 |
+
// Besides the checks already included in FunctionSchema::may_alias, this
|
| 42 |
+
// method also accounts special aliasing cases causes by aliasing argument
|
| 43 |
+
// values supplied from addArgumentValue.
|
| 44 |
+
bool may_alias(
|
| 45 |
+
const c10::SchemaArgument& lhs,
|
| 46 |
+
const c10::SchemaArgument& rhs);
|
| 47 |
+
|
| 48 |
+
// Returns whether lhs and rhs may alias directly or whether lhs/rhs are a
|
| 49 |
+
// container that may contain elements that alias the other argument. Besides
|
| 50 |
+
// the checks already included in FunctionSchema::may_contain_alias, this
|
| 51 |
+
// method also accounts for special aliasing cases causes by aliasing argument
|
| 52 |
+
// values supplied from addArgumentValue. bidirectional = false only returns
|
| 53 |
+
// whether lhs may contain an alias of rhs while bidirectional = true returns
|
| 54 |
+
// both directions.
|
| 55 |
+
bool may_contain_alias(
|
| 56 |
+
const c10::SchemaArgument& lhs,
|
| 57 |
+
const c10::SchemaArgument& rhs,
|
| 58 |
+
bool bidirectional = true);
|
| 59 |
+
|
| 60 |
+
void addArgumentValue(const std::string& name, const at::IValue& value);
|
| 61 |
+
|
| 62 |
+
void addArgumentValues(
|
| 63 |
+
const std::vector<std::optional<at::IValue>>& value_list);
|
| 64 |
+
|
| 65 |
+
void addArgumentValues(
|
| 66 |
+
const std::unordered_map<std::string, at::IValue>& values);
|
| 67 |
+
|
| 68 |
+
bool hasInputArgumentNamed(const std::string& name) const;
|
| 69 |
+
|
| 70 |
+
private:
|
| 71 |
+
// This function enforces more conservative results when the TORCH_WARN is
|
| 72 |
+
// triggered from above due to duplicates in an argument list
|
| 73 |
+
void ensureConservativity(
|
| 74 |
+
const std::unordered_set<at::Symbol>& duplicates,
|
| 75 |
+
const std::vector<c10::Argument>& arguments_list,
|
| 76 |
+
c10::SchemaArgType type);
|
| 77 |
+
|
| 78 |
+
void initSchemaInfo();
|
| 79 |
+
|
| 80 |
+
void generateAliasMaps();
|
| 81 |
+
|
| 82 |
+
bool mayContainAliasImpl(
|
| 83 |
+
const c10::SchemaArgument& lhs,
|
| 84 |
+
const c10::SchemaArgument& rhs);
|
| 85 |
+
|
| 86 |
+
static std::vector<c10::FunctionSchema> getNonDeterministicOps();
|
| 87 |
+
|
| 88 |
+
static std::vector<SchemaSpecialCasePair> getTrainingOps();
|
| 89 |
+
|
| 90 |
+
const std::unordered_set<c10::SchemaArgument>& wildcardSet();
|
| 91 |
+
|
| 92 |
+
const std::unordered_set<c10::SchemaArgument>& containerSet();
|
| 93 |
+
|
| 94 |
+
// Set of all wildcard arguments
|
| 95 |
+
std::unordered_set<c10::SchemaArgument> wildcard_set_;
|
| 96 |
+
|
| 97 |
+
// Set of all container arguments
|
| 98 |
+
std::unordered_set<c10::SchemaArgument> container_set_;
|
| 99 |
+
|
| 100 |
+
// Map of argument IValues
|
| 101 |
+
std::unordered_map<std::string, at::IValue> value_map_;
|
| 102 |
+
|
| 103 |
+
// Alias map of inputs with each other
|
| 104 |
+
std::vector<std::unordered_set<size_t>> input_alias_map_;
|
| 105 |
+
|
| 106 |
+
// Alias map of outputs to inputs
|
| 107 |
+
std::vector<std::unordered_set<size_t>> output_alias_map_;
|
| 108 |
+
|
| 109 |
+
// NOLINTNEXTLINE(cppcoreguidelines-avoid-const-or-ref-data-members)
|
| 110 |
+
const c10::FunctionSchema schema_;
|
| 111 |
+
|
| 112 |
+
bool alias_maps_current_;
|
| 113 |
+
|
| 114 |
+
bool has_init_;
|
| 115 |
+
};
|
| 116 |
+
} // namespace torch::utils
|
phivenv/Lib/site-packages/torch/include/torch/csrc/utils/six.h
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#pragma once
|
| 2 |
+
|
| 3 |
+
#include <pybind11/pybind11.h>
|
| 4 |
+
#include <torch/csrc/utils/object_ptr.h>
|
| 5 |
+
#include <torch/csrc/utils/pybind.h>
|
| 6 |
+
#include <torch/csrc/utils/structseq.h>
|
| 7 |
+
|
| 8 |
+
namespace six {
|
| 9 |
+
|
| 10 |
+
// Usually instances of PyStructSequence is also an instance of tuple
|
| 11 |
+
// but in some py2 environment it is not, so we have to manually check
|
| 12 |
+
// the name of the type to determine if it is a namedtupled returned
|
| 13 |
+
// by a pytorch operator.
|
| 14 |
+
|
| 15 |
+
inline bool isStructSeq(pybind11::handle input) {
|
| 16 |
+
return pybind11::cast<std::string>(pybind11::type::handle_of(input).attr(
|
| 17 |
+
"__module__")) == "torch.return_types";
|
| 18 |
+
}
|
| 19 |
+
|
| 20 |
+
inline bool isStructSeq(PyObject* obj) {
|
| 21 |
+
return isStructSeq(pybind11::handle(obj));
|
| 22 |
+
}
|
| 23 |
+
|
| 24 |
+
inline bool isTuple(pybind11::handle input) {
|
| 25 |
+
if (PyTuple_Check(input.ptr())) {
|
| 26 |
+
return true;
|
| 27 |
+
}
|
| 28 |
+
return false;
|
| 29 |
+
}
|
| 30 |
+
|
| 31 |
+
inline bool isTuple(PyObject* obj) {
|
| 32 |
+
return isTuple(pybind11::handle(obj));
|
| 33 |
+
}
|
| 34 |
+
|
| 35 |
+
// maybeAsTuple: if the input is a structseq, then convert it to a tuple
|
| 36 |
+
//
|
| 37 |
+
// On Python 3, structseq is a subtype of tuple, so these APIs could be used
|
| 38 |
+
// directly. But on Python 2, structseq is not a subtype of tuple, so we need to
|
| 39 |
+
// manually create a new tuple object from structseq.
|
| 40 |
+
inline THPObjectPtr maybeAsTuple(PyStructSequence* obj) {
|
| 41 |
+
Py_INCREF(obj);
|
| 42 |
+
return THPObjectPtr((PyObject*)obj);
|
| 43 |
+
}
|
| 44 |
+
|
| 45 |
+
inline THPObjectPtr maybeAsTuple(PyObject* obj) {
|
| 46 |
+
if (isStructSeq(obj))
|
| 47 |
+
return maybeAsTuple((PyStructSequence*)obj);
|
| 48 |
+
Py_INCREF(obj);
|
| 49 |
+
return THPObjectPtr(obj);
|
| 50 |
+
}
|
| 51 |
+
|
| 52 |
+
} // namespace six
|
phivenv/Lib/site-packages/torch/include/torch/csrc/utils/structseq.h
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#pragma once
|
| 2 |
+
|
| 3 |
+
#include <torch/csrc/python_headers.h>
|
| 4 |
+
|
| 5 |
+
namespace torch::utils {
|
| 6 |
+
|
| 7 |
+
PyObject* returned_structseq_repr(PyStructSequence* obj);
|
| 8 |
+
|
| 9 |
+
}
|
phivenv/Lib/site-packages/torch/include/torch/csrc/utils/tensor_apply.h
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#pragma once
|
| 2 |
+
|
| 3 |
+
#include <ATen/core/Tensor.h>
|
| 4 |
+
#include <torch/csrc/python_headers.h>
|
| 5 |
+
|
| 6 |
+
namespace torch::utils {
|
| 7 |
+
|
| 8 |
+
const at::Tensor& apply_(const at::Tensor& self, PyObject* fn);
|
| 9 |
+
const at::Tensor& map_(
|
| 10 |
+
const at::Tensor& self,
|
| 11 |
+
const at::Tensor& other_,
|
| 12 |
+
PyObject* fn);
|
| 13 |
+
const at::Tensor& map2_(
|
| 14 |
+
const at::Tensor& self,
|
| 15 |
+
const at::Tensor& x_,
|
| 16 |
+
const at::Tensor& y_,
|
| 17 |
+
PyObject* fn);
|
| 18 |
+
|
| 19 |
+
} // namespace torch::utils
|