gaia-assembler 0.1.1

Universal assembler framework for Gaia project
Documentation
//! .NET backend compiler
//! This backend generates .NET PE files containing IL code

use crate::{
    backends::{Backend, GeneratedFiles},
    config::GaiaConfig,
    program::GaiaModule,
};
#[allow(unused_imports)]
use gaia_types::{
    helpers::{AbiCompatible, ApiCompatible, Architecture, ArtifactType, CompilationTarget},
    *,
};
#[cfg(feature = "clr-assembler")]
use msil::ClrBackend;
#[cfg(feature = "pe-assembler")]
use pe_assembler::*;
#[cfg(feature = "pe-assembler")]
use std::collections::HashMap;

#[cfg(feature = "clr-assembler")]
pub mod msil;

/// .NET Backend implementation
#[derive(Default)]
pub struct DotNetBackend {}

impl Backend for DotNetBackend {
    fn name(&self) -> &'static str {
        ".NET (CLR)"
    }

    fn primary_target(&self) -> CompilationTarget {
        CompilationTarget { build: Architecture::CLR, host: AbiCompatible::PE, target: ApiCompatible::ClrRuntime(4) }
    }

    fn artifact_type(&self) -> ArtifactType {
        ArtifactType::Executable
    }

    fn match_score(&self, target: &CompilationTarget) -> f32 {
        match target.build {
            Architecture::CLR => 100.0,
            _ => {
                if target.host == AbiCompatible::PE {
                    5.0 // Can generate PE, but not native
                }
                else {
                    0.0
                }
            }
        }
    }

    fn generate(&self, _program: &GaiaModule, config: &GaiaConfig) -> Result<GeneratedFiles> {
        #[cfg(all(feature = "pe-assembler", feature = "clr-assembler"))]
        {
            let mut files = HashMap::new();
            // If main function exists, output executable; otherwise output DLL
            let has_main = _program.functions.iter().any(|f| f.name == "main");
            let filename = if has_main { "main.exe" } else { "main.dll" };
            // Use CLR backend to generate IL with unified settings, then package as PE
            let il_code = ClrBackend::generate_with_settings(_program, &config.setting)?;
            files.insert(filename.to_string(), self.generate_dotnet_pe_file(&il_code, &_program.name)?);
            Ok(GeneratedFiles { artifact_type: ArtifactType::Executable, files, custom: None, diagnostics: vec![] })
        }
        #[cfg(all(feature = "pe-assembler", not(feature = "clr-assembler")))]
        {
            Err(GaiaError::platform_unsupported("DotNet", "CLR assembler required for .NET output"))
        }
        #[cfg(not(feature = "pe-assembler"))]
        {
            Err(GaiaError::platform_unsupported("DotNet", "PE assembler required"))
        }
    }
}

impl DotNetBackend {
    /// Generate a .NET PE file containing the IL code
    #[cfg(feature = "clr-assembler")]
    fn generate_dotnet_pe_file(&self, il_code: &[u8], _program_name: &str) -> Result<Vec<u8>> {
        // The IL code already contains the complete DLL file content
        // generated by ClrBackend::generate_with_settings
        Ok(il_code.to_vec())
    }
}