gaia_assembler/backends/pe/
mod.rs1use super::{Backend, GeneratedFiles};
5#[cfg(feature = "clr")]
6use crate::backends::msil::ClrBackend;
7use crate::{config::GaiaConfig, program::GaiaModule};
8#[allow(unused_imports)]
9use gaia_types::{
10 helpers::{AbiCompatible, ApiCompatible, Architecture, CompilationTarget},
11 *,
12};
13#[cfg(feature = "clr")]
14use std::collections::HashMap;
15
16#[derive(Default)]
18pub struct PeBackend {}
19
20impl Backend for PeBackend {
21 fn name(&self) -> &'static str {
22 "Windows PE Assembly"
23 }
24
25 fn primary_target(&self) -> CompilationTarget {
26 CompilationTarget { build: Architecture::CLR, host: AbiCompatible::PE, target: ApiCompatible::ClrRuntime(4) }
27 }
28
29 fn match_score(&self, target: &CompilationTarget) -> f32 {
30 match target.host {
31 AbiCompatible::PE => match target.build {
32 Architecture::CLR => 80.0,
33 Architecture::X86 | Architecture::X86_64 => 5.0,
35 _ => -100.0,
36 },
37 _ => -100.0,
38 }
39 }
40
41 fn generate(&self, _program: &GaiaModule, _config: &GaiaConfig) -> Result<GeneratedFiles> {
42 #[cfg(feature = "clr")]
43 {
44 let mut files = HashMap::new();
45 let has_main = _program.functions.iter().any(|f| f.name == "main");
47 let filename = if has_main { "main.exe" } else { "main.dll" };
48 let il_code = ClrBackend::generate_with_settings(_program, &_config.setting)?;
50 files.insert(filename.to_string(), generate_dotnet_pe_file(&il_code, &_program.name)?);
51 Ok(GeneratedFiles { files, diagnostics: vec![] })
52 }
53 #[cfg(not(feature = "clr"))]
54 {
55 Err(GaiaError::platform_unsupported("PE", "CLR backend required"))
56 }
57 }
58}
59
60#[cfg(feature = "clr")]
62pub fn compile(program: &GaiaModule) -> Result<Vec<u8>> {
63 let il_code = ClrBackend::generate(program)?;
65 generate_dotnet_pe_file(&il_code, &program.name)
66}
67
68#[cfg(feature = "clr")]
70fn generate_dotnet_pe_file(il_code: &[u8], program_name: &str) -> Result<Vec<u8>> {
71 let il_text = String::from_utf8_lossy(il_code);
76
77 let pe_content = create_minimal_dotnet_pe(&il_text, program_name)?;
80
81 Ok(pe_content)
82}
83
84#[cfg(feature = "clr")]
86fn create_minimal_dotnet_pe(il_code: &str, program_name: &str) -> Result<Vec<u8>> {
87 let mut pe_data = Vec::new();
95
96 pe_data.extend_from_slice(b"MZ");
98 pe_data.resize(0x80, 0);
99
100 pe_data.extend_from_slice(b"PE\0\0");
102
103 pe_data.extend_from_slice(&[
105 0x4C, 0x01, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0x00, 0x02, 0x01, ]);
113
114 pe_data.extend_from_slice(&[
116 0x0B, 0x01, 0x0E, 0x00, ]);
119
120 let il_comment = format!("// IL Code for {}\n{}", program_name, il_code);
126 pe_data.extend_from_slice(il_comment.as_bytes());
127
128 pe_data.resize(1024, 0);
130
131 Ok(pe_data)
132}