Vectorized compiler skeleton

This commit is contained in:
David Gonzalez Martin 2025-02-11 08:26:22 -06:00 committed by David
parent 0e8f04e408
commit f9bfbf9e8f
17 changed files with 7887 additions and 492 deletions

2
.gitignore vendored
View File

@ -8,3 +8,5 @@ project
imgui.ini
/cache/
.DS_Store
/*.perf
/.gdb_history

File diff suppressed because it is too large Load Diff

View 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]

View 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

View File

@ -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;
}

View File

@ -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);

View File

@ -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;
}

View File

@ -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);

View File

@ -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);
}

View File

@ -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);

View File

@ -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;

View File

@ -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;
}

View File

@ -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, ...);

View File

@ -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

View File

@ -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

1951
build.c

File diff suppressed because it is too large Load Diff

View File

@ -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