1use cranelift_object::{ObjectBuilder, ObjectModule};
4use nifty_check::hir::Program;
5use nifty_rt::SourceLocation;
6use nifty_syntax::Span;
7
8use crate::CodegenError;
9use crate::compile::compile;
10use crate::emit::{Emitter, host_isa};
11
12pub fn compile_app(
18 name: &str,
19 program: &Program,
20 locate: &dyn Fn(Span) -> SourceLocation,
21) -> Result<Vec<u8>, CodegenError> {
22 let mut emitter = object_emitter(name)?;
23 let descriptor = compile(&mut emitter, program, locate)?;
24 emitter.define_main(descriptor)?;
25 finish(emitter)
26}
27
28pub fn object_emitter(name: &str) -> Result<Emitter<ObjectModule>, CodegenError> {
33 let builder = ObjectBuilder::new(
34 host_isa(true)?,
35 name,
36 cranelift_module::default_libcall_names(),
37 )?;
38 Ok(Emitter::new(ObjectModule::new(builder)))
39}
40
41pub fn finish(emitter: Emitter<ObjectModule>) -> Result<Vec<u8>, CodegenError> {
46 let product = emitter.into_module().finish();
47 #[cfg(target_os = "macos")]
48 let product = {
49 let mut product = product;
50 product
51 .object
52 .set_macho_build_version(macos_build_version());
53 product
54 };
55 product
56 .emit()
57 .map_err(|error| CodegenError::new(error.to_string()))
58}
59
60#[cfg(target_os = "macos")]
63const MINIMUM_MACOS: (u32, u32) = (11, 0);
64
65#[cfg(target_os = "macos")]
67fn macos_build_version() -> object::write::MachOBuildVersion {
68 let (major, minor) = MINIMUM_MACOS;
69 let mut version = object::write::MachOBuildVersion::default();
70 version.platform = object::macho::PLATFORM_MACOS;
71 version.minos = (major << 16) | (minor << 8);
73 version
74}