[runtime] Replace pedump boehm dependency with sgen dependency
[mono.git] / mcs / class / referencesource / System / regex / system / text / regularexpressions / RegexCompiler.cs
1 //------------------------------------------------------------------------------
2 // <copyright file="RegexCompiler.cs" company="Microsoft">
3 //     Copyright (c) Microsoft Corporation.  All rights reserved.
4 // </copyright>                                                                
5 //------------------------------------------------------------------------------
6
7 // The RegexCompiler class is internal to the Regex package.
8 // It translates a block of RegexCode to MSIL, and creates a
9 // subclass of the RegexRunner type.
10
11
12 #if !SILVERLIGHT && !FULL_AOT_RUNTIME
13
14 namespace System.Text.RegularExpressions {
15
16     using System.Collections;
17         using System.Collections.Generic;
18     using System.Threading;
19     using System.Reflection;
20     using System.Reflection.Emit;
21     using System.Security;
22     using System.Security.Policy;
23     using System.Security.Permissions;
24     using System.Diagnostics;
25     using System.Diagnostics.CodeAnalysis;
26     using System.Globalization;
27     using System.Runtime.Versioning;
28
29     /*
30      * RegexDynamicModule
31      *
32      * Because dynamic modules are expensive and not thread-safe, we create
33      * one dynamic module per-thread, and cache as much information about it
34      * as we can.
35      *
36      * While we're at it, we just create one RegexCompiler per thread
37      * as well, and have RegexCompiler inherit from RegexDynamicModule.
38      */
39     internal abstract class RegexCompiler {
40         // fields that never change (making them saves about 6% overall running time)
41
42         internal static FieldInfo      _textbegF;
43         internal static FieldInfo      _textendF;
44         internal static FieldInfo      _textstartF;
45         internal static FieldInfo      _textposF;
46         internal static FieldInfo      _textF;
47         internal static FieldInfo      _trackposF;
48         internal static FieldInfo      _trackF;
49         internal static FieldInfo      _stackposF;
50         internal static FieldInfo      _stackF;
51         internal static FieldInfo      _trackcountF;
52
53         // note some methods
54
55         internal static MethodInfo     _ensurestorageM;
56         internal static MethodInfo     _captureM;
57         internal static MethodInfo     _transferM;
58         internal static MethodInfo     _uncaptureM;
59         internal static MethodInfo     _ismatchedM;
60         internal static MethodInfo     _matchlengthM;
61         internal static MethodInfo     _matchindexM;
62         internal static MethodInfo     _isboundaryM;
63         internal static MethodInfo     _isECMABoundaryM;
64         internal static MethodInfo     _chartolowerM; 
65         internal static MethodInfo     _getcharM; 
66         internal static MethodInfo     _crawlposM; 
67         internal static MethodInfo     _charInSetM;
68         internal static MethodInfo     _getCurrentCulture;
69         internal static MethodInfo     _getInvariantCulture;
70         internal static MethodInfo     _checkTimeoutM;
71     #if DBG
72         internal static MethodInfo     _dumpstateM;
73     #endif
74
75         internal ILGenerator     _ilg;
76
77         // tokens representing local variables
78         internal LocalBuilder      _textstartV;
79         internal LocalBuilder      _textbegV;
80         internal LocalBuilder      _textendV;
81         internal LocalBuilder      _textposV;
82         internal LocalBuilder      _textV;
83         internal LocalBuilder      _trackposV;
84         internal LocalBuilder      _trackV;
85         internal LocalBuilder      _stackposV;
86         internal LocalBuilder      _stackV;
87         internal LocalBuilder      _tempV;
88         internal LocalBuilder      _temp2V;
89         internal LocalBuilder      _temp3V;
90
91
92         internal RegexCode       _code;              // the RegexCode object (used for debugging only)
93         internal int[]           _codes;             // the RegexCodes being translated
94         internal String[]        _strings;           // the stringtable associated with the RegexCodes
95         internal RegexPrefix     _fcPrefix;          // the possible first chars computed by RegexFCD
96         internal RegexBoyerMoore _bmPrefix;          // a prefix as a boyer-moore machine
97         internal int             _anchors;           // the set of anchors
98
99         internal Label[]         _labels;            // a label for every operation in _codes
100         internal BacktrackNote[] _notes;             // a list of the backtracking states to be generated
101         internal int             _notecount;         // true count of _notes (allocation grows exponentially)
102         internal int             _trackcount;        // count of backtracking states (used to reduce allocations)
103
104         internal Label           _backtrack;         // label for backtracking
105
106
107         internal int             _regexopcode;       // the current opcode being processed
108         internal int             _codepos;           // the current code being translated
109         internal int             _backpos;           // the current backtrack-note being translated
110
111         internal RegexOptions    _options;           // options
112
113         // special code fragments
114         internal int[]           _uniquenote;        // _notes indices for code that should be emitted <= once
115         internal int[]           _goto;              // indices for forward-jumps-through-switch (for allocations)
116
117         // indices for unique code fragments
118         internal const int stackpop               = 0;    // pop one
119         internal const int stackpop2              = 1;    // pop two
120         internal const int stackpop3              = 2;    // pop three
121         internal const int capback                = 3;    // uncapture
122         internal const int capback2               = 4;    // uncapture 2
123         internal const int branchmarkback2        = 5;    // back2 part of branchmark
124         internal const int lazybranchmarkback2    = 6;    // back2 part of lazybranchmark
125         internal const int branchcountback2       = 7;    // back2 part of branchcount
126         internal const int lazybranchcountback2   = 8;    // back2 part of lazybranchcount
127         internal const int forejumpback           = 9;    // back part of forejump
128         internal const int uniquecount            = 10;
129
130         static RegexCompiler() {
131             // <SECREVIEW> Regex only generates string manipulation, so this is ok.
132             // </SECREVIEW>      
133
134 #if !DISABLE_CAS_USE
135             new ReflectionPermission(PermissionState.Unrestricted).Assert();
136 #endif
137             try {
138                 // note some fields
139                 _textbegF       = RegexRunnerField("runtextbeg");
140                 _textendF       = RegexRunnerField("runtextend");
141                 _textstartF     = RegexRunnerField("runtextstart");
142                 _textposF       = RegexRunnerField("runtextpos");
143                 _textF          = RegexRunnerField("runtext");
144                 _trackposF      = RegexRunnerField("runtrackpos");
145                 _trackF         = RegexRunnerField("runtrack");
146                 _stackposF      = RegexRunnerField("runstackpos");
147                 _stackF         = RegexRunnerField("runstack");
148                 _trackcountF    = RegexRunnerField("runtrackcount");
149
150                 // note some methods
151                 _ensurestorageM = RegexRunnerMethod("EnsureStorage");
152                 _captureM       = RegexRunnerMethod("Capture");
153                 _transferM      = RegexRunnerMethod("TransferCapture");
154                 _uncaptureM     = RegexRunnerMethod("Uncapture");
155                 _ismatchedM     = RegexRunnerMethod("IsMatched");
156                 _matchlengthM   = RegexRunnerMethod("MatchLength");
157                 _matchindexM    = RegexRunnerMethod("MatchIndex");
158                 _isboundaryM    = RegexRunnerMethod("IsBoundary");
159                 _charInSetM     = RegexRunnerMethod("CharInClass");
160                 _isECMABoundaryM= RegexRunnerMethod("IsECMABoundary");
161                 _crawlposM      = RegexRunnerMethod("Crawlpos");
162                 _checkTimeoutM  = RegexRunnerMethod("CheckTimeout");
163
164                 _chartolowerM   = typeof(Char).GetMethod("ToLower", new Type[] {typeof(Char), typeof(CultureInfo)});
165                 _getcharM       = typeof(String).GetMethod("get_Chars", new Type[] {typeof(int)});
166                 _getCurrentCulture   = typeof(CultureInfo).GetMethod("get_CurrentCulture");
167                 _getInvariantCulture = typeof(CultureInfo).GetMethod("get_InvariantCulture");
168                 
169
170 #if DBG
171                 _dumpstateM     = RegexRunnerMethod("DumpState");
172 #endif
173             }
174             finally {
175                 CodeAccessPermission.RevertAssert();
176             }
177         }
178
179         private static FieldInfo RegexRunnerField(String fieldname) {
180             return typeof(RegexRunner).GetField(fieldname, BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static);
181         }
182
183         private static MethodInfo RegexRunnerMethod(String methname) {
184             return typeof(RegexRunner).GetMethod(methname, BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static);
185         }
186
187
188         /* 
189          * Entry point to dynamically compile a regular expression.  The expression is compiled to 
190          * an in-memory assembly.
191          */
192         internal static RegexRunnerFactory Compile(RegexCode code, RegexOptions options) {
193             RegexLWCGCompiler c = new RegexLWCGCompiler();
194             RegexRunnerFactory factory;
195
196             // <SECREVIEW> Regex only generates string manipulation, so this is ok.
197             // </SECREVIEW>         
198 #if !DISABLE_CAS_USE
199             new ReflectionPermission(PermissionState.Unrestricted).Assert();
200 #endif
201             try {
202                 factory = c.FactoryInstanceFromCode(code, options);
203             }
204             finally {
205                 CodeAccessPermission.RevertAssert();
206             }
207             return factory;
208         }
209
210         /* 
211          * Compile regular expressions into an assembly on disk.
212          */
213         [ResourceExposure(ResourceScope.Machine)]
214         [ResourceConsumption(ResourceScope.Machine)]
215         [SuppressMessage("Microsoft.Security","CA2106:SecureAsserts", Justification="[....]: SECREVIEW : Regex only generates string manipulation, so this is OK")]
216         internal static void CompileToAssembly(RegexCompilationInfo[] regexes, AssemblyName an, CustomAttributeBuilder[] attribs, String resourceFile) {
217             RegexTypeCompiler c = new RegexTypeCompiler(an, attribs, resourceFile);
218         
219             for (int i=0; i<regexes.Length; i++) {
220                 if (regexes[i] == null) {
221                     throw new ArgumentNullException("regexes", SR.GetString(SR.ArgumentNull_ArrayWithNullElements));
222                 }
223                 String pattern = regexes[i].Pattern;
224                 RegexOptions options = regexes[i].Options;
225                 String fullname;
226                 if (regexes[i].Namespace.Length == 0)
227                     fullname = regexes[i].Name;
228                 else
229                     fullname = regexes[i].Namespace + "." + regexes[i].Name;
230
231                 TimeSpan mTimeout = regexes[i].MatchTimeout;
232         
233                 RegexTree tree = RegexParser.Parse(pattern, options);
234                 RegexCode code = RegexWriter.Write(tree);
235         
236                 Type factory;
237         
238 #if !DISABLE_CAS_USE
239                 new ReflectionPermission(PermissionState.Unrestricted).Assert();
240 #endif
241                 try {
242                     factory = c.FactoryTypeFromCode(code, options, fullname);
243                     c.GenerateRegexType(pattern, options, fullname, regexes[i].IsPublic, code, tree, factory, mTimeout);
244                 }
245                 finally {
246                     CodeAccessPermission.RevertAssert();
247                 }
248             }
249         
250             c.Save();
251         }
252         
253
254         /*
255          * Keeps track of an operation that needs to be referenced in the backtrack-jump
256          * switch table, and that needs backtracking code to be emitted (if flags != 0)
257          */
258         internal sealed class BacktrackNote {
259             internal BacktrackNote(int flags, Label label, int codepos) {
260                 _codepos = codepos;
261                 _flags = flags;
262                 _label = label;
263             }
264
265             internal int _codepos;
266             internal int _flags;
267             internal Label _label;
268         }
269
270         /*
271          * Adds a backtrack note to the list of them, and returns the index of the new
272          * note (which is also the index for the jump used by the switch table)
273          */
274         internal int AddBacktrackNote(int flags, Label l, int codepos) {
275             if (_notes == null || _notecount >= _notes.Length) {
276                 BacktrackNote[] newnotes = new BacktrackNote[_notes == null ? 16 : _notes.Length * 2];
277                 if (_notes != null)
278                     System.Array.Copy(_notes, 0, newnotes, 0, _notecount);
279                 _notes = newnotes;
280             }
281
282             _notes[_notecount] = new BacktrackNote(flags, l, codepos);
283
284             return _notecount++;
285         }
286
287         /*
288          * Adds a backtrack note for the current operation; creates a new label for
289          * where the code will be, and returns the switch index.
290          */
291         internal int AddTrack() {
292             return AddTrack(RegexCode.Back);
293         }
294
295         /*
296          * Adds a backtrack note for the current operation; creates a new label for
297          * where the code will be, and returns the switch index.
298          */
299         internal int AddTrack(int flags) {
300             return AddBacktrackNote(flags, DefineLabel(), _codepos);
301         }
302
303         /*
304          * Adds a switchtable entry for the specified position (for the forward
305          * logic; does not cause backtracking logic to be generated)
306          */
307         internal int AddGoto(int destpos) {
308             if (_goto[destpos] == -1)
309                 _goto[destpos] = AddBacktrackNote(0, _labels[destpos], destpos);
310
311             return _goto[destpos];
312         }
313
314         /*
315          * Adds a note for backtracking code that only needs to be generated once;
316          * if it's already marked to be generated, returns the switch index
317          * for the unique piece of code.
318          */
319         internal int AddUniqueTrack(int i) {
320             return AddUniqueTrack(i, RegexCode.Back);
321         }
322
323         /*
324          * Adds a note for backtracking code that only needs to be generated once;
325          * if it's already marked to be generated, returns the switch index
326          * for the unique piece of code.
327          */
328         internal int AddUniqueTrack(int i, int flags) {
329             if (_uniquenote[i] == -1)
330                 _uniquenote[i] = AddTrack(flags);
331
332             return _uniquenote[i];
333         }
334
335         /*
336          * A macro for _ilg.DefineLabel
337          */
338         internal Label DefineLabel() {
339             return _ilg.DefineLabel();
340         }
341
342         /*
343          * A macro for _ilg.MarkLabel
344          */
345         internal void MarkLabel(Label l) {
346             _ilg.MarkLabel(l);
347         }
348
349         /*
350          * Returns the ith operand of the current operation
351          */
352         internal int Operand(int i) {
353             return _codes[_codepos + i + 1];
354         }
355
356         /*
357          * True if the current operation is marked for the leftward direction
358          */
359         internal bool IsRtl() {
360             return(_regexopcode & RegexCode.Rtl) != 0;
361         }
362
363         /*
364          * True if the current operation is marked for case insensitive operation
365          */
366         internal bool IsCi() {
367             return(_regexopcode & RegexCode.Ci) != 0;
368         }
369
370 #if DBG
371         /*
372          * True if we need to do the backtrack logic for the current operation
373          */
374         internal bool IsBack() {
375             return(_regexopcode & RegexCode.Back) != 0;
376         }
377
378         /*
379          * True if we need to do the second-backtrack logic for the current operation
380          */
381         internal bool IsBack2() {
382             return(_regexopcode & RegexCode.Back2) != 0;
383         }
384 #endif
385
386         /*
387          * Returns the raw regex opcode (masking out Back and Rtl)
388          */
389         internal int Code() {
390             return _regexopcode & RegexCode.Mask;
391         }
392
393         internal void Ldstr(string str) {
394             _ilg.Emit(OpCodes.Ldstr, str);
395         }
396
397         /*
398          * A macro for the various forms of Ldc
399          */
400         internal void Ldc(int i) {
401             if (i <= 127 && i >= -128)
402                 _ilg.Emit(OpCodes.Ldc_I4_S, (byte)i);
403             else
404                 _ilg.Emit(OpCodes.Ldc_I4, i);
405         }
406
407         internal void LdcI8(long i) {
408             if (i <= Int32.MaxValue && i >= Int32.MinValue) {
409                 Ldc((Int32) i);
410                 _ilg.Emit(OpCodes.Conv_I8);
411             } else {
412                 _ilg.Emit(OpCodes.Ldc_I8, i);
413             }
414         }
415
416         /*
417          * A macro for _ilg.Emit(OpCodes.Dup)
418          */
419         internal void Dup() {
420             _ilg.Emit(OpCodes.Dup);
421         }
422
423         /*
424          * A macro for _ilg.Emit(OpCodes.Ret)
425          */
426         internal void Ret() {
427             _ilg.Emit(OpCodes.Ret);
428         }
429
430         /*
431          * A macro for _ilg.Emit(OpCodes.Pop)
432          */
433         internal void Pop() {
434             _ilg.Emit(OpCodes.Pop);
435         }
436
437         /*
438          * A macro for _ilg.Emit(OpCodes.Add)
439          */
440         internal void Add() {
441             _ilg.Emit(OpCodes.Add);
442         }
443
444         /*
445          * A macro for _ilg.Emit(OpCodes.Add); a true flag can turn it into a Sub
446          */
447         internal void Add(bool negate) {
448             if (negate)
449                 _ilg.Emit(OpCodes.Sub);
450             else
451                 _ilg.Emit(OpCodes.Add);
452         }
453
454         /*
455          * A macro for _ilg.Emit(OpCodes.Sub)
456          */
457         internal void Sub() {
458             _ilg.Emit(OpCodes.Sub);
459         }
460
461         /*
462          * A macro for _ilg.Emit(OpCodes.Sub); a true flag can turn it into a Add
463          */
464         internal void Sub(bool negate) {
465             if (negate)
466                 _ilg.Emit(OpCodes.Add);
467             else
468                 _ilg.Emit(OpCodes.Sub);
469         }
470
471         /*
472          * A macro for _ilg.Emit(OpCodes.Ldloc);
473          */
474         internal void Ldloc(LocalBuilder lt) {
475             _ilg.Emit(OpCodes.Ldloc_S, lt);
476         }
477
478         /*
479          * A macro for _ilg.Emit(OpCodes.Stloc);
480          */
481         internal void Stloc(LocalBuilder lt) {
482             _ilg.Emit(OpCodes.Stloc_S, lt);
483         }
484
485         /*
486          * A macro for _ilg.Emit(OpCodes.Ldarg_0);
487          */
488         internal void Ldthis() {
489             _ilg.Emit(OpCodes.Ldarg_0);
490         }
491
492         /*
493          * A macro for Ldthis(); Ldfld();
494          */
495         internal void Ldthisfld(FieldInfo ft) {
496             Ldthis();
497             _ilg.Emit(OpCodes.Ldfld, ft);
498         }
499
500         /*
501          * A macro for Ldthis(); Ldfld(); Stloc();
502          */
503         internal void Mvfldloc(FieldInfo ft, LocalBuilder lt) {
504             Ldthisfld(ft);
505             Stloc(lt);
506         }
507
508         /*
509          * A macro for Ldthis(); Ldthisfld(); Stloc();
510          */
511         internal void Mvlocfld(LocalBuilder lt, FieldInfo ft) {
512             Ldthis();
513             Ldloc(lt);
514             Stfld(ft);
515         }
516
517         /*
518          * A macro for _ilg.Emit(OpCodes.Stfld);
519          */
520         internal void Stfld(FieldInfo ft) {
521             _ilg.Emit(OpCodes.Stfld, ft);
522         }
523
524         /*
525          * A macro for _ilg.Emit(OpCodes.Callvirt);
526          */
527         internal void Callvirt(MethodInfo mt) {
528             _ilg.Emit(OpCodes.Callvirt, mt);
529         }
530
531         /*
532          * A macro for _ilg.Emit(OpCodes.Call);
533          */
534         internal void Call(MethodInfo mt) {
535             _ilg.Emit(OpCodes.Call, mt);
536         }
537
538         /*
539          * A macro for _ilg.Emit(OpCodes.Newobj);
540          */
541         internal void Newobj(ConstructorInfo ct) {
542             _ilg.Emit(OpCodes.Newobj, ct);
543         }
544
545         /*
546          * A macro for _ilg.Emit(OpCodes.Brfalse) (long form)
547          */
548         internal void BrfalseFar(Label l) {
549             _ilg.Emit(OpCodes.Brfalse, l);
550         }
551
552         /*
553          * A macro for _ilg.Emit(OpCodes.Brtrue) (long form)
554          */
555         internal void BrtrueFar(Label l) {
556             _ilg.Emit(OpCodes.Brtrue, l);
557         }
558
559         /*
560          * A macro for _ilg.Emit(OpCodes.Br) (long form)
561          */
562         internal void BrFar(Label l) {
563             _ilg.Emit(OpCodes.Br, l);
564         }
565
566         /*
567          * A macro for _ilg.Emit(OpCodes.Ble) (long form)
568          */
569         internal void BleFar(Label l) {
570             _ilg.Emit(OpCodes.Ble, l);
571         }
572
573         /*
574          * A macro for _ilg.Emit(OpCodes.Blt) (long form)
575          */
576         internal void BltFar(Label l) {
577             _ilg.Emit(OpCodes.Blt, l);
578         }
579
580         /*
581          * A macro for _ilg.Emit(OpCodes.Bge) (long form)
582          */
583         internal void BgeFar(Label l) {
584             _ilg.Emit(OpCodes.Bge, l);
585         }
586
587         /*
588          * A macro for _ilg.Emit(OpCodes.Bgt) (long form)
589          */
590         internal void BgtFar(Label l) {
591             _ilg.Emit(OpCodes.Bgt, l);
592         }
593
594         /*
595          * A macro for _ilg.Emit(OpCodes.Bne) (long form)
596          */
597         internal void BneFar(Label l) {
598             _ilg.Emit(OpCodes.Bne_Un, l);
599         }
600
601         /*
602          * A macro for _ilg.Emit(OpCodes.Beq) (long form)
603          */
604         internal void BeqFar(Label l) {
605             _ilg.Emit(OpCodes.Beq, l);
606         }
607
608         /*
609          * A macro for _ilg.Emit(OpCodes.Brfalse_S) (short jump)
610          */
611         internal void Brfalse(Label l) {
612             _ilg.Emit(OpCodes.Brfalse_S, l);
613         }
614
615         /*
616          * A macro for _ilg.Emit(OpCodes.Br_S) (short jump)
617          */
618         internal void Br(Label l) {
619             _ilg.Emit(OpCodes.Br_S, l);
620         }
621
622         /*
623          * A macro for _ilg.Emit(OpCodes.Ble_S) (short jump)
624          */
625         internal void Ble(Label l) {
626             _ilg.Emit(OpCodes.Ble_S, l);
627         }
628
629         /*
630          * A macro for _ilg.Emit(OpCodes.Blt_S) (short jump)
631          */
632         internal void Blt(Label l) {
633             _ilg.Emit(OpCodes.Blt_S, l);
634         }
635
636         /*
637          * A macro for _ilg.Emit(OpCodes.Bge_S) (short jump)
638          */
639         internal void Bge(Label l) {
640             _ilg.Emit(OpCodes.Bge_S, l);
641         }
642
643         /*
644          * A macro for _ilg.Emit(OpCodes.Bgt_S) (short jump)
645          */
646         internal void Bgt(Label l) {
647             _ilg.Emit(OpCodes.Bgt_S, l);
648         }
649
650         /*
651          * A macro for _ilg.Emit(OpCodes.Bleun_S) (short jump)
652          */
653         internal void Bgtun(Label l) {
654             _ilg.Emit(OpCodes.Bgt_Un_S, l);
655         }
656
657         /*
658          * A macro for _ilg.Emit(OpCodes.Bne_S) (short jump)
659          */
660         internal void Bne(Label l) {
661             _ilg.Emit(OpCodes.Bne_Un_S, l);
662         }
663
664         /*
665          * A macro for _ilg.Emit(OpCodes.Beq_S) (short jump)
666          */
667         internal void Beq(Label l) {
668             _ilg.Emit(OpCodes.Beq_S, l);
669         }
670
671         /*
672          * A macro for the Ldlen instruction
673          */
674         internal void Ldlen() {
675             _ilg.Emit(OpCodes.Ldlen);
676         }
677
678         /*
679          * Loads the char to the right of the current position
680          */
681         internal void Rightchar() {
682             Ldloc(_textV);
683             Ldloc(_textposV);
684             Callvirt(_getcharM);
685         }
686
687         /*
688          * Loads the char to the right of the current position and advances the current position
689          */
690         internal void Rightcharnext() {
691             Ldloc(_textV);
692             Ldloc(_textposV);
693             Dup();
694             Ldc(1);
695             Add();
696             Stloc(_textposV);
697             Callvirt(_getcharM);
698         }
699
700         /*
701          * Loads the char to the left of the current position
702          */
703         internal void Leftchar() {
704             Ldloc(_textV);
705             Ldloc(_textposV);
706             Ldc(1);
707             Sub();
708             Callvirt(_getcharM);
709         }
710
711         /*
712          * Loads the char to the left of the current position and advances (leftward)
713          */
714         internal void Leftcharnext() {
715             Ldloc(_textV);
716             Ldloc(_textposV);
717             Ldc(1);
718             Sub();
719             Dup();
720             Stloc(_textposV);
721             Callvirt(_getcharM);
722         }
723
724         /*
725          * Creates a backtrack note and pushes the switch index it on the tracking stack
726          */
727         internal void Track() {
728             ReadyPushTrack();
729             Ldc(AddTrack());
730             DoPush();
731         }
732
733         /*
734          * Pushes the current switch index on the tracking stack so the backtracking
735          * logic will be repeated again next time we backtrack here.
736          *
737          * <
738
739 */
740         internal void Trackagain() {
741             ReadyPushTrack();
742             Ldc(_backpos);
743             DoPush();
744         }
745
746         /*
747          * Saves the value of a local variable on the tracking stack
748          */
749         internal void PushTrack(LocalBuilder lt) {
750             ReadyPushTrack();
751             Ldloc(lt);
752             DoPush();
753         }
754
755         /*
756          * Creates a backtrack note for a piece of code that should only be generated once,
757          * and emits code that pushes the switch index on the backtracking stack.
758          */
759         internal void TrackUnique(int i) {
760             ReadyPushTrack();
761             Ldc(AddUniqueTrack(i));
762             DoPush();
763         }
764
765         /*
766          * Creates a second-backtrack note for a piece of code that should only be
767          * generated once, and emits code that pushes the switch index on the
768          * backtracking stack.
769          */
770         internal void TrackUnique2(int i) {
771             ReadyPushTrack();
772             Ldc(AddUniqueTrack(i, RegexCode.Back2));
773             DoPush();
774         }
775
776         /*
777          * Prologue to code that will push an element on the tracking stack
778          */
779         internal void ReadyPushTrack() {
780             _ilg.Emit(OpCodes.Ldloc_S, _trackV);
781             _ilg.Emit(OpCodes.Ldloc_S, _trackposV);
782             _ilg.Emit(OpCodes.Ldc_I4_1);
783             _ilg.Emit(OpCodes.Sub);
784             _ilg.Emit(OpCodes.Dup);
785             _ilg.Emit(OpCodes.Stloc_S, _trackposV);
786         }
787
788         /*
789          * Pops an element off the tracking stack (leave it on the operand stack)
790          */
791         internal void PopTrack() {
792             _ilg.Emit(OpCodes.Ldloc_S, _trackV);
793             _ilg.Emit(OpCodes.Ldloc_S, _trackposV);
794             _ilg.Emit(OpCodes.Dup);
795             _ilg.Emit(OpCodes.Ldc_I4_1);
796             _ilg.Emit(OpCodes.Add);
797             _ilg.Emit(OpCodes.Stloc_S, _trackposV);
798             _ilg.Emit(OpCodes.Ldelem_I4);
799         }
800
801         /*
802          * Retrieves the top entry on the tracking stack without popping
803          */
804         internal void TopTrack() {
805             _ilg.Emit(OpCodes.Ldloc_S, _trackV);
806             _ilg.Emit(OpCodes.Ldloc_S, _trackposV);
807             _ilg.Emit(OpCodes.Ldelem_I4);
808         }
809
810         /*
811          * Saves the value of a local variable on the grouping stack
812          */
813         internal void PushStack(LocalBuilder lt) {
814             ReadyPushStack();
815             _ilg.Emit(OpCodes.Ldloc_S, lt);
816             DoPush();
817         }
818
819         /*
820          * Prologue to code that will replace the ith element on the grouping stack
821          */
822         internal void ReadyReplaceStack(int i) {
823             _ilg.Emit(OpCodes.Ldloc_S, _stackV);
824             _ilg.Emit(OpCodes.Ldloc_S, _stackposV);
825             if (i != 0) {
826                 Ldc(i);
827                 _ilg.Emit(OpCodes.Add);
828             }
829         }
830
831         /*
832          * Prologue to code that will push an element on the grouping stack
833          */
834         internal void ReadyPushStack() {
835             _ilg.Emit(OpCodes.Ldloc_S, _stackV);
836             _ilg.Emit(OpCodes.Ldloc_S, _stackposV);
837             _ilg.Emit(OpCodes.Ldc_I4_1);
838             _ilg.Emit(OpCodes.Sub);
839             _ilg.Emit(OpCodes.Dup);
840             _ilg.Emit(OpCodes.Stloc_S, _stackposV);
841         }
842
843         /*
844          * Retrieves the top entry on the stack without popping
845          */
846         internal void TopStack() {
847             _ilg.Emit(OpCodes.Ldloc_S, _stackV);
848             _ilg.Emit(OpCodes.Ldloc_S, _stackposV);
849             _ilg.Emit(OpCodes.Ldelem_I4);
850         }
851
852         /*
853          * Pops an element off the grouping stack (leave it on the operand stack)
854          */
855         internal void PopStack() {
856             _ilg.Emit(OpCodes.Ldloc_S, _stackV);
857             _ilg.Emit(OpCodes.Ldloc_S, _stackposV);
858             _ilg.Emit(OpCodes.Dup);
859             _ilg.Emit(OpCodes.Ldc_I4_1);
860             _ilg.Emit(OpCodes.Add);
861             _ilg.Emit(OpCodes.Stloc_S, _stackposV);
862             _ilg.Emit(OpCodes.Ldelem_I4);
863         }
864
865         /*
866          * Pops 1 element off the grouping stack and discards it
867          */
868         internal void PopDiscardStack() {
869             PopDiscardStack(1);
870         }
871
872         /*
873          * Pops i elements off the grouping stack and discards them
874          */
875         internal void PopDiscardStack(int i) {
876             _ilg.Emit(OpCodes.Ldloc_S, _stackposV);
877             Ldc(i);
878             _ilg.Emit(OpCodes.Add);
879             _ilg.Emit(OpCodes.Stloc_S, _stackposV);
880         }
881
882         /*
883          * Epilogue to code that will replace an element on a stack (use Ld* in between)
884          */
885         internal void DoReplace() {
886             _ilg.Emit(OpCodes.Stelem_I4);
887         }
888
889         /*
890          * Epilogue to code that will push an element on a stack (use Ld* in between)
891          */
892         internal void DoPush() {
893             _ilg.Emit(OpCodes.Stelem_I4);
894         }
895
896         /*
897          * Jump to the backtracking switch
898          */
899         internal void Back() {
900             _ilg.Emit(OpCodes.Br, _backtrack);
901         }
902
903         /*
904          * Branch to the MSIL corresponding to the regex code at i
905          *
906          * A trick: since track and stack space is gobbled up unboundedly
907          * only as a result of branching backwards, this is where we check
908          * for sufficient space and trigger reallocations.
909          *
910          * If the "goto" is backwards, we generate code that checks
911          * available space against the amount of space that would be needed
912          * in the worst case by code that will only go forward; if there's
913          * not enough, we push the destination on the tracking stack, then
914          * we jump to the place where we invoke the allocator.
915          *
916          * Since forward gotos pose no threat, they just turn into a Br.
917          */
918         internal void Goto(int i) {
919             if (i < _codepos) {
920                 Label l1 = DefineLabel();
921
922                 // When going backwards, ensure enough space.
923                 Ldloc(_trackposV);
924                 Ldc(_trackcount * 4);
925                 Ble(l1);
926                 Ldloc(_stackposV);
927                 Ldc(_trackcount * 3);
928                 BgtFar(_labels[i]);
929                 MarkLabel(l1); 
930                 ReadyPushTrack();
931                 Ldc(AddGoto(i));
932                 DoPush();
933                 BrFar(_backtrack);
934             }
935             else {
936                 BrFar(_labels[i]);
937             }
938         }
939
940         /*
941          * Returns the position of the next operation in the regex code, taking
942          * into account the different numbers of arguments taken by operations
943          */
944         internal int NextCodepos() {
945             return _codepos + RegexCode.OpcodeSize(_codes[_codepos]);
946         }
947
948         /*
949          * The label for the next (forward) operation
950          */
951         internal Label AdvanceLabel() {
952             return _labels[NextCodepos()];
953         }
954
955         /*
956          * Goto the next (forward) operation
957          */
958         internal void Advance() {
959             _ilg.Emit(OpCodes.Br, AdvanceLabel());
960         }
961
962         internal void CallToLower()
963         {
964             if ((_options & RegexOptions.CultureInvariant) != 0)
965                 Call(_getInvariantCulture);
966             else
967                 Call(_getCurrentCulture);
968             
969             Call(_chartolowerM);
970         }
971
972         /*
973          * Generates the first section of the MSIL. This section contains all
974          * the forward logic, and corresponds directly to the regex codes.
975          *
976          * In the absence of backtracking, this is all we would need.
977          */
978         internal void GenerateForwardSection() {
979             int codepos;
980
981             _labels = new Label[_codes.Length];
982             _goto   = new int[_codes.Length];
983
984             // initialize
985
986             for (codepos = 0; codepos < _codes.Length; codepos += RegexCode.OpcodeSize(_codes[codepos])) {
987                 _goto[codepos]   = -1;
988                 _labels[codepos] = _ilg.DefineLabel();
989             }
990
991             _uniquenote   = new int[uniquecount];
992             for (int i = 0; i < uniquecount; i++)
993                 _uniquenote[i] = -1;
994
995             // emit variable initializers
996
997             Mvfldloc(_textF,      _textV);
998             Mvfldloc(_textstartF, _textstartV);
999             Mvfldloc(_textbegF,   _textbegV);
1000             Mvfldloc(_textendF,   _textendV);
1001             Mvfldloc(_textposF,   _textposV);
1002             Mvfldloc(_trackF,     _trackV);
1003             Mvfldloc(_trackposF,  _trackposV);
1004             Mvfldloc(_stackF,     _stackV);
1005             Mvfldloc(_stackposF,  _stackposV);
1006
1007             _backpos = -1;
1008
1009             for (codepos = 0; codepos < _codes.Length; codepos += RegexCode.OpcodeSize(_codes[codepos])) {
1010                 MarkLabel(_labels[codepos]);
1011                 _codepos = codepos;
1012                 _regexopcode = _codes[codepos];
1013                 GenerateOneCode();
1014             }
1015         }
1016
1017         /*
1018          * Generates the middle section of the MSIL. This section contains the
1019          * big switch jump that allows us to simulate a stack of addresses,
1020          * and it also contains the calls that expand the tracking and the
1021          * grouping stack when they get too full.
1022          */
1023         internal void GenerateMiddleSection() {
1024 #pragma warning disable 219
1025             Label l1 = DefineLabel();
1026 #pragma warning restore 219
1027             Label[] table;
1028             int i;
1029
1030             // Backtrack switch
1031             MarkLabel(_backtrack);
1032
1033             // first call EnsureStorage 
1034             Mvlocfld(_trackposV, _trackposF);
1035             Mvlocfld(_stackposV, _stackposF);
1036             Ldthis();
1037             Callvirt(_ensurestorageM);
1038             Mvfldloc(_trackposF, _trackposV);
1039             Mvfldloc(_stackposF, _stackposV);
1040             Mvfldloc(_trackF, _trackV);
1041             Mvfldloc(_stackF, _stackV);
1042
1043
1044             PopTrack();
1045
1046             table = new Label[_notecount];
1047             for (i = 0; i < _notecount; i++)
1048                 table[i] = _notes[i]._label;
1049
1050             _ilg.Emit(OpCodes.Switch, table);
1051
1052         }
1053
1054         /*
1055          * Generates the last section of the MSIL. This section contains all of
1056          * the backtracking logic.
1057          */
1058         internal void GenerateBacktrackSection() {
1059             int i;
1060
1061             for (i = 0; i < _notecount; i++) {
1062                 BacktrackNote n = _notes[i];
1063                 if (n._flags != 0) {
1064                     _ilg.MarkLabel(n._label);
1065                     _codepos = n._codepos;
1066                     _backpos = i;
1067                     _regexopcode = _codes[n._codepos] | n._flags;
1068                     GenerateOneCode();
1069                 }
1070             }
1071         }
1072
1073         /*
1074          * Generates FindFirstChar
1075          */
1076         // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1077         // !!!! This function must be kept synchronized with FindFirstChar in      !!!!
1078         // !!!! RegexInterpreter.cs                                                !!!!
1079         // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1080         internal void GenerateFindFirstChar() {
1081             _textposV       = DeclareInt();
1082             _textV          = DeclareString();
1083             _tempV          = DeclareInt();
1084             _temp2V         = DeclareInt();
1085
1086             if (0 != (_anchors & (RegexFCD.Beginning | RegexFCD.Start | RegexFCD.EndZ | RegexFCD.End))) {
1087                 if (!_code._rightToLeft) {
1088                     if (0 != (_anchors & RegexFCD.Beginning)) {
1089                         Label l1 = DefineLabel();
1090                         Ldthisfld(_textposF);
1091                         Ldthisfld(_textbegF);
1092                         Ble(l1);
1093                         Ldthis();
1094                         Ldthisfld(_textendF);
1095                         Stfld(_textposF);
1096                         Ldc(0);
1097                         Ret();
1098                         MarkLabel(l1);
1099                     }
1100
1101                     if (0 != (_anchors & RegexFCD.Start)) {
1102                         Label l1 = DefineLabel();
1103                         Ldthisfld(_textposF);
1104                         Ldthisfld(_textstartF);
1105                         Ble(l1);
1106                         Ldthis();
1107                         Ldthisfld(_textendF);
1108                         Stfld(_textposF);
1109                         Ldc(0);
1110                         Ret();
1111                         MarkLabel(l1);
1112                     }
1113
1114                     if (0 != (_anchors & RegexFCD.EndZ)) {
1115                         Label l1 = DefineLabel();
1116                         Ldthisfld(_textposF);
1117                         Ldthisfld(_textendF);
1118                         Ldc(1);
1119                         Sub();
1120                         Bge(l1);
1121                         Ldthis();
1122                         Ldthisfld(_textendF);
1123                         Ldc(1);
1124                         Sub();
1125                         Stfld(_textposF);
1126                         MarkLabel(l1);
1127                     }
1128
1129                     if (0 != (_anchors & RegexFCD.End)) {
1130                         Label l1 = DefineLabel();
1131                         Ldthisfld(_textposF);
1132                         Ldthisfld(_textendF);
1133                         Bge(l1);
1134                         Ldthis();
1135                         Ldthisfld(_textendF);
1136                         Stfld(_textposF);
1137                         MarkLabel(l1);
1138                     }
1139                 }
1140                 else {
1141                     if (0 != (_anchors & RegexFCD.End)) {
1142                         Label l1 = DefineLabel();
1143                         Ldthisfld(_textposF);
1144                         Ldthisfld(_textendF);
1145                         Bge(l1);
1146                         Ldthis();
1147                         Ldthisfld(_textbegF);
1148                         Stfld(_textposF);
1149                         Ldc(0);
1150                         Ret();
1151                         MarkLabel(l1);
1152                     }
1153
1154                     if (0 != (_anchors & RegexFCD.EndZ)) {
1155                         Label l1 = DefineLabel();
1156                         Label l2 = DefineLabel();
1157                         Ldthisfld(_textposF);
1158                         Ldthisfld(_textendF);
1159                         Ldc(1);
1160                         Sub();
1161                         Blt(l1);
1162                         Ldthisfld(_textposF);
1163                         Ldthisfld(_textendF);
1164                         Beq(l2);
1165                         Ldthisfld(_textF);
1166                         Ldthisfld(_textposF);
1167                         Callvirt(_getcharM);
1168                         Ldc((int)'\n');
1169                         Beq(l2);
1170                         MarkLabel(l1);
1171                         Ldthis();
1172                         Ldthisfld(_textbegF);
1173                         Stfld(_textposF);
1174                         Ldc(0);
1175                         Ret();
1176                         MarkLabel(l2);
1177                     }
1178
1179                     if (0 != (_anchors & RegexFCD.Start)) {
1180                         Label l1 = DefineLabel();
1181                         Ldthisfld(_textposF);
1182                         Ldthisfld(_textstartF);
1183                         Bge(l1);
1184                         Ldthis();
1185                         Ldthisfld(_textbegF);
1186                         Stfld(_textposF);
1187                         Ldc(0);
1188                         Ret();
1189                         MarkLabel(l1);
1190                     }
1191
1192                     if (0 != (_anchors & RegexFCD.Beginning)) {
1193                         Label l1 = DefineLabel();
1194                         Ldthisfld(_textposF);
1195                         Ldthisfld(_textbegF);
1196                         Ble(l1);
1197                         Ldthis();
1198                         Ldthisfld(_textbegF);
1199                         Stfld(_textposF);
1200                         MarkLabel(l1);
1201                     }
1202                 }
1203
1204                 // <
1205
1206
1207                 Ldc(1);
1208                 Ret();
1209             }
1210             else if (_bmPrefix != null && _bmPrefix._negativeUnicode == null) {
1211                 // Compiled Boyer-Moore string matching
1212                 // <
1213
1214
1215                 LocalBuilder chV      = _tempV;
1216                 LocalBuilder testV    = _tempV;
1217                 LocalBuilder limitV   = _temp2V;
1218                 Label      lDefaultAdvance  = DefineLabel();
1219                 Label      lAdvance         = DefineLabel();
1220                 Label      lFail            = DefineLabel();
1221                 Label      lStart           = DefineLabel();
1222 #pragma warning disable 219
1223                 Label      lOutOfRange      = DefineLabel();
1224 #pragma warning restore 219
1225                 Label      lPartialMatch    = DefineLabel();
1226
1227
1228                 int chLast;
1229                 int i;
1230                 int beforefirst;
1231                 int last;
1232                 Label[] table;
1233
1234                 if (!_code._rightToLeft) {
1235                     beforefirst = -1;
1236                     last = _bmPrefix._pattern.Length - 1;
1237                 }
1238                 else {
1239                     beforefirst = _bmPrefix._pattern.Length;
1240                     last = 0;
1241                 }
1242
1243                 chLast = _bmPrefix._pattern[last];
1244
1245                 Mvfldloc(_textF, _textV);
1246                 if (!_code._rightToLeft)
1247                     Ldthisfld(_textendF);
1248                 else
1249                     Ldthisfld(_textbegF);
1250                 Stloc(limitV);
1251
1252                 Ldthisfld(_textposF);
1253                 if (!_code._rightToLeft) {
1254                     Ldc(_bmPrefix._pattern.Length - 1);
1255                     Add();
1256                 }
1257                 else {
1258                     Ldc(_bmPrefix._pattern.Length);
1259                     Sub();
1260                 }
1261                 Stloc(_textposV);
1262                 Br(lStart);
1263
1264                 MarkLabel(lDefaultAdvance);
1265
1266                 if (!_code._rightToLeft)
1267                     Ldc(_bmPrefix._pattern.Length);
1268                 else
1269                     Ldc(-_bmPrefix._pattern.Length);
1270
1271                 MarkLabel(lAdvance);
1272
1273                 Ldloc(_textposV);
1274                 Add();
1275                 Stloc(_textposV);
1276
1277                 MarkLabel(lStart);
1278
1279                 Ldloc(_textposV);
1280                 Ldloc(limitV);
1281                 if (!_code._rightToLeft)
1282                     BgeFar(lFail);
1283                 else
1284                     BltFar(lFail);
1285
1286                 Rightchar();
1287                 if (_bmPrefix._caseInsensitive)
1288                     CallToLower();
1289
1290                 Dup();
1291                 Stloc(chV);
1292                 Ldc(chLast);
1293                 BeqFar(lPartialMatch);
1294
1295                 Ldloc(chV);
1296                 Ldc(_bmPrefix._lowASCII);
1297                 Sub();
1298                 Dup();
1299                 Stloc(chV);
1300                 Ldc(_bmPrefix._highASCII - _bmPrefix._lowASCII);
1301                 Bgtun(lDefaultAdvance);
1302
1303                 table = new Label[_bmPrefix._highASCII - _bmPrefix._lowASCII + 1];
1304
1305                 for (i = _bmPrefix._lowASCII; i <= _bmPrefix._highASCII; i++) {
1306                     if (_bmPrefix._negativeASCII[i] == beforefirst)
1307                         table[i - _bmPrefix._lowASCII] = lDefaultAdvance;
1308                     else
1309                         table[i - _bmPrefix._lowASCII] = DefineLabel();
1310                 }
1311
1312                 Ldloc(chV);
1313                 _ilg.Emit(OpCodes.Switch, table);
1314
1315                 for (i = _bmPrefix._lowASCII; i <= _bmPrefix._highASCII; i++) {
1316                     if (_bmPrefix._negativeASCII[i] == beforefirst)
1317                         continue;
1318
1319                     MarkLabel(table[i - _bmPrefix._lowASCII]);
1320
1321                     Ldc(_bmPrefix._negativeASCII[i]);
1322                     BrFar(lAdvance);
1323                 }
1324
1325                 MarkLabel(lPartialMatch);
1326
1327                 Ldloc(_textposV);
1328                 Stloc(testV);
1329
1330                 for (i = _bmPrefix._pattern.Length - 2; i >= 0; i--) {
1331                     Label lNext = DefineLabel();
1332                     int charindex;
1333
1334                     if (!_code._rightToLeft)
1335                         charindex = i;
1336                     else
1337                         charindex = _bmPrefix._pattern.Length - 1 - i;
1338
1339                     Ldloc(_textV);
1340                     Ldloc(testV);
1341                     Ldc(1);
1342                     Sub(_code._rightToLeft);
1343                     Dup();
1344                     Stloc(testV);
1345                     Callvirt(_getcharM);
1346                     if (_bmPrefix._caseInsensitive)
1347                         CallToLower();
1348                     
1349                     Ldc(_bmPrefix._pattern[charindex]);
1350                     Beq(lNext);
1351                     Ldc(_bmPrefix._positive[charindex]);
1352                     BrFar(lAdvance);
1353
1354                     MarkLabel(lNext);
1355
1356                 }
1357
1358                 Ldthis();
1359                 Ldloc(testV);
1360                 if (_code._rightToLeft) {
1361                     Ldc(1);
1362                     Add();
1363                 }
1364                 Stfld(_textposF);
1365                 Ldc(1);
1366                 Ret();
1367
1368                 MarkLabel(lFail);
1369
1370                 Ldthis();
1371                 if (!_code._rightToLeft)
1372                     Ldthisfld(_textendF);
1373                 else
1374                     Ldthisfld(_textbegF);
1375                 Stfld(_textposF);
1376                 Ldc(0);
1377                 Ret();
1378             }
1379             else if (_fcPrefix == null) {
1380                 Ldc(1);
1381                 Ret();
1382             }
1383             else {
1384                 LocalBuilder cV   = _temp2V;
1385 #pragma warning disable 219
1386                 LocalBuilder chV  = _tempV;
1387 #pragma warning restore 219
1388                 Label      l1   = DefineLabel();
1389                 Label      l2   = DefineLabel();
1390                 Label      l3   = DefineLabel();
1391                 Label      l4   = DefineLabel();
1392                 Label      l5   = DefineLabel();
1393
1394                 Mvfldloc(_textposF, _textposV);
1395                 Mvfldloc(_textF, _textV);
1396
1397                 if (!_code._rightToLeft) {
1398                     Ldthisfld(_textendF);
1399                     Ldloc(_textposV);
1400                 }
1401                 else {
1402                     Ldloc(_textposV);
1403                     Ldthisfld(_textbegF);
1404                 }
1405                 Sub();
1406                 Stloc(cV);
1407
1408                 Ldloc(cV);
1409                 Ldc(0);
1410                 BleFar(l4);
1411
1412                 MarkLabel(l1);
1413
1414                 Ldloc(cV);
1415                 Ldc(1);
1416                 Sub();
1417                 Stloc(cV);
1418
1419                 if (_code._rightToLeft)
1420                     Leftcharnext();
1421                 else
1422                     Rightcharnext();
1423
1424                 if (_fcPrefix.CaseInsensitive)
1425                     CallToLower();
1426                 
1427                 if (!RegexCharClass.IsSingleton(_fcPrefix.Prefix)) {
1428                     Ldstr(_fcPrefix.Prefix);
1429                     Call(_charInSetM);
1430
1431                     BrtrueFar(l2);
1432                 }
1433                 else {
1434                     Ldc(RegexCharClass.SingletonChar(_fcPrefix.Prefix));
1435                     Beq(l2);
1436                 }
1437
1438                 MarkLabel(l5);
1439
1440                 Ldloc(cV);
1441                 Ldc(0);
1442                 if (!RegexCharClass.IsSingleton(_fcPrefix.Prefix))
1443                     BgtFar(l1);
1444                 else
1445                     Bgt(l1);
1446
1447                 Ldc(0);
1448                 BrFar(l3);
1449
1450                 MarkLabel(l2);
1451
1452                 /*          // CURRENTLY DISABLED
1453                             // If for some reason we have a prefix we didn't use, use it now.
1454                 
1455                             if (_bmPrefix != null) {
1456                                 if (!_code._rightToLeft) {
1457                                     Ldthisfld(_textendF);
1458                                     Ldloc(_textposV);
1459                                 }
1460                                 else {
1461                                     Ldloc(_textposV);
1462                                     Ldthisfld(_textbegF);
1463                                 }
1464                                 Sub();
1465                                 Ldc(_bmPrefix._pattern.Length - 1);
1466                                 BltFar(l5);
1467                                 
1468                                 for (int i = 1; i < _bmPrefix._pattern.Length; i++) {
1469                                     Ldloc(_textV);
1470                                     Ldloc(_textposV);
1471                                     if (!_code._rightToLeft) {
1472                                         Ldc(i - 1);
1473                                         Add();
1474                                     }
1475                                     else {
1476                                         Ldc(i);
1477                                         Sub();
1478                                     }
1479                                     Callvirt(_getcharM);
1480                                     if (!_code._rightToLeft)
1481                                         Ldc(_bmPrefix._pattern[i]);
1482                                     else
1483                                         Ldc(_bmPrefix._pattern[_bmPrefix._pattern.Length - 1 - i]);
1484                                     BneFar(l5);
1485                                 }
1486                             }
1487                 */
1488
1489                 Ldloc(_textposV);
1490                 Ldc(1);
1491                 Sub(_code._rightToLeft);
1492                 Stloc(_textposV);
1493                 Ldc(1);
1494
1495                 MarkLabel(l3);
1496
1497                 Mvlocfld(_textposV, _textposF);
1498                 Ret();
1499
1500                 MarkLabel(l4);
1501                 Ldc(0);
1502                 Ret();
1503             }
1504
1505         }
1506
1507         /*
1508          * Generates a very simple method that sets the _trackcount field.
1509          */
1510         internal void GenerateInitTrackCount() {
1511             Ldthis();
1512             Ldc(_trackcount);
1513             Stfld(_trackcountF);
1514             Ret();
1515         }
1516
1517         /*
1518          * Declares a local int
1519          */
1520         internal LocalBuilder DeclareInt() {
1521             return _ilg.DeclareLocal(typeof(int));            
1522         }
1523
1524         /*
1525          * Declares a local int array
1526          */
1527         internal LocalBuilder DeclareIntArray() {
1528             return _ilg.DeclareLocal(typeof(int[]));
1529         }
1530
1531         /*
1532          * Declares a local string
1533          */
1534         internal LocalBuilder DeclareString() {
1535             return _ilg.DeclareLocal(typeof(string));
1536         }
1537         
1538         /*
1539          * Generates the code for "RegexRunner.Go"
1540          */
1541         internal void GenerateGo() {
1542             // declare some locals
1543
1544             _textposV       = DeclareInt();
1545             _textV          = DeclareString();
1546             _trackposV      = DeclareInt();
1547             _trackV         = DeclareIntArray();
1548             _stackposV      = DeclareInt();
1549             _stackV         = DeclareIntArray();
1550             _tempV          = DeclareInt();
1551             _temp2V         = DeclareInt();
1552             _temp3V         = DeclareInt();
1553             _textbegV       = DeclareInt();
1554             _textendV       = DeclareInt();
1555             _textstartV     = DeclareInt();
1556
1557             // clear some tables
1558
1559             _labels = null;
1560             _notes = null;
1561             _notecount = 0;
1562
1563             // globally used labels
1564
1565             _backtrack = DefineLabel();
1566
1567             // emit the code!
1568
1569             GenerateForwardSection();
1570             GenerateMiddleSection();
1571             GenerateBacktrackSection();
1572         }
1573
1574 #if DBG
1575         /*
1576          * Some simple debugging stuff
1577          */
1578         internal static MethodInfo _debugWriteLine = typeof(Debug).GetMethod("WriteLine", new Type[] {typeof(string)});
1579
1580         /*
1581          * Debug only: emit code to print out a message
1582          */
1583         internal void Message(String str) {
1584             Ldstr(str);
1585             Call(_debugWriteLine);
1586         }
1587
1588 #endif
1589
1590         /*
1591          * The main translation function. It translates the logic for a single opcode at
1592          * the current position. The structure of this function exactly mirrors
1593          * the structure of the inner loop of RegexInterpreter.Go().
1594          *
1595          * The C# code from RegexInterpreter.Go() that corresponds to each case is
1596          * included as a comment.
1597          *
1598          * Note that since we're generating code, we can collapse many cases that are
1599          * dealt with one-at-a-time in RegexIntepreter. We can also unroll loops that
1600          * iterate over constant strings or sets.
1601          */
1602         internal void GenerateOneCode() {
1603 #if DBG
1604             if ((_options & RegexOptions.Debug) != 0) {
1605                 Mvlocfld(_textposV, _textposF);
1606                 Mvlocfld(_trackposV, _trackposF);
1607                 Mvlocfld(_stackposV, _stackposF);
1608                 Ldthis();
1609                 Callvirt(_dumpstateM);
1610                 StringBuilder sb = new StringBuilder();
1611                 if (_backpos > 0)
1612                     sb.AppendFormat("{0:D6} ", _backpos);
1613                 else
1614                     sb.Append("       ");
1615                 sb.Append(_code.OpcodeDescription(_codepos));
1616                 if (IsBack())
1617                     sb.Append(" Back");
1618                 if (IsBack2())
1619                     sb.Append(" Back2");
1620                 Message(sb.ToString());
1621             }
1622 #endif
1623
1624             // Before executing any RegEx code in the unrolled loop,
1625             // we try checking for the match timeout:
1626
1627             Ldthis();            
1628             Callvirt(_checkTimeoutM);
1629
1630             // Now generate the IL for the RegEx code saved in _regexopcode.
1631             // We unroll the loop done by the RegexCompiler creating as very long method
1632             // that is longer if the pattern is longer:
1633
1634             switch (_regexopcode) {
1635                 case RegexCode.Stop:
1636                     //: return;
1637                     Mvlocfld(_textposV, _textposF);       // update _textpos
1638                     Ret();
1639                     break;
1640
1641                 case RegexCode.Nothing:
1642                     //: break Backward;
1643                     Back();
1644                     break;
1645
1646                 case RegexCode.Goto:
1647                     //: Goto(Operand(0));
1648                     Goto(Operand(0));
1649                     break;
1650
1651                 case RegexCode.Testref:
1652                     //: if (!_match.IsMatched(Operand(0)))
1653                     //:     break Backward;
1654                     Ldthis();
1655                     Ldc(Operand(0));
1656                     Callvirt(_ismatchedM);
1657                     BrfalseFar(_backtrack);
1658                     break;
1659
1660                 case RegexCode.Lazybranch:
1661                     //: Track(Textpos());
1662                     PushTrack(_textposV);
1663                     Track();
1664                     break;
1665
1666                 case RegexCode.Lazybranch | RegexCode.Back:
1667                     //: Trackframe(1);
1668                     //: Textto(Tracked(0));
1669                     //: Goto(Operand(0));
1670                     PopTrack();
1671                     Stloc(_textposV);
1672                     Goto(Operand(0));
1673                     break;
1674
1675                 case RegexCode.Nullmark:
1676                     //: Stack(-1);
1677                     //: Track();
1678                     ReadyPushStack();
1679                     Ldc(-1);
1680                     DoPush();
1681                     TrackUnique(stackpop);
1682                     break;
1683
1684                 case RegexCode.Setmark:
1685                     //: Stack(Textpos());
1686                     //: Track();
1687                     PushStack(_textposV);
1688                     TrackUnique(stackpop);
1689                     break;
1690
1691                 case RegexCode.Nullmark | RegexCode.Back:
1692                 case RegexCode.Setmark | RegexCode.Back:
1693                     //: Stackframe(1);
1694                     //: break Backward;
1695                     PopDiscardStack();
1696                     Back();
1697                     break;
1698
1699                 case RegexCode.Getmark:
1700                     //: Stackframe(1);
1701                     //: Track(Stacked(0));
1702                     //: Textto(Stacked(0));
1703                     ReadyPushTrack();
1704                     PopStack();
1705                     Dup();
1706                     Stloc(_textposV);
1707                     DoPush();
1708
1709                     Track();
1710                     break;
1711
1712                 case RegexCode.Getmark | RegexCode.Back:
1713                     //: Trackframe(1);
1714                     //: Stack(Tracked(0));
1715                     //: break Backward;
1716                     ReadyPushStack();
1717                     PopTrack();
1718                     DoPush();
1719                     Back();
1720                     break;
1721
1722                 case RegexCode.Capturemark:
1723                     //: if (!IsMatched(Operand(1)))
1724                     //:     break Backward;
1725                     //: Stackframe(1);
1726                     //: if (Operand(1) != -1)
1727                     //:     TransferCapture(Operand(0), Operand(1), Stacked(0), Textpos());
1728                     //: else
1729                     //:     Capture(Operand(0), Stacked(0), Textpos());
1730                     //: Track(Stacked(0));
1731
1732                     //: Stackframe(1);
1733                     //: Capture(Operand(0), Stacked(0), Textpos());
1734                     //: Track(Stacked(0));
1735
1736                     if (Operand(1) != -1) {
1737                         Ldthis();
1738                         Ldc(Operand(1));
1739                         Callvirt(_ismatchedM);
1740                         BrfalseFar(_backtrack);
1741                     }
1742
1743                     PopStack();
1744                     Stloc(_tempV);
1745
1746                     if (Operand(1) != -1) {
1747                         Ldthis();
1748                         Ldc(Operand(0));
1749                         Ldc(Operand(1));
1750                         Ldloc(_tempV);
1751                         Ldloc(_textposV);
1752                         Callvirt(_transferM);
1753                     }
1754                     else {
1755                         Ldthis();
1756                         Ldc(Operand(0));
1757                         Ldloc(_tempV);
1758                         Ldloc(_textposV);
1759                         Callvirt(_captureM);
1760                     }
1761
1762                     PushTrack(_tempV);
1763
1764                     if (Operand(0) != -1 && Operand(1) != -1)
1765                         TrackUnique(capback2);
1766                     else
1767                         TrackUnique(capback);
1768
1769                     break;
1770
1771
1772                 case RegexCode.Capturemark | RegexCode.Back:
1773                     //: Trackframe(1);
1774                     //: Stack(Tracked(0));
1775                     //: Uncapture();
1776                     //: if (Operand(0) != -1 && Operand(1) != -1)
1777                     //:     Uncapture();
1778                     //: break Backward;
1779                     ReadyPushStack();
1780                     PopTrack();
1781                     DoPush();
1782                     Ldthis();
1783                     Callvirt(_uncaptureM);
1784                     if (Operand(0) != -1 && Operand(1) != -1) {
1785                         Ldthis();
1786                         Callvirt(_uncaptureM);
1787                     }
1788                     Back();
1789                     break;
1790
1791                 case RegexCode.Branchmark:
1792                     //: Stackframe(1);
1793                     //: 
1794                     //: if (Textpos() != Stacked(0))
1795                     //: {                                   // Nonempty match -> loop now
1796                     //:     Track(Stacked(0), Textpos());   // Save old mark, textpos
1797                     //:     Stack(Textpos());               // Make new mark
1798                     //:     Goto(Operand(0));               // Loop
1799                     //: }
1800                     //: else
1801                     //: {                                   // Empty match -> straight now
1802                     //:     Track2(Stacked(0));             // Save old mark
1803                     //:     Advance(1);                     // Straight
1804                     //: }
1805                     //: continue Forward;
1806                     {
1807                         LocalBuilder mark = _tempV;
1808                         Label      l1   = DefineLabel();
1809
1810                         PopStack();
1811                         Dup();
1812                         Stloc(mark);                            // Stacked(0) -> temp
1813                         PushTrack(mark);
1814                         Ldloc(_textposV);
1815                         Beq(l1);                                // mark == textpos -> branch
1816
1817                         // (matched != 0)
1818
1819                         PushTrack(_textposV);
1820                         PushStack(_textposV);
1821                         Track();
1822                         Goto(Operand(0));                       // Goto(Operand(0))
1823
1824                         // else
1825
1826                         MarkLabel(l1);
1827                         TrackUnique2(branchmarkback2);
1828                         break;
1829                     }
1830
1831                 case RegexCode.Branchmark | RegexCode.Back:
1832                     //: Trackframe(2);
1833                     //: Stackframe(1);
1834                     //: Textto(Tracked(1));                     // Recall position
1835                     //: Track2(Tracked(0));                     // Save old mark
1836                     //: Advance(1);
1837                     PopTrack();
1838                     Stloc(_textposV);
1839                     PopStack();
1840                     Pop();
1841                     // track spot 0 is already in place
1842                     TrackUnique2(branchmarkback2);
1843                     Advance();
1844                     break;
1845
1846                 case RegexCode.Branchmark | RegexCode.Back2:
1847                     //: Trackframe(1);
1848                     //: Stack(Tracked(0));                      // Recall old mark
1849                     //: break Backward;                         // Backtrack
1850                     ReadyPushStack();
1851                     PopTrack();
1852                     DoPush();
1853                     Back();
1854                     break;
1855
1856
1857                 case RegexCode.Lazybranchmark:
1858                     //: StackPop();
1859                     //: int oldMarkPos = StackPeek();
1860                     //: 
1861                     //: if (Textpos() != oldMarkPos) {         // Nonempty match -> next loop
1862                     //: {                                   // Nonempty match -> next loop
1863                     //:     if (oldMarkPos != -1)
1864                     //:         Track(Stacked(0), Textpos());   // Save old mark, textpos
1865                     //:     else
1866                     //:         TrackPush(Textpos(), Textpos());   
1867                     //: }
1868                     //: else
1869                     //: {                                   // Empty match -> no loop
1870                     //:     Track2(Stacked(0));             // Save old mark
1871                     //: }
1872                     //: Advance(1);
1873                     //: continue Forward;
1874                     {
1875                         LocalBuilder mark = _tempV;
1876                         Label      l1   = DefineLabel();
1877                         Label      l2   = DefineLabel();
1878                         Label      l3   = DefineLabel();
1879
1880                         PopStack();
1881                         Dup();
1882                         Stloc(mark);                      // Stacked(0) -> temp
1883
1884                         // if (oldMarkPos != -1)
1885                         Ldloc(mark);
1886                         Ldc(-1);
1887                         Beq(l2);                                // mark == -1 -> branch
1888                             PushTrack(mark);
1889                             Br(l3);
1890                         // else
1891                             MarkLabel(l2);
1892                             PushTrack(_textposV);
1893                         MarkLabel(l3);
1894                             
1895                         // if (Textpos() != mark)
1896                         Ldloc(_textposV);
1897                         Beq(l1);                                // mark == textpos -> branch
1898                             PushTrack(_textposV);
1899                             Track();
1900                             Br(AdvanceLabel());                 // Advance (near)
1901                         // else
1902                             MarkLabel(l1);
1903                             ReadyPushStack();                   // push the current textPos on the stack. 
1904                                                                 // May be ignored by 'back2' or used by a true empty match.
1905                             Ldloc(mark);                        
1906
1907                             DoPush();
1908                             TrackUnique2(lazybranchmarkback2);
1909
1910                         break;
1911                     }
1912
1913                 case RegexCode.Lazybranchmark | RegexCode.Back:
1914                     //: Trackframe(2);
1915                     //: Track2(Tracked(0));                     // Save old mark
1916                     //: Stack(Textpos());                       // Make new mark
1917                     //: Textto(Tracked(1));                     // Recall position
1918                     //: Goto(Operand(0));                       // Loop
1919
1920                     PopTrack();
1921                     Stloc(_textposV);
1922                     PushStack(_textposV);
1923                     TrackUnique2(lazybranchmarkback2);
1924                     Goto(Operand(0));
1925                     break;
1926
1927                 case RegexCode.Lazybranchmark | RegexCode.Back2:
1928                     //: Stackframe(1);
1929                     //: Trackframe(1);
1930                     //: Stack(Tracked(0));                  // Recall old mark
1931                     //: break Backward;
1932                     ReadyReplaceStack(0);
1933                     PopTrack();
1934                     DoReplace();
1935                     Back();
1936                     break;
1937
1938                 case RegexCode.Nullcount:
1939                     //: Stack(-1, Operand(0));
1940                     //: Track();
1941                     ReadyPushStack();
1942                     Ldc(-1);
1943                     DoPush();
1944                     ReadyPushStack();
1945                     Ldc(Operand(0));
1946                     DoPush();
1947                     TrackUnique(stackpop2);
1948                     break;
1949
1950                 case RegexCode.Setcount:
1951                     //: Stack(Textpos(), Operand(0));
1952                     //: Track();
1953                     PushStack(_textposV);
1954                     ReadyPushStack();
1955                     Ldc(Operand(0));
1956                     DoPush();
1957                     TrackUnique(stackpop2);
1958                     break;
1959
1960
1961                 case RegexCode.Nullcount | RegexCode.Back:
1962                 case RegexCode.Setcount | RegexCode.Back:
1963                     //: Stackframe(2);
1964                     //: break Backward;
1965                     PopDiscardStack(2);
1966                     Back();
1967                     break;
1968
1969
1970                 case RegexCode.Branchcount:
1971                     //: Stackframe(2);
1972                     //: int mark = Stacked(0);
1973                     //: int count = Stacked(1);
1974                     //: 
1975                     //: if (count >= Operand(1) || Textpos() == mark && count >= 0)
1976                     //: {                                   // Max loops or empty match -> straight now
1977                     //:     Track2(mark, count);            // Save old mark, count
1978                     //:     Advance(2);                     // Straight
1979                     //: }
1980                     //: else
1981                     //: {                                   // Nonempty match -> count+loop now
1982                     //:     Track(mark);                    // remember mark
1983                     //:     Stack(Textpos(), count + 1);    // Make new mark, incr count
1984                     //:     Goto(Operand(0));               // Loop
1985                     //: }
1986                     //: continue Forward;
1987                     {
1988                         LocalBuilder count = _tempV;
1989                         LocalBuilder mark  = _temp2V;
1990                         Label      l1    = DefineLabel();
1991                         Label      l2    = DefineLabel();
1992
1993                         PopStack();
1994                         Stloc(count);                           // count -> temp
1995                         PopStack();
1996                         Dup();
1997                         Stloc(mark);                            // mark -> temp2
1998                         PushTrack(mark);
1999
2000                         Ldloc(_textposV);
2001                         Bne(l1);                                // mark != textpos -> l1
2002                         Ldloc(count);
2003                         Ldc(0);
2004                         Bge(l2);                                // count >= 0 && mark == textpos -> l2
2005
2006                         MarkLabel(l1);
2007                         Ldloc(count);
2008                         Ldc(Operand(1));
2009                         Bge(l2);                                // count >= Operand(1) -> l2
2010
2011                         // else
2012                         PushStack(_textposV);
2013                         ReadyPushStack();
2014                         Ldloc(count);                           // mark already on track
2015                         Ldc(1);
2016                         Add();
2017                         DoPush();
2018                         Track();
2019                         Goto(Operand(0));
2020
2021                         // if (count >= Operand(1) || Textpos() == mark)
2022                         MarkLabel(l2);
2023                         PushTrack(count);                       // mark already on track
2024                         TrackUnique2(branchcountback2);
2025                         break;
2026                     }
2027
2028                 case RegexCode.Branchcount | RegexCode.Back:
2029                     //: Trackframe(1);
2030                     //: Stackframe(2);
2031                     //: if (Stacked(1) > 0)                     // Positive -> can go straight
2032                     //: {
2033                     //:     Textto(Stacked(0));                 // Zap to mark
2034                     //:     Track2(Tracked(0), Stacked(1) - 1); // Save old mark, old count
2035                     //:     Advance(2);                         // Straight
2036                     //:     continue Forward;
2037                     //: }
2038                     //: Stack(Tracked(0), Stacked(1) - 1);      // recall old mark, old count
2039                     //: break Backward;
2040                     {
2041
2042                         LocalBuilder count = _tempV;
2043                         Label      l1    = DefineLabel();
2044                         PopStack();
2045                         Ldc(1);
2046                         Sub();
2047                         Dup();
2048                         Stloc(count);
2049                         Ldc(0);
2050                         Blt(l1);
2051
2052                         // if (count >= 0)
2053                         PopStack();
2054                         Stloc(_textposV);
2055                         PushTrack(count);                       // Tracked(0) is alredy on the track
2056                         TrackUnique2(branchcountback2);
2057                         Advance();
2058
2059                         // else
2060                         MarkLabel(l1);
2061                         ReadyReplaceStack(0);
2062                         PopTrack();
2063                         DoReplace();
2064                         PushStack(count);
2065                         Back();
2066                         break;
2067                     }
2068
2069                 case RegexCode.Branchcount | RegexCode.Back2:
2070                     //: Trackframe(2);
2071                     //: Stack(Tracked(0), Tracked(1));      // Recall old mark, old count
2072                     //: break Backward;                     // Backtrack
2073
2074                     PopTrack();
2075                     Stloc(_tempV);
2076                     ReadyPushStack();
2077                     PopTrack();
2078                     DoPush();
2079                     PushStack(_tempV);
2080                     Back();
2081                     break;
2082
2083                 case RegexCode.Lazybranchcount:
2084                     //: Stackframe(2);
2085                     //: int mark = Stacked(0);
2086                     //: int count = Stacked(1);
2087                     //:
2088                     //: if (count < 0)
2089                     //: {                                   // Negative count -> loop now
2090                     //:     Track2(mark);                   // Save old mark
2091                     //:     Stack(Textpos(), count + 1);    // Make new mark, incr count
2092                     //:     Goto(Operand(0));               // Loop
2093                     //: }
2094                     //: else
2095                     //: {                                   // Nonneg count or empty match -> straight now
2096                     //:     Track(mark, count, Textpos());  // Save mark, count, position
2097                     //: }
2098                     {
2099                         LocalBuilder count = _tempV;
2100                         LocalBuilder mark  = _temp2V;
2101                         Label      l1    = DefineLabel();
2102 #pragma warning disable 219
2103                         Label      l2    = DefineLabel();
2104                         Label      l3    = _labels[NextCodepos()];
2105 #pragma warning restore 219
2106
2107                         PopStack();
2108                         Stloc(count);                           // count -> temp
2109                         PopStack();
2110                         Stloc(mark);                            // mark -> temp2
2111
2112                         Ldloc(count);
2113                         Ldc(0);
2114                         Bge(l1);                                // count >= 0 -> l1
2115
2116                         // if (count < 0)
2117                         PushTrack(mark);
2118                         PushStack(_textposV);
2119                         ReadyPushStack();
2120                         Ldloc(count);
2121                         Ldc(1);
2122                         Add();
2123                         DoPush();
2124                         TrackUnique2(lazybranchcountback2);
2125                         Goto(Operand(0));
2126
2127                         // else
2128                         MarkLabel(l1);
2129                         PushTrack(mark);
2130                         PushTrack(count);
2131                         PushTrack(_textposV);
2132                         Track();
2133                         break;
2134                     }
2135
2136                 case RegexCode.Lazybranchcount | RegexCode.Back:
2137                     //: Trackframe(3);
2138                     //: int mark = Tracked(0);
2139                     //: int textpos = Tracked(2);
2140                     //: if (Tracked(1) < Operand(1) && textpos != mark)
2141                     //: {                                       // Under limit and not empty match -> loop
2142                     //:     Textto(Tracked(2));                 // Recall position
2143                     //:     Stack(Textpos(), Tracked(1) + 1);   // Make new mark, incr count
2144                     //:     Track2(Tracked(0));                 // Save old mark
2145                     //:     Goto(Operand(0));                   // Loop
2146                     //:     continue Forward;
2147                     //: }
2148                     //: else
2149                     //: {
2150                     //:     Stack(Tracked(0), Tracked(1));      // Recall old mark, count
2151                     //:     break Backward;                     // backtrack
2152                     //: }
2153                     {
2154                         Label       l1 = DefineLabel();
2155                         LocalBuilder  cV = _tempV;
2156                         PopTrack();
2157                         Stloc(_textposV);
2158                         PopTrack();
2159                         Dup();
2160                         Stloc(cV);
2161                         Ldc(Operand(1));
2162                         Bge(l1);                                // Tracked(1) >= Operand(1) -> l1
2163
2164                         Ldloc(_textposV);
2165                         TopTrack();
2166                         Beq(l1);                                // textpos == mark -> l1
2167
2168                         PushStack(_textposV);
2169                         ReadyPushStack();
2170                         Ldloc(cV);
2171                         Ldc(1);
2172                         Add();
2173                         DoPush();
2174                         TrackUnique2(lazybranchcountback2);
2175                         Goto(Operand(0));
2176
2177                         MarkLabel(l1);
2178                         ReadyPushStack();
2179                         PopTrack();
2180                         DoPush();
2181                         PushStack(cV);
2182                         Back();
2183                         break;
2184                     }
2185
2186                 case RegexCode.Lazybranchcount | RegexCode.Back2:
2187                     // <
2188
2189
2190
2191
2192
2193                     ReadyReplaceStack(1);
2194                     PopTrack();
2195                     DoReplace();
2196                     ReadyReplaceStack(0);
2197                     TopStack();
2198                     Ldc(1);
2199                     Sub();
2200                     DoReplace();
2201                     Back();
2202                     break;
2203
2204
2205                 case RegexCode.Setjump:
2206                     //: Stack(Trackpos(), Crawlpos());
2207                     //: Track();
2208                     ReadyPushStack();
2209                     Ldthisfld(_trackF);
2210                     Ldlen();
2211                     Ldloc(_trackposV);
2212                     Sub();
2213                     DoPush();
2214                     ReadyPushStack();
2215                     Ldthis();
2216                     Callvirt(_crawlposM);
2217                     DoPush();
2218                     TrackUnique(stackpop2);
2219                     break;
2220
2221                 case RegexCode.Setjump | RegexCode.Back:
2222                     //: Stackframe(2);
2223                     PopDiscardStack(2);
2224                     Back();
2225                     break;
2226
2227
2228                 case RegexCode.Backjump:
2229                     //: Stackframe(2);
2230                     //: Trackto(Stacked(0));
2231                     //: while (Crawlpos() != Stacked(1))
2232                     //:     Uncapture();
2233                     //: break Backward;
2234                     {
2235                         Label      l1    = DefineLabel();
2236                         Label      l2    = DefineLabel();
2237
2238                         PopStack();
2239                         Ldthisfld(_trackF);
2240                         Ldlen();
2241                         PopStack();
2242                         Sub();
2243                         Stloc(_trackposV);
2244                         Dup();
2245                         Ldthis();
2246                         Callvirt(_crawlposM);
2247                         Beq(l2);
2248
2249                         MarkLabel(l1);
2250                         Ldthis();
2251                         Callvirt(_uncaptureM);
2252                         Dup();
2253                         Ldthis();
2254                         Callvirt(_crawlposM);
2255                         Bne(l1);
2256
2257                         MarkLabel(l2);
2258                         Pop();
2259                         Back();
2260                         break;
2261                     }
2262
2263                 case RegexCode.Forejump:
2264                     //: Stackframe(2);
2265                     //: Trackto(Stacked(0));
2266                     //: Track(Stacked(1));
2267                     PopStack();
2268                     Stloc(_tempV);
2269                     Ldthisfld(_trackF);
2270                     Ldlen();
2271                     PopStack();
2272                     Sub();
2273                     Stloc(_trackposV);
2274                     PushTrack(_tempV);
2275                     TrackUnique(forejumpback);
2276                     break;
2277
2278                 case RegexCode.Forejump | RegexCode.Back:
2279                     //: Trackframe(1);
2280                     //: while (Crawlpos() != Tracked(0))
2281                     //:     Uncapture();
2282                     //: break Backward;
2283                     {
2284                         Label      l1    = DefineLabel();
2285                         Label      l2    = DefineLabel();
2286
2287                         PopTrack();
2288
2289                         Dup();
2290                         Ldthis();
2291                         Callvirt(_crawlposM);
2292                         Beq(l2);
2293
2294                         MarkLabel(l1);
2295                         Ldthis();
2296                         Callvirt(_uncaptureM);
2297                         Dup();
2298                         Ldthis();
2299                         Callvirt(_crawlposM);
2300                         Bne(l1);
2301
2302                         MarkLabel(l2);
2303                         Pop();
2304                         Back();
2305                         break;
2306                     }
2307
2308                 case RegexCode.Bol:
2309                     //: if (Leftchars() > 0 && CharAt(Textpos() - 1) != '\n')
2310                     //:     break Backward;
2311                     {
2312                         Label      l1    = _labels[NextCodepos()];
2313                         Ldloc(_textposV);
2314                         Ldloc(_textbegV);
2315                         Ble(l1);
2316                         Leftchar();
2317                         Ldc((int)'\n');
2318                         BneFar(_backtrack);
2319                         break;
2320                     }
2321
2322                 case RegexCode.Eol:
2323                     //: if (Rightchars() > 0 && CharAt(Textpos()) != '\n')
2324                     //:     break Backward;
2325                     {
2326                         Label      l1    = _labels[NextCodepos()];
2327                         Ldloc(_textposV);
2328                         Ldloc(_textendV);
2329                         Bge(l1);
2330                         Rightchar();
2331                         Ldc((int)'\n');
2332                         BneFar(_backtrack);
2333                         break;
2334                     }
2335
2336                 case RegexCode.Boundary:
2337                 case RegexCode.Nonboundary:
2338                     //: if (!IsBoundary(Textpos(), _textbeg, _textend))
2339                     //:     break Backward;
2340                     Ldthis();
2341                     Ldloc(_textposV);
2342                     Ldloc(_textbegV);
2343                     Ldloc(_textendV);
2344                     Callvirt(_isboundaryM);
2345                     if (Code() == RegexCode.Boundary)
2346                         BrfalseFar(_backtrack);
2347                     else
2348                         BrtrueFar(_backtrack);
2349                     break;
2350
2351                 case RegexCode.ECMABoundary:
2352                 case RegexCode.NonECMABoundary:
2353                     //: if (!IsECMABoundary(Textpos(), _textbeg, _textend))
2354                     //:     break Backward;
2355                     Ldthis();
2356                     Ldloc(_textposV);
2357                     Ldloc(_textbegV);
2358                     Ldloc(_textendV);
2359                     Callvirt(_isECMABoundaryM);
2360                     if (Code() == RegexCode.ECMABoundary)
2361                         BrfalseFar(_backtrack);
2362                     else
2363                         BrtrueFar(_backtrack);
2364                     break;
2365
2366                 case RegexCode.Beginning:
2367                     //: if (Leftchars() > 0)
2368                     //:    break Backward;
2369                     Ldloc(_textposV);
2370                     Ldloc(_textbegV);
2371                     BgtFar(_backtrack);
2372                     break;
2373
2374                 case RegexCode.Start:
2375                     //: if (Textpos() != Textstart())
2376                     //:    break Backward;
2377                     Ldloc(_textposV);
2378                     Ldthisfld(_textstartF);
2379                     BneFar(_backtrack);
2380                     break;
2381
2382                 case RegexCode.EndZ:
2383                     //: if (Rightchars() > 1 || Rightchars() == 1 && CharAt(Textpos()) != '\n')
2384                     //:    break Backward;
2385                     Ldloc(_textposV);
2386                     Ldloc(_textendV);
2387                     Ldc(1);
2388                     Sub();
2389                     BltFar(_backtrack);
2390                     Ldloc(_textposV);
2391                     Ldloc(_textendV);
2392                     Bge(_labels[NextCodepos()]);
2393                     Rightchar();
2394                     Ldc((int)'\n');
2395                     BneFar(_backtrack);
2396                     break;
2397
2398                 case RegexCode.End:
2399                     //: if (Rightchars() > 0)
2400                     //:    break Backward;
2401                     Ldloc(_textposV);
2402                     Ldloc(_textendV);
2403                     BltFar(_backtrack);
2404                     break;
2405
2406                 case RegexCode.One:
2407                 case RegexCode.Notone:
2408                 case RegexCode.Set:
2409                 case RegexCode.One      | RegexCode.Rtl:
2410                 case RegexCode.Notone   | RegexCode.Rtl:
2411                 case RegexCode.Set      | RegexCode.Rtl:
2412                 case RegexCode.One      | RegexCode.Ci:
2413                 case RegexCode.Notone   | RegexCode.Ci:
2414                 case RegexCode.Set      | RegexCode.Ci:
2415                 case RegexCode.One      | RegexCode.Ci  | RegexCode.Rtl:
2416                 case RegexCode.Notone   | RegexCode.Ci  | RegexCode.Rtl:
2417                 case RegexCode.Set      | RegexCode.Ci  | RegexCode.Rtl:
2418
2419                     //: if (Rightchars() < 1 || Rightcharnext() != (char)Operand(0))
2420                     //:    break Backward;
2421                     Ldloc(_textposV);
2422
2423                     if (!IsRtl()) {
2424                         Ldloc(_textendV);
2425                         BgeFar(_backtrack);
2426                         Rightcharnext();
2427                     }
2428                     else {
2429                         Ldloc(_textbegV);
2430                         BleFar(_backtrack);
2431                         Leftcharnext();
2432                     }
2433
2434                     if (IsCi())
2435                         CallToLower();
2436
2437                     if (Code() == RegexCode.Set) {
2438
2439                         Ldstr(_strings[Operand(0)]);
2440                         Call(_charInSetM);
2441
2442                         BrfalseFar(_backtrack);
2443                     }
2444                     else {
2445                         Ldc(Operand(0));
2446                         if (Code() == RegexCode.One)
2447                             BneFar(_backtrack);
2448                         else
2449                             BeqFar(_backtrack);
2450                     }
2451                     break;
2452
2453                 case RegexCode.Multi:
2454                 case RegexCode.Multi | RegexCode.Ci:
2455                     //
2456                     // <
2457
2458
2459
2460
2461
2462
2463                     //: String Str = _strings[Operand(0)];
2464                     //: int i, c;
2465                     //: if (Rightchars() < (c = Str.Length))
2466                     //:     break Backward;
2467                     //: for (i = 0; c > 0; i++, c--)
2468                     //:     if (Str[i] != Rightcharnext())
2469                     //:         break Backward;
2470                     {
2471                         int i;
2472                         String str;
2473
2474                         str = _strings[Operand(0)];
2475
2476                         Ldc(str.Length);
2477                         Ldloc(_textendV);
2478                         Ldloc(_textposV);
2479                         Sub();
2480                         BgtFar(_backtrack);
2481
2482                         // unroll the string
2483                         for (i = 0; i < str.Length; i++) {
2484                             Ldloc(_textV);
2485                             Ldloc(_textposV);
2486                             if (i != 0) {
2487                                 Ldc(i);
2488                                 Add();
2489                             }
2490                             Callvirt(_getcharM);
2491                             if (IsCi())
2492                                 CallToLower();
2493                             
2494                             Ldc((int)str[i]);
2495                             BneFar(_backtrack);
2496                         }
2497
2498                         Ldloc(_textposV);
2499                         Ldc(str.Length);
2500                         Add();
2501                         Stloc(_textposV);
2502                         break;
2503                     }
2504
2505
2506                 case RegexCode.Multi | RegexCode.Rtl:
2507                 case RegexCode.Multi | RegexCode.Ci  | RegexCode.Rtl:
2508                     //: String Str = _strings[Operand(0)];
2509                     //: int c;
2510                     //: if (Leftchars() < (c = Str.Length))
2511                     //:     break Backward;
2512                     //: while (c > 0)
2513                     //:     if (Str[--c] != Leftcharnext())
2514                     //:         break Backward;
2515                     {
2516                         int i;
2517                         String str;
2518
2519                         str = _strings[Operand(0)];
2520
2521                         Ldc(str.Length);
2522                         Ldloc(_textposV);
2523                         Ldloc(_textbegV);
2524                         Sub();
2525                         BgtFar(_backtrack);
2526
2527                         // unroll the string
2528                         for (i = str.Length; i > 0;) {
2529                             i--;
2530                             Ldloc(_textV);
2531                             Ldloc(_textposV);
2532                             Ldc(str.Length - i);
2533                             Sub();
2534                             Callvirt(_getcharM);
2535                             if (IsCi()) 
2536                             {
2537                                 CallToLower();
2538                             }
2539                             Ldc((int)str[i]);
2540                             BneFar(_backtrack);
2541                         }
2542
2543                         Ldloc(_textposV);
2544                         Ldc(str.Length);
2545                         Sub();
2546                         Stloc(_textposV);
2547
2548                         break;
2549                     }
2550
2551                 case RegexCode.Ref:
2552                 case RegexCode.Ref | RegexCode.Rtl:
2553                 case RegexCode.Ref | RegexCode.Ci:
2554                 case RegexCode.Ref | RegexCode.Ci | RegexCode.Rtl:
2555                     //: int capnum = Operand(0);
2556                     //: int j, c;
2557                     //: if (!_match.IsMatched(capnum)) {
2558                     //:     if (!RegexOptions.ECMAScript)
2559                     //:         break Backward;
2560                     //: } else {
2561                     //:     if (Rightchars() < (c = _match.MatchLength(capnum)))
2562                     //:         break Backward;
2563                     //:     for (j = _match.MatchIndex(capnum); c > 0; j++, c--)
2564                     //:         if (CharAt(j) != Rightcharnext())
2565                     //:             break Backward;
2566                     //: }
2567                     {
2568                         LocalBuilder lenV     = _tempV;
2569                         LocalBuilder indexV   = _temp2V;
2570                         Label      l1       = DefineLabel();
2571
2572                         Ldthis();
2573                         Ldc(Operand(0));
2574                         Callvirt(_ismatchedM);
2575                         if ((_options & RegexOptions.ECMAScript) != 0)
2576                             Brfalse(AdvanceLabel());
2577                         else
2578                             BrfalseFar(_backtrack); // !IsMatched() -> back
2579
2580                         Ldthis();
2581                         Ldc(Operand(0));
2582                         Callvirt(_matchlengthM);
2583                         Dup();
2584                         Stloc(lenV);
2585                         if (!IsRtl()) {
2586                             Ldloc(_textendV);
2587                             Ldloc(_textposV);
2588                         }
2589                         else {
2590                             Ldloc(_textposV);
2591                             Ldloc(_textbegV);
2592                         }
2593                         Sub();
2594                         BgtFar(_backtrack);         // Matchlength() > Rightchars() -> back
2595
2596                         Ldthis();
2597                         Ldc(Operand(0));
2598                         Callvirt(_matchindexM);
2599                         if (!IsRtl()) {
2600                             Ldloc(lenV);
2601                             Add(IsRtl());
2602                         }
2603                         Stloc(indexV);              // index += len
2604
2605                         Ldloc(_textposV);
2606                         Ldloc(lenV);
2607                         Add(IsRtl());
2608                         Stloc(_textposV);           // texpos += len
2609
2610                         MarkLabel(l1);
2611                         Ldloc(lenV);
2612                         Ldc(0);
2613                         Ble(AdvanceLabel());
2614                         Ldloc(_textV);
2615                         Ldloc(indexV);
2616                         Ldloc(lenV);
2617                         if (IsRtl()) {
2618                             Ldc(1);
2619                             Sub();
2620                             Dup();
2621                             Stloc(lenV);
2622                         }
2623                         Sub(IsRtl());
2624                         Callvirt(_getcharM);
2625                         if (IsCi())
2626                             CallToLower();
2627                         
2628                         Ldloc(_textV);
2629                         Ldloc(_textposV);
2630                         Ldloc(lenV);
2631                         if (!IsRtl()) {
2632                             Dup();
2633                             Ldc(1);
2634                             Sub();
2635                             Stloc(lenV);
2636                         }
2637                         Sub(IsRtl());
2638                         Callvirt(_getcharM);
2639                         if (IsCi())
2640                             CallToLower();
2641                         
2642                         Beq(l1);
2643                         Back();
2644                         break;
2645                     }
2646
2647
2648                 case RegexCode.Onerep:
2649                 case RegexCode.Notonerep:
2650                 case RegexCode.Setrep:
2651                 case RegexCode.Onerep | RegexCode.Rtl:
2652                 case RegexCode.Notonerep | RegexCode.Rtl:
2653                 case RegexCode.Setrep | RegexCode.Rtl:
2654                 case RegexCode.Onerep | RegexCode.Ci:
2655                 case RegexCode.Notonerep | RegexCode.Ci:
2656                 case RegexCode.Setrep | RegexCode.Ci:
2657                 case RegexCode.Onerep | RegexCode.Ci | RegexCode.Rtl:
2658                 case RegexCode.Notonerep | RegexCode.Ci | RegexCode.Rtl:
2659                 case RegexCode.Setrep | RegexCode.Ci | RegexCode.Rtl:
2660                     //: int c = Operand(1);
2661                     //: if (Rightchars() < c)
2662                     //:     break Backward;
2663                     //: char ch = (char)Operand(0);
2664                     //: while (c-- > 0)
2665                     //:     if (Rightcharnext() != ch)
2666                     //:         break Backward;
2667                     {
2668                         LocalBuilder lenV = _tempV;
2669                         Label      l1   = DefineLabel();
2670
2671                         int c = Operand(1);
2672
2673                         if (c == 0)
2674                             break;
2675
2676                         Ldc(c);
2677                         if (!IsRtl()) {
2678                             Ldloc(_textendV);
2679                             Ldloc(_textposV);
2680                         }
2681                         else {
2682                             Ldloc(_textposV);
2683                             Ldloc(_textbegV);
2684                         }
2685                         Sub();
2686                         BgtFar(_backtrack);         // Matchlength() > Rightchars() -> back
2687
2688                         Ldloc(_textposV);
2689                         Ldc(c);
2690                         Add(IsRtl());
2691                         Stloc(_textposV);           // texpos += len
2692
2693                         Ldc(c);
2694                         Stloc(lenV);
2695
2696                         MarkLabel(l1);
2697                         Ldloc(_textV);
2698                         Ldloc(_textposV);
2699                         Ldloc(lenV);
2700                         if (IsRtl()) {
2701                             Ldc(1);
2702                             Sub();
2703                             Dup();
2704                             Stloc(lenV);
2705                             Add();
2706                         }
2707                         else {
2708                             Dup();
2709                             Ldc(1);
2710                             Sub();
2711                             Stloc(lenV);
2712                             Sub();
2713                         }
2714                         Callvirt(_getcharM);
2715                         if (IsCi())
2716                             CallToLower();
2717                         
2718                         if (Code() == RegexCode.Setrep) {
2719                             Ldstr(_strings[Operand(0)]);
2720                             Call(_charInSetM);
2721
2722                             BrfalseFar(_backtrack);
2723                         }
2724                         else {
2725                             Ldc(Operand(0));
2726                             if (Code() == RegexCode.Onerep)
2727                                 BneFar(_backtrack);
2728                             else
2729                                 BeqFar(_backtrack);
2730                         }
2731                         Ldloc(lenV);
2732                         Ldc(0);
2733                         if (Code() == RegexCode.Setrep)
2734                             BgtFar(l1);
2735                         else
2736                             Bgt(l1);
2737                         break;
2738                     }
2739
2740
2741                 case RegexCode.Oneloop:
2742                 case RegexCode.Notoneloop:
2743                 case RegexCode.Setloop:
2744                 case RegexCode.Oneloop | RegexCode.Rtl:
2745                 case RegexCode.Notoneloop | RegexCode.Rtl:
2746                 case RegexCode.Setloop | RegexCode.Rtl:
2747                 case RegexCode.Oneloop | RegexCode.Ci:
2748                 case RegexCode.Notoneloop | RegexCode.Ci:
2749                 case RegexCode.Setloop | RegexCode.Ci:
2750                 case RegexCode.Oneloop | RegexCode.Ci | RegexCode.Rtl:
2751                 case RegexCode.Notoneloop | RegexCode.Ci | RegexCode.Rtl:
2752                 case RegexCode.Setloop | RegexCode.Ci | RegexCode.Rtl:
2753                     //: int c = Operand(1);
2754                     //: if (c > Rightchars())
2755                     //:     c = Rightchars();
2756                     //: char ch = (char)Operand(0);
2757                     //: int i;
2758                     //: for (i = c; i > 0; i--)
2759                     //: {
2760                     //:     if (Rightcharnext() != ch)
2761                     //:     {
2762                     //:         Leftnext();
2763                     //:         break;
2764                     //:     }
2765                     //: }
2766                     //: if (c > i)
2767                     //:     Track(c - i - 1, Textpos() - 1);
2768
2769                     {
2770                         LocalBuilder cV   = _tempV;
2771                         LocalBuilder lenV = _temp2V;
2772                         Label      l1   = DefineLabel();
2773                         Label      l2   = DefineLabel();
2774
2775                         int c = Operand(1);
2776
2777                         if (c == 0)
2778                             break;
2779                         if (!IsRtl()) {
2780                             Ldloc(_textendV);
2781                             Ldloc(_textposV);
2782                         }
2783                         else {
2784                             Ldloc(_textposV);
2785                             Ldloc(_textbegV);
2786                         }
2787                         Sub();
2788                         if (c != Int32.MaxValue) {
2789                             Label l4 = DefineLabel();
2790                             Dup();
2791                             Ldc(c);
2792                             Blt(l4);
2793                             Pop();
2794                             Ldc(c);
2795                             MarkLabel(l4);
2796                         }
2797                         Dup();
2798                         Stloc(lenV);
2799                         Ldc(1);
2800                         Add();
2801                         Stloc(cV);
2802
2803                         MarkLabel(l1);
2804                         Ldloc(cV);
2805                         Ldc(1);
2806                         Sub();
2807                         Dup();
2808                         Stloc(cV);
2809                         Ldc(0);
2810                         if (Code() == RegexCode.Setloop)
2811                             BleFar(l2);
2812                         else
2813                             Ble(l2);
2814
2815                         if (IsRtl())
2816                             Leftcharnext();
2817                         else
2818                             Rightcharnext();
2819                         if (IsCi()) 
2820                             CallToLower();
2821                         
2822                         if (Code() == RegexCode.Setloop) {
2823                             Ldstr(_strings[Operand(0)]);
2824                             Call(_charInSetM);
2825
2826                             BrtrueFar(l1);
2827                         }
2828                         else {
2829                             Ldc(Operand(0));
2830                             if (Code() == RegexCode.Oneloop)
2831                                 Beq(l1);
2832                             else
2833                                 Bne(l1);
2834                         }
2835
2836                         Ldloc(_textposV);
2837                         Ldc(1);
2838                         Sub(IsRtl());
2839                         Stloc(_textposV);
2840
2841                         MarkLabel(l2);
2842                         Ldloc(lenV);
2843                         Ldloc(cV);
2844                         Ble(AdvanceLabel());
2845
2846                         ReadyPushTrack();
2847                         Ldloc(lenV);
2848                         Ldloc(cV);
2849                         Sub();
2850                         Ldc(1);
2851                         Sub();
2852                         DoPush();
2853
2854                         ReadyPushTrack();
2855                         Ldloc(_textposV);
2856                         Ldc(1);
2857                         Sub(IsRtl());
2858                         DoPush();
2859
2860                         Track();
2861                         break;
2862                     }
2863
2864                 case RegexCode.Oneloop | RegexCode.Back:
2865                 case RegexCode.Notoneloop | RegexCode.Back:
2866                 case RegexCode.Setloop | RegexCode.Back:
2867                 case RegexCode.Oneloop | RegexCode.Rtl | RegexCode.Back:
2868                 case RegexCode.Notoneloop | RegexCode.Rtl | RegexCode.Back:
2869                 case RegexCode.Setloop | RegexCode.Rtl | RegexCode.Back:
2870                 case RegexCode.Oneloop | RegexCode.Ci | RegexCode.Back:
2871                 case RegexCode.Notoneloop | RegexCode.Ci | RegexCode.Back:
2872                 case RegexCode.Setloop | RegexCode.Ci | RegexCode.Back:
2873                 case RegexCode.Oneloop | RegexCode.Ci | RegexCode.Rtl | RegexCode.Back:
2874                 case RegexCode.Notoneloop | RegexCode.Ci | RegexCode.Rtl | RegexCode.Back:
2875                 case RegexCode.Setloop | RegexCode.Ci | RegexCode.Rtl | RegexCode.Back:
2876                     //: Trackframe(2);
2877                     //: int i   = Tracked(0);
2878                     //: int pos = Tracked(1);
2879                     //: Textto(pos);
2880                     //: if (i > 0)
2881                     //:     Track(i - 1, pos - 1);
2882                     //: Advance(2);
2883                     PopTrack();
2884                     Stloc(_textposV);
2885                     PopTrack();
2886                     Stloc(_tempV);
2887                     Ldloc(_tempV);
2888                     Ldc(0);
2889                     BleFar(AdvanceLabel());
2890                     ReadyPushTrack();
2891                     Ldloc(_tempV);
2892                     Ldc(1);
2893                     Sub();
2894                     DoPush();
2895                     ReadyPushTrack();
2896                     Ldloc(_textposV);
2897                     Ldc(1);
2898                     Sub(IsRtl());
2899                     DoPush();
2900                     Trackagain();
2901                     Advance();
2902                     break;
2903
2904                 case RegexCode.Onelazy:
2905                 case RegexCode.Notonelazy:
2906                 case RegexCode.Setlazy:
2907                 case RegexCode.Onelazy | RegexCode.Rtl:
2908                 case RegexCode.Notonelazy | RegexCode.Rtl:
2909                 case RegexCode.Setlazy | RegexCode.Rtl:
2910                 case RegexCode.Onelazy | RegexCode.Ci:
2911                 case RegexCode.Notonelazy | RegexCode.Ci:
2912                 case RegexCode.Setlazy | RegexCode.Ci:
2913                 case RegexCode.Onelazy | RegexCode.Ci | RegexCode.Rtl:
2914                 case RegexCode.Notonelazy | RegexCode.Ci | RegexCode.Rtl:
2915                 case RegexCode.Setlazy | RegexCode.Ci | RegexCode.Rtl:
2916                     //: int c = Operand(1);
2917                     //: if (c > Rightchars())
2918                     //:     c = Rightchars();
2919                     //: if (c > 0)
2920                     //:     Track(c - 1, Textpos());
2921                     {
2922                         LocalBuilder cV   = _tempV;
2923
2924                         int c = Operand(1);
2925
2926                         if (c == 0)
2927                             break;
2928
2929                         if (!IsRtl()) {
2930                             Ldloc(_textendV);
2931                             Ldloc(_textposV);
2932                         }
2933                         else {
2934                             Ldloc(_textposV);
2935                             Ldloc(_textbegV);
2936                         }
2937                         Sub();
2938                         if (c != Int32.MaxValue) {
2939                             Label l4 = DefineLabel();
2940                             Dup();
2941                             Ldc(c);
2942                             Blt(l4);
2943                             Pop();
2944                             Ldc(c);
2945                             MarkLabel(l4);
2946                         }
2947                         Dup();
2948                         Stloc(cV);
2949                         Ldc(0);
2950                         Ble(AdvanceLabel());
2951                         ReadyPushTrack();
2952                         Ldloc(cV);
2953                         Ldc(1);
2954                         Sub();
2955                         DoPush();
2956                         PushTrack(_textposV);
2957                         Track();
2958                         break;
2959                     }
2960
2961                 case RegexCode.Onelazy | RegexCode.Back:
2962                 case RegexCode.Notonelazy | RegexCode.Back:
2963                 case RegexCode.Setlazy | RegexCode.Back:
2964                 case RegexCode.Onelazy | RegexCode.Rtl | RegexCode.Back:
2965                 case RegexCode.Notonelazy | RegexCode.Rtl | RegexCode.Back:
2966                 case RegexCode.Setlazy | RegexCode.Rtl | RegexCode.Back:
2967                 case RegexCode.Onelazy | RegexCode.Ci | RegexCode.Back:
2968                 case RegexCode.Notonelazy | RegexCode.Ci | RegexCode.Back:
2969                 case RegexCode.Setlazy | RegexCode.Ci | RegexCode.Back:
2970                 case RegexCode.Onelazy | RegexCode.Ci | RegexCode.Rtl | RegexCode.Back:
2971                 case RegexCode.Notonelazy | RegexCode.Ci | RegexCode.Rtl | RegexCode.Back:
2972                 case RegexCode.Setlazy | RegexCode.Ci | RegexCode.Rtl | RegexCode.Back:
2973                     //: Trackframe(2);
2974                     //: int pos = Tracked(1);
2975                     //: Textto(pos);
2976                     //: if (Rightcharnext() != (char)Operand(0))
2977                     //:     break Backward;
2978                     //: int i = Tracked(0);
2979                     //: if (i > 0)
2980                     //:     Track(i - 1, pos + 1);
2981
2982                     PopTrack();
2983                     Stloc(_textposV);
2984                     PopTrack();
2985                     Stloc(_temp2V);
2986
2987                     if (!IsRtl())
2988                         Rightcharnext();
2989                     else
2990                         Leftcharnext();
2991
2992                     if (IsCi())
2993                         CallToLower();
2994
2995                     if (Code() == RegexCode.Setlazy) {
2996                         Ldstr(_strings[Operand(0)]);
2997                         Call(_charInSetM);
2998
2999                         BrfalseFar(_backtrack);
3000                     }
3001                     else {
3002                         Ldc(Operand(0));
3003                         if (Code() == RegexCode.Onelazy)
3004                             BneFar(_backtrack);
3005                         else
3006                             BeqFar(_backtrack);
3007                     }
3008
3009                     Ldloc(_temp2V);
3010                     Ldc(0);
3011                     BleFar(AdvanceLabel());
3012                     ReadyPushTrack();
3013                     Ldloc(_temp2V);
3014                     Ldc(1);
3015                     Sub();
3016                     DoPush();
3017                     PushTrack(_textposV);
3018                     Trackagain();
3019                     Advance();
3020                     break;
3021
3022                 default:
3023                     throw new NotImplementedException(SR.GetString(SR.UnimplementedState));
3024             }
3025         }
3026     }
3027
3028     internal class RegexTypeCompiler : RegexCompiler {
3029         private static int _typeCount = 0;
3030         private static LocalDataStoreSlot _moduleSlot = Thread.AllocateDataSlot();
3031
3032         private  AssemblyBuilder _assembly;
3033         private  ModuleBuilder  _module;
3034
3035         // state of the type builder
3036         private  TypeBuilder     _typebuilder;
3037         private  MethodBuilder   _methbuilder;
3038
3039         [ResourceExposure(ResourceScope.Machine)]
3040         [ResourceConsumption(ResourceScope.Machine)]
3041         [SuppressMessage("Microsoft.Security","CA2106:SecureAsserts", Justification="[....]: SECREVIEW : Regex only generates string manipulation, so this is OK")]
3042         internal RegexTypeCompiler(AssemblyName an, CustomAttributeBuilder[] attribs, String resourceFile) {
3043             // SECREVIEW : Regex only generates string manipulation, so this is
3044             //           : ok.
3045             //
3046 #if !DISABLE_CAS_USE
3047             new ReflectionPermission(PermissionState.Unrestricted).Assert();
3048 #endif
3049             try {
3050                 Debug.Assert(an != null, "AssemblyName should not be null");
3051
3052                 List<CustomAttributeBuilder> assemblyAttributes = new List<CustomAttributeBuilder>();
3053
3054                 ConstructorInfo transparencyCtor = typeof(SecurityTransparentAttribute).GetConstructor(Type.EmptyTypes);
3055                 CustomAttributeBuilder transparencyAttribute = new CustomAttributeBuilder(transparencyCtor, new object[0]);
3056                 assemblyAttributes.Add(transparencyAttribute);
3057
3058 #if !DISABLE_CAS_USE
3059                 ConstructorInfo securityRulesCtor = typeof(SecurityRulesAttribute).GetConstructor(new Type[] { typeof(SecurityRuleSet) });
3060                 CustomAttributeBuilder securityRulesAttribute =
3061                     new CustomAttributeBuilder(securityRulesCtor, new object[] { SecurityRuleSet.Level2 });
3062                 assemblyAttributes.Add(securityRulesAttribute);
3063 #endif
3064         
3065                 _assembly = AppDomain.CurrentDomain.DefineDynamicAssembly(an, AssemblyBuilderAccess.RunAndSave, assemblyAttributes);
3066                 _module = _assembly.DefineDynamicModule(an.Name + ".dll");
3067
3068                 if (attribs != null) {
3069                     for (int i=0; i<attribs.Length; i++) {
3070                         _assembly.SetCustomAttribute(attribs[i]);
3071                     }
3072                 }
3073
3074                 if (resourceFile != null) {
3075 #if FEATURE_PAL
3076                     // unmanaged resources are not supported
3077                     throw new ArgumentOutOfRangeException("resourceFile");
3078 #else
3079                     _assembly.DefineUnmanagedResource(resourceFile);
3080 #endif
3081                 }
3082             }
3083             finally {
3084                 CodeAccessPermission.RevertAssert();
3085             }
3086         }
3087
3088         /*
3089          * The top-level driver. Initializes everything then calls the Generate* methods.
3090          */
3091         internal Type FactoryTypeFromCode(RegexCode code, RegexOptions options, String typeprefix) {
3092             String runnertypename;
3093             String runnerfactoryname;
3094             Type runnertype;
3095             Type factory;
3096         
3097             _code       = code;
3098             _codes      = code._codes;
3099             _strings    = code._strings;
3100             _fcPrefix   = code._fcPrefix;
3101             _bmPrefix   = code._bmPrefix;
3102             _anchors    = code._anchors;
3103             _trackcount = code._trackcount;
3104             _options    = options;
3105         
3106             // pick a name for the class
3107             int typenum = Interlocked.Increment(ref _typeCount);
3108             string typenumString = typenum.ToString(CultureInfo.InvariantCulture);
3109             runnertypename = typeprefix + "Runner" + typenumString ;
3110             runnerfactoryname = typeprefix + "Factory" + typenumString;
3111         
3112             // Generate a RegexRunner class
3113             // (blocks are simply illustrative)
3114         
3115             DefineType(runnertypename, false, typeof(RegexRunner));
3116             {
3117                 DefineMethod("Go", null);
3118                 {
3119                     GenerateGo();
3120                     BakeMethod();
3121                 }
3122         
3123                 DefineMethod("FindFirstChar", typeof(bool));
3124                 {
3125                     GenerateFindFirstChar();
3126                     BakeMethod();
3127                 }
3128         
3129                 DefineMethod("InitTrackCount", null);
3130                 {
3131                     GenerateInitTrackCount();
3132                     BakeMethod();
3133                 }
3134         
3135                 runnertype = BakeType();
3136             }
3137         
3138             // Generate a RegexRunnerFactory class
3139         
3140             DefineType(runnerfactoryname, false, typeof(RegexRunnerFactory));
3141             {
3142                 DefineMethod("CreateInstance", typeof(RegexRunner));
3143                 {
3144                     GenerateCreateInstance(runnertype);
3145                     BakeMethod();
3146                 }
3147         
3148                 factory = BakeType();
3149             }
3150         
3151             return factory;
3152         }
3153         
3154         internal void GenerateRegexType(String pattern, RegexOptions opts, String name, bool ispublic, RegexCode code, RegexTree tree, Type factory, TimeSpan matchTimeout) {
3155             FieldInfo patternF                = RegexField("pattern");
3156             FieldInfo optionsF                = RegexField("roptions");
3157             FieldInfo factoryF                = RegexField("factory");
3158             FieldInfo capsF                   = RegexField("caps");
3159             FieldInfo capnamesF               = RegexField("capnames");
3160             FieldInfo capslistF               = RegexField("capslist");
3161             FieldInfo capsizeF                = RegexField("capsize");
3162             FieldInfo internalMatchTimeoutF   = RegexField("internalMatchTimeout");
3163             Type[] noTypeArray                = new Type[0];
3164             ConstructorBuilder defCtorBuilder, tmoutCtorBuilder;
3165         
3166             DefineType(name, ispublic, typeof(Regex));
3167             {
3168                 // Define default constructor:
3169                 _methbuilder = null;
3170                 MethodAttributes ma = System.Reflection.MethodAttributes.Public;
3171                 defCtorBuilder = _typebuilder.DefineConstructor(ma, CallingConventions.Standard, noTypeArray);
3172                 _ilg = defCtorBuilder.GetILGenerator();
3173                 {
3174                     // call base constructor
3175                     Ldthis();
3176                     _ilg.Emit(OpCodes.Call, typeof(Regex).GetConstructor(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance,
3177                                                                          null, new Type[0], new ParameterModifier[0]));
3178                     // set pattern
3179                     Ldthis();
3180                     Ldstr(pattern);
3181                     Stfld(patternF);
3182
3183                     // set options
3184                     Ldthis();
3185                     Ldc((int) opts);
3186                     Stfld(optionsF);
3187
3188                     // Set timeout (no need to validate as it should have happened in RegexCompilationInfo):
3189                     Ldthis();
3190                     LdcI8(matchTimeout.Ticks);
3191                     Call(typeof(TimeSpan).GetMethod("FromTicks", BindingFlags.Static | BindingFlags.Public));
3192                     Stfld(internalMatchTimeoutF);
3193
3194                     // set factory
3195                     Ldthis();
3196                     Newobj(factory.GetConstructor(noTypeArray));
3197                     Stfld(factoryF);
3198
3199                     // set caps
3200                     if (code._caps != null)
3201 #if SILVERLIGHT
3202                         GenerateCreateType(typeof(Dictionary<Int32, Int32>), capsF, code._caps);
3203 #else
3204                         GenerateCreateHashtable(capsF, code._caps);
3205 #endif
3206
3207                     // set capnames
3208                     if (tree._capnames != null)
3209 #if SILVERLIGHT
3210                         GenerateCreateType(typeof(Dictionary<String, Int32>), capnamesF, tree._capnames);
3211 #else
3212                         GenerateCreateHashtable(capnamesF, tree._capnames);
3213 #endif
3214
3215
3216                     // set capslist
3217                     if (tree._capslist != null) {
3218                         Ldthis();
3219                         Ldc(tree._capslist.Length);
3220                         _ilg.Emit(OpCodes.Newarr, typeof(String));  // create new string array
3221                         Stfld(capslistF);
3222
3223                         for (int i=0; i< tree._capslist.Length; i++) {
3224                             Ldthisfld(capslistF);
3225
3226                             Ldc(i);
3227                             Ldstr(tree._capslist[i]);
3228                             _ilg.Emit(OpCodes.Stelem_Ref);
3229                         }
3230                     }
3231
3232                     // set capsize
3233                     Ldthis();
3234                     Ldc(code._capsize);
3235                     Stfld(capsizeF);
3236
3237                     // set runnerref and replref by calling InitializeReferences()
3238                     Ldthis();
3239                     Call(typeof(Regex).GetMethod("InitializeReferences", BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic));
3240
3241
3242                     Ret();
3243                 }
3244
3245                 // Constructor with the timeout parameter:
3246                 _methbuilder = null;
3247                 ma = System.Reflection.MethodAttributes.Public;
3248                 tmoutCtorBuilder = _typebuilder.DefineConstructor(ma, CallingConventions.Standard, new Type[] { typeof(TimeSpan) });
3249                 _ilg = tmoutCtorBuilder.GetILGenerator();
3250                 {
3251                     // Call the default constructor:
3252                     Ldthis();
3253                     _ilg.Emit(OpCodes.Call, defCtorBuilder);
3254
3255                     // Validate timeout:
3256                     _ilg.Emit(OpCodes.Ldarg_1);
3257                     Call(typeof(Regex).GetMethod("ValidateMatchTimeout", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic));
3258
3259                     // Set timeout:
3260                     Ldthis();
3261                     _ilg.Emit(OpCodes.Ldarg_1);
3262                     Stfld(internalMatchTimeoutF);
3263
3264                     Ret();
3265                 }
3266             }
3267         
3268             // bake the constructor and type, then save the assembly
3269             defCtorBuilder = null;
3270             tmoutCtorBuilder = null;
3271             _typebuilder.CreateType();
3272             _ilg = null;
3273             _typebuilder = null;
3274         }
3275
3276 #if SILVERLIGHT
3277         internal void GenerateCreateType<TKey>(Type myCollectionType, FieldInfo field, Dictionary<TKey,int> ht) {
3278             MethodInfo addMethod = myCollectionType.GetMethod("Add", BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
3279             
3280             Ldthis();
3281             Newobj(myCollectionType.GetConstructor(new Type[0]));
3282 #else
3283         internal void GenerateCreateHashtable(FieldInfo field, Hashtable ht) {
3284             MethodInfo addMethod = typeof(Hashtable).GetMethod("Add", BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
3285             
3286             Ldthis();
3287             Newobj(typeof(Hashtable).GetConstructor(new Type[0]));
3288 #endif
3289
3290             Stfld(field);
3291         
3292             IDictionaryEnumerator en = ht.GetEnumerator();
3293             while (en.MoveNext()) {
3294                 Ldthisfld(field);
3295         
3296                 if (en.Key is int) {
3297                     Ldc((int) en.Key);  
3298 #if !SILVERLIGHT
3299                     _ilg.Emit(OpCodes.Box, typeof(Int32));
3300 #endif
3301                 }
3302                 else 
3303                     Ldstr((String) en.Key);
3304         
3305                 Ldc((int) en.Value);
3306 #if !SILVERLIGHT
3307                 _ilg.Emit(OpCodes.Box, typeof(Int32));
3308 #endif   
3309                 Callvirt(addMethod);
3310             }
3311         }
3312
3313         private FieldInfo RegexField(String fieldname) {
3314             return typeof(Regex).GetField(fieldname, BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
3315         }
3316
3317         // Note that we save the assembly to the current directory, and we believe this is not a
3318         // problem because this should only be used by tools, not at runtime.
3319         [ResourceExposure(ResourceScope.None)]
3320         [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)]
3321         internal void Save() {
3322             _assembly.Save(_assembly.GetName().Name + ".dll");
3323         }
3324
3325         /*
3326          * Generates a very simple factory method.
3327          */
3328         internal void GenerateCreateInstance(Type newtype) {
3329             Newobj(newtype.GetConstructor(new Type[0]));
3330             Ret();
3331         }
3332
3333         /*
3334          * Begins the definition of a new type with a specified base class
3335          */
3336         internal void DefineType(String typename, bool ispublic, Type inheritfromclass) {
3337             if (ispublic)
3338                 _typebuilder = _module.DefineType(typename, TypeAttributes.Class | TypeAttributes.Public, inheritfromclass);
3339             else
3340                 _typebuilder = _module.DefineType(typename, TypeAttributes.Class | TypeAttributes.NotPublic, inheritfromclass);
3341         
3342         }
3343         
3344         /*
3345          * Begins the definition of a new method (no args) with a specified return value
3346          */
3347         internal void DefineMethod(String methname, Type returntype) {
3348             MethodAttributes ma = System.Reflection.MethodAttributes.Public | System.Reflection.MethodAttributes.Virtual;
3349         
3350             _methbuilder = _typebuilder.DefineMethod(methname, ma, returntype, null);
3351             _ilg = _methbuilder.GetILGenerator();
3352         }
3353         
3354         /*
3355          * Ends the definition of a method
3356          */
3357         internal void BakeMethod() {
3358             _methbuilder = null;
3359         }
3360         
3361         /*
3362          * Ends the definition of a class and returns the type
3363          */
3364         internal Type BakeType() {
3365             Type retval = _typebuilder.CreateType();
3366             _typebuilder = null;
3367         
3368             return retval;
3369         }
3370         
3371     }
3372
3373     internal class RegexLWCGCompiler : RegexCompiler {
3374         private static int _regexCount = 0;
3375         private static Type[] _paramTypes = new Type[] {typeof(RegexRunner)};
3376         
3377         internal RegexLWCGCompiler() {
3378         }
3379         
3380         /*
3381          * The top-level driver. Initializes everything then calls the Generate* methods.
3382          */
3383         internal RegexRunnerFactory FactoryInstanceFromCode(RegexCode code, RegexOptions options) {
3384             _code       = code;
3385             _codes      = code._codes;
3386             _strings    = code._strings;
3387             _fcPrefix   = code._fcPrefix;
3388             _bmPrefix   = code._bmPrefix;
3389             _anchors    = code._anchors;
3390             _trackcount = code._trackcount;
3391             _options    = options;
3392         
3393             // pick a unique number for the methods we generate
3394             int regexnum = Interlocked.Increment(ref _regexCount);
3395             string regexnumString = regexnum.ToString(CultureInfo.InvariantCulture);
3396             
3397             DynamicMethod goMethod = DefineDynamicMethod("Go" + regexnumString, null, typeof(CompiledRegexRunner));
3398             GenerateGo();
3399     
3400             DynamicMethod firstCharMethod = DefineDynamicMethod("FindFirstChar" + regexnumString, typeof(bool), typeof(CompiledRegexRunner));
3401             GenerateFindFirstChar();
3402     
3403             DynamicMethod trackCountMethod = DefineDynamicMethod("InitTrackCount" + regexnumString, null, typeof(CompiledRegexRunner));
3404             GenerateInitTrackCount();
3405
3406             return new CompiledRegexRunnerFactory(goMethod, firstCharMethod, trackCountMethod);
3407         }
3408         
3409         /*
3410          * Begins the definition of a new method (no args) with a specified return value
3411          */
3412         internal DynamicMethod DefineDynamicMethod(String methname, Type returntype, Type hostType) {
3413             // We're claiming that these are static methods, but really they are instance methods.
3414             // By giving them a parameter which represents "this", we're tricking them into 
3415             // being instance methods.  
3416
3417             MethodAttributes attribs =  MethodAttributes.Public | MethodAttributes.Static;
3418             CallingConventions conventions = CallingConventions.Standard;
3419                             
3420             DynamicMethod dm = new DynamicMethod(methname, attribs, conventions, returntype, _paramTypes, hostType, false /*skipVisibility*/);
3421             _ilg = dm.GetILGenerator();
3422             return dm;
3423         }
3424
3425     }
3426     
3427 }
3428 #endif