1 //
2 // StackDecoder.cs
3 //
4 // Authors:
5 //	Alexander Chebaturkin (chebaturkin@gmail.com)
6 //
7 // Copyright (C) 2011 Alexander Chebaturkin
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 using Mono.CodeContracts.Static.AST;
32 using Mono.CodeContracts.Static.AST.Visitors;
33 using Mono.CodeContracts.Static.ControlFlow;
34 using Mono.CodeContracts.Static.DataStructures;
35 
36 namespace Mono.CodeContracts.Static.Analysis.StackAnalysis {
37 	struct StackDecoder<TContext, TData, TResult, TVisitor> : IILVisitor<APC, Dummy, Dummy, TData, TResult>
38 		where TContext : IMethodContextProvider
39 		where TVisitor : IILVisitor<APC, int, int, TData, TResult>
40 	{
41 		private readonly StackDepthProvider<TContext> parent;
42 		private readonly TVisitor visitor;
43 
StackDecoderMono.CodeContracts.Static.Analysis.StackAnalysis.StackDecoder44 		public StackDecoder(StackDepthProvider<TContext> parent,
45 		                    TVisitor visitor)
46 		{
47 			this.parent = parent;
48 			this.visitor = visitor;
49 		}
50 
PopMono.CodeContracts.Static.Analysis.StackAnalysis.StackDecoder51 		private int Pop(APC label, int count)
52 		{
53 			return this.parent.GlobalStackDepth (label) - 1 - count;
54 		}
55 
PopSequenceMono.CodeContracts.Static.Analysis.StackAnalysis.StackDecoder56 		private SequenceGenerator PopSequence(APC pc, int args, int offset)
57 		{
58 			return new SequenceGenerator (this.parent.GlobalStackDepth (pc) - args - offset, args);
59 		}
60 
PushMono.CodeContracts.Static.Analysis.StackAnalysis.StackDecoder61 		private int Push(APC label, int count)
62 		{
63 			return this.parent.GlobalStackDepth (label) - count;
64 		}
65 
PushMono.CodeContracts.Static.Analysis.StackAnalysis.StackDecoder66 		private int Push(APC label, int args, TypeNode returnType)
67 		{
68 			if (this.parent.MetaDataProvider.IsVoid (returnType))
69 				return -1;
70 
71 			return Push (label, args);
72 		}
73 
GetParametersCountMono.CodeContracts.Static.Analysis.StackAnalysis.StackDecoder74 		private int GetParametersCount(Method ctor, int extraVarargs)
75 		{
76 			int result = extraVarargs + this.parent.MetaDataProvider.Parameters (ctor).Count;
77 			if (!this.parent.MetaDataProvider.IsStatic (ctor))
78 				++result;
79 			return result;
80 		}
81 
RemapParameterToLoadStackMono.CodeContracts.Static.Analysis.StackAnalysis.StackDecoder82 		private bool RemapParameterToLoadStack(APC pc, ref Parameter param, out bool isLoadResult, out int loadStackOffset, out bool isOld, out APC lookupPC)
83 		{
84 			if (pc.SubroutineContext == null) {
85 				isLoadResult = false;
86 				loadStackOffset = 0;
87 				isOld = false;
88 				lookupPC = pc;
89 				return false;
90 			}
91 
92 			if (pc.Block.Subroutine.IsRequires) {
93 				isLoadResult = false;
94 				isOld = false;
95 				lookupPC = pc;
96 				for (Sequence<Edge<CFGBlock, EdgeTag>> list = pc.SubroutineContext; list != null; list = list.Tail) {
97 					EdgeTag edgeTag = list.Head.Tag;
98 					if (edgeTag == EdgeTag.Entry) {
99 						param = RemapParameter (param, list.Head.From, pc.Block);
100 						loadStackOffset = 0;
101 						return false;
102 					}
103 					if (edgeTag.Is (EdgeTag.BeforeMask)) {
104 						int stackDepth = this.parent.LocalStackDepth (pc);
105 						loadStackOffset = this.parent.MetaDataProvider.ParameterStackIndex (param) + stackDepth;
106 						return true;
107 					}
108 				}
109 				throw new InvalidOperationException ();
110 			}
111 
112 			if (pc.Block.Subroutine.IsEnsuresOrOldValue) {
113 				isOld = true;
114 				for (Sequence<Edge<CFGBlock, EdgeTag>> ctx = pc.SubroutineContext; ctx != null; ctx = ctx.Tail) {
115 					EdgeTag tag = ctx.Head.Tag;
116 					if (tag == EdgeTag.Exit) {
117 						param = RemapParameter (param, ctx.Head.From, pc.Block);
118 						isLoadResult = false;
119 						loadStackOffset = 0;
120 						lookupPC = pc;
121 						return false;
122 					}
123 
124 					if (tag == EdgeTag.AfterCall) {
125 						loadStackOffset = this.parent.MetaDataProvider.ParameterStackIndex (param);
126 						isLoadResult = false;
127 						lookupPC = new APC (ctx.Head.From, 0, ctx.Tail);
128 						return true;
129 					}
130 
131 					if (tag == EdgeTag.AfterNewObj) {
132 						if (this.parent.MetaDataProvider.ParameterIndex (param) == 0) {
133 							loadStackOffset = this.parent.LocalStackDepth (pc);
134 							isLoadResult = true;
135 							lookupPC = pc;
136 							isOld = false;
137 							return false;
138 						}
139 
140 						loadStackOffset = this.parent.MetaDataProvider.ParameterIndex (param);
141 						isLoadResult = false;
142 						lookupPC = new APC (ctx.Head.From, 0, ctx.Tail);
143 						return true;
144 					}
145 					if (tag == EdgeTag.OldManifest) {
146 						param = RemapParameter (param, ctx.Tail.Head.From, pc.Block);
147 						isOld = false;
148 						isLoadResult = false;
149 						loadStackOffset = 0;
150 						lookupPC = pc;
151 						return false;
152 					}
153 				}
154 				throw new InvalidOperationException ();
155 			}
156 
157 			if (pc.Block.Subroutine.IsInvariant) {
158 				for (Sequence<Edge<CFGBlock, EdgeTag>> list = pc.SubroutineContext; list != null; list = list.Tail) {
159 					EdgeTag tag = list.Head.Tag;
160 					if (tag == EdgeTag.Entry || tag == EdgeTag.Exit) {
161 						Method method;
162 						if (pc.TryGetContainingMethod (out method)) {
163 							param = this.parent.MetaDataProvider.This (method);
164 							isLoadResult = false;
165 							loadStackOffset = 0;
166 							isOld = tag == EdgeTag.Exit;
167 							lookupPC = pc;
168 							return false;
169 						}
170 						isLoadResult = false;
171 						loadStackOffset = 0;
172 						isOld = false;
173 						lookupPC = pc;
174 						return false;
175 					}
176 					if (tag == EdgeTag.AfterCall) {
177 						Method calledMethod;
178 						bool isNewObj;
179 						bool isVirtual;
180 						list.Head.From.IsMethodCallBlock (out calledMethod, out isNewObj, out isVirtual);
181 						int count = this.parent.MetaDataProvider.Parameters (calledMethod).Count;
182 						loadStackOffset = count;
183 						isLoadResult = false;
184 						isOld = true;
185 						lookupPC = new APC (list.Head.From, 0, list.Tail);
186 						return true;
187 					}
188 					if (tag == EdgeTag.AfterNewObj) {
189 						isLoadResult = true;
190 						loadStackOffset = this.parent.LocalStackDepth (pc);
191 						isOld = false;
192 						lookupPC = pc;
193 						return false;
194 					}
195 					if (tag.Is (EdgeTag.BeforeMask))
196 						throw new InvalidOperationException ("this should never happen");
197 				}
198 				throw new InvalidOperationException ("this should never happen");
199 			}
200 
201 			isLoadResult = false;
202 			loadStackOffset = 0;
203 			isOld = false;
204 			lookupPC = pc;
205 			return false;
206 		}
207 
RemapParameterMono.CodeContracts.Static.Analysis.StackAnalysis.StackDecoder208 		private Parameter RemapParameter(Parameter p, CFGBlock parentMethodBlock, CFGBlock subroutineBlock)
209 		{
210 			Method parentMethod = ((IMethodInfo) parentMethodBlock.Subroutine).Method;
211 			Method method = ((IMethodInfo) subroutineBlock.Subroutine).Method;
212 
213 			if (this.parent.MetaDataProvider.Equal (method, parentMethod))
214 				return p;
215 
216 			int index = this.parent.MetaDataProvider.ParameterIndex (p);
217 			if (this.parent.MetaDataProvider.IsStatic (parentMethod) || index != 0)
218 				return this.parent.MetaDataProvider.Parameters (parentMethod)[index];
219 
220 			return this.parent.MetaDataProvider.This (parentMethod);
221 		}
222 
IsReferenceTypeMono.CodeContracts.Static.Analysis.StackAnalysis.StackDecoder223 		private bool IsReferenceType(APC pc, TypeNode type)
224 		{
225 			return this.parent.MetaDataProvider.IsReferenceType (type);
226 		}
227 
GetSpecializedTypeMono.CodeContracts.Static.Analysis.StackAnalysis.StackDecoder228 		private TypeNode GetSpecializedType(APC pc, TypeNode type)
229 		{
230 			var methodInfo = pc.Block.Subroutine as IMethodInfo;
231 			if (methodInfo == null)
232 				return type;
233 
234 			throw new NotImplementedException ();
235 		}
236 
237 		#region Implementation of IExpressionILVisitor<APC,Type,Dummy,Dummy,Data,Result>
BinaryMono.CodeContracts.Static.Analysis.StackAnalysis.StackDecoder238 		public TResult Binary(APC pc, BinaryOperator op, Dummy dest, Dummy operand1, Dummy operand2, TData data)
239 		{
240 			return this.visitor.Binary (pc, op, Push (pc, 2), Pop (pc, 1), Pop (pc, 0), data);
241 		}
242 
IsinstMono.CodeContracts.Static.Analysis.StackAnalysis.StackDecoder243 		public TResult Isinst(APC pc, TypeNode type, Dummy dest, Dummy obj, TData data)
244 		{
245 			return this.visitor.Isinst (pc, type, Push (pc, 1), Pop (pc, 0), data);
246 		}
247 
LoadNullMono.CodeContracts.Static.Analysis.StackAnalysis.StackDecoder248 		public TResult LoadNull(APC pc, Dummy dest, TData polarity)
249 		{
250 			return this.visitor.LoadNull (pc, Push (pc, 0), polarity);
251 		}
252 
LoadConstMono.CodeContracts.Static.Analysis.StackAnalysis.StackDecoder253 		public TResult LoadConst(APC pc, TypeNode type, object constant, Dummy dest, TData data)
254 		{
255 			return this.visitor.LoadConst (pc, type, constant, Push (pc, 0), data);
256 		}
257 
SizeofMono.CodeContracts.Static.Analysis.StackAnalysis.StackDecoder258 		public TResult Sizeof(APC pc, TypeNode type, Dummy dest, TData data)
259 		{
260 			return this.visitor.Sizeof (pc, type, Push (pc, 0), data);
261 		}
262 
UnaryMono.CodeContracts.Static.Analysis.StackAnalysis.StackDecoder263 		public TResult Unary(APC pc, UnaryOperator op, bool unsigned, Dummy dest, Dummy source, TData data)
264 		{
265 			return this.visitor.Unary (pc, op, unsigned, Push (pc, 1), Pop (pc, 0), data);
266 		}
267 		#endregion
268 
269 		#region Implementation of ISyntheticILVisitor<APC,Method,Field,Type,Dummy,Dummy,Data,Result>
EntryMono.CodeContracts.Static.Analysis.StackAnalysis.StackDecoder270 		public TResult Entry(APC pc, Method method, TData data)
271 		{
272 			return this.visitor.Entry (pc, method, data);
273 		}
274 
AssumeMono.CodeContracts.Static.Analysis.StackAnalysis.StackDecoder275 		public TResult Assume(APC pc, EdgeTag tag, Dummy condition, TData data)
276 		{
277 			return this.visitor.Assume (pc, tag, Pop (pc, 0), data);
278 		}
279 
AssertMono.CodeContracts.Static.Analysis.StackAnalysis.StackDecoder280 		public TResult Assert(APC pc, EdgeTag tag, Dummy condition, TData data)
281 		{
282 			return this.visitor.Assert (pc, tag, Pop (pc, 0), data);
283 		}
284 
BeginOldMono.CodeContracts.Static.Analysis.StackAnalysis.StackDecoder285 		public TResult BeginOld(APC pc, APC matchingEnd, TData data)
286 		{
287 			return this.visitor.BeginOld (pc, matchingEnd, data);
288 		}
289 
EndOldMono.CodeContracts.Static.Analysis.StackAnalysis.StackDecoder290 		public TResult EndOld(APC pc, APC matchingBegin, TypeNode type, Dummy dest, Dummy source, TData data)
291 		{
292 			if (pc.InsideOldManifestation)
293 				return this.visitor.LoadStack (pc, 1, Push (matchingBegin, 0), Pop (pc, 0), false, data);
294 
295 			return this.visitor.EndOld (pc, matchingBegin, type, Push (matchingBegin, 0), Pop (pc, 0), data);
296 		}
297 
LoadStackMono.CodeContracts.Static.Analysis.StackAnalysis.StackDecoder298 		public TResult LoadStack(APC pc, int offset, Dummy dest, Dummy source, bool isOld, TData data)
299 		{
300 			return this.visitor.LoadStack (pc, offset, Push (pc, 0), Pop (pc, offset), isOld, data);
301 		}
302 
LoadStackAddressMono.CodeContracts.Static.Analysis.StackAnalysis.StackDecoder303 		public TResult LoadStackAddress(APC pc, int offset, Dummy dest, Dummy source, TypeNode type, bool isOld, TData data)
304 		{
305 			return this.visitor.LoadStackAddress (pc, offset, Push (pc, 0), Pop (pc, offset), type, isOld, data);
306 		}
307 
LoadResultMono.CodeContracts.Static.Analysis.StackAnalysis.StackDecoder308 		public TResult LoadResult(APC pc, TypeNode type, Dummy dest, Dummy source, TData data)
309 		{
310 			int offset = this.parent.LocalStackDepth (pc);
311 			return this.visitor.LoadResult (pc, type, Push (pc, 0), Pop (pc, offset), data);
312 		}
313 		#endregion
314 
315 		#region Implementation of IILVisitor<APC,Local,Parameter,Method,Field,Type,Dummy,Dummy,Data,Result>
ArglistMono.CodeContracts.Static.Analysis.StackAnalysis.StackDecoder316 		public TResult Arglist(APC pc, Dummy dest, TData data)
317 		{
318 			return this.visitor.Arglist (pc, Push (pc, 0), data);
319 		}
320 
BranchMono.CodeContracts.Static.Analysis.StackAnalysis.StackDecoder321 		public TResult Branch(APC pc, APC target, bool leavesExceptionBlock, TData data)
322 		{
323 			return this.visitor.Branch (pc, target, leavesExceptionBlock, data);
324 		}
325 
BranchCondMono.CodeContracts.Static.Analysis.StackAnalysis.StackDecoder326 		public TResult BranchCond(APC pc, APC target, BranchOperator bop, Dummy value1, Dummy value2, TData data)
327 		{
328 			return this.visitor.BranchCond (pc, target, bop, Pop (pc, 1), Pop (pc, 0), data);
329 		}
330 
BranchTrueMono.CodeContracts.Static.Analysis.StackAnalysis.StackDecoder331 		public TResult BranchTrue(APC pc, APC target, Dummy cond, TData data)
332 		{
333 			return this.visitor.BranchTrue (pc, target, Pop (pc, 0), data);
334 		}
335 
BranchFalseMono.CodeContracts.Static.Analysis.StackAnalysis.StackDecoder336 		public TResult BranchFalse(APC pc, APC target, Dummy cond, TData data)
337 		{
338 			return this.visitor.BranchFalse (pc, target, Pop (pc, 0), data);
339 		}
340 
BreakMono.CodeContracts.Static.Analysis.StackAnalysis.StackDecoder341 		public TResult Break(APC pc, TData data)
342 		{
343 			return this.visitor.Break (pc, data);
344 		}
345 
346 		public TResult Call<TypeList, ArgList>(APC pc, Method method, bool virt, TypeList extraVarargs, Dummy dest, ArgList args, TData data)
347 			where TypeList : IIndexable<TypeNode>
348 			where ArgList : IIndexable<Dummy>
349 		{
350 			int argsCount = GetParametersCount (method, extraVarargs == null ? 0 : extraVarargs.Count);
351 			return this.visitor.Call (pc, method, virt, extraVarargs, Push (pc, argsCount, this.parent.MetaDataProvider.ReturnType (method)), PopSequence (pc, argsCount, 0), data);
352 		}
353 
354 		public TResult Calli<TypeList, ArgList>(APC pc, TypeNode returnType, TypeList argTypes, bool instance, Dummy dest, Dummy functionPointer, ArgList args, TData data)
355 			where TypeList : IIndexable<TypeNode>
356 			where ArgList : IIndexable<Dummy>
357 		{
358 			int argsCount = argTypes.Count + (instance ? 1 : 0);
359 			return this.visitor.Calli (pc, returnType, argTypes, instance, Push (pc, argsCount + 1, returnType), Pop (pc, 0), PopSequence (pc, argsCount, 1), data);
360 		}
361 
CheckFinite(APC pc, Dummy dest, Dummy source, TData data)362 		public TResult CheckFinite(APC pc, Dummy dest, Dummy source, TData data)
363 		{
364 			return this.visitor.CheckFinite (pc, Push (pc, 1), Pop (pc, 0), data);
365 		}
366 
CopyBlock(APC pc, Dummy destAddress, Dummy srcAddress, Dummy len, TData data)367 		public TResult CopyBlock(APC pc, Dummy destAddress, Dummy srcAddress, Dummy len, TData data)
368 		{
369 			return this.visitor.CopyBlock (pc, Pop (pc, 2), Pop (pc, 1), Pop (pc, 0), data);
370 		}
371 
EndFilter(APC pc, Dummy decision, TData data)372 		public TResult EndFilter(APC pc, Dummy decision, TData data)
373 		{
374 			return this.visitor.EndFilter (pc, Pop (pc, 0), data);
375 		}
376 
EndFinally(APC pc, TData data)377 		public TResult EndFinally(APC pc, TData data)
378 		{
379 			return this.visitor.EndFinally (pc, data);
380 		}
381 
Jmp(APC pc, Method method, TData data)382 		public TResult Jmp(APC pc, Method method, TData data)
383 		{
384 			return this.visitor.Jmp (pc, method, data);
385 		}
386 
LoadArg(APC pc, Parameter argument, bool dummyOld, Dummy dest, TData data)387 		public TResult LoadArg(APC pc, Parameter argument, bool dummyOld, Dummy dest, TData data)
388 		{
389 			Parameter p = argument;
390 			bool isLdResult;
391 			int loadStackOffset;
392 			bool isOld;
393 			APC lookupPC;
394 			if (RemapParameterToLoadStack (pc, ref argument, out isLdResult, out loadStackOffset, out isOld, out lookupPC))
395 				return this.visitor.LoadStack (pc, loadStackOffset, Push (pc, 0), Pop (lookupPC, loadStackOffset), isOld, data);
396 
397 			if (argument == null)
398 				argument = p;
399 
400 			if (isLdResult) {
401 				if (this.parent.MetaDataProvider.IsStruct (this.parent.MetaDataProvider.DeclaringType (this.parent.MetaDataProvider.DeclaringMethod (argument))))
402 					return this.visitor.LoadStackAddress (pc, loadStackOffset, Push (pc, 0), Pop (pc, loadStackOffset), this.parent.MetaDataProvider.ParameterType (argument), isOld, data);
403 
404 				return this.visitor.LoadResult (pc, this.parent.MetaDataProvider.ParameterType (argument), Push (pc, 0), Pop (pc, loadStackOffset), data);
405 			}
406 
407 			return this.visitor.LoadArg (pc, argument, isOld, Push (pc, 0), data);
408 		}
409 
LoadArgAddress(APC pc, Parameter argument, bool dummyOld, Dummy dest, TData data)410 		public TResult LoadArgAddress(APC pc, Parameter argument, bool dummyOld, Dummy dest, TData data)
411 		{
412 			bool isLoadResult;
413 			int loadStackOffset;
414 			bool isOld;
415 			APC lookupPC;
416 			if (RemapParameterToLoadStack (pc, ref argument, out isLoadResult, out loadStackOffset, out isOld, out lookupPC))
417 				return this.visitor.LoadStackAddress (pc, loadStackOffset, Push (pc, 0), Pop (lookupPC, loadStackOffset), this.parent.MetaDataProvider.ParameterType (argument), isOld, data);
418 
419 			if (isLoadResult)
420 				throw new InvalidOperationException ();
421 
422 			return this.visitor.LoadArgAddress (pc, argument, isOld, Push (pc, 0), data);
423 		}
424 
LoadLocal(APC pc, Local local, Dummy dest, TData data)425 		public TResult LoadLocal(APC pc, Local local, Dummy dest, TData data)
426 		{
427 			return this.visitor.LoadLocal (pc, local, Push (pc, 0), data);
428 		}
429 
LoadLocalAddress(APC pc, Local local, Dummy dest, TData data)430 		public TResult LoadLocalAddress(APC pc, Local local, Dummy dest, TData data)
431 		{
432 			return this.visitor.LoadLocalAddress (pc, local, Push (pc, 0), data);
433 		}
434 
Nop(APC pc, TData data)435 		public TResult Nop(APC pc, TData data)
436 		{
437 			return this.visitor.Nop (pc, data);
438 		}
439 
Pop(APC pc, Dummy source, TData data)440 		public TResult Pop(APC pc, Dummy source, TData data)
441 		{
442 			return this.visitor.Pop (pc, Pop (pc, 0), data);
443 		}
444 
Return(APC pc, Dummy source, TData data)445 		public TResult Return(APC pc, Dummy source, TData data)
446 		{
447 			return this.visitor.Nop (pc, data);
448 		}
449 
StoreArg(APC pc, Parameter argument, Dummy source, TData data)450 		public TResult StoreArg(APC pc, Parameter argument, Dummy source, TData data)
451 		{
452 			return this.visitor.StoreArg (pc, argument, Pop (pc, 0), data);
453 		}
454 
StoreLocal(APC pc, Local local, Dummy source, TData data)455 		public TResult StoreLocal(APC pc, Local local, Dummy source, TData data)
456 		{
457 			return this.visitor.StoreLocal (pc, local, Pop (pc, 0), data);
458 		}
459 
Switch(APC pc, TypeNode type, IEnumerable<Pair<object, APC>> cases, Dummy value, TData data)460 		public TResult Switch(APC pc, TypeNode type, IEnumerable<Pair<object, APC>> cases, Dummy value, TData data)
461 		{
462 			return this.visitor.Switch (pc, type, cases, Pop (pc, 0), data);
463 		}
464 
Box(APC pc, TypeNode type, Dummy dest, Dummy source, TData data)465 		public TResult Box(APC pc, TypeNode type, Dummy dest, Dummy source, TData data)
466 		{
467 			type = GetSpecializedType (pc, type);
468 			if (IsReferenceType (pc, type))
469 				return this.visitor.Nop (pc, data);
470 
471 			return this.visitor.Box (pc, type, Push (pc, 1), Pop (pc, 0), data);
472 		}
473 
474 		public TResult ConstrainedCallvirt<TypeList, ArgList>(APC pc, Method method, TypeNode constraint, TypeList extraVarargs, Dummy dest, ArgList args, TData data)
475 			where TypeList : IIndexable<TypeNode>
476 			where ArgList : IIndexable<Dummy>
477 		{
478 			int argsCount = GetParametersCount (method, extraVarargs == null ? 0 : extraVarargs.Count);
479 			return this.visitor.ConstrainedCallvirt (pc, method, constraint, extraVarargs, Push (pc, argsCount, this.parent.MetaDataProvider.ReturnType (method)), PopSequence (pc, argsCount, 0), data);
480 		}
481 
CastClass(APC pc, TypeNode type, Dummy dest, Dummy obj, TData data)482 		public TResult CastClass(APC pc, TypeNode type, Dummy dest, Dummy obj, TData data)
483 		{
484 			return this.visitor.CastClass (pc, type, Push (pc, 1), Pop (pc, 0), data);
485 		}
486 
CopyObj(APC pc, TypeNode type, Dummy destPtr, Dummy sourcePtr, TData data)487 		public TResult CopyObj(APC pc, TypeNode type, Dummy destPtr, Dummy sourcePtr, TData data)
488 		{
489 			return this.visitor.CopyObj (pc, type, Pop (pc, 1), Pop (pc, 0), data);
490 		}
491 
Initobj(APC pc, TypeNode type, Dummy ptr, TData data)492 		public TResult Initobj(APC pc, TypeNode type, Dummy ptr, TData data)
493 		{
494 			return this.visitor.Initobj (pc, type, Pop (pc, 0), data);
495 		}
496 
LoadElement(APC pc, TypeNode type, Dummy dest, Dummy array, Dummy index, TData data)497 		public TResult LoadElement(APC pc, TypeNode type, Dummy dest, Dummy array, Dummy index, TData data)
498 		{
499 			return this.visitor.LoadElement (pc, type, Push (pc, 2), Pop (pc, 1), Pop (pc, 0), data);
500 		}
501 
LoadField(APC pc, Field field, Dummy dest, Dummy obj, TData data)502 		public TResult LoadField(APC pc, Field field, Dummy dest, Dummy obj, TData data)
503 		{
504 			return this.visitor.LoadField (pc, field, Push (pc, 1), Pop (pc, 0), data);
505 		}
506 
LoadFieldAddress(APC pc, Field field, Dummy dest, Dummy obj, TData data)507 		public TResult LoadFieldAddress(APC pc, Field field, Dummy dest, Dummy obj, TData data)
508 		{
509 			return this.visitor.LoadFieldAddress (pc, field, Push (pc, 1), Pop (pc, 0), data);
510 		}
511 
LoadLength(APC pc, Dummy dest, Dummy array, TData data)512 		public TResult LoadLength(APC pc, Dummy dest, Dummy array, TData data)
513 		{
514 			return this.visitor.LoadLength (pc, Push (pc, 1), Pop (pc, 0), data);
515 		}
516 
LoadStaticField(APC pc, Field field, Dummy dest, TData data)517 		public TResult LoadStaticField(APC pc, Field field, Dummy dest, TData data)
518 		{
519 			return this.visitor.LoadStaticField (pc, field, Push (pc, 0), data);
520 		}
521 
LoadStaticFieldAddress(APC pc, Field field, Dummy dest, TData data)522 		public TResult LoadStaticFieldAddress(APC pc, Field field, Dummy dest, TData data)
523 		{
524 			return this.visitor.LoadStaticFieldAddress (pc, field, Push (pc, 0), data);
525 		}
526 
LoadTypeToken(APC pc, TypeNode type, Dummy dest, TData data)527 		public TResult LoadTypeToken(APC pc, TypeNode type, Dummy dest, TData data)
528 		{
529 			return this.visitor.LoadTypeToken (pc, type, Push (pc, 0), data);
530 		}
531 
LoadFieldToken(APC pc, Field field, Dummy dest, TData data)532 		public TResult LoadFieldToken(APC pc, Field field, Dummy dest, TData data)
533 		{
534 			return this.visitor.LoadFieldToken (pc, field, Push (pc, 0), data);
535 		}
536 
LoadMethodToken(APC pc, Method method, Dummy dest, TData data)537 		public TResult LoadMethodToken(APC pc, Method method, Dummy dest, TData data)
538 		{
539 			return this.visitor.LoadMethodToken (pc, method, Push (pc, 0), data);
540 		}
541 
542 		public TResult NewArray<ArgList>(APC pc, TypeNode type, Dummy dest, ArgList lengths, TData data)
543 			where ArgList : IIndexable<Dummy>
544 		{
545 			return this.visitor.NewArray (pc, type, Push (pc, 1), PopSequence (pc, lengths.Count, 0), data);
546 		}
547 
548 		public TResult NewObj<ArgList>(APC pc, Method ctor, Dummy dest, ArgList args, TData data)
549 			where ArgList : IIndexable<Dummy>
550 		{
551 			int argsCount = GetParametersCount (ctor, 0) - 1;
552 			return this.visitor.NewObj (pc, ctor, Push (pc, argsCount), PopSequence (pc, argsCount, 0), data);
553 		}
554 
MkRefAny(APC pc, TypeNode type, Dummy dest, Dummy obj, TData data)555 		public TResult MkRefAny(APC pc, TypeNode type, Dummy dest, Dummy obj, TData data)
556 		{
557 			return this.visitor.MkRefAny (pc, type, Push (pc, 1), Pop (pc, 0), data);
558 		}
559 
RefAnyType(APC pc, Dummy dest, Dummy source, TData data)560 		public TResult RefAnyType(APC pc, Dummy dest, Dummy source, TData data)
561 		{
562 			return this.visitor.RefAnyType (pc, Push (pc, 1), Pop (pc, 0), data);
563 		}
564 
RefAnyVal(APC pc, TypeNode type, Dummy dest, Dummy source, TData data)565 		public TResult RefAnyVal(APC pc, TypeNode type, Dummy dest, Dummy source, TData data)
566 		{
567 			return this.visitor.RefAnyVal (pc, type, Push (pc, 1), Pop (pc, 0), data);
568 		}
569 
Rethrow(APC pc, TData data)570 		public TResult Rethrow(APC pc, TData data)
571 		{
572 			return this.visitor.Rethrow (pc, data);
573 		}
574 
StoreElement(APC pc, TypeNode type, Dummy array, Dummy index, Dummy value, TData data)575 		public TResult StoreElement(APC pc, TypeNode type, Dummy array, Dummy index, Dummy value, TData data)
576 		{
577 			return this.visitor.StoreElement (pc, type, Pop (pc, 2), Pop (pc, 1), Pop (pc, 0), data);
578 		}
579 
StoreField(APC pc, Field field, Dummy obj, Dummy value, TData data)580 		public TResult StoreField(APC pc, Field field, Dummy obj, Dummy value, TData data)
581 		{
582 			return this.visitor.StoreField (pc, field, Pop (pc, 1), Pop (pc, 0), data);
583 		}
584 
StoreStaticField(APC pc, Field field, Dummy value, TData data)585 		public TResult StoreStaticField(APC pc, Field field, Dummy value, TData data)
586 		{
587 			return this.visitor.StoreStaticField (pc, field, Pop (pc, 0), data);
588 		}
589 
Throw(APC pc, Dummy exception, TData data)590 		public TResult Throw(APC pc, Dummy exception, TData data)
591 		{
592 			return this.visitor.Throw (pc, Pop (pc, 0), data);
593 		}
594 
Unbox(APC pc, TypeNode type, Dummy dest, Dummy obj, TData data)595 		public TResult Unbox(APC pc, TypeNode type, Dummy dest, Dummy obj, TData data)
596 		{
597 			return this.visitor.Unbox (pc, type, Push (pc, 1), Pop (pc, 0), data);
598 		}
599 
UnboxAny(APC pc, TypeNode type, Dummy dest, Dummy obj, TData data)600 		public TResult UnboxAny(APC pc, TypeNode type, Dummy dest, Dummy obj, TData data)
601 		{
602 			return this.visitor.UnboxAny (pc, type, Push (pc, 1), Pop (pc, 0), data);
603 		}
604 		#endregion
605 	}
606 }