cpyte 2.3.0__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.
Files changed (33) hide show
  1. cpyte-2.4.0/MANIFEST.in +1 -0
  2. {cpyte-2.3.0 → cpyte-2.4.0}/PKG-INFO +1 -1
  3. {cpyte-2.3.0 → cpyte-2.4.0}/pyproject.toml +1 -1
  4. cpyte-2.4.0/source/cpyte/bignum.c +469 -0
  5. {cpyte-2.3.0 → cpyte-2.4.0}/source/cpyte/bytecoding.py +57 -29
  6. {cpyte-2.3.0 → cpyte-2.4.0}/source/cpyte/compiling.py +195 -1
  7. cpyte-2.4.0/source/cpyte/gc_runtime.c +322 -0
  8. {cpyte-2.3.0 → cpyte-2.4.0}/source/cpyte/mainpie.py +15 -6
  9. cpyte-2.4.0/source/cpyte/runtime.c +63 -0
  10. cpyte-2.4.0/source/cpyte/runtime_scorpion.c +197 -0
  11. {cpyte-2.3.0 → cpyte-2.4.0}/source/cpyte.egg-info/PKG-INFO +1 -1
  12. {cpyte-2.3.0 → cpyte-2.4.0}/source/cpyte.egg-info/SOURCES.txt +5 -0
  13. {cpyte-2.3.0 → cpyte-2.4.0}/readme.md +0 -0
  14. {cpyte-2.3.0 → cpyte-2.4.0}/setup.cfg +0 -0
  15. {cpyte-2.3.0 → cpyte-2.4.0}/source/cpyte/__init__.py +0 -0
  16. {cpyte-2.3.0 → cpyte-2.4.0}/source/cpyte/__main__.py +0 -0
  17. {cpyte-2.3.0 → cpyte-2.4.0}/source/cpyte/_bignum_bc.py +0 -0
  18. {cpyte-2.3.0 → cpyte-2.4.0}/source/cpyte/_gc_bc.py +0 -0
  19. {cpyte-2.3.0 → cpyte-2.4.0}/source/cpyte/_runtime_bc.py +0 -0
  20. {cpyte-2.3.0 → cpyte-2.4.0}/source/cpyte/astparse.py +0 -0
  21. {cpyte-2.3.0 → cpyte-2.4.0}/source/cpyte/clib.py +0 -0
  22. {cpyte-2.3.0 → cpyte-2.4.0}/source/cpyte/extension_hooks.py +0 -0
  23. {cpyte-2.3.0 → cpyte-2.4.0}/source/cpyte/generate_bc.py +0 -0
  24. {cpyte-2.3.0 → cpyte-2.4.0}/source/cpyte/lexar.py +0 -0
  25. {cpyte-2.3.0 → cpyte-2.4.0}/source/cpyte/linker.py +0 -0
  26. {cpyte-2.3.0 → cpyte-2.4.0}/source/cpyte/lsp_server.py +0 -0
  27. {cpyte-2.3.0 → cpyte-2.4.0}/source/cpyte/package_manifest.py +0 -0
  28. {cpyte-2.3.0 → cpyte-2.4.0}/source/cpyte/semantic_analasis.py +0 -0
  29. {cpyte-2.3.0 → cpyte-2.4.0}/source/cpyte.egg-info/dependency_links.txt +0 -0
  30. {cpyte-2.3.0 → cpyte-2.4.0}/source/cpyte.egg-info/entry_points.txt +0 -0
  31. {cpyte-2.3.0 → cpyte-2.4.0}/source/cpyte.egg-info/requires.txt +0 -0
  32. {cpyte-2.3.0 → cpyte-2.4.0}/source/cpyte.egg-info/top_level.txt +0 -0
  33. {cpyte-2.3.0 → cpyte-2.4.0}/test/test_bignum_jit.py +0 -0
@@ -0,0 +1 @@
1
+ include source/cpyte/*.c
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: cpyte
3
- Version: 2.3.0
3
+ Version: 2.4.0
4
4
  Summary: The Cpyte programming language compiler
5
5
  Author: Hoang Duy Tung
6
6
  License: MIT
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "cpyte"
7
- version = "2.3.0"
7
+ version = "2.4.0"
8
8
  description = "The Cpyte programming language compiler"
9
9
  readme = "readme.md"
10
10
  requires-python = ">=3.11"
@@ -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
- _target = _binding.Target.from_default_triple()
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()
@@ -200,6 +205,7 @@ class LLVM:
200
205
  self._free_fn = None
201
206
  self._gc_alloc_fn = None
202
207
  self._gc_write_barrier_fn = None
208
+ self._sizeof_cache = {}
203
209
  self._strlen_fn = None
204
210
  self._memcpy_fn = None
205
211
  self.no_userspace = no_userspace
@@ -252,18 +258,19 @@ class LLVM:
252
258
  self.functions[name] = fn
253
259
 
254
260
  # Concurrent tri-color GC runtime functions (ugc-based)
255
- gc_fns = [
256
- ('gc_init', _void, []),
257
- ('gc_malloc', _i8ptr, [_i64]),
258
- ('gc_write_barrier', _void, [_i8ptr, _i8ptr]),
259
- ('gc_collect', _void, []),
260
- ('gc_start_thread', _void, []),
261
- ('gc_stop_thread', _void, []),
262
- ('gc_shutdown', _void, []),
263
- ]
264
- for name, ret, args in gc_fns:
265
- fn = ir.Function(self.module, ir.FunctionType(ret, args), name=name)
266
- self.functions[name] = fn
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
267
274
 
268
275
  # Exception handling globals
269
276
  self._exc_buf_ptr = ir.GlobalVariable(self.module, _i8ptr, "_exc_buf_ptr")
@@ -509,19 +516,20 @@ class LLVM:
509
516
 
510
517
  if wrapper_builder is not None:
511
518
  self.builder = wrapper_builder
512
- # Initialize concurrent tri-color GC and start background thread
513
- gc_init_fn = self.functions.get('gc_init')
514
- if gc_init_fn:
515
- self.builder.call(gc_init_fn, [])
516
- gc_start_fn = self.functions.get('gc_start_thread')
517
- if gc_start_fn:
518
- self.builder.call(gc_start_fn, [])
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, [])
519
527
  for node in toplevel:
520
528
  self.emit(node)
521
- # Shutdown GC before exit
522
- gc_shutdown_fn = self.functions.get('gc_shutdown')
523
- if gc_shutdown_fn:
524
- self.builder.call(gc_shutdown_fn, [])
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, [])
525
533
  self.builder.ret(ir.Constant(ir.IntType(32), 0))
526
534
 
527
535
  return self.module, self.import_src_files
@@ -757,6 +765,19 @@ class LLVM:
757
765
  return ptr
758
766
 
759
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
760
781
  # Concurrent tri-color GC allocator
761
782
  fn = self._gc_alloc_fn
762
783
  if fn is not None:
@@ -787,6 +808,8 @@ class LLVM:
787
808
  def _emit_write_barrier(self, parent_ptr, child_ptr):
788
809
  """Insert a write barrier call when storing a pointer value into a heap object.
789
810
  parent_ptr and child_ptr must be i8* typed LLVM values."""
811
+ if self.no_gc:
812
+ return
790
813
  if parent_ptr.type != _i8ptr:
791
814
  parent_ptr = self.builder.bitcast(parent_ptr, _i8ptr)
792
815
  if child_ptr.type != _i8ptr:
@@ -845,8 +868,13 @@ class LLVM:
845
868
  return (4, 4)
846
869
 
847
870
  def _sizeof_type(self, ty):
871
+ key = id(ty)
872
+ if key in self._sizeof_cache:
873
+ return self._sizeof_cache[key]
848
874
  sz, _ = self._type_abi_info(ty)
849
- return ir.Constant(ir.IntType(32), sz)
875
+ c = ir.Constant(ir.IntType(32), sz)
876
+ self._sizeof_cache[key] = c
877
+ return c
850
878
 
851
879
  def emit_deref(self, node: Deref):
852
880
  ptr = self.emit(node.operand)
@@ -1042,7 +1070,7 @@ class LLVM:
1042
1070
  self.builder.position_at_end(entry)
1043
1071
 
1044
1072
  # Initialize concurrent tri-color GC in main function
1045
- if node.name == 'main':
1073
+ if node.name == 'main' and not self.no_gc:
1046
1074
  gc_init_fn = self.functions.get('gc_init')
1047
1075
  if gc_init_fn:
1048
1076
  self.builder.call(gc_init_fn, [])
@@ -1066,7 +1094,7 @@ class LLVM:
1066
1094
 
1067
1095
  if not self.builder.block.is_terminated:
1068
1096
  # Shutdown GC before main returns
1069
- if node.name == 'main':
1097
+ if node.name == 'main' and not self.no_gc:
1070
1098
  gc_shutdown_fn = self.functions.get('gc_shutdown')
1071
1099
  if gc_shutdown_fn:
1072
1100
  self.builder.call(gc_shutdown_fn, [])
@@ -1086,7 +1114,7 @@ class LLVM:
1086
1114
  return None
1087
1115
  # Shutdown GC before main returns
1088
1116
  fn_name = self.builder.function.name
1089
- if fn_name == 'main':
1117
+ if fn_name == 'main' and not self.no_gc:
1090
1118
  gc_shutdown_fn = self.functions.get('gc_shutdown')
1091
1119
  if gc_shutdown_fn:
1092
1120
  self.builder.call(gc_shutdown_fn, [])