jso0 / runsharp

Automatically exported from code.google.com/p/runsharp
MIT License
2 stars 0 forks source link

Illegal one-byte branch error #20

Closed GoogleCodeExporter closed 9 years ago

GoogleCodeExporter commented 9 years ago
Hi

I'm trying to generate the following C# rule using runsharp:

        public static bool RuleT6195(HTANTRL.IOptionValueProvider options)
        {
            return 
                (
                 (System.String.Compare(options.GetOptionValueAsString(1686), "G1 S1", System.StringComparison.OrdinalIgnoreCase) == 0) && 
                 (System.String.Compare(options.GetOptionValueAsString(1687), "G1 S2", System.StringComparison.OrdinalIgnoreCase) == 0)) && 
                 ((((
                 (System.String.Compare(options.GetOptionValueAsString(1168), "12", System.StringComparison.OrdinalIgnoreCase) == 0) || 
                 (System.String.Compare(options.GetOptionValueAsString(1168), "13", System.StringComparison.OrdinalIgnoreCase) == 0)) || 
                 (System.String.Compare(options.GetOptionValueAsString(1168), "14", System.StringComparison.OrdinalIgnoreCase) == 0)) || 
                 (System.String.Compare(options.GetOptionValueAsString(1168), "16", System.StringComparison.OrdinalIgnoreCase) == 0)) || 
                 (System.String.Compare(options.GetOptionValueAsString(1168), "17", System.StringComparison.OrdinalIgnoreCase) == 0));
        }

I have written the following code using runsharp to generate the equivalent IL:

            CodeGen g = typeGen.Public.Static.Method(typeof(bool), "Rule06195").Parameter(typeof(IOptionValueProvider), "options");
            {
                Operand op1 = Static.Invoke(typeof(System.String), "Compare", g.Arg("options").Invoke("GetOptionValueAsString", 1686), "G1 S1", System.StringComparison.OrdinalIgnoreCase) == 0;
                Operand op2 = Static.Invoke(typeof(System.String), "Compare", g.Arg("options").Invoke("GetOptionValueAsString", 1687), "G1 S2", System.StringComparison.OrdinalIgnoreCase) == 0;

                Operand op3 = Static.Invoke(typeof(System.String), "Compare", g.Arg("options").Invoke("GetOptionValueAsString", 1168), "12", System.StringComparison.OrdinalIgnoreCase) == 0;
                Operand op4 = Static.Invoke(typeof(System.String), "Compare", g.Arg("options").Invoke("GetOptionValueAsString", 1168), "13", System.StringComparison.OrdinalIgnoreCase) == 0;
                Operand op5 = Static.Invoke(typeof(System.String), "Compare", g.Arg("options").Invoke("GetOptionValueAsString", 1168), "14", System.StringComparison.OrdinalIgnoreCase) == 0;
                Operand op6 = Static.Invoke(typeof(System.String), "Compare", g.Arg("options").Invoke("GetOptionValueAsString", 1168), "16", System.StringComparison.OrdinalIgnoreCase) == 0;
                Operand op7 = Static.Invoke(typeof(System.String), "Compare", g.Arg("options").Invoke("GetOptionValueAsString", 1168), "17", System.StringComparison.OrdinalIgnoreCase) == 0;

                g.Return(((op1) && (op2)) && ((((op3 || op4) || op5) || op6) || op7));
            }

When I try to save the assembly I get the following error:

System.NotSupportedException was unhandled
  Message=Illegal one-byte branch at position: 57. Requested branch was: 143.
  Source=mscorlib
  StackTrace:
       at System.Reflection.Emit.ILGenerator.BakeByteArray()
       at System.Reflection.Emit.MethodBuilder.CreateMethodBodyHelper(ILGenerator il)
       at System.Reflection.Emit.TypeBuilder.CreateTypeNoLock()
       at System.Reflection.Emit.TypeBuilder.CreateType()
       at TriAxis.RunSharp.TypeGen.Complete() in D:\Downloads\Software Development\Frameworks\RunSharp\runsharp-0.1.2-pre-alpha-src\runsharp-0.1.2-pre-alpha-src\RunSharp\TypeGen.cs:line 683
       at TriAxis.RunSharp.AssemblyGen.Complete() in D:\Downloads\Software Development\Frameworks\RunSharp\runsharp-0.1.2-pre-alpha-src\runsharp-0.1.2-pre-alpha-src\RunSharp\AssemblyGen.cs:line 257
       at TriAxis.RunSharp.AssemblyGen.Save() in D:\Downloads\Software Development\Frameworks\RunSharp\runsharp-0.1.2-pre-alpha-src\runsharp-0.1.2-pre-alpha-src\RunSharp\AssemblyGen.cs:line 242
       at HTANTRL.CILOutputProvider.WriteToFile(String outputFile) in D:\PragmaDev\OK52\zTemp\Hendrik\HTANTRL\HTANTRL\CILOutputProvider.cs:line 114

Any ideas?  It this a bug?

Thanks
Carel

Original issue reported on code.google.com by carel.l...@gmail.com on 20 Aug 2010 at 9:25

GoogleCodeExporter commented 9 years ago
Yay, that's a long sequence of logical operators :)

For a quick solution, just apply the attached patch - it will add a few bytes 
to your generated IL, but will solve this issue.

The problem lies in forward branches - you can't tell if it's possible to use 
the short form, because you don't know how much code will follow before the 
target instruction. For some reason, I've assumed that the operands of the 
conditional operator (used for logical and and or) will always generate less 
than 128 bytes of IL. You've proved me wrong :)

Anyway, since RunSharp already generates long branches everywhere else, it's 
probably correct to fix it by changing this last short branch to a long one and 
worry about size optimization much later.

Original comment by StefanSi...@gmail.com on 20 Aug 2010 at 9:42

Attachments:

GoogleCodeExporter commented 9 years ago
Cool, I'll try it out now and let you know.

Thx

Original comment by carel.l...@gmail.com on 20 Aug 2010 at 9:45

GoogleCodeExporter commented 9 years ago
Stefan

The patch seems to be working!!  The first 20000 rules have just generated 
successfully.  10000 to go!

Thanks a lot.  You've made my day.  I'll let you know when I get all 30 000 
rules generated successfully.

Original comment by carel.l...@gmail.com on 20 Aug 2010 at 10:05

GoogleCodeExporter commented 9 years ago
Yay!

It's running through!  I'm parsing, type checking and translating 30 000 SAP 
rules into IL within 15 seconds! Pretty impressive results!  Assembly is 4.8MB. 
 If I generate the same rules first to C# syntax and then use the C# compiler I 
generate the same set of rules in 9 seconds and the assembly is 3.8MB big.  The 
benefit now however is that because the rules change at run-time, I can use the 
DynamicMethodGen to regenerate the method without having to worry about having 
to unload the assembly which is not possible in as the latter solution 
requires.  I can just regen the method on the fly!

Thanks again for a great library.

Original comment by carel.l...@gmail.com on 20 Aug 2010 at 10:53

GoogleCodeExporter commented 9 years ago
This issue was closed by revision 77b5c4ab1c.

Original comment by StefanSi...@gmail.com on 22 Aug 2010 at 9:10