Skip to content

Commit 822a09d

Browse files
committed
Move most of codegen into basm-std
1 parent 0893c5e commit 822a09d

18 files changed

+116
-101
lines changed

basm-std/Cargo.toml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,4 +25,8 @@ compiler_builtins = { version = "0.1.103", features = ["mem"] }
2525
compiler_builtins = { version = "0.1.103", features = ["mem"] }
2626

2727
[features]
28+
# Enables codegen routines.
29+
# When this feature is enabled, the external implementations should provide an `extern "C" fn _basm_main()`.
30+
codegen = []
31+
# Favors short routines for code golf.
2832
short = []

basm/src/bin/codegen.rs renamed to basm-std/src/platform/codegen.rs

Lines changed: 17 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,9 @@
1-
#![cfg(not(test))]
2-
31
#[cfg(not(target_arch = "wasm32"))]
42
use core::arch::asm;
53

6-
use crate::solution;
7-
use basm::platform;
8-
use basm::platform::allocator;
4+
use crate::platform;
95
#[cfg(not(target_arch = "wasm32"))]
10-
use basm::platform::loader;
11-
12-
#[global_allocator]
13-
static ALLOC: allocator::Allocator = allocator::Allocator;
6+
use crate::platform::loader;
147

158
/* We need to support multiple scenarios.
169
* 1) Architectures: x86, x86-64
@@ -28,9 +21,9 @@ static ALLOC: allocator::Allocator = allocator::Allocator;
2821
* For 4), we build the binary to run without the loader.
2922
* When running without the loader, the binary will fabricate a dummy
3023
* SERVICE_FUNCTIONS and PLATFORM_DATA table at the beginning of the
31-
* EntryPoint (_start).
24+
* EntryPoint (_basm_start).
3225
* When running with the loader, the loader patches the beginning of
33-
* the EntryPoint (_start) to override the platform configuration data.
26+
* the EntryPoint (_basm_start) to override the platform configuration data.
3427
*
3528
* When running without the loader, the relocations are handled differently.
3629
* For Windows, the Windows kernel will handle relocations for us,
@@ -54,7 +47,7 @@ compile_error!("The target architecture is not supported.");
5447
#[cfg(all(target_arch = "x86_64", not(target_os = "windows")))]
5548
#[no_mangle]
5649
#[naked]
57-
unsafe extern "win64" fn _start() -> ! {
50+
pub unsafe extern "win64" fn _basm_start() -> ! {
5851
// AMD64 System V ABI requires RSP to be aligned
5952
// on the 16-byte boundary BEFORE `call` instruction.
6053
// However, when called as the entrypoint by the Linux OS,
@@ -103,7 +96,7 @@ unsafe extern "sysv64" fn get_kernel32() -> usize {
10396
#[cfg(all(target_arch = "x86_64", target_os = "windows"))]
10497
#[no_mangle]
10598
#[naked]
106-
unsafe extern "win64" fn _start() -> ! {
99+
pub unsafe extern "win64" fn _basm_start() -> ! {
107100
// Microsoft x64 ABI requires RSP to be aligned
108101
// on the 16-byte boundary BEFORE `call` instruction.
109102
// Also, when called as the entrypoint by the Windows OS,
@@ -162,7 +155,7 @@ unsafe extern "win64" fn _start() -> ! {
162155
#[link_section = ".data"]
163156
unsafe extern "cdecl" fn _get_start_offset() -> ! {
164157
asm!(
165-
"lea eax, [_start]",
158+
"lea eax, [_basm_start]",
166159
"ret",
167160
options(noreturn)
168161
);
@@ -183,7 +176,7 @@ unsafe extern "cdecl" fn _get_dynamic_section_offset() -> ! {
183176
#[cfg(target_arch = "x86")]
184177
#[no_mangle]
185178
#[naked]
186-
unsafe extern "cdecl" fn _start() -> ! {
179+
pub unsafe extern "cdecl" fn _basm_start() -> ! {
187180
// i386 System V ABI requires ESP to be aligned
188181
// on the 16-byte boundary BEFORE `call` instruction
189182
asm!(
@@ -205,9 +198,9 @@ unsafe extern "cdecl" fn _start() -> ! {
205198
"2:",
206199
"call 3f",
207200
"3:",
208-
"pop ecx", // ecx = _start + 36 (obtained by counting the opcode size in bytes)
201+
"pop ecx", // ecx = _basm_start + 36 (obtained by counting the opcode size in bytes)
209202
"push edx", // [esp + 0] = PLATFORM_DATA table
210-
"call {2}", // eax = offset of _start from the image base
203+
"call {2}", // eax = offset of _basm_start from the image base
211204
"sub ecx, eax",
212205
"sub ecx, 36", // ecx = the in-memory image base (i.e., __ehdr_start)
213206
"call {3}", // eax = offset of _DYNAMIC table from the image base
@@ -231,7 +224,7 @@ unsafe extern "cdecl" fn _start() -> ! {
231224

232225
#[cfg(target_arch = "wasm32")]
233226
#[no_mangle]
234-
extern "C" fn _start() {
227+
pub extern "C" fn _basm_start() {
235228
let mut pd = platform::services::PlatformData {
236229
env_id: platform::services::ENV_ID_WASM,
237230
.. Default::default()
@@ -246,7 +239,10 @@ extern "C" fn _start() {
246239
*/
247240
#[cfg_attr(not(feature = "short"), inline(never))]
248241
fn _call_main() {
249-
solution::main();
242+
extern "C" {
243+
fn _basm_main();
244+
}
245+
unsafe { _basm_main() }
250246
}
251247
fn _start_rust(platform_data: usize) -> i32 {
252248
platform::init(platform_data);
@@ -259,7 +255,7 @@ fn _start_rust(platform_data: usize) -> i32 {
259255
#[naked]
260256
#[repr(align(4))]
261257
#[cfg(all(target_arch = "x86_64", target_os = "windows"))]
262-
unsafe extern "win64" fn __chkstk() -> ! {
258+
pub unsafe extern "win64" fn __chkstk() -> ! {
263259
asm!(
264260
"push rcx",
265261
"push rax",
@@ -280,30 +276,4 @@ unsafe extern "win64" fn __chkstk() -> ! {
280276
"ret",
281277
options(noreturn)
282278
);
283-
}
284-
285-
#[no_mangle]
286-
#[cfg(target_os = "windows")]
287-
static mut _fltused: i32 = 0;
288-
289-
#[no_mangle]
290-
#[cfg(target_os = "windows")]
291-
extern "win64" fn __CxxFrameHandler3() -> ! {
292-
unsafe { core::hint::unreachable_unchecked() }
293-
}
294-
295-
#[alloc_error_handler]
296-
fn alloc_fail(_: core::alloc::Layout) -> ! {
297-
unsafe { core::hint::unreachable_unchecked() }
298-
}
299-
300-
#[no_mangle]
301-
#[allow(non_snake_case)]
302-
pub fn _Unwind_Resume() {
303-
unsafe { core::hint::unreachable_unchecked() }
304-
}
305-
306-
#[no_mangle]
307-
pub fn rust_eh_personality() {
308-
unsafe { core::hint::unreachable_unchecked() }
309-
}
279+
}

basm-std/src/platform/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
#[cfg(all(not(test), feature = "codegen"))]
2+
pub mod codegen;
13
#[cfg(not(test))]
24
pub mod loader;
35
#[cfg(not(test))]

basm/Cargo.toml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,12 +21,13 @@ name = "basm-submit"
2121
test = false
2222
bench = false
2323
path = "src/bin/basm-submit.rs"
24+
required-features = ["submit"]
2425

2526
[dependencies]
2627
libm = "0.2.7"
2728
ryu = "1.0"
28-
basm-std = { path = "../basm-std" }
2929
basm-macro = { path = "../basm-macro" }
30+
basm-std = { path = "../basm-std", features = ["codegen"] }
3031

3132
[target.x86_64-pc-windows-msvc.dependencies]
3233
compiler_builtins = { version = "0.1.103", features = ["mem"] }
@@ -39,3 +40,4 @@ compiler_builtins = { version = "0.1.103", features = ["mem"] }
3940

4041
[features]
4142
short = []
43+
submit = []

basm/build.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ fn main() {
1111
link_args_basm.push("/SUBSYSTEM:CONSOLE");
1212
link_args_basm.push("/NODEFAULTLIB");
1313
link_args_basm.push("/DYNAMICBASE");
14-
link_args_basm.push("/ENTRY:_start");
14+
link_args_basm.push("/ENTRY:_basm_start");
1515
link_args_basm.push("/NXCOMPAT:NO");
1616
link_args_basm.push("/STACK:268435456");
1717
link_args_basm.push("/EMITTOOLVERSIONINFO:NO");
@@ -30,9 +30,9 @@ fn main() {
3030
if target == "i686-unknown-linux-gnu" {
3131
// Prevent linker from putting data into text, which is non-writable and hence not relocatable.
3232
// This prevents the hack for getting the _DYNAMIC symbol in the entrypoint.
33-
link_args_basm.push("-Wl,--build-id=none,--gc-sections,--export-dynamic,--no-eh-frame-hdr,-z,norelro,-z,notext");
33+
link_args_basm.push("-Wl,--entry=_basm_start,--build-id=none,--gc-sections,--export-dynamic,--no-eh-frame-hdr,-z,norelro,-z,notext");
3434
} else {
35-
link_args_basm.push("-Wl,--build-id=none,--gc-sections,--export-dynamic,--no-eh-frame-hdr,-z,norelro");
35+
link_args_basm.push("-Wl,--entry=_basm_start,--build-id=none,--gc-sections,--export-dynamic,--no-eh-frame-hdr,-z,norelro");
3636
}
3737
link_args_basm_submit.push("-Wl,-z,max-page-size=128");
3838
},

basm/src/bin/basm-lib.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,12 @@
77
#![cfg_attr(not(test), no_builtins)]
88
#![cfg_attr(not(test), no_std)]
99
#![cfg_attr(not(test), no_main)]
10-
extern crate alloc;
1110

11+
extern crate alloc;
1212
extern crate basm_std as basm;
13+
mod lang_items;
1314

14-
#[allow(dead_code)]
15+
#[cfg_attr(test, allow(dead_code))]
1516
#[path = "../solution.rs"]
1617
mod solution;
1718

basm/src/bin/basm-submit.rs

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -7,17 +7,11 @@
77
#![cfg_attr(not(test), no_builtins)]
88
#![cfg_attr(not(test), no_std)]
99
#![cfg_attr(not(test), no_main)]
10-
extern crate alloc;
1110

11+
extern crate alloc;
1212
extern crate basm_std as basm;
13+
mod lang_items;
1314

1415
#[cfg_attr(test, allow(dead_code))]
1516
#[path = "../solution.rs"]
16-
mod solution;
17-
mod codegen;
18-
19-
#[cfg(not(test))]
20-
#[panic_handler]
21-
fn panic(_pi: &core::panic::PanicInfo) -> ! {
22-
unsafe { core::hint::unreachable_unchecked() }
23-
}
17+
mod solution;

basm/src/bin/basm.rs

Lines changed: 3 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -7,36 +7,11 @@
77
#![cfg_attr(not(test), no_builtins)]
88
#![cfg_attr(not(test), no_std)]
99
#![cfg_attr(not(test), no_main)]
10-
extern crate alloc;
1110

11+
extern crate alloc;
1212
extern crate basm_std as basm;
13+
mod lang_items;
1314

1415
#[cfg_attr(test, allow(dead_code))]
1516
#[path = "../solution.rs"]
16-
mod solution;
17-
mod codegen;
18-
19-
#[cfg(not(test))]
20-
#[panic_handler]
21-
fn panic(_pi: &core::panic::PanicInfo) -> ! {
22-
use alloc::string::ToString;
23-
use basm::platform::services::write_stdio;
24-
write_stdio(2, _pi.to_string().as_bytes());
25-
write_stdio(2, b"\n");
26-
27-
// Rust sets an exit code of 101 when the process panicked.
28-
// Hence, we follow that practice for maximum compatibility.
29-
// Reference: https://rust-cli.github.io/book/in-depth/exit-code.html
30-
#[cfg(all(windows, target_arch = "x86_64"))]
31-
{
32-
extern "win64" {
33-
fn ExitProcess(uExitCode: u32) -> !;
34-
}
35-
unsafe { ExitProcess(101); }
36-
}
37-
#[cfg(target_os = "linux")] {
38-
unsafe { basm::platform::os::linux::syscall::exit_group(101); }
39-
}
40-
#[cfg(not(any(all(windows, target_arch = "x86_64"), target_os = "linux")))]
41-
unsafe { core::hint::unreachable_unchecked() }
42-
}
17+
mod solution;

basm/src/bin/lang_items.rs

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
#[no_mangle]
2+
extern "C" fn _basm_main() {
3+
crate::solution::main()
4+
}
5+
6+
#[cfg(not(test))]
7+
mod runtime {
8+
#[global_allocator]
9+
static ALLOC: basm::platform::allocator::Allocator = basm::platform::allocator::Allocator;
10+
11+
#[no_mangle]
12+
#[cfg(target_os = "windows")]
13+
static mut _fltused: i32 = 0;
14+
15+
#[no_mangle]
16+
#[cfg(target_os = "windows")]
17+
extern "win64" fn __CxxFrameHandler3() -> ! {
18+
unsafe { core::hint::unreachable_unchecked() }
19+
}
20+
21+
#[alloc_error_handler]
22+
fn alloc_fail(_: core::alloc::Layout) -> ! {
23+
unsafe { core::hint::unreachable_unchecked() }
24+
}
25+
26+
#[no_mangle]
27+
#[allow(non_snake_case)]
28+
fn _Unwind_Resume() {
29+
unsafe { core::hint::unreachable_unchecked() }
30+
}
31+
32+
#[no_mangle]
33+
fn rust_eh_personality() {
34+
unsafe { core::hint::unreachable_unchecked() }
35+
}
36+
37+
#[cfg(all(not(test), feature = "submit"))]
38+
#[panic_handler]
39+
fn panic(_pi: &core::panic::PanicInfo) -> ! {
40+
unsafe { core::hint::unreachable_unchecked() }
41+
}
42+
43+
#[cfg(all(not(test), not(feature = "submit")))]
44+
#[panic_handler]
45+
fn panic(_pi: &core::panic::PanicInfo) -> ! {
46+
use alloc::string::ToString;
47+
use basm::platform::services::write_stdio;
48+
write_stdio(2, _pi.to_string().as_bytes());
49+
write_stdio(2, b"\n");
50+
51+
// Rust sets an exit code of 101 when the process panicked.
52+
// Hence, we follow that practice for maximum compatibility.
53+
// Reference: https://rust-cli.github.io/book/in-depth/exit-code.html
54+
#[cfg(all(windows, target_arch = "x86_64"))]
55+
{
56+
extern "win64" {
57+
fn ExitProcess(uExitCode: u32) -> !;
58+
}
59+
unsafe { ExitProcess(101); }
60+
}
61+
#[cfg(target_os = "linux")] {
62+
unsafe { basm::platform::os::linux::syscall::exit_group(101); }
63+
}
64+
#[cfg(not(any(all(windows, target_arch = "x86_64"), target_os = "linux")))]
65+
unsafe { core::hint::unreachable_unchecked() }
66+
}
67+
}

release-64bit-windows-fn-impl.cmd

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
@echo off
2-
cargo +nightly build --target x86_64-pc-windows-msvc --bin basm-submit --release || goto :error
2+
cargo +nightly build --target x86_64-pc-windows-msvc --bin basm-submit --features=submit --release || goto :error
33
python scripts/static-pie-gen.py basm/src/solution.rs x86_64-pc-windows-msvc target/x86_64-pc-windows-msvc/release/basm-submit.exe static-pie-stub-amd64.bin C static-pie-template-amd64-fn-impl.c || goto :error
44

55
:; exit 0

0 commit comments

Comments
 (0)