Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,9 @@ jobs:
- name: Run Tests
run: |
PATH=$(realpath uxn11/bin):$PATH ./build/btest -xt *darwin
- name: Run Tests With Opts
run: |
PATH=$(realpath uxn11/bin):$PATH ./build/btest -xt *darwin -O
macos-aarch64:
runs-on: macos-latest
steps:
Expand All @@ -37,6 +40,8 @@ jobs:
run: make -B
- name: Run Tests
run: ./build/btest -t gas-aarch64-darwin
- name: Run Tests With Opts
run: ./build/btest -t gas-aarch64-darwin -O
macos-x86_64:
runs-on: macos-13
steps:
Expand All @@ -48,3 +53,5 @@ jobs:
run: make -B
- name: Run Tests
run: ./build/btest -t gas-x86_64-darwin
- name: Run Tests With Opts
run: ./build/btest -t gas-x86_64-darwin -O
5 changes: 4 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1 +1,4 @@
build/
build/

# used for rust-analyzer
rust-project.json
1 change: 1 addition & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ CRUST_FLAGS=-g --edition 2021 -C opt-level=0 -C panic="abort"

RSS=\
$(SRC)/arena.rs \
$(SRC)/opt.rs \
$(SRC)/b.rs \
$(SRC)/crust.rs \
$(SRC)/flag.rs \
Expand Down
32 changes: 26 additions & 6 deletions src/b.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ pub mod codegen;
pub mod runner;
pub mod lexer;
pub mod targets;
pub mod opt;

use core::ffi::*;
use core::mem::zeroed;
Expand Down Expand Up @@ -214,7 +215,7 @@ pub unsafe fn define_goto_label(c: *mut Compiler, name: *const c_char, loc: Loc,
Some(())
}

#[derive(Clone, Copy)]
#[derive(Clone, Copy, PartialEq)]
pub enum Arg {
/// Bogus value of an Arg.
///
Expand Down Expand Up @@ -322,13 +323,13 @@ impl Binop {
}
}

#[derive(Clone, Copy)]
#[derive(Clone, Copy, PartialEq)]
pub struct AsmStmt {
line: *const c_char,
loc: Loc,
}

#[derive(Clone, Copy)]
#[derive(Clone, Copy, PartialEq)]
pub enum Op {
Bogus,
UnaryNot {result: usize, arg: Arg},
Expand All @@ -343,7 +344,8 @@ pub enum Op {
Label {label: usize},
JmpLabel {label: usize},
JmpIfNotLabel {label: usize, arg: Arg},
Return {arg: Option<Arg>},
SetRetReg {arg: Arg},
Return,
}

#[derive(Clone, Copy)]
Expand Down Expand Up @@ -846,12 +848,13 @@ pub unsafe fn compile_statement(l: *mut Lexer, c: *mut Compiler) -> Option<()> {
Token::Return => {
get_and_expect_tokens(l, &[Token::SemiColon, Token::OParen])?;
if (*l).token == Token::SemiColon {
push_opcode(Op::Return {arg: None}, (*l).loc, c);
push_opcode(Op::Return, (*l).loc, c);
} else if (*l).token == Token::OParen {
let (arg, _) = compile_expression(l, c)?;
get_and_expect_token_but_continue(l, c, Token::CParen)?;
get_and_expect_token_but_continue(l, c, Token::SemiColon)?;
push_opcode(Op::Return {arg: Some(arg)}, (*l).loc, c);
push_opcode(Op::SetRetReg { arg }, (*l).loc, c);
push_opcode(Op::Return, (*l).loc, c);
} else {
unreachable!();
}
Expand Down Expand Up @@ -973,6 +976,7 @@ pub struct Func {
body: Array<OpWithLocation>,
params_count: usize,
auto_vars_count: usize,
label_count: usize,
}

#[derive(Clone, Copy)]
Expand Down Expand Up @@ -1125,6 +1129,16 @@ pub unsafe fn compile_program(l: *mut Lexer, c: *mut Compiler) -> Option<()> {
}
}
compile_statement(l, c)?;
// setup function epilogue
if let Some(last_op) = da_last_mut(&mut (*c).func_body) {
if (*last_op).opcode != Op::Return {
push_opcode(Op::SetRetReg { arg: Arg::Literal(0) }, (*l).loc, c);
push_opcode(Op::Return, (*l).loc, c);
}
} else {
push_opcode(Op::SetRetReg { arg: Arg::Literal(0) }, (*l).loc, c);
push_opcode(Op::Return, (*l).loc, c);
}
scope_pop(&mut (*c).vars); // end function scope

for i in 0..(*c).func_gotos.count {
Expand All @@ -1144,6 +1158,7 @@ pub unsafe fn compile_program(l: *mut Lexer, c: *mut Compiler) -> Option<()> {
body: (*c).func_body,
params_count,
auto_vars_count: (*c).auto_vars_ator.max,
label_count: (*c).op_label_count,
});
(*c).func_body = zeroed();
(*c).func_goto_labels.count = 0;
Expand Down Expand Up @@ -1286,6 +1301,7 @@ pub unsafe fn main(mut argc: i32, mut argv: *mut*mut c_char) -> Option<()> {
let output_path = flag_str(c!("o"), ptr::null(), c!("Output path"));
let run = flag_bool(c!("run"), false, c!("Run the compiled program (if applicable for the target)"));
let help = flag_bool(c!("help"), false, c!("Print this help message"));
let opt = flag_bool(c!("O"), false, c!("Enable optimizations"));
let linker = flag_list(c!("L"), c!("Append a flag to the linker of the target platform"));
let nostdlib = flag_bool(c!("nostdlib"), false, c!("Do not link with standard libraries like libb and/or libc on some platforms"));
let ir = flag_bool(c!("ir"), false, c!("Instead of compiling, dump the IR of the program to stdout"));
Expand Down Expand Up @@ -1409,6 +1425,10 @@ pub unsafe fn main(mut argc: i32, mut argv: *mut*mut c_char) -> Option<()> {
return None
}

if *opt {
opt::optimize(&mut c);
}

let garbage_base = if (*output_path).is_null() {
get_garbage_base(*input_paths.items, target)?
} else {
Expand Down
23 changes: 14 additions & 9 deletions src/btest.rs
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,7 @@ pub struct Report {

pub unsafe fn execute_test(
// Inputs
test_folder: *const c_char, name: *const c_char, target: Target,
test_folder: *const c_char, name: *const c_char, target: Target, opt: bool,
// Outputs
cmd: *mut Cmd, sb: *mut String_Builder,
) -> Option<Outcome> {
Expand All @@ -185,6 +185,9 @@ pub unsafe fn execute_test(
c!("-t"), target.name(),
c!("-o"), program_path,
}
if opt {
da_append(cmd, c!("-O"));
}
if !cmd_run_sync_and_reset(cmd) {
return Some(Outcome::BuildFail);
}
Expand Down Expand Up @@ -300,7 +303,7 @@ pub unsafe fn matches_glob(pattern: *const c_char, text: *const c_char) -> Optio

pub unsafe fn record_tests(
// Inputs
test_folder: *const c_char, cases: *const [*const c_char], targets: *const [Target], bat: *mut Bat,
test_folder: *const c_char, cases: *const [*const c_char], targets: *const [Target], bat: *mut Bat, opt: bool,
// Outputs
cmd: *mut Cmd, sb: *mut String_Builder,
reports: *mut Array<Report>, stats_by_target: *mut Array<ReportStats>,
Expand Down Expand Up @@ -329,7 +332,7 @@ pub unsafe fn record_tests(
TestState::Enabled => {
let outcome = execute_test(
// Inputs
test_folder, case_name, target,
test_folder, case_name, target, opt,
// Outputs
cmd, sb,
)?;
Expand All @@ -347,7 +350,7 @@ pub unsafe fn record_tests(
} else {
let outcome = execute_test(
// Inputs
test_folder, case_name, target,
test_folder, case_name, target, opt,
// Outputs
cmd, sb,
)?;
Expand Down Expand Up @@ -514,7 +517,7 @@ pub unsafe fn save_bat_to_json_file(
pub unsafe fn replay_tests(
// TODO: The Inputs and the Outputs want to be their own entity. But what should they be called?
// Inputs
test_folder: *const c_char, cases: *const [*const c_char], targets: *const [Target], bat: Bat,
test_folder: *const c_char, cases: *const [*const c_char], targets: *const [Target], bat: Bat, opt: bool,
// Outputs
cmd: *mut Cmd, sb: *mut String_Builder, reports: *mut Array<Report>, stats_by_target: *mut Array<ReportStats>, jim: *mut Jim,
) -> Option<()> {
Expand Down Expand Up @@ -542,7 +545,7 @@ pub unsafe fn replay_tests(
TestState::Enabled => {
let outcome = execute_test(
// Inputs
test_folder, case_name, target,
test_folder, case_name, target, opt,
// Outputs
cmd, sb,
)?;
Expand All @@ -569,7 +572,7 @@ pub unsafe fn replay_tests(
} else {
let outcome = execute_test(
// Inputs
test_folder, case_name, target,
test_folder, case_name, target, opt,
// Outputs
cmd, sb,
)?;
Expand Down Expand Up @@ -640,6 +643,8 @@ pub unsafe fn main(argc: i32, argv: *mut*mut c_char) -> Option<()> {
let record = flag_bool(c!("record"), false, strdup(temp_sprintf(c!("DEPRECATED! Please use `-%s %s` flag instead."), flag_name(action_flag), Action::Record.name()))); // TODO: memory leak
let comment = flag_str(c!("comment"), ptr::null(), strdup(temp_sprintf(c!("Set the comment on disabled test cases when you do `-%s %s`"), flag_name(action_flag), Action::Disable.name()))); // TODO: memory leak

let opt = flag_bool(c!("O"), false, c!("Enable compiler optimizations"));

let test_folder = flag_str(c!("dir"), c!("./tests/"), c!("Test folder"));
let help = flag_bool(c!("help"), false, c!("Print this help message"));

Expand Down Expand Up @@ -815,7 +820,7 @@ pub unsafe fn main(argc: i32, argv: *mut*mut c_char) -> Option<()> {
let mut bat = load_bat_from_json_file_if_exists(json_path, *test_folder, &mut sb, &mut jimp)?;
record_tests(
// Inputs
*test_folder, da_slice(cases), da_slice(targets), &mut bat,
*test_folder, da_slice(cases), da_slice(targets), &mut bat, *opt,
// Outputs
&mut cmd, &mut sb, &mut reports, &mut stats_by_target,
)?;
Expand All @@ -825,7 +830,7 @@ pub unsafe fn main(argc: i32, argv: *mut*mut c_char) -> Option<()> {
let bat = load_bat_from_json_file_if_exists(json_path, *test_folder, &mut sb, &mut jimp)?;
replay_tests(
// Inputs
*test_folder, da_slice(cases), da_slice(targets), bat,
*test_folder, da_slice(cases), da_slice(targets), bat, *opt,
// Outputs
&mut cmd, &mut sb, &mut reports, &mut stats_by_target, &mut jim,
);
Expand Down
12 changes: 4 additions & 8 deletions src/codegen/gas_aarch64.rs
Original file line number Diff line number Diff line change
Expand Up @@ -154,10 +154,10 @@ pub unsafe fn generate_function(name: *const c_char, _name_loc: Loc, params_coun
let op = (*body)[i];
match op.opcode {
Op::Bogus => unreachable!("bogus-amogus"),
Op::Return {arg} => {
if let Some(arg) = arg {
load_arg_to_reg(arg, c!("x0"), output, op.loc, os);
}
Op::SetRetReg { arg } => {
load_arg_to_reg(arg, c!("x0"), output, op.loc, os);
}
Op::Return => {
sb_appendf(output, c!(" add sp, sp, %zu\n"), stack_size);
sb_appendf(output, c!(" ldp x29, x30, [sp], 2*8\n"));
sb_appendf(output, c!(" ret\n"));
Expand Down Expand Up @@ -376,10 +376,6 @@ pub unsafe fn generate_function(name: *const c_char, _name_loc: Loc, params_coun
},
}
}
sb_appendf(output, c!(" mov x0, 0\n"));
sb_appendf(output, c!(" add sp, sp, %zu\n"), stack_size);
sb_appendf(output, c!(" ldp x29, x30, [sp], 2*8\n"));
sb_appendf(output, c!(" ret\n"));
}

pub unsafe fn generate_funcs(output: *mut String_Builder, funcs: *const [Func], variadics: *const [(*const c_char, Variadic)], os: Os) {
Expand Down
12 changes: 4 additions & 8 deletions src/codegen/gas_x86_64.rs
Original file line number Diff line number Diff line change
Expand Up @@ -84,10 +84,10 @@ pub unsafe fn generate_function(name: *const c_char, params_count: usize, auto_v
let op = (*body)[i];
match op.opcode {
Op::Bogus => unreachable!("bogus-amogus"),
Op::Return { arg } => {
if let Some(arg) = arg {
load_arg_to_reg(arg, c!("rax"), output, os);
}
Op::SetRetReg { arg } => {
load_arg_to_reg(arg, c!("rax"), output, os);
}
Op::Return => {
sb_appendf(output, c!(" movq %%rbp, %%rsp\n"));
sb_appendf(output, c!(" popq %%rbp\n"));
sb_appendf(output, c!(" ret\n"));
Expand Down Expand Up @@ -241,10 +241,6 @@ pub unsafe fn generate_function(name: *const c_char, params_count: usize, auto_v
},
}
}
sb_appendf(output, c!(" movq $0, %%rax\n"));
sb_appendf(output, c!(" movq %%rbp, %%rsp\n"));
sb_appendf(output, c!(" popq %%rbp\n"));
sb_appendf(output, c!(" ret\n"));
}

pub unsafe fn generate_funcs(output: *mut String_Builder, funcs: *const [Func], os: Os) {
Expand Down
11 changes: 6 additions & 5 deletions src/codegen/ir.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,13 @@ pub unsafe fn dump_arg(output: *mut String_Builder, arg: Arg) {
pub unsafe fn dump_op(op: OpWithLocation, output: *mut String_Builder) {
match op.opcode {
Op::Bogus => unreachable!("bogus-amogus"),
Op::Return {arg} => {
sb_appendf(output, c!(" return "));
if let Some(arg) = arg {
dump_arg(output, arg);
}
Op::SetRetReg { arg } => {
sb_appendf(output, c!(" ret_reg = "));
dump_arg(output, arg);
sb_appendf(output, c!("\n"));
}
Op::Return => {
sb_appendf(output, c!(" return\n"));
},
Op::Store{index, arg} => {
sb_appendf(output, c!(" store deref[%zu], "), index);
Expand Down
32 changes: 10 additions & 22 deletions src/codegen/mos6502.rs
Original file line number Diff line number Diff line change
Expand Up @@ -756,15 +756,17 @@ pub unsafe fn generate_function(name: *const c_char, params_count: usize, auto_v
let op = (*body)[i];
match op.opcode {
Op::Bogus => unreachable!("bogus-amogus"),
Op::Return {arg} => {
if let Some(arg) = arg {
load_arg(arg, op.loc, out, asm);
Op::SetRetReg { arg } => {
load_arg(arg, op.loc, out, asm);
}
Op::Return => {
if stack_size > 0 {
// seriously... we don't have enough registers to save A to...
instr8(out, STA, ZP, ZP_TMP_0);
add_sp(out, stack_size, asm);
instr8(out, LDA, ZP, ZP_TMP_0);
}

// jump to ret statement
instr0(out, JMP, ABS);
add_reloc(out, RelocationKind::AddressAbs
{idx: *op_addresses.items.add(body.len())}, asm);
instr(out, RTS);
},
Op::Store {index, arg} => {
load_auto_var(out, index, asm);
Expand Down Expand Up @@ -1268,20 +1270,6 @@ pub unsafe fn generate_function(name: *const c_char, params_count: usize, auto_v
},
}
}

instr8(out, LDA, IMM, 0);
instr(out, TAY);

let addr_idx = *op_addresses.items.add(body.len());
*(*asm).addresses.items.add(addr_idx) = (*out).count as u16;

if stack_size > 0 {
// seriously... we don't have enough registers to save A to...
instr8(out, STA, ZP, ZP_TMP_0);
add_sp(out, stack_size, asm);
instr8(out, LDA, ZP, ZP_TMP_0);
}
instr(out, RTS);
}

pub unsafe fn generate_funcs(out: *mut String_Builder, funcs: *const [Func], asm: *mut Assembler) {
Expand Down
Loading