Improve timer and entry point code
This commit is contained in:
parent
b82f9d45ef
commit
9cc928c439
@ -145,6 +145,8 @@ fn void compile_c(const CompileOptions *const options, char** envp)
|
||||
memcpy(vb_add(args, array_length(static_options)), static_options, sizeof(static_options));
|
||||
}
|
||||
|
||||
*vb_add(args, 1) = "-DSILENT";
|
||||
|
||||
if (options->compiler == clang)
|
||||
{
|
||||
*vb_add(args, 1) = "-MJ";
|
||||
@ -364,14 +366,13 @@ fn void run_tests(Arena* arena, TestOptions const * const test_options, char** e
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[], char** envp)
|
||||
fn void entry_point(int argc, char* argv[], char* envp[])
|
||||
{
|
||||
if (argc < 2)
|
||||
{
|
||||
print("Expected some arguments\n");
|
||||
return 1;
|
||||
fail();
|
||||
}
|
||||
// calibrate_cpu_timer();
|
||||
|
||||
CompilerBackend preferred_compiler_backend = COMPILER_BACKEND_COUNT;
|
||||
Command command = COMMAND_COUNT;
|
||||
@ -437,7 +438,7 @@ int main(int argc, char* argv[], char** envp)
|
||||
if (command == COMMAND_COUNT && !source_file_path.pointer)
|
||||
{
|
||||
print("Expected a command\n");
|
||||
return 1;
|
||||
fail();
|
||||
}
|
||||
|
||||
if (command == COMMAND_COUNT)
|
||||
@ -461,12 +462,8 @@ int main(int argc, char* argv[], char** envp)
|
||||
fail();
|
||||
}
|
||||
|
||||
Linkage linkage =
|
||||
#if defined(__linux__)
|
||||
LINKAGE_STATIC;
|
||||
#else
|
||||
LINKAGE_DYNAMIC;
|
||||
#endif
|
||||
// Test always with dynamic linkage because it's more trustworthy
|
||||
Linkage linkage = LINKAGE_DYNAMIC;
|
||||
|
||||
compile_and_run(&(CompileOptions) {
|
||||
.in_path = compiler_source_path,
|
||||
@ -481,8 +478,13 @@ int main(int argc, char* argv[], char** envp)
|
||||
case COMMAND_RUN_TESTS:
|
||||
{
|
||||
Arena* arena = arena_init_default(KB(64));
|
||||
Linkage all_linkages[] = { LINKAGE_DYNAMIC, LINKAGE_STATIC };
|
||||
static_assert(array_length(all_linkages) == LINKAGE_COUNT);
|
||||
Linkage all_linkages[] = {
|
||||
LINKAGE_DYNAMIC,
|
||||
#ifdef __linux__
|
||||
LINKAGE_STATIC
|
||||
#endif
|
||||
};
|
||||
|
||||
OptimizationMode all_optimization_modes[] = {
|
||||
O0,
|
||||
O1,
|
||||
|
172
bootstrap/lib.h
172
bootstrap/lib.h
@ -97,15 +97,34 @@ FOR_N(_i, 0, ((set)->arr.capacity + 63) / 64) FOR_BIT(it, _i*64, (set)->arr.poin
|
||||
b = temp;\
|
||||
} while (0)
|
||||
|
||||
fn u64 timestamp()
|
||||
fn
|
||||
#if LINK_LIBC
|
||||
struct timespec
|
||||
#else
|
||||
u64
|
||||
#endif
|
||||
timestamp()
|
||||
{
|
||||
#if LINK_LIBC
|
||||
struct timespec ts;
|
||||
clock_gettime(CLOCK_MONOTONIC, &ts);
|
||||
return ts;
|
||||
#else
|
||||
#if defined(__x86_64__)
|
||||
return __rdtsc();
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
#if LINK_LIBC
|
||||
global struct timespec cpu_resolution;
|
||||
#else
|
||||
global u64 cpu_frequency;
|
||||
#endif
|
||||
|
||||
|
||||
may_be_unused fn void print(const char* format, ...);
|
||||
|
||||
may_be_unused fn u16 cast_u32_to_u16(u32 source, const char* name, int line)
|
||||
@ -435,6 +454,75 @@ may_be_unused fn s32 cast_s64_to_s32(s64 source, const char* name, int line)
|
||||
const global u64 page_size = KB(4);
|
||||
#endif
|
||||
|
||||
typedef enum TimeUnit
|
||||
{
|
||||
TIME_UNIT_NANOSECONDS,
|
||||
TIME_UNIT_MICROSECONDS,
|
||||
TIME_UNIT_MILLISECONDS,
|
||||
TIME_UNIT_SECONDS,
|
||||
} TimeUnit;
|
||||
|
||||
fn f64 resolve_timestamp(
|
||||
#if LINK_LIBC
|
||||
struct timespec start, struct timespec end,
|
||||
#else
|
||||
u64 start, u64 end,
|
||||
#endif
|
||||
TimeUnit time_unit)
|
||||
{
|
||||
#if LINK_LIBC
|
||||
assert(end.tv_sec >= start.tv_sec);
|
||||
struct timespec result = {
|
||||
.tv_sec = end.tv_sec - start.tv_sec,
|
||||
.tv_nsec = end.tv_nsec - start.tv_nsec,
|
||||
};
|
||||
|
||||
auto ns_in_a_sec = 1000000000;
|
||||
if (result.tv_nsec < 0)
|
||||
{
|
||||
result.tv_sec -= 1;
|
||||
result.tv_nsec += ns_in_a_sec;
|
||||
}
|
||||
|
||||
auto ns = result.tv_sec * ns_in_a_sec + result.tv_nsec;
|
||||
switch (time_unit)
|
||||
{
|
||||
case TIME_UNIT_NANOSECONDS:
|
||||
return (f64)ns;
|
||||
case TIME_UNIT_MICROSECONDS:
|
||||
return ns / 1000.0;
|
||||
case TIME_UNIT_MILLISECONDS:
|
||||
return ns / 1000000.0;
|
||||
case TIME_UNIT_SECONDS:
|
||||
return ns / 1000000000.0;
|
||||
}
|
||||
#else
|
||||
assert(end >= start);
|
||||
auto ticks = end - start;
|
||||
f64 s = (f64)(end - start);
|
||||
if (cpu_frequency)
|
||||
{
|
||||
s = s / (f64)cpu_frequency;
|
||||
|
||||
switch (time_unit)
|
||||
{
|
||||
case TIME_UNIT_NANOSECONDS:
|
||||
return s / 1000000000.0;
|
||||
case TIME_UNIT_MICROSECONDS:
|
||||
return s / 1000000.0;
|
||||
case TIME_UNIT_MILLISECONDS:
|
||||
return s / 1000.0;
|
||||
case TIME_UNIT_SECONDS:
|
||||
return s;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// warning: rdtsc frequency not queried (returning ticks as are)
|
||||
return s;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
const may_be_unused global u8 brace_open = '{';
|
||||
const may_be_unused global u8 brace_close = '}';
|
||||
@ -1425,10 +1513,11 @@ may_be_unused fn u64 os_timer_get()
|
||||
return result;
|
||||
}
|
||||
|
||||
global u64 cpu_frequency;
|
||||
|
||||
may_be_unused fn void calibrate_cpu_timer()
|
||||
{
|
||||
#if LINK_LIBC
|
||||
// clock_getres(CLOCK_MONOTONIC, &cpu_resolution);
|
||||
#else
|
||||
u64 miliseconds_to_wait = 100;
|
||||
u64 cpu_start = timestamp();
|
||||
u64 os_frequency = os_timer_freq();
|
||||
@ -1445,6 +1534,7 @@ may_be_unused fn void calibrate_cpu_timer()
|
||||
u64 cpu_end = timestamp();
|
||||
u64 cpu_elapsed = cpu_end - cpu_start;
|
||||
cpu_frequency = os_frequency * cpu_elapsed / os_elapsed;
|
||||
#endif
|
||||
}
|
||||
|
||||
fn u8* reserve(u64 size)
|
||||
@ -1538,7 +1628,6 @@ fn u32 format_decimal(String buffer, u64 decimal)
|
||||
}
|
||||
}
|
||||
|
||||
#define SILENT (0)
|
||||
STRUCT(SmallIntResult)
|
||||
{
|
||||
u64 mantissa;
|
||||
@ -2210,7 +2299,7 @@ fn void write_float_decimal(String buffer, u64* value, u64 count)
|
||||
|
||||
may_be_unused fn void print(const char* format, ...)
|
||||
{
|
||||
#if SILENT == 0
|
||||
#ifndef SILENT
|
||||
u8 stack_buffer[4096];
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
@ -2463,7 +2552,24 @@ may_be_unused fn void print(const char* format, ...)
|
||||
}
|
||||
else
|
||||
{
|
||||
__builtin_trap();
|
||||
auto dp_uoffset = (u64)dp_offset;
|
||||
if (dp_uoffset >= olength)
|
||||
{
|
||||
write_float_decimal(s_get_slice(u8, buffer, buffer_i, buffer.length), &output, olength);
|
||||
buffer_i += olength;
|
||||
auto length = dp_uoffset - olength;
|
||||
auto memset_slice = s_get_slice(u8, buffer, buffer_i, buffer_i + length);
|
||||
memset(memset_slice.pointer, 0, length);
|
||||
buffer_i += length;
|
||||
}
|
||||
else
|
||||
{
|
||||
write_float_decimal(s_get_slice(u8, buffer, buffer_i + dp_uoffset + 1, buffer.length), &output, olength - dp_uoffset);
|
||||
buffer.pointer[buffer_i + dp_uoffset] = '.';
|
||||
auto dp_index = buffer_i + dp_uoffset + 1;
|
||||
write_float_decimal(s_get_slice(u8, buffer, buffer_i, buffer.length), &output, dp_uoffset);
|
||||
buffer_i += olength + 1;
|
||||
}
|
||||
}
|
||||
} break;
|
||||
}
|
||||
@ -2692,7 +2798,7 @@ fn void run_command(CStringSlice arguments, char* envp[])
|
||||
trap();
|
||||
}
|
||||
|
||||
u64 start_ns = timestamp();
|
||||
auto start_timestamp = timestamp();
|
||||
|
||||
if (pid == 0)
|
||||
{
|
||||
@ -2712,7 +2818,7 @@ fn void run_command(CStringSlice arguments, char* envp[])
|
||||
int status = 0;
|
||||
int options = 0;
|
||||
pid_t result = syscall_waitpid(pid, &status, options);
|
||||
u64 end_ns = timestamp();
|
||||
auto end_timestamp = timestamp();
|
||||
int success = 0;
|
||||
if (result == pid)
|
||||
{
|
||||
@ -2736,14 +2842,15 @@ fn void run_command(CStringSlice arguments, char* envp[])
|
||||
fail();
|
||||
}
|
||||
|
||||
if (cpu_frequency)
|
||||
{
|
||||
auto ticks = end_ns - start_ns;
|
||||
auto ticks_f = (f64)ticks;
|
||||
auto time_frequency_f = (f64)cpu_frequency;
|
||||
auto s = ticks_f / time_frequency_f;
|
||||
print("Command run successfully in {f64} s\n", s);
|
||||
}
|
||||
auto ms = resolve_timestamp(start_timestamp, end_timestamp, TIME_UNIT_MILLISECONDS);
|
||||
auto ticks =
|
||||
#if LINK_LIBC
|
||||
0
|
||||
#else
|
||||
cpu_frequency != 0
|
||||
#endif
|
||||
;
|
||||
print("Command run successfully in {f64} {cstr}\n", ms, ticks ? "ticks" : "ms");
|
||||
}
|
||||
}
|
||||
|
||||
@ -2840,3 +2947,36 @@ may_be_unused fn Hash32 hash64_fib_end(Hash64 hash)
|
||||
auto result = truncate(Hash32, (hash * 11400714819323198485ull) >> 32);
|
||||
return result;
|
||||
}
|
||||
|
||||
fn void entry_point(int argc, char* argv[], char* envp[]);
|
||||
|
||||
#if LINK_LIBC
|
||||
int main(int argc, char* argv[], char* envp[])
|
||||
{
|
||||
entry_point(argc, argv, envp);
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
[[gnu::naked]] [[noreturn]] void _start()
|
||||
{
|
||||
__asm__ __volatile__(
|
||||
"\nxor %ebp, %ebp"
|
||||
"\npopq %rdi"
|
||||
"\nmov %rsp, %rsi"
|
||||
"\nand $~0xf, %rsp"
|
||||
"\npushq %rsp"
|
||||
"\npushq $0"
|
||||
"\ncallq static_entry_point"
|
||||
"\nud2\n"
|
||||
);
|
||||
}
|
||||
|
||||
void static_entry_point(int argc, char* argv[])
|
||||
{
|
||||
char** envp = (char**)&argv[argc + 1];
|
||||
calibrate_cpu_timer();
|
||||
entry_point(argc, argv, envp);
|
||||
syscall_exit(0);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -61,7 +61,7 @@ fn String file_read(Arena* arena, String path)
|
||||
|
||||
fn void print_string(String message)
|
||||
{
|
||||
#if SILENT == 0
|
||||
#ifndef SILENT
|
||||
ssize_t result = syscall_write(1, message.pointer, message.length);
|
||||
assert(result >= 0);
|
||||
assert((u64)result == message.length);
|
||||
@ -12538,21 +12538,6 @@ fn void print_ir(Thread* restrict thread)
|
||||
}
|
||||
}
|
||||
|
||||
#if LINK_LIBC == 0
|
||||
[[gnu::naked]] [[noreturn]] void _start()
|
||||
{
|
||||
__asm__ __volatile__(
|
||||
"\nxor %ebp, %ebp"
|
||||
"\npopq %rdi"
|
||||
"\nmov %rsp, %rsi"
|
||||
"\nand $~0xf, %rsp"
|
||||
"\npushq %rsp"
|
||||
"\npushq $0"
|
||||
"\ncallq entry_point"
|
||||
"\nud2\n"
|
||||
);
|
||||
}
|
||||
#endif
|
||||
|
||||
fn void dwarf_playground(Thread* thread)
|
||||
{
|
||||
@ -12817,22 +12802,12 @@ fn void dwarf_playground(Thread* thread)
|
||||
assert(*debug_info_bytes.pointer == 0);
|
||||
}
|
||||
|
||||
#if LINK_LIBC
|
||||
int main(int argc, const char* argv[], char* envp[])
|
||||
fn void entry_point(int argc, char* argv[], char* envp[])
|
||||
{
|
||||
#else
|
||||
void entry_point(int argc, const char* argv[])
|
||||
{
|
||||
char** envp = (char**)&argv[argc + 1];
|
||||
unused(envp);
|
||||
#endif
|
||||
#if DO_UNIT_TESTS
|
||||
unit_tests();
|
||||
#endif
|
||||
|
||||
// calibrate_cpu_timer();
|
||||
|
||||
|
||||
Arena* global_arena = arena_init(MB(2), KB(64), KB(64));
|
||||
|
||||
{
|
||||
@ -12890,13 +12865,10 @@ void entry_point(int argc, const char* argv[])
|
||||
else
|
||||
{
|
||||
code_generation(thread, (CodegenOptions) {
|
||||
.test_name = test_name,
|
||||
.backend = compiler_backend,
|
||||
}, envp);
|
||||
.test_name = test_name,
|
||||
.backend = compiler_backend,
|
||||
}, envp);
|
||||
}
|
||||
|
||||
thread_clear(thread);
|
||||
#if LINK_LIBC == 0
|
||||
syscall_exit(0);
|
||||
#endif
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user