コード例 #1
0
        private List <CilSigArg> CompleteSigArgs(CilInstructionMethod instruction, CilMethod method)
        {
            var isInstanceCall = instruction.CallConv.IsInstance;

            var instanceSigArg = new CilSigArg
            {
                Id   = ".this",
                Type = instruction.TypeSpec.GetCilType(_program)
            };

            var result = isInstanceCall ?
                         (new List <CilSigArg> {
                instanceSigArg
            }).Concat(instruction.SigArgs).ToList() :
                         instruction.SigArgs;

            var start = isInstanceCall ? 1 : 0;

            for (int i = start; i < result.Count; i++)
            {
                result[i].Id = isInstanceCall ? method.Arguments[i - 1].Id : method.Arguments[i].Id;
            }

            return(result);
        }
コード例 #2
0
        public JSExpression Translate(CilAssembly assembly, CilType type, CilMethod method)
        {
            if (type.IsIgnored)
            {
                throw new ArgumentException("cannot translate method of ignored class");
            }

            if (method.NeedTranslation == false)
            {
                return(null);
            }

            var r = method.GetReplacement();

            if (r != null && r.Kind == ReplacementKind.Function)
            {
                return(new JSRaw {
                    Value = r.Replacement
                });
            }

            if (type.IsUserDelegate)
            {
                return(TranslateDelegateMethod(method));
            }
            else
            {
                return(TranslateNormalMethod(assembly, type, method));
            }
        }
コード例 #3
0
 public BlockTranslator(Context context, CilAssembly assembly, CilType type, CilMethod method, JSExpression this_)
     : base(context)
 {
     this.type     = type;
     this.assembly = assembly;
     this.method   = method;
     this.this_    = this_;
 }
コード例 #4
0
ファイル: StackAnalyzer.cs プロジェクト: BenitoJedai/Braille
        public void Run(CilMethod method)
        {
            IList <OpExpression> infos = method.OpTree;

            if (infos.Any() == false)
            {
                return;
            }

            infos.First().StackBefore = new List <StackUseDefinition>();

            var methodBody = method.MethodBody;

            var processStack = new Stack <OpExpression>();

            var handlers = methodBody != null ? methodBody.ExceptionHandlingClauses : new List <ExceptionHandlingClause>();

            foreach (var handler in handlers.Where(h => h.TryOffset == 0))
            {
                var handlerStart = method.OpTree.First(i => i.Position == handler.HandlerOffset);

                if (handler.Flags == ExceptionHandlingClauseOptions.Clause)
                {
                    handlerStart.StackBefore = new List <StackUseDefinition>
                    {
                        new StackUseDefinition
                        {
                            Definitions = new List <Node> {
                                new ExceptionNode()
                            }
                        }
                    };
                }
                else
                {
                    handlerStart.StackBefore = new List <StackUseDefinition>();
                }

                processStack.Push(handlerStart);
            }

            processStack.Push(infos.First());

            while (processStack.Any())
            {
                var opInfo = processStack.Pop();

                //
                // Part I

                var newStack = GetStackAfter(opInfo);

                //
                // Part II: update branch targets

                UpdateTargets(processStack, opInfo, newStack);
            }
        }
コード例 #5
0
        public void Run(CilMethod method)
        {
            IEnumerable <OpExpression> opAst = method.OpTree;

            foreach (var op in opAst)
            {
                ProcessOp(op, op);
            }
        }
コード例 #6
0
        public void Run(CilMethod method)
        {
            IEnumerable <OpExpression> opAst = method.OpTree;

            method.ReferencedTypes = opAst
                                     .SelectMany(op => FindTypes(method, op))
                                     .SelectMany(t => ExpandGenericTypes(t))
                                     .Distinct()
                                     .ToArray();
        }
コード例 #7
0
 public void Run(CilMethod method)
 {
     method.OpTree = method.OpTree
                     //.Where(o => o.StackBefore != null) // unreachable
                     .Where(
         o => false == (
             o.Instruction.OpCode.Name == "br.s" &&
             ((o.Targeting.Count == 1 && o.Targeting[0] == o.Prev) || o.Targeting.Count == 0) &&
             o.Targets.Count == 1 && o.Targets[0] == o.Next))
                     .ToList();
 }
コード例 #8
0
        public void Run(CilMethod method, List <OpExpression> infos)
        {
            processStack.Push(infos.First());

            //foreach (var opInfo in infos)
            while (processStack.Any())
            {
                var opInfo = processStack.Pop();

                Process(opInfo);
            }
        }
コード例 #9
0
        public static int GetPushCount(CilMethod method, OpInstruction instruction)
        {
            switch (instruction.OpCode.StackBehaviourPush)
            {
            case StackBehaviour.Push0:
                return(0);

            case StackBehaviour.Push1:
            case StackBehaviour.Pushi:
            case StackBehaviour.Pushi8:
            case StackBehaviour.Pushr4:
            case StackBehaviour.Pushr8:
            case StackBehaviour.Pushref:
                return(1);

            case StackBehaviour.Varpush:
                if (instruction.OpCode.Name.StartsWith("call"))
                {
                    if (instruction.Data is ConstructorInfo)
                    {
                        return(0);
                    }

                    var mi = (MethodInfo)instruction.Data;

                    if (mi.ReturnType.FullName == "System.Void")
                    {
                        return(0);
                    }
                    else
                    {
                        return(1);
                    }
                }
                else
                {
                    throw new NotImplementedException();
                }

            case StackBehaviour.Push1_push1:
                if (instruction.OpCode.Name == "dup")
                {
                    return(2);
                }
                else
                {
                    throw new NotImplementedException();
                }

            default:
                throw new NotImplementedException();
            }
        }
コード例 #10
0
        private static List <ProtectedRegion> GetRegions(CilMethod method)
        {
            var mtdb = method.MethodBody;

            if (mtdb == null)
            {
                return new List <ProtectedRegion>()
                       {
                           null
                       }
            }
            ;

            var ex = mtdb
                     .ExceptionHandlingClauses
                     .GroupBy(e => new { e.TryOffset, e.TryLength });

            var regions = new List <ProtectedRegion>();

            foreach (var clauseGroup in ex)
            {
                var result = new ProtectedRegion();

                var key = clauseGroup.Key;

                result.TrySpan = new ProtectedRegionSpan(key.TryOffset, key.TryOffset + key.TryLength, RegionKind.Try);

                result.CatchSpan = clauseGroup
                                   .Where(e => e.Flags == ExceptionHandlingClauseOptions.Clause)
                                   .Select(
                    e => new ProtectedRegionSpan(e.HandlerOffset, e.HandlerOffset + e.HandlerLength, RegionKind.Catch)
                {
                    CatchType = e.CatchType
                })
                                   .ToList();

                var finallyClause = clauseGroup.FirstOrDefault(f => f.Flags == ExceptionHandlingClauseOptions.Finally);
                if (finallyClause != null)
                {
                    result.FinallySpan = new ProtectedRegionSpan(finallyClause.HandlerOffset, finallyClause.HandlerOffset + finallyClause.HandlerLength, RegionKind.Finally);
                }

                var faultClause = clauseGroup.FirstOrDefault(f => f.Flags == ExceptionHandlingClauseOptions.Fault);
                if (faultClause != null)
                {
                    result.FaultSpan = new ProtectedRegionSpan(faultClause.HandlerOffset, faultClause.HandlerOffset + faultClause.HandlerLength, RegionKind.Fault);
                }

                regions.Add(result);
            }
            return(regions);
        }
    }
コード例 #11
0
        public CilMethodState(CilMethod method, List <CilSigArg> argTypes, List <IValue> argValues, CilProgram program)
        {
            Instruction     = method.Instructions.First();
            EvaluationStack = new CilEvaluationStack();
            MethodInfo      = new CilMethodInfo(method);
            Locals          = new CilOrderedDictionary(method.Locals, program);

            Arguments = new CilOrderedDictionary(argTypes, program);
            for (int i = 0; i < argValues.Count; i++)
            {
                Arguments.Store(null, i, argValues[i]);
            }
        }
コード例 #12
0
        public void Run(CilMethod method)
        {
            IList <OpExpression> infos = method.OpTree;

            method.Locals = method
                            .MethodBody
                            .LocalVariables
                            .Select(v => new LocalInfo {
                ReflectionObject = v
            })
                            .ToArray();

            // TODO: this is probably not enough. need to do proper flow analysis.

            foreach (var op in infos)
            {
                if (op.Instruction.OpCode.Name.StartsWith("stloc"))
                {
                    int id;
                    if (op.Instruction.Data != null)
                    {
                        id = int.Parse(op.Instruction.Data.ToString());
                    }
                    else
                    {
                        id = int.Parse(op.Instruction.OpCode.Name.Substring(5).Replace(".s", ".").Replace(".", ""));
                    }

                    method.Locals[id].IsAssigned = true;
                }
                else if (op.Instruction.OpCode.Name.StartsWith("ldloc"))
                {
                    int id;
                    if (op.Instruction.Data != null)
                    {
                        id = int.Parse(op.Instruction.Data.ToString());
                    }
                    else
                    {
                        id = int.Parse(op.Instruction.OpCode.Name.Substring(5).Replace(".s", ".").Replace(".", ""));
                    }

                    method.Locals[id].IsUsed = true;

                    if (!method.Locals[id].IsAssigned)
                    {
                        method.Locals[id].NeedInit = true;
                    }
                }
            }
        }
コード例 #13
0
        private static int GetParameterCount(CilMethod method)
        {
            var ps = method
                     .ReflectionMethod
                     .GetParameters()
                     .Length;

            if (false == method.ReflectionMethod.IsStatic)
            {
                ps++;
            }

            return(ps);
        }
コード例 #14
0
        private JSFunctionDelcaration CreateGenericFunction(CilMethod method, JSFunctionDelcaration function)
        {
            var mi = method.ReflectionMethod;

            // For static methods on generic classes, the type arguments are passed to
            // the method at the call site rather than wired through the generic class type.

            var types = GetGenericParameterList(mi);

            return(new JSFunctionDelcaration
            {
                Body = { new JSExpressionStatement {
                             Expression = new JSReturnExpression{
                                 Expression = function
                             }
                         } },
                Parameters = types.Select(t => new JSFunctionParameter {
                    Name = t.Name
                }).ToList()
            });
        }
コード例 #15
0
        private JSExpression TranslateDelegateMethod(CilMethod method)
        {
            // TODO: we should avoid the extra trampoline for invoking delegates.
            // We could leave the codegen here though as it can be useful for reflection later

            switch (method.Name)
            {
            case "Invoke":
                return(JSFactory.Identifier("BLR", "delegate_invoke"));

            case "BeginInvoke":
                return(JSFactory.Identifier("BLR", "delegate_begin_invoke"));

            case "EndInvoke":
                return(JSFactory.Identifier("BLR", "delegate_end_invoke"));

            case ".ctor":
                return(JSFactory.Identifier("BLR", "delegate_ctor"));

            default:
                return(JSFunctionDelcaration.Empty);
            }
        }
コード例 #16
0
ファイル: TypeInference.cs プロジェクト: BenitoJedai/Braille
        public void Run(CilMethod method)
        {
            IList <OpExpression> opAst = method.OpTree;

            var visitedTargets = new HashSet <OpExpression>();
            var processStack   = new Stack <OpExpression>();

            processStack.Push(opAst.First());

            while (processStack.Any())
            {
                var op = processStack.Pop();

                if (!visitedTargets.Add(op))
                {
                    continue; // visited already
                }
                foreach (var t in op.Targets)
                {
                    processStack.Push(t);
                }

                if (op.PushCount == 0)
                {
                    continue;
                }

                op.ResultType = InferType(method, op);

                foreach (var loc in op.StoreLocations)
                {
                    loc.ResultType = MergeTypes(loc.ResultType, op.ResultType);
                }
            }

            UpdateVariables(opAst);
        }
コード例 #17
0
ファイル: StackRemoval.cs プロジェクト: BenitoJedai/Braille
        public void Run(CilMethod method)
        {
            var counter = 0;

            foreach (var opInfo in method.OpTree)
            {
                if (opInfo.StackBefore == null)
                {
                    continue;
                }

                foreach (var usage in opInfo.StackBefore.Skip(opInfo.StackBefore.Count() - opInfo.GetRealPopCount()))
                {
                    usage.Variable = new VariableInfo
                    {
                        Name       = string.Format("st_{0:X2}", counter++),
                        ResultType = usage.Type
                    };

                    foreach (var def in usage.Definitions)
                    {
                        if (def is OpExpression)
                        {
                            ((OpExpression)def).StoreLocations.Add(usage.Variable);
                        }
                        else if (def is ExceptionNode)
                        {
                            ((ExceptionNode)def).StoreLocations.Add(usage.Variable);
                        }
                        else
                        {
                            throw new NotImplementedException();
                        }
                    }
                }
            }
        }
コード例 #18
0
        public static int?GetPopCount(CilMethod method, OpInstruction instruction)
        {
            if (instruction.OpCode.Name.StartsWith("leave"))
            {
                return(null); // pops all
            }
            switch (instruction.OpCode.StackBehaviourPop)
            {
            case StackBehaviour.Pop0:
                return(0);

            case StackBehaviour.Pop1:
            case StackBehaviour.Popi:
            case StackBehaviour.Popref:
                return(1);

            case StackBehaviour.Pop1_pop1:
            case StackBehaviour.Popi_pop1:
            case StackBehaviour.Popi_popi:
            case StackBehaviour.Popi_popi8:
            case StackBehaviour.Popi_popr4:
            case StackBehaviour.Popi_popr8:
            case StackBehaviour.Popref_pop1:
            case StackBehaviour.Popref_popi:
                return(2);

            case StackBehaviour.Popi_popi_popi:
            case StackBehaviour.Popref_popi_pop1:
            case StackBehaviour.Popref_popi_popi:
            case StackBehaviour.Popref_popi_popi8:
            case StackBehaviour.Popref_popi_popr4:
            case StackBehaviour.Popref_popi_popr8:
            case StackBehaviour.Popref_popi_popref:
                return(3);

            case StackBehaviour.Varpop:
                if (instruction.OpCode.Name.StartsWith("call"))
                {
                    var callTarget = (MethodBase)instruction.Data;

                    var result = callTarget.GetParameters().Count();

                    if (callTarget.IsStatic == false)
                    {
                        result++;
                    }

                    return(result);
                }
                else if (instruction.OpCode.Name == "newobj")
                {
                    return(((ConstructorInfo)instruction.Data).GetParameters().Count());
                }
                else if (instruction.OpCode.Name == "ret")
                {
                    var mi = method.ReflectionMethod as MethodInfo;

                    if (mi != null && mi.ReturnType.FullName != "System.Void")
                    {
                        return(1);
                    }
                    else
                    {
                        return(0);
                    }
                }
                else
                {
                    throw new NotImplementedException();
                }

            default:
                throw new NotImplementedException();
            }
        }
コード例 #19
0
        public void Run(CilMethod method)
        {
            var opInfos = CreateOpInfos(method);

            method.OpTree = opInfos;
        }
コード例 #20
0
        public override void VisitCallVirtualInstruction(CallVirtualInstruction instruction)
        {
            if (!instruction.CallConv.IsInstance)
            {
                throw new System.NotImplementedException();
            }

            var methodArgs = PopMethodArgs(instruction);

            ControlState.EvaluationStack.PopValue(_program, instruction.TypeSpec.GetCilType(_program), out var thisVal);

            var callExternal = true;

            CilClassInstance thisClassInstance = null;
            CilObject        thisObject        = null;

            if (thisVal is CilValueReference thisValRef)
            {
                var thisObj = ManagedMemory.Load(thisValRef);

                if (thisObj is CilClassInstance)
                {
                    thisClassInstance = thisObj as CilClassInstance;
                }
                else
                {
                    thisObject   = thisObj;
                    callExternal = true;
                }
            }
            else
            {
                throw new System.NotImplementedException();
            }

            CilMethod method = null;

            if (thisClassInstance != null)
            {
                var currentClass = thisClassInstance.Class;
                while (true)
                {
                    var possibleMethod = currentClass.Methods.SingleOrDefault(m => m.Name == instruction.MethodName && AreArgumentsAssignable(instruction.SigArgs, m.Arguments));
                    if (possibleMethod != null)
                    {
                        method       = possibleMethod;
                        callExternal = false;
                        break;
                    }

                    currentClass = currentClass.Extends;
                    if (currentClass == null)
                    {
                        callExternal = true;
                        break;
                    }
                }
            }

            if (callExternal)
            {
                var result = CallExternalMethod(instruction, thisVal, methodArgs.ToArray(), null);

                if (!(instruction.ReturnType is CilTypeVoid))
                {
                    var resultVal = instruction.ReturnType.CreateValueFromRuntime(result, ManagedMemory, _program);
                    ControlState.EvaluationStack.PushValue(resultVal);
                }

                ControlState.MoveToNextInstruction();
            }
            else
            {
                var sigArgsWithThis = CompleteSigArgs(instruction, method);
                var argsWithThis    = CompleteArgs(instruction, methodArgs, thisVal);

                var newMethodState = new CilMethodState(method, sigArgsWithThis, argsWithThis, _program);

                ControlState.MoveToNextInstruction();
                ControlState.CallStack.Push(newMethodState);
            }
        }
コード例 #21
0
        public void Run(CilMethod method)
        {
            var regions = GetRegions(method);

            var spans = regions
                        .SelectMany(r => r.GetSpans())
                        .OrderBy(s => s.From)
                        .ThenByDescending(s => s.To);

            var regionQueue = new Queue <ProtectedRegionSpan>(spans);

            ProtectedRegionSpan awaitedRegion = null;
            ProtectedRegionSpan currentRegion = null;

            var regionStack = new Stack <ProtectedRegionSpan>();

            if (regionQueue.Any())
            {
                awaitedRegion = regionQueue.Dequeue();
            }

            var block = new Block(BlockKind.Normal, 0, 0);

            block.Ast.Add(new JumpLabel(0, false));

            var rootBlock = block;

            var blockStack = new Stack <Block>();

            foreach (var op in method.OpTree)
            {
                while (currentRegion != null && false == currentRegion.Contains(op))
                {
                    // we are no longer in currentRegion, let's wrap it up!

                    var parentBlock = blockStack.Pop();

                    parentBlock.Ast.Add(block);

                    block         = parentBlock;
                    currentRegion = regionStack.Pop();
                }

                if (op.IsLabel)
                {
                    block.Ast.Add(new JumpLabel(op.Position, true));
                }

                while (awaitedRegion != null && awaitedRegion.Contains(op))
                {
                    // we've entered awaitedRegion

                    blockStack.Push(block);

                    block = CreateBlock(awaitedRegion);

                    block.Ast.Add(new JumpLabel(op.Position, false));

                    regionStack.Push(currentRegion);
                    currentRegion = awaitedRegion;

                    if (regionQueue.Any())
                    {
                        awaitedRegion = regionQueue.Dequeue();
                    }
                    else
                    {
                        awaitedRegion = null;
                    }
                }

                block.Ast.Add(op);
                block.To = op.Position;
            }

            if (blockStack.Any())
            {
                var parentBlock = blockStack.Pop();
                parentBlock.Ast.Add(block);
            }

            method.Block = rootBlock;
        }
コード例 #22
0
        public JSFunctionDelcaration GetFirstCallInitializer(CilAssembly assembly, CilType type, CilMethod method)
        {
            if (type.IsIgnored)
            {
                throw new ArgumentException("cannot translate method of ignored class");
            }

            if (!method.NeedInitializer)
            {
                throw new ArgumentException("method need no initialization");
            }

            var functionBlock = new List <JSStatement>();

            JSExpression closedMethodInitializer;
            JSExpression openMethodInitializer = JSFactory.Identifier("asm", GetMethodIdentifier(method.ReflectionMethod) + "_init");

            if (HasGenericParameters(method))
            {
                closedMethodInitializer = new JSCallExpression
                {
                    Function  = openMethodInitializer,
                    Arguments = GetGenericParameterList(method.ReflectionMethod)
                                .Select(t => JSFactory.Identifier(t.Name))
                                .ToList()
                };
            }
            else
            {
                closedMethodInitializer = openMethodInitializer;
            }

            functionBlock.Add(
                new JSCallExpression
            {
                Function  = JSFactory.Identifier(closedMethodInitializer, "apply"),
                Arguments = { JSFactory.Identifier("this"), JSFactory.Identifier("arguments") }
            }.ToStatement());

            JSExpression openMethodImplementation = JSFactory.Identifier("asm", GetMethodIdentifier(method.ReflectionMethod) + "_");
            JSExpression closedMethodImplementation;

            if (HasGenericParameters(method))
            {
                closedMethodImplementation = new JSCallExpression
                {
                    Function  = openMethodImplementation,
                    Arguments = GetGenericParameterList(method.ReflectionMethod)
                                .Select(t => JSFactory.Identifier(t.Name))
                                .ToList()
                };
            }
            else
            {
                closedMethodImplementation = openMethodImplementation;
            }

            functionBlock.Add(
                new JSReturnExpression
            {
                Expression = new JSCallExpression
                {
                    Function  = JSFactory.Identifier(closedMethodImplementation, "apply"),
                    Arguments = { JSFactory.Identifier("this"), JSFactory.Identifier("arguments") }
                }
            }.ToStatement());

            var ps = GetParameterCount(method);

            var f = new JSFunctionDelcaration
            {
                Body       = functionBlock,
                Parameters = Enumerable.Range(0, ps).Select(i => new JSFunctionParameter {
                    Name = "arg" + i
                }).ToList()
            };

            return(HasGenericParameters(method) ? CreateGenericFunction(method, f) : f);
        }
コード例 #23
0
 public ComparisonTranslator(Context context, CilAssembly assembly, CilType type, CilMethod method, Block block)
     : base(context, assembly, type, method, block)
 {
 }
コード例 #24
0
 public void Run(CilMethod method)
 {
     ProcessBlock(method.Block);
 }
コード例 #25
0
 private static bool HasGenericParameters(CilMethod method)
 {
     return((method.ReflectionMethod.IsGenericMethodDefinition) ||
            (method.ReflectionMethod.IsStatic && method.ReflectionMethod.DeclaringType.IsGenericType));
 }
コード例 #26
0
ファイル: TypeInference.cs プロジェクト: BenitoJedai/Braille
        private IKVM.Reflection.Type InferType(CilMethod method, OpExpression op)
        {
            var opc = op.Instruction.OpCode.Name;

            var i    = opc.IndexOf(".");
            var opc_ = i > 0 ? opc.Substring(0, i) : opc;

            var methodBody = method.MethodBody;

            switch (opc_)
            {
            case "add":
            case "and":
                return(InferBinaryArithmeticType(op));

            case "box":
                return(types.Object);

            case "call":
            case "callvirt":
            {
                var mb = ((MethodBase)op.Instruction.Data);

                var mi = mb as MethodInfo;

                if (mi != null)
                {
                    return(mi.ReturnType);
                }

                return(null);
            }

            case "castclass":
                return((IKVM.Reflection.Type)op.Instruction.Data);

            case "ceq":
            case "cgt":
            case "clt":
                return(types.Boolean);    // err... should this be int?

            case "conv":
                var t =
                    opc == "conv.i1" ? types.Int32 :
                    opc == "conv.i2" ? types.Int32 :
                    opc == "conv.i4" ? types.Int32 :
                    opc == "conv.i8" ? types.Int64 :
                    opc == "conv.r4" ? types.Single :
                    opc == "conv.r8" ? types.Double :
                    opc == "conv.u1" ? types.UInt32 :
                    opc == "conv.u2" ? types.UInt32 :
                    opc == "conv.u4" ? types.UInt32 :
                    opc == "conv.u8" ? types.UInt64 :
                    opc == "conv.i" ? types.Int32 :
                    opc == "conv.u" ? types.Int32 :
                    opc == "conv.r.un" ? types.Single : null;

                return(t);

            case "div":
            case "div.un":
                return(InferBinaryArithmeticType(op));

            case "dup":
                return(op.Targeting.First().ResultType);

            case "endfinally":
                return(null);

            case "initobj":
                return((Type)op.Instruction.Data);

            case "isinst":
                return((Type)op.Instruction.Data);

            case "ldarg":
            {
                var id = "";
                if (op.Instruction.Data != null)
                {
                    id = op.Instruction.Data.ToString();
                }
                else
                {
                    id = opc.Replace(".s", ".").Replace(".", "").Substring("ldarg".Length);
                }

                var idx = int.Parse(id);

                if (false == method.ReflectionMethod.IsStatic)
                {
                    if (idx == 0)
                    {
                        if (method.ReflectionMethod.DeclaringType.IsValueType)
                        {
                            return(types.ManagedPointer.MakeGenericType(method.ReflectionMethod.DeclaringType));
                        }
                        else
                        {
                            return(method.ReflectionMethod.DeclaringType);
                        }
                    }
                    else
                    {
                        idx -= 1;
                    }
                }

                return(method.ReflectionMethod.GetParameters()[idx].ParameterType);
            }

            case "ldarga":
            {
                var idxStr = "";

                if (op.Instruction.Data != null)
                {
                    idxStr = op.Instruction.Data.ToString();
                }

                idxStr = opc.Replace(".s", ".").Replace(".", "").Substring("ldarga".Length) + idxStr;

                var idx = int.Parse(idxStr);

                if (method.ReflectionMethod.IsStatic == false)
                {
                    idx--;
                }

                var args = method.ReflectionMethod.GetParameters();
                var type = args[idx].ParameterType;
                return(types.ManagedPointer.MakeGenericType(type));
            }

            case "ldc":
                if (opc.StartsWith("ldc.i4"))
                {
                    return(types.Int32);
                }
                else if (opc.StartsWith("ldc.i8"))
                {
                    return(types.Int64);
                }
                else if (opc.StartsWith("ldc.r8"))
                {
                    return(types.Double);
                }
                else
                {
                    return(types.Single);
                }

            case "ldelem":
                switch (opc)
                {
                case "ldelem":
                    return((Type)op.Instruction.Data);

                case "ldelem.ref":
                    return(op.Arguments.First().ResultType.GetElementType());

                //throw new NotImplementedException(); // array element type
                case "ldelem.i1":
                    return(types.Sbyte);

                case "ldelem.i2":
                    return(types.Int16);

                case "ldelem.i4":
                    return(types.Int32);

                case "ldelem.i8":
                    return(types.Int64);

                case "ldelem.u1":
                    return(types.Byte);

                case "ldelem.u2":
                    return(types.UInt16);

                case "ldelem.u4":
                    return(types.UInt32);

                case "ldelem.u8":
                    return(types.UInt64);

                case "ldelem.r4":
                    return(types.Single);

                case "ldelem.r8":
                    return(types.Double);

                case "ldelem.i":
                    return(types.Int32);

                default:
                    throw new NotSupportedException();
                }

            case "ldelema":
            {
                var type = (Type)op.Instruction.Data;
                return(types.ManagedPointer.MakeGenericType(type));
            }

            case "ldfld":
                return(((FieldInfo)op.Instruction.Data).FieldType);

            case "ldftn":
                return(types.IntPtr);

            case "ldlen":
                return(types.UInt32);

            case "ldloc":
            {
                var id = "";
                if (op.Instruction.Data != null)
                {
                    id = op.Instruction.Data.ToString();
                }
                id = opc.Substring(5).Replace(".s", ".").Replace(".", "") + id;

                return(methodBody.LocalVariables[int.Parse(id)].LocalType);
            }

            case "ldloca":
            {
                var id = "";
                if (op.Instruction.Data != null)
                {
                    id = op.Instruction.Data.ToString();
                }

                var idx = int.Parse(opc.Substring(5).Replace("a.", ".").Replace(".s", ".").Replace(".", "") + id);

                var type = methodBody.LocalVariables[idx].LocalType;
                return(types.ManagedPointer.MakeGenericType(type));
            }

            case "ldnull":
                return(types.Null);

            case "ldobj":
                return((Type)op.Instruction.Data);

            case "ldsfld":
                return(((FieldInfo)op.Instruction.Data).FieldType);

            case "ldflda":
            {
                var fieldType = ((FieldInfo)op.Instruction.Data).FieldType;
                return(types.ManagedPointer.MakeGenericType(fieldType));
            }

            case "ldstr":
                return(types.String);

            case "ldtoken":
                return(types.Object);    //universe.GetType("System.Reflection.MemberInfo");

            case "mul":
                return(InferBinaryArithmeticType(op));

            case "neg":
                return(op.Arguments.First().ResultType);

            case "newarr":
                return(((Type)op.Instruction.Data).MakeArrayType());

            case "newobj":
                return(((ConstructorInfo)op.Instruction.Data).DeclaringType);

            case "nop":
                return(null);

            case "or":
                return(InferBinaryArithmeticType(op));

            case "pop":
                return(null);

            case "rem":
            case "rem.un":
                return(InferBinaryArithmeticType(op));

            case "ret":
                return(null);

            case "shl":
            case "shr":
            case "shr.un":
                return(InferBinaryArithmeticType(op));

            case "stelem":
            case "stind":
            case "stloc":
            case "stfld":
            case "stsfld":
                return(null);

            case "sub":
                return(InferBinaryArithmeticType(op));

            case "throw":
                return(null);

            case "unbox":
                return((Type)op.Instruction.Data);

            default:
                return(null);
            }
        }
コード例 #27
0
        private JSFunctionDelcaration TranslateNormalMethod(CilAssembly asm, CilType type, CilMethod method)
        {
            var functionBlock = new List <JSStatement>();

            if (method.Name == ".cctor")
            {
                var type_id  = GetTypeIdentifier(type.ReflectionType, method.ReflectionMethod);
                var has_init = JSFactory.Identifier(type_id, "FieldsInitialized");

                functionBlock.Add(
                    new JSIfStatement
                {
                    Condition  = has_init,
                    Statements =
                    {
                        new JSReturnExpression().ToStatement()
                    }
                });

                functionBlock.Add(
                    JSFactory
                    .Assignment(has_init, JSFactory.Literal(true))
                    .ToStatement());
            }

            var thisScope = GetThisScope(method.ReflectionMethod, method.ReflectionMethod.DeclaringType);

            if (method.ReferencedTypes != null)
            {
                var tIdx         = 0;
                var typesInScope = new List <Type>();
                foreach (var t in method.ReferencedTypes)
                {
                    functionBlock.Add(
                        new JSVariableDelcaration
                    {
                        Name  = "t" + tIdx,
                        Value = GetTypeIdentifier(t, method.ReflectionMethod, method.ReflectionMethod.DeclaringType, thisScope, typesInScope)
                    }
                        .ToStatement());

                    typesInScope.Add(t);

                    tIdx++;
                }
            }

            if (method.MethodBody.InitLocals)
            {
                var locIdx = 0;

                foreach (var loc in method.MethodBody.LocalVariables)
                {
                    if (method.Locals[locIdx].NeedInit)
                    {
                        functionBlock.Add(
                            new JSExpressionStatement
                        {
                            Expression = new JSVariableDelcaration
                            {
                                Name  = "loc" + locIdx,
                                Value = GetDefaultValue(loc.LocalType, methodScope: method.ReflectionMethod, typeScope: method.ReflectionMethod.DeclaringType, thisScope: thisScope)
                            }
                        });
                    }

                    locIdx++;
                }
            }

            functionBlock.AddRange(
                method
                .Block
                .GetExpressions()
                .Where(o => o.StoreLocations != null)
                .SelectMany(o => o.StoreLocations)
                .Select(l => l.Name)
                .Distinct()
                .OrderBy(n => n)
                .Select(
                    n => new JSExpressionStatement
            {
                Expression = new JSVariableDelcaration
                {
                    Name = n
                }
            }));

            var blockTranslator = new BlockTranslator(context, asm, type, method, thisScope);

            functionBlock.AddRange(
                blockTranslator
                .Translate(method.Block)
                .Where(s => !(s is JSSwitchCase) && !((s is JSExpressionStatement) && (
                                                          ((JSExpressionStatement)s).Expression is JSBreakExpression)))
                .StartWith(
                    new JSVariableDelcaration {
                Name = "__pos__", Value = JSFactory.Hex(0)
            }
                    .ToStatement()));

            var ps = GetParameterCount(method);

            var function = new JSFunctionDelcaration
            {
                Body       = functionBlock,
                Name       = GetSimpleName(method.ReflectionMethod),
                Parameters = Enumerable.Range(0, ps).Select(i => new JSFunctionParameter {
                    Name = "arg" + i
                }).ToList()
            };

            return
                (HasGenericParameters(method) ?
                 CreateGenericFunction(method, function) :
                 function);
        }
コード例 #28
0
        private List <OpExpression> CreateOpInfos(CilMethod method)
        {
            var ilOps    = new OpInstructionReader(method.MethodBody.GetILAsByteArray(), method.Resolver);
            var opInfos  = new List <OpExpression>();
            var prefixes = new List <OpInstruction>();

            foreach (var op in ilOps.Process())
            {
                if (op.OpCode.OpCodeType == OpCodeType.Prefix)
                {
                    prefixes.Add(op);
                    continue;
                }

                OpExpression opx;

                if (op.OpCode.Name.StartsWith("call"))
                {
                    opx = new CallNode(op, prefixes, GetPopCount(method, op), GetPushCount(method, op), context.LookupMethod((MethodBase)op.Data));
                }
                else if (op.OpCode.Name.StartsWith("ldftn"))
                {
                    opx = new LoadFunctionNode(op, prefixes, GetPopCount(method, op), GetPushCount(method, op), context.LookupMethod((MethodBase)op.Data));
                }
                else
                {
                    opx = new OpExpression(op, prefixes, GetPopCount(method, op), GetPushCount(method, op));
                }

                opInfos.Add(opx);

                prefixes = new List <OpInstruction>();
            }

            foreach (var pairs in opInfos.Zip(opInfos.Skip(1), (current, next) => new { current, next }))
            {
                pairs.current.Next = pairs.next;
            }

            foreach (var pairs in opInfos.Zip(opInfos.Skip(1), (prev, current) => new { current, prev }))
            {
                pairs.current.Prev = pairs.prev;
            }

            var body     = method.MethodBody;
            var handlers = body != null ? body.ExceptionHandlingClauses : new List <ExceptionHandlingClause>();

            // Create targets
            foreach (var opInfo in opInfos)
            {
                if (opInfo.Instruction.OpCode.Name == "switch")
                {
                    var i = opInfo.Instruction;
                    var switchEndPosition = 1 + i.Position + i.Size;
                    var target            = opInfos.First(p => p.Position == switchEndPosition);
                    opInfo.Targets.Add(target);

                    foreach (var targetOffset in (int[])i.Data)
                    {
                        var targetPosition = 1 + i.Position + i.Size + targetOffset;
                        target = opInfos.First(f2 => f2.Position == targetPosition);
                        opInfo.Targets.Add(target);
                    }
                }
                else if (opInfo.Instruction.OpCode.FlowControl == FlowControl.Branch)
                {
                    var position = GetTargetPosition(opInfo.Instruction);
                    opInfo.Targets = new List <OpExpression>
                    {
                        opInfos.First(i => i.Position == position)
                    };
                }
                else if (opInfo.Instruction.OpCode.FlowControl == FlowControl.Cond_Branch)
                {
                    var position = GetTargetPosition(opInfo.Instruction);
                    opInfo.Targets = new List <OpExpression>
                    {
                        opInfos.First(i => i.Position == position)
                    };

                    if (opInfo.Next != null)
                    {
                        opInfo.Targets.Add(opInfo.Next);
                    }
                }
                else if (opInfo.Instruction.OpCode.FlowControl == FlowControl.Throw)
                {
                    // nothing
                }
                else
                {
                    if (opInfo.Next != null)
                    {
                        opInfo.Targets.Add(opInfo.Next);
                    }
                }

                if (opInfo.Next != null)
                {
                    foreach (var handler in handlers.Where(t => t.TryOffset == opInfo.Next.Position))
                    {
                        if (handler.Flags != ExceptionHandlingClauseOptions.Clause &&
                            handler.Flags != ExceptionHandlingClauseOptions.Finally)
                        {
                            continue;
                        }

                        var handlerStart = opInfos.First(i => i.Position == handler.HandlerOffset);

                        opInfo.Targets.Add(handlerStart);
                    }
                }

                foreach (var target in opInfo.Targets)
                {
                    target.Targeting.Add(opInfo);
                }
            }

            foreach (var handler in handlers)
            {
                if (handler.Flags != ExceptionHandlingClauseOptions.Clause)
                {
                    continue;
                }

                var handlerStart = opInfos.First(i => i.Position == handler.HandlerOffset);
                handlerStart.IsHandlerStart = true;
            }
            return(opInfos);
        }
コード例 #29
0
 public void Run(CilMethod method)
 {
     InternalProcess(method.OpTree);
 }
コード例 #30
0
        public JSFunctionDelcaration GetInitializer(CilAssembly assembly, CilType type, CilMethod method)
        {
            if (type.IsIgnored)
            {
                throw new ArgumentException("cannot translate method of ignored class");
            }

            if (method.NeedInitializer == false)
            {
                return(null);
            }

            var functionBlock = new List <JSStatement>();

            var thisScope = GetThisScope(method.ReflectionMethod, method.ReflectionMethod.DeclaringType);

            foreach (var t in method.ReferencedTypes)
            {
                if (t.IsGenericParameter) // types shall be initialized before they are used as generic parameters
                {
                    continue;
                }

                functionBlock.Add(
                    new JSCallExpression
                {
                    Function = JSFactory.Identifier(GetTypeIdentifier(t, method.ReflectionMethod, method.ReflectionMethod.DeclaringType, thisScope), "init")
                }
                    .ToStatement());
            }

            bool mustInitialize = false;

            if (method.DeclaringType.ReflectionType.IsGenericTypeDefinition && method.ReflectionMethod.IsConstructor)
            {
                mustInitialize = true;
            }

            else if (HasGenericParameters(method) || type.ReflectionType.IsGenericType)
            {
                var args = GetGenericParameterList(method.ReflectionMethod)
                           .Concat(type.ReflectionType.GetGenericArguments())
                           .ToList()
                ;

                mustInitialize = method
                                 .ReferencedTypes
                                 .Where(r => r.IsGenericType || r.IsArray)
                                 .Any(r => r
                                      .GetGenericArguments()
                                      .Intersect(args)
                                      .Any() ||
                                      (r.IsArray && args.Contains(r.GetElementType())));
            }

            // We need to always call the initializer for
            //  1. constructors of generic types, since we have no type arguments
            //  2. any method with generic arguments which are used in the initializer
            //
            // TODO: we should inline the initialization for those cases.

            if (!mustInitialize)
            {
                functionBlock.Add(
                    JSFactory
                    .Assignment(
                        JSFactory.Identifier("asm", GetMethodIdentifier(method.ReflectionMethod)),
                        JSFactory.Identifier("asm", GetMethodIdentifier(method.ReflectionMethod) + "_"))
                    .ToStatement());
            }

            var f = new JSFunctionDelcaration
            {
                Body = functionBlock
            };

            return(HasGenericParameters(method) ? CreateGenericFunction(method, f) : f);
        }