Skip to main content

gaia_assembler/backends/jvm/
mod.rs

1//! JVM (Java Virtual Machine) backend compiler
2
3use crate::{
4    adapters::FunctionMapper,
5    backends::{Backend, GeneratedFiles},
6    config::GaiaConfig,
7    instruction::{CoreInstruction, GaiaInstruction},
8    program::{GaiaConstant, GaiaFunction, GaiaGlobal, GaiaModule},
9    types::GaiaType,
10};
11use gaia_types::{
12    helpers::{AbiCompatible, ApiCompatible, Architecture, CompilationTarget},
13    GaiaError, Result,
14};
15use jvm_assembler::{
16    formats::{class::writer::ClassWriter /* , jasm::ast::to_jasm::JvmToJasmConverter */},
17    program::{JvmAccessFlags, JvmField, JvmInstruction, JvmMethod, JvmProgram, JvmVersion},
18};
19use std::collections::HashMap;
20
21/// JVM Backend implementation
22#[derive(Default)]
23pub struct JvmBackend {}
24
25impl Backend for JvmBackend {
26    fn name(&self) -> &'static str {
27        "JVM"
28    }
29
30    fn primary_target(&self) -> CompilationTarget {
31        CompilationTarget { build: Architecture::JVM, host: AbiCompatible::Unknown, target: ApiCompatible::JvmRuntime(8) }
32    }
33
34    fn match_score(&self, target: &CompilationTarget) -> f32 {
35        match target.build {
36            Architecture::JVM => match target.host {
37                // bytecode output, 80% support (primary)
38                AbiCompatible::Unknown => 80.0,
39                // jasm output, 5% support (disabled)
40                AbiCompatible::JavaAssembly => 5.0,
41                _ => -100.0,
42            },
43            _ => -100.0,
44        }
45    }
46
47    fn generate(&self, program: &GaiaModule, config: &GaiaConfig) -> Result<GeneratedFiles> {
48        let mut files = HashMap::new();
49
50        // 将 GaiaModule 转换为 JvmProgram(带配置与函数映射)
51        let jvm_program = convert_gaia_to_jvm(program, config)?;
52
53        match config.target.host {
54            AbiCompatible::Unknown => {
55                // 生成 .class 字节码文件
56                let buffer = Vec::new();
57                let class_writer = ClassWriter::new(buffer);
58                let class_bytes = class_writer.write(&jvm_program).result?;
59                files.insert("main.class".to_string(), class_bytes);
60            }
61            AbiCompatible::JavaAssembly => {
62                // 生成 .jasm 汇编文件
63                // let mut converter = JvmToJasmConverter::new();
64                // let jasm_result = converter.convert(jvm_program);
65                // match jasm_result.result {
66                // Ok(jasm_root) => {
67                // let jasm_string = format!("{:#?}", jasm_root);
68                // files.insert("main.jasm".to_string(), jasm_string.into_bytes());
69                // }
70                // Err(error) => return Err(error),
71                // }
72                return Err(GaiaError::custom_error("JASM output is currently disabled"));
73            }
74            _ => return Err(GaiaError::custom_error(&format!("Unsupported host ABI: {:?}", config.target.host))),
75        }
76
77        Ok(GeneratedFiles { files, diagnostics: vec![] })
78    }
79}
80
81impl JvmBackend {
82    /// Generate JVM program from Gaia program
83    pub fn generate_program(program: &GaiaModule) -> Result<JvmProgram> {
84        // 使用默认配置生成(保持向后兼容)
85        let default_config = GaiaConfig::default();
86        convert_gaia_to_jvm(program, &default_config)
87    }
88}
89
90/// JVM 编译上下文,携带函数映射与目标信息
91struct JvmContext {
92    function_mapper: FunctionMapper,
93    /// 字段类型映射 (类名, 字段名) -> 描述符
94    field_types: HashMap<(String, String), String>,
95}
96
97/// Convert GaiaModule to JvmProgram
98fn convert_gaia_to_jvm(program: &GaiaModule, config: &GaiaConfig) -> Result<JvmProgram> {
99    let mut jvm_program = JvmProgram::new(program.name.clone());
100
101    // Set version information
102    jvm_program.version = JvmVersion { major: 52, minor: 0 }; // Java 8
103
104    // Set access flags
105    jvm_program.access_flags = JvmAccessFlags::PUBLIC;
106
107    // 构建字段类型映射
108    let mut field_types = HashMap::new();
109    for class in &program.classes {
110        for field in &class.fields {
111            field_types.insert((class.name.clone(), field.name.clone()), convert_gaia_type_to_jvm_descriptor(&field.ty));
112        }
113    }
114    for global in &program.globals {
115        field_types.insert(("Main".to_string(), global.name.clone()), convert_gaia_type_to_jvm_descriptor(&global.ty));
116    }
117
118    // 构建上下文(从配置初始化函数映射)
119    let ctx = JvmContext { function_mapper: FunctionMapper::from_config(&config.setting)?, field_types };
120
121    // 处理导入 (JVM 中通常通过外部类引用实现,不需要显式导入表,但可以记录)
122    // for import in &program.imports { ... }
123
124    // Convert functions(带上下文)
125    for function in &program.functions {
126        let jvm_method = convert_gaia_function_to_jvm(function, &ctx)?;
127        jvm_program.add_method(jvm_method);
128    }
129
130    // Convert classes
131    for class in &program.classes {
132        // 在 JVM 中,每个类通常是一个单独的文件。
133        // 这里简化处理,如果是 GaiaModule 中的类,可能需要生成多个 JvmProgram
134        // 或者将它们作为内部类处理。
135        // 目前我们只处理主类中的字段和方法。
136        for field in &class.fields {
137            let jvm_field = convert_gaia_field_to_jvm_field(field)?;
138            jvm_program.add_field(jvm_field);
139        }
140        for method in &class.methods {
141            let jvm_method = convert_gaia_function_to_jvm(method, &ctx)?;
142            jvm_program.add_method(jvm_method);
143        }
144    }
145
146    // Convert global variables to fields
147    for global in &program.globals {
148        let jvm_field = convert_gaia_global_to_jvm_field(global)?;
149        jvm_program.add_field(jvm_field);
150    }
151
152    Ok(jvm_program)
153}
154
155/// Convert GaiaFunction to JvmMethod
156fn convert_gaia_function_to_jvm(function: &GaiaFunction, ctx: &JvmContext) -> Result<JvmMethod> {
157    // 构建方法描述符
158    let descriptor = build_method_descriptor(&function.signature.params, &Some(function.signature.return_type.clone()));
159
160    let mut method = JvmMethod::new(function.name.clone(), descriptor);
161
162    // 设置访问标志
163    method = method.with_public().with_static();
164
165    // 转换基本块
166    for block in &function.blocks {
167        // 在 JVM 中,标签通常是指令流的一部分或由汇编器处理
168        // 这里我们简化处理,假设 jvm-assembler 能处理标签指令
169        // method = method.with_instruction(JvmInstruction::Label { name: block.label.clone() });
170
171        for instruction in &block.instructions {
172            let jvm_instructions = convert_gaia_instruction_to_jvm(instruction, ctx)?;
173            for ji in jvm_instructions {
174                method = method.with_instruction(ji);
175            }
176        }
177
178        // 处理终止符
179        match &block.terminator {
180            crate::program::GaiaTerminator::Jump(label) => {
181                method = method.with_instruction(JvmInstruction::Goto { target: label.clone() });
182            }
183            crate::program::GaiaTerminator::Branch { true_label, false_label } => {
184                // JVM 通常先判断 false 情况跳转,或者 true 跳转。这里采用 Ifne (if not zero)
185                method = method.with_instruction(JvmInstruction::Ifne { target: true_label.clone() });
186                method = method.with_instruction(JvmInstruction::Goto { target: false_label.clone() });
187            }
188            crate::program::GaiaTerminator::Return => {
189                method = method.with_instruction(JvmInstruction::Return);
190            }
191            crate::program::GaiaTerminator::Call { callee, args_count: _, next_block } => {
192                // JVM call 映射
193                let jvm_target = CompilationTarget {
194                    build: Architecture::JVM,
195                    host: AbiCompatible::JavaAssembly,
196                    target: ApiCompatible::JvmRuntime(8),
197                };
198                let mapped = ctx.function_mapper.map_function(&jvm_target, callee).unwrap_or(callee.as_str()).to_string();
199
200                method = method.with_instruction(JvmInstruction::Invokestatic {
201                    class_name: "Main".to_string(),
202                    method_name: mapped,
203                    descriptor: "()V".to_string(), // 简化处理,实际需要根据函数签名确定
204                });
205                method = method.with_instruction(JvmInstruction::Goto { target: next_block.clone() });
206            }
207            crate::program::GaiaTerminator::Halt => {
208                // JVM 中 Halt 可以映射为 System.exit(0)
209                method = method.with_instruction(JvmInstruction::Iconst0);
210                method = method.with_instruction(JvmInstruction::Invokestatic {
211                    class_name: "java/lang/System".to_string(),
212                    method_name: "exit".to_string(),
213                    descriptor: "(I)V".to_string(),
214                });
215            }
216        }
217    }
218
219    // 设置栈和局部变量大小(简化处理)
220    method = method.with_max_stack(10).with_max_locals(10);
221
222    Ok(method)
223}
224
225/// Convert GaiaField to JvmField
226fn convert_gaia_field_to_jvm_field(field: &crate::program::GaiaField) -> Result<JvmField> {
227    let descriptor = convert_gaia_type_to_jvm_descriptor(&field.ty);
228    let mut jvm_field = JvmField::new(field.name.clone(), descriptor);
229
230    if field.is_static {
231        jvm_field = jvm_field.with_static();
232    }
233
234    match field.visibility {
235        crate::program::Visibility::Public => jvm_field = jvm_field.with_public(),
236        crate::program::Visibility::Private => jvm_field = jvm_field.with_private(),
237        crate::program::Visibility::Protected => jvm_field = jvm_field.with_protected(),
238        _ => {}
239    }
240
241    Ok(jvm_field)
242}
243
244/// Convert GaiaGlobal to JvmField
245fn convert_gaia_global_to_jvm_field(global: &GaiaGlobal) -> Result<JvmField> {
246    let descriptor = convert_gaia_type_to_jvm_descriptor(&global.ty);
247    let field = JvmField::new(global.name.clone(), descriptor).with_public().with_static();
248
249    Ok(field)
250}
251
252/// Convert GaiaInstruction to JvmInstruction
253fn convert_gaia_instruction_to_jvm(instruction: &GaiaInstruction, ctx: &JvmContext) -> Result<Vec<JvmInstruction>> {
254    match instruction {
255        GaiaInstruction::Core(core) => match core {
256            CoreInstruction::PushConstant(constant) => match constant {
257                GaiaConstant::I8(value) => Ok(vec![JvmInstruction::Bipush { value: *value }]),
258                GaiaConstant::U8(value) => Ok(vec![JvmInstruction::Bipush { value: *value as i8 }]),
259                GaiaConstant::I16(value) => Ok(vec![JvmInstruction::Sipush { value: *value }]),
260                GaiaConstant::U16(value) => Ok(vec![JvmInstruction::Sipush { value: *value as i16 }]),
261                GaiaConstant::I32(value) => match *value {
262                    0 => Ok(vec![JvmInstruction::Iconst0]),
263                    1 => Ok(vec![JvmInstruction::Iconst1]),
264                    2 => Ok(vec![JvmInstruction::Iconst2]),
265                    3 => Ok(vec![JvmInstruction::Iconst3]),
266                    4 => Ok(vec![JvmInstruction::Iconst4]),
267                    5 => Ok(vec![JvmInstruction::Iconst5]),
268                    -1 => Ok(vec![JvmInstruction::IconstM1]),
269                    _ if *value >= -128 && *value <= 127 => Ok(vec![JvmInstruction::Bipush { value: *value as i8 }]),
270                    _ if *value >= -32768 && *value <= 32767 => Ok(vec![JvmInstruction::Sipush { value: *value as i16 }]),
271                    _ => Ok(vec![JvmInstruction::Ldc { symbol: value.to_string() }]),
272                },
273                GaiaConstant::U32(value) => Ok(vec![JvmInstruction::Ldc { symbol: value.to_string() }]),
274                GaiaConstant::I64(value) => Ok(vec![JvmInstruction::Ldc2W { symbol: value.to_string() }]),
275                GaiaConstant::U64(value) => Ok(vec![JvmInstruction::Ldc2W { symbol: value.to_string() }]),
276                GaiaConstant::F32(value) => match *value {
277                    0.0 => Ok(vec![JvmInstruction::Fconst0]),
278                    1.0 => Ok(vec![JvmInstruction::Fconst1]),
279                    2.0 => Ok(vec![JvmInstruction::Fconst2]),
280                    _ => Ok(vec![JvmInstruction::Ldc { symbol: value.to_string() }]),
281                },
282                GaiaConstant::F64(value) => match *value {
283                    0.0 => Ok(vec![JvmInstruction::Dconst0]),
284                    1.0 => Ok(vec![JvmInstruction::Dconst1]),
285                    _ => Ok(vec![JvmInstruction::Ldc2W { symbol: value.to_string() }]),
286                },
287                GaiaConstant::String(value) => Ok(vec![JvmInstruction::Ldc { symbol: value.clone() }]),
288                GaiaConstant::Bool(value) => Ok(vec![if *value { JvmInstruction::Iconst1 } else { JvmInstruction::Iconst0 }]),
289                GaiaConstant::Null => Ok(vec![JvmInstruction::AconstNull]),
290                _ => Err(GaiaError::custom_error("Unsupported constant type for JVM")),
291            },
292            CoreInstruction::Load(_gaia_type) => {
293                // JVM 不直接支持内存间接加载,这里可能需要映射到数组访问或抛出未实现
294                Err(GaiaError::not_implemented("JVM indirect load"))
295            }
296            CoreInstruction::Store(_gaia_type) => {
297                // JVM 不直接支持内存间接存储
298                Err(GaiaError::not_implemented("JVM indirect store"))
299            }
300            CoreInstruction::Add(_) => Ok(vec![JvmInstruction::Iadd]),
301            CoreInstruction::Sub(_) => Ok(vec![JvmInstruction::Isub]),
302            CoreInstruction::Mul(_) => Ok(vec![JvmInstruction::Imul]),
303            CoreInstruction::Div(_) => Ok(vec![JvmInstruction::Idiv]),
304            CoreInstruction::Pop => Ok(vec![JvmInstruction::Pop]),
305            CoreInstruction::Dup => Ok(vec![JvmInstruction::Dup]),
306            CoreInstruction::Ret => Ok(vec![JvmInstruction::Return]),
307            CoreInstruction::Br(label) => Ok(vec![JvmInstruction::Goto { target: label.clone() }]),
308            CoreInstruction::BrTrue(label) => Ok(vec![JvmInstruction::Ifne { target: label.clone() }]),
309            CoreInstruction::BrFalse(label) => Ok(vec![JvmInstruction::Ifeq { target: label.clone() }]),
310            CoreInstruction::Label(name) => Ok(vec![JvmInstruction::Label { name: name.clone() }]),
311            CoreInstruction::Call(name, arg_count) => {
312                // 简化处理,由适配器完成映射
313                let jvm_target = gaia_types::helpers::CompilationTarget {
314                    build: gaia_types::helpers::Architecture::JVM,
315                    host: gaia_types::helpers::AbiCompatible::JavaAssembly,
316                    target: gaia_types::helpers::ApiCompatible::JvmRuntime(8),
317                };
318                let mapped = ctx.function_mapper.map_function(&jvm_target, name).unwrap_or(name);
319                Ok(vec![JvmInstruction::Invokestatic {
320                    class_name: "Main".to_string(), // 假设在 Main 类中
321                    method_name: mapped.to_string(),
322                    descriptor: format!("({})V", "I".repeat(*arg_count)), // 简化:假设全为 I,返回 Void
323                }])
324            }
325            CoreInstruction::LoadLocal(index, ty) => Ok(vec![match ty {
326                GaiaType::I32
327                | GaiaType::U32
328                | GaiaType::Bool
329                | GaiaType::I8
330                | GaiaType::U8
331                | GaiaType::I16
332                | GaiaType::U16 => JvmInstruction::Iload { index: *index as u16 },
333                GaiaType::I64 | GaiaType::U64 => JvmInstruction::Lload { index: *index as u16 },
334                GaiaType::F32 => JvmInstruction::Fload { index: *index as u16 },
335                GaiaType::F64 => JvmInstruction::Dload { index: *index as u16 },
336                _ => JvmInstruction::Aload { index: *index as u16 },
337            }]),
338            CoreInstruction::StoreLocal(index, ty) => Ok(vec![match ty {
339                GaiaType::I32
340                | GaiaType::U32
341                | GaiaType::Bool
342                | GaiaType::I8
343                | GaiaType::U8
344                | GaiaType::I16
345                | GaiaType::U16 => JvmInstruction::Istore { index: *index as u16 },
346                GaiaType::I64 | GaiaType::U64 => JvmInstruction::Lstore { index: *index as u16 },
347                GaiaType::F32 => JvmInstruction::Fstore { index: *index as u16 },
348                GaiaType::F64 => JvmInstruction::Dstore { index: *index as u16 },
349                _ => JvmInstruction::Astore { index: *index as u16 },
350            }]),
351            CoreInstruction::LoadArg(index, ty) => Ok(vec![match ty {
352                GaiaType::I32
353                | GaiaType::U32
354                | GaiaType::Bool
355                | GaiaType::I8
356                | GaiaType::U8
357                | GaiaType::I16
358                | GaiaType::U16 => JvmInstruction::Iload { index: *index as u16 },
359                GaiaType::I64 | GaiaType::U64 => JvmInstruction::Lload { index: *index as u16 },
360                GaiaType::F32 => JvmInstruction::Fload { index: *index as u16 },
361                GaiaType::F64 => JvmInstruction::Dload { index: *index as u16 },
362                _ => JvmInstruction::Aload { index: *index as u16 },
363            }]),
364            CoreInstruction::StoreArg(index, ty) => Ok(vec![match ty {
365                GaiaType::I32
366                | GaiaType::U32
367                | GaiaType::Bool
368                | GaiaType::I8
369                | GaiaType::U8
370                | GaiaType::I16
371                | GaiaType::U16 => JvmInstruction::Istore { index: *index as u16 },
372                GaiaType::I64 | GaiaType::U64 => JvmInstruction::Lstore { index: *index as u16 },
373                GaiaType::F32 => JvmInstruction::Fstore { index: *index as u16 },
374                GaiaType::F64 => JvmInstruction::Dstore { index: *index as u16 },
375                _ => JvmInstruction::Astore { index: *index as u16 },
376            }]),
377            CoreInstruction::New(type_name) => Ok(vec![
378                JvmInstruction::New { class_name: type_name.replace('.', "/") },
379                JvmInstruction::Dup,
380                JvmInstruction::Invokespecial {
381                    class_name: type_name.replace('.', "/"),
382                    method_name: "<init>".to_string(),
383                    descriptor: "()V".to_string(),
384                },
385            ]),
386            CoreInstruction::LoadField(type_name, field_name) => {
387                let descriptor = ctx
388                    .field_types
389                    .get(&(type_name.clone(), field_name.clone()))
390                    .cloned()
391                    .unwrap_or_else(|| "Ljava/lang/Object;".to_string());
392                Ok(vec![JvmInstruction::Getfield {
393                    class_name: type_name.replace('.', "/"),
394                    field_name: field_name.to_string(),
395                    descriptor,
396                }])
397            }
398            CoreInstruction::StoreField(type_name, field_name) => {
399                let descriptor = ctx
400                    .field_types
401                    .get(&(type_name.clone(), field_name.clone()))
402                    .cloned()
403                    .unwrap_or_else(|| "Ljava/lang/Object;".to_string());
404                Ok(vec![JvmInstruction::Putfield {
405                    class_name: type_name.replace('.', "/"),
406                    field_name: field_name.to_string(),
407                    descriptor,
408                }])
409            }
410            CoreInstruction::LoadElement(ty) => Ok(vec![match ty {
411                GaiaType::I32 | GaiaType::U32 => JvmInstruction::Iaload,
412                GaiaType::I64 | GaiaType::U64 => JvmInstruction::Laload,
413                GaiaType::F32 => JvmInstruction::Faload,
414                GaiaType::F64 => JvmInstruction::Daload,
415                GaiaType::I8 | GaiaType::U8 | GaiaType::Bool => JvmInstruction::Baload,
416                GaiaType::I16 | GaiaType::U16 => JvmInstruction::Saload,
417                _ => JvmInstruction::Aaload,
418            }]),
419            CoreInstruction::StoreElement(ty) => Ok(vec![match ty {
420                GaiaType::I32 | GaiaType::U32 => JvmInstruction::Iastore,
421                GaiaType::I64 | GaiaType::U64 => JvmInstruction::Lastore,
422                GaiaType::F32 => JvmInstruction::Fastore,
423                GaiaType::F64 => JvmInstruction::Dastore,
424                GaiaType::I8 | GaiaType::U8 | GaiaType::Bool => JvmInstruction::Bastore,
425                GaiaType::I16 | GaiaType::U16 => JvmInstruction::Sastore,
426                _ => JvmInstruction::Aastore,
427            }]),
428            CoreInstruction::ArrayLength => Ok(vec![JvmInstruction::Arraylength]),
429            CoreInstruction::NewArray(elem_type, _) => {
430                Ok(vec![match elem_type {
431                    GaiaType::I32 | GaiaType::U32 => JvmInstruction::Newarray { atype: 10 }, // T_INT
432                    GaiaType::I64 | GaiaType::U64 => JvmInstruction::Newarray { atype: 11 }, // T_LONG
433                    GaiaType::F32 => JvmInstruction::Newarray { atype: 6 },                  // T_FLOAT
434                    GaiaType::F64 => JvmInstruction::Newarray { atype: 7 },                  // T_DOUBLE
435                    GaiaType::I8 | GaiaType::U8 => JvmInstruction::Newarray { atype: 8 },    // T_BYTE
436                    GaiaType::Bool => JvmInstruction::Newarray { atype: 4 },                 // T_BOOLEAN
437                    GaiaType::I16 | GaiaType::U16 => JvmInstruction::Newarray { atype: 9 },  // T_SHORT
438                    _ => JvmInstruction::Anewarray { class_name: convert_gaia_type_to_jvm_descriptor(elem_type) },
439                }])
440            }
441            _ => Ok(vec![]),
442        },
443        GaiaInstruction::Managed(managed) => match managed {
444            _ => Ok(vec![]),
445        },
446        _ => Ok(vec![]),
447    }
448}
449
450/// Build JVM method descriptor from parameters and return type
451fn build_method_descriptor(parameters: &[GaiaType], return_type: &Option<GaiaType>) -> String {
452    let mut descriptor = String::from("(");
453
454    // 添加参数类型
455    for param in parameters {
456        descriptor.push_str(&convert_gaia_type_to_jvm_descriptor(param));
457    }
458
459    descriptor.push(')');
460
461    // 添加返回类型
462    match return_type {
463        Some(ret_type) => descriptor.push_str(&convert_gaia_type_to_jvm_descriptor(ret_type)),
464        None => descriptor.push('V'), // void
465    }
466
467    descriptor
468}
469
470/// Convert GaiaType to JVM type descriptor
471fn convert_gaia_type_to_jvm_descriptor(gaia_type: &GaiaType) -> String {
472    match gaia_type {
473        GaiaType::Bool => "Z".to_string(),
474        GaiaType::I8 | GaiaType::U8 => "B".to_string(),
475        GaiaType::I16 | GaiaType::U16 => "S".to_string(),
476        GaiaType::I32 | GaiaType::U32 => "I".to_string(),
477        GaiaType::I64 | GaiaType::U64 => "J".to_string(),
478        GaiaType::F32 | GaiaType::F16 => "F".to_string(),
479        GaiaType::F64 => "D".to_string(),
480        GaiaType::String => "Ljava/lang/String;".to_string(),
481        GaiaType::Class(name) => format!("L{};", name.replace('.', "/")),
482        GaiaType::Struct(name) => format!("L{};", name.replace('.', "/")),
483        GaiaType::Array(elem, _) => format!("[{}", convert_gaia_type_to_jvm_descriptor(elem)),
484        GaiaType::Void => "V".to_string(),
485        GaiaType::Object => "Ljava/lang/Object;".to_string(),
486        _ => "Ljava/lang/Object;".to_string(),
487    }
488}