cranky-coder08 commited on
Commit
44823a3
·
verified ·
1 Parent(s): 568f19a

Add files using upload-large-folder tool

Browse files
This view is limited to 50 files because it contains too many changes.   See raw diff
Files changed (50) hide show
  1. .gitattributes +7 -0
  2. phivenv/Lib/site-packages/torch/include/torch/csrc/profiler/unwind/communicate.h +73 -0
  3. phivenv/Lib/site-packages/torch/include/torch/csrc/profiler/unwind/debug_info.h +280 -0
  4. phivenv/Lib/site-packages/torch/include/torch/csrc/profiler/unwind/dwarf_enums.h +46 -0
  5. phivenv/Lib/site-packages/torch/include/torch/csrc/profiler/unwind/dwarf_symbolize_enums.h +179 -0
  6. phivenv/Lib/site-packages/torch/include/torch/csrc/profiler/unwind/eh_frame_hdr.h +100 -0
  7. phivenv/Lib/site-packages/torch/include/torch/csrc/profiler/unwind/fast_symbolizer.h +108 -0
  8. phivenv/Lib/site-packages/torch/include/torch/csrc/profiler/unwind/fde.h +411 -0
  9. phivenv/Lib/site-packages/torch/include/torch/csrc/profiler/unwind/lexer.h +159 -0
  10. phivenv/Lib/site-packages/torch/include/torch/csrc/profiler/unwind/line_number_program.h +328 -0
  11. phivenv/Lib/site-packages/torch/include/torch/csrc/profiler/unwind/mem_file.h +159 -0
  12. phivenv/Lib/site-packages/torch/include/torch/csrc/profiler/unwind/range_table.h +73 -0
  13. phivenv/Lib/site-packages/torch/include/torch/csrc/profiler/unwind/sections.h +120 -0
  14. phivenv/Lib/site-packages/torch/include/torch/csrc/profiler/unwind/unwind.h +43 -0
  15. phivenv/Lib/site-packages/torch/include/torch/csrc/profiler/unwind/unwind_error.h +29 -0
  16. phivenv/Lib/site-packages/torch/include/torch/csrc/profiler/unwind/unwinder.h +81 -0
  17. phivenv/Lib/site-packages/torch/include/torch/csrc/stable/library.h +356 -0
  18. phivenv/Lib/site-packages/torch/include/torch/csrc/stable/tensor.h +126 -0
  19. phivenv/Lib/site-packages/torch/include/torch/csrc/tensor/python_tensor.h +35 -0
  20. phivenv/Lib/site-packages/torch/include/torch/csrc/utils/byte_order.h +81 -0
  21. phivenv/Lib/site-packages/torch/include/torch/csrc/utils/cpp_stacktraces.h +9 -0
  22. phivenv/Lib/site-packages/torch/include/torch/csrc/utils/cuda_enabled.h +13 -0
  23. phivenv/Lib/site-packages/torch/include/torch/csrc/utils/device_lazy_init.h +87 -0
  24. phivenv/Lib/site-packages/torch/include/torch/csrc/utils/disable_torch_function.h +45 -0
  25. phivenv/Lib/site-packages/torch/include/torch/csrc/utils/generated_serialization_types.h +0 -0
  26. phivenv/Lib/site-packages/torch/include/torch/csrc/utils/init.h +9 -0
  27. phivenv/Lib/site-packages/torch/include/torch/csrc/utils/invalid_arguments.h +15 -0
  28. phivenv/Lib/site-packages/torch/include/torch/csrc/utils/nested.h +15 -0
  29. phivenv/Lib/site-packages/torch/include/torch/csrc/utils/numpy_stub.h +21 -0
  30. phivenv/Lib/site-packages/torch/include/torch/csrc/utils/object_ptr.h +81 -0
  31. phivenv/Lib/site-packages/torch/include/torch/csrc/utils/out_types.h +15 -0
  32. phivenv/Lib/site-packages/torch/include/torch/csrc/utils/pybind.h +420 -0
  33. phivenv/Lib/site-packages/torch/include/torch/csrc/utils/pycfunction_helpers.h +13 -0
  34. phivenv/Lib/site-packages/torch/include/torch/csrc/utils/pyobject_preservation.h +7 -0
  35. phivenv/Lib/site-packages/torch/include/torch/csrc/utils/python_arg_parser.h +1303 -0
  36. phivenv/Lib/site-packages/torch/include/torch/csrc/utils/python_compat.h +46 -0
  37. phivenv/Lib/site-packages/torch/include/torch/csrc/utils/python_dispatch.h +16 -0
  38. phivenv/Lib/site-packages/torch/include/torch/csrc/utils/python_numbers.h +204 -0
  39. phivenv/Lib/site-packages/torch/include/torch/csrc/utils/python_raii.h +84 -0
  40. phivenv/Lib/site-packages/torch/include/torch/csrc/utils/python_scalars.h +172 -0
  41. phivenv/Lib/site-packages/torch/include/torch/csrc/utils/python_strings.h +129 -0
  42. phivenv/Lib/site-packages/torch/include/torch/csrc/utils/python_stub.h +4 -0
  43. phivenv/Lib/site-packages/torch/include/torch/csrc/utils/python_symnode.h +328 -0
  44. phivenv/Lib/site-packages/torch/include/torch/csrc/utils/python_torch_function_mode.h +29 -0
  45. phivenv/Lib/site-packages/torch/include/torch/csrc/utils/python_tuples.h +27 -0
  46. phivenv/Lib/site-packages/torch/include/torch/csrc/utils/pythoncapi_compat.h +1520 -0
  47. phivenv/Lib/site-packages/torch/include/torch/csrc/utils/schema_info.h +116 -0
  48. phivenv/Lib/site-packages/torch/include/torch/csrc/utils/six.h +52 -0
  49. phivenv/Lib/site-packages/torch/include/torch/csrc/utils/structseq.h +9 -0
  50. 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