1use gaia_types::{GaiaError, Result, SourceLocation};
2use std::collections::HashMap;
3
4#[derive(Debug, Clone)]
9pub struct ClrProgram {
10 pub name: String,
12 pub version: ClrVersion,
14 pub access_flags: ClrAccessFlags,
16 pub external_assemblies: Vec<ClrExternalAssembly>,
18 pub module: Option<ClrModule>,
20 pub types: Vec<ClrType>,
22 pub global_methods: Vec<ClrMethod>,
24 pub global_fields: Vec<ClrField>,
26 pub attributes: Vec<ClrAttribute>,
28 pub constant_pool: ClrConstantPool,
30 pub source_file: Option<String>,
32}
33
34#[derive(Debug, Clone, Copy)]
36pub struct ClrVersion {
37 pub major: u16,
39 pub minor: u16,
41 pub build: u16,
43 pub revision: u16,
45}
46
47#[derive(Debug, Clone, Copy)]
49pub struct ClrAccessFlags {
50 pub is_public: bool,
52 pub is_private: bool,
54 pub is_security_transparent: bool,
56 pub is_retargetable: bool,
58}
59
60#[derive(Debug, Clone)]
62pub struct ClrExternalAssembly {
63 pub name: String,
65 pub version: ClrVersion,
67 pub public_key_token: Option<Vec<u8>>,
69 pub culture: Option<String>,
71 pub hash_algorithm: Option<u32>,
73}
74
75#[derive(Debug, Clone)]
77pub struct ClrModule {
78 pub name: String,
80 pub mvid: Option<Vec<u8>>,
82}
83
84#[derive(Debug, Clone)]
86pub struct ClrType {
87 pub name: String,
89 pub namespace: Option<String>,
91 pub access_flags: ClrAccessFlags,
93 pub base_type: Option<String>,
95 pub interfaces: Vec<String>,
97 pub fields: Vec<ClrField>,
99 pub methods: Vec<ClrMethod>,
101 pub properties: Vec<ClrProperty>,
103 pub events: Vec<ClrEvent>,
105 pub nested_types: Vec<ClrType>,
107 pub attributes: Vec<ClrAttribute>,
109}
110
111#[derive(Debug, Clone)]
113pub struct ClrMethod {
114 pub name: String,
116 pub return_type: ClrTypeReference,
118 pub parameters: Vec<ClrParameter>,
120 pub access_flags: ClrAccessFlags,
122 pub impl_flags: ClrMethodImplFlags,
124 pub instructions: Vec<ClrInstruction>,
126 pub max_stack: u16,
128 pub locals: Vec<ClrLocalVariable>,
130 pub exception_handlers: Vec<ClrExceptionHandler>,
132 pub attributes: Vec<ClrAttribute>,
134 pub is_entry_point: bool,
136}
137
138#[derive(Debug, Clone)]
140pub struct ClrField {
141 pub name: String,
143 pub field_type: ClrTypeReference,
145 pub access_flags: ClrAccessFlags,
147 pub default_value: Option<ClrConstantValue>,
149 pub attributes: Vec<ClrAttribute>,
151}
152
153#[derive(Debug, Clone)]
155pub struct ClrProperty {
156 pub name: String,
158 pub property_type: ClrTypeReference,
160 pub getter: Option<String>,
162 pub setter: Option<String>,
164 pub attributes: Vec<ClrAttribute>,
166}
167
168#[derive(Debug, Clone)]
170pub struct ClrEvent {
171 pub name: String,
173 pub event_type: ClrTypeReference,
175 pub add_method: Option<String>,
177 pub remove_method: Option<String>,
179 pub raise_method: Option<String>,
181 pub attributes: Vec<ClrAttribute>,
183}
184
185#[derive(Debug, Clone, PartialEq)]
187pub enum ClrInstruction {
188 Simple { opcode: ClrOpcode },
190 WithImmediate { opcode: ClrOpcode, value: i32 },
192 WithLocalVar { opcode: ClrOpcode, index: u16 },
194 WithParameter { opcode: ClrOpcode, index: u16 },
196 WithField { opcode: ClrOpcode, field_ref: String },
198 WithMethod { opcode: ClrOpcode, method_ref: String },
200 WithType { opcode: ClrOpcode, type_ref: String },
202 WithString { opcode: ClrOpcode, value: String },
204 WithLabel { opcode: ClrOpcode, label: String },
206 WithSwitch { opcode: ClrOpcode, labels: Vec<String> },
208}
209
210#[derive(Debug, Clone, Copy, PartialEq)]
212pub enum ClrOpcode {
213 Nop,
215 LdcI4,
216 LdcI4S,
217 LdcI4M1,
218 LdcI40,
219 LdcI41,
220 LdcI42,
221 LdcI43,
222 LdcI44,
223 LdcI45,
224 LdcI46,
225 LdcI47,
226 LdcI48,
227 LdcI8,
228 LdcR4,
229 LdcR8,
230 Ldnull,
231 Ldstr,
232
233 Ldarg,
235 LdargS,
236 Ldarg0,
237 Ldarg1,
238 Ldarg2,
239 Ldarg3,
240 Ldloc,
241 LdlocS,
242 Ldloc0,
243 Ldloc1,
244 Ldloc2,
245 Ldloc3,
246 Starg,
247 StargS,
248 Stloc,
249 StlocS,
250 Stloc0,
251 Stloc1,
252 Stloc2,
253 Stloc3,
254 Ldarga,
255 LdargaS,
256 Ldloca,
257 LdlocaS,
258
259 Ldelem,
261 LdelemI1,
262 LdelemU1,
263 LdelemI2,
264 LdelemU2,
265 LdelemI4,
266 LdelemU4,
267 LdelemI8,
268 LdelemI,
269 LdelemR4,
270 LdelemR8,
271 LdelemRef,
272 Stelem,
273 StelemI1,
274 StelemI2,
275 StelemI4,
276 StelemI8,
277 StelemI,
278 StelemR4,
279 StelemR8,
280 StelemRef,
281 Ldlen,
282 Newarr,
283
284 Ldfld,
286 Ldflda,
287 Stfld,
288 Ldsfld,
289 Ldsflda,
290 Stsfld,
291
292 Call,
294 Callvirt,
295 Calli,
296 Ret,
297
298 Newobj,
300 Castclass,
301 Isinst,
302 Unbox,
303 UnboxAny,
304 Box,
305
306 Br,
308 BrS,
309 Brtrue,
310 BrtrueS,
311 Brfalse,
312 BrfalseS,
313 Beq,
314 BeqS,
315 Bne,
316 BneS,
317 Blt,
318 BltS,
319 BltUn,
320 BltUnS,
321 Ble,
322 BleS,
323 BleUn,
324 BleUnS,
325 Bgt,
326 BgtS,
327 BgtUn,
328 BgtUnS,
329 Bge,
330 BgeS,
331 BgeUn,
332 BgeUnS,
333 Switch,
334
335 Add,
337 AddOvf,
338 AddOvfUn,
339 Sub,
340 SubOvf,
341 SubOvfUn,
342 Mul,
343 MulOvf,
344 MulOvfUn,
345 Div,
346 DivUn,
347 Rem,
348 RemUn,
349 And,
350 Or,
351 Xor,
352 Not,
353 Shl,
354 Shr,
355 ShrUn,
356 Neg,
357
358 Ceq,
360 Cgt,
361 CgtUn,
362 Clt,
363 CltUn,
364
365 ConvI1,
367 ConvI2,
368 ConvI4,
369 ConvI8,
370 ConvR4,
371 ConvR8,
372 ConvU4,
373 ConvU8,
374 ConvOvfI1,
375 ConvOvfI2,
376 ConvOvfI4,
377 ConvOvfI8,
378 ConvOvfU1,
379 ConvOvfU2,
380 ConvOvfU4,
381 ConvOvfU8,
382 ConvOvfI1Un,
383 ConvOvfI2Un,
384 ConvOvfI4Un,
385 ConvOvfI8Un,
386 ConvOvfU1Un,
387 ConvOvfU2Un,
388 ConvOvfU4Un,
389 ConvOvfU8Un,
390 ConvRUn,
391 ConvOvfIUn,
392 ConvOvfUUn,
393
394 Dup,
396 Pop,
397
398 Throw,
400 Rethrow,
401 Leave,
402 LeaveS,
403 Endfinally,
404 Endfilter,
405
406 Sizeof,
408 Refanytype,
409 Refanyval,
410 Mkrefany,
411 Arglist,
412 Localloc,
413 Jmp,
414 Calli2,
415 Tail,
416 Volatile,
417 Unaligned,
418 Constrained,
419 Readonly,
420}
421
422#[derive(Debug, Clone, PartialEq)]
424pub struct ClrTypeReference {
425 pub name: String,
427 pub namespace: Option<String>,
429 pub assembly: Option<String>,
431 pub is_value_type: bool,
433 pub is_reference_type: bool,
435 pub generic_parameters: Vec<ClrTypeReference>,
437}
438
439#[derive(Debug, Clone)]
441pub struct ClrParameter {
442 pub name: String,
444 pub parameter_type: ClrTypeReference,
446 pub is_in: bool,
448 pub is_out: bool,
450 pub is_optional: bool,
452 pub default_value: Option<ClrConstantValue>,
454 pub attributes: Vec<ClrAttribute>,
456}
457
458#[derive(Debug, Clone)]
460pub struct ClrLocalVariable {
461 pub name: Option<String>,
463 pub variable_type: ClrTypeReference,
465 pub is_pinned: bool,
467}
468
469#[derive(Debug, Clone)]
471pub struct ClrExceptionHandler {
472 pub handler_type: ClrExceptionHandlerType,
474 pub try_start: u32,
476 pub try_length: u32,
478 pub handler_start: u32,
480 pub handler_length: u32,
482 pub catch_type: Option<ClrTypeReference>,
484 pub filter_start: Option<u32>,
486}
487
488#[derive(Debug, Clone, Copy, PartialEq)]
490pub enum ClrExceptionHandlerType {
491 Catch,
493 Filter,
495 Finally,
497 Fault,
499}
500
501#[derive(Debug, Clone, Copy)]
503pub struct ClrMethodImplFlags {
504 pub is_managed: bool,
506 pub is_native: bool,
508 pub is_runtime: bool,
510 pub is_inline: bool,
512 pub is_no_inline: bool,
514 pub is_synchronized: bool,
516}
517
518#[derive(Debug, Clone)]
520pub struct ClrAttribute {
521 pub attribute_type: ClrTypeReference,
523 pub constructor_args: Vec<ClrConstantValue>,
525 pub named_args: Vec<(String, ClrConstantValue)>,
527}
528
529#[derive(Debug, Clone, PartialEq)]
531pub enum ClrConstantValue {
532 Boolean(bool),
534 I1(i8),
536 U1(u8),
538 I2(i16),
540 U2(u16),
542 I4(i32),
544 U4(u32),
546 I8(i64),
548 U8(u64),
550 R4(f32),
552 R8(f64),
554 String(String),
556 Null,
558 Type(ClrTypeReference),
560 Enum(ClrTypeReference, Box<ClrConstantValue>),
562 Array(Vec<ClrConstantValue>),
564}
565
566#[derive(Debug, Clone)]
568pub struct ClrConstantPool {
569 pub strings: HashMap<String, u32>,
571 pub guids: HashMap<Vec<u8>, u32>,
573 pub blobs: HashMap<Vec<u8>, u32>,
575 pub user_strings: HashMap<String, u32>,
577}
578
579impl ClrProgram {
580 pub fn new(name: impl Into<String>) -> Self {
582 Self {
583 name: name.into(),
584 version: ClrVersion::default(),
585 access_flags: ClrAccessFlags::default(),
586 external_assemblies: Vec::new(),
587 module: None,
588 types: Vec::new(),
589 global_methods: Vec::new(),
590 global_fields: Vec::new(),
591 attributes: Vec::new(),
592 constant_pool: ClrConstantPool::new(),
593 source_file: None,
594 }
595 }
596
597 pub fn add_type(&mut self, clr_type: ClrType) {
599 self.types.push(clr_type);
600 }
601
602 pub fn add_external_assembly(&mut self, assembly: ClrExternalAssembly) {
604 self.external_assemblies.push(assembly);
605 }
606
607 pub fn set_module(&mut self, module: ClrModule) {
609 self.module = Some(module);
610 }
611
612 pub fn set_source_file(&mut self, filename: String) {
614 self.source_file = Some(filename);
615 }
616
617 pub fn validate(&self) -> Result<()> {
619 if self.name.is_empty() {
621 return Err(GaiaError::syntax_error("程序集名称不能为空".to_string(), SourceLocation::default()));
622 }
623
624 for clr_type in &self.types {
626 clr_type.validate()?;
627 }
628
629 Ok(())
630 }
631
632 pub fn get_type_count(&self) -> usize {
634 self.types.len()
635 }
636
637 pub fn get_method_count(&self) -> usize {
639 let type_methods: usize = self.types.iter().map(|t| t.methods.len()).sum();
640 type_methods + self.global_methods.len()
641 }
642
643 pub fn get_field_count(&self) -> usize {
645 let type_fields: usize = self.types.iter().map(|t| t.fields.len()).sum();
646 type_fields + self.global_fields.len()
647 }
648
649 pub fn get_sample_type_name(&self) -> Option<String> {
651 self.types.first().map(|t| {
652 if let Some(namespace) = &t.namespace {
653 format!("{}.{}", namespace, t.name)
654 }
655 else {
656 t.name.clone()
657 }
658 })
659 }
660
661 pub fn get_sample_method_name(&self) -> Option<String> {
663 for clr_type in &self.types {
665 if let Some(method) = clr_type.methods.first() {
666 return Some(format!("{}.{}", clr_type.name, method.name));
667 }
668 }
669 self.global_methods.first().map(|m| m.name.clone())
671 }
672
673 pub fn get_referenced_assemblies(&self) -> Vec<String> {
675 self.external_assemblies.iter().map(|a| a.name.clone()).collect()
676 }
677}
678
679impl ClrConstantPool {
680 pub fn new() -> Self {
682 Self { strings: HashMap::new(), guids: HashMap::new(), blobs: HashMap::new(), user_strings: HashMap::new() }
683 }
684
685 pub fn add_string(&mut self, s: String) -> u32 {
687 let next_index = self.strings.len() as u32;
688 *self.strings.entry(s).or_insert(next_index)
689 }
690
691 pub fn add_guid(&mut self, guid: Vec<u8>) -> u32 {
693 let next_index = self.guids.len() as u32;
694 *self.guids.entry(guid).or_insert(next_index)
695 }
696
697 pub fn add_blob(&mut self, blob: Vec<u8>) -> u32 {
699 let next_index = self.blobs.len() as u32;
700 *self.blobs.entry(blob).or_insert(next_index)
701 }
702
703 pub fn add_user_string(&mut self, s: String) -> u32 {
705 let next_index = self.user_strings.len() as u32;
706 *self.user_strings.entry(s).or_insert(next_index)
707 }
708}
709
710impl ClrType {
711 pub fn new(name: String, namespace: Option<String>) -> Self {
713 Self {
714 name,
715 namespace,
716 access_flags: ClrAccessFlags::default(),
717 base_type: None,
718 interfaces: Vec::new(),
719 fields: Vec::new(),
720 methods: Vec::new(),
721 properties: Vec::new(),
722 events: Vec::new(),
723 nested_types: Vec::new(),
724 attributes: Vec::new(),
725 }
726 }
727
728 pub fn add_method(&mut self, method: ClrMethod) {
730 self.methods.push(method);
731 }
732
733 pub fn add_field(&mut self, field: ClrField) {
735 self.fields.push(field);
736 }
737
738 pub fn validate(&self) -> Result<()> {
740 if self.name.is_empty() {
742 return Err(GaiaError::syntax_error("类型名称不能为空".to_string(), SourceLocation::default()));
743 }
744
745 for method in &self.methods {
747 method.validate()?;
748 }
749
750 Ok(())
751 }
752}
753
754impl ClrMethod {
755 pub fn new(name: String, return_type: ClrTypeReference) -> Self {
757 Self {
758 name,
759 return_type,
760 parameters: Vec::new(),
761 access_flags: ClrAccessFlags::default(),
762 impl_flags: ClrMethodImplFlags::default(),
763 instructions: Vec::new(),
764 max_stack: 8,
765 locals: Vec::new(),
766 exception_handlers: Vec::new(),
767 attributes: Vec::new(),
768 is_entry_point: false,
769 }
770 }
771
772 pub fn add_instruction(&mut self, instruction: ClrInstruction) {
774 self.instructions.push(instruction);
775 }
776
777 pub fn add_parameter(&mut self, parameter: ClrParameter) {
779 self.parameters.push(parameter);
780 }
781
782 pub fn validate(&self) -> Result<()> {
784 if self.name.is_empty() {
786 return Err(GaiaError::syntax_error("方法名称不能为空".to_string(), SourceLocation::default()));
787 }
788
789 Ok(())
790 }
791}
792
793impl Default for ClrVersion {
794 fn default() -> Self {
795 Self { major: 0, minor: 0, build: 0, revision: 0 }
796 }
797}
798
799impl Default for ClrAccessFlags {
800 fn default() -> Self {
801 Self { is_public: false, is_private: true, is_security_transparent: false, is_retargetable: false }
802 }
803}
804
805impl Default for ClrMethodImplFlags {
806 fn default() -> Self {
807 Self {
808 is_managed: true,
809 is_native: false,
810 is_runtime: false,
811 is_inline: false,
812 is_no_inline: false,
813 is_synchronized: false,
814 }
815 }
816}
817
818impl ClrOpcode {
819 pub fn to_byte(&self) -> u8 {
821 match self {
822 ClrOpcode::Nop => 0x00,
823 ClrOpcode::LdcI4M1 => 0x15,
824 ClrOpcode::LdcI40 => 0x16,
825 ClrOpcode::LdcI41 => 0x17,
826 ClrOpcode::LdcI42 => 0x18,
827 ClrOpcode::LdcI43 => 0x19,
828 ClrOpcode::LdcI44 => 0x1A,
829 ClrOpcode::LdcI45 => 0x1B,
830 ClrOpcode::LdcI46 => 0x1C,
831 ClrOpcode::LdcI47 => 0x1D,
832 ClrOpcode::LdcI48 => 0x1E,
833 ClrOpcode::LdcI4S => 0x1F,
834 ClrOpcode::LdcI4 => 0x20,
835 ClrOpcode::LdcI8 => 0x21,
836 ClrOpcode::LdcR4 => 0x22,
837 ClrOpcode::LdcR8 => 0x23,
838 ClrOpcode::Ldnull => 0x14,
839 ClrOpcode::Ldstr => 0x72,
840 ClrOpcode::Ldarg0 => 0x02,
841 ClrOpcode::Ldarg1 => 0x03,
842 ClrOpcode::Ldarg2 => 0x04,
843 ClrOpcode::Ldarg3 => 0x05,
844 ClrOpcode::Ldloc0 => 0x06,
845 ClrOpcode::Ldloc1 => 0x07,
846 ClrOpcode::Ldloc2 => 0x08,
847 ClrOpcode::Ldloc3 => 0x09,
848 ClrOpcode::Stloc0 => 0x0A,
849 ClrOpcode::Stloc1 => 0x0B,
850 ClrOpcode::Stloc2 => 0x0C,
851 ClrOpcode::Stloc3 => 0x0D,
852 ClrOpcode::Call => 0x28,
853 ClrOpcode::Callvirt => 0x6F,
854 ClrOpcode::Ret => 0x2A,
855 ClrOpcode::Newobj => 0x73,
856 ClrOpcode::Pop => 0x26,
857 ClrOpcode::Dup => 0x25,
858 _ => 0x00, }
860 }
861
862 pub fn from_str(s: &str) -> Option<Self> {
864 match s.to_lowercase().as_str() {
865 "nop" => Some(ClrOpcode::Nop),
866 "ldc.i4.m1" => Some(ClrOpcode::LdcI4M1),
867 "ldc.i4.0" => Some(ClrOpcode::LdcI40),
868 "ldc.i4.1" => Some(ClrOpcode::LdcI41),
869 "ldc.i4.2" => Some(ClrOpcode::LdcI42),
870 "ldc.i4.3" => Some(ClrOpcode::LdcI43),
871 "ldc.i4.4" => Some(ClrOpcode::LdcI44),
872 "ldc.i4.5" => Some(ClrOpcode::LdcI45),
873 "ldc.i4.6" => Some(ClrOpcode::LdcI46),
874 "ldc.i4.7" => Some(ClrOpcode::LdcI47),
875 "ldc.i4.8" => Some(ClrOpcode::LdcI48),
876 "ldc.i4.s" => Some(ClrOpcode::LdcI4S),
877 "ldc.i4" => Some(ClrOpcode::LdcI4),
878 "ldc.i8" => Some(ClrOpcode::LdcI8),
879 "ldc.r4" => Some(ClrOpcode::LdcR4),
880 "ldc.r8" => Some(ClrOpcode::LdcR8),
881 "ldnull" => Some(ClrOpcode::Ldnull),
882 "ldstr" => Some(ClrOpcode::Ldstr),
883 "ldarg.0" => Some(ClrOpcode::Ldarg0),
884 "ldarg.1" => Some(ClrOpcode::Ldarg1),
885 "ldarg.2" => Some(ClrOpcode::Ldarg2),
886 "ldarg.3" => Some(ClrOpcode::Ldarg3),
887 "ldloc.0" => Some(ClrOpcode::Ldloc0),
888 "ldloc.1" => Some(ClrOpcode::Ldloc1),
889 "ldloc.2" => Some(ClrOpcode::Ldloc2),
890 "ldloc.3" => Some(ClrOpcode::Ldloc3),
891 "stloc.0" => Some(ClrOpcode::Stloc0),
892 "stloc.1" => Some(ClrOpcode::Stloc1),
893 "stloc.2" => Some(ClrOpcode::Stloc2),
894 "stloc.3" => Some(ClrOpcode::Stloc3),
895 "call" => Some(ClrOpcode::Call),
896 "callvirt" => Some(ClrOpcode::Callvirt),
897 "ret" => Some(ClrOpcode::Ret),
898 "newobj" => Some(ClrOpcode::Newobj),
899 "pop" => Some(ClrOpcode::Pop),
900 "dup" => Some(ClrOpcode::Dup),
901 _ => None,
902 }
903 }
904}
905
906#[derive(Copy, Debug, Clone)]
911pub struct ClrHeader {
912 pub cb: u32,
914 pub major_runtime_version: u16,
916 pub minor_runtime_version: u16,
918 pub metadata_rva: u32,
920 pub metadata_size: u32,
922 pub flags: u32,
924}
925
926#[derive(Debug, Clone)]
928pub struct MetadataHeader {
929 pub signature: u32,
931 pub major_version: u16,
933 pub minor_version: u16,
935 pub reserved: u32,
937 pub version_length: u32,
939 pub version_string: String,
941 pub flags: u16,
943 pub streams: u16,
945}
946
947#[derive(Debug, Clone)]
949pub struct StreamHeader {
950 pub offset: u32,
952 pub size: u32,
954 pub name: String,
956}
957
958#[derive(Debug, Clone)]
960pub struct DotNetAssemblyInfo {
961 pub name: String,
963 pub version: String,
965 pub culture: Option<String>,
967 pub public_key_token: Option<String>,
969 pub runtime_version: Option<String>,
971}