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.
Files changed (33) hide show
  1. cpyte-2.4.0/MANIFEST.in +1 -0
  2. {cpyte-2.3.1 → cpyte-2.4.0}/PKG-INFO +1 -1
  3. {cpyte-2.3.1 → cpyte-2.4.0}/pyproject.toml +1 -1
  4. cpyte-2.4.0/source/cpyte/bignum.c +469 -0
  5. {cpyte-2.3.1 → cpyte-2.4.0}/source/cpyte/bytecoding.py +50 -28
  6. {cpyte-2.3.1 → cpyte-2.4.0}/source/cpyte/compiling.py +159 -1
  7. cpyte-2.4.0/source/cpyte/gc_runtime.c +322 -0
  8. {cpyte-2.3.1 → 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.1 → cpyte-2.4.0}/source/cpyte.egg-info/PKG-INFO +1 -1
  12. {cpyte-2.3.1 → cpyte-2.4.0}/source/cpyte.egg-info/SOURCES.txt +5 -0
  13. {cpyte-2.3.1 → cpyte-2.4.0}/readme.md +0 -0
  14. {cpyte-2.3.1 → cpyte-2.4.0}/setup.cfg +0 -0
  15. {cpyte-2.3.1 → cpyte-2.4.0}/source/cpyte/__init__.py +0 -0
  16. {cpyte-2.3.1 → cpyte-2.4.0}/source/cpyte/__main__.py +0 -0
  17. {cpyte-2.3.1 → cpyte-2.4.0}/source/cpyte/_bignum_bc.py +0 -0
  18. {cpyte-2.3.1 → cpyte-2.4.0}/source/cpyte/_gc_bc.py +0 -0
  19. {cpyte-2.3.1 → cpyte-2.4.0}/source/cpyte/_runtime_bc.py +0 -0
  20. {cpyte-2.3.1 → cpyte-2.4.0}/source/cpyte/astparse.py +0 -0
  21. {cpyte-2.3.1 → cpyte-2.4.0}/source/cpyte/clib.py +0 -0
  22. {cpyte-2.3.1 → cpyte-2.4.0}/source/cpyte/extension_hooks.py +0 -0
  23. {cpyte-2.3.1 → cpyte-2.4.0}/source/cpyte/generate_bc.py +0 -0
  24. {cpyte-2.3.1 → cpyte-2.4.0}/source/cpyte/lexar.py +0 -0
  25. {cpyte-2.3.1 → cpyte-2.4.0}/source/cpyte/linker.py +0 -0
  26. {cpyte-2.3.1 → cpyte-2.4.0}/source/cpyte/lsp_server.py +0 -0
  27. {cpyte-2.3.1 → cpyte-2.4.0}/source/cpyte/package_manifest.py +0 -0
  28. {cpyte-2.3.1 → cpyte-2.4.0}/source/cpyte/semantic_analasis.py +0 -0
  29. {cpyte-2.3.1 → cpyte-2.4.0}/source/cpyte.egg-info/dependency_links.txt +0 -0
  30. {cpyte-2.3.1 → cpyte-2.4.0}/source/cpyte.egg-info/entry_points.txt +0 -0
  31. {cpyte-2.3.1 → cpyte-2.4.0}/source/cpyte.egg-info/requires.txt +0 -0
  32. {cpyte-2.3.1 → cpyte-2.4.0}/source/cpyte.egg-info/top_level.txt +0 -0
  33. {cpyte-2.3.1 → 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.1
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.1"
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()
@@ -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
- gc_fns = [
257
- ('gc_init', _void, []),
258
- ('gc_malloc', _i8ptr, [_i64]),
259
- ('gc_write_barrier', _void, [_i8ptr, _i8ptr]),
260
- ('gc_collect', _void, []),
261
- ('gc_start_thread', _void, []),
262
- ('gc_stop_thread', _void, []),
263
- ('gc_shutdown', _void, []),
264
- ]
265
- for name, ret, args in gc_fns:
266
- fn = ir.Function(self.module, ir.FunctionType(ret, args), name=name)
267
- 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
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
- # Initialize concurrent tri-color GC and start background thread
514
- gc_init_fn = self.functions.get('gc_init')
515
- if gc_init_fn:
516
- self.builder.call(gc_init_fn, [])
517
- gc_start_fn = self.functions.get('gc_start_thread')
518
- if gc_start_fn:
519
- 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, [])
520
527
  for node in toplevel:
521
528
  self.emit(node)
522
- # Shutdown GC before exit
523
- gc_shutdown_fn = self.functions.get('gc_shutdown')
524
- if gc_shutdown_fn:
525
- 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, [])
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, [])