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);