Don't create temporary module builder for dynamic context, compiler no longer relies...
[mono.git] / mcs / class / Mono.Cecil / Mono.Cecil.Cil / MethodBody.cs
1 //
2 // MethodBody.cs
3 //
4 // Author:
5 //   Jb Evain (jbevain@gmail.com)
6 //
7 // Copyright (c) 2008 - 2011 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
31 using Mono.Collections.Generic;
32
33 namespace Mono.Cecil.Cil {
34
35         public sealed class MethodBody : IVariableDefinitionProvider {
36
37                 readonly internal MethodDefinition method;
38
39                 internal ParameterDefinition this_parameter;
40                 internal int max_stack_size;
41                 internal int code_size;
42                 internal bool init_locals;
43                 internal MetadataToken local_var_token;
44
45                 internal Collection<Instruction> instructions;
46                 internal Collection<ExceptionHandler> exceptions;
47                 internal Collection<VariableDefinition> variables;
48                 Scope scope;
49
50                 public MethodDefinition Method {
51                         get { return method; }
52                 }
53
54                 public int MaxStackSize {
55                         get { return max_stack_size; }
56                         set { max_stack_size = value; }
57                 }
58
59                 public int CodeSize {
60                         get { return code_size; }
61                 }
62
63                 public bool InitLocals {
64                         get { return init_locals; }
65                         set { init_locals = value; }
66                 }
67
68                 public MetadataToken LocalVarToken {
69                         get { return local_var_token; }
70                         set { local_var_token = value; }
71                 }
72
73                 public Collection<Instruction> Instructions {
74                         get { return instructions ?? (instructions = new InstructionCollection ()); }
75                 }
76
77                 public bool HasExceptionHandlers {
78                         get { return !exceptions.IsNullOrEmpty (); }
79                 }
80
81                 public Collection<ExceptionHandler> ExceptionHandlers {
82                         get { return exceptions ?? (exceptions = new Collection<ExceptionHandler> ()); }
83                 }
84
85                 public bool HasVariables {
86                         get { return !variables.IsNullOrEmpty (); }
87                 }
88
89                 public Collection<VariableDefinition> Variables {
90                         get { return variables ?? (variables = new VariableDefinitionCollection ()); }
91                 }
92
93                 public Scope Scope {
94                         get { return scope; }
95                         set { scope = value; }
96                 }
97
98                 public ParameterDefinition ThisParameter {
99                         get {
100                                 if (method == null || method.DeclaringType == null)
101                                         throw new NotSupportedException ();
102
103                                 if (!method.HasThis)
104                                         return null;
105
106                                 if (this_parameter != null)
107                                         return this_parameter;
108
109                                 var declaring_type = method.DeclaringType;
110                                 var type = declaring_type.IsValueType || declaring_type.IsPrimitive
111                                         ? new PointerType (declaring_type)
112                                         : declaring_type as TypeReference;
113
114                                 return this_parameter = new ParameterDefinition (type, method);
115                         }
116                 }
117
118                 public MethodBody (MethodDefinition method)
119                 {
120                         this.method = method;
121                 }
122
123                 public ILProcessor GetILProcessor ()
124                 {
125                         return new ILProcessor (this);
126                 }
127         }
128
129         public interface IVariableDefinitionProvider {
130                 bool HasVariables { get; }
131                 Collection<VariableDefinition> Variables { get; }
132         }
133
134         class VariableDefinitionCollection : Collection<VariableDefinition> {
135
136                 internal VariableDefinitionCollection ()
137                 {
138                 }
139
140                 internal VariableDefinitionCollection (int capacity)
141                         : base (capacity)
142                 {
143                 }
144
145                 protected override void OnAdd (VariableDefinition item, int index)
146                 {
147                         item.index = index;
148                 }
149
150                 protected override void OnInsert (VariableDefinition item, int index)
151                 {
152                         item.index = index;
153
154                         for (int i = index; i < size; i++)
155                                 items [i].index = i + 1;
156                 }
157
158                 protected override void OnSet (VariableDefinition item, int index)
159                 {
160                         item.index = index;
161                 }
162
163                 protected override void OnRemove (VariableDefinition item, int index)
164                 {
165                         item.index = -1;
166
167                         for (int i = index + 1; i < size; i++)
168                                 items [i].index = i - 1;
169                 }
170         }
171
172         class InstructionCollection : Collection<Instruction> {
173
174                 internal InstructionCollection ()
175                 {
176                 }
177
178                 internal InstructionCollection (int capacity)
179                         : base (capacity)
180                 {
181                 }
182
183                 protected override void OnAdd (Instruction item, int index)
184                 {
185                         if (index == 0)
186                                 return;
187
188                         var previous = items [index - 1];
189                         previous.next = item;
190                         item.previous = previous;
191                 }
192
193                 protected override void OnInsert (Instruction item, int index)
194                 {
195                         if (size == 0)
196                                 return;
197
198                         var current = items [index];
199                         if (current == null) {
200                                 var last = items [index - 1];
201                                 last.next = item;
202                                 item.previous = last;
203                                 return;
204                         }
205
206                         var previous = current.previous;
207                         if (previous != null) {
208                                 previous.next = item;
209                                 item.previous = previous;
210                         }
211
212                         current.previous = item;
213                         item.next = current;
214                 }
215
216                 protected override void OnSet (Instruction item, int index)
217                 {
218                         var current = items [index];
219
220                         item.previous = current.previous;
221                         item.next = current.next;
222
223                         current.previous = null;
224                         current.next = null;
225                 }
226
227                 protected override void OnRemove (Instruction item, int index)
228                 {
229                         var previous = item.previous;
230                         if (previous != null)
231                                 previous.next = item.next;
232
233                         var next = item.next;
234                         if (next != null)
235                                 next.previous = item.previous;
236
237                         item.previous = null;
238                         item.next = null;
239                 }
240         }
241 }