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 void CompressCustomAttribute (CustomAttrib ca, MethodReference ctor, MemoryBinaryWriter writer)
129 m_sigWriter.Empty ();
130 Write (ca, ctor, writer);
133 public override void VisitMethodDefSig (MethodDefSig methodDef)
135 m_sigWriter.Write (methodDef.CallingConvention);
136 if (methodDef.GenericParameterCount > 0)
137 Write (methodDef.GenericParameterCount);
138 Write (methodDef.ParamCount);
139 Write (methodDef.RetType);
140 Write (methodDef.Parameters, methodDef.Sentinel);
143 public override void VisitMethodRefSig (MethodRefSig methodRef)
145 m_sigWriter.Write (methodRef.CallingConvention);
146 Write (methodRef.ParamCount);
147 Write (methodRef.RetType);
148 Write (methodRef.Parameters, methodRef.Sentinel);
151 public override void VisitFieldSig (FieldSig field)
153 m_sigWriter.Write (field.CallingConvention);
154 Write (field.CustomMods);
158 public override void VisitPropertySig (PropertySig property)
160 m_sigWriter.Write (property.CallingConvention);
161 Write (property.ParamCount);
162 Write (property.CustomMods);
163 Write (property.Type);
164 Write (property.Parameters);
167 public override void VisitLocalVarSig (LocalVarSig localvar)
169 m_sigWriter.Write (localvar.CallingConvention);
170 Write (localvar.Count);
171 Write (localvar.LocalVariables);
174 void Write (LocalVarSig.LocalVariable [] vars)
176 foreach (LocalVarSig.LocalVariable var in vars)
180 void Write (LocalVarSig.LocalVariable var)
182 Write (var.CustomMods);
183 if ((var.Constraint & Constraint.Pinned) != 0)
184 Write (ElementType.Pinned);
186 Write (ElementType.ByRef);
190 void Write (RetType retType)
192 Write (retType.CustomMods);
194 Write (ElementType.Void);
195 else if (retType.TypedByRef)
196 Write (ElementType.TypedByRef);
197 else if (retType.ByRef) {
198 Write (ElementType.ByRef);
199 Write (retType.Type);
201 Write (retType.Type);
204 void Write (Param [] parameters, int sentinel)
206 for (int i = 0; i < parameters.Length; i++) {
208 Write (ElementType.Sentinel);
210 Write (parameters [i]);
214 void Write (Param [] parameters)
216 foreach (Param p in parameters)
220 void Write (ElementType et)
225 void Write (SigType t)
227 Write ((int) t.ElementType);
229 switch (t.ElementType) {
230 case ElementType.ValueType :
231 Write ((int) Utilities.CompressMetadataToken (
232 CodedIndex.TypeDefOrRef, ((VALUETYPE) t).Type));
234 case ElementType.Class :
235 Write ((int) Utilities.CompressMetadataToken (
236 CodedIndex.TypeDefOrRef, ((CLASS) t).Type));
238 case ElementType.Ptr :
241 Write (ElementType.Void);
243 Write (p.CustomMods);
247 case ElementType.FnPtr :
248 FNPTR fp = (FNPTR) t;
249 if (fp.Method is MethodRefSig)
250 (fp.Method as MethodRefSig).Accept (this);
252 (fp.Method as MethodDefSig).Accept (this);
254 case ElementType.Array :
255 ARRAY ary = (ARRAY) t;
256 Write (ary.CustomMods);
257 ArrayShape shape = ary.Shape;
260 Write (shape.NumSizes);
261 foreach (int size in shape.Sizes)
263 Write (shape.NumLoBounds);
264 foreach (int loBound in shape.LoBounds)
267 case ElementType.SzArray :
268 SZARRAY sa = (SZARRAY) t;
269 Write (sa.CustomMods);
272 case ElementType.Var :
273 Write (((VAR) t).Index);
275 case ElementType.MVar :
276 Write (((MVAR) t).Index);
278 case ElementType.GenericInst :
279 GENERICINST gi = t as GENERICINST;
280 Write (gi.ValueType ? ElementType.ValueType : ElementType.Class);
281 Write ((int) Utilities.CompressMetadataToken (
282 CodedIndex.TypeDefOrRef, gi.Type));
283 Write (gi.Signature);
288 void Write (TypeSpec ts)
293 void Write (MethodSpec ms)
296 Write (ms.Signature);
299 void Write (GenericInstSignature gis)
302 for (int i = 0; i < gis.Arity; i++)
303 Write (gis.Types [i]);
306 void Write (GenericArg arg)
308 Write (arg.CustomMods);
314 Write (p.CustomMods);
316 Write (ElementType.TypedByRef);
318 Write (ElementType.ByRef);
324 void Write (CustomMod [] customMods)
326 foreach (CustomMod cm in customMods)
330 void Write (CustomMod cm)
333 case CustomMod.CMODType.OPT :
334 Write (ElementType.CModOpt);
336 case CustomMod.CMODType.REQD :
337 Write (ElementType.CModReqD);
341 Write ((int) Utilities.CompressMetadataToken (
342 CodedIndex.TypeDefOrRef, cm.TypeDefOrRef));
345 void Write (MarshalSig ms)
347 Write ((int) ms.NativeInstrinsic);
348 switch (ms.NativeInstrinsic) {
349 case NativeType.ARRAY :
350 MarshalSig.Array ar = (MarshalSig.Array) ms.Spec;
351 Write ((int) ar.ArrayElemType);
352 if (ar.ParamNum != -1)
354 if (ar.NumElem != -1)
356 if (ar.ElemMult != -1)
359 case NativeType.CUSTOMMARSHALER :
360 MarshalSig.CustomMarshaler cm = (MarshalSig.CustomMarshaler) ms.Spec;
362 Write (cm.UnmanagedType);
363 Write (cm.ManagedType);
366 case NativeType.FIXEDARRAY :
367 MarshalSig.FixedArray fa = (MarshalSig.FixedArray) ms.Spec;
369 if (fa.ArrayElemType != NativeType.NONE)
370 Write ((int) fa.ArrayElemType);
372 case NativeType.SAFEARRAY :
373 Write ((int) ((MarshalSig.SafeArray) ms.Spec).ArrayElemType);
375 case NativeType.FIXEDSYSSTRING :
376 Write (((MarshalSig.FixedSysString) ms.Spec).Size);
381 void Write (CustomAttrib ca, MethodReference ctor, MemoryBinaryWriter writer)
386 if (ca.Prolog != CustomAttrib.StdProlog)
389 writer.Write (ca.Prolog);
391 for (int i = 0; i < ctor.Parameters.Count; i++)
392 Write (ca.FixedArgs [i], writer);
394 writer.Write (ca.NumNamed);
396 for (int i = 0; i < ca.NumNamed; i++)
397 Write (ca.NamedArgs [i], writer);
400 void Write (CustomAttrib.FixedArg fa, MemoryBinaryWriter writer)
403 writer.Write (fa.NumElem);
405 foreach (CustomAttrib.Elem elem in fa.Elems)
406 Write (elem, writer);
409 void Write (CustomAttrib.NamedArg na, MemoryBinaryWriter writer)
412 writer.Write ((byte) 0x53);
413 else if (na.Property)
414 writer.Write ((byte) 0x54);
416 throw new MetadataFormatException ("Unknown kind of namedarg");
418 if (na.FixedArg.SzArray)
419 writer.Write ((byte) ElementType.SzArray);
421 if (na.FieldOrPropType == ElementType.Object)
422 writer.Write ((byte) ElementType.Boxed);
424 writer.Write ((byte) na.FieldOrPropType);
426 if (na.FieldOrPropType == ElementType.Enum)
427 Write (na.FixedArg.Elems [0].ElemType.FullName);
429 Write (na.FieldOrPropName);
431 Write (na.FixedArg, writer);
434 void Write (CustomAttrib.Elem elem, MemoryBinaryWriter writer) // TODO
437 elem.FieldOrPropType = ElementType.String;
439 elem.FieldOrPropType = ElementType.Type;
440 else if (elem.BoxedValueType)
441 Write (elem.FieldOrPropType);
443 switch (elem.FieldOrPropType) {
444 case ElementType.Boolean :
445 writer.Write ((byte) ((bool) elem.Value ? 1 : 0));
447 case ElementType.Char :
448 writer.Write ((ushort) (char) elem.Value);
450 case ElementType.R4 :
451 writer.Write ((float) elem.Value);
453 case ElementType.R8 :
454 writer.Write ((double) elem.Value);
456 case ElementType.I1 :
457 writer.Write ((sbyte) elem.Value);
459 case ElementType.I2 :
460 writer.Write ((short) elem.Value);
462 case ElementType.I4 :
463 writer.Write ((int) elem.Value);
465 case ElementType.I8 :
466 writer.Write ((long) elem.Value);
468 case ElementType.U1 :
469 writer.Write ((byte) elem.Value);
471 case ElementType.U2 :
472 writer.Write ((ushort) elem.Value);
474 case ElementType.U4 :
475 writer.Write ((uint) elem.Value);
477 case ElementType.U8 :
478 writer.Write ((long) elem.Value);
480 case ElementType.String :
481 case ElementType.Type :
482 string s = elem.Value as string;
484 writer.Write ((byte) 0xff);
485 else if (s.Length == 0)
486 writer.Write ((byte) 0x00);
490 case ElementType.Object :
491 if (elem.Value != null)
492 throw new NotSupportedException ("Unknown state");
493 writer.Write ((byte) 0xff);
496 throw new NotImplementedException ("WriteElem " + elem.FieldOrPropType.ToString ());
500 void Write (string s)
502 byte [] str = Encoding.UTF8.GetBytes (s);
504 m_sigWriter.Write (str);
509 Utilities.WriteCompressedInteger (m_sigWriter, i);