~ubuntu-branches/ubuntu/trusty/monodevelop/trusty-proposed

« back to all changes in this revision

Viewing changes to external/mono-addins/Mono.Addins.CecilReflector/Mono.Cecil/Mono.Cecil.Cil/CodeWriter.cs

  • Committer: Package Import Robot
  • Author(s): Jo Shields
  • Date: 2013-05-12 09:46:03 UTC
  • mto: This revision was merged to the branch mainline in revision 29.
  • Revision ID: package-import@ubuntu.com-20130512094603-mad323bzcxvmcam0
Tags: upstream-4.0.5+dfsg
ImportĀ upstreamĀ versionĀ 4.0.5+dfsg

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
//
 
2
// CodeWriter.cs
 
3
//
 
4
// Author:
 
5
//   Jb Evain (jbevain@gmail.com)
 
6
//
 
7
// Copyright (c) 2008 - 2010 Jb Evain
 
8
//
 
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:
 
16
//
 
17
// The above copyright notice and this permission notice shall be
 
18
// included in all copies or substantial portions of the Software.
 
19
//
 
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.
 
27
//
 
28
 
 
29
using System;
 
30
using System.Collections.Generic;
 
31
 
 
32
using Mono.Collections.Generic;
 
33
 
 
34
using Mono.Cecil.Metadata;
 
35
using Mono.Cecil.PE;
 
36
 
 
37
using RVA = System.UInt32;
 
38
 
 
39
#if !READ_ONLY
 
40
 
 
41
namespace Mono.Cecil.Cil {
 
42
 
 
43
        sealed class CodeWriter : ByteBuffer {
 
44
 
 
45
                readonly RVA code_base;
 
46
                internal readonly MetadataBuilder metadata;
 
47
                readonly Dictionary<uint, MetadataToken> standalone_signatures;
 
48
 
 
49
                RVA current;
 
50
                MethodBody body;
 
51
 
 
52
                public CodeWriter (MetadataBuilder metadata)
 
53
                        : base (0)
 
54
                {
 
55
                        this.code_base = metadata.text_map.GetNextRVA (TextSegment.CLIHeader);
 
56
                        this.current = code_base;
 
57
                        this.metadata = metadata;
 
58
                        this.standalone_signatures = new Dictionary<uint, MetadataToken> ();
 
59
                }
 
60
 
 
61
                public RVA WriteMethodBody (MethodDefinition method)
 
62
                {
 
63
                        var rva = BeginMethod ();
 
64
 
 
65
                        if (IsUnresolved (method)) {
 
66
                                if (method.rva == 0)
 
67
                                        return 0;
 
68
 
 
69
                                WriteUnresolvedMethodBody (method);
 
70
                        } else {
 
71
                                if (IsEmptyMethodBody (method.Body))
 
72
                                        return 0;
 
73
 
 
74
                                WriteResolvedMethodBody (method);
 
75
                        }
 
76
 
 
77
                        Align (4);
 
78
 
 
79
                        EndMethod ();
 
80
                        return rva;
 
81
                }
 
82
 
 
83
                static bool IsEmptyMethodBody (MethodBody body)
 
84
                {
 
85
                        return body.instructions.IsNullOrEmpty ()
 
86
                                && body.variables.IsNullOrEmpty ();
 
87
                }
 
88
 
 
89
                static bool IsUnresolved (MethodDefinition method)
 
90
                {
 
91
                        return method.HasBody && method.HasImage && method.body == null;
 
92
                }
 
93
 
 
94
                void WriteUnresolvedMethodBody (MethodDefinition method)
 
95
                {
 
96
                        var code_reader = metadata.module.Read (method, (_, reader) => reader.code);
 
97
 
 
98
                        MethodSymbols symbols;
 
99
                        var buffer = code_reader.PatchRawMethodBody (method, this, out symbols);
 
100
 
 
101
                        WriteBytes (buffer);
 
102
 
 
103
                        if (symbols.instructions.IsNullOrEmpty ())
 
104
                                return;
 
105
 
 
106
                        symbols.method_token = method.token;
 
107
                        symbols.local_var_token = GetLocalVarToken (buffer, symbols);
 
108
 
 
109
                        var symbol_writer = metadata.symbol_writer;
 
110
                        if (symbol_writer != null)
 
111
                                symbol_writer.Write (symbols);
 
112
                }
 
113
 
 
114
                static MetadataToken GetLocalVarToken (ByteBuffer buffer, MethodSymbols symbols)
 
115
                {
 
116
                        if (symbols.variables.IsNullOrEmpty ())
 
117
                                return MetadataToken.Zero;
 
118
 
 
119
                        buffer.position = 8;
 
120
                        return new MetadataToken (buffer.ReadUInt32 ());
 
121
                }
 
122
 
 
123
                void WriteResolvedMethodBody (MethodDefinition method)
 
124
                {
 
125
                        body = method.Body;
 
126
                        ComputeHeader ();
 
127
                        if (RequiresFatHeader ())
 
128
                                WriteFatHeader ();
 
129
                        else
 
130
                                WriteByte ((byte) (0x2 | (body.CodeSize << 2))); // tiny
 
131
 
 
132
                        WriteInstructions ();
 
133
 
 
134
                        if (body.HasExceptionHandlers)
 
135
                                WriteExceptionHandlers ();
 
136
 
 
137
                        var symbol_writer = metadata.symbol_writer;
 
138
                        if (symbol_writer != null)
 
139
                                symbol_writer.Write (body);
 
140
                }
 
141
 
 
142
                void WriteFatHeader ()
 
143
                {
 
144
                        var body = this.body;
 
145
                        byte flags = 0x3;       // fat
 
146
                        if (body.InitLocals)
 
147
                                flags |= 0x10;  // init locals
 
148
                        if (body.HasExceptionHandlers)
 
149
                                flags |= 0x8;   // more sections
 
150
 
 
151
                        WriteByte (flags);
 
152
                        WriteByte (0x30);
 
153
                        WriteInt16 ((short) body.max_stack_size);
 
154
                        WriteInt32 (body.code_size);
 
155
                        body.local_var_token = body.HasVariables
 
156
                                ? GetStandAloneSignature (body.Variables)
 
157
                                : MetadataToken.Zero;
 
158
                        WriteMetadataToken (body.local_var_token);
 
159
                }
 
160
 
 
161
                void WriteInstructions ()
 
162
                {
 
163
                        var instructions = body.Instructions;
 
164
                        var items = instructions.items;
 
165
                        var size = instructions.size;
 
166
 
 
167
                        for (int i = 0; i < size; i++) {
 
168
                                var instruction = items [i];
 
169
                                WriteOpCode (instruction.opcode);
 
170
                                WriteOperand (instruction);
 
171
                        }
 
172
                }
 
173
 
 
174
                void WriteOpCode (OpCode opcode)
 
175
                {
 
176
                        if (opcode.Size == 1) {
 
177
                                WriteByte (opcode.Op2);
 
178
                        } else {
 
179
                                WriteByte (opcode.Op1);
 
180
                                WriteByte (opcode.Op2);
 
181
                        }
 
182
                }
 
183
 
 
184
                void WriteOperand (Instruction instruction)
 
185
                {
 
186
                        var opcode = instruction.opcode;
 
187
                        var operand_type = opcode.OperandType;
 
188
                        if (operand_type == OperandType.InlineNone)
 
189
                                return;
 
190
 
 
191
                        var operand = instruction.operand;
 
192
                        if (operand == null)
 
193
                                throw new ArgumentException ();
 
194
 
 
195
                        switch (operand_type) {
 
196
                        case OperandType.InlineSwitch: {
 
197
                                var targets = (Instruction []) operand;
 
198
                                WriteInt32 (targets.Length);
 
199
                                var diff = instruction.Offset + opcode.Size + (4 * (targets.Length + 1));
 
200
                                for (int i = 0; i < targets.Length; i++)
 
201
                                        WriteInt32 (GetTargetOffset (targets [i]) - diff);
 
202
                                break;
 
203
                        }
 
204
                        case OperandType.ShortInlineBrTarget: {
 
205
                                var target = (Instruction) operand;
 
206
                                WriteSByte ((sbyte) (GetTargetOffset (target) - (instruction.Offset + opcode.Size + 1)));
 
207
                                break;
 
208
                        }
 
209
                        case OperandType.InlineBrTarget: {
 
210
                                var target = (Instruction) operand;
 
211
                                WriteInt32 (GetTargetOffset (target) - (instruction.Offset + opcode.Size + 4));
 
212
                                break;
 
213
                        }
 
214
                        case OperandType.ShortInlineVar:
 
215
                                WriteByte ((byte) GetVariableIndex ((VariableDefinition) operand));
 
216
                                break;
 
217
                        case OperandType.ShortInlineArg:
 
218
                                WriteByte ((byte) GetParameterIndex ((ParameterDefinition) operand));
 
219
                                break;
 
220
                        case OperandType.InlineVar:
 
221
                                WriteInt16 ((short) GetVariableIndex ((VariableDefinition) operand));
 
222
                                break;
 
223
                        case OperandType.InlineArg:
 
224
                                WriteInt16 ((short) GetParameterIndex ((ParameterDefinition) operand));
 
225
                                break;
 
226
                        case OperandType.InlineSig:
 
227
                                WriteMetadataToken (GetStandAloneSignature ((CallSite) operand));
 
228
                                break;
 
229
                        case OperandType.ShortInlineI:
 
230
                                if (opcode == OpCodes.Ldc_I4_S)
 
231
                                        WriteSByte ((sbyte) operand);
 
232
                                else
 
233
                                        WriteByte ((byte) operand);
 
234
                                break;
 
235
                        case OperandType.InlineI:
 
236
                                WriteInt32 ((int) operand);
 
237
                                break;
 
238
                        case OperandType.InlineI8:
 
239
                                WriteInt64 ((long) operand);
 
240
                                break;
 
241
                        case OperandType.ShortInlineR:
 
242
                                WriteSingle ((float) operand);
 
243
                                break;
 
244
                        case OperandType.InlineR:
 
245
                                WriteDouble ((double) operand);
 
246
                                break;
 
247
                        case OperandType.InlineString:
 
248
                                WriteMetadataToken (
 
249
                                        new MetadataToken (
 
250
                                                TokenType.String,
 
251
                                                GetUserStringIndex ((string) operand)));
 
252
                                break;
 
253
                        case OperandType.InlineType:
 
254
                        case OperandType.InlineField:
 
255
                        case OperandType.InlineMethod:
 
256
                        case OperandType.InlineTok:
 
257
                                WriteMetadataToken (metadata.LookupToken ((IMetadataTokenProvider) operand));
 
258
                                break;
 
259
                        default:
 
260
                                throw new ArgumentException ();
 
261
                        }
 
262
                }
 
263
 
 
264
                int GetTargetOffset (Instruction instruction)
 
265
                {
 
266
                        if (instruction == null) {
 
267
                                var last = body.instructions [body.instructions.size - 1];
 
268
                                return last.offset + last.GetSize ();
 
269
                        }
 
270
 
 
271
                        return instruction.offset;
 
272
                }
 
273
 
 
274
                uint GetUserStringIndex (string @string)
 
275
                {
 
276
                        if (@string == null)
 
277
                                return 0;
 
278
 
 
279
                        return metadata.user_string_heap.GetStringIndex (@string);
 
280
                }
 
281
 
 
282
                static int GetVariableIndex (VariableDefinition variable)
 
283
                {
 
284
                        return variable.Index;
 
285
                }
 
286
 
 
287
                int GetParameterIndex (ParameterDefinition parameter)
 
288
                {
 
289
                        if (body.method.HasThis) {
 
290
                                if (parameter == body.this_parameter)
 
291
                                        return 0;
 
292
 
 
293
                                return parameter.Index + 1;
 
294
                        }
 
295
 
 
296
                        return parameter.Index;
 
297
                }
 
298
 
 
299
                bool RequiresFatHeader ()
 
300
                {
 
301
                        var body = this.body;
 
302
                        return body.CodeSize >= 64
 
303
                                || body.InitLocals
 
304
                                || body.HasVariables
 
305
                                || body.HasExceptionHandlers
 
306
                                || body.MaxStackSize > 8;
 
307
                }
 
308
 
 
309
                void ComputeHeader ()
 
310
                {
 
311
                        int offset = 0;
 
312
                        var instructions = body.instructions;
 
313
                        var items = instructions.items;
 
314
                        var count = instructions.size;
 
315
                        var stack_size = 0;
 
316
                        var max_stack = 0;
 
317
                        Dictionary<Instruction, int> stack_sizes = null;
 
318
 
 
319
                        if (body.HasExceptionHandlers)
 
320
                                ComputeExceptionHandlerStackSize (ref stack_sizes);
 
321
 
 
322
                        for (int i = 0; i < count; i++) {
 
323
                                var instruction = items [i];
 
324
                                instruction.offset = offset;
 
325
                                offset += instruction.GetSize ();
 
326
 
 
327
                                ComputeStackSize (instruction, ref stack_sizes, ref stack_size, ref max_stack);
 
328
                        }
 
329
 
 
330
                        body.code_size = offset;
 
331
                        body.max_stack_size = max_stack;
 
332
                }
 
333
 
 
334
                void ComputeExceptionHandlerStackSize (ref Dictionary<Instruction, int> stack_sizes)
 
335
                {
 
336
                        var exception_handlers = body.ExceptionHandlers;
 
337
 
 
338
                        for (int i = 0; i < exception_handlers.Count; i++) {
 
339
                                var exception_handler = exception_handlers [i];
 
340
 
 
341
                                switch (exception_handler.HandlerType) {
 
342
                                case ExceptionHandlerType.Catch:
 
343
                                        AddExceptionStackSize (exception_handler.HandlerStart, ref stack_sizes);
 
344
                                        break;
 
345
                                case ExceptionHandlerType.Filter:
 
346
                                        AddExceptionStackSize (exception_handler.FilterStart, ref stack_sizes);
 
347
                                        AddExceptionStackSize (exception_handler.HandlerStart, ref stack_sizes);
 
348
                                        break;
 
349
                                }
 
350
                        }
 
351
                }
 
352
 
 
353
                static void AddExceptionStackSize (Instruction handler_start, ref Dictionary<Instruction, int> stack_sizes)
 
354
                {
 
355
                        if (handler_start == null)
 
356
                                return;
 
357
 
 
358
                        if (stack_sizes == null)
 
359
                                stack_sizes = new Dictionary<Instruction, int> ();
 
360
 
 
361
                        stack_sizes [handler_start] = 1;
 
362
                }
 
363
 
 
364
                static void ComputeStackSize (Instruction instruction, ref Dictionary<Instruction, int> stack_sizes, ref int stack_size, ref int max_stack)
 
365
                {
 
366
                        int computed_size;
 
367
                        if (stack_sizes != null && stack_sizes.TryGetValue (instruction, out computed_size))
 
368
                                stack_size = computed_size;
 
369
 
 
370
                        max_stack = System.Math.Max (max_stack, stack_size);
 
371
                        ComputeStackDelta (instruction, ref stack_size);
 
372
                        max_stack = System.Math.Max (max_stack, stack_size);
 
373
 
 
374
                        CopyBranchStackSize (instruction, ref stack_sizes, stack_size);
 
375
                        ComputeStackSize (instruction, ref stack_size);
 
376
                }
 
377
 
 
378
                static void CopyBranchStackSize (Instruction instruction, ref Dictionary<Instruction, int> stack_sizes, int stack_size)
 
379
                {
 
380
                        if (stack_size == 0)
 
381
                                return;
 
382
 
 
383
                        switch (instruction.opcode.OperandType) {
 
384
                        case OperandType.ShortInlineBrTarget:
 
385
                        case OperandType.InlineBrTarget:
 
386
                                CopyBranchStackSize (ref stack_sizes, (Instruction) instruction.operand, stack_size);
 
387
                                break;
 
388
                        case OperandType.InlineSwitch:
 
389
                                var targets = (Instruction[]) instruction.operand;
 
390
                                for (int i = 0; i < targets.Length; i++)
 
391
                                        CopyBranchStackSize (ref stack_sizes, targets [i], stack_size);
 
392
                                break;
 
393
                        }
 
394
                }
 
395
 
 
396
                static void CopyBranchStackSize (ref Dictionary<Instruction, int> stack_sizes, Instruction target, int stack_size)
 
397
                {
 
398
                        if (stack_sizes == null)
 
399
                                stack_sizes = new Dictionary<Instruction, int> ();
 
400
 
 
401
                        int branch_stack_size = stack_size;
 
402
 
 
403
                        int computed_size;
 
404
                        if (stack_sizes.TryGetValue (target, out computed_size))
 
405
                                branch_stack_size = System.Math.Max (branch_stack_size, computed_size);
 
406
 
 
407
                        stack_sizes [target] = branch_stack_size;
 
408
                }
 
409
 
 
410
                static void ComputeStackSize (Instruction instruction, ref int stack_size)
 
411
                {
 
412
                        switch (instruction.opcode.FlowControl) {
 
413
                        case FlowControl.Branch:
 
414
                        case FlowControl.Break:
 
415
                        case FlowControl.Throw:
 
416
                        case FlowControl.Return:
 
417
                                stack_size = 0;
 
418
                                break;
 
419
                        }
 
420
                }
 
421
 
 
422
                static void ComputeStackDelta (Instruction instruction, ref int stack_size)
 
423
                {
 
424
                        switch (instruction.opcode.FlowControl) {
 
425
                        case FlowControl.Call: {
 
426
                                var method = (IMethodSignature) instruction.operand;
 
427
                                stack_size -= (method.HasParameters ? method.Parameters.Count : 0)
 
428
                                        + (method.HasThis && instruction.opcode.Code != Code.Newobj ? 1 : 0);
 
429
                                stack_size += (method.ReturnType.etype == ElementType.Void ? 0 : 1)
 
430
                                        + (method.HasThis && instruction.opcode.Code == Code.Newobj ? 1 : 0);
 
431
                                break;
 
432
                        }
 
433
                        default:
 
434
                                ComputePopDelta (instruction.opcode.StackBehaviourPop, ref stack_size);
 
435
                                ComputePushDelta (instruction.opcode.StackBehaviourPush, ref stack_size);
 
436
                                break;
 
437
                        }
 
438
                }
 
439
 
 
440
                static void ComputePopDelta (StackBehaviour pop_behavior, ref int stack_size)
 
441
                {
 
442
                        switch (pop_behavior) {
 
443
                        case StackBehaviour.Popi:
 
444
                        case StackBehaviour.Popref:
 
445
                        case StackBehaviour.Pop1:
 
446
                                stack_size--;
 
447
                                break;
 
448
                        case StackBehaviour.Pop1_pop1:
 
449
                        case StackBehaviour.Popi_pop1:
 
450
                        case StackBehaviour.Popi_popi:
 
451
                        case StackBehaviour.Popi_popi8:
 
452
                        case StackBehaviour.Popi_popr4:
 
453
                        case StackBehaviour.Popi_popr8:
 
454
                        case StackBehaviour.Popref_pop1:
 
455
                        case StackBehaviour.Popref_popi:
 
456
                                stack_size -= 2;
 
457
                                break;
 
458
                        case StackBehaviour.Popi_popi_popi:
 
459
                        case StackBehaviour.Popref_popi_popi:
 
460
                        case StackBehaviour.Popref_popi_popi8:
 
461
                        case StackBehaviour.Popref_popi_popr4:
 
462
                        case StackBehaviour.Popref_popi_popr8:
 
463
                        case StackBehaviour.Popref_popi_popref:
 
464
                                stack_size -= 3;
 
465
                                break;
 
466
                        case StackBehaviour.PopAll:
 
467
                                stack_size = 0;
 
468
                                break;
 
469
                        }
 
470
                }
 
471
 
 
472
                static void ComputePushDelta (StackBehaviour push_behaviour, ref int stack_size)
 
473
                {
 
474
                        switch (push_behaviour) {
 
475
                        case StackBehaviour.Push1:
 
476
                        case StackBehaviour.Pushi:
 
477
                        case StackBehaviour.Pushi8:
 
478
                        case StackBehaviour.Pushr4:
 
479
                        case StackBehaviour.Pushr8:
 
480
                        case StackBehaviour.Pushref:
 
481
                                stack_size++;
 
482
                                break;
 
483
                        case StackBehaviour.Push1_push1:
 
484
                                stack_size += 2;
 
485
                                break;
 
486
                        }
 
487
                }
 
488
 
 
489
                void WriteExceptionHandlers ()
 
490
                {
 
491
                        Align (4);
 
492
 
 
493
                        var handlers = body.ExceptionHandlers;
 
494
 
 
495
                        if (handlers.Count < 0x15 && !RequiresFatSection (handlers))
 
496
                                WriteSmallSection (handlers);
 
497
                        else
 
498
                                WriteFatSection (handlers);
 
499
                }
 
500
 
 
501
                static bool RequiresFatSection (Collection<ExceptionHandler> handlers)
 
502
                {
 
503
                        for (int i = 0; i < handlers.Count; i++) {
 
504
                                var handler = handlers [i];
 
505
 
 
506
                                if (IsFatRange (handler.TryStart, handler.TryEnd))
 
507
                                        return true;
 
508
 
 
509
                                if (IsFatRange (handler.HandlerStart, handler.HandlerEnd))
 
510
                                        return true;
 
511
 
 
512
                                if (handler.HandlerType == ExceptionHandlerType.Filter
 
513
                                        && IsFatRange (handler.FilterStart, handler.FilterEnd))
 
514
                                        return true;
 
515
                        }
 
516
 
 
517
                        return false;
 
518
                }
 
519
 
 
520
                static bool IsFatRange (Instruction start, Instruction end)
 
521
                {
 
522
                        if (end == null)
 
523
                                return true;
 
524
 
 
525
                        return end.Offset - start.Offset > 255 || start.Offset > 65535;
 
526
                }
 
527
 
 
528
                void WriteSmallSection (Collection<ExceptionHandler> handlers)
 
529
                {
 
530
                        const byte eh_table = 0x1;
 
531
 
 
532
                        WriteByte (eh_table);
 
533
                        WriteByte ((byte) (handlers.Count * 12 + 4));
 
534
                        WriteBytes (2);
 
535
 
 
536
                        WriteExceptionHandlers (
 
537
                                handlers,
 
538
                                i => WriteUInt16 ((ushort) i),
 
539
                                i => WriteByte ((byte) i));
 
540
                }
 
541
 
 
542
                void WriteFatSection (Collection<ExceptionHandler> handlers)
 
543
                {
 
544
                        const byte eh_table = 0x1;
 
545
                        const byte fat_format = 0x40;
 
546
 
 
547
                        WriteByte (eh_table | fat_format);
 
548
 
 
549
                        int size = handlers.Count * 24 + 4;
 
550
                        WriteByte ((byte) (size & 0xff));
 
551
                        WriteByte ((byte) ((size >> 8) & 0xff));
 
552
                        WriteByte ((byte) ((size >> 16) & 0xff));
 
553
 
 
554
                        WriteExceptionHandlers (handlers, WriteInt32, WriteInt32);
 
555
                }
 
556
 
 
557
                void WriteExceptionHandlers (Collection<ExceptionHandler> handlers, Action<int> write_entry, Action<int> write_length)
 
558
                {
 
559
                        for (int i = 0; i < handlers.Count; i++) {
 
560
                                var handler = handlers [i];
 
561
 
 
562
                                write_entry ((int) handler.HandlerType);
 
563
 
 
564
                                write_entry (handler.TryStart.Offset);
 
565
                                write_length (GetTargetOffset (handler.TryEnd) - handler.TryStart.Offset);
 
566
 
 
567
                                write_entry (handler.HandlerStart.Offset);
 
568
                                write_length (GetTargetOffset (handler.HandlerEnd) - handler.HandlerStart.Offset);
 
569
 
 
570
                                WriteExceptionHandlerSpecific (handler);
 
571
                        }
 
572
                }
 
573
 
 
574
                void WriteExceptionHandlerSpecific (ExceptionHandler handler)
 
575
                {
 
576
                        switch (handler.HandlerType) {
 
577
                        case ExceptionHandlerType.Catch:
 
578
                                WriteMetadataToken (metadata.LookupToken (handler.CatchType));
 
579
                                break;
 
580
                        case ExceptionHandlerType.Filter:
 
581
                                WriteInt32 (handler.FilterStart.Offset);
 
582
                                break;
 
583
                        default:
 
584
                                WriteInt32 (0);
 
585
                                break;
 
586
                        }
 
587
                }
 
588
 
 
589
                public MetadataToken GetStandAloneSignature (Collection<VariableDefinition> variables)
 
590
                {
 
591
                        var signature = metadata.GetLocalVariableBlobIndex (variables);
 
592
 
 
593
                        return GetStandAloneSignatureToken (signature);
 
594
                }
 
595
 
 
596
                public MetadataToken GetStandAloneSignature (CallSite call_site)
 
597
                {
 
598
                        var signature = metadata.GetCallSiteBlobIndex (call_site);
 
599
                        var token = GetStandAloneSignatureToken (signature);
 
600
                        call_site.MetadataToken = token;
 
601
                        return token;
 
602
                }
 
603
 
 
604
                MetadataToken GetStandAloneSignatureToken (uint signature)
 
605
                {
 
606
                        MetadataToken token;
 
607
                        if (standalone_signatures.TryGetValue (signature, out token))
 
608
                                return token;
 
609
 
 
610
                        token = new MetadataToken (TokenType.Signature, metadata.AddStandAloneSignature (signature));
 
611
                        standalone_signatures.Add (signature, token);
 
612
                        return token;
 
613
                }
 
614
 
 
615
                RVA BeginMethod ()
 
616
                {
 
617
                        return current;
 
618
                }
 
619
 
 
620
                void WriteMetadataToken (MetadataToken token)
 
621
                {
 
622
                        WriteUInt32 (token.ToUInt32 ());
 
623
                }
 
624
 
 
625
                void Align (int align)
 
626
                {
 
627
                        align--;
 
628
                        WriteBytes (((position + align) & ~align) - position);
 
629
                }
 
630
 
 
631
                void EndMethod ()
 
632
                {
 
633
                        current = (RVA) (code_base + position);
 
634
                }
 
635
        }
 
636
}
 
637
 
 
638
#endif