/// <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(_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)); } }
/// <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)); }