eliminate os_core, move into base; eliminate regs, move into arch abstraction layer, define x64 regs in x64 layer; move win32 backend for os core (now base) functionality to top-level win32 layer

This commit is contained in:
Ryan Fleury committed 2026-05-08 15:21:21 -07:00
1 parent 24c858171f
commit aea4a4ff9d
148 files changed
+7942 -5268

No files matched your search

+133 -133
View File
@@ -28,9 +28,9 @@ internal char *
t_string_from_result(T_RunStatus v)
{
switch (v) {
case T_RunStatus_Fail: return "FAIL";
case T_RunStatus_Crash: return "CRASH";
case T_RunStatus_Pass: return "PASS";
case T_RunStatus_Fail: return "FAIL";
case T_RunStatus_Crash: return "CRASH";
case T_RunStatus_Pass: return "PASS";
}
return 0;
}
@@ -40,7 +40,7 @@ t_write_file_list(String8 name, String8List data)
{
Temp scratch = scratch_begin(0,0);
String8 path = t_make_file_path(scratch.arena, name);
B32 is_written = os_write_data_list_to_file_path(path, data);
B32 is_written = write_data_list_to_file_path(path, data);
scratch_end(scratch);
return is_written;
}
@@ -50,10 +50,10 @@ t_write_file(String8 name, String8 data)
{
String8Node temp_node = {0};
temp_node.string = data;
String8List temp_list = {0};
str8_list_push_node(&temp_list, &temp_node);
return t_write_file_list(name, temp_list);
}
@@ -62,7 +62,7 @@ t_read_file(Arena *arena, String8 name)
{
Temp scratch = scratch_begin(&arena,1);
String8 path = t_make_file_path(scratch.arena, name);
String8 data = os_data_from_file_path(arena, path);
String8 data = data_from_file_path(arena, path);
scratch_end(scratch);
return data;
}
@@ -72,7 +72,7 @@ t_delete_file(String8 name)
{
Temp scratch = scratch_begin(0,0);
String8 path = t_make_file_path(scratch.arena, name);
B32 is_deleted = os_delete_file_at_path(path);
B32 is_deleted = delete_file_at_path(path);
scratch_end(scratch);
return is_deleted;
}
@@ -81,26 +81,26 @@ internal void
t_delete_dir(String8 path)
{
Temp scratch = scratch_begin(0,0);
OS_FileIter *file_iter = os_file_iter_begin(scratch.arena, path, 0);
FileIter *file_iter = file_iter_begin(scratch.arena, path, 0);
for (;;) {
OS_FileInfo info = {0};
if ( ! os_file_iter_next(scratch.arena, file_iter, &info)) { break; }
FileInfo info = {0};
if ( ! file_iter_next(scratch.arena, file_iter, &info)) { break; }
if (info.props.flags & FilePropertyFlag_IsFolder) {
t_delete_dir(str8f(scratch.arena, "%S/%S", path, info.name));
continue;
}
String8 file_path = str8f(scratch.arena, "%S/%S", path, info.name);
if ( ! os_delete_file_at_path(file_path)) {
if ( ! delete_file_at_path(file_path)) {
fprintf(stderr, "ERROR: unable to delete file %.*s\n", str8_varg(file_path));
}
}
os_file_iter_end(file_iter);
file_iter_end(file_iter);
// TODO: delete directories
scratch_end(scratch);
}
@@ -114,7 +114,7 @@ internal B32
t_make_dir(String8 name)
{
Temp scratch = scratch_begin(0,0);
B32 is_ok = os_make_directory(t_make_file_path(scratch.arena, name));
B32 is_ok = make_directory(t_make_file_path(scratch.arena, name));
scratch_end(scratch);
return is_ok;
}
@@ -148,7 +148,7 @@ internal T_RunResult
t_run(T_Run run)
{
T_RunCtx ctx = { .run = run };
B32 do_safe_call = 1;
#if OS_WINDOWS
if (IsDebuggerPresent()) {
@@ -156,7 +156,7 @@ t_run(T_Run run)
}
#endif
if (do_safe_call) {
os_safe_call(t_run_caller, t_run_fail_handler, &ctx);
safe_call(t_run_caller, t_run_fail_handler, &ctx);
} else {
t_run_caller(&ctx);
}
@@ -172,9 +172,9 @@ t_radbin_path(void)
ArenaParams params = { .reserve_size = sizeof(buffer), .commit_size = sizeof(buffer), .optional_backing_buffer = buffer };
Arena *arena = arena_alloc_(&params);
#if OS_WINDOWS
path = os_full_path_from_path(arena, str8_lit("radbin.exe"));
path = full_path_from_path(arena, str8_lit("radbin.exe"));
#else
path = os_full_path_from_path(arena, str8_lit("radbin"));
path = full_path_from_path(arena, str8_lit("radbin"));
#endif
AssertAlways(path.size);
}
@@ -205,33 +205,33 @@ internal String8
t_cl_version(void)
{
local_persist String8 version;
if ( ! version.size) {
Temp scratch = scratch_begin(0, 0);
String8 output = {0};
t_invoke_(t_cl_path(), str8_zero(), max_U64, scratch.arena, &output);
AssertAlways(g_last_exit_code == 0);
String8 needle = str8_lit("Version");
U64 version_lo = str8_find_needle(output, 0, needle, 0);
version_lo += needle.size + 1;
AssertAlways(version_lo < output.size);
U64 version_hi = str8_find_needle(output, version_lo, str8_lit(" "), 0);
AssertAlways(version_hi < output.size);
version = str8_substr(output, r1u64(version_lo, version_hi));
AssertAlways(version.size > 0);
local_persist U8 buffer[4096];
ArenaParams params = { .reserve_size = sizeof(buffer), .commit_size = sizeof(buffer), .optional_backing_buffer = buffer };
Arena *arena = arena_alloc_(&params);
version = str8_copy(arena, version);
scratch_end(scratch);
}
return version;
}
@@ -244,9 +244,9 @@ t_radlink_path(void)
ArenaParams params = { .reserve_size = sizeof(buffer), .commit_size = sizeof(buffer), .optional_backing_buffer = buffer };
Arena *arena = arena_alloc_(&params);
#if OS_WINDOWS
path = os_full_path_from_path(arena, str8_lit("radlink.exe"));
path = full_path_from_path(arena, str8_lit("radlink.exe"));
#else
path = os_full_path_from_path(arena, str8_lit("radlink"));
path = full_path_from_path(arena, str8_lit("radlink"));
#endif
AssertAlways(path.size);
}
@@ -259,7 +259,7 @@ t_cwd_path(void)
local_persist U8 path[4096] = {0};
if (path[0] == 0) {
Temp scratch = scratch_begin(0, 0);
String8 cwd = os_get_current_path(scratch.arena);
String8 cwd = get_current_path(scratch.arena);
cwd = str8_chop_last_slash(cwd);
cwd = str8f(scratch.arena, "%S", cwd);
MemoryCopyStr8(path, cwd);
@@ -287,26 +287,26 @@ internal B32
t_invoke_env(String8 exe_path, String8 cmdline, String8List env, U64 timeout, Arena *output_arena, String8 *output_out)
{
Temp scratch = scratch_begin(&output_arena,1);
B32 is_ok = 0;
B32 capture_output = output_out || g_redirect_stdout;
g_last_exit_code = -1;
OS_Handle read_pipe_handle = {0}, write_pipe_handle = {0};
File read_pipe_handle = {0}, write_pipe_handle = {0};
if (capture_output) {
HANDLE read_pipe, write_pipe;
SECURITY_ATTRIBUTES at = { .nLength = sizeof(at), .bInheritHandle = 1 };
if (!CreatePipe(&read_pipe, &write_pipe, &at, 0)) {
AssertAlways(0 && "failed to create a pipe");
}
read_pipe_handle = (OS_Handle){ .u64[0] = (U64)read_pipe };
write_pipe_handle = (OS_Handle){ .u64[0] = (U64)write_pipe };
read_pipe_handle = (File){ .u64[0] = (U64)read_pipe };
write_pipe_handle = (File){ .u64[0] = (U64)write_pipe };
}
// Build Launch Options
OS_ProcessLaunchParams launch_opts = {
ProcessLaunchParams launch_opts = {
.path = g_wdir,
.inherit_env = 1,
.env = env,
@@ -315,49 +315,49 @@ t_invoke_env(String8 exe_path, String8 cmdline, String8List env, U64 timeout, Ar
.cmd_line = lnk_arg_list_parse_windows_rules(scratch.arena, cmdline),
};
str8_list_push_front(scratch.arena, &launch_opts.cmd_line, exe_path);
if (g_verbose) {
String8 full_cmd_line = str8_list_join(scratch.arena, &launch_opts.cmd_line, &(StringJoin){ .sep = str8_lit(" ") });
fprintf(stdout, "Command Line: %.*s\n", str8_varg(full_cmd_line));
fprintf(stdout, "Working Dir: %.*s\n", str8_varg(g_wdir));
}
// invoke exe
OS_Handle process_handle = os_process_launch(&launch_opts);
Process process_handle = process_launch(&launch_opts);
// close handle so last to ReadFile does not block
os_file_close(write_pipe_handle);
if ( ! os_handle_match(process_handle, os_handle_zero())) {
file_close(write_pipe_handle);
if ( ! process_match(process_handle, process_zero())) {
if (capture_output) {
// capture process output
String8List output = {0};
for (;;) {
String8 string = os_file_read_cstring(scratch.arena, read_pipe_handle, 0);
String8 string = file_read_cstring(scratch.arena, read_pipe_handle, 0);
if (string.size == 0) { break; }
str8_list_push(scratch.arena, &output, string);
}
os_file_close(read_pipe_handle);
file_close(read_pipe_handle);
if (output_out) {
*output_out = str8_list_join(output_arena, &output, 0);
}
// write to the output file
if (g_redirect_stdout) {
os_write_data_list_to_file_path(g_stdout_file_name, output);
write_data_list_to_file_path(g_stdout_file_name, output);
}
}
U64 exit_code_u64 = 0;
if (os_process_join(process_handle, timeout, &exit_code_u64)) {
if (process_join(process_handle, timeout, &exit_code_u64)) {
g_last_exit_code = (int)exit_code_u64;
is_ok = 1;
} else {
os_process_kill(process_handle);
process_kill(process_handle);
}
}
scratch_end(scratch);
return is_ok;
}
@@ -428,24 +428,24 @@ t_file_paths_from_dir(Arena *arena, String8 dir)
Temp scratch = scratch_begin(&arena, 1);
String8List dirs = {0};
String8List files = {0};
OS_FileIter *iter = os_file_iter_begin(scratch.arena, dir, 0);
OS_FileInfo file;
while (os_file_iter_next(scratch.arena, iter, &file)) {
FileIter *iter = file_iter_begin(scratch.arena, dir, 0);
FileInfo file;
while (file_iter_next(scratch.arena, iter, &file)) {
if (file.props.flags & FilePropertyFlag_IsFolder) {
str8_list_pushf(scratch.arena, &dirs, "%S/%S", dir, file.name);
} else {
str8_list_pushf(arena, &files, "%S/%S", dir, file.name);
}
}
os_file_iter_end(iter);
file_iter_end(iter);
String8List result = {0};
for EachNode(n, String8Node, dirs.first) {
String8List sub_result = t_file_paths_from_dir(arena, n->string);
str8_list_concat_in_place(&result, &sub_result);
}
scratch_end(scratch);
//str8_list_concat_in_place(&result, &dirs);
str8_list_concat_in_place(&result, &files);
@@ -463,12 +463,12 @@ t_match_folders(String8 a, String8 b)
//for EachNode(n, String8Node, files_a.first) printf("%.*s\n", str8_varg(n->string));
String8List files_b = t_file_paths_from_dir(scratch.arena, b);
B32 is_match = 0;
String8Array sorted_a = str8_array_from_list(scratch.arena, &files_a);
String8Array sorted_b = str8_array_from_list(scratch.arena, &files_b);
t_sort_str8_array(sorted_a);
t_sort_str8_array(sorted_b);
if (sorted_a.count == sorted_b.count) {
for EachIndex(i, sorted_a.count) {
Temp temp = temp_begin(scratch.arena);
@@ -477,15 +477,15 @@ t_match_folders(String8 a, String8 b)
if (str8_match(ext_a, ext_b, 0)) {
if (str8_match(ext_a, str8_lit("obj"), StringMatchFlag_CaseInsensitive) ||
str8_match(ext_a, str8_lit("lib"), StringMatchFlag_CaseInsensitive)) {
String8 data_a = os_data_from_file_path(temp.arena, sorted_a.v[i]);
String8 data_b = os_data_from_file_path(temp.arena, sorted_b.v[i]);
String8 data_a = data_from_file_path(temp.arena, sorted_a.v[i]);
String8 data_b = data_from_file_path(temp.arena, sorted_b.v[i]);
is_match = str8_match(data_a, data_b, 0);
if ( ! is_match) {
OS_Handle h;
h = os_cmd_line_launchf("dumpbin /all %S /out:a.txt", sorted_a.v[i]);
os_process_join(h, max_U64, 0);
h = os_cmd_line_launchf("dumpbin /all %S /out:b.txt", sorted_b.v[i]);
os_process_join(h, max_U64, 0);
Process h;
h = launch_cmd_linef("dumpbin /all %S /out:a.txt", sorted_a.v[i]);
process_join(h, max_U64, 0);
h = launch_cmd_linef("dumpbin /all %S /out:b.txt", sorted_b.v[i]);
process_join(h, max_U64, 0);
}
Assert(is_match);
if (!is_match) { break; }
@@ -495,7 +495,7 @@ t_match_folders(String8 a, String8 b)
temp_end(temp);
}
}
scratch_end(scratch);
return is_match;
}
@@ -504,25 +504,25 @@ internal void
t_entry_point(CmdLine *cmdline)
{
Temp scratch = scratch_begin(0,0);
U64 dashes_size = 9999;
U8 *dashes = push_array(scratch.arena, U8, dashes_size);
MemorySet(dashes, '-', dashes_size);
U64 dots_size = 9999;
U8 *dots = push_array(scratch.arena, U8, dots_size);
MemorySet(dots, '.', dots_size);
char *spaces = " ";
#define PrintHeader(p) fprintf(stderr, "--- %s %.*s\n", p, Max((80-4) - (int)strlen(p), 3), dashes)
//
// Handle -help
//
{
B32 print_help = cmd_line_has_flag(cmdline, str8_lit("help")) ||
cmd_line_has_flag(cmdline, str8_lit("h"));
cmd_line_has_flag(cmdline, str8_lit("h"));
if (print_help) {
PrintHeader("Help");
fprintf(stderr, " %s\n\n", BUILD_TITLE_STRING_LITERAL);
@@ -536,10 +536,10 @@ t_entry_point(CmdLine *cmdline)
fprintf(stderr, " -verbose Enable verbose mode\n");
fprintf(stderr, " -print_stdout Print to console stdout and stderr of a run\n");
fprintf(stderr, " -help Print help menu and exit\n");
os_abort(0);
abort_self(0);
}
}
#if 0
//
// config
@@ -564,7 +564,7 @@ t_entry_point(CmdLine *cmdline)
fprintf(stderr, "\n");
}
#endif
//
// Handle -list
//
@@ -574,10 +574,10 @@ t_entry_point(CmdLine *cmdline)
for EachIndex(i, g_torture_test_count) {
fprintf(stdout, " %s\n", g_torture_tests[i].label);
}
os_abort(0);
abort_self(0);
}
}
//
// Handle -linker
//
@@ -591,14 +591,14 @@ t_entry_point(CmdLine *cmdline)
g_linker = linker_opt->value_string;
} else {
fprintf(stderr, "ERROR: -linker has invalid number of arguments\n");
os_abort(1);
abort_self(1);
}
} else {
// assume default linker
g_linker = str8_lit("radlink");
}
}
//
// Handle -test_data
//
@@ -609,7 +609,7 @@ t_entry_point(CmdLine *cmdline)
//fprintf(stderr, "WARNING: The test data folder path was not specified. Specify the path when running the program, assuming: %.*s --test_data:%.*s\n", str8_varg(cmdline->exe_name), str8_varg(g_test_data));
}
}
//
// Handle optional -target
//
@@ -637,31 +637,31 @@ t_entry_point(CmdLine *cmdline)
}
}
}
if (ht->count == 0) {
fprintf(stderr, "ERROR: -target matches not found for the following patterns: ");
for EachNode(n, String8Node, target_opt->value_strings.first) {
fprintf(stderr, "\"%.*s\"\n", str8_varg(n->string));
}
os_abort(1);
abort_self(1);
}
} else {
fprintf(stderr, "ERROR: -target has invalid number of arguments\n");
}
}
}
g_verbose = cmd_line_has_flag(cmdline, str8_lit("verbose"));
g_redirect_stdout = !cmd_line_has_flag(cmdline, str8_lit("print_stdout"));
g_stop_on_first_fail_or_crash = !cmd_line_has_flag(cmdline, str8_lit("keep_going"));
// default options when running under debugger
#if OS_WINDOWS
if (!cmd_line_has_flag(cmdline, str8_lit("print_stdout")) && IsDebuggerPresent()) {
g_redirect_stdout = 0;
}
#endif
// Handle -out
{
CmdLineOpt *out_opt = cmd_line_opt_from_string(cmdline, str8_lit("out"));
@@ -673,27 +673,27 @@ t_entry_point(CmdLine *cmdline)
}
}
}
//
// Make Output Directory
//
os_make_directory(g_out);
if (!os_folder_path_exists(g_out)) {
make_directory(g_out);
if (!folder_path_exists(g_out)) {
fprintf(stderr, "ERROR: unable to create output directory \"%.*s\"\n", str8_varg(g_out));
os_abort(1);
abort_self(1);
}
//
// Clean up output from previous run
//
os_delete_file_at_path(g_stdout_file_name);
delete_file_at_path(g_stdout_file_name);
//
// Run tests
//
{
radsort(g_torture_tests, g_torture_test_count, t_test_is_before);
U64List target_indices_list = {0};
if (target.node_count == 0) {
for EachIndex(i, g_torture_test_count) { u64_list_push(scratch.arena, &target_indices_list, i); }
@@ -712,7 +712,7 @@ t_entry_point(CmdLine *cmdline)
}
}
}
//
// -skip
//
@@ -730,15 +730,15 @@ t_entry_point(CmdLine *cmdline)
break;
}
}
if (include_test) {
u64_list_push(scratch.arena, &final_target_list, n->data);
}
}
U64 skip_count = target_indices_list.count - final_target_list.count;
U64Array target_indices = u64_array_from_list(scratch.arena, &final_target_list);
U64 max_label_size = 0;
U64 max_group_size = 0;
for EachIndex(i, target_indices.count) {
@@ -746,19 +746,19 @@ t_entry_point(CmdLine *cmdline)
max_label_size = Max(max_label_size, cstring8_length((U8*)g_torture_tests[test_idx].label));
max_group_size = Max(max_group_size, cstring8_length((U8*)g_torture_tests[test_idx].group));
}
PrintHeader("Tests");
U64 pass_count = 0;
U64 fail_count = 0;
U64 crash_count = 0;
U64 max_digit_count = count_digits_u64(target_indices.count, 10);
U64 total_time_start = os_now_microseconds();
U64 total_time_start = now_time_us();
typedef struct { U64 target_idx, d; } Slowest;
Slowest slowest[5] = {0};
for EachElement(i, slowest) { slowest[i].target_idx = max_U64; }
for EachIndex(i, target_indices.count) {
U64 target_idx = target_indices.v[i];
// print run progress
U64 dots_min = 10;
U64 dots_count = (max_label_size - cstring8_length((U8*)g_torture_tests[target_idx].label)) + dots_min;
@@ -767,27 +767,27 @@ t_entry_point(CmdLine *cmdline)
fprintf(stdout, "[%.*s%I64u/%I64u] ", idx_align_space_count, spaces, i+1, target_indices.count);
fprintf(stdout, "%s %.*s:: %s", g_torture_tests[target_idx].group, (int)(max_group_size - cstring8_length((U8*)g_torture_tests[target_idx].group)), spaces, g_torture_tests[target_idx].label);
fprintf(stdout, " %.*s ", (int)dots_count, dots);
// setup output directory
g_wdir = push_str8f(scratch.arena, "%S\\%s", g_out, g_torture_tests[target_idx].label);
g_wdir = os_full_path_from_path(scratch.arena, g_wdir);
g_wdir = full_path_from_path(scratch.arena, g_wdir);
// delete files from last run in the work directory
if (os_folder_path_exists(g_wdir)) {
if (folder_path_exists(g_wdir)) {
t_delete_dir(g_wdir);
}
os_make_directory(g_wdir);
if (!os_folder_path_exists(g_out)) {
make_directory(g_wdir);
if (!folder_path_exists(g_out)) {
fprintf(stderr, "ERROR: unable to create output directory for test run %.*s\n", str8_varg(g_wdir));
continue;
}
// run test
U64 run_start_time = os_now_microseconds();
U64 run_start_time = now_time_us();
T_RunResult result = t_run(g_torture_tests[target_idx].r);
U64 run_end_time = os_now_microseconds();
U64 run_end_time = now_time_us();
// print result
if (result.status == T_RunStatus_Pass) {
fprintf(stdout, "\x1b[32m" "%s" "\x1b[0m", t_string_from_result(result.status));
@@ -799,13 +799,13 @@ t_entry_point(CmdLine *cmdline)
fprintf(stdout, "\x1b[33m" "%s" "\x1b[0m", t_string_from_result(result.status));
crash_count += 1;
}
if (result.status == T_RunStatus_Pass) {
U64 d = run_end_time - run_start_time;
DateTime t = date_time_from_micro_seconds(d);
String8 s = string_from_elapsed_time(scratch.arena, t);
fprintf(stdout, " %.*s", str8_varg(s));
U64 insert_idx = max_U64;
for EachElement(i, slowest) {
if (d > slowest[i].d) {
@@ -822,18 +822,18 @@ t_entry_point(CmdLine *cmdline)
}
}
fprintf(stdout, "\n");
if (result.status == T_RunStatus_Fail) {
fprintf(stdout, " ERROR: %s:%d: condition: \"%s\"\n", result.fail_file, result.fail_line, result.fail_cond);
}
if (result.status == T_RunStatus_Fail || result.status == T_RunStatus_Crash) {
if (g_stop_on_first_fail_or_crash) { goto exit; }
}
}
fprintf(stderr, "\n");
U64 total_time_end = os_now_microseconds();
U64 total_time_end = now_time_us();
PrintHeader("Summary");
U64 total_time_dt = total_time_end - total_time_start;
String8 total_time_str = string_from_elapsed_time(scratch.arena, date_time_from_micro_seconds(total_time_dt));
@@ -843,7 +843,7 @@ t_entry_point(CmdLine *cmdline)
fprintf(stderr, " Skipped %llu\n", skip_count);
fprintf(stderr, " Time %.*s\n", str8_varg(total_time_str));
fprintf(stderr, "\n");
{
fprintf(stderr, " Slow Tests\n");
U64 label_max = 0;
@@ -854,7 +854,7 @@ t_entry_point(CmdLine *cmdline)
label_max = Max(strlen(g_torture_tests[s.target_idx].label), label_max);
group_max = Max(strlen(g_torture_tests[s.target_idx].group), group_max);
}
for EachElement(i, slowest) {
Slowest s = slowest[i];
if (s.target_idx >= g_torture_test_count) { break; }
@@ -866,17 +866,17 @@ t_entry_point(CmdLine *cmdline)
(int)(label_max - strlen(g_torture_tests[s.target_idx].label)) + 4, dots,
str8_varg(elapsed_time));
}
fprintf(stderr, "\n");
}
exit:;
if (fail_count + crash_count != 0) {
fflush(stdout);
os_abort(fail_count + crash_count);
abort_self(fail_count + crash_count);
}
}
scratch_end(scratch);
}
+6 -6
View File
@@ -25,7 +25,7 @@ d2r_rdi_from_dwarf_writer(Arena *arena, DW_Writer *writer)
String8 exe = t_read_file(scratch.arena, str8_lit("a.exe"));
Assert(exe.size > 0);
B32 was_pdb_deleted = os_delete_file_at_path(t_make_file_path(scratch.arena, str8_lit("a.pdb")));
B32 was_pdb_deleted = delete_file_at_path(t_make_file_path(scratch.arena, str8_lit("a.pdb")));
Assert(was_pdb_deleted);
t_invoke_(t_radbin_path(), str8_lit("-rdi a.exe -out:a.rdi"), max_U64, 0, 0);
@@ -489,14 +489,14 @@ TEST(d2r_general)
T_Ok((test_local->symbol_flags & RDI_SymbolFlag_IsParam) == 0);
String8 test_local_name = str8_from_rdi_string_idx(rdi, test_local->name_string_idx);
T_Ok(str8_match(test_local_name, str8_lit("TestLocal"), 0));
RDI_TypeNode *test_local_type = rdi_element_from_name_idx(rdi, TypeNodes, test_local->type_idx);
T_Ok(test_local_type);
T_Ok(test_local_type->kind == RDI_TypeKind_Alias);
T_Ok(test_local_type->flags == 0);
String8 alias_name = str8_from_rdi_string_idx(rdi, test_local_type->user_defined.name_string_idx);
T_Ok(str8_match(alias_name, str8_lit("char"), 0));
RDI_TypeNode *char_type = rdi_element_from_name_idx(rdi, TypeNodes, test_local_type->user_defined.direct_type_idx);
T_Ok(char_type);
T_Ok(char_type->kind == RDI_TypeKind_Char8);
@@ -505,21 +505,21 @@ TEST(d2r_general)
String8 char_type_name = str8_from_rdi_string_idx(rdi, char_type->built_in.name_string_idx);
T_Ok(str8_match(char_type_name, str8_lit("Char8"), 0));
}
{
RDI_Symbol *test_local = rdi_element_from_name_idx(rdi, LocalVariables, root_scope->local_first + 1);
T_Ok(test_local);
T_Ok((test_local->symbol_flags & RDI_SymbolFlag_IsParam) != 0);
String8 test_local_name = str8_from_rdi_string_idx(rdi, test_local->name_string_idx);
T_Ok(str8_match(test_local_name, str8_lit("TestParam"), 0));
RDI_TypeNode *test_local_type = rdi_element_from_name_idx(rdi, TypeNodes, test_local->type_idx);
T_Ok(test_local_type);
T_Ok(test_local_type->kind == RDI_TypeKind_Alias);
T_Ok(test_local_type->flags == 0);
String8 alias_name = str8_from_rdi_string_idx(rdi, test_local_type->user_defined.name_string_idx);
T_Ok(str8_match(alias_name, str8_lit("char"), 0));
RDI_TypeNode *char_type = rdi_element_from_name_idx(rdi, TypeNodes, test_local_type->user_defined.direct_type_idx);
T_Ok(char_type);
T_Ok(char_type->kind == RDI_TypeKind_Char8);
+29 -23
View File
@@ -121,7 +121,7 @@ dw_input_from_writer(Arena *arena, DW_Writer *writer)
t_write_file(str8_lit("dwarf.obj"), raw_coff);
t_invoke(str8_lit("radlink"), str8_lit("/subsystem:console /entry:entry /out:a.exe /debug:full dwarf.obj"), max_U64);
os_delete_file_at_path(t_make_file_path(scratch.arena, str8_lit("a.pdb")));
delete_file_at_path(t_make_file_path(scratch.arena, str8_lit("a.pdb")));
String8 exe = t_read_file(arena, str8_lit("a.exe"));
PE_BinInfo pe = pe_bin_info_from_data(scratch.arena, exe);
@@ -862,9 +862,10 @@ TEST(dwarf_writer)
TEST(value_in_register)
{
// setup register context
REGS_RegBlockX64 regs = {0};
REGS_RegCode reg_code = reg_code_from_dw_reg(Arch_x64, DW_ExprOp_Reg3 - DW_ExprOp_Reg0);
Rng1U64 reg_range = regs_range_from_code(Arch_x64, 0, reg_code);
X64_RegBlock regs = {0};
ARCH_Info *arch_info = arch_info_from_arch(Arch_x64);
ARCH_RegCode reg_code = arch_reg_code_from_dw(Arch_x64, DW_ExprOp_Reg3 - DW_ExprOp_Reg0);
Rng1U16 reg_range = arch_info->reg_code_rng_table[reg_code];
U64 value = 0xc0ffee;
MemoryCopy((U8 *)&regs + reg_range.min, &value, sizeof(value));
@@ -875,7 +876,7 @@ TEST(value_in_register)
// evaluate the program
DW_ExprValue expr_value;
DW_ExprEvalResult expr_eval = dw_eval_expr(arena, Arch_x64, DW_Format_64Bit, 0, 0, 0, max_U64, expr, regs_read_dwarf_x64, &regs, 0, 0, &expr_value);
DW_ExprEvalResult expr_eval = dw_eval_expr(arena, Arch_x64, DW_Format_64Bit, 0, 0, 0, max_U64, expr, &regs, 0, 0, &expr_value);
// validate eval result
T_Ok(expr_eval == DW_ExprEvalResult_Ok);
@@ -886,9 +887,10 @@ TEST(value_in_register)
TEST(value_in_x_register)
{
// setup register context
REGS_RegBlockX64 regs = {0};
REGS_RegCode reg_code = reg_code_from_dw_reg(Arch_x64, DW_RegX64_FsBase);
Rng1U64 reg_range = regs_range_from_code(Arch_x64, 0, reg_code);
X64_RegBlock regs = {0};
ARCH_Info *arch_info = arch_info_from_arch(Arch_x64);
ARCH_RegCode reg_code = arch_reg_code_from_dw(Arch_x64, DW_RegX64_FsBase);
Rng1U16 reg_range = arch_info->reg_code_rng_table[reg_code];
U64 value = 0xc0ffee;
MemoryCopy((U8 *)&regs + reg_range.min, &value, sizeof(value));
@@ -899,7 +901,7 @@ TEST(value_in_x_register)
// evaluate the program
DW_ExprValue expr_value;
DW_ExprEvalResult expr_eval = dw_eval_expr(arena, Arch_x64, DW_Format_64Bit, 0, 0, 0, max_U64, expr, regs_read_dwarf_x64, &regs, 0, 0, &expr_value);
DW_ExprEvalResult expr_eval = dw_eval_expr(arena, Arch_x64, DW_Format_64Bit, 0, 0, 0, max_U64, expr, &regs, 0, 0, &expr_value);
// validate eval result
T_Ok(expr_eval == DW_ExprEvalResult_Ok);
@@ -917,7 +919,7 @@ TEST(address_of_value)
// evaluate the program
DW_ExprValue expr_value;
DW_ExprEvalResult expr_eval = dw_eval_expr(arena, Arch_x64, DW_Format_64Bit, 0, 0, 0, max_U64, expr, 0, 0, 0, 0, &expr_value);
DW_ExprEvalResult expr_eval = dw_eval_expr(arena, Arch_x64, DW_Format_64Bit, 0, 0, 0, max_U64, expr, 0, 0, 0, &expr_value);
// validate eval result
T_Ok(expr_eval == DW_ExprEvalResult_Ok);
@@ -927,19 +929,22 @@ TEST(address_of_value)
TEST(register_relative_variable)
{
ARCH_Info *arch_info = arch_info_from_arch(Arch_x64);
// setup register context
REGS_RegBlockX64 regs = {0};
REGS_RegCode reg_code = reg_code_from_dw_reg(Arch_x64, DW_ExprOp_BReg11 - DW_ExprOp_BReg0);
Rng1U64 reg_range = regs_range_from_code(Arch_x64, 0, reg_code);
X64_RegBlock regs = {0};
DW_Reg reg_dw_id = (DW_ExprOp_BReg11 - DW_ExprOp_BReg0);
ARCH_RegCode reg_code = arch_reg_code_from_dw(Arch_x64, reg_dw_id);
Rng1U16 reg_rng = arch_info->reg_code_rng_table[reg_code];
U64 value = 1;
MemoryCopy((U8 *)&regs + reg_range.min, &value, sizeof(value));
MemoryCopy((U8 *)&regs + reg_rng.min, &value, sizeof(value));
DW_ExprEnc expr_encs[] = { DW_ExprEnc_Op(BReg11), DW_ExprEnc_SLEB128(44) };
String8 expr_data = dw_encode_expr(arena, Arch_x64, DW_Format_64Bit, expr_encs, ArrayCount(expr_encs));
DW_Expr expr = dw_expr_from_data(arena, DW_Format_64Bit, byte_size_from_arch(Arch_x64), expr_data);
DW_ExprValue expr_value;
DW_ExprEvalResult expr_eval = dw_eval_expr(arena, Arch_x64, DW_Format_64Bit, 0, 0, 0, max_U64, expr, regs_read_dwarf_x64, &regs, 0, 0, &expr_value);
DW_ExprEvalResult expr_eval = dw_eval_expr(arena, Arch_x64, DW_Format_64Bit, 0, 0, 0, max_U64, expr, &regs, 0, 0, &expr_value);
// validate eval result
T_Ok(expr_eval == DW_ExprEvalResult_Ok);
@@ -955,7 +960,7 @@ TEST(frame_relative_variable)
U64 frame_base = 123;
DW_ExprValue expr_value;
DW_ExprEvalResult expr_eval = dw_eval_expr(arena, Arch_x64, DW_Format_64Bit, frame_base, 0, 0, max_U64, expr, 0, 0, 0, 0, &expr_value);
DW_ExprEvalResult expr_eval = dw_eval_expr(arena, Arch_x64, DW_Format_64Bit, frame_base, 0, 0, max_U64, expr, 0, 0, 0, &expr_value);
T_Ok(expr_eval == DW_ExprEvalResult_Ok);
T_Ok(expr_value.type == DW_ExprValueType_Addr);
@@ -975,18 +980,19 @@ TEST(call_by_reference)
U64 value = 0xc0ffee;
MemoryCopy(memory + 32, &value, sizeof(value));
REGS_RegBlockX64 regs = {0};
REGS_RegCode reg_code = reg_code_from_dw_reg(Arch_x64, 58); // fsbase
Rng1U64 reg_range = regs_range_from_code(Arch_x64, 0, reg_code);
ARCH_Info *arch_info = arch_info_from_arch(Arch_x64);
X64_RegBlock regs = {0};
ARCH_RegCode reg_code = arch_reg_code_from_dw(Arch_x64, 58); // fsbase
Rng1U16 reg_rng = arch_info->reg_code_rng_table[reg_code];
U64 memory_ptr = IntFromPtr(memory);
MemoryCopy((U8 *)&regs + reg_range.min, &memory_ptr, sizeof(memory_ptr));
MemoryCopy((U8 *)&regs + reg_rng.min, &memory_ptr, sizeof(memory_ptr));
DW_ExprEnc expr_encs[] = { DW_ExprEnc_Op(BRegX), DW_ExprEnc_ULEB128(58), DW_ExprEnc_SLEB128(32), DW_ExprEnc_Op(Deref) };
String8 expr_data = dw_encode_expr(arena, Arch_x64, DW_Format_64Bit, expr_encs, ArrayCount(expr_encs));
DW_Expr expr = dw_expr_from_data(arena, DW_Format_64Bit, byte_size_from_arch(Arch_x64), expr_data);
DW_ExprValue expr_value = { 0 };
DW_ExprEvalResult expr_eval = dw_eval_expr(arena, Arch_x64, DW_Format_64Bit, 0, 0, 0, max_U64, expr, regs_read_dwarf_x64, &regs, t_machine_op_mem_read, 0, &expr_value);
DW_ExprEvalResult expr_eval = dw_eval_expr(arena, Arch_x64, DW_Format_64Bit, 0, 0, 0, max_U64, expr, &regs, t_machine_op_mem_read, 0, &expr_value);
T_Ok(expr_value.type == DW_ExprValueType_Generic);
T_Ok(expr_value.generic.size == sizeof(U64));
@@ -1001,7 +1007,7 @@ TEST(plus_uconst)
DW_Expr expr = dw_expr_from_data(arena, DW_Format_64Bit, byte_size_from_arch(Arch_x64), expr_data);
DW_ExprValue expr_value;
DW_ExprEvalResult expr_eval = dw_eval_expr(arena, Arch_x64, DW_Format_64Bit, 0, 0, 0, max_U64, expr, 0, 0, t_machine_op_mem_read, 0, &expr_value);
DW_ExprEvalResult expr_eval = dw_eval_expr(arena, Arch_x64, DW_Format_64Bit, 0, 0, 0, max_U64, expr, 0, t_machine_op_mem_read, 0, &expr_value);
T_Ok(expr_value.type == DW_ExprValueType_Addr);
T_Ok(expr_value.addr == 0x123 + 4);
@@ -1011,7 +1017,7 @@ TEST(plus_uconst)
TEST(reg_split_spill)
{
// setup register context
REGS_RegBlockX64 regs = {0};
X64_RegBlock regs = {0};
{
REGS_RegCode reg_code = reg_code_from_dw_reg(Arch_x64, DW_ExprOp_BReg3 - DW_ExprOp_BReg0);
Rng1U64 reg_range = regs_range_from_code(Arch_x64, 0, reg_code);
+2 -6
View File
@@ -62,9 +62,7 @@
#include "rdi_from_dwarf/rdi_from_dwarf_2.h"
#include "obj/obj.h"
#include "radbin/radbin.h"
#include "regs/regs.h"
#include "regs/rdi/regs_rdi.h"
#include "regs/dwarf/regs_dwarf.h"
#include "arch/arch_inc.h"
#include "dbg_info/dbg_info.h"
#include "disasm/disasm.h"
#include "stap/stap_parse.h"
@@ -137,9 +135,7 @@
#include "rdi_from_dwarf/rdi_from_dwarf_2.c"
#include "obj/obj.c"
#include "radbin/radbin.c"
#include "regs/regs.c"
#include "regs/rdi/regs_rdi.c"
#include "regs/dwarf/regs_dwarf.c"
#include "arch/arch_inc.c"
#include "dbg_info/dbg_info.c"
#include "disasm/disasm.c"
#include "stap/stap_parse.c"
+27 -23
View File
@@ -16,42 +16,46 @@ TEST(p2r_determ)
{
// rjf: unpack paths, make output directory
String8 pdb_path = path_normalized_from_string(arena, pdb_paths[pdb_idx]);
// rjf: generate all RDIs
String8List rdi_paths = {0};
String8List dump_paths = {0};
{
OS_HandleList processes = {0};
ProcessList processes = {0};
for EachIndex(repeat_idx, num_repeats_per_pdb)
{
String8 rdi_name = push_str8f(arena, "repeat_%I64u.rdi", repeat_idx);
String8 rdi_path = t_make_file_path(arena, rdi_name);
str8_list_push(arena, &rdi_paths, rdi_path);
String8 cmdl = str8f(arena, "radbin -rdi -deterministic %S -out:%S", pdb_path, rdi_path);
OS_Handle process_handle = os_cmd_line_launch(cmdl);
T_Ok(!os_handle_match(os_handle_zero(), process_handle));
os_handle_list_push(arena, &processes, process_handle);
Process process = launch_cmd_line(cmdl);
T_Ok(!process_match(process_zero(), process));
process_list_push(arena, &processes, process);
}
for EachNode(n, ProcessNode, processes.first)
{
process_join(n->v, max_U64, 0);
}
// wait on the converters
for EachNode(n, OS_HandleNode, processes.first) { os_process_join(n->v, max_U64, 0); }
}
// rjf: generate all dumps
{
OS_HandleList processes = {0};
ProcessList processes = {0};
for EachNode(n, String8Node, rdi_paths.first)
{
String8 rdi_path = n->string;
String8 dump_path = push_str8f(arena, "%S.dump", rdi_path);
String8 dump_path = str8f(arena, "%S.dump", rdi_path);
str8_list_push(arena, &dump_paths, dump_path);
OS_Handle process_handle = os_cmd_line_launchf("radbin -dump -deterministic %S -out:%S", rdi_path, dump_path);
T_Ok(!os_handle_match(os_handle_zero(), process_handle));
os_handle_list_push(arena, &processes, process_handle);
Process process_handle = launch_cmd_linef("radbin -dump -deterministic %S -out:%S", rdi_path, dump_path);
T_Ok(!process_match(process_zero(), process_handle));
process_list_push(arena, &processes, process_handle);
}
for EachNode(n, ProcessNode, processes.first)
{
process_join(n->v, max_U64, 0);
}
for EachNode(n, OS_HandleNode, processes.first) { os_process_join(n->v, max_U64, 0); }
}
// rjf: gather all hashes/paths
U64 rdi_hashes_count = rdi_paths.node_count;
U128 *rdi_hashes = push_array(arena, U128, rdi_hashes_count);
@@ -65,11 +69,11 @@ TEST(p2r_determ)
{
Temp scratch = scratch_begin(0, 0);
String8 rdi_path = n->string;
String8 path = rdi_path;
String8 path = rdi_path;
T_Ok(path.size);
String8 data = os_data_from_file_path(scratch.arena, path);
String8 data = data_from_file_path(scratch.arena, path);
T_Ok(data.size);
rdi_hashes [idx] = u128_hash_from_str8(data);
rdi_hashes[idx] = u128_hash_from_str8(data);
rdi_paths_array[idx] = path;
scratch_end(scratch);
idx += 1;
@@ -82,15 +86,15 @@ TEST(p2r_determ)
Temp scratch = scratch_begin(0, 0);
String8 path = n->string;
T_Ok(path.size);
String8 data = os_data_from_file_path(scratch.arena, path);
String8 data = data_from_file_path(scratch.arena, path);
T_Ok(data.size);
dump_hashes [idx] = u128_hash_from_str8(data);
dump_hashes[idx] = u128_hash_from_str8(data);
dump_paths_array[idx] = path;
scratch_end(scratch);
idx += 1;
}
}
// rjf: determine if all hashes match
U64 mismatch_idx = max_U64;
for EachIndex(idx, rdi_hashes_count)
@@ -109,7 +113,7 @@ TEST(p2r_determ)
break;
}
}
// rjf: output bad case info
if (mismatch_idx != max_U64) {
U64 idx = mismatch_idx;
+12 -12
View File
@@ -1915,7 +1915,7 @@ TEST(weak_cycle)
.symbols = (T_COFF_DefSymbol[]){ T_COFF_DefSymbol_Extern("my_entry", "text", 0), {0} }
}));
U64 timeout = os_now_microseconds() + 3 * 1000 * 1000; // give a generous 3 seconds
U64 timeout = now_time_us() + 3 * 1000 * 1000; // give a generous 3 seconds
t_invoke_linker_timeoutf(timeout, "/subsystem:console /entry:my_entry %S %S %S", entry_obj_name, ab_obj_name, ba_obj_name);
}
@@ -3979,18 +3979,18 @@ TEST(import_kernel32)
#if OS_WINDOWS
{
String8 test_file_path = push_str8f(arena, "%S/test", g_wdir);
os_delete_file_at_path(test_file_path);
delete_file_at_path(test_file_path);
OS_ProcessLaunchParams launch_opts = {0};
ProcessLaunchParams launch_opts = {0};
launch_opts.inherit_env = 0;
launch_opts.path = g_wdir;
str8_list_pushf(arena, &launch_opts.cmd_line, "%S/a.exe", g_wdir);
OS_Handle handle = os_process_launch(&launch_opts);
AssertAlways(!os_handle_match(handle, os_handle_zero()));
Process handle = process_launch(&launch_opts);
AssertAlways(!process_match(handle, process_zero()));
U64 exit_code = max_U64;
os_process_join(handle, max_U64, &exit_code);
process_join(handle, max_U64, &exit_code);
T_Ok(exit_code == 0);
T_Ok(os_file_path_exists(test_file_path));
T_Ok(file_path_exists(test_file_path));
}
#endif
}
@@ -6413,17 +6413,17 @@ TEST(determ_test)
String8 main_pdb = t_read_file(arena, str8_lit("main.pdb"));
// multi-threaded links
OS_HandleList linkers = {0};
ProcessList linkers = {0};
for EachIndex(i, run_count) {
String8 out_path = t_make_file_path(arena, str8f(arena, "%llu.exe", i));
String8 cmdl = str8f(arena, "%S %S /debug:full /rad_time_stamp:0 /rad_imagealtpath:main.exe /pdbaltpath:main.pdb /rad_log:-all /rad_ignore:74 /out:%S", t_radlink_path(), test_path, out_path);
OS_Handle process_handle = os_cmd_line_launch(cmdl);
T_Ok(!os_handle_match(os_handle_zero(), process_handle));
os_handle_list_push(arena, &linkers, process_handle);
Process process_handle = launch_cmd_line(cmdl);
T_Ok(!process_match(process_zero(), process_handle));
process_list_push(arena, &linkers, process_handle);
}
// wait for linkers
for EachNode(n, OS_HandleNode, linkers.first) { os_process_join(n->v, max_U64, 0); }
for EachNode(n, ProcessNode, linkers.first) { process_join(n->v, max_U64, 0); }
for EachIndex(i, run_count) {
Temp temp = temp_begin(arena);