@tishlang/tish-lint 3.2.2 → 3.3.3
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.
- package/bin/tish-lint +0 -0
- package/crates/tish_compile/src/codegen.rs +1838 -162
- package/crates/tish_compile/src/types.rs +6 -0
- package/crates/tish_compile/tests/perf_codegen_i32_native_abi.rs +113 -0
- package/crates/tish_compile/tests/regr_gba_lowered_call_sites.rs +891 -0
- package/crates/tish_lint/Cargo.toml +1 -1
- package/crates/tish_native/src/build.rs +24 -6
- package/crates/tish_runtime_gba/src/gba.rs +26 -6
- package/crates/tish_runtime_gba/src/lib.rs +29 -0
- package/package.json +1 -1
- package/platform/darwin-arm64/tish-lint +0 -0
- package/platform/darwin-x64/tish-lint +0 -0
- package/platform/linux-arm64/tish-lint +0 -0
- package/platform/linux-x64/tish-lint +0 -0
- package/platform/win32-x64/tish-lint.exe +0 -0
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
//! Build native binary via cargo (interim path until Cranelift backend is ready).
|
|
2
2
|
|
|
3
3
|
use std::fs;
|
|
4
|
-
use std::path::Path;
|
|
4
|
+
use std::path::{Path, PathBuf};
|
|
5
5
|
|
|
6
6
|
use tishlang_compile::ResolvedNativeModule;
|
|
7
7
|
|
|
@@ -627,15 +627,34 @@ runner = ["mgba-qt", "-C", "logToStdout=1", "-C", "logLevel.gba.debug=127"]
|
|
|
627
627
|
// with `-Tgba.ld` — cargo *joins* rustflags arrays across config files, so a
|
|
628
628
|
// config-file approach would pass `-Tgba.ld` twice ("region already defined").
|
|
629
629
|
// build-std still comes from the generated `[unstable]` config (not rustflags).
|
|
630
|
-
|
|
630
|
+
//
|
|
631
|
+
// TISH_GBA_TARGET_DIR (opt-in, explicit — deliberately NOT the ambient
|
|
632
|
+
// CARGO_TARGET_DIR, which the desktop path scrubs for good reason): share ONE
|
|
633
|
+
// cargo target dir across every example's ROM build. Each example otherwise
|
|
634
|
+
// carries a full private dependency tree — measured at ~45 GB across the
|
|
635
|
+
// tish-gba fleet, and it filled the disk mid-build once. An inherited
|
|
636
|
+
// CARGO_TARGET_DIR meanwhile made cargo write where the ELF lookup below
|
|
637
|
+
// never looked ("GBA ELF not found" on a SUCCESSFUL compile), so that env is
|
|
638
|
+
// scrubbed here and only the explicit opt-in steers both paths together.
|
|
639
|
+
let shared_target = std::env::var_os("TISH_GBA_TARGET_DIR").map(PathBuf::from);
|
|
640
|
+
let target_root = shared_target
|
|
641
|
+
.clone()
|
|
642
|
+
.unwrap_or_else(|| build_dir.join("target"));
|
|
643
|
+
let mut cargo = Command::new("cargo");
|
|
644
|
+
cargo
|
|
631
645
|
.arg("build")
|
|
632
646
|
.arg("--release")
|
|
633
647
|
.current_dir(&build_dir)
|
|
648
|
+
.env_remove("CARGO_TARGET_DIR")
|
|
634
649
|
.env(
|
|
635
650
|
"RUSTFLAGS",
|
|
636
651
|
"-Clink-arg=-Tgba.ld -Ctarget-cpu=arm7tdmi -Cforce-frame-pointers=yes",
|
|
637
652
|
)
|
|
638
|
-
.env("CARGO_TERM_COLOR", "always")
|
|
653
|
+
.env("CARGO_TERM_COLOR", "always");
|
|
654
|
+
if let Some(dir) = &shared_target {
|
|
655
|
+
cargo.env("CARGO_TARGET_DIR", dir);
|
|
656
|
+
}
|
|
657
|
+
let status = cargo
|
|
639
658
|
.status()
|
|
640
659
|
.map_err(|e| format!("Failed to run cargo for GBA build: {}", e))?;
|
|
641
660
|
if !status.success() {
|
|
@@ -645,9 +664,8 @@ runner = ["mgba-qt", "-C", "logToStdout=1", "-C", "logLevel.gba.debug=127"]
|
|
|
645
664
|
));
|
|
646
665
|
}
|
|
647
666
|
|
|
648
|
-
// ELF → .gba via agb-gbafix.
|
|
649
|
-
let elf =
|
|
650
|
-
.join("target")
|
|
667
|
+
// ELF → .gba via agb-gbafix. Resolved from the SAME root the build wrote to.
|
|
668
|
+
let elf = target_root
|
|
651
669
|
.join("thumbv4t-none-eabi")
|
|
652
670
|
.join("release")
|
|
653
671
|
.join(&cargo_name);
|
|
@@ -101,21 +101,41 @@ type BgAsset = (
|
|
|
101
101
|
&'static agb::display::tile_data::TileData,
|
|
102
102
|
);
|
|
103
103
|
|
|
104
|
-
|
|
104
|
+
/// ⚠️ A FIXED TABLE, not a `Vec`, because every entry is `&'static` cartridge data and the registry
|
|
105
|
+
/// never needed to own one.
|
|
106
|
+
///
|
|
107
|
+
/// As a `Vec` it did: registering N backgrounds ran N pushes with log2(N) reallocs, all during
|
|
108
|
+
/// module init before the program body, and the freed buffers left the heap too fragmented for the
|
|
109
|
+
/// one big contiguous block a GBA UI canvas wants. A game with a handful of backgrounds booted; a
|
|
110
|
+
/// game with 162 died in the allocator with plenty of total heap free.
|
|
111
|
+
///
|
|
112
|
+
/// This costs `MAX_BGS * size_of::<Option<BgAsset>>()` of STATIC memory and allocates nothing.
|
|
113
|
+
/// ⚠️ Not a `Vec` with `reserve` — that charges every small game for the largest one.
|
|
114
|
+
const MAX_BGS: usize = 256;
|
|
115
|
+
static ASSET_BGS: SingleCore<RefCell<[Option<BgAsset>; MAX_BGS]>> =
|
|
116
|
+
SingleCore::new(RefCell::new([None; MAX_BGS]));
|
|
117
|
+
static ASSET_BGS_N: SingleCore<RefCell<usize>> = SingleCore::new(RefCell::new(0));
|
|
105
118
|
|
|
106
119
|
/// Register a background (palettes + tile data), returning its i32 handle.
|
|
107
120
|
pub fn __asset_register_bg(bg: BgAsset) -> i32 {
|
|
108
|
-
|
|
109
|
-
let mut
|
|
110
|
-
|
|
111
|
-
|
|
121
|
+
ASSET_BGS_N.with(|n| {
|
|
122
|
+
let mut n = n.borrow_mut();
|
|
123
|
+
if *n >= MAX_BGS {
|
|
124
|
+
return -1;
|
|
125
|
+
}
|
|
126
|
+
let idx = *n as i32;
|
|
127
|
+
ASSET_BGS.with(|c| c.borrow_mut()[*n] = Some(bg));
|
|
128
|
+
*n += 1;
|
|
112
129
|
idx
|
|
113
130
|
})
|
|
114
131
|
}
|
|
115
132
|
|
|
116
133
|
/// Look up a registered background by handle. `None` if out of range.
|
|
117
134
|
pub fn asset_bg(handle: i32) -> Option<BgAsset> {
|
|
118
|
-
|
|
135
|
+
if handle < 0 || handle as usize >= MAX_BGS {
|
|
136
|
+
return None;
|
|
137
|
+
}
|
|
138
|
+
ASSET_BGS.with(|c| c.borrow()[handle as usize])
|
|
119
139
|
}
|
|
120
140
|
|
|
121
141
|
/// Registered fonts (`font<N>:` imports) — a compile-time-baked `Font`. All `font<N>:` schemes share
|
|
@@ -283,6 +283,35 @@ pub fn str_index(s: &str, idx: &Value) -> Value {
|
|
|
283
283
|
}
|
|
284
284
|
}
|
|
285
285
|
|
|
286
|
+
/// `&str` charCodeAt — the code unit at `idx`, NaN when out of range. Mirrors
|
|
287
|
+
/// `tish_runtime::str_char_code_at`, and missing here for the same reason `str_index` was: codegen
|
|
288
|
+
/// emits it whenever the receiver is statically a `&str`, so `"abc".charCodeAt(i)` was a hard E0425
|
|
289
|
+
/// on the GBA target only while compiling everywhere else. Found by a ROM that hashes its own trace.
|
|
290
|
+
#[inline]
|
|
291
|
+
pub fn str_char_code_at(s: &str, idx: &Value) -> Value {
|
|
292
|
+
let i = match idx {
|
|
293
|
+
Value::Number(n) if *n >= 0.0 && n.fract() == 0.0 => *n as usize,
|
|
294
|
+
_ => return Value::Number(f64::NAN),
|
|
295
|
+
};
|
|
296
|
+
match s.chars().nth(i) {
|
|
297
|
+
Some(c) => Value::Number(c as u32 as f64),
|
|
298
|
+
None => Value::Number(f64::NAN),
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
/// `&str` charAt — the 1-character string at `idx`, `""` out of range. Same reason as above.
|
|
303
|
+
#[inline]
|
|
304
|
+
pub fn str_char_at(s: &str, idx: &Value) -> Value {
|
|
305
|
+
let i = match idx {
|
|
306
|
+
Value::Number(n) if *n >= 0.0 && n.fract() == 0.0 => *n as usize,
|
|
307
|
+
_ => return Value::String("".into()),
|
|
308
|
+
};
|
|
309
|
+
match s.chars().nth(i) {
|
|
310
|
+
Some(c) => Value::String(c.to_string().into()),
|
|
311
|
+
None => Value::String("".into()),
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
|
|
286
315
|
pub fn delete_property(obj: &Value, key: &Value) -> Value {
|
|
287
316
|
match obj {
|
|
288
317
|
Value::Object(m) => {
|
package/package.json
CHANGED
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|