Compare commits
No commits in common. "main" and "large-assets" have entirely different histories.
main
...
large-asse
@ -1,30 +0,0 @@
|
|||||||
name: CI
|
|
||||||
|
|
||||||
on:
|
|
||||||
pull_request:
|
|
||||||
push:
|
|
||||||
tags:
|
|
||||||
- "**"
|
|
||||||
branches:
|
|
||||||
- main
|
|
||||||
- zig
|
|
||||||
schedule:
|
|
||||||
- cron: "0 0 * * *"
|
|
||||||
|
|
||||||
env:
|
|
||||||
BB_CI: 1
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
ci:
|
|
||||||
strategy:
|
|
||||||
fail-fast: false
|
|
||||||
matrix:
|
|
||||||
os: [ ubuntu-latest ]
|
|
||||||
BIRTH_ZIG_BUILD_TYPE: [ Debug, ReleaseSafe, ReleaseFast, ReleaseSmall ]
|
|
||||||
runs-on: ${{ matrix.os }}
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
- name: Build and test (Packaged LLVM)
|
|
||||||
run: |
|
|
||||||
~/zig-linux-x86_64-0.14.0/zig build test -Doptimize=${{matrix.BIRTH_ZIG_BUILD_TYPE}} -Dsystem_llvm=false
|
|
||||||
ldd zig-out/bin/bloat-buster
|
|
76
.github/workflows/ci.yml
vendored
Normal file
76
.github/workflows/ci.yml
vendored
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
name: CI
|
||||||
|
|
||||||
|
on:
|
||||||
|
pull_request:
|
||||||
|
push:
|
||||||
|
tags:
|
||||||
|
- "**"
|
||||||
|
branches:
|
||||||
|
- main
|
||||||
|
schedule:
|
||||||
|
- cron: "0 0 * * *"
|
||||||
|
|
||||||
|
env:
|
||||||
|
BB_CI: 1
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
generate-config:
|
||||||
|
runs-on: ubuntu-24.04
|
||||||
|
permissions: write-all
|
||||||
|
outputs:
|
||||||
|
BIRTH_GITHUB_TARGETS: ${{ steps.generate-config.outputs.BIRTH_GITHUB_TARGETS }}
|
||||||
|
BIRTH_BUILD_TYPES: ${{ steps.generate-config.outputs.BIRTH_BUILD_TYPES }}
|
||||||
|
BIRTH_CMAKE_BUILD_TYPES: ${{ steps.generate-config.outputs.BIRTH_CMAKE_BUILD_TYPES }}
|
||||||
|
BIRTH_COMPILERS: ${{ steps.generate-config.outputs.BIRTH_COMPILERS }}
|
||||||
|
BIRTH_LINUX_IMAGE: ${{ steps.generate-config.outputs.BIRTH_LINUX_IMAGE }}
|
||||||
|
BIRTH_MACOS_IMAGE: ${{ steps.generate-config.outputs.BIRTH_MACOS_IMAGE }}
|
||||||
|
BIRTH_WINDOWS_IMAGE: ${{ steps.generate-config.outputs.BIRTH_WINDOWS_IMAGE }}
|
||||||
|
RELEASE_TAG_NAME: ${{ steps.generate-tag.outputs.RELEASE_TAG_NAME }} # Define job output here
|
||||||
|
steps:
|
||||||
|
- name: Check out repository
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
- name: Generate config
|
||||||
|
id: generate-config
|
||||||
|
uses: birth-software/github-config@v4
|
||||||
|
- name: Create tag
|
||||||
|
if: github.ref == 'refs/heads/main'
|
||||||
|
shell: bash
|
||||||
|
id: generate-tag
|
||||||
|
env:
|
||||||
|
GH_TOKEN: ${{ github.token }}
|
||||||
|
run: |
|
||||||
|
set -eux
|
||||||
|
git config --global user.name "github-actions"
|
||||||
|
git config --global user.email "github-actions@github.com"
|
||||||
|
TAG="dev"
|
||||||
|
gh release delete $TAG --yes || true
|
||||||
|
git tag -d $TAG || true
|
||||||
|
git push origin --delete $TAG || true
|
||||||
|
git fetch --tags
|
||||||
|
git tag -l
|
||||||
|
git tag $TAG
|
||||||
|
git push origin $TAG
|
||||||
|
echo "RELEASE_TAG_NAME=$TAG" >> $GITHUB_OUTPUT
|
||||||
|
ci:
|
||||||
|
needs: generate-config
|
||||||
|
permissions: write-all
|
||||||
|
strategy:
|
||||||
|
fail-fast: true
|
||||||
|
matrix:
|
||||||
|
os: [ x86_64-linux-znver4 ]
|
||||||
|
BIRTH_BUILD_TYPE: ${{ fromJSON(needs.generate-config.outputs.BIRTH_BUILD_TYPES) }}
|
||||||
|
runs-on: ${{ matrix.os }}
|
||||||
|
env:
|
||||||
|
BIRTH_LINUX_IMAGE: ${{ needs.generate-config.outputs.BIRTH_LINUX_IMAGE }}
|
||||||
|
BIRTH_MACOS_IMAGE: ${{ needs.generate-config.outputs.BIRTH_MACOS_IMAGE }}
|
||||||
|
BIRTH_WINDOWS_IMAGE: ${{ needs.generate-config.outputs.BIRTH_WINDOWS_IMAGE }}
|
||||||
|
RELEASE_TAG_NAME: ${{ needs.generate-config.outputs.RELEASE_TAG_NAME }}
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- name: Build
|
||||||
|
env:
|
||||||
|
CC: clang
|
||||||
|
BB_BUILD_TYPE: ${{matrix.BIRTH_BUILD_TYPE}}
|
||||||
|
run: ./build.sh
|
||||||
|
- name: Run
|
||||||
|
run: ./cache/bb
|
5
.gitignore
vendored
5
.gitignore
vendored
@ -8,8 +8,3 @@ project
|
|||||||
imgui.ini
|
imgui.ini
|
||||||
/cache/
|
/cache/
|
||||||
.DS_Store
|
.DS_Store
|
||||||
/*.perf
|
|
||||||
/.gdb_history
|
|
||||||
/.zig-cache/
|
|
||||||
/zig-out/
|
|
||||||
/bb-cache/
|
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -1,281 +0,0 @@
|
|||||||
adc: class base_arithmetic(/2, 15, 11, 13)
|
|
||||||
adcx: class unsigned_add_flag(66)
|
|
||||||
add: class base_arithmetic(/0, 05, 01, 03)
|
|
||||||
adox: class unsigned_add_flag(f3)
|
|
||||||
and: class base_arithmetic(/4, 25, 21, 23)
|
|
||||||
bsf:
|
|
||||||
r16, rm16 [rm: rex.r 0f bc /r]
|
|
||||||
r32, rm32 [rm: 0f bc /r]
|
|
||||||
r64, rm64 [rm: rex.w 0f bc /r]
|
|
||||||
bsr:
|
|
||||||
r16, rm16 [rm: rex.r 0f bd /r]
|
|
||||||
r32, rm32 [rm: 0f bd /r]
|
|
||||||
r64, rm64 [rm: rex.w 0f bd /r]
|
|
||||||
bswap:
|
|
||||||
r32 [o: 0f c8+r]
|
|
||||||
r64 [o: rex.w 0f c8+r]
|
|
||||||
bt: class bittest(/4, a3)
|
|
||||||
btc: class bittest(/7, bb)
|
|
||||||
btr: class bittest(/6, b3)
|
|
||||||
bts: class bittest(/5, ab)
|
|
||||||
call:
|
|
||||||
rel [d: e8 rel32]
|
|
||||||
rm64 [m: ff /2]
|
|
||||||
cbw: [zo: rex.r 98]
|
|
||||||
cwde: [zo: 98]
|
|
||||||
cwqe: [zo: rex.w 98]
|
|
||||||
clc: [zo: f8]
|
|
||||||
cld: [zo: fd]
|
|
||||||
clflush: m8 [m: 0f ae /7]
|
|
||||||
clflushopt: m8 [m: 66 0f ae /7]
|
|
||||||
cli: [zo: fa]
|
|
||||||
clts: [zo: 0f 06]
|
|
||||||
cmc: [zo: f5]
|
|
||||||
cmovcc: class cmov
|
|
||||||
cmp: class base_arithmetic(/7, 3d, 39, 3b)
|
|
||||||
cmpsb: [zo: a6]
|
|
||||||
cmpsw: [zo: a7]
|
|
||||||
cmpsd: [zo: a7]
|
|
||||||
cmpsq: [zo: a7]
|
|
||||||
cmpxchg:
|
|
||||||
rm8, r8 [mr: 0f b0]
|
|
||||||
rm16, r16 [mr: 0f b1]
|
|
||||||
rm32, r32 [mr: 0f b1]
|
|
||||||
rm64, r64 [mr: 0f b1]
|
|
||||||
cmpxchg8b: m64 [m: 0f c7 /1]
|
|
||||||
cmpxchg16b: m64 [m: rex.w 0f c7 /1]
|
|
||||||
cpuid: [zo: 0f a2]
|
|
||||||
crc32:
|
|
||||||
r32, rm8 [rm: f2 0f 38 f0]
|
|
||||||
r32, rm16 [rm: 66 f2 0f 38 f1]
|
|
||||||
r32, rm32 [rm: f2 0f 38 f1]
|
|
||||||
r64, rm8 [rm: f2 rex.w 0f 38 f0]
|
|
||||||
r64, rm64 [rm: f2 rex.w 0f 38 f1]
|
|
||||||
dec:
|
|
||||||
rm8 [m: fe /1]
|
|
||||||
rm16 [m: fe /1]
|
|
||||||
rm32 [m: fe /1]
|
|
||||||
rm64 [m: fe /1]
|
|
||||||
div:
|
|
||||||
rm8 [m: f6 /6]
|
|
||||||
rm16 [m: f7 /6]
|
|
||||||
rm32 [m: f7 /6]
|
|
||||||
rm64 [m: f7 /6]
|
|
||||||
hlt: [zo: f4]
|
|
||||||
idiv:
|
|
||||||
rm8 [m: f6 /7]
|
|
||||||
rm16 [m: f7 /7]
|
|
||||||
rm32 [m: f7 /7]
|
|
||||||
rm64 [m: f7 /7]
|
|
||||||
imul:
|
|
||||||
rm8 [m: f6 /5]
|
|
||||||
rm16 [m: f7 /5]
|
|
||||||
rm32 [m: f7 /5]
|
|
||||||
rm64 [m: f7 /5]
|
|
||||||
r16, rm16 [rm: 0f af]
|
|
||||||
r32, rm32 [rm: 0f af]
|
|
||||||
r64, rm64 [rm: 0f af]
|
|
||||||
r16, rm16, imm [rmi: 6b ib]
|
|
||||||
r32, rm32, imm [rmi: 6b ib]
|
|
||||||
r64, rm64, imm [rmi: 6b ib]
|
|
||||||
r16, rm16, imm16 [rmi: 69 iw]
|
|
||||||
r32, rm32, imm32 [rmi: 69 id]
|
|
||||||
r64, rm64, imm32 [rmi: 69 id]
|
|
||||||
in:
|
|
||||||
al, imm8 [-i: e4 ib]
|
|
||||||
ax, imm8 [-i: e5 ib]
|
|
||||||
eax, imm8 [-i: e5 ib]
|
|
||||||
al, dx [--: ec]
|
|
||||||
ax, dx [--: ed]
|
|
||||||
eax, dx [--: ed]
|
|
||||||
inc:
|
|
||||||
rm8 [m: fe /0]
|
|
||||||
rm16 [m: fe /0]
|
|
||||||
rm32 [m: fe /0]
|
|
||||||
rm64 [m: fe /0]
|
|
||||||
insb: [zo: 6c]
|
|
||||||
insw: [zo: 6d]
|
|
||||||
insd: [zo: 6d]
|
|
||||||
int: imm [i: cd ib]
|
|
||||||
int3: [zo: cc]
|
|
||||||
invd: [zo: 0f 08]
|
|
||||||
invlpg: m8 [m: 0f 01 /7]
|
|
||||||
iret: [zo: 66 cf]
|
|
||||||
iretd: [zo: cf]
|
|
||||||
iretq: [zo: rex.w cf]
|
|
||||||
jmp:
|
|
||||||
rel [d: eb rel8]
|
|
||||||
rel [d: e9 rel32]
|
|
||||||
rm64 [m: ff /4]
|
|
||||||
jcc: class jcc
|
|
||||||
jrcxz: rel [d: e3 rel8]
|
|
||||||
lahf: [zo: 9f]
|
|
||||||
lea:
|
|
||||||
r16, m16 [rm: 8d /r]
|
|
||||||
r32, m32 [rm: 8d /r]
|
|
||||||
r64, m64 [rm: 8d /r]
|
|
||||||
lodsb: [zo: ac]
|
|
||||||
lodsw: [zo: ad]
|
|
||||||
lodsd: [zo: ad]
|
|
||||||
lodsq: [zo: ad]
|
|
||||||
loop: rel [d: e2 rel8]
|
|
||||||
loope: rel [d: e1 rel8]
|
|
||||||
loopne: rel [d: e0 rel8]
|
|
||||||
monitor: [zo: 0f 01 c8]
|
|
||||||
mov:
|
|
||||||
rm8, r8 [mr: 88 /r]
|
|
||||||
rm16, r16 [mr: 89 /r]
|
|
||||||
rm32, r32 [mr: 89 /r]
|
|
||||||
rm64, r64 [mr: 89 /r]
|
|
||||||
r8, rm8 [rm: 8a /r]
|
|
||||||
r16, rm16 [rm: 8b /r]
|
|
||||||
r32, rm32 [rm: 8b /r]
|
|
||||||
r64, rm64 [rm: 8b /r]
|
|
||||||
r8, imm [ri: b0+r ib]
|
|
||||||
r16, imm [ri: b8+r iw]
|
|
||||||
r32, imm [ri: b8+r id]
|
|
||||||
r64, imm [ri: b8+r iq]
|
|
||||||
r8, imm [ri: c6 /0 ib]
|
|
||||||
r16, imm [ri: c7 /0 iw]
|
|
||||||
r32, imm [ri: c7 /0 id]
|
|
||||||
r64, imm [ri: c7 /0 id]
|
|
||||||
movsb: [zo: a4]
|
|
||||||
movsw: [zo: a5]
|
|
||||||
movsd: [zo: a5]
|
|
||||||
movsq: [zo: a5]
|
|
||||||
movsx:
|
|
||||||
r16, rm8 [rm: 0f be /r]
|
|
||||||
r32, rm8 [rm: 0f be /r]
|
|
||||||
r64, rm8 [rm: 0f be /r]
|
|
||||||
r32, rm16 [rm: 0f bf /r]
|
|
||||||
r64, rm16 [rm: 0f bf /r]
|
|
||||||
movsxd: r64, rm32 [rm: rex.w 63 /r]
|
|
||||||
movzx:
|
|
||||||
r16, rm8 [rm: 0f b6 /r]
|
|
||||||
r32, rm8 [rm: 0f b6 /r]
|
|
||||||
r64, rm8 [rm: 0f b6 /r]
|
|
||||||
r32, rm16 [rm: 0f b7 /r]
|
|
||||||
r64, rm16 [rm: 0f b7 /r]
|
|
||||||
mul:
|
|
||||||
rm8 [m: f6 /4]
|
|
||||||
rm16 [m: f7 /4]
|
|
||||||
rm32 [m: f7 /4]
|
|
||||||
rm64 [m: f7 /4]
|
|
||||||
mwait: [zo: 0f 01 c9]
|
|
||||||
neg:
|
|
||||||
rm8 [m: f6 /3]
|
|
||||||
rm16 [m: f7 /3]
|
|
||||||
rm32 [m: f7 /3]
|
|
||||||
rm64 [m: f7 /3]
|
|
||||||
nop:
|
|
||||||
[zo: 90]
|
|
||||||
rm16 [m: 0f 1f /0]
|
|
||||||
rm32 [m: 0f 1f /0]
|
|
||||||
not:
|
|
||||||
rm8 [m: f6 /2]
|
|
||||||
rm16 [m: f7 /2]
|
|
||||||
rm32 [m: f7 /2]
|
|
||||||
rm64 [m: f7 /2]
|
|
||||||
or: class base_arithmetic(/1, 0d, 09, 0b)
|
|
||||||
out:
|
|
||||||
imm, al [i-: e6 ib]
|
|
||||||
imm, ax [i-: e7 ib]
|
|
||||||
imm, ax [i-: e7 ib]
|
|
||||||
pause: [zo: f3 90]
|
|
||||||
pop:
|
|
||||||
rm16 [m: 8f /0]
|
|
||||||
rm64 [m: 8f /0]
|
|
||||||
r16 [o: 58+r]
|
|
||||||
r64 [o: 58+r]
|
|
||||||
popcnt:
|
|
||||||
r16, rm16 [rm: f3 0f b8 /r]
|
|
||||||
r32, rm32 [rm: f3 0f b8 /r]
|
|
||||||
r64, rm64 [rm: f3 0f b8 /r]
|
|
||||||
popf: [zo: 66 9d]
|
|
||||||
popfq: [zo: 9d]
|
|
||||||
prefetcht0: m8 [m: 0f 18 /1]
|
|
||||||
prefetcht1: m8 [m: 0f 18 /2]
|
|
||||||
prefetcht2: m8 [m: 0f 18 /3]
|
|
||||||
prefetchnta: m8 [m: 0f 18 /0]
|
|
||||||
push:
|
|
||||||
rm16 [m: ff /6]
|
|
||||||
rm64 [m: ff /6]
|
|
||||||
r16 [o: 50+r]
|
|
||||||
r64 [o: 50+r]
|
|
||||||
imm [i: 6a ib]
|
|
||||||
imm [i: 68 iw]
|
|
||||||
imm [i: 68 id]
|
|
||||||
pushf: [zo: 66 9c]
|
|
||||||
pushfq: [zo: 9c]
|
|
||||||
rol: class rotate(/0)
|
|
||||||
ror: class rotate(/1)
|
|
||||||
rcl: class rotate(/2)
|
|
||||||
rcr: class rotate(/3)
|
|
||||||
rdmsr: [zo: 0f 32]
|
|
||||||
rdpmc: [zo: 0f 33]
|
|
||||||
rdtsc: [zo: 0f 31]
|
|
||||||
rdtscp: [zo: 0f 01 f9]
|
|
||||||
ret:
|
|
||||||
[zo: c3]
|
|
||||||
imm [i: c2 iw]
|
|
||||||
retf:
|
|
||||||
[zo: cb]
|
|
||||||
imm [i: ca iw]
|
|
||||||
rsm: [zo: 0f aa]
|
|
||||||
sal: class shift(/4)
|
|
||||||
sar: class shift(/7)
|
|
||||||
shl: class shift(/4)
|
|
||||||
shr: class shift(/5)
|
|
||||||
scasb: [zo: ae]
|
|
||||||
scasw: [zo: af]
|
|
||||||
scasd: [zo: af]
|
|
||||||
scasq: [zo: af]
|
|
||||||
setcc: class setcc
|
|
||||||
stc: [zo: f9]
|
|
||||||
std: [zo: fd]
|
|
||||||
sti: [zo: fb]
|
|
||||||
stosb: [zo: aa]
|
|
||||||
stosw: [zo: ab]
|
|
||||||
stosd: [zo: ab]
|
|
||||||
stosq: [zo: ab]
|
|
||||||
sub: class base_arithmetic(/5, 2d, 29, 2b)
|
|
||||||
syscall: [zo: 0f 05]
|
|
||||||
sysenter: [zo: 0f 34]
|
|
||||||
sysexit: [zo: 0f 35]
|
|
||||||
sysret: [zo: 0f 07]
|
|
||||||
test:
|
|
||||||
al, imm8 [-i: a8 ib]
|
|
||||||
ax, imm16 [-i: a9 iw]
|
|
||||||
eax, imm32 [-i: a9 id]
|
|
||||||
rax, imm32 [-i: a9 id]
|
|
||||||
rm8, imm8 [mi: f6 /0 ib]
|
|
||||||
rm16, imm8 [mi: f7 /0 ib]
|
|
||||||
rm32, imm8 [mi: f7 /0 ib]
|
|
||||||
rm64, imm8 [mi: f7 /0 ib]
|
|
||||||
rm8, r8 [mr: 84 /r]
|
|
||||||
rm16, r16 [mr: 85 /r]
|
|
||||||
rm32, r32 [mr: 85 /r]
|
|
||||||
rm64, r64 [mr: 85 /r]
|
|
||||||
ud0: r32, rm32 [rm: 0f ff /r]
|
|
||||||
ud1: r32, rm32 [rm: 0f ff /r]
|
|
||||||
ud2: [zo: 0f 0b]
|
|
||||||
xadd:
|
|
||||||
rm8, r8 [mr: 0f c0 /r]
|
|
||||||
rm16, r16 [mr: 0f c1 /r]
|
|
||||||
rm32, r32 [mr: 0f c1 /r]
|
|
||||||
rm64, r64 [mr: 0f c1 /r]
|
|
||||||
xchg:
|
|
||||||
ax, r16 [-o: 90+r]
|
|
||||||
r16, ax [o-: 90+r]
|
|
||||||
eax, r32 [-o: 90+r]
|
|
||||||
r32, eax [o-: 90+r]
|
|
||||||
rax, r64 [-o: 90+r]
|
|
||||||
r64, rax [o-: 90+r]
|
|
||||||
rm8, r8 [mr: 86 /r]
|
|
||||||
r8, rm8 [rm: 86 /r]
|
|
||||||
rm16, r16 [mr: 87 /r]
|
|
||||||
r16, rm16 [rm: 87 /r]
|
|
||||||
rm32, r32 [mr: 87 /r]
|
|
||||||
r32, rm32 [rm: 87 /r]
|
|
||||||
rm64, r64 [mr: 87 /r]
|
|
||||||
r64, rm64 [rm: 87 /r]
|
|
@ -1,226 +0,0 @@
|
|||||||
adc
|
|
||||||
adcx
|
|
||||||
add
|
|
||||||
adox
|
|
||||||
and
|
|
||||||
bsf
|
|
||||||
bsr
|
|
||||||
bswap
|
|
||||||
bt
|
|
||||||
btc
|
|
||||||
btr
|
|
||||||
bts
|
|
||||||
call
|
|
||||||
cbw
|
|
||||||
cwde
|
|
||||||
cdqe
|
|
||||||
cwd
|
|
||||||
cdq
|
|
||||||
cqo
|
|
||||||
clc
|
|
||||||
cld
|
|
||||||
clflush
|
|
||||||
clflushopt
|
|
||||||
cli
|
|
||||||
clts
|
|
||||||
cmc
|
|
||||||
cmova
|
|
||||||
cmovae
|
|
||||||
cmovb
|
|
||||||
cmovbe
|
|
||||||
cmovc
|
|
||||||
cmove
|
|
||||||
cmovg
|
|
||||||
cmovge
|
|
||||||
cmovl
|
|
||||||
cmovle
|
|
||||||
cmovna
|
|
||||||
cmovnae
|
|
||||||
cmovnb
|
|
||||||
cmovnbe
|
|
||||||
cmovnc
|
|
||||||
cmovne
|
|
||||||
cmovng
|
|
||||||
cmovnge
|
|
||||||
cmovnl
|
|
||||||
cmovnle
|
|
||||||
cmovno
|
|
||||||
cmovnp
|
|
||||||
cmovns
|
|
||||||
cmovnz
|
|
||||||
cmovo
|
|
||||||
cmovp
|
|
||||||
cmovpe
|
|
||||||
cmovpo
|
|
||||||
cmovs
|
|
||||||
cmovz
|
|
||||||
cmp
|
|
||||||
cmpsb
|
|
||||||
cmpsw
|
|
||||||
cmpsd
|
|
||||||
cmpsq
|
|
||||||
cmpxchg
|
|
||||||
cmpxchg8b
|
|
||||||
cmpxchg16b
|
|
||||||
cpuid
|
|
||||||
crc32
|
|
||||||
dec
|
|
||||||
div
|
|
||||||
hlt
|
|
||||||
idiv
|
|
||||||
imul
|
|
||||||
in
|
|
||||||
inc
|
|
||||||
insb
|
|
||||||
insw
|
|
||||||
insd
|
|
||||||
int
|
|
||||||
int3
|
|
||||||
invd
|
|
||||||
invlpg
|
|
||||||
iret
|
|
||||||
iretd
|
|
||||||
iretq
|
|
||||||
jmp
|
|
||||||
ja
|
|
||||||
jae
|
|
||||||
jb
|
|
||||||
jbe
|
|
||||||
jc
|
|
||||||
je
|
|
||||||
jg
|
|
||||||
jge
|
|
||||||
jl
|
|
||||||
jle
|
|
||||||
jna
|
|
||||||
jnae
|
|
||||||
jnb
|
|
||||||
jnbe
|
|
||||||
jnc
|
|
||||||
jne
|
|
||||||
jng
|
|
||||||
jnge
|
|
||||||
jnl
|
|
||||||
jnle
|
|
||||||
jno
|
|
||||||
jnp
|
|
||||||
jns
|
|
||||||
jnz
|
|
||||||
jo
|
|
||||||
jp
|
|
||||||
jpe
|
|
||||||
jpo
|
|
||||||
js
|
|
||||||
jz
|
|
||||||
jrcxz
|
|
||||||
lahf
|
|
||||||
lea
|
|
||||||
lodsb
|
|
||||||
lodsw
|
|
||||||
lodsd
|
|
||||||
lodsq
|
|
||||||
loop
|
|
||||||
loope
|
|
||||||
loopne
|
|
||||||
monitor
|
|
||||||
mov
|
|
||||||
movsb
|
|
||||||
movsw
|
|
||||||
movsd
|
|
||||||
movsq
|
|
||||||
movsx
|
|
||||||
movsxd
|
|
||||||
movzx
|
|
||||||
mul
|
|
||||||
mwait
|
|
||||||
neg
|
|
||||||
nop
|
|
||||||
not
|
|
||||||
or
|
|
||||||
out
|
|
||||||
outsb
|
|
||||||
outsw
|
|
||||||
outsd
|
|
||||||
pause
|
|
||||||
pop
|
|
||||||
popcnt
|
|
||||||
popf
|
|
||||||
popfq
|
|
||||||
prefetcht0
|
|
||||||
prefetcht1
|
|
||||||
prefetcht2
|
|
||||||
prefetchnta
|
|
||||||
push
|
|
||||||
pushf
|
|
||||||
pushfq
|
|
||||||
rcl
|
|
||||||
rcr
|
|
||||||
rol
|
|
||||||
ror
|
|
||||||
rdmsr
|
|
||||||
rdpmc
|
|
||||||
rdtsc
|
|
||||||
rdtscp
|
|
||||||
ret
|
|
||||||
retf
|
|
||||||
rsm
|
|
||||||
sal
|
|
||||||
sar
|
|
||||||
shl
|
|
||||||
shr
|
|
||||||
sbb
|
|
||||||
scasb
|
|
||||||
scasw
|
|
||||||
scasd
|
|
||||||
scasq
|
|
||||||
seta
|
|
||||||
setae
|
|
||||||
setb
|
|
||||||
setbe
|
|
||||||
setc
|
|
||||||
sete
|
|
||||||
setg
|
|
||||||
setge
|
|
||||||
setl
|
|
||||||
setle
|
|
||||||
setna
|
|
||||||
setnae
|
|
||||||
setnb
|
|
||||||
setnbe
|
|
||||||
setnc
|
|
||||||
setne
|
|
||||||
setng
|
|
||||||
setnge
|
|
||||||
setnl
|
|
||||||
setnle
|
|
||||||
setno
|
|
||||||
setnp
|
|
||||||
setns
|
|
||||||
setnz
|
|
||||||
seto
|
|
||||||
setp
|
|
||||||
setpe
|
|
||||||
setpo
|
|
||||||
sets
|
|
||||||
setz
|
|
||||||
stc
|
|
||||||
std
|
|
||||||
sti
|
|
||||||
stosb
|
|
||||||
stosw
|
|
||||||
stosd
|
|
||||||
stosq
|
|
||||||
sub
|
|
||||||
syscall
|
|
||||||
sysenter
|
|
||||||
sysexit
|
|
||||||
sysret
|
|
||||||
test
|
|
||||||
ud0
|
|
||||||
ud1
|
|
||||||
ud2
|
|
||||||
wbinvd
|
|
||||||
wrmsr
|
|
||||||
xadd
|
|
||||||
xchg
|
|
||||||
xor
|
|
@ -1,63 +1,24 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#if _MSC_VER
|
#if _MSC_VER
|
||||||
extern u32 _lzcnt_u32(u32);
|
|
||||||
extern u32 _tzcnt_u32(u32);
|
|
||||||
extern u64 _lzcnt_u64(u64);
|
extern u64 _lzcnt_u64(u64);
|
||||||
extern u64 _tzcnt_u64(u64);
|
extern u64 _tzcnt_u64(u64);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
fn u8 leading_zeroes_u32(u32 value)
|
|
||||||
{
|
|
||||||
#if _MSC_VER
|
|
||||||
return (u8)_lzcnt_u32(value);
|
|
||||||
#else
|
|
||||||
return __builtin_clz(value);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
fn u8 leading_zeroes_u64(u64 value)
|
|
||||||
{
|
|
||||||
#if _MSC_VER
|
|
||||||
return (u8)_lzcnt_u64(value);
|
|
||||||
#else
|
|
||||||
return __builtin_clzll(value);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
fn u8 log2_alignment(u64 alignment)
|
fn u8 log2_alignment(u64 alignment)
|
||||||
{
|
{
|
||||||
assert(alignment != 0);
|
assert(alignment != 0);
|
||||||
assert((alignment & (alignment - 1)) == 0);
|
assert((alignment & (alignment - 1)) == 0);
|
||||||
u8 left = (sizeof(alignment) * 8) - 1;
|
u64 left = (sizeof(alignment) * 8) - 1;
|
||||||
u8 right = leading_zeroes_u64(alignment);
|
#if _MSC_VER
|
||||||
|
let_cast(u64, right, _lzcnt_u64(alignment));
|
||||||
|
#else
|
||||||
|
let_cast(u64, right, __builtin_clzll(alignment));
|
||||||
|
#endif
|
||||||
let_cast(u8, result, left - right);
|
let_cast(u8, result, left - right);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn u8 log2_u64(u64 v)
|
|
||||||
{
|
|
||||||
assert(v != 0);
|
|
||||||
return (sizeof(u64) * 8 - 1) - leading_zeroes_u64(v);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn u8 log2_u32(u32 v)
|
|
||||||
{
|
|
||||||
assert(v != 0);
|
|
||||||
return (sizeof(u32) * 8 - 1) - leading_zeroes_u32(v);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn u8 hex_digit_count(u64 v)
|
|
||||||
{
|
|
||||||
u8 result = 1;
|
|
||||||
if (v)
|
|
||||||
{
|
|
||||||
result = log2_u64(v) / log2_u64(16) + 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
fn u128 u128_from_u64(u64 n)
|
fn u128 u128_from_u64(u64 n)
|
||||||
{
|
{
|
||||||
#if defined(__TINYC__) || defined(_MSC_VER)
|
#if defined(__TINYC__) || defined(_MSC_VER)
|
||||||
@ -202,7 +163,7 @@ fn u64 generate_random_number()
|
|||||||
return u128_shift_right_by_64(rn_state);
|
return u128_shift_right_by_64(rn_state);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn u64 next_power_of_two(u64 n)
|
fn u64 round_up_to_next_power_of_2(u64 n)
|
||||||
{
|
{
|
||||||
n -= 1;
|
n -= 1;
|
||||||
n |= n >> 1;
|
n |= n >> 1;
|
||||||
@ -276,49 +237,9 @@ fn u64 is_decimal_digit(u8 ch)
|
|||||||
return (ch >= '0') & (ch <= '9');
|
return (ch >= '0') & (ch <= '9');
|
||||||
}
|
}
|
||||||
|
|
||||||
fn u64 is_alphanumeric(u8 ch)
|
|
||||||
{
|
|
||||||
return is_alphabetic(ch) | is_decimal_digit(ch);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn u64 is_hex_digit_alpha_lower(u8 ch)
|
|
||||||
{
|
|
||||||
return (ch >= 'a') & (ch <= 'f');
|
|
||||||
}
|
|
||||||
|
|
||||||
fn u64 is_hex_digit_alpha_upper(u8 ch)
|
|
||||||
{
|
|
||||||
return (ch >= 'A') & (ch <= 'F');
|
|
||||||
}
|
|
||||||
|
|
||||||
fn u64 is_hex_digit_alpha(u8 ch)
|
|
||||||
{
|
|
||||||
return is_hex_digit_alpha_lower(ch) | is_hex_digit_alpha_upper(ch);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn u64 is_hex_digit(u8 ch)
|
fn u64 is_hex_digit(u8 ch)
|
||||||
{
|
{
|
||||||
return is_decimal_digit(ch) | is_hex_digit_alpha(ch);
|
return (is_decimal_digit(ch) | (((ch == 'a') | (ch == 'A')) | ((ch == 'b') | (ch == 'B')))) | ((((ch == 'c') | (ch == 'C')) | ((ch == 'd') | (ch == 'D'))) | (((ch == 'e') | (ch == 'E')) | ((ch == 'f') | (ch == 'F'))));
|
||||||
}
|
|
||||||
|
|
||||||
fn u8 hex_ch_to_int(u8 ch)
|
|
||||||
{
|
|
||||||
if ((ch >= '0') & (ch <= '9'))
|
|
||||||
{
|
|
||||||
return ch - '0';
|
|
||||||
}
|
|
||||||
else if ((ch >= 'a') & (ch <= 'f'))
|
|
||||||
{
|
|
||||||
return ch - 'a' + 10;
|
|
||||||
}
|
|
||||||
else if ((ch >= 'A') & (ch <= 'F'))
|
|
||||||
{
|
|
||||||
return ch - 'A' + 10;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
unreachable();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn u64 is_identifier_start(u8 ch)
|
fn u64 is_identifier_start(u8 ch)
|
||||||
@ -361,38 +282,25 @@ fn Hash32 hash64_to_hash32(Hash64 hash64)
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn u64 align_forward_u32(u32 value, u32 alignment)
|
fn u64 align_forward(u64 value, u64 alignment)
|
||||||
{
|
|
||||||
u32 mask = alignment - 1;
|
|
||||||
u32 result = (value + mask) & ~mask;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
fn u32 align_backward_u32(u32 value, u32 alignment)
|
|
||||||
{
|
|
||||||
u32 result = value & ~(alignment - 1);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
fn u64 align_forward_u64(u64 value, u64 alignment)
|
|
||||||
{
|
{
|
||||||
u64 mask = alignment - 1;
|
u64 mask = alignment - 1;
|
||||||
u64 result = (value + mask) & ~mask;
|
u64 result = (value + mask) & ~mask;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn u64 align_backward_u64(u64 value, u64 alignment)
|
fn u64 align_backward(u64 value, u64 alignment)
|
||||||
{
|
{
|
||||||
u64 result = value & ~(alignment - 1);
|
u64 result = value & ~(alignment - 1);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn u8 is_power_of_two_u64(u64 value)
|
fn u8 is_power_of_two(u64 value)
|
||||||
{
|
{
|
||||||
return (value & (value - 1)) == 0;
|
return (value & (value - 1)) == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn u8 first_bit_set_u32(u32 value)
|
fn u8 first_bit_set_32(u32 value)
|
||||||
{
|
{
|
||||||
#if _MSC_VER
|
#if _MSC_VER
|
||||||
DWORD result_dword;
|
DWORD result_dword;
|
||||||
@ -406,7 +314,7 @@ fn u8 first_bit_set_u32(u32 value)
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn u64 first_bit_set_u64(u64 value)
|
fn u64 first_bit_set_64(u64 value)
|
||||||
{
|
{
|
||||||
#if _MSC_VER
|
#if _MSC_VER
|
||||||
DWORD result_dword;
|
DWORD result_dword;
|
||||||
@ -431,33 +339,3 @@ fn Hash32 hash64_fib_end(Hash64 hash)
|
|||||||
let(result, TRUNCATE(Hash32, ((hash + 1) * 11400714819323198485ull) >> 32));
|
let(result, TRUNCATE(Hash32, ((hash + 1) * 11400714819323198485ull) >> 32));
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn u64 parse_hexadecimal(String string, u8* error)
|
|
||||||
{
|
|
||||||
u8* it = &string.pointer[string.length - 1];
|
|
||||||
u8 is_error = 0;
|
|
||||||
|
|
||||||
u64 result = 0;
|
|
||||||
|
|
||||||
while (it >= string.pointer)
|
|
||||||
{
|
|
||||||
u8 ch = *it;
|
|
||||||
|
|
||||||
u8 is_error_it = !is_hex_digit(ch);
|
|
||||||
is_error |= is_error_it;
|
|
||||||
if (is_error_it)
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
u8 sub = is_decimal_digit(ch) ? '0' : (is_hex_digit_alpha_lower(ch) ? 'a' : 'A');
|
|
||||||
u8 hex_value = ch - sub + 10 * is_hex_digit_alpha(ch);
|
|
||||||
assert((hex_value & 0xf) == hex_value);
|
|
||||||
result = (result << 4) | hex_value;
|
|
||||||
|
|
||||||
it -= 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
*error = is_error;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
@ -1,10 +1,5 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#define STRINGIFY(x) #x
|
|
||||||
#define TOSTRING(x) STRINGIFY(x)
|
|
||||||
|
|
||||||
#define USE_MEMCPY 1
|
|
||||||
|
|
||||||
#if _WIN32
|
#if _WIN32
|
||||||
#define _CRT_SECURE_NO_WARNINGS
|
#define _CRT_SECURE_NO_WARNINGS
|
||||||
#endif
|
#endif
|
||||||
@ -15,6 +10,16 @@
|
|||||||
#define BB_DEBUG 1
|
#define BB_DEBUG 1
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define BB_INCLUDE_INTRINSIC 0
|
||||||
|
#if BB_DEBUG == 0
|
||||||
|
#undef BB_INCLUDE_INTRINSIC
|
||||||
|
#define BB_INCLUDE_INTRINSIC 1
|
||||||
|
#endif
|
||||||
|
#if BB_INCLUDE_INTRINSIC
|
||||||
|
#if defined(__x86_64__)
|
||||||
|
#include <immintrin.h>
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
@ -135,7 +140,6 @@ declare_slice(s32);
|
|||||||
declare_slice(s64);
|
declare_slice(s64);
|
||||||
|
|
||||||
declare_slice_p(char);
|
declare_slice_p(char);
|
||||||
declare_slice_p(u8);
|
|
||||||
declare_slice_p(void);
|
declare_slice_p(void);
|
||||||
|
|
||||||
typedef Slice(u8) String;
|
typedef Slice(u8) String;
|
||||||
@ -190,7 +194,7 @@ declare_slice(String);
|
|||||||
#define unlikely(x) expect(x, 0)
|
#define unlikely(x) expect(x, 0)
|
||||||
#define breakpoint() __builtin_debugtrap()
|
#define breakpoint() __builtin_debugtrap()
|
||||||
#define failed_execution() panic("Failed execution at {cstr}:{u32}\n", __FILE__, __LINE__)
|
#define failed_execution() panic("Failed execution at {cstr}:{u32}\n", __FILE__, __LINE__)
|
||||||
#define todo() os_is_being_debugged() ? trap() : panic("TODO at {cstr}:{u32}\n", __FILE__, __LINE__); fix_unreachable()
|
#define todo() panic("TODO at {cstr}:{u32}\n", __FILE__, __LINE__); fix_unreachable()
|
||||||
|
|
||||||
fn void print(const char* format, ...);
|
fn void print(const char* format, ...);
|
||||||
BB_NORETURN BB_COLD fn void os_exit(u32 exit_code);
|
BB_NORETURN BB_COLD fn void os_exit(u32 exit_code);
|
||||||
@ -212,8 +216,7 @@ fn BB_NORETURN BB_COLD void trap_ext()
|
|||||||
#define trap() (trap_ext(), __builtin_unreachable())
|
#define trap() (trap_ext(), __builtin_unreachable())
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
fn u8 os_is_being_debugged();
|
#define panic(format, ...) (print(format, __VA_ARGS__), os_exit(1))
|
||||||
#define panic(format, ...) (!os_is_being_debugged() ? print(format, __VA_ARGS__), os_exit(1) : os_exit(1))
|
|
||||||
|
|
||||||
#define let_pointer_cast(PointerChildType, var_name, value) PointerChildType* var_name = (PointerChildType*)(value)
|
#define let_pointer_cast(PointerChildType, var_name, value) PointerChildType* var_name = (PointerChildType*)(value)
|
||||||
#if defined(__TINYC__) || defined(_MSC_VER)
|
#if defined(__TINYC__) || defined(_MSC_VER)
|
||||||
@ -320,12 +323,12 @@ global_variable const u8 bracket_close = ']';
|
|||||||
#define s_get_slice(T, s, start, end) (Slice(T)){ .pointer = ((s).pointer) + (start), .length = (end) - (start) }
|
#define s_get_slice(T, s, start, end) (Slice(T)){ .pointer = ((s).pointer) + (start), .length = (end) - (start) }
|
||||||
#define s_equal(a, b) ((a).length == (b).length && memcmp((a).pointer, (b).pointer, sizeof(*((a).pointer)) * (a).length) == 0)
|
#define s_equal(a, b) ((a).length == (b).length && memcmp((a).pointer, (b).pointer, sizeof(*((a).pointer)) * (a).length) == 0)
|
||||||
|
|
||||||
fn u64 align_forward_u64(u64 value, u64 alignment);
|
fn u64 align_forward(u64 value, u64 alignment);
|
||||||
fn u64 align_backward_u64(u64 value, u64 alignment);
|
fn u64 align_backward(u64 value, u64 alignment);
|
||||||
fn u8 log2_alignment_u64(u64 alignment);
|
fn u8 log2_alignment(u64 alignment);
|
||||||
fn u8 is_power_of_two_u64(u64 value);
|
fn u8 is_power_of_two(u64 value);
|
||||||
fn u8 first_bit_set_u32(u32 value);
|
fn u8 first_bit_set_32(u32 value);
|
||||||
fn u64 first_bit_set_u64(u64 value);
|
fn u64 first_bit_set_64(u64 value);
|
||||||
|
|
||||||
fn u32 format_decimal(String buffer, u64 decimal);
|
fn u32 format_decimal(String buffer, u64 decimal);
|
||||||
fn u32 format_hexadecimal(String buffer, u64 hexadecimal);
|
fn u32 format_hexadecimal(String buffer, u64 hexadecimal);
|
||||||
@ -337,7 +340,6 @@ fn u8 get_next_ch_safe(String string, u64 index);
|
|||||||
fn u64 is_identifier_start(u8 ch);
|
fn u64 is_identifier_start(u8 ch);
|
||||||
fn u64 is_identifier_ch(u8 ch);
|
fn u64 is_identifier_ch(u8 ch);
|
||||||
fn u64 is_alphabetic(u8 ch);
|
fn u64 is_alphabetic(u8 ch);
|
||||||
fn u64 is_alphanumeric(u8 ch);
|
|
||||||
|
|
||||||
fn u64 parse_decimal(String string);
|
fn u64 parse_decimal(String string);
|
||||||
|
|
||||||
|
@ -1075,72 +1075,6 @@ typedef enum IntegerFormat
|
|||||||
INTEGER_FORMAT_BINARY,
|
INTEGER_FORMAT_BINARY,
|
||||||
} IntegerFormat;
|
} IntegerFormat;
|
||||||
|
|
||||||
STRUCT(IntegerFormatOptions)
|
|
||||||
{
|
|
||||||
IntegerFormat format;
|
|
||||||
u32 width;
|
|
||||||
};
|
|
||||||
|
|
||||||
fn IntegerFormatOptions integer_format_options(u8** it)
|
|
||||||
{
|
|
||||||
IntegerFormatOptions options = {
|
|
||||||
.format = INTEGER_FORMAT_DECIMAL,
|
|
||||||
};
|
|
||||||
|
|
||||||
if (**it == ':')
|
|
||||||
{
|
|
||||||
*it += 1;
|
|
||||||
|
|
||||||
while (**it != brace_close)
|
|
||||||
{
|
|
||||||
switch (**it)
|
|
||||||
{
|
|
||||||
case 'x':
|
|
||||||
options.format = INTEGER_FORMAT_HEXADECIMAL;
|
|
||||||
*it += 1;
|
|
||||||
break;
|
|
||||||
case 'd':
|
|
||||||
options.format = INTEGER_FORMAT_DECIMAL;
|
|
||||||
*it += 1;
|
|
||||||
break;
|
|
||||||
case 'o':
|
|
||||||
options.format = INTEGER_FORMAT_OCTAL;
|
|
||||||
*it += 1;
|
|
||||||
break;
|
|
||||||
case 'b':
|
|
||||||
options.format = INTEGER_FORMAT_BINARY;
|
|
||||||
*it += 1;
|
|
||||||
break;
|
|
||||||
case 'w':
|
|
||||||
{
|
|
||||||
*it += 1;
|
|
||||||
|
|
||||||
if (**it != '=')
|
|
||||||
{
|
|
||||||
todo();
|
|
||||||
}
|
|
||||||
|
|
||||||
*it += 1;
|
|
||||||
|
|
||||||
let(start, *it);
|
|
||||||
while (is_decimal_digit(**it))
|
|
||||||
{
|
|
||||||
*it += 1;
|
|
||||||
}
|
|
||||||
let(end, *it);
|
|
||||||
assign_cast(options.width, parse_decimal(slice_from_pointer_range(u8, start, end)));
|
|
||||||
} break;
|
|
||||||
default:
|
|
||||||
unreachable();
|
|
||||||
}
|
|
||||||
|
|
||||||
*it += **it == ',';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return options;
|
|
||||||
}
|
|
||||||
|
|
||||||
fn String format_string_va(String buffer, const char* format, va_list args)
|
fn String format_string_va(String buffer, const char* format, va_list args)
|
||||||
{
|
{
|
||||||
u8* it = (u8*)format;
|
u8* it = (u8*)format;
|
||||||
@ -1247,7 +1181,31 @@ fn String format_string_va(String buffer, const char* format, va_list args)
|
|||||||
u8* bit_count_end = it;
|
u8* bit_count_end = it;
|
||||||
u64 bit_count = parse_decimal(slice_from_pointer_range(u8, (u8*)bit_count_start, (u8*)bit_count_end));
|
u64 bit_count = parse_decimal(slice_from_pointer_range(u8, (u8*)bit_count_start, (u8*)bit_count_end));
|
||||||
|
|
||||||
IntegerFormatOptions options = integer_format_options(&it);
|
IntegerFormat integer_format = INTEGER_FORMAT_DECIMAL;
|
||||||
|
|
||||||
|
if (*it == ':')
|
||||||
|
{
|
||||||
|
it += 1;
|
||||||
|
switch (*it)
|
||||||
|
{
|
||||||
|
case 'x':
|
||||||
|
integer_format = INTEGER_FORMAT_HEXADECIMAL;
|
||||||
|
break;
|
||||||
|
case 'd':
|
||||||
|
integer_format = INTEGER_FORMAT_DECIMAL;
|
||||||
|
break;
|
||||||
|
case 'o':
|
||||||
|
integer_format = INTEGER_FORMAT_OCTAL;
|
||||||
|
break;
|
||||||
|
case 'b':
|
||||||
|
integer_format = INTEGER_FORMAT_BINARY;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
unreachable();
|
||||||
|
}
|
||||||
|
|
||||||
|
it += 1;
|
||||||
|
}
|
||||||
|
|
||||||
s64 original_value;
|
s64 original_value;
|
||||||
switch (bit_count)
|
switch (bit_count)
|
||||||
@ -1266,21 +1224,11 @@ fn String format_string_va(String buffer, const char* format, va_list args)
|
|||||||
|
|
||||||
String buffer_slice = s_get_slice(u8, buffer, buffer_i, buffer.length);
|
String buffer_slice = s_get_slice(u8, buffer, buffer_i, buffer.length);
|
||||||
|
|
||||||
switch (options.format)
|
switch (integer_format)
|
||||||
{
|
{
|
||||||
case INTEGER_FORMAT_HEXADECIMAL:
|
case INTEGER_FORMAT_HEXADECIMAL:
|
||||||
{
|
{
|
||||||
u32 expected_characters = hex_digit_count(original_value);
|
|
||||||
|
|
||||||
if (expected_characters < options.width)
|
|
||||||
{
|
|
||||||
u32 extra_characters = options.width - expected_characters;
|
|
||||||
memset(buffer.pointer, '0', extra_characters);
|
|
||||||
buffer_i += extra_characters;
|
|
||||||
}
|
|
||||||
|
|
||||||
let(written_characters, format_hexadecimal(buffer_slice, original_value));
|
let(written_characters, format_hexadecimal(buffer_slice, original_value));
|
||||||
assert(expected_characters == written_characters);
|
|
||||||
buffer_i += written_characters;
|
buffer_i += written_characters;
|
||||||
} break;
|
} break;
|
||||||
case INTEGER_FORMAT_DECIMAL:
|
case INTEGER_FORMAT_DECIMAL:
|
||||||
@ -1333,7 +1281,39 @@ fn String format_string_va(String buffer, const char* format, va_list args)
|
|||||||
u8* bit_count_end = it;
|
u8* bit_count_end = it;
|
||||||
u64 bit_count = parse_decimal(slice_from_pointer_range(u8, (u8*)bit_count_start, (u8*)bit_count_end));
|
u64 bit_count = parse_decimal(slice_from_pointer_range(u8, (u8*)bit_count_start, (u8*)bit_count_end));
|
||||||
|
|
||||||
IntegerFormatOptions options = integer_format_options(&it);
|
typedef enum IntegerFormat
|
||||||
|
{
|
||||||
|
INTEGER_FORMAT_HEXADECIMAL,
|
||||||
|
INTEGER_FORMAT_DECIMAL,
|
||||||
|
INTEGER_FORMAT_OCTAL,
|
||||||
|
INTEGER_FORMAT_BINARY,
|
||||||
|
} IntegerFormat;
|
||||||
|
|
||||||
|
IntegerFormat integer_format = INTEGER_FORMAT_DECIMAL;
|
||||||
|
|
||||||
|
if (*it == ':')
|
||||||
|
{
|
||||||
|
it += 1;
|
||||||
|
switch (*it)
|
||||||
|
{
|
||||||
|
case 'x':
|
||||||
|
integer_format = INTEGER_FORMAT_HEXADECIMAL;
|
||||||
|
break;
|
||||||
|
case 'd':
|
||||||
|
integer_format = INTEGER_FORMAT_DECIMAL;
|
||||||
|
break;
|
||||||
|
case 'o':
|
||||||
|
integer_format = INTEGER_FORMAT_OCTAL;
|
||||||
|
break;
|
||||||
|
case 'b':
|
||||||
|
integer_format = INTEGER_FORMAT_BINARY;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
unreachable();
|
||||||
|
}
|
||||||
|
|
||||||
|
it += 1;
|
||||||
|
}
|
||||||
|
|
||||||
u64 original_value;
|
u64 original_value;
|
||||||
switch (bit_count)
|
switch (bit_count)
|
||||||
@ -1350,41 +1330,26 @@ fn String format_string_va(String buffer, const char* format, va_list args)
|
|||||||
unreachable();
|
unreachable();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let(buffer_slice, s_get_slice(u8, buffer, buffer_i, buffer.length));
|
||||||
|
|
||||||
switch (options.format)
|
switch (integer_format)
|
||||||
{
|
{
|
||||||
case INTEGER_FORMAT_HEXADECIMAL:
|
case INTEGER_FORMAT_HEXADECIMAL:
|
||||||
{
|
{
|
||||||
u32 expected_characters = hex_digit_count(original_value);
|
|
||||||
|
|
||||||
if (expected_characters < options.width)
|
|
||||||
{
|
|
||||||
u32 extra_characters = options.width - expected_characters;
|
|
||||||
memset(buffer.pointer + buffer_i, '0', extra_characters);
|
|
||||||
buffer_i += extra_characters;
|
|
||||||
}
|
|
||||||
|
|
||||||
let(buffer_slice, s_get_slice(u8, buffer, buffer_i, buffer.length));
|
|
||||||
let(written_characters, format_hexadecimal(buffer_slice, original_value));
|
let(written_characters, format_hexadecimal(buffer_slice, original_value));
|
||||||
assert(expected_characters == written_characters);
|
|
||||||
buffer_i += written_characters;
|
buffer_i += written_characters;
|
||||||
} break;
|
} break;
|
||||||
case INTEGER_FORMAT_DECIMAL:
|
case INTEGER_FORMAT_DECIMAL:
|
||||||
{
|
{
|
||||||
let(buffer_slice, s_get_slice(u8, buffer, buffer_i, buffer.length));
|
|
||||||
let(written_characters, format_decimal(buffer_slice, original_value));
|
let(written_characters, format_decimal(buffer_slice, original_value));
|
||||||
buffer_i += written_characters;
|
buffer_i += written_characters;
|
||||||
} break;
|
} break;
|
||||||
case INTEGER_FORMAT_OCTAL:
|
case INTEGER_FORMAT_OCTAL:
|
||||||
{
|
{
|
||||||
let(buffer_slice, s_get_slice(u8, buffer, buffer_i, buffer.length));
|
|
||||||
unused(buffer_slice);
|
|
||||||
todo();
|
todo();
|
||||||
} break;
|
} break;
|
||||||
case INTEGER_FORMAT_BINARY:
|
case INTEGER_FORMAT_BINARY:
|
||||||
{
|
{
|
||||||
let(buffer_slice, s_get_slice(u8, buffer, buffer_i, buffer.length));
|
|
||||||
unused(buffer_slice);
|
|
||||||
todo();
|
todo();
|
||||||
} break;
|
} break;
|
||||||
}
|
}
|
||||||
@ -1416,27 +1381,3 @@ fn String format_string(String buffer, const char* format, ...)
|
|||||||
va_end(args);
|
va_end(args);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn void formatter_append(StringFormatter* formatter, const char* format, ...)
|
|
||||||
{
|
|
||||||
va_list args;
|
|
||||||
va_start(args, format);
|
|
||||||
String buffer = s_get_slice(u8, formatter->buffer, formatter->index, formatter->buffer.length);
|
|
||||||
let(result, format_string_va(buffer, format, args));
|
|
||||||
va_end(args);
|
|
||||||
formatter->index += result.length;
|
|
||||||
}
|
|
||||||
|
|
||||||
fn void formatter_append_string(StringFormatter* formatter, String string)
|
|
||||||
{
|
|
||||||
assert(string.length + formatter->index <= formatter->buffer.length);
|
|
||||||
memcpy(formatter->buffer.pointer + formatter->index, string.pointer, string.length);
|
|
||||||
formatter->index += string.length;
|
|
||||||
}
|
|
||||||
|
|
||||||
fn void formatter_append_character(StringFormatter* formatter, u8 ch)
|
|
||||||
{
|
|
||||||
assert(formatter->index < formatter->buffer.length);
|
|
||||||
formatter->buffer.pointer[formatter->index] = ch;
|
|
||||||
formatter->index += 1;
|
|
||||||
}
|
|
||||||
|
@ -1,13 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
STRUCT(StringFormatter)
|
#include <std/base.h>
|
||||||
{
|
|
||||||
String buffer;
|
|
||||||
u64 index;
|
|
||||||
};
|
|
||||||
|
|
||||||
fn void formatter_append(StringFormatter* formatter, const char* format, ...);
|
|
||||||
fn void formatter_append_string(StringFormatter* formatter, String string);
|
|
||||||
fn void formatter_append_character(StringFormatter* formatter, u8 ch);
|
|
||||||
fn String format_string(String buffer, const char* format, ...);
|
fn String format_string(String buffer, const char* format, ...);
|
||||||
fn String format_string_va(String buffer, const char* format, va_list args);
|
fn String format_string_va(String buffer, const char* format, va_list args);
|
||||||
|
@ -2,11 +2,9 @@
|
|||||||
|
|
||||||
#include <std/string.h>
|
#include <std/string.h>
|
||||||
#include <std/format.h>
|
#include <std/format.h>
|
||||||
#include <std/virtual_buffer.h>
|
|
||||||
|
|
||||||
#include <std/string.c>
|
#include <std/string.c>
|
||||||
#include <std/format.c>
|
#include <std/format.c>
|
||||||
#include <std/virtual_buffer.c>
|
|
||||||
|
|
||||||
#if _WIN32
|
#if _WIN32
|
||||||
global_variable u64 cpu_frequency;
|
global_variable u64 cpu_frequency;
|
||||||
@ -776,15 +774,6 @@ fn u64 os_timer_get()
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
FileDescriptor os_file_descriptor_invalid()
|
|
||||||
{
|
|
||||||
#if _WIN32
|
|
||||||
return INVALID_HANDLE_VALUE;
|
|
||||||
#else
|
|
||||||
return -1;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
fn u8 os_file_descriptor_is_valid(FileDescriptor fd)
|
fn u8 os_file_descriptor_is_valid(FileDescriptor fd)
|
||||||
{
|
{
|
||||||
#if _WIN32
|
#if _WIN32
|
||||||
@ -863,8 +852,6 @@ fn void os_file_write(FileDescriptor fd, String content)
|
|||||||
assert(result != 0);
|
assert(result != 0);
|
||||||
#else
|
#else
|
||||||
let(result, syscall_write(fd, content.pointer, content.length));
|
let(result, syscall_write(fd, content.pointer, content.length));
|
||||||
let(my_errno, strerror(errno));
|
|
||||||
unused(my_errno);
|
|
||||||
assert(cast_to(u64, result) == content.length);
|
assert(cast_to(u64, result) == content.length);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
@ -950,9 +937,6 @@ fn u8* os_reserve(u64 base, u64 size, OSReserveProtectionFlags protection, OSRes
|
|||||||
#else
|
#else
|
||||||
int protection_flags = (protection.read * PROT_READ) | (protection.write * PROT_WRITE) | (protection.execute * PROT_EXEC);
|
int protection_flags = (protection.read * PROT_READ) | (protection.write * PROT_WRITE) | (protection.execute * PROT_EXEC);
|
||||||
int map_flags = (map.anon * MAP_ANONYMOUS) | (map.priv * MAP_PRIVATE) | (map.noreserve * MAP_NORESERVE);
|
int map_flags = (map.anon * MAP_ANONYMOUS) | (map.priv * MAP_PRIVATE) | (map.noreserve * MAP_NORESERVE);
|
||||||
#ifdef __linux__
|
|
||||||
map_flags |= (map.populate * MAP_POPULATE);
|
|
||||||
#endif
|
|
||||||
u8* result = (u8*)posix_mmap((void*)base, size, protection_flags, map_flags, -1, 0);
|
u8* result = (u8*)posix_mmap((void*)base, size, protection_flags, map_flags, -1, 0);
|
||||||
assert(result != MAP_FAILED);
|
assert(result != MAP_FAILED);
|
||||||
return result;
|
return result;
|
||||||
@ -979,36 +963,8 @@ fn void os_directory_make(String path)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
fn u8 os_is_being_debugged()
|
|
||||||
{
|
|
||||||
u8 result = 0;
|
|
||||||
#if _WIN32
|
|
||||||
result = IsDebuggerPresent() != 0;
|
|
||||||
#else
|
|
||||||
#ifdef __APPLE__
|
|
||||||
let(request, PT_TRACE_ME);
|
|
||||||
#else
|
|
||||||
let(request, PTRACE_TRACEME);
|
|
||||||
#endif
|
|
||||||
if (ptrace(request, 0, 0, 0) == -1)
|
|
||||||
{
|
|
||||||
let(error, errno);
|
|
||||||
if (error == EPERM)
|
|
||||||
{
|
|
||||||
result = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
BB_NORETURN BB_COLD fn void os_exit(u32 exit_code)
|
BB_NORETURN BB_COLD fn void os_exit(u32 exit_code)
|
||||||
{
|
{
|
||||||
if (exit_code != 0 && os_is_being_debugged())
|
|
||||||
{
|
|
||||||
trap();
|
|
||||||
}
|
|
||||||
exit(exit_code);
|
exit(exit_code);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1060,12 +1016,12 @@ fn Arena* arena_initialize_default(u64 initial_size)
|
|||||||
|
|
||||||
fn u8* arena_allocate_bytes(Arena* arena, u64 size, u64 alignment)
|
fn u8* arena_allocate_bytes(Arena* arena, u64 size, u64 alignment)
|
||||||
{
|
{
|
||||||
u64 aligned_offset = align_forward_u64(arena->position, alignment);
|
u64 aligned_offset = align_forward(arena->position, alignment);
|
||||||
u64 aligned_size_after = aligned_offset + size;
|
u64 aligned_size_after = aligned_offset + size;
|
||||||
|
|
||||||
if (aligned_size_after > arena->os_position)
|
if (aligned_size_after > arena->os_position)
|
||||||
{
|
{
|
||||||
u64 committed_size = align_forward_u64(aligned_size_after, arena->granularity);
|
u64 committed_size = align_forward(aligned_size_after, arena->granularity);
|
||||||
u64 size_to_commit = committed_size - arena->os_position;
|
u64 size_to_commit = committed_size - arena->os_position;
|
||||||
void* commit_pointer = (u8*)arena + arena->os_position;
|
void* commit_pointer = (u8*)arena + arena->os_position;
|
||||||
os_commit(commit_pointer, size_to_commit);
|
os_commit(commit_pointer, size_to_commit);
|
||||||
@ -1101,18 +1057,6 @@ fn String arena_join_string(Arena* arena, Slice(String) pieces)
|
|||||||
return (String) { .pointer = pointer, .length = size };
|
return (String) { .pointer = pointer, .length = size };
|
||||||
}
|
}
|
||||||
|
|
||||||
fn String arena_duplicate_string(Arena* arena, String string)
|
|
||||||
{
|
|
||||||
u8* result = arena_allocate(arena, u8, string.length + 1);
|
|
||||||
memcpy(result, string.pointer, string.length);
|
|
||||||
result[string.length] = 0;
|
|
||||||
|
|
||||||
return (String) {
|
|
||||||
.pointer = result,
|
|
||||||
.length = string.length,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
fn void arena_reset(Arena* arena)
|
fn void arena_reset(Arena* arena)
|
||||||
{
|
{
|
||||||
arena->position = minimum_position;
|
arena->position = minimum_position;
|
||||||
@ -1161,6 +1105,7 @@ fn String file_read(Arena* arena, String path)
|
|||||||
|
|
||||||
fn void file_write(FileWriteOptions options)
|
fn void file_write(FileWriteOptions options)
|
||||||
{
|
{
|
||||||
|
print("Writing file \"{s}\"...\n", options.path);
|
||||||
let(fd, os_file_open(options.path, (OSFileOpenFlags) {
|
let(fd, os_file_open(options.path, (OSFileOpenFlags) {
|
||||||
.write = 1,
|
.write = 1,
|
||||||
.truncate = 1,
|
.truncate = 1,
|
||||||
@ -1177,18 +1122,11 @@ fn void file_write(FileWriteOptions options)
|
|||||||
os_file_close(fd);
|
os_file_close(fd);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn RunCommandResult run_command(Arena* arena, CStringSlice arguments, char* envp[], RunCommandOptions run_options)
|
fn void run_command(Arena* arena, CStringSlice arguments, char* envp[], RunCommandOptions run_options)
|
||||||
{
|
{
|
||||||
unused(arena);
|
|
||||||
assert(arguments.length > 0);
|
assert(arguments.length > 0);
|
||||||
assert(arguments.pointer[arguments.length - 1] == 0);
|
assert(arguments.pointer[arguments.length - 1] == 0);
|
||||||
|
|
||||||
RunCommandResult result = {};
|
|
||||||
Timestamp start_timestamp = {};
|
|
||||||
Timestamp end_timestamp = {};
|
|
||||||
f64 ms = 0.0;
|
|
||||||
u64 measure_time = run_options.debug;
|
|
||||||
|
|
||||||
if (run_options.debug)
|
if (run_options.debug)
|
||||||
{
|
{
|
||||||
print("Running command:\n");
|
print("Running command:\n");
|
||||||
@ -1201,6 +1139,8 @@ fn RunCommandResult run_command(Arena* arena, CStringSlice arguments, char* envp
|
|||||||
}
|
}
|
||||||
|
|
||||||
#if _WIN32
|
#if _WIN32
|
||||||
|
let(start_timestamp, os_timestamp());
|
||||||
|
|
||||||
u32 length = 0;
|
u32 length = 0;
|
||||||
for (u32 i = 0; i < arguments.length; i += 1)
|
for (u32 i = 0; i < arguments.length; i += 1)
|
||||||
{
|
{
|
||||||
@ -1227,6 +1167,7 @@ fn RunCommandResult run_command(Arena* arena, CStringSlice arguments, char* envp
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
bytes[byte_i - 1] = 0;
|
bytes[byte_i - 1] = 0;
|
||||||
|
let(end_timestamp, os_timestamp());
|
||||||
|
|
||||||
PROCESS_INFORMATION process_information = {};
|
PROCESS_INFORMATION process_information = {};
|
||||||
STARTUPINFOA startup_info = {};
|
STARTUPINFOA startup_info = {};
|
||||||
@ -1234,22 +1175,14 @@ fn RunCommandResult run_command(Arena* arena, CStringSlice arguments, char* envp
|
|||||||
startup_info.dwFlags |= STARTF_USESTDHANDLES;
|
startup_info.dwFlags |= STARTF_USESTDHANDLES;
|
||||||
startup_info.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE);
|
startup_info.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||||
startup_info.hStdError = GetStdHandle(STD_ERROR_HANDLE);
|
startup_info.hStdError = GetStdHandle(STD_ERROR_HANDLE);
|
||||||
|
|
||||||
let(handle_inheritance, 1);
|
let(handle_inheritance, 1);
|
||||||
|
let(start, os_timestamp());
|
||||||
if (measure_time)
|
|
||||||
{
|
|
||||||
start_timestamp = os_timestamp();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (CreateProcessA(0, bytes, 0, 0, handle_inheritance, 0, 0, 0, &startup_info, &process_information))
|
if (CreateProcessA(0, bytes, 0, 0, handle_inheritance, 0, 0, 0, &startup_info, &process_information))
|
||||||
{
|
{
|
||||||
WaitForSingleObject(process_information.hProcess, INFINITE);
|
WaitForSingleObject(process_information.hProcess, INFINITE);
|
||||||
if (measure_time)
|
let(end, os_timestamp());
|
||||||
{
|
let(ms, os_resolve_timestamps(start, end, TIME_UNIT_MILLISECONDS));
|
||||||
end_timestamp = os_timestamp();
|
|
||||||
ms = os_resolve_timestamps(start_timestamp, end_timestamp, TIME_UNIT_MILLISECONDS);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if (run_options.debug)
|
if (run_options.debug)
|
||||||
{
|
{
|
||||||
@ -1294,179 +1227,74 @@ fn RunCommandResult run_command(Arena* arena, CStringSlice arguments, char* envp
|
|||||||
print("CreateProcessA call failed: {cstr}\n", lpMsgBuf);
|
print("CreateProcessA call failed: {cstr}\n", lpMsgBuf);
|
||||||
todo();
|
todo();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unused(start_timestamp);
|
||||||
|
unused(end_timestamp);
|
||||||
|
unused(envp);
|
||||||
#else
|
#else
|
||||||
int null_fd;
|
unused(arena);
|
||||||
|
|
||||||
if (run_options.use_null_file_descriptor)
|
|
||||||
{
|
|
||||||
null_fd = run_options.null_file_descriptor;
|
|
||||||
assert(os_file_descriptor_is_valid(null_fd));
|
|
||||||
}
|
|
||||||
else if (run_options.stdout_stream.policy == CHILD_PROCESS_STREAM_IGNORE || run_options.stderr_stream.policy == CHILD_PROCESS_STREAM_IGNORE)
|
|
||||||
{
|
|
||||||
null_fd = open("/dev/null", O_WRONLY);
|
|
||||||
assert(os_file_descriptor_is_valid(null_fd));
|
|
||||||
}
|
|
||||||
|
|
||||||
int stdout_pipe[2];
|
|
||||||
int stderr_pipe[2];
|
|
||||||
|
|
||||||
if (run_options.stdout_stream.policy == CHILD_PROCESS_STREAM_PIPE && pipe(stdout_pipe) == -1)
|
|
||||||
{
|
|
||||||
todo();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (run_options.stderr_stream.policy == CHILD_PROCESS_STREAM_PIPE && pipe(stderr_pipe) == -1)
|
|
||||||
{
|
|
||||||
todo();
|
|
||||||
}
|
|
||||||
|
|
||||||
pid_t pid = syscall_fork();
|
pid_t pid = syscall_fork();
|
||||||
|
|
||||||
if (pid == -1)
|
if (pid == -1)
|
||||||
{
|
{
|
||||||
todo();
|
todo();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (measure_time)
|
let(start_timestamp, os_timestamp());
|
||||||
{
|
|
||||||
start_timestamp = os_timestamp();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pid == 0)
|
if (pid == 0)
|
||||||
{
|
{
|
||||||
switch (run_options.stdout_stream.policy)
|
// close(pipes[0]);
|
||||||
{
|
|
||||||
case CHILD_PROCESS_STREAM_PIPE:
|
|
||||||
{
|
|
||||||
close(stdout_pipe[0]);
|
|
||||||
dup2(stdout_pipe[1], STDOUT_FILENO);
|
|
||||||
close(stdout_pipe[1]);
|
|
||||||
} break;
|
|
||||||
case CHILD_PROCESS_STREAM_IGNORE:
|
|
||||||
{
|
|
||||||
dup2(null_fd, STDOUT_FILENO);
|
|
||||||
close(null_fd);
|
|
||||||
} break;
|
|
||||||
case CHILD_PROCESS_STREAM_INHERIT:
|
|
||||||
{
|
|
||||||
} break;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (run_options.stderr_stream.policy)
|
|
||||||
{
|
|
||||||
case CHILD_PROCESS_STREAM_PIPE:
|
|
||||||
{
|
|
||||||
close(stderr_pipe[0]);
|
|
||||||
dup2(stderr_pipe[1], STDERR_FILENO);
|
|
||||||
close(stderr_pipe[1]);
|
|
||||||
} break;
|
|
||||||
case CHILD_PROCESS_STREAM_IGNORE:
|
|
||||||
{
|
|
||||||
dup2(null_fd, STDERR_FILENO);
|
|
||||||
close(null_fd);
|
|
||||||
} break;
|
|
||||||
case CHILD_PROCESS_STREAM_INHERIT:
|
|
||||||
{
|
|
||||||
} break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// fcntl(pipes[1], F_SETFD, FD_CLOEXEC);
|
// fcntl(pipes[1], F_SETFD, FD_CLOEXEC);
|
||||||
let(result, syscall_execve(arguments.pointer[0], arguments.pointer, envp));
|
let(result, syscall_execve(arguments.pointer[0], arguments.pointer, envp));
|
||||||
unused(result);
|
unused(result);
|
||||||
|
#if LINK_LIBC
|
||||||
panic("Execve failed! Error: {cstr}\n", strerror(errno));
|
panic("Execve failed! Error: {cstr}\n", strerror(errno));
|
||||||
|
#else
|
||||||
|
todo();
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (run_options.stdout_stream.policy == CHILD_PROCESS_STREAM_PIPE)
|
|
||||||
{
|
|
||||||
close(stdout_pipe[1]);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (run_options.stderr_stream.policy == CHILD_PROCESS_STREAM_PIPE)
|
|
||||||
{
|
|
||||||
close(stderr_pipe[1]);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (run_options.stdout_stream.policy == CHILD_PROCESS_STREAM_PIPE)
|
|
||||||
{
|
|
||||||
assert(run_options.stdout_stream.capacity);
|
|
||||||
ssize_t byte_count = read(stdout_pipe[0], run_options.stdout_stream.buffer, run_options.stdout_stream.capacity);
|
|
||||||
assert(byte_count >= 0);
|
|
||||||
*run_options.stdout_stream.length = byte_count;
|
|
||||||
|
|
||||||
close(stdout_pipe[0]);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (run_options.stderr_stream.policy == CHILD_PROCESS_STREAM_PIPE)
|
|
||||||
{
|
|
||||||
assert(run_options.stderr_stream.capacity);
|
|
||||||
ssize_t byte_count = read(stderr_pipe[0], run_options.stderr_stream.buffer, run_options.stderr_stream.capacity);
|
|
||||||
assert(byte_count >= 0);
|
|
||||||
*run_options.stderr_stream.length = byte_count;
|
|
||||||
|
|
||||||
close(stderr_pipe[0]);
|
|
||||||
}
|
|
||||||
|
|
||||||
int status = 0;
|
int status = 0;
|
||||||
int options = 0;
|
int options = 0;
|
||||||
pid_t waitpid_result = syscall_waitpid(pid, &status, options);
|
pid_t result = syscall_waitpid(pid, &status, options);
|
||||||
|
let(end_timestamp, os_timestamp());
|
||||||
if (measure_time)
|
int success = 0;
|
||||||
{
|
if (result == pid)
|
||||||
end_timestamp = os_timestamp();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (waitpid_result == pid)
|
|
||||||
{
|
{
|
||||||
if (run_options.debug)
|
if (run_options.debug)
|
||||||
{
|
{
|
||||||
print("{cstr} ", arguments.pointer[0]);
|
print("{cstr} ", arguments.pointer[0]);
|
||||||
|
|
||||||
|
if (WIFEXITED(status))
|
||||||
|
{
|
||||||
|
let(exit_code, WEXITSTATUS(status));
|
||||||
|
print("exited with code {u32}\n", exit_code);
|
||||||
|
}
|
||||||
|
else if (WIFSIGNALED(status))
|
||||||
|
{
|
||||||
|
let(signal_code, WTERMSIG(status));
|
||||||
|
print("was signaled: {u32}\n", signal_code);
|
||||||
|
}
|
||||||
|
else if (WIFSTOPPED(status))
|
||||||
|
{
|
||||||
|
let(stopped_code, WSTOPSIG(status));
|
||||||
|
print("was stopped: {u32}\n", stopped_code);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
print("terminated unexpectedly with status {u32}\n", status);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (WIFEXITED(status))
|
if (WIFEXITED(status))
|
||||||
{
|
{
|
||||||
let(exit_code, WEXITSTATUS(status));
|
let(exit_code, WEXITSTATUS(status));
|
||||||
result.termination_code = exit_code;
|
success = exit_code == 0;
|
||||||
result.termination_kind = PROCESS_TERMINATION_EXIT;
|
|
||||||
|
|
||||||
if (run_options.debug)
|
|
||||||
{
|
|
||||||
print("exited with code {u32}\n", exit_code);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (WIFSIGNALED(status))
|
|
||||||
{
|
|
||||||
let(signal_code, WTERMSIG(status));
|
|
||||||
result.termination_code = signal_code;
|
|
||||||
result.termination_kind = PROCESS_TERMINATION_SIGNAL;
|
|
||||||
|
|
||||||
if (run_options.debug)
|
|
||||||
{
|
|
||||||
print("was signaled: {u32}\n", signal_code);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (WIFSTOPPED(status))
|
|
||||||
{
|
|
||||||
let(stop_code, WSTOPSIG(status));
|
|
||||||
result.termination_code = stop_code;
|
|
||||||
result.termination_kind = PROCESS_TERMINATION_STOP;
|
|
||||||
|
|
||||||
if (run_options.debug)
|
|
||||||
{
|
|
||||||
print("was stopped: {u32}\n", stop_code);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
result.termination_kind = PROCESS_TERMINATION_UNKNOWN;
|
|
||||||
|
|
||||||
if (run_options.debug)
|
|
||||||
{
|
|
||||||
print("terminated unexpectedly with status {u32}\n", status);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (waitpid_result == -1)
|
else if (result == -1)
|
||||||
{
|
{
|
||||||
let(waitpid_error, errno);
|
let(waitpid_error, errno);
|
||||||
print("Error waiting for process termination: {u32}\n", waitpid_error);
|
print("Error waiting for process termination: {u32}\n", waitpid_error);
|
||||||
@ -1477,25 +1305,42 @@ fn RunCommandResult run_command(Arena* arena, CStringSlice arguments, char* envp
|
|||||||
todo();
|
todo();
|
||||||
}
|
}
|
||||||
|
|
||||||
let(success, result.termination_kind == PROCESS_TERMINATION_EXIT && result.termination_code == 0);
|
if (!success)
|
||||||
if (run_options.debug && !success)
|
|
||||||
{
|
{
|
||||||
print("{cstr} failed to run successfully!\n", arguments.pointer[0]);
|
print("Program failed to run successfully!\n");
|
||||||
|
failed_execution();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (run_options.debug)
|
if (run_options.debug)
|
||||||
{
|
{
|
||||||
ms = os_resolve_timestamps(start_timestamp, end_timestamp, TIME_UNIT_MILLISECONDS);
|
let(ms, os_resolve_timestamps(start_timestamp, end_timestamp, TIME_UNIT_MILLISECONDS));
|
||||||
u32 ticks = 0;
|
u32 ticks = 0;
|
||||||
#if LINK_LIBC == 0
|
#if LINK_LIBC == 0
|
||||||
ticks = cpu_frequency != 0;
|
ticks = cpu_frequency != 0;
|
||||||
#endif
|
#endif
|
||||||
print("Command run {cstr} in {f64} {cstr}\n", success ? "successfully" : "with errors", ms, ticks ? "ticks" : "ms");
|
print("Command run successfully in {f64} {cstr}\n", ms, ticks ? "ticks" : "ms");
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
if (!run_options.use_null_file_descriptor && os_file_descriptor_is_valid(null_fd))
|
fn u8 os_is_being_debugged()
|
||||||
|
{
|
||||||
|
u8 result = 0;
|
||||||
|
#if _WIN32
|
||||||
|
result = IsDebuggerPresent() != 0;
|
||||||
|
#else
|
||||||
|
#ifdef __APPLE__
|
||||||
|
let(request, PT_TRACE_ME);
|
||||||
|
#else
|
||||||
|
let(request, PTRACE_TRACEME);
|
||||||
|
#endif
|
||||||
|
if (ptrace(request, 0, 0, 0) == -1)
|
||||||
|
{
|
||||||
|
let(error, errno);
|
||||||
|
if (error == EPERM)
|
||||||
{
|
{
|
||||||
close(null_fd);
|
result = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@ -1617,85 +1462,3 @@ fn u8 os_library_is_valid(OSLibrary library)
|
|||||||
{
|
{
|
||||||
return library.handle != 0;
|
return library.handle != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn String file_find_in_path(Arena* arena, String file, String path_env, String extension)
|
|
||||||
{
|
|
||||||
String result = {};
|
|
||||||
assert(path_env.pointer);
|
|
||||||
|
|
||||||
String path_it = path_env;
|
|
||||||
u8 buffer[4096];
|
|
||||||
|
|
||||||
#if _WIN32
|
|
||||||
u8 env_path_separator = ';';
|
|
||||||
u8 path_separator = '\\';
|
|
||||||
#else
|
|
||||||
u8 env_path_separator = ':';
|
|
||||||
u8 path_separator = '/';
|
|
||||||
#endif
|
|
||||||
|
|
||||||
while (path_it.length)
|
|
||||||
{
|
|
||||||
let(index, string_first_ch(path_it, env_path_separator));
|
|
||||||
index = unlikely(index == STRING_NO_MATCH) ? path_it.length : index;
|
|
||||||
let(path_chunk, s_get_slice(u8, path_it, 0, index));
|
|
||||||
|
|
||||||
u64 i = 0;
|
|
||||||
|
|
||||||
memcpy(&buffer[i], path_chunk.pointer, path_chunk.length);
|
|
||||||
i += path_chunk.length;
|
|
||||||
|
|
||||||
buffer[i] = path_separator;
|
|
||||||
i += 1;
|
|
||||||
|
|
||||||
memcpy(&buffer[i], file.pointer, file.length);
|
|
||||||
i += file.length;
|
|
||||||
|
|
||||||
if (extension.length)
|
|
||||||
{
|
|
||||||
memcpy(&buffer[i], extension.pointer, extension.length);
|
|
||||||
i += extension.length;
|
|
||||||
}
|
|
||||||
|
|
||||||
buffer[i] = 0;
|
|
||||||
i += 1;
|
|
||||||
|
|
||||||
let(total_length, i - 1);
|
|
||||||
OSFileOpenFlags flags = {
|
|
||||||
.read = 1,
|
|
||||||
};
|
|
||||||
OSFilePermissions permissions = {
|
|
||||||
.readable = 1,
|
|
||||||
.writable = 1,
|
|
||||||
};
|
|
||||||
|
|
||||||
String path = { .pointer = buffer, .length = total_length };
|
|
||||||
|
|
||||||
FileDescriptor fd = os_file_open(path, flags, permissions);
|
|
||||||
|
|
||||||
if (os_file_descriptor_is_valid(fd))
|
|
||||||
{
|
|
||||||
os_file_close(fd);
|
|
||||||
result.pointer = arena_allocate(arena, u8, total_length + 1);
|
|
||||||
memcpy(result.pointer, buffer, total_length + 1);
|
|
||||||
result.length = total_length;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
String new_path = s_get_slice(u8, path_it, index + (index != path_it.length), path_it.length);
|
|
||||||
assert(new_path.length < path_env.length);
|
|
||||||
path_it = new_path;
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
fn String executable_find_in_path(Arena* arena, String executable, String path_env)
|
|
||||||
{
|
|
||||||
String extension = {};
|
|
||||||
#if _WIN32
|
|
||||||
extension = strlit(".exe");
|
|
||||||
#endif
|
|
||||||
return file_find_in_path(arena, executable, path_env, extension);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
@ -27,43 +27,9 @@ typedef enum TimeUnit
|
|||||||
TIME_UNIT_SECONDS,
|
TIME_UNIT_SECONDS,
|
||||||
} TimeUnit;
|
} TimeUnit;
|
||||||
|
|
||||||
ENUM(ProcessTerminationKind, u8,
|
|
||||||
PROCESS_TERMINATION_UNKNOWN,
|
|
||||||
PROCESS_TERMINATION_EXIT,
|
|
||||||
PROCESS_TERMINATION_SIGNAL,
|
|
||||||
PROCESS_TERMINATION_STOP,
|
|
||||||
);
|
|
||||||
|
|
||||||
STRUCT(RunCommandResult)
|
|
||||||
{
|
|
||||||
u32 termination_code;
|
|
||||||
ProcessTerminationKind termination_kind;
|
|
||||||
u8 reserved[3];
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef enum ChildProcessStreamPolicy
|
|
||||||
{
|
|
||||||
CHILD_PROCESS_STREAM_INHERIT,
|
|
||||||
CHILD_PROCESS_STREAM_PIPE,
|
|
||||||
CHILD_PROCESS_STREAM_IGNORE,
|
|
||||||
} ChildProcessStreamPolicy;
|
|
||||||
|
|
||||||
STRUCT(ChildProcessStream)
|
|
||||||
{
|
|
||||||
u8* buffer;
|
|
||||||
u32* length;
|
|
||||||
u32 capacity;
|
|
||||||
ChildProcessStreamPolicy policy;
|
|
||||||
};
|
|
||||||
|
|
||||||
STRUCT(RunCommandOptions)
|
STRUCT(RunCommandOptions)
|
||||||
{
|
{
|
||||||
ChildProcessStream stdout_stream;
|
|
||||||
ChildProcessStream stderr_stream;
|
|
||||||
FileDescriptor null_file_descriptor;
|
|
||||||
u64 use_null_file_descriptor:1;
|
|
||||||
u64 debug:1;
|
u64 debug:1;
|
||||||
u64 reserved:62;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
STRUCT(Timestamp)
|
STRUCT(Timestamp)
|
||||||
@ -100,7 +66,6 @@ STRUCT(OSReserveMapFlags)
|
|||||||
{
|
{
|
||||||
u32 priv:1;
|
u32 priv:1;
|
||||||
u32 anon:1;
|
u32 anon:1;
|
||||||
u32 populate:1;
|
|
||||||
u32 noreserve:1;
|
u32 noreserve:1;
|
||||||
u32 reserved:29;
|
u32 reserved:29;
|
||||||
};
|
};
|
||||||
@ -134,7 +99,7 @@ global_variable u64 default_size = GB(4);
|
|||||||
|
|
||||||
fn void vprint(const char* format, va_list args);
|
fn void vprint(const char* format, va_list args);
|
||||||
fn void print(const char* format, ...);
|
fn void print(const char* format, ...);
|
||||||
fn RunCommandResult run_command(Arena* arena, CStringSlice arguments, char* envp[], RunCommandOptions options);
|
fn void run_command(Arena* arena, CStringSlice arguments, char* envp[], RunCommandOptions options);
|
||||||
fn String file_read(Arena* arena, String path);
|
fn String file_read(Arena* arena, String path);
|
||||||
fn void file_write(FileWriteOptions options);
|
fn void file_write(FileWriteOptions options);
|
||||||
|
|
||||||
|
@ -31,7 +31,7 @@ fn u8 rendering_backend_is_valid(RenderingBackend rendering_backend)
|
|||||||
{
|
{
|
||||||
#ifdef __linux__
|
#ifdef __linux__
|
||||||
valid = rendering_backend == RENDERING_BACKEND_VULKAN;
|
valid = rendering_backend == RENDERING_BACKEND_VULKAN;
|
||||||
#elif defined(__APPLE__)
|
#elif __APPLE__
|
||||||
valid = rendering_backend == RENDERING_BACKEND_METAL || rendering_backend == RENDERING_BACKEND_VULKAN;
|
valid = rendering_backend == RENDERING_BACKEND_METAL || rendering_backend == RENDERING_BACKEND_VULKAN;
|
||||||
#elif _WIN32
|
#elif _WIN32
|
||||||
valid = rendering_backend == RENDERING_BACKEND_DIRECTX12 || rendering_backend == RENDERING_BACKEND_VULKAN;
|
valid = rendering_backend == RENDERING_BACKEND_DIRECTX12 || rendering_backend == RENDERING_BACKEND_VULKAN;
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
#pragma once
|
#include <std/virtual_buffer.h>
|
||||||
|
#include <std/os.h>
|
||||||
|
|
||||||
fn void vb_generic_ensure_capacity(VirtualBuffer(u8)* vb, u32 item_size, u32 item_count)
|
fn void vb_generic_ensure_capacity(VirtualBuffer(u8)* vb, u32 item_size, u32 item_count)
|
||||||
{
|
{
|
||||||
@ -12,8 +13,8 @@ fn void vb_generic_ensure_capacity(VirtualBuffer(u8)* vb, u32 item_size, u32 ite
|
|||||||
vb->pointer = os_reserve(0, item_size * UINT32_MAX, (OSReserveProtectionFlags) {}, (OSReserveMapFlags) { .priv = 1, .anon = 1, .noreserve = 1 });
|
vb->pointer = os_reserve(0, item_size * UINT32_MAX, (OSReserveProtectionFlags) {}, (OSReserveMapFlags) { .priv = 1, .anon = 1, .noreserve = 1 });
|
||||||
}
|
}
|
||||||
|
|
||||||
let_cast(u32, old_page_capacity, align_forward_u64(old_capacity * item_size, minimum_granularity));
|
let_cast(u32, old_page_capacity, align_forward(old_capacity * item_size, minimum_granularity));
|
||||||
let_cast(u32, new_page_capacity, align_forward_u64(wanted_capacity * item_size, minimum_granularity));
|
let_cast(u32, new_page_capacity, align_forward(wanted_capacity * item_size, minimum_granularity));
|
||||||
|
|
||||||
let(commit_size, new_page_capacity - old_page_capacity);
|
let(commit_size, new_page_capacity - old_page_capacity);
|
||||||
void* commit_pointer = vb->pointer + old_page_capacity;
|
void* commit_pointer = vb->pointer + old_page_capacity;
|
||||||
@ -48,13 +49,11 @@ fn u8* vb_append_bytes(VirtualBuffer(u8*) vb, Slice(u8) bytes)
|
|||||||
return pointer;
|
return pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn u32 vb_copy_string(VirtualBuffer(u8)* buffer, String string)
|
fn void vb_copy_string(VirtualBuffer(u8)* buffer, String string)
|
||||||
{
|
{
|
||||||
let(offset, buffer->length);
|
|
||||||
let_cast(u32, length, string.length);
|
let_cast(u32, length, string.length);
|
||||||
let(pointer, vb_add(buffer, length));
|
let(pointer, vb_add(buffer, length));
|
||||||
memcpy(pointer, string.pointer, length);
|
memcpy(pointer, string.pointer, length);
|
||||||
return offset;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn u64 vb_copy_string_zero_terminated(VirtualBuffer(u8)* buffer, String string)
|
fn u64 vb_copy_string_zero_terminated(VirtualBuffer(u8)* buffer, String string)
|
||||||
@ -66,23 +65,3 @@ fn u64 vb_copy_string_zero_terminated(VirtualBuffer(u8)* buffer, String string)
|
|||||||
|
|
||||||
return string.length;
|
return string.length;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn void vb_copy_byte_repeatedly(VirtualBuffer(u8)* buffer, u8 byte, u32 times)
|
|
||||||
{
|
|
||||||
u8* ptr = vb_generic_add(buffer, 1, times);
|
|
||||||
memset(ptr, byte, times);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn u64 vb_format(VirtualBuffer(u8)* vb, const char* format, ...)
|
|
||||||
{
|
|
||||||
u8 buffer[4096];
|
|
||||||
va_list args;
|
|
||||||
va_start(args, format);
|
|
||||||
let(result, format_string_va((String)array_to_slice(buffer), format, args));
|
|
||||||
va_end(args);
|
|
||||||
|
|
||||||
assert(result.length <= array_length(buffer));
|
|
||||||
vb_copy_string(vb, result);
|
|
||||||
|
|
||||||
return result.length;
|
|
||||||
}
|
|
||||||
|
@ -49,6 +49,5 @@ fn void vb_generic_ensure_capacity(VirtualBuffer(u8)* vb, u32 item_size, u32 ite
|
|||||||
fn u8* vb_generic_add_assume_capacity(VirtualBuffer(u8)* vb, u32 item_size, u32 item_count);
|
fn u8* vb_generic_add_assume_capacity(VirtualBuffer(u8)* vb, u32 item_size, u32 item_count);
|
||||||
fn u8* vb_generic_add(VirtualBuffer(u8)* vb, u32 item_size, u32 item_count);
|
fn u8* vb_generic_add(VirtualBuffer(u8)* vb, u32 item_size, u32 item_count);
|
||||||
fn u8* vb_append_bytes(VirtualBuffer(u8*) vb, Slice(u8) bytes);
|
fn u8* vb_append_bytes(VirtualBuffer(u8*) vb, Slice(u8) bytes);
|
||||||
fn u32 vb_copy_string(VirtualBuffer(u8)* buffer, String string);
|
fn void vb_copy_string(VirtualBuffer(u8)* buffer, String string);
|
||||||
fn u64 vb_copy_string_zero_terminated(VirtualBuffer(u8)* buffer, String string);
|
fn u64 vb_copy_string_zero_terminated(VirtualBuffer(u8)* buffer, String string);
|
||||||
fn u64 vb_format(VirtualBuffer(u8)* vb, const char* format, ...);
|
|
||||||
|
@ -312,6 +312,7 @@ fn void buffer_copy_to_host(VulkanBuffer buffer, Slice(HostBufferCopy) regions)
|
|||||||
let(region, regions.pointer[i]);
|
let(region, regions.pointer[i]);
|
||||||
let(destination, buffer_pointer + region.destination_offset);
|
let(destination, buffer_pointer + region.destination_offset);
|
||||||
assert(destination + region.source.length <= (u8*)buffer.address + buffer.size);
|
assert(destination + region.source.length <= (u8*)buffer.address + buffer.size);
|
||||||
|
#define USE_MEMCPY 1
|
||||||
#if USE_MEMCPY
|
#if USE_MEMCPY
|
||||||
memcpy(destination, region.source.pointer, region.source.length);
|
memcpy(destination, region.source.pointer, region.source.length);
|
||||||
#else
|
#else
|
||||||
|
@ -22,10 +22,10 @@ mkdir %BUILD_DIR% > NUL 2>&1
|
|||||||
set BUILD_OUT=cache\build.exe
|
set BUILD_OUT=cache\build.exe
|
||||||
set BB_ERROR_ON_WARNINGS=%BB_CI%
|
set BB_ERROR_ON_WARNINGS=%BB_CI%
|
||||||
|
|
||||||
REM if "%BB_CI%" == "0" (
|
if "%BB_CI%" == "0" (
|
||||||
REM %VK_SDK_PATH%\Bin\glslangValidator.exe -V bootstrap\std\shaders\rect.vert -o cache\rect.vert.spv --quiet || exit /b 1
|
%VK_SDK_PATH%\Bin\glslangValidator.exe -V bootstrap\std\shaders\rect.vert -o cache\rect.vert.spv --quiet || exit /b 1
|
||||||
REM %VK_SDK_PATH%\Bin\glslangValidator.exe -V bootstrap\std\shaders\rect.frag -o cache\rect.frag.spv --quiet || exit /b 1
|
%VK_SDK_PATH%\Bin\glslangValidator.exe -V bootstrap\std\shaders\rect.frag -o cache\rect.frag.spv --quiet || exit /b 1
|
||||||
REM )
|
)
|
||||||
|
|
||||||
|
|
||||||
cl /Zi /Y- /Gm- /std:clatest /diagnostics:caret -FC /nologo build.c /Fd%BUILD_DIR%\ /Fo%BUILD_DIR%\ /Fe%BUILD_OUT% -Ibootstrap -DBB_TIMETRACE=0 -DBB_BUILD_TYPE=\"%BB_BUILD_TYPE%\" -DBB_CI=%BB_CI% -DBB_ERROR_ON_WARNINGS=%BB_ERROR_ON_WARNINGS% -DBB_ERROR_LIMIT=%BB_ERROR_LIMIT% /link /INCREMENTAL:NO || exit /b 1
|
cl /Zi /Y- /Gm- /std:clatest /diagnostics:caret -FC /nologo build.c /Fd%BUILD_DIR%\ /Fo%BUILD_DIR%\ /Fe%BUILD_OUT% -Ibootstrap -DBB_TIMETRACE=0 -DBB_BUILD_TYPE=\"%BB_BUILD_TYPE%\" -DBB_CI=%BB_CI% -DBB_ERROR_ON_WARNINGS=%BB_ERROR_ON_WARNINGS% -DBB_ERROR_LIMIT=%BB_ERROR_LIMIT% /link /INCREMENTAL:NO || exit /b 1
|
||||||
|
13
build.sh
13
build.sh
@ -1,8 +1,6 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
set -eu
|
set -eu
|
||||||
|
|
||||||
MY_CWD=$PWD
|
|
||||||
|
|
||||||
if [[ -z "${BB_CI-}" ]]; then
|
if [[ -z "${BB_CI-}" ]]; then
|
||||||
BB_CI=0
|
BB_CI=0
|
||||||
fi
|
fi
|
||||||
@ -19,19 +17,10 @@ if [[ -z "${BB_ERROR_LIMIT-}" ]]; then
|
|||||||
BB_ERROR_LIMIT=$((1 - BB_CI))
|
BB_ERROR_LIMIT=$((1 - BB_CI))
|
||||||
fi
|
fi
|
||||||
|
|
||||||
BB_COMPILE_SHADERS=0
|
|
||||||
|
|
||||||
BUILD_DIR=cache
|
BUILD_DIR=cache
|
||||||
LARGE_ASSET_BASE_URL=https://github.com/birth-software/bloat-buster/releases/download/large-assets
|
|
||||||
mkdir -p $BUILD_DIR
|
mkdir -p $BUILD_DIR
|
||||||
|
|
||||||
if [[ ! -f "$BUILD_DIR/large_assembly.s" ]]; then
|
if [[ "${BB_CI}" == "0" ]]; then
|
||||||
cd $BUILD_DIR
|
|
||||||
wget $LARGE_ASSET_BASE_URL/large_assembly.s -o large_assembly.s
|
|
||||||
cd $MY_CWD
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [[ "${BB_COMPILE_SHADERS}" == "1" ]]; then
|
|
||||||
glslangValidator -V bootstrap/std/shaders/rect.vert -o $BUILD_DIR/rect.vert.spv --quiet
|
glslangValidator -V bootstrap/std/shaders/rect.vert -o $BUILD_DIR/rect.vert.spv --quiet
|
||||||
glslangValidator -V bootstrap/std/shaders/rect.frag -o $BUILD_DIR/rect.frag.spv --quiet
|
glslangValidator -V bootstrap/std/shaders/rect.frag -o $BUILD_DIR/rect.frag.spv --quiet
|
||||||
fi
|
fi
|
||||||
|
363
build.zig
363
build.zig
@ -1,363 +0,0 @@
|
|||||||
const std = @import("std");
|
|
||||||
const builtin = @import("builtin");
|
|
||||||
|
|
||||||
fn run_process_and_capture_stdout(b: *std.Build, argv: []const []const u8) ![]const u8 {
|
|
||||||
const result = std.process.Child.run(.{
|
|
||||||
.allocator = b.allocator,
|
|
||||||
.argv = argv,
|
|
||||||
}) catch |err| return err;
|
|
||||||
switch (result.term) {
|
|
||||||
.Exited => |exit_code| {
|
|
||||||
if (exit_code != 0) {
|
|
||||||
return error.SpawnError;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
else => return error.SpawnError,
|
|
||||||
}
|
|
||||||
|
|
||||||
return result.stdout;
|
|
||||||
}
|
|
||||||
|
|
||||||
fn file_find_in_path(allocator: std.mem.Allocator, file_name: []const u8, path_env: []const u8, extension: []const u8) ?[]const u8 {
|
|
||||||
const path_env_separator = switch (builtin.os.tag) {
|
|
||||||
.windows => ';',
|
|
||||||
else => ':',
|
|
||||||
};
|
|
||||||
const path_separator = switch (builtin.os.tag) {
|
|
||||||
.windows => '\\',
|
|
||||||
else => '/',
|
|
||||||
};
|
|
||||||
var env_it = std.mem.splitScalar(u8, path_env, path_env_separator);
|
|
||||||
const result: ?[]const u8 = while (env_it.next()) |dir_path| {
|
|
||||||
const full_path = std.mem.concatWithSentinel(allocator, u8, &.{ dir_path, &[1]u8{path_separator}, file_name, extension }, 0) catch unreachable;
|
|
||||||
const file = std.fs.cwd().openFile(full_path, .{}) catch continue;
|
|
||||||
file.close();
|
|
||||||
break full_path;
|
|
||||||
} else null;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
fn executable_find_in_path(allocator: std.mem.Allocator, file_name: []const u8, path_env: []const u8) ?[]const u8 {
|
|
||||||
const extension = switch (builtin.os.tag) {
|
|
||||||
.windows => ".exe",
|
|
||||||
else => "",
|
|
||||||
};
|
|
||||||
return file_find_in_path(allocator, file_name, path_env, extension);
|
|
||||||
}
|
|
||||||
|
|
||||||
const CmakeBuildType = enum {
|
|
||||||
Debug,
|
|
||||||
RelWithDebInfo,
|
|
||||||
MinSizeRel,
|
|
||||||
Release,
|
|
||||||
|
|
||||||
fn from_zig_build_type(o: std.builtin.OptimizeMode) CmakeBuildType {
|
|
||||||
return switch (o) {
|
|
||||||
.Debug => .Debug,
|
|
||||||
.ReleaseSafe => .RelWithDebInfo,
|
|
||||||
.ReleaseSmall => .MinSizeRel,
|
|
||||||
.ReleaseFast => .Release,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
var system_llvm: bool = undefined;
|
|
||||||
var target: std.Build.ResolvedTarget = undefined;
|
|
||||||
var optimize: std.builtin.OptimizeMode = undefined;
|
|
||||||
var env: std.process.EnvMap = undefined;
|
|
||||||
|
|
||||||
const BuildMode = enum {
|
|
||||||
debug_none,
|
|
||||||
debug_fast,
|
|
||||||
debug_size,
|
|
||||||
soft_optimize,
|
|
||||||
optimize_for_speed,
|
|
||||||
optimize_for_size,
|
|
||||||
aggressively_optimize_for_speed,
|
|
||||||
aggressively_optimize_for_size,
|
|
||||||
};
|
|
||||||
|
|
||||||
pub fn build(b: *std.Build) !void {
|
|
||||||
env = try std.process.getEnvMap(b.allocator);
|
|
||||||
target = b.standardTargetOptions(.{});
|
|
||||||
optimize = b.standardOptimizeOption(.{});
|
|
||||||
system_llvm = b.option(bool, "system_llvm", "Link against system LLVM libraries") orelse false;
|
|
||||||
|
|
||||||
const c_abi = b.addObject(.{
|
|
||||||
.name = "c_abi",
|
|
||||||
.link_libc = true,
|
|
||||||
.root_module = b.createModule(.{
|
|
||||||
.target = target,
|
|
||||||
.optimize = optimize,
|
|
||||||
.link_libc = true,
|
|
||||||
.sanitize_c = false,
|
|
||||||
}),
|
|
||||||
.optimize = optimize,
|
|
||||||
});
|
|
||||||
c_abi.addCSourceFiles(.{
|
|
||||||
.files = &.{"tests/c_abi.c"},
|
|
||||||
.flags = &.{"-g"},
|
|
||||||
});
|
|
||||||
|
|
||||||
const path = env.get("PATH") orelse unreachable;
|
|
||||||
|
|
||||||
const stack_trace_library = b.addObject(.{
|
|
||||||
.name = "stack_trace",
|
|
||||||
.root_module = b.createModule(.{
|
|
||||||
.target = target,
|
|
||||||
.optimize = .ReleaseFast,
|
|
||||||
.root_source_file = b.path("src/stack_trace.zig"),
|
|
||||||
.link_libc = true,
|
|
||||||
}),
|
|
||||||
});
|
|
||||||
|
|
||||||
const exe_mod = b.createModule(.{
|
|
||||||
.root_source_file = b.path("src/main.zig"),
|
|
||||||
.target = target,
|
|
||||||
.optimize = optimize,
|
|
||||||
.link_libc = true,
|
|
||||||
.sanitize_c = false,
|
|
||||||
});
|
|
||||||
const configuration = b.addOptions();
|
|
||||||
configuration.addOptionPath("c_abi_object_path", c_abi.getEmittedBin());
|
|
||||||
exe_mod.addOptions("configuration", configuration);
|
|
||||||
|
|
||||||
const exe = b.addExecutable(.{
|
|
||||||
.name = "bloat-buster",
|
|
||||||
.root_module = exe_mod,
|
|
||||||
.link_libc = true,
|
|
||||||
});
|
|
||||||
exe.addObject(stack_trace_library);
|
|
||||||
var llvm_libs = std.ArrayList([]const u8).init(b.allocator);
|
|
||||||
var flags = std.ArrayList([]const u8).init(b.allocator);
|
|
||||||
const llvm_config_path = if (b.option([]const u8, "llvm_prefix", "LLVM prefix")) |llvm_prefix| blk: {
|
|
||||||
const full_path = try std.mem.concat(b.allocator, u8, &.{ llvm_prefix, "/bin/llvm-config" });
|
|
||||||
const f = std.fs.cwd().openFile(full_path, .{}) catch return error.llvm_not_found;
|
|
||||||
f.close();
|
|
||||||
break :blk full_path;
|
|
||||||
} else if (system_llvm) executable_find_in_path(b.allocator, "llvm-config", path) orelse return error.llvm_not_found else blk: {
|
|
||||||
const home_env = switch (@import("builtin").os.tag) {
|
|
||||||
.windows => "USERPROFILE",
|
|
||||||
else => "HOME",
|
|
||||||
};
|
|
||||||
const home_path = env.get(home_env) orelse unreachable;
|
|
||||||
const is_ci = std.mem.eql(u8, (env.get("BB_CI") orelse "0"), "1");
|
|
||||||
const download_dir = try std.mem.concat(b.allocator, u8, &.{ home_path, "/Downloads" });
|
|
||||||
std.fs.makeDirAbsolute(download_dir) catch {};
|
|
||||||
const cmake_build_type = if (is_ci) CmakeBuildType.from_zig_build_type(optimize) else CmakeBuildType.Release;
|
|
||||||
const version_string = "20.1.2";
|
|
||||||
const llvm_base = try std.mem.concat(b.allocator, u8, &.{ "llvm_", version_string, "_", @tagName(target.result.cpu.arch), "-", @tagName(target.result.os.tag), "-", @tagName(cmake_build_type) });
|
|
||||||
const base = try std.mem.concat(b.allocator, u8, &.{ download_dir, "/", llvm_base });
|
|
||||||
const full_path = try std.mem.concat(b.allocator, u8, &.{ base, "/bin/llvm-config" });
|
|
||||||
|
|
||||||
const f = std.fs.cwd().openFile(full_path, .{}) catch {
|
|
||||||
const url = try std.mem.concat(b.allocator, u8, &.{ "https://github.com/birth-software/llvm/releases/download/v", version_string, "/", llvm_base, ".7z" });
|
|
||||||
var result = try std.process.Child.run(.{
|
|
||||||
.allocator = b.allocator,
|
|
||||||
.argv = &.{ "wget", "-P", download_dir, url },
|
|
||||||
.max_output_bytes = std.math.maxInt(usize),
|
|
||||||
});
|
|
||||||
var success = false;
|
|
||||||
switch (result.term) {
|
|
||||||
.Exited => |exit_code| {
|
|
||||||
success = exit_code == 0;
|
|
||||||
},
|
|
||||||
else => {},
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!success) {
|
|
||||||
std.debug.print("{s}\n{s}\n", .{ result.stdout, result.stderr });
|
|
||||||
}
|
|
||||||
|
|
||||||
if (success) {
|
|
||||||
const file_7z = try std.mem.concat(b.allocator, u8, &.{ base, ".7z" });
|
|
||||||
result = try std.process.Child.run(.{
|
|
||||||
.allocator = b.allocator,
|
|
||||||
.argv = &.{ "7z", "x", try std.mem.concat(b.allocator, u8, &.{ "-o", download_dir }), file_7z },
|
|
||||||
.max_output_bytes = std.math.maxInt(usize),
|
|
||||||
});
|
|
||||||
success = false;
|
|
||||||
switch (result.term) {
|
|
||||||
.Exited => |exit_code| {
|
|
||||||
success = exit_code == 0;
|
|
||||||
},
|
|
||||||
else => {},
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!success) {
|
|
||||||
std.debug.print("{s}\n{s}\n", .{ result.stdout, result.stderr });
|
|
||||||
}
|
|
||||||
|
|
||||||
break :blk full_path;
|
|
||||||
}
|
|
||||||
|
|
||||||
return error.llvm_not_found;
|
|
||||||
};
|
|
||||||
|
|
||||||
f.close();
|
|
||||||
break :blk full_path;
|
|
||||||
};
|
|
||||||
const llvm_components_result = try run_process_and_capture_stdout(b, &.{ llvm_config_path, "--components" });
|
|
||||||
var it = std.mem.splitScalar(u8, llvm_components_result, ' ');
|
|
||||||
{
|
|
||||||
var args = std.ArrayList([]const u8).init(b.allocator);
|
|
||||||
try args.append(llvm_config_path);
|
|
||||||
try args.append("--libs");
|
|
||||||
while (it.next()) |component| {
|
|
||||||
try args.append(std.mem.trimRight(u8, component, "\n"));
|
|
||||||
}
|
|
||||||
const llvm_libs_result = try run_process_and_capture_stdout(b, args.items);
|
|
||||||
it = std.mem.splitScalar(u8, llvm_libs_result, ' ');
|
|
||||||
}
|
|
||||||
|
|
||||||
while (it.next()) |lib| {
|
|
||||||
const llvm_lib = std.mem.trimLeft(u8, std.mem.trimRight(u8, lib, "\n"), "-l");
|
|
||||||
try llvm_libs.append(llvm_lib);
|
|
||||||
}
|
|
||||||
|
|
||||||
const llvm_cxx_flags_result = try run_process_and_capture_stdout(b, &.{ llvm_config_path, "--cxxflags" });
|
|
||||||
it = std.mem.splitScalar(u8, llvm_cxx_flags_result, ' ');
|
|
||||||
while (it.next()) |flag| {
|
|
||||||
const llvm_cxx_flag = std.mem.trimRight(u8, flag, "\n");
|
|
||||||
try flags.append(llvm_cxx_flag);
|
|
||||||
}
|
|
||||||
|
|
||||||
const llvm_lib_dir = std.mem.trimRight(u8, try run_process_and_capture_stdout(b, &.{ llvm_config_path, "--libdir" }), "\n");
|
|
||||||
|
|
||||||
if (optimize != .ReleaseSmall) {
|
|
||||||
try flags.append("-g");
|
|
||||||
}
|
|
||||||
|
|
||||||
try flags.append("-fno-rtti");
|
|
||||||
|
|
||||||
exe.addLibraryPath(.{ .cwd_relative = llvm_lib_dir });
|
|
||||||
|
|
||||||
const a = std.fs.cwd().openDir("/usr/lib/x86_64-linux-gnu/", .{});
|
|
||||||
if (a) |_| {
|
|
||||||
var dir = a catch unreachable;
|
|
||||||
dir.close();
|
|
||||||
exe.addLibraryPath(.{ .cwd_relative = "/usr/lib/x86_64-linux-gnu/" });
|
|
||||||
} else |err| {
|
|
||||||
err catch {};
|
|
||||||
}
|
|
||||||
|
|
||||||
exe.addCSourceFiles(.{
|
|
||||||
.files = &.{"src/llvm.cpp"},
|
|
||||||
.flags = flags.items,
|
|
||||||
});
|
|
||||||
|
|
||||||
var dir = try std.fs.cwd().openDir("/usr/include/c++", .{
|
|
||||||
.iterate = true,
|
|
||||||
});
|
|
||||||
var iterator = dir.iterate();
|
|
||||||
const gcc_version = while (try iterator.next()) |entry| {
|
|
||||||
if (entry.kind == .directory) {
|
|
||||||
break entry.name;
|
|
||||||
}
|
|
||||||
} else return error.include_cpp_dir_not_found;
|
|
||||||
dir.close();
|
|
||||||
const general_cpp_include_dir = try std.mem.concat(b.allocator, u8, &.{ "/usr/include/c++/", gcc_version });
|
|
||||||
exe.addIncludePath(.{ .cwd_relative = general_cpp_include_dir });
|
|
||||||
|
|
||||||
{
|
|
||||||
const arch_cpp_include_dir = try std.mem.concat(b.allocator, u8, &.{ general_cpp_include_dir, "/x86_64-pc-linux-gnu" });
|
|
||||||
const d2 = std.fs.cwd().openDir(arch_cpp_include_dir, .{});
|
|
||||||
if (d2) |_| {
|
|
||||||
var d = d2 catch unreachable;
|
|
||||||
d.close();
|
|
||||||
exe.addIncludePath(.{ .cwd_relative = arch_cpp_include_dir });
|
|
||||||
} else |err| err catch {};
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
const arch_cpp_include_dir = try std.mem.concat(b.allocator, u8, &.{ "/usr/include/x86_64-linux-gnu/c++/", gcc_version });
|
|
||||||
const d2 = std.fs.cwd().openDir(arch_cpp_include_dir, .{});
|
|
||||||
if (d2) |_| {
|
|
||||||
var d = d2 catch unreachable;
|
|
||||||
d.close();
|
|
||||||
exe.addIncludePath(.{ .cwd_relative = arch_cpp_include_dir });
|
|
||||||
} else |err| err catch {};
|
|
||||||
}
|
|
||||||
|
|
||||||
var found_libcpp = false;
|
|
||||||
|
|
||||||
if (std.fs.cwd().openFile("/usr/lib/libstdc++.so.6", .{})) |file| {
|
|
||||||
file.close();
|
|
||||||
found_libcpp = true;
|
|
||||||
exe.addObjectFile(.{ .cwd_relative = "/usr/lib/libstdc++.so.6" });
|
|
||||||
} else |err| {
|
|
||||||
err catch {};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (std.fs.cwd().openFile("/usr/lib/x86_64-linux-gnu/libstdc++.so.6", .{})) |file| {
|
|
||||||
file.close();
|
|
||||||
found_libcpp = true;
|
|
||||||
exe.addObjectFile(.{ .cwd_relative = "/usr/lib/x86_64-linux-gnu/libstdc++.so.6" });
|
|
||||||
} else |err| {
|
|
||||||
err catch {};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!found_libcpp) {
|
|
||||||
return error.libcpp_not_found;
|
|
||||||
}
|
|
||||||
|
|
||||||
const needed_libraries: []const []const u8 = &.{ "unwind", "z", "zstd" };
|
|
||||||
for (needed_libraries) |lib| {
|
|
||||||
exe.linkSystemLibrary(lib);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (llvm_libs.items) |lib| {
|
|
||||||
exe.linkSystemLibrary(lib);
|
|
||||||
}
|
|
||||||
|
|
||||||
const lld_libs: []const []const u8 = &.{ "lldCommon", "lldCOFF", "lldELF", "lldMachO", "lldMinGW", "lldWasm" };
|
|
||||||
for (lld_libs) |lib| {
|
|
||||||
exe.linkSystemLibrary(lib);
|
|
||||||
}
|
|
||||||
|
|
||||||
b.installArtifact(exe);
|
|
||||||
|
|
||||||
for ([_]bool{ false, true }) |is_test| {
|
|
||||||
const run_step_name = switch (is_test) {
|
|
||||||
true => "test",
|
|
||||||
false => "run",
|
|
||||||
};
|
|
||||||
|
|
||||||
const debug_step_name = switch (is_test) {
|
|
||||||
true => "debug_test",
|
|
||||||
false => "debug",
|
|
||||||
};
|
|
||||||
|
|
||||||
const command = b.addRunArtifact(exe);
|
|
||||||
command.step.dependOn(b.getInstallStep());
|
|
||||||
|
|
||||||
if (is_test) {
|
|
||||||
command.addArg("test");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (b.args) |args| {
|
|
||||||
command.addArgs(args);
|
|
||||||
}
|
|
||||||
|
|
||||||
const run_step = b.step(run_step_name, "");
|
|
||||||
run_step.dependOn(&command.step);
|
|
||||||
|
|
||||||
const debug_command = std.Build.Step.Run.create(b, b.fmt("{s} {s}", .{ debug_step_name, exe.name }));
|
|
||||||
debug_command.addArg("gdb");
|
|
||||||
debug_command.addArg("-ex");
|
|
||||||
debug_command.addArg("r");
|
|
||||||
debug_command.addArg("--args");
|
|
||||||
debug_command.addArtifactArg(exe);
|
|
||||||
|
|
||||||
if (is_test) {
|
|
||||||
debug_command.addArg("test");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (b.args) |args| {
|
|
||||||
debug_command.addArgs(args);
|
|
||||||
}
|
|
||||||
|
|
||||||
const debug_step = b.step(debug_step_name, "");
|
|
||||||
debug_step.dependOn(&debug_command.step);
|
|
||||||
}
|
|
||||||
}
|
|
1865
src/LLVM.zig
1865
src/LLVM.zig
File diff suppressed because it is too large
Load Diff
8290
src/bootstrap.zig
8290
src/bootstrap.zig
File diff suppressed because it is too large
Load Diff
261
src/compiler.bbb
261
src/compiler.bbb
@ -1,261 +0,0 @@
|
|||||||
[extern] memcmp = fn [cc(c)] (a: &u8, b: &u8, byte_count: u64) s32;
|
|
||||||
|
|
||||||
string_no_match = #integer_max(u64);
|
|
||||||
|
|
||||||
c_string_length = fn (c_string: &u8) u64
|
|
||||||
{
|
|
||||||
>it = c_string;
|
|
||||||
|
|
||||||
while (it.&)
|
|
||||||
{
|
|
||||||
it = it + 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return #int_from_pointer(it) - #int_from_pointer(c_string);
|
|
||||||
}
|
|
||||||
|
|
||||||
c_string_to_slice = fn (c_string: &u8) []u8
|
|
||||||
{
|
|
||||||
>length = c_string_length(c_string);
|
|
||||||
return c_string[0..length];
|
|
||||||
}
|
|
||||||
|
|
||||||
string_equal = fn(a: []u8, b: []u8) u1
|
|
||||||
{
|
|
||||||
>result: #ReturnType = 0;
|
|
||||||
|
|
||||||
if (a.length == b.length)
|
|
||||||
{
|
|
||||||
result = memcmp(a.pointer, b.pointer, a.length) == 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
string_last_character = fn(string: []u8, character: u8) u64
|
|
||||||
{
|
|
||||||
>i = string.length;
|
|
||||||
|
|
||||||
while (i > 0)
|
|
||||||
{
|
|
||||||
i -= 1;
|
|
||||||
|
|
||||||
if (string[i] == character)
|
|
||||||
{
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return string_no_match;
|
|
||||||
}
|
|
||||||
|
|
||||||
OS_Linux_PROT = bits u32
|
|
||||||
{
|
|
||||||
read: u1,
|
|
||||||
write: u1,
|
|
||||||
execute: u1,
|
|
||||||
sem: u1,
|
|
||||||
_: u28,
|
|
||||||
}
|
|
||||||
|
|
||||||
OS_Linux_MAP_Type = enum u4
|
|
||||||
{
|
|
||||||
shared = 0x1,
|
|
||||||
private = 0x2,
|
|
||||||
shared_validate = 0x3,
|
|
||||||
}
|
|
||||||
|
|
||||||
OS_Linux_MAP = bits u32
|
|
||||||
{
|
|
||||||
type: OS_Linux_MAP_Type,
|
|
||||||
fixed: u1,
|
|
||||||
anonymous: u1,
|
|
||||||
bit_32: u1,
|
|
||||||
_: u1,
|
|
||||||
grows_down: u1,
|
|
||||||
_: u2,
|
|
||||||
deny_write: u1,
|
|
||||||
executable: u1,
|
|
||||||
locked: u1,
|
|
||||||
no_reserve: u1,
|
|
||||||
populate: u1,
|
|
||||||
non_block: u1,
|
|
||||||
stack: u1,
|
|
||||||
huge_tlb: u1,
|
|
||||||
sync: u1,
|
|
||||||
fixed_noreplace: u1,
|
|
||||||
_: u5,
|
|
||||||
uninitialized: u1,
|
|
||||||
_: u5,
|
|
||||||
}
|
|
||||||
|
|
||||||
[extern] mmap = fn [cc(c)] (address: u64, size: u64, protection: OS_Linux_PROT, map: OS_Linux_MAP, file_descriptor: s32, offset: s64) &u8;
|
|
||||||
[extern] mprotect = fn [cc(c)] (address: u64, size: u64, protection: OS_Linux_PROT) s32;
|
|
||||||
|
|
||||||
OS_ProtectionFlags = bits
|
|
||||||
{
|
|
||||||
read: u1,
|
|
||||||
write: u1,
|
|
||||||
execute: u1,
|
|
||||||
}
|
|
||||||
|
|
||||||
OS_MapFlags = bits
|
|
||||||
{
|
|
||||||
private: u1,
|
|
||||||
anonymous: u1,
|
|
||||||
no_reserve: u1,
|
|
||||||
populate: u1,
|
|
||||||
}
|
|
||||||
|
|
||||||
os_linux_protection_flags = fn(map_flags: OS_ProtectionFlags) OS_Linux_PROT
|
|
||||||
{
|
|
||||||
return {
|
|
||||||
.read = map_flags.read,
|
|
||||||
.write = map_flags.write,
|
|
||||||
.execute = map_flags.execute,
|
|
||||||
zero,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
os_linux_map_flags = fn(map_flags: OS_MapFlags) OS_Linux_MAP
|
|
||||||
{
|
|
||||||
return {
|
|
||||||
.type = #select(map_flags.private, .private, .shared),
|
|
||||||
.anonymous = map_flags.anonymous,
|
|
||||||
.no_reserve = map_flags.no_reserve,
|
|
||||||
.populate = map_flags.populate,
|
|
||||||
zero,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
os_reserve = fn (base: u64, size: u64, protection: OS_ProtectionFlags, map: OS_MapFlags) &u8
|
|
||||||
{
|
|
||||||
>protection_flags = os_linux_protection_flags(protection);
|
|
||||||
>map_flags = os_linux_map_flags(map);
|
|
||||||
>address = mmap(base, size, protection_flags, map_flags, -1, 0);
|
|
||||||
if (#int_from_pointer(address) == #integer_max(u64))
|
|
||||||
{
|
|
||||||
unreachable;
|
|
||||||
}
|
|
||||||
|
|
||||||
return address;
|
|
||||||
}
|
|
||||||
|
|
||||||
os_commit = fn (address: u64, size: u64, protection: OS_ProtectionFlags) void
|
|
||||||
{
|
|
||||||
>protection_flags = os_linux_protection_flags(protection);
|
|
||||||
>result = mprotect(address, size, protection_flags);
|
|
||||||
if (result != 0)
|
|
||||||
{
|
|
||||||
unreachable;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Arena = struct
|
|
||||||
{
|
|
||||||
reserved_size: u64,
|
|
||||||
position: u64,
|
|
||||||
os_position: u64,
|
|
||||||
granularity: u64,
|
|
||||||
reserved: [32]u8,
|
|
||||||
}
|
|
||||||
|
|
||||||
minimum_position: u64 = #byte_size(Arena);
|
|
||||||
|
|
||||||
ArenaInitialization = struct
|
|
||||||
{
|
|
||||||
reserved_size: u64,
|
|
||||||
granularity: u64,
|
|
||||||
initial_size: u64,
|
|
||||||
}
|
|
||||||
|
|
||||||
arena_initialize = fn (initialization: ArenaInitialization) &Arena
|
|
||||||
{
|
|
||||||
>protection_flags: OS_ProtectionFlags = {
|
|
||||||
.read = 1,
|
|
||||||
.write = 1,
|
|
||||||
zero,
|
|
||||||
};
|
|
||||||
|
|
||||||
>map_flags: OS_MapFlags = {
|
|
||||||
.private = 1,
|
|
||||||
.anonymous = 1,
|
|
||||||
.no_reserve = 1,
|
|
||||||
.populate = 0,
|
|
||||||
};
|
|
||||||
|
|
||||||
>arena: &Arena = #pointer_cast(os_reserve(0, initialization.reserved_size, protection_flags, map_flags));
|
|
||||||
os_commit(#int_from_pointer(arena), initialization.initial_size, {
|
|
||||||
.read = 1,
|
|
||||||
.write = 1,
|
|
||||||
zero,
|
|
||||||
});
|
|
||||||
|
|
||||||
arena.& = {
|
|
||||||
.reserved_size = initialization.reserved_size,
|
|
||||||
.position = minimum_position,
|
|
||||||
.os_position = initialization.initial_size,
|
|
||||||
.granularity = initialization.granularity,
|
|
||||||
zero,
|
|
||||||
};
|
|
||||||
|
|
||||||
return arena;
|
|
||||||
}
|
|
||||||
|
|
||||||
arena_initialize_default = fn (initial_size: u64) &Arena
|
|
||||||
{
|
|
||||||
return arena_initialize({
|
|
||||||
.reserved_size = 4 * 1024 * 1024 * 1024,
|
|
||||||
.granularity = 4 * 1024,
|
|
||||||
.initial_size = initial_size,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
GlobalState = struct
|
|
||||||
{
|
|
||||||
arena: &Arena,
|
|
||||||
}
|
|
||||||
|
|
||||||
global_state: GlobalState = undefined;
|
|
||||||
|
|
||||||
global_state_initialize = fn () void
|
|
||||||
{
|
|
||||||
global_state = {
|
|
||||||
.arena = arena_initialize_default(2 * 1024 * 1024),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
[export] main = fn [cc(c)] (argument_count: u32, argv: &&u8) s32
|
|
||||||
{
|
|
||||||
if (argument_count < 2)
|
|
||||||
{
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
>relative_file_path_pointer = argv[2];
|
|
||||||
if (!relative_file_path_pointer)
|
|
||||||
{
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
>relative_file_path = c_string_to_slice(relative_file_path_pointer);
|
|
||||||
|
|
||||||
if (relative_file_path.length < 5)
|
|
||||||
{
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
>extension_start = string_last_character(relative_file_path, '.');
|
|
||||||
if (extension_start == string_no_match)
|
|
||||||
{
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!string_equal(relative_file_path[extension_start..], ".bbb"))
|
|
||||||
{
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
global_state_initialize();
|
|
||||||
return 0;
|
|
||||||
}
|
|
3151
src/lib.zig
3151
src/lib.zig
File diff suppressed because it is too large
Load Diff
1858
src/llvm.cpp
1858
src/llvm.cpp
File diff suppressed because it is too large
Load Diff
290
src/llvm_api.zig
290
src/llvm_api.zig
@ -1,290 +0,0 @@
|
|||||||
const llvm = @import("LLVM.zig");
|
|
||||||
const lld = llvm.lld;
|
|
||||||
|
|
||||||
const Bool = c_int;
|
|
||||||
|
|
||||||
pub extern fn llvm_context_create_module(context: *llvm.Context, name: llvm.String) *llvm.Module;
|
|
||||||
pub extern fn LLVMContextCreate() *llvm.Context;
|
|
||||||
pub extern fn LLVMCreateBuilderInContext(context: *llvm.Context) *llvm.Builder;
|
|
||||||
|
|
||||||
pub extern fn LLVMGetOperand(value: *llvm.Value, index: c_uint) *llvm.Value;
|
|
||||||
pub extern fn LLVMSetAlignment(value: *llvm.Value, alignment: c_uint) void;
|
|
||||||
pub extern fn llvm_instruction_is_call_base(instruction: *llvm.Instruction) bool;
|
|
||||||
|
|
||||||
// Module
|
|
||||||
pub extern fn llvm_module_create_global_variable(module: *llvm.Module, global_type: *llvm.Type, is_constant: bool, linkage: llvm.LinkageType, initial_value: *llvm.Constant, name: llvm.String, before: ?*llvm.GlobalVariable, thread_local_mode: llvm.ThreadLocalMode, address_space: c_uint, externally_initialized: bool) *llvm.GlobalVariable;
|
|
||||||
pub extern fn LLVMSetUnnamedAddress(global: *llvm.GlobalVariable, unnamed_address: llvm.GlobalVariable.UnnamedAddress) void;
|
|
||||||
pub extern fn llvm_module_create_function(module: *llvm.Module, function_type: *llvm.Type.Function, linkage_type: llvm.LinkageType, address_space: c_uint, name: llvm.String) *llvm.Function;
|
|
||||||
pub extern fn llvm_context_create_basic_block(context: *llvm.Context, name: llvm.String, parent: ?*llvm.Function) *llvm.BasicBlock;
|
|
||||||
pub extern fn LLVMGetNextBasicBlock(basic_block: *llvm.BasicBlock) ?*llvm.BasicBlock;
|
|
||||||
pub extern fn LLVMDeleteBasicBlock(basic_block: *llvm.BasicBlock) void;
|
|
||||||
pub extern fn LLVMGetLastBasicBlock(function: *llvm.Function) *llvm.BasicBlock;
|
|
||||||
pub extern fn LLVMGetBasicBlockParent(basic_block: *llvm.BasicBlock) ?*llvm.BasicBlock;
|
|
||||||
pub extern fn LLVMAppendExistingBasicBlock(function: *llvm.Function, basic_block: *llvm.BasicBlock) void;
|
|
||||||
pub extern fn LLVMInsertExistingBasicBlockAfterInsertBlock(builder: *llvm.Builder, basic_block: *llvm.BasicBlock) void;
|
|
||||||
|
|
||||||
pub extern fn LLVMSetValueName2(value: *llvm.Value, name_pointer: [*]const u8, name_length: usize) void;
|
|
||||||
pub extern fn llvm_value_use_empty(value: *llvm.Value) bool;
|
|
||||||
pub extern fn llvm_value_has_one_use(value: *llvm.Value) bool;
|
|
||||||
pub extern fn llvm_value_to_branch(value: ?*llvm.Value) ?*llvm.Instruction.Branch;
|
|
||||||
pub extern fn LLVMReplaceAllUsesWith(old: *llvm.Value, new: *llvm.Value) void;
|
|
||||||
|
|
||||||
pub extern fn LLVMGetSuccessor(branch: *llvm.Instruction.Branch, index: c_uint) *llvm.BasicBlock;
|
|
||||||
pub extern fn LLVMIsConditional(branch: *llvm.Instruction.Branch) bool;
|
|
||||||
pub extern fn LLVMGetInstructionParent(instruction: *llvm.Instruction) *llvm.BasicBlock;
|
|
||||||
|
|
||||||
pub extern fn llvm_basic_block_is_empty(basic_block: *llvm.BasicBlock) bool;
|
|
||||||
pub extern fn llvm_basic_block_user_begin(basic_block: *llvm.BasicBlock) ?*llvm.Value;
|
|
||||||
pub extern fn llvm_basic_block_delete(basic_block: *llvm.BasicBlock) void;
|
|
||||||
pub extern fn LLVMGetBasicBlockTerminator(basic_block: *llvm.BasicBlock) ?*llvm.Value;
|
|
||||||
|
|
||||||
pub extern fn LLVMSetFunctionCallConv(function: *llvm.Function, calling_convention: llvm.CallingConvention) void;
|
|
||||||
pub extern fn LLVMGetFunctionCallConv(function: *llvm.Function) llvm.CallingConvention;
|
|
||||||
|
|
||||||
pub extern fn LLVMSetInstructionCallConv(instruction: *llvm.Instruction.CallBase, calling_convention: llvm.CallingConvention) void;
|
|
||||||
|
|
||||||
pub extern fn LLVMGetParams(function: *llvm.Function, argument_buffer: [*]*llvm.Argument) void;
|
|
||||||
|
|
||||||
pub extern fn llvm_function_to_string(function: *llvm.Function) llvm.String;
|
|
||||||
pub extern fn llvm_function_verify(function: *llvm.Function, error_message: *llvm.String) bool;
|
|
||||||
pub extern fn llvm_module_verify(module: *llvm.Module, error_message: *llvm.String) bool;
|
|
||||||
|
|
||||||
pub extern fn llvm_module_to_string(module: *llvm.Module) llvm.String;
|
|
||||||
|
|
||||||
// Builder API
|
|
||||||
pub extern fn LLVMPositionBuilderAtEnd(builder: *llvm.Builder, basic_block: *llvm.BasicBlock) void;
|
|
||||||
pub extern fn LLVMClearInsertionPosition(builder: *llvm.Builder) void;
|
|
||||||
pub extern fn LLVMGetInsertBlock(builder: *llvm.Builder) ?*llvm.BasicBlock;
|
|
||||||
|
|
||||||
pub extern fn llvm_find_return_value_dominating_store(builder: *llvm.Builder, return_alloca: *llvm.Value, element_type: *llvm.Type) ?*llvm.Instruction.Store;
|
|
||||||
|
|
||||||
pub extern fn LLVMDeleteInstruction(instruction: *llvm.Instruction) void;
|
|
||||||
pub extern fn LLVMInstructionEraseFromParent(instruction: *llvm.Instruction) void;
|
|
||||||
|
|
||||||
pub extern fn LLVMBuildRet(builder: *llvm.Builder, value: ?*llvm.Value) void;
|
|
||||||
pub extern fn LLVMBuildAdd(builder: *llvm.Builder, left: *llvm.Value, right: *llvm.Value, name: [*:0]const u8) *llvm.Value;
|
|
||||||
pub extern fn LLVMBuildSub(builder: *llvm.Builder, left: *llvm.Value, right: *llvm.Value, name: [*:0]const u8) *llvm.Value;
|
|
||||||
pub extern fn LLVMBuildMul(builder: *llvm.Builder, left: *llvm.Value, right: *llvm.Value, name: [*:0]const u8) *llvm.Value;
|
|
||||||
pub extern fn LLVMBuildSDiv(builder: *llvm.Builder, left: *llvm.Value, right: *llvm.Value, name: [*:0]const u8) *llvm.Value;
|
|
||||||
pub extern fn LLVMBuildUDiv(builder: *llvm.Builder, left: *llvm.Value, right: *llvm.Value, name: [*:0]const u8) *llvm.Value;
|
|
||||||
pub extern fn LLVMBuildSRem(builder: *llvm.Builder, left: *llvm.Value, right: *llvm.Value, name: [*:0]const u8) *llvm.Value;
|
|
||||||
pub extern fn LLVMBuildURem(builder: *llvm.Builder, left: *llvm.Value, right: *llvm.Value, name: [*:0]const u8) *llvm.Value;
|
|
||||||
pub extern fn LLVMBuildShl(builder: *llvm.Builder, left: *llvm.Value, right: *llvm.Value, name: [*:0]const u8) *llvm.Value;
|
|
||||||
pub extern fn LLVMBuildAShr(builder: *llvm.Builder, left: *llvm.Value, right: *llvm.Value, name: [*:0]const u8) *llvm.Value;
|
|
||||||
pub extern fn LLVMBuildLShr(builder: *llvm.Builder, left: *llvm.Value, right: *llvm.Value, name: [*:0]const u8) *llvm.Value;
|
|
||||||
pub extern fn LLVMBuildAnd(builder: *llvm.Builder, left: *llvm.Value, right: *llvm.Value, name: [*:0]const u8) *llvm.Value;
|
|
||||||
pub extern fn LLVMBuildOr(builder: *llvm.Builder, left: *llvm.Value, right: *llvm.Value, name: [*:0]const u8) *llvm.Value;
|
|
||||||
pub extern fn LLVMBuildXor(builder: *llvm.Builder, left: *llvm.Value, right: *llvm.Value, name: [*:0]const u8) *llvm.Value;
|
|
||||||
pub extern fn LLVMBuildICmp(builder: *llvm.Builder, predicate: llvm.IntPredicate, left: *llvm.Value, right: *llvm.Value, name: [*:0]const u8) *llvm.Value;
|
|
||||||
pub extern fn LLVMBuildBr(builder: *llvm.Builder, block: *llvm.BasicBlock) *llvm.Value;
|
|
||||||
pub extern fn LLVMBuildCondBr(builder: *llvm.Builder, condition: *llvm.Value, taken: *llvm.BasicBlock, not_taken: *llvm.BasicBlock) *llvm.Value;
|
|
||||||
pub extern fn LLVMBuildNeg(builder: *llvm.Builder, value: *llvm.Value, name: [*:0]const u8) *llvm.Value;
|
|
||||||
pub extern fn LLVMBuildNot(builder: *llvm.Builder, value: *llvm.Value, name: [*:0]const u8) *llvm.Value;
|
|
||||||
|
|
||||||
pub extern fn llvm_builder_create_alloca(builder: *llvm.Builder, ty: *llvm.Type, address_space: c_uint, name: llvm.String) *llvm.Value;
|
|
||||||
pub extern fn LLVMBuildStore(builder: *llvm.Builder, value: *llvm.Value, pointer: *llvm.Value) *llvm.Value;
|
|
||||||
pub extern fn LLVMBuildLoad2(builder: *llvm.Builder, ty: *llvm.Type, pointer: *llvm.Value, name: [*:0]const u8) *llvm.Value;
|
|
||||||
pub extern fn LLVMBuildCall2(builder: *llvm.Builder, ty: *llvm.Type.Function, pointer: *llvm.Value, argument_pointer: [*]const *llvm.Value, argument_count: c_uint, name: [*:0]const u8) *llvm.Value;
|
|
||||||
pub extern fn LLVMBuildStructGEP2(builder: *llvm.Builder, struct_type: *llvm.Type.Struct, pointer: *llvm.Value, index: c_uint, name: [*:0]const u8) *llvm.Value;
|
|
||||||
pub extern fn LLVMBuildGEP2(builder: *llvm.Builder, ty: *llvm.Type, aggregate: *llvm.Value, index_pointer: [*]const *llvm.Value, index_count: c_uint, name: [*:0]const u8) *llvm.Value;
|
|
||||||
pub extern fn LLVMBuildInBoundsGEP2(builder: *llvm.Builder, ty: *llvm.Type, aggregate: *llvm.Value, index_pointer: [*]const *llvm.Value, index_count: c_uint, name: [*:0]const u8) *llvm.Value;
|
|
||||||
|
|
||||||
pub extern fn LLVMBuildInsertValue(builder: *llvm.Builder, aggregate: *llvm.Value, element: *llvm.Value, index: c_uint, name: [*:0]const u8) *llvm.Value;
|
|
||||||
pub extern fn LLVMBuildExtractValue(builder: *llvm.Builder, aggregate: *llvm.Value, index: c_uint, name: [*:0]const u8) *llvm.Value;
|
|
||||||
pub extern fn LLVMBuildUnreachable(builder: *llvm.Builder) *llvm.Value;
|
|
||||||
pub extern fn LLVMBuildMemCpy(builder: *llvm.Builder, destination: *llvm.Value, destination_alignment: c_uint, source: *llvm.Value, source_alignment: c_uint, size: *llvm.Value) *llvm.Value;
|
|
||||||
pub extern fn LLVMBuildMemSet(builder: *llvm.Builder, pointer: *llvm.Value, value: *llvm.Value, value_count: *llvm.Value, alignment: c_uint) *llvm.Value;
|
|
||||||
pub extern fn LLVMBuildPhi(builder: *llvm.Builder, ty: *llvm.Type, name: [*:0]const u8) *llvm.Instruction.Phi;
|
|
||||||
pub extern fn LLVMAddIncoming(phi: *llvm.Instruction.Phi, incoming_value_pointer: [*]const *llvm.Value, incoming_basic_block_pointer: [*]const *llvm.BasicBlock, incoming_count: c_uint) void;
|
|
||||||
pub extern fn LLVMBuildSelect(builder: *llvm.Builder, condition: *llvm.Value, true_value: *llvm.Value, false_value: *llvm.Value, name: [*:0]const u8) *llvm.Value;
|
|
||||||
|
|
||||||
pub extern fn LLVMBuildVAArg(builder: *llvm.Builder, va_list: *llvm.Value, arg_type: *llvm.Type, name: [*:0]const u8) *llvm.Value;
|
|
||||||
pub extern fn LLVMBuildSwitch(builder: *llvm.Builder, discriminant: *llvm.Value, else_basic_block: *llvm.BasicBlock, case_count: c_uint) *llvm.Instruction.Switch;
|
|
||||||
pub extern fn LLVMAddCase(switchi: *llvm.Instruction.Switch, case_value: *llvm.Value, case_block: *llvm.BasicBlock) void;
|
|
||||||
|
|
||||||
// Casts
|
|
||||||
pub extern fn LLVMBuildZExt(builder: *llvm.Builder, value: *llvm.Value, destination_type: *llvm.Type, name: [*:0]const u8) *llvm.Value;
|
|
||||||
pub extern fn LLVMBuildSExt(builder: *llvm.Builder, value: *llvm.Value, destination_type: *llvm.Type, name: [*:0]const u8) *llvm.Value;
|
|
||||||
pub extern fn LLVMBuildIntToPtr(builder: *llvm.Builder, value: *llvm.Value, destination_type: *llvm.Type, name: [*:0]const u8) *llvm.Value;
|
|
||||||
pub extern fn LLVMBuildPtrToInt(builder: *llvm.Builder, value: *llvm.Value, destination_type: *llvm.Type, name: [*:0]const u8) *llvm.Value;
|
|
||||||
pub extern fn LLVMBuildPointerCast(builder: *llvm.Builder, value: *llvm.Value, ty: *llvm.Type, name: [*:0]const u8) *llvm.Value;
|
|
||||||
pub extern fn LLVMBuildTrunc(builder: *llvm.Builder, value: *llvm.Value, destination_type: *llvm.Type, name: [*:0]const u8) *llvm.Value;
|
|
||||||
|
|
||||||
pub extern fn LLVMSetCurrentDebugLocation2(builder: *llvm.Builder, location: ?*llvm.DI.Location) void;
|
|
||||||
|
|
||||||
pub extern fn LLVMTypeOf(value: *llvm.Value) *llvm.Type;
|
|
||||||
pub extern fn LLVMSizeOf(ty: *llvm.Type) *llvm.Constant;
|
|
||||||
pub extern fn LLVMAlignOf(ty: *llvm.Type) *llvm.Constant;
|
|
||||||
pub extern fn LLVMGlobalGetValueType(value: *llvm.GlobalValue) *llvm.Type;
|
|
||||||
pub extern fn LLVMGetInitializer(global_variable: *llvm.GlobalVariable) *llvm.Constant;
|
|
||||||
pub extern fn LLVMSetInitializer(global_variable: *llvm.GlobalVariable, initializer: *llvm.Constant) void;
|
|
||||||
pub extern fn LLVMDeleteGlobal(global_variable: *llvm.GlobalVariable) void;
|
|
||||||
pub extern fn llvm_global_variable_delete(global_variable: *llvm.GlobalVariable) void;
|
|
||||||
pub extern fn llvm_value_is_instruction(value: *llvm.Value) bool;
|
|
||||||
|
|
||||||
// Intrinsics
|
|
||||||
pub extern fn LLVMLookupIntrinsicID(name_pointer: [*]const u8, name_length: usize) llvm.Intrinsic.Id;
|
|
||||||
pub extern fn LLVMGetIntrinsicDeclaration(module: *llvm.Module, intrinsic_id: llvm.Intrinsic.Id, parameter_type_pointer: [*]const *llvm.Type, parameter_type_count: usize) *llvm.Value;
|
|
||||||
pub extern fn LLVMIntrinsicGetType(context: *llvm.Context, intrinsic_id: llvm.Intrinsic.Id, parameter_type_pointer: [*]const *llvm.Type, parameter_type_count: usize) *llvm.Type.Function;
|
|
||||||
|
|
||||||
// Attributes
|
|
||||||
pub extern fn llvm_attribute_list_build(context: *llvm.Context, options: *const llvm.Attribute.List.Options, call_site: bool) *llvm.Attribute.List;
|
|
||||||
pub extern fn llvm_function_set_attributes(function: *llvm.Function, attribute_list: *llvm.Attribute.List) void;
|
|
||||||
pub extern fn llvm_call_base_set_attributes(function: *llvm.Instruction.CallBase, attribute_list: *llvm.Attribute.List) void;
|
|
||||||
|
|
||||||
// pub extern fn LLVMGetEnumAttributeKindForName(name_pointer: [*]const u8, name_length: usize) llvm.Attribute.Kind;
|
|
||||||
//
|
|
||||||
// pub extern fn LLVMCreateEnumAttribute(context: *llvm.Context, kind: llvm.Attribute.Kind, value: u64) *llvm.Attribute;
|
|
||||||
// pub extern fn LLVMCreateTypeAttribute(context: *llvm.Context, kind: llvm.Attribute.Kind, ty: *llvm.Type) *llvm.Attribute;
|
|
||||||
// pub extern fn LLVMCreateConstantRangeAttribute(context: *llvm.Context, kind: llvm.Attribute.Kind, bit_count: c_uint, lower_words: [*]const u64, upper_words: [*]const u64) *llvm.Attribute;
|
|
||||||
// pub extern fn LLVMCreateStringAttribute(context: *llvm.Context, key_pointer: [*]const u8, key_length: c_uint, value_pointer: [*]const u8, value_length: usize) *llvm.Attribute;
|
|
||||||
//
|
|
||||||
// pub extern fn LLVMAddAttributeAtIndex(function: *llvm.Function, attribute_index: llvm.Attribute.Index, attribute: *llvm.Attribute) void;
|
|
||||||
// pub extern fn LLVMAddCallSiteAttribute(call: *llvm.Instruction.Call, attribute_index: llvm.Attribute.Index, attribute: *llvm.Attribute) void;
|
|
||||||
|
|
||||||
// TYPES
|
|
||||||
// Types: integers
|
|
||||||
pub extern fn LLVMVoidTypeInContext(context: *llvm.Context) *llvm.Type;
|
|
||||||
pub extern fn LLVMInt1TypeInContext(context: *llvm.Context) *llvm.Type.Integer;
|
|
||||||
pub extern fn LLVMInt8TypeInContext(context: *llvm.Context) *llvm.Type.Integer;
|
|
||||||
pub extern fn LLVMInt16TypeInContext(context: *llvm.Context) *llvm.Type.Integer;
|
|
||||||
pub extern fn LLVMInt32TypeInContext(context: *llvm.Context) *llvm.Type.Integer;
|
|
||||||
pub extern fn LLVMInt64TypeInContext(context: *llvm.Context) *llvm.Type.Integer;
|
|
||||||
pub extern fn LLVMInt128TypeInContext(context: *llvm.Context) *llvm.Type.Integer;
|
|
||||||
pub extern fn LLVMIntTypeInContext(context: *llvm.Context, bit_count: c_uint) *llvm.Type.Integer;
|
|
||||||
|
|
||||||
// Types: floating point
|
|
||||||
pub extern fn LLVMHalfTypeInContext(context: *llvm.Context) *llvm.Type;
|
|
||||||
pub extern fn LLVMBFloatTypeInContext(context: *llvm.Context) *llvm.Type;
|
|
||||||
pub extern fn LLVMFloatTypeInContext(context: *llvm.Context) *llvm.Type;
|
|
||||||
pub extern fn LLVMDoubleTypeInContext(context: *llvm.Context) *llvm.Type;
|
|
||||||
pub extern fn LLVMFP128TypeInContext(context: *llvm.Context) *llvm.Type;
|
|
||||||
|
|
||||||
// Types: functions
|
|
||||||
pub extern fn LLVMFunctionType(return_type: *llvm.Type, parameter_type_pointer: [*]const *llvm.Type, parameter_type_count: c_uint, is_var_arg: Bool) *llvm.Type.Function;
|
|
||||||
pub extern fn LLVMIsFunctionVarArg(function_type: *llvm.Type.Function) Bool;
|
|
||||||
pub extern fn LLVMGetReturnType(function_type: *llvm.Type.Function) *llvm.Type;
|
|
||||||
pub extern fn LLVMSetSubprogram(function: *llvm.Function, subprogram: *llvm.DI.Subprogram) void;
|
|
||||||
pub extern fn LLVMGetSubprogram(function: *llvm.Function) ?*llvm.DI.Subprogram;
|
|
||||||
pub extern fn LLVMCountParamTypes(function_type: *llvm.Type.Function) c_uint;
|
|
||||||
pub extern fn LLVMGetParamTypes(function_type: *llvm.Type.Function, types: [*]*llvm.Type) void;
|
|
||||||
|
|
||||||
// Types: struct
|
|
||||||
pub extern fn LLVMStructSetBody(struct_type: *llvm.Type.Struct, element_type_pointer: [*]const *llvm.Type, element_type_count: c_uint, is_packed: Bool) void;
|
|
||||||
pub extern fn llvm_context_create_forward_declared_struct_type(context: *llvm.Context, name: llvm.String) *llvm.Type.Struct;
|
|
||||||
pub extern fn llvm_context_create_struct_type(context: *llvm.Context, element_types_pointer: [*]const *llvm.Type, element_type_count: usize, name: llvm.String, is_packed: bool) *llvm.Type.Struct;
|
|
||||||
pub extern fn llvm_context_get_struct_type(context: *llvm.Context, element_types_pointer: [*]const *llvm.Type, element_type_count: usize, is_packed: bool) *llvm.Type.Struct;
|
|
||||||
|
|
||||||
// Types: arrays
|
|
||||||
pub extern fn LLVMArrayType2(element_type: *llvm.Type, element_count: u64) *llvm.Type.Array;
|
|
||||||
|
|
||||||
// Types: pointers
|
|
||||||
pub extern fn LLVMPointerTypeInContext(context: *llvm.Context, address_space: c_uint) *llvm.Type.Pointer;
|
|
||||||
|
|
||||||
// Types: vectors
|
|
||||||
pub extern fn LLVMVectorType(element_type: *llvm.Type, element_count: c_uint) *llvm.Type.FixedVector;
|
|
||||||
pub extern fn LLVMScalableVectorType(element_type: *llvm.Type, element_count: c_uint) *llvm.Type.ScalableVector;
|
|
||||||
|
|
||||||
pub extern fn LLVMGetTypeKind(ty: *llvm.Type) llvm.Type.Kind;
|
|
||||||
|
|
||||||
pub extern fn llvm_integer_type_get_bit_count(integer_type: *llvm.Type.Integer) c_uint;
|
|
||||||
|
|
||||||
// VALUES
|
|
||||||
pub extern fn LLVMGetPoison(type: *llvm.Type) *llvm.Value;
|
|
||||||
pub extern fn LLVMConstNeg(constant: *llvm.Constant) *llvm.Constant;
|
|
||||||
pub extern fn LLVMConstNull(type: *llvm.Type) *llvm.Constant;
|
|
||||||
pub extern fn LLVMConstInt(type: *llvm.Type.Integer, value: c_ulonglong, sign_extend: Bool) *llvm.Constant.Integer;
|
|
||||||
pub extern fn LLVMConstIntGetZExtValue(constant: *llvm.Constant) u64;
|
|
||||||
pub extern fn LLVMConstIntGetSExtValue(constant: *llvm.Constant) i64;
|
|
||||||
pub extern fn LLVMConstArray2(element_type: *llvm.Type, value_pointer: [*]const *llvm.Constant, value_length: u64) *llvm.Constant;
|
|
||||||
pub extern fn LLVMConstStructInContext(context: *llvm.Context, constant_value_pointer: [*]const *llvm.Constant, constant_value_count: c_uint, is_packed: c_uint) *llvm.Constant;
|
|
||||||
pub extern fn LLVMConstNamedStruct(struct_type: *llvm.Type.Struct, constant_value_pointer: [*]const *llvm.Constant, constant_value_count: c_uint) *llvm.Constant;
|
|
||||||
pub extern fn LLVMConstStringInContext2(context: *llvm.Context, string_pointer: [*]const u8, string_length: usize, dont_null_terminate: Bool) *llvm.Constant;
|
|
||||||
|
|
||||||
pub extern fn LLVMGetValueKind(value: *llvm.Value) llvm.Value.Kind;
|
|
||||||
pub extern fn LLVMIsConstant(value: *llvm.Value) Bool;
|
|
||||||
|
|
||||||
// Debug info API
|
|
||||||
pub extern fn LLVMCreateDIBuilder(module: *llvm.Module) *llvm.DI.Builder;
|
|
||||||
pub extern fn LLVMDIBuilderFinalize(builder: *llvm.DI.Builder) void;
|
|
||||||
pub extern fn LLVMDIBuilderCreateFile(builder: *llvm.DI.Builder, file_name: llvm.String, directory_name: llvm.String) *llvm.DI.File;
|
|
||||||
pub extern fn LLVMDIBuilderCreateCompileUnit(builder: *llvm.DI.Builder, language: llvm.Dwarf.SourceLanguage, file: *llvm.DI.File, producer_name: llvm.String, optimized: Bool, flags: llvm.String, runtime_version: c_uint, split_name: llvm.String, dwarf_emission_kind: llvm.Dwarf.EmissionKind, debug_with_offset_id: c_uint, split_debug_inlining: Bool, debug_info_for_profiling: Bool, sysroot: llvm.String, sdk: llvm.String) *llvm.DI.CompileUnit;
|
|
||||||
pub extern fn LLVMDIBuilderCreateSubroutineType(builder: *llvm.DI.Builder, file: *llvm.DI.File, parameter_type_pointer: [*]const *llvm.DI.Type, parameter_type_count: c_uint, flags: llvm.DI.Flags) *llvm.DI.Type.Subroutine;
|
|
||||||
pub extern fn LLVMDIBuilderCreateFunction(builder: *llvm.DI.Builder, scope: *llvm.DI.Scope, name: llvm.String, linkage_name: llvm.String, file: *llvm.DI.File, line_number: c_uint, type: *llvm.DI.Type.Subroutine, local_to_unit: Bool, is_definition: Bool, scope_line: c_uint, flags: llvm.DI.Flags, is_optimized: Bool) *llvm.DI.Subprogram;
|
|
||||||
pub extern fn LLVMDIBuilderFinalizeSubprogram(builder: *llvm.DI.Builder, subprogram: *llvm.DI.Subprogram) void;
|
|
||||||
pub extern fn LLVMDIBuilderCreateExpression(builder: *llvm.DI.Builder, address: ?[*]const u64, length: u64) *llvm.DI.Expression;
|
|
||||||
pub extern fn LLVMDIBuilderCreateDebugLocation(context: *llvm.Context, line: c_uint, column: c_uint, scope: *llvm.DI.Scope, inlined_at: ?*llvm.DI.Metadata) *llvm.DI.Location;
|
|
||||||
pub extern fn LLVMDIBuilderCreateBasicType(builder: *llvm.DI.Builder, name_pointer: [*]const u8, name_length: usize, bit_count: u64, dwarf_type: llvm.Dwarf.Type, flags: llvm.DI.Flags) *llvm.DI.Type;
|
|
||||||
pub extern fn LLVMDIBuilderCreateAutoVariable(builder: *llvm.DI.Builder, scope: *llvm.DI.Scope, name_pointer: [*]const u8, name_length: usize, file: *llvm.DI.File, line: c_uint, type: *llvm.DI.Type, always_preserve: Bool, flags: llvm.DI.Flags, align_in_bits: u32) *llvm.DI.LocalVariable;
|
|
||||||
pub extern fn LLVMDIBuilderInsertDeclareRecordAtEnd(builder: *llvm.DI.Builder, storage: *llvm.Value, local_variable: *llvm.DI.LocalVariable, expression: *llvm.DI.Expression, debug_location: *llvm.DI.Location, basic_block: *llvm.BasicBlock) *llvm.DI.Record;
|
|
||||||
pub extern fn LLVMDIBuilderCreateParameterVariable(builder: *llvm.DI.Builder, scope: *llvm.DI.Scope, name_pointer: [*]const u8, name_length: usize, argument_number: c_uint, file: *llvm.DI.File, line: c_uint, type: *llvm.DI.Type, always_preserve: Bool, flags: llvm.DI.Flags) *llvm.DI.LocalVariable;
|
|
||||||
pub extern fn LLVMDIBuilderCreateGlobalVariableExpression(builder: *llvm.DI.Builder, scope: *llvm.DI.Scope, name_pointer: [*]const u8, name_length: usize, linkage_name_pointer: [*]const u8, linkage_name_length: usize, file: *llvm.DI.File, line: c_uint, global_type: *llvm.DI.Type, local_to_unit: Bool, expression: *llvm.DI.Expression, declaration: ?*llvm.DI.Metadata, align_in_bits: u32) *llvm.DI.GlobalVariableExpression;
|
|
||||||
pub extern fn llvm_global_variable_add_debug_info(global_variable: *llvm.GlobalVariable, debug_global_variable: *llvm.DI.GlobalVariableExpression) void;
|
|
||||||
pub extern fn LLVMDIBuilderCreateLexicalBlock(builder: *llvm.DI.Builder, scope: *llvm.DI.Scope, file: *llvm.DI.File, line: c_uint, column: c_uint) *llvm.DI.LexicalBlock;
|
|
||||||
pub extern fn LLVMDIBuilderCreateReplaceableCompositeType(builder: *llvm.DI.Builder, tag: c_uint, name_pointer: [*]const u8, name_length: usize, scope: *llvm.DI.Scope, file: *llvm.DI.File, line: c_uint, runtime_language: c_uint, bit_size: u64, align_in_bits: u32, flags: llvm.DI.Flags, unique_identifier_pointer: ?[*]const u8, unique_identifier_length: usize) *llvm.DI.Type.Composite;
|
|
||||||
pub extern fn LLVMDIBuilderCreateArrayType(builder: *llvm.DI.Builder, element_count: u64, align_in_bits: u32, element_type: *llvm.DI.Type, subscript_pointer: ?[*]const *llvm.DI.Metadata, subscript_count: c_uint) *llvm.DI.Type.Composite;
|
|
||||||
pub extern fn LLVMDIBuilderCreateStructType(builder: *llvm.DI.Builder, scope: *llvm.DI.Scope, name_pointer: [*]const u8, name_length: usize, file: *llvm.DI.File, line: c_uint, bit_size: u64, align_in_bits: u32, flags: llvm.DI.Flags, derived_from: ?*llvm.DI.Type, member_pointer: [*]const *llvm.DI.Type.Derived, member_length: c_uint, runtime_language: c_uint, vtable_holder: ?*llvm.DI.Metadata, unique_id_pointer: ?[*]const u8, unique_id_length: usize) *llvm.DI.Type.Composite;
|
|
||||||
pub extern fn LLVMDIBuilderCreateMemberType(builder: *llvm.DI.Builder, scope: *llvm.DI.Scope, name_pointer: [*]const u8, name_length: usize, file: *llvm.DI.File, line: c_uint, bit_size: u64, align_in_bits: u32, bit_offset: u64, flags: llvm.DI.Flags, member_type: *llvm.DI.Type) *llvm.DI.Type.Derived;
|
|
||||||
pub extern fn LLVMDIBuilderCreateBitFieldMemberType(builder: *llvm.DI.Builder, scope: *llvm.DI.Scope, name_pointer: [*]const u8, name_length: usize, file: *llvm.DI.File, line: c_uint, bit_size: u64, bit_offset: u64, bit_storage_offset: u64, flags: llvm.DI.Flags, member_type: *llvm.DI.Type) *llvm.DI.Type.Derived;
|
|
||||||
pub extern fn LLVMDIBuilderCreatePointerType(builder: *llvm.DI.Builder, element_type: *llvm.DI.Type, bit_size: u64, align_in_bits: u32, address_space: c_uint, name_pointer: [*]const u8, name_length: usize) *llvm.DI.Type.Derived;
|
|
||||||
pub extern fn LLVMDIBuilderCreateEnumerator(builder: *llvm.DI.Builder, name_pointer: [*]const u8, name_length: usize, value: i64, is_unsigned: Bool) *llvm.DI.Enumerator;
|
|
||||||
pub extern fn LLVMDIBuilderCreateEnumerationType(builder: *llvm.DI.Builder, scope: *llvm.DI.Scope, name_pointer: [*]const u8, name_length: usize, file: *llvm.DI.File, line: c_uint, bit_size: u64, align_in_bits: u32, enumerator_pointer: [*]const *llvm.DI.Enumerator, enumerator_count: c_uint, backing_type: *llvm.DI.Type) *llvm.DI.Type.Composite;
|
|
||||||
|
|
||||||
pub extern fn LLVMMetadataReplaceAllUsesWith(forward: *llvm.DI.Type.Composite, complete: *llvm.DI.Type.Composite) void;
|
|
||||||
|
|
||||||
// Target
|
|
||||||
pub extern fn llvm_default_target_triple() llvm.String;
|
|
||||||
pub extern fn llvm_host_cpu_name() llvm.String;
|
|
||||||
pub extern fn llvm_host_cpu_features() llvm.String;
|
|
||||||
|
|
||||||
pub extern fn llvm_create_target_machine(create: *const llvm.Target.Machine.Create, error_message: *llvm.String) ?*llvm.Target.Machine;
|
|
||||||
pub extern fn llvm_module_set_target(module: *llvm.Module, target_machine: *llvm.Target.Machine) void;
|
|
||||||
|
|
||||||
pub extern fn llvm_module_run_optimization_pipeline(module: *llvm.Module, target_machine: *llvm.Target.Machine, options: llvm.OptimizationPipelineOptions) void;
|
|
||||||
pub extern fn llvm_module_run_code_generation_pipeline(module: *llvm.Module, target_machine: *llvm.Target.Machine, options: llvm.CodeGenerationPipelineOptions) llvm.CodeGenerationPipelineResult;
|
|
||||||
|
|
||||||
pub fn get_initializer(comptime llvm_arch: llvm.Architecture) type {
|
|
||||||
const arch_name = @tagName(llvm_arch);
|
|
||||||
return struct {
|
|
||||||
pub const initialize_target_info = @extern(*const fn () callconv(.C) void, .{
|
|
||||||
.name = "LLVMInitialize" ++ arch_name ++ "TargetInfo",
|
|
||||||
});
|
|
||||||
pub const initialize_target = @extern(*const fn () callconv(.C) void, .{
|
|
||||||
.name = "LLVMInitialize" ++ arch_name ++ "Target",
|
|
||||||
});
|
|
||||||
pub const initialize_target_mc = @extern(*const fn () callconv(.C) void, .{
|
|
||||||
.name = "LLVMInitialize" ++ arch_name ++ "TargetMC",
|
|
||||||
});
|
|
||||||
pub const initialize_asm_printer = @extern(*const fn () callconv(.C) void, .{
|
|
||||||
.name = "LLVMInitialize" ++ arch_name ++ "AsmPrinter",
|
|
||||||
});
|
|
||||||
pub const initialize_asm_parser = @extern(*const fn () callconv(.C) void, .{
|
|
||||||
.name = "LLVMInitialize" ++ arch_name ++ "AsmParser",
|
|
||||||
});
|
|
||||||
pub const initialize_disassembler = @extern(*const fn () callconv(.C) void, .{
|
|
||||||
.name = "LLVMInitialize" ++ arch_name ++ "Disassembler",
|
|
||||||
});
|
|
||||||
|
|
||||||
pub fn initialize(options: llvm.TargetInitializerOptions) void {
|
|
||||||
initialize_target_info();
|
|
||||||
initialize_target();
|
|
||||||
initialize_target_mc();
|
|
||||||
|
|
||||||
if (options.asm_printer) {
|
|
||||||
initialize_asm_printer();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (options.asm_parser) {
|
|
||||||
initialize_asm_parser();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (options.disassembler) {
|
|
||||||
initialize_disassembler();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
// LLD
|
|
||||||
|
|
||||||
pub extern fn lld_elf_link(argument_pointer: [*:null]const ?[*:0]const u8, argument_length: u64, exit_early: bool, disable_output: bool) lld.Result;
|
|
4
src/main.nat
Normal file
4
src/main.nat
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
fn main() s32
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
312
src/main.zig
312
src/main.zig
@ -1,312 +0,0 @@
|
|||||||
const lib = @import("lib.zig");
|
|
||||||
const configuration = @import("configuration");
|
|
||||||
const os = lib.os;
|
|
||||||
const llvm = @import("LLVM.zig");
|
|
||||||
const Arena = lib.Arena;
|
|
||||||
|
|
||||||
const compiler = @import("bootstrap.zig");
|
|
||||||
const BuildMode = compiler.BuildMode;
|
|
||||||
|
|
||||||
test {
|
|
||||||
_ = lib;
|
|
||||||
_ = llvm;
|
|
||||||
_ = compiler;
|
|
||||||
}
|
|
||||||
|
|
||||||
fn fail() noreturn {
|
|
||||||
lib.libc.exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
const Command = enum {
|
|
||||||
@"test",
|
|
||||||
compile,
|
|
||||||
};
|
|
||||||
|
|
||||||
const Compile = struct {
|
|
||||||
relative_file_path: [:0]const u8,
|
|
||||||
build_mode: BuildMode,
|
|
||||||
has_debug_info: bool,
|
|
||||||
silent: bool,
|
|
||||||
};
|
|
||||||
|
|
||||||
fn compile_file(arena: *Arena, compile: Compile) compiler.Options {
|
|
||||||
const relative_file_path = compile.relative_file_path;
|
|
||||||
if (relative_file_path.len < 5) {
|
|
||||||
fail();
|
|
||||||
}
|
|
||||||
|
|
||||||
const extension_start = lib.string.last_character(relative_file_path, '.') orelse fail();
|
|
||||||
if (!lib.string.equal(relative_file_path[extension_start..], ".bbb")) {
|
|
||||||
fail();
|
|
||||||
}
|
|
||||||
|
|
||||||
const separator_index = lib.string.last_character(relative_file_path, '/') orelse 0;
|
|
||||||
const base_start = separator_index + @intFromBool(separator_index != 0 or relative_file_path[separator_index] == '/');
|
|
||||||
const base_name = relative_file_path[base_start..extension_start];
|
|
||||||
|
|
||||||
const is_compiler = lib.string.equal(relative_file_path, "src/compiler.bbb");
|
|
||||||
const output_path_dir = arena.join_string(&.{
|
|
||||||
base_cache_dir,
|
|
||||||
if (is_compiler) "/compiler/" else "/",
|
|
||||||
@tagName(compile.build_mode),
|
|
||||||
"_",
|
|
||||||
if (compile.has_debug_info) "di" else "nodi",
|
|
||||||
});
|
|
||||||
|
|
||||||
os.make_directory(base_cache_dir);
|
|
||||||
if (is_compiler) {
|
|
||||||
os.make_directory(base_cache_dir ++ "/compiler");
|
|
||||||
}
|
|
||||||
|
|
||||||
os.make_directory(output_path_dir);
|
|
||||||
|
|
||||||
const output_path_base = arena.join_string(&.{
|
|
||||||
output_path_dir,
|
|
||||||
"/",
|
|
||||||
base_name,
|
|
||||||
});
|
|
||||||
|
|
||||||
const output_object_path = arena.join_string(&.{ output_path_base, ".o" });
|
|
||||||
const output_executable_path = output_path_base;
|
|
||||||
|
|
||||||
const file_content = lib.file.read(arena, relative_file_path);
|
|
||||||
const file_path = os.absolute_path(arena, relative_file_path);
|
|
||||||
const c_abi_object_path = arena.duplicate_string(configuration.c_abi_object_path);
|
|
||||||
|
|
||||||
const convert_options = compiler.Options{
|
|
||||||
.executable = output_executable_path,
|
|
||||||
.objects = if (lib.string.equal(base_name, "c_abi")) &.{ output_object_path, c_abi_object_path } else &.{output_object_path},
|
|
||||||
.name = base_name,
|
|
||||||
.build_mode = compile.build_mode,
|
|
||||||
.content = file_content,
|
|
||||||
.path = file_path,
|
|
||||||
.has_debug_info = compile.has_debug_info,
|
|
||||||
.target = compiler.Target.get_native(),
|
|
||||||
.silent = compile.silent,
|
|
||||||
};
|
|
||||||
|
|
||||||
compiler.compile(arena, convert_options);
|
|
||||||
|
|
||||||
return convert_options;
|
|
||||||
}
|
|
||||||
|
|
||||||
const base_cache_dir = "bb-cache";
|
|
||||||
|
|
||||||
pub const panic = lib.panic_struct;
|
|
||||||
pub const std_options = lib.std_options;
|
|
||||||
pub const main = lib.main;
|
|
||||||
|
|
||||||
pub fn entry_point(arguments: []const [*:0]const u8, environment: [*:null]const ?[*:0]const u8) void {
|
|
||||||
lib.GlobalState.initialize();
|
|
||||||
const arena = lib.global.arena;
|
|
||||||
|
|
||||||
if (arguments.len < 2) {
|
|
||||||
lib.print_string("error: Not enough arguments\n");
|
|
||||||
fail();
|
|
||||||
}
|
|
||||||
|
|
||||||
const command = lib.string.to_enum(Command, lib.cstring.to_slice(arguments[1])) orelse fail();
|
|
||||||
|
|
||||||
switch (command) {
|
|
||||||
.compile => {
|
|
||||||
if (arguments.len < 3) {
|
|
||||||
lib.libc.exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
var build_mode = compiler.BuildMode.debug_none;
|
|
||||||
var has_debug_info = true;
|
|
||||||
|
|
||||||
if (arguments.len >= 4) {
|
|
||||||
const build_mode_string = lib.cstring.to_slice(arguments[3]);
|
|
||||||
build_mode = lib.string.to_enum(compiler.BuildMode, build_mode_string) orelse lib.libc.exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (arguments.len >= 5) {
|
|
||||||
const has_debug_info_string = lib.cstring.to_slice(arguments[4]);
|
|
||||||
has_debug_info = if (lib.string.equal(has_debug_info_string, "true")) true else if (lib.string.equal(has_debug_info_string, "false")) false else lib.libc.exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
const relative_file_path = lib.cstring.to_slice(arguments[2]);
|
|
||||||
_ = compile_file(arena, .{
|
|
||||||
.relative_file_path = relative_file_path,
|
|
||||||
.build_mode = build_mode,
|
|
||||||
.has_debug_info = has_debug_info,
|
|
||||||
.silent = false,
|
|
||||||
});
|
|
||||||
},
|
|
||||||
.@"test" => {
|
|
||||||
if (arguments.len != 2) {
|
|
||||||
fail();
|
|
||||||
}
|
|
||||||
|
|
||||||
const stop_at_failure = true;
|
|
||||||
|
|
||||||
var build_modes: [@typeInfo(BuildMode).@"enum".fields.len]BuildMode = undefined;
|
|
||||||
inline for (@typeInfo(BuildMode).@"enum".fields, 0..) |field, field_index| {
|
|
||||||
const build_mode = @field(BuildMode, field.name);
|
|
||||||
build_modes[field_index] = build_mode;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (names) |name| {
|
|
||||||
for (build_modes) |build_mode| {
|
|
||||||
for ([2]bool{ true, false }) |has_debug_info| {
|
|
||||||
const position = arena.position;
|
|
||||||
defer arena.restore(position);
|
|
||||||
|
|
||||||
const relative_file_path = arena.join_string(&.{ "tests/", name, ".bbb" });
|
|
||||||
const compile_result = compile_file(arena, .{
|
|
||||||
.relative_file_path = relative_file_path,
|
|
||||||
.build_mode = build_mode,
|
|
||||||
.has_debug_info = has_debug_info,
|
|
||||||
.silent = true,
|
|
||||||
});
|
|
||||||
|
|
||||||
const result = lib.os.run_child_process(arena, &.{compile_result.executable}, environment, .{
|
|
||||||
.stdout = .inherit,
|
|
||||||
.stderr = .inherit,
|
|
||||||
.null_file_descriptor = null,
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!result.is_successful()) {
|
|
||||||
lib.print_string("[BOOTSTRAP] Failed to run test ");
|
|
||||||
lib.print_string(name);
|
|
||||||
lib.print_string(" with build mode ");
|
|
||||||
lib.print_string(@tagName(build_mode));
|
|
||||||
lib.print_string("\n");
|
|
||||||
|
|
||||||
if (stop_at_failure) {
|
|
||||||
lib.libc.exit(1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const relative_file_path = arena.join_string(&.{"src/compiler.bbb"});
|
|
||||||
for (build_modes) |build_mode| {
|
|
||||||
for ([2]bool{ true, false }) |has_debug_info| {
|
|
||||||
const position = arena.position;
|
|
||||||
defer arena.restore(position);
|
|
||||||
|
|
||||||
const compile_result = compile_file(arena, .{
|
|
||||||
.relative_file_path = relative_file_path,
|
|
||||||
.build_mode = build_mode,
|
|
||||||
.has_debug_info = has_debug_info,
|
|
||||||
.silent = true,
|
|
||||||
});
|
|
||||||
|
|
||||||
for (names[0..1]) |name| {
|
|
||||||
for (build_modes) |self_hosted_build_mode| {
|
|
||||||
for ([2]bool{ true, false }) |self_hosted_has_debug_info| {
|
|
||||||
const self_hosted_relative_file_path = arena.join_string(&.{ "tests/", name, ".bbb" });
|
|
||||||
// TODO: investigar corrupcion de memoria en compile_result.executable porque compile_file borra la memoria
|
|
||||||
const result = lib.os.run_child_process(arena, &.{ compile_result.executable, "compile", self_hosted_relative_file_path, @tagName(self_hosted_build_mode), if (self_hosted_has_debug_info) "true" else "false" }, environment, .{
|
|
||||||
.stdout = .inherit,
|
|
||||||
.stderr = .inherit,
|
|
||||||
.null_file_descriptor = null,
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!result.is_successful()) {
|
|
||||||
lib.print_string("[SELF-HOSTED] Failed to compile ");
|
|
||||||
lib.print_string(name);
|
|
||||||
lib.print_string(" with build mode ");
|
|
||||||
lib.print_string(@tagName(build_mode));
|
|
||||||
lib.print_string(" and debug info ");
|
|
||||||
lib.print_string(if (has_debug_info) "on" else "off");
|
|
||||||
lib.print_string(", with self-hosted build mode ");
|
|
||||||
lib.print_string(@tagName(self_hosted_build_mode));
|
|
||||||
lib.print_string(" and self-hosted debug info ");
|
|
||||||
lib.print_string(if (self_hosted_has_debug_info) "on" else "off");
|
|
||||||
lib.print_string("\n");
|
|
||||||
|
|
||||||
if (stop_at_failure) {
|
|
||||||
lib.libc.exit(1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const names = &[_][]const u8{
|
|
||||||
"minimal",
|
|
||||||
"comments",
|
|
||||||
"constant_add",
|
|
||||||
"constant_and",
|
|
||||||
"constant_div",
|
|
||||||
"constant_mul",
|
|
||||||
"constant_rem",
|
|
||||||
"constant_or",
|
|
||||||
"constant_sub",
|
|
||||||
"constant_xor",
|
|
||||||
"constant_shift_left",
|
|
||||||
"constant_shift_right",
|
|
||||||
"minimal_stack",
|
|
||||||
"minimal_stack_arithmetic",
|
|
||||||
"minimal_stack_arithmetic2",
|
|
||||||
"minimal_stack_arithmetic3",
|
|
||||||
"extend",
|
|
||||||
"stack_negation",
|
|
||||||
"stack_add",
|
|
||||||
"stack_sub",
|
|
||||||
"integer_max",
|
|
||||||
"integer_hex",
|
|
||||||
"basic_pointer",
|
|
||||||
"basic_call",
|
|
||||||
"pointer",
|
|
||||||
"pointer_cast",
|
|
||||||
"u1_return",
|
|
||||||
"local_type_inference",
|
|
||||||
"global",
|
|
||||||
"function_pointer",
|
|
||||||
"extern",
|
|
||||||
"byte_size",
|
|
||||||
"basic_branch",
|
|
||||||
"basic_array",
|
|
||||||
"basic_enum",
|
|
||||||
"argv",
|
|
||||||
"assignment_operators",
|
|
||||||
"basic_enum",
|
|
||||||
"basic_slice",
|
|
||||||
"basic_string",
|
|
||||||
"basic_varargs",
|
|
||||||
"basic_while",
|
|
||||||
"not_pointer",
|
|
||||||
"bits",
|
|
||||||
"bits_no_backing_type",
|
|
||||||
"bits_return_u1",
|
|
||||||
"bits_zero",
|
|
||||||
"comparison",
|
|
||||||
"global_struct",
|
|
||||||
"if_no_else",
|
|
||||||
"if_no_else_void",
|
|
||||||
"indirect",
|
|
||||||
"indirect_struct",
|
|
||||||
"indirect_varargs",
|
|
||||||
"ret_c_bool",
|
|
||||||
"return_type_builtin",
|
|
||||||
"return_u64_u64",
|
|
||||||
"select",
|
|
||||||
"slice",
|
|
||||||
"small_struct_ints",
|
|
||||||
"struct_assignment",
|
|
||||||
"struct",
|
|
||||||
"struct_u64_u64",
|
|
||||||
"struct_varargs",
|
|
||||||
"struct_zero",
|
|
||||||
"unreachable",
|
|
||||||
"varargs",
|
|
||||||
"c_abi0",
|
|
||||||
"c_abi1",
|
|
||||||
"c_med_struct_ints",
|
|
||||||
"c_ret_struct_array",
|
|
||||||
"c_split_struct_ints",
|
|
||||||
"c_string_to_slice",
|
|
||||||
"c_struct_with_array",
|
|
||||||
"c_function_pointer",
|
|
||||||
"c_abi",
|
|
||||||
};
|
|
@ -1,20 +0,0 @@
|
|||||||
const std = @import("std");
|
|
||||||
export fn enable_signal_handlers() void {
|
|
||||||
std.debug.attachSegfaultHandler();
|
|
||||||
}
|
|
||||||
|
|
||||||
export fn dump_stack_trace(return_address: usize) void {
|
|
||||||
const stderr = std.io.getStdErr().writer();
|
|
||||||
if (@import("builtin").strip_debug_info) {
|
|
||||||
stderr.print("Unable to dump stack trace: debug info stripped\n", .{}) catch return;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const debug_info = std.debug.getSelfDebugInfo() catch |err| {
|
|
||||||
stderr.print("Unable to dump stack trace: Unable to open debug info: {s}\n", .{@errorName(err)}) catch return;
|
|
||||||
return;
|
|
||||||
};
|
|
||||||
std.debug.writeCurrentStackTrace(stderr, debug_info, std.io.tty.detectConfig(std.io.getStdErr()), return_address) catch |err| {
|
|
||||||
stderr.print("Unable to dump stack trace: {s}\n", .{@errorName(err)}) catch return;
|
|
||||||
return;
|
|
||||||
};
|
|
||||||
}
|
|
4
tests/add_sub.nat
Normal file
4
tests/add_sub.nat
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
fn main() s32
|
||||||
|
{
|
||||||
|
return 1 - 1 + 1 - 1;
|
||||||
|
}
|
4
tests/and.nat
Normal file
4
tests/and.nat
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
fn main() s32
|
||||||
|
{
|
||||||
|
return 1 & 0;
|
||||||
|
}
|
@ -1,13 +0,0 @@
|
|||||||
[export] main = fn [cc(c)] (argument_count: u32, argument_pointer: &&u8) s32
|
|
||||||
{
|
|
||||||
if (argument_count != 1)
|
|
||||||
{
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
>arg = argument_pointer[0];
|
|
||||||
if (arg != argument_pointer[0])
|
|
||||||
{
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
@ -1,35 +0,0 @@
|
|||||||
unsigned = fn(n: s32) s32
|
|
||||||
{
|
|
||||||
>result: u32 = #extend(n);
|
|
||||||
result >>= 1;
|
|
||||||
result <<= 1;
|
|
||||||
result ^= 1;
|
|
||||||
result |= 1;
|
|
||||||
result &= 1;
|
|
||||||
result += 1;
|
|
||||||
result -= 1;
|
|
||||||
result /= 1;
|
|
||||||
result %= 1;
|
|
||||||
result *= 0;
|
|
||||||
|
|
||||||
return #extend(result);
|
|
||||||
}
|
|
||||||
|
|
||||||
[export] main = fn [cc(c)] () s32
|
|
||||||
{
|
|
||||||
>result: s32 = 0;
|
|
||||||
>pointer = &result;
|
|
||||||
pointer -= 1;
|
|
||||||
pointer += 1;
|
|
||||||
result >>= 1;
|
|
||||||
result <<= 1;
|
|
||||||
result ^= 1;
|
|
||||||
result |= 1;
|
|
||||||
result &= 1;
|
|
||||||
result += 1;
|
|
||||||
result -= 1;
|
|
||||||
result /= 1;
|
|
||||||
result %= 1;
|
|
||||||
result *= 0;
|
|
||||||
return unsigned(result);
|
|
||||||
}
|
|
@ -1,5 +0,0 @@
|
|||||||
[export] main = fn [cc(c)] () s32
|
|
||||||
{
|
|
||||||
>array: [_]s32 = [3, 2, 1, 0];
|
|
||||||
return array[3];
|
|
||||||
}
|
|
@ -1,12 +0,0 @@
|
|||||||
[export] main = fn [cc(c)] () s32
|
|
||||||
{
|
|
||||||
>result: s32 = 1;
|
|
||||||
if (result != 1)
|
|
||||||
{
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,9 +0,0 @@
|
|||||||
foo = fn() s32
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
[export] main = fn[cc(c)] () s32
|
|
||||||
{
|
|
||||||
return foo();
|
|
||||||
}
|
|
@ -1,18 +0,0 @@
|
|||||||
E = enum
|
|
||||||
{
|
|
||||||
zero = 0,
|
|
||||||
one = 1,
|
|
||||||
two = 2,
|
|
||||||
three = 3,
|
|
||||||
}
|
|
||||||
|
|
||||||
[export] main = fn [cc(c)] () s32
|
|
||||||
{
|
|
||||||
>a: E = .three;
|
|
||||||
>b: E = .two;
|
|
||||||
>c: E = .one;
|
|
||||||
>a_int: s32 = #extend(#int_from_enum(a));
|
|
||||||
>b_int: s32 = #extend(#int_from_enum(b));
|
|
||||||
>c_int: s32 = #extend(#int_from_enum(c));
|
|
||||||
return a_int - (b_int + c_int);
|
|
||||||
}
|
|
@ -1,6 +0,0 @@
|
|||||||
[export] main = fn [cc(c)] () s32
|
|
||||||
{
|
|
||||||
>a: s32 = 0;
|
|
||||||
>pointer = &a;
|
|
||||||
return pointer.&;
|
|
||||||
}
|
|
@ -1,22 +0,0 @@
|
|||||||
require = fn (ok: u1) void
|
|
||||||
{
|
|
||||||
if (!ok)
|
|
||||||
{
|
|
||||||
#trap();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
slice_receiver = fn (slice: []u8) void
|
|
||||||
{
|
|
||||||
require(slice.length == 3);
|
|
||||||
require(slice[0] == 0);
|
|
||||||
require(slice[1] == 1);
|
|
||||||
require(slice[2] == 2);
|
|
||||||
}
|
|
||||||
|
|
||||||
[export] main = fn [cc(c)] () s32
|
|
||||||
{
|
|
||||||
>a: [_]u8 = [0, 1, 2];
|
|
||||||
slice_receiver(&a);
|
|
||||||
return 0;
|
|
||||||
}
|
|
@ -1,16 +0,0 @@
|
|||||||
require = fn (ok: u1) void
|
|
||||||
{
|
|
||||||
if (!ok)
|
|
||||||
{
|
|
||||||
#trap();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[export] main = fn [cc(c)] () s32
|
|
||||||
{
|
|
||||||
>string = "abc";
|
|
||||||
require(string[0] == 'a');
|
|
||||||
require(string[1] == 'b');
|
|
||||||
require(string[2] == 'c');
|
|
||||||
return 0;
|
|
||||||
}
|
|
@ -1,26 +0,0 @@
|
|||||||
E = enum
|
|
||||||
{
|
|
||||||
a,
|
|
||||||
b,
|
|
||||||
c,
|
|
||||||
}
|
|
||||||
|
|
||||||
[export] main = fn [cc(c)] () s32
|
|
||||||
{
|
|
||||||
>some_enum: E = .a;
|
|
||||||
switch (some_enum)
|
|
||||||
{
|
|
||||||
.a =>
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
},
|
|
||||||
.b =>
|
|
||||||
{
|
|
||||||
return 1;
|
|
||||||
},
|
|
||||||
.c =>
|
|
||||||
{
|
|
||||||
return 1;
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,29 +0,0 @@
|
|||||||
va_arg_fn = fn [cc(c)] (first_arg: u32, ...) void
|
|
||||||
{
|
|
||||||
if (first_arg != 123456789)
|
|
||||||
{
|
|
||||||
#trap();
|
|
||||||
}
|
|
||||||
|
|
||||||
>va = #va_start();
|
|
||||||
|
|
||||||
>a = #va_arg(&va, u32);
|
|
||||||
if (a != 987654321)
|
|
||||||
{
|
|
||||||
#trap();
|
|
||||||
}
|
|
||||||
|
|
||||||
>first_arg_b = #va_arg(&va, u32);
|
|
||||||
if (first_arg_b != 123456789)
|
|
||||||
{
|
|
||||||
#trap();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[export] main = fn [cc(c)] () s32
|
|
||||||
{
|
|
||||||
>first_arg: u32 = 123456789;
|
|
||||||
>a: u32 = 987654321;
|
|
||||||
va_arg_fn(first_arg, a, first_arg);
|
|
||||||
return 0;
|
|
||||||
}
|
|
@ -1,38 +0,0 @@
|
|||||||
c_string_length = fn (c_string: &u8) u64
|
|
||||||
{
|
|
||||||
>it = c_string;
|
|
||||||
|
|
||||||
while (it.&)
|
|
||||||
{
|
|
||||||
it = it + 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return #int_from_pointer(it) - #int_from_pointer(c_string);
|
|
||||||
}
|
|
||||||
|
|
||||||
[export] main = fn (argument_count: u32, argument_pointer: &&u8) s32
|
|
||||||
{
|
|
||||||
if (argument_count == 0)
|
|
||||||
{
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
>first_arg = argument_pointer[0];
|
|
||||||
if (!first_arg)
|
|
||||||
{
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
>arg_length = c_string_length(first_arg);
|
|
||||||
if (arg_length == 0)
|
|
||||||
{
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (first_arg[arg_length] != 0)
|
|
||||||
{
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
@ -1,18 +0,0 @@
|
|||||||
BitField = bits u8
|
|
||||||
{
|
|
||||||
a: u2,
|
|
||||||
b: u2,
|
|
||||||
c: u2,
|
|
||||||
d: u2,
|
|
||||||
};
|
|
||||||
|
|
||||||
[export] main = fn [cc(c)] () s32
|
|
||||||
{
|
|
||||||
>b: BitField = {
|
|
||||||
.a = 3,
|
|
||||||
.b = 2,
|
|
||||||
.c = 2,
|
|
||||||
.d = 3,
|
|
||||||
};
|
|
||||||
return #extend((b.a - b.d) + (b.b - b.c));
|
|
||||||
}
|
|
@ -1,13 +0,0 @@
|
|||||||
A = bits {
|
|
||||||
a: u1,
|
|
||||||
b: u1,
|
|
||||||
}
|
|
||||||
|
|
||||||
[export] main = fn [cc(c)] () s32
|
|
||||||
{
|
|
||||||
>a: A = {
|
|
||||||
.a = 1,
|
|
||||||
.b = 1,
|
|
||||||
};
|
|
||||||
return #extend(a.a - a.b);
|
|
||||||
}
|
|
@ -1,17 +0,0 @@
|
|||||||
S = bits u32
|
|
||||||
{
|
|
||||||
a: u1,
|
|
||||||
b: u1,
|
|
||||||
c: u1,
|
|
||||||
}
|
|
||||||
|
|
||||||
foo = fn () u1
|
|
||||||
{
|
|
||||||
>a: S = { .a = 1, .b = 1, .c = 0 };
|
|
||||||
return a.c;
|
|
||||||
}
|
|
||||||
|
|
||||||
[export] main = fn [cc(c)] () s32
|
|
||||||
{
|
|
||||||
return #extend(foo() == 1);
|
|
||||||
}
|
|
@ -1,35 +0,0 @@
|
|||||||
require = fn (ok: u1) void
|
|
||||||
{
|
|
||||||
if (!ok)
|
|
||||||
{
|
|
||||||
#trap();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
S = bits
|
|
||||||
{
|
|
||||||
a: u1,
|
|
||||||
b: u1,
|
|
||||||
c: u1,
|
|
||||||
}
|
|
||||||
|
|
||||||
[export] main = fn () s32
|
|
||||||
{
|
|
||||||
>a: S = zero;
|
|
||||||
|
|
||||||
require(a.a == 0);
|
|
||||||
require(a.b == 0);
|
|
||||||
require(a.c == 0);
|
|
||||||
|
|
||||||
>b: S = {
|
|
||||||
.a = 1,
|
|
||||||
.b = 1,
|
|
||||||
zero,
|
|
||||||
};
|
|
||||||
|
|
||||||
require(b.a == 1);
|
|
||||||
require(b.b == 1);
|
|
||||||
require(b.c == 0);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
166
tests/break_continue.nat
Normal file
166
tests/break_continue.nat
Normal file
@ -0,0 +1,166 @@
|
|||||||
|
fn fn0(arg: s32) s32
|
||||||
|
{
|
||||||
|
>a = arg;
|
||||||
|
while (a < 10)
|
||||||
|
{
|
||||||
|
a = a + 1;
|
||||||
|
if (a == 5)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (a == 6)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn fn1(arg: s32) s32
|
||||||
|
{
|
||||||
|
>a: s32 = 1;
|
||||||
|
>i = arg;
|
||||||
|
while (i < 10)
|
||||||
|
{
|
||||||
|
i = i + 1;
|
||||||
|
if (i == 5)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i == 7)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
a = a + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn fn2(arg: s32) s32
|
||||||
|
{
|
||||||
|
>i = arg;
|
||||||
|
while (i < 10)
|
||||||
|
{
|
||||||
|
i = i + 1;
|
||||||
|
if (i == 5)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i == 6)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn fn3(arg: s32) s32
|
||||||
|
{
|
||||||
|
>i = arg;
|
||||||
|
while (i < 10)
|
||||||
|
{
|
||||||
|
i = i + 1;
|
||||||
|
if (i == 6)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn fn4(arg: s32) s32
|
||||||
|
{
|
||||||
|
>i = arg;
|
||||||
|
while (i < 10)
|
||||||
|
{
|
||||||
|
i = i + 1;
|
||||||
|
if (i == 5)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (i == 6)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn fn5(arg: s32) s32
|
||||||
|
{
|
||||||
|
>i = arg;
|
||||||
|
while (i < 10)
|
||||||
|
{
|
||||||
|
i = i + 1;
|
||||||
|
if (i == 5)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn fn6(arg: s32) s32
|
||||||
|
{
|
||||||
|
>i = arg;
|
||||||
|
while (i < 10)
|
||||||
|
{
|
||||||
|
>a = i + 2;
|
||||||
|
if (a > 4)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn fn7(arg: s32) s32
|
||||||
|
{
|
||||||
|
>i = arg;
|
||||||
|
while (i < 10)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn fn8(arg: s32) s32
|
||||||
|
{
|
||||||
|
>a: s32 = 1;
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
a = a + 1;
|
||||||
|
if (a < 10)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn[cc(.c)] main[export]() s32
|
||||||
|
{
|
||||||
|
return fn0(0) +
|
||||||
|
fn1(1) +
|
||||||
|
fn2(2) +
|
||||||
|
fn3(3) +
|
||||||
|
fn4(4) +
|
||||||
|
fn5(5) +
|
||||||
|
fn6(6) +
|
||||||
|
fn7(7) +
|
||||||
|
fn8(8);
|
||||||
|
}
|
@ -1,6 +0,0 @@
|
|||||||
[export] main = fn [cc(c)] () s32
|
|
||||||
{
|
|
||||||
>a: s32 = #byte_size(s32);
|
|
||||||
>b: s32 = #byte_size(s32);
|
|
||||||
return a - b;
|
|
||||||
}
|
|
539
tests/c_abi.bbb
539
tests/c_abi.bbb
@ -1,539 +0,0 @@
|
|||||||
Struct_u64_u64 = struct
|
|
||||||
{
|
|
||||||
a: u64,
|
|
||||||
b: u64,
|
|
||||||
}
|
|
||||||
|
|
||||||
BigStruct = struct
|
|
||||||
{
|
|
||||||
a: u64,
|
|
||||||
b: u64,
|
|
||||||
c: u64,
|
|
||||||
d: u64,
|
|
||||||
e: u8,
|
|
||||||
}
|
|
||||||
|
|
||||||
SmallPackedStruct = bits u8
|
|
||||||
{
|
|
||||||
a: u2,
|
|
||||||
b: u2,
|
|
||||||
c: u2,
|
|
||||||
d: u2,
|
|
||||||
}
|
|
||||||
|
|
||||||
SmallStructInts = struct
|
|
||||||
{
|
|
||||||
a: u8,
|
|
||||||
b: u8,
|
|
||||||
c: u8,
|
|
||||||
d: u8,
|
|
||||||
}
|
|
||||||
|
|
||||||
SplitStructInt = struct
|
|
||||||
{
|
|
||||||
a: u64,
|
|
||||||
b: u8,
|
|
||||||
c: u32,
|
|
||||||
}
|
|
||||||
|
|
||||||
MedStructInts = struct
|
|
||||||
{
|
|
||||||
x: s32,
|
|
||||||
y: s32,
|
|
||||||
z: s32,
|
|
||||||
}
|
|
||||||
|
|
||||||
Rect = struct
|
|
||||||
{
|
|
||||||
left: u32,
|
|
||||||
right: u32,
|
|
||||||
top: u32,
|
|
||||||
bottom: u32,
|
|
||||||
}
|
|
||||||
|
|
||||||
StructWithArray = struct
|
|
||||||
{
|
|
||||||
a: s32,
|
|
||||||
padding: [4]u8,
|
|
||||||
b: s64,
|
|
||||||
}
|
|
||||||
|
|
||||||
ByRef = struct
|
|
||||||
{
|
|
||||||
val: s32,
|
|
||||||
arr: [15]s32,
|
|
||||||
}
|
|
||||||
|
|
||||||
ByValOrigin = struct
|
|
||||||
{
|
|
||||||
x: u64,
|
|
||||||
y: u64,
|
|
||||||
z: u64,
|
|
||||||
}
|
|
||||||
|
|
||||||
ByValSize = struct
|
|
||||||
{
|
|
||||||
width: u64,
|
|
||||||
height: u64,
|
|
||||||
depth: u64,
|
|
||||||
}
|
|
||||||
|
|
||||||
ByVal = struct
|
|
||||||
{
|
|
||||||
origin: ByValOrigin,
|
|
||||||
size: ByValSize,
|
|
||||||
}
|
|
||||||
|
|
||||||
[extern] run_c_tests = fn [cc(c)] () void;
|
|
||||||
|
|
||||||
[extern] c_u8 = fn [cc(c)] (x: u8) void;
|
|
||||||
[extern] c_u16 = fn [cc(c)] (x: u16) void;
|
|
||||||
[extern] c_u32 = fn [cc(c)] (x: u32) void;
|
|
||||||
[extern] c_u64 = fn [cc(c)] (x: u64) void;
|
|
||||||
|
|
||||||
[extern] c_s8 = fn [cc(c)] (x: s8) void;
|
|
||||||
[extern] c_s16 = fn [cc(c)] (x: s16) void;
|
|
||||||
[extern] c_s32 = fn [cc(c)] (x: s32) void;
|
|
||||||
[extern] c_s64 = fn [cc(c)] (x: s64) void;
|
|
||||||
|
|
||||||
[extern] c_bool = fn [cc(c)] (x: u8) void;
|
|
||||||
|
|
||||||
[extern] c_five_integers = fn [cc(c)] (a: s32, b: s32, c: s32, d: s32, e: s32) void;
|
|
||||||
[extern] c_ret_struct_u64_u64 = fn [cc(c)] () Struct_u64_u64;
|
|
||||||
|
|
||||||
[extern] c_struct_u64_u64_0 = fn [cc(c)] (a: Struct_u64_u64) void;
|
|
||||||
[extern] c_struct_u64_u64_1 = fn [cc(c)] (a: u64, b: Struct_u64_u64) void;
|
|
||||||
[extern] c_struct_u64_u64_2 = fn [cc(c)] (a: u64, b: u64, c: Struct_u64_u64) void;
|
|
||||||
[extern] c_struct_u64_u64_3 = fn [cc(c)] (a: u64, b: u64, c: u64, d: Struct_u64_u64) void;
|
|
||||||
[extern] c_struct_u64_u64_4 = fn [cc(c)] (a: u64, b: u64, c: u64, d: u64, e: Struct_u64_u64) void;
|
|
||||||
[extern] c_struct_u64_u64_5 = fn [cc(c)] (a: u64, b: u64, c: u64, d: u64, e: u64, f: Struct_u64_u64) void;
|
|
||||||
[extern] c_struct_u64_u64_6 = fn [cc(c)] (a: u64, b: u64, c: u64, d: u64, e: u64, f: u64, g: Struct_u64_u64) void;
|
|
||||||
[extern] c_struct_u64_u64_7 = fn [cc(c)] (a: u64, b: u64, c: u64, d: u64, e: u64, f: u64, g: u64, h: Struct_u64_u64) void;
|
|
||||||
[extern] c_struct_u64_u64_8 = fn [cc(c)] (a: u64, b: u64, c: u64, d: u64, e: u64, f: u64, g: u64, h: u64, i: Struct_u64_u64) void;
|
|
||||||
|
|
||||||
[extern] c_big_struct = fn [cc(c)] (x: BigStruct) void;
|
|
||||||
[extern] c_small_struct_ints = fn [cc(c)] (x: SmallStructInts) void;
|
|
||||||
[extern] c_ret_small_struct_ints = fn [cc(c)] () SmallStructInts;
|
|
||||||
[extern] c_med_struct_ints = fn [cc(c)] (x: MedStructInts) void;
|
|
||||||
[extern] c_ret_med_struct_ints = fn [cc(c)] () MedStructInts;
|
|
||||||
[extern] c_small_packed_struct = fn [cc(c)] (x: SmallPackedStruct) void;
|
|
||||||
[extern] c_ret_small_packed_struct = fn [cc(c)] () SmallPackedStruct;
|
|
||||||
[extern] c_split_struct_ints = fn [cc(c)] (x: SplitStructInt) void;
|
|
||||||
[extern] c_big_struct_both = fn [cc(c)] (x: BigStruct) BigStruct;
|
|
||||||
[extern] c_multiple_struct_ints = fn [cc(c)] (a: Rect, b: Rect) void;
|
|
||||||
|
|
||||||
[extern] c_ret_bool = fn [cc(c)] () u8;
|
|
||||||
|
|
||||||
[extern] c_ret_u8 = fn [cc(c)] () u8;
|
|
||||||
[extern] c_ret_u16 = fn [cc(c)] () u16;
|
|
||||||
[extern] c_ret_u32 = fn [cc(c)] () u32;
|
|
||||||
[extern] c_ret_u64 = fn [cc(c)] () u64;
|
|
||||||
|
|
||||||
[extern] c_ret_s8 = fn [cc(c)] () s8;
|
|
||||||
[extern] c_ret_s16 = fn [cc(c)] () s16;
|
|
||||||
[extern] c_ret_s32 = fn [cc(c)] () s32;
|
|
||||||
[extern] c_ret_s64 = fn [cc(c)] () s64;
|
|
||||||
|
|
||||||
[extern] c_struct_with_array = fn [cc(c)] (x: StructWithArray) void;
|
|
||||||
[extern] c_ret_struct_with_array = fn [cc(c)] () StructWithArray;
|
|
||||||
|
|
||||||
[extern] c_modify_by_ref_param = fn [cc(c)] (x: ByRef) ByRef;
|
|
||||||
[extern] c_func_ptr_byval = fn [cc(c)] (a: u64, b: u64, c: ByVal, d: u64, e: u64, f: u64) void;
|
|
||||||
|
|
||||||
require = fn (ok: u1) void
|
|
||||||
{
|
|
||||||
if (!ok)
|
|
||||||
{
|
|
||||||
#trap();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[export] main = fn [cc(c)] () s32
|
|
||||||
{
|
|
||||||
run_c_tests();
|
|
||||||
c_u8(0xff);
|
|
||||||
c_u16(0xfffe);
|
|
||||||
c_u32(0xfffffffd);
|
|
||||||
c_u64(0xfffffffffffffffc);
|
|
||||||
|
|
||||||
//if (has_i128) {
|
|
||||||
// c_struct_u128({ .value = 0xfffffffffffffffc, });
|
|
||||||
//}
|
|
||||||
|
|
||||||
c_s8(-1);
|
|
||||||
c_s16(-2);
|
|
||||||
c_s32(-3);
|
|
||||||
c_s64(-4);
|
|
||||||
|
|
||||||
//if (has_i128) {
|
|
||||||
// c_struct_i128({ .value = -6, });
|
|
||||||
//}
|
|
||||||
|
|
||||||
c_bool(1);
|
|
||||||
|
|
||||||
c_five_integers(12, 34, 56, 78, 90);
|
|
||||||
|
|
||||||
>s = c_ret_struct_u64_u64();
|
|
||||||
require(s.a == 21);
|
|
||||||
require(s.b == 22);
|
|
||||||
c_struct_u64_u64_0({ .a = 23, .b = 24, });
|
|
||||||
c_struct_u64_u64_1(0, { .a = 25, .b = 26, });
|
|
||||||
c_struct_u64_u64_2(0, 1, { .a = 27, .b = 28, });
|
|
||||||
c_struct_u64_u64_3(0, 1, 2, { .a = 29, .b = 30, });
|
|
||||||
c_struct_u64_u64_4(0, 1, 2, 3, { .a = 31, .b = 32, });
|
|
||||||
c_struct_u64_u64_5(0, 1, 2, 3, 4, { .a = 33, .b = 34, });
|
|
||||||
c_struct_u64_u64_6(0, 1, 2, 3, 4, 5, { .a = 35, .b = 36, });
|
|
||||||
c_struct_u64_u64_7(0, 1, 2, 3, 4, 5, 6, { .a = 37, .b = 38, });
|
|
||||||
c_struct_u64_u64_8(0, 1, 2, 3, 4, 5, 6, 7, { .a = 39, .b = 40, });
|
|
||||||
|
|
||||||
>big_struct: BigStruct = {
|
|
||||||
.a = 1,
|
|
||||||
.b = 2,
|
|
||||||
.c = 3,
|
|
||||||
.d = 4,
|
|
||||||
.e = 5,
|
|
||||||
};
|
|
||||||
c_big_struct(big_struct);
|
|
||||||
|
|
||||||
>small: SmallStructInts = {
|
|
||||||
.a = 1,
|
|
||||||
.b = 2,
|
|
||||||
.c = 3,
|
|
||||||
.d = 4,
|
|
||||||
};
|
|
||||||
c_small_struct_ints(small);
|
|
||||||
>small2 = c_ret_small_struct_ints();
|
|
||||||
require(small2.a == 1);
|
|
||||||
require(small2.b == 2);
|
|
||||||
require(small2.c == 3);
|
|
||||||
require(small2.d == 4);
|
|
||||||
|
|
||||||
>med: MedStructInts = {
|
|
||||||
.x = 1,
|
|
||||||
.y = 2,
|
|
||||||
.z = 3,
|
|
||||||
};
|
|
||||||
c_med_struct_ints(med);
|
|
||||||
>med2 = c_ret_med_struct_ints();
|
|
||||||
require(med2.x == 1);
|
|
||||||
require(med2.y == 2);
|
|
||||||
require(med2.z == 3);
|
|
||||||
|
|
||||||
>p: SmallPackedStruct = { .a = 0, .b = 1, .c = 2, .d = 3, };
|
|
||||||
c_small_packed_struct(p);
|
|
||||||
>p2 = c_ret_small_packed_struct();
|
|
||||||
require(p2.a == 0);
|
|
||||||
require(p2.b == 1);
|
|
||||||
require(p2.c == 2);
|
|
||||||
require(p2.d == 3);
|
|
||||||
|
|
||||||
>split: SplitStructInt = {
|
|
||||||
.a = 1234,
|
|
||||||
.b = 100,
|
|
||||||
.c = 1337,
|
|
||||||
};
|
|
||||||
c_split_struct_ints(split);
|
|
||||||
|
|
||||||
> big: BigStruct = {
|
|
||||||
.a = 1,
|
|
||||||
.b = 2,
|
|
||||||
.c = 3,
|
|
||||||
.d = 4,
|
|
||||||
.e = 5,
|
|
||||||
};
|
|
||||||
>big2 = c_big_struct_both(big);
|
|
||||||
require(big2.a == 10);
|
|
||||||
require(big2.b == 11);
|
|
||||||
require(big2.c == 12);
|
|
||||||
require(big2.d == 13);
|
|
||||||
require(big2.e == 14);
|
|
||||||
|
|
||||||
>r1: Rect = {
|
|
||||||
.left = 1,
|
|
||||||
.right = 21,
|
|
||||||
.top = 16,
|
|
||||||
.bottom = 4,
|
|
||||||
};
|
|
||||||
>r2: Rect = {
|
|
||||||
.left = 178,
|
|
||||||
.right = 189,
|
|
||||||
.top = 21,
|
|
||||||
.bottom = 15,
|
|
||||||
};
|
|
||||||
c_multiple_struct_ints(r1, r2);
|
|
||||||
|
|
||||||
require(c_ret_bool() == 1);
|
|
||||||
|
|
||||||
require(c_ret_u8() == 0xff);
|
|
||||||
require(c_ret_u16() == 0xffff);
|
|
||||||
require(c_ret_u32() == 0xffffffff);
|
|
||||||
require(c_ret_u64() == 0xffffffffffffffff);
|
|
||||||
|
|
||||||
require(c_ret_s8() == -1);
|
|
||||||
require(c_ret_s16() == -1);
|
|
||||||
require(c_ret_s32() == -1);
|
|
||||||
require(c_ret_s64() == -1);
|
|
||||||
|
|
||||||
c_struct_with_array({ .a = 1, .padding = [0, 0, 0, 0], .b = 2, });
|
|
||||||
|
|
||||||
>x = c_ret_struct_with_array();
|
|
||||||
require(x.a == 4);
|
|
||||||
require(x.b == 155);
|
|
||||||
|
|
||||||
>res = c_modify_by_ref_param({ .val = 1, .arr = [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ] });
|
|
||||||
require(res.val == 42);
|
|
||||||
|
|
||||||
>function_pointer = &c_func_ptr_byval;
|
|
||||||
function_pointer(1, 2, { .origin = { .x = 9, .y = 10, .z = 11, }, .size = { .width = 12, .height = 13, .depth = 14, }, }, 3, 4, 5);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
[export] bb_u8 = fn [cc(c)] (x: u8) void
|
|
||||||
{
|
|
||||||
require(x == 0xff);
|
|
||||||
}
|
|
||||||
|
|
||||||
[export] bb_u16 = fn [cc(c)] (x: u16) void
|
|
||||||
{
|
|
||||||
require(x == 0xfffe);
|
|
||||||
}
|
|
||||||
|
|
||||||
[export] bb_u32 = fn [cc(c)] (x: u32) void
|
|
||||||
{
|
|
||||||
require(x == 0xfffffffd);
|
|
||||||
}
|
|
||||||
|
|
||||||
[export] bb_u64 = fn [cc(c)] (x: u64) void
|
|
||||||
{
|
|
||||||
require(x == 0xfffffffffffffffc);
|
|
||||||
}
|
|
||||||
|
|
||||||
[export] bb_s8 = fn [cc(c)] (x: s8) void
|
|
||||||
{
|
|
||||||
require(x == -1);
|
|
||||||
}
|
|
||||||
|
|
||||||
[export] bb_s16 = fn [cc(c)] (x: s16) void
|
|
||||||
{
|
|
||||||
require(x == -2);
|
|
||||||
}
|
|
||||||
|
|
||||||
[export] bb_s32 = fn [cc(c)] (x: s32) void
|
|
||||||
{
|
|
||||||
require(x == -3);
|
|
||||||
}
|
|
||||||
|
|
||||||
[export] bb_s64 = fn [cc(c)] (x: s64) void
|
|
||||||
{
|
|
||||||
require(x == -4);
|
|
||||||
}
|
|
||||||
|
|
||||||
[export] bb_ptr = fn [cc(c)] (x: &u8) void
|
|
||||||
{
|
|
||||||
require(#int_from_pointer(x) == 0xdeadbeef);
|
|
||||||
}
|
|
||||||
|
|
||||||
[export] bb_five_integers = fn [cc(c)] (a: s32, b: s32, c: s32, d: s32, e: s32) void
|
|
||||||
{
|
|
||||||
require(a == 12);
|
|
||||||
require(b == 34);
|
|
||||||
require(c == 56);
|
|
||||||
require(d == 78);
|
|
||||||
require(e == 90);
|
|
||||||
}
|
|
||||||
|
|
||||||
[export] bb_bool = fn [cc(c)] (x: u8) void
|
|
||||||
{
|
|
||||||
require(#truncate(x));
|
|
||||||
}
|
|
||||||
|
|
||||||
[export] bb_ret_struct_u64_u64 = fn [cc(c)] () Struct_u64_u64
|
|
||||||
{
|
|
||||||
return { .a = 1, .b = 2, };
|
|
||||||
}
|
|
||||||
|
|
||||||
[export] bb_struct_u64_u64_0 = fn [cc(c)] (s: Struct_u64_u64) void
|
|
||||||
{
|
|
||||||
require(s.a == 3);
|
|
||||||
require(s.b == 4);
|
|
||||||
}
|
|
||||||
|
|
||||||
[export] bb_struct_u64_u64_1 = fn [cc(c)] (_: u64, s: Struct_u64_u64) void
|
|
||||||
{
|
|
||||||
require(s.a == 5);
|
|
||||||
require(s.b == 6);
|
|
||||||
}
|
|
||||||
|
|
||||||
[export] bb_struct_u64_u64_2 = fn [cc(c)] (_: u64, _: u64, s: Struct_u64_u64) void
|
|
||||||
{
|
|
||||||
require(s.a == 7);
|
|
||||||
require(s.b == 8);
|
|
||||||
}
|
|
||||||
|
|
||||||
[export] bb_struct_u64_u64_3 = fn [cc(c)] (_: u64, _: u64, _: u64, s: Struct_u64_u64) void
|
|
||||||
{
|
|
||||||
require(s.a == 9);
|
|
||||||
require(s.b == 10);
|
|
||||||
}
|
|
||||||
|
|
||||||
[export] bb_struct_u64_u64_4 = fn [cc(c)] (_: u64, _: u64, _: u64, _: u64, s: Struct_u64_u64) void
|
|
||||||
{
|
|
||||||
require(s.a == 11);
|
|
||||||
require(s.b == 12);
|
|
||||||
}
|
|
||||||
|
|
||||||
[export] bb_struct_u64_u64_5 = fn [cc(c)] (_: u64, _: u64, _: u64, _: u64, _: u64, s: Struct_u64_u64) void
|
|
||||||
{
|
|
||||||
require(s.a == 13);
|
|
||||||
require(s.b == 14);
|
|
||||||
}
|
|
||||||
|
|
||||||
[export] bb_struct_u64_u64_6 = fn [cc(c)] (_: u64, _: u64, _: u64, _: u64, _: u64, _: u64, s: Struct_u64_u64) void
|
|
||||||
{
|
|
||||||
require(s.a == 15);
|
|
||||||
require(s.b == 16);
|
|
||||||
}
|
|
||||||
|
|
||||||
[export] bb_struct_u64_u64_7 = fn [cc(c)] (_: u64, _: u64, _: u64, _: u64, _: u64, _: u64, _: u64, s: Struct_u64_u64) void
|
|
||||||
{
|
|
||||||
require(s.a == 17);
|
|
||||||
require(s.b == 18);
|
|
||||||
}
|
|
||||||
|
|
||||||
[export] bb_struct_u64_u64_8 = fn [cc(c)] (_: u64, _: u64, _: u64, _: u64, _: u64, _: u64, _: u64, _: u64, s: Struct_u64_u64) void
|
|
||||||
{
|
|
||||||
require(s.a == 19);
|
|
||||||
require(s.b == 20);
|
|
||||||
}
|
|
||||||
|
|
||||||
[export] bb_big_struct = fn [cc(c)] (x: BigStruct) void
|
|
||||||
{
|
|
||||||
require(x.a == 1);
|
|
||||||
require(x.b == 2);
|
|
||||||
require(x.c == 3);
|
|
||||||
require(x.d == 4);
|
|
||||||
require(x.e == 5);
|
|
||||||
}
|
|
||||||
|
|
||||||
[export] bb_small_packed_struct = fn [cc(c)] (x: SmallPackedStruct) void
|
|
||||||
{
|
|
||||||
require(x.a == 0);
|
|
||||||
require(x.b == 1);
|
|
||||||
require(x.c == 2);
|
|
||||||
require(x.d == 3);
|
|
||||||
}
|
|
||||||
|
|
||||||
[export] bb_split_struct_ints = fn [cc(c)] (x: SplitStructInt) void
|
|
||||||
{
|
|
||||||
require(x.a == 1234);
|
|
||||||
require(x.b == 100);
|
|
||||||
require(x.c == 1337);
|
|
||||||
}
|
|
||||||
|
|
||||||
[export] bb_big_struct_both = fn [cc(c)] (x: BigStruct) BigStruct
|
|
||||||
{
|
|
||||||
require(x.a == 30);
|
|
||||||
require(x.b == 31);
|
|
||||||
require(x.c == 32);
|
|
||||||
require(x.d == 33);
|
|
||||||
require(x.e == 34);
|
|
||||||
>s: BigStruct = {
|
|
||||||
.a = 20,
|
|
||||||
.b = 21,
|
|
||||||
.c = 22,
|
|
||||||
.d = 23,
|
|
||||||
.e = 24,
|
|
||||||
};
|
|
||||||
return s;
|
|
||||||
}
|
|
||||||
|
|
||||||
[export] bb_ret_bool = fn [cc(c)] () u8
|
|
||||||
{
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
[export] bb_ret_u8 = fn [cc(c)] () u8
|
|
||||||
{
|
|
||||||
return 0xff;
|
|
||||||
}
|
|
||||||
|
|
||||||
[export] bb_ret_u16 = fn [cc(c)] () u16
|
|
||||||
{
|
|
||||||
return 0xffff;
|
|
||||||
}
|
|
||||||
|
|
||||||
[export] bb_ret_u32 = fn [cc(c)] () u32
|
|
||||||
{
|
|
||||||
return 0xffffffff;
|
|
||||||
}
|
|
||||||
|
|
||||||
[export] bb_ret_u64 = fn [cc(c)] () u64
|
|
||||||
{
|
|
||||||
return 0xffffffffffffffff;
|
|
||||||
}
|
|
||||||
|
|
||||||
[export] bb_ret_s8 = fn [cc(c)] () s8
|
|
||||||
{
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
[export] bb_ret_s16 = fn [cc(c)] () s16
|
|
||||||
{
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
[export] bb_ret_s32 = fn [cc(c)] () s32
|
|
||||||
{
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
[export] bb_ret_s64 = fn [cc(c)] () s64
|
|
||||||
{
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
[export] bb_ret_small_struct_ints = fn [cc(c)] () SmallStructInts
|
|
||||||
{
|
|
||||||
return {
|
|
||||||
.a = 1,
|
|
||||||
.b = 2,
|
|
||||||
.c = 3,
|
|
||||||
.d = 4,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
[export] bb_ret_med_struct_ints = fn [cc(c)] () MedStructInts
|
|
||||||
{
|
|
||||||
return {
|
|
||||||
.x = 1,
|
|
||||||
.y = 2,
|
|
||||||
.z = 3,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
[export] bb_multiple_struct_ints = fn [cc(c)] (x: Rect, y: Rect) void
|
|
||||||
{
|
|
||||||
require(x.left == 1);
|
|
||||||
require(x.right == 21);
|
|
||||||
require(x.top == 16);
|
|
||||||
require(x.bottom == 4);
|
|
||||||
require(y.left == 178);
|
|
||||||
require(y.right == 189);
|
|
||||||
require(y.top == 21);
|
|
||||||
require(y.bottom == 15);
|
|
||||||
}
|
|
||||||
|
|
||||||
[export] bb_small_struct_ints = fn [cc(c)] (x: SmallStructInts) void
|
|
||||||
{
|
|
||||||
require(x.a == 1);
|
|
||||||
require(x.b == 2);
|
|
||||||
require(x.c == 3);
|
|
||||||
require(x.d == 4);
|
|
||||||
}
|
|
||||||
|
|
||||||
[export] bb_med_struct_ints = fn [cc(c)] (s: MedStructInts) void
|
|
||||||
{
|
|
||||||
require(s.x == 1);
|
|
||||||
require(s.y == 2);
|
|
||||||
require(s.z == 3);
|
|
||||||
}
|
|
5487
tests/c_abi.c
5487
tests/c_abi.c
File diff suppressed because it is too large
Load Diff
@ -1,20 +0,0 @@
|
|||||||
require = fn (ok: u1) void
|
|
||||||
{
|
|
||||||
if (!ok)
|
|
||||||
{
|
|
||||||
#trap();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
c_u8 = fn [cc(c)] (x: u8) void
|
|
||||||
{
|
|
||||||
require(x == 0xff);
|
|
||||||
}
|
|
||||||
|
|
||||||
[export] main = fn [cc(c)] () s32
|
|
||||||
{
|
|
||||||
>v: u8 = 0xff;
|
|
||||||
c_u8(v);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
@ -1,18 +0,0 @@
|
|||||||
require = fn(ok: u1) void
|
|
||||||
{
|
|
||||||
if (!ok)
|
|
||||||
{
|
|
||||||
#trap();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
c_u16 = fn [cc(c)] (v: u16) void
|
|
||||||
{
|
|
||||||
require(v == 0xfffe);
|
|
||||||
}
|
|
||||||
|
|
||||||
[export] main = fn [cc(c)] () s32
|
|
||||||
{
|
|
||||||
c_u16(0xfffe);
|
|
||||||
return 0;
|
|
||||||
}
|
|
@ -1,7 +0,0 @@
|
|||||||
[extern] exit = fn [cc(c)] (exit_code: s32) noreturn;
|
|
||||||
|
|
||||||
[export] main = fn [cc(c)] () s32
|
|
||||||
{
|
|
||||||
>c_function_pointer = &exit;
|
|
||||||
c_function_pointer(0);
|
|
||||||
}
|
|
@ -1,51 +0,0 @@
|
|||||||
require = fn (ok: u1) void
|
|
||||||
{
|
|
||||||
if (!ok)
|
|
||||||
{
|
|
||||||
#trap();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
MedStructInts = struct
|
|
||||||
{
|
|
||||||
x: s32,
|
|
||||||
y: s32,
|
|
||||||
z: s32,
|
|
||||||
}
|
|
||||||
|
|
||||||
bb_ret_med_struct_ints = fn [cc(c)] () MedStructInts
|
|
||||||
{
|
|
||||||
return {
|
|
||||||
.x = 1,
|
|
||||||
.y = 2,
|
|
||||||
.z = 3,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
c_med_struct_ints = fn [cc(c)] (s: MedStructInts) void
|
|
||||||
{
|
|
||||||
require(s.x == 1);
|
|
||||||
require(s.y == 2);
|
|
||||||
require(s.z == 3);
|
|
||||||
|
|
||||||
>s2 = bb_ret_med_struct_ints();
|
|
||||||
|
|
||||||
require(s2.x == 1);
|
|
||||||
require(s2.y == 2);
|
|
||||||
require(s2.z == 3);
|
|
||||||
}
|
|
||||||
|
|
||||||
[export] main = fn [cc(c)] () s32
|
|
||||||
{
|
|
||||||
>med: MedStructInts = {
|
|
||||||
.x = 1,
|
|
||||||
.y = 2,
|
|
||||||
.z = 3,
|
|
||||||
};
|
|
||||||
c_med_struct_ints(med);
|
|
||||||
>med2 = bb_ret_med_struct_ints();
|
|
||||||
require(med2.x == 1);
|
|
||||||
require(med2.y == 2);
|
|
||||||
require(med2.z == 3);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
@ -1,27 +0,0 @@
|
|||||||
StructWithArray = struct
|
|
||||||
{
|
|
||||||
a: u32,
|
|
||||||
padding: [4]u8,
|
|
||||||
c: u64,
|
|
||||||
};
|
|
||||||
|
|
||||||
c_ret_struct_with_array = fn [cc(c)] () StructWithArray
|
|
||||||
{
|
|
||||||
return { .a = 4, .padding = [ 0, 0, 0, 0 ], .c = 155 };
|
|
||||||
}
|
|
||||||
|
|
||||||
require = fn(ok: u1) void
|
|
||||||
{
|
|
||||||
if (!ok)
|
|
||||||
{
|
|
||||||
#trap();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[export] main = fn [cc(c)] () s32
|
|
||||||
{
|
|
||||||
>s = c_ret_struct_with_array();
|
|
||||||
require(s.a == 4);
|
|
||||||
require(s.c == 155);
|
|
||||||
return 0;
|
|
||||||
}
|
|
@ -1,36 +0,0 @@
|
|||||||
SplitStructInt = struct
|
|
||||||
{
|
|
||||||
a: u64,
|
|
||||||
b: u8,
|
|
||||||
c: u32,
|
|
||||||
}
|
|
||||||
|
|
||||||
require = fn (ok: u1) void
|
|
||||||
{
|
|
||||||
if (!ok)
|
|
||||||
{
|
|
||||||
#trap();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bb_split_struct_ints = fn [cc(c)] (x: SplitStructInt) void
|
|
||||||
{
|
|
||||||
require(x.a == 1234);
|
|
||||||
require(x.b == 100);
|
|
||||||
require(x.c == 1337);
|
|
||||||
}
|
|
||||||
|
|
||||||
[export] main = fn [cc(c)] () s32
|
|
||||||
{
|
|
||||||
>split: SplitStructInt = {
|
|
||||||
.a = 1234,
|
|
||||||
.b = 100,
|
|
||||||
.c = 1337,
|
|
||||||
};
|
|
||||||
|
|
||||||
bb_split_struct_ints(split);
|
|
||||||
>a: s32 = #truncate(split.a);
|
|
||||||
>b: s32 = #extend(split.b);
|
|
||||||
>c: s32 = #extend(split.c);
|
|
||||||
return a + b + 3 - c;
|
|
||||||
}
|
|
@ -1,33 +0,0 @@
|
|||||||
require = fn (ok: u1) void
|
|
||||||
{
|
|
||||||
if (!ok)
|
|
||||||
{
|
|
||||||
#trap();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
c_string_length = fn (c_string: &u8) u64
|
|
||||||
{
|
|
||||||
>it = c_string;
|
|
||||||
|
|
||||||
while (it.&)
|
|
||||||
{
|
|
||||||
it = it + 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return #int_from_pointer(it) - #int_from_pointer(c_string);
|
|
||||||
}
|
|
||||||
|
|
||||||
c_string_slice_build = fn (c_string: &u8, length: u64) []u8
|
|
||||||
{
|
|
||||||
return c_string[0..length];
|
|
||||||
}
|
|
||||||
|
|
||||||
[export] main = fn [cc(c)] (argument_count: u32, argument_pointer: &&u8) s32
|
|
||||||
{
|
|
||||||
>length = c_string_length(argument_pointer[0]);
|
|
||||||
>string = c_string_slice_build(argument_pointer[0], length);
|
|
||||||
require(string.pointer == argument_pointer[0]);
|
|
||||||
require(string.length == length);
|
|
||||||
return 0;
|
|
||||||
}
|
|
@ -1,26 +0,0 @@
|
|||||||
require = fn(ok: u1) void
|
|
||||||
{
|
|
||||||
if (!ok)
|
|
||||||
{
|
|
||||||
#trap();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
StructWithArray = struct
|
|
||||||
{
|
|
||||||
a: u32,
|
|
||||||
padding: [4]u8,
|
|
||||||
b: u64,
|
|
||||||
}
|
|
||||||
|
|
||||||
c_struct_with_array = fn [cc(c)] (x: StructWithArray) void
|
|
||||||
{
|
|
||||||
require(x.a == 1);
|
|
||||||
require(x.b == 2);
|
|
||||||
}
|
|
||||||
|
|
||||||
[export] main = fn [cc(c)] () s32
|
|
||||||
{
|
|
||||||
c_struct_with_array({ .a = 1, .padding = [0, 0, 0, 0], .b = 2 });
|
|
||||||
return 0;
|
|
||||||
}
|
|
@ -1,7 +0,0 @@
|
|||||||
[export] main = fn [cc(c)] () s32 // This is a comment
|
|
||||||
// This is a comment
|
|
||||||
{ // This is a comment
|
|
||||||
// This is a comment
|
|
||||||
return 0; // This is a comment
|
|
||||||
}// This is a comment
|
|
||||||
// This is a comment
|
|
@ -1,14 +0,0 @@
|
|||||||
trivial_comparison = fn (a: u32, b: u32) u1
|
|
||||||
{
|
|
||||||
return a + 1 == b + 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
[export] main = fn [cc(c)] (argument_count: u32) s32
|
|
||||||
{
|
|
||||||
>result = trivial_comparison(argument_count, argument_count);
|
|
||||||
if (!result)
|
|
||||||
{
|
|
||||||
#trap();
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
4
tests/comparison.nat
Normal file
4
tests/comparison.nat
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
fn main (argc: s32) s32
|
||||||
|
{
|
||||||
|
return argc != 1;
|
||||||
|
}
|
@ -1,4 +0,0 @@
|
|||||||
[export] main = fn [cc(c)] () s32
|
|
||||||
{
|
|
||||||
return -1 + 1;
|
|
||||||
}
|
|
@ -1,4 +0,0 @@
|
|||||||
[export] main = fn [cc(c)] () s32
|
|
||||||
{
|
|
||||||
return 1 & 2;
|
|
||||||
}
|
|
@ -1,4 +0,0 @@
|
|||||||
[export] main = fn [cc(c)] () s32
|
|
||||||
{
|
|
||||||
return 0 / 5;
|
|
||||||
}
|
|
@ -1,4 +0,0 @@
|
|||||||
[export] main = fn [cc(c)] () s32
|
|
||||||
{
|
|
||||||
return 1 * 0;
|
|
||||||
}
|
|
@ -1,4 +0,0 @@
|
|||||||
[export] main = fn [cc(c)] () s32
|
|
||||||
{
|
|
||||||
return 0 | 0;
|
|
||||||
}
|
|
4
tests/constant_prop.nat
Normal file
4
tests/constant_prop.nat
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
fn[cc(.c)] main [export] () s32
|
||||||
|
{
|
||||||
|
return 2 + 4 - 1 - 5;
|
||||||
|
}
|
@ -1,4 +0,0 @@
|
|||||||
[export] main = fn [cc(c)] () s32
|
|
||||||
{
|
|
||||||
return 5 % 5;
|
|
||||||
}
|
|
@ -1,4 +0,0 @@
|
|||||||
[export] main = fn [cc(c)] () s32
|
|
||||||
{
|
|
||||||
return 0 << 1;
|
|
||||||
}
|
|
@ -1,4 +0,0 @@
|
|||||||
[export] main = fn [cc(c)] () s32
|
|
||||||
{
|
|
||||||
return 0 >> 1;
|
|
||||||
}
|
|
@ -1,5 +0,0 @@
|
|||||||
[export] main = fn [cc(c)] () s32
|
|
||||||
{
|
|
||||||
return 1 - 1;
|
|
||||||
}
|
|
||||||
|
|
@ -1,4 +0,0 @@
|
|||||||
[export] main = fn [cc(c)] () s32
|
|
||||||
{
|
|
||||||
return 0 ^ 0;
|
|
||||||
}
|
|
4
tests/div.nat
Normal file
4
tests/div.nat
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
fn main() s32
|
||||||
|
{
|
||||||
|
return 0 / 1;
|
||||||
|
}
|
@ -1,5 +0,0 @@
|
|||||||
[export] main = fn [cc(c)] () s32
|
|
||||||
{
|
|
||||||
>result: s8 = 0;
|
|
||||||
return #extend(result);
|
|
||||||
}
|
|
@ -1,5 +0,0 @@
|
|||||||
[extern] exit = fn [cc(c)] (exit_code: s32) noreturn;
|
|
||||||
[export] main = fn [cc(c)] () s32
|
|
||||||
{
|
|
||||||
exit(0);
|
|
||||||
}
|
|
4
tests/first.nat
Normal file
4
tests/first.nat
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
fn main () s32
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
10
tests/function_call_args.nat
Normal file
10
tests/function_call_args.nat
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
fn foo(arg: s32) s32
|
||||||
|
{
|
||||||
|
return arg;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn[cc(.c)] main [export] () s32
|
||||||
|
{
|
||||||
|
>arg: s32 = 6;
|
||||||
|
return foo(arg) - arg;
|
||||||
|
}
|
@ -1,10 +0,0 @@
|
|||||||
foo = fn [cc(c)] () s32
|
|
||||||
{
|
|
||||||
return 123;
|
|
||||||
}
|
|
||||||
|
|
||||||
[export] main = fn [cc(c)] () s32
|
|
||||||
{
|
|
||||||
>fn_ptr = &foo;
|
|
||||||
return fn_ptr() - 123;
|
|
||||||
}
|
|
@ -1,5 +0,0 @@
|
|||||||
result: s32 = 0;
|
|
||||||
|
|
||||||
[export] main = fn [cc(c)] () s32 {
|
|
||||||
return result;
|
|
||||||
}
|
|
@ -1,28 +0,0 @@
|
|||||||
S = struct
|
|
||||||
{
|
|
||||||
a: u32,
|
|
||||||
b: u32,
|
|
||||||
c: u32,
|
|
||||||
}
|
|
||||||
|
|
||||||
s: S = {
|
|
||||||
.a = 1,
|
|
||||||
.b = 2,
|
|
||||||
.c = 3,
|
|
||||||
};
|
|
||||||
|
|
||||||
require = fn (ok: u1) void
|
|
||||||
{
|
|
||||||
if (!ok)
|
|
||||||
{
|
|
||||||
#trap();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[export] main = fn () s32
|
|
||||||
{
|
|
||||||
require(s.a == 1);
|
|
||||||
require(s.b == 2);
|
|
||||||
require(s.c == 3);
|
|
||||||
return 0;
|
|
||||||
}
|
|
131
tests/if.nat
Normal file
131
tests/if.nat
Normal file
@ -0,0 +1,131 @@
|
|||||||
|
fn if0(arg: s32) s32
|
||||||
|
{
|
||||||
|
>a: s32 = 1;
|
||||||
|
if (arg == 1)
|
||||||
|
{
|
||||||
|
a = arg + 2;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
a = arg - 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn if1(arg: s32) s32
|
||||||
|
{
|
||||||
|
>c: s32 = 3;
|
||||||
|
>b: s32 = 2;
|
||||||
|
|
||||||
|
if (arg == 1)
|
||||||
|
{
|
||||||
|
b = 3;
|
||||||
|
c = 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn if2(arg: s32) s32
|
||||||
|
{
|
||||||
|
if (arg == 1)
|
||||||
|
{
|
||||||
|
return 3;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return 4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn if3(arg: s32) s32
|
||||||
|
{
|
||||||
|
>a: s32 = arg + 1;
|
||||||
|
>b: s32 = 0;
|
||||||
|
if (arg == 1)
|
||||||
|
{
|
||||||
|
b = a;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
b = a + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return a + b;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn if4(arg: s32) s32
|
||||||
|
{
|
||||||
|
>a: s32 = arg + 1;
|
||||||
|
>b: s32 = arg + 2;
|
||||||
|
if (arg == 1)
|
||||||
|
{
|
||||||
|
b = b + a;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
a = b + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return a + b;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn if5(arg: s32) s32
|
||||||
|
{
|
||||||
|
>a: s32 = 1;
|
||||||
|
|
||||||
|
if (arg == 1)
|
||||||
|
{
|
||||||
|
if (arg == 2)
|
||||||
|
{
|
||||||
|
a = 2;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
a = 3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (arg == 3)
|
||||||
|
{
|
||||||
|
a = 4;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
a = 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn if6(arg: s32) s32
|
||||||
|
{
|
||||||
|
>a: s32 = 0;
|
||||||
|
>b: s32 = 0;
|
||||||
|
if (arg)
|
||||||
|
{
|
||||||
|
a = 1;
|
||||||
|
}
|
||||||
|
if (arg == 0)
|
||||||
|
{
|
||||||
|
b = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
return arg + a + b;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn if7(arg: s32) s32
|
||||||
|
{
|
||||||
|
>a: s32 = arg == 2;
|
||||||
|
if (arg == 1)
|
||||||
|
{
|
||||||
|
a = arg == 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn[cc(.c)] main[export] () s32
|
||||||
|
{
|
||||||
|
return if0(3) + if1(1) - 4 + if2(1) - 3 + if3(1) - 4 + if4(0) - 5 + if5(4) - 5 + if6(0) - 2 + if7(0);
|
||||||
|
}
|
@ -1,9 +0,0 @@
|
|||||||
[export] main = fn [cc(c)] () s32
|
|
||||||
{
|
|
||||||
>a: s32 = 5;
|
|
||||||
if (a == 2)
|
|
||||||
{
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
@ -1,14 +0,0 @@
|
|||||||
require = fn [cc(c)] (ok: u1) void
|
|
||||||
{
|
|
||||||
if (!ok)
|
|
||||||
{
|
|
||||||
#trap();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[export] main = fn [cc(c)] () s32
|
|
||||||
{
|
|
||||||
>result: s32 = 0;
|
|
||||||
require(result == 0);
|
|
||||||
return result;
|
|
||||||
}
|
|
@ -1,45 +0,0 @@
|
|||||||
require = fn (ok: u1) void
|
|
||||||
{
|
|
||||||
if (!ok)
|
|
||||||
{
|
|
||||||
#trap();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
S = struct
|
|
||||||
{
|
|
||||||
a: u32,
|
|
||||||
b: u32,
|
|
||||||
c: u32,
|
|
||||||
d: u32,
|
|
||||||
e: u32,
|
|
||||||
f: u32,
|
|
||||||
}
|
|
||||||
|
|
||||||
ret = fn [cc(c)] () S
|
|
||||||
{
|
|
||||||
return { .a = 56, .b = 57, .c = 58, .d = 59, .e = 60, .f = 61 };
|
|
||||||
}
|
|
||||||
|
|
||||||
arg = fn [cc(c)] (s: S) void
|
|
||||||
{
|
|
||||||
require(s.a == 56);
|
|
||||||
require(s.b == 57);
|
|
||||||
require(s.c == 58);
|
|
||||||
require(s.d == 59);
|
|
||||||
require(s.e == 60);
|
|
||||||
require(s.f == 61);
|
|
||||||
}
|
|
||||||
|
|
||||||
[export] main = fn [cc(c)] () s32
|
|
||||||
{
|
|
||||||
>s = ret();
|
|
||||||
require(s.a == 56);
|
|
||||||
require(s.b == 57);
|
|
||||||
require(s.c == 58);
|
|
||||||
require(s.d == 59);
|
|
||||||
require(s.e == 60);
|
|
||||||
require(s.f == 61);
|
|
||||||
arg(s);
|
|
||||||
return 0;
|
|
||||||
}
|
|
@ -1,46 +0,0 @@
|
|||||||
Struct_u64_u64 = struct
|
|
||||||
{
|
|
||||||
a: u64,
|
|
||||||
b: u64,
|
|
||||||
}
|
|
||||||
|
|
||||||
require = fn (ok: u1) void
|
|
||||||
{
|
|
||||||
if (!ok)
|
|
||||||
{
|
|
||||||
#trap();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
c_struct_u64_u64_5 = fn [cc(c)] (a: u64, b: u64, c: u64, d: u64, e: u64, s: Struct_u64_u64) void
|
|
||||||
{
|
|
||||||
require(s.a == 33);
|
|
||||||
require(s.b == 34);
|
|
||||||
}
|
|
||||||
|
|
||||||
c_struct_u64_u64_6 = fn [cc(c)] (a: u64, b: u64, c: u64, d: u64, e: u64, f: u64, s: Struct_u64_u64) void
|
|
||||||
{
|
|
||||||
require(s.a == 35);
|
|
||||||
require(s.b == 36);
|
|
||||||
}
|
|
||||||
|
|
||||||
c_struct_u64_u64_7 = fn [cc(c)] (a: u64, b: u64, c: u64, d: u64, e: u64, f: u64, g: u64, s: Struct_u64_u64) void
|
|
||||||
{
|
|
||||||
require(s.a == 37);
|
|
||||||
require(s.b == 38);
|
|
||||||
}
|
|
||||||
|
|
||||||
c_struct_u64_u64_8 = fn [cc(c)] (a: u64, b: u64, c: u64, d: u64, e: u64, f: u64, g: u64, h: u64, s: Struct_u64_u64) void
|
|
||||||
{
|
|
||||||
require(s.a == 39);
|
|
||||||
require(s.b == 40);
|
|
||||||
}
|
|
||||||
|
|
||||||
[export] main = fn [cc(c)] () s32
|
|
||||||
{
|
|
||||||
c_struct_u64_u64_5(0, 0, 0, 0, 0, { .a = 33, .b = 34, });
|
|
||||||
c_struct_u64_u64_6(0, 0, 0, 0, 0, 0, { .a = 35, .b = 36, });
|
|
||||||
c_struct_u64_u64_7(0, 0, 0, 0, 0, 0, 0, { .a = 37, .b = 38, });
|
|
||||||
c_struct_u64_u64_8(0, 0, 0, 0, 0, 0, 0, 0, { .a = 39, .b = 40, });
|
|
||||||
return 0;
|
|
||||||
}
|
|
@ -1,62 +0,0 @@
|
|||||||
S = struct
|
|
||||||
{
|
|
||||||
a: u64,
|
|
||||||
b: u64,
|
|
||||||
c: u64,
|
|
||||||
d: u64,
|
|
||||||
e: u64
|
|
||||||
f: u64,
|
|
||||||
g: u64,
|
|
||||||
h: u64,
|
|
||||||
i: u64,
|
|
||||||
j: u64
|
|
||||||
}
|
|
||||||
|
|
||||||
require = fn (ok: u1) void
|
|
||||||
{
|
|
||||||
if (!ok)
|
|
||||||
{
|
|
||||||
#trap();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
va_arg_fn = fn [cc(c)] (first_arg: u32, ...) void
|
|
||||||
{
|
|
||||||
if (first_arg != 123456789)
|
|
||||||
{
|
|
||||||
#trap();
|
|
||||||
}
|
|
||||||
|
|
||||||
>va = #va_start();
|
|
||||||
|
|
||||||
>s = #va_arg(&va, S);
|
|
||||||
require(s.a == 9);
|
|
||||||
require(s.b == 8);
|
|
||||||
require(s.c == 7);
|
|
||||||
require(s.d == 6);
|
|
||||||
require(s.e == 5);
|
|
||||||
require(s.f == 4);
|
|
||||||
require(s.g == 3);
|
|
||||||
require(s.h == 2);
|
|
||||||
require(s.i == 1);
|
|
||||||
require(s.j == 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
[export] main = fn [cc(c)] () s32
|
|
||||||
{
|
|
||||||
>first_arg: u32 = 123456789;
|
|
||||||
>s : S = {
|
|
||||||
.a = 9,
|
|
||||||
.b = 8,
|
|
||||||
.c = 7,
|
|
||||||
.d = 6,
|
|
||||||
.e = 5,
|
|
||||||
.f = 4,
|
|
||||||
.g = 3,
|
|
||||||
.h = 2,
|
|
||||||
.i = 1,
|
|
||||||
.j = 0,
|
|
||||||
};
|
|
||||||
va_arg_fn(first_arg, s);
|
|
||||||
return 0;
|
|
||||||
}
|
|
@ -1,5 +0,0 @@
|
|||||||
[export] main = fn [cc(c)] () s32
|
|
||||||
{
|
|
||||||
>result: s32 = 0x0;
|
|
||||||
return result;
|
|
||||||
}
|
|
@ -1,5 +0,0 @@
|
|||||||
[export] main = fn [cc(c)] () s32
|
|
||||||
{
|
|
||||||
>a = #integer_max(u64);
|
|
||||||
return #truncate(a + 1);
|
|
||||||
}
|
|
@ -1,10 +0,0 @@
|
|||||||
foo = fn() s32
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
[export] main = fn [cc(c)] () s32
|
|
||||||
{
|
|
||||||
>a: s32 = 0;
|
|
||||||
>result = foo() + a;
|
|
||||||
return result;
|
|
||||||
}
|
|
1000001
tests/million_simple_functions.nat
Normal file
1000001
tests/million_simple_functions.nat
Normal file
File diff suppressed because it is too large
Load Diff
@ -1,5 +0,0 @@
|
|||||||
[export] main = fn [cc(c)] () s32
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
@ -1,5 +0,0 @@
|
|||||||
[export] main = fn [cc(c)] () s32
|
|
||||||
{
|
|
||||||
>result: s32 = 0;
|
|
||||||
return result;
|
|
||||||
}
|
|
@ -1,5 +0,0 @@
|
|||||||
[export] main = fn [cc(c)] () s32
|
|
||||||
{
|
|
||||||
>a: s32 = 1;
|
|
||||||
return a - 1;
|
|
||||||
}
|
|
@ -1,6 +0,0 @@
|
|||||||
[export] main = fn [cc(c)] () s32
|
|
||||||
{
|
|
||||||
>a: s32 = 1;
|
|
||||||
>b = a - 1;
|
|
||||||
return b;
|
|
||||||
}
|
|
@ -1,6 +0,0 @@
|
|||||||
[export] main = fn [cc(c)] () s32
|
|
||||||
{
|
|
||||||
>a: s32 = 1;
|
|
||||||
>b = 1 - a;
|
|
||||||
return b;
|
|
||||||
}
|
|
4
tests/mul.nat
Normal file
4
tests/mul.nat
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
fn main() s32
|
||||||
|
{
|
||||||
|
return 1 * 0;
|
||||||
|
}
|
@ -1,7 +0,0 @@
|
|||||||
[export] main = fn [cc(c)] () s32
|
|
||||||
{
|
|
||||||
>a: s32 = 0;
|
|
||||||
>ptr = &a;
|
|
||||||
>b = !ptr;
|
|
||||||
return #extend(b);
|
|
||||||
}
|
|
4
tests/or.nat
Normal file
4
tests/or.nat
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
fn main() s32
|
||||||
|
{
|
||||||
|
return 0 | 0;
|
||||||
|
}
|
@ -1,11 +0,0 @@
|
|||||||
modify = fn (v: &s32) void
|
|
||||||
{
|
|
||||||
v.& = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
[export] main = fn [cc(c)] () s32
|
|
||||||
{
|
|
||||||
>value: s32 = 0;
|
|
||||||
modify(&value);
|
|
||||||
return #extend(value == 0);
|
|
||||||
}
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user