/// <summary> /// Create static constructor that initializes XmlQueryStaticData instance at runtime. /// </summary> public void CreateTypeInitializer(XmlQueryStaticData staticData) { byte[] data; Type[] ebTypes; FieldInfo fldInitData, fldData, fldTypes; ConstructorInfo cctor; staticData.GetObjectData(out data, out ebTypes); fldInitData = _module !.DefineInitializedData("__" + XmlQueryStaticData.DataFieldName, data); fldData = _module.DefineField(XmlQueryStaticData.DataFieldName, typeof(object)); fldTypes = _module.DefineField(XmlQueryStaticData.TypesFieldName, typeof(Type[])); cctor = _module.DefineTypeInitializer(); _helper !.MethodBegin(cctor, null, false); // s_data = new byte[s_initData.Length] { s_initData }; _helper.LoadInteger(data.Length); _helper.Emit(OpCodes.Newarr, typeof(byte)); _helper.Emit(OpCodes.Dup); _helper.Emit(OpCodes.Ldtoken, fldInitData); _helper.Call(XmlILMethods.InitializeArray); _helper.Emit(OpCodes.Stsfld, fldData); if (ebTypes != null) { // Type[] types = new Type[s_ebTypes.Length]; LocalBuilder locTypes = _helper.DeclareLocal("$$$types", typeof(Type[])); _helper.LoadInteger(ebTypes.Length); _helper.Emit(OpCodes.Newarr, typeof(Type)); _helper.Emit(OpCodes.Stloc, locTypes); for (int idx = 0; idx < ebTypes.Length; idx++) { // types[idx] = ebTypes[idx]; _helper.Emit(OpCodes.Ldloc, locTypes); _helper.LoadInteger(idx); _helper.LoadType(ebTypes[idx]); _helper.Emit(OpCodes.Stelem_Ref); } // s_types = types; _helper.Emit(OpCodes.Ldloc, locTypes); _helper.Emit(OpCodes.Stsfld, fldTypes); } _helper.MethodEnd(); }
/// <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)); } }
/// <summary> /// Constructor. /// </summary> public XmlILCommand(ExecuteDelegate delExec, XmlQueryStaticData staticData) { Debug.Assert(delExec != null && staticData != null); _delExec = delExec; _staticData = staticData; }
public XmlILCommand(System.Xml.Xsl.ExecuteDelegate delExec, XmlQueryStaticData staticData) { this.delExec = delExec; this.staticData = staticData; }