Skip to main content

gaia_assembler/backends/dotnet/
mod.rs

1//! .NET backend compiler
2//! This backend generates .NET PE files containing IL code
3
4use crate::{
5    backends::{Backend, GeneratedFiles},
6    config::GaiaConfig,
7    program::GaiaModule,
8};
9#[allow(unused_imports)]
10use gaia_types::{
11    helpers::{AbiCompatible, ApiCompatible, Architecture, ArtifactType, CompilationTarget},
12    *,
13};
14#[cfg(feature = "clr-assembler")]
15use msil::ClrBackend;
16#[cfg(feature = "pe-assembler")]
17use pe_assembler::*;
18#[cfg(feature = "pe-assembler")]
19use std::collections::HashMap;
20
21#[cfg(feature = "clr-assembler")]
22pub mod msil;
23
24/// .NET Backend implementation
25#[derive(Default)]
26pub struct DotNetBackend {}
27
28impl Backend for DotNetBackend {
29    fn name(&self) -> &'static str {
30        ".NET (CLR)"
31    }
32
33    fn primary_target(&self) -> CompilationTarget {
34        CompilationTarget { build: Architecture::CLR, host: AbiCompatible::PE, target: ApiCompatible::ClrRuntime(4) }
35    }
36
37    fn artifact_type(&self) -> ArtifactType {
38        ArtifactType::Executable
39    }
40
41    fn match_score(&self, target: &CompilationTarget) -> f32 {
42        match target.build {
43            Architecture::CLR => 100.0,
44            _ => {
45                if target.host == AbiCompatible::PE {
46                    5.0 // Can generate PE, but not native
47                }
48                else {
49                    0.0
50                }
51            }
52        }
53    }
54
55    fn generate(&self, _program: &GaiaModule, config: &GaiaConfig) -> Result<GeneratedFiles> {
56        #[cfg(all(feature = "pe-assembler", feature = "clr-assembler"))]
57        {
58            let mut files = HashMap::new();
59            // If main function exists, output executable; otherwise output DLL
60            let has_main = _program.functions.iter().any(|f| f.name == "main");
61            let filename = if has_main { "main.exe" } else { "main.dll" };
62            // Use CLR backend to generate IL with unified settings, then package as PE
63            let il_code = ClrBackend::generate_with_settings(_program, &config.setting)?;
64            files.insert(filename.to_string(), self.generate_dotnet_pe_file(&il_code, &_program.name)?);
65            Ok(GeneratedFiles { artifact_type: ArtifactType::Executable, files, custom: None, diagnostics: vec![] })
66        }
67        #[cfg(all(feature = "pe-assembler", not(feature = "clr-assembler")))]
68        {
69            Err(GaiaError::platform_unsupported("DotNet", "CLR assembler required for .NET output"))
70        }
71        #[cfg(not(feature = "pe-assembler"))]
72        {
73            Err(GaiaError::platform_unsupported("DotNet", "PE assembler required"))
74        }
75    }
76}
77
78impl DotNetBackend {
79    /// Generate a .NET PE file containing the IL code
80    #[cfg(feature = "clr-assembler")]
81    fn generate_dotnet_pe_file(&self, il_code: &[u8], _program_name: &str) -> Result<Vec<u8>> {
82        // The IL code already contains the complete DLL file content
83        // generated by ClrBackend::generate_with_settings
84        Ok(il_code.to_vec())
85    }
86}