this repo has no description
1// Copyright (c) Facebook, Inc. and its affiliates. (http://www.facebook.com)
2// longobject.c implementation
3
4#include "cpython-data.h"
5#include "cpython-func.h"
6
7#include "api-handle.h"
8#include "float-builtins.h"
9#include "handles.h"
10#include "int-builtins.h"
11#include "objects.h"
12#include "runtime.h"
13
14// Table of digit values for 8-bit string -> integer conversion.
15// '0' maps to 0, ..., '9' maps to 9.
16// 'a' and 'A' map to 10, ..., 'z' and 'Z' map to 35.
17// All other indices map to 37.
18// Note that when converting a base B string, a char c is a legitimate
19// base B digit iff _PyLong_DigitValue[Py_CHARMASK(c)] < B.
20// clang-format off
21const unsigned char _PyLong_DigitValue[256] = { // NOLINT
22 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37,
23 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37,
24 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37,
25 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 37, 37, 37, 37, 37, 37,
26 37, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
27 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 37, 37, 37, 37, 37,
28 37, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
29 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 37, 37, 37, 37, 37,
30 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37,
31 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37,
32 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37,
33 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37,
34 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37,
35 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37,
36 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37,
37 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37,
38};
39// clang-format on
40
41namespace py {
42
43PY_EXPORT int PyLong_CheckExact_Func(PyObject* obj) {
44 RawObject arg = ApiHandle::asObject(ApiHandle::fromPyObject(obj));
45 return arg.isSmallInt() || arg.isLargeInt();
46}
47
48PY_EXPORT int PyLong_Check_Func(PyObject* obj) {
49 return Thread::current()->runtime()->isInstanceOfInt(
50 ApiHandle::asObject(ApiHandle::fromPyObject(obj)));
51}
52
53// Converting from signed ints.
54
55PY_EXPORT PyObject* PyLong_FromLong(long ival) {
56 if (SmallInt::isValid(ival)) {
57 return ApiHandle::handleFromImmediate(SmallInt::fromWord(ival));
58 }
59 Runtime* runtime = Thread::current()->runtime();
60 return ApiHandle::newReferenceWithManaged(runtime, runtime->newInt(ival));
61}
62
63PY_EXPORT PyObject* PyLong_FromLongLong(long long ival) {
64 static_assert(sizeof(ival) <= sizeof(long), "Unsupported long long size");
65 return PyLong_FromLong(ival);
66}
67
68PY_EXPORT PyObject* PyLong_FromPid(pid_t ival) {
69 static_assert(sizeof(ival) <= sizeof(long), "Unsupported pid_t size");
70 return PyLong_FromLong(ival);
71}
72
73PY_EXPORT PyObject* PyLong_FromSsize_t(Py_ssize_t ival) {
74 static_assert(sizeof(ival) <= sizeof(long), "Unsupported Py_ssize_t size");
75 return PyLong_FromLong(ival);
76}
77
78// Converting from unsigned ints.
79
80PY_EXPORT PyObject* PyLong_FromUnsignedLong(unsigned long ival) {
81 static_assert(sizeof(ival) <= sizeof(uword),
82 "Unsupported unsigned long type");
83 if (ival <= static_cast<unsigned long>(SmallInt::kMaxValue)) {
84 return ApiHandle::handleFromImmediate(
85 SmallInt::fromWord(static_cast<word>(ival)));
86 }
87 Runtime* runtime = Thread::current()->runtime();
88 return ApiHandle::newReferenceWithManaged(runtime,
89 runtime->newIntFromUnsigned(ival));
90}
91
92PY_EXPORT PyObject* PyLong_FromUnsignedLongLong(unsigned long long ival) {
93 static_assert(sizeof(ival) <= sizeof(unsigned long),
94 "Unsupported unsigned long long size");
95 return PyLong_FromUnsignedLong(ival);
96}
97
98PY_EXPORT PyObject* PyLong_FromSize_t(size_t ival) {
99 static_assert(sizeof(ival) <= sizeof(unsigned long),
100 "Unsupported size_t size");
101 return PyLong_FromUnsignedLong(ival);
102}
103
104// Attempt to convert the given PyObject to T. When overflow != nullptr,
105// *overflow will be set to -1, 1, or 0 to indicate underflow, overflow, or
106// neither, respectively. When under/overflow occurs, -1 is returned; otherwise,
107// the value is returned.
108//
109// When overflow == nullptr, an exception will be raised and -1 is returned if
110// the value doesn't fit in T.
111template <typename T>
112static T asInt(Thread* thread, PyObject* pylong, const char* type_name,
113 int* overflow) {
114 if (pylong == nullptr) {
115 thread->raiseBadInternalCall();
116 return -1;
117 }
118
119 HandleScope scope(thread);
120 Object long_obj(&scope, ApiHandle::asObject(ApiHandle::fromPyObject(pylong)));
121 if (!thread->runtime()->isInstanceOfInt(*long_obj)) {
122 long_obj =
123 thread->invokeFunction1(ID(builtins), ID(_index_or_int), long_obj);
124 if (long_obj.isError()) {
125 return -1;
126 }
127 }
128
129 Int num(&scope, intUnderlying(*long_obj));
130 auto const result = num.asInt<T>();
131 if (result.error == CastError::None) {
132 if (overflow) *overflow = 0;
133 return result.value;
134 }
135
136 if (overflow) {
137 *overflow = (result.error == CastError::Underflow) ? -1 : 1;
138 } else if (result.error == CastError::Underflow &&
139 std::is_unsigned<T>::value) {
140 thread->raiseWithFmt(LayoutId::kOverflowError,
141 "can't convert negative value to unsigned");
142 } else {
143 thread->raiseWithFmt(LayoutId::kOverflowError,
144 "Python int too big to convert to C %s", type_name);
145 }
146 return -1;
147}
148
149template <typename T>
150static T asIntWithoutOverflowCheck(PyObject* pylong) {
151 Thread* thread = Thread::current();
152 if (pylong == nullptr) {
153 thread->raiseBadInternalCall();
154 return -1;
155 }
156
157 HandleScope scope(thread);
158 Object long_obj(&scope, ApiHandle::asObject(ApiHandle::fromPyObject(pylong)));
159 if (!thread->runtime()->isInstanceOfInt(*long_obj)) {
160 long_obj =
161 thread->invokeFunction1(ID(builtins), ID(_index_or_int), long_obj);
162 if (long_obj.isError()) {
163 return -1;
164 }
165 }
166
167 Int num(&scope, intUnderlying(*long_obj));
168 return num.digitAt(0);
169}
170
171PY_EXPORT size_t _PyLong_NumBits(PyObject* pylong) {
172 DCHECK(pylong != nullptr, "argument to _PyLong_NumBits must not be null");
173 Thread* thread = Thread::current();
174 HandleScope scope(thread);
175 Object long_obj(&scope, ApiHandle::asObject(ApiHandle::fromPyObject(pylong)));
176 DCHECK(thread->runtime()->isInstanceOfInt(*long_obj),
177 "argument to _PyLong_NumBits must be an int");
178 Int obj(&scope, intUnderlying(*long_obj));
179 return obj.bitLength();
180}
181
182// Converting to signed ints.
183
184PY_EXPORT int _PyLong_AsInt(PyObject* pylong) {
185 return asInt<int>(Thread::current(), pylong, "int", nullptr);
186}
187
188PY_EXPORT long PyLong_AsLong(PyObject* pylong) {
189 return asInt<long>(Thread::current(), pylong, "long", nullptr);
190}
191
192PY_EXPORT long long PyLong_AsLongLong(PyObject* val) {
193 return asInt<long long>(Thread::current(), val, "long long", nullptr);
194}
195
196PY_EXPORT pid_t PyLong_AsPid(PyObject* val) {
197 return asInt<pid_t>(Thread::current(), val, "pid_t", nullptr);
198}
199
200PY_EXPORT Py_ssize_t PyLong_AsSsize_t(PyObject* val) {
201 return asInt<Py_ssize_t>(Thread::current(), val, "ssize_t", nullptr);
202}
203
204// Converting to unsigned ints.
205
206PY_EXPORT unsigned long PyLong_AsUnsignedLong(PyObject* val) {
207 return asInt<unsigned long>(Thread::current(), val, "unsigned long", nullptr);
208}
209
210PY_EXPORT unsigned long long PyLong_AsUnsignedLongLong(PyObject* val) {
211 return asInt<unsigned long long>(Thread::current(), val, "unsigned long long",
212 nullptr);
213}
214
215PY_EXPORT size_t PyLong_AsSize_t(PyObject* val) {
216 return asInt<size_t>(Thread::current(), val, "size_t", nullptr);
217}
218
219PY_EXPORT long PyLong_AsLongAndOverflow(PyObject* pylong, int* overflow) {
220 return asInt<long>(Thread::current(), pylong, "", overflow);
221}
222
223PY_EXPORT long long PyLong_AsLongLongAndOverflow(PyObject* pylong,
224 int* overflow) {
225 return asInt<long long>(Thread::current(), pylong, "", overflow);
226}
227
228PY_EXPORT PyObject* PyLong_FromDouble(double value) {
229 Thread* thread = Thread::current();
230 RawObject result = intFromDouble(thread, value);
231 if (result.isErrorException()) {
232 return nullptr;
233 }
234 return ApiHandle::newReference(thread->runtime(), result);
235}
236
237PY_EXPORT PyObject* PyLong_FromString(const char* str, char** pend, int base) {
238 if (pend != nullptr) {
239 UNIMPLEMENTED("pend != NULL");
240 }
241 Thread* thread = Thread::current();
242 HandleScope scope(thread);
243 Runtime* runtime = thread->runtime();
244 Str str_obj(&scope, runtime->newStrFromCStr(str));
245 Int base_obj(&scope, runtime->newInt(base));
246 Type int_cls(&scope, runtime->typeAt(LayoutId::kInt));
247 Object result(&scope,
248 thread->invokeFunction3(ID(builtins), ID(_int_new_from_str),
249 int_cls, str_obj, base_obj));
250 if (result.isError()) {
251 DCHECK(!result.isErrorNotFound(), "could not call _int_new_from_str");
252 return nullptr;
253 }
254 return ApiHandle::newReference(runtime, *result);
255}
256
257PY_EXPORT double PyLong_AsDouble(PyObject* obj) {
258 Thread* thread = Thread::current();
259 if (obj == nullptr) {
260 thread->raiseBadInternalCall();
261 return -1.0;
262 }
263 HandleScope scope(thread);
264 Object object(&scope, ApiHandle::asObject(ApiHandle::fromPyObject(obj)));
265 if (!thread->runtime()->isInstanceOfInt(*object)) {
266 thread->raiseWithFmt(LayoutId::kTypeError, "an integer is required");
267 return -1.0;
268 }
269 Int value(&scope, intUnderlying(*object));
270 double result;
271 Object err(&scope, convertIntToDouble(thread, value, &result));
272 return err.isError() ? -1.0 : result;
273}
274
275PY_EXPORT unsigned long long PyLong_AsUnsignedLongLongMask(PyObject* op) {
276 return asIntWithoutOverflowCheck<unsigned long long>(op);
277}
278
279PY_EXPORT unsigned long PyLong_AsUnsignedLongMask(PyObject* op) {
280 return asIntWithoutOverflowCheck<unsigned long>(op);
281}
282
283PY_EXPORT void* PyLong_AsVoidPtr(PyObject* pylong) {
284 static_assert(kPointerSize >= sizeof(long long),
285 "PyLong_AsVoidPtr: sizeof(long long) < sizeof(void*)");
286 long long x;
287 if (PyLong_Check(pylong) && _PyLong_Sign(pylong) < 0) {
288 x = PyLong_AsLongLong(pylong);
289 } else {
290 x = PyLong_AsUnsignedLongLong(pylong);
291 }
292
293 if (x == -1 && PyErr_Occurred()) return nullptr;
294 return reinterpret_cast<void*>(x);
295}
296
297PY_EXPORT PyObject* PyLong_FromVoidPtr(void* ptr) {
298 static_assert(kPointerSize >= sizeof(long long),
299 "PyLong_FromVoidPtr: sizeof(long long) < sizeof(void*)");
300 return PyLong_FromUnsignedLongLong(reinterpret_cast<unsigned long long>(ptr));
301}
302
303PY_EXPORT PyObject* PyLong_GetInfo() { UNIMPLEMENTED("PyLong_GetInfo"); }
304
305PY_EXPORT int _PyLong_AsByteArray(PyLongObject* longobj, unsigned char* dst,
306 size_t n, int little_endian, int is_signed) {
307 DCHECK(longobj != nullptr, "null argument to _PyLong_AsByteArray");
308 Thread* thread = Thread::current();
309 HandleScope scope(thread);
310 Runtime* runtime = thread->runtime();
311 PyObject* pyobj = reinterpret_cast<PyObject*>(longobj);
312 Object self_obj(&scope, ApiHandle::asObject(ApiHandle::fromPyObject(pyobj)));
313 Int self(&scope, intUnderlying(*self_obj));
314 if (!is_signed && self.isNegative()) {
315 thread->raiseWithFmt(LayoutId::kOverflowError,
316 "can't convert negative int to unsigned");
317 return -1;
318 }
319 word length = static_cast<word>(n);
320 endian endianness = little_endian ? endian::little : endian::big;
321 Bytes result(&scope, runtime->intToBytes(thread, self, length, endianness));
322 result.copyTo(dst, length);
323
324 // Check for overflow.
325 word num_digits = self.numDigits();
326 uword high_digit = self.digitAt(num_digits - 1);
327 word bit_length =
328 num_digits * kBitsPerWord - Utils::numRedundantSignBits(high_digit);
329 if (bit_length > length * kBitsPerByte + !is_signed) {
330 thread->raiseWithFmt(LayoutId::kOverflowError, "int too big to convert");
331 return -1;
332 }
333 return 0;
334}
335
336PY_EXPORT PyTypeObject* PyLong_Type_Ptr() {
337 Runtime* runtime = Thread::current()->runtime();
338 return reinterpret_cast<PyTypeObject*>(
339 ApiHandle::borrowedReference(runtime, runtime->typeAt(LayoutId::kInt)));
340}
341
342PY_EXPORT PyObject* _PyLong_Copy(PyLongObject* longobj) {
343 Thread* thread = Thread::current();
344 HandleScope scope(thread);
345 PyObject* pyobj = reinterpret_cast<PyObject*>(longobj);
346 Object obj(&scope, ApiHandle::asObject(ApiHandle::fromPyObject(pyobj)));
347 Runtime* runtime = thread->runtime();
348 DCHECK(runtime->isInstanceOfInt(*obj), "_PyLong_Copy requires an int");
349 return ApiHandle::newReference(runtime, intUnderlying(*obj));
350}
351
352PY_EXPORT PyObject* _PyLong_DivmodNear(PyObject* a, PyObject* b) {
353 Thread* thread = Thread::current();
354 HandleScope scope(thread);
355 Runtime* runtime = thread->runtime();
356 Object dividend_obj(&scope, ApiHandle::asObject(ApiHandle::fromPyObject(a)));
357 Object divisor_obj(&scope, ApiHandle::asObject(ApiHandle::fromPyObject(b)));
358 if (!runtime->isInstanceOfInt(*dividend_obj) ||
359 !runtime->isInstanceOfInt(*divisor_obj)) {
360 thread->raiseWithFmt(LayoutId::kTypeError,
361 "non-integer arguments in division");
362 return nullptr;
363 }
364
365 Int dividend(&scope, intUnderlying(*dividend_obj));
366 Int divisor(&scope, intUnderlying(*divisor_obj));
367 Object quotient(&scope, NoneType::object());
368 Object remainder(&scope, NoneType::object());
369 if (!intDivmodNear(thread, dividend, divisor, "ient, &remainder)) {
370 thread->raiseWithFmt(LayoutId::kZeroDivisionError,
371 "integer division or modulo by zero");
372 return nullptr;
373 }
374 return ApiHandle::newReference(runtime,
375 runtime->newTupleWith2(quotient, remainder));
376}
377
378PY_EXPORT double _PyLong_Frexp(PyLongObject*, Py_ssize_t*) {
379 UNIMPLEMENTED("_PyLong_Frexp");
380}
381
382PY_EXPORT PyObject* _PyLong_FromByteArray(const unsigned char* bytes, size_t n,
383 int little_endian, int is_signed) {
384 if (n == 0) return PyLong_FromLong(0);
385 Thread* thread = Thread::current();
386 HandleScope scope(thread);
387 Runtime* runtime = thread->runtime();
388 // This copies the bytes an extra time, but it is more important for the
389 // runtime to accommodate int.from_bytes(), so allow the extra copy.
390 Bytes source(&scope, runtime->newBytesWithAll(
391 View<byte>(bytes, static_cast<word>(n))));
392 endian endianness = little_endian ? endian::little : endian::big;
393 Object result(&scope,
394 runtime->bytesToInt(thread, source, endianness, is_signed));
395 return result.isError() ? nullptr : ApiHandle::newReference(runtime, *result);
396}
397
398PY_EXPORT PyObject* _PyLong_GCD(PyObject* a, PyObject* b) {
399 Thread* thread = Thread::current();
400 HandleScope scope(thread);
401 Object dividend_obj(&scope, ApiHandle::asObject(ApiHandle::fromPyObject(a)));
402 Object divisor_obj(&scope, ApiHandle::asObject(ApiHandle::fromPyObject(b)));
403 Runtime* runtime = thread->runtime();
404
405 DCHECK(runtime->isInstanceOfInt(*dividend_obj),
406 "dividend argument to _PyLong_GCD must be an int");
407 DCHECK(runtime->isInstanceOfInt(*divisor_obj),
408 "divisor argument to _PyLong_GCD must be an int");
409 Int dividend(&scope, intUnderlying(*dividend_obj));
410 Int divisor(&scope, intUnderlying(*divisor_obj));
411
412 return ApiHandle::newReference(runtime, intGCD(thread, dividend, divisor));
413}
414
415PY_EXPORT PyLongObject* _PyLong_FromNbInt(PyObject*) {
416 UNIMPLEMENTED("_PyLong_FromNbInt");
417}
418
419PY_EXPORT PyObject* _PyLong_Lshift(PyObject* a, size_t shiftby) {
420 Thread* thread = Thread::current();
421 HandleScope scope(thread);
422 Object obj(&scope, ApiHandle::asObject(ApiHandle::fromPyObject(a)));
423 Runtime* runtime = thread->runtime();
424 DCHECK(runtime->isInstanceOfInt(*obj), "_PyLong_Lshift requires an int");
425 Int num(&scope, intUnderlying(*obj));
426 if (num.isZero()) {
427 return ApiHandle::newReference(runtime, SmallInt::fromWord(0));
428 }
429 Int shift(&scope, runtime->newIntFromUnsigned(shiftby));
430 return ApiHandle::newReference(runtime,
431 runtime->intBinaryLshift(thread, num, shift));
432}
433
434PY_EXPORT PyObject* _PyLong_One_Ptr() {
435 return ApiHandle::borrowedReference(Thread::current()->runtime(),
436 SmallInt::fromWord(1));
437}
438
439PY_EXPORT PyObject* _PyLong_Rshift(PyObject* a, size_t shiftby) {
440 Thread* thread = Thread::current();
441 HandleScope scope(thread);
442 Object obj(&scope, ApiHandle::asObject(ApiHandle::fromPyObject(a)));
443 Runtime* runtime = thread->runtime();
444 DCHECK(runtime->isInstanceOfInt(*obj), "_PyLong_Rshift requires an int");
445 Int num(&scope, intUnderlying(*obj));
446 if (num.isZero()) {
447 return ApiHandle::newReference(runtime, SmallInt::fromWord(0));
448 }
449 Int shift(&scope, runtime->newIntFromUnsigned(shiftby));
450 return ApiHandle::newReference(runtime,
451 runtime->intBinaryRshift(thread, num, shift));
452}
453
454PY_EXPORT int _PyLong_Sign(PyObject* vv) {
455 Thread* thread = Thread::current();
456 HandleScope scope(thread);
457 Object obj(&scope, ApiHandle::asObject(ApiHandle::fromPyObject(vv)));
458 DCHECK(thread->runtime()->isInstanceOfInt(*obj), "requires an integer");
459 Int value(&scope, intUnderlying(*obj));
460 return value.isZero() ? 0 : (value.isNegative() ? -1 : 1);
461}
462
463template <typename T>
464static T unsignedConverter(PyObject* obj, void* ptr, const char* type_name) {
465 Thread* thread = Thread::current();
466 HandleScope scope(thread);
467 Object object(&scope, ApiHandle::asObject(ApiHandle::fromPyObject(obj)));
468 if (thread->runtime()->isInstanceOfInt(*object)) {
469 Int num(&scope, intUnderlying(*object));
470 if (num.isNegative()) {
471 thread->raiseWithFmt(LayoutId::kValueError, "value must be positive");
472 return 0;
473 }
474 }
475 T result = asInt<T>(thread, obj, type_name, nullptr);
476 if (result == static_cast<T>(-1) && thread->hasPendingException()) {
477 return 0;
478 }
479 *reinterpret_cast<T*>(ptr) = result;
480 return 1;
481}
482
483PY_EXPORT int _PyLong_Size_t_Converter(PyObject* obj, void* ptr) {
484 return unsignedConverter<size_t>(obj, ptr, "size_t");
485}
486
487PY_EXPORT int _PyLong_UnsignedInt_Converter(PyObject* obj, void* ptr) {
488 return unsignedConverter<unsigned int>(obj, ptr, "unsigned int");
489}
490
491PY_EXPORT int _PyLong_UnsignedLong_Converter(PyObject* obj, void* ptr) {
492 return unsignedConverter<unsigned long>(obj, ptr, "unsigned long");
493}
494
495PY_EXPORT int _PyLong_UnsignedLongLong_Converter(PyObject* obj, void* ptr) {
496 return unsignedConverter<unsigned long long>(obj, ptr, "unsigned long long");
497}
498
499PY_EXPORT int _PyLong_UnsignedShort_Converter(PyObject* obj, void* ptr) {
500 return unsignedConverter<unsigned short>(obj, ptr, "unsigned short");
501}
502
503PY_EXPORT PyObject* _PyLong_Zero_Ptr() {
504 return ApiHandle::borrowedReference(Thread::current()->runtime(),
505 SmallInt::fromWord(0));
506}
507
508} // namespace py