gaia_assembler/backends/msil/
mod.rs

1//! IL (Intermediate Language) backend compiler
2
3use crate::{
4    adapters::FunctionMapper,
5    config::GaiaConfig,
6    instruction::GaiaInstruction,
7    program::{GaiaConstant, GaiaFunction, GaiaProgram},
8    types::GaiaType,
9    Backend, GeneratedFiles,
10};
11use clr_assembler::formats::msil::writer::MsilWriter;
12use gaia_types::{
13    helpers::{AbiCompatible, ApiCompatible, Architecture, CompilationTarget},
14    GaiaError, Result,
15};
16use std::collections::HashMap;
17
18/// IL Backend implementation
19#[derive(Default)]
20pub struct ClrBackend {}
21
22impl Backend for ClrBackend {
23    fn name(&self) -> &'static str {
24        "MSIL"
25    }
26
27    fn primary_target(&self) -> CompilationTarget {
28        CompilationTarget {
29            build: Architecture::CLR,
30            host: AbiCompatible::MicrosoftIntermediateLanguage,
31            target: ApiCompatible::ClrRuntime(4),
32        }
33    }
34
35    fn match_score(&self, target: &CompilationTarget) -> f32 {
36        match target.build {
37            Architecture::CLR => match target.host {
38                // dll, exe output, 5% support
39                AbiCompatible::Unknown => 5.0,
40                // msil output, 30% support
41                AbiCompatible::MicrosoftIntermediateLanguage => 30.0,
42                _ => -100.0,
43            },
44            _ => -100.0,
45        }
46    }
47
48    fn generate(&self, program: &GaiaProgram, _config: &GaiaConfig) -> Result<GeneratedFiles> {
49        let mut files = HashMap::new();
50        match _config.target.host {
51            AbiCompatible::Unknown => {
52                files.insert("main.dll".to_string(), compile(program)?);
53            }
54            AbiCompatible::MicrosoftIntermediateLanguage => {
55                files.insert("main.il".to_string(), compile(program)?);
56            }
57            _ => Err(GaiaError::invalid_data("Unsupported host ABI for CLR backend"))?,
58        }
59
60        Ok(GeneratedFiles { files, diagnostics: vec![] })
61    }
62}
63
64impl ClrBackend {
65    /// Generate IL bytecode from Gaia program
66    pub fn generate(program: &GaiaProgram) -> Result<Vec<u8>> {
67        let mut context = create_il_context()?;
68        compile_program(&mut context, program)?;
69        generate_il_bytecode(context)
70    }
71}
72
73/// Compile Gaia program to IL bytecode
74pub fn compile(program: &GaiaProgram) -> Result<Vec<u8>> {
75    ClrBackend::generate(program)
76}
77
78/// Create IL assembler context
79fn create_il_context() -> Result<IlContext> {
80    Ok(IlContext::new())
81}
82
83/// Compile entire program
84fn compile_program(context: &mut IlContext, program: &GaiaProgram) -> Result<()> {
85    // 添加程序集声明
86    context.emit_assembly_declaration(&program.name)?;
87
88    // Compile all functions
89    for function in &program.functions {
90        compile_function(context, function)?;
91    }
92
93    Ok(())
94}
95
96/// Compile single function
97fn compile_function(context: &mut IlContext, function: &GaiaFunction) -> Result<()> {
98    // 为 main 函数进行特殊处理:如果有返回指令且没有显式返回类型,推断为 int32
99    let inferred_return_type = if function.name == "main" && function.return_type.is_none() {
100        // 检查是否有返回指令
101        let has_return = function.instructions.iter().any(|inst| matches!(inst, GaiaInstruction::Return));
102        if has_return {
103            Some(GaiaType::Integer32)
104        }
105        else {
106            function.return_type.clone()
107        }
108    }
109    else {
110        function.return_type.clone()
111    };
112
113    // Start function definition
114    start_function(context, &function.name, &function.parameters, &inferred_return_type)?;
115
116    // Compile instructions
117    for instruction in &function.instructions {
118        compile_instruction(context, instruction)?;
119    }
120
121    // End function definition
122    end_function(context)?;
123
124    Ok(())
125}
126
127/// Compile single instruction
128fn compile_instruction(context: &mut IlContext, instruction: &GaiaInstruction) -> Result<()> {
129    match instruction {
130        GaiaInstruction::LoadConstant(constant) => compile_load_constant(context, constant),
131        GaiaInstruction::LoadLocal(index) => compile_load_local(context, (*index).try_into().unwrap()),
132        GaiaInstruction::StoreLocal(index) => compile_store_local(context, (*index).try_into().unwrap()),
133        GaiaInstruction::LoadArgument(index) => compile_load_argument(context, (*index).try_into().unwrap()),
134        // 当前枚举无独立 LoadArgument;参数按局部变量处理(如有需要在前置阶段映射)
135        GaiaInstruction::Add => compile_add(context),
136        GaiaInstruction::Subtract => compile_subtract(context),
137        GaiaInstruction::Multiply => compile_multiply(context),
138        GaiaInstruction::Divide => compile_divide(context),
139        GaiaInstruction::Equal => compile_equal(context),
140        GaiaInstruction::NotEqual => compile_not_equal(context),
141        GaiaInstruction::LessThan => compile_less_than(context),
142        GaiaInstruction::GreaterThan => compile_greater_than(context),
143        GaiaInstruction::Jump(label) => compile_branch(context, label),
144        GaiaInstruction::JumpIfTrue(label) => compile_branch_if_true(context, label),
145        GaiaInstruction::JumpIfFalse(label) => compile_branch_if_false(context, label),
146        GaiaInstruction::Call(function_name, _arg_count) => compile_call(context, function_name),
147        GaiaInstruction::Return => compile_return(context),
148        GaiaInstruction::Label(name) => compile_label(context, name),
149        GaiaInstruction::Duplicate => compile_duplicate(context),
150        GaiaInstruction::Pop => compile_pop(context),
151        // 已移除的指令:LoadAddress(如需地址应由前端生成 LoadIndirect 所需的指针)
152        GaiaInstruction::LoadIndirect(gaia_type) => compile_load_indirect(context, gaia_type),
153        GaiaInstruction::StoreIndirect(gaia_type) => compile_store_indirect(context, gaia_type),
154        GaiaInstruction::Convert(from_type, to_type) => compile_convert(context, from_type, to_type),
155        GaiaInstruction::Box(gaia_type) => compile_box(context, gaia_type),
156        GaiaInstruction::Unbox(gaia_type) => compile_unbox(context, gaia_type),
157        _ => Ok(()), // 忽略其他指令
158    }
159}
160
161fn compile_load_constant(context: &mut IlContext, constant: &GaiaConstant) -> Result<()> {
162    match constant {
163        GaiaConstant::Integer8(value) => context.emit_ldc_i4(*value as i32),
164        GaiaConstant::Integer16(value) => context.emit_ldc_i4(*value as i32),
165        GaiaConstant::Integer32(value) => context.emit_ldc_i4(*value),
166        GaiaConstant::Integer64(value) => context.emit_ldc_i8(*value),
167        GaiaConstant::Float32(value) => context.emit_ldc_r4(*value),
168        GaiaConstant::Float64(value) => context.emit_ldc_r8(*value),
169        GaiaConstant::String(value) => context.emit_ldstr(value),
170        GaiaConstant::Boolean(value) => context.emit_ldc_i4(if *value { 1 } else { 0 }),
171        GaiaConstant::Null => context.emit_ldnull(),
172    }
173}
174
175fn compile_load_local(context: &mut IlContext, index: u32) -> Result<()> {
176    context.emit_ldloc(index)
177}
178
179fn compile_store_local(context: &mut IlContext, index: u32) -> Result<()> {
180    context.emit_stloc(index)
181}
182
183fn compile_load_argument(context: &mut IlContext, index: u32) -> Result<()> {
184    context.emit_ldarg(index)
185}
186
187fn compile_add(context: &mut IlContext) -> Result<()> {
188    context.emit_add()
189}
190
191fn compile_subtract(context: &mut IlContext) -> Result<()> {
192    context.emit_sub()
193}
194
195fn compile_multiply(context: &mut IlContext) -> Result<()> {
196    context.emit_mul()
197}
198
199fn compile_divide(context: &mut IlContext) -> Result<()> {
200    context.emit_div()
201}
202
203fn compile_equal(context: &mut IlContext) -> Result<()> {
204    context.emit_ceq()
205}
206
207fn compile_not_equal(context: &mut IlContext) -> Result<()> {
208    context.emit_ceq()?;
209    context.emit_ldc_i4(0)?;
210    context.emit_ceq()
211}
212
213fn compile_less_than(context: &mut IlContext) -> Result<()> {
214    context.emit_clt()
215}
216
217fn compile_greater_than(context: &mut IlContext) -> Result<()> {
218    context.emit_cgt()
219}
220
221fn compile_branch(context: &mut IlContext, label: &str) -> Result<()> {
222    context.emit_br(label)
223}
224
225fn compile_branch_if_true(context: &mut IlContext, label: &str) -> Result<()> {
226    context.emit_brtrue(label)
227}
228
229fn compile_branch_if_false(context: &mut IlContext, label: &str) -> Result<()> {
230    context.emit_brfalse(label)
231}
232
233fn compile_call(context: &mut IlContext, function_name: &str) -> Result<()> {
234    let mapper = FunctionMapper::new();
235    let il_target = CompilationTarget {
236        build: Architecture::CLR,
237        host: AbiCompatible::MicrosoftIntermediateLanguage,
238        target: ApiCompatible::ClrRuntime(4),
239    };
240    let mapped_name = mapper.map_function(&il_target, function_name);
241    context.emit_call(&mapped_name.unwrap_or(function_name))
242}
243
244fn compile_return(context: &mut IlContext) -> Result<()> {
245    context.emit_ret()
246}
247
248fn compile_label(context: &mut IlContext, name: &str) -> Result<()> {
249    context.define_label(name)
250}
251
252fn compile_duplicate(context: &mut IlContext) -> Result<()> {
253    context.emit_dup()
254}
255
256fn compile_pop(context: &mut IlContext) -> Result<()> {
257    context.emit_pop()
258}
259
260fn compile_load_address(context: &mut IlContext, addr: u32) -> Result<()> {
261    context.emit_ldloca(addr)
262}
263
264fn compile_load_indirect(context: &mut IlContext, gaia_type: &GaiaType) -> Result<()> {
265    match gaia_type {
266        GaiaType::Integer8 => context.emit_ldind_i4(),  // 8位整数加载为32位
267        GaiaType::Integer16 => context.emit_ldind_i4(), // 16位整数加载为32位
268        GaiaType::Integer32 => context.emit_ldind_i4(),
269        GaiaType::Integer64 => context.emit_ldind_i8(),
270        GaiaType::Float32 => context.emit_ldind_r4(),
271        GaiaType::Float64 => context.emit_ldind_r8(),
272        _ => context.emit_ldind_ref(),
273    }
274}
275
276fn compile_store_indirect(context: &mut IlContext, gaia_type: &GaiaType) -> Result<()> {
277    match gaia_type {
278        GaiaType::Integer8 => context.emit_stind_i4(),  // 8位整数存储为32位
279        GaiaType::Integer16 => context.emit_stind_i4(), // 16位整数存储为32位
280        GaiaType::Integer32 => context.emit_stind_i4(),
281        GaiaType::Integer64 => context.emit_stind_i8(),
282        GaiaType::Float32 => context.emit_stind_r4(),
283        GaiaType::Float64 => context.emit_stind_r8(),
284        _ => context.emit_stind_ref(),
285    }
286}
287
288fn compile_convert(_context: &mut IlContext, _from_type: &GaiaType, _to_type: &GaiaType) -> Result<()> {
289    match _to_type {
290        GaiaType::Integer8 => _context.emit_conv_i4(),  // 8位整数转换为32位
291        GaiaType::Integer16 => _context.emit_conv_i4(), // 16位整数转换为32位
292        GaiaType::Integer32 => _context.emit_conv_i4(),
293        GaiaType::Integer64 => _context.emit_conv_i8(),
294        GaiaType::Float32 => _context.emit_conv_r4(),
295        GaiaType::Float64 => _context.emit_conv_r8(),
296        _ => Ok(()),
297    }
298}
299
300fn compile_box(context: &mut IlContext, gaia_type: &GaiaType) -> Result<()> {
301    context.emit_box(gaia_type)
302}
303
304fn compile_unbox(context: &mut IlContext, gaia_type: &GaiaType) -> Result<()> {
305    context.emit_unbox(gaia_type)
306}
307
308/// Start function definition
309fn start_function(context: &mut IlContext, name: &str, parameters: &[GaiaType], return_type: &Option<GaiaType>) -> Result<()> {
310    context.start_method(name, parameters, return_type)
311}
312
313fn end_function(context: &mut IlContext) -> Result<()> {
314    context.end_method()
315}
316
317/// 将 GaiaType 映射为 MSIL 类型名称
318fn gaia_type_to_msil_name(gaia_type: &GaiaType) -> &'static str {
319    match gaia_type {
320        GaiaType::Integer8 => "int8",
321        GaiaType::Integer16 => "int16",
322        GaiaType::Integer32 => "int32",
323        GaiaType::Integer64 => "int64",
324        GaiaType::Float32 => "float32",
325        GaiaType::Float64 => "float64",
326        GaiaType::Boolean => "bool",
327        GaiaType::String => "string",
328        GaiaType::Object => "object",
329        GaiaType::Array(_) => "object",
330        GaiaType::Pointer(_) => "native int",
331        GaiaType::Void => "void",
332        GaiaType::Integer => "int32",
333        GaiaType::Float => "float32",
334        GaiaType::Double => "float64",
335    }
336}
337
338/// Generate IL bytecode
339fn generate_il_bytecode(context: IlContext) -> Result<Vec<u8>> {
340    context.generate_bytecode()
341}
342
343/// IL Context for code generation
344struct IlContext {
345    writer: MsilWriter<String>,
346}
347
348impl IlContext {
349    fn new() -> Self {
350        Self { writer: MsilWriter::new(String::new()) }
351    }
352
353    fn emit_assembly_declaration(&mut self, name: &str) -> Result<()> {
354        self.writer.write_assembly(name)
355    }
356
357    fn start_method(&mut self, name: &str, parameters: &[GaiaType], return_type: &Option<GaiaType>) -> Result<()> {
358        let param_names: Vec<&str> = parameters.iter().map(|t| gaia_type_to_msil_name(t)).collect();
359        let ret_name: Option<&str> = return_type.as_ref().map(|t| gaia_type_to_msil_name(t));
360        self.writer.start_method(name, &param_names, ret_name)
361    }
362
363    fn end_method(&mut self) -> Result<()> {
364        self.writer.end_method()
365    }
366
367    fn generate_bytecode(self) -> Result<Vec<u8>> {
368        Ok(self.writer.finish().into_bytes())
369    }
370
371    fn emit_ldc_i4(&mut self, value: i32) -> Result<()> {
372        self.writer.emit_ldc_i4(value)
373    }
374
375    fn emit_ldc_i8(&mut self, value: i64) -> Result<()> {
376        self.writer.emit_ldc_i8(value)
377    }
378
379    fn emit_ldc_r4(&mut self, value: f32) -> Result<()> {
380        self.writer.emit_ldc_r4(value)
381    }
382
383    fn emit_ldc_r8(&mut self, value: f64) -> Result<()> {
384        self.writer.emit_ldc_r8(value)
385    }
386
387    fn emit_ldstr(&mut self, value: &str) -> Result<()> {
388        self.writer.emit_ldstr(value)
389    }
390
391    fn emit_ldnull(&mut self) -> Result<()> {
392        self.writer.emit_ldnull()
393    }
394
395    fn emit_ldloc(&mut self, index: u32) -> Result<()> {
396        self.writer.emit_ldloc(index)
397    }
398
399    fn emit_stloc(&mut self, index: u32) -> Result<()> {
400        self.writer.emit_stloc(index)
401    }
402
403    fn emit_ldarg(&mut self, index: u32) -> Result<()> {
404        self.writer.emit_ldarg(index)
405    }
406
407    fn emit_add(&mut self) -> Result<()> {
408        self.writer.emit_add()
409    }
410
411    fn emit_sub(&mut self) -> Result<()> {
412        self.writer.emit_sub()
413    }
414
415    fn emit_mul(&mut self) -> Result<()> {
416        self.writer.emit_mul()
417    }
418
419    fn emit_div(&mut self) -> Result<()> {
420        self.writer.emit_div()
421    }
422
423    fn emit_ceq(&mut self) -> Result<()> {
424        self.writer.emit_ceq()
425    }
426
427    fn emit_clt(&mut self) -> Result<()> {
428        self.writer.emit_clt()
429    }
430
431    fn emit_cgt(&mut self) -> Result<()> {
432        self.writer.emit_cgt()
433    }
434
435    fn emit_br(&mut self, label: &str) -> Result<()> {
436        self.writer.emit_br(label)
437    }
438
439    fn emit_brtrue(&mut self, label: &str) -> Result<()> {
440        self.writer.emit_brtrue(label)
441    }
442
443    fn emit_brfalse(&mut self, label: &str) -> Result<()> {
444        self.writer.emit_brfalse(label)
445    }
446
447    fn emit_call(&mut self, function_name: &str) -> Result<()> {
448        self.writer.emit_call(function_name)
449    }
450
451    fn emit_ret(&mut self) -> Result<()> {
452        self.writer.emit_ret()
453    }
454
455    fn define_label(&mut self, name: &str) -> Result<()> {
456        self.writer.define_label(name)
457    }
458
459    fn emit_dup(&mut self) -> Result<()> {
460        self.writer.emit_dup()
461    }
462
463    fn emit_pop(&mut self) -> Result<()> {
464        self.writer.emit_pop()
465    }
466
467    fn emit_ldloca(&mut self, addr: u32) -> Result<()> {
468        self.writer.emit_ldloca(addr)
469    }
470
471    fn emit_ldind_i4(&mut self) -> Result<()> {
472        self.writer.emit_ldind_i4()
473    }
474
475    fn emit_ldind_i8(&mut self) -> Result<()> {
476        self.writer.emit_ldind_i8()
477    }
478
479    fn emit_ldind_r4(&mut self) -> Result<()> {
480        self.writer.emit_ldind_r4()
481    }
482
483    fn emit_ldind_r8(&mut self) -> Result<()> {
484        self.writer.emit_ldind_r8()
485    }
486
487    fn emit_ldind_ref(&mut self) -> Result<()> {
488        self.writer.emit_ldind_ref()
489    }
490
491    fn emit_stind_i4(&mut self) -> Result<()> {
492        self.writer.emit_stind_i4()
493    }
494
495    fn emit_stind_i8(&mut self) -> Result<()> {
496        self.writer.emit_stind_i8()
497    }
498
499    fn emit_stind_r4(&mut self) -> Result<()> {
500        self.writer.emit_stind_r4()
501    }
502
503    fn emit_stind_r8(&mut self) -> Result<()> {
504        self.writer.emit_stind_r8()
505    }
506
507    fn emit_stind_ref(&mut self) -> Result<()> {
508        self.writer.emit_stind_ref()
509    }
510
511    fn emit_conv_i4(&mut self) -> Result<()> {
512        self.writer.emit_conv_i4()
513    }
514
515    fn emit_conv_i8(&mut self) -> Result<()> {
516        self.writer.emit_conv_i8()
517    }
518
519    fn emit_conv_r4(&mut self) -> Result<()> {
520        self.writer.emit_conv_r4()
521    }
522
523    fn emit_conv_r8(&mut self) -> Result<()> {
524        self.writer.emit_conv_r8()
525    }
526
527    fn emit_box(&mut self, gaia_type: &GaiaType) -> Result<()> {
528        let type_name = match gaia_type {
529            GaiaType::Integer32 => "int32",
530            GaiaType::Integer64 => "int64",
531            GaiaType::Float32 => "float32",
532            GaiaType::Float64 => "float64",
533            GaiaType::Boolean => "bool",
534            _ => "object",
535        };
536        self.writer.emit_box(type_name)
537    }
538
539    fn emit_unbox(&mut self, gaia_type: &GaiaType) -> Result<()> {
540        let type_name = match gaia_type {
541            GaiaType::Integer32 => "int32",
542            GaiaType::Integer64 => "int64",
543            GaiaType::Float32 => "float32",
544            GaiaType::Float64 => "float64",
545            GaiaType::Boolean => "bool",
546            _ => "object",
547        };
548        self.writer.emit_unbox(type_name)
549    }
550}