private void TransformPInvokeMethodDefinitionToImplementedMethodDefinition(MethodDefinition methodDefinition)
        {
            methodDefinition.IsPlatformInvoke  = false;
            methodDefinition.IsExternal        = false;
            methodDefinition.PreserveSignature = false;

            var ilGenerator            = new ILGenerator(this.host, methodDefinition);
            var label                  = new ILGeneratorLabel();
            var transformationMetadata = this.metadataProvider.Retrieve(methodDefinition);

            var fieldDef        = transformationMetadata.FunctionPointer;
            var locals          = new List <ILocalDefinition>();
            var paramToLocalMap = new Dictionary <IParameterDefinition, ILocalDefinition>();

            ilGenerator.Emit(OperationCode.Ldsfld, fieldDef);
            ilGenerator.Emit(OperationCode.Ldsfld, this.intPtrZero);
            ilGenerator.Emit(OperationCode.Call, this.intPtrOpEquality);
            ilGenerator.Emit(OperationCode.Brfalse_S, label);
            ilGenerator.Emit(OperationCode.Call, transformationMetadata.InitializeMethod);
            ilGenerator.MarkLabel(label);
            this.LoadArguments(locals, paramToLocalMap, ilGenerator, methodDefinition.ParameterCount, i => methodDefinition.Parameters[i], methodDefinition.PlatformInvokeData);
            ilGenerator.Emit(OperationCode.Ldsfld, fieldDef);
            ilGenerator.Emit(OperationCode.Call, transformationMetadata.NativeMethod);
            this.ReturnMarshalling(ilGenerator, methodDefinition);
            this.PostprocessNonBlittableArrayArguments(methodDefinition, locals, paramToLocalMap, ilGenerator);
            ilGenerator.Emit(OperationCode.Ret);

            var ilMethodBody = new ILGeneratorMethodBody(ilGenerator, true, (ushort)((methodDefinition.ParameterCount + 1) * 2), methodDefinition, locals, new List <ITypeDefinition>());

            methodDefinition.PlatformInvokeData = null;
            methodDefinition.Body = ilMethodBody;
        }
Exemple #2
0
        private static IMethodDefinition CreateFreeLibrary(IMetadataHost host, ITypeDefinition typeDef, IMethodReference windowsFreeLibrary, IMethodReference unixFreeLibrary, IFieldReference isUnix)
        {
            var methodDefinition = new MethodDefinition
            {
                Name = host.NameTable.GetNameFor("FreeLibrary"),
                ContainingTypeDefinition = typeDef,
                Parameters = new List <IParameterDefinition> {
                    new ParameterDefinition {
                        Index = 0, Type = host.PlatformType.SystemIntPtr
                    }
                },
                IsStatic            = true,
                IsHiddenBySignature = true,
                Visibility          = TypeMemberVisibility.Public,
                Type = host.PlatformType.SystemInt32
            };

            var ilGenerator = new ILGenerator(host, methodDefinition);
            var label       = new ILGeneratorLabel();

            ilGenerator.Emit(OperationCode.Ldsfld, isUnix);
            ilGenerator.Emit(OperationCode.Brtrue_S, label);
            ilGenerator.Emit(OperationCode.Ldarg_0);
            ilGenerator.Emit(OperationCode.Call, windowsFreeLibrary);
            ilGenerator.Emit(OperationCode.Ret);
            ilGenerator.MarkLabel(label);
            ilGenerator.Emit(OperationCode.Ldarg_0);
            ilGenerator.Emit(OperationCode.Ldc_I4_0);
            ilGenerator.Emit(OperationCode.Call, unixFreeLibrary);
            ilGenerator.Emit(OperationCode.Ret);

            methodDefinition.Body = new ILGeneratorMethodBody(ilGenerator, true, 8, methodDefinition, new List <ILocalDefinition>(), new List <ITypeDefinition>());

            return(methodDefinition);
        }
        /// <summary>
        /// This method is called for all labels.
        /// </summary>
        /// <param name="op">The Microsoft intermediate language (MSIL) instruction that is marked as being a label.</param>
        /// <param name="label">A label that can be used to designate locations in MSIL where an instruction may jump.</param>
        protected virtual void RewriteLabel(IOperation op, ILGeneratorLabel label)
        {
            Contract.Requires(this.generator != null);
            Contract.Requires(op != null);
            Contract.Requires(label != null);

            this.generator.MarkLabel(label);
        }
        private static IMethodDefinition CreateGetOperatingSystemMethod(IMetadataHost host, ITypeDefinition typeDef, IMethodReference stringOPEquality, IMethodReference uname)
        {
            var methodDefinition = new MethodDefinition
            {
                Name     = host.NameTable.GetNameFor("GetOperatingSystem"),
                IsStatic = true,
                ContainingTypeDefinition = typeDef,
                IsHiddenBySignature      = true,
                Visibility = TypeMemberVisibility.Private,
                Type       = host.PlatformType.SystemInt32
            };

            ILGenerator ilGenerator = new ILGenerator(host, methodDefinition);

            ilGenerator.Emit(OperationCode.Call, uname);
            ilGenerator.Emit(OperationCode.Stloc_0);

            var linuxLabel   = new ILGeneratorLabel();
            var darwinLabel  = new ILGeneratorLabel();
            var freebsdLabel = new ILGeneratorLabel();
            var netbsdLabel  = new ILGeneratorLabel();
            var unknownLabel = new ILGeneratorLabel();

            AddOperatingSystemCase(ilGenerator, "Linux", stringOPEquality, linuxLabel);
            AddOperatingSystemCase(ilGenerator, "Darwin", stringOPEquality, darwinLabel);
            AddOperatingSystemCase(ilGenerator, "FreeBSD", stringOPEquality, freebsdLabel);
            AddOperatingSystemCase(ilGenerator, "NetBSD", stringOPEquality, netbsdLabel);

            ilGenerator.Emit(OperationCode.Br_S, unknownLabel);

            ilGenerator.MarkLabel(linuxLabel);
            ilGenerator.Emit(OperationCode.Ldc_I4_1);
            ilGenerator.Emit(OperationCode.Ret);

            ilGenerator.MarkLabel(darwinLabel);
            ilGenerator.Emit(OperationCode.Ldc_I4_2);
            ilGenerator.Emit(OperationCode.Ret);

            ilGenerator.MarkLabel(freebsdLabel);
            ilGenerator.Emit(OperationCode.Ldc_I4_3);
            ilGenerator.Emit(OperationCode.Ret);

            ilGenerator.MarkLabel(netbsdLabel);
            ilGenerator.Emit(OperationCode.Ldc_I4_4);
            ilGenerator.Emit(OperationCode.Ret);

            ilGenerator.MarkLabel(unknownLabel);
            ilGenerator.Emit(OperationCode.Ldc_I4_0);
            ilGenerator.Emit(OperationCode.Ret);

            methodDefinition.Body = new ILGeneratorMethodBody(ilGenerator, true, 2, methodDefinition, new List <ILocalDefinition> {
                new LocalDefinition {
                    Type = host.PlatformType.SystemString
                }
            }, new List <ITypeDefinition>());
            return(methodDefinition);
        }
        private ILGeneratorLabel GetLabelFor(uint offset)
        {
            var result = this.labelFor[offset];

            if (result == null)
            {
                this.labelFor[offset] = result = new ILGeneratorLabel();
            }
            return(result);
        }
        /// <summary>
        /// This method is called for all opcodes related to branches:
        ///    OperationCode.Beq:
        ///    OperationCode.Bge:
        ///    OperationCode.Bge_Un:
        ///    OperationCode.Bgt:
        ///    OperationCode.Bgt_Un:
        ///    OperationCode.Ble:
        ///    OperationCode.Ble_Un:
        ///    OperationCode.Blt:
        ///    OperationCode.Blt_Un:
        ///    OperationCode.Bne_Un:
        ///    OperationCode.Br:
        ///    OperationCode.Brfalse:
        ///    OperationCode.Brtrue:
        ///    OperationCode.Leave:
        ///    OperationCode.Beq_S:
        ///    OperationCode.Bge_S:
        ///    OperationCode.Bge_Un_S:
        ///    OperationCode.Bgt_S:
        ///    OperationCode.Bgt_Un_S:
        ///    OperationCode.Ble_S:
        ///    OperationCode.Ble_Un_S:
        ///    OperationCode.Blt_S:
        ///    OperationCode.Blt_Un_S:
        ///    OperationCode.Bne_Un_S:
        ///    OperationCode.Br_S:
        ///    OperationCode.Brfalse_S:
        ///    OperationCode.Brtrue_S:
        ///    OperationCode.Leave_S:
        /// </summary>
        /// <param name="op">The Microsoft intermediate language (MSIL) instruction to be copied.</param>
        protected virtual void RewriteBranch(IOperation op)
        {
            Contract.Requires(this.generator != null);
            Contract.Requires(op != null);

            // handle branches
            switch (op.OperationCode)
            {
            // Branches
            case OperationCode.Beq:
            case OperationCode.Bge:
            case OperationCode.Bge_Un:
            case OperationCode.Bgt:
            case OperationCode.Bgt_Un:
            case OperationCode.Ble:
            case OperationCode.Ble_Un:
            case OperationCode.Blt:
            case OperationCode.Blt_Un:
            case OperationCode.Bne_Un:
            case OperationCode.Br:
            case OperationCode.Brfalse:
            case OperationCode.Brtrue:
            case OperationCode.Leave:
            case OperationCode.Beq_S:
            case OperationCode.Bge_S:
            case OperationCode.Bge_Un_S:
            case OperationCode.Bgt_S:
            case OperationCode.Bgt_Un_S:
            case OperationCode.Ble_S:
            case OperationCode.Ble_Un_S:
            case OperationCode.Blt_S:
            case OperationCode.Blt_Un_S:
            case OperationCode.Bne_Un_S:
            case OperationCode.Br_S:
            case OperationCode.Brfalse_S:
            case OperationCode.Brtrue_S:
            case OperationCode.Leave_S:
                this.generator.Emit(ILGenerator.LongVersionOf(op.OperationCode),
                                    this.offset2Label[(uint)op.Value]);
                break;

            case OperationCode.Switch:
                uint[]             offsets = op.Value as uint[];
                ILGeneratorLabel[] labels  = new ILGeneratorLabel[offsets.Length];
                for (int j = 0, n = offsets.Length; j < n; j++)
                {
                    labels[j] = offset2Label[offsets[j]];
                }
                this.generator.Emit(OperationCode.Switch, labels);
                break;

            default:
                throw new Exception("Only branches should be handled here");
            }
        }
        private static void EmitBoolMarshalling(ILGenerator ilGenerator)
        {
            var trueCase  = new ILGeneratorLabel();
            var falseCase = new ILGeneratorLabel();

            ilGenerator.Emit(OperationCode.Brtrue_S, trueCase);
            ilGenerator.Emit(OperationCode.Ldc_I4_0);
            ilGenerator.Emit(OperationCode.Br_S, falseCase);
            ilGenerator.MarkLabel(trueCase);
            ilGenerator.Emit(OperationCode.Ldc_I4_1);
            ilGenerator.MarkLabel(falseCase);
        }
        private static void EmitUnicodeStringMarshalling(List <ILocalDefinition> locals, ILGenerator ilGenerator, IMethodReference getOffsetToStringData, ITypeReference stringType)
        {
            var pinnedLocal = new LocalDefinition {
                IsPinned = true, Type = stringType
            };

            locals.Add(pinnedLocal);

            var nullCaseLabel = new ILGeneratorLabel();

            ilGenerator.Emit(OperationCode.Stloc, pinnedLocal);
            ilGenerator.Emit(OperationCode.Ldloc, pinnedLocal);
            ilGenerator.Emit(OperationCode.Conv_I);
            ilGenerator.Emit(OperationCode.Dup);
            ilGenerator.Emit(OperationCode.Brfalse_S, nullCaseLabel);
            ilGenerator.Emit(OperationCode.Call, getOffsetToStringData);
            ilGenerator.Emit(OperationCode.Add);
            ilGenerator.MarkLabel(nullCaseLabel);
        }
        private void PostprocessNonBlittableArrayArguments(IMethodDefinition methodDefinition, List <ILocalDefinition> locals, Dictionary <IParameterDefinition, ILocalDefinition> paramToLocalMap, ILGenerator ilGenerator)
        {
            bool hasReturnValue = methodDefinition.Type != this.host.PlatformType.SystemVoid;

            if (IsAnyParameterNonBlittableArray(methodDefinition))
            {
                var retLocal = new LocalDefinition
                {
                    IsPinned = false,
                    Type     = methodDefinition.Type
                };

                if (hasReturnValue)
                {
                    locals.Add(retLocal);
                    ilGenerator.Emit(OperationCode.Stloc, retLocal);
                }

                var exitLabel = new ILGeneratorLabel();
                ilGenerator.Emit(OperationCode.Leave, exitLabel);
                ilGenerator.BeginFinallyBlock();

                foreach (var elem in methodDefinition.Parameters)
                {
                    ILocalDefinition t;
                    if (paramToLocalMap.TryGetValue(elem, out t))
                    {
                        ilGenerator.Emit(OperationCode.Ldloc, t);
                        ilGenerator.Emit(OperationCode.Call, this.stringArrayMarshallingEpilog); // TODO: Generalize for other array types
                    }
                }

                ilGenerator.Emit(OperationCode.Endfinally);
                ilGenerator.EndTryBody();
                ilGenerator.MarkLabel(exitLabel);

                if (hasReturnValue)
                {
                    ilGenerator.Emit(OperationCode.Ldloc, retLocal);
                }
            }
        }
        private static void EmitBlittableTypeArrayMarshalling(List <ILocalDefinition> locals, ILGenerator ilGenerator, IArrayType arrayType)
        {
            var nullCaseLabel = new ILGeneratorLabel();

            // [0] T& pinned x
            var pinnedLocal = new LocalDefinition
            {
                IsPinned    = true,
                IsReference = true,
                Type        = arrayType.ElementType
            };

            // [1] T[] V_1,
            var duplicatearray = new LocalDefinition
            {
                IsPinned = false,
                Type     = arrayType
            };

            locals.Add(pinnedLocal);
            locals.Add(duplicatearray);

            ilGenerator.Emit(OperationCode.Dup);
            ilGenerator.Emit(OperationCode.Stloc, duplicatearray);
            ilGenerator.Emit(OperationCode.Brfalse, nullCaseLabel);
            ilGenerator.Emit(OperationCode.Ldloc, duplicatearray);
            ilGenerator.Emit(OperationCode.Ldlen);
            ilGenerator.Emit(OperationCode.Conv_I4);
            ilGenerator.Emit(OperationCode.Brfalse, nullCaseLabel);
            ilGenerator.Emit(OperationCode.Ldloc, duplicatearray);
            ilGenerator.Emit(OperationCode.Ldc_I4_0);
            ilGenerator.Emit(OperationCode.Ldelema, arrayType.ElementType);
            ilGenerator.Emit(OperationCode.Stloc, pinnedLocal);
            ilGenerator.MarkLabel(nullCaseLabel);
            ilGenerator.Emit(OperationCode.Ldloc, pinnedLocal);
            ilGenerator.Emit(OperationCode.Conv_I);
        }
        /// <summary>
        /// Emits the specified number of operations from the original method body.
        /// </summary>
        /// <param name="count"></param>
        public void EmitOperations(int count)
        {
            for (int i = 0; i < count; i++)
            {
                IOperation op = operations[0];
                operations.RemoveAt(0);
                ILGeneratorLabel label;
                if (op.Location is IILLocation)
                {
                    MarkSequencePoint(op.Location);
                }

                // Mark operation if it is a label for a branch
                if (offset2Label.TryGetValue(op.Offset, out label))
                {
                    MarkLabel(label);
                }

                // Mark operation if it is pointed to by an exception handler
                bool ignore;
                uint offset = op.Offset;
                if (offsetsUsedInExceptionInformation.TryGetValue(offset, out ignore))
                {
                    foreach (var exceptionInfo in methodBody.OperationExceptionInformation)
                    {
                        if (offset == exceptionInfo.TryStartOffset)
                        {
                            BeginTryBody();
                        }

                        // Never need to do anthing when offset == exceptionInfo.TryEndOffset because
                        // we pick up an EndTryBody from the HandlerEndOffset below
                        //  EndTryBody();

                        if (offset == exceptionInfo.HandlerStartOffset)
                        {
                            switch (exceptionInfo.HandlerKind)
                            {
                            case HandlerKind.Catch:
                                BeginCatchBlock(exceptionInfo.ExceptionType);
                                break;

                            case HandlerKind.Fault:
                                BeginFaultBlock();
                                break;

                            case HandlerKind.Filter:
                                BeginFilterBody();
                                break;

                            case HandlerKind.Finally:
                                BeginFinallyBlock();
                                break;
                            }
                        }

                        if (exceptionInfo.HandlerKind == HandlerKind.Filter && offset == exceptionInfo.FilterDecisionStartOffset)
                        {
                            BeginFilterBlock();
                        }

                        if (offset == exceptionInfo.HandlerEndOffset)
                        {
                            EndTryBody();
                        }
                    }
                }

                // Emit operation along with any injection
                switch (op.OperationCode)
                {
                // Branches
                case OperationCode.Beq:
                case OperationCode.Bge:
                case OperationCode.Bge_Un:
                case OperationCode.Bgt:
                case OperationCode.Bgt_Un:
                case OperationCode.Ble:
                case OperationCode.Ble_Un:
                case OperationCode.Blt:
                case OperationCode.Blt_Un:
                case OperationCode.Bne_Un:
                case OperationCode.Br:
                case OperationCode.Brfalse:
                case OperationCode.Brtrue:
                case OperationCode.Leave:
                case OperationCode.Beq_S:
                case OperationCode.Bge_S:
                case OperationCode.Bge_Un_S:
                case OperationCode.Bgt_S:
                case OperationCode.Bgt_Un_S:
                case OperationCode.Ble_S:
                case OperationCode.Ble_Un_S:
                case OperationCode.Blt_S:
                case OperationCode.Blt_Un_S:
                case OperationCode.Bne_Un_S:
                case OperationCode.Br_S:
                case OperationCode.Brfalse_S:
                case OperationCode.Brtrue_S:
                case OperationCode.Leave_S:
                    Emit(ILGenerator.LongVersionOf(op.OperationCode), offset2Label[(uint)op.Value]);
                    break;

                case OperationCode.Switch:
                    uint[]             offsets = op.Value as uint[];
                    ILGeneratorLabel[] labels  = new ILGeneratorLabel[offsets.Length];
                    for (int j = 0, n = offsets.Length; j < n; j++)
                    {
                        labels[j] = offset2Label[offsets[j]];
                    }
                    Emit(OperationCode.Switch, labels);
                    break;

                // Everything else
                default:
                    if (op.Value == null)
                    {
                        Emit(op.OperationCode);
                        break;
                    }
                    var typeCode = System.Convert.GetTypeCode(op.Value);
                    switch (typeCode)
                    {
                    case TypeCode.Byte:
                        Emit(op.OperationCode, (byte)op.Value);
                        break;

                    case TypeCode.Double:
                        Emit(op.OperationCode, (double)op.Value);
                        break;

                    case TypeCode.Int16:
                        Emit(op.OperationCode, (short)op.Value);
                        break;

                    case TypeCode.Int32:
                        Emit(op.OperationCode, (int)op.Value);
                        break;

                    case TypeCode.Int64:
                        Emit(op.OperationCode, (long)op.Value);
                        break;

                    case TypeCode.Object:
                        IFieldReference fieldReference = op.Value as IFieldReference;
                        if (fieldReference != null)
                        {
                            Emit(op.OperationCode, fieldReference);
                            break;
                        }
                        ILocalDefinition localDefinition = op.Value as ILocalDefinition;
                        if (localDefinition != null)
                        {
                            Emit(op.OperationCode, localDefinition);
                            break;
                        }
                        IMethodReference methodReference = op.Value as IMethodReference;
                        if (methodReference != null)
                        {
                            Emit(op.OperationCode, methodReference);
                            break;
                        }
                        IParameterDefinition parameterDefinition = op.Value as IParameterDefinition;
                        if (parameterDefinition != null)
                        {
                            Emit(op.OperationCode, parameterDefinition);
                            break;
                        }
                        ISignature signature = op.Value as ISignature;
                        if (signature != null)
                        {
                            Emit(op.OperationCode, signature);
                            break;
                        }
                        ITypeReference typeReference = op.Value as ITypeReference;
                        if (typeReference != null)
                        {
                            Emit(op.OperationCode, typeReference);
                            break;
                        }
                        throw new Exception("Should never get here: no other IOperation argument types should exist");

                    case TypeCode.SByte:
                        Emit(op.OperationCode, (sbyte)op.Value);
                        break;

                    case TypeCode.Single:
                        Emit(op.OperationCode, (float)op.Value);
                        break;

                    case TypeCode.String:
                        Emit(op.OperationCode, (string)op.Value);
                        break;

                    default:
                        throw new Exception("Should never get here: no other IOperation argument types should exist");
                    }
                    break;
                }
            }
        }
Exemple #12
0
        private static IMethodDefinition CreateStringArrayMarshallingProlog(IMetadataHost host, ITypeDefinition typeDef, IMethodReference stringToHGlobal, string methodName)
        {
            var stringArrayType = new VectorTypeReference {
                ElementType = host.PlatformType.SystemString, Rank = 1
            };
            var intPtrArrayType = new VectorTypeReference {
                ElementType = host.PlatformType.SystemIntPtr, Rank = 1
            };

            MethodDefinition methodDefinition = new MethodDefinition
            {
                ContainingTypeDefinition = typeDef,
                IsStatic   = true,
                Visibility = TypeMemberVisibility.Assembly,
                Parameters = new List <IParameterDefinition> {
                    new ParameterDefinition {
                        Index = 0, Type = stringArrayType
                    }, new ParameterDefinition {
                        Index = 1, Type = intPtrArrayType
                    }
                },
                Type = host.PlatformType.SystemVoid,
                Name = host.NameTable.GetNameFor(methodName)
            };

            var size = new LocalDefinition {
                Type = host.PlatformType.SystemInt32
            };
            var index = new LocalDefinition {
                Type = host.PlatformType.SystemInt32
            };

            var locals = new List <ILocalDefinition> {
                size, index
            };

            var ilGenerator  = new ILGenerator(host, methodDefinition);
            var loopStart    = new ILGeneratorLabel();
            var loopBackEdge = new ILGeneratorLabel();

            ilGenerator.Emit(OperationCode.Ldarg_0);
            ilGenerator.Emit(OperationCode.Ldlen);
            ilGenerator.Emit(OperationCode.Conv_I4);
            ilGenerator.Emit(OperationCode.Stloc_0);
            ilGenerator.Emit(OperationCode.Ldc_I4_0);
            ilGenerator.Emit(OperationCode.Stloc_1);
            ilGenerator.Emit(OperationCode.Br_S, loopBackEdge);
            ilGenerator.MarkLabel(loopStart);
            ilGenerator.Emit(OperationCode.Ldarg_1);
            ilGenerator.Emit(OperationCode.Ldloc_1);
            ilGenerator.Emit(OperationCode.Ldarg_0);
            ilGenerator.Emit(OperationCode.Ldloc_1);
            ilGenerator.Emit(OperationCode.Ldelem_Ref);
            ilGenerator.Emit(OperationCode.Call, stringToHGlobal);
            ilGenerator.Emit(OperationCode.Stelem_I);
            ilGenerator.Emit(OperationCode.Ldloc_1);
            ilGenerator.Emit(OperationCode.Ldc_I4_1);
            ilGenerator.Emit(OperationCode.Add);
            ilGenerator.Emit(OperationCode.Stloc_1);
            ilGenerator.MarkLabel(loopBackEdge);
            ilGenerator.Emit(OperationCode.Ldloc_1);
            ilGenerator.Emit(OperationCode.Ldloc_0);
            ilGenerator.Emit(OperationCode.Blt_S, loopStart);
            ilGenerator.Emit(OperationCode.Ret);

            methodDefinition.Body = new ILGeneratorMethodBody(ilGenerator, true, 4, methodDefinition, locals, new List <ITypeDefinition>());

            return(methodDefinition);
        }
Exemple #13
0
        private static IMethodDefinition CreateStringToAnsi(IMetadataHost host, ITypeDefinition typeDef, IMethodReference getLength, IMethodReference getChars)
        {
            var byteType      = host.PlatformType.SystemUInt8;
            var byteArrayType = new VectorTypeReference {
                ElementType = byteType, Rank = 1
            };

            MethodDefinition methodDefinition = new MethodDefinition
            {
                ContainingTypeDefinition = typeDef,
                IsStatic   = true,
                Visibility = TypeMemberVisibility.Assembly,
                Type       = byteArrayType.ResolvedArrayType,
                Parameters = new List <IParameterDefinition> {
                    new ParameterDefinition {
                        Type = host.PlatformType.SystemString
                    }
                },
                Name = host.NameTable.GetNameFor("StringToAnsiByteArray")
            };

            var length = new LocalDefinition {
                Type = host.PlatformType.SystemInt32
            };
            var byteArray = new LocalDefinition {
                Type = byteArrayType.ResolvedArrayType
            };
            var loopIndex = new LocalDefinition {
                Type = host.PlatformType.SystemInt32
            };

            var locals = new List <ILocalDefinition> {
                length, byteArray, loopIndex
            };

            var ilGenerator   = new ILGenerator(host, methodDefinition);
            var nullCaseLabel = new ILGeneratorLabel();
            var loopStart     = new ILGeneratorLabel();
            var loopBackEdge  = new ILGeneratorLabel();

            ilGenerator.Emit(OperationCode.Ldarg_0);
            ilGenerator.Emit(OperationCode.Brtrue_S, nullCaseLabel);
            ilGenerator.Emit(OperationCode.Ldnull);
            ilGenerator.Emit(OperationCode.Ret);
            ilGenerator.MarkLabel(nullCaseLabel);
            ilGenerator.Emit(OperationCode.Ldarg_0);
            ilGenerator.Emit(OperationCode.Call, getLength);
            ilGenerator.Emit(OperationCode.Stloc_0);
            ilGenerator.Emit(OperationCode.Ldloc_0);
            ilGenerator.Emit(OperationCode.Ldc_I4_1);
            ilGenerator.Emit(OperationCode.Add);
            ilGenerator.Emit(OperationCode.Newarr, byteArrayType);
            ilGenerator.Emit(OperationCode.Stloc_1);
            ilGenerator.Emit(OperationCode.Ldc_I4_0);
            ilGenerator.Emit(OperationCode.Stloc_2);
            ilGenerator.Emit(OperationCode.Br_S, loopStart);
            ilGenerator.MarkLabel(loopBackEdge);
            ilGenerator.Emit(OperationCode.Ldloc_1);
            ilGenerator.Emit(OperationCode.Ldloc_2);
            ilGenerator.Emit(OperationCode.Ldarg_0);
            ilGenerator.Emit(OperationCode.Ldloc_2);
            ilGenerator.Emit(OperationCode.Call, getChars);
            ilGenerator.Emit(OperationCode.Conv_U1);
            ilGenerator.Emit(OperationCode.Stelem_I1);
            ilGenerator.Emit(OperationCode.Ldloc_2);
            ilGenerator.Emit(OperationCode.Ldc_I4_1);
            ilGenerator.Emit(OperationCode.Add);
            ilGenerator.Emit(OperationCode.Stloc_2);
            ilGenerator.MarkLabel(loopStart);
            ilGenerator.Emit(OperationCode.Ldloc_2);
            ilGenerator.Emit(OperationCode.Ldloc_0);
            ilGenerator.Emit(OperationCode.Blt_S, loopBackEdge);
            ilGenerator.Emit(OperationCode.Ldloc_1);
            ilGenerator.Emit(OperationCode.Ldloc_0);
            ilGenerator.Emit(OperationCode.Ldc_I4_0);
            ilGenerator.Emit(OperationCode.Stelem_I1);
            ilGenerator.Emit(OperationCode.Ldloc_1);
            ilGenerator.Emit(OperationCode.Ret);

            methodDefinition.Body = new ILGeneratorMethodBody(ilGenerator, true, 8, methodDefinition, locals, new List <ITypeDefinition>());

            return(methodDefinition);
        }
        private void InstrumentBlock(BasicBlock <Instruction> block)
        {
            var blockOffset = block.Instructions[0].Operation.Offset;

            this.ilGenerator.MarkLabel(this.GetLabelFor(blockOffset));
            for (int i = 0, n = block.Instructions.Count - 1; i < n; i++)
            {
                var operation = block.Instructions[i].Operation;
                this.EmitDebugInformationFor(operation);
                this.ilGenerator.Emit(operation.OperationCode, operation.Value);
            }

            var lastOperation = block.Instructions[block.Instructions.Count - 1].Operation;

            this.EmitDebugInformationFor(lastOperation);
            switch (lastOperation.OperationCode)
            {
            case OperationCode.Beq:
            case OperationCode.Beq_S:
            case OperationCode.Bge:
            case OperationCode.Bge_S:
            case OperationCode.Bge_Un:
            case OperationCode.Bge_Un_S:
            case OperationCode.Bgt:
            case OperationCode.Bgt_S:
            case OperationCode.Bgt_Un:
            case OperationCode.Bgt_Un_S:
            case OperationCode.Ble:
            case OperationCode.Ble_S:
            case OperationCode.Ble_Un:
            case OperationCode.Ble_Un_S:
            case OperationCode.Blt:
            case OperationCode.Blt_S:
            case OperationCode.Blt_Un:
            case OperationCode.Blt_Un_S:
            case OperationCode.Bne_Un:
            case OperationCode.Bne_Un_S:
            case OperationCode.Brfalse:
            case OperationCode.Brfalse_S:
            case OperationCode.Brtrue:
            case OperationCode.Brtrue_S:
                var unconditionalBranch = new ILGeneratorLabel();
                var fallThrough         = new ILGeneratorLabel();
                this.ilGenerator.Emit(lastOperation.OperationCode, unconditionalBranch);
                this.ilGenerator.Emit(OperationCode.Br_S, fallThrough);
                this.ilGenerator.MarkLabel(unconditionalBranch);
                this.EmitCounterIncrement(lastOperation.Offset);
                this.ilGenerator.Emit(OperationCode.Br, this.GetLabelFor((uint)lastOperation.Value));
                this.ilGenerator.MarkLabel(fallThrough);
                this.EmitCounterIncrement(lastOperation.Offset + 1);
                break;

            case OperationCode.Br:
            case OperationCode.Br_S:
                this.EmitCounterIncrement(lastOperation.Offset);
                this.ilGenerator.Emit(OperationCode.Br, this.GetLabelFor((uint)lastOperation.Value));
                break;

            case OperationCode.Leave:
            case OperationCode.Leave_S:
                this.EmitCounterIncrement(lastOperation.Offset);
                this.ilGenerator.Emit(OperationCode.Leave, this.GetLabelFor((uint)lastOperation.Value));
                break;

            case OperationCode.Endfilter:
            case OperationCode.Endfinally:
            case OperationCode.Jmp:
            case OperationCode.Ret:
            case OperationCode.Rethrow:
            case OperationCode.Throw:
                //No need to count the outgoing edge. Its count is the same as the number of times this block executes.
                this.ilGenerator.Emit(lastOperation.OperationCode, lastOperation.Value);
                break;

            case OperationCode.Switch:
                fallThrough = new ILGeneratorLabel();
                uint[]             targets  = (uint[])lastOperation.Value;
                ILGeneratorLabel[] counters = new ILGeneratorLabel[targets.Length];
                for (int i = 0, n = counters.Length; i < n; i++)
                {
                    counters[i] = new ILGeneratorLabel();
                }
                this.ilGenerator.Emit(OperationCode.Switch, counters);
                this.EmitCounterIncrement(lastOperation.Offset);
                this.ilGenerator.Emit(OperationCode.Br, fallThrough);
                for (int i = 0, n = counters.Length; i < n; i++)
                {
                    var counterLabel = counters[i];
                    this.ilGenerator.MarkLabel(counterLabel);
                    this.EmitCounterIncrement(lastOperation.Offset + 1 + (uint)i);
                    this.ilGenerator.Emit(OperationCode.Br, this.GetLabelFor(targets[i]));
                }
                this.ilGenerator.MarkLabel(fallThrough);
                break;

            default:
                this.ilGenerator.Emit(lastOperation.OperationCode, lastOperation.Value);
                this.EmitCounterIncrement(lastOperation.Offset);
                break;
            }
        }
Exemple #15
0
        private static IMethodDefinition CreateStringArrayMarshallingEpilog(IMetadataHost host, ITypeDefinition typeDef, IFieldReference intPtrZero, IMethodReference intPtrOpInequality, IMethodReference freeHGlobal)
        {
            var intPtrArrayType = new VectorTypeReference {
                ElementType = host.PlatformType.SystemIntPtr, Rank = 1
            };

            MethodDefinition methodDefinition = new MethodDefinition
            {
                ContainingTypeDefinition = typeDef,
                IsStatic   = true,
                Visibility = TypeMemberVisibility.Assembly,
                Type       = host.PlatformType.SystemVoid,
                Parameters = new List <IParameterDefinition> {
                    new ParameterDefinition {
                        Index = 0, Type = intPtrArrayType
                    }
                },
                Name = host.NameTable.GetNameFor("StringArrayMarshallingEpilog")
            };

            var size = new LocalDefinition {
                Type = host.PlatformType.SystemInt32
            };
            var index = new LocalDefinition {
                Type = host.PlatformType.SystemInt32
            };

            var locals = new List <ILocalDefinition> {
                size, index
            };

            var ilGenerator  = new ILGenerator(host, methodDefinition);
            var loopStart    = new ILGeneratorLabel();
            var loopBackEdge = new ILGeneratorLabel();
            var exitLabel    = new ILGeneratorLabel();

            ilGenerator.Emit(OperationCode.Ldarg_0);
            ilGenerator.Emit(OperationCode.Ldlen);
            ilGenerator.Emit(OperationCode.Conv_I4);
            ilGenerator.Emit(OperationCode.Stloc_0);
            ilGenerator.Emit(OperationCode.Ldc_I4_0);
            ilGenerator.Emit(OperationCode.Stloc_1);
            ilGenerator.Emit(OperationCode.Br_S, loopBackEdge);
            ilGenerator.MarkLabel(loopStart);
            ilGenerator.Emit(OperationCode.Ldarg_0);
            ilGenerator.Emit(OperationCode.Ldloc_1);
            ilGenerator.Emit(OperationCode.Ldelem_I);
            ilGenerator.Emit(OperationCode.Ldsfld, intPtrZero);
            ilGenerator.Emit(OperationCode.Call, intPtrOpInequality);
            ilGenerator.Emit(OperationCode.Brfalse_S, exitLabel);
            ilGenerator.Emit(OperationCode.Ldarg_0);
            ilGenerator.Emit(OperationCode.Ldloc_1);
            ilGenerator.Emit(OperationCode.Ldelem_I);
            ilGenerator.Emit(OperationCode.Call, freeHGlobal);
            ilGenerator.MarkLabel(exitLabel);
            ilGenerator.Emit(OperationCode.Ldloc_1);
            ilGenerator.Emit(OperationCode.Ldc_I4_1);
            ilGenerator.Emit(OperationCode.Add);
            ilGenerator.Emit(OperationCode.Stloc_1);
            ilGenerator.MarkLabel(loopBackEdge);
            ilGenerator.Emit(OperationCode.Ldloc_1);
            ilGenerator.Emit(OperationCode.Ldloc_0);
            ilGenerator.Emit(OperationCode.Blt_S, loopStart);
            ilGenerator.Emit(OperationCode.Ret);

            methodDefinition.Body = new ILGeneratorMethodBody(ilGenerator, true, 2, methodDefinition, locals, new List <ITypeDefinition>());

            return(methodDefinition);
        }
        private static IMethodDefinition CreateDLMethod(IMetadataHost host, ITypeDefinition typeDef, IName name, List <IParameterDefinition> parameters, ITypeReference returnType, IMethodReference getOperatingSystem, IMethodReference linuxHelpers, IMethodReference darwinHelpers, IMethodReference bsdHelpers, bool generateSecondLoad = true)
        {
            var methodDefinition = new MethodDefinition
            {
                Name       = name,
                Parameters = parameters,
                ContainingTypeDefinition = typeDef,
                IsStatic            = true,
                IsHiddenBySignature = true,
                Visibility          = TypeMemberVisibility.Public,
                Type = returnType
            };

            var labels = new ILGeneratorLabel[4];

            var linuxLabel   = new ILGeneratorLabel();
            var darwinLabel  = new ILGeneratorLabel();
            var bsdLabel     = new ILGeneratorLabel();
            var unknownLabel = new ILGeneratorLabel();

            labels[0] = linuxLabel;
            labels[1] = darwinLabel;
            labels[2] = bsdLabel;
            labels[3] = bsdLabel;

            var ilGenerator = new ILGenerator(host, methodDefinition);

            ilGenerator.Emit(OperationCode.Call, getOperatingSystem);
            ilGenerator.Emit(OperationCode.Stloc_0);
            ilGenerator.Emit(OperationCode.Ldloc_0);
            ilGenerator.Emit(OperationCode.Ldc_I4_1);
            ilGenerator.Emit(OperationCode.Sub);
            ilGenerator.Emit(OperationCode.Switch, labels);
            ilGenerator.Emit(OperationCode.Br_S, unknownLabel);

            AddOperatingSystemCase2(ilGenerator, linuxHelpers, linuxLabel, generateSecondLoad);
            AddOperatingSystemCase2(ilGenerator, darwinHelpers, darwinLabel, generateSecondLoad);
            AddOperatingSystemCase2(ilGenerator, bsdHelpers, bsdLabel, generateSecondLoad);

            ilGenerator.MarkLabel(unknownLabel);
            ilGenerator.Emit(OperationCode.Ldstr, "Platform Not Supported");

            var exceptionCtor = new Microsoft.Cci.MutableCodeModel.MethodReference
            {
                Name              = host.NameTable.GetNameFor(".ctor"),
                ContainingType    = host.PlatformType.SystemException,
                Type              = host.PlatformType.SystemVoid,
                CallingConvention = CallingConvention.HasThis,
                Parameters        = new List <IParameterTypeInformation> {
                    new ParameterDefinition {
                        Index = 0, Type = host.PlatformType.SystemString
                    }
                }
            };

            ilGenerator.Emit(OperationCode.Newobj, exceptionCtor);
            ilGenerator.Emit(OperationCode.Throw);

            methodDefinition.Body = new ILGeneratorMethodBody(ilGenerator, true, 2, methodDefinition, new List <ILocalDefinition> {
                new LocalDefinition {
                    Type = host.PlatformType.SystemInt32
                }
            }, new List <ITypeDefinition>());
            return(methodDefinition);
        }
        private static void AddOperatingSystemCase2(ILGenerator ilGenerator, IMethodReference helper, ILGeneratorLabel label, bool generateSecondLoad = true)
        {
            ilGenerator.MarkLabel(label);
            ilGenerator.Emit(OperationCode.Ldarg_0);

            if (generateSecondLoad)
            {
                ilGenerator.Emit(OperationCode.Ldarg_1);
            }

            ilGenerator.Emit(OperationCode.Call, helper);
            ilGenerator.Emit(OperationCode.Ret);
        }
 private static void AddOperatingSystemCase(ILGenerator ilGenerator, string operatingSystemName, IMethodReference stringOPEquality, ILGeneratorLabel operatingSystemSwitchLabel)
 {
     ilGenerator.Emit(OperationCode.Ldloc_0);
     ilGenerator.Emit(OperationCode.Ldstr, operatingSystemName);
     ilGenerator.Emit(OperationCode.Call, stringOPEquality);
     ilGenerator.Emit(OperationCode.Brtrue_S, operatingSystemSwitchLabel);
 }
        private static IMethodDefinition CreateUnameMethod(IMetadataHost host, ITypeDefinition typeDef, IFieldReference intPtrZero, IMethodReference allocHGlobal, IMethodReference ptrToStringAnsi, IMethodReference freeHGlobal, IMethodReference unamePInvoke, IMethodReference intPtrOpInequality)
        {
            var methodDefinition = new MethodDefinition
            {
                Name                     = host.NameTable.GetNameFor("uname"),
                IsStatic                 = true,
                IsHiddenBySignature      = true,
                ContainingTypeDefinition = typeDef,
                Visibility               = TypeMemberVisibility.Private,
                Type                     = host.PlatformType.SystemString
            };

            var ilGenerator = new ILGenerator(host, methodDefinition);

            ilGenerator.Emit(OperationCode.Ldsfld, intPtrZero);
            ilGenerator.Emit(OperationCode.Stloc_0);
            ilGenerator.BeginTryBody();
            ilGenerator.Emit(OperationCode.Ldc_I4, 4096);
            ilGenerator.Emit(OperationCode.Call, allocHGlobal);
            ilGenerator.Emit(OperationCode.Stloc_0);
            ilGenerator.Emit(OperationCode.Ldloc_0);
            ilGenerator.Emit(OperationCode.Call, unamePInvoke);

            var emptyStringLabel = new ILGeneratorLabel();

            ilGenerator.Emit(OperationCode.Brtrue_S, emptyStringLabel);
            ilGenerator.Emit(OperationCode.Ldloc_0);

            ilGenerator.Emit(OperationCode.Call, ptrToStringAnsi);
            ilGenerator.Emit(OperationCode.Stloc_1);

            var exitLabel       = new ILGeneratorLabel();
            var endFinallyLabel = new ILGeneratorLabel();

            ilGenerator.Emit(OperationCode.Leave_S, exitLabel);
            ilGenerator.MarkLabel(emptyStringLabel);
            ilGenerator.Emit(OperationCode.Ldstr, "");
            ilGenerator.Emit(OperationCode.Stloc_1);
            ilGenerator.Emit(OperationCode.Leave_S, exitLabel);
            ilGenerator.BeginFinallyBlock();
            ilGenerator.Emit(OperationCode.Ldloc_0);
            ilGenerator.Emit(OperationCode.Ldsfld, intPtrZero);
            ilGenerator.Emit(OperationCode.Call, intPtrOpInequality);
            ilGenerator.Emit(OperationCode.Brfalse_S, endFinallyLabel);
            ilGenerator.Emit(OperationCode.Ldloc_0);
            ilGenerator.Emit(OperationCode.Call, freeHGlobal);
            ilGenerator.MarkLabel(endFinallyLabel);
            ilGenerator.Emit(OperationCode.Endfinally);
            ilGenerator.EndTryBody();
            ilGenerator.MarkLabel(exitLabel);
            ilGenerator.Emit(OperationCode.Ldloc_1);
            ilGenerator.Emit(OperationCode.Ret);

            methodDefinition.Body = new ILGeneratorMethodBody(ilGenerator, true, 2, methodDefinition, new List <ILocalDefinition> {
                new LocalDefinition {
                    Type = host.PlatformType.SystemIntPtr
                }, new LocalDefinition {
                    Type = host.PlatformType.SystemString
                }
            }, new List <ITypeDefinition>());
            return(methodDefinition);
        }
Exemple #20
0
        private static IMethodDefinition CreateIsLibraryInitialized(IMetadataHost host, ITypeDefinition typeDef, IFieldReference intPtrZero)
        {
            MethodDefinition methodDefinition = new MethodDefinition
            {
                ContainingTypeDefinition = typeDef,
                IsStatic            = true,
                IsNeverInlined      = true,
                IsHiddenBySignature = true,
                Visibility          = TypeMemberVisibility.Assembly,
                Type       = host.PlatformType.SystemVoid,
                Parameters = new List <IParameterDefinition> {
                    new ParameterDefinition {
                        Index = 0, Type = host.PlatformType.SystemIntPtr
                    }, new ParameterDefinition {
                        Index = 1, Type = host.PlatformType.SystemString
                    }
                },
                Name = host.NameTable.GetNameFor("IsLibraryInitialized")
            };

            var ilGenerator = new ILGenerator(host, methodDefinition);
            var retLabel    = new ILGeneratorLabel();

            var exceptionCtor = new Microsoft.Cci.MutableCodeModel.MethodReference
            {
                Name              = host.NameTable.GetNameFor(".ctor"),
                ContainingType    = host.PlatformType.SystemException,
                Type              = host.PlatformType.SystemVoid,
                CallingConvention = CallingConvention.HasThis,
                Parameters        = new List <IParameterTypeInformation> {
                    new ParameterDefinition {
                        Index = 0, Type = host.PlatformType.SystemString
                    }
                }
            };

            var stringConcat = new Microsoft.Cci.MutableCodeModel.MethodReference
            {
                Name           = host.NameTable.GetNameFor("Concat"),
                ContainingType = host.PlatformType.SystemString,
                Type           = host.PlatformType.SystemString,
                Parameters     = new List <IParameterTypeInformation> {
                    new ParameterDefinition {
                        Index = 0, Type = host.PlatformType.SystemString
                    }, new ParameterDefinition {
                        Index = 1, Type = host.PlatformType.SystemString
                    }, new ParameterDefinition {
                        Index = 2, Type = host.PlatformType.SystemString
                    }, new ParameterDefinition {
                        Index = 3, Type = host.PlatformType.SystemString
                    }
                }
            };

            var intPtrOpEquality = new Microsoft.Cci.MutableCodeModel.MethodReference
            {
                Name           = host.NameTable.OpEquality,
                ContainingType = host.PlatformType.SystemIntPtr,
                Type           = host.PlatformType.SystemBoolean,
                Parameters     = new List <IParameterTypeInformation> {
                    new ParameterDefinition {
                        Index = 0, Type = host.PlatformType.SystemIntPtr
                    }, new ParameterDefinition {
                        Index = 1, Type = host.PlatformType.SystemIntPtr
                    }
                }
            };

            ilGenerator.Emit(OperationCode.Ldarg_0);
            ilGenerator.Emit(OperationCode.Ldsfld, intPtrZero);
            ilGenerator.Emit(OperationCode.Call, intPtrOpEquality);
            ilGenerator.Emit(OperationCode.Brfalse_S, retLabel);
            ilGenerator.Emit(OperationCode.Ldstr, "Library '");
            ilGenerator.Emit(OperationCode.Ldarg_1);
            ilGenerator.Emit(OperationCode.Ldstr, "' is not initialized. Load the native library (from its file path) by calling LoadLibrary");
            ilGenerator.Emit(OperationCode.Ldarg_1);
            ilGenerator.Emit(OperationCode.Call, stringConcat);
            ilGenerator.Emit(OperationCode.Newobj, exceptionCtor);
            ilGenerator.Emit(OperationCode.Throw);
            ilGenerator.MarkLabel(retLabel);
            ilGenerator.Emit(OperationCode.Ret);

            methodDefinition.Body = new ILGeneratorMethodBody(ilGenerator, true, 8, methodDefinition, new List <ILocalDefinition>(), new List <ITypeDefinition>());

            return(methodDefinition);
        }
Exemple #21
0
        private static IMethodDefinition CreateGetProcAddress(IMetadataHost host, ITypeDefinition typeDef, IMethodReference windowsGetProcAddress, IMethodReference unixGetProcAddress, IFieldReference isUnix, IFieldReference intPtrZero)
        {
            var methodDefinition = new MethodDefinition
            {
                Name = host.NameTable.GetNameFor("GetProcAddress"),
                ContainingTypeDefinition = typeDef,
                Parameters = new List <IParameterDefinition>
                {
                    new ParameterDefinition {
                        Index = 0, Type = host.PlatformType.SystemIntPtr
                    },
                    new ParameterDefinition {
                        Index = 1, Type = host.PlatformType.SystemString
                    }
                },
                IsStatic            = true,
                IsHiddenBySignature = true,
                Visibility          = TypeMemberVisibility.Public,
                Type = host.PlatformType.SystemIntPtr
            };

            var ilGenerator = new ILGenerator(host, methodDefinition);

            var label    = new ILGeneratorLabel();
            var retLabel = new ILGeneratorLabel();
            var dupLabel = new ILGeneratorLabel();

            var exceptionCtor = new Microsoft.Cci.MutableCodeModel.MethodReference
            {
                Name              = host.NameTable.GetNameFor(".ctor"),
                ContainingType    = host.PlatformType.SystemException,
                Type              = host.PlatformType.SystemVoid,
                CallingConvention = CallingConvention.HasThis,
                Parameters        = new List <IParameterTypeInformation> {
                    new ParameterDefinition {
                        Index = 0, Type = host.PlatformType.SystemString
                    }
                }
            };

            var stringConcat = new Microsoft.Cci.MutableCodeModel.MethodReference
            {
                Name           = host.NameTable.GetNameFor("Concat"),
                ContainingType = host.PlatformType.SystemString,
                Type           = host.PlatformType.SystemString,
                Parameters     = new List <IParameterTypeInformation> {
                    new ParameterDefinition {
                        Index = 0, Type = host.PlatformType.SystemString
                    }, new ParameterDefinition {
                        Index = 1, Type = host.PlatformType.SystemString
                    }
                }
            };

            var intPtrOpEquality = new Microsoft.Cci.MutableCodeModel.MethodReference
            {
                Name           = host.NameTable.OpEquality,
                ContainingType = host.PlatformType.SystemIntPtr,
                Type           = host.PlatformType.SystemBoolean,
                Parameters     = new List <IParameterTypeInformation> {
                    new ParameterDefinition {
                        Index = 0, Type = host.PlatformType.SystemIntPtr
                    }, new ParameterDefinition {
                        Index = 1, Type = host.PlatformType.SystemIntPtr
                    }
                }
            };

            ilGenerator.Emit(OperationCode.Ldsfld, isUnix);
            ilGenerator.Emit(OperationCode.Brtrue_S, label);
            ilGenerator.Emit(OperationCode.Ldarg_0);
            ilGenerator.Emit(OperationCode.Ldarg_1);
            ilGenerator.Emit(OperationCode.Call, windowsGetProcAddress);
            ilGenerator.Emit(OperationCode.Br_S, dupLabel);
            ilGenerator.MarkLabel(label);
            ilGenerator.Emit(OperationCode.Ldarg_0);
            ilGenerator.Emit(OperationCode.Ldarg_1);
            ilGenerator.Emit(OperationCode.Call, unixGetProcAddress);
            ilGenerator.MarkLabel(dupLabel);
            ilGenerator.Emit(OperationCode.Dup);
            ilGenerator.Emit(OperationCode.Ldsfld, intPtrZero);
            ilGenerator.Emit(OperationCode.Call, intPtrOpEquality);
            ilGenerator.Emit(OperationCode.Brfalse_S, retLabel);
            ilGenerator.Emit(OperationCode.Ldstr, "GetProcAddress failed for: ");
            ilGenerator.Emit(OperationCode.Ldarg_1);
            ilGenerator.Emit(OperationCode.Call, stringConcat);
            ilGenerator.Emit(OperationCode.Newobj, exceptionCtor);
            ilGenerator.Emit(OperationCode.Throw);
            ilGenerator.MarkLabel(retLabel);
            ilGenerator.Emit(OperationCode.Ret);

            methodDefinition.Body = new ILGeneratorMethodBody(ilGenerator, true, 8, methodDefinition, new List <ILocalDefinition>(), new List <ITypeDefinition>());

            return(methodDefinition);
        }
Exemple #22
0
    [ContractVerification(false)] //Times out
    private void Inline(IMethodBody methodBody) {
      Contract.Requires(methodBody != null);

      var savedCombinedMaxStack = this.combinedMaxStack;
      this.combinedMaxStack += methodBody.MaxStack;
      if (this.combinedMaxStack > this.maxStack) this.maxStack = this.combinedMaxStack;

      var savedLocalForThis = this.localForThis;
      var nametable = this.Host.NameTable;
      var method = methodBody.MethodDefinition;
      var n = method.ParameterCount;
      if (!method.IsStatic) n++;
      var temps = new GeneratorLocal[n];
      for (ushort i = 0; i < n; i++) temps[i] = new GeneratorLocal() { MethodDefinition = method };
      var j = 0;
      if (!method.IsStatic) {
        var temp0 = temps[0];
        Contract.Assume(temp0 != null);
        temp0.Name = nametable.GetNameFor("this");
        temp0.Type = method.ContainingTypeDefinition;
        if (method.ContainingTypeDefinition.IsValueType)
          temp0.Type = ManagedPointerType.GetManagedPointerType(temp0.Type, this.Host.InternFactory);
        j = 1;
        this.localForThis = temp0;
      }
      foreach (var par in methodBody.MethodDefinition.Parameters) {
        Contract.Assume(par != null);
        Contract.Assume(j < n);
        var tempj = temps[j++];
        Contract.Assume(tempj != null);
        this.localFor[par] = tempj;
        tempj.Name = par.Name;
        tempj.Type = par.Type;
        if (par.IsByReference)
          tempj.Type = ManagedPointerType.GetManagedPointerType(tempj.Type, this.Host.InternFactory);
      }
      this.Generator.BeginScope();
      for (int i = n-1; i >= 0; i--) {
        var temp = temps[i];
        Contract.Assume(temp != null);
        this.Generator.Emit(OperationCode.Stloc, temp);
        this.TrackLocal(temp);
        this.Generator.AddVariableToCurrentScope(temp);
      }

      var savedReturnLabel = this.returnLabel;
      var returnLabel = this.returnLabel = new ILGeneratorLabel();
      this.EmitMethodBody(methodBody);
      this.Generator.MarkLabel(returnLabel);
      this.returnLabel = savedReturnLabel;
      this.localForThis = savedLocalForThis;
      this.Generator.EndScope();
      this.combinedMaxStack = savedCombinedMaxStack;

    }
Exemple #23
0
        public void Compile(string fileName)
        {
            string appName = Path.GetFileNameWithoutExtension(fileName);
            string exeName = appName + ".exe";
            string src     = "";

            using (TextReader file = new StreamReader(fileName))
            {
                src = file.ReadToEnd();
            }

            var nameTable = new NameTable();

            using (var host = new PeReader.DefaultHost(nameTable))
            {
                // Load Mirage types

                IModule module = host.LoadUnitFrom("Mirage.dll") as IModule;
                if (module == null || module is Dummy)
                {
                    return;
                }
                var machineType = module.GetAllTypes().First(x => x.Name.Value == "Machine");
                var inputType   = module.GetAllTypes().First(x => x.Name.Value == "ConsoleInput");
                var outputType  = module.GetAllTypes().First(x => x.Name.Value == "ConsoleOutput");

                // Create assembly

                var coreAssembly = host.LoadAssembly(host.CoreAssemblySymbolicIdentity);
                var assembly     = new Assembly()
                {
                    Name                 = nameTable.GetNameFor(appName),
                    ModuleName           = nameTable.GetNameFor(exeName),
                    PlatformType         = host.PlatformType,
                    Kind                 = ModuleKind.ConsoleApplication,
                    RequiresStartupStub  = host.PointerSize == 4,
                    TargetRuntimeVersion = coreAssembly.TargetRuntimeVersion,
                };
                assembly.AssemblyReferences.Add(coreAssembly);

                // Create namespace

                var rootUnitNamespace = new RootUnitNamespace();
                assembly.UnitNamespaceRoot = rootUnitNamespace;
                rootUnitNamespace.Unit     = assembly;

                // Create module class

                var moduleClass = new NamespaceTypeDefinition()
                {
                    ContainingUnitNamespace = rootUnitNamespace,
                    InternFactory           = host.InternFactory,
                    IsClass = true,
                    Name    = nameTable.GetNameFor("<Module>"),
                };
                assembly.AllTypes.Add(moduleClass);

                // Create program class

                var programClass = new NamespaceTypeDefinition()
                {
                    ContainingUnitNamespace = rootUnitNamespace,
                    InternFactory           = host.InternFactory,
                    IsClass  = true,
                    IsPublic = true,
                    Methods  = new List <IMethodDefinition>(1),
                    Name     = nameTable.GetNameFor("Program"),
                };
                programClass.BaseClasses = new List <ITypeReference>()
                {
                    host.PlatformType.SystemObject
                };
                rootUnitNamespace.Members.Add(programClass);

                // Add types to the assembly

                assembly.AllTypes.Add(machineType);
                foreach (var t in machineType.NestedTypes)
                {
                    assembly.AllTypes.Add(t);
                }
                assembly.AllTypes.Add(inputType);
                assembly.AllTypes.Add(outputType);
                assembly.AllTypes.Add(programClass);

                // Create main method

                var mainMethod = new MethodDefinition()
                {
                    ContainingTypeDefinition = programClass,
                    InternFactory            = host.InternFactory,
                    IsCil      = true,
                    IsStatic   = true,
                    Name       = nameTable.GetNameFor("Main"),
                    Type       = host.PlatformType.SystemVoid,
                    Visibility = TypeMemberVisibility.Public,
                };
                assembly.EntryPoint = mainMethod;
                programClass.Methods.Add(mainMethod);

                // Create constructors and methods

                IMethodReference machineConstructor = new Microsoft.Cci.MethodReference(
                    host,
                    machineType,
                    CallingConvention.HasThis,
                    host.PlatformType.SystemVoid,
                    host.NameTable.Ctor,
                    0
                    );

                IMethodReference inputConstructor = new Microsoft.Cci.MethodReference(
                    host,
                    inputType,
                    CallingConvention.HasThis,
                    host.PlatformType.SystemVoid,
                    host.NameTable.Ctor,
                    0
                    );
                var inputCast = TypeHelper.GetMethod(inputType, nameTable.GetNameFor("op_Implicit"), inputType);

                IMethodReference outputConstructor = new Microsoft.Cci.MethodReference(
                    host,
                    outputType,
                    CallingConvention.HasThis,
                    host.PlatformType.SystemVoid,
                    host.NameTable.Ctor,
                    0
                    );
                var outputCast = TypeHelper.GetMethod(outputType, nameTable.GetNameFor("op_Implicit"), outputType);

                var opIncPointers      = TypeHelper.GetMethod(machineType, nameTable.GetNameFor("IncPointers"));
                var opDecPointers      = TypeHelper.GetMethod(machineType, nameTable.GetNameFor("DecPointers"));
                var opIncHiPointer     = TypeHelper.GetMethod(machineType, nameTable.GetNameFor("IncHiPointer"));
                var opDecHiPointer     = TypeHelper.GetMethod(machineType, nameTable.GetNameFor("DecHiPointer"));
                var opReflectHiPointer = TypeHelper.GetMethod(machineType, nameTable.GetNameFor("ReflectHiPointer"));
                var opLoadHiPointer    = TypeHelper.GetMethod(machineType, nameTable.GetNameFor("LoadHiPointer"));
                var opDragLoPointer    = TypeHelper.GetMethod(machineType, nameTable.GetNameFor("DragLoPointer"));
                var opXchPointers      = TypeHelper.GetMethod(machineType, nameTable.GetNameFor("XchPointers"));

                var opClear = TypeHelper.GetMethod(machineType, nameTable.GetNameFor("Clear"));
                var opAdd   = TypeHelper.GetMethod(machineType, nameTable.GetNameFor("Add"));
                var opDec   = TypeHelper.GetMethod(machineType, nameTable.GetNameFor("Dec"));
                var opNot   = TypeHelper.GetMethod(machineType, nameTable.GetNameFor("Not"));
                var opAnd   = TypeHelper.GetMethod(machineType, nameTable.GetNameFor("And"));
                var opOr    = TypeHelper.GetMethod(machineType, nameTable.GetNameFor("Or"));
                var opXor   = TypeHelper.GetMethod(machineType, nameTable.GetNameFor("Xor"));
                var opSal   = TypeHelper.GetMethod(machineType, nameTable.GetNameFor("Sal"));
                var opSar   = TypeHelper.GetMethod(machineType, nameTable.GetNameFor("Sar"));

                var opLoadData = TypeHelper.GetMethod(machineType, nameTable.GetNameFor("LoadData"), host.PlatformType.SystemString);
                var opInput    = TypeHelper.GetMethod(machineType, nameTable.GetNameFor("Input"), inputCast.Type);
                var opOutput   = TypeHelper.GetMethod(machineType, nameTable.GetNameFor("Output"), outputCast.Type);

                var opJz = TypeHelper.GetMethod(machineType, nameTable.GetNameFor("Jz"));

                // Create program code

                var labels = new Stack <ILGeneratorLabel>(100);

                var ilGenerator = new ILGenerator(host, mainMethod);
                ilGenerator.Emit(OperationCode.Newobj, machineConstructor);
                ilGenerator.Emit(OperationCode.Stloc_0);
                ilGenerator.Emit(OperationCode.Newobj, inputConstructor);
                ilGenerator.Emit(OperationCode.Stloc_1);
                ilGenerator.Emit(OperationCode.Newobj, outputConstructor);
                ilGenerator.Emit(OperationCode.Stloc_2);

                int pc = 0;
                while (pc < src.Length)
                {
                    char opcode = src[pc++];

                    switch (opcode)
                    {
                    case '>':
                        ilGenerator.Emit(OperationCode.Ldloc_0);
                        ilGenerator.Emit(OperationCode.Callvirt, opIncPointers);
                        break;

                    case '<':
                        ilGenerator.Emit(OperationCode.Ldloc_0);
                        ilGenerator.Emit(OperationCode.Callvirt, opDecPointers);
                        break;

                    case ']':
                        ilGenerator.Emit(OperationCode.Ldloc_0);
                        ilGenerator.Emit(OperationCode.Callvirt, opIncHiPointer);
                        break;

                    case '[':
                        ilGenerator.Emit(OperationCode.Ldloc_0);
                        ilGenerator.Emit(OperationCode.Callvirt, opDecHiPointer);
                        break;

                    case '#':
                        ilGenerator.Emit(OperationCode.Ldloc_0);
                        ilGenerator.Emit(OperationCode.Callvirt, opReflectHiPointer);
                        break;

                    case '$':
                        ilGenerator.Emit(OperationCode.Ldloc_0);
                        ilGenerator.Emit(OperationCode.Callvirt, opLoadHiPointer);
                        break;

                    case '=':
                        ilGenerator.Emit(OperationCode.Ldloc_0);
                        ilGenerator.Emit(OperationCode.Callvirt, opDragLoPointer);
                        break;

                    case '%':
                        ilGenerator.Emit(OperationCode.Ldloc_0);
                        ilGenerator.Emit(OperationCode.Callvirt, opXchPointers);
                        break;

                    case '_':
                        ilGenerator.Emit(OperationCode.Ldloc_0);
                        ilGenerator.Emit(OperationCode.Callvirt, opClear);
                        break;

                    case '+':
                        ilGenerator.Emit(OperationCode.Ldloc_0);
                        ilGenerator.Emit(OperationCode.Callvirt, opAdd);
                        break;

                    case '-':
                        ilGenerator.Emit(OperationCode.Ldloc_0);
                        ilGenerator.Emit(OperationCode.Callvirt, opDec);
                        break;

                    case '~':
                        ilGenerator.Emit(OperationCode.Ldloc_0);
                        ilGenerator.Emit(OperationCode.Callvirt, opNot);
                        break;

                    case '&':
                        ilGenerator.Emit(OperationCode.Ldloc_0);
                        ilGenerator.Emit(OperationCode.Callvirt, opAnd);
                        break;

                    case '|':
                        ilGenerator.Emit(OperationCode.Ldloc_0);
                        ilGenerator.Emit(OperationCode.Callvirt, opOr);
                        break;

                    case '^':
                        ilGenerator.Emit(OperationCode.Ldloc_0);
                        ilGenerator.Emit(OperationCode.Callvirt, opXor);
                        break;

                    case '*':
                        ilGenerator.Emit(OperationCode.Ldloc_0);
                        ilGenerator.Emit(OperationCode.Callvirt, opSal);
                        break;

                    case '/':
                        ilGenerator.Emit(OperationCode.Ldloc_0);
                        ilGenerator.Emit(OperationCode.Callvirt, opSar);
                        break;

                    case '(':
                        int dataStart = pc;
                        int dataEnd   = dataStart;
                        while (src[pc++] != ')')
                        {
                            dataEnd = pc;
                        }
                        ilGenerator.Emit(OperationCode.Ldloc_0);
                        ilGenerator.Emit(OperationCode.Ldstr, src.Substring(dataStart, dataEnd - dataStart));
                        ilGenerator.Emit(OperationCode.Callvirt, opLoadData);
                        break;

                    case '?':
                        ilGenerator.Emit(OperationCode.Ldloc_0);
                        ilGenerator.Emit(OperationCode.Ldloc_1);
                        ilGenerator.Emit(OperationCode.Call, inputCast);
                        ilGenerator.Emit(OperationCode.Callvirt, opInput);
                        break;

                    case '!':
                        ilGenerator.Emit(OperationCode.Ldloc_0);
                        ilGenerator.Emit(OperationCode.Ldloc_2);
                        ilGenerator.Emit(OperationCode.Call, outputCast);
                        ilGenerator.Emit(OperationCode.Callvirt, opOutput);
                        break;

                    case '{':
                        var cycleStart = new ILGeneratorLabel();
                        var cycleEnd   = new ILGeneratorLabel();
                        labels.Push(cycleStart);
                        labels.Push(cycleEnd);
                        ilGenerator.Emit(OperationCode.Br, cycleEnd);
                        ilGenerator.MarkLabel(cycleStart);
                        break;

                    case '}':
                        ilGenerator.MarkLabel(labels.Pop());
                        ilGenerator.Emit(OperationCode.Ldloc_0);
                        ilGenerator.Emit(OperationCode.Callvirt, opJz);
                        ilGenerator.Emit(OperationCode.Ldc_I4_0);
                        ilGenerator.Emit(OperationCode.Ceq);
                        ilGenerator.Emit(OperationCode.Stloc_3);
                        ilGenerator.Emit(OperationCode.Ldloc_3);
                        ilGenerator.Emit(OperationCode.Brtrue, labels.Pop());
                        break;

                    default:
                        break;
                    }
                }

                ilGenerator.Emit(OperationCode.Ret);

                mainMethod.Body = new ILGeneratorMethodBody(
                    ilGenerator,
                    true,
                    8,
                    mainMethod,
                    new List <ILocalDefinition>()
                {
                    new LocalDefinition()
                    {
                        Type = machineType
                    },
                    new LocalDefinition()
                    {
                        Type = inputType
                    },
                    new LocalDefinition()
                    {
                        Type = outputType
                    },
                    new LocalDefinition()
                    {
                        Type = host.PlatformType.SystemInt32
                    },
                },
                    Enumerable <ITypeDefinition> .Empty
                    );

                using (var peStream = File.Create(exeName))
                {
                    PeWriter.WritePeToStream(assembly, host, peStream);
                }
            }
        }
Exemple #24
0
        // makes a copy of the method
        public void copyMethod(MethodDefinition dest, IMethodDefinition source)
        {
            // only copy body if it is not a dummy (= empty)
            if (!(source.Body is Microsoft.Cci.Dummy))
            {
                // copy instructions
                ILGenerator ilGenerator = new ILGenerator(this.host, dest);
                foreach (var operation in source.Body.Operations)
                {
                    ilGenerator.Emit(operation.OperationCode, operation.Value);
                }

                // copy the exception handler
                foreach (IOperationExceptionInformation exceptionToCopy in source.Body.OperationExceptionInformation)
                {
                    ILGeneratorLabel tryStart = new ILGeneratorLabel();
                    tryStart.Offset = exceptionToCopy.TryStartOffset;
                    ILGeneratorLabel tryEnd = new ILGeneratorLabel();
                    tryEnd.Offset = exceptionToCopy.TryEndOffset;
                    ILGeneratorLabel handlerStart = new ILGeneratorLabel();
                    handlerStart.Offset = exceptionToCopy.HandlerStartOffset;
                    ILGeneratorLabel handlerEnd = new ILGeneratorLabel();
                    handlerEnd.Offset = exceptionToCopy.HandlerEndOffset;
                    ILGeneratorLabel filterStart = new ILGeneratorLabel();
                    filterStart.Offset = exceptionToCopy.FilterDecisionStartOffset;

                    ilGenerator.AddExceptionHandlerInformation(exceptionToCopy.HandlerKind, exceptionToCopy.ExceptionType,
                                                               tryStart, tryEnd, handlerStart, handlerEnd, filterStart);
                }

                // create the body
                List <ILocalDefinition> variableListCopy           = new List <ILocalDefinition>(source.Body.LocalVariables);
                List <ITypeDefinition>  privateHelperTypesListCopy = new List <ITypeDefinition>(source.Body.PrivateHelperTypes);
                var newBody = new ILGeneratorMethodBody(ilGenerator, source.Body.LocalsAreZeroed, source.Body.MaxStack, dest,
                                                        variableListCopy, privateHelperTypesListCopy);
                dest.Body = newBody;
            }

            dest.CallingConvention = source.CallingConvention;
            if (source.IsGeneric)
            {
                dest.GenericParameters = new List <IGenericMethodParameter>(source.GenericParameters);
            }
            else
            {
                dest.GenericParameters = null;
            }
            if (source.ParameterCount > 0)
            {
                dest.Parameters = new List <IParameterDefinition>(source.Parameters);
            }
            else
            {
                dest.Parameters = null;
            }
            if (source.IsPlatformInvoke)
            {
                dest.PlatformInvokeData = source.PlatformInvokeData;
            }
            else
            {
                dest.PlatformInvokeData = Dummy.PlatformInvokeInformation;
            }
            dest.ReturnValueAttributes = new List <ICustomAttribute>(source.ReturnValueAttributes);
            if (source.ReturnValueIsModified)
            {
                dest.ReturnValueCustomModifiers = new List <ICustomModifier>(source.ReturnValueCustomModifiers);
            }
            else
            {
                dest.ReturnValueCustomModifiers = new List <ICustomModifier>(0);
            }
            if (source.ReturnValueIsMarshalledExplicitly)
            {
                dest.ReturnValueMarshallingInformation = source.ReturnValueMarshallingInformation;
            }
            else
            {
                dest.ReturnValueMarshallingInformation = Dummy.MarshallingInformation;
            }
            if (source.HasDeclarativeSecurity && IteratorHelper.EnumerableIsNotEmpty(source.SecurityAttributes))
            {
                dest.SecurityAttributes = new List <ISecurityAttribute>(source.SecurityAttributes);
            }
            else
            {
                dest.SecurityAttributes = null;
            }
            dest.Type = source.Type;
            dest.AcceptsExtraArguments     = source.AcceptsExtraArguments;
            dest.HasDeclarativeSecurity    = source.HasDeclarativeSecurity;
            dest.IsAbstract                = source.IsAbstract;
            dest.IsAccessCheckedOnOverride = source.IsAccessCheckedOnOverride;
            dest.IsCil                 = source.IsCil;
            dest.IsExternal            = source.IsExternal;
            dest.IsForwardReference    = source.IsForwardReference;
            dest.IsHiddenBySignature   = source.IsHiddenBySignature;
            dest.IsNativeCode          = source.IsNativeCode;
            dest.IsNewSlot             = source.IsNewSlot;
            dest.IsNeverInlined        = source.IsNeverInlined;
            dest.IsAggressivelyInlined = source.IsAggressivelyInlined;
            dest.IsNeverOptimized      = source.IsNeverOptimized;
            dest.IsPlatformInvoke      = source.IsPlatformInvoke;
            dest.IsRuntimeImplemented  = source.IsRuntimeImplemented;
            dest.IsRuntimeInternal     = source.IsRuntimeInternal;
            dest.IsRuntimeSpecial      = source.IsRuntimeSpecial;
            dest.IsSealed              = source.IsSealed;
            dest.IsSpecialName         = source.IsSpecialName;
            dest.IsStatic              = source.IsStatic;
            dest.IsSynchronized        = source.IsSynchronized;
            dest.IsUnmanaged           = source.IsUnmanaged;
            if (dest.IsStatic)
            {
                dest.IsVirtual = false;
            }
            else
            {
                dest.IsVirtual = source.IsVirtual;
            }
            dest.PreserveSignature                 = source.PreserveSignature;
            dest.RequiresSecurityObject            = source.RequiresSecurityObject;
            dest.ReturnValueIsByRef                = source.ReturnValueIsByRef;
            dest.ReturnValueIsMarshalledExplicitly = source.ReturnValueIsMarshalledExplicitly;
            dest.ReturnValueName = source.ReturnValueName;
            dest.Name            = source.Name;
            dest.Visibility      = source.Visibility;
        }
Exemple #25
0
        [ContractVerification(false)] //Times out
        private void Inline(IMethodBody methodBody)
        {
            Contract.Requires(methodBody != null);

            var savedCombinedMaxStack = this.combinedMaxStack;

            this.combinedMaxStack += methodBody.MaxStack;
            if (this.combinedMaxStack > this.maxStack)
            {
                this.maxStack = this.combinedMaxStack;
            }

            var savedLocalForThis = this.localForThis;
            var nametable         = this.Host.NameTable;
            var method            = methodBody.MethodDefinition;
            var n = method.ParameterCount;

            if (!method.IsStatic)
            {
                n++;
            }
            var temps = new GeneratorLocal[n];

            for (ushort i = 0; i < n; i++)
            {
                temps[i] = new GeneratorLocal()
                {
                    MethodDefinition = method
                }
            }
            ;
            var j = 0;

            if (!method.IsStatic)
            {
                var temp0 = temps[0];
                Contract.Assume(temp0 != null);
                temp0.Name = nametable.GetNameFor("this");
                temp0.Type = method.ContainingTypeDefinition;
                if (method.ContainingTypeDefinition.IsValueType)
                {
                    temp0.Type = ManagedPointerType.GetManagedPointerType(temp0.Type, this.Host.InternFactory);
                }
                j = 1;
                this.localForThis = temp0;
            }
            foreach (var par in methodBody.MethodDefinition.Parameters)
            {
                Contract.Assume(par != null);
                Contract.Assume(j < n);
                var tempj = temps[j++];
                Contract.Assume(tempj != null);
                this.localFor[par] = tempj;
                tempj.Name         = par.Name;
                tempj.Type         = par.Type;
                if (par.IsByReference)
                {
                    tempj.Type = ManagedPointerType.GetManagedPointerType(tempj.Type, this.Host.InternFactory);
                }
            }
            this.Generator.BeginScope();
            for (int i = n - 1; i >= 0; i--)
            {
                var temp = temps[i];
                Contract.Assume(temp != null);
                this.Generator.Emit(OperationCode.Stloc, temp);
                this.TrackLocal(temp);
                this.Generator.AddVariableToCurrentScope(temp);
            }

            var savedReturnLabel = this.returnLabel;
            var returnLabel      = this.returnLabel = new ILGeneratorLabel();

            this.EmitMethodBody(methodBody);
            this.Generator.MarkLabel(returnLabel);
            this.returnLabel  = savedReturnLabel;
            this.localForThis = savedLocalForThis;
            this.Generator.EndScope();
            this.combinedMaxStack = savedCombinedMaxStack;
        }
    }
Exemple #26
0
        private void ProcessOperations(IMethodBody methodBody)
        {
            List <IOperation> operations = ((methodBody.Operations == null) ? new List <IOperation>(): new List <IOperation>(methodBody.Operations));
            int count = operations.Count;

            ILGenerator generator = new ILGenerator(this.host, methodBody.MethodDefinition);

            if (this.pdbReader != null)
            {
                foreach (var ns in this.pdbReader.GetNamespaceScopes(methodBody))
                {
                    foreach (var uns in ns.UsedNamespaces)
                    {
                        generator.UseNamespace(uns.NamespaceName.Value);
                    }
                }
            }

            this.currentGenerator       = generator;
            this.scopeEnumerator        = this.pdbReader == null ? null : this.pdbReader.GetLocalScopes(methodBody).GetEnumerator();
            this.scopeEnumeratorIsValid = this.scopeEnumerator != null && this.scopeEnumerator.MoveNext();

            var methodName = MemberHelper.GetMemberSignature(methodBody.MethodDefinition, NameFormattingOptions.SmartTypeName);

            #region Record all offsets that appear as part of an exception handler
            Dictionary <uint, bool> offsetsUsedInExceptionInformation = new Dictionary <uint, bool>();
            foreach (var exceptionInfo in methodBody.OperationExceptionInformation ?? Enumerable <IOperationExceptionInformation> .Empty)
            {
                uint x = exceptionInfo.TryStartOffset;
                if (!offsetsUsedInExceptionInformation.ContainsKey(x))
                {
                    offsetsUsedInExceptionInformation.Add(x, true);
                }
                x = exceptionInfo.TryEndOffset;
                if (!offsetsUsedInExceptionInformation.ContainsKey(x))
                {
                    offsetsUsedInExceptionInformation.Add(x, true);
                }
                x = exceptionInfo.HandlerStartOffset;
                if (!offsetsUsedInExceptionInformation.ContainsKey(x))
                {
                    offsetsUsedInExceptionInformation.Add(x, true);
                }
                x = exceptionInfo.HandlerEndOffset;
                if (!offsetsUsedInExceptionInformation.ContainsKey(x))
                {
                    offsetsUsedInExceptionInformation.Add(x, true);
                }
                if (exceptionInfo.HandlerKind == HandlerKind.Filter)
                {
                    x = exceptionInfo.FilterDecisionStartOffset;
                    if (!offsetsUsedInExceptionInformation.ContainsKey(x))
                    {
                        offsetsUsedInExceptionInformation.Add(x, true);
                    }
                }
            }
            #endregion Record all offsets that appear as part of an exception handler

            Dictionary <uint, ILGeneratorLabel> offset2Label = new Dictionary <uint, ILGeneratorLabel>();
            #region Pass 1: Make a label for each branch target
            for (int i = 0; i < count; i++)
            {
                IOperation op = operations[i];
                switch (op.OperationCode)
                {
                case OperationCode.Beq:
                case OperationCode.Bge:
                case OperationCode.Bge_Un:
                case OperationCode.Bgt:
                case OperationCode.Bgt_Un:
                case OperationCode.Ble:
                case OperationCode.Ble_Un:
                case OperationCode.Blt:
                case OperationCode.Blt_Un:
                case OperationCode.Bne_Un:
                case OperationCode.Br:
                case OperationCode.Brfalse:
                case OperationCode.Brtrue:
                case OperationCode.Leave:
                case OperationCode.Beq_S:
                case OperationCode.Bge_S:
                case OperationCode.Bge_Un_S:
                case OperationCode.Bgt_S:
                case OperationCode.Bgt_Un_S:
                case OperationCode.Ble_S:
                case OperationCode.Ble_Un_S:
                case OperationCode.Blt_S:
                case OperationCode.Blt_Un_S:
                case OperationCode.Bne_Un_S:
                case OperationCode.Br_S:
                case OperationCode.Brfalse_S:
                case OperationCode.Brtrue_S:
                case OperationCode.Leave_S:
                    uint x = (uint)op.Value;
                    if (!offset2Label.ContainsKey(x))
                    {
                        offset2Label.Add(x, new ILGeneratorLabel());
                    }
                    break;

                case OperationCode.Switch:
                    uint[] offsets = op.Value as uint[];
                    foreach (var offset in offsets)
                    {
                        if (!offset2Label.ContainsKey(offset))
                        {
                            offset2Label.Add(offset, new ILGeneratorLabel());
                        }
                    }
                    break;

                default:
                    break;
                }
            }
            #endregion Pass 1: Make a label for each branch target

            #region Pass 2: Emit each operation, along with labels
            for (int i = 0; i < count; i++)
            {
                IOperation       op = operations[i];
                ILGeneratorLabel label;
                this.EmitDebugInformationFor(op);
                #region Mark operation if it is a label for a branch
                if (offset2Label.TryGetValue(op.Offset, out label))
                {
                    generator.MarkLabel(label);
                }
                #endregion Mark operation if it is a label for a branch

                #region Mark operation if it is pointed to by an exception handler
                bool ignore;
                uint offset = op.Offset;
                if (offsetsUsedInExceptionInformation.TryGetValue(offset, out ignore))
                {
                    foreach (var exceptionInfo in methodBody.OperationExceptionInformation)
                    {
                        if (offset == exceptionInfo.TryStartOffset)
                        {
                            generator.BeginTryBody();
                        }

                        // Never need to do anthing when offset == exceptionInfo.TryEndOffset because
                        // we pick up an EndTryBody from the HandlerEndOffset below
                        //  generator.EndTryBody();

                        if (offset == exceptionInfo.HandlerStartOffset)
                        {
                            switch (exceptionInfo.HandlerKind)
                            {
                            case HandlerKind.Catch:
                                generator.BeginCatchBlock(exceptionInfo.ExceptionType);
                                break;

                            case HandlerKind.Fault:
                                generator.BeginFaultBlock();
                                break;

                            case HandlerKind.Filter:
                                generator.BeginFilterBody();
                                break;

                            case HandlerKind.Finally:
                                generator.BeginFinallyBlock();
                                break;
                            }
                        }
                        if (exceptionInfo.HandlerKind == HandlerKind.Filter && offset == exceptionInfo.FilterDecisionStartOffset)
                        {
                            generator.BeginFilterBlock();
                        }
                        if (offset == exceptionInfo.HandlerEndOffset)
                        {
                            generator.EndTryBody();
                        }
                    }
                }
                #endregion Mark operation if it is pointed to by an exception handler

                #region Emit operation along with any injection
                switch (op.OperationCode)
                {
                    #region Branches
                case OperationCode.Beq:
                case OperationCode.Bge:
                case OperationCode.Bge_Un:
                case OperationCode.Bgt:
                case OperationCode.Bgt_Un:
                case OperationCode.Ble:
                case OperationCode.Ble_Un:
                case OperationCode.Blt:
                case OperationCode.Blt_Un:
                case OperationCode.Bne_Un:
                case OperationCode.Br:
                case OperationCode.Brfalse:
                case OperationCode.Brtrue:
                case OperationCode.Leave:
                case OperationCode.Beq_S:
                case OperationCode.Bge_S:
                case OperationCode.Bge_Un_S:
                case OperationCode.Bgt_S:
                case OperationCode.Bgt_Un_S:
                case OperationCode.Ble_S:
                case OperationCode.Ble_Un_S:
                case OperationCode.Blt_S:
                case OperationCode.Blt_Un_S:
                case OperationCode.Bne_Un_S:
                case OperationCode.Br_S:
                case OperationCode.Brfalse_S:
                case OperationCode.Brtrue_S:
                case OperationCode.Leave_S:
                    generator.Emit(ILGenerator.LongVersionOf(op.OperationCode), offset2Label[(uint)op.Value]);
                    break;

                case OperationCode.Switch:
                    uint[]             offsets = op.Value as uint[];
                    ILGeneratorLabel[] labels  = new ILGeneratorLabel[offsets.Length];
                    for (int j = 0, n = offsets.Length; j < n; j++)
                    {
                        labels[j] = offset2Label[offsets[j]];
                    }
                    generator.Emit(OperationCode.Switch, labels);
                    break;

                    #endregion Branches
                    #region Everything else
                case OperationCode.Stloc_0:
                case OperationCode.Stloc_1:
                case OperationCode.Stloc_2:
                case OperationCode.Stloc_3:
                    generator.Emit(op.OperationCode);
                    EmitStoreLocal(generator, op);
                    break;

                case OperationCode.Stloc:
                case OperationCode.Stloc_S:
                    generator.Emit(op.OperationCode, op.Value);
                    EmitStoreLocal(generator, op);
                    break;

                default:
                    if (op.Value == null)
                    {
                        generator.Emit(op.OperationCode);
                        break;
                    }
                    var typeCode = System.Convert.GetTypeCode(op.Value);
                    switch (typeCode)
                    {
                    case TypeCode.Byte:
                        generator.Emit(op.OperationCode, (byte)op.Value);
                        break;

                    case TypeCode.Double:
                        generator.Emit(op.OperationCode, (double)op.Value);
                        break;

                    case TypeCode.Int16:
                        generator.Emit(op.OperationCode, (short)op.Value);
                        break;

                    case TypeCode.Int32:
                        generator.Emit(op.OperationCode, (int)op.Value);
                        break;

                    case TypeCode.Int64:
                        generator.Emit(op.OperationCode, (long)op.Value);
                        break;

                    case TypeCode.Object:
                        IFieldReference fieldReference = op.Value as IFieldReference;
                        if (fieldReference != null)
                        {
                            generator.Emit(op.OperationCode, this.Rewrite(fieldReference));
                            break;
                        }
                        ILocalDefinition localDefinition = op.Value as ILocalDefinition;
                        if (localDefinition != null)
                        {
                            generator.Emit(op.OperationCode, localDefinition);
                            break;
                        }
                        IMethodReference methodReference = op.Value as IMethodReference;
                        if (methodReference != null)
                        {
                            generator.Emit(op.OperationCode, this.Rewrite(methodReference));
                            break;
                        }
                        IParameterDefinition parameterDefinition = op.Value as IParameterDefinition;
                        if (parameterDefinition != null)
                        {
                            generator.Emit(op.OperationCode, parameterDefinition);
                            break;
                        }
                        ISignature signature = op.Value as ISignature;
                        if (signature != null)
                        {
                            generator.Emit(op.OperationCode, signature);
                            break;
                        }
                        ITypeReference typeReference = op.Value as ITypeReference;
                        if (typeReference != null)
                        {
                            generator.Emit(op.OperationCode, this.Rewrite(typeReference));
                            break;
                        }
                        throw new ILMutatorException("Should never get here: no other IOperation argument types should exist");

                    case TypeCode.SByte:
                        generator.Emit(op.OperationCode, (sbyte)op.Value);
                        break;

                    case TypeCode.Single:
                        generator.Emit(op.OperationCode, (float)op.Value);
                        break;

                    case TypeCode.String:
                        generator.Emit(op.OperationCode, (string)op.Value);
                        break;

                    default:
                        // The other cases are the other enum values that TypeCode has.
                        // But no other argument types should be in the Operations. ILGenerator cannot handle anything else,
                        // so such IOperations should never exist.
                        //case TypeCode.Boolean:
                        //case TypeCode.Char:
                        //case TypeCode.DateTime:
                        //case TypeCode.DBNull:
                        //case TypeCode.Decimal:
                        //case TypeCode.Empty: // this would be the value for null, but the case when op.Value is null is handled before the switch statement
                        //case TypeCode.UInt16:
                        //case TypeCode.UInt32:
                        //case TypeCode.UInt64:
                        throw new ILMutatorException("Should never get here: no other IOperation argument types should exist");
                    }
                    break;
                    #endregion Everything else
                }
                #endregion Emit operation along with any injection
            }
            while (generator.InTryBody)
            {
                generator.EndTryBody();
            }
            while (this.scopeStack.Count > 0)
            {
                this.currentGenerator.EndScope();
                this.scopeStack.Pop();
            }
            #endregion Pass 2: Emit each operation, along with labels
        }