cpyte 2.3.1__tar.gz → 2.4.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- cpyte-2.4.0/MANIFEST.in +1 -0
- {cpyte-2.3.1 → cpyte-2.4.0}/PKG-INFO +1 -1
- {cpyte-2.3.1 → cpyte-2.4.0}/pyproject.toml +1 -1
- cpyte-2.4.0/source/cpyte/bignum.c +469 -0
- {cpyte-2.3.1 → cpyte-2.4.0}/source/cpyte/bytecoding.py +50 -28
- {cpyte-2.3.1 → cpyte-2.4.0}/source/cpyte/compiling.py +159 -1
- cpyte-2.4.0/source/cpyte/gc_runtime.c +322 -0
- {cpyte-2.3.1 → cpyte-2.4.0}/source/cpyte/mainpie.py +15 -6
- cpyte-2.4.0/source/cpyte/runtime.c +63 -0
- cpyte-2.4.0/source/cpyte/runtime_scorpion.c +197 -0
- {cpyte-2.3.1 → cpyte-2.4.0}/source/cpyte.egg-info/PKG-INFO +1 -1
- {cpyte-2.3.1 → cpyte-2.4.0}/source/cpyte.egg-info/SOURCES.txt +5 -0
- {cpyte-2.3.1 → cpyte-2.4.0}/readme.md +0 -0
- {cpyte-2.3.1 → cpyte-2.4.0}/setup.cfg +0 -0
- {cpyte-2.3.1 → cpyte-2.4.0}/source/cpyte/__init__.py +0 -0
- {cpyte-2.3.1 → cpyte-2.4.0}/source/cpyte/__main__.py +0 -0
- {cpyte-2.3.1 → cpyte-2.4.0}/source/cpyte/_bignum_bc.py +0 -0
- {cpyte-2.3.1 → cpyte-2.4.0}/source/cpyte/_gc_bc.py +0 -0
- {cpyte-2.3.1 → cpyte-2.4.0}/source/cpyte/_runtime_bc.py +0 -0
- {cpyte-2.3.1 → cpyte-2.4.0}/source/cpyte/astparse.py +0 -0
- {cpyte-2.3.1 → cpyte-2.4.0}/source/cpyte/clib.py +0 -0
- {cpyte-2.3.1 → cpyte-2.4.0}/source/cpyte/extension_hooks.py +0 -0
- {cpyte-2.3.1 → cpyte-2.4.0}/source/cpyte/generate_bc.py +0 -0
- {cpyte-2.3.1 → cpyte-2.4.0}/source/cpyte/lexar.py +0 -0
- {cpyte-2.3.1 → cpyte-2.4.0}/source/cpyte/linker.py +0 -0
- {cpyte-2.3.1 → cpyte-2.4.0}/source/cpyte/lsp_server.py +0 -0
- {cpyte-2.3.1 → cpyte-2.4.0}/source/cpyte/package_manifest.py +0 -0
- {cpyte-2.3.1 → cpyte-2.4.0}/source/cpyte/semantic_analasis.py +0 -0
- {cpyte-2.3.1 → cpyte-2.4.0}/source/cpyte.egg-info/dependency_links.txt +0 -0
- {cpyte-2.3.1 → cpyte-2.4.0}/source/cpyte.egg-info/entry_points.txt +0 -0
- {cpyte-2.3.1 → cpyte-2.4.0}/source/cpyte.egg-info/requires.txt +0 -0
- {cpyte-2.3.1 → cpyte-2.4.0}/source/cpyte.egg-info/top_level.txt +0 -0
- {cpyte-2.3.1 → cpyte-2.4.0}/test/test_bignum_jit.py +0 -0
cpyte-2.4.0/MANIFEST.in
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
include source/cpyte/*.c
|
|
@@ -0,0 +1,469 @@
|
|
|
1
|
+
#include <stdio.h>
|
|
2
|
+
#include <stdlib.h>
|
|
3
|
+
#include <stdint.h>
|
|
4
|
+
#include <string.h>
|
|
5
|
+
#include <unistd.h>
|
|
6
|
+
|
|
7
|
+
// --- Minimal bignum implementation ---
|
|
8
|
+
// Each bignum is a 64-bit limb array (little-endian), dynamically allocated.
|
|
9
|
+
|
|
10
|
+
typedef struct {
|
|
11
|
+
uint64_t* limbs;
|
|
12
|
+
size_t len;
|
|
13
|
+
size_t used;
|
|
14
|
+
int negative;
|
|
15
|
+
} BigNum;
|
|
16
|
+
|
|
17
|
+
static void _bn_fail(const char* msg) {
|
|
18
|
+
write(2, msg, strlen(msg));
|
|
19
|
+
write(2, "\n", 1);
|
|
20
|
+
exit(1);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
static BigNum* _bn_alloc(void) {
|
|
24
|
+
BigNum* b = malloc(sizeof(BigNum));
|
|
25
|
+
if (!b) _bn_fail("bigint: alloc failed");
|
|
26
|
+
b->limbs = NULL;
|
|
27
|
+
b->len = 0;
|
|
28
|
+
b->used = 0;
|
|
29
|
+
b->negative = 0;
|
|
30
|
+
return b;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
static void _bn_reserve(BigNum* b, size_t n) {
|
|
34
|
+
if (n > b->len) {
|
|
35
|
+
size_t new_len = n < 4 ? 4 : n;
|
|
36
|
+
uint64_t* p = realloc(b->limbs, new_len * sizeof(uint64_t));
|
|
37
|
+
if (!p) _bn_fail("bigint: realloc failed");
|
|
38
|
+
b->limbs = p;
|
|
39
|
+
b->len = new_len;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
static void _bn_trim(BigNum* b) {
|
|
44
|
+
if (b->used == 0) return;
|
|
45
|
+
while (b->used > 1 && b->limbs[b->used - 1] == 0)
|
|
46
|
+
b->used--;
|
|
47
|
+
if (b->used == 1 && b->limbs[0] == 0)
|
|
48
|
+
b->negative = 0;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
static void _bn_set_uint64(BigNum* b, uint64_t v) {
|
|
52
|
+
_bn_reserve(b, 1);
|
|
53
|
+
b->limbs[0] = v;
|
|
54
|
+
b->used = 1;
|
|
55
|
+
b->negative = 0;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
static int _bn_cmp_mag(const BigNum* a, const BigNum* b) {
|
|
59
|
+
if (a->used != b->used) return a->used < b->used ? -1 : 1;
|
|
60
|
+
for (size_t i = a->used; i > 0; i--) {
|
|
61
|
+
size_t idx = i - 1;
|
|
62
|
+
if (a->limbs[idx] != b->limbs[idx])
|
|
63
|
+
return a->limbs[idx] < b->limbs[idx] ? -1 : 1;
|
|
64
|
+
}
|
|
65
|
+
return 0;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
void* bigint_new(void) {
|
|
69
|
+
BigNum* b = _bn_alloc();
|
|
70
|
+
_bn_reserve(b, 1);
|
|
71
|
+
b->limbs[0] = 0;
|
|
72
|
+
b->used = 1;
|
|
73
|
+
b->negative = 0;
|
|
74
|
+
return b;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
void bigint_free(void* p) {
|
|
78
|
+
if (!p) return;
|
|
79
|
+
BigNum* b = (BigNum*)p;
|
|
80
|
+
free(b->limbs);
|
|
81
|
+
free(b);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
void* bigint_from_int(int64_t val) {
|
|
85
|
+
BigNum* b = _bn_alloc();
|
|
86
|
+
if (val < 0) {
|
|
87
|
+
_bn_set_uint64(b, (uint64_t)(-(val + 1)) + 1);
|
|
88
|
+
b->negative = 1;
|
|
89
|
+
} else {
|
|
90
|
+
_bn_set_uint64(b, (uint64_t)val);
|
|
91
|
+
}
|
|
92
|
+
return b;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
void* bigint_from_uint64(uint64_t val) {
|
|
96
|
+
BigNum* b = _bn_alloc();
|
|
97
|
+
_bn_set_uint64(b, val);
|
|
98
|
+
return b;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
void* bigint_from_str(const char* str) {
|
|
102
|
+
if (!str || str[0] == '\0') return bigint_from_int(0);
|
|
103
|
+
BigNum* b = _bn_alloc();
|
|
104
|
+
const char* p = str;
|
|
105
|
+
int neg = 0;
|
|
106
|
+
if (*p == '-') { neg = 1; p++; }
|
|
107
|
+
else if (*p == '+') { p++; }
|
|
108
|
+
|
|
109
|
+
while (*p == '0') p++;
|
|
110
|
+
|
|
111
|
+
size_t digits = strlen(p);
|
|
112
|
+
if (digits == 0 || *p == '\0') {
|
|
113
|
+
_bn_reserve(b, 1);
|
|
114
|
+
b->limbs[0] = 0;
|
|
115
|
+
b->used = 1;
|
|
116
|
+
return b;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
_bn_reserve(b, (digits / 19) + 2);
|
|
120
|
+
b->used = 1;
|
|
121
|
+
b->limbs[0] = 0;
|
|
122
|
+
|
|
123
|
+
while (*p) {
|
|
124
|
+
uint64_t carry = 0;
|
|
125
|
+
for (size_t i = 0; i < b->used; i++) {
|
|
126
|
+
__uint128_t v = (__uint128_t)b->limbs[i] * 10 + carry;
|
|
127
|
+
b->limbs[i] = (uint64_t)v;
|
|
128
|
+
carry = (uint64_t)(v >> 64);
|
|
129
|
+
}
|
|
130
|
+
if (carry) {
|
|
131
|
+
_bn_reserve(b, b->used + 1);
|
|
132
|
+
b->limbs[b->used++] = carry;
|
|
133
|
+
}
|
|
134
|
+
uint64_t d = (uint64_t)(*p - '0');
|
|
135
|
+
carry = d;
|
|
136
|
+
for (size_t i = 0; i < b->used && carry; i++) {
|
|
137
|
+
__uint128_t v = (__uint128_t)b->limbs[i] + carry;
|
|
138
|
+
b->limbs[i] = (uint64_t)v;
|
|
139
|
+
carry = (uint64_t)(v >> 64);
|
|
140
|
+
}
|
|
141
|
+
if (carry) {
|
|
142
|
+
_bn_reserve(b, b->used + 1);
|
|
143
|
+
b->limbs[b->used++] = carry;
|
|
144
|
+
}
|
|
145
|
+
p++;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
_bn_trim(b);
|
|
149
|
+
b->negative = neg;
|
|
150
|
+
return b;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
void* bigint_add(void* a, void* b) {
|
|
154
|
+
BigNum* x = (BigNum*)a;
|
|
155
|
+
if (!x) return b ? bigint_add(b, a) : bigint_from_int(0);
|
|
156
|
+
if (!b) return a;
|
|
157
|
+
BigNum* y = (BigNum*)b;
|
|
158
|
+
BigNum* r = _bn_alloc();
|
|
159
|
+
|
|
160
|
+
if (x->negative == y->negative) {
|
|
161
|
+
size_t max_used = x->used > y->used ? x->used : y->used;
|
|
162
|
+
_bn_reserve(r, max_used + 1);
|
|
163
|
+
uint64_t carry = 0;
|
|
164
|
+
size_t i = 0;
|
|
165
|
+
for (; i < x->used && i < y->used; i++) {
|
|
166
|
+
__uint128_t v = (__uint128_t)x->limbs[i] + y->limbs[i] + carry;
|
|
167
|
+
r->limbs[i] = (uint64_t)v;
|
|
168
|
+
carry = (uint64_t)(v >> 64);
|
|
169
|
+
}
|
|
170
|
+
for (; i < x->used; i++) {
|
|
171
|
+
__uint128_t v = (__uint128_t)x->limbs[i] + carry;
|
|
172
|
+
r->limbs[i] = (uint64_t)v;
|
|
173
|
+
carry = (uint64_t)(v >> 64);
|
|
174
|
+
}
|
|
175
|
+
for (; i < y->used; i++) {
|
|
176
|
+
__uint128_t v = (__uint128_t)y->limbs[i] + carry;
|
|
177
|
+
r->limbs[i] = (uint64_t)v;
|
|
178
|
+
carry = (uint64_t)(v >> 64);
|
|
179
|
+
}
|
|
180
|
+
if (carry)
|
|
181
|
+
r->limbs[i++] = carry;
|
|
182
|
+
r->used = i;
|
|
183
|
+
r->negative = x->negative;
|
|
184
|
+
} else {
|
|
185
|
+
int cmp = _bn_cmp_mag(x, y);
|
|
186
|
+
const BigNum* bigger = (cmp >= 0) ? x : y;
|
|
187
|
+
const BigNum* smaller = (cmp >= 0) ? y : x;
|
|
188
|
+
_bn_reserve(r, bigger->used);
|
|
189
|
+
uint64_t borrow = 0;
|
|
190
|
+
size_t i = 0;
|
|
191
|
+
for (; i < smaller->used; i++) {
|
|
192
|
+
__uint128_t v = (__uint128_t)bigger->limbs[i] - smaller->limbs[i] - borrow;
|
|
193
|
+
r->limbs[i] = (uint64_t)v;
|
|
194
|
+
borrow = (uint64_t)((v >> 64) & 1);
|
|
195
|
+
}
|
|
196
|
+
for (; i < bigger->used; i++) {
|
|
197
|
+
__uint128_t v = (__uint128_t)bigger->limbs[i] - borrow;
|
|
198
|
+
r->limbs[i] = (uint64_t)v;
|
|
199
|
+
borrow = (uint64_t)((v >> 64) & 1);
|
|
200
|
+
}
|
|
201
|
+
r->used = bigger->used;
|
|
202
|
+
_bn_trim(r);
|
|
203
|
+
r->negative = (bigger == x) ? x->negative : y->negative;
|
|
204
|
+
}
|
|
205
|
+
return r;
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
void* bigint_neg(void* a) {
|
|
209
|
+
if (!a) return bigint_from_int(0);
|
|
210
|
+
BigNum* x = (BigNum*)a;
|
|
211
|
+
BigNum* r = _bn_alloc();
|
|
212
|
+
_bn_reserve(r, x->used);
|
|
213
|
+
memcpy(r->limbs, x->limbs, x->used * sizeof(uint64_t));
|
|
214
|
+
r->used = x->used;
|
|
215
|
+
r->negative = !x->negative;
|
|
216
|
+
if (r->used == 1 && r->limbs[0] == 0) r->negative = 0;
|
|
217
|
+
return r;
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
void* bigint_sub(void* a, void* b) {
|
|
221
|
+
if (!a) return b ? bigint_neg(b) : bigint_from_int(0);
|
|
222
|
+
if (!b) return a;
|
|
223
|
+
BigNum* y = (BigNum*)b;
|
|
224
|
+
int orig_neg = y->negative;
|
|
225
|
+
y->negative = !y->negative;
|
|
226
|
+
void* r = bigint_add(a, b);
|
|
227
|
+
y->negative = orig_neg;
|
|
228
|
+
return r;
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
void* bigint_mul(void* a, void* b) {
|
|
232
|
+
if (!a || !b) return bigint_from_int(0);
|
|
233
|
+
BigNum* x = (BigNum*)a;
|
|
234
|
+
BigNum* y = (BigNum*)b;
|
|
235
|
+
BigNum* r = _bn_alloc();
|
|
236
|
+
|
|
237
|
+
size_t n = x->used + y->used;
|
|
238
|
+
_bn_reserve(r, n);
|
|
239
|
+
memset(r->limbs, 0, n * sizeof(uint64_t));
|
|
240
|
+
r->used = n;
|
|
241
|
+
|
|
242
|
+
for (size_t i = 0; i < x->used; i++) {
|
|
243
|
+
uint64_t carry = 0;
|
|
244
|
+
for (size_t j = 0; j < y->used; j++) {
|
|
245
|
+
__uint128_t v = (__uint128_t)x->limbs[i] * y->limbs[j]
|
|
246
|
+
+ r->limbs[i + j] + carry;
|
|
247
|
+
r->limbs[i + j] = (uint64_t)v;
|
|
248
|
+
carry = (uint64_t)(v >> 64);
|
|
249
|
+
}
|
|
250
|
+
if (carry)
|
|
251
|
+
r->limbs[i + y->used] += carry;
|
|
252
|
+
}
|
|
253
|
+
_bn_trim(r);
|
|
254
|
+
r->negative = x->negative ^ y->negative;
|
|
255
|
+
if (r->used == 1 && r->limbs[0] == 0) r->negative = 0;
|
|
256
|
+
return r;
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
void* bigint_div(void* a, void* b) {
|
|
260
|
+
if (!a || !b) return bigint_from_int(0);
|
|
261
|
+
BigNum* x = (BigNum*)a;
|
|
262
|
+
BigNum* y = (BigNum*)b;
|
|
263
|
+
if (y->used == 1 && y->limbs[0] == 0)
|
|
264
|
+
return bigint_from_int(0);
|
|
265
|
+
BigNum* r = _bn_alloc();
|
|
266
|
+
|
|
267
|
+
if (_bn_cmp_mag(y, x) > 0) {
|
|
268
|
+
_bn_reserve(r, 1);
|
|
269
|
+
r->limbs[0] = 0;
|
|
270
|
+
r->used = 1;
|
|
271
|
+
r->negative = 0;
|
|
272
|
+
return r;
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
// Schoolbook division for single-limb divisor (fast path)
|
|
276
|
+
if (y->used == 1) {
|
|
277
|
+
uint64_t div = y->limbs[0];
|
|
278
|
+
_bn_reserve(r, x->used);
|
|
279
|
+
r->used = x->used;
|
|
280
|
+
uint64_t rem = 0;
|
|
281
|
+
for (size_t i = x->used; i > 0; i--) {
|
|
282
|
+
__uint128_t v = ((__uint128_t)rem << 64) | x->limbs[i - 1];
|
|
283
|
+
r->limbs[i - 1] = (uint64_t)(v / div);
|
|
284
|
+
rem = (uint64_t)(v % div);
|
|
285
|
+
}
|
|
286
|
+
_bn_trim(r);
|
|
287
|
+
r->negative = x->negative ^ y->negative;
|
|
288
|
+
if (r->used == 1 && r->limbs[0] == 0) r->negative = 0;
|
|
289
|
+
return r;
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
// General case: long division (Knuth Algorithm D)
|
|
293
|
+
// Normalize divisor by shifting
|
|
294
|
+
int norm_shift = __builtin_clzll(y->limbs[y->used - 1]);
|
|
295
|
+
BigNum* u = _bn_alloc(); // normalized dividend
|
|
296
|
+
BigNum* v = _bn_alloc(); // normalized divisor
|
|
297
|
+
_bn_reserve(u, x->used + 1);
|
|
298
|
+
_bn_reserve(v, y->used);
|
|
299
|
+
|
|
300
|
+
if (norm_shift > 0) {
|
|
301
|
+
uint64_t carry = 0;
|
|
302
|
+
for (size_t i = 0; i < y->used; i++) {
|
|
303
|
+
uint64_t val = (carry) | (y->limbs[i] << norm_shift);
|
|
304
|
+
v->limbs[i] = val;
|
|
305
|
+
carry = y->limbs[i] >> (64 - norm_shift);
|
|
306
|
+
}
|
|
307
|
+
v->used = y->used;
|
|
308
|
+
|
|
309
|
+
carry = 0;
|
|
310
|
+
for (size_t i = 0; i < x->used; i++) {
|
|
311
|
+
uint64_t val = (carry) | (x->limbs[i] << norm_shift);
|
|
312
|
+
u->limbs[i] = val;
|
|
313
|
+
carry = x->limbs[i] >> (64 - norm_shift);
|
|
314
|
+
}
|
|
315
|
+
u->limbs[x->used] = carry;
|
|
316
|
+
u->used = x->used + (carry ? 1 : 0);
|
|
317
|
+
} else {
|
|
318
|
+
memcpy(v->limbs, y->limbs, y->used * sizeof(uint64_t));
|
|
319
|
+
v->used = y->used;
|
|
320
|
+
memcpy(u->limbs, x->limbs, x->used * sizeof(uint64_t));
|
|
321
|
+
u->used = x->used;
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
size_t q_len = u->used - v->used + 1;
|
|
325
|
+
_bn_reserve(r, q_len);
|
|
326
|
+
memset(r->limbs, 0, q_len * sizeof(uint64_t));
|
|
327
|
+
r->used = q_len;
|
|
328
|
+
|
|
329
|
+
uint64_t v_top = v->limbs[v->used - 1];
|
|
330
|
+
|
|
331
|
+
for (size_t j = q_len; j > 0; j--) {
|
|
332
|
+
size_t idx = j - 1;
|
|
333
|
+
size_t u_idx = idx + v->used;
|
|
334
|
+
|
|
335
|
+
// Estimate quotient digit
|
|
336
|
+
__uint128_t u_hi;
|
|
337
|
+
if (u_idx >= u->used) {
|
|
338
|
+
if (u->used > 0) {
|
|
339
|
+
u_hi = ((__uint128_t)u->limbs[u->used - 1] << 64) |
|
|
340
|
+
(u->used > 1 ? u->limbs[u->used - 2] : 0);
|
|
341
|
+
} else {
|
|
342
|
+
u_hi = 0;
|
|
343
|
+
}
|
|
344
|
+
} else {
|
|
345
|
+
u_hi = ((__uint128_t)u->limbs[u_idx] << 64) |
|
|
346
|
+
(u_idx > 0 ? u->limbs[u_idx - 1] : 0);
|
|
347
|
+
}
|
|
348
|
+
__uint128_t q_est = u_hi / v_top;
|
|
349
|
+
if (q_est > 0xFFFFFFFFFFFFFFFFULL)
|
|
350
|
+
q_est = 0xFFFFFFFFFFFFFFFFULL;
|
|
351
|
+
|
|
352
|
+
// Subtract q_est * v from u
|
|
353
|
+
uint64_t borrow = 0;
|
|
354
|
+
for (size_t i = 0; i < v->used; i++) {
|
|
355
|
+
__uint128_t prod = q_est * v->limbs[i];
|
|
356
|
+
__uint128_t sub = (__uint128_t)u->limbs[idx + i] - (uint64_t)prod - borrow;
|
|
357
|
+
u->limbs[idx + i] = (uint64_t)sub;
|
|
358
|
+
borrow = (uint64_t)(prod >> 64) - (uint64_t)(sub >> 64);
|
|
359
|
+
}
|
|
360
|
+
__uint128_t final_sub = (__uint128_t)u->limbs[u_idx] - borrow;
|
|
361
|
+
u->limbs[u_idx] = (uint64_t)final_sub;
|
|
362
|
+
|
|
363
|
+
if ((uint64_t)(final_sub >> 64) != 0) {
|
|
364
|
+
// Quotient was too large, add back
|
|
365
|
+
q_est--;
|
|
366
|
+
uint64_t carry = 0;
|
|
367
|
+
for (size_t i = 0; i < v->used; i++) {
|
|
368
|
+
__uint128_t sum = (__uint128_t)u->limbs[idx + i] + v->limbs[i] + carry;
|
|
369
|
+
u->limbs[idx + i] = (uint64_t)sum;
|
|
370
|
+
carry = (uint64_t)(sum >> 64);
|
|
371
|
+
}
|
|
372
|
+
u->limbs[u_idx] += carry;
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
r->limbs[idx] = (uint64_t)q_est;
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
_bn_trim(r);
|
|
379
|
+
bigint_free(u);
|
|
380
|
+
bigint_free(v);
|
|
381
|
+
|
|
382
|
+
r->negative = x->negative ^ y->negative;
|
|
383
|
+
if (r->used == 1 && r->limbs[0] == 0) r->negative = 0;
|
|
384
|
+
return r;
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
void* bigint_mod(void* a, void* b) {
|
|
388
|
+
if (!a || !b) return bigint_from_int(0);
|
|
389
|
+
BigNum* x = (BigNum*)a;
|
|
390
|
+
void* q = bigint_div(a, b);
|
|
391
|
+
BigNum* qt = (BigNum*)q;
|
|
392
|
+
void* prod = bigint_mul(q, b);
|
|
393
|
+
BigNum* pt = (BigNum*)prod;
|
|
394
|
+
pt->negative = 0;
|
|
395
|
+
qt->negative = 0;
|
|
396
|
+
|
|
397
|
+
BigNum* r = _bn_alloc();
|
|
398
|
+
int cmp = _bn_cmp_mag(x, pt);
|
|
399
|
+
const BigNum* bigger = (cmp >= 0) ? (BigNum*)a : pt;
|
|
400
|
+
const BigNum* smaller = (cmp >= 0) ? pt : (BigNum*)a;
|
|
401
|
+
_bn_reserve(r, bigger->used);
|
|
402
|
+
uint64_t borrow = 0;
|
|
403
|
+
size_t i = 0;
|
|
404
|
+
for (; i < smaller->used; i++) {
|
|
405
|
+
__uint128_t v = (__uint128_t)bigger->limbs[i] - smaller->limbs[i] - borrow;
|
|
406
|
+
r->limbs[i] = (uint64_t)v;
|
|
407
|
+
borrow = (uint64_t)((v >> 64) & 1);
|
|
408
|
+
}
|
|
409
|
+
for (; i < bigger->used; i++) {
|
|
410
|
+
__uint128_t v = (__uint128_t)bigger->limbs[i] - borrow;
|
|
411
|
+
r->limbs[i] = (uint64_t)v;
|
|
412
|
+
borrow = (uint64_t)((v >> 64) & 1);
|
|
413
|
+
}
|
|
414
|
+
r->used = bigger->used;
|
|
415
|
+
_bn_trim(r);
|
|
416
|
+
r->negative = 0;
|
|
417
|
+
|
|
418
|
+
bigint_free(q);
|
|
419
|
+
bigint_free(prod);
|
|
420
|
+
return r;
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
int bigint_cmp(void* a, void* b) {
|
|
424
|
+
BigNum* x = (BigNum*)a;
|
|
425
|
+
BigNum* y = (BigNum*)b;
|
|
426
|
+
if (!x && !y) return 0;
|
|
427
|
+
if (!x) return y->negative ? 1 : -1;
|
|
428
|
+
if (!y) return x->negative ? -1 : 1;
|
|
429
|
+
if (x->negative != y->negative)
|
|
430
|
+
return x->negative ? -1 : 1;
|
|
431
|
+
int cmp = _bn_cmp_mag(x, y);
|
|
432
|
+
return x->negative ? -cmp : cmp;
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
void bigint_print(void* p) {
|
|
436
|
+
BigNum* b = (BigNum*)p;
|
|
437
|
+
if (!b) { printf("(null)"); return; }
|
|
438
|
+
if (b->negative) putchar('-');
|
|
439
|
+
if (b->used == 1 && b->limbs[0] == 0) {
|
|
440
|
+
putchar('0');
|
|
441
|
+
return;
|
|
442
|
+
}
|
|
443
|
+
size_t max_digits = b->used * 20 + 1;
|
|
444
|
+
char* buf = malloc(max_digits);
|
|
445
|
+
if (!buf) _bn_fail("bigint_print: alloc failed");
|
|
446
|
+
|
|
447
|
+
BigNum tmp;
|
|
448
|
+
tmp.limbs = malloc(b->used * sizeof(uint64_t));
|
|
449
|
+
memcpy(tmp.limbs, b->limbs, b->used * sizeof(uint64_t));
|
|
450
|
+
tmp.used = b->used;
|
|
451
|
+
tmp.len = b->used;
|
|
452
|
+
tmp.negative = 0;
|
|
453
|
+
|
|
454
|
+
size_t pos = max_digits;
|
|
455
|
+
buf[--pos] = '\0';
|
|
456
|
+
while (!(tmp.used == 1 && tmp.limbs[0] == 0)) {
|
|
457
|
+
uint64_t carry = 0;
|
|
458
|
+
for (size_t i = tmp.used; i > 0; i--) {
|
|
459
|
+
__uint128_t v = (__uint128_t)carry << 64 | tmp.limbs[i - 1];
|
|
460
|
+
tmp.limbs[i - 1] = (uint64_t)(v / 10);
|
|
461
|
+
carry = (uint64_t)(v % 10);
|
|
462
|
+
}
|
|
463
|
+
buf[--pos] = (char)('0' + carry);
|
|
464
|
+
_bn_trim(&tmp);
|
|
465
|
+
}
|
|
466
|
+
free(tmp.limbs);
|
|
467
|
+
printf("%s", buf + pos);
|
|
468
|
+
free(buf);
|
|
469
|
+
}
|
|
@@ -172,12 +172,17 @@ class LLVM:
|
|
|
172
172
|
return val
|
|
173
173
|
return self.builder.call(fn, [val])
|
|
174
174
|
|
|
175
|
-
def __init__(self, no_userspace=False, enable_extensions=True):
|
|
175
|
+
def __init__(self, no_userspace=False, enable_extensions=True, target_triple=None, no_gc=False):
|
|
176
176
|
self.module = ir.Module("main")
|
|
177
|
+
self.no_gc = no_gc
|
|
178
|
+
self._target_triple = target_triple
|
|
177
179
|
try:
|
|
178
180
|
import llvmlite.binding as _binding
|
|
179
181
|
_binding.initialize_native_target()
|
|
180
|
-
|
|
182
|
+
if target_triple:
|
|
183
|
+
_target = _binding.Target.from_triple(target_triple)
|
|
184
|
+
else:
|
|
185
|
+
_target = _binding.Target.from_default_triple()
|
|
181
186
|
_tm = _target.create_target_machine()
|
|
182
187
|
self.module.triple = _tm.triple
|
|
183
188
|
self.module.data_layout = _tm.target_data.get_data_layout()
|
|
@@ -253,18 +258,19 @@ class LLVM:
|
|
|
253
258
|
self.functions[name] = fn
|
|
254
259
|
|
|
255
260
|
# Concurrent tri-color GC runtime functions (ugc-based)
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
261
|
+
if not self.no_gc:
|
|
262
|
+
gc_fns = [
|
|
263
|
+
('gc_init', _void, []),
|
|
264
|
+
('gc_malloc', _i8ptr, [_i64]),
|
|
265
|
+
('gc_write_barrier', _void, [_i8ptr, _i8ptr]),
|
|
266
|
+
('gc_collect', _void, []),
|
|
267
|
+
('gc_start_thread', _void, []),
|
|
268
|
+
('gc_stop_thread', _void, []),
|
|
269
|
+
('gc_shutdown', _void, []),
|
|
270
|
+
]
|
|
271
|
+
for name, ret, args in gc_fns:
|
|
272
|
+
fn = ir.Function(self.module, ir.FunctionType(ret, args), name=name)
|
|
273
|
+
self.functions[name] = fn
|
|
268
274
|
|
|
269
275
|
# Exception handling globals
|
|
270
276
|
self._exc_buf_ptr = ir.GlobalVariable(self.module, _i8ptr, "_exc_buf_ptr")
|
|
@@ -510,19 +516,20 @@ class LLVM:
|
|
|
510
516
|
|
|
511
517
|
if wrapper_builder is not None:
|
|
512
518
|
self.builder = wrapper_builder
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
519
|
+
if not self.no_gc:
|
|
520
|
+
# Initialize concurrent tri-color GC and start background thread
|
|
521
|
+
gc_init_fn = self.functions.get('gc_init')
|
|
522
|
+
if gc_init_fn:
|
|
523
|
+
self.builder.call(gc_init_fn, [])
|
|
524
|
+
gc_start_fn = self.functions.get('gc_start_thread')
|
|
525
|
+
if gc_start_fn:
|
|
526
|
+
self.builder.call(gc_start_fn, [])
|
|
520
527
|
for node in toplevel:
|
|
521
528
|
self.emit(node)
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
529
|
+
if not self.no_gc:
|
|
530
|
+
gc_shutdown_fn = self.functions.get('gc_shutdown')
|
|
531
|
+
if gc_shutdown_fn:
|
|
532
|
+
self.builder.call(gc_shutdown_fn, [])
|
|
526
533
|
self.builder.ret(ir.Constant(ir.IntType(32), 0))
|
|
527
534
|
|
|
528
535
|
return self.module, self.import_src_files
|
|
@@ -758,6 +765,19 @@ class LLVM:
|
|
|
758
765
|
return ptr
|
|
759
766
|
|
|
760
767
|
def _get_malloc_fn(self):
|
|
768
|
+
if self.no_gc:
|
|
769
|
+
# Bare-metal: use plain malloc
|
|
770
|
+
fn = self._malloc_fn
|
|
771
|
+
if fn is not None:
|
|
772
|
+
return fn
|
|
773
|
+
for f in self.module.functions:
|
|
774
|
+
if f.name == 'malloc':
|
|
775
|
+
self._malloc_fn = f
|
|
776
|
+
return f
|
|
777
|
+
fnty = ir.FunctionType(_i8ptr, [_i64])
|
|
778
|
+
fn = ir.Function(self.module, fnty, 'malloc')
|
|
779
|
+
self._malloc_fn = fn
|
|
780
|
+
return fn
|
|
761
781
|
# Concurrent tri-color GC allocator
|
|
762
782
|
fn = self._gc_alloc_fn
|
|
763
783
|
if fn is not None:
|
|
@@ -788,6 +808,8 @@ class LLVM:
|
|
|
788
808
|
def _emit_write_barrier(self, parent_ptr, child_ptr):
|
|
789
809
|
"""Insert a write barrier call when storing a pointer value into a heap object.
|
|
790
810
|
parent_ptr and child_ptr must be i8* typed LLVM values."""
|
|
811
|
+
if self.no_gc:
|
|
812
|
+
return
|
|
791
813
|
if parent_ptr.type != _i8ptr:
|
|
792
814
|
parent_ptr = self.builder.bitcast(parent_ptr, _i8ptr)
|
|
793
815
|
if child_ptr.type != _i8ptr:
|
|
@@ -1048,7 +1070,7 @@ class LLVM:
|
|
|
1048
1070
|
self.builder.position_at_end(entry)
|
|
1049
1071
|
|
|
1050
1072
|
# Initialize concurrent tri-color GC in main function
|
|
1051
|
-
if node.name == 'main':
|
|
1073
|
+
if node.name == 'main' and not self.no_gc:
|
|
1052
1074
|
gc_init_fn = self.functions.get('gc_init')
|
|
1053
1075
|
if gc_init_fn:
|
|
1054
1076
|
self.builder.call(gc_init_fn, [])
|
|
@@ -1072,7 +1094,7 @@ class LLVM:
|
|
|
1072
1094
|
|
|
1073
1095
|
if not self.builder.block.is_terminated:
|
|
1074
1096
|
# Shutdown GC before main returns
|
|
1075
|
-
if node.name == 'main':
|
|
1097
|
+
if node.name == 'main' and not self.no_gc:
|
|
1076
1098
|
gc_shutdown_fn = self.functions.get('gc_shutdown')
|
|
1077
1099
|
if gc_shutdown_fn:
|
|
1078
1100
|
self.builder.call(gc_shutdown_fn, [])
|
|
@@ -1092,7 +1114,7 @@ class LLVM:
|
|
|
1092
1114
|
return None
|
|
1093
1115
|
# Shutdown GC before main returns
|
|
1094
1116
|
fn_name = self.builder.function.name
|
|
1095
|
-
if fn_name == 'main':
|
|
1117
|
+
if fn_name == 'main' and not self.no_gc:
|
|
1096
1118
|
gc_shutdown_fn = self.functions.get('gc_shutdown')
|
|
1097
1119
|
if gc_shutdown_fn:
|
|
1098
1120
|
self.builder.call(gc_shutdown_fn, [])
|