Nuitka
The Python compiler
Loading...
Searching...
No Matches
HelpersOperationInplaceAdd.c
1// Copyright 2025, Kay Hayen, mailto:kay.hayen@gmail.com find license text at end of file
2
3/* WARNING, this code is GENERATED. Modify the template HelperOperationInplace.c.j2 instead! */
4
5/* This file is included from another C file, help IDEs to still parse it on its own. */
6#ifdef __IDE_ONLY__
7#include "nuitka/prelude.h"
8#endif
9
10#include "HelpersOperationInplaceAddUtils.c"
11/* C helpers for type in-place "+" (ADD) operations */
12
13#if PYTHON_VERSION < 0x300
14/* Code referring to "INT" corresponds to Python2 'int' and "INT" to Python2 'int'. */
15static inline bool _INPLACE_OPERATION_ADD_INT_INT(PyObject **operand1, PyObject *operand2) {
16 assert(operand1); // Pointer must be non-null.
17
18 CHECK_OBJECT(*operand1);
19 assert(PyInt_CheckExact(*operand1));
20 CHECK_OBJECT(operand2);
21 assert(PyInt_CheckExact(operand2));
22
23 // Not every code path will make use of all possible results.
24#if defined(_MSC_VER)
25#pragma warning(push)
26#pragma warning(disable : 4101)
27#endif
28 NUITKA_MAY_BE_UNUSED bool cbool_result;
29 NUITKA_MAY_BE_UNUSED PyObject *obj_result;
30 NUITKA_MAY_BE_UNUSED long clong_result;
31 NUITKA_MAY_BE_UNUSED double cfloat_result;
32#if defined(_MSC_VER)
33#pragma warning(pop)
34#endif
35
36 CHECK_OBJECT(*operand1);
37 assert(PyInt_CheckExact(*operand1));
38 CHECK_OBJECT(operand2);
39 assert(PyInt_CheckExact(operand2));
40
41 const long a = PyInt_AS_LONG(*operand1);
42 const long b = PyInt_AS_LONG(operand2);
43
44 const long x = (long)((unsigned long)a + b);
45 bool no_overflow = ((x ^ a) >= 0 || (x ^ b) >= 0);
46 if (likely(no_overflow)) {
47 clong_result = x;
48 goto exit_result_ok_clong;
49 }
50
51 {
52 PyObject *operand1_object = *operand1;
53 PyObject *operand2_object = operand2;
54
55 PyObject *r = PyLong_Type.tp_as_number->nb_add(operand1_object, operand2_object);
56 assert(r != Py_NotImplemented);
57
58 obj_result = r;
59 goto exit_result_object;
60 }
61
62exit_result_ok_clong:
63
64 // We got an object handed, that we have to release.
65 Py_DECREF(*operand1);
66
67 // That's our return value then. As we use a dedicated variable, it's
68 // OK that way.
69 *operand1 = Nuitka_PyInt_FromLong(clong_result);
70 goto exit_result_ok;
71
72exit_result_object:
73 if (unlikely(obj_result == NULL)) {
74 goto exit_result_exception;
75 }
76 // We got an object handed, that we have to release.
77 Py_DECREF(*operand1);
78
79 *operand1 = obj_result;
80 goto exit_result_ok;
81
82exit_result_ok:
83 return true;
84
85exit_result_exception:
86 return false;
87}
88
89bool INPLACE_OPERATION_ADD_INT_INT(PyObject **operand1, PyObject *operand2) {
90 return _INPLACE_OPERATION_ADD_INT_INT(operand1, operand2);
91}
92#endif
93
94#if PYTHON_VERSION < 0x300
95/* Code referring to "OBJECT" corresponds to any Python object and "INT" to Python2 'int'. */
96static HEDLEY_NEVER_INLINE bool __INPLACE_OPERATION_ADD_OBJECT_INT(PyObject **operand1, PyObject *operand2) {
97 PyTypeObject *type1 = Py_TYPE(*operand1);
98
99#if defined(_MSC_VER)
100#pragma warning(push)
101#pragma warning(disable : 4101)
102#endif
103 NUITKA_MAY_BE_UNUSED bool cbool_result;
104 NUITKA_MAY_BE_UNUSED PyObject *obj_result;
105#if defined(_MSC_VER)
106#pragma warning(pop)
107#endif
108
109 binaryfunc islot =
110 (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_inplace_add : NULL;
111
112 if (islot != NULL) {
113 PyObject *x = islot(*operand1, operand2);
114
115 if (x != Py_NotImplemented) {
116 obj_result = x;
117 goto exit_inplace_result_object;
118 }
119
120 Py_DECREF_IMMORTAL(x);
121 }
122
123 {
124 binaryfunc slot1 =
125 (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_add : NULL;
126 binaryfunc slot2 = NULL;
127
128 if (!(type1 == &PyInt_Type)) {
129 // Different types, need to consider second value slot.
130
131 slot2 = PyInt_Type.tp_as_number->nb_add;
132
133 if (slot1 == slot2) {
134 slot2 = NULL;
135 }
136 }
137
138 if (slot1 != NULL) {
139 PyObject *x = slot1(*operand1, operand2);
140
141 if (x != Py_NotImplemented) {
142 obj_result = x;
143 goto exit_inplace_result_object;
144 }
145
146 Py_DECREF_IMMORTAL(x);
147 }
148
149 if (slot2 != NULL) {
150 PyObject *x = slot2(*operand1, operand2);
151
152 if (x != Py_NotImplemented) {
153 obj_result = x;
154 goto exit_inplace_result_object;
155 }
156
157 Py_DECREF_IMMORTAL(x);
158 }
159
160#if PYTHON_VERSION < 0x300
161 if (!NEW_STYLE_NUMBER_TYPE(type1) || !1) {
162 coercion c1 =
163 (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_coerce : NULL;
164
165 if (c1 != NULL) {
166 PyObject *coerced1 = *operand1;
167 PyObject *coerced2 = operand2;
168
169 int err = c1(&coerced1, &coerced2);
170
171 if (unlikely(err < 0)) {
172 goto exit_inplace_exception;
173 }
174
175 if (err == 0) {
176 PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number;
177
178 if (likely(mv == NULL)) {
179 binaryfunc slot = mv->nb_add;
180
181 if (likely(slot != NULL)) {
182 PyObject *x = slot(coerced1, coerced2);
183
184 Py_DECREF(coerced1);
185 Py_DECREF(coerced2);
186
187 obj_result = x;
188 goto exit_inplace_result_object;
189 }
190 }
191
192 // nb_coerce took a reference.
193 Py_DECREF(coerced1);
194 Py_DECREF(coerced2);
195 }
196 }
197 coercion c2 = PyInt_Type.tp_as_number->nb_coerce;
198
199 if (c2 != NULL) {
200 PyObject *coerced1 = *operand1;
201 PyObject *coerced2 = operand2;
202
203 int err = c2(&coerced2, &coerced1);
204
205 if (unlikely(err < 0)) {
206 goto exit_inplace_exception;
207 }
208
209 if (err == 0) {
210 PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number;
211
212 if (likely(mv == NULL)) {
213 binaryfunc slot = mv->nb_add;
214
215 if (likely(slot != NULL)) {
216 PyObject *x = slot(coerced1, coerced2);
217
218 Py_DECREF(coerced1);
219 Py_DECREF(coerced2);
220
221 obj_result = x;
222 goto exit_inplace_result_object;
223 }
224 }
225
226 // nb_coerce took a reference.
227 Py_DECREF(coerced1);
228 Py_DECREF(coerced2);
229 }
230 }
231 }
232#endif
233
234 {
235 // Special case for "+" and "*", also works as sequence concat/repeat.
236 binaryfunc sq_slot = type1->tp_as_sequence != NULL ? type1->tp_as_sequence->sq_inplace_concat : NULL;
237 if (sq_slot == NULL) {
238 sq_slot = type1->tp_as_sequence != NULL ? type1->tp_as_sequence->sq_concat : NULL;
239 }
240
241 if (sq_slot != NULL) {
242 PyObject *result = sq_slot(*operand1, operand2);
243
244 obj_result = result;
245 goto exit_inplace_result_object;
246 }
247 }
248
249 PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for +=: '%s' and 'int'", type1->tp_name);
250 goto exit_inplace_exception;
251 }
252
253exit_inplace_result_object:
254 if (unlikely(obj_result == NULL)) {
255 return false;
256 }
257
258 // We got an object handed, that we have to release.
259 Py_DECREF(*operand1);
260
261 // That's our return value then. As we use a dedicated variable, it's
262 // OK that way.
263 *operand1 = obj_result;
264
265 return true;
266
267exit_inplace_exception:
268 return false;
269}
270static inline bool _INPLACE_OPERATION_ADD_OBJECT_INT(PyObject **operand1, PyObject *operand2) {
271 assert(operand1); // Pointer must be non-null.
272
273 CHECK_OBJECT(*operand1);
274 CHECK_OBJECT(operand2);
275 assert(PyInt_CheckExact(operand2));
276
277 PyTypeObject *type1 = Py_TYPE(*operand1);
278
279 if (type1 == &PyInt_Type) {
280 // return _BINARY_OPERATION_ADD_INT_INT_INPLACE(operand1, operand2);
281
282 // Not every code path will make use of all possible results.
283#if defined(_MSC_VER)
284#pragma warning(push)
285#pragma warning(disable : 4101)
286#endif
287 NUITKA_MAY_BE_UNUSED bool cbool_result;
288 NUITKA_MAY_BE_UNUSED PyObject *obj_result;
289 NUITKA_MAY_BE_UNUSED long clong_result;
290 NUITKA_MAY_BE_UNUSED double cfloat_result;
291#if defined(_MSC_VER)
292#pragma warning(pop)
293#endif
294
295 CHECK_OBJECT(*operand1);
296 assert(PyInt_CheckExact(*operand1));
297 CHECK_OBJECT(operand2);
298 assert(PyInt_CheckExact(operand2));
299
300 const long a = PyInt_AS_LONG(*operand1);
301 const long b = PyInt_AS_LONG(operand2);
302
303 const long x = (long)((unsigned long)a + b);
304 bool no_overflow = ((x ^ a) >= 0 || (x ^ b) >= 0);
305 if (likely(no_overflow)) {
306 clong_result = x;
307 goto exit_result_ok_clong;
308 }
309
310 {
311 PyObject *operand1_object = *operand1;
312 PyObject *operand2_object = operand2;
313
314 PyObject *r = PyLong_Type.tp_as_number->nb_add(operand1_object, operand2_object);
315 assert(r != Py_NotImplemented);
316
317 obj_result = r;
318 goto exit_result_object;
319 }
320
321 exit_result_ok_clong:
322
323 // We got an object handed, that we have to release.
324 Py_DECREF(*operand1);
325
326 // That's our return value then. As we use a dedicated variable, it's
327 // OK that way.
328 *operand1 = Nuitka_PyInt_FromLong(clong_result);
329 goto exit_result_ok;
330
331 exit_result_object:
332 if (unlikely(obj_result == NULL)) {
333 goto exit_result_exception;
334 }
335 // We got an object handed, that we have to release.
336 Py_DECREF(*operand1);
337
338 *operand1 = obj_result;
339 goto exit_result_ok;
340
341 exit_result_ok:
342 return true;
343
344 exit_result_exception:
345 return false;
346 }
347
348 return __INPLACE_OPERATION_ADD_OBJECT_INT(operand1, operand2);
349}
350
351bool INPLACE_OPERATION_ADD_OBJECT_INT(PyObject **operand1, PyObject *operand2) {
352 return _INPLACE_OPERATION_ADD_OBJECT_INT(operand1, operand2);
353}
354#endif
355
356#if PYTHON_VERSION < 0x300
357/* Code referring to "INT" corresponds to Python2 'int' and "OBJECT" to any Python object. */
358static HEDLEY_NEVER_INLINE bool __INPLACE_OPERATION_ADD_INT_OBJECT(PyObject **operand1, PyObject *operand2) {
359 PyTypeObject *type2 = Py_TYPE(operand2);
360
361#if defined(_MSC_VER)
362#pragma warning(push)
363#pragma warning(disable : 4101)
364#endif
365 NUITKA_MAY_BE_UNUSED bool cbool_result;
366 NUITKA_MAY_BE_UNUSED PyObject *obj_result;
367#if defined(_MSC_VER)
368#pragma warning(pop)
369#endif
370
371 // No inplace number slot nb_inplace_add available for this type.
372
373 {
374 binaryfunc slot1 = PyInt_Type.tp_as_number->nb_add;
375 binaryfunc slot2 = NULL;
376
377 if (!(&PyInt_Type == type2)) {
378 // Different types, need to consider second value slot.
379
380 slot2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_add : NULL;
381
382 if (slot1 == slot2) {
383 slot2 = NULL;
384 }
385 }
386
387 if (slot1 != NULL) {
388 if (slot2 != NULL) {
389 if (Nuitka_Type_IsSubtype(type2, &PyInt_Type)) {
390 PyObject *x = slot2(*operand1, operand2);
391
392 if (x != Py_NotImplemented) {
393 obj_result = x;
394 goto exit_inplace_result_object;
395 }
396
397 Py_DECREF_IMMORTAL(x);
398 slot2 = NULL;
399 }
400 }
401
402 PyObject *x = slot1(*operand1, operand2);
403
404 if (x != Py_NotImplemented) {
405 obj_result = x;
406 goto exit_inplace_result_object;
407 }
408
409 Py_DECREF_IMMORTAL(x);
410 }
411
412 if (slot2 != NULL) {
413 PyObject *x = slot2(*operand1, operand2);
414
415 if (x != Py_NotImplemented) {
416 obj_result = x;
417 goto exit_inplace_result_object;
418 }
419
420 Py_DECREF_IMMORTAL(x);
421 }
422
423#if PYTHON_VERSION < 0x300
424 if (!1 || !NEW_STYLE_NUMBER_TYPE(type2)) {
425 coercion c1 = PyInt_Type.tp_as_number->nb_coerce;
426
427 if (c1 != NULL) {
428 PyObject *coerced1 = *operand1;
429 PyObject *coerced2 = operand2;
430
431 int err = c1(&coerced1, &coerced2);
432
433 if (unlikely(err < 0)) {
434 goto exit_inplace_exception;
435 }
436
437 if (err == 0) {
438 PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number;
439
440 if (likely(mv == NULL)) {
441 binaryfunc slot = mv->nb_add;
442
443 if (likely(slot != NULL)) {
444 PyObject *x = slot(coerced1, coerced2);
445
446 Py_DECREF(coerced1);
447 Py_DECREF(coerced2);
448
449 obj_result = x;
450 goto exit_inplace_result_object;
451 }
452 }
453
454 // nb_coerce took a reference.
455 Py_DECREF(coerced1);
456 Py_DECREF(coerced2);
457 }
458 }
459 coercion c2 =
460 (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_coerce : NULL;
461
462 if (c2 != NULL) {
463 PyObject *coerced1 = *operand1;
464 PyObject *coerced2 = operand2;
465
466 int err = c2(&coerced2, &coerced1);
467
468 if (unlikely(err < 0)) {
469 goto exit_inplace_exception;
470 }
471
472 if (err == 0) {
473 PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number;
474
475 if (likely(mv == NULL)) {
476 binaryfunc slot = mv->nb_add;
477
478 if (likely(slot != NULL)) {
479 PyObject *x = slot(coerced1, coerced2);
480
481 Py_DECREF(coerced1);
482 Py_DECREF(coerced2);
483
484 obj_result = x;
485 goto exit_inplace_result_object;
486 }
487 }
488
489 // nb_coerce took a reference.
490 Py_DECREF(coerced1);
491 Py_DECREF(coerced2);
492 }
493 }
494 }
495#endif
496
497 {
498 // No sequence repeat slot sq_concat available for this type.
499 // No inplace sequence repeat slot sq_inplace_concat available for this type.
500 }
501
502 PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for +=: 'int' and '%s'", type2->tp_name);
503 goto exit_inplace_exception;
504 }
505
506exit_inplace_result_object:
507 if (unlikely(obj_result == NULL)) {
508 return false;
509 }
510
511 // We got an object handed, that we have to release.
512 Py_DECREF(*operand1);
513
514 // That's our return value then. As we use a dedicated variable, it's
515 // OK that way.
516 *operand1 = obj_result;
517
518 return true;
519
520exit_inplace_exception:
521 return false;
522}
523static inline bool _INPLACE_OPERATION_ADD_INT_OBJECT(PyObject **operand1, PyObject *operand2) {
524 assert(operand1); // Pointer must be non-null.
525
526 CHECK_OBJECT(*operand1);
527 assert(PyInt_CheckExact(*operand1));
528 CHECK_OBJECT(operand2);
529
530 PyTypeObject *type2 = Py_TYPE(operand2);
531
532 if (&PyInt_Type == type2) {
533 // return _BINARY_OPERATION_ADD_INT_INT_INPLACE(operand1, operand2);
534
535 // Not every code path will make use of all possible results.
536#if defined(_MSC_VER)
537#pragma warning(push)
538#pragma warning(disable : 4101)
539#endif
540 NUITKA_MAY_BE_UNUSED bool cbool_result;
541 NUITKA_MAY_BE_UNUSED PyObject *obj_result;
542 NUITKA_MAY_BE_UNUSED long clong_result;
543 NUITKA_MAY_BE_UNUSED double cfloat_result;
544#if defined(_MSC_VER)
545#pragma warning(pop)
546#endif
547
548 CHECK_OBJECT(*operand1);
549 assert(PyInt_CheckExact(*operand1));
550 CHECK_OBJECT(operand2);
551 assert(PyInt_CheckExact(operand2));
552
553 const long a = PyInt_AS_LONG(*operand1);
554 const long b = PyInt_AS_LONG(operand2);
555
556 const long x = (long)((unsigned long)a + b);
557 bool no_overflow = ((x ^ a) >= 0 || (x ^ b) >= 0);
558 if (likely(no_overflow)) {
559 clong_result = x;
560 goto exit_result_ok_clong;
561 }
562
563 {
564 PyObject *operand1_object = *operand1;
565 PyObject *operand2_object = operand2;
566
567 PyObject *r = PyLong_Type.tp_as_number->nb_add(operand1_object, operand2_object);
568 assert(r != Py_NotImplemented);
569
570 obj_result = r;
571 goto exit_result_object;
572 }
573
574 exit_result_ok_clong:
575
576 // We got an object handed, that we have to release.
577 Py_DECREF(*operand1);
578
579 // That's our return value then. As we use a dedicated variable, it's
580 // OK that way.
581 *operand1 = Nuitka_PyInt_FromLong(clong_result);
582 goto exit_result_ok;
583
584 exit_result_object:
585 if (unlikely(obj_result == NULL)) {
586 goto exit_result_exception;
587 }
588 // We got an object handed, that we have to release.
589 Py_DECREF(*operand1);
590
591 *operand1 = obj_result;
592 goto exit_result_ok;
593
594 exit_result_ok:
595 return true;
596
597 exit_result_exception:
598 return false;
599 }
600
601 return __INPLACE_OPERATION_ADD_INT_OBJECT(operand1, operand2);
602}
603
604bool INPLACE_OPERATION_ADD_INT_OBJECT(PyObject **operand1, PyObject *operand2) {
605 return _INPLACE_OPERATION_ADD_INT_OBJECT(operand1, operand2);
606}
607#endif
608
609/* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "LONG" to Python2 'long', Python3 'int'. */
610static inline bool _INPLACE_OPERATION_ADD_LONG_LONG(PyObject **operand1, PyObject *operand2) {
611 assert(operand1); // Pointer must be non-null.
612
613 CHECK_OBJECT(*operand1);
614 assert(PyLong_CheckExact(*operand1));
615 CHECK_OBJECT(operand2);
616 assert(PyLong_CheckExact(operand2));
617
618 // Not every code path will make use of all possible results.
619#if defined(_MSC_VER)
620#pragma warning(push)
621#pragma warning(disable : 4101)
622#endif
623 NUITKA_MAY_BE_UNUSED PyObject *obj_result;
624 NUITKA_MAY_BE_UNUSED long clong_result;
625#if defined(_MSC_VER)
626#pragma warning(pop)
627#endif
628
629 PyLongObject *operand1_long_object = (PyLongObject *)*operand1;
630
631 PyLongObject *operand2_long_object = (PyLongObject *)operand2;
632
633 if (Nuitka_LongGetDigitSize(operand1_long_object) <= 1 && Nuitka_LongGetDigitSize(operand2_long_object) <= 1) {
634 long r = (long)(MEDIUM_VALUE(operand1_long_object) + MEDIUM_VALUE(operand2_long_object));
635
636 if (Py_REFCNT(*operand1) == 1) {
637 Nuitka_LongUpdateFromCLong(&*operand1, (long)r);
638 goto exit_result_ok;
639 } else {
640 PyObject *obj = Nuitka_LongFromCLong(r);
641
642 obj_result = obj;
643 goto exit_result_object;
644 }
645 clong_result = r;
646 goto exit_result_ok_clong;
647 }
648
649 if (Py_REFCNT(*operand1) == 1) {
650 digit const *b_digits = Nuitka_LongGetDigitPointer(operand2_long_object);
651 Py_ssize_t b_digit_count = Nuitka_LongGetDigitSize(operand2_long_object);
652
653 bool a_negative = Nuitka_LongIsNegative(operand1_long_object);
654 bool b_negative = Nuitka_LongIsNegative(operand2_long_object);
655
656 if (a_negative) {
657 if (b_negative) {
658 *operand1 = _Nuitka_LongAddInplaceDigits(*operand1, b_digits, b_digit_count);
659 Nuitka_LongSetSignNegative(*operand1);
660 } else {
661 *operand1 = _Nuitka_LongSubInplaceDigits(*operand1, b_digits, b_digit_count, -1);
662 }
663 } else {
664 if (b_negative) {
665 *operand1 = _Nuitka_LongSubInplaceDigits(*operand1, b_digits, b_digit_count, 1);
666 } else {
667 *operand1 = _Nuitka_LongAddInplaceDigits(*operand1, b_digits, b_digit_count);
668 }
669 }
670
671 goto exit_result_ok;
672 }
673 {
674 PyLongObject *z;
675
676 digit const *a_digits = Nuitka_LongGetDigitPointer(operand1_long_object);
677 Py_ssize_t a_digit_count = Nuitka_LongGetDigitSize(operand1_long_object);
678 bool a_negative = Nuitka_LongIsNegative(operand1_long_object);
679 digit const *b_digits = Nuitka_LongGetDigitPointer(operand2_long_object);
680 Py_ssize_t b_digit_count = Nuitka_LongGetDigitSize(operand2_long_object);
681 bool b_negative = Nuitka_LongIsNegative(operand2_long_object);
682
683 if (a_negative) {
684 if (b_negative) {
685 z = _Nuitka_LongAddDigits(a_digits, a_digit_count, b_digits, b_digit_count);
686 Nuitka_LongFlipSign(z);
687 } else {
688 z = _Nuitka_LongSubDigits(b_digits, b_digit_count, a_digits, a_digit_count);
689 }
690 } else {
691 if (b_negative) {
692 z = _Nuitka_LongSubDigits(a_digits, a_digit_count, b_digits, b_digit_count);
693 } else {
694 z = _Nuitka_LongAddDigits(a_digits, a_digit_count, b_digits, b_digit_count);
695 }
696 }
697
698 obj_result = (PyObject *)z;
699 goto exit_result_object;
700 }
701
702exit_result_object:
703 if (unlikely(obj_result == NULL)) {
704 goto exit_result_exception;
705 }
706 // We got an object handed, that we have to release.
707 Py_DECREF(*operand1);
708 *operand1 = obj_result;
709 goto exit_result_ok;
710
711exit_result_ok_clong:
712
713 // We got an object handed, that we have to release.
714 Py_DECREF(*operand1);
715
716 // That's our return value then. As we use a dedicated variable, it's
717 // OK that way.
718 *operand1 = Nuitka_PyLong_FromLong(clong_result);
719 goto exit_result_ok;
720
721exit_result_ok:
722 return true;
723
724exit_result_exception:
725 return false;
726}
727
728bool INPLACE_OPERATION_ADD_LONG_LONG(PyObject **operand1, PyObject *operand2) {
729 return _INPLACE_OPERATION_ADD_LONG_LONG(operand1, operand2);
730}
731
732/* Code referring to "OBJECT" corresponds to any Python object and "LONG" to Python2 'long', Python3 'int'. */
733static HEDLEY_NEVER_INLINE bool __INPLACE_OPERATION_ADD_OBJECT_LONG(PyObject **operand1, PyObject *operand2) {
734 PyTypeObject *type1 = Py_TYPE(*operand1);
735
736#if defined(_MSC_VER)
737#pragma warning(push)
738#pragma warning(disable : 4101)
739#endif
740 NUITKA_MAY_BE_UNUSED bool cbool_result;
741 NUITKA_MAY_BE_UNUSED PyObject *obj_result;
742#if defined(_MSC_VER)
743#pragma warning(pop)
744#endif
745
746 binaryfunc islot =
747 (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_inplace_add : NULL;
748
749 if (islot != NULL) {
750 PyObject *x = islot(*operand1, operand2);
751
752 if (x != Py_NotImplemented) {
753 obj_result = x;
754 goto exit_inplace_result_object;
755 }
756
757 Py_DECREF_IMMORTAL(x);
758 }
759
760 {
761 binaryfunc slot1 =
762 (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_add : NULL;
763 binaryfunc slot2 = NULL;
764
765 if (!(type1 == &PyLong_Type)) {
766 // Different types, need to consider second value slot.
767
768 slot2 = PyLong_Type.tp_as_number->nb_add;
769
770 if (slot1 == slot2) {
771 slot2 = NULL;
772 }
773 }
774
775 if (slot1 != NULL) {
776 PyObject *x = slot1(*operand1, operand2);
777
778 if (x != Py_NotImplemented) {
779 obj_result = x;
780 goto exit_inplace_result_object;
781 }
782
783 Py_DECREF_IMMORTAL(x);
784 }
785
786 if (slot2 != NULL) {
787 PyObject *x = slot2(*operand1, operand2);
788
789 if (x != Py_NotImplemented) {
790 obj_result = x;
791 goto exit_inplace_result_object;
792 }
793
794 Py_DECREF_IMMORTAL(x);
795 }
796
797#if PYTHON_VERSION < 0x300
798 if (!NEW_STYLE_NUMBER_TYPE(type1) || !1) {
799 coercion c1 =
800 (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_coerce : NULL;
801
802 if (c1 != NULL) {
803 PyObject *coerced1 = *operand1;
804 PyObject *coerced2 = operand2;
805
806 int err = c1(&coerced1, &coerced2);
807
808 if (unlikely(err < 0)) {
809 goto exit_inplace_exception;
810 }
811
812 if (err == 0) {
813 PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number;
814
815 if (likely(mv == NULL)) {
816 binaryfunc slot = mv->nb_add;
817
818 if (likely(slot != NULL)) {
819 PyObject *x = slot(coerced1, coerced2);
820
821 Py_DECREF(coerced1);
822 Py_DECREF(coerced2);
823
824 obj_result = x;
825 goto exit_inplace_result_object;
826 }
827 }
828
829 // nb_coerce took a reference.
830 Py_DECREF(coerced1);
831 Py_DECREF(coerced2);
832 }
833 }
834 coercion c2 = PyLong_Type.tp_as_number->nb_coerce;
835
836 if (c2 != NULL) {
837 PyObject *coerced1 = *operand1;
838 PyObject *coerced2 = operand2;
839
840 int err = c2(&coerced2, &coerced1);
841
842 if (unlikely(err < 0)) {
843 goto exit_inplace_exception;
844 }
845
846 if (err == 0) {
847 PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number;
848
849 if (likely(mv == NULL)) {
850 binaryfunc slot = mv->nb_add;
851
852 if (likely(slot != NULL)) {
853 PyObject *x = slot(coerced1, coerced2);
854
855 Py_DECREF(coerced1);
856 Py_DECREF(coerced2);
857
858 obj_result = x;
859 goto exit_inplace_result_object;
860 }
861 }
862
863 // nb_coerce took a reference.
864 Py_DECREF(coerced1);
865 Py_DECREF(coerced2);
866 }
867 }
868 }
869#endif
870
871 {
872 // Special case for "+" and "*", also works as sequence concat/repeat.
873 binaryfunc sq_slot = type1->tp_as_sequence != NULL ? type1->tp_as_sequence->sq_inplace_concat : NULL;
874 if (sq_slot == NULL) {
875 sq_slot = type1->tp_as_sequence != NULL ? type1->tp_as_sequence->sq_concat : NULL;
876 }
877
878 if (sq_slot != NULL) {
879 PyObject *result = sq_slot(*operand1, operand2);
880
881 obj_result = result;
882 goto exit_inplace_result_object;
883 }
884 }
885
886#if PYTHON_VERSION < 0x300
887 PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for +=: '%s' and 'long'", type1->tp_name);
888#else
889 PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for +=: '%s' and 'int'", type1->tp_name);
890#endif
891 goto exit_inplace_exception;
892 }
893
894exit_inplace_result_object:
895 if (unlikely(obj_result == NULL)) {
896 return false;
897 }
898
899 // We got an object handed, that we have to release.
900 Py_DECREF(*operand1);
901
902 // That's our return value then. As we use a dedicated variable, it's
903 // OK that way.
904 *operand1 = obj_result;
905
906 return true;
907
908exit_inplace_exception:
909 return false;
910}
911static inline bool _INPLACE_OPERATION_ADD_OBJECT_LONG(PyObject **operand1, PyObject *operand2) {
912 assert(operand1); // Pointer must be non-null.
913
914 CHECK_OBJECT(*operand1);
915 CHECK_OBJECT(operand2);
916 assert(PyLong_CheckExact(operand2));
917
918 PyTypeObject *type1 = Py_TYPE(*operand1);
919
920 if (type1 == &PyLong_Type) {
921 // return _BINARY_OPERATION_ADD_LONG_LONG_INPLACE(operand1, operand2);
922
923 // Not every code path will make use of all possible results.
924#if defined(_MSC_VER)
925#pragma warning(push)
926#pragma warning(disable : 4101)
927#endif
928 NUITKA_MAY_BE_UNUSED PyObject *obj_result;
929 NUITKA_MAY_BE_UNUSED long clong_result;
930#if defined(_MSC_VER)
931#pragma warning(pop)
932#endif
933
934 PyLongObject *operand1_long_object = (PyLongObject *)*operand1;
935
936 PyLongObject *operand2_long_object = (PyLongObject *)operand2;
937
938 if (Nuitka_LongGetDigitSize(operand1_long_object) <= 1 && Nuitka_LongGetDigitSize(operand2_long_object) <= 1) {
939 long r = (long)(MEDIUM_VALUE(operand1_long_object) + MEDIUM_VALUE(operand2_long_object));
940
941 if (Py_REFCNT(*operand1) == 1) {
942 Nuitka_LongUpdateFromCLong(&*operand1, (long)r);
943 goto exit_result_ok;
944 } else {
945 PyObject *obj = Nuitka_LongFromCLong(r);
946
947 obj_result = obj;
948 goto exit_result_object;
949 }
950 clong_result = r;
951 goto exit_result_ok_clong;
952 }
953
954 if (Py_REFCNT(*operand1) == 1) {
955 digit const *b_digits = Nuitka_LongGetDigitPointer(operand2_long_object);
956 Py_ssize_t b_digit_count = Nuitka_LongGetDigitSize(operand2_long_object);
957
958 bool a_negative = Nuitka_LongIsNegative(operand1_long_object);
959 bool b_negative = Nuitka_LongIsNegative(operand2_long_object);
960
961 if (a_negative) {
962 if (b_negative) {
963 *operand1 = _Nuitka_LongAddInplaceDigits(*operand1, b_digits, b_digit_count);
964 Nuitka_LongSetSignNegative(*operand1);
965 } else {
966 *operand1 = _Nuitka_LongSubInplaceDigits(*operand1, b_digits, b_digit_count, -1);
967 }
968 } else {
969 if (b_negative) {
970 *operand1 = _Nuitka_LongSubInplaceDigits(*operand1, b_digits, b_digit_count, 1);
971 } else {
972 *operand1 = _Nuitka_LongAddInplaceDigits(*operand1, b_digits, b_digit_count);
973 }
974 }
975
976 goto exit_result_ok;
977 }
978 {
979 PyLongObject *z;
980
981 digit const *a_digits = Nuitka_LongGetDigitPointer(operand1_long_object);
982 Py_ssize_t a_digit_count = Nuitka_LongGetDigitSize(operand1_long_object);
983 bool a_negative = Nuitka_LongIsNegative(operand1_long_object);
984 digit const *b_digits = Nuitka_LongGetDigitPointer(operand2_long_object);
985 Py_ssize_t b_digit_count = Nuitka_LongGetDigitSize(operand2_long_object);
986 bool b_negative = Nuitka_LongIsNegative(operand2_long_object);
987
988 if (a_negative) {
989 if (b_negative) {
990 z = _Nuitka_LongAddDigits(a_digits, a_digit_count, b_digits, b_digit_count);
991 Nuitka_LongFlipSign(z);
992 } else {
993 z = _Nuitka_LongSubDigits(b_digits, b_digit_count, a_digits, a_digit_count);
994 }
995 } else {
996 if (b_negative) {
997 z = _Nuitka_LongSubDigits(a_digits, a_digit_count, b_digits, b_digit_count);
998 } else {
999 z = _Nuitka_LongAddDigits(a_digits, a_digit_count, b_digits, b_digit_count);
1000 }
1001 }
1002
1003 obj_result = (PyObject *)z;
1004 goto exit_result_object;
1005 }
1006
1007 exit_result_object:
1008 if (unlikely(obj_result == NULL)) {
1009 goto exit_result_exception;
1010 }
1011 // We got an object handed, that we have to release.
1012 Py_DECREF(*operand1);
1013 *operand1 = obj_result;
1014 goto exit_result_ok;
1015
1016 exit_result_ok_clong:
1017
1018 // We got an object handed, that we have to release.
1019 Py_DECREF(*operand1);
1020
1021 // That's our return value then. As we use a dedicated variable, it's
1022 // OK that way.
1023 *operand1 = Nuitka_PyLong_FromLong(clong_result);
1024 goto exit_result_ok;
1025
1026 exit_result_ok:
1027 return true;
1028
1029 exit_result_exception:
1030 return false;
1031 }
1032
1033 return __INPLACE_OPERATION_ADD_OBJECT_LONG(operand1, operand2);
1034}
1035
1036bool INPLACE_OPERATION_ADD_OBJECT_LONG(PyObject **operand1, PyObject *operand2) {
1037 return _INPLACE_OPERATION_ADD_OBJECT_LONG(operand1, operand2);
1038}
1039
1040/* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "OBJECT" to any Python object. */
1041static HEDLEY_NEVER_INLINE bool __INPLACE_OPERATION_ADD_LONG_OBJECT(PyObject **operand1, PyObject *operand2) {
1042 PyTypeObject *type2 = Py_TYPE(operand2);
1043
1044#if defined(_MSC_VER)
1045#pragma warning(push)
1046#pragma warning(disable : 4101)
1047#endif
1048 NUITKA_MAY_BE_UNUSED bool cbool_result;
1049 NUITKA_MAY_BE_UNUSED PyObject *obj_result;
1050#if defined(_MSC_VER)
1051#pragma warning(pop)
1052#endif
1053
1054 // No inplace number slot nb_inplace_add available for this type.
1055
1056 {
1057 binaryfunc slot1 = PyLong_Type.tp_as_number->nb_add;
1058 binaryfunc slot2 = NULL;
1059
1060 if (!(&PyLong_Type == type2)) {
1061 // Different types, need to consider second value slot.
1062
1063 slot2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_add : NULL;
1064
1065 if (slot1 == slot2) {
1066 slot2 = NULL;
1067 }
1068 }
1069
1070 if (slot1 != NULL) {
1071 if (slot2 != NULL) {
1072 if (Nuitka_Type_IsSubtype(type2, &PyLong_Type)) {
1073 PyObject *x = slot2(*operand1, operand2);
1074
1075 if (x != Py_NotImplemented) {
1076 obj_result = x;
1077 goto exit_inplace_result_object;
1078 }
1079
1080 Py_DECREF_IMMORTAL(x);
1081 slot2 = NULL;
1082 }
1083 }
1084
1085 PyObject *x = slot1(*operand1, operand2);
1086
1087 if (x != Py_NotImplemented) {
1088 obj_result = x;
1089 goto exit_inplace_result_object;
1090 }
1091
1092 Py_DECREF_IMMORTAL(x);
1093 }
1094
1095 if (slot2 != NULL) {
1096 PyObject *x = slot2(*operand1, operand2);
1097
1098 if (x != Py_NotImplemented) {
1099 obj_result = x;
1100 goto exit_inplace_result_object;
1101 }
1102
1103 Py_DECREF_IMMORTAL(x);
1104 }
1105
1106#if PYTHON_VERSION < 0x300
1107 if (!1 || !NEW_STYLE_NUMBER_TYPE(type2)) {
1108 coercion c1 = PyLong_Type.tp_as_number->nb_coerce;
1109
1110 if (c1 != NULL) {
1111 PyObject *coerced1 = *operand1;
1112 PyObject *coerced2 = operand2;
1113
1114 int err = c1(&coerced1, &coerced2);
1115
1116 if (unlikely(err < 0)) {
1117 goto exit_inplace_exception;
1118 }
1119
1120 if (err == 0) {
1121 PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number;
1122
1123 if (likely(mv == NULL)) {
1124 binaryfunc slot = mv->nb_add;
1125
1126 if (likely(slot != NULL)) {
1127 PyObject *x = slot(coerced1, coerced2);
1128
1129 Py_DECREF(coerced1);
1130 Py_DECREF(coerced2);
1131
1132 obj_result = x;
1133 goto exit_inplace_result_object;
1134 }
1135 }
1136
1137 // nb_coerce took a reference.
1138 Py_DECREF(coerced1);
1139 Py_DECREF(coerced2);
1140 }
1141 }
1142 coercion c2 =
1143 (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_coerce : NULL;
1144
1145 if (c2 != NULL) {
1146 PyObject *coerced1 = *operand1;
1147 PyObject *coerced2 = operand2;
1148
1149 int err = c2(&coerced2, &coerced1);
1150
1151 if (unlikely(err < 0)) {
1152 goto exit_inplace_exception;
1153 }
1154
1155 if (err == 0) {
1156 PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number;
1157
1158 if (likely(mv == NULL)) {
1159 binaryfunc slot = mv->nb_add;
1160
1161 if (likely(slot != NULL)) {
1162 PyObject *x = slot(coerced1, coerced2);
1163
1164 Py_DECREF(coerced1);
1165 Py_DECREF(coerced2);
1166
1167 obj_result = x;
1168 goto exit_inplace_result_object;
1169 }
1170 }
1171
1172 // nb_coerce took a reference.
1173 Py_DECREF(coerced1);
1174 Py_DECREF(coerced2);
1175 }
1176 }
1177 }
1178#endif
1179
1180 {
1181 // No sequence repeat slot sq_concat available for this type.
1182 // No inplace sequence repeat slot sq_inplace_concat available for this type.
1183 }
1184
1185#if PYTHON_VERSION < 0x300
1186 PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for +=: 'long' and '%s'", type2->tp_name);
1187#else
1188 PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for +=: 'int' and '%s'", type2->tp_name);
1189#endif
1190 goto exit_inplace_exception;
1191 }
1192
1193exit_inplace_result_object:
1194 if (unlikely(obj_result == NULL)) {
1195 return false;
1196 }
1197
1198 // We got an object handed, that we have to release.
1199 Py_DECREF(*operand1);
1200
1201 // That's our return value then. As we use a dedicated variable, it's
1202 // OK that way.
1203 *operand1 = obj_result;
1204
1205 return true;
1206
1207exit_inplace_exception:
1208 return false;
1209}
1210static inline bool _INPLACE_OPERATION_ADD_LONG_OBJECT(PyObject **operand1, PyObject *operand2) {
1211 assert(operand1); // Pointer must be non-null.
1212
1213 CHECK_OBJECT(*operand1);
1214 assert(PyLong_CheckExact(*operand1));
1215 CHECK_OBJECT(operand2);
1216
1217 PyTypeObject *type2 = Py_TYPE(operand2);
1218
1219 if (&PyLong_Type == type2) {
1220 // return _BINARY_OPERATION_ADD_LONG_LONG_INPLACE(operand1, operand2);
1221
1222 // Not every code path will make use of all possible results.
1223#if defined(_MSC_VER)
1224#pragma warning(push)
1225#pragma warning(disable : 4101)
1226#endif
1227 NUITKA_MAY_BE_UNUSED PyObject *obj_result;
1228 NUITKA_MAY_BE_UNUSED long clong_result;
1229#if defined(_MSC_VER)
1230#pragma warning(pop)
1231#endif
1232
1233 PyLongObject *operand1_long_object = (PyLongObject *)*operand1;
1234
1235 PyLongObject *operand2_long_object = (PyLongObject *)operand2;
1236
1237 if (Nuitka_LongGetDigitSize(operand1_long_object) <= 1 && Nuitka_LongGetDigitSize(operand2_long_object) <= 1) {
1238 long r = (long)(MEDIUM_VALUE(operand1_long_object) + MEDIUM_VALUE(operand2_long_object));
1239
1240 if (Py_REFCNT(*operand1) == 1) {
1241 Nuitka_LongUpdateFromCLong(&*operand1, (long)r);
1242 goto exit_result_ok;
1243 } else {
1244 PyObject *obj = Nuitka_LongFromCLong(r);
1245
1246 obj_result = obj;
1247 goto exit_result_object;
1248 }
1249 clong_result = r;
1250 goto exit_result_ok_clong;
1251 }
1252
1253 if (Py_REFCNT(*operand1) == 1) {
1254 digit const *b_digits = Nuitka_LongGetDigitPointer(operand2_long_object);
1255 Py_ssize_t b_digit_count = Nuitka_LongGetDigitSize(operand2_long_object);
1256
1257 bool a_negative = Nuitka_LongIsNegative(operand1_long_object);
1258 bool b_negative = Nuitka_LongIsNegative(operand2_long_object);
1259
1260 if (a_negative) {
1261 if (b_negative) {
1262 *operand1 = _Nuitka_LongAddInplaceDigits(*operand1, b_digits, b_digit_count);
1263 Nuitka_LongSetSignNegative(*operand1);
1264 } else {
1265 *operand1 = _Nuitka_LongSubInplaceDigits(*operand1, b_digits, b_digit_count, -1);
1266 }
1267 } else {
1268 if (b_negative) {
1269 *operand1 = _Nuitka_LongSubInplaceDigits(*operand1, b_digits, b_digit_count, 1);
1270 } else {
1271 *operand1 = _Nuitka_LongAddInplaceDigits(*operand1, b_digits, b_digit_count);
1272 }
1273 }
1274
1275 goto exit_result_ok;
1276 }
1277 {
1278 PyLongObject *z;
1279
1280 digit const *a_digits = Nuitka_LongGetDigitPointer(operand1_long_object);
1281 Py_ssize_t a_digit_count = Nuitka_LongGetDigitSize(operand1_long_object);
1282 bool a_negative = Nuitka_LongIsNegative(operand1_long_object);
1283 digit const *b_digits = Nuitka_LongGetDigitPointer(operand2_long_object);
1284 Py_ssize_t b_digit_count = Nuitka_LongGetDigitSize(operand2_long_object);
1285 bool b_negative = Nuitka_LongIsNegative(operand2_long_object);
1286
1287 if (a_negative) {
1288 if (b_negative) {
1289 z = _Nuitka_LongAddDigits(a_digits, a_digit_count, b_digits, b_digit_count);
1290 Nuitka_LongFlipSign(z);
1291 } else {
1292 z = _Nuitka_LongSubDigits(b_digits, b_digit_count, a_digits, a_digit_count);
1293 }
1294 } else {
1295 if (b_negative) {
1296 z = _Nuitka_LongSubDigits(a_digits, a_digit_count, b_digits, b_digit_count);
1297 } else {
1298 z = _Nuitka_LongAddDigits(a_digits, a_digit_count, b_digits, b_digit_count);
1299 }
1300 }
1301
1302 obj_result = (PyObject *)z;
1303 goto exit_result_object;
1304 }
1305
1306 exit_result_object:
1307 if (unlikely(obj_result == NULL)) {
1308 goto exit_result_exception;
1309 }
1310 // We got an object handed, that we have to release.
1311 Py_DECREF(*operand1);
1312 *operand1 = obj_result;
1313 goto exit_result_ok;
1314
1315 exit_result_ok_clong:
1316
1317 // We got an object handed, that we have to release.
1318 Py_DECREF(*operand1);
1319
1320 // That's our return value then. As we use a dedicated variable, it's
1321 // OK that way.
1322 *operand1 = Nuitka_PyLong_FromLong(clong_result);
1323 goto exit_result_ok;
1324
1325 exit_result_ok:
1326 return true;
1327
1328 exit_result_exception:
1329 return false;
1330 }
1331
1332 return __INPLACE_OPERATION_ADD_LONG_OBJECT(operand1, operand2);
1333}
1334
1335bool INPLACE_OPERATION_ADD_LONG_OBJECT(PyObject **operand1, PyObject *operand2) {
1336 return _INPLACE_OPERATION_ADD_LONG_OBJECT(operand1, operand2);
1337}
1338
1339/* Code referring to "FLOAT" corresponds to Python 'float' and "FLOAT" to Python 'float'. */
1340static inline bool _INPLACE_OPERATION_ADD_FLOAT_FLOAT(PyObject **operand1, PyObject *operand2) {
1341 assert(operand1); // Pointer must be non-null.
1342
1343 CHECK_OBJECT(*operand1);
1344 assert(PyFloat_CheckExact(*operand1));
1345 CHECK_OBJECT(operand2);
1346 assert(PyFloat_CheckExact(operand2));
1347
1348#if defined(_MSC_VER)
1349#pragma warning(push)
1350#pragma warning(disable : 4101)
1351#endif
1352 // Not every code path will make use of all possible results.
1353 NUITKA_MAY_BE_UNUSED PyObject *obj_result;
1354 NUITKA_MAY_BE_UNUSED long clong_result;
1355 NUITKA_MAY_BE_UNUSED double cfloat_result;
1356#if defined(_MSC_VER)
1357#pragma warning(pop)
1358#endif
1359
1360 CHECK_OBJECT(*operand1);
1361 assert(PyFloat_CheckExact(*operand1));
1362 CHECK_OBJECT(operand2);
1363 assert(PyFloat_CheckExact(operand2));
1364
1365 const double a = PyFloat_AS_DOUBLE(*operand1);
1366 const double b = PyFloat_AS_DOUBLE(operand2);
1367
1368 double r = a + b;
1369
1370 cfloat_result = r;
1371 goto exit_result_ok_cfloat;
1372
1373exit_result_ok_cfloat:
1374 if (Py_REFCNT(*operand1) == 1) {
1375 PyFloat_SET_DOUBLE(*operand1, cfloat_result);
1376 } else {
1377 // We got an object handed, that we have to release.
1378 Py_DECREF(*operand1);
1379
1380 *operand1 = MAKE_FLOAT_FROM_DOUBLE(cfloat_result);
1381 }
1382 goto exit_result_ok;
1383
1384exit_result_ok:
1385 return true;
1386}
1387
1388bool INPLACE_OPERATION_ADD_FLOAT_FLOAT(PyObject **operand1, PyObject *operand2) {
1389 return _INPLACE_OPERATION_ADD_FLOAT_FLOAT(operand1, operand2);
1390}
1391
1392/* Code referring to "OBJECT" corresponds to any Python object and "FLOAT" to Python 'float'. */
1393static HEDLEY_NEVER_INLINE bool __INPLACE_OPERATION_ADD_OBJECT_FLOAT(PyObject **operand1, PyObject *operand2) {
1394 PyTypeObject *type1 = Py_TYPE(*operand1);
1395
1396#if defined(_MSC_VER)
1397#pragma warning(push)
1398#pragma warning(disable : 4101)
1399#endif
1400 NUITKA_MAY_BE_UNUSED bool cbool_result;
1401 NUITKA_MAY_BE_UNUSED PyObject *obj_result;
1402#if defined(_MSC_VER)
1403#pragma warning(pop)
1404#endif
1405
1406 binaryfunc islot =
1407 (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_inplace_add : NULL;
1408
1409 if (islot != NULL) {
1410 PyObject *x = islot(*operand1, operand2);
1411
1412 if (x != Py_NotImplemented) {
1413 obj_result = x;
1414 goto exit_inplace_result_object;
1415 }
1416
1417 Py_DECREF_IMMORTAL(x);
1418 }
1419
1420 {
1421 binaryfunc slot1 =
1422 (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_add : NULL;
1423 binaryfunc slot2 = NULL;
1424
1425 if (!(type1 == &PyFloat_Type)) {
1426 // Different types, need to consider second value slot.
1427
1428 slot2 = PyFloat_Type.tp_as_number->nb_add;
1429
1430 if (slot1 == slot2) {
1431 slot2 = NULL;
1432 }
1433 }
1434
1435 if (slot1 != NULL) {
1436 PyObject *x = slot1(*operand1, operand2);
1437
1438 if (x != Py_NotImplemented) {
1439 obj_result = x;
1440 goto exit_inplace_result_object;
1441 }
1442
1443 Py_DECREF_IMMORTAL(x);
1444 }
1445
1446 if (slot2 != NULL) {
1447 PyObject *x = slot2(*operand1, operand2);
1448
1449 if (x != Py_NotImplemented) {
1450 obj_result = x;
1451 goto exit_inplace_result_object;
1452 }
1453
1454 Py_DECREF_IMMORTAL(x);
1455 }
1456
1457#if PYTHON_VERSION < 0x300
1458 if (!NEW_STYLE_NUMBER_TYPE(type1) || !1) {
1459 coercion c1 =
1460 (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_coerce : NULL;
1461
1462 if (c1 != NULL) {
1463 PyObject *coerced1 = *operand1;
1464 PyObject *coerced2 = operand2;
1465
1466 int err = c1(&coerced1, &coerced2);
1467
1468 if (unlikely(err < 0)) {
1469 goto exit_inplace_exception;
1470 }
1471
1472 if (err == 0) {
1473 PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number;
1474
1475 if (likely(mv == NULL)) {
1476 binaryfunc slot = mv->nb_add;
1477
1478 if (likely(slot != NULL)) {
1479 PyObject *x = slot(coerced1, coerced2);
1480
1481 Py_DECREF(coerced1);
1482 Py_DECREF(coerced2);
1483
1484 obj_result = x;
1485 goto exit_inplace_result_object;
1486 }
1487 }
1488
1489 // nb_coerce took a reference.
1490 Py_DECREF(coerced1);
1491 Py_DECREF(coerced2);
1492 }
1493 }
1494 coercion c2 = PyFloat_Type.tp_as_number->nb_coerce;
1495
1496 if (c2 != NULL) {
1497 PyObject *coerced1 = *operand1;
1498 PyObject *coerced2 = operand2;
1499
1500 int err = c2(&coerced2, &coerced1);
1501
1502 if (unlikely(err < 0)) {
1503 goto exit_inplace_exception;
1504 }
1505
1506 if (err == 0) {
1507 PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number;
1508
1509 if (likely(mv == NULL)) {
1510 binaryfunc slot = mv->nb_add;
1511
1512 if (likely(slot != NULL)) {
1513 PyObject *x = slot(coerced1, coerced2);
1514
1515 Py_DECREF(coerced1);
1516 Py_DECREF(coerced2);
1517
1518 obj_result = x;
1519 goto exit_inplace_result_object;
1520 }
1521 }
1522
1523 // nb_coerce took a reference.
1524 Py_DECREF(coerced1);
1525 Py_DECREF(coerced2);
1526 }
1527 }
1528 }
1529#endif
1530
1531 {
1532 // Special case for "+" and "*", also works as sequence concat/repeat.
1533 binaryfunc sq_slot = type1->tp_as_sequence != NULL ? type1->tp_as_sequence->sq_inplace_concat : NULL;
1534 if (sq_slot == NULL) {
1535 sq_slot = type1->tp_as_sequence != NULL ? type1->tp_as_sequence->sq_concat : NULL;
1536 }
1537
1538 if (sq_slot != NULL) {
1539 PyObject *result = sq_slot(*operand1, operand2);
1540
1541 obj_result = result;
1542 goto exit_inplace_result_object;
1543 }
1544 }
1545
1546 PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for +=: '%s' and 'float'", type1->tp_name);
1547 goto exit_inplace_exception;
1548 }
1549
1550exit_inplace_result_object:
1551 if (unlikely(obj_result == NULL)) {
1552 return false;
1553 }
1554
1555 // We got an object handed, that we have to release.
1556 Py_DECREF(*operand1);
1557
1558 // That's our return value then. As we use a dedicated variable, it's
1559 // OK that way.
1560 *operand1 = obj_result;
1561
1562 return true;
1563
1564exit_inplace_exception:
1565 return false;
1566}
1567static inline bool _INPLACE_OPERATION_ADD_OBJECT_FLOAT(PyObject **operand1, PyObject *operand2) {
1568 assert(operand1); // Pointer must be non-null.
1569
1570 CHECK_OBJECT(*operand1);
1571 CHECK_OBJECT(operand2);
1572 assert(PyFloat_CheckExact(operand2));
1573
1574 PyTypeObject *type1 = Py_TYPE(*operand1);
1575
1576 if (type1 == &PyFloat_Type) {
1577 // return _BINARY_OPERATION_ADD_FLOAT_FLOAT_INPLACE(operand1, operand2);
1578
1579#if defined(_MSC_VER)
1580#pragma warning(push)
1581#pragma warning(disable : 4101)
1582#endif
1583 // Not every code path will make use of all possible results.
1584 NUITKA_MAY_BE_UNUSED PyObject *obj_result;
1585 NUITKA_MAY_BE_UNUSED long clong_result;
1586 NUITKA_MAY_BE_UNUSED double cfloat_result;
1587#if defined(_MSC_VER)
1588#pragma warning(pop)
1589#endif
1590
1591 CHECK_OBJECT(*operand1);
1592 assert(PyFloat_CheckExact(*operand1));
1593 CHECK_OBJECT(operand2);
1594 assert(PyFloat_CheckExact(operand2));
1595
1596 const double a = PyFloat_AS_DOUBLE(*operand1);
1597 const double b = PyFloat_AS_DOUBLE(operand2);
1598
1599 double r = a + b;
1600
1601 cfloat_result = r;
1602 goto exit_result_ok_cfloat;
1603
1604 exit_result_ok_cfloat:
1605 if (Py_REFCNT(*operand1) == 1) {
1606 PyFloat_SET_DOUBLE(*operand1, cfloat_result);
1607 } else {
1608 // We got an object handed, that we have to release.
1609 Py_DECREF(*operand1);
1610
1611 *operand1 = MAKE_FLOAT_FROM_DOUBLE(cfloat_result);
1612 }
1613 goto exit_result_ok;
1614
1615 exit_result_ok:
1616 return true;
1617 }
1618
1619 return __INPLACE_OPERATION_ADD_OBJECT_FLOAT(operand1, operand2);
1620}
1621
1622bool INPLACE_OPERATION_ADD_OBJECT_FLOAT(PyObject **operand1, PyObject *operand2) {
1623 return _INPLACE_OPERATION_ADD_OBJECT_FLOAT(operand1, operand2);
1624}
1625
1626/* Code referring to "FLOAT" corresponds to Python 'float' and "OBJECT" to any Python object. */
1627static HEDLEY_NEVER_INLINE bool __INPLACE_OPERATION_ADD_FLOAT_OBJECT(PyObject **operand1, PyObject *operand2) {
1628 PyTypeObject *type2 = Py_TYPE(operand2);
1629
1630#if defined(_MSC_VER)
1631#pragma warning(push)
1632#pragma warning(disable : 4101)
1633#endif
1634 NUITKA_MAY_BE_UNUSED bool cbool_result;
1635 NUITKA_MAY_BE_UNUSED PyObject *obj_result;
1636#if defined(_MSC_VER)
1637#pragma warning(pop)
1638#endif
1639
1640 // No inplace number slot nb_inplace_add available for this type.
1641
1642 {
1643 binaryfunc slot1 = PyFloat_Type.tp_as_number->nb_add;
1644 binaryfunc slot2 = NULL;
1645
1646 if (!(&PyFloat_Type == type2)) {
1647 // Different types, need to consider second value slot.
1648
1649 slot2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_add : NULL;
1650
1651 if (slot1 == slot2) {
1652 slot2 = NULL;
1653 }
1654 }
1655
1656 if (slot1 != NULL) {
1657 if (slot2 != NULL) {
1658 if (Nuitka_Type_IsSubtype(type2, &PyFloat_Type)) {
1659 PyObject *x = slot2(*operand1, operand2);
1660
1661 if (x != Py_NotImplemented) {
1662 obj_result = x;
1663 goto exit_inplace_result_object;
1664 }
1665
1666 Py_DECREF_IMMORTAL(x);
1667 slot2 = NULL;
1668 }
1669 }
1670
1671 PyObject *x = slot1(*operand1, operand2);
1672
1673 if (x != Py_NotImplemented) {
1674 obj_result = x;
1675 goto exit_inplace_result_object;
1676 }
1677
1678 Py_DECREF_IMMORTAL(x);
1679 }
1680
1681 if (slot2 != NULL) {
1682 PyObject *x = slot2(*operand1, operand2);
1683
1684 if (x != Py_NotImplemented) {
1685 obj_result = x;
1686 goto exit_inplace_result_object;
1687 }
1688
1689 Py_DECREF_IMMORTAL(x);
1690 }
1691
1692#if PYTHON_VERSION < 0x300
1693 if (!1 || !NEW_STYLE_NUMBER_TYPE(type2)) {
1694 coercion c1 = PyFloat_Type.tp_as_number->nb_coerce;
1695
1696 if (c1 != NULL) {
1697 PyObject *coerced1 = *operand1;
1698 PyObject *coerced2 = operand2;
1699
1700 int err = c1(&coerced1, &coerced2);
1701
1702 if (unlikely(err < 0)) {
1703 goto exit_inplace_exception;
1704 }
1705
1706 if (err == 0) {
1707 PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number;
1708
1709 if (likely(mv == NULL)) {
1710 binaryfunc slot = mv->nb_add;
1711
1712 if (likely(slot != NULL)) {
1713 PyObject *x = slot(coerced1, coerced2);
1714
1715 Py_DECREF(coerced1);
1716 Py_DECREF(coerced2);
1717
1718 obj_result = x;
1719 goto exit_inplace_result_object;
1720 }
1721 }
1722
1723 // nb_coerce took a reference.
1724 Py_DECREF(coerced1);
1725 Py_DECREF(coerced2);
1726 }
1727 }
1728 coercion c2 =
1729 (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_coerce : NULL;
1730
1731 if (c2 != NULL) {
1732 PyObject *coerced1 = *operand1;
1733 PyObject *coerced2 = operand2;
1734
1735 int err = c2(&coerced2, &coerced1);
1736
1737 if (unlikely(err < 0)) {
1738 goto exit_inplace_exception;
1739 }
1740
1741 if (err == 0) {
1742 PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number;
1743
1744 if (likely(mv == NULL)) {
1745 binaryfunc slot = mv->nb_add;
1746
1747 if (likely(slot != NULL)) {
1748 PyObject *x = slot(coerced1, coerced2);
1749
1750 Py_DECREF(coerced1);
1751 Py_DECREF(coerced2);
1752
1753 obj_result = x;
1754 goto exit_inplace_result_object;
1755 }
1756 }
1757
1758 // nb_coerce took a reference.
1759 Py_DECREF(coerced1);
1760 Py_DECREF(coerced2);
1761 }
1762 }
1763 }
1764#endif
1765
1766 {
1767 // No sequence repeat slot sq_concat available for this type.
1768 // No inplace sequence repeat slot sq_inplace_concat available for this type.
1769 }
1770
1771 PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for +=: 'float' and '%s'", type2->tp_name);
1772 goto exit_inplace_exception;
1773 }
1774
1775exit_inplace_result_object:
1776 if (unlikely(obj_result == NULL)) {
1777 return false;
1778 }
1779
1780 // We got an object handed, that we have to release.
1781 Py_DECREF(*operand1);
1782
1783 // That's our return value then. As we use a dedicated variable, it's
1784 // OK that way.
1785 *operand1 = obj_result;
1786
1787 return true;
1788
1789exit_inplace_exception:
1790 return false;
1791}
1792static inline bool _INPLACE_OPERATION_ADD_FLOAT_OBJECT(PyObject **operand1, PyObject *operand2) {
1793 assert(operand1); // Pointer must be non-null.
1794
1795 CHECK_OBJECT(*operand1);
1796 assert(PyFloat_CheckExact(*operand1));
1797 CHECK_OBJECT(operand2);
1798
1799 PyTypeObject *type2 = Py_TYPE(operand2);
1800
1801 if (&PyFloat_Type == type2) {
1802 // return _BINARY_OPERATION_ADD_FLOAT_FLOAT_INPLACE(operand1, operand2);
1803
1804#if defined(_MSC_VER)
1805#pragma warning(push)
1806#pragma warning(disable : 4101)
1807#endif
1808 // Not every code path will make use of all possible results.
1809 NUITKA_MAY_BE_UNUSED PyObject *obj_result;
1810 NUITKA_MAY_BE_UNUSED long clong_result;
1811 NUITKA_MAY_BE_UNUSED double cfloat_result;
1812#if defined(_MSC_VER)
1813#pragma warning(pop)
1814#endif
1815
1816 CHECK_OBJECT(*operand1);
1817 assert(PyFloat_CheckExact(*operand1));
1818 CHECK_OBJECT(operand2);
1819 assert(PyFloat_CheckExact(operand2));
1820
1821 const double a = PyFloat_AS_DOUBLE(*operand1);
1822 const double b = PyFloat_AS_DOUBLE(operand2);
1823
1824 double r = a + b;
1825
1826 cfloat_result = r;
1827 goto exit_result_ok_cfloat;
1828
1829 exit_result_ok_cfloat:
1830 if (Py_REFCNT(*operand1) == 1) {
1831 PyFloat_SET_DOUBLE(*operand1, cfloat_result);
1832 } else {
1833 // We got an object handed, that we have to release.
1834 Py_DECREF(*operand1);
1835
1836 *operand1 = MAKE_FLOAT_FROM_DOUBLE(cfloat_result);
1837 }
1838 goto exit_result_ok;
1839
1840 exit_result_ok:
1841 return true;
1842 }
1843
1844 return __INPLACE_OPERATION_ADD_FLOAT_OBJECT(operand1, operand2);
1845}
1846
1847bool INPLACE_OPERATION_ADD_FLOAT_OBJECT(PyObject **operand1, PyObject *operand2) {
1848 return _INPLACE_OPERATION_ADD_FLOAT_OBJECT(operand1, operand2);
1849}
1850
1851/* Code referring to "FLOAT" corresponds to Python 'float' and "LONG" to Python2 'long', Python3 'int'. */
1852static inline bool _INPLACE_OPERATION_ADD_FLOAT_LONG(PyObject **operand1, PyObject *operand2) {
1853 assert(operand1); // Pointer must be non-null.
1854
1855 CHECK_OBJECT(*operand1);
1856 assert(PyFloat_CheckExact(*operand1));
1857 CHECK_OBJECT(operand2);
1858 assert(PyLong_CheckExact(operand2));
1859
1860#if defined(_MSC_VER)
1861#pragma warning(push)
1862#pragma warning(disable : 4101)
1863#endif
1864 NUITKA_MAY_BE_UNUSED bool cbool_result;
1865 NUITKA_MAY_BE_UNUSED PyObject *obj_result;
1866#if defined(_MSC_VER)
1867#pragma warning(pop)
1868#endif
1869
1870 // No inplace number slot nb_inplace_add available for this type.
1871
1872 {
1873 binaryfunc slot1 = PyFloat_Type.tp_as_number->nb_add;
1874 // Slot2 ignored on purpose, type1 takes precedence.
1875
1876 if (slot1 != NULL) {
1877 PyObject *x = slot1(*operand1, operand2);
1878
1879 if (x != Py_NotImplemented) {
1880 obj_result = x;
1881 goto exit_inplace_result_object;
1882 }
1883
1884 Py_DECREF_IMMORTAL(x);
1885 }
1886
1887 // Statically recognized that coercion is not possible with these types
1888
1889 {
1890 // No sequence repeat slot sq_concat available for this type.
1891 // No inplace sequence repeat slot sq_inplace_concat available for this type.
1892 }
1893
1894#if PYTHON_VERSION < 0x300
1895 PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for +=: 'float' and 'long'");
1896#else
1897 PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for +=: 'float' and 'int'");
1898#endif
1899 goto exit_inplace_exception;
1900 }
1901
1902exit_inplace_result_object:
1903 if (unlikely(obj_result == NULL)) {
1904 return false;
1905 }
1906
1907 // We got an object handed, that we have to release.
1908 Py_DECREF(*operand1);
1909
1910 // That's our return value then. As we use a dedicated variable, it's
1911 // OK that way.
1912 *operand1 = obj_result;
1913
1914 return true;
1915
1916exit_inplace_exception:
1917 return false;
1918}
1919
1920bool INPLACE_OPERATION_ADD_FLOAT_LONG(PyObject **operand1, PyObject *operand2) {
1921 return _INPLACE_OPERATION_ADD_FLOAT_LONG(operand1, operand2);
1922}
1923
1924/* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "FLOAT" to Python 'float'. */
1925static inline bool _INPLACE_OPERATION_ADD_LONG_FLOAT(PyObject **operand1, PyObject *operand2) {
1926 assert(operand1); // Pointer must be non-null.
1927
1928 CHECK_OBJECT(*operand1);
1929 assert(PyLong_CheckExact(*operand1));
1930 CHECK_OBJECT(operand2);
1931 assert(PyFloat_CheckExact(operand2));
1932
1933#if defined(_MSC_VER)
1934#pragma warning(push)
1935#pragma warning(disable : 4101)
1936#endif
1937 NUITKA_MAY_BE_UNUSED bool cbool_result;
1938 NUITKA_MAY_BE_UNUSED PyObject *obj_result;
1939#if defined(_MSC_VER)
1940#pragma warning(pop)
1941#endif
1942
1943 // No inplace number slot nb_inplace_add available for this type.
1944
1945 {
1946 // Slot1 ignored on purpose, type2 takes precedence.
1947 binaryfunc slot2 = NULL;
1948
1949 if (!(0)) {
1950 // Different types, need to consider second value slot.
1951
1952 slot2 = PyFloat_Type.tp_as_number->nb_add;
1953 }
1954
1955 if (slot2 != NULL) {
1956 PyObject *x = slot2(*operand1, operand2);
1957
1958 if (x != Py_NotImplemented) {
1959 obj_result = x;
1960 goto exit_inplace_result_object;
1961 }
1962
1963 Py_DECREF_IMMORTAL(x);
1964 }
1965
1966 // Statically recognized that coercion is not possible with these types
1967
1968 {
1969 // No sequence repeat slot sq_concat available for this type.
1970 // No inplace sequence repeat slot sq_inplace_concat available for this type.
1971 }
1972
1973#if PYTHON_VERSION < 0x300
1974 PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for +=: 'long' and 'float'");
1975#else
1976 PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for +=: 'int' and 'float'");
1977#endif
1978 goto exit_inplace_exception;
1979 }
1980
1981exit_inplace_result_object:
1982 if (unlikely(obj_result == NULL)) {
1983 return false;
1984 }
1985
1986 // We got an object handed, that we have to release.
1987 Py_DECREF(*operand1);
1988
1989 // That's our return value then. As we use a dedicated variable, it's
1990 // OK that way.
1991 *operand1 = obj_result;
1992
1993 return true;
1994
1995exit_inplace_exception:
1996 return false;
1997}
1998
1999bool INPLACE_OPERATION_ADD_LONG_FLOAT(PyObject **operand1, PyObject *operand2) {
2000 return _INPLACE_OPERATION_ADD_LONG_FLOAT(operand1, operand2);
2001}
2002
2003#if PYTHON_VERSION < 0x300
2004/* Code referring to "FLOAT" corresponds to Python 'float' and "INT" to Python2 'int'. */
2005static inline bool _INPLACE_OPERATION_ADD_FLOAT_INT(PyObject **operand1, PyObject *operand2) {
2006 assert(operand1); // Pointer must be non-null.
2007
2008 CHECK_OBJECT(*operand1);
2009 assert(PyFloat_CheckExact(*operand1));
2010 CHECK_OBJECT(operand2);
2011 assert(PyInt_CheckExact(operand2));
2012
2013#if defined(_MSC_VER)
2014#pragma warning(push)
2015#pragma warning(disable : 4101)
2016#endif
2017 NUITKA_MAY_BE_UNUSED bool cbool_result;
2018 NUITKA_MAY_BE_UNUSED PyObject *obj_result;
2019#if defined(_MSC_VER)
2020#pragma warning(pop)
2021#endif
2022
2023 // No inplace number slot nb_inplace_add available for this type.
2024
2025 {
2026 binaryfunc slot1 = PyFloat_Type.tp_as_number->nb_add;
2027 // Slot2 ignored on purpose, type1 takes precedence.
2028
2029 if (slot1 != NULL) {
2030 PyObject *x = slot1(*operand1, operand2);
2031
2032 if (x != Py_NotImplemented) {
2033 obj_result = x;
2034 goto exit_inplace_result_object;
2035 }
2036
2037 Py_DECREF_IMMORTAL(x);
2038 }
2039
2040 // Statically recognized that coercion is not possible with these types
2041
2042 {
2043 // No sequence repeat slot sq_concat available for this type.
2044 // No inplace sequence repeat slot sq_inplace_concat available for this type.
2045 }
2046
2047 PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for +=: 'float' and 'int'");
2048 goto exit_inplace_exception;
2049 }
2050
2051exit_inplace_result_object:
2052 if (unlikely(obj_result == NULL)) {
2053 return false;
2054 }
2055
2056 // We got an object handed, that we have to release.
2057 Py_DECREF(*operand1);
2058
2059 // That's our return value then. As we use a dedicated variable, it's
2060 // OK that way.
2061 *operand1 = obj_result;
2062
2063 return true;
2064
2065exit_inplace_exception:
2066 return false;
2067}
2068
2069bool INPLACE_OPERATION_ADD_FLOAT_INT(PyObject **operand1, PyObject *operand2) {
2070 return _INPLACE_OPERATION_ADD_FLOAT_INT(operand1, operand2);
2071}
2072#endif
2073
2074#if PYTHON_VERSION < 0x300
2075/* Code referring to "INT" corresponds to Python2 'int' and "FLOAT" to Python 'float'. */
2076static inline bool _INPLACE_OPERATION_ADD_INT_FLOAT(PyObject **operand1, PyObject *operand2) {
2077 assert(operand1); // Pointer must be non-null.
2078
2079 CHECK_OBJECT(*operand1);
2080 assert(PyInt_CheckExact(*operand1));
2081 CHECK_OBJECT(operand2);
2082 assert(PyFloat_CheckExact(operand2));
2083
2084#if defined(_MSC_VER)
2085#pragma warning(push)
2086#pragma warning(disable : 4101)
2087#endif
2088 NUITKA_MAY_BE_UNUSED bool cbool_result;
2089 NUITKA_MAY_BE_UNUSED PyObject *obj_result;
2090#if defined(_MSC_VER)
2091#pragma warning(pop)
2092#endif
2093
2094 // No inplace number slot nb_inplace_add available for this type.
2095
2096 {
2097 // Slot1 ignored on purpose, type2 takes precedence.
2098 binaryfunc slot2 = NULL;
2099
2100 if (!(0)) {
2101 // Different types, need to consider second value slot.
2102
2103 slot2 = PyFloat_Type.tp_as_number->nb_add;
2104 }
2105
2106 if (slot2 != NULL) {
2107 PyObject *x = slot2(*operand1, operand2);
2108
2109 if (x != Py_NotImplemented) {
2110 obj_result = x;
2111 goto exit_inplace_result_object;
2112 }
2113
2114 Py_DECREF_IMMORTAL(x);
2115 }
2116
2117 // Statically recognized that coercion is not possible with these types
2118
2119 {
2120 // No sequence repeat slot sq_concat available for this type.
2121 // No inplace sequence repeat slot sq_inplace_concat available for this type.
2122 }
2123
2124 PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for +=: 'int' and 'float'");
2125 goto exit_inplace_exception;
2126 }
2127
2128exit_inplace_result_object:
2129 if (unlikely(obj_result == NULL)) {
2130 return false;
2131 }
2132
2133 // We got an object handed, that we have to release.
2134 Py_DECREF(*operand1);
2135
2136 // That's our return value then. As we use a dedicated variable, it's
2137 // OK that way.
2138 *operand1 = obj_result;
2139
2140 return true;
2141
2142exit_inplace_exception:
2143 return false;
2144}
2145
2146bool INPLACE_OPERATION_ADD_INT_FLOAT(PyObject **operand1, PyObject *operand2) {
2147 return _INPLACE_OPERATION_ADD_INT_FLOAT(operand1, operand2);
2148}
2149#endif
2150
2151#if PYTHON_VERSION < 0x300
2152/* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "INT" to Python2 'int'. */
2153static inline bool _INPLACE_OPERATION_ADD_LONG_INT(PyObject **operand1, PyObject *operand2) {
2154 assert(operand1); // Pointer must be non-null.
2155
2156 CHECK_OBJECT(*operand1);
2157 assert(PyLong_CheckExact(*operand1));
2158 CHECK_OBJECT(operand2);
2159 assert(PyInt_CheckExact(operand2));
2160
2161#if defined(_MSC_VER)
2162#pragma warning(push)
2163#pragma warning(disable : 4101)
2164#endif
2165 NUITKA_MAY_BE_UNUSED bool cbool_result;
2166 NUITKA_MAY_BE_UNUSED PyObject *obj_result;
2167#if defined(_MSC_VER)
2168#pragma warning(pop)
2169#endif
2170
2171 // No inplace number slot nb_inplace_add available for this type.
2172
2173 {
2174 binaryfunc slot1 = PyLong_Type.tp_as_number->nb_add;
2175 // Slot2 ignored on purpose, type1 takes precedence.
2176
2177 if (slot1 != NULL) {
2178 PyObject *x = slot1(*operand1, operand2);
2179
2180 if (x != Py_NotImplemented) {
2181 obj_result = x;
2182 goto exit_inplace_result_object;
2183 }
2184
2185 Py_DECREF_IMMORTAL(x);
2186 }
2187
2188 // Statically recognized that coercion is not possible with these types
2189
2190 {
2191 // No sequence repeat slot sq_concat available for this type.
2192 // No inplace sequence repeat slot sq_inplace_concat available for this type.
2193 }
2194
2195 PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for +=: 'long' and 'int'");
2196 goto exit_inplace_exception;
2197 }
2198
2199exit_inplace_result_object:
2200 if (unlikely(obj_result == NULL)) {
2201 return false;
2202 }
2203
2204 // We got an object handed, that we have to release.
2205 Py_DECREF(*operand1);
2206
2207 // That's our return value then. As we use a dedicated variable, it's
2208 // OK that way.
2209 *operand1 = obj_result;
2210
2211 return true;
2212
2213exit_inplace_exception:
2214 return false;
2215}
2216
2217bool INPLACE_OPERATION_ADD_LONG_INT(PyObject **operand1, PyObject *operand2) {
2218 return _INPLACE_OPERATION_ADD_LONG_INT(operand1, operand2);
2219}
2220#endif
2221
2222#if PYTHON_VERSION < 0x300
2223/* Code referring to "INT" corresponds to Python2 'int' and "LONG" to Python2 'long', Python3 'int'. */
2224static inline bool _INPLACE_OPERATION_ADD_INT_LONG(PyObject **operand1, PyObject *operand2) {
2225 assert(operand1); // Pointer must be non-null.
2226
2227 CHECK_OBJECT(*operand1);
2228 assert(PyInt_CheckExact(*operand1));
2229 CHECK_OBJECT(operand2);
2230 assert(PyLong_CheckExact(operand2));
2231
2232#if defined(_MSC_VER)
2233#pragma warning(push)
2234#pragma warning(disable : 4101)
2235#endif
2236 NUITKA_MAY_BE_UNUSED bool cbool_result;
2237 NUITKA_MAY_BE_UNUSED PyObject *obj_result;
2238#if defined(_MSC_VER)
2239#pragma warning(pop)
2240#endif
2241
2242 // No inplace number slot nb_inplace_add available for this type.
2243
2244 {
2245 // Slot1 ignored on purpose, type2 takes precedence.
2246 binaryfunc slot2 = NULL;
2247
2248 if (!(0)) {
2249 // Different types, need to consider second value slot.
2250
2251 slot2 = PyLong_Type.tp_as_number->nb_add;
2252 }
2253
2254 if (slot2 != NULL) {
2255 PyObject *x = slot2(*operand1, operand2);
2256
2257 if (x != Py_NotImplemented) {
2258 obj_result = x;
2259 goto exit_inplace_result_object;
2260 }
2261
2262 Py_DECREF_IMMORTAL(x);
2263 }
2264
2265 // Statically recognized that coercion is not possible with these types
2266
2267 {
2268 // No sequence repeat slot sq_concat available for this type.
2269 // No inplace sequence repeat slot sq_inplace_concat available for this type.
2270 }
2271
2272 PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for +=: 'int' and 'long'");
2273 goto exit_inplace_exception;
2274 }
2275
2276exit_inplace_result_object:
2277 if (unlikely(obj_result == NULL)) {
2278 return false;
2279 }
2280
2281 // We got an object handed, that we have to release.
2282 Py_DECREF(*operand1);
2283
2284 // That's our return value then. As we use a dedicated variable, it's
2285 // OK that way.
2286 *operand1 = obj_result;
2287
2288 return true;
2289
2290exit_inplace_exception:
2291 return false;
2292}
2293
2294bool INPLACE_OPERATION_ADD_INT_LONG(PyObject **operand1, PyObject *operand2) {
2295 return _INPLACE_OPERATION_ADD_INT_LONG(operand1, operand2);
2296}
2297#endif
2298
2299#if PYTHON_VERSION < 0x300
2300/* Code referring to "INT" corresponds to Python2 'int' and "CLONG" to C platform long value. */
2301static inline bool _INPLACE_OPERATION_ADD_INT_CLONG(PyObject **operand1, long operand2) {
2302 assert(operand1); // Pointer must be non-null.
2303
2304 CHECK_OBJECT(*operand1);
2305 assert(PyInt_CheckExact(*operand1));
2306
2307 // Not every code path will make use of all possible results.
2308#if defined(_MSC_VER)
2309#pragma warning(push)
2310#pragma warning(disable : 4101)
2311#endif
2312 NUITKA_MAY_BE_UNUSED bool cbool_result;
2313 NUITKA_MAY_BE_UNUSED PyObject *obj_result;
2314 NUITKA_MAY_BE_UNUSED long clong_result;
2315 NUITKA_MAY_BE_UNUSED double cfloat_result;
2316#if defined(_MSC_VER)
2317#pragma warning(pop)
2318#endif
2319
2320 CHECK_OBJECT(*operand1);
2321 assert(PyInt_CheckExact(*operand1));
2322
2323 const long a = PyInt_AS_LONG(*operand1);
2324 const long b = operand2;
2325
2326 const long x = (long)((unsigned long)a + b);
2327 bool no_overflow = ((x ^ a) >= 0 || (x ^ b) >= 0);
2328 if (likely(no_overflow)) {
2329 clong_result = x;
2330 goto exit_result_ok_clong;
2331 }
2332
2333 {
2334 PyObject *operand1_object = *operand1;
2335 PyObject *operand2_object = Nuitka_PyLong_FromLong(operand2);
2336
2337 PyObject *r = PyLong_Type.tp_as_number->nb_add(operand1_object, operand2_object);
2338 assert(r != Py_NotImplemented);
2339
2340 Py_DECREF(operand2_object);
2341
2342 obj_result = r;
2343 goto exit_result_object;
2344 }
2345
2346exit_result_ok_clong:
2347
2348 // We got an object handed, that we have to release.
2349 Py_DECREF(*operand1);
2350
2351 // That's our return value then. As we use a dedicated variable, it's
2352 // OK that way.
2353 *operand1 = Nuitka_PyInt_FromLong(clong_result);
2354 goto exit_result_ok;
2355
2356exit_result_object:
2357 if (unlikely(obj_result == NULL)) {
2358 goto exit_result_exception;
2359 }
2360 // We got an object handed, that we have to release.
2361 Py_DECREF(*operand1);
2362
2363 *operand1 = obj_result;
2364 goto exit_result_ok;
2365
2366exit_result_ok:
2367 return true;
2368
2369exit_result_exception:
2370 return false;
2371}
2372
2373bool INPLACE_OPERATION_ADD_INT_CLONG(PyObject **operand1, long operand2) {
2374 return _INPLACE_OPERATION_ADD_INT_CLONG(operand1, operand2);
2375}
2376#endif
2377
2378/* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "DIGIT" to C platform digit value for long
2379 * Python objects. */
2380static inline bool _INPLACE_OPERATION_ADD_LONG_DIGIT(PyObject **operand1, long operand2) {
2381 assert(operand1); // Pointer must be non-null.
2382
2383 CHECK_OBJECT(*operand1);
2384 assert(PyLong_CheckExact(*operand1));
2385 assert(Py_ABS(operand2) < (1 << PyLong_SHIFT));
2386
2387 // Not every code path will make use of all possible results.
2388#if defined(_MSC_VER)
2389#pragma warning(push)
2390#pragma warning(disable : 4101)
2391#endif
2392 NUITKA_MAY_BE_UNUSED PyObject *obj_result;
2393 NUITKA_MAY_BE_UNUSED long clong_result;
2394#if defined(_MSC_VER)
2395#pragma warning(pop)
2396#endif
2397
2398 PyLongObject *operand1_long_object = (PyLongObject *)*operand1;
2399
2400 if (Nuitka_LongGetDigitSize(operand1_long_object) <= 1 && (operand2 == 0 ? 0 : 1) <= 1) {
2401 long r = (long)(MEDIUM_VALUE(operand1_long_object) + (sdigit)operand2);
2402
2403 if (Py_REFCNT(*operand1) == 1) {
2404 Nuitka_LongUpdateFromCLong(&*operand1, (long)r);
2405 goto exit_result_ok;
2406 } else {
2407 PyObject *obj = Nuitka_LongFromCLong(r);
2408
2409 obj_result = obj;
2410 goto exit_result_object;
2411 }
2412 clong_result = r;
2413 goto exit_result_ok_clong;
2414 }
2415
2416 if (Py_REFCNT(*operand1) == 1) {
2417 digit const *b_digits = (digit *)&operand2;
2418 Py_ssize_t b_digit_count = (operand2 == 0 ? 0 : 1);
2419
2420 bool a_negative = Nuitka_LongIsNegative(operand1_long_object);
2421 bool b_negative = operand2 < 0;
2422
2423 if (a_negative) {
2424 if (b_negative) {
2425 *operand1 = _Nuitka_LongAddInplaceDigits(*operand1, b_digits, b_digit_count);
2426 Nuitka_LongSetSignNegative(*operand1);
2427 } else {
2428 *operand1 = _Nuitka_LongSubInplaceDigits(*operand1, b_digits, b_digit_count, -1);
2429 }
2430 } else {
2431 if (b_negative) {
2432 *operand1 = _Nuitka_LongSubInplaceDigits(*operand1, b_digits, b_digit_count, 1);
2433 } else {
2434 *operand1 = _Nuitka_LongAddInplaceDigits(*operand1, b_digits, b_digit_count);
2435 }
2436 }
2437
2438 goto exit_result_ok;
2439 }
2440 {
2441 PyLongObject *z;
2442
2443 digit const *a_digits = Nuitka_LongGetDigitPointer(operand1_long_object);
2444 Py_ssize_t a_digit_count = Nuitka_LongGetDigitSize(operand1_long_object);
2445 bool a_negative = Nuitka_LongIsNegative(operand1_long_object);
2446 digit const *b_digits = (digit *)&operand2;
2447 Py_ssize_t b_digit_count = (operand2 == 0 ? 0 : 1);
2448 bool b_negative = operand2 < 0;
2449
2450 if (a_negative) {
2451 if (b_negative) {
2452 z = _Nuitka_LongAddDigits(a_digits, a_digit_count, b_digits, b_digit_count);
2453 Nuitka_LongFlipSign(z);
2454 } else {
2455 z = _Nuitka_LongSubDigits(b_digits, b_digit_count, a_digits, a_digit_count);
2456 }
2457 } else {
2458 if (b_negative) {
2459 z = _Nuitka_LongSubDigits(a_digits, a_digit_count, b_digits, b_digit_count);
2460 } else {
2461 z = _Nuitka_LongAddDigits(a_digits, a_digit_count, b_digits, b_digit_count);
2462 }
2463 }
2464
2465 obj_result = (PyObject *)z;
2466 goto exit_result_object;
2467 }
2468
2469exit_result_object:
2470 if (unlikely(obj_result == NULL)) {
2471 goto exit_result_exception;
2472 }
2473 // We got an object handed, that we have to release.
2474 Py_DECREF(*operand1);
2475 *operand1 = obj_result;
2476 goto exit_result_ok;
2477
2478exit_result_ok_clong:
2479
2480 // We got an object handed, that we have to release.
2481 Py_DECREF(*operand1);
2482
2483 // That's our return value then. As we use a dedicated variable, it's
2484 // OK that way.
2485 *operand1 = Nuitka_PyLong_FromLong(clong_result);
2486 goto exit_result_ok;
2487
2488exit_result_ok:
2489 return true;
2490
2491exit_result_exception:
2492 return false;
2493}
2494
2495bool INPLACE_OPERATION_ADD_LONG_DIGIT(PyObject **operand1, long operand2) {
2496 return _INPLACE_OPERATION_ADD_LONG_DIGIT(operand1, operand2);
2497}
2498
2499/* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "CLONG" to C platform long value. */
2500static inline bool _INPLACE_OPERATION_ADD_LONG_CLONG(PyObject **operand1, long operand2) {
2501 assert(operand1); // Pointer must be non-null.
2502
2503 CHECK_OBJECT(*operand1);
2504 assert(PyLong_CheckExact(*operand1));
2505
2506 // Not every code path will make use of all possible results.
2507#if defined(_MSC_VER)
2508#pragma warning(push)
2509#pragma warning(disable : 4101)
2510#endif
2511 NUITKA_MAY_BE_UNUSED PyObject *obj_result;
2512 NUITKA_MAY_BE_UNUSED long clong_result;
2513#if defined(_MSC_VER)
2514#pragma warning(pop)
2515#endif
2516
2517 PyLongObject *operand1_long_object = (PyLongObject *)*operand1;
2518
2519 bool operand2_is_negative;
2520 unsigned long operand2_abs_ival;
2521
2522 if (operand2 < 0) {
2523 operand2_abs_ival = (unsigned long)(-1 - operand2) + 1;
2524 operand2_is_negative = true;
2525 } else {
2526 operand2_abs_ival = (unsigned long)operand2;
2527 operand2_is_negative = false;
2528 }
2529
2530 Py_ssize_t operand2_digit_count = 0;
2531 digit operand2_digits[5] = {0}; // Could be more minimal and depend on sizeof(digit)
2532 {
2533 unsigned long t = operand2_abs_ival;
2534
2535 while (t != 0) {
2536 operand2_digit_count += 1;
2537 assert(operand2_digit_count <= (Py_ssize_t)(sizeof(operand2_digit_count) / sizeof(digit)));
2538
2539 operand2_digits[operand2_digit_count] = (digit)(t & PyLong_MASK);
2540 t >>= PyLong_SHIFT;
2541 }
2542 }
2543
2544 NUITKA_MAY_BE_UNUSED Py_ssize_t operand2_size =
2545 operand2_is_negative == false ? operand2_digit_count : -operand2_digit_count;
2546
2547 if (Nuitka_LongGetDigitSize(operand1_long_object) <= 1 && operand2_digit_count <= 1) {
2548 long r = (long)(MEDIUM_VALUE(operand1_long_object) + (sdigit)operand2);
2549
2550 if (Py_REFCNT(*operand1) == 1) {
2551 Nuitka_LongUpdateFromCLong(&*operand1, (long)r);
2552 goto exit_result_ok;
2553 } else {
2554 PyObject *obj = Nuitka_LongFromCLong(r);
2555
2556 obj_result = obj;
2557 goto exit_result_object;
2558 }
2559 clong_result = r;
2560 goto exit_result_ok_clong;
2561 }
2562
2563 if (Py_REFCNT(*operand1) == 1) {
2564 digit const *b_digits = operand2_digits;
2565 Py_ssize_t b_digit_count = operand2_digit_count;
2566
2567 bool a_negative = Nuitka_LongIsNegative(operand1_long_object);
2568 bool b_negative = operand2_is_negative;
2569
2570 if (a_negative) {
2571 if (b_negative) {
2572 *operand1 = _Nuitka_LongAddInplaceDigits(*operand1, b_digits, b_digit_count);
2573 Nuitka_LongSetSignNegative(*operand1);
2574 } else {
2575 *operand1 = _Nuitka_LongSubInplaceDigits(*operand1, b_digits, b_digit_count, -1);
2576 }
2577 } else {
2578 if (b_negative) {
2579 *operand1 = _Nuitka_LongSubInplaceDigits(*operand1, b_digits, b_digit_count, 1);
2580 } else {
2581 *operand1 = _Nuitka_LongAddInplaceDigits(*operand1, b_digits, b_digit_count);
2582 }
2583 }
2584
2585 goto exit_result_ok;
2586 }
2587 {
2588 PyLongObject *z;
2589
2590 digit const *a_digits = Nuitka_LongGetDigitPointer(operand1_long_object);
2591 Py_ssize_t a_digit_count = Nuitka_LongGetDigitSize(operand1_long_object);
2592 bool a_negative = Nuitka_LongIsNegative(operand1_long_object);
2593 digit const *b_digits = operand2_digits;
2594 Py_ssize_t b_digit_count = operand2_digit_count;
2595 bool b_negative = operand2_is_negative;
2596
2597 if (a_negative) {
2598 if (b_negative) {
2599 z = _Nuitka_LongAddDigits(a_digits, a_digit_count, b_digits, b_digit_count);
2600 Nuitka_LongFlipSign(z);
2601 } else {
2602 z = _Nuitka_LongSubDigits(b_digits, b_digit_count, a_digits, a_digit_count);
2603 }
2604 } else {
2605 if (b_negative) {
2606 z = _Nuitka_LongSubDigits(a_digits, a_digit_count, b_digits, b_digit_count);
2607 } else {
2608 z = _Nuitka_LongAddDigits(a_digits, a_digit_count, b_digits, b_digit_count);
2609 }
2610 }
2611
2612 obj_result = (PyObject *)z;
2613 goto exit_result_object;
2614 }
2615
2616exit_result_object:
2617 if (unlikely(obj_result == NULL)) {
2618 goto exit_result_exception;
2619 }
2620 // We got an object handed, that we have to release.
2621 Py_DECREF(*operand1);
2622 *operand1 = obj_result;
2623 goto exit_result_ok;
2624
2625exit_result_ok_clong:
2626
2627 // We got an object handed, that we have to release.
2628 Py_DECREF(*operand1);
2629
2630 // That's our return value then. As we use a dedicated variable, it's
2631 // OK that way.
2632 *operand1 = Nuitka_PyLong_FromLong(clong_result);
2633 goto exit_result_ok;
2634
2635exit_result_ok:
2636 return true;
2637
2638exit_result_exception:
2639 return false;
2640}
2641
2642bool INPLACE_OPERATION_ADD_LONG_CLONG(PyObject **operand1, long operand2) {
2643 return _INPLACE_OPERATION_ADD_LONG_CLONG(operand1, operand2);
2644}
2645
2646/* Code referring to "FLOAT" corresponds to Python 'float' and "CFLOAT" to C platform float value. */
2647static inline bool _INPLACE_OPERATION_ADD_FLOAT_CFLOAT(PyObject **operand1, double operand2) {
2648 assert(operand1); // Pointer must be non-null.
2649
2650 CHECK_OBJECT(*operand1);
2651 assert(PyFloat_CheckExact(*operand1));
2652
2653#if defined(_MSC_VER)
2654#pragma warning(push)
2655#pragma warning(disable : 4101)
2656#endif
2657 // Not every code path will make use of all possible results.
2658 NUITKA_MAY_BE_UNUSED PyObject *obj_result;
2659 NUITKA_MAY_BE_UNUSED long clong_result;
2660 NUITKA_MAY_BE_UNUSED double cfloat_result;
2661#if defined(_MSC_VER)
2662#pragma warning(pop)
2663#endif
2664
2665 CHECK_OBJECT(*operand1);
2666 assert(PyFloat_CheckExact(*operand1));
2667
2668 const double a = PyFloat_AS_DOUBLE(*operand1);
2669 const double b = operand2;
2670
2671 double r = a + b;
2672
2673 cfloat_result = r;
2674 goto exit_result_ok_cfloat;
2675
2676exit_result_ok_cfloat:
2677 if (Py_REFCNT(*operand1) == 1) {
2678 PyFloat_SET_DOUBLE(*operand1, cfloat_result);
2679 } else {
2680 // We got an object handed, that we have to release.
2681 Py_DECREF(*operand1);
2682
2683 *operand1 = MAKE_FLOAT_FROM_DOUBLE(cfloat_result);
2684 }
2685 goto exit_result_ok;
2686
2687exit_result_ok:
2688 return true;
2689}
2690
2691bool INPLACE_OPERATION_ADD_FLOAT_CFLOAT(PyObject **operand1, double operand2) {
2692 return _INPLACE_OPERATION_ADD_FLOAT_CFLOAT(operand1, operand2);
2693}
2694
2695#if PYTHON_VERSION < 0x300
2696/* Code referring to "STR" corresponds to Python2 'str' and "STR" to Python2 'str'. */
2697static inline bool _INPLACE_OPERATION_ADD_STR_STR(PyObject **operand1, PyObject *operand2) {
2698 assert(operand1); // Pointer must be non-null.
2699
2700 CHECK_OBJECT(*operand1);
2701 assert(PyString_CheckExact(*operand1));
2702 CHECK_OBJECT(operand2);
2703 assert(PyString_CheckExact(operand2));
2704
2705 if (Py_REFCNT(*operand1) == 1) {
2706 // We more or less own the operand, so we might reuse its storage and
2707 // execute stuff in-place.
2708#if PYTHON_VERSION < 0x300
2709 if (1 && !PyString_CHECK_INTERNED(*operand1) && 1) {
2710 return STRING_ADD_INPLACE(operand1, operand2);
2711 }
2712#endif
2713 }
2714
2715#if PYTHON_VERSION < 0x300
2716 // Python2 strings are to be treated differently, fall back to Python API here.
2717 if (1 && 1) {
2718 PyString_Concat(operand1, operand2);
2719
2720 // TODO: Have this more globally passed in
2721 PyThreadState *tstate = PyThreadState_GET();
2722
2723 return !HAS_ERROR_OCCURRED(tstate);
2724 }
2725#endif
2726
2727 // Not every code path will make use of all possible results.
2728 NUITKA_MAY_BE_UNUSED PyObject *obj_result;
2729
2730 PyObject *x = PyString_Type.tp_as_sequence->sq_concat(*operand1, operand2);
2731 assert(x != Py_NotImplemented);
2732
2733 obj_result = x;
2734 goto exit_result_object;
2735
2736exit_result_object:
2737 if (unlikely(obj_result == NULL)) {
2738 goto exit_result_exception;
2739 }
2740 // We got an object handed, that we have to release.
2741 Py_DECREF(*operand1);
2742
2743 *operand1 = obj_result;
2744 goto exit_result_ok;
2745
2746exit_result_ok:
2747 return true;
2748
2749exit_result_exception:
2750 return false;
2751}
2752
2753bool INPLACE_OPERATION_ADD_STR_STR(PyObject **operand1, PyObject *operand2) {
2754 return _INPLACE_OPERATION_ADD_STR_STR(operand1, operand2);
2755}
2756#endif
2757
2758#if PYTHON_VERSION < 0x300
2759/* Code referring to "OBJECT" corresponds to any Python object and "STR" to Python2 'str'. */
2760static HEDLEY_NEVER_INLINE bool __INPLACE_OPERATION_ADD_OBJECT_STR(PyObject **operand1, PyObject *operand2) {
2761 PyTypeObject *type1 = Py_TYPE(*operand1);
2762
2763#if defined(_MSC_VER)
2764#pragma warning(push)
2765#pragma warning(disable : 4101)
2766#endif
2767 NUITKA_MAY_BE_UNUSED bool cbool_result;
2768 NUITKA_MAY_BE_UNUSED PyObject *obj_result;
2769#if defined(_MSC_VER)
2770#pragma warning(pop)
2771#endif
2772
2773 binaryfunc islot =
2774 (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_inplace_add : NULL;
2775
2776 if (islot != NULL) {
2777 PyObject *x = islot(*operand1, operand2);
2778
2779 if (x != Py_NotImplemented) {
2780 obj_result = x;
2781 goto exit_inplace_result_object;
2782 }
2783
2784 Py_DECREF_IMMORTAL(x);
2785 }
2786
2787 {
2788 binaryfunc slot1 =
2789 (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_add : NULL;
2790
2791 if (slot1 != NULL) {
2792 PyObject *x = slot1(*operand1, operand2);
2793
2794 if (x != Py_NotImplemented) {
2795 obj_result = x;
2796 goto exit_inplace_result_object;
2797 }
2798
2799 Py_DECREF_IMMORTAL(x);
2800 }
2801
2802#if PYTHON_VERSION < 0x300
2803 if (!NEW_STYLE_NUMBER_TYPE(type1) || !1) {
2804 coercion c1 =
2805 (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_coerce : NULL;
2806
2807 if (c1 != NULL) {
2808 PyObject *coerced1 = *operand1;
2809 PyObject *coerced2 = operand2;
2810
2811 int err = c1(&coerced1, &coerced2);
2812
2813 if (unlikely(err < 0)) {
2814 goto exit_inplace_exception;
2815 }
2816
2817 if (err == 0) {
2818 PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number;
2819
2820 if (likely(mv == NULL)) {
2821 binaryfunc slot = mv->nb_add;
2822
2823 if (likely(slot != NULL)) {
2824 PyObject *x = slot(coerced1, coerced2);
2825
2826 Py_DECREF(coerced1);
2827 Py_DECREF(coerced2);
2828
2829 obj_result = x;
2830 goto exit_inplace_result_object;
2831 }
2832 }
2833
2834 // nb_coerce took a reference.
2835 Py_DECREF(coerced1);
2836 Py_DECREF(coerced2);
2837 }
2838 }
2839 }
2840#endif
2841
2842 {
2843 // Special case for "+" and "*", also works as sequence concat/repeat.
2844 binaryfunc sq_slot = type1->tp_as_sequence != NULL ? type1->tp_as_sequence->sq_inplace_concat : NULL;
2845 if (sq_slot == NULL) {
2846 sq_slot = type1->tp_as_sequence != NULL ? type1->tp_as_sequence->sq_concat : NULL;
2847 }
2848
2849 if (sq_slot != NULL) {
2850 PyObject *result = sq_slot(*operand1, operand2);
2851
2852 obj_result = result;
2853 goto exit_inplace_result_object;
2854 }
2855 }
2856
2857 PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for +=: '%s' and 'str'", type1->tp_name);
2858 goto exit_inplace_exception;
2859 }
2860
2861exit_inplace_result_object:
2862 if (unlikely(obj_result == NULL)) {
2863 return false;
2864 }
2865
2866 // We got an object handed, that we have to release.
2867 Py_DECREF(*operand1);
2868
2869 // That's our return value then. As we use a dedicated variable, it's
2870 // OK that way.
2871 *operand1 = obj_result;
2872
2873 return true;
2874
2875exit_inplace_exception:
2876 return false;
2877}
2878static inline bool _INPLACE_OPERATION_ADD_OBJECT_STR(PyObject **operand1, PyObject *operand2) {
2879 assert(operand1); // Pointer must be non-null.
2880
2881 CHECK_OBJECT(*operand1);
2882 CHECK_OBJECT(operand2);
2883 assert(PyString_CheckExact(operand2));
2884
2885 if (Py_REFCNT(*operand1) == 1) {
2886 // We more or less own the operand, so we might reuse its storage and
2887 // execute stuff in-place.
2888#if PYTHON_VERSION < 0x300
2889 if (PyString_CheckExact(*operand1) && !PyString_CHECK_INTERNED(*operand1) && 1) {
2890 return STRING_ADD_INPLACE(operand1, operand2);
2891 }
2892#endif
2893 }
2894
2895 PyTypeObject *type1 = Py_TYPE(*operand1);
2896
2897 if (type1 == &PyString_Type) {
2898 // return _BINARY_OPERATION_ADD_STR_STR_INPLACE(operand1, operand2);
2899
2900 // Not every code path will make use of all possible results.
2901 NUITKA_MAY_BE_UNUSED PyObject *obj_result;
2902
2903 PyObject *x = PyString_Type.tp_as_sequence->sq_concat(*operand1, operand2);
2904 assert(x != Py_NotImplemented);
2905
2906 obj_result = x;
2907 goto exit_result_object;
2908
2909 exit_result_object:
2910 if (unlikely(obj_result == NULL)) {
2911 goto exit_result_exception;
2912 }
2913 // We got an object handed, that we have to release.
2914 Py_DECREF(*operand1);
2915
2916 *operand1 = obj_result;
2917 goto exit_result_ok;
2918
2919 exit_result_ok:
2920 return true;
2921
2922 exit_result_exception:
2923 return false;
2924 }
2925
2926 return __INPLACE_OPERATION_ADD_OBJECT_STR(operand1, operand2);
2927}
2928
2929bool INPLACE_OPERATION_ADD_OBJECT_STR(PyObject **operand1, PyObject *operand2) {
2930 return _INPLACE_OPERATION_ADD_OBJECT_STR(operand1, operand2);
2931}
2932#endif
2933
2934#if PYTHON_VERSION < 0x300
2935/* Code referring to "STR" corresponds to Python2 'str' and "OBJECT" to any Python object. */
2936static HEDLEY_NEVER_INLINE bool __INPLACE_OPERATION_ADD_STR_OBJECT(PyObject **operand1, PyObject *operand2) {
2937 PyTypeObject *type2 = Py_TYPE(operand2);
2938
2939#if defined(_MSC_VER)
2940#pragma warning(push)
2941#pragma warning(disable : 4101)
2942#endif
2943 NUITKA_MAY_BE_UNUSED bool cbool_result;
2944 NUITKA_MAY_BE_UNUSED PyObject *obj_result;
2945#if defined(_MSC_VER)
2946#pragma warning(pop)
2947#endif
2948
2949 // No inplace number slot nb_inplace_add available for this type.
2950
2951 {
2952 binaryfunc slot2 = NULL;
2953
2954 if (!(&PyString_Type == type2)) {
2955 // Different types, need to consider second value slot.
2956
2957 slot2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_add : NULL;
2958 }
2959
2960 if (slot2 != NULL) {
2961 PyObject *x = slot2(*operand1, operand2);
2962
2963 if (x != Py_NotImplemented) {
2964 obj_result = x;
2965 goto exit_inplace_result_object;
2966 }
2967
2968 Py_DECREF_IMMORTAL(x);
2969 }
2970
2971#if PYTHON_VERSION < 0x300
2972 if (!1 || !NEW_STYLE_NUMBER_TYPE(type2)) {
2973 coercion c2 =
2974 (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_coerce : NULL;
2975
2976 if (c2 != NULL) {
2977 PyObject *coerced1 = *operand1;
2978 PyObject *coerced2 = operand2;
2979
2980 int err = c2(&coerced2, &coerced1);
2981
2982 if (unlikely(err < 0)) {
2983 goto exit_inplace_exception;
2984 }
2985
2986 if (err == 0) {
2987 PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number;
2988
2989 if (likely(mv == NULL)) {
2990 binaryfunc slot = mv->nb_add;
2991
2992 if (likely(slot != NULL)) {
2993 PyObject *x = slot(coerced1, coerced2);
2994
2995 Py_DECREF(coerced1);
2996 Py_DECREF(coerced2);
2997
2998 obj_result = x;
2999 goto exit_inplace_result_object;
3000 }
3001 }
3002
3003 // nb_coerce took a reference.
3004 Py_DECREF(coerced1);
3005 Py_DECREF(coerced2);
3006 }
3007 }
3008 }
3009#endif
3010
3011 {
3012 PyObject *o = PyString_Type.tp_as_sequence->sq_concat(*operand1, operand2);
3013 obj_result = o;
3014 goto exit_inplace_result_object;
3015 }
3016
3017 NUITKA_CANNOT_GET_HERE("missing error exit annotation");
3018 }
3019
3020exit_inplace_result_object:
3021 if (unlikely(obj_result == NULL)) {
3022 return false;
3023 }
3024
3025 // We got an object handed, that we have to release.
3026 Py_DECREF(*operand1);
3027
3028 // That's our return value then. As we use a dedicated variable, it's
3029 // OK that way.
3030 *operand1 = obj_result;
3031
3032 return true;
3033
3034#if PYTHON_VERSION < 0x300
3035exit_inplace_exception:
3036 return false;
3037#endif
3038}
3039static inline bool _INPLACE_OPERATION_ADD_STR_OBJECT(PyObject **operand1, PyObject *operand2) {
3040 assert(operand1); // Pointer must be non-null.
3041
3042 CHECK_OBJECT(*operand1);
3043 assert(PyString_CheckExact(*operand1));
3044 CHECK_OBJECT(operand2);
3045
3046 if (Py_REFCNT(*operand1) == 1) {
3047 // We more or less own the operand, so we might reuse its storage and
3048 // execute stuff in-place.
3049#if PYTHON_VERSION < 0x300
3050 if (1 && !PyString_CHECK_INTERNED(*operand1) && PyString_CheckExact(operand2)) {
3051 return STRING_ADD_INPLACE(operand1, operand2);
3052 }
3053#endif
3054 }
3055
3056 PyTypeObject *type2 = Py_TYPE(operand2);
3057
3058 if (&PyString_Type == type2) {
3059 // return _BINARY_OPERATION_ADD_STR_STR_INPLACE(operand1, operand2);
3060
3061 // Not every code path will make use of all possible results.
3062 NUITKA_MAY_BE_UNUSED PyObject *obj_result;
3063
3064 PyObject *x = PyString_Type.tp_as_sequence->sq_concat(*operand1, operand2);
3065 assert(x != Py_NotImplemented);
3066
3067 obj_result = x;
3068 goto exit_result_object;
3069
3070 exit_result_object:
3071 if (unlikely(obj_result == NULL)) {
3072 goto exit_result_exception;
3073 }
3074 // We got an object handed, that we have to release.
3075 Py_DECREF(*operand1);
3076
3077 *operand1 = obj_result;
3078 goto exit_result_ok;
3079
3080 exit_result_ok:
3081 return true;
3082
3083 exit_result_exception:
3084 return false;
3085 }
3086
3087 return __INPLACE_OPERATION_ADD_STR_OBJECT(operand1, operand2);
3088}
3089
3090bool INPLACE_OPERATION_ADD_STR_OBJECT(PyObject **operand1, PyObject *operand2) {
3091 return _INPLACE_OPERATION_ADD_STR_OBJECT(operand1, operand2);
3092}
3093#endif
3094
3095/* Code referring to "UNICODE" corresponds to Python2 'unicode', Python3 'str' and "UNICODE" to Python2 'unicode',
3096 * Python3 'str'. */
3097static inline bool _INPLACE_OPERATION_ADD_UNICODE_UNICODE(PyObject **operand1, PyObject *operand2) {
3098 assert(operand1); // Pointer must be non-null.
3099
3100 CHECK_OBJECT(*operand1);
3101 assert(PyUnicode_CheckExact(*operand1));
3102 CHECK_OBJECT(operand2);
3103 assert(PyUnicode_CheckExact(operand2));
3104
3105 if (Py_REFCNT(*operand1) == 1) {
3106 // We more or less own the operand, so we might reuse its storage and
3107 // execute stuff in-place.
3108
3109#if PYTHON_VERSION >= 0x300
3110 if (1 && !PyUnicode_CHECK_INTERNED(*operand1) && 1) {
3111 // TODO: Push outward.
3112 PyThreadState *tstate = PyThreadState_GET();
3113
3114 return UNICODE_ADD_INCREMENTAL(tstate, operand1, operand2);
3115 }
3116#endif
3117 }
3118
3119 // Not every code path will make use of all possible results.
3120 NUITKA_MAY_BE_UNUSED PyObject *obj_result;
3121
3122 // TODO: Have this more globally passed in
3123 PyThreadState *tstate = PyThreadState_GET();
3124
3125 PyObject *x = UNICODE_CONCAT(tstate, *operand1, operand2);
3126
3127 obj_result = x;
3128 goto exit_result_object;
3129
3130exit_result_object:
3131 if (unlikely(obj_result == NULL)) {
3132 goto exit_result_exception;
3133 }
3134 // We got an object handed, that we have to release.
3135 Py_DECREF(*operand1);
3136
3137 *operand1 = obj_result;
3138 goto exit_result_ok;
3139
3140exit_result_ok:
3141 return true;
3142
3143exit_result_exception:
3144 return false;
3145}
3146
3147bool INPLACE_OPERATION_ADD_UNICODE_UNICODE(PyObject **operand1, PyObject *operand2) {
3148 return _INPLACE_OPERATION_ADD_UNICODE_UNICODE(operand1, operand2);
3149}
3150
3151/* Code referring to "OBJECT" corresponds to any Python object and "UNICODE" to Python2 'unicode', Python3 'str'. */
3152static HEDLEY_NEVER_INLINE bool __INPLACE_OPERATION_ADD_OBJECT_UNICODE(PyObject **operand1, PyObject *operand2) {
3153 PyTypeObject *type1 = Py_TYPE(*operand1);
3154
3155#if defined(_MSC_VER)
3156#pragma warning(push)
3157#pragma warning(disable : 4101)
3158#endif
3159 NUITKA_MAY_BE_UNUSED bool cbool_result;
3160 NUITKA_MAY_BE_UNUSED PyObject *obj_result;
3161#if defined(_MSC_VER)
3162#pragma warning(pop)
3163#endif
3164
3165 binaryfunc islot =
3166 (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_inplace_add : NULL;
3167
3168 if (islot != NULL) {
3169 PyObject *x = islot(*operand1, operand2);
3170
3171 if (x != Py_NotImplemented) {
3172 obj_result = x;
3173 goto exit_inplace_result_object;
3174 }
3175
3176 Py_DECREF_IMMORTAL(x);
3177 }
3178
3179 {
3180 binaryfunc slot1 =
3181 (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_add : NULL;
3182
3183 if (slot1 != NULL) {
3184 PyObject *x = slot1(*operand1, operand2);
3185
3186 if (x != Py_NotImplemented) {
3187 obj_result = x;
3188 goto exit_inplace_result_object;
3189 }
3190
3191 Py_DECREF_IMMORTAL(x);
3192 }
3193
3194#if PYTHON_VERSION < 0x300
3195 if (!NEW_STYLE_NUMBER_TYPE(type1) || !1) {
3196 coercion c1 =
3197 (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_coerce : NULL;
3198
3199 if (c1 != NULL) {
3200 PyObject *coerced1 = *operand1;
3201 PyObject *coerced2 = operand2;
3202
3203 int err = c1(&coerced1, &coerced2);
3204
3205 if (unlikely(err < 0)) {
3206 goto exit_inplace_exception;
3207 }
3208
3209 if (err == 0) {
3210 PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number;
3211
3212 if (likely(mv == NULL)) {
3213 binaryfunc slot = mv->nb_add;
3214
3215 if (likely(slot != NULL)) {
3216 PyObject *x = slot(coerced1, coerced2);
3217
3218 Py_DECREF(coerced1);
3219 Py_DECREF(coerced2);
3220
3221 obj_result = x;
3222 goto exit_inplace_result_object;
3223 }
3224 }
3225
3226 // nb_coerce took a reference.
3227 Py_DECREF(coerced1);
3228 Py_DECREF(coerced2);
3229 }
3230 }
3231 }
3232#endif
3233
3234 {
3235 // Special case for "+" and "*", also works as sequence concat/repeat.
3236 binaryfunc sq_slot = type1->tp_as_sequence != NULL ? type1->tp_as_sequence->sq_inplace_concat : NULL;
3237 if (sq_slot == NULL) {
3238 sq_slot = type1->tp_as_sequence != NULL ? type1->tp_as_sequence->sq_concat : NULL;
3239 }
3240
3241 if (sq_slot != NULL) {
3242 PyObject *result = sq_slot(*operand1, operand2);
3243
3244 obj_result = result;
3245 goto exit_inplace_result_object;
3246 }
3247 }
3248
3249#if PYTHON_VERSION < 0x300
3250 PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for +=: '%s' and 'unicode'", type1->tp_name);
3251#else
3252 PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for +=: '%s' and 'str'", type1->tp_name);
3253#endif
3254 goto exit_inplace_exception;
3255 }
3256
3257exit_inplace_result_object:
3258 if (unlikely(obj_result == NULL)) {
3259 return false;
3260 }
3261
3262 // We got an object handed, that we have to release.
3263 Py_DECREF(*operand1);
3264
3265 // That's our return value then. As we use a dedicated variable, it's
3266 // OK that way.
3267 *operand1 = obj_result;
3268
3269 return true;
3270
3271exit_inplace_exception:
3272 return false;
3273}
3274static inline bool _INPLACE_OPERATION_ADD_OBJECT_UNICODE(PyObject **operand1, PyObject *operand2) {
3275 assert(operand1); // Pointer must be non-null.
3276
3277 CHECK_OBJECT(*operand1);
3278 CHECK_OBJECT(operand2);
3279 assert(PyUnicode_CheckExact(operand2));
3280
3281 if (Py_REFCNT(*operand1) == 1) {
3282 // We more or less own the operand, so we might reuse its storage and
3283 // execute stuff in-place.
3284
3285#if PYTHON_VERSION >= 0x300
3286 if (PyUnicode_CheckExact(*operand1) && !PyUnicode_CHECK_INTERNED(*operand1) && 1) {
3287 // TODO: Push outward.
3288 PyThreadState *tstate = PyThreadState_GET();
3289
3290 return UNICODE_ADD_INCREMENTAL(tstate, operand1, operand2);
3291 }
3292#endif
3293 }
3294
3295 PyTypeObject *type1 = Py_TYPE(*operand1);
3296
3297 if (type1 == &PyUnicode_Type) {
3298 // return _BINARY_OPERATION_ADD_UNICODE_UNICODE_INPLACE(operand1, operand2);
3299
3300 // Not every code path will make use of all possible results.
3301 NUITKA_MAY_BE_UNUSED PyObject *obj_result;
3302
3303 // TODO: Have this more globally passed in
3304 PyThreadState *tstate = PyThreadState_GET();
3305
3306 PyObject *x = UNICODE_CONCAT(tstate, *operand1, operand2);
3307
3308 obj_result = x;
3309 goto exit_result_object;
3310
3311 exit_result_object:
3312 if (unlikely(obj_result == NULL)) {
3313 goto exit_result_exception;
3314 }
3315 // We got an object handed, that we have to release.
3316 Py_DECREF(*operand1);
3317
3318 *operand1 = obj_result;
3319 goto exit_result_ok;
3320
3321 exit_result_ok:
3322 return true;
3323
3324 exit_result_exception:
3325 return false;
3326 }
3327
3328 return __INPLACE_OPERATION_ADD_OBJECT_UNICODE(operand1, operand2);
3329}
3330
3331bool INPLACE_OPERATION_ADD_OBJECT_UNICODE(PyObject **operand1, PyObject *operand2) {
3332 return _INPLACE_OPERATION_ADD_OBJECT_UNICODE(operand1, operand2);
3333}
3334
3335/* Code referring to "UNICODE" corresponds to Python2 'unicode', Python3 'str' and "OBJECT" to any Python object. */
3336static HEDLEY_NEVER_INLINE bool __INPLACE_OPERATION_ADD_UNICODE_OBJECT(PyObject **operand1, PyObject *operand2) {
3337 PyTypeObject *type2 = Py_TYPE(operand2);
3338
3339#if defined(_MSC_VER)
3340#pragma warning(push)
3341#pragma warning(disable : 4101)
3342#endif
3343 NUITKA_MAY_BE_UNUSED bool cbool_result;
3344 NUITKA_MAY_BE_UNUSED PyObject *obj_result;
3345#if defined(_MSC_VER)
3346#pragma warning(pop)
3347#endif
3348
3349 // No inplace number slot nb_inplace_add available for this type.
3350
3351 {
3352 binaryfunc slot2 = NULL;
3353
3354 if (!(&PyUnicode_Type == type2)) {
3355 // Different types, need to consider second value slot.
3356
3357 slot2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_add : NULL;
3358 }
3359
3360 if (slot2 != NULL) {
3361 PyObject *x = slot2(*operand1, operand2);
3362
3363 if (x != Py_NotImplemented) {
3364 obj_result = x;
3365 goto exit_inplace_result_object;
3366 }
3367
3368 Py_DECREF_IMMORTAL(x);
3369 }
3370
3371#if PYTHON_VERSION < 0x300
3372 if (!1 || !NEW_STYLE_NUMBER_TYPE(type2)) {
3373 coercion c2 =
3374 (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_coerce : NULL;
3375
3376 if (c2 != NULL) {
3377 PyObject *coerced1 = *operand1;
3378 PyObject *coerced2 = operand2;
3379
3380 int err = c2(&coerced2, &coerced1);
3381
3382 if (unlikely(err < 0)) {
3383 goto exit_inplace_exception;
3384 }
3385
3386 if (err == 0) {
3387 PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number;
3388
3389 if (likely(mv == NULL)) {
3390 binaryfunc slot = mv->nb_add;
3391
3392 if (likely(slot != NULL)) {
3393 PyObject *x = slot(coerced1, coerced2);
3394
3395 Py_DECREF(coerced1);
3396 Py_DECREF(coerced2);
3397
3398 obj_result = x;
3399 goto exit_inplace_result_object;
3400 }
3401 }
3402
3403 // nb_coerce took a reference.
3404 Py_DECREF(coerced1);
3405 Py_DECREF(coerced2);
3406 }
3407 }
3408 }
3409#endif
3410
3411 {
3412 PyObject *o = PyUnicode_Type.tp_as_sequence->sq_concat(*operand1, operand2);
3413 obj_result = o;
3414 goto exit_inplace_result_object;
3415 }
3416
3417 NUITKA_CANNOT_GET_HERE("missing error exit annotation");
3418 }
3419
3420exit_inplace_result_object:
3421 if (unlikely(obj_result == NULL)) {
3422 return false;
3423 }
3424
3425 // We got an object handed, that we have to release.
3426 Py_DECREF(*operand1);
3427
3428 // That's our return value then. As we use a dedicated variable, it's
3429 // OK that way.
3430 *operand1 = obj_result;
3431
3432 return true;
3433
3434#if PYTHON_VERSION < 0x300
3435exit_inplace_exception:
3436 return false;
3437#endif
3438}
3439static inline bool _INPLACE_OPERATION_ADD_UNICODE_OBJECT(PyObject **operand1, PyObject *operand2) {
3440 assert(operand1); // Pointer must be non-null.
3441
3442 CHECK_OBJECT(*operand1);
3443 assert(PyUnicode_CheckExact(*operand1));
3444 CHECK_OBJECT(operand2);
3445
3446 if (Py_REFCNT(*operand1) == 1) {
3447 // We more or less own the operand, so we might reuse its storage and
3448 // execute stuff in-place.
3449
3450#if PYTHON_VERSION >= 0x300
3451 if (1 && !PyUnicode_CHECK_INTERNED(*operand1) && PyUnicode_CheckExact(operand2)) {
3452 // TODO: Push outward.
3453 PyThreadState *tstate = PyThreadState_GET();
3454
3455 return UNICODE_ADD_INCREMENTAL(tstate, operand1, operand2);
3456 }
3457#endif
3458 }
3459
3460 PyTypeObject *type2 = Py_TYPE(operand2);
3461
3462 if (&PyUnicode_Type == type2) {
3463 // return _BINARY_OPERATION_ADD_UNICODE_UNICODE_INPLACE(operand1, operand2);
3464
3465 // Not every code path will make use of all possible results.
3466 NUITKA_MAY_BE_UNUSED PyObject *obj_result;
3467
3468 // TODO: Have this more globally passed in
3469 PyThreadState *tstate = PyThreadState_GET();
3470
3471 PyObject *x = UNICODE_CONCAT(tstate, *operand1, operand2);
3472
3473 obj_result = x;
3474 goto exit_result_object;
3475
3476 exit_result_object:
3477 if (unlikely(obj_result == NULL)) {
3478 goto exit_result_exception;
3479 }
3480 // We got an object handed, that we have to release.
3481 Py_DECREF(*operand1);
3482
3483 *operand1 = obj_result;
3484 goto exit_result_ok;
3485
3486 exit_result_ok:
3487 return true;
3488
3489 exit_result_exception:
3490 return false;
3491 }
3492
3493 return __INPLACE_OPERATION_ADD_UNICODE_OBJECT(operand1, operand2);
3494}
3495
3496bool INPLACE_OPERATION_ADD_UNICODE_OBJECT(PyObject **operand1, PyObject *operand2) {
3497 return _INPLACE_OPERATION_ADD_UNICODE_OBJECT(operand1, operand2);
3498}
3499
3500#if PYTHON_VERSION >= 0x300
3501/* Code referring to "BYTES" corresponds to Python3 'bytes' and "BYTES" to Python3 'bytes'. */
3502static inline bool _INPLACE_OPERATION_ADD_BYTES_BYTES(PyObject **operand1, PyObject *operand2) {
3503 assert(operand1); // Pointer must be non-null.
3504
3505 CHECK_OBJECT(*operand1);
3506 assert(PyBytes_CheckExact(*operand1));
3507 CHECK_OBJECT(operand2);
3508 assert(PyBytes_CheckExact(operand2));
3509
3510 if (Py_REFCNT(*operand1) == 1) {
3511 // We more or less own the operand, so we might reuse its storage and
3512 // execute stuff in-place.
3513
3514#if PYTHON_VERSION >= 0x300
3515 if (1 && 1) {
3516 return BYTES_ADD_INCREMENTAL(operand1, operand2);
3517 }
3518#endif
3519 }
3520
3521 // Not every code path will make use of all possible results.
3522 NUITKA_MAY_BE_UNUSED PyObject *obj_result;
3523
3524 PyObject *x = PyBytes_Type.tp_as_sequence->sq_concat(*operand1, operand2);
3525 assert(x != Py_NotImplemented);
3526
3527 obj_result = x;
3528 goto exit_result_object;
3529
3530exit_result_object:
3531 if (unlikely(obj_result == NULL)) {
3532 goto exit_result_exception;
3533 }
3534 // We got an object handed, that we have to release.
3535 Py_DECREF(*operand1);
3536
3537 *operand1 = obj_result;
3538 goto exit_result_ok;
3539
3540exit_result_ok:
3541 return true;
3542
3543exit_result_exception:
3544 return false;
3545}
3546
3547bool INPLACE_OPERATION_ADD_BYTES_BYTES(PyObject **operand1, PyObject *operand2) {
3548 return _INPLACE_OPERATION_ADD_BYTES_BYTES(operand1, operand2);
3549}
3550#endif
3551
3552#if PYTHON_VERSION >= 0x300
3553/* Code referring to "OBJECT" corresponds to any Python object and "BYTES" to Python3 'bytes'. */
3554static HEDLEY_NEVER_INLINE bool __INPLACE_OPERATION_ADD_OBJECT_BYTES(PyObject **operand1, PyObject *operand2) {
3555 PyTypeObject *type1 = Py_TYPE(*operand1);
3556
3557#if defined(_MSC_VER)
3558#pragma warning(push)
3559#pragma warning(disable : 4101)
3560#endif
3561 NUITKA_MAY_BE_UNUSED bool cbool_result;
3562 NUITKA_MAY_BE_UNUSED PyObject *obj_result;
3563#if defined(_MSC_VER)
3564#pragma warning(pop)
3565#endif
3566
3567 binaryfunc islot =
3568 (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_inplace_add : NULL;
3569
3570 if (islot != NULL) {
3571 PyObject *x = islot(*operand1, operand2);
3572
3573 if (x != Py_NotImplemented) {
3574 obj_result = x;
3575 goto exit_inplace_result_object;
3576 }
3577
3578 Py_DECREF_IMMORTAL(x);
3579 }
3580
3581 {
3582 binaryfunc slot1 =
3583 (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_add : NULL;
3584
3585 if (slot1 != NULL) {
3586 PyObject *x = slot1(*operand1, operand2);
3587
3588 if (x != Py_NotImplemented) {
3589 obj_result = x;
3590 goto exit_inplace_result_object;
3591 }
3592
3593 Py_DECREF_IMMORTAL(x);
3594 }
3595
3596#if PYTHON_VERSION < 0x300
3597 if (!NEW_STYLE_NUMBER_TYPE(type1) || !0) {
3598 coercion c1 =
3599 (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_coerce : NULL;
3600
3601 if (c1 != NULL) {
3602 PyObject *coerced1 = *operand1;
3603 PyObject *coerced2 = operand2;
3604
3605 int err = c1(&coerced1, &coerced2);
3606
3607 if (unlikely(err < 0)) {
3608 goto exit_inplace_exception;
3609 }
3610
3611 if (err == 0) {
3612 PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number;
3613
3614 if (likely(mv == NULL)) {
3615 binaryfunc slot = mv->nb_add;
3616
3617 if (likely(slot != NULL)) {
3618 PyObject *x = slot(coerced1, coerced2);
3619
3620 Py_DECREF(coerced1);
3621 Py_DECREF(coerced2);
3622
3623 obj_result = x;
3624 goto exit_inplace_result_object;
3625 }
3626 }
3627
3628 // nb_coerce took a reference.
3629 Py_DECREF(coerced1);
3630 Py_DECREF(coerced2);
3631 }
3632 }
3633 }
3634#endif
3635
3636 {
3637 // Special case for "+" and "*", also works as sequence concat/repeat.
3638 binaryfunc sq_slot = type1->tp_as_sequence != NULL ? type1->tp_as_sequence->sq_inplace_concat : NULL;
3639 if (sq_slot == NULL) {
3640 sq_slot = type1->tp_as_sequence != NULL ? type1->tp_as_sequence->sq_concat : NULL;
3641 }
3642
3643 if (sq_slot != NULL) {
3644 PyObject *result = sq_slot(*operand1, operand2);
3645
3646 obj_result = result;
3647 goto exit_inplace_result_object;
3648 }
3649 }
3650
3651 PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for +=: '%s' and 'bytes'", type1->tp_name);
3652 goto exit_inplace_exception;
3653 }
3654
3655exit_inplace_result_object:
3656 if (unlikely(obj_result == NULL)) {
3657 return false;
3658 }
3659
3660 // We got an object handed, that we have to release.
3661 Py_DECREF(*operand1);
3662
3663 // That's our return value then. As we use a dedicated variable, it's
3664 // OK that way.
3665 *operand1 = obj_result;
3666
3667 return true;
3668
3669exit_inplace_exception:
3670 return false;
3671}
3672static inline bool _INPLACE_OPERATION_ADD_OBJECT_BYTES(PyObject **operand1, PyObject *operand2) {
3673 assert(operand1); // Pointer must be non-null.
3674
3675 CHECK_OBJECT(*operand1);
3676 CHECK_OBJECT(operand2);
3677 assert(PyBytes_CheckExact(operand2));
3678
3679 if (Py_REFCNT(*operand1) == 1) {
3680 // We more or less own the operand, so we might reuse its storage and
3681 // execute stuff in-place.
3682
3683#if PYTHON_VERSION >= 0x300
3684 if (PyBytes_CheckExact(*operand1) && 1) {
3685 return BYTES_ADD_INCREMENTAL(operand1, operand2);
3686 }
3687#endif
3688 }
3689
3690 PyTypeObject *type1 = Py_TYPE(*operand1);
3691
3692 if (type1 == &PyBytes_Type) {
3693 // return _BINARY_OPERATION_ADD_BYTES_BYTES_INPLACE(operand1, operand2);
3694
3695 // Not every code path will make use of all possible results.
3696 NUITKA_MAY_BE_UNUSED PyObject *obj_result;
3697
3698 PyObject *x = PyBytes_Type.tp_as_sequence->sq_concat(*operand1, operand2);
3699 assert(x != Py_NotImplemented);
3700
3701 obj_result = x;
3702 goto exit_result_object;
3703
3704 exit_result_object:
3705 if (unlikely(obj_result == NULL)) {
3706 goto exit_result_exception;
3707 }
3708 // We got an object handed, that we have to release.
3709 Py_DECREF(*operand1);
3710
3711 *operand1 = obj_result;
3712 goto exit_result_ok;
3713
3714 exit_result_ok:
3715 return true;
3716
3717 exit_result_exception:
3718 return false;
3719 }
3720
3721 return __INPLACE_OPERATION_ADD_OBJECT_BYTES(operand1, operand2);
3722}
3723
3724bool INPLACE_OPERATION_ADD_OBJECT_BYTES(PyObject **operand1, PyObject *operand2) {
3725 return _INPLACE_OPERATION_ADD_OBJECT_BYTES(operand1, operand2);
3726}
3727#endif
3728
3729#if PYTHON_VERSION >= 0x300
3730/* Code referring to "BYTES" corresponds to Python3 'bytes' and "OBJECT" to any Python object. */
3731static HEDLEY_NEVER_INLINE bool __INPLACE_OPERATION_ADD_BYTES_OBJECT(PyObject **operand1, PyObject *operand2) {
3732 PyTypeObject *type2 = Py_TYPE(operand2);
3733
3734#if defined(_MSC_VER)
3735#pragma warning(push)
3736#pragma warning(disable : 4101)
3737#endif
3738 NUITKA_MAY_BE_UNUSED bool cbool_result;
3739 NUITKA_MAY_BE_UNUSED PyObject *obj_result;
3740#if defined(_MSC_VER)
3741#pragma warning(pop)
3742#endif
3743
3744 // No inplace number slot nb_inplace_add available for this type.
3745
3746 {
3747 binaryfunc slot2 = NULL;
3748
3749 if (!(&PyBytes_Type == type2)) {
3750 // Different types, need to consider second value slot.
3751
3752 slot2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_add : NULL;
3753 }
3754
3755 if (slot2 != NULL) {
3756 PyObject *x = slot2(*operand1, operand2);
3757
3758 if (x != Py_NotImplemented) {
3759 obj_result = x;
3760 goto exit_inplace_result_object;
3761 }
3762
3763 Py_DECREF_IMMORTAL(x);
3764 }
3765
3766#if PYTHON_VERSION < 0x300
3767 if (!0 || !NEW_STYLE_NUMBER_TYPE(type2)) {
3768 coercion c2 =
3769 (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_coerce : NULL;
3770
3771 if (c2 != NULL) {
3772 PyObject *coerced1 = *operand1;
3773 PyObject *coerced2 = operand2;
3774
3775 int err = c2(&coerced2, &coerced1);
3776
3777 if (unlikely(err < 0)) {
3778 goto exit_inplace_exception;
3779 }
3780
3781 if (err == 0) {
3782 PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number;
3783
3784 if (likely(mv == NULL)) {
3785 binaryfunc slot = mv->nb_add;
3786
3787 if (likely(slot != NULL)) {
3788 PyObject *x = slot(coerced1, coerced2);
3789
3790 Py_DECREF(coerced1);
3791 Py_DECREF(coerced2);
3792
3793 obj_result = x;
3794 goto exit_inplace_result_object;
3795 }
3796 }
3797
3798 // nb_coerce took a reference.
3799 Py_DECREF(coerced1);
3800 Py_DECREF(coerced2);
3801 }
3802 }
3803 }
3804#endif
3805
3806 {
3807 PyObject *o = PyBytes_Type.tp_as_sequence->sq_concat(*operand1, operand2);
3808 obj_result = o;
3809 goto exit_inplace_result_object;
3810 }
3811
3812 NUITKA_CANNOT_GET_HERE("missing error exit annotation");
3813 }
3814
3815exit_inplace_result_object:
3816 if (unlikely(obj_result == NULL)) {
3817 return false;
3818 }
3819
3820 // We got an object handed, that we have to release.
3821 Py_DECREF(*operand1);
3822
3823 // That's our return value then. As we use a dedicated variable, it's
3824 // OK that way.
3825 *operand1 = obj_result;
3826
3827 return true;
3828
3829#if PYTHON_VERSION < 0x300
3830exit_inplace_exception:
3831 return false;
3832#endif
3833}
3834static inline bool _INPLACE_OPERATION_ADD_BYTES_OBJECT(PyObject **operand1, PyObject *operand2) {
3835 assert(operand1); // Pointer must be non-null.
3836
3837 CHECK_OBJECT(*operand1);
3838 assert(PyBytes_CheckExact(*operand1));
3839 CHECK_OBJECT(operand2);
3840
3841 if (Py_REFCNT(*operand1) == 1) {
3842 // We more or less own the operand, so we might reuse its storage and
3843 // execute stuff in-place.
3844
3845#if PYTHON_VERSION >= 0x300
3846 if (1 && PyBytes_CheckExact(operand2)) {
3847 return BYTES_ADD_INCREMENTAL(operand1, operand2);
3848 }
3849#endif
3850 }
3851
3852 PyTypeObject *type2 = Py_TYPE(operand2);
3853
3854 if (&PyBytes_Type == type2) {
3855 // return _BINARY_OPERATION_ADD_BYTES_BYTES_INPLACE(operand1, operand2);
3856
3857 // Not every code path will make use of all possible results.
3858 NUITKA_MAY_BE_UNUSED PyObject *obj_result;
3859
3860 PyObject *x = PyBytes_Type.tp_as_sequence->sq_concat(*operand1, operand2);
3861 assert(x != Py_NotImplemented);
3862
3863 obj_result = x;
3864 goto exit_result_object;
3865
3866 exit_result_object:
3867 if (unlikely(obj_result == NULL)) {
3868 goto exit_result_exception;
3869 }
3870 // We got an object handed, that we have to release.
3871 Py_DECREF(*operand1);
3872
3873 *operand1 = obj_result;
3874 goto exit_result_ok;
3875
3876 exit_result_ok:
3877 return true;
3878
3879 exit_result_exception:
3880 return false;
3881 }
3882
3883 return __INPLACE_OPERATION_ADD_BYTES_OBJECT(operand1, operand2);
3884}
3885
3886bool INPLACE_OPERATION_ADD_BYTES_OBJECT(PyObject **operand1, PyObject *operand2) {
3887 return _INPLACE_OPERATION_ADD_BYTES_OBJECT(operand1, operand2);
3888}
3889#endif
3890
3891/* Code referring to "TUPLE" corresponds to Python 'tuple' and "TUPLE" to Python 'tuple'. */
3892static inline bool _INPLACE_OPERATION_ADD_TUPLE_TUPLE(PyObject **operand1, PyObject *operand2) {
3893 assert(operand1); // Pointer must be non-null.
3894
3895 CHECK_OBJECT(*operand1);
3896 assert(PyTuple_CheckExact(*operand1));
3897 CHECK_OBJECT(operand2);
3898 assert(PyTuple_CheckExact(operand2));
3899
3900 if (1 && 1) {
3901 PyObject *result = PySequence_InPlaceConcat(*operand1, operand2);
3902
3903 if (unlikely(result == NULL)) {
3904 return false;
3905 }
3906
3907 Py_DECREF(*operand1);
3908 *operand1 = result;
3909
3910 return true;
3911 }
3912
3913 // Not every code path will make use of all possible results.
3914 NUITKA_MAY_BE_UNUSED PyObject *obj_result;
3915
3916 // TODO: Have this more globally passed in
3917 PyThreadState *tstate = PyThreadState_GET();
3918
3919 PyObject *x = TUPLE_CONCAT(tstate, *operand1, operand2);
3920
3921 assert(x != Py_NotImplemented);
3922 obj_result = x;
3923 goto exit_result_object;
3924
3925exit_result_object:
3926 if (unlikely(obj_result == NULL)) {
3927 goto exit_result_exception;
3928 }
3929 // We got an object handed, that we have to release.
3930 Py_DECREF(*operand1);
3931
3932 *operand1 = obj_result;
3933 goto exit_result_ok;
3934
3935exit_result_ok:
3936 return true;
3937
3938exit_result_exception:
3939 return false;
3940}
3941
3942bool INPLACE_OPERATION_ADD_TUPLE_TUPLE(PyObject **operand1, PyObject *operand2) {
3943 return _INPLACE_OPERATION_ADD_TUPLE_TUPLE(operand1, operand2);
3944}
3945
3946/* Code referring to "OBJECT" corresponds to any Python object and "TUPLE" to Python 'tuple'. */
3947static HEDLEY_NEVER_INLINE bool __INPLACE_OPERATION_ADD_OBJECT_TUPLE(PyObject **operand1, PyObject *operand2) {
3948 PyTypeObject *type1 = Py_TYPE(*operand1);
3949
3950#if defined(_MSC_VER)
3951#pragma warning(push)
3952#pragma warning(disable : 4101)
3953#endif
3954 NUITKA_MAY_BE_UNUSED bool cbool_result;
3955 NUITKA_MAY_BE_UNUSED PyObject *obj_result;
3956#if defined(_MSC_VER)
3957#pragma warning(pop)
3958#endif
3959
3960 binaryfunc islot =
3961 (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_inplace_add : NULL;
3962
3963 if (islot != NULL) {
3964 PyObject *x = islot(*operand1, operand2);
3965
3966 if (x != Py_NotImplemented) {
3967 obj_result = x;
3968 goto exit_inplace_result_object;
3969 }
3970
3971 Py_DECREF_IMMORTAL(x);
3972 }
3973
3974 {
3975 binaryfunc slot1 =
3976 (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_add : NULL;
3977
3978 if (slot1 != NULL) {
3979 PyObject *x = slot1(*operand1, operand2);
3980
3981 if (x != Py_NotImplemented) {
3982 obj_result = x;
3983 goto exit_inplace_result_object;
3984 }
3985
3986 Py_DECREF_IMMORTAL(x);
3987 }
3988
3989#if PYTHON_VERSION < 0x300
3990 if (!NEW_STYLE_NUMBER_TYPE(type1) || !0) {
3991 coercion c1 =
3992 (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_coerce : NULL;
3993
3994 if (c1 != NULL) {
3995 PyObject *coerced1 = *operand1;
3996 PyObject *coerced2 = operand2;
3997
3998 int err = c1(&coerced1, &coerced2);
3999
4000 if (unlikely(err < 0)) {
4001 goto exit_inplace_exception;
4002 }
4003
4004 if (err == 0) {
4005 PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number;
4006
4007 if (likely(mv == NULL)) {
4008 binaryfunc slot = mv->nb_add;
4009
4010 if (likely(slot != NULL)) {
4011 PyObject *x = slot(coerced1, coerced2);
4012
4013 Py_DECREF(coerced1);
4014 Py_DECREF(coerced2);
4015
4016 obj_result = x;
4017 goto exit_inplace_result_object;
4018 }
4019 }
4020
4021 // nb_coerce took a reference.
4022 Py_DECREF(coerced1);
4023 Py_DECREF(coerced2);
4024 }
4025 }
4026 }
4027#endif
4028
4029 {
4030 // Special case for "+" and "*", also works as sequence concat/repeat.
4031 binaryfunc sq_slot = type1->tp_as_sequence != NULL ? type1->tp_as_sequence->sq_inplace_concat : NULL;
4032 if (sq_slot == NULL) {
4033 sq_slot = type1->tp_as_sequence != NULL ? type1->tp_as_sequence->sq_concat : NULL;
4034 }
4035
4036 if (sq_slot != NULL) {
4037 PyObject *result = sq_slot(*operand1, operand2);
4038
4039 obj_result = result;
4040 goto exit_inplace_result_object;
4041 }
4042 }
4043
4044 PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for +=: '%s' and 'tuple'", type1->tp_name);
4045 goto exit_inplace_exception;
4046 }
4047
4048exit_inplace_result_object:
4049 if (unlikely(obj_result == NULL)) {
4050 return false;
4051 }
4052
4053 // We got an object handed, that we have to release.
4054 Py_DECREF(*operand1);
4055
4056 // That's our return value then. As we use a dedicated variable, it's
4057 // OK that way.
4058 *operand1 = obj_result;
4059
4060 return true;
4061
4062exit_inplace_exception:
4063 return false;
4064}
4065static inline bool _INPLACE_OPERATION_ADD_OBJECT_TUPLE(PyObject **operand1, PyObject *operand2) {
4066 assert(operand1); // Pointer must be non-null.
4067
4068 CHECK_OBJECT(*operand1);
4069 CHECK_OBJECT(operand2);
4070 assert(PyTuple_CheckExact(operand2));
4071
4072 PyTypeObject *type1 = Py_TYPE(*operand1);
4073
4074 if (type1 == &PyTuple_Type) {
4075 // return _BINARY_OPERATION_ADD_TUPLE_TUPLE_INPLACE(operand1, operand2);
4076
4077 // Not every code path will make use of all possible results.
4078 NUITKA_MAY_BE_UNUSED PyObject *obj_result;
4079
4080 // TODO: Have this more globally passed in
4081 PyThreadState *tstate = PyThreadState_GET();
4082
4083 PyObject *x = TUPLE_CONCAT(tstate, *operand1, operand2);
4084
4085 assert(x != Py_NotImplemented);
4086 obj_result = x;
4087 goto exit_result_object;
4088
4089 exit_result_object:
4090 if (unlikely(obj_result == NULL)) {
4091 goto exit_result_exception;
4092 }
4093 // We got an object handed, that we have to release.
4094 Py_DECREF(*operand1);
4095
4096 *operand1 = obj_result;
4097 goto exit_result_ok;
4098
4099 exit_result_ok:
4100 return true;
4101
4102 exit_result_exception:
4103 return false;
4104 }
4105
4106 return __INPLACE_OPERATION_ADD_OBJECT_TUPLE(operand1, operand2);
4107}
4108
4109bool INPLACE_OPERATION_ADD_OBJECT_TUPLE(PyObject **operand1, PyObject *operand2) {
4110 return _INPLACE_OPERATION_ADD_OBJECT_TUPLE(operand1, operand2);
4111}
4112
4113/* Code referring to "TUPLE" corresponds to Python 'tuple' and "OBJECT" to any Python object. */
4114static HEDLEY_NEVER_INLINE bool __INPLACE_OPERATION_ADD_TUPLE_OBJECT(PyObject **operand1, PyObject *operand2) {
4115 PyTypeObject *type2 = Py_TYPE(operand2);
4116
4117#if defined(_MSC_VER)
4118#pragma warning(push)
4119#pragma warning(disable : 4101)
4120#endif
4121 NUITKA_MAY_BE_UNUSED bool cbool_result;
4122 NUITKA_MAY_BE_UNUSED PyObject *obj_result;
4123#if defined(_MSC_VER)
4124#pragma warning(pop)
4125#endif
4126
4127 // No inplace number slot nb_inplace_add available for this type.
4128
4129 {
4130 binaryfunc slot2 = NULL;
4131
4132 if (!(&PyTuple_Type == type2)) {
4133 // Different types, need to consider second value slot.
4134
4135 slot2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_add : NULL;
4136 }
4137
4138 if (slot2 != NULL) {
4139 PyObject *x = slot2(*operand1, operand2);
4140
4141 if (x != Py_NotImplemented) {
4142 obj_result = x;
4143 goto exit_inplace_result_object;
4144 }
4145
4146 Py_DECREF_IMMORTAL(x);
4147 }
4148
4149#if PYTHON_VERSION < 0x300
4150 if (!0 || !NEW_STYLE_NUMBER_TYPE(type2)) {
4151 coercion c2 =
4152 (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_coerce : NULL;
4153
4154 if (c2 != NULL) {
4155 PyObject *coerced1 = *operand1;
4156 PyObject *coerced2 = operand2;
4157
4158 int err = c2(&coerced2, &coerced1);
4159
4160 if (unlikely(err < 0)) {
4161 goto exit_inplace_exception;
4162 }
4163
4164 if (err == 0) {
4165 PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number;
4166
4167 if (likely(mv == NULL)) {
4168 binaryfunc slot = mv->nb_add;
4169
4170 if (likely(slot != NULL)) {
4171 PyObject *x = slot(coerced1, coerced2);
4172
4173 Py_DECREF(coerced1);
4174 Py_DECREF(coerced2);
4175
4176 obj_result = x;
4177 goto exit_inplace_result_object;
4178 }
4179 }
4180
4181 // nb_coerce took a reference.
4182 Py_DECREF(coerced1);
4183 Py_DECREF(coerced2);
4184 }
4185 }
4186 }
4187#endif
4188
4189 {
4190 PyObject *o = PyTuple_Type.tp_as_sequence->sq_concat(*operand1, operand2);
4191 obj_result = o;
4192 goto exit_inplace_result_object;
4193 }
4194
4195 NUITKA_CANNOT_GET_HERE("missing error exit annotation");
4196 }
4197
4198exit_inplace_result_object:
4199 if (unlikely(obj_result == NULL)) {
4200 return false;
4201 }
4202
4203 // We got an object handed, that we have to release.
4204 Py_DECREF(*operand1);
4205
4206 // That's our return value then. As we use a dedicated variable, it's
4207 // OK that way.
4208 *operand1 = obj_result;
4209
4210 return true;
4211
4212#if PYTHON_VERSION < 0x300
4213exit_inplace_exception:
4214 return false;
4215#endif
4216}
4217static inline bool _INPLACE_OPERATION_ADD_TUPLE_OBJECT(PyObject **operand1, PyObject *operand2) {
4218 assert(operand1); // Pointer must be non-null.
4219
4220 CHECK_OBJECT(*operand1);
4221 assert(PyTuple_CheckExact(*operand1));
4222 CHECK_OBJECT(operand2);
4223
4224 if (1 && (PyTuple_CheckExact(operand2) || PySequence_Check(operand2))) {
4225 PyObject *result = PySequence_InPlaceConcat(*operand1, operand2);
4226
4227 if (unlikely(result == NULL)) {
4228 return false;
4229 }
4230
4231 Py_DECREF(*operand1);
4232 *operand1 = result;
4233
4234 return true;
4235 }
4236
4237 PyTypeObject *type2 = Py_TYPE(operand2);
4238
4239 if (&PyTuple_Type == type2) {
4240 // return _BINARY_OPERATION_ADD_TUPLE_TUPLE_INPLACE(operand1, operand2);
4241
4242 // Not every code path will make use of all possible results.
4243 NUITKA_MAY_BE_UNUSED PyObject *obj_result;
4244
4245 // TODO: Have this more globally passed in
4246 PyThreadState *tstate = PyThreadState_GET();
4247
4248 PyObject *x = TUPLE_CONCAT(tstate, *operand1, operand2);
4249
4250 assert(x != Py_NotImplemented);
4251 obj_result = x;
4252 goto exit_result_object;
4253
4254 exit_result_object:
4255 if (unlikely(obj_result == NULL)) {
4256 goto exit_result_exception;
4257 }
4258 // We got an object handed, that we have to release.
4259 Py_DECREF(*operand1);
4260
4261 *operand1 = obj_result;
4262 goto exit_result_ok;
4263
4264 exit_result_ok:
4265 return true;
4266
4267 exit_result_exception:
4268 return false;
4269 }
4270
4271 return __INPLACE_OPERATION_ADD_TUPLE_OBJECT(operand1, operand2);
4272}
4273
4274bool INPLACE_OPERATION_ADD_TUPLE_OBJECT(PyObject **operand1, PyObject *operand2) {
4275 return _INPLACE_OPERATION_ADD_TUPLE_OBJECT(operand1, operand2);
4276}
4277
4278/* Code referring to "LIST" corresponds to Python 'list' and "LIST" to Python 'list'. */
4279static inline bool _INPLACE_OPERATION_ADD_LIST_LIST(PyObject **operand1, PyObject *operand2) {
4280 assert(operand1); // Pointer must be non-null.
4281
4282 CHECK_OBJECT(*operand1);
4283 assert(PyList_CheckExact(*operand1));
4284 CHECK_OBJECT(operand2);
4285 assert(PyList_CheckExact(operand2));
4286
4287 if (1 && 1) {
4288 return LIST_EXTEND_FROM_LIST(*operand1, operand2);
4289 }
4290
4291 if (1 && 1) {
4292 PyObject *result = PySequence_InPlaceConcat(*operand1, operand2);
4293
4294 if (unlikely(result == NULL)) {
4295 return false;
4296 }
4297
4298 Py_DECREF(*operand1);
4299 *operand1 = result;
4300
4301 return true;
4302 }
4303
4304 // Not every code path will make use of all possible results.
4305 NUITKA_MAY_BE_UNUSED PyObject *obj_result;
4306
4307 // TODO: Have this more globally passed in
4308 PyThreadState *tstate = PyThreadState_GET();
4309
4310 PyObject *x = LIST_CONCAT(tstate, *operand1, operand2);
4311 assert(x != Py_NotImplemented);
4312
4313 obj_result = x;
4314 goto exit_result_object;
4315
4316exit_result_object:
4317 if (unlikely(obj_result == NULL)) {
4318 goto exit_result_exception;
4319 }
4320
4321 // We got an object handed, that we have to release.
4322 Py_DECREF(*operand1);
4323
4324 *operand1 = obj_result;
4325 goto exit_result_ok;
4326
4327exit_result_ok:
4328 return true;
4329
4330exit_result_exception:
4331 return false;
4332}
4333
4334bool INPLACE_OPERATION_ADD_LIST_LIST(PyObject **operand1, PyObject *operand2) {
4335 return _INPLACE_OPERATION_ADD_LIST_LIST(operand1, operand2);
4336}
4337
4338/* Code referring to "OBJECT" corresponds to any Python object and "LIST" to Python 'list'. */
4339static HEDLEY_NEVER_INLINE bool __INPLACE_OPERATION_ADD_OBJECT_LIST(PyObject **operand1, PyObject *operand2) {
4340 PyTypeObject *type1 = Py_TYPE(*operand1);
4341
4342#if defined(_MSC_VER)
4343#pragma warning(push)
4344#pragma warning(disable : 4101)
4345#endif
4346 NUITKA_MAY_BE_UNUSED bool cbool_result;
4347 NUITKA_MAY_BE_UNUSED PyObject *obj_result;
4348#if defined(_MSC_VER)
4349#pragma warning(pop)
4350#endif
4351
4352 binaryfunc islot =
4353 (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_inplace_add : NULL;
4354
4355 if (islot != NULL) {
4356 PyObject *x = islot(*operand1, operand2);
4357
4358 if (x != Py_NotImplemented) {
4359 obj_result = x;
4360 goto exit_inplace_result_object;
4361 }
4362
4363 Py_DECREF_IMMORTAL(x);
4364 }
4365
4366 {
4367 binaryfunc slot1 =
4368 (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_add : NULL;
4369
4370 if (slot1 != NULL) {
4371 PyObject *x = slot1(*operand1, operand2);
4372
4373 if (x != Py_NotImplemented) {
4374 obj_result = x;
4375 goto exit_inplace_result_object;
4376 }
4377
4378 Py_DECREF_IMMORTAL(x);
4379 }
4380
4381#if PYTHON_VERSION < 0x300
4382 if (!NEW_STYLE_NUMBER_TYPE(type1) || !0) {
4383 coercion c1 =
4384 (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_coerce : NULL;
4385
4386 if (c1 != NULL) {
4387 PyObject *coerced1 = *operand1;
4388 PyObject *coerced2 = operand2;
4389
4390 int err = c1(&coerced1, &coerced2);
4391
4392 if (unlikely(err < 0)) {
4393 goto exit_inplace_exception;
4394 }
4395
4396 if (err == 0) {
4397 PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number;
4398
4399 if (likely(mv == NULL)) {
4400 binaryfunc slot = mv->nb_add;
4401
4402 if (likely(slot != NULL)) {
4403 PyObject *x = slot(coerced1, coerced2);
4404
4405 Py_DECREF(coerced1);
4406 Py_DECREF(coerced2);
4407
4408 obj_result = x;
4409 goto exit_inplace_result_object;
4410 }
4411 }
4412
4413 // nb_coerce took a reference.
4414 Py_DECREF(coerced1);
4415 Py_DECREF(coerced2);
4416 }
4417 }
4418 }
4419#endif
4420
4421 {
4422 // Special case for "+" and "*", also works as sequence concat/repeat.
4423 binaryfunc sq_slot = type1->tp_as_sequence != NULL ? type1->tp_as_sequence->sq_inplace_concat : NULL;
4424 if (sq_slot == NULL) {
4425 sq_slot = type1->tp_as_sequence != NULL ? type1->tp_as_sequence->sq_concat : NULL;
4426 }
4427
4428 if (sq_slot != NULL) {
4429 PyObject *result = sq_slot(*operand1, operand2);
4430
4431 obj_result = result;
4432 goto exit_inplace_result_object;
4433 }
4434 }
4435
4436 PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for +=: '%s' and 'list'", type1->tp_name);
4437 goto exit_inplace_exception;
4438 }
4439
4440exit_inplace_result_object:
4441 if (unlikely(obj_result == NULL)) {
4442 return false;
4443 }
4444
4445 // We got an object handed, that we have to release.
4446 Py_DECREF(*operand1);
4447
4448 // That's our return value then. As we use a dedicated variable, it's
4449 // OK that way.
4450 *operand1 = obj_result;
4451
4452 return true;
4453
4454exit_inplace_exception:
4455 return false;
4456}
4457static inline bool _INPLACE_OPERATION_ADD_OBJECT_LIST(PyObject **operand1, PyObject *operand2) {
4458 assert(operand1); // Pointer must be non-null.
4459
4460 CHECK_OBJECT(*operand1);
4461 CHECK_OBJECT(operand2);
4462 assert(PyList_CheckExact(operand2));
4463
4464 if (PyList_CheckExact(*operand1) && 1) {
4465 return LIST_EXTEND_FROM_LIST(*operand1, operand2);
4466 }
4467
4468 PyTypeObject *type1 = Py_TYPE(*operand1);
4469
4470 if (type1 == &PyList_Type) {
4471 // return _BINARY_OPERATION_ADD_LIST_LIST_INPLACE(operand1, operand2);
4472
4473 // Not every code path will make use of all possible results.
4474 NUITKA_MAY_BE_UNUSED PyObject *obj_result;
4475
4476 // TODO: Have this more globally passed in
4477 PyThreadState *tstate = PyThreadState_GET();
4478
4479 PyObject *x = LIST_CONCAT(tstate, *operand1, operand2);
4480 assert(x != Py_NotImplemented);
4481
4482 obj_result = x;
4483 goto exit_result_object;
4484
4485 exit_result_object:
4486 if (unlikely(obj_result == NULL)) {
4487 goto exit_result_exception;
4488 }
4489
4490 // We got an object handed, that we have to release.
4491 Py_DECREF(*operand1);
4492
4493 *operand1 = obj_result;
4494 goto exit_result_ok;
4495
4496 exit_result_ok:
4497 return true;
4498
4499 exit_result_exception:
4500 return false;
4501 }
4502
4503 return __INPLACE_OPERATION_ADD_OBJECT_LIST(operand1, operand2);
4504}
4505
4506bool INPLACE_OPERATION_ADD_OBJECT_LIST(PyObject **operand1, PyObject *operand2) {
4507 return _INPLACE_OPERATION_ADD_OBJECT_LIST(operand1, operand2);
4508}
4509
4510/* Code referring to "LIST" corresponds to Python 'list' and "OBJECT" to any Python object. */
4511static HEDLEY_NEVER_INLINE bool __INPLACE_OPERATION_ADD_LIST_OBJECT(PyObject **operand1, PyObject *operand2) {
4512 PyTypeObject *type2 = Py_TYPE(operand2);
4513
4514#if defined(_MSC_VER)
4515#pragma warning(push)
4516#pragma warning(disable : 4101)
4517#endif
4518 NUITKA_MAY_BE_UNUSED bool cbool_result;
4519 NUITKA_MAY_BE_UNUSED PyObject *obj_result;
4520#if defined(_MSC_VER)
4521#pragma warning(pop)
4522#endif
4523
4524 // No inplace number slot nb_inplace_add available for this type.
4525
4526 {
4527 binaryfunc slot2 = NULL;
4528
4529 if (!(&PyList_Type == type2)) {
4530 // Different types, need to consider second value slot.
4531
4532 slot2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_add : NULL;
4533 }
4534
4535 if (slot2 != NULL) {
4536 PyObject *x = slot2(*operand1, operand2);
4537
4538 if (x != Py_NotImplemented) {
4539 obj_result = x;
4540 goto exit_inplace_result_object;
4541 }
4542
4543 Py_DECREF_IMMORTAL(x);
4544 }
4545
4546#if PYTHON_VERSION < 0x300
4547 if (!0 || !NEW_STYLE_NUMBER_TYPE(type2)) {
4548 coercion c2 =
4549 (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_coerce : NULL;
4550
4551 if (c2 != NULL) {
4552 PyObject *coerced1 = *operand1;
4553 PyObject *coerced2 = operand2;
4554
4555 int err = c2(&coerced2, &coerced1);
4556
4557 if (unlikely(err < 0)) {
4558 goto exit_inplace_exception;
4559 }
4560
4561 if (err == 0) {
4562 PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number;
4563
4564 if (likely(mv == NULL)) {
4565 binaryfunc slot = mv->nb_add;
4566
4567 if (likely(slot != NULL)) {
4568 PyObject *x = slot(coerced1, coerced2);
4569
4570 Py_DECREF(coerced1);
4571 Py_DECREF(coerced2);
4572
4573 obj_result = x;
4574 goto exit_inplace_result_object;
4575 }
4576 }
4577
4578 // nb_coerce took a reference.
4579 Py_DECREF(coerced1);
4580 Py_DECREF(coerced2);
4581 }
4582 }
4583 }
4584#endif
4585
4586 {
4587 PyObject *o = PyList_Type.tp_as_sequence->sq_inplace_concat(*operand1, operand2);
4588 obj_result = o;
4589 goto exit_inplace_result_object;
4590 }
4591 {
4592 PyObject *o = PyList_Type.tp_as_sequence->sq_concat(*operand1, operand2);
4593 obj_result = o;
4594 goto exit_inplace_result_object;
4595 }
4596
4597 NUITKA_CANNOT_GET_HERE("missing error exit annotation");
4598 }
4599
4600exit_inplace_result_object:
4601 if (unlikely(obj_result == NULL)) {
4602 return false;
4603 }
4604
4605 // We got an object handed, that we have to release.
4606 Py_DECREF(*operand1);
4607
4608 // That's our return value then. As we use a dedicated variable, it's
4609 // OK that way.
4610 *operand1 = obj_result;
4611
4612 return true;
4613
4614#if PYTHON_VERSION < 0x300
4615exit_inplace_exception:
4616 return false;
4617#endif
4618}
4619static inline bool _INPLACE_OPERATION_ADD_LIST_OBJECT(PyObject **operand1, PyObject *operand2) {
4620 assert(operand1); // Pointer must be non-null.
4621
4622 CHECK_OBJECT(*operand1);
4623 assert(PyList_CheckExact(*operand1));
4624 CHECK_OBJECT(operand2);
4625
4626 if (1 && PyList_CheckExact(operand2)) {
4627 return LIST_EXTEND_FROM_LIST(*operand1, operand2);
4628 }
4629
4630 if (1 && PySequence_Check(operand2)) {
4631 PyObject *result = PySequence_InPlaceConcat(*operand1, operand2);
4632
4633 if (unlikely(result == NULL)) {
4634 return false;
4635 }
4636
4637 Py_DECREF(*operand1);
4638 *operand1 = result;
4639
4640 return true;
4641 }
4642
4643 PyTypeObject *type2 = Py_TYPE(operand2);
4644
4645 if (&PyList_Type == type2) {
4646 // return _BINARY_OPERATION_ADD_LIST_LIST_INPLACE(operand1, operand2);
4647
4648 // Not every code path will make use of all possible results.
4649 NUITKA_MAY_BE_UNUSED PyObject *obj_result;
4650
4651 // TODO: Have this more globally passed in
4652 PyThreadState *tstate = PyThreadState_GET();
4653
4654 PyObject *x = LIST_CONCAT(tstate, *operand1, operand2);
4655 assert(x != Py_NotImplemented);
4656
4657 obj_result = x;
4658 goto exit_result_object;
4659
4660 exit_result_object:
4661 if (unlikely(obj_result == NULL)) {
4662 goto exit_result_exception;
4663 }
4664
4665 // We got an object handed, that we have to release.
4666 Py_DECREF(*operand1);
4667
4668 *operand1 = obj_result;
4669 goto exit_result_ok;
4670
4671 exit_result_ok:
4672 return true;
4673
4674 exit_result_exception:
4675 return false;
4676 }
4677
4678 return __INPLACE_OPERATION_ADD_LIST_OBJECT(operand1, operand2);
4679}
4680
4681bool INPLACE_OPERATION_ADD_LIST_OBJECT(PyObject **operand1, PyObject *operand2) {
4682 return _INPLACE_OPERATION_ADD_LIST_OBJECT(operand1, operand2);
4683}
4684
4685#if PYTHON_VERSION < 0x300
4686/* Code referring to "UNICODE" corresponds to Python2 'unicode', Python3 'str' and "STR" to Python2 'str'. */
4687static inline bool _INPLACE_OPERATION_ADD_UNICODE_STR(PyObject **operand1, PyObject *operand2) {
4688 assert(operand1); // Pointer must be non-null.
4689
4690 CHECK_OBJECT(*operand1);
4691 assert(PyUnicode_CheckExact(*operand1));
4692 CHECK_OBJECT(operand2);
4693 assert(PyString_CheckExact(operand2));
4694
4695#if defined(_MSC_VER)
4696#pragma warning(push)
4697#pragma warning(disable : 4101)
4698#endif
4699 NUITKA_MAY_BE_UNUSED bool cbool_result;
4700 NUITKA_MAY_BE_UNUSED PyObject *obj_result;
4701#if defined(_MSC_VER)
4702#pragma warning(pop)
4703#endif
4704
4705 // No inplace number slot nb_inplace_add available for this type.
4706
4707 {
4708
4709 // Statically recognized that coercion is not possible with these types
4710
4711 {
4712 PyObject *o = PyUnicode_Type.tp_as_sequence->sq_concat(*operand1, operand2);
4713 obj_result = o;
4714 goto exit_inplace_result_object;
4715 }
4716
4717 NUITKA_CANNOT_GET_HERE("missing error exit annotation");
4718 }
4719
4720exit_inplace_result_object:
4721 if (unlikely(obj_result == NULL)) {
4722 return false;
4723 }
4724
4725 // We got an object handed, that we have to release.
4726 Py_DECREF(*operand1);
4727
4728 // That's our return value then. As we use a dedicated variable, it's
4729 // OK that way.
4730 *operand1 = obj_result;
4731
4732 return true;
4733}
4734
4735bool INPLACE_OPERATION_ADD_UNICODE_STR(PyObject **operand1, PyObject *operand2) {
4736 return _INPLACE_OPERATION_ADD_UNICODE_STR(operand1, operand2);
4737}
4738#endif
4739
4740#if PYTHON_VERSION < 0x300
4741/* Code referring to "STR" corresponds to Python2 'str' and "UNICODE" to Python2 'unicode', Python3 'str'. */
4742static inline bool _INPLACE_OPERATION_ADD_STR_UNICODE(PyObject **operand1, PyObject *operand2) {
4743 assert(operand1); // Pointer must be non-null.
4744
4745 CHECK_OBJECT(*operand1);
4746 assert(PyString_CheckExact(*operand1));
4747 CHECK_OBJECT(operand2);
4748 assert(PyUnicode_CheckExact(operand2));
4749
4750#if defined(_MSC_VER)
4751#pragma warning(push)
4752#pragma warning(disable : 4101)
4753#endif
4754 NUITKA_MAY_BE_UNUSED bool cbool_result;
4755 NUITKA_MAY_BE_UNUSED PyObject *obj_result;
4756#if defined(_MSC_VER)
4757#pragma warning(pop)
4758#endif
4759
4760 // No inplace number slot nb_inplace_add available for this type.
4761
4762 {
4763
4764 // Statically recognized that coercion is not possible with these types
4765
4766 {
4767 PyObject *o = PyUnicode_Type.tp_as_sequence->sq_concat(*operand1, operand2);
4768 obj_result = o;
4769 goto exit_inplace_result_object;
4770 }
4771
4772 NUITKA_CANNOT_GET_HERE("missing error exit annotation");
4773 }
4774
4775exit_inplace_result_object:
4776 if (unlikely(obj_result == NULL)) {
4777 return false;
4778 }
4779
4780 // We got an object handed, that we have to release.
4781 Py_DECREF(*operand1);
4782
4783 // That's our return value then. As we use a dedicated variable, it's
4784 // OK that way.
4785 *operand1 = obj_result;
4786
4787 return true;
4788}
4789
4790bool INPLACE_OPERATION_ADD_STR_UNICODE(PyObject **operand1, PyObject *operand2) {
4791 return _INPLACE_OPERATION_ADD_STR_UNICODE(operand1, operand2);
4792}
4793#endif
4794
4795/* Code referring to "OBJECT" corresponds to any Python object and "OBJECT" to any Python object. */
4796static inline bool _INPLACE_OPERATION_ADD_OBJECT_OBJECT(PyObject **operand1, PyObject *operand2) {
4797 assert(operand1); // Pointer must be non-null.
4798
4799 CHECK_OBJECT(*operand1);
4800 CHECK_OBJECT(operand2);
4801
4802#if PYTHON_VERSION < 0x300
4803 if (PyInt_CheckExact(*operand1) && PyInt_CheckExact(operand2)) {
4804
4805 // Not every code path will make use of all possible results.
4806#if defined(_MSC_VER)
4807#pragma warning(push)
4808#pragma warning(disable : 4101)
4809#endif
4810 NUITKA_MAY_BE_UNUSED bool cbool_result;
4811 NUITKA_MAY_BE_UNUSED PyObject *obj_result;
4812 NUITKA_MAY_BE_UNUSED long clong_result;
4813 NUITKA_MAY_BE_UNUSED double cfloat_result;
4814#if defined(_MSC_VER)
4815#pragma warning(pop)
4816#endif
4817
4818 CHECK_OBJECT(*operand1);
4819 assert(PyInt_CheckExact(*operand1));
4820 CHECK_OBJECT(operand2);
4821 assert(PyInt_CheckExact(operand2));
4822
4823 const long a = PyInt_AS_LONG(*operand1);
4824 const long b = PyInt_AS_LONG(operand2);
4825
4826 const long x = (long)((unsigned long)a + b);
4827 bool no_overflow = ((x ^ a) >= 0 || (x ^ b) >= 0);
4828 if (likely(no_overflow)) {
4829 clong_result = x;
4830 goto exit_result_ok_clong;
4831 }
4832
4833 {
4834 PyObject *operand1_object = *operand1;
4835 PyObject *operand2_object = operand2;
4836
4837 PyObject *r = PyLong_Type.tp_as_number->nb_add(operand1_object, operand2_object);
4838 assert(r != Py_NotImplemented);
4839
4840 obj_result = r;
4841 goto exit_result_object;
4842 }
4843
4844 exit_result_ok_clong:
4845
4846 // We got an object handed, that we have to release.
4847 Py_DECREF(*operand1);
4848
4849 // That's our return value then. As we use a dedicated variable, it's
4850 // OK that way.
4851 *operand1 = Nuitka_PyInt_FromLong(clong_result);
4852 goto exit_result_ok;
4853
4854 exit_result_object:
4855 if (unlikely(obj_result == NULL)) {
4856 goto exit_result_exception;
4857 }
4858 // We got an object handed, that we have to release.
4859 Py_DECREF(*operand1);
4860
4861 *operand1 = obj_result;
4862 goto exit_result_ok;
4863
4864 exit_result_ok:
4865 return true;
4866
4867 exit_result_exception:
4868 return false;
4869 }
4870#endif
4871
4872 if (Py_REFCNT(*operand1) == 1) {
4873 // We more or less own the operand, so we might reuse its storage and
4874 // execute stuff in-place.
4875#if PYTHON_VERSION < 0x300
4876 if (PyString_CheckExact(*operand1) && !PyString_CHECK_INTERNED(*operand1) && PyString_CheckExact(operand2)) {
4877 return STRING_ADD_INPLACE(operand1, operand2);
4878 }
4879#endif
4880
4881#if PYTHON_VERSION >= 0x300
4882 if (PyUnicode_CheckExact(*operand1) && !PyUnicode_CHECK_INTERNED(*operand1) && PyUnicode_CheckExact(operand2)) {
4883 // TODO: Push outward.
4884 PyThreadState *tstate = PyThreadState_GET();
4885
4886 return UNICODE_ADD_INCREMENTAL(tstate, operand1, operand2);
4887 }
4888#endif
4889 }
4890
4891 if (Py_TYPE(*operand1) == Py_TYPE(operand2)) {
4892 if (PyFloat_CheckExact(operand2)) {
4893 return _INPLACE_OPERATION_ADD_FLOAT_FLOAT(operand1, operand2);
4894 }
4895#if PYTHON_VERSION >= 0x300
4896 if (PyLong_CheckExact(operand2)) {
4897 return _INPLACE_OPERATION_ADD_LONG_LONG(operand1, operand2);
4898 }
4899#endif
4900 }
4901
4902#if PYTHON_VERSION < 0x300
4903 // Python2 strings are to be treated differently, fall back to Python API here.
4904 if (PyString_CheckExact(*operand1) && PyString_CheckExact(operand2)) {
4905 PyString_Concat(operand1, operand2);
4906
4907 // TODO: Have this more globally passed in
4908 PyThreadState *tstate = PyThreadState_GET();
4909
4910 return !HAS_ERROR_OCCURRED(tstate);
4911 }
4912#endif
4913#if PYTHON_VERSION >= 0x300
4914 // Python3 Strings are to be treated differently.
4915 if (PyUnicode_CheckExact(*operand1) && PyUnicode_CheckExact(operand2)) {
4916 // TODO: Have this more globally passed in
4917 PyThreadState *tstate = PyThreadState_GET();
4918
4919 PyObject *result = UNICODE_CONCAT(tstate, *operand1, operand2);
4920
4921 if (unlikely(result == NULL)) {
4922 return false;
4923 }
4924
4925 Py_DECREF(*operand1);
4926 *operand1 = result;
4927
4928 return true;
4929 }
4930#endif
4931
4932 PyTypeObject *type1 = Py_TYPE(*operand1);
4933 PyTypeObject *type2 = Py_TYPE(operand2);
4934
4935#if defined(_MSC_VER)
4936#pragma warning(push)
4937#pragma warning(disable : 4101)
4938#endif
4939 NUITKA_MAY_BE_UNUSED bool cbool_result;
4940 NUITKA_MAY_BE_UNUSED PyObject *obj_result;
4941#if defined(_MSC_VER)
4942#pragma warning(pop)
4943#endif
4944
4945 binaryfunc islot =
4946 (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_inplace_add : NULL;
4947
4948 if (islot != NULL) {
4949 PyObject *x = islot(*operand1, operand2);
4950
4951 if (x != Py_NotImplemented) {
4952 obj_result = x;
4953 goto exit_inplace_result_object;
4954 }
4955
4956 Py_DECREF_IMMORTAL(x);
4957 }
4958
4959 {
4960 binaryfunc slot1 =
4961 (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_add : NULL;
4962 binaryfunc slot2 = NULL;
4963
4964 if (!(type1 == type2)) {
4965 // Different types, need to consider second value slot.
4966
4967 slot2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_add : NULL;
4968
4969 if (slot1 == slot2) {
4970 slot2 = NULL;
4971 }
4972 }
4973
4974 if (slot1 != NULL) {
4975 if (slot2 != NULL) {
4976 if (Nuitka_Type_IsSubtype(type2, type1)) {
4977 PyObject *x = slot2(*operand1, operand2);
4978
4979 if (x != Py_NotImplemented) {
4980 obj_result = x;
4981 goto exit_inplace_result_object;
4982 }
4983
4984 Py_DECREF_IMMORTAL(x);
4985 slot2 = NULL;
4986 }
4987 }
4988
4989 PyObject *x = slot1(*operand1, operand2);
4990
4991 if (x != Py_NotImplemented) {
4992 obj_result = x;
4993 goto exit_inplace_result_object;
4994 }
4995
4996 Py_DECREF_IMMORTAL(x);
4997 }
4998
4999 if (slot2 != NULL) {
5000 PyObject *x = slot2(*operand1, operand2);
5001
5002 if (x != Py_NotImplemented) {
5003 obj_result = x;
5004 goto exit_inplace_result_object;
5005 }
5006
5007 Py_DECREF_IMMORTAL(x);
5008 }
5009
5010#if PYTHON_VERSION < 0x300
5011 if (!NEW_STYLE_NUMBER_TYPE(type1) || !NEW_STYLE_NUMBER_TYPE(type2)) {
5012 coercion c1 =
5013 (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_coerce : NULL;
5014
5015 if (c1 != NULL) {
5016 PyObject *coerced1 = *operand1;
5017 PyObject *coerced2 = operand2;
5018
5019 int err = c1(&coerced1, &coerced2);
5020
5021 if (unlikely(err < 0)) {
5022 goto exit_inplace_exception;
5023 }
5024
5025 if (err == 0) {
5026 PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number;
5027
5028 if (likely(mv == NULL)) {
5029 binaryfunc slot = mv->nb_add;
5030
5031 if (likely(slot != NULL)) {
5032 PyObject *x = slot(coerced1, coerced2);
5033
5034 Py_DECREF(coerced1);
5035 Py_DECREF(coerced2);
5036
5037 obj_result = x;
5038 goto exit_inplace_result_object;
5039 }
5040 }
5041
5042 // nb_coerce took a reference.
5043 Py_DECREF(coerced1);
5044 Py_DECREF(coerced2);
5045 }
5046 }
5047 coercion c2 =
5048 (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_coerce : NULL;
5049
5050 if (c2 != NULL) {
5051 PyObject *coerced1 = *operand1;
5052 PyObject *coerced2 = operand2;
5053
5054 int err = c2(&coerced2, &coerced1);
5055
5056 if (unlikely(err < 0)) {
5057 goto exit_inplace_exception;
5058 }
5059
5060 if (err == 0) {
5061 PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number;
5062
5063 if (likely(mv == NULL)) {
5064 binaryfunc slot = mv->nb_add;
5065
5066 if (likely(slot != NULL)) {
5067 PyObject *x = slot(coerced1, coerced2);
5068
5069 Py_DECREF(coerced1);
5070 Py_DECREF(coerced2);
5071
5072 obj_result = x;
5073 goto exit_inplace_result_object;
5074 }
5075 }
5076
5077 // nb_coerce took a reference.
5078 Py_DECREF(coerced1);
5079 Py_DECREF(coerced2);
5080 }
5081 }
5082 }
5083#endif
5084
5085 {
5086 // Special case for "+" and "*", also works as sequence concat/repeat.
5087 binaryfunc sq_slot = type1->tp_as_sequence != NULL ? type1->tp_as_sequence->sq_inplace_concat : NULL;
5088 if (sq_slot == NULL) {
5089 sq_slot = type1->tp_as_sequence != NULL ? type1->tp_as_sequence->sq_concat : NULL;
5090 }
5091
5092 if (sq_slot != NULL) {
5093 PyObject *result = sq_slot(*operand1, operand2);
5094
5095 obj_result = result;
5096 goto exit_inplace_result_object;
5097 }
5098 }
5099
5100 PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for +=: '%s' and '%s'", type1->tp_name,
5101 type2->tp_name);
5102 goto exit_inplace_exception;
5103 }
5104
5105exit_inplace_result_object:
5106 if (unlikely(obj_result == NULL)) {
5107 return false;
5108 }
5109
5110 // We got an object handed, that we have to release.
5111 Py_DECREF(*operand1);
5112
5113 // That's our return value then. As we use a dedicated variable, it's
5114 // OK that way.
5115 *operand1 = obj_result;
5116
5117 return true;
5118
5119exit_inplace_exception:
5120 return false;
5121}
5122
5123bool INPLACE_OPERATION_ADD_OBJECT_OBJECT(PyObject **operand1, PyObject *operand2) {
5124 return _INPLACE_OPERATION_ADD_OBJECT_OBJECT(operand1, operand2);
5125}
5126
5127/* Code referring to "LIST" corresponds to Python 'list' and "TUPLE" to Python 'tuple'. */
5128static inline bool _INPLACE_OPERATION_ADD_LIST_TUPLE(PyObject **operand1, PyObject *operand2) {
5129 assert(operand1); // Pointer must be non-null.
5130
5131 CHECK_OBJECT(*operand1);
5132 assert(PyList_CheckExact(*operand1));
5133 CHECK_OBJECT(operand2);
5134 assert(PyTuple_CheckExact(operand2));
5135
5136 if (1 && 1) {
5137 PyObject *result = PySequence_InPlaceConcat(*operand1, operand2);
5138
5139 if (unlikely(result == NULL)) {
5140 return false;
5141 }
5142
5143 Py_DECREF(*operand1);
5144 *operand1 = result;
5145
5146 return true;
5147 }
5148
5149#if defined(_MSC_VER)
5150#pragma warning(push)
5151#pragma warning(disable : 4101)
5152#endif
5153 NUITKA_MAY_BE_UNUSED bool cbool_result;
5154 NUITKA_MAY_BE_UNUSED PyObject *obj_result;
5155#if defined(_MSC_VER)
5156#pragma warning(pop)
5157#endif
5158
5159 // No inplace number slot nb_inplace_add available for this type.
5160
5161 {
5162
5163 // Statically recognized that coercion is not possible with these types
5164
5165 {
5166 PyObject *o = PyList_Type.tp_as_sequence->sq_inplace_concat(*operand1, operand2);
5167 obj_result = o;
5168 goto exit_inplace_result_object;
5169 }
5170 {
5171 PyObject *o = PyList_Type.tp_as_sequence->sq_concat(*operand1, operand2);
5172 obj_result = o;
5173 goto exit_inplace_result_object;
5174 }
5175
5176 NUITKA_CANNOT_GET_HERE("missing error exit annotation");
5177 }
5178
5179exit_inplace_result_object:
5180 if (unlikely(obj_result == NULL)) {
5181 return false;
5182 }
5183
5184 // We got an object handed, that we have to release.
5185 Py_DECREF(*operand1);
5186
5187 // That's our return value then. As we use a dedicated variable, it's
5188 // OK that way.
5189 *operand1 = obj_result;
5190
5191 return true;
5192}
5193
5194bool INPLACE_OPERATION_ADD_LIST_TUPLE(PyObject **operand1, PyObject *operand2) {
5195 return _INPLACE_OPERATION_ADD_LIST_TUPLE(operand1, operand2);
5196}
5197
5198// Part of "Nuitka", an optimizing Python compiler that is compatible and
5199// integrates with CPython, but also works on its own.
5200//
5201// Licensed under the Apache License, Version 2.0 (the "License");
5202// you may not use this file except in compliance with the License.
5203// You may obtain a copy of the License at
5204//
5205// http://www.apache.org/licenses/LICENSE-2.0
5206//
5207// Unless required by applicable law or agreed to in writing, software
5208// distributed under the License is distributed on an "AS IS" BASIS,
5209// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
5210// See the License for the specific language governing permissions and
5211// limitations under the License.