--- Linking helper --- This is the canonical "link with stdlib" path used by the GUI and tests: 1. Compile stdlib once -> Vec token stream 2. Compile user source independently -> Vec token stream 3. Assemble stdlib + user into relocatable objects 4. Link the objects and inject the kernel layout symbols 5. Load the resulting ELF into VM and run To link with a differen
(user_src: &str)
| 81 | let stdlib_objs = |
| 82 | CompilationPipeline::compile_stdlib_objects(TargetMode::Hosted).expect("stdlib compile"); |
| 83 | let user_result = pipeline.compile(user_src).expect("user compile"); |
| 84 | let (_, user_tokens) = pipeline |
| 85 | .compile_ir_to_assembly_with_tokens(&user_result.ir_program) |
| 86 | .expect("valid IR layout"); |
| 87 | let user_obj = pipeline.assemble(&user_tokens).expect("user assemble"); |
| 88 | let mut modules: Vec<(&str, &AssembledOutput)> = |
| 89 | stdlib_objs.iter().map(|(n, o)| (n.as_str(), o)).collect(); |
| 90 | modules.push(("user", &user_obj)); |
| 91 | let assembled = pipeline.link_assembled_objects(&modules).expect("link"); |
| 92 | let elf = assembled.to_elf(ELF_LOAD_BASE); |
| 93 | let mut vm = VirtualMachine::from_elf(&elf).expect("load elf"); |
| 94 | let run = vm.run(5_000_000); |
| 95 | |
| 96 | let exit = match run.outcome { |
| 97 | StepOutcome::Halted(code) => Some(code), |
| 98 | _ => None, |
| 99 | }; |
| 100 | (run.uart_output, exit) |
| 101 | } |
| 102 | |
| 103 | // Verify the stdlib compiles and that its token stream defines malloc, which |
| 104 | // is required by any user code that calls new(T) or free(ptr). |
| 105 | #[test] |
| 106 | fn stdlib_provides_malloc() { |
| 107 | let mut pipeline = CompilationPipeline::new(); |
| 108 | pipeline.set_write_artifacts(false); |
| 109 | |
| 110 | // Compile each stdlib module independently; malloc lives in the allocator module. |
no test coverage detected