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));
|
memcpy(vb_add(args, array_length(static_options)), static_options, sizeof(static_options));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
*vb_add(args, 1) = "-DSILENT";
|
||||||
|
|
||||||
if (options->compiler == clang)
|
if (options->compiler == clang)
|
||||||
{
|
{
|
||||||
*vb_add(args, 1) = "-MJ";
|
*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)
|
if (argc < 2)
|
||||||
{
|
{
|
||||||
print("Expected some arguments\n");
|
print("Expected some arguments\n");
|
||||||
return 1;
|
fail();
|
||||||
}
|
}
|
||||||
// calibrate_cpu_timer();
|
|
||||||
|
|
||||||
CompilerBackend preferred_compiler_backend = COMPILER_BACKEND_COUNT;
|
CompilerBackend preferred_compiler_backend = COMPILER_BACKEND_COUNT;
|
||||||
Command command = COMMAND_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)
|
if (command == COMMAND_COUNT && !source_file_path.pointer)
|
||||||
{
|
{
|
||||||
print("Expected a command\n");
|
print("Expected a command\n");
|
||||||
return 1;
|
fail();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (command == COMMAND_COUNT)
|
if (command == COMMAND_COUNT)
|
||||||
@ -461,12 +462,8 @@ int main(int argc, char* argv[], char** envp)
|
|||||||
fail();
|
fail();
|
||||||
}
|
}
|
||||||
|
|
||||||
Linkage linkage =
|
// Test always with dynamic linkage because it's more trustworthy
|
||||||
#if defined(__linux__)
|
Linkage linkage = LINKAGE_DYNAMIC;
|
||||||
LINKAGE_STATIC;
|
|
||||||
#else
|
|
||||||
LINKAGE_DYNAMIC;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
compile_and_run(&(CompileOptions) {
|
compile_and_run(&(CompileOptions) {
|
||||||
.in_path = compiler_source_path,
|
.in_path = compiler_source_path,
|
||||||
@ -481,8 +478,13 @@ int main(int argc, char* argv[], char** envp)
|
|||||||
case COMMAND_RUN_TESTS:
|
case COMMAND_RUN_TESTS:
|
||||||
{
|
{
|
||||||
Arena* arena = arena_init_default(KB(64));
|
Arena* arena = arena_init_default(KB(64));
|
||||||
Linkage all_linkages[] = { LINKAGE_DYNAMIC, LINKAGE_STATIC };
|
Linkage all_linkages[] = {
|
||||||
static_assert(array_length(all_linkages) == LINKAGE_COUNT);
|
LINKAGE_DYNAMIC,
|
||||||
|
#ifdef __linux__
|
||||||
|
LINKAGE_STATIC
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
OptimizationMode all_optimization_modes[] = {
|
OptimizationMode all_optimization_modes[] = {
|
||||||
O0,
|
O0,
|
||||||
O1,
|
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;\
|
b = temp;\
|
||||||
} while (0)
|
} 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__)
|
#if defined(__x86_64__)
|
||||||
return __rdtsc();
|
return __rdtsc();
|
||||||
#else
|
#else
|
||||||
return 0;
|
return 0;
|
||||||
#endif
|
#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 void print(const char* format, ...);
|
||||||
|
|
||||||
may_be_unused fn u16 cast_u32_to_u16(u32 source, const char* name, int line)
|
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);
|
const global u64 page_size = KB(4);
|
||||||
#endif
|
#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_open = '{';
|
||||||
const may_be_unused global u8 brace_close = '}';
|
const may_be_unused global u8 brace_close = '}';
|
||||||
@ -1425,10 +1513,11 @@ may_be_unused fn u64 os_timer_get()
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
global u64 cpu_frequency;
|
|
||||||
|
|
||||||
may_be_unused fn void calibrate_cpu_timer()
|
may_be_unused fn void calibrate_cpu_timer()
|
||||||
{
|
{
|
||||||
|
#if LINK_LIBC
|
||||||
|
// clock_getres(CLOCK_MONOTONIC, &cpu_resolution);
|
||||||
|
#else
|
||||||
u64 miliseconds_to_wait = 100;
|
u64 miliseconds_to_wait = 100;
|
||||||
u64 cpu_start = timestamp();
|
u64 cpu_start = timestamp();
|
||||||
u64 os_frequency = os_timer_freq();
|
u64 os_frequency = os_timer_freq();
|
||||||
@ -1445,6 +1534,7 @@ may_be_unused fn void calibrate_cpu_timer()
|
|||||||
u64 cpu_end = timestamp();
|
u64 cpu_end = timestamp();
|
||||||
u64 cpu_elapsed = cpu_end - cpu_start;
|
u64 cpu_elapsed = cpu_end - cpu_start;
|
||||||
cpu_frequency = os_frequency * cpu_elapsed / os_elapsed;
|
cpu_frequency = os_frequency * cpu_elapsed / os_elapsed;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
fn u8* reserve(u64 size)
|
fn u8* reserve(u64 size)
|
||||||
@ -1538,7 +1628,6 @@ fn u32 format_decimal(String buffer, u64 decimal)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#define SILENT (0)
|
|
||||||
STRUCT(SmallIntResult)
|
STRUCT(SmallIntResult)
|
||||||
{
|
{
|
||||||
u64 mantissa;
|
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, ...)
|
may_be_unused fn void print(const char* format, ...)
|
||||||
{
|
{
|
||||||
#if SILENT == 0
|
#ifndef SILENT
|
||||||
u8 stack_buffer[4096];
|
u8 stack_buffer[4096];
|
||||||
va_list args;
|
va_list args;
|
||||||
va_start(args, format);
|
va_start(args, format);
|
||||||
@ -2463,7 +2552,24 @@ may_be_unused fn void print(const char* format, ...)
|
|||||||
}
|
}
|
||||||
else
|
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;
|
} break;
|
||||||
}
|
}
|
||||||
@ -2692,7 +2798,7 @@ fn void run_command(CStringSlice arguments, char* envp[])
|
|||||||
trap();
|
trap();
|
||||||
}
|
}
|
||||||
|
|
||||||
u64 start_ns = timestamp();
|
auto start_timestamp = timestamp();
|
||||||
|
|
||||||
if (pid == 0)
|
if (pid == 0)
|
||||||
{
|
{
|
||||||
@ -2712,7 +2818,7 @@ fn void run_command(CStringSlice arguments, char* envp[])
|
|||||||
int status = 0;
|
int status = 0;
|
||||||
int options = 0;
|
int options = 0;
|
||||||
pid_t result = syscall_waitpid(pid, &status, options);
|
pid_t result = syscall_waitpid(pid, &status, options);
|
||||||
u64 end_ns = timestamp();
|
auto end_timestamp = timestamp();
|
||||||
int success = 0;
|
int success = 0;
|
||||||
if (result == pid)
|
if (result == pid)
|
||||||
{
|
{
|
||||||
@ -2736,14 +2842,15 @@ fn void run_command(CStringSlice arguments, char* envp[])
|
|||||||
fail();
|
fail();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cpu_frequency)
|
auto ms = resolve_timestamp(start_timestamp, end_timestamp, TIME_UNIT_MILLISECONDS);
|
||||||
{
|
auto ticks =
|
||||||
auto ticks = end_ns - start_ns;
|
#if LINK_LIBC
|
||||||
auto ticks_f = (f64)ticks;
|
0
|
||||||
auto time_frequency_f = (f64)cpu_frequency;
|
#else
|
||||||
auto s = ticks_f / time_frequency_f;
|
cpu_frequency != 0
|
||||||
print("Command run successfully in {f64} s\n", s);
|
#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);
|
auto result = truncate(Hash32, (hash * 11400714819323198485ull) >> 32);
|
||||||
return result;
|
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)
|
fn void print_string(String message)
|
||||||
{
|
{
|
||||||
#if SILENT == 0
|
#ifndef SILENT
|
||||||
ssize_t result = syscall_write(1, message.pointer, message.length);
|
ssize_t result = syscall_write(1, message.pointer, message.length);
|
||||||
assert(result >= 0);
|
assert(result >= 0);
|
||||||
assert((u64)result == message.length);
|
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)
|
fn void dwarf_playground(Thread* thread)
|
||||||
{
|
{
|
||||||
@ -12817,22 +12802,12 @@ fn void dwarf_playground(Thread* thread)
|
|||||||
assert(*debug_info_bytes.pointer == 0);
|
assert(*debug_info_bytes.pointer == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if LINK_LIBC
|
fn void entry_point(int argc, char* argv[], char* envp[])
|
||||||
int main(int argc, const 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
|
#if DO_UNIT_TESTS
|
||||||
unit_tests();
|
unit_tests();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// calibrate_cpu_timer();
|
|
||||||
|
|
||||||
|
|
||||||
Arena* global_arena = arena_init(MB(2), KB(64), KB(64));
|
Arena* global_arena = arena_init(MB(2), KB(64), KB(64));
|
||||||
|
|
||||||
{
|
{
|
||||||
@ -12890,13 +12865,10 @@ void entry_point(int argc, const char* argv[])
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
code_generation(thread, (CodegenOptions) {
|
code_generation(thread, (CodegenOptions) {
|
||||||
.test_name = test_name,
|
.test_name = test_name,
|
||||||
.backend = compiler_backend,
|
.backend = compiler_backend,
|
||||||
}, envp);
|
}, envp);
|
||||||
}
|
}
|
||||||
|
|
||||||
thread_clear(thread);
|
thread_clear(thread);
|
||||||
#if LINK_LIBC == 0
|
|
||||||
syscall_exit(0);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user