Vectorized compiler skeleton
This commit is contained in:
parent
0e8f04e408
commit
f9bfbf9e8f
2
.gitignore
vendored
2
.gitignore
vendored
@ -8,3 +8,5 @@ project
|
||||
imgui.ini
|
||||
/cache/
|
||||
.DS_Store
|
||||
/*.perf
|
||||
/.gdb_history
|
||||
|
File diff suppressed because it is too large
Load Diff
281
bootstrap/bloat-buster/data/instructions.dat
Normal file
281
bootstrap/bloat-buster/data/instructions.dat
Normal file
@ -0,0 +1,281 @@
|
||||
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:
|
||||
imm [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:
|
||||
imm [d: eb rel8]
|
||||
imm [d: e9 rel32]
|
||||
rm64 [m: ff /4]
|
||||
jcc: class jcc
|
||||
jrcxz: imm [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: imm [d: e2 rel8]
|
||||
loope: imm [d: e1 rel8]
|
||||
loopne: imm [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]
|
226
bootstrap/bloat-buster/data/x86_mnemonic.dat
Normal file
226
bootstrap/bloat-buster/data/x86_mnemonic.dat
Normal file
@ -0,0 +1,226 @@
|
||||
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,24 +1,63 @@
|
||||
#pragma once
|
||||
|
||||
#if _MSC_VER
|
||||
extern u32 _lzcnt_u32(u32);
|
||||
extern u32 _tzcnt_u32(u32);
|
||||
extern u64 _lzcnt_u64(u64);
|
||||
extern u64 _tzcnt_u64(u64);
|
||||
#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)
|
||||
{
|
||||
assert(alignment != 0);
|
||||
assert((alignment & (alignment - 1)) == 0);
|
||||
u64 left = (sizeof(alignment) * 8) - 1;
|
||||
#if _MSC_VER
|
||||
let_cast(u64, right, _lzcnt_u64(alignment));
|
||||
#else
|
||||
let_cast(u64, right, __builtin_clzll(alignment));
|
||||
#endif
|
||||
u8 left = (sizeof(alignment) * 8) - 1;
|
||||
u8 right = leading_zeroes_u64(alignment);
|
||||
let_cast(u8, result, left - right);
|
||||
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)
|
||||
{
|
||||
#if defined(__TINYC__) || defined(_MSC_VER)
|
||||
@ -237,9 +276,49 @@ fn u64 is_decimal_digit(u8 ch)
|
||||
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)
|
||||
{
|
||||
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'))));
|
||||
return is_decimal_digit(ch) | is_hex_digit_alpha(ch);
|
||||
}
|
||||
|
||||
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)
|
||||
@ -282,25 +361,38 @@ fn Hash32 hash64_to_hash32(Hash64 hash64)
|
||||
return result;
|
||||
}
|
||||
|
||||
fn u64 align_forward(u64 value, u64 alignment)
|
||||
fn u64 align_forward_u32(u32 value, u32 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 result = (value + mask) & ~mask;
|
||||
return result;
|
||||
}
|
||||
|
||||
fn u64 align_backward(u64 value, u64 alignment)
|
||||
fn u64 align_backward_u64(u64 value, u64 alignment)
|
||||
{
|
||||
u64 result = value & ~(alignment - 1);
|
||||
return result;
|
||||
}
|
||||
|
||||
fn u8 is_power_of_two(u64 value)
|
||||
fn u8 is_power_of_two_u64(u64 value)
|
||||
{
|
||||
return (value & (value - 1)) == 0;
|
||||
}
|
||||
|
||||
fn u8 first_bit_set_32(u32 value)
|
||||
fn u8 first_bit_set_u32(u32 value)
|
||||
{
|
||||
#if _MSC_VER
|
||||
DWORD result_dword;
|
||||
@ -314,7 +406,7 @@ fn u8 first_bit_set_32(u32 value)
|
||||
return result;
|
||||
}
|
||||
|
||||
fn u64 first_bit_set_64(u64 value)
|
||||
fn u64 first_bit_set_u64(u64 value)
|
||||
{
|
||||
#if _MSC_VER
|
||||
DWORD result_dword;
|
||||
@ -339,3 +431,33 @@ fn Hash32 hash64_fib_end(Hash64 hash)
|
||||
let(result, TRUNCATE(Hash32, ((hash + 1) * 11400714819323198485ull) >> 32));
|
||||
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,5 +1,10 @@
|
||||
#pragma once
|
||||
|
||||
#define STRINGIFY(x) #x
|
||||
#define TOSTRING(x) STRINGIFY(x)
|
||||
|
||||
#define USE_MEMCPY 1
|
||||
|
||||
#if _WIN32
|
||||
#define _CRT_SECURE_NO_WARNINGS
|
||||
#endif
|
||||
@ -10,16 +15,6 @@
|
||||
#define BB_DEBUG 1
|
||||
#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 <stddef.h>
|
||||
#include <stdarg.h>
|
||||
@ -140,6 +135,7 @@ declare_slice(s32);
|
||||
declare_slice(s64);
|
||||
|
||||
declare_slice_p(char);
|
||||
declare_slice_p(u8);
|
||||
declare_slice_p(void);
|
||||
|
||||
typedef Slice(u8) String;
|
||||
@ -194,7 +190,7 @@ declare_slice(String);
|
||||
#define unlikely(x) expect(x, 0)
|
||||
#define breakpoint() __builtin_debugtrap()
|
||||
#define failed_execution() panic("Failed execution at {cstr}:{u32}\n", __FILE__, __LINE__)
|
||||
#define todo() panic("TODO at {cstr}:{u32}\n", __FILE__, __LINE__); fix_unreachable()
|
||||
#define todo() os_is_being_debugged() ? trap() : panic("TODO at {cstr}:{u32}\n", __FILE__, __LINE__); fix_unreachable()
|
||||
|
||||
fn void print(const char* format, ...);
|
||||
BB_NORETURN BB_COLD fn void os_exit(u32 exit_code);
|
||||
@ -216,7 +212,8 @@ fn BB_NORETURN BB_COLD void trap_ext()
|
||||
#define trap() (trap_ext(), __builtin_unreachable())
|
||||
#endif
|
||||
|
||||
#define panic(format, ...) (print(format, __VA_ARGS__), os_exit(1))
|
||||
fn u8 os_is_being_debugged();
|
||||
#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)
|
||||
#if defined(__TINYC__) || defined(_MSC_VER)
|
||||
@ -323,12 +320,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_equal(a, b) ((a).length == (b).length && memcmp((a).pointer, (b).pointer, sizeof(*((a).pointer)) * (a).length) == 0)
|
||||
|
||||
fn u64 align_forward(u64 value, u64 alignment);
|
||||
fn u64 align_backward(u64 value, u64 alignment);
|
||||
fn u8 log2_alignment(u64 alignment);
|
||||
fn u8 is_power_of_two(u64 value);
|
||||
fn u8 first_bit_set_32(u32 value);
|
||||
fn u64 first_bit_set_64(u64 value);
|
||||
fn u64 align_forward_u64(u64 value, u64 alignment);
|
||||
fn u64 align_backward_u64(u64 value, u64 alignment);
|
||||
fn u8 log2_alignment_u64(u64 alignment);
|
||||
fn u8 is_power_of_two_u64(u64 value);
|
||||
fn u8 first_bit_set_u32(u32 value);
|
||||
fn u64 first_bit_set_u64(u64 value);
|
||||
|
||||
fn u32 format_decimal(String buffer, u64 decimal);
|
||||
fn u32 format_hexadecimal(String buffer, u64 hexadecimal);
|
||||
@ -340,6 +337,7 @@ fn u8 get_next_ch_safe(String string, u64 index);
|
||||
fn u64 is_identifier_start(u8 ch);
|
||||
fn u64 is_identifier_ch(u8 ch);
|
||||
fn u64 is_alphabetic(u8 ch);
|
||||
fn u64 is_alphanumeric(u8 ch);
|
||||
|
||||
fn u64 parse_decimal(String string);
|
||||
|
||||
|
@ -1075,6 +1075,72 @@ typedef enum IntegerFormat
|
||||
INTEGER_FORMAT_BINARY,
|
||||
} 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)
|
||||
{
|
||||
u8* it = (u8*)format;
|
||||
@ -1181,31 +1247,7 @@ fn String format_string_va(String buffer, const char* format, va_list args)
|
||||
u8* bit_count_end = it;
|
||||
u64 bit_count = parse_decimal(slice_from_pointer_range(u8, (u8*)bit_count_start, (u8*)bit_count_end));
|
||||
|
||||
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;
|
||||
}
|
||||
IntegerFormatOptions options = integer_format_options(&it);
|
||||
|
||||
s64 original_value;
|
||||
switch (bit_count)
|
||||
@ -1224,11 +1266,21 @@ 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);
|
||||
|
||||
switch (integer_format)
|
||||
switch (options.format)
|
||||
{
|
||||
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));
|
||||
assert(expected_characters == written_characters);
|
||||
buffer_i += written_characters;
|
||||
} break;
|
||||
case INTEGER_FORMAT_DECIMAL:
|
||||
@ -1281,39 +1333,7 @@ fn String format_string_va(String buffer, const char* format, va_list args)
|
||||
u8* bit_count_end = it;
|
||||
u64 bit_count = parse_decimal(slice_from_pointer_range(u8, (u8*)bit_count_start, (u8*)bit_count_end));
|
||||
|
||||
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;
|
||||
}
|
||||
IntegerFormatOptions options = integer_format_options(&it);
|
||||
|
||||
u64 original_value;
|
||||
switch (bit_count)
|
||||
@ -1330,26 +1350,41 @@ fn String format_string_va(String buffer, const char* format, va_list args)
|
||||
unreachable();
|
||||
}
|
||||
|
||||
let(buffer_slice, s_get_slice(u8, buffer, buffer_i, buffer.length));
|
||||
|
||||
switch (integer_format)
|
||||
switch (options.format)
|
||||
{
|
||||
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));
|
||||
assert(expected_characters == written_characters);
|
||||
buffer_i += written_characters;
|
||||
} break;
|
||||
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));
|
||||
buffer_i += written_characters;
|
||||
} break;
|
||||
case INTEGER_FORMAT_OCTAL:
|
||||
{
|
||||
let(buffer_slice, s_get_slice(u8, buffer, buffer_i, buffer.length));
|
||||
unused(buffer_slice);
|
||||
todo();
|
||||
} break;
|
||||
case INTEGER_FORMAT_BINARY:
|
||||
{
|
||||
let(buffer_slice, s_get_slice(u8, buffer, buffer_i, buffer.length));
|
||||
unused(buffer_slice);
|
||||
todo();
|
||||
} break;
|
||||
}
|
||||
@ -1381,3 +1416,27 @@ fn String format_string(String buffer, const char* format, ...)
|
||||
va_end(args);
|
||||
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,6 +1,13 @@
|
||||
#pragma once
|
||||
|
||||
#include <std/base.h>
|
||||
STRUCT(StringFormatter)
|
||||
{
|
||||
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_va(String buffer, const char* format, va_list args);
|
||||
|
@ -2,9 +2,11 @@
|
||||
|
||||
#include <std/string.h>
|
||||
#include <std/format.h>
|
||||
#include <std/virtual_buffer.h>
|
||||
|
||||
#include <std/string.c>
|
||||
#include <std/format.c>
|
||||
#include <std/virtual_buffer.c>
|
||||
|
||||
#if _WIN32
|
||||
global_variable u64 cpu_frequency;
|
||||
@ -774,6 +776,15 @@ fn u64 os_timer_get()
|
||||
#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)
|
||||
{
|
||||
#if _WIN32
|
||||
@ -852,6 +863,8 @@ fn void os_file_write(FileDescriptor fd, String content)
|
||||
assert(result != 0);
|
||||
#else
|
||||
let(result, syscall_write(fd, content.pointer, content.length));
|
||||
let(my_errno, strerror(errno));
|
||||
unused(my_errno);
|
||||
assert(cast_to(u64, result) == content.length);
|
||||
#endif
|
||||
}
|
||||
@ -937,6 +950,9 @@ fn u8* os_reserve(u64 base, u64 size, OSReserveProtectionFlags protection, OSRes
|
||||
#else
|
||||
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);
|
||||
#ifdef __linux__
|
||||
map_flags |= (map.populate * MAP_POPULATE);
|
||||
#endif
|
||||
u8* result = (u8*)posix_mmap((void*)base, size, protection_flags, map_flags, -1, 0);
|
||||
assert(result != MAP_FAILED);
|
||||
return result;
|
||||
@ -963,8 +979,36 @@ fn void os_directory_make(String path)
|
||||
#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)
|
||||
{
|
||||
if (exit_code != 0 && os_is_being_debugged())
|
||||
{
|
||||
trap();
|
||||
}
|
||||
exit(exit_code);
|
||||
}
|
||||
|
||||
@ -1016,12 +1060,12 @@ fn Arena* arena_initialize_default(u64 initial_size)
|
||||
|
||||
fn u8* arena_allocate_bytes(Arena* arena, u64 size, u64 alignment)
|
||||
{
|
||||
u64 aligned_offset = align_forward(arena->position, alignment);
|
||||
u64 aligned_offset = align_forward_u64(arena->position, alignment);
|
||||
u64 aligned_size_after = aligned_offset + size;
|
||||
|
||||
if (aligned_size_after > arena->os_position)
|
||||
{
|
||||
u64 committed_size = align_forward(aligned_size_after, arena->granularity);
|
||||
u64 committed_size = align_forward_u64(aligned_size_after, arena->granularity);
|
||||
u64 size_to_commit = committed_size - arena->os_position;
|
||||
void* commit_pointer = (u8*)arena + arena->os_position;
|
||||
os_commit(commit_pointer, size_to_commit);
|
||||
@ -1057,6 +1101,18 @@ fn String arena_join_string(Arena* arena, Slice(String) pieces)
|
||||
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)
|
||||
{
|
||||
arena->position = minimum_position;
|
||||
@ -1105,7 +1161,6 @@ fn String file_read(Arena* arena, String path)
|
||||
|
||||
fn void file_write(FileWriteOptions options)
|
||||
{
|
||||
print("Writing file \"{s}\"...\n", options.path);
|
||||
let(fd, os_file_open(options.path, (OSFileOpenFlags) {
|
||||
.write = 1,
|
||||
.truncate = 1,
|
||||
@ -1122,11 +1177,18 @@ fn void file_write(FileWriteOptions options)
|
||||
os_file_close(fd);
|
||||
}
|
||||
|
||||
fn void run_command(Arena* arena, CStringSlice arguments, char* envp[], RunCommandOptions run_options)
|
||||
fn RunCommandResult run_command(Arena* arena, CStringSlice arguments, char* envp[], RunCommandOptions run_options)
|
||||
{
|
||||
unused(arena);
|
||||
assert(arguments.length > 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)
|
||||
{
|
||||
print("Running command:\n");
|
||||
@ -1139,8 +1201,6 @@ fn void run_command(Arena* arena, CStringSlice arguments, char* envp[], RunComma
|
||||
}
|
||||
|
||||
#if _WIN32
|
||||
let(start_timestamp, os_timestamp());
|
||||
|
||||
u32 length = 0;
|
||||
for (u32 i = 0; i < arguments.length; i += 1)
|
||||
{
|
||||
@ -1167,7 +1227,6 @@ fn void run_command(Arena* arena, CStringSlice arguments, char* envp[], RunComma
|
||||
}
|
||||
}
|
||||
bytes[byte_i - 1] = 0;
|
||||
let(end_timestamp, os_timestamp());
|
||||
|
||||
PROCESS_INFORMATION process_information = {};
|
||||
STARTUPINFOA startup_info = {};
|
||||
@ -1175,14 +1234,22 @@ fn void run_command(Arena* arena, CStringSlice arguments, char* envp[], RunComma
|
||||
startup_info.dwFlags |= STARTF_USESTDHANDLES;
|
||||
startup_info.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||
startup_info.hStdError = GetStdHandle(STD_ERROR_HANDLE);
|
||||
|
||||
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))
|
||||
{
|
||||
WaitForSingleObject(process_information.hProcess, INFINITE);
|
||||
let(end, os_timestamp());
|
||||
let(ms, os_resolve_timestamps(start, end, TIME_UNIT_MILLISECONDS));
|
||||
if (measure_time)
|
||||
{
|
||||
end_timestamp = os_timestamp();
|
||||
ms = os_resolve_timestamps(start_timestamp, end_timestamp, TIME_UNIT_MILLISECONDS);
|
||||
}
|
||||
|
||||
|
||||
if (run_options.debug)
|
||||
{
|
||||
@ -1227,74 +1294,179 @@ fn void run_command(Arena* arena, CStringSlice arguments, char* envp[], RunComma
|
||||
print("CreateProcessA call failed: {cstr}\n", lpMsgBuf);
|
||||
todo();
|
||||
}
|
||||
|
||||
unused(start_timestamp);
|
||||
unused(end_timestamp);
|
||||
unused(envp);
|
||||
#else
|
||||
unused(arena);
|
||||
pid_t pid = syscall_fork();
|
||||
int null_fd;
|
||||
|
||||
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();
|
||||
if (pid == -1)
|
||||
{
|
||||
todo();
|
||||
}
|
||||
|
||||
let(start_timestamp, os_timestamp());
|
||||
if (measure_time)
|
||||
{
|
||||
start_timestamp = os_timestamp();
|
||||
}
|
||||
|
||||
if (pid == 0)
|
||||
{
|
||||
// close(pipes[0]);
|
||||
switch (run_options.stdout_stream.policy)
|
||||
{
|
||||
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);
|
||||
let(result, syscall_execve(arguments.pointer[0], arguments.pointer, envp));
|
||||
unused(result);
|
||||
#if LINK_LIBC
|
||||
panic("Execve failed! Error: {cstr}\n", strerror(errno));
|
||||
#else
|
||||
todo();
|
||||
#endif
|
||||
}
|
||||
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 options = 0;
|
||||
pid_t result = syscall_waitpid(pid, &status, options);
|
||||
let(end_timestamp, os_timestamp());
|
||||
int success = 0;
|
||||
if (result == pid)
|
||||
pid_t waitpid_result = syscall_waitpid(pid, &status, options);
|
||||
|
||||
if (measure_time)
|
||||
{
|
||||
end_timestamp = os_timestamp();
|
||||
}
|
||||
|
||||
if (waitpid_result == pid)
|
||||
{
|
||||
if (run_options.debug)
|
||||
{
|
||||
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))
|
||||
{
|
||||
let(exit_code, WEXITSTATUS(status));
|
||||
success = exit_code == 0;
|
||||
result.termination_code = exit_code;
|
||||
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 (result == -1)
|
||||
else if (waitpid_result == -1)
|
||||
{
|
||||
let(waitpid_error, errno);
|
||||
print("Error waiting for process termination: {u32}\n", waitpid_error);
|
||||
@ -1305,42 +1477,25 @@ fn void run_command(Arena* arena, CStringSlice arguments, char* envp[], RunComma
|
||||
todo();
|
||||
}
|
||||
|
||||
if (!success)
|
||||
let(success, result.termination_kind == PROCESS_TERMINATION_EXIT && result.termination_code == 0);
|
||||
if (run_options.debug && !success)
|
||||
{
|
||||
print("Program failed to run successfully!\n");
|
||||
failed_execution();
|
||||
print("{cstr} failed to run successfully!\n", arguments.pointer[0]);
|
||||
}
|
||||
|
||||
if (run_options.debug)
|
||||
{
|
||||
let(ms, os_resolve_timestamps(start_timestamp, end_timestamp, TIME_UNIT_MILLISECONDS));
|
||||
ms = os_resolve_timestamps(start_timestamp, end_timestamp, TIME_UNIT_MILLISECONDS);
|
||||
u32 ticks = 0;
|
||||
#if LINK_LIBC == 0
|
||||
ticks = cpu_frequency != 0;
|
||||
#endif
|
||||
print("Command run successfully in {f64} {cstr}\n", ms, ticks ? "ticks" : "ms");
|
||||
print("Command run {cstr} in {f64} {cstr}\n", success ? "successfully" : "with errors", ms, ticks ? "ticks" : "ms");
|
||||
}
|
||||
}
|
||||
#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)
|
||||
if (!run_options.use_null_file_descriptor && os_file_descriptor_is_valid(null_fd))
|
||||
{
|
||||
result = 1;
|
||||
close(null_fd);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@ -1462,3 +1617,85 @@ fn u8 os_library_is_valid(OSLibrary library)
|
||||
{
|
||||
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,9 +27,43 @@ typedef enum TimeUnit
|
||||
TIME_UNIT_SECONDS,
|
||||
} 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)
|
||||
{
|
||||
ChildProcessStream stdout_stream;
|
||||
ChildProcessStream stderr_stream;
|
||||
FileDescriptor null_file_descriptor;
|
||||
u64 use_null_file_descriptor:1;
|
||||
u64 debug:1;
|
||||
u64 reserved:62;
|
||||
};
|
||||
|
||||
STRUCT(Timestamp)
|
||||
@ -66,6 +100,7 @@ STRUCT(OSReserveMapFlags)
|
||||
{
|
||||
u32 priv:1;
|
||||
u32 anon:1;
|
||||
u32 populate:1;
|
||||
u32 noreserve:1;
|
||||
u32 reserved:29;
|
||||
};
|
||||
@ -99,7 +134,7 @@ global_variable u64 default_size = GB(4);
|
||||
|
||||
fn void vprint(const char* format, va_list args);
|
||||
fn void print(const char* format, ...);
|
||||
fn void run_command(Arena* arena, CStringSlice arguments, char* envp[], RunCommandOptions options);
|
||||
fn RunCommandResult run_command(Arena* arena, CStringSlice arguments, char* envp[], RunCommandOptions options);
|
||||
fn String file_read(Arena* arena, String path);
|
||||
fn void file_write(FileWriteOptions options);
|
||||
|
||||
|
@ -31,7 +31,7 @@ fn u8 rendering_backend_is_valid(RenderingBackend rendering_backend)
|
||||
{
|
||||
#ifdef __linux__
|
||||
valid = rendering_backend == RENDERING_BACKEND_VULKAN;
|
||||
#elif __APPLE__
|
||||
#elif defined(__APPLE__)
|
||||
valid = rendering_backend == RENDERING_BACKEND_METAL || rendering_backend == RENDERING_BACKEND_VULKAN;
|
||||
#elif _WIN32
|
||||
valid = rendering_backend == RENDERING_BACKEND_DIRECTX12 || rendering_backend == RENDERING_BACKEND_VULKAN;
|
||||
|
@ -1,5 +1,4 @@
|
||||
#include <std/virtual_buffer.h>
|
||||
#include <std/os.h>
|
||||
#pragma once
|
||||
|
||||
fn void vb_generic_ensure_capacity(VirtualBuffer(u8)* vb, u32 item_size, u32 item_count)
|
||||
{
|
||||
@ -13,8 +12,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 });
|
||||
}
|
||||
|
||||
let_cast(u32, old_page_capacity, align_forward(old_capacity * item_size, minimum_granularity));
|
||||
let_cast(u32, new_page_capacity, align_forward(wanted_capacity * item_size, minimum_granularity));
|
||||
let_cast(u32, old_page_capacity, align_forward_u64(old_capacity * item_size, minimum_granularity));
|
||||
let_cast(u32, new_page_capacity, align_forward_u64(wanted_capacity * item_size, minimum_granularity));
|
||||
|
||||
let(commit_size, new_page_capacity - old_page_capacity);
|
||||
void* commit_pointer = vb->pointer + old_page_capacity;
|
||||
@ -49,11 +48,13 @@ fn u8* vb_append_bytes(VirtualBuffer(u8*) vb, Slice(u8) bytes)
|
||||
return pointer;
|
||||
}
|
||||
|
||||
fn void vb_copy_string(VirtualBuffer(u8)* buffer, String string)
|
||||
fn u32 vb_copy_string(VirtualBuffer(u8)* buffer, String string)
|
||||
{
|
||||
let(offset, buffer->length);
|
||||
let_cast(u32, length, string.length);
|
||||
let(pointer, vb_add(buffer, length));
|
||||
memcpy(pointer, string.pointer, length);
|
||||
return offset;
|
||||
}
|
||||
|
||||
fn u64 vb_copy_string_zero_terminated(VirtualBuffer(u8)* buffer, String string)
|
||||
@ -65,3 +66,23 @@ fn u64 vb_copy_string_zero_terminated(VirtualBuffer(u8)* buffer, String string)
|
||||
|
||||
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,5 +49,6 @@ 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(VirtualBuffer(u8)* vb, u32 item_size, u32 item_count);
|
||||
fn u8* vb_append_bytes(VirtualBuffer(u8*) vb, Slice(u8) bytes);
|
||||
fn void vb_copy_string(VirtualBuffer(u8)* buffer, String string);
|
||||
fn u32 vb_copy_string(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,7 +312,6 @@ fn void buffer_copy_to_host(VulkanBuffer buffer, Slice(HostBufferCopy) regions)
|
||||
let(region, regions.pointer[i]);
|
||||
let(destination, buffer_pointer + region.destination_offset);
|
||||
assert(destination + region.source.length <= (u8*)buffer.address + buffer.size);
|
||||
#define USE_MEMCPY 1
|
||||
#if USE_MEMCPY
|
||||
memcpy(destination, region.source.pointer, region.source.length);
|
||||
#else
|
||||
|
@ -22,10 +22,10 @@ mkdir %BUILD_DIR% > NUL 2>&1
|
||||
set BUILD_OUT=cache\build.exe
|
||||
set BB_ERROR_ON_WARNINGS=%BB_CI%
|
||||
|
||||
if "%BB_CI%" == "0" (
|
||||
%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.frag -o cache\rect.frag.spv --quiet || exit /b 1
|
||||
)
|
||||
REM 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
|
||||
REM %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
|
||||
|
13
build.sh
13
build.sh
@ -1,6 +1,8 @@
|
||||
#!/usr/bin/env bash
|
||||
set -eu
|
||||
|
||||
MY_CWD=$PWD
|
||||
|
||||
if [[ -z "${BB_CI-}" ]]; then
|
||||
BB_CI=0
|
||||
fi
|
||||
@ -17,10 +19,19 @@ if [[ -z "${BB_ERROR_LIMIT-}" ]]; then
|
||||
BB_ERROR_LIMIT=$((1 - BB_CI))
|
||||
fi
|
||||
|
||||
BB_COMPILE_SHADERS=0
|
||||
|
||||
BUILD_DIR=cache
|
||||
LARGE_ASSET_BASE_URL=https://github.com/birth-software/bloat-buster/releases/download/large-assets
|
||||
mkdir -p $BUILD_DIR
|
||||
|
||||
if [[ "${BB_CI}" == "0" ]]; then
|
||||
if [[ ! -f "$BUILD_DIR/large_assembly.s" ]]; 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.frag -o $BUILD_DIR/rect.frag.spv --quiet
|
||||
fi
|
||||
|
Loading…
x
Reference in New Issue
Block a user