5 // Jb Evain (jbevain@gmail.com)
7 // (C) 2005 - 2007 Jb Evain
9 // Permission is hereby granted, free of charge, to any person obtaining
10 // a copy of this software and associated documentation files (the
11 // "Software"), to deal in the Software without restriction, including
12 // without limitation the rights to use, copy, modify, merge, publish,
13 // distribute, sublicense, and/or sell copies of the Software, and to
14 // permit persons to whom the Software is furnished to do so, subject to
15 // the following conditions:
17 // The above copyright notice and this permission notice shall be
18 // included in all copies or substantial portions of the Software.
20 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
24 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
29 namespace Mono.Cecil.Signatures {
35 using Mono.Cecil.Binary;
36 using Mono.Cecil.Metadata;
38 internal sealed class SignatureWriter : BaseSignatureVisitor {
40 MetadataWriter m_mdWriter;
41 MemoryBinaryWriter m_sigWriter;
43 public SignatureWriter (MetadataWriter mdWriter)
45 m_mdWriter = mdWriter;
46 m_sigWriter = new MemoryBinaryWriter ();
51 return m_mdWriter.AddBlob (m_sigWriter.ToArray ());
54 public uint AddMethodDefSig (MethodDefSig methSig)
56 return AddSignature (methSig);
59 public uint AddMethodRefSig (MethodRefSig methSig)
61 return AddSignature (methSig);
64 public uint AddPropertySig (PropertySig ps)
66 return AddSignature (ps);
69 public uint AddFieldSig (FieldSig fSig)
71 return AddSignature (fSig);
74 public uint AddLocalVarSig (LocalVarSig lvs)
76 return AddSignature (lvs);
79 uint AddSignature (Signature s)
86 public uint AddTypeSpec (TypeSpec ts)
93 public uint AddMethodSpec (MethodSpec ms)
100 public uint AddMarshalSig (MarshalSig ms)
102 m_sigWriter.Empty ();
104 return GetPointer ();
107 public uint AddCustomAttribute (CustomAttrib ca, MethodReference ctor)
109 CompressCustomAttribute (ca, ctor, m_sigWriter);
110 return GetPointer ();
113 public byte [] CompressCustomAttribute (CustomAttrib ca, MethodReference ctor)
115 MemoryBinaryWriter writer = new MemoryBinaryWriter ();
116 CompressCustomAttribute (ca, ctor, writer);
117 return writer.ToArray ();
120 public byte [] CompressFieldSig (FieldSig field)
122 m_sigWriter.Empty ();
123 VisitFieldSig (field);
124 return m_sigWriter.ToArray ();
127 public byte [] CompressLocalVar (LocalVarSig.LocalVariable var)
129 m_sigWriter.Empty ();
131 return m_sigWriter.ToArray ();
134 void CompressCustomAttribute (CustomAttrib ca, MethodReference ctor, MemoryBinaryWriter writer)
136 m_sigWriter.Empty ();
137 Write (ca, ctor, writer);
140 public override void VisitMethodDefSig (MethodDefSig methodDef)
142 m_sigWriter.Write (methodDef.CallingConvention);
143 if (methodDef.GenericParameterCount > 0)
144 Write (methodDef.GenericParameterCount);
145 Write (methodDef.ParamCount);
146 Write (methodDef.RetType);
147 Write (methodDef.Parameters, methodDef.Sentinel);
150 public override void VisitMethodRefSig (MethodRefSig methodRef)
152 m_sigWriter.Write (methodRef.CallingConvention);
153 Write (methodRef.ParamCount);
154 Write (methodRef.RetType);
155 Write (methodRef.Parameters, methodRef.Sentinel);
158 public override void VisitFieldSig (FieldSig field)
160 m_sigWriter.Write (field.CallingConvention);
161 Write (field.CustomMods);
165 public override void VisitPropertySig (PropertySig property)
167 m_sigWriter.Write (property.CallingConvention);
168 Write (property.ParamCount);
169 Write (property.CustomMods);
170 Write (property.Type);
171 Write (property.Parameters);
174 public override void VisitLocalVarSig (LocalVarSig localvar)
176 m_sigWriter.Write (localvar.CallingConvention);
177 Write (localvar.Count);
178 Write (localvar.LocalVariables);
181 void Write (LocalVarSig.LocalVariable [] vars)
183 foreach (LocalVarSig.LocalVariable var in vars)
187 void Write (LocalVarSig.LocalVariable var)
189 Write (var.CustomMods);
190 if ((var.Constraint & Constraint.Pinned) != 0)
191 Write (ElementType.Pinned);
193 Write (ElementType.ByRef);
197 void Write (RetType retType)
199 Write (retType.CustomMods);
201 Write (ElementType.Void);
202 else if (retType.TypedByRef)
203 Write (ElementType.TypedByRef);
204 else if (retType.ByRef) {
205 Write (ElementType.ByRef);
206 Write (retType.Type);
208 Write (retType.Type);
211 void Write (Param [] parameters, int sentinel)
213 for (int i = 0; i < parameters.Length; i++) {
215 Write (ElementType.Sentinel);
217 Write (parameters [i]);
221 void Write (Param [] parameters)
223 foreach (Param p in parameters)
227 void Write (ElementType et)
232 void Write (SigType t)
234 Write ((int) t.ElementType);
236 switch (t.ElementType) {
237 case ElementType.ValueType :
238 Write ((int) Utilities.CompressMetadataToken (
239 CodedIndex.TypeDefOrRef, ((VALUETYPE) t).Type));
241 case ElementType.Class :
242 Write ((int) Utilities.CompressMetadataToken (
243 CodedIndex.TypeDefOrRef, ((CLASS) t).Type));
245 case ElementType.Ptr :
248 Write (ElementType.Void);
250 Write (p.CustomMods);
254 case ElementType.FnPtr :
255 FNPTR fp = (FNPTR) t;
256 if (fp.Method is MethodRefSig)
257 (fp.Method as MethodRefSig).Accept (this);
259 (fp.Method as MethodDefSig).Accept (this);
261 case ElementType.Array :
262 ARRAY ary = (ARRAY) t;
263 Write (ary.CustomMods);
264 ArrayShape shape = ary.Shape;
267 Write (shape.NumSizes);
268 foreach (int size in shape.Sizes)
270 Write (shape.NumLoBounds);
271 foreach (int loBound in shape.LoBounds)
274 case ElementType.SzArray :
275 SZARRAY sa = (SZARRAY) t;
276 Write (sa.CustomMods);
279 case ElementType.Var :
280 Write (((VAR) t).Index);
282 case ElementType.MVar :
283 Write (((MVAR) t).Index);
285 case ElementType.GenericInst :
286 GENERICINST gi = t as GENERICINST;
287 Write (gi.ValueType ? ElementType.ValueType : ElementType.Class);
288 Write ((int) Utilities.CompressMetadataToken (
289 CodedIndex.TypeDefOrRef, gi.Type));
290 Write (gi.Signature);
295 void Write (TypeSpec ts)
297 Write (ts.CustomMods);
301 void Write (MethodSpec ms)
304 Write (ms.Signature);
307 void Write (GenericInstSignature gis)
310 for (int i = 0; i < gis.Arity; i++)
311 Write (gis.Types [i]);
314 void Write (GenericArg arg)
316 Write (arg.CustomMods);
322 Write (p.CustomMods);
324 Write (ElementType.TypedByRef);
326 Write (ElementType.ByRef);
332 void Write (CustomMod [] customMods)
334 foreach (CustomMod cm in customMods)
338 void Write (CustomMod cm)
341 case CustomMod.CMODType.OPT :
342 Write (ElementType.CModOpt);
344 case CustomMod.CMODType.REQD :
345 Write (ElementType.CModReqD);
349 Write ((int) Utilities.CompressMetadataToken (
350 CodedIndex.TypeDefOrRef, cm.TypeDefOrRef));
353 void Write (MarshalSig ms)
355 Write ((int) ms.NativeInstrinsic);
356 switch (ms.NativeInstrinsic) {
357 case NativeType.ARRAY :
358 MarshalSig.Array ar = (MarshalSig.Array) ms.Spec;
359 Write ((int) ar.ArrayElemType);
360 if (ar.ParamNum != -1)
362 if (ar.NumElem != -1)
364 if (ar.ElemMult != -1)
367 case NativeType.CUSTOMMARSHALER :
368 MarshalSig.CustomMarshaler cm = (MarshalSig.CustomMarshaler) ms.Spec;
370 Write (cm.UnmanagedType);
371 Write (cm.ManagedType);
374 case NativeType.FIXEDARRAY :
375 MarshalSig.FixedArray fa = (MarshalSig.FixedArray) ms.Spec;
377 if (fa.ArrayElemType != NativeType.NONE)
378 Write ((int) fa.ArrayElemType);
380 case NativeType.SAFEARRAY :
381 Write ((int) ((MarshalSig.SafeArray) ms.Spec).ArrayElemType);
383 case NativeType.FIXEDSYSSTRING :
384 Write (((MarshalSig.FixedSysString) ms.Spec).Size);
389 void Write (CustomAttrib ca, MethodReference ctor, MemoryBinaryWriter writer)
394 if (ca.Prolog != CustomAttrib.StdProlog)
397 writer.Write (ca.Prolog);
399 for (int i = 0; i < ctor.Parameters.Count; i++)
400 Write (ca.FixedArgs [i], writer);
402 writer.Write (ca.NumNamed);
404 for (int i = 0; i < ca.NumNamed; i++)
405 Write (ca.NamedArgs [i], writer);
408 void Write (CustomAttrib.FixedArg fa, MemoryBinaryWriter writer)
411 writer.Write (fa.NumElem);
413 foreach (CustomAttrib.Elem elem in fa.Elems)
414 Write (elem, writer);
417 static string GetEnumFullName (TypeReference type)
419 string fullname = type.FullName;
422 fullname = fullname.Replace ('/', '+');
424 if (type is TypeDefinition)
427 return string.Concat (fullname, ", ", type.Module.Assembly.Name.FullName);
430 void Write (CustomAttrib.NamedArg na, MemoryBinaryWriter writer)
433 writer.Write ((byte) 0x53);
434 else if (na.Property)
435 writer.Write ((byte) 0x54);
437 throw new MetadataFormatException ("Unknown kind of namedarg");
439 if (na.FieldOrPropType == ElementType.Class)
440 na.FieldOrPropType = ElementType.Enum;
442 if (na.FixedArg.SzArray)
443 writer.Write ((byte) ElementType.SzArray);
445 if (na.FieldOrPropType == ElementType.Object)
446 writer.Write ((byte) ElementType.Boxed);
448 writer.Write ((byte) na.FieldOrPropType);
450 if (na.FieldOrPropType == ElementType.Enum)
451 Write (GetEnumFullName (na.FixedArg.Elems [0].ElemType));
453 Write (na.FieldOrPropName);
455 Write (na.FixedArg, writer);
458 static ElementType GetElementTypeFromTypeCode (TypeCode tc)
462 return ElementType.U1;
464 return ElementType.I1;
466 return ElementType.I2;
467 case TypeCode.UInt16:
468 return ElementType.U2;
470 return ElementType.I4;
471 case TypeCode.UInt32:
472 return ElementType.U4;
474 return ElementType.I8;
475 case TypeCode.UInt64:
476 return ElementType.U8;
478 throw new ArgumentException ("tc");
482 void Write (CustomAttrib.Elem elem, MemoryBinaryWriter writer)
485 elem.FieldOrPropType = ElementType.String;
487 elem.FieldOrPropType = ElementType.Type;
489 if (elem.FieldOrPropType == ElementType.Class) // an enum in fact
490 elem.FieldOrPropType = GetElementTypeFromTypeCode (Type.GetTypeCode (elem.Value.GetType ()));
492 if (elem.BoxedValueType)
493 Write (elem.FieldOrPropType);
495 switch (elem.FieldOrPropType) {
496 case ElementType.Boolean :
497 writer.Write ((byte) ((bool) elem.Value ? 1 : 0));
499 case ElementType.Char :
500 writer.Write ((ushort) (char) elem.Value);
502 case ElementType.R4 :
503 writer.Write ((float) elem.Value);
505 case ElementType.R8 :
506 writer.Write ((double) elem.Value);
508 case ElementType.I1 :
509 writer.Write ((sbyte) elem.Value);
511 case ElementType.I2 :
512 writer.Write ((short) elem.Value);
514 case ElementType.I4 :
515 writer.Write ((int) elem.Value);
517 case ElementType.I8 :
518 writer.Write ((long) elem.Value);
520 case ElementType.U1 :
521 writer.Write ((byte) elem.Value);
523 case ElementType.U2 :
524 writer.Write ((ushort) elem.Value);
526 case ElementType.U4 :
527 writer.Write ((uint) elem.Value);
529 case ElementType.U8 :
530 writer.Write ((ulong) elem.Value);
532 case ElementType.String :
533 case ElementType.Type :
534 string s = elem.Value as string;
536 writer.Write ((byte) 0xff);
537 else if (s.Length == 0)
538 writer.Write ((byte) 0x00);
542 case ElementType.Object :
543 if (elem.Value != null)
544 throw new NotSupportedException ("Unknown state");
545 writer.Write ((byte) 0xff);
548 throw new NotImplementedException ("WriteElem " + elem.FieldOrPropType.ToString ());
552 void Write (string s)
554 byte [] str = Encoding.UTF8.GetBytes (s);
556 m_sigWriter.Write (str);
561 Utilities.WriteCompressedInteger (m_sigWriter, i);