summaryrefslogtreecommitdiff
path: root/src/inc/OpCodeGen.pl
diff options
context:
space:
mode:
Diffstat (limited to 'src/inc/OpCodeGen.pl')
-rw-r--r--src/inc/OpCodeGen.pl501
1 files changed, 501 insertions, 0 deletions
diff --git a/src/inc/OpCodeGen.pl b/src/inc/OpCodeGen.pl
new file mode 100644
index 0000000000..d9294519b0
--- /dev/null
+++ b/src/inc/OpCodeGen.pl
@@ -0,0 +1,501 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+#
+# GENREFOPS.PL
+#
+# PERL script used to generate the numbering of the reference opcodes
+#
+#use strict 'vars';
+#use strict 'subs';
+#use strict 'refs';
+
+
+my $ret = 0;
+my %oneByte;
+my %twoByte;
+my %controlFlow;
+my @singleByteArg;
+my %stackbehav;
+my %opcodetype;
+my %operandtype;
+my %opcodes;
+my $popstate;
+my $pushstate;
+
+$ctrlflowcount = 0;
+
+$count = 0;
+
+my @lowercaseAlphabet = ('a'..'z','0'..'9');
+my %upcaseAlphabet = ();
+
+foreach $letter (@lowercaseAlphabet) {
+ $j = $letter;
+ $j=~tr/a-z/A-Z/;
+ $upcaseAlphabet{$letter}=$j;
+}
+
+open (OPCODE, "opcode.def") or die "Couldn't open opcode.def: $!\n";
+open (OUTPUT, ">OpCodes.cs") or die "Couldn't open OpCodes.cs: $!\n";
+open (FCOUTPUT, ">FlowControl.cs") or die "Couldn't open FlowControl.cs: $!\n";
+open (SOUTPUT, ">StackBehaviour.cs") or die "Couldn't open StackBehaviour.cs: $!\n";
+open (OCOUTPUT, ">OpCodeType.cs") or die "Couldn't open OpCodeType.cs: $!\n";
+open (OPOUTPUT, ">OperandType.cs") or die "Couldn't open OprandType.cs: $!\n";
+
+
+print OUTPUT "/*============================================================\n";
+print OUTPUT "**\n";
+print OUTPUT "**Class: OpCodes\n";
+print OUTPUT "**\n";
+print OUTPUT "**Purpose: Exposes all of the il instructions supported by the runtime.\n";
+print OUTPUT "**\n";
+print OUTPUT "**Licensed to the .NET Foundation under one or more agreements.\n";
+print OUTPUT "**The .NET Foundation licenses this file to you under the MIT license.\n";
+print OUTPUT "**See the LICENSE file in the project root for more information.\n";
+print OUTPUT "**\n";
+print OUTPUT "** THIS FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT BY HAND!\n";
+print OUTPUT "** See clr\src\inc\opcodegen.pl for more information.**\n";
+print OUTPUT "============================================================*/\n";
+
+print OUTPUT "namespace System.Reflection.Emit {\n\n";
+print OUTPUT "using System;\n\n";;
+print OUTPUT "public class OpCodes {\n\n";;
+print OUTPUT "/// <summary>\n";
+print OUTPUT "/// <para>\n";
+print OUTPUT "/// The IL instruction opcodes supported by the\n";
+print OUTPUT "/// runtime. The IL Instruction Specification describes each\n";
+print OUTPUT "/// Opcode.\n";
+print OUTPUT "/// </para>\n";
+print OUTPUT "/// </summary>\n";
+print OUTPUT "/// <seealso topic='IL Instruction Set Specification'/>\n";
+print OUTPUT "\n";
+print OUTPUT "\tprivate OpCodes() { \n\t}\n\n";
+
+
+print FCOUTPUT "/*============================================================\n";
+print FCOUTPUT "**\n";
+print FCOUTPUT "**Class: FlowControl\n";
+print FCOUTPUT "**\n";
+print FCOUTPUT "**Purpose: Exposes FlowControl Attribute of IL .\n";
+print FCOUTPUT "**\n";
+print FCOUTPUT "**Licensed to the .NET Foundation under one or more agreements.\n";
+print FCOUTPUT "**The .NET Foundation licenses this file to you under the MIT license.\n";
+print FCOUTPUT "**See the LICENSE file in the project root for more information.\n";
+print FCOUTPUT "**\n";
+print FCOUTPUT "** THIS FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT BY HAND!\n";
+print FCOUTPUT "** See clr\src\inc\opcodegen.pl for more information.**\n";
+print FCOUTPUT "============================================================*/\n";
+
+print FCOUTPUT "namespace System.Reflection.Emit {\n\n";
+print FCOUTPUT "using System;\n\n";
+print FCOUTPUT "public enum FlowControl\n{\n\n";
+
+print SOUTPUT "/*============================================================\n";
+print SOUTPUT "**\n";
+print SOUTPUT "**Class: StackBehaviour\n";
+print SOUTPUT "**\n";
+print SOUTPUT "**Purpose: Exposes StackBehaviour Attribute of IL .\n";
+print SOUTPUT "**\n";
+print SOUTPUT "**Licensed to the .NET Foundation under one or more agreements.\n";
+print SOUTPUT "**The .NET Foundation licenses this file to you under the MIT license.\n";
+print SOUTPUT "**See the LICENSE file in the project root for more information.\n";
+print SOUTPUT "**\n";
+print SOUTPUT "** THIS FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT BY HAND!\n";
+print SOUTPUT "** See clr\src\inc\opcodegen.pl for more information.**\n";
+print SOUTPUT "============================================================*/\n";
+
+print SOUTPUT "namespace System.Reflection.Emit {\n\n";
+print SOUTPUT "using System;\n\n";
+print SOUTPUT "public enum StackBehaviour\n{\n\n";
+
+print OCOUTPUT "/*============================================================\n";
+print OCOUTPUT "**\n";
+print OCOUTPUT "**Class: OpCodeType\n";
+print OCOUTPUT "**\n";
+print OCOUTPUT "**Purpose: Exposes OpCodeType Attribute of IL .\n";
+print OCOUTPUT "**\n";
+print OCOUTPUT "**Licensed to the .NET Foundation under one or more agreements.\n";
+print OCOUTPUT "**The .NET Foundation licenses this file to you under the MIT license.\n";
+print OCOUTPUT "**See the LICENSE file in the project root for more information.\n";
+print OCOUTPUT "**\n";
+print OCOUTPUT "** THIS FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT BY HAND!\n";
+print OCOUTPUT "** See clr\src\inc\opcodegen.pl for more information.**\n";
+print OCOUTPUT "============================================================*/\n";
+
+print OCOUTPUT "namespace System.Reflection.Emit {\n\n";
+print OCOUTPUT "using System;\n\n";
+print OCOUTPUT "public enum OpCodeType\n{\n\n";
+
+print OPOUTPUT "/*============================================================\n";
+print OPOUTPUT "**\n";
+print OPOUTPUT "**Class: OperandType\n";
+print OPOUTPUT "**\n";
+print OPOUTPUT "**Purpose: Exposes OperandType Attribute of IL .\n";
+print OPOUTPUT "**\n";
+print OPOUTPUT "**Licensed to the .NET Foundation under one or more agreements.\n";
+print OPOUTPUT "**The .NET Foundation licenses this file to you under the MIT license.\n";
+print OPOUTPUT "**See the LICENSE file in the project root for more information.\n";
+print OPOUTPUT "**\n";
+print OPOUTPUT "** THIS FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT BY HAND!\n";
+print OPOUTPUT "** See clr\src\inc\opcodegen.pl for more information.**\n";
+print OPOUTPUT "============================================================*/\n";
+
+print OPOUTPUT "namespace System.Reflection.Emit {\n\n";
+print OPOUTPUT "using System;\n\n";
+print OPOUTPUT "public enum OperandType\n{\n\n";
+
+while (<OPCODE>)
+{
+ # Process only OPDEF(....) lines
+ if (/OPDEF\(\s*/)
+ {
+ chop; # Strip off trailing CR
+ s/^OPDEF\(\s*//; # Strip off "OP("
+ s/\)$//; # Strip off ")" at end
+ s/,\s*/,/g; # Remove whitespace
+
+ # Split the line up into its basic parts
+ ($enumname, $stringname, $pop, $push, $operand, $type, $size, $s1, $s2, $ctrl) = split(/,/);
+ $s1 =~ s/0x//;
+ $s1 = hex($s1);
+ $s2 =~ s/0x//;
+ $s2 = hex($s2);
+
+ if ($size == 0)
+ {
+ next;
+ }
+
+ next if ($enumname =~ /UNUSED/);
+
+ #Remove the prefix
+ $enumname=~s/CEE_//g;
+
+ #Convert name to our casing convention
+ $enumname=~tr/A-Z/a-z/;
+ $enumname=~s/^(.)/\u$1/g;
+ $enumname=~s/_(.)/_\u$1/g;
+
+
+ #Convert pop to our casing convention
+ $pop=~tr/A-Z/a-z/;
+ $pop=~s/^(.)/\u$1/g;
+ $pop=~s/_(.)/_\u$1/g;
+
+
+ #Convert push to our casing convention
+ $push=~tr/A-Z/a-z/;
+ $push=~s/^(.)/\u$1/g;
+ $push=~s/_(.)/_\u$1/g;
+
+
+ #Convert operand to our casing convention
+ #$operand=~tr/A-Z/a-z/;
+ #$operand=~s/^(.)/\u$1/g;
+ #$operand=~s/_(.)/_\u$1/g;
+
+ #Remove the I prefix on type
+ $type=~s/I//g;
+
+ #Convert Type to our casing convention
+ $type=~tr/A-Z/a-z/;
+ $type=~s/^(.)/\u$1/g;
+ $type=~s/_(.)/_\u$1/g;
+
+
+ #Convert ctrl to our casing convention
+ $ctrl=~tr/A-Z/a-z/;
+ $ctrl=~s/^(.)/\u$1/g;
+ $ctrl=~s/_(.)/_\u$1/g;
+
+
+
+
+ # Make a list of the flow Control type
+
+ # Make a list of the opcodes and there values
+ if ($opcodes{$enumname})
+ {
+
+ }
+ else
+ {
+ if ($size == 1)
+ {
+ $opcodes{$enumname} = $s2;
+ }
+ else
+ {
+ $opcodes{$enumname} = ($s2 + 256 * $s1);
+ }
+ }
+
+ #Make a list of the instructions which only take one-byte arguments
+ if ($enumname =~ /^.*_S$/) {
+ #but exclude the deprecated expressions (sometimes spelled "depricated")
+ if (!($enumname=~/^Depr.cated.*/)) {
+ my $caseStatement = sprintf("\t\tcase %-20s: \n", $enumname);
+ push(@singleByteArg, $caseStatement);
+ }
+ }
+
+ #make a list of the control Flow Types
+ if ($controlFlow{$ctrl})
+ {
+ #printf("DUPE Control Flow\n");
+ }
+ else
+ {
+ $controlFlow{$ctrl} = $ctrlflowcount;
+ $ctrlflowcount++;
+ }
+
+ $ctrlflowcount = 0;
+ #make a list of the control Flow Types
+ $pop=~s/\+/_/g;
+ if ($stackbehav{$pop})
+ {
+ #printf("DUPE Control Flow\n");
+ }
+ else
+ {
+ $stackbehav{$pop} = $ctrlflowcount;
+ $ctrlflowcount++;
+ }
+
+ #make a list of the control Flow Types
+ $push=~s/\+/_/g;
+ if ($stackbehav{$push})
+ {
+ #printf("DUPE Control Flow\n");
+ }
+ else
+ {
+ $stackbehav{$push} = $ctrlflowcount;
+ $ctrlflowcount++;
+ }
+ #make a list of operand types
+ if ($operandtype{$operand})
+ {
+ #printf("DUPE Control Flow\n");
+ }
+ else
+ {
+ $operandtype{$operand} = $ctrlflowcount;
+ $ctrlflowcount++;
+ }
+
+
+ #make a list of opcode types
+ if ($opcodetype{$type})
+ {
+ #printf("DUPE Control Flow\n");
+ }
+ else
+ {
+ $opcodetype{$type} = $ctrlflowcount;
+ $ctrlflowcount++;
+ }
+
+ print "$enumname\n";
+ print "$stringname\n";
+ if ($stringname eq "arglist")
+ {
+ print "This is arglist----------\n";
+ }
+ my $line = sprintf("\tpublic static readonly OpCode %-20s = ", $enumname);
+ if ($size == 1)
+ {
+ $line .= sprintf("new OpCode(%s, StackBehaviour.%s, StackBehaviour.%s, OperandType.%s, OpCodeType.%s, %u, (byte)0x%x, (byte)0x%x, FlowControl.%s, " , $stringname, $pop, $push, $operand, $type, $size, $s1, $s2, $ctrl);
+
+
+ if ($ctrl eq "Return" || $ctrl eq "Branch" || $ctrl eq "Throw" || $stringname eq "\"jmp\"" || $stringname eq "\"jmpi\"")
+ {
+ $line .= sprintf("true, ");
+
+ }
+ else
+ {
+ $line .= sprintf("false, ");
+ }
+
+ $popstate = 0;
+ if($pop eq "Pop0" || $pop eq "Varpop")
+ {
+ $popstate = 0;
+ }
+ elsif ($pop eq "Pop1" || $pop eq "Popi" || $pop eq "Popref")
+ {
+ $popstate = $popstate -1;
+ }
+ elsif ($pop eq "Pop1_pop1" || $pop eq "Popi_pop1" || $pop eq "Popi_popi" || $pop eq "Popi_popi8" || $pop eq "Popi_popr4" || $pop eq "Popi_popr8" || $pop eq "Popref_pop1" || $pop eq "Popref_popi")
+ {
+ $popstate = $popstate -2;
+ }
+ elsif ($pop eq "Popi_popi_popi" || $pop eq "Popref_popi_popi" || $pop eq "Popref_popi_popi8" || $pop eq "Popref_popi_popr4" || $pop eq "Popref_popi_popr8" || $pop eq "Popref_popi_popref")
+ {
+ $popstate = $popstate -3;
+ }
+
+ if ($push eq "Push1" || $push eq "Pushi" ||$push eq "Pushi8" ||$push eq "Pushr4" ||$push eq "Pushr8" ||$push eq "Pushref")
+ {
+ $popstate = $popstate + 1;
+ }
+ elsif($push eq "Push1_push1")
+ {
+ $popstate = $popstate + 2;
+ }
+
+
+ $line .= sprintf(" $popstate");
+ $line .= sprintf(");\n\n");
+ if ($oneByte{$s2})
+ {
+ printf("Error opcode 0x%x already defined!\n", $s2);
+ print " Old = $oneByte{$s2}";
+ print " New = $line";
+ $ret = -1;
+ }
+ $oneByte{$s2} = $line;
+ }
+ elsif ($size == 2)
+ {
+ if ($twoByte{$s2})
+ {
+ printf("Error opcode 0x%x%x already defined!\n", $s1, $s2);
+ print " Old = $oneByte{$s2}";
+ print " New = $line";
+ $ret = -1;
+ }
+ $line .= sprintf("new OpCode(%s, StackBehaviour.%s, StackBehaviour.%s, OperandType.%s, OpCodeType.%s, %u, (byte)0x%x, (byte)0x%x, FlowControl.%s, " , $stringname, $pop, $push, $operand, $type, $size, $s1, $s2, $ctrl);
+
+ if ($ctrl eq "Return" || $ctrl eq "Branch" || $ctrl eq "Throw" || $stringname eq "\"jmp\"" || $stringname eq "\"jmpi\"")
+ {
+ $line .= sprintf("true, ");
+
+ }
+ else
+ {
+ $line .= sprintf("false, ");
+ }
+
+ $popstate = 0;
+ if($pop eq "Pop0" || $pop eq "Varpop")
+ {
+ $popstate = 0;
+ }
+ elsif($pop eq "Pop1" || $pop eq "Popi" || $pop eq "Popref")
+ {
+ $popstate = $popstate -1;
+ }
+ elsif ($pop eq "Pop1_pop1" || $pop eq "Popi_pop1" || $pop eq "Popi_popi" || $pop eq "Popi_popi8" || $pop eq "Popi_popr4" || $pop eq "Popi_popr8" || $pop eq "Popref_pop1" || $pop eq "Popref_popi")
+ {
+ $popstate = $popstate -2;
+ }
+ elsif ($pop eq "Popi_popi_popi" || $pop eq "Popref_popi_popi" || $pop eq "Popref_popi_popi8" || $pop eq "Popref_popi_popr4" || $pop eq "Popref_popi_popr8" || $pop eq "Popref_popi_popref")
+ {
+ $popstate = $popstate -3;
+ }
+
+ if ($push eq "Push1" || $push eq "Pushi" ||$push eq "Pushi8" ||$push eq "Pushr4" ||$push eq "Pushr8" ||$push eq "Pushref")
+ {
+ $popstate = $popstate + 1;
+ }
+ elsif($push eq "Push1_push1")
+ {
+ $popstate = $popstate + 2;
+ }
+
+ $line .= sprintf(" $popstate");
+ $line .= sprintf(");\n\n");
+
+ $twoByte{$s2 + 256 * $s1} = $line;
+
+ }
+ else
+ {
+ $line .= "\n";
+ push(@deprecated, $line);
+ }
+ $count++;
+ }
+}
+
+#Write out the Flow Control class
+$ctrlflowcount = 0;
+foreach $key (sort {$a cmp $b} keys (%controlFlow))
+{
+ print FCOUTPUT "\t$key";
+ print FCOUTPUT "\t= $ctrlflowcount,\n";
+ $ctrlflowcount++;
+}
+
+#end the flowcontrol class
+print FCOUTPUT "}\n}";
+
+#Write out the StackBehaviour class
+$ctrlflowcount = 0;
+foreach $key (sort {$a cmp $b} keys (%stackbehav))
+{
+ print SOUTPUT "\t$key";
+ print SOUTPUT "\t= $ctrlflowcount,\n";
+ $ctrlflowcount++;
+}
+#end the StackBehaviour class
+print SOUTPUT "}\n}";
+
+$ctrlflowcount = 0;
+foreach $key (sort {$a cmp $b} keys (%opcodetype))
+{
+ print OCOUTPUT "\t$key";
+ print OCOUTPUT "\t= $ctrlflowcount,\n";
+ $ctrlflowcount++;
+}
+#end the OpCodeTYpe class
+print OCOUTPUT "}\n}";
+
+$ctrlflowcount = 0;
+foreach $key (sort {$a cmp $b} keys (%operandtype))
+{
+ print OPOUTPUT "\t$key";
+ print OPOUTPUT "\t= $ctrlflowcount,\n";
+ $ctrlflowcount++;
+}
+#end the OperandType class
+print OPOUTPUT "}\n}";
+
+
+my $opcode;
+my $lastOp = -1;
+foreach $opcode (sort {$a <=> $b} keys(%oneByte)) {
+ printf("***** GAP %d instrs ****\n", $opcode - $lastOp) if ($lastOp + 1 != $opcode && $lastOp > 0);
+ print OUTPUT $oneByte{$opcode};
+ $lastOp = $opcode;
+}
+
+$lastOp = -1;
+foreach $opcode (sort {$a <=> $b} keys(%twoByte)) {
+ printf("***** GAP %d instrs ****\n", $opcode - $lastOp) if ($lastOp + 1 != $opcode && $lastOp > 0);
+ print OUTPUT $twoByte{$opcode};
+ $lastOp = $opcode;
+}
+
+
+
+
+
+print OUTPUT "\n\n\tpublic static bool TakesSingleByteArgument(OpCode inst)\n\t{\n";
+print OUTPUT"\t\tswitch(inst.m_operand)\n\t\t{\n";
+print OUTPUT "\t\t\tcase OperandType.ShortInlineBrTarget :\n";
+print OUTPUT "\t\t\tcase OperandType.ShortInlineI :\n";
+print OUTPUT "\t\t\tcase OperandType.ShortInlineVar :\n";
+print OUTPUT "\t\t\treturn true;\n";
+print OUTPUT "\t\t};\n";
+print OUTPUT "\t\treturn false;\n";
+print OUTPUT "\t}\n";
+print OUTPUT "}\n}";
+exit($ret);
+
+
+