diff options
Diffstat (limited to 'src/inc/OpCodeGen.pl')
-rw-r--r-- | src/inc/OpCodeGen.pl | 501 |
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); + + + |