Skip to content

Commit 7d013d4

Browse files
committed
Introduce codegen arguments via -C flag
1 parent 518a558 commit 7d013d4

13 files changed

Lines changed: 690 additions & 60 deletions

File tree

Makefile

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,8 @@ POSIX_OBJS=\
3939
$(BUILD)/libc.posix.o \
4040
$(BUILD)/arena.posix.o \
4141
$(BUILD)/jim.posix.o \
42-
$(BUILD)/jimp.posix.o
42+
$(BUILD)/jimp.posix.o \
43+
$(BUILD)/shlex.posix.o \
4344

4445
MINGW32_OBJS=\
4546
$(BUILD)/nob.mingw32.o \
@@ -48,7 +49,8 @@ MINGW32_OBJS=\
4849
$(BUILD)/libc.mingw32.o \
4950
$(BUILD)/arena.mingw32.o \
5051
$(BUILD)/jim.mingw32.o \
51-
$(BUILD)/jimp.mingw32.o
52+
$(BUILD)/jimp.mingw32.o \
53+
$(BUILD)/shlex.mingw32.o \
5254

5355
.PHONY: all
5456
all: $(BUILD)/b $(BUILD)/btest

examples/game_of_b.b

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
// To compile this example you need to pass appropriate linker flags to the b compiler:
2-
// $ b 65_game_of_b.b -L -lncurses -L -lpanel -run
2+
// $ b 65_game_of_b.b -C link-args='-lncurses -lpanel' -run
33

44
TRUE;
55
FALSE;

examples/raylib.b

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,10 @@
44
// Than pass appropriate linker flags to the b compiler.
55
// # Linux
66
//
7-
// $ b raylib.b -L -L/path/to/raylib-version_linux_amd64/lib/ -L -l:libraylib.a -L -lm -run
7+
// $ b raylib.b -C link-args='-L/path/to/raylib-version_linux_amd64/lib/ -l:libraylib.a -lm' -run
88
//
99
// # Windows mingw32-w64
10-
// > b -t gas-x86_64-windows raylib.b -L -L$HOME/opt/raylib-version_win64_mingw-w64/lib/ -L -l:libraylib.a -L -lwinmm -L -lgdi32 -run
10+
// > b -t gas-x86_64-windows raylib.b -C link-args='-L$HOME/opt/raylib-version_win64_mingw-w64/lib/ -l:libraylib.a -lwinmm -lgdi32' -run
1111
1212
W;
1313

src/b.rs

Lines changed: 28 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ pub mod codegen;
3535
pub mod lexer;
3636
pub mod targets;
3737
pub mod ir;
38+
pub mod shlex;
3839

3940
use core::ffi::*;
4041
use core::mem::zeroed;
@@ -49,6 +50,8 @@ use arena::Arena;
4950
use targets::*;
5051
use lexer::{Lexer, Loc, Token};
5152
use ir::*;
53+
use codegen::*;
54+
use shlex::*;
5255

5356
pub unsafe fn expect_tokens(l: *mut Lexer, tokens: *const [Token]) -> Option<()> {
5457
for i in 0..tokens.len() {
@@ -1191,9 +1194,13 @@ pub unsafe fn main(mut argc: i32, mut argv: *mut*mut c_char) -> Option<()> {
11911194
let target_name = flag_str(c!("t"), default_target_name, c!("Compilation target. Pass \"list\" to get the list of available targets."));
11921195
let output_path = flag_str(c!("o"), ptr::null(), c!("Output path"));
11931196
let run = flag_bool(c!("run"), false, c!("Run the compiled program (if applicable for the target)"));
1194-
let nobuild = flag_bool(c!("nobuild"), false, strdup(temp_sprintf(c!("Skip the build step. Useful in conjunction with the -%s flag when you already have a built program and just want to run it on the specified target without rebuilding it."), flag_name(run)))); // memory leak
1197+
let nobuild = flag_bool(c!("nobuild"), false, temp_sprintf(c!("Skip the build step. Useful in conjunction with the -%s flag when you already have a built program and just want to run it on the specified target without rebuilding it."), flag_name(run)));
11951198
let help = flag_bool(c!("help"), false, c!("Print this help message"));
1196-
let linker = flag_list(c!("L"), c!("Append a flag to the linker of the target platform"));
1199+
let codegen_args = flag_list(CODEGEN_FLAG_NAME, temp_sprintf(c!("Pass an argument to the codegen of the current target selected by the -%s flag. Pass argument `-%s help` to learn more about what current codegen provides. All sorts of linker flag parameters are probably there."), flag_name(target_name), CODEGEN_FLAG_NAME));
1200+
let linker = {
1201+
let name = c!("L");
1202+
flag_list(name, temp_sprintf(c!("DEPRECATED! Append a flag to the linker of the target platform. But not every target even has a linker! For backward compatibility we transform `-%s foo -%s bar -%s ...` into `-%s link-args='foo bar ...'` but do not expect every codegen to support that. Use `-%s help` to learn more about what your current codegen supports. Expect this flag to be removed entirely in the future"), name, name, name, CODEGEN_FLAG_NAME, CODEGEN_FLAG_NAME))
1203+
};
11971204
let nostdlib = flag_bool(c!("nostdlib"), false, c!("Do not link with standard libraries like libb and/or libc on some platforms"));
11981205
let ir = flag_bool(c!("ir"), false, c!("Instead of compiling, dump the IR of the program to stdout"));
11991206
let historical = flag_bool(c!("hist"), false, c!("Makes the compiler strictly follow the description of the B language from the \"Users' Reference to B\" by Ken Thompson as much as possible"));
@@ -1354,12 +1361,23 @@ pub unsafe fn main(mut argc: i32, mut argv: *mut*mut c_char) -> Option<()> {
13541361
// to that object should be computed as `temp_sprintf("%s.o", garbase_base)`.
13551362
let garbage_base = get_garbage_base(program_path, target)?;
13561363

1364+
if (*linker).count > 0 {
1365+
let mut s: Shlex = zeroed();
1366+
for i in 0..(*linker).count {
1367+
shlex_append_quoted(&mut s, *(*linker).items.add(i));
1368+
}
1369+
let codegen_arg = temp_sprintf(c!("link-args=%s"), shlex_join(&mut s));
1370+
da_append(codegen_args, codegen_arg);
1371+
shlex_free(&mut s);
1372+
log(Log_Level::WARNING, c!("Flag -%s is DEPRECATED! Interpreting it as `-%s %s` instead."), flag_name(linker), CODEGEN_FLAG_NAME, codegen_arg);
1373+
}
1374+
13571375
match target {
13581376
Target::Gas_AArch64_Linux => {
13591377
codegen::gas_aarch64::generate_program(
13601378
// Inputs
13611379
&c.program, program_path, garbage_base,
1362-
da_slice(*linker), da_slice(run_args), targets::Os::Linux,
1380+
da_slice(*codegen_args), da_slice(run_args), targets::Os::Linux,
13631381
*nostdlib, *debug, *nobuild, *run,
13641382
// Temporaries
13651383
&mut output, &mut cmd,
@@ -1369,7 +1387,7 @@ pub unsafe fn main(mut argc: i32, mut argv: *mut*mut c_char) -> Option<()> {
13691387
codegen::gas_aarch64::generate_program(
13701388
// Inputs
13711389
&c.program, program_path, garbage_base,
1372-
da_slice(*linker), da_slice(run_args), targets::Os::Darwin,
1390+
da_slice(*codegen_args), da_slice(run_args), targets::Os::Darwin,
13731391
*nostdlib, *debug, *nobuild, *run,
13741392
// Temporaries
13751393
&mut output, &mut cmd,
@@ -1379,7 +1397,7 @@ pub unsafe fn main(mut argc: i32, mut argv: *mut*mut c_char) -> Option<()> {
13791397
codegen::gas_x86_64::generate_program(
13801398
// Inputs
13811399
&c.program, program_path, garbage_base,
1382-
da_slice(*linker), da_slice(run_args), targets::Os::Linux,
1400+
da_slice(*codegen_args), da_slice(run_args), targets::Os::Linux,
13831401
*nostdlib, *debug, *nobuild, *run,
13841402
// Temporaries
13851403
&mut output, &mut cmd,
@@ -1389,7 +1407,7 @@ pub unsafe fn main(mut argc: i32, mut argv: *mut*mut c_char) -> Option<()> {
13891407
codegen::gas_x86_64::generate_program(
13901408
// Inputs
13911409
&c.program, program_path, garbage_base,
1392-
da_slice(*linker), da_slice(run_args), targets::Os::Windows,
1410+
da_slice(*codegen_args), da_slice(run_args), targets::Os::Windows,
13931411
*nostdlib, *debug, *nobuild, *run,
13941412
// Temporaries
13951413
&mut output, &mut cmd,
@@ -1399,7 +1417,7 @@ pub unsafe fn main(mut argc: i32, mut argv: *mut*mut c_char) -> Option<()> {
13991417
codegen::gas_x86_64::generate_program(
14001418
// Inputs
14011419
&c.program, program_path, garbage_base,
1402-
da_slice(*linker), da_slice(run_args), targets::Os::Darwin,
1420+
da_slice(*codegen_args), da_slice(run_args), targets::Os::Darwin,
14031421
*nostdlib, *debug, *nobuild, *run,
14041422
// Temporaries
14051423
&mut output, &mut cmd,
@@ -1409,7 +1427,7 @@ pub unsafe fn main(mut argc: i32, mut argv: *mut*mut c_char) -> Option<()> {
14091427
codegen::uxn::generate_program(
14101428
// Inputs
14111429
&c.program, program_path, garbage_base,
1412-
da_slice(*linker), da_slice(run_args),
1430+
da_slice(*codegen_args), da_slice(run_args),
14131431
*nostdlib, *debug, *nobuild, *run,
14141432
// Temporaries
14151433
&mut output, &mut cmd,
@@ -1419,7 +1437,7 @@ pub unsafe fn main(mut argc: i32, mut argv: *mut*mut c_char) -> Option<()> {
14191437
codegen::mos6502::generate_program(
14201438
// Inputs
14211439
&c.program, program_path, garbage_base,
1422-
da_slice(*linker), da_slice(run_args),
1440+
da_slice(*codegen_args), da_slice(run_args),
14231441
*nostdlib, *debug, *nobuild, *run,
14241442
// Temporaries
14251443
&mut output, &mut cmd,
@@ -1429,7 +1447,7 @@ pub unsafe fn main(mut argc: i32, mut argv: *mut*mut c_char) -> Option<()> {
14291447
codegen::ilasm_mono::generate_program(
14301448
// Inputs
14311449
&c.program, program_path, garbage_base,
1432-
da_slice(*linker), da_slice(run_args),
1450+
da_slice(*codegen_args), da_slice(run_args),
14331451
*nostdlib, *debug, *nobuild, *run,
14341452
// Temporaries
14351453
&mut output, &mut cmd,

src/codegen/gas_aarch64.rs

Lines changed: 48 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ use crate::ir::*;
77
use crate::lexer::*;
88
use crate::missingf;
99
use crate::targets::Os;
10+
use crate::codegen::*;
11+
use crate::shlex::*;
1012

1113
pub unsafe fn align_bytes(bytes: usize, alignment: usize) -> usize {
1214
let rem = bytes%alignment;
@@ -489,14 +491,46 @@ pub unsafe fn generate_asm_funcs(output: *mut String_Builder, asm_funcs: *const
489491
}
490492
}
491493

494+
pub unsafe fn usage(params: *const [Param]) {
495+
fprintf(stderr(), c!("gas_aarch64 codegen for the B compiler\n"));
496+
fprintf(stderr(), c!("OPTIONS:\n"));
497+
print_params_help(params);
498+
}
499+
492500
pub unsafe fn generate_program(
493501
// Inputs
494502
p: *const Program, program_path: *const c_char, garbage_base: *const c_char,
495-
linker: *const [*const c_char], run_args: *const [*const c_char], os: Os,
503+
codegen_args: *const [*const c_char], run_args: *const [*const c_char], os: Os,
496504
nostdlib: bool, debug: bool, nobuild: bool, run: bool,
497505
// Temporaries
498506
output: *mut String_Builder, cmd: *mut Cmd,
499507
) -> Option<()> {
508+
let mut help = false;
509+
let mut link_args = c!("");
510+
let params = &[
511+
Param {
512+
name: c!("help"),
513+
description: c!("Print this help message"),
514+
value: ParamValue::Flag { var: &mut help },
515+
},
516+
Param {
517+
name: c!("link-args"),
518+
description: c!("Additional linker arguments"),
519+
value: ParamValue::String { var: &mut link_args, default: c!("") },
520+
},
521+
];
522+
523+
if let Err(message) = parse_args(params, codegen_args) {
524+
usage(params);
525+
log(Log_Level::ERROR, c!("%s"), message);
526+
return None;
527+
}
528+
529+
if help {
530+
usage(params);
531+
return Some(());
532+
}
533+
500534
if !nobuild {
501535
if debug { todo!("Debug information for aarch64") }
502536

@@ -538,7 +572,12 @@ pub unsafe fn generate_program(
538572
if nostdlib {
539573
cmd_append!(cmd, c!("-nostdlib"));
540574
}
541-
da_append_many(cmd, linker);
575+
let mut s: Shlex = zeroed();
576+
shlex_init(&mut s, link_args, link_args.add(strlen(link_args)));
577+
while !shlex_next(&mut s).is_null() {
578+
da_append(cmd, temp_strdup(s.string));
579+
}
580+
shlex_free(&mut s);
542581
if !cmd_run_sync_and_reset(cmd) { return None; }
543582
}
544583
Os::Darwin => {
@@ -565,7 +604,12 @@ pub unsafe fn generate_program(
565604
c!("-nostdlib"),
566605
}
567606
}
568-
da_append_many(cmd, linker);
607+
let mut s: Shlex = zeroed();
608+
shlex_init(&mut s, link_args, link_args.add(strlen(link_args)));
609+
while !shlex_next(&mut s).is_null() {
610+
da_append(cmd, temp_strdup(s.string));
611+
}
612+
shlex_free(&mut s);
569613
if !cmd_run_sync_and_reset(cmd) { return None; }
570614
}
571615
Os::Windows => todo!(),
@@ -624,4 +668,4 @@ pub unsafe fn generate_program(
624668
}
625669
}
626670
Some(())
627-
}
671+
}

src/codegen/gas_x86_64.rs

Lines changed: 55 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,13 @@
11
use core::ffi::*;
2+
use core::mem::zeroed;
23
use core::cmp;
34
use crate::ir::*;
45
use crate::nob::*;
56
use crate::targets::Os;
67
use crate::crust::libc::*;
78
use crate::lexer::Loc;
9+
use crate::codegen::*;
10+
use crate::shlex::*;
811

912
pub unsafe fn align_bytes(bytes: usize, alignment: usize) -> usize {
1013
let rem = bytes%alignment;
@@ -366,14 +369,46 @@ pub unsafe fn generate_data_section(output: *mut String_Builder, data: *const [u
366369
}
367370
}
368371

372+
pub unsafe fn usage(params: *const [Param]) {
373+
fprintf(stderr(), c!("gas_x86_64 codegen for the B compiler\n"));
374+
fprintf(stderr(), c!("OPTIONS:\n"));
375+
print_params_help(params);
376+
}
377+
369378
pub unsafe fn generate_program(
370379
// Inputs
371380
p: *const Program, program_path: *const c_char, garbage_base: *const c_char,
372-
linker: *const [*const c_char], run_args: *const [*const c_char], os: Os,
381+
codegen_args: *const [*const c_char], run_args: *const [*const c_char], os: Os,
373382
nostdlib: bool, debug: bool, nobuild: bool, run: bool,
374383
// Temporaries
375384
output: *mut String_Builder, cmd: *mut Cmd,
376385
) -> Option<()> {
386+
let mut help = false;
387+
let mut link_args = c!("");
388+
let params = &[
389+
Param {
390+
name: c!("help"),
391+
description: c!("Print this help message"),
392+
value: ParamValue::Flag { var: &mut help },
393+
},
394+
Param {
395+
name: c!("link-args"),
396+
description: c!("Additional linker arguments"),
397+
value: ParamValue::String { var: &mut link_args, default: c!("") },
398+
},
399+
];
400+
401+
if let Err(message) = parse_args(params, codegen_args) {
402+
usage(params);
403+
log(Log_Level::ERROR, c!("%s"), message);
404+
return None;
405+
}
406+
407+
if help {
408+
usage(params);
409+
return Some(());
410+
}
411+
377412
if !nobuild {
378413
match os {
379414
Os::Darwin => sb_appendf(output, c!(".text\n")),
@@ -416,7 +451,12 @@ pub unsafe fn generate_program(
416451
if nostdlib {
417452
cmd_append!(cmd, c!("-nostdlib"));
418453
}
419-
da_append_many(cmd, linker);
454+
let mut s: Shlex = zeroed();
455+
shlex_init(&mut s, link_args, link_args.add(strlen(link_args)));
456+
while !shlex_next(&mut s).is_null() {
457+
da_append(cmd, temp_strdup(s.string));
458+
}
459+
shlex_free(&mut s);
420460
if !cmd_run_sync_and_reset(cmd) { return None; }
421461
}
422462
Os::Linux => {
@@ -440,7 +480,12 @@ pub unsafe fn generate_program(
440480
if nostdlib {
441481
cmd_append!(cmd, c!("-nostdlib"));
442482
}
443-
da_append_many(cmd, linker);
483+
let mut s: Shlex = zeroed();
484+
shlex_init(&mut s, link_args, link_args.add(strlen(link_args)));
485+
while !shlex_next(&mut s).is_null() {
486+
da_append(cmd, temp_strdup(s.string));
487+
}
488+
shlex_free(&mut s);
444489
if !cmd_run_sync_and_reset(cmd) { return None; }
445490
}
446491
Os::Windows => {
@@ -458,7 +503,12 @@ pub unsafe fn generate_program(
458503
if nostdlib {
459504
cmd_append!(cmd, c!("-nostdlib"));
460505
}
461-
da_append_many(cmd, linker);
506+
let mut s: Shlex = zeroed();
507+
shlex_init(&mut s, link_args, link_args.add(strlen(link_args)));
508+
while !shlex_next(&mut s).is_null() {
509+
da_append(cmd, temp_strdup(s.string));
510+
}
511+
shlex_free(&mut s);
462512
if !cmd_run_sync_and_reset(cmd) { return None; }
463513
}
464514
}
@@ -514,4 +564,4 @@ pub unsafe fn generate_program(
514564
}
515565

516566
Some(())
517-
}
567+
}

0 commit comments

Comments
 (0)