Skip to content

Commit dfc20e5

Browse files
authored
Merge pull request #185 from tsoding/rere
Implement Record/Replay functionality for btest
2 parents f756cbf + 06a5daa commit dfc20e5

21 files changed

+3031
-241
lines changed

.github/workflows/ci.yml

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ on:
99
- main
1010

1111
# TODO: add jobs that test on different host platforms (windows, aarch64, etc)
12+
# TODO: build examples on CI
13+
# May require a special support for build-only mode in btest
1214

1315
jobs:
1416
btest:
@@ -31,6 +33,3 @@ jobs:
3133
- name: Run Tests
3234
run: |
3335
PATH=$(realpath uxn11/bin):$PATH ./build/btest
34-
- name: Build Examples
35-
run: |
36-
PATH=$(realpath uxn11/bin):$PATH ./build/btest -dir ./examples/ -build-only

Makefile

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,14 +31,18 @@ LINUX_OBJS=\
3131
$(BUILD)/flag.linux.o \
3232
$(BUILD)/libc.linux.o \
3333
$(BUILD)/arena.linux.o \
34-
$(BUILD)/fake6502.linux.o
34+
$(BUILD)/fake6502.linux.o \
35+
$(BUILD)/jim.linux.o \
36+
$(BUILD)/jimp.linux.o
3537

3638
MINGW32_OBJS=\
3739
$(BUILD)/nob.mingw32.o \
3840
$(BUILD)/flag.mingw32.o \
3941
$(BUILD)/libc.mingw32.o \
4042
$(BUILD)/arena.mingw32.o \
41-
$(BUILD)/fake6502.mingw32.o
43+
$(BUILD)/fake6502.mingw32.o \
44+
$(BUILD)/jim.mingw32.o \
45+
$(BUILD)/jimp.mingw32.o
4246

4347
.PHONY: all
4448
all: $(BUILD)/b $(BUILD)/btest

src/b.rs

Lines changed: 24 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -487,7 +487,7 @@ pub unsafe fn compile_primary_expression(l: *mut Lexer, c: *mut Compiler) -> Opt
487487
get_and_expect_token_but_continue(l, c, Token::CBracket)?;
488488

489489
let result = allocate_auto_var(&mut (*c).auto_vars_ator);
490-
let word_size = Arg::Literal(target_word_size((*c).target));
490+
let word_size = Arg::Literal((*c).target.word_size());
491491
// TODO: Introduce Op::Index instruction that indices values without explicitly emit Binop::Mult and uses efficient multiplication by the size of the word at the codegen level.
492492
push_opcode(Op::Binop {binop: Binop::Mult, index: result, lhs: offset, rhs: word_size}, (*l).loc, c);
493493
push_opcode(Op::Binop {binop: Binop::Plus, index: result, lhs: arg, rhs: Arg::AutoVar(result)}, (*l).loc, c);
@@ -1139,9 +1139,9 @@ pub unsafe fn compile_program(l: *mut Lexer, c: *mut Compiler) -> Option<()> {
11391139
}
11401140

11411141
pub unsafe fn include_path_if_exists(input_paths: &mut Array<*const c_char>, path: *const c_char) -> Option<()> {
1142-
let path_exists = file_exists(path);
1143-
if path_exists < 0 { return None; }
1144-
if path_exists > 0 { da_append(input_paths, path); }
1142+
if file_exists(path)? {
1143+
da_append(input_paths, path);
1144+
}
11451145
Some(())
11461146
}
11471147

@@ -1158,7 +1158,7 @@ pub unsafe fn main(mut argc: i32, mut argv: *mut*mut c_char) -> Option<()> {
11581158
}
11591159

11601160
let default_target_name = if let Some(default_target) = default_target {
1161-
name_of_target(default_target).expect("default target name not found")
1161+
default_target.name()
11621162
} else {
11631163
ptr::null()
11641164
};
@@ -1205,13 +1205,13 @@ pub unsafe fn main(mut argc: i32, mut argv: *mut*mut c_char) -> Option<()> {
12051205

12061206
if strcmp(*target_name, c!("list")) == 0 {
12071207
fprintf(stderr(), c!("Compilation targets:\n"));
1208-
for i in 0..TARGET_NAMES.len() {
1209-
fprintf(stderr(), c!(" %s\n"), (*TARGET_NAMES)[i].name);
1208+
for i in 0..TARGET_ORDER.len() {
1209+
fprintf(stderr(), c!(" %s\n"), (*TARGET_ORDER)[i].name());
12101210
}
12111211
return Some(());
12121212
}
12131213

1214-
let Some(target) = target_by_name(*target_name) else {
1214+
let Some(target) = Target::by_name(*target_name) else {
12151215
usage();
12161216
fprintf(stderr(), c!("ERROR: unknown target `%s`\n"), *target_name);
12171217
return None;
@@ -1238,9 +1238,7 @@ pub unsafe fn main(mut argc: i32, mut argv: *mut*mut c_char) -> Option<()> {
12381238
//
12391239
// - rexim (2025-06-12 20:56:08)
12401240
let libb_path = c!("./libb");
1241-
let libb_path_exist = file_exists(libb_path);
1242-
if libb_path_exist < 0 { return None; }
1243-
if libb_path_exist == 0 {
1241+
if !file_exists(libb_path)? {
12441242
fprintf(stderr(), c!("ERROR: No standard library path %s found. Please run the compiler from the same folder where %s is located. Or if you don't want to use the standard library pass the -%s flag.\n"), libb_path, libb_path, flag_name(nostdlib));
12451243
return None;
12461244
}
@@ -1272,7 +1270,7 @@ pub unsafe fn main(mut argc: i32, mut argv: *mut*mut c_char) -> Option<()> {
12721270
let input_path = *input_paths.items.add(i);
12731271

12741272
input.count = 0;
1275-
if !read_entire_file(input_path, &mut input) { return None; }
1273+
read_entire_file(input_path, &mut input)?;
12761274

12771275
let mut l: Lexer = lexer::new(input_path, input.items, input.items.add(input.count), *historical);
12781276

@@ -1310,7 +1308,7 @@ pub unsafe fn main(mut argc: i32, mut argv: *mut*mut c_char) -> Option<()> {
13101308
}
13111309

13121310
let output_asm_path = temp_sprintf(c!("%s.s"), effective_output_path);
1313-
if !write_entire_file(output_asm_path, output.items as *const c_void, output.count) { return None; }
1311+
write_entire_file(output_asm_path, output.items as *const c_void, output.count)?;
13141312
printf(c!("INFO: Generated %s\n"), output_asm_path);
13151313

13161314
let (gas, cc) = if cfg!(target_arch = "aarch64") && (cfg!(target_os = "linux") || cfg!(target_os = "android")) {
@@ -1351,7 +1349,7 @@ pub unsafe fn main(mut argc: i32, mut argv: *mut*mut c_char) -> Option<()> {
13511349
}
13521350
if !cmd_run_sync_and_reset(&mut cmd) { return None; }
13531351
if *run {
1354-
runner::gas_aarch64_linux::run(&mut cmd, effective_output_path, da_slice(run_args))?;
1352+
runner::gas_aarch64_linux::run(&mut cmd, effective_output_path, da_slice(run_args), None)?;
13551353
}
13561354
}
13571355
Target::Gas_x86_64_Linux => {
@@ -1369,7 +1367,7 @@ pub unsafe fn main(mut argc: i32, mut argv: *mut*mut c_char) -> Option<()> {
13691367
}
13701368

13711369
let output_asm_path = temp_sprintf(c!("%s.s"), effective_output_path);
1372-
if !write_entire_file(output_asm_path, output.items as *const c_void, output.count) { return None; }
1370+
write_entire_file(output_asm_path, output.items as *const c_void, output.count)?;
13731371
printf(c!("INFO: Generated %s\n"), output_asm_path);
13741372

13751373
if !(cfg!(target_arch = "x86_64") && cfg!(target_os = "linux")) {
@@ -1402,7 +1400,7 @@ pub unsafe fn main(mut argc: i32, mut argv: *mut*mut c_char) -> Option<()> {
14021400
}
14031401
if !cmd_run_sync_and_reset(&mut cmd) { return None; }
14041402
if *run {
1405-
runner::gas_x86_64_linux::run(&mut cmd, effective_output_path, da_slice(run_args))?
1403+
runner::gas_x86_64_linux::run(&mut cmd, effective_output_path, da_slice(run_args), None)?
14061404
}
14071405
}
14081406
Target::Gas_x86_64_Windows => {
@@ -1426,7 +1424,7 @@ pub unsafe fn main(mut argc: i32, mut argv: *mut*mut c_char) -> Option<()> {
14261424
let effective_output_path = temp_sprintf(c!("%s.exe"), base_path);
14271425

14281426
let output_asm_path = temp_sprintf(c!("%s.s"), base_path);
1429-
if !write_entire_file(output_asm_path, output.items as *const c_void, output.count) { return None; }
1427+
write_entire_file(output_asm_path, output.items as *const c_void, output.count)?;
14301428
printf(c!("INFO: Generated %s\n"), output_asm_path);
14311429

14321430
let cc = if cfg!(target_arch = "x86_64") && cfg!(target_os = "windows") {
@@ -1459,7 +1457,7 @@ pub unsafe fn main(mut argc: i32, mut argv: *mut*mut c_char) -> Option<()> {
14591457
}
14601458
if !cmd_run_sync_and_reset(&mut cmd) { return None; }
14611459
if *run {
1462-
runner::gas_x86_64_windows::run(&mut cmd, effective_output_path, da_slice(run_args))?;
1460+
runner::gas_x86_64_windows::run(&mut cmd, effective_output_path, da_slice(run_args), None)?;
14631461
}
14641462
}
14651463
Target::Fasm_x86_64_Linux => {
@@ -1477,7 +1475,7 @@ pub unsafe fn main(mut argc: i32, mut argv: *mut*mut c_char) -> Option<()> {
14771475
}
14781476

14791477
let output_asm_path = temp_sprintf(c!("%s.asm"), effective_output_path);
1480-
if !write_entire_file(output_asm_path, output.items as *const c_void, output.count) { return None; }
1478+
write_entire_file(output_asm_path, output.items as *const c_void, output.count)?;
14811479
printf(c!("INFO: Generated %s\n"), output_asm_path);
14821480

14831481
if !(cfg!(target_arch = "x86_64") && cfg!(target_os = "linux")) {
@@ -1510,7 +1508,7 @@ pub unsafe fn main(mut argc: i32, mut argv: *mut*mut c_char) -> Option<()> {
15101508
}
15111509
if !cmd_run_sync_and_reset(&mut cmd) { return None; }
15121510
if *run {
1513-
runner::fasm_x86_64_linux::run(&mut cmd, effective_output_path, da_slice(run_args))?
1511+
runner::fasm_x86_64_linux::run(&mut cmd, effective_output_path, da_slice(run_args), None)?
15141512
}
15151513
}
15161514
Target::Fasm_x86_64_Windows => {
@@ -1534,7 +1532,7 @@ pub unsafe fn main(mut argc: i32, mut argv: *mut*mut c_char) -> Option<()> {
15341532
let effective_output_path = temp_sprintf(c!("%s.exe"), base_path);
15351533

15361534
let output_asm_path = temp_sprintf(c!("%s.asm"), base_path);
1537-
if !write_entire_file(output_asm_path, output.items as *const c_void, output.count) { return None; }
1535+
write_entire_file(output_asm_path, output.items as *const c_void, output.count)?;
15381536
printf(c!("INFO: Generated %s\n"), output_asm_path);
15391537

15401538
let cc = if cfg!(target_arch = "x86_64") && cfg!(target_os = "windows") {
@@ -1567,7 +1565,7 @@ pub unsafe fn main(mut argc: i32, mut argv: *mut*mut c_char) -> Option<()> {
15671565
}
15681566
if !cmd_run_sync_and_reset(&mut cmd) { return None; }
15691567
if *run {
1570-
runner::fasm_x86_64_windows::run(&mut cmd, effective_output_path, da_slice(run_args))?;
1568+
runner::fasm_x86_64_windows::run(&mut cmd, effective_output_path, da_slice(run_args), None)?;
15711569
}
15721570
}
15731571
Target::Uxn => {
@@ -1582,10 +1580,10 @@ pub unsafe fn main(mut argc: i32, mut argv: *mut*mut c_char) -> Option<()> {
15821580
effective_output_path = *output_path;
15831581
}
15841582

1585-
if !write_entire_file(effective_output_path, output.items as *const c_void, output.count) { return None; }
1583+
write_entire_file(effective_output_path, output.items as *const c_void, output.count)?;
15861584
printf(c!("INFO: Generated %s\n"), effective_output_path);
15871585
if *run {
1588-
runner::uxn::run(&mut cmd, c!("uxnemu"), effective_output_path, da_slice(run_args))?;
1586+
runner::uxn::run(&mut cmd, c!("uxnemu"), effective_output_path, da_slice(run_args), None)?;
15891587
}
15901588
}
15911589
Target::Mos6502 => {
@@ -1601,10 +1599,10 @@ pub unsafe fn main(mut argc: i32, mut argv: *mut*mut c_char) -> Option<()> {
16011599
effective_output_path = *output_path;
16021600
}
16031601

1604-
if !write_entire_file(effective_output_path, output.items as *const c_void, output.count) { return None; }
1602+
write_entire_file(effective_output_path, output.items as *const c_void, output.count)?;
16051603
printf(c!("INFO: Generated %s\n"), effective_output_path);
16061604
if *run {
1607-
runner::mos6502::run(&mut output, config, effective_output_path)?;
1605+
runner::mos6502::run(&mut output, config, effective_output_path, None)?;
16081606
}
16091607
}
16101608
}

0 commit comments

Comments
 (0)