Exemplo n.º 1
0
        public StringLiteralDictionary(ReferenceResolver resolver)
        {
            m_dict      = new Dictionary <string, FieldReference>();
            m_resolver  = resolver;
            m_usedNames = new HashSet <string>();

            m_typedef = new TypeDefinition("", ARRAY_CLASS_NAME,
                                           TypeAttributes.Public |
                                           TypeAttributes.Sealed | TypeAttributes.Abstract /*static*/);


            // make sure other parts of the system don't get confused
            m_resolver.GetTypeReference(typeof(ESharp.EObject)).Module.Types.Add(m_typedef);
        }
Exemplo n.º 2
0
        public void TransformIL(IEnumerable <TypeDefinition> types)
        {
            m_resolver = new ReferenceResolver(types);
            var mod = ModuleDefinition.CreateModule("t", ModuleKind.Dll);

            foreach (var t in types)
            {
                foreach (var m in t.Methods)
                {
                    if (!m.HasBody)
                    {
                        continue;
                    }

                    var exceptionVariable = new VariableDefinition(m_resolver.GetTypeReference(typeof(EException)));
                    m.Body.Variables.Add(exceptionVariable);

                    var ilp   = m.Body.GetILProcessor();
                    var insts = m.Body.Instructions;


                    for (int idx = 0; idx < m.Body.Instructions.Count; idx++)
                    {
                        var i    = m.Body.Instructions[idx];
                        var next = i.Next;

                        //store thrown exceptions in variable, this is how the rest of this function expects it
                        if (i.OpCode == OpCodes.Throw)
                        {
                            ilp.InsertBefore(i, ilp.Create(OpCodes.Stloc, exceptionVariable));
                            idx++;
                        }
                    }


                    RethrowCallException(m, exceptionVariable);

                    // remember that this method might throw.
                    // todo, base this on the outcome of this routine??
                    if (m_helper.CanThrow(m))
                    {
                        m.CustomAttributes.Add(new CustomAttribute(mod.ImportReference(typeof(Throws).GetConstructor(new Type[] { })), new byte[] { 1, 0, 0, 0 }));
                    }



                    if (m.Body.Instructions.Any(x => x.OpCode == OpCodes.Throw))
                    {
                        AddUncaugtCatch(m, exceptionVariable);
                    }



                    foreach (var handlerGroup in m.Body.ExceptionHandlers.GroupBy(x => Tuple.Create(x.TryStart, x.TryEnd)).ToArray())                       //x.TryStart.Offset << 16 + x.TryEnd.Offset


                    // todo support multiple catch handlers
                    {
                        var catchHandler   = handlerGroup.SingleOrDefault(x => x.HandlerType == ExceptionHandlerType.Catch);
                        var finallyHandler = handlerGroup.SingleOrDefault(x => x.HandlerType == ExceptionHandlerType.Finally);

                        if (catchHandler != null)                           // catch handler
                        {
                            ReplaceCatch(ilp, catchHandler, exceptionVariable);

                            // remove old catch
                            var block = insts.SkipWhile(x => x != catchHandler.HandlerStart).TakeWhile(x => x != catchHandler.HandlerEnd).ToArray();
                            foreach (var bi in block)
                            {
                                ilp.Remove(bi);
                            }
                            m.Body.ExceptionHandlers.Remove(catchHandler);

                            // todo remove handler
                        }
                        //{ // finally handler

                        //}
                    }


                    Debug.Assert(!m.Body.Instructions.Any(x => x.OpCode == OpCodes.Throw), "No throw insturction should be remaining");
                    Debug.Assert(!m.Body.HasExceptionHandlers, "No Exception Handlers should be remaining");
                }
            }
        }
Exemplo n.º 3
0
        // This logic will catch uncaught exceptions when leaving a function
        public void AddUncaugtCatch(MethodDefinition m, VariableDefinition excpetionVariable)
        {
            if (!m.HasBody || m.Body.Instructions.Count == 0)
            {
                return;
            }

            var insts = m.Body.Instructions;
            var ilp   = m.Body.GetILProcessor();

            var retType    = m.ReturnType.Resolve();
            var useRetType = retType.Name != "Void";

            var catchLabel = ilp.Create(OpCodes.Nop);
            var retunLabel = ilp.Create(OpCodes.Nop);


            if (!insts.Any(x => x.OpCode == OpCodes.Ret))
            {
                // no ret, eg because the function throws; need dummy ret

                if (retType.Name != "Void")
                {
                    if (retType.IsValueType)
                    {
                        var variable = new VariableDefinition(retType);
                        m.Body.Variables.Add(variable);
                        ilp.Emit(OpCodes.Ldloca, variable);
                        ilp.Emit(OpCodes.Initobj, retType);
                        ilp.Emit(OpCodes.Ldloc, variable);
                    }
                    else
                    {
                        ilp.Emit(OpCodes.Ldnull);
                    }
                }

                ilp.Emit(OpCodes.Ret);
            }

            var old_ret = insts.Last();

            Debug.Assert(old_ret.OpCode == OpCodes.Ret, "Ret instruction expected at the end of each function");

            // No need for leave here as stack is always correct.
            // Actually don't use leave as a return code might be on the stack.
            ilp.InsertBefore(old_ret, ilp.Create(OpCodes.Br, retunLabel));

            ilp.InsertBefore(old_ret, catchLabel);
            ilp.InsertBefore(old_ret, retunLabel);

            // create catch block (store exception, exception should be on the top of the stack)
            var fieldref = m_resolver.GetField("ESharp.EException", "S_EException_LastException");

            ilp.InsertBefore(retunLabel, ilp.Create(OpCodes.Stsfld, fieldref));

            // load default return value
            if (useRetType)
            {
                if (retType.IsValueType)
                {
                    var variable = new VariableDefinition(retType);
                    m.Body.Variables.Add(variable);
                    ilp.InsertBefore(retunLabel, ilp.Create(OpCodes.Ldloca, variable));
                    ilp.InsertBefore(retunLabel, ilp.Create(OpCodes.Initobj, retType));
                    ilp.InsertBefore(retunLabel, ilp.Create(OpCodes.Ldloc, variable));
                }
                else
                {
                    ilp.InsertBefore(retunLabel, ilp.Create(OpCodes.Ldnull));
                }
                // fall through to return label
            }

            var handler = new ExceptionHandler(ExceptionHandlerType.Catch)
            {
                TryStart     = insts.First(),
                TryEnd       = catchLabel,
                HandlerStart = catchLabel,
                HandlerEnd   = retunLabel,
                CatchType    = m_resolver.GetTypeReference("EException")
            };

            m.Body.ExceptionHandlers.Add(handler);
        }
Exemplo n.º 4
0
 public FieldReference AddArray_1(byte[] data)
 {
     return(AddGeneric("array" + m_counter++, m_resolver.GetTypeReference("Array_1"), "Array_1", data.Cast <object>()));
 }