4 using System.Collections.Generic;
10 public partial class ILDAsm
12 public static int Main (String[] args) {
13 if (args.Length != 1) {
14 Console.Error.WriteLine ("Usage: ildasm <assembly file>");
18 var inst = new ILDAsm ();
19 return inst.Run (args);
22 public AssemblyDefinition ad;
23 public ModuleDefinition main;
26 public List<FieldDefinition> fields_with_rva = new List<FieldDefinition> ();
28 public void WriteLine () {
32 public void WriteLine (String s) {
33 for (int i = 0; i < indent; ++i)
38 public int Run (String[] args) {
39 ad = AssemblyDefinition.ReadAssembly (args [0]);
45 // Emit assembly references
46 EmitAssemblyReferences ();
49 foreach (var typedef in main.Types) {
51 if (typedef.Name == "<Module>")
52 EmitGlobals (typedef);
61 string EscapeName (string s) {
64 if (s.Contains ("/")) {
65 string[] parts = s.Split ('/');
66 var sb = new StringBuilder ();
67 for (int i = 0; i < parts.Length; ++i) {
70 sb.Append (EscapeName (parts [i]));
72 return sb.ToString ();
75 foreach (char c in s) {
76 if (!((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9') || (c == '_') || (c == '.') || (c == '`')))
79 if (!escape && keyword_table.ContainsKey (s))
87 string EscapeString (string s) {
88 return s.Replace ("\\", "\\\\").Replace ("\"", "\\\"");
91 void EmitScope (IMetadataScope s, StringBuilder sb) {
92 if (s is AssemblyNameReference) {
93 AssemblyNameReference aname = (s as AssemblyNameReference);
94 sb.Append ("[" + EscapeName (aname.Name) + "]");
95 } else if (s is ModuleDefinition) {
97 throw new NotImplementedException ();
99 throw new NotImplementedException (s.GetType ().ToString ());
103 string StringifyTypeRef (TypeReference t) {
104 switch (t.MetadataType) {
105 case MetadataType.Void:
107 case MetadataType.Boolean:
109 case MetadataType.Char:
111 case MetadataType.SByte:
113 case MetadataType.Byte:
114 return "unsigned int8";
115 case MetadataType.Int16:
117 case MetadataType.UInt16:
118 return "unsigned int16";
119 case MetadataType.Int32:
121 case MetadataType.UInt32:
122 return "unsigned int32";
123 case MetadataType.Int64:
125 case MetadataType.UInt64:
126 return "unsigned int64";
127 case MetadataType.Single:
129 case MetadataType.Double:
131 case MetadataType.String:
133 case MetadataType.IntPtr:
135 case MetadataType.UIntPtr:
136 //return "unsigned native int";
137 return "[mscorlib]System.UIntPtr";
138 case MetadataType.TypedByReference:
140 case MetadataType.Class:
141 case MetadataType.Object:
142 case MetadataType.ValueType: {
143 var sb = new StringBuilder ();
144 IMetadataScope s = t.Scope;
145 if (t.MetadataType == MetadataType.ValueType)
146 sb.Append ("valuetype ");
148 sb.Append ("class ");
150 sb.Append (EscapeName (t.FullName));
151 return sb.ToString ();
153 case MetadataType.Array: {
154 ArrayType at = (t as ArrayType);
157 return StringifyTypeRef (at.ElementType) + "[]";
159 var suffix = new StringBuilder ();
161 for (int i = 0; i < at.Dimensions.Count; i++) {
165 suffix.Append (at.Dimensions [i].ToString ());
169 return StringifyTypeRef (at.ElementType) + suffix;
171 case MetadataType.Pointer:
172 return StringifyTypeRef ((t as TypeSpecification).ElementType) + "*";
173 case MetadataType.ByReference:
174 return StringifyTypeRef ((t as TypeSpecification).ElementType) + "&";
175 case MetadataType.Pinned:
176 return StringifyTypeRef ((t as TypeSpecification).ElementType) + " pinned";
177 case MetadataType.GenericInstance: {
178 var sb = new StringBuilder ();
179 var inst = (t as GenericInstanceType);
180 sb.Append (StringifyTypeRef (inst.ElementType));
183 foreach (TypeReference arg in inst.GenericArguments) {
186 sb.Append (StringifyTypeRef (arg));
190 return sb.ToString ();
192 case MetadataType.Var:
193 return "!" + (t as GenericParameter).Position;
194 case MetadataType.MVar:
195 return "!!" + (t as GenericParameter).Position;
196 case MetadataType.Sentinel:
197 return "..., " + StringifyTypeRef ((t as SentinelType).ElementType);
198 case MetadataType.RequiredModifier: {
199 var mod = (t as RequiredModifierType);
200 if (mod.ModifierType.MetadataType != MetadataType.Class)
201 throw new NotImplementedException ();
202 var sb = new StringBuilder ();
203 sb.Append (StringifyTypeRef (mod.ElementType));
204 sb.Append (" modreq (");
205 EmitScope (mod.ModifierType.Scope, sb);
206 sb.Append (EscapeName (mod.ModifierType.FullName));
208 return sb.ToString ();
211 throw new NotImplementedException ("" + t.MetadataType + " " + t.ToString ());
215 // Same as StringifyTypeRef, but emit primitive types as [mscorlib]...
216 string StringifyTypeRefNoPrim (TypeReference t) {
217 switch (t.MetadataType) {
218 case MetadataType.Void:
219 case MetadataType.Boolean:
220 case MetadataType.Char:
221 case MetadataType.SByte:
222 case MetadataType.Byte:
223 case MetadataType.Int16:
224 case MetadataType.UInt16:
225 case MetadataType.Int32:
226 case MetadataType.UInt32:
227 case MetadataType.Int64:
228 case MetadataType.UInt64:
229 case MetadataType.Single:
230 case MetadataType.Double:
231 case MetadataType.String:
232 case MetadataType.IntPtr:
233 case MetadataType.UIntPtr:
234 case MetadataType.TypedByReference:
235 return "[mscorlib]" + t.FullName;
237 return StringifyTypeRef (t);
241 string StringifyMethodRef (MethodReference method) {
242 var sb = new StringBuilder ();
243 if (method.CallingConvention == MethodCallingConvention.VarArg)
244 sb.Append ("vararg ");
246 sb.Append ("instance ");
247 sb.Append (StringifyTypeRef (method.ReturnType));
249 sb.Append (StringifyTypeRefNoPrim (method.DeclaringType));
251 sb.Append (EscapeName (method.Name));
252 if (method is GenericInstanceMethod) {
255 foreach (var gpar in (method as GenericInstanceMethod).GenericArguments) {
258 sb.Append (StringifyTypeRef (gpar));
265 foreach (ParameterReference par in method.Parameters) {
268 sb.Append (StringifyTypeRef (par.ParameterType));
272 return sb.ToString ();
275 string StringifyFieldRef (FieldReference field) {
276 var sb = new StringBuilder ();
277 sb.Append (StringifyTypeRef (field.FieldType));
279 sb.Append (StringifyTypeRefNoPrim (field.DeclaringType));
281 sb.Append (EscapeName (field.Name));
282 return sb.ToString ();
285 void WriteBlob (byte[] blob) {
287 while (idx < blob.Length) {
288 int len = idx + 16 < blob.Length ? 16 : blob.Length - idx;
289 var sb = new StringBuilder ();
290 var sb2 = new StringBuilder ();
291 for (int i = idx; i < idx + len; ++i) {
292 sb.Append (String.Format ("{0:X2} ", blob [i]));
293 if (Char.IsLetterOrDigit ((char)blob [i]))
294 sb2.Append ((char)blob [i]);
298 for (int i = 0; i < 16 - len; ++i)
300 if (len < 16 || idx + 16 == blob.Length)
304 WriteLine (String.Format ("{0} // {1}", sb.ToString (), sb2.ToString ()));
309 string Map (Dictionary <uint, string> map, uint val) {
312 if (map.TryGetValue (val, out s))
315 throw new NotImplementedException ("Value '" + val + "' not supported.");
318 string MapFlags (Dictionary <uint, string> map, uint val) {
319 var sb = new StringBuilder ();
320 foreach (var flag in map.Keys)
321 if ((val & flag) != 0)
322 sb.Append (map [flag]);
323 return sb.ToString ();
326 void EmitAssemblyReferences () {
327 foreach (var aname in main.AssemblyReferences) {
328 os.WriteLine (".assembly extern " + EscapeName (aname.Name));
331 Version v = aname.Version;
332 WriteLine (String.Format (".ver {0}:{1}:{2}:{3}", v.Major, v.Minor, v.Build, v.Revision));
333 byte [] token = aname.PublicKeyToken;
334 if (token.Length > 0) {
335 StringBuilder sb = new StringBuilder ();
336 StringBuilder sb2 = new StringBuilder ();
337 for (int i = 0; i < token.Length; ++i) {
340 sb.Append (String.Format ("{0:X2}", token [i]));
341 if (Char.IsLetterOrDigit ((char)token [i]))
342 sb2.Append ((char)token [i]);
346 WriteLine (String.Format (".publickeytoken = ({0}) // {1}", sb, sb2));
353 void EmitCattrs (ICustomAttributeProvider prov) {
354 foreach (var cattr in prov.CustomAttributes) {
355 WriteLine (String.Format (".custom {0} = (", StringifyMethodRef (cattr.Constructor)));
357 byte[] blob = cattr.GetBlob ();
363 void EmitSecDeclarations (ISecurityDeclarationProvider prov) {
364 foreach (var sec in prov.SecurityDeclarations) {
365 string act_str = null;
366 if (!sec_action_to_string.TryGetValue (sec.Action, out act_str))
367 throw new NotImplementedException (sec.Action.ToString ());
368 WriteLine (".permissionset " + act_str + " = (");
369 WriteBlob (sec.GetBlob ());
373 void EmitAssembly () {
374 AssemblyNameDefinition aname = ad.Name;
376 WriteLine (".assembly " + EscapeName (aname.Name));
380 EmitSecDeclarations (ad);
381 WriteLine (String.Format (".hash algorithm 0x{0:X8}", (int)aname.HashAlgorithm));
382 Version v = aname.Version;
383 WriteLine (String.Format (".ver {0}:{1}:{2}:{3}", v.Major, v.Minor, v.Build, v.Revision));
384 byte[] token = aname.PublicKey;
385 if (token != null && token.Length > 0) {
386 StringBuilder sb = new StringBuilder ();
387 StringBuilder sb2 = new StringBuilder ();
388 for (int i = 0; i < token.Length; ++i) {
391 sb.Append (String.Format ("{0:X2}", token [i]));
392 if (Char.IsLetterOrDigit ((char)token [i]))
393 sb2.Append ((char)token [i]);
397 WriteLine (String.Format (".publickey = ({0}) // {1}", sb, sb2));
404 WriteLine (".module " + EscapeName (main.Name) + " // GUID = " + "{" + main.Mvid.ToString ().ToUpper () + "}");
408 string StringifyTypeAttrs (TypeAttributes attrs) {
409 var sb = new StringBuilder ();
411 sb.Append (Map (type_sem_map, (uint)(attrs & TypeAttributes.ClassSemanticMask)));
412 sb.Append (Map (type_access_map, (uint)(attrs & TypeAttributes.VisibilityMask)));
413 sb.Append (Map (type_layout_map, (uint)(attrs & TypeAttributes.LayoutMask)));
414 sb.Append (Map (type_string_format_map, (uint)(attrs & TypeAttributes.StringFormatMask)));
415 sb.Append (MapFlags (type_flag_map, (uint)(attrs)));
417 return sb.ToString ();
420 void EmitGenParams (IGenericParameterProvider prov, StringBuilder sb) {
423 foreach (var gpar in prov.GenericParameters) {
426 if (gpar.HasDefaultConstructorConstraint)
427 sb.Append (".ctor ");
428 if (gpar.HasNotNullableValueTypeConstraint)
429 sb.Append ("valuetype ");
430 if (gpar.HasReferenceTypeConstraint)
431 sb.Append ("class ");
432 if (gpar.HasConstraints) {
435 foreach (var c in gpar.Constraints) {
438 sb.Append (StringifyTypeRef (c));
443 sb.Append (EscapeName (gpar.Name));
449 void EmitGenParamCattrs (IGenericParameterProvider prov) {
450 foreach (var gpar in prov.GenericParameters) {
451 if (gpar.HasCustomAttributes) {
452 WriteLine (".param type " + gpar.Name);
458 void EmitGlobals (TypeDefinition td) {
459 foreach (var md in td.Methods)
463 void EmitType (TypeDefinition td) {
466 if (td.MetadataType != MetadataType.Class && td.MetadataType != MetadataType.ValueType)
467 throw new NotImplementedException (td.MetadataType.ToString ());
469 // FIXME: Group types by namespaces
470 if (!td.IsNested && td.Namespace != null && td.Namespace != String.Empty) {
471 WriteLine (".namespace " + EscapeName (td.Namespace));
476 var sb = new StringBuilder ();
477 sb.Append (".class ");
478 sb.Append (StringifyTypeAttrs (td.Attributes));
479 sb.Append (EscapeName (td.Name));
480 if (td.HasGenericParameters)
481 EmitGenParams (td, sb);
482 WriteLine (sb.ToString ());
484 if (td.BaseType != null)
485 WriteLine ("extends " + StringifyTypeRef (td.BaseType));
486 if (td.HasInterfaces) {
488 sb = new StringBuilder ();
489 foreach (TypeReference t in td.Interfaces) {
492 sb.Append (StringifyTypeRef (t));
495 WriteLine (String.Format ("implements {0}", sb.ToString ()));
500 if (td.PackingSize != -1)
501 WriteLine (".pack " + td.PackingSize);
502 if (td.ClassSize != -1)
503 WriteLine (".size " + td.ClassSize);
505 EmitGenParamCattrs (td);
506 EmitSecDeclarations (td);
507 foreach (var fd in td.Fields)
509 foreach (var md in td.Methods)
511 foreach (var p in td.Properties)
513 foreach (var e in td.Events)
515 foreach (var t in td.NestedTypes)
520 if (!td.IsNested && td.Namespace != null && td.Namespace != String.Empty) {
526 string StringifyFieldAttributes (FieldAttributes attrs) {
527 var sb = new StringBuilder ();
528 sb.Append (Map (field_access_map, (uint)(attrs & FieldAttributes.FieldAccessMask)));
529 sb.Append (MapFlags (field_flag_map, (uint)(attrs)));
530 return sb.ToString ();
533 void EmitField (FieldDefinition fd) {
534 var sb = new StringBuilder ();
535 sb.Append (".field ");
537 sb.Append ("[" + fd.Offset + "] ");
538 sb.Append (StringifyFieldAttributes (fd.Attributes));
539 if (fd.HasMarshalInfo) {
541 sb.Append (StringifyMarshalInfo (fd.MarshalInfo));
544 sb.Append (StringifyTypeRef (fd.FieldType));
546 sb.Append (EscapeName (fd.Name));
548 EmitConstant (fd.Constant, sb);
550 sb.Append (String.Format (" at D_{0:x8}", fd.RVA));
551 fields_with_rva.Add (fd);
553 WriteLine (sb.ToString ());
557 string StringifyMethodAttributes (MethodAttributes attrs) {
558 var sb = new StringBuilder ();
559 sb.Append (Map (method_access_map, (uint)(attrs & MethodAttributes.MemberAccessMask)));
560 sb.Append (MapFlags (method_flag_map, (uint)(attrs)));
561 return sb.ToString ();
564 string StringifyMethodImplAttributes (MethodImplAttributes attrs) {
565 var sb = new StringBuilder ();
566 sb.Append (Map (method_impl_map, (uint)(attrs & MethodImplAttributes.CodeTypeMask)));
567 sb.Append (Map (method_managed_map, (uint)(attrs & MethodImplAttributes.ManagedMask)));
568 sb.Append (MapFlags (method_impl_flag_map, (uint)(attrs)));
570 return sb.ToString ();
573 string StringifyTypeNameReflection (TypeReference t) {
574 if (t.MetadataType != MetadataType.Class)
575 throw new NotImplementedException ();
576 IMetadataScope s = t.Scope;
577 if (!(s is ModuleDefinition))
578 throw new NotImplementedException ();
579 return t.FullName.Replace ("/", "+");
582 string StringifyMarshalInfo (MarshalInfo mi) {
583 var sb = new StringBuilder ();
585 sb.Append ("marshal (");
588 switch (mi.NativeType) {
589 case NativeType.Array: {
590 var ami = (mi as ArrayMarshalInfo);
591 if (native_type_to_str.TryGetValue (ami.ElementType, out s)) {
595 //Console.WriteLine ("// XXX: " + ami.Size + " " + ami.SizeParameterIndex + " " + ami.SizeParameterMultiplier);
598 * Comments in metadata.c:
599 * So if (param_num == 0) && (num_elem > 0), then
600 * elem_mult == 0 -> the array size is num_elem
601 * elem_mult == 1 -> the array size is @param_num + num_elem
603 if (ami.Size != -1 && ami.Size != 0)
604 sb.Append (ami.Size.ToString ());
605 if (ami.SizeParameterMultiplier != 0 && ami.SizeParameterIndex != -1)
606 sb.Append ("+" + ami.SizeParameterIndex.ToString ());
610 case NativeType.FixedArray: {
611 var ami = (mi as FixedArrayMarshalInfo);
613 if (native_type_to_str.TryGetValue (ami.ElementType, out s)) {
617 sb.Append ("fixed array [" + ami.Size + "]");
620 case NativeType.FixedSysString: {
621 var ami = (mi as FixedSysStringMarshalInfo);
622 sb.Append ("fixed sysstring [" + ami.Size + "]");
625 case NativeType.SafeArray: {
626 var sami = (mi as SafeArrayMarshalInfo);
627 sb.Append ("safearray ");
628 switch (sami.ElementType) {
629 case VariantType.Variant:
630 sb.Append ("variant");
633 throw new NotImplementedException ();
637 case NativeType.CustomMarshaler: {
638 var cmi = (mi as CustomMarshalInfo);
640 if (cmi.Guid != Guid.Empty || cmi.UnmanagedType != String.Empty)
641 throw new NotImplementedException ();
642 sb.Append ("custom (\"" + StringifyTypeNameReflection (cmi.ManagedType) + "\", \"" + EscapeString (cmi.Cookie) + "\")");
646 if (native_type_to_str.TryGetValue (mi.NativeType, out s))
649 throw new NotImplementedException (mi.NativeType.ToString ());
653 return sb.ToString ();
656 string StringifySignature (MethodDefinition md) {
657 var sb = new StringBuilder ();
659 foreach (var par in md.Parameters) {
665 sb.Append ("[out] ");
667 sb.Append ("[opt] ");
668 sb.Append (StringifyTypeRef (par.ParameterType));
669 if (par.HasMarshalInfo) {
671 sb.Append (StringifyMarshalInfo (par.MarshalInfo));
674 sb.Append (EscapeName (par.Name));
678 return sb.ToString ();
681 string StringifyPInvokeAttrs (PInvokeAttributes attrs) {
682 var sb = new StringBuilder ();
683 sb.Append (Map (pinvoke_char_set_map, (uint)(attrs & PInvokeAttributes.CharSetMask)));
684 sb.Append (Map (pinvoke_cconv_map, (uint)(attrs & PInvokeAttributes.CallConvMask)));
685 sb.Append (MapFlags (pinvoke_flags_map, (uint)(attrs)));
686 return sb.ToString ();
689 string StringifyCallingConvention (MethodCallingConvention cconv) {
691 case MethodCallingConvention.Default:
693 case MethodCallingConvention.VarArg:
696 throw new NotImplementedException (cconv.ToString ());
700 void EmitMethod (MethodDefinition md) {
704 var pinvoke_sb = new StringBuilder ();
705 if ((uint)(md.Attributes & MethodAttributes.PInvokeImpl) != 0) {
706 var pinvoke = md.PInvokeInfo;
707 pinvoke_sb.Append ("pinvokeimpl (\"" + pinvoke.Module.Name + "\" as \"" + pinvoke.EntryPoint + "\" " + StringifyPInvokeAttrs (pinvoke.Attributes) + " )");
709 WriteLine (String.Format (".method {0}{1}", StringifyMethodAttributes (md.Attributes), pinvoke_sb));
711 var sb = new StringBuilder ();
714 sb.Append ("instance ");
715 // CallingConvention seems to be 32
716 sb.Append (StringifyCallingConvention ((MethodCallingConvention)((uint)md.CallingConvention & 0xf)));
718 sb.Append (StringifyTypeRef (md.ReturnType));
720 if (md.MethodReturnType.HasMarshalInfo) {
721 sb.Append (StringifyMarshalInfo (md.MethodReturnType.MarshalInfo));
724 sb.Append (EscapeName (md.Name));
725 if (md.HasGenericParameters)
726 EmitGenParams (md, sb);
727 WriteLine (String.Format ("{0} ({1}) {2}", sb, StringifySignature (md), StringifyMethodImplAttributes (md.ImplAttributes)));
730 foreach (var ov in md.Overrides)
731 WriteLine (".override method " + StringifyMethodRef (ov));
733 EmitGenParamCattrs (md);
734 EmitSecDeclarations (md);
736 foreach (var par in md.Parameters) {
737 if (par.HasCustomAttributes) {
738 WriteLine (".param [" + (idx + 1) + "]");
741 if (par.HasConstant) {
742 sb = new StringBuilder ();
743 EmitConstant (par.Constant, sb);
744 WriteLine (".param [" + (idx + 1) + "]" + sb);
748 // FIXME: Print RVA, code size
749 if (md == main.EntryPoint)
750 WriteLine (".entrypoint");
752 MethodBody body = md.Body;
753 WriteLine (".maxstack " + body.MaxStackSize);
755 WriteLine (".locals init (");
757 WriteLine (".locals (");
760 foreach (var v in body.Variables) {
761 WriteLine (StringifyTypeRef (v.VariableType) + " " + (v.Name == "" ? "V_" + v.Index : v.Name) + (vindex + 1 < body.Variables.Count ? ", " : ""));
767 List<ExceptionHandler> handlers = body.ExceptionHandlers.ToList ();
768 List<ExceptionHandler> reverse_handlers = body.ExceptionHandlers.Reverse ().ToList ();
770 var trys = new Dictionary<ExceptionHandler, bool> ();
771 if (handlers.Count > 0)
772 trys [handlers [0]] = true;
773 for (int i = 1; i < handlers.Count; ++i) {
774 trys [handlers [i]] = true;
775 for (int j = 0; j < i; ++j) {
776 if (handlers [i].TryStart == handlers [j].TryStart && handlers [i].TryEnd == handlers [j].TryEnd) {
777 trys [handlers [i]] = false;
784 var handler_to_idx = new Dictionary<ExceptionHandler, int> ();
785 foreach (ExceptionHandler eh in body.ExceptionHandlers) {
786 handler_to_idx [eh] = idx;
790 foreach (var ins in body.Instructions) {
791 foreach (var eh in handlers) {
792 if (eh.TryEnd == ins && trys [eh]) {
794 WriteLine ("} // end try " + handler_to_idx [eh]);
797 if (eh.HandlerEnd == ins) {
799 WriteLine ("} // end handler " + handler_to_idx [eh]);
803 foreach (var eh in reverse_handlers) {
804 if (eh.TryStart == ins && trys [eh]) {
805 WriteLine (".try { // " + handler_to_idx [eh]);
808 if (eh.HandlerStart == ins) {
809 string type_str = null;
810 switch (eh.HandlerType) {
811 case ExceptionHandlerType.Catch:
814 case ExceptionHandlerType.Finally:
815 type_str = "finally";
818 throw new NotImplementedException (eh.HandlerType.ToString ());
820 if (eh.CatchType == null)
821 WriteLine (type_str + " { // " + handler_to_idx [eh]);
823 WriteLine (type_str + " " + StringifyTypeRef (eh.CatchType) + " { // " + handler_to_idx [eh]);
828 WriteLine (StringifyIns (ins));
835 // Based on Instruction:ToString ()
836 public string StringifyIns (Instruction ins) {
837 var sb = new StringBuilder ();
839 AppendLabel (sb, ins);
842 sb.Append (ins.OpCode.Name);
844 if (ins.Operand == null)
845 return sb.ToString ();
849 object operand = ins.Operand;
850 switch (ins.OpCode.OperandType) {
851 case OperandType.ShortInlineBrTarget:
852 case OperandType.InlineBrTarget:
853 AppendLabel (sb, (Instruction) operand);
855 case OperandType.InlineSwitch:
856 var labels = (Instruction []) operand;
858 for (int i = 0; i < labels.Length; i++) {
862 AppendLabel (sb, labels [i]);
866 case OperandType.InlineString:
868 sb.Append (EscapeString ((string)operand));
872 if (operand is MethodReference) {
873 if (ins.OpCode == OpCodes.Ldtoken)
874 sb.Append ("method ");
875 sb.Append (StringifyMethodRef ((MethodReference)operand));
876 } else if (operand is TypeReference)
877 sb.Append (StringifyTypeRef ((TypeReference)operand));
878 else if (operand is VariableDefinition)
879 sb.Append (operand.ToString ());
880 else if (operand is FieldReference) {
881 if (ins.OpCode == OpCodes.Ldtoken)
882 sb.Append ("field ");
883 sb.Append (StringifyFieldRef ((FieldReference)operand));
884 } else if (operand is ParameterDefinition) {
885 var pd = (operand as ParameterDefinition);
886 sb.Append (pd.Index + (pd.Method.HasThis ? 1 : 0));
889 EmitConstantOperand (operand, sb);
894 return sb.ToString ();
897 static void AppendLabel (StringBuilder builder, Instruction instruction) {
898 builder.Append ("IL_");
899 builder.Append (instruction.Offset.ToString ("x4"));
902 void EmitProperty (PropertyDefinition p) {
905 var sb = new StringBuilder ();
906 sb.Append (".property ");
908 sb.Append ("instance ");
909 sb.Append (StringifyTypeRef (p.PropertyType));
911 sb.Append (EscapeName (p.Name));
914 foreach (var par in p.Parameters) {
917 sb.Append (StringifyTypeRef (par.ParameterType));
921 WriteLine (sb.ToString ());
925 if (p.SetMethod != null)
926 WriteLine (".set " + StringifyMethodRef (p.SetMethod));
927 if (p.GetMethod != null)
928 WriteLine (".get " + StringifyMethodRef (p.GetMethod));
929 if (p.HasOtherMethods)
930 throw new NotImplementedException ();
935 void EmitEvent (EventDefinition e) {
936 WriteLine (".event " + StringifyTypeRef (e.EventType) + " " + EscapeName (e.Name));
939 if (e.AddMethod != null)
940 WriteLine (".addon " + StringifyMethodRef (e.AddMethod));
941 if (e.RemoveMethod != null)
942 WriteLine (".removeon " + StringifyMethodRef (e.RemoveMethod));
943 foreach (var m in e.OtherMethods)
944 WriteLine (".other " + StringifyMethodRef (m));
950 foreach (var fd in fields_with_rva) {
951 WriteLine (String.Format (".data D_{0:x8} = bytearray (", fd.RVA));
952 WriteBlob (fd.InitialValue);
956 void EmitConstantOperand (object operand, StringBuilder sb) {
957 if (operand is double) {
958 double d = (double)operand;
960 //if (Double.IsNaN (d) || Double.IsInfinity (d)) {
962 byte[] b = DataConverter.GetBytesLE (d);
965 for (int i = 0; i < b.Length; ++i) {
968 sb.Append (String.Format ("{0:x2}", b [i]));
973 } else if (operand is float) {
974 float d = (float)operand;
976 //if (Single.IsNaN (d) || Single.IsInfinity (d)) {
978 byte[] b = DataConverter.GetBytesLE (d);
981 for (int i = 0; i < b.Length; ++i) {
984 sb.Append (String.Format ("{0:x2}", b [i]));
989 } else if (operand.GetType ().Assembly == typeof (int).Assembly)
990 sb.Append (operand.ToString ());
992 throw new NotImplementedException (operand.GetType ().ToString ());
995 void EmitConstant (object o, StringBuilder sb) {
997 sb.Append (String.Format (" = int8(0x{0:x2})", (byte)o));
999 sb.Append (String.Format (" = int8(0x{0:x2})", (sbyte)o));
1000 else if (o is short)
1001 sb.Append (String.Format (" = int16(0x{0:x4})", (short)o));
1002 else if (o is ushort)
1003 sb.Append (String.Format (" = int16(0x{0:x4})", (ushort)o));
1005 sb.Append (String.Format (" = int32(0x{0:x8})", (int)o));
1007 sb.Append (String.Format (" = int32(0x{0:x8})", (uint)o));
1009 sb.Append (String.Format (" = int64(0x{0:x8})", (long)o));
1010 else if (o is ulong)
1011 sb.Append (String.Format (" = int64(0x{0:x8})", (ulong)o));
1012 else if (o is string)
1013 sb.Append (String.Format (" = \"{0}\"", EscapeString ((string)o)));
1015 sb.Append (String.Format (" = bool({0})", (bool)o ? "true" : " false"));
1017 sb.Append (String.Format (" = char(0x{0:x4})", (int)(char)o));
1018 else if (o is double)
1020 sb.Append (String.Format (" = float64({0:f})", (double)o));
1021 else if (o is float)
1023 sb.Append (String.Format (" = float32({0:f})", (float)o));
1025 sb.Append ("= nullref");
1027 throw new NotImplementedException ("" + o.GetType ().ToString () + " " + o.ToString ());