Ejemplo n.º 1
0
		Instruction LoadIndirect(TypeSig type) {
			switch (type.GetElementType()) {
			case ElementType.Boolean:		return Instruction.Create(OpCodes.Ldind_I1);
			case ElementType.Char:			return Instruction.Create(OpCodes.Ldind_U2);
			case ElementType.I1:			return Instruction.Create(OpCodes.Ldind_I1);
			case ElementType.U1:			return Instruction.Create(OpCodes.Ldind_U1);
			case ElementType.I2:			return Instruction.Create(OpCodes.Ldind_I2);
			case ElementType.U2:			return Instruction.Create(OpCodes.Ldind_U2);
			case ElementType.I4:			return Instruction.Create(OpCodes.Ldind_I4);
			case ElementType.U4:			return Instruction.Create(OpCodes.Ldind_U4);
			case ElementType.I8:			return Instruction.Create(OpCodes.Ldind_I8);
			case ElementType.U8:			return Instruction.Create(OpCodes.Ldind_I8);
			case ElementType.R4:			return Instruction.Create(OpCodes.Ldind_R4);
			case ElementType.R8:			return Instruction.Create(OpCodes.Ldind_R8);
			case ElementType.String:		return Instruction.Create(OpCodes.Ldind_Ref);
			case ElementType.I:				return Instruction.Create(OpCodes.Ldind_I);
			case ElementType.U:				return Instruction.Create(OpCodes.Ldind_I);
			case ElementType.ValueType:		return Instruction.Create(OpCodes.Ldobj, generatedModule.Import(type).ToTypeDefOrRef());
			case ElementType.Class:			return Instruction.Create(OpCodes.Ldind_Ref);
			case ElementType.Array:			return Instruction.Create(OpCodes.Ldind_Ref);
			case ElementType.Object:		return Instruction.Create(OpCodes.Ldind_Ref);
			case ElementType.SZArray:		return Instruction.Create(OpCodes.Ldind_Ref);
			case ElementType.Ptr:			return Instruction.Create(OpCodes.Ldind_I);
			case ElementType.FnPtr:			return Instruction.Create(OpCodes.Ldind_I);
			case ElementType.Var:			return Instruction.Create(OpCodes.Ldobj, generatedModule.Import(type).ToTypeDefOrRef());
			case ElementType.MVar:			return Instruction.Create(OpCodes.Ldobj, generatedModule.Import(type).ToTypeDefOrRef());
			case ElementType.TypedByRef:	return Instruction.Create(OpCodes.Ldobj, generatedModule.Import(type).ToTypeDefOrRef());

			case ElementType.GenericInst:
				var gis = type as GenericInstSig;
				if (gis.GenericType.IsValueTypeSig)
					return Instruction.Create(OpCodes.Ldobj, generatedModule.Import(type).ToTypeDefOrRef());
				return Instruction.Create(OpCodes.Ldind_Ref);

			case ElementType.End:
			case ElementType.Void:
			case ElementType.ByRef:
			case ElementType.ValueArray:
			case ElementType.R:
			case ElementType.CModReqd:
			case ElementType.CModOpt:
			case ElementType.Internal:
			case ElementType.Module:
			case ElementType.Sentinel:
			case ElementType.Pinned:
			default:
				return Instruction.Create(OpCodes.Nop);
			}
		}
Ejemplo n.º 2
0
        static TypeSig GetArgType(MethodDef method, TypeSig arg)
        {
            if (arg.GetElementType() != ElementType.MVar)
            {
                return(arg);
            }
            var mvar = (GenericMVar)arg;

            foreach (var gp in method.GenericParameters)
            {
                if (gp.Number != mvar.Number)
                {
                    continue;
                }
                foreach (var gpc in gp.GenericParamConstraints)
                {
                    return(gpc.Constraint.ToTypeSig());
                }
            }
            return(arg);
        }
Ejemplo n.º 3
0
        public bool SimplifyTernaryOperator(List <ILNode> body, ILBasicBlock head, int pos)
        {
            Debug.Assert(body.Contains(head));

            ILExpression condExpr;
            ILLabel      trueLabel;
            ILLabel      falseLabel;
            ILVariable   trueLocVar = null;
            ILExpression trueExpr;
            ILLabel      trueFall;
            ILVariable   falseLocVar = null;
            ILExpression falseExpr;
            ILLabel      falseFall;
            object       unused;

            if (head.MatchLastAndBr(ILCode.Brtrue, out trueLabel, out condExpr, out falseLabel) &&
                labelGlobalRefCount[trueLabel] == 1 &&
                labelGlobalRefCount[falseLabel] == 1 &&
                ((labelToBasicBlock[trueLabel].MatchSingleAndBr(ILCode.Stloc, out trueLocVar, out trueExpr, out trueFall) &&
                  labelToBasicBlock[falseLabel].MatchSingleAndBr(ILCode.Stloc, out falseLocVar, out falseExpr, out falseFall) &&
                  trueLocVar == falseLocVar && trueFall == falseFall) ||
                 (labelToBasicBlock[trueLabel].MatchSingle(ILCode.Ret, out unused, out trueExpr) &&
                  labelToBasicBlock[falseLabel].MatchSingle(ILCode.Ret, out unused, out falseExpr))) &&
                body.Contains(labelToBasicBlock[trueLabel]) &&
                body.Contains(labelToBasicBlock[falseLabel])
                )
            {
                bool         isStloc          = trueLocVar != null;
                ILCode       opCode           = isStloc ? ILCode.Stloc : ILCode.Ret;
                TypeSig      retType          = isStloc ? trueLocVar.Type : this.context.CurrentMethod.ReturnType;
                bool         retTypeIsBoolean = retType.GetElementType() == ElementType.Boolean;
                int          leftBoolVal;
                int          rightBoolVal;
                ILExpression newExpr;
                // a ? true:false  is equivalent to  a
                // a ? false:true  is equivalent to  !a
                // a ? true : b    is equivalent to  a || b
                // a ? b : true    is equivalent to  !a || b
                // a ? b : false   is equivalent to  a && b
                // a ? false : b   is equivalent to  !a && b
                if (retTypeIsBoolean &&
                    trueExpr.Match(ILCode.Ldc_I4, out leftBoolVal) &&
                    falseExpr.Match(ILCode.Ldc_I4, out rightBoolVal) &&
                    ((leftBoolVal != 0 && rightBoolVal == 0) || (leftBoolVal == 0 && rightBoolVal != 0))
                    )
                {
                    // It can be expressed as trivilal expression
                    if (leftBoolVal != 0)
                    {
                        newExpr = condExpr;
                    }
                    else
                    {
                        newExpr = new ILExpression(ILCode.LogicNot, null, condExpr)
                        {
                            InferredType = corLib.Boolean
                        };
                    }
                }
                else if ((retTypeIsBoolean || falseExpr.InferredType.GetElementType() == ElementType.Boolean) && trueExpr.Match(ILCode.Ldc_I4, out leftBoolVal) && (leftBoolVal == 0 || leftBoolVal == 1))
                {
                    // It can be expressed as logical expression
                    if (leftBoolVal != 0)
                    {
                        newExpr = MakeLeftAssociativeShortCircuit(ILCode.LogicOr, condExpr, falseExpr);
                    }
                    else
                    {
                        newExpr = MakeLeftAssociativeShortCircuit(ILCode.LogicAnd, new ILExpression(ILCode.LogicNot, null, condExpr), falseExpr);
                    }
                }
                else if ((retTypeIsBoolean || trueExpr.InferredType.GetElementType() == ElementType.Boolean) && falseExpr.Match(ILCode.Ldc_I4, out rightBoolVal) && (rightBoolVal == 0 || rightBoolVal == 1))
                {
                    // It can be expressed as logical expression
                    if (rightBoolVal != 0)
                    {
                        newExpr = MakeLeftAssociativeShortCircuit(ILCode.LogicOr, new ILExpression(ILCode.LogicNot, null, condExpr), trueExpr);
                    }
                    else
                    {
                        newExpr = MakeLeftAssociativeShortCircuit(ILCode.LogicAnd, condExpr, trueExpr);
                    }
                }
                else
                {
                    // Ternary operator tends to create long complicated return statements
                    if (opCode == ILCode.Ret)
                    {
                        return(false);
                    }

                    // Only simplify generated variables
                    if (opCode == ILCode.Stloc && !trueLocVar.GeneratedByDecompiler)
                    {
                        return(false);
                    }

                    // Create ternary expression
                    newExpr = new ILExpression(ILCode.TernaryOp, null, condExpr, trueExpr, falseExpr);
                }

                var tail         = head.Body.RemoveTail(ILCode.Brtrue, ILCode.Br);
                var listNodes    = new List <ILNode>();
                var newExprNodes = newExpr.GetSelfAndChildrenRecursive <ILNode>(listNodes).ToArray();
                foreach (var node in labelToBasicBlock[trueLabel].GetSelfAndChildrenRecursive <ILNode>(listNodes).Except(newExprNodes))
                {
                    newExpr.ILRanges.AddRange(node.AllILRanges);
                }
                foreach (var node in labelToBasicBlock[falseLabel].GetSelfAndChildrenRecursive <ILNode>(listNodes).Except(newExprNodes))
                {
                    newExpr.ILRanges.AddRange(node.AllILRanges);
                }
                newExpr.ILRanges.AddRange(tail[0].ILRanges);
                tail[1].AddSelfAndChildrenRecursiveILRanges(newExpr.ILRanges);

                head.Body.Add(new ILExpression(opCode, trueLocVar, newExpr));
                if (isStloc)
                {
                    head.Body.Add(new ILExpression(ILCode.Br, trueFall));
                }

                // Remove the old basic blocks
                body.RemoveOrThrow(labelToBasicBlock[trueLabel]);
                body.RemoveOrThrow(labelToBasicBlock[falseLabel]);

                return(true);
            }
            return(false);
        }
Ejemplo n.º 4
0
        void Hash(TypeSig sig, int level)
        {
            if (sig == null)
            {
                return;
            }
            if (level++ > 20)
            {
                return;
            }

            hasher.Hash((byte)0x41);
            var etype = sig.GetElementType();

            hasher.Hash((byte)etype);
            switch (etype)
            {
            case ElementType.Ptr:
            case ElementType.ByRef:
            case ElementType.SZArray:
            case ElementType.Pinned:
                Hash(sig.Next, level);
                break;

            case ElementType.Array:
                var arySig = (ArraySig)sig;
                hasher.Hash(arySig.Rank);
                hasher.Hash(arySig.Sizes.Count);
                hasher.Hash(arySig.LowerBounds.Count);
                Hash(sig.Next, level);
                break;

            case ElementType.CModReqd:
            case ElementType.CModOpt:
                Hash(((ModifierSig)sig).Modifier);
                Hash(sig.Next, level);
                break;

            case ElementType.ValueArray:
                hasher.Hash(((ValueArraySig)sig).Size);
                Hash(sig.Next, level);
                break;

            case ElementType.Module:
                hasher.Hash(((ModuleSig)sig).Index);
                Hash(sig.Next, level);
                break;

            case ElementType.GenericInst:
                var gis = (GenericInstSig)sig;
                Hash(gis.GenericType, level);
                foreach (var ga in gis.GenericArguments)
                {
                    Hash(ga, level);
                }
                Hash(sig.Next, level);
                break;

            case ElementType.FnPtr:
                Hash(((FnPtrSig)sig).Signature);
                break;

            case ElementType.Var:
            case ElementType.MVar:
                hasher.Hash(((GenericSig)sig).Number);
                break;

            case ElementType.ValueType:
            case ElementType.Class:
                Hash(((TypeDefOrRefSig)sig).TypeDefOrRef);
                break;

            case ElementType.End:
            case ElementType.Void:
            case ElementType.Boolean:
            case ElementType.Char:
            case ElementType.I1:
            case ElementType.U1:
            case ElementType.I2:
            case ElementType.U2:
            case ElementType.I4:
            case ElementType.U4:
            case ElementType.I8:
            case ElementType.U8:
            case ElementType.R4:
            case ElementType.R8:
            case ElementType.String:
            case ElementType.TypedByRef:
            case ElementType.I:
            case ElementType.U:
            case ElementType.R:
            case ElementType.Object:
            case ElementType.Internal:
            case ElementType.Sentinel:
            default:
                break;
            }
        }
Ejemplo n.º 5
0
        public static bool IsValueTypeOrVoid(this TypeSig type)
        {
            var elemType = type.GetElementType();

            return(elemType == ElementType.Void || elemType == ElementType.ValueType);
        }
Ejemplo n.º 6
0
 public static bool IsVoid(this TypeSig type)
 {
     return(type.GetElementType() == ElementType.Void);
 }
        void Write(BinaryWriter writer, TypeSig sig, int level)
        {
            if (level++ > 20)
            {
                return;
            }

            writer.Write((byte)ObjectType.TypeSig);
            var etype = sig.GetElementType();

            writer.Write((byte)etype);
            switch (etype)
            {
            case ElementType.Ptr:
            case ElementType.ByRef:
            case ElementType.SZArray:
            case ElementType.Pinned:
                Write(writer, sig.Next, level);
                break;

            case ElementType.Array:
                var arySig = (ArraySig)sig;
                writer.Write(arySig.Rank);
                writer.Write(arySig.Sizes.Count);
                writer.Write(arySig.LowerBounds.Count);
                Write(writer, sig.Next, level);
                break;

            case ElementType.CModReqd:
            case ElementType.CModOpt:
                Write(writer, ((ModifierSig)sig).Modifier);
                Write(writer, sig.Next, level);
                break;

            case ElementType.ValueArray:
                writer.Write(((ValueArraySig)sig).Size);
                Write(writer, sig.Next, level);
                break;

            case ElementType.Module:
                writer.Write(((ModuleSig)sig).Index);
                Write(writer, sig.Next, level);
                break;

            case ElementType.GenericInst:
                var gis = (GenericInstSig)sig;
                Write(writer, gis.GenericType, level);
                foreach (var ga in gis.GenericArguments)
                {
                    Write(writer, ga, level);
                }
                Write(writer, sig.Next, level);
                break;

            case ElementType.FnPtr:
                Write(writer, ((FnPtrSig)sig).Signature);
                break;

            case ElementType.Var:
            case ElementType.MVar:
                writer.Write(((GenericSig)sig).Number);
                break;

            case ElementType.ValueType:
            case ElementType.Class:
                Write(writer, ((TypeDefOrRefSig)sig).TypeDefOrRef);
                break;

            case ElementType.End:
            case ElementType.Void:
            case ElementType.Boolean:
            case ElementType.Char:
            case ElementType.I1:
            case ElementType.U1:
            case ElementType.I2:
            case ElementType.U2:
            case ElementType.I4:
            case ElementType.U4:
            case ElementType.I8:
            case ElementType.U8:
            case ElementType.R4:
            case ElementType.R8:
            case ElementType.String:
            case ElementType.TypedByRef:
            case ElementType.I:
            case ElementType.U:
            case ElementType.R:
            case ElementType.Object:
            case ElementType.Internal:
            case ElementType.Sentinel:
            default:
                break;
            }
        }
Ejemplo n.º 8
0
        public static void WriteInstruction(string line, ModuleDefUser mod, CilBody epBody)
        {
            string[]    splitline = line.Split(new string[] { ", " }, StringSplitOptions.None);
            Instruction previous;
            TypeSig     type = mod.CorLibTypes.Int32;

            var consoleRef = new TypeRefUser(mod, "System", "Console", mod.CorLibTypes.AssemblyRef);
            var stringRef  = new TypeRefUser(mod, "System", "String", mod.CorLibTypes.AssemblyRef);

            switch (splitline[0])
            {
            case "ldstr":
                ldstr(epBody, splitline[1]);
                return;

            case "ldint":
                ldint(epBody, int.Parse(splitline[1]));
                return;

            case "ldbool":
                ldbool(epBody, splitline[1]);
                return;

            case "call":
                int placeholder;
                switch (splitline[1])
                {
                case "print":
                    previous = epBody.Instructions[epBody.Instructions.Count - 1];
                    if (previous.OpCode == OpCodes.Ldstr)
                    {
                        type = mod.CorLibTypes.String;
                    }
                    else if (previous.OpCode == OpCodes.Call)
                    {
                        type = getReturnType(previous.GetOperand());
                    }
                    else if (previous.IsLdloc())
                    {
                        type = previous.GetLocal(epBody.Variables).Type;
                    }
                    var consoleWrite1 = new MemberRefUser(mod, "WriteLine", MethodSig.CreateStatic(mod.CorLibTypes.Void, type), consoleRef);
                    epBody.Instructions.Add(OpCodes.Call.ToInstruction(consoleWrite1));
                    return;

                case "readline":
                    var consoleRead1 = new MemberRefUser(mod, "ReadLine", MethodSig.CreateStatic(mod.CorLibTypes.String), consoleRef);
                    epBody.Instructions.Add(OpCodes.Call.ToInstruction(consoleRead1));
                    return;

                case "concat":
                    var concat = new MemberRefUser(mod, "Concat", MethodSig.CreateStatic(mod.CorLibTypes.String, mod.CorLibTypes.String, mod.CorLibTypes.String), stringRef);
                    epBody.Instructions.Add(OpCodes.Call.ToInstruction(concat));
                    return;

                case "seq":
                    var seq = new MemberRefUser(mod, "op_Equality", MethodSig.CreateStatic(mod.CorLibTypes.Boolean, mod.CorLibTypes.String, mod.CorLibTypes.String), stringRef);
                    epBody.Instructions.Add(OpCodes.Call.ToInstruction(seq));
                    return;

                case "return":
                    epBody.Instructions.Add(OpCodes.Ret.ToInstruction());
                    return;

                case "add":
                    epBody.Instructions.Add(OpCodes.Add.ToInstruction());
                    return;

                case "sub":
                    epBody.Instructions.Add(OpCodes.Sub.ToInstruction());
                    return;

                case "mult":
                    epBody.Instructions.Add(OpCodes.Mul.ToInstruction());
                    return;

                case "div":
                    epBody.Instructions.Add(OpCodes.Div_Un.ToInstruction());
                    return;

                case "eq":
                    epBody.Instructions.Add(OpCodes.Ceq.ToInstruction());
                    return;

                case "gt":
                    epBody.Instructions.Add(OpCodes.Cgt.ToInstruction());
                    return;

                case "lt":
                    epBody.Instructions.Add(OpCodes.Clt.ToInstruction());
                    return;
                }
                epBody.Instructions.Add(OpCodes.Call.ToInstruction(findfunc(splitline[1])));
                return;

            case "ldvar":
                ldvar(epBody, splitline[1]);
                return;

            case "setvar":
                Local local = getvar(typeFromString(mod, splitline[2]), splitline[1], epBody.Variables);
                epBody.Instructions.Add(OpCodes.Stloc.ToInstruction(epBody.Variables.Add(local)));
                return;

            case "newfunc":
                List <string> arguments = new List <string>();
                foreach (string arg in splitline)
                {
                    arguments.Add(arg);
                }
                arguments.RemoveRange(0, 3);
                currentfunc = newfunc(mod, splitline[1], typeFromString(mod, splitline[2]), argumentsFromStrings(mod, arguments.ToArray()));
                return;

            case "endfunc":
                currentfunc = mod.EntryPoint;
                return;

            case "br":
                handleBrBegin(epBody, int.Parse(splitline[1]), "br");
                return;

            case "brtrue":
                handleBrBegin(epBody, int.Parse(splitline[1]), "brtrue");
                return;

            case "brfalse":
                handleBrBegin(epBody, int.Parse(splitline[1]), "brfalse");
                return;

            case "brend":
                //wasted instruction, fix potentially
                epBody.Instructions.Add(OpCodes.Nop.ToInstruction());
                placeholder = epBody.Instructions.Count - 1;
                int branch = int.Parse(splitline[1]);
                if (manager.branchExists(branch))
                {
                    handleBrEnd(epBody, branch, placeholder, manager.getBranchType(branch));
                }
                else
                {
                    manager.pushBranch(branch, placeholder, "brend");
                }
                return;

            case "pop?":
                previous = epBody.Instructions[epBody.Instructions.Count - 1];
                if (previous.OpCode != OpCodes.Call)
                {
                    return;
                }
                type = getReturnType(previous.GetOperand());
                if (type.GetElementType() != ElementType.Void)
                {
                    epBody.Instructions.Add(OpCodes.Pop.ToInstruction());
                }
                return;

            case "arg":
                epBody.Instructions.Add(OpCodes.Ldarg.ToInstruction(mod.EntryPoint.Parameters[int.Parse(splitline[1])]));
                return;
            }
            Console.WriteLine(line);
            throw new Exception("unknown intermediate instruction");
        }