From 1709fbd2f627d52c4d793ea15de17c462dcd82f7 Mon Sep 17 00:00:00 2001 From: dzaima Date: Sun, 15 Sep 2024 20:07:18 +0300 Subject: [PATCH] new precompiled bytecode generator --- build/cc.bqn | 86 ++++++++++++++++++++++++++++++++++++++++------------ src/load.c | 31 ++++++++++++++----- 2 files changed, 90 insertions(+), 27 deletions(-) diff --git a/build/cc.bqn b/build/cc.bqn index f8804414..d57014a6 100755 --- a/build/cc.bqn +++ b/build/cc.bqn @@ -27,33 +27,79 @@ FmtComp ← { 𝕩 ↩ i ⊏⟜out⌾((i<≠out)⊸/) 𝕩 # Replace ∾(i<≠in) /⟜"\"⊸∾¨ 𝕩 # Insert \ } - + U32Len ← (≠ - ·+´ ≥⟜55296 ∧ ≤⟜56319)-⟜@ # for dzaima/BQN; shouldn't break things in proper BQN impls, as surrogate values don't map to valid codepoints - + CStr ← {"""" (∾∾⊣) Esc 𝕩} - - OStr ← { # A BQN string + + List ← (0<≠)◶⟨"",1↓·∾","⊸∾¨⟩ + + lf ← ⥊@+10 + Cache ← { + tag ← 𝕩 + values ← ⟨⟩ + Add ⇐ {(values∾↩ <𝕩) ⊢ tag⋈≠values} + Done ⇐ { 𝕊: + unq ← ⊐values + uncomp ⇐ {(⍋≠¨ 𝕩/values) ⊏ /𝕩} ∊unq # compressed index → canonical original index; sort by length to make length predictable + comp ⇐ (uncomp⊏unq)⊐unq # original index → compressed index + counts ⇐ /⁼comp # compressed index → count of such + compvals ⇐ uncomp⊏values # compressed index → data + n ⇐ ≠uncomp + } + } + + intarrCache ← Cache 1 + Li ← intarrCache.Add + _Lo ← {{∾⟨"m_lvB_", F≠𝕩, "(", List 𝕩, ")"⟩} 𝔽¨𝕩} + OStr2C ← { # A BQN string a←∧´𝕩<128+@ ∾⟨a⊑"m_c32vec"‿"m_c8vec","(",a¬⊸⥊"U","",CStr𝕩,",",•Repr U32Len 𝕩,")"⟩ } - OChr ← {"m_c32(U'"∾(Esc⥊𝕩)∾"')"} # A BQN character - ONum ← {s←"-"/˜𝕩<0 ⋄ ∞⊸=∘|◶⟨"m_f64("∾")"∾˜s∾F∘| ⋄ "m_f64("∾s∾"1.0/0.0)"⟩𝕩} # Format number - OAny ← ≡◶⟨@⊸≤◶ONum‿OChr, OStr, ⊑⟩ - - List ← (0<≠)◶⟨"",1↓·∾","⊸∾¨⟩ - ShortList ← {"m_lv"∾𝕨∾"_"∾(F≠𝕩)∾"("∾(List𝕩)∾")"} - LongList ← {"m_ca"∾𝕨∾"("∾(F≠𝕩)∾",("∾𝕨∾"[]){"∾(List𝕩)∾"})"} - ConstList ← {"m_ca"∾𝕨∾"("∾(F≠𝕩)∾",({static "∾𝕨∾" l_[]={"∾(List𝕩)∾"};l_;}))"} - _makeList ← {𝕨 (≠∘⊢>4˙)◶⟨ShortList,𝕗⊑LongList‿ConstList⟩ 𝕩} - Li ← {"i32" 1 _makeList F¨𝕩} - _Lo ← {"B" 0 _makeList 𝔽¨𝕩} + OChr2C ← {"m_c32(U'"∾(Esc⥊𝕩)∾"')"} # A BQN character + ONum2C ← {s←"-"/˜𝕩<0 ⋄ ∞⊸=∘|◶⟨"m_f64("∾")"∾˜s∾F∘| ⋄ "m_f64("∾s∾"1.0/0.0)"⟩𝕩} # Format number + OAny2C ← ≡◶⟨@⊸≤◶ONum2C‿OChr2C, OStr2C, ⊑⟩ + + TmpNum ← 0⊸⋈ + # 0‿123: number + # 1‿n: int arr ref + # ⟨a,b,c⟩: obj arr + # "foo": literal code + a ← ((≠𝕩)↑⟨Li ⋄ OAny2C¨ ⋄ {0=⌈´=¨𝕩? Li 𝕩; =◶⟨TmpNum,Li¨⟩¨ 𝕩}¨ ⋄ (Li 2⊸↑)¨ ⋄ Li¨ ⋄ OStr2C⟩) {𝕎𝕩}¨ 𝕩 + + iarrs ← intarrCache.Done@ ⋄ Li↩! + + ! ⟨⟩ ≡ ⊑iarrs.compvals + + init ← ⟨⟩ + a { + 1‿i: n ← i⊑iarrs.comp ⋄ (0=n) ⊑ ⟨∾⟨"iarrs[",F n,"]"⟩, "iarrs0"⟩; # special-case first array (i.e. empty array) as there isn't enough aliasing info for the compiler to deduplicate loads + 2=•Type⊑𝕩? 𝕩; + 0‿n: ONum2C n; + ⟨0‿a, 0‿b, ⟨c, d⟩⟩: cs≡⌊cs←a‿b? ∧´cs≥0? ∧´cs<4? ∾⟨"m_blockinfo(", F a+b×4, ", ", 𝕊 c, ", ", 𝕊 d, ")"⟩; + 4≥≠𝕩? 𝕊_Lo 𝕩; + n ← "a" ∾ F ≠init + np ← n∾"p" + init∾↩< ∾⟨lf + "B ", n, "; B* ", np, " = m_lvBn(&", n, ", ", F ≠𝕩, ");", lf + "assume_separate_storage(", np, ", ", "iarrs", ");", lf # allow the compiler to vectorize copying from iarrs to np if so beneficial + ⟩ ∾ (⍋{⊑'('∊𝕩}¨)⊸⊏ {∾⟨np,"[", F 𝕩, "] = ", 𝕨, ";", lf⟩}¨⟜↕⟜≠ 𝕊¨ 𝕩 + n + }¨↩ - a ← ((≠𝕩)↑⟨Li ⋄ OAny¨ ⋄ {0=⌈´=¨𝕩? Li 𝕩; =◶⟨ONum,Li¨⟩¨ 𝕩}¨ ⋄ (Li 2⊸↑)¨ ⋄ Li¨ ⋄ OStr⟩) {𝕎𝕩}¨ 𝕩 - a {2=•Type⊑𝕩? 𝕩; 𝕊_Lo 𝕩}¨↩ ∾⟨ - "load_importBlock", srcmap/"_src", "(", CStr name, ",", ⥊@+10, - (","∾@+10) Join a - ⥊@+10 + "B iarrs[", F iarrs.n, "];", lf + "static const i32 iarrs_data[] = {", lf + ∾ ∾⟜lf¨ {∾⟨∾∾⟜','¨ F¨ 𝕨, " // ", F 𝕩⟩}¨⟜↕⟜≠ iarrs.compvals + "};", lf + "static const u32 iarrs_lens[] = {", ','Join F∘≠¨ iarrs.compvals, "};", lf + "init_intarrs(iarrs, iarrs_data, iarrs_lens, ", F iarrs.n, ");", lf + "B iarrs0 = iarrs[0];", lf + ∾{0𝕊𝕩: ""; ∾⟨"incByG(iarrs[", F 𝕩, "], ", F 𝕨, ");", lf⟩}¨⟜↕⟜≠ iarrs.counts-1 + ∾init + "load_importBlock", srcmap/"_src", "(", CStr name, ",", lf + (','∾lf) Join " "⊸∾¨ a + lf ");" ⟩ } diff --git a/src/load.c b/src/load.c index 9623b351..b54c0ff0 100644 --- a/src/load.c +++ b/src/load.c @@ -23,8 +23,6 @@ FOR_INIT(F) GLOBAL u64 mm_heapMax = HEAP_MAX; GLOBAL u64 mm_heapAlloc; -extern Arr* staticSliceRoot; - // compiler result: // [ // [...bytecode], @@ -104,16 +102,35 @@ GLOBAL B r1Objs[RT_LEN]; B rtWrap_wrap(B x, bool nnbi); // consumes void rtWrap_print(void); +static NOINLINE B* m_lvBn(B* dst, ux n) { HArr_p p = m_harr0v(n); *dst = p.b; return p.a; } // m_harrUv might be fine for initial init as it doesn't run with GC, but explain is loaded later static NOINLINE B m_lvB_0( ) { return emptyHVec(); } static NOINLINE B m_lvB_1(B a ) { return m_hvec1(a); } static NOINLINE B m_lvB_2(B a, B b ) { return m_hvec2(a,b); } static NOINLINE B m_lvB_3(B a, B b, B c ) { return m_hvec3(a,b,c); } static NOINLINE B m_lvB_4(B a, B b, B c, B d) { return m_hvec4(a,b,c,d); } -static NOINLINE B m_lvi32_0( ) { return emptyIVec(); } -static NOINLINE B m_lvi32_1(i32 a ) { i32* rp; B r = m_i32arrv(&rp,1); rp[0]=a; return r; } -static NOINLINE B m_lvi32_2(i32 a, i32 b ) { i32* rp; B r = m_i32arrv(&rp,2); rp[0]=a; rp[1]=b; return r; } -static NOINLINE B m_lvi32_3(i32 a, i32 b, i32 c ) { i32* rp; B r = m_i32arrv(&rp,3); rp[0]=a; rp[1]=b; rp[2]=c; return r; } -static NOINLINE B m_lvi32_4(i32 a, i32 b, i32 c, i32 d) { i32* rp; B r = m_i32arrv(&rp,4); rp[0]=a; rp[1]=b; rp[2]=c; rp[3]=d; return r; } +static NOINLINE B m_blockinfo(ux info, B c, B d) { + return m_lvB_3(m_f64(info&3), m_f64(info>>2), m_lvB_2(c, d)); +} + +#ifndef __has_builtin + #define __has_builtin(x) 0 +#endif +#if __has_builtin(__builtin_assume_separate_storage) + #define assume_separate_storage(A, B) __builtin_assume_separate_storage(A, B) +#else + #define assume_separate_storage(A, B) +#endif + +extern Arr* staticSliceRoot; + +static NOINLINE void init_intarrs(B* dst, const i32* all_data, const u32* lengths, ux n) { + ptr_incBy(staticSliceRoot, n); + for (ux i = 0; i < n; i++) { + ux len = lengths[i]; + dst[i] = taga(arr_shVec(m_tyslice((i32*) all_data, staticSliceRoot, t_i32slice, len))); + all_data+= len; + } +} static NOINLINE B m_importMap(void) { return c2(bi_hashMap, emptyHVec(), emptyHVec());