diff --git a/.gitignore b/.gitignore index e06fa259..803aeabe 100644 --- a/.gitignore +++ b/.gitignore @@ -8,6 +8,7 @@ libcbqn.so # build system things /build/obj/ +/build/obj2/ /build/singeliLocal /build/replxxLocal /build/bytecodeLocal diff --git a/build/build b/build/build new file mode 100755 index 00000000..984638b9 --- /dev/null +++ b/build/build @@ -0,0 +1,3 @@ +#!/usr/bin/env bash +DIR="$(dirname $0)" +"$DIR/obj2/for_build" "$DIR/src/build.bqn" "$@" diff --git a/build/singeliMake.bqn b/build/singeliMake.bqn index 4245589d..f6083b63 100755 --- a/build/singeliMake.bqn +++ b/build/singeliMake.bqn @@ -13,7 +13,7 @@ depfile ← (At buildDir) •file.At filename∾".d" prefix ← "si_"∾ (∧`'.'⊸≠)⊸/ •file.Name srcfile # invoke singeli, which creates the result file -(⟨"-d" ⋄ tmpfile ⋄ "-o" ⋄ resfile ⋄ "-n" ⋄ prefix ⋄ srcfile⟩) •Import siDir •file.At "singeli" +(⟨"-l", "gen=src/singeli/gen", "-d" ⋄ tmpfile ⋄ "-o" ⋄ resfile ⋄ "-n" ⋄ prefix ⋄ srcfile⟩) •Import siDir •file.At "singeli" # output dependency file deps ← siDir⊸•file.At¨ •file.Lines tmpfile diff --git a/build/singeliSubmodule b/build/singeliSubmodule index 2fefe457..f60a3c73 160000 --- a/build/singeliSubmodule +++ b/build/singeliSubmodule @@ -1 +1 @@ -Subproject commit 2fefe457b47005f1aff2e67f73bbef7eb9173833 +Subproject commit f60a3c73450b8d5ae18bdc76f090b20437cf7ab2 diff --git a/build/src/build.bqn b/build/src/build.bqn new file mode 100755 index 00000000..d6dcb1cc --- /dev/null +++ b/build/src/build.bqn @@ -0,0 +1,545 @@ +#!build/obj2/for_build + +# to emulate on makefile transition: NO_LDL → rm_lf=-ldl; no_fPIC → rm_f=-fPIC; something something PIE + +⟨Spawn, WaitForOne⟩ ← ⟨⟩ •Import "fork.bqn" +⟨Serialize, Deserialize⟩ ← •Import "serialize.bqn" + +# modes: +# 0: single string option +# 1: toggle +# 2: flag list +opts ← ⟨ + ⟨0, "j", "4"⟩ # number of parallel jobs + ⟨1, "verbose", 0⟩ # log more things + ⟨1, "rebuild", 0⟩ # forcibly rebuild everything + # TODO clean + + ⟨0, "CC", @⟩ # the C compiler + ⟨0, "LD", @⟩ # linker of the final binary; default CC, or CXX if REPLXX=1 + ⟨1, "color", 1⟩ # whether to enable colored diagnostics + ⟨0, "os", @⟩ # target OS (linux, bsd, macos); used for .so vs .dylib, and changing linker flags for bsd + ⟨0, "arch", @⟩ # target architecture (x86-64, aarch64, generic); used for Singeli target deciding + + ⟨0, "OUTPUT", ""⟩ # output location; default depends + ⟨2, "f", ⟨⟩⟩ # C flags for CBQN files + ⟨2, "CCFLAGS", ⟨⟩⟩ # flags for all C compiler & linker invocations + ⟨2, "lf", ⟨⟩⟩ # linker flags + ⟨2, "LDFLAGS", ⟨⟩⟩ # more linker flags (identical to lf) + ⟨2, "rm_f", ⟨⟩⟩ # forcibly remove C compiler flag(s) + ⟨2, "rm_lf", ⟨⟩⟩ # forcibly remove linker flag(s) + + # also define the default OUTPUT value (default default being "BQN") + ⟨1, "shared", 0⟩ # build a shared library; OUTPUT = "libcbqn.[so|dylib]" + ⟨1, "wasi", 0⟩ # build with WASI; OUTPUT = "BQN.wasm" + ⟨1, "emcc", 0⟩ # build with emscripten; OUTPUT = ".", is used as a directory + + ⟨1, "FFI", @⟩ # enable FFI through libffi; default ≡ ¬wasi∨emcc + ⟨1, "pkgconfig", 1⟩ # attempt to use pkg-config to find libffi inclusion flags + ⟨1, "singeli", 0⟩ # enable Singeli + ⟨1, "REPLXX", 0⟩ # enable replxx + # TODO options for forcing around the bytecode/singeli/replxx directories + + # CBQN toggles + ⟨1, "rtverify", 0⟩ + ⟨1, "heapverify", 0⟩ + + ⟨1, "c", 0⟩ # disable some default flags + ⟨1, "O3", @⟩ # -O3; default ≡ ¬c + ⟨1, "g", @⟩ # -g; default ≡ debug + ⟨1, "native", 0⟩ # -march=native & use native arch as lower & upper bound for Singeli + ⟨1, "debug", 0⟩ # -DDEBUG & -g + + ⟨0, "CXX", "c++"⟩ # C++ compiler (for replxx) + ⟨2, "REPLXX_FLAGS", ⟨"-std=c++11", "-Os"⟩⟩ # default replxx C++ build flags +⟩ + +Log ← •Out +_verboseLog ← {𝔽_𝕣:⊢} +onExitList ← ⟨⟩ +OnExit ← {𝕊: {𝕏@}¨ onExitList} +_assert_ ← { 𝔾𝕩?𝕩; Log 𝕨𝔽𝕩 ⋄ OnExit@ ⋄ •Exit 1} + +SepArgs ← {' ' ((¬-˜⊢×·+`»⊸>)∘≠⊔⊢) 𝕩} +Lowercase ← {𝕩 - (-´"Aa")×(𝕩≥'A')∧𝕩≤'Z'} + +getOpt ← { + args ← ×∘≠¨⊸/ •args + [ot, on0, od] ← ⍉>opts + on ← Lowercase¨ on0 + ot1 ← 1=ot + ot2 ← 2=ot + + s1 ← ⊑∘⊐⟜'='¨ args # start of = + hs ← s1<≠¨args # has value + fl ← hs∧'+'=(0⌈s1-1)⊑¨args # is appended flag, i.e. "f+=a b c" + s0 ← s1-fl # end of key + ks ← s0↑¨args # keys + ks Lowercase¨↩ # lowercase keys + vs ← (1+s1)↓¨args # values + {𝕊: "Unknown option -- "∾⊑(¬ks∊on)/ks}_assert_(∧´) ks∊on + + ci ← on⊐ks # index in option specification + {𝕊: ∾⟨"Error: Unexpected '+=' for '",ks⊑˜⊑/¬𝕩,"'"⟩}_assert_(∧´) (ci⊏ot2)∨¬fl + + Gr ← {(≠ot)↑ci⊔𝕩} + gvs ← Gr vs # values for each option + {𝕊: ∾⟨"Error: Multiple values given for '",on⊑˜⊑/¬𝕩,"'"⟩}_assert_(∧´) ot2∨1≥≠¨gvs + + {𝕊: ∾⟨"Error: Expected value to be provided for ",⊑𝕩/ks⟩}_assert_(¬∨´) (¬ci⊏ot1) ∧ ¬hs + + # f='a b' f+='c d' → "a" "b" "c d" + gvs ↩ (Gr fl) (∾{𝕨?⋈𝕩;×≠𝕩?SepArgs 𝕩;⋈⟨⟩}¨)¨⌾(ot2⊸/) gvs + # map toggles to their actual values, error on invalid + gvs ↩ on {𝕨{𝕊: ∾⟨"Error: Invalid value for '",𝕨,"'"⟩}_assert_⊢ ∧´𝕩∊""‿"0"‿"1" ⋄ ≠◶⊢‿(⋈"0"≢⊑) 𝕩}¨⌾(ot1⊸/) gvs + + gvs ↩ ((¬ot2) ⋈∘⊢⍟⊣¨ od) {×≠𝕩?𝕩;𝕨}¨ gvs # map in defaults + + gvs ↩ (¬ot2) ⋈⁼∘⊢⍟⊣¨ gvs # disclose options with only one expected result + + # •Show [ks, fl, hs, ci, vs] + # •Show {𝕩/˜×(≠1⊑⊢)˘𝕩} ⍉[on, gvs] + {(⊑on⊐&i32" +libc_read ← @ •FFI ssz‿"read"‿"i32"‿"&i8"‿sz +libc_write ← @ •FFI ssz‿"write"‿"i32"‿"*i8"‿sz +libc_close ← @ •FFI "i32"‿"close"‿">i32" +libc_poll ← @ •FFI "i32"‿"poll"‿"&i16"‿nfds‿"i32" + +Pipe ← { 𝕊: readfd‿writefd ⇐ + ⟨c, readfd‿writefd⟩ ← Libc_pipe 0‿0 + ! c=0 + Write ⇐ {Libc_write ⟨writefd, 𝕩, ≠𝕩⟩} + Read ⇐ {n‿b ← Libc_read ⟨readfd, 𝕩⥊0, 𝕩⟩ ⋄ !n≥0 ⋄ n↑b} +} + +BiDiFork ← { 𝕊: + p1 ← Pipe@ + p2 ← Pipe@ + pid ⇐ Libc_fork@ + ! pid≥0 + parent ⇐ pid=0 + CloseWR ← {! ¬∨´ Libc_close¨ {𝕨.writefd‿𝕩.readfd}´ ⌽⍟parent 𝕩} + CloseWR p1‿p2 + r‿w ⇐ ⌽⍟parent p1‿p2 + Read‿readfd ⇐ r + Write‿writefd ⇐ w + Close ⇐ CloseWR∘p2‿p1 +} + +FFn ← { 𝕊 fn: + f ← BiDiFork@ + {f.parent? Fn f ⋄ f.Close@ ⋄ •Exit 0; f} +} + +WriteAll ← {p𝕊x: {𝕩-p.Write 𝕩-⊸↑x}•_while_× ≠x} +_readAll ← {p E _𝕣 n: ⊑⍟(¬=) {v←p.Read n-≠𝕩 ⋄ 0<≠v? 𝕩∾v; *u8:c8" +Split ← {𝕩⊔˜(⊢-˜+`׬)𝕩=𝕨} +SimplifyPath ← { + 1↓∾'/'⊸∾¨ {(∊××) ⌊`⌾⌽ +` ¬⊸- ".."⊸≡¨𝕩}⊸/ "."⊸≢¨⊸/ '/'Split𝕩 +} +Good ← { 𝕊 dir‿t0‿t1‿o‿e‿deps: + ⟨1, o∾e, t1-t0, deps ⋈¨ (•file.Modified dir•file.At⊢)¨ deps⟩ +} + +_runSingeli_ ← { runArgs GetDeps _𝕣_ dir runFile: + t0 ← •MonoTime@ + e←@ ⋄ deps←@ + {𝕊: + runArgs •Import runFile + deps ↩ GetDeps@ + }⎊{𝕊: e↩•CurrentError@} @ + t1 ← •MonoTime@ + { + e≢@? ⟨0, e⟩; + Good ⟨dir,t0,t1,"","",deps⟩ + } +} + +{ + "sh"‿dir‿cmd‿depf: + t0 ← •MonoTime@ + Chdir @∾˜ •ToUTF8 dir + c‿o‿e ← •SH cmd + t1 ← •MonoTime@ + { + 0: @≡depf? + Good ⟨dir,t0,t1,o,e,⟨⟩⟩; + 0: + deps ← •FLines depf + deps {𝕩/˜1»∧`'\'=¯1⊑∘↑¨𝕩}↩ # remove all but the initial rule + deps {𝕩↓˜1+⊑𝕩⊐':'}⌾⊑↩ # remove rule name + deps ¯1⊸↓¨⌾(¯1↓⊢)↩ # remove trailing backslashes + deps ({𝕩/˜¬∧`𝕩=' '}⌽)⍟2¨↩ # trim whitespace from both sides + deps (∾' 'Split¨⊢)↩ # split each on spaces + deps {¬∨´"/build/obj2/"⍷𝕩}¨⊸/↩ # remove autogenerated dependencies, those are handled manually + deps SimplifyPath¨↩ # remove "."s & ".."s + deps {dir<○≠𝕩? dir≡(≠dir)↑𝕩? (≠dir)↓𝕩; 𝕩}¨↩ # relativize + Good ⟨dir,t0,t1,o,e,deps⟩; + # c≠0: + ⟨0, o∾e⟩ + } c + ; + "singeli"‿dir‿dst‿singeliDir‿args‿src‿dep: + prefix ← "si_"∾ (∧`'.'⊸≠)⊸/ •file.Name src + argsFinal ← args∾⟨"-d" ⋄ dep ⋄ "-o" ⋄ dst ⋄ "-n" ⋄ prefix ⋄ src⟩ + argsFinal {𝕊: src<⊸∾ SimplifyPath¨ singeliDir⊸•file.At¨ •FLines dep}_runSingeli_ dir singeliDir •file.At "singeli" + ; + "runbqn"‿dir‿file‿args‿deps: + args deps _runSingeli_ dir file + ; + 0⋈"unknown command" +} \ No newline at end of file diff --git a/build/src/serialize.bqn b/build/src/serialize.bqn new file mode 100644 index 00000000..1945a667 --- /dev/null +++ b/build/src/serialize.bqn @@ -0,0 +1,54 @@ +eltype2bit ← ⟨1,8,16,32,64,8‿'c',16‿'c',32‿'c'⟩ +eltypeWidth ← ⟨1,1,2,4,8,1,2,4⟩ + +SStep ← •Type◶⟨ + { + 𝕩 •internal.Squeeze↩ + eltype ← •internal.ElType𝕩 + ×∘≠¨⊸/ ⟨ + ⟨0, eltype⟩ + 32‿8•bit._cast ⋈=𝕩 + 64‿8•bit._cast ≢𝕩 + { + eltype=8? SStep¨ ⥊𝕩; + ⟨eltype⊑eltype2bit, 8⟩•bit._cast (8×·⌈≠÷8˙)⊸↑⍟(0=eltype) ⥊𝕩 + }𝕩 + ⟩ + } + { ⟨⟨1⟩, 64‿8•bit._cast⋈𝕩⟩ } + { ⟨⟨2⟩, 32‿8•bit._cast⋈𝕩⟩ } + {𝕊:!"Cannot serialize functions"} + {𝕊:!"Cannot serialize 1-modifiers"} + {𝕊:!"Cannot serialize 2-modifiers"} + {𝕊:!"Cannot serialize namespaces"} +⟩ + +Serialize ⇐ { + lists ← ⟨⟩ + {0=•Type⊑𝕩? 𝕊¨𝕩; lists∾↩<𝕩 ⋄ 1} SStep 𝕩 + ∾lists +} +Deserialize ⇐ { + s←𝕩 + off←0 + Next ← {r←𝕩↑off↓s ⋄ off+↩𝕩 ⋄ r} + Read ← { 𝕊: + type ← ⊑Next 1 + type◶⟨ + {𝕊: + et ← ⊑Next 1 + rank ← ⊑8‿32•bit._cast Next 4 + shape ← 8‿64•bit._cast Next rank×8 + shape⥊{ + et=8? Read¨ ↕×´shape; + ⟨8, et⊑eltype2bit⟩•bit._cast Next (⌈÷⟜8)⍟(0=et) (et⊑eltypeWidth)×´shape + } + } + {𝕊: ⊑⟨8, 64 ⟩•bit._cast Next 8} + {𝕊: ⊑⟨8, 32‿'c'⟩•bit._cast Next 4} + ⟩@ + } + r ← Read@ + off=≠s? r; + ! "invalid input: data after end" +} \ No newline at end of file diff --git a/makefile b/makefile index 386b7e85..81b578cf 100644 --- a/makefile +++ b/makefile @@ -37,6 +37,8 @@ shared-o3: @${MAKE} i_OUTPUT=libcbqn.so i_SHARED=1 i_t=shared_o3 i_f="-O3" run_incremental_0 shared-c: @${MAKE} i_OUTPUT=libcbqn.so i_SHARED=1 custom=1 run_incremental_0 +forbuild: + @${MAKE} i_singeli=0 i_t=forbuild i_f="-O2" i_FFI=2 i_OUTPUT=build/obj2/for_build i_f='-DFOR_BUILD' run_incremental_0 c: @${MAKE} custom=1 run_incremental_0 @@ -179,6 +181,9 @@ single-c: # actual build run_incremental_0: +ifeq ($(i_t),forbuild) + mkdir -p build/obj2 +endif ifeq ($(verbose),1) @echo "build directory: $$(${MAKE} builddir)" @echo " bytecode: build/$(BYTECODE_DIR)" diff --git a/src/singeli/c/arithdDispatch.c b/src/singeli/c/arithdDispatch.c index 579ae776..40afd15e 100644 --- a/src/singeli/c/arithdDispatch.c +++ b/src/singeli/c/arithdDispatch.c @@ -352,4 +352,5 @@ static NOINLINE B or_SA(B t, B w, B x) { return r; } -#include "../gen/arTables.c" +#define SINGELI_FILE arTables +#include "../../utils/includeSingeli.h" diff --git a/src/singeli/src/dyarith.singeli b/src/singeli/src/dyarith.singeli index 7a9f9c08..53b1d434 100644 --- a/src/singeli/src/dyarith.singeli +++ b/src/singeli/src/dyarith.singeli @@ -189,4 +189,4 @@ andBytes{vw}(r: *u8, x: *u8, maskU64:u64, len:u64) : void = { 'avx2_andBytes'=andBytes{256} 'orSAc_f64_f64_f64'=arithSA{2,bqn_or,0,f64,f64,f64} -include './../gen/arDefs' \ No newline at end of file +include 'gen/arDefs' diff --git a/src/utils/includeSingeli.h b/src/utils/includeSingeli.h index c5d7d1a6..262b6191 100644 --- a/src/utils/includeSingeli.h +++ b/src/utils/includeSingeli.h @@ -19,7 +19,11 @@ #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wunused-variable" +#ifdef SINGELI_DIR +#include SINGELI_FILE1(../../build/obj2/SINGELI_DIR/SINGELI_FILE.c) +#else #include SINGELI_FILE1(../singeli/gen/SINGELI_FILE.c) +#endif #pragma GCC diagnostic pop #undef SINGELI_FILE \ No newline at end of file