Example #1
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.
        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(this.qil, "qilbefore.xml");

            // Trace optimizations
            XmlILTrace.TraceOptimizations(this.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(this.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), new Type[] { }, new 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), new Type[] { }, new 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);
            }
        }
Example #2
0
        /// <summary>
        /// Cache metadata used during code-generation phase.
        /// </summary>
        // SxS note: Using hardcoded "dump.il" is an SxS issue. Since we are doing this ONLY in debug builds 
        // and only for tracing purposes and MakeVersionSafeName does not seem to be able to handle file 
        // extensions correctly I decided to suppress the SxS message (as advised by SxS guys).
        public GenerateHelper(XmlILModule module, bool isDebug)
        {
            _isDebug = isDebug;
            _module = module;
            _staticData = new StaticDataManager();

#if DEBUG
            if (XmlILTrace.IsEnabled)
                XmlILTrace.PrepareTraceWriter("dump.il");
#endif
        }
        /// <summary>
        /// Given the logical query plan (QilExpression) generate a physical query plan (MSIL) that can be executed.
        /// </summary>
        public XmlCommand Generate(QilExpression query, AssemblyName asmName) {
            MethodInfo methRoot, methExec;
            bool useLRE, emitSymbols;
            ExecuteDelegate delExec;
            XmlILMethodAttributes methAttrs;

            this.qil = query;

            useLRE = !this.qil.IsDebug && (asmName == null);
            emitSymbols = this.qil.IsDebug;

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

            // Trace Qil before optimization
            XmlILTrace.WriteQil(this.qil, "qilbefore.xml");

            // Trace optimizations
            XmlILTrace.TraceOptimizations(this.qil, "qilopt.xml");

            if (XmlILTrace.IsEnabled) {
                // Dump assembly to disk; can't do this when using LRE
                useLRE = false;
            }

            // Optimize and annotate the Qil graph
            this.optVisitor = new XmlILOptimizerVisitor(this.qil, !this.qil.IsDebug);
            this.qil = this.optVisitor.Optimize();

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

            // Trace Qil after optimization
            XmlILTrace.WriteQil(this.qil, "qilafter.xml");

            // Create module in which methods will be generated
            this.module = new XmlILModule(useLRE, emitSymbols, asmName);

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

            // Create helper methods
            CreateHelperFunctions();

            // Create metadata for the root expression
            // public void Root()
            Debug.Assert(this.qil.Root != null);
            methAttrs = (this.qil.Root.SourceLine == null) ? XmlILMethodAttributes.NonUser : XmlILMethodAttributes.None;
            methRoot = this.module.DefineMethod("Root", typeof(void), new Type[] {}, new string[] {}, methAttrs);

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

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

            // Create Execute method
            methExec = CreateExecuteFunction(methRoot);

            // Visit the QilExpression graph
            this.xmlIlVisitor = new XmlILVisitor();
            this.xmlIlVisitor.Visit(this.qil, this.helper, methRoot);

            this.module.BakeMethods();

            // Create delegate over "Execute" method
            delExec = (ExecuteDelegate) this.module.CreateDelegate("Execute", typeof(ExecuteDelegate));

            return new XmlILCommand(delExec, this.qil, this.helper.StaticData);
        }