cpyte 4.3.2__tar.gz → 4.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-4.3.2/source/cpyte.egg-info → cpyte-4.4.0}/PKG-INFO +1 -1
- {cpyte-4.3.2 → cpyte-4.4.0}/source/cpyte/__init__.py +1 -1
- {cpyte-4.3.2 → cpyte-4.4.0}/source/cpyte/bytecoding.py +89 -60
- {cpyte-4.3.2 → cpyte-4.4.0}/source/cpyte/compiling.py +53 -12
- {cpyte-4.3.2 → cpyte-4.4.0}/source/cpyte/lsp_server.py +5 -3
- {cpyte-4.3.2 → cpyte-4.4.0}/source/cpyte/mainpie.py +209 -31
- {cpyte-4.3.2 → cpyte-4.4.0}/source/cpyte/runtime_scorpion.c +172 -18
- cpyte-4.4.0/source/cpyte/scorpion_abi.py +220 -0
- {cpyte-4.3.2 → cpyte-4.4.0}/source/cpyte/semantic_analasis.py +184 -18
- {cpyte-4.3.2 → cpyte-4.4.0/source/cpyte.egg-info}/PKG-INFO +1 -1
- {cpyte-4.3.2 → cpyte-4.4.0}/source/cpyte.egg-info/SOURCES.txt +3 -0
- cpyte-4.4.0/test/test_scorpion_abi.py +359 -0
- cpyte-4.4.0/test/test_scorpion_dl.py +329 -0
- {cpyte-4.3.2 → cpyte-4.4.0}/MANIFEST.in +0 -0
- {cpyte-4.3.2 → cpyte-4.4.0}/pyproject.toml +0 -0
- {cpyte-4.3.2 → cpyte-4.4.0}/readme.md +0 -0
- {cpyte-4.3.2 → cpyte-4.4.0}/setup.cfg +0 -0
- {cpyte-4.3.2 → cpyte-4.4.0}/source/cpyte/__main__.py +0 -0
- {cpyte-4.3.2 → cpyte-4.4.0}/source/cpyte/_bignum_bc.py +0 -0
- {cpyte-4.3.2 → cpyte-4.4.0}/source/cpyte/_runtime_bc.py +0 -0
- {cpyte-4.3.2 → cpyte-4.4.0}/source/cpyte/astparse.py +0 -0
- {cpyte-4.3.2 → cpyte-4.4.0}/source/cpyte/bignum.c +0 -0
- {cpyte-4.3.2 → cpyte-4.4.0}/source/cpyte/clib.py +0 -0
- {cpyte-4.3.2 → cpyte-4.4.0}/source/cpyte/elf2sef.py +0 -0
- {cpyte-4.3.2 → cpyte-4.4.0}/source/cpyte/extension_hooks.py +0 -0
- {cpyte-4.3.2 → cpyte-4.4.0}/source/cpyte/formatter.py +0 -0
- {cpyte-4.3.2 → cpyte-4.4.0}/source/cpyte/gc_runtime.c +0 -0
- {cpyte-4.3.2 → cpyte-4.4.0}/source/cpyte/generate_bc.py +0 -0
- {cpyte-4.3.2 → cpyte-4.4.0}/source/cpyte/lexar.py +0 -0
- {cpyte-4.3.2 → cpyte-4.4.0}/source/cpyte/linker.py +0 -0
- {cpyte-4.3.2 → cpyte-4.4.0}/source/cpyte/mksef.py +0 -0
- {cpyte-4.3.2 → cpyte-4.4.0}/source/cpyte/optimizations.py +0 -0
- {cpyte-4.3.2 → cpyte-4.4.0}/source/cpyte/package_manifest.py +0 -0
- {cpyte-4.3.2 → cpyte-4.4.0}/source/cpyte/runtime.c +0 -0
- {cpyte-4.3.2 → cpyte-4.4.0}/source/cpyte/sef.py +0 -0
- {cpyte-4.3.2 → cpyte-4.4.0}/source/cpyte/ugc.h +0 -0
- {cpyte-4.3.2 → cpyte-4.4.0}/source/cpyte/ui.py +0 -0
- {cpyte-4.3.2 → cpyte-4.4.0}/source/cpyte/update_check.py +0 -0
- {cpyte-4.3.2 → cpyte-4.4.0}/source/cpyte/winjit_patch.py +0 -0
- {cpyte-4.3.2 → cpyte-4.4.0}/source/cpyte/winjit_stubs.c +0 -0
- {cpyte-4.3.2 → cpyte-4.4.0}/source/cpyte.egg-info/dependency_links.txt +0 -0
- {cpyte-4.3.2 → cpyte-4.4.0}/source/cpyte.egg-info/entry_points.txt +0 -0
- {cpyte-4.3.2 → cpyte-4.4.0}/source/cpyte.egg-info/requires.txt +0 -0
- {cpyte-4.3.2 → cpyte-4.4.0}/source/cpyte.egg-info/top_level.txt +0 -0
- {cpyte-4.3.2 → cpyte-4.4.0}/test/test_bignum_jit.py +0 -0
- {cpyte-4.3.2 → cpyte-4.4.0}/test/test_fuzz_del_has.py +0 -0
- {cpyte-4.3.2 → cpyte-4.4.0}/test/test_sef_tools.py +0 -0
|
@@ -261,6 +261,12 @@ class LLVM:
|
|
|
261
261
|
# i32 fallthrough) lets `(size_t)ptr`/`(ptr)(size_t)` round-trips
|
|
262
262
|
# preserve the full address instead of truncating to 32 bits.
|
|
263
263
|
result = ir.IntType(64)
|
|
264
|
+
elif t in ("uint8", "char"):
|
|
265
|
+
result = ir.IntType(8)
|
|
266
|
+
elif t == "uint16":
|
|
267
|
+
result = ir.IntType(16)
|
|
268
|
+
elif t in ("uint32", "unsigned"):
|
|
269
|
+
result = ir.IntType(32)
|
|
264
270
|
elif t == "bool":
|
|
265
271
|
result = ir.IntType(1)
|
|
266
272
|
elif t in ("float", "double"):
|
|
@@ -269,8 +275,6 @@ class LLVM:
|
|
|
269
275
|
result = ir.VoidType()
|
|
270
276
|
elif t == "str":
|
|
271
277
|
result = ir.PointerType(ir.IntType(8))
|
|
272
|
-
elif t == "char":
|
|
273
|
-
result = ir.IntType(8)
|
|
274
278
|
elif t == "void*" or t == "big" or t == "ubig":
|
|
275
279
|
result = ir.PointerType(ir.IntType(8))
|
|
276
280
|
elif t == "dynamic":
|
|
@@ -674,9 +678,11 @@ class LLVM:
|
|
|
674
678
|
debug_instrument=False,
|
|
675
679
|
debug_nids=None,
|
|
676
680
|
debug_step_ids=None,
|
|
681
|
+
scorpion=False,
|
|
677
682
|
):
|
|
678
683
|
self.module = ir.Module("main")
|
|
679
684
|
self.no_gc = no_gc
|
|
685
|
+
self.scorpion = scorpion
|
|
680
686
|
self.use_native_eh = use_native_eh
|
|
681
687
|
# --- cpdb debug instrumentation (opt-in, off by default) -------------
|
|
682
688
|
# When enabled, the emitter emits one `cpdbd_t_<nid>` tracer per step
|
|
@@ -813,6 +819,9 @@ class LLVM:
|
|
|
813
819
|
input_str_fn = ir.Function(self.module, input_str_ty, "input_str")
|
|
814
820
|
self.functions["input_str"] = input_str_fn
|
|
815
821
|
|
|
822
|
+
if self.scorpion:
|
|
823
|
+
self._declare_scorpion_abi()
|
|
824
|
+
|
|
816
825
|
# BigNum runtime functions
|
|
817
826
|
bignum_fns = [
|
|
818
827
|
("bigint_new", _i8ptr, []),
|
|
@@ -986,6 +995,38 @@ class LLVM:
|
|
|
986
995
|
)
|
|
987
996
|
self._code_skip.initializer = ir.Constant(ir.IntType(1), 0) # type: ignore[attr-defined]
|
|
988
997
|
|
|
998
|
+
def _declare_scorpion_abi(self):
|
|
999
|
+
"""Declare the Scorpion ABI wrappers and register `ScorpionLibInfo`.
|
|
1000
|
+
|
|
1001
|
+
Enabled by the `#scorpion` source directive. Each wrapper is an extern
|
|
1002
|
+
resolved by `runtime_scorpion.c`, which ships the same `ecall`
|
|
1003
|
+
encoding the Xtensa-only inline wrappers in `abi/scorpion.h` use (the
|
|
1004
|
+
`a0`-`a7` register names are the RISC-V argument registers too, so the
|
|
1005
|
+
ABI is identical on both architectures).
|
|
1006
|
+
|
|
1007
|
+
`ScorpionLibInfo` is materialized here rather than as a parsed
|
|
1008
|
+
StructDef because it has no node in the AST: the kernel writes the
|
|
1009
|
+
exact 32-byte layout through `scorpion_lib_info()`, so the `uint16`
|
|
1010
|
+
tail must really be i16 (seven i32 + two i16, no padding).
|
|
1011
|
+
"""
|
|
1012
|
+
from . import scorpion_abi
|
|
1013
|
+
|
|
1014
|
+
st = self.module.context.get_identified_type(
|
|
1015
|
+
f"struct.{scorpion_abi.LIB_INFO_NAME}"
|
|
1016
|
+
)
|
|
1017
|
+
if st.is_opaque:
|
|
1018
|
+
st.set_body(*[self.llvm_type(t) for _, t in scorpion_abi.LIB_INFO_FIELDS])
|
|
1019
|
+
self.structs[scorpion_abi.LIB_INFO_NAME] = st
|
|
1020
|
+
self.struct_fields[scorpion_abi.LIB_INFO_NAME] = scorpion_abi.lib_info_fields()
|
|
1021
|
+
|
|
1022
|
+
for name, (ret_type, params, vararg) in scorpion_abi.FUNCTIONS.items():
|
|
1023
|
+
fnty = ir.FunctionType(
|
|
1024
|
+
self.llvm_type(ret_type),
|
|
1025
|
+
[self.llvm_type(t) for _, t in params],
|
|
1026
|
+
var_arg=vararg,
|
|
1027
|
+
)
|
|
1028
|
+
self.functions[name] = ir.Function(self.module, fnty, name)
|
|
1029
|
+
|
|
989
1030
|
# CRITICAL CONSTANT FOLDING BUG
|
|
990
1031
|
def _isolate_const_prop_branch(self, body):
|
|
991
1032
|
"""Run one control-flow branch with isolated constant propagation.
|
|
@@ -1451,8 +1492,17 @@ class LLVM:
|
|
|
1451
1492
|
|
|
1452
1493
|
if os.environ.get("CPYTE_JIT_DEBUG"):
|
|
1453
1494
|
import sys as _sys
|
|
1454
|
-
|
|
1455
|
-
print(
|
|
1495
|
+
|
|
1496
|
+
print(
|
|
1497
|
+
"[bytecoding] runtime hooks:",
|
|
1498
|
+
[h.name for h in self._hook_registry.get(HookStage.RUNTIME)],
|
|
1499
|
+
file=_sys.stderr,
|
|
1500
|
+
)
|
|
1501
|
+
print(
|
|
1502
|
+
"[bytecoding] import_src_files:",
|
|
1503
|
+
self.import_src_files,
|
|
1504
|
+
file=_sys.stderr,
|
|
1505
|
+
)
|
|
1456
1506
|
|
|
1457
1507
|
for node in structs:
|
|
1458
1508
|
if isinstance(node, ClassDef):
|
|
@@ -1638,25 +1688,20 @@ class LLVM:
|
|
|
1638
1688
|
name = target.name
|
|
1639
1689
|
if name in self.locals:
|
|
1640
1690
|
ptr = self.locals[name]
|
|
1641
|
-
if not isinstance(
|
|
1642
|
-
|
|
1643
|
-
):
|
|
1644
|
-
self.builder.store(
|
|
1645
|
-
ir.Constant(ptr.type.pointee, None), ptr
|
|
1646
|
-
)
|
|
1691
|
+
if not isinstance(getattr(ptr.type, "pointee", None), ir.PointerType):
|
|
1692
|
+
self.builder.store(ir.Constant(ptr.type.pointee, None), ptr)
|
|
1647
1693
|
for table in (self.locals, self.local_types, self.ssa_values):
|
|
1648
1694
|
table.pop(name, None)
|
|
1649
1695
|
self.const_vars.pop(name, None)
|
|
1650
1696
|
return
|
|
1651
1697
|
if kind == "dynamic":
|
|
1652
1698
|
name = target.name
|
|
1653
|
-
if
|
|
1654
|
-
self.locals
|
|
1655
|
-
|
|
1699
|
+
if (
|
|
1700
|
+
name in self.locals
|
|
1701
|
+
and getattr(self.locals[name].type, "pointee", None) == _DynValue
|
|
1702
|
+
):
|
|
1656
1703
|
zero = ir.Constant(_DynValue, ir.Undefined)
|
|
1657
|
-
zero = self.builder.insert_value(
|
|
1658
|
-
zero, ir.Constant(_i32, _DYN_NONE), 0
|
|
1659
|
-
)
|
|
1704
|
+
zero = self.builder.insert_value(zero, ir.Constant(_i32, _DYN_NONE), 0)
|
|
1660
1705
|
zero = self.builder.insert_value(zero, ir.Constant(_i64, 0), 1)
|
|
1661
1706
|
self.builder.store(zero, self.locals[name])
|
|
1662
1707
|
else:
|
|
@@ -2075,18 +2120,14 @@ class LLVM:
|
|
|
2075
2120
|
index_fields = [Field("@vptr", "void*", token=node._token)] + all_fields
|
|
2076
2121
|
field_tys = [self.llvm_type(f.type_expr) for f in index_fields]
|
|
2077
2122
|
llvm_struct = self.structs.get(node.name)
|
|
2078
|
-
if llvm_struct is None or not isinstance(
|
|
2079
|
-
llvm_struct, ir.IdentifiedStructType
|
|
2080
|
-
):
|
|
2123
|
+
if llvm_struct is None or not isinstance(llvm_struct, ir.IdentifiedStructType):
|
|
2081
2124
|
# Pre-register an opaque identified struct BEFORE resolving field
|
|
2082
2125
|
# types so self-referential fields resolve to a pointer to this
|
|
2083
2126
|
# type instead of silently degrading to `i32`. get_identified_type
|
|
2084
2127
|
# registers into the module's context so the definition is
|
|
2085
2128
|
# serialized into the IR. Fieldless sealed classes still register
|
|
2086
2129
|
# (as an empty struct) so `new T` can allocate them.
|
|
2087
|
-
llvm_struct = self.module.context.get_identified_type(
|
|
2088
|
-
f"class.{node.name}"
|
|
2089
|
-
)
|
|
2130
|
+
llvm_struct = self.module.context.get_identified_type(f"class.{node.name}")
|
|
2090
2131
|
self.structs[node.name] = llvm_struct
|
|
2091
2132
|
if field_tys or index_fields:
|
|
2092
2133
|
if llvm_struct.is_opaque:
|
|
@@ -2141,9 +2182,7 @@ class LLVM:
|
|
|
2141
2182
|
wb.ret(ret)
|
|
2142
2183
|
self.functions[child_name] = wrapper
|
|
2143
2184
|
|
|
2144
|
-
def _declare_class_method(
|
|
2145
|
-
self, class_node: ClassDef, method: FuncDef
|
|
2146
|
-
):
|
|
2185
|
+
def _declare_class_method(self, class_node: ClassDef, method: FuncDef):
|
|
2147
2186
|
"""Create the `Class.method` header function if it doesn't exist yet."""
|
|
2148
2187
|
class_ty = self.structs.get(class_node.name)
|
|
2149
2188
|
if class_ty is None:
|
|
@@ -2197,17 +2236,13 @@ class LLVM:
|
|
|
2197
2236
|
slots = self._class_slot_list(cls)
|
|
2198
2237
|
vt_ty = ir.LiteralStructType(
|
|
2199
2238
|
[_i64]
|
|
2200
|
-
+ [
|
|
2201
|
-
self.functions[f"{d}.{n}"].function_type.as_pointer()
|
|
2202
|
-
for n, d in slots
|
|
2203
|
-
]
|
|
2239
|
+
+ [self.functions[f"{d}.{n}"].function_type.as_pointer() for n, d in slots]
|
|
2204
2240
|
)
|
|
2205
2241
|
cid = self._class_ids.setdefault(cls, len(self._class_ids))
|
|
2206
2242
|
cv = ir.GlobalVariable(self.module, vt_ty, name=f"vt.{cls}")
|
|
2207
2243
|
cv.initializer = ir.Constant(
|
|
2208
2244
|
vt_ty,
|
|
2209
|
-
[ir.Constant(_i64, cid)]
|
|
2210
|
-
+ [self.functions[f"{d}.{n}"] for n, d in slots],
|
|
2245
|
+
[ir.Constant(_i64, cid)] + [self.functions[f"{d}.{n}"] for n, d in slots],
|
|
2211
2246
|
)
|
|
2212
2247
|
self._vt_types[cls] = vt_ty
|
|
2213
2248
|
self._vt_globals[cls] = cv
|
|
@@ -2356,7 +2391,9 @@ class LLVM:
|
|
|
2356
2391
|
for i, arg in enumerate(node.args or []):
|
|
2357
2392
|
init_args.append(
|
|
2358
2393
|
self._coerce_call_arg(
|
|
2359
|
-
self.emit(arg),
|
|
2394
|
+
self.emit(arg),
|
|
2395
|
+
ptypes[i + 1],
|
|
2396
|
+
getattr(arg, "inferred_type", None),
|
|
2360
2397
|
)
|
|
2361
2398
|
)
|
|
2362
2399
|
self.builder.call(init_fn, init_args)
|
|
@@ -2694,7 +2731,9 @@ class LLVM:
|
|
|
2694
2731
|
obj_decl = obj_decl or getattr(node.obj, "inferred_type", None)
|
|
2695
2732
|
if not (obj_decl and str(obj_decl).endswith("[]")):
|
|
2696
2733
|
call = Call(
|
|
2697
|
-
Attr(
|
|
2734
|
+
Attr(
|
|
2735
|
+
node.obj, "__getitem__", token=getattr(node.obj, "_token", None)
|
|
2736
|
+
),
|
|
2698
2737
|
[node.index],
|
|
2699
2738
|
token=node._token,
|
|
2700
2739
|
)
|
|
@@ -4629,7 +4668,9 @@ class LLVM:
|
|
|
4629
4668
|
typed class pointers and integer/fp literals."""
|
|
4630
4669
|
if isinstance(expected, ir.PointerType):
|
|
4631
4670
|
if isinstance(val.type, ir.PointerType):
|
|
4632
|
-
return
|
|
4671
|
+
return (
|
|
4672
|
+
self.builder.bitcast(val, expected) if val.type != expected else val
|
|
4673
|
+
)
|
|
4633
4674
|
if isinstance(val.type, ir.IntType):
|
|
4634
4675
|
return self.builder.inttoptr(val, expected)
|
|
4635
4676
|
return val
|
|
@@ -4640,7 +4681,9 @@ class LLVM:
|
|
|
4640
4681
|
return self.builder.sext(val, expected)
|
|
4641
4682
|
return self.builder.trunc(val, expected)
|
|
4642
4683
|
return val
|
|
4643
|
-
if isinstance(val.type, ir.DoubleType) or isinstance(
|
|
4684
|
+
if isinstance(val.type, ir.DoubleType) or isinstance(
|
|
4685
|
+
val.type, ir.FloatType
|
|
4686
|
+
):
|
|
4644
4687
|
return self.builder.fptosi(val, expected)
|
|
4645
4688
|
if isinstance(val.type, ir.PointerType) and expected.width >= 32:
|
|
4646
4689
|
return self.builder.ptrtoint(val, expected)
|
|
@@ -5731,7 +5774,8 @@ class LLVM:
|
|
|
5731
5774
|
for arg in node.args:
|
|
5732
5775
|
arg_val = self.emit(arg)
|
|
5733
5776
|
arg_val = self._coerce_call_arg(
|
|
5734
|
-
arg_val,
|
|
5777
|
+
arg_val,
|
|
5778
|
+
slot_fnty.args[len(args)],
|
|
5735
5779
|
getattr(arg, "inferred_type", None),
|
|
5736
5780
|
)
|
|
5737
5781
|
args.append(arg_val)
|
|
@@ -5760,7 +5804,8 @@ class LLVM:
|
|
|
5760
5804
|
for arg in node.args:
|
|
5761
5805
|
arg_val = self.emit(arg)
|
|
5762
5806
|
arg_val = self._coerce_call_arg(
|
|
5763
|
-
arg_val,
|
|
5807
|
+
arg_val,
|
|
5808
|
+
func.function_type.args[len(args)],
|
|
5764
5809
|
getattr(arg, "inferred_type", None),
|
|
5765
5810
|
)
|
|
5766
5811
|
args.append(arg_val)
|
|
@@ -5859,10 +5904,7 @@ class LLVM:
|
|
|
5859
5904
|
dunder_cls = node.callee._dunder_via
|
|
5860
5905
|
if dunder_cls is None:
|
|
5861
5906
|
dunder_cls = self._static_obj_class(node.callee)
|
|
5862
|
-
if (
|
|
5863
|
-
dunder_cls
|
|
5864
|
-
and self._dunder_fn_name(dunder_cls, "__call__") is not None
|
|
5865
|
-
):
|
|
5907
|
+
if dunder_cls and self._dunder_fn_name(dunder_cls, "__call__") is not None:
|
|
5866
5908
|
call = Call(
|
|
5867
5909
|
Attr(node.callee, "__call__", token=node.callee._token),
|
|
5868
5910
|
node.args,
|
|
@@ -6238,9 +6280,7 @@ class LLVM:
|
|
|
6238
6280
|
for f in fields:
|
|
6239
6281
|
fname = self._string_const(f.name)
|
|
6240
6282
|
cmp_res = self.builder.call(self._strcmp_fn, [name_val, fname])
|
|
6241
|
-
match = self.builder.icmp_signed(
|
|
6242
|
-
"==", cmp_res, ir.Constant(_i32, 0)
|
|
6243
|
-
)
|
|
6283
|
+
match = self.builder.icmp_signed("==", cmp_res, ir.Constant(_i32, 0))
|
|
6244
6284
|
result = self.builder.or_(result, match)
|
|
6245
6285
|
return result
|
|
6246
6286
|
if kind == "get_attr_lit":
|
|
@@ -6259,12 +6299,8 @@ class LLVM:
|
|
|
6259
6299
|
for i, f in enumerate(fields):
|
|
6260
6300
|
fname = self._string_const(f.name)
|
|
6261
6301
|
cmp_res = self.builder.call(self._strcmp_fn, [name_val, fname])
|
|
6262
|
-
match = self.builder.icmp_signed(
|
|
6263
|
-
|
|
6264
|
-
)
|
|
6265
|
-
idx = self.builder.select(
|
|
6266
|
-
match, ir.Constant(_i32, i), idx
|
|
6267
|
-
)
|
|
6302
|
+
match = self.builder.icmp_signed("==", cmp_res, ir.Constant(_i32, 0))
|
|
6303
|
+
idx = self.builder.select(match, ir.Constant(_i32, i), idx)
|
|
6268
6304
|
struct_start = self.builder.gep(
|
|
6269
6305
|
obj_ptr,
|
|
6270
6306
|
[ir.Constant(_i32, 0), ir.Constant(_i32, 0)],
|
|
@@ -6289,9 +6325,7 @@ class LLVM:
|
|
|
6289
6325
|
if getattr(self, "_ancestor_grid_emitted", False):
|
|
6290
6326
|
return
|
|
6291
6327
|
self._ancestor_grid_emitted = True
|
|
6292
|
-
classes = [
|
|
6293
|
-
c for c, n in self._struct_nodes.items() if isinstance(n, ClassDef)
|
|
6294
|
-
]
|
|
6328
|
+
classes = [c for c, n in self._struct_nodes.items() if isinstance(n, ClassDef)]
|
|
6295
6329
|
chains = {}
|
|
6296
6330
|
for c in classes:
|
|
6297
6331
|
cur = self._struct_nodes.get(c)
|
|
@@ -6359,13 +6393,9 @@ class LLVM:
|
|
|
6359
6393
|
self.builder.mul(rcid, ir.Constant(_i64, stride)),
|
|
6360
6394
|
ir.Constant(_i64, depth_t),
|
|
6361
6395
|
)
|
|
6362
|
-
row = self.builder.gep(
|
|
6363
|
-
grid, [ir.Constant(_i32, 0), off], inbounds=True
|
|
6364
|
-
)
|
|
6396
|
+
row = self.builder.gep(grid, [ir.Constant(_i32, 0), off], inbounds=True)
|
|
6365
6397
|
anc = self.builder.load(row)
|
|
6366
|
-
return self.builder.icmp_signed(
|
|
6367
|
-
"==", anc, ir.Constant(_i64, id_t)
|
|
6368
|
-
)
|
|
6398
|
+
return self.builder.icmp_signed("==", anc, ir.Constant(_i64, id_t))
|
|
6369
6399
|
|
|
6370
6400
|
def _emit_builtin_append(self, node):
|
|
6371
6401
|
"""append(arr, x) — grow a registered array by one element.
|
|
@@ -6941,7 +6971,6 @@ class LLVM:
|
|
|
6941
6971
|
self._const_prop_f = saved_f
|
|
6942
6972
|
|
|
6943
6973
|
def _emit_for_worker(self, node, var_name, iterable, body, iter_type, var_type):
|
|
6944
|
-
|
|
6945
6974
|
# ---- 3. Bounded loop unrolling for constant-size list literals ----
|
|
6946
6975
|
if (
|
|
6947
6976
|
isinstance(iterable, ListLit)
|
|
@@ -1677,9 +1677,14 @@ def _map_process_libc(engine, mod):
|
|
|
1677
1677
|
pass
|
|
1678
1678
|
break
|
|
1679
1679
|
if os.environ.get("CPYTE_JIT_DEBUG"):
|
|
1680
|
-
unset = [
|
|
1681
|
-
|
|
1682
|
-
|
|
1680
|
+
unset = [
|
|
1681
|
+
f.name
|
|
1682
|
+
for f in mod.functions
|
|
1683
|
+
if f.is_declaration
|
|
1684
|
+
and not f.name.startswith("llvm.")
|
|
1685
|
+
and f.name not in mapped
|
|
1686
|
+
and f.name not in _explicit_mapped
|
|
1687
|
+
]
|
|
1683
1688
|
if unset:
|
|
1684
1689
|
print("[jit] unresolved externs: %s" % sorted(unset), file=sys.stderr)
|
|
1685
1690
|
|
|
@@ -1817,7 +1822,9 @@ def _scorpion_tool(name):
|
|
|
1817
1822
|
if os.path.isfile(bundled):
|
|
1818
1823
|
return bundled
|
|
1819
1824
|
sibling = os.path.join(
|
|
1820
|
-
os.path.dirname(
|
|
1825
|
+
os.path.dirname(
|
|
1826
|
+
os.path.dirname(os.path.dirname(os.path.dirname(_RUNTIME_SCORPION_C)))
|
|
1827
|
+
),
|
|
1821
1828
|
"WEW-scorpion",
|
|
1822
1829
|
"tools" if name == "elf2sef.py" else "user",
|
|
1823
1830
|
name,
|
|
@@ -1833,6 +1840,11 @@ def run_scorpion(
|
|
|
1833
1840
|
pic=False,
|
|
1834
1841
|
exports=None,
|
|
1835
1842
|
auto_exports=None,
|
|
1843
|
+
requires=None,
|
|
1844
|
+
scopes=None,
|
|
1845
|
+
weaks=None,
|
|
1846
|
+
lazy=None,
|
|
1847
|
+
versym=None,
|
|
1836
1848
|
):
|
|
1837
1849
|
"""Compile a Cpyte module for Scorpion (RV32 bare-metal) producing a SEF file.
|
|
1838
1850
|
Please use it good! :):)
|
|
@@ -1840,11 +1852,20 @@ def run_scorpion(
|
|
|
1840
1852
|
With pic=True the module is compiled with -fPIC and the final ELF is linked
|
|
1841
1853
|
with --emit-relocs so it can be converted to a dynamic (SEF v2) image via
|
|
1842
1854
|
WEW-scorpion/tools/elf2sef.py. `exports` names the symbols to mark as
|
|
1843
|
-
exported for dynamic linking (libraries)
|
|
1844
|
-
|
|
1845
|
-
|
|
1846
|
-
|
|
1847
|
-
|
|
1855
|
+
exported for dynamic linking (libraries); an entry is either `NAME` or
|
|
1856
|
+
elf2sef's `SYMBOL=WIRE_NAME` form to publish SYMBOL under a different wire
|
|
1857
|
+
name. `auto_exports` are additional candidates discovered automatically
|
|
1858
|
+
(top-level `public` functions); only those that actually resolve to a
|
|
1859
|
+
defined symbol in the emitted module are added (elf2sef refuses unknown
|
|
1860
|
+
names).
|
|
1861
|
+
|
|
1862
|
+
`requires` (`NAME=VER`), `scopes`, `weaks`, `lazy` and `versym` are the
|
|
1863
|
+
remaining elf2sef dynamic-linking controls, forwarded verbatim; see
|
|
1864
|
+
WEW-scorpion/docs/dynamic-linking.md. `lazy`/`versym` are tri-state (None
|
|
1865
|
+
= leave elf2sef's default). They only apply to the pic path.
|
|
1866
|
+
|
|
1867
|
+
Returns (elf_file, [final exports]) so callers can report exactly what was
|
|
1868
|
+
published.
|
|
1848
1869
|
"""
|
|
1849
1870
|
from llvmlite import binding
|
|
1850
1871
|
|
|
@@ -1858,9 +1879,7 @@ def run_scorpion(
|
|
|
1858
1879
|
optimize(mod, opt_level)
|
|
1859
1880
|
mod.verify()
|
|
1860
1881
|
|
|
1861
|
-
defined = {
|
|
1862
|
-
f.name for f in mod.functions if not getattr(f, "is_declaration", True)
|
|
1863
|
-
}
|
|
1882
|
+
defined = {f.name for f in mod.functions if not getattr(f, "is_declaration", True)}
|
|
1864
1883
|
final_exports = list(exports or [])
|
|
1865
1884
|
seen = set(final_exports)
|
|
1866
1885
|
if auto_exports:
|
|
@@ -1941,6 +1960,28 @@ def run_scorpion(
|
|
|
1941
1960
|
if final_exports:
|
|
1942
1961
|
for name in final_exports:
|
|
1943
1962
|
cmd += ["--export", name]
|
|
1963
|
+
# elf2sef rejects --no-versym together with --lazy (a v2.0 import record
|
|
1964
|
+
# has no plt field, so a lazy site would point into an unresolvable
|
|
1965
|
+
# hole). Surface that here instead of as a subprocess error.
|
|
1966
|
+
if versym is False and lazy:
|
|
1967
|
+
print_err(
|
|
1968
|
+
"error: --no-versym cannot be combined with --lazy "
|
|
1969
|
+
"(a v2.0 import record has no plt field)"
|
|
1970
|
+
)
|
|
1971
|
+
raise SystemExit(1)
|
|
1972
|
+
for req in requires or ():
|
|
1973
|
+
cmd += ["--require", req]
|
|
1974
|
+
for scope in scopes or ():
|
|
1975
|
+
cmd += ["--scope", scope]
|
|
1976
|
+
for weak in weaks or ():
|
|
1977
|
+
cmd += ["--weak", weak]
|
|
1978
|
+
if lazy is not None:
|
|
1979
|
+
cmd.append("--lazy" if lazy else "--no-lazy")
|
|
1980
|
+
# elf2sef has no `--versym`: wide (v2.1) records are the default and
|
|
1981
|
+
# only the downgrade is selectable. So `--versym` is an explicit
|
|
1982
|
+
# restatement of the default and forwards nothing.
|
|
1983
|
+
if versym is False:
|
|
1984
|
+
cmd.append("--no-versym")
|
|
1944
1985
|
r = subprocess.run(cmd, capture_output=True, text=True)
|
|
1945
1986
|
if r.returncode != 0:
|
|
1946
1987
|
print_err(f"error converting to SEF: {format_cc_diag(r.stderr)}")
|
|
@@ -11,14 +11,12 @@ from pygls.cli import start_server
|
|
|
11
11
|
from pygls.lsp.server import LanguageServer
|
|
12
12
|
|
|
13
13
|
from .astparse import (
|
|
14
|
-
Assign,
|
|
15
14
|
Call,
|
|
16
15
|
ClassDef,
|
|
17
16
|
EnumDef,
|
|
18
17
|
FuncDef,
|
|
19
18
|
If,
|
|
20
19
|
Import,
|
|
21
|
-
NewExpr,
|
|
22
20
|
ParseError,
|
|
23
21
|
StructDef,
|
|
24
22
|
Switch,
|
|
@@ -31,6 +29,7 @@ from .astparse import (
|
|
|
31
29
|
from .formatter import format_source
|
|
32
30
|
from .lexar import Lexer, LexerError, TokenType
|
|
33
31
|
from .semantic_analasis import SemanticAnalyzer
|
|
32
|
+
from . import scorpion_abi
|
|
34
33
|
from .clib import _BUILTIN_LIB_HEADERS
|
|
35
34
|
|
|
36
35
|
logging.basicConfig(level=logging.INFO, format="%(message)s")
|
|
@@ -282,7 +281,10 @@ def _analyze(source, filepath=None, workspace_root=None):
|
|
|
282
281
|
return tokens, parsed, analyzer, error
|
|
283
282
|
try:
|
|
284
283
|
analyzer = SemanticAnalyzer(
|
|
285
|
-
source,
|
|
284
|
+
source,
|
|
285
|
+
filepath=filepath,
|
|
286
|
+
workspace_root=workspace_root,
|
|
287
|
+
scorpion=scorpion_abi.detect(source)[1],
|
|
286
288
|
)
|
|
287
289
|
analyzer.analyze(parsed)
|
|
288
290
|
except Exception as e:
|