예제 #1
0
        /// <summary>
        /// Define a method in this module with the specified name and parameters.
        /// </summary>
        public MethodInfo DefineMethod(string name, Type returnType, Type[] paramTypes, string[] paramNames, XmlILMethodAttributes xmlAttrs) {
            MethodInfo methResult;
            int uniqueId = 1;
            string nameOrig = name;
            Type[] paramTypesNew;
            bool isRaw = (xmlAttrs & XmlILMethodAttributes.Raw) != 0;

            // Ensure that name is unique
            while (this.methods[name] != null) {
                // Add unique id to end of name in order to make it unique within this module
                uniqueId++;
                name = nameOrig + " (" + uniqueId + ")";
            }

            if (!isRaw) {
                // XmlQueryRuntime is always 0th parameter
                paramTypesNew = new Type[paramTypes.Length + 1];
                paramTypesNew[0] = typeof(XmlQueryRuntime);
                Array.Copy(paramTypes, 0, paramTypesNew, 1, paramTypes.Length);
                paramTypes = paramTypesNew;
            }

            if (!this.useLRE) {
                MethodBuilder methBldr;

                methBldr = this.typeBldr.DefineMethod(
                            name,
                            MethodAttributes.Private | MethodAttributes.Static, 
                            returnType,
                            paramTypes);

                if (emitSymbols && (xmlAttrs & XmlILMethodAttributes.NonUser) != 0) {
                    // Add DebuggerStepThroughAttribute and DebuggerNonUserCodeAttribute to non-user methods so that debugging is a better experience
                    methBldr.SetCustomAttribute(new CustomAttributeBuilder(XmlILConstructors.StepThrough, new object[] {}));
                    methBldr.SetCustomAttribute(new CustomAttributeBuilder(XmlILConstructors.NonUserCode, new object[] {}));
                }

                if (!isRaw)
                    methBldr.DefineParameter(1, ParameterAttributes.None, RuntimeName);

                for (int i = 0; i < paramNames.Length; i++) {
                    if (paramNames[i] != null && paramNames[i].Length != 0)
                        methBldr.DefineParameter(i + (isRaw ? 1 : 2), ParameterAttributes.None, paramNames[i]);
                }

                methResult = methBldr;
            }
            else {
                DynamicMethod methDyn = new DynamicMethod(name, returnType, paramTypes, LREModule);
                methDyn.InitLocals = true;

                if (!isRaw)
                    methDyn.DefineParameter(1, ParameterAttributes.None, RuntimeName);

                for (int i = 0; i < paramNames.Length; i++) {
                    if (paramNames[i] != null && paramNames[i].Length != 0)
                        methDyn.DefineParameter(i + (isRaw ? 1 : 2), ParameterAttributes.None, paramNames[i]);
                }

                methResult = methDyn;
            }

            // Index method by name
            this.methods[name] = methResult;
            return methResult;
        }
예제 #2
0
        /// <summary>
        /// Define a method in this module with the specified name and parameters.
        /// </summary>
        public MethodInfo DefineMethod(string name, Type returnType, Type[] paramTypes, string?[] paramNames, XmlILMethodAttributes xmlAttrs)
        {
            MethodInfo methResult;
            int        uniqueId = 1;
            string     nameOrig = name;

            Type[] paramTypesNew;
            bool   isRaw = (xmlAttrs & XmlILMethodAttributes.Raw) != 0;

            // Ensure that name is unique
            while (_methods[name] != null)
            {
                // Add unique id to end of name in order to make it unique within this module
                uniqueId++;
                name = $"{nameOrig} ({uniqueId})";
            }

            if (!isRaw)
            {
                // XmlQueryRuntime is always 0th parameter
                paramTypesNew    = new Type[paramTypes.Length + 1];
                paramTypesNew[0] = typeof(XmlQueryRuntime);
                Array.Copy(paramTypes, 0, paramTypesNew, 1, paramTypes.Length);
                paramTypes = paramTypesNew;
            }

            if (!_useLRE)
            {
                MethodBuilder methBldr = _typeBldr !.DefineMethod(
                    name,
                    MethodAttributes.Private | MethodAttributes.Static,
                    returnType,
                    paramTypes);

                if (_emitSymbols && (xmlAttrs & XmlILMethodAttributes.NonUser) != 0)
                {
                    // Add DebuggerStepThroughAttribute and DebuggerNonUserCodeAttribute to non-user methods so that debugging is a better experience
                    methBldr.SetCustomAttribute(new CustomAttributeBuilder(XmlILConstructors.StepThrough, Array.Empty <object>()));
                    methBldr.SetCustomAttribute(new CustomAttributeBuilder(XmlILConstructors.NonUserCode, Array.Empty <object>()));
                }

                if (!isRaw)
                {
                    methBldr.DefineParameter(1, ParameterAttributes.None, RuntimeName);
                }

                for (int i = 0; i < paramNames.Length; i++)
                {
                    if (paramNames[i] != null && paramNames[i] !.Length != 0)
                    {
                        methBldr.DefineParameter(i + (isRaw ? 1 : 2), ParameterAttributes.None, paramNames[i]);
                    }
                }

                methResult = methBldr;
            }
            else
            {
                DynamicMethod methDyn = new DynamicMethod(name, returnType, paramTypes, s_LREModule);
                methDyn.InitLocals = true;

                methResult = methDyn;
            }

            // Index method by name
            _methods[name] = methResult;
            return(methResult);
        }
예제 #3
0
        /// <summary>
        /// Given the logical query plan (QilExpression) generate a physical query plan (MSIL) that can be executed.
        /// </summary>
        // SxS Note: The way the trace file names are created (hardcoded) is NOT SxS safe. However the files are
        // created only for internal tracing purposes. In addition XmlILTrace class is not compiled into retail
        // builds. As a result it is fine to suppress the FxCop SxS warning.
        // TODO-NULLABLE: missing [return: NotNullIfNull("typeBldr")]
        public XmlILCommand?Generate(QilExpression query, TypeBuilder?typeBldr)
        {
            _qil = query;

            bool useLRE = (
                !_qil.IsDebug &&
                (typeBldr == null)
#if DEBUG
                && !XmlILTrace.IsEnabled // Dump assembly to disk; can't do this when using LRE
#endif
                );
            bool emitSymbols = _qil.IsDebug;

            // In debug code, ensure that input QIL is correct
            QilValidationVisitor.Validate(_qil);

#if DEBUG
            // Trace Qil before optimization
            XmlILTrace.WriteQil(_qil, "qilbefore.xml");

            // Trace optimizations
            XmlILTrace.TraceOptimizations(_qil, "qilopt.xml");
#endif

            // Optimize and annotate the Qil graph
            _optVisitor = new XmlILOptimizerVisitor(_qil, !_qil.IsDebug);
            _qil        = _optVisitor.Optimize();

            // In debug code, ensure that output QIL is correct
            QilValidationVisitor.Validate(_qil);

#if DEBUG
            // Trace Qil after optimization
            XmlILTrace.WriteQil(_qil, "qilafter.xml");
#endif

            // Create module in which methods will be generated
            if (typeBldr != null)
            {
                _module = new XmlILModule(typeBldr);
            }
            else
            {
                _module = new XmlILModule(useLRE, emitSymbols);
            }

            // Create a code generation helper for the module; enable optimizations if IsDebug is false
            _helper = new GenerateHelper(_module, _qil.IsDebug);

            // Create helper methods
            CreateHelperFunctions();

            // Create metadata for the Execute function, which is the entry point to the query
            // public static void Execute(XmlQueryRuntime);
            MethodInfo methExec = _module.DefineMethod("Execute", typeof(void), Array.Empty <Type>(), Array.Empty <string>(), XmlILMethodAttributes.NonUser);

            // Create metadata for the root expression
            // public void Root()
            Debug.Assert(_qil.Root != null);
            XmlILMethodAttributes methAttrs = (_qil.Root.SourceLine == null) ? XmlILMethodAttributes.NonUser : XmlILMethodAttributes.None;
            MethodInfo            methRoot  = _module.DefineMethod("Root", typeof(void), Array.Empty <Type>(), Array.Empty <string>(), methAttrs);

            // Declare all early bound function objects
            foreach (EarlyBoundInfo info in _qil.EarlyBoundTypes)
            {
                _helper.StaticData.DeclareEarlyBound(info.NamespaceUri, info.EarlyBoundType);
            }

            // Create metadata for each QilExpression function that has at least one caller
            CreateFunctionMetadata(_qil.FunctionList);

            // Create metadata for each QilExpression global variable and parameter
            CreateGlobalValueMetadata(_qil.GlobalVariableList);
            CreateGlobalValueMetadata(_qil.GlobalParameterList);

            // Generate Execute method
            GenerateExecuteFunction(methExec, methRoot);

            // Visit the QilExpression graph
            _xmlIlVisitor = new XmlILVisitor();
            _xmlIlVisitor.Visit(_qil, _helper, methRoot);

            // Collect all static information required by the runtime
            XmlQueryStaticData staticData = new XmlQueryStaticData(
                _qil.DefaultWriterSettings,
                _qil.WhitespaceRules,
                _helper.StaticData
                );

            // Create static constructor that initializes XmlQueryStaticData instance at runtime
            if (typeBldr != null)
            {
                CreateTypeInitializer(staticData);

                // Finish up creation of the type
                _module.BakeMethods();

                return(null);
            }
            else
            {
                // Finish up creation of the type
                _module.BakeMethods();

                // Create delegate over "Execute" method
                ExecuteDelegate delExec = (ExecuteDelegate)_module.CreateDelegate("Execute", typeof(ExecuteDelegate));
                return(new XmlILCommand(delExec, staticData));
            }
        }
예제 #4
0
        /// <summary>
        /// Define a method in this module with the specified name and parameters.
        /// </summary>
        public MethodInfo DefineMethod(string name, Type returnType, Type[] paramTypes, string[] paramNames, XmlILMethodAttributes xmlAttrs)
        {
            MethodInfo methResult;
            int        uniqueId = 1;
            string     nameOrig = name;

            Type[] paramTypesNew;
            bool   isRaw = (xmlAttrs & XmlILMethodAttributes.Raw) != 0;

            // Ensure that name is unique
            while (this.methods[name] != null)
            {
                // Add unique id to end of name in order to make it unique within this module
                uniqueId++;
                name = nameOrig + " (" + uniqueId + ")";
            }

            if (!isRaw)
            {
                // XmlQueryRuntime is always 0th parameter
                paramTypesNew    = new Type[paramTypes.Length + 1];
                paramTypesNew[0] = typeof(XmlQueryRuntime);
                Array.Copy(paramTypes, 0, paramTypesNew, 1, paramTypes.Length);
                paramTypes = paramTypesNew;
            }

            if (!this.useLRE)
            {
                MethodBuilder methBldr;

                methBldr = this.typeBldr.DefineMethod(
                    name,
                    MethodAttributes.Public | MethodAttributes.Static,
                    returnType,
                    paramTypes);

                if (emitSymbols && (xmlAttrs & XmlILMethodAttributes.NonUser) != 0)
                {
                    // Add DebuggerStepThroughAttribute and DebuggerNonUserCodeAttribute to non-user methods so that debugging is a better experience
                    methBldr.SetCustomAttribute(new CustomAttributeBuilder(XmlILConstructors.StepThrough, new object[] {}));
                    methBldr.SetCustomAttribute(new CustomAttributeBuilder(XmlILConstructors.NonUserCode, new object[] {}));
                }

                if (!isRaw)
                {
                    methBldr.DefineParameter(1, ParameterAttributes.None, RuntimeName);
                }

                for (int i = 0; i < paramNames.Length; i++)
                {
                    if (paramNames[i] != null && paramNames[i].Length != 0)
                    {
                        methBldr.DefineParameter(i + (isRaw ? 1 : 2), ParameterAttributes.None, paramNames[i]);
                    }
                }

                methResult = methBldr;
            }
            else
            {
                try {
                    // DynamicMethod constructor demands ReflectionEmit and ControlEvidence permission
                    CreateMethodPermissionSet.Assert();

                    DynamicMethod methDyn = new DynamicMethod(name, returnType, paramTypes, LREModule);
                    methDyn.InitLocals = true;

                    if (!isRaw)
                    {
                        methDyn.DefineParameter(1, ParameterAttributes.None, RuntimeName);
                    }

                    for (int i = 0; i < paramNames.Length; i++)
                    {
                        if (paramNames[i] != null && paramNames[i].Length != 0)
                        {
                            methDyn.DefineParameter(i + (isRaw ? 1 : 2), ParameterAttributes.None, paramNames[i]);
                        }
                    }

                    methResult = methDyn;
                }
                finally {
                    CodeAccessPermission.RevertAssert();
                }
            }

            // Index method by name
            this.methods[name] = methResult;
            return(methResult);
        }