public static int InsertInstructions(this MethodDefinition method, ILEmitter weakHandler, int insertPoint) { foreach (var i in weakHandler.Emit()) { method.Body.Instructions.Insert(insertPoint, i); ++insertPoint; } return insertPoint; }
public static object EmitReferencePeekUnchecked(ILEmitter /*!*/ il, IPlace /*!*/ stack, IPlace /*!*/ index) { Debug.Assert(il != null && stack != null && index != null); // LOAD stack.PeekReferenceUnchecked(<index+1>); stack.EmitLoad(il); index.EmitLoad(il); il.Emit(OpCodes.Call, Methods.PhpStack.PeekReferenceUnchecked); return(typeof(PhpReference)); }
//public static MethodCallPlace/*!*/ MakePeekValuePlace(IPlace/*!*/ stack, IPlace/*!*/ index) //{ // Debug.Assert(stack != null && index != null); // return new MethodCallPlace(Methods.PhpStack.PeekValue, false, stack, index); //} //public static MethodCallPlace/*!*/ MakeValuePeekUncheckedPlace(IPlace/*!*/ stack, IPlace/*!*/ index) //{ // Debug.Assert(stack != null && index != null); // return new MethodCallPlace(Methods.PhpStack.PeekValueUnchecked, false, stack, index); //} //public static MethodCallPlace/*!*/ MakeReferencePeekPlace(IPlace/*!*/ stack, IPlace/*!*/ index) //{ // Debug.Assert(stack != null && index != null); // return new MethodCallPlace(Methods.PhpStack.PeekReference, false, stack, index); //} //public static MethodCallPlace/*!*/ MakeReferencePeekUncheckedPlace(IPlace/*!*/ stack, IPlace/*!*/ index) //{ // Debug.Assert(stack != null && index != null); // return new MethodCallPlace(Methods.PhpStack.PeekReferenceUnchecked, false, stack, index); //} public static object EmitValuePeek(ILEmitter /*!*/ il, IPlace /*!*/ stack, IPlace /*!*/ index) { Debug.Assert(il != null && stack != null && index != null); // CALL stack.PeekValue(<index+1>); stack.EmitLoad(il); index.EmitLoad(il); il.Emit(OpCodes.Call, Methods.PhpStack.PeekValue); return(typeof(object)); }
/// <include file='Doc/Nodes.xml' path='doc/method[@name="Emit"]/*'/> internal override PhpTypeCode Emit(CodeGenerator codeGenerator) { Debug.Assert(access == AccessType.Read || access == AccessType.None); ILEmitter il = codeGenerator.IL; // count integer and string keys: int int_count = 0; int string_count = 0; DetermineCapacities(out int_count, out string_count); // array = new PhpArray(<int_count>, <string_count>); il.Emit(OpCodes.Ldc_I4, int_count); il.Emit(OpCodes.Ldc_I4, string_count); il.Emit(OpCodes.Newobj, Constructors.PhpArray.Int32_Int32); if (codeGenerator.Context.Config.Compiler.Debug) { il.Emit(OpCodes.Nop); il.Emit(OpCodes.Nop); il.Emit(OpCodes.Nop); } foreach (Item item in items) { // CALL array.SetArrayItemRef(z, p); // CALL array.SetArrayItem(x, PhpVariable.Copy(y, CopyReason.Assigned)); // CALL array.SetArrayItem(PhpVariable.Copy(x, CopyReason.Assigned)) // CALL array.AddToEnd(x) il.Emit(OpCodes.Dup); PhpTypeCode index_type_code = item.EmitIndex(codeGenerator); item.EmitValue(codeGenerator); codeGenerator.EmitSetArrayItem(index_type_code, item.Index, item is RefItem, true); } switch (this.access) { case AccessType.Read: // keep array on the stack return(PhpTypeCode.PhpArray); case AccessType.None: // pop array from the stack il.Emit(OpCodes.Pop); return(PhpTypeCode.Void); } Debug.Fail(); return(PhpTypeCode.Invalid); }
internal override void Emit(WhileStmt node, CodeGenerator codeGenerator) { Statistics.AST.AddNode("Loop.While"); ILEmitter il = codeGenerator.IL; Label cond_label = il.DefineLabel(); Label exit_label = il.DefineLabel(); Label stat_label = il.DefineLabel(); codeGenerator.BranchingStack.BeginLoop(cond_label, exit_label, codeGenerator.ExceptionBlockNestingLevel); if (node.LoopType == WhileStmt.Type.While) { il.Emit(OpCodes.Br, cond_label); } // body: il.MarkLabel(stat_label); node.Body.Emit(codeGenerator); // marks a sequence point containing condition: codeGenerator.MarkSequencePoint(node.CondExpr); // condition: il.MarkLabel(cond_label); // bounded loop: if (node.CondExpr != null) { // IF (<(bool) condition>) GOTO stat; codeGenerator.EmitConversion(node.CondExpr, PhpTypeCode.Boolean); il.Emit(OpCodes.Brtrue, stat_label); } il.MarkLabel(exit_label); codeGenerator.BranchingStack.EndLoop(); il.ForgetLabel(cond_label); il.ForgetLabel(exit_label); il.ForgetLabel(stat_label); }
/// <summary> /// Emit the PhpType finalizer. The finalizer is emitted only if there is __destruct() function /// and there is no finalizer in any base class already. The finalizer calls this.Dispose() which /// calls __destruct() function directly. /// </summary> /// <param name="phpType"></param> private static void EmitFinalizer(PhpType /*!*/ phpType) { // only if __destruct was now defined in some base class, no need to override existing definition on Finalize DRoutine basedestruct; DRoutineDesc destruct; if ((destruct = phpType.TypeDesc.GetMethod(DObject.SpecialMethodNames.Destruct)) != null && (phpType.Base == null || phpType.Base.GetMethod(DObject.SpecialMethodNames.Destruct, phpType, out basedestruct) == GetMemberResult.NotFound)) { MethodBuilder finalizer_builder = phpType.RealTypeBuilder.DefineMethod("Finalize", MethodAttributes.HideBySig | MethodAttributes.Virtual | MethodAttributes.Family, typeof(void), Type.EmptyTypes); ILEmitter dil = new ILEmitter(finalizer_builder); // exact Finalize() method pattern follows: // try dil.BeginExceptionBlock(); // this.Dispose(false) dil.Emit(OpCodes.Ldarg_0); dil.Emit(OpCodes.Ldc_I4_0); dil.Emit(OpCodes.Callvirt, PHP.Core.Emit.Methods.DObject_Dispose); // finally dil.BeginFinallyBlock(); // Object.Finalize() dil.Emit(OpCodes.Ldarg_0); dil.Emit(OpCodes.Call, PHP.Core.Emit.Methods.Object_Finalize); dil.EndExceptionBlock(); dil.Emit(OpCodes.Ret); } }
/// <summary> /// Define new instance of CallSite<<paramref name="delegateType"/>> and initialize it with specified binder. /// </summary> /// <param name="bodyEmitter"><see cref="ILEmitter"/> of the body that is using this call site. This method may emit initialization of the call site into this <paramref name="bodyEmitter"/>.</param> /// <param name="userFriendlyName">User friendly name used as name for the CallSite field.</param> /// <param name="delegateType">CallSite type argument.</param> /// <param name="binderInstanceEmitter">Function used to emit initialization of the binder from within the call sites container .cctor.</param> /// <returns>The <see cref="FieldInfo"/> containing the instance of the created CallSite.</returns> public FieldInfo /*!*/ DefineCallSite(ILEmitter /*!*/ bodyEmitter, string /*!*/ userFriendlyName, Type /*!*/ delegateType, Action <ILEmitter> /*!*/ binderInstanceEmitter) { Debug.Assert(userFriendlyName != null && delegateType != null && binderInstanceEmitter != null); userFriendlyName += ("'" + (callSitesCount++)); // call site type var callSiteType = Types.CallSiteGeneric[0].MakeGenericType(delegateType); // define the field: // public static readonly CallSite<delegateType> <userFriendlyName> var attrs = FieldAttributes.Static | FieldAttributes.InitOnly | ((staticCtorEmitter == null) ? FieldAttributes.Private : FieldAttributes.Assembly); var field = this.DefineField(PluginHandler.ConvertCallSiteName(userFriendlyName), callSiteType, attrs); if (staticCtorEmitter == null) // => this.classContext != null { // emit initialization of the call site just in the body of current method (as it is in C#, we need current generic arguments): Debug.Assert(this.classContext != null); // check if the call site if not null, otherwise initialize it first: // if (<field> == null) <InitializeCallSite>; Label ifend = bodyEmitter.DefineLabel(); bodyEmitter.Emit(OpCodes.Ldsfld, field); bodyEmitter.Emit(OpCodes.Brtrue, ifend); // init the field: InitializeCallSite(bodyEmitter, callSiteType, field, binderInstanceEmitter); bodyEmitter.MarkLabel(ifend); } else { // init the field in .cctor: InitializeCallSite(staticCtorEmitter, callSiteType, field, binderInstanceEmitter); } // return(field); }
internal override void EmitStoreAssign(CodeGenerator codeGenerator) { ILEmitter il = codeGenerator.IL; if (varName.IsThisVariableName) { // emit error throwing code il.Emit(OpCodes.Pop); codeGenerator.EmitPhpException(Methods.PhpException.CannotReassignThis); } else if (codeGenerator.VariableIsAutoGlobal(varName)) { // Check if the variable is auto-global codeGenerator.EmitAutoGlobalStoreAssign(); } else if (codeGenerator.OptimizedLocals) { // Template: // "WRITE($x,value);" // **** // if specified variable is of type PhpReference // ldloc local // **** // Otherwise do nothing VariablesTable.Entry entry = codeGenerator.CurrentVariablesTable[varName]; if (entry.IsPhpReference) { il.Emit(OpCodes.Stfld, Fields.PhpReference_Value); } else { entry.Variable.EmitStore(il); } } else { // CALL Operators.SetVariable(STACK:table,STACK:name,STACK:value); il.Emit(OpCodes.Call, Methods.Operators.SetVariable); } }
/// <summary> /// Emit lambda function that returns values used for sorting and /// call to OrderedSequence.OrderBy method (with current LINQ context as /// first and generated lambda as a second parameter) /// </summary> public override PhpTypeCode Emit(LinqBuilder codeGenerator) { ILEmitter il = codeGenerator.IL; // NEW Func[object,object](<linq context>, <&lambda>); codeGenerator.EmitLoadLinqContext(); il.Emit(OpCodes.Ldftn, codeGenerator.EmitLambda(string.Format("<Comparer_{0}>", codeGenerator.GetNextComparerNum()), valueVar, expression, PhpTypeCode.Object)); il.Emit(OpCodes.Newobj, LinqExterns.Func2_object_object_ctor); // LOAD Select[object,object](<source>, <delegate>); if (isThenBy) { il.Emit(OpCodes.Call, ordering == Ordering.Descending ? LinqExterns.ThenByDescending : LinqExterns.ThenBy); } else { il.Emit(OpCodes.Call, ordering == Ordering.Descending ? LinqExterns.OrderByDescending : LinqExterns.OrderBy); } return(base.Emit(codeGenerator)); }
/// <summary> /// Emits dynamic inclusion. /// </summary> private PhpTypeCode EmitDynamicInclusion(CodeGenerator /*!*/ codeGenerator) { // do not generate dynamic auto inclusions: if (InclusionTypesEnum.IsAutoInclusion(inclusionType)) { return(PhpTypeCode.Void); } ILEmitter il = codeGenerator.IL; // CALL context.DynamicInclude(<file name>,<relative includer source path>,variables,self,includer); codeGenerator.EmitLoadScriptContext(); codeGenerator.EmitConversion(fileNameEx, PhpTypeCode.String); il.Emit(OpCodes.Ldstr, codeGenerator.SourceUnit.SourceFile.RelativePath.ToString()); codeGenerator.EmitLoadRTVariablesTable(); codeGenerator.EmitLoadSelf(); codeGenerator.EmitLoadClassContext(); il.LoadLiteral(inclusionType); il.Emit(OpCodes.Call, Methods.ScriptContext.DynamicInclude); return(PhpTypeCode.Object); }
/// <summary> /// Stores a value on the top of the stack to a specified variable. /// </summary> internal void StoreLocalAssign(CodeGenerator codeGenerator, VariablesTable.Entry variable, LocalBuilder variableName) { ILEmitter il = codeGenerator.IL; Debug.Assert(variable == null ^ variableName == null); LocalBuilder temp; if (variable != null) { if (variable.IsPhpReference) { // temp = STACK temp = il.GetTemporaryLocal(Types.Object[0], true); il.Stloc(temp); // <variable>.value = temp; variable.Variable.EmitLoad(il); il.Ldloc(temp); il.Emit(OpCodes.Stfld, Fields.PhpReference_Value); } else { variable.Variable.EmitStore(il); } } else { // temp = STACK temp = il.GetTemporaryLocal(Types.Object[0], true); il.Stloc(temp); // CALL Operators.SetVariable(<local variables table>,<name>,temp); codeGenerator.EmitLoadScriptContext(); codeGenerator.EmitLoadRTVariablesTable(); il.Ldloc(variableName); il.Ldloc(temp); il.Emit(OpCodes.Call, Methods.Operators.SetVariable); } }
public static void EmitArgFullPreCall(ILEmitter /*!*/ il, IPlace /*!*/ stack, bool argsAware, int formalParamCount, int formalTypeParamCount, out LocalBuilder locArgsCount) { if (argsAware) { locArgsCount = il.DeclareLocal(typeof(int)); // locArgsCount = stack.MakeArgsAware(<formal tpye param count | formal param count>); stack.EmitLoad(il); il.LdcI4((formalTypeParamCount << 16) | formalParamCount); il.Emit(OpCodes.Call, Methods.PhpStack.MakeArgsAware); il.Stloc(locArgsCount); } else { locArgsCount = null; // CALL stack.RemoveFrame(); stack.EmitLoad(il); il.Emit(OpCodes.Call, Methods.PhpStack.RemoveFrame); } }
/// <summary> /// Emits IL instructions that transfer the control to the target label for <B>break</B> statement /// having parameter that cannot be evaluated at compile time. /// </summary> /// <remarks>This function is used to generate code for <B>break v;</B> where <i>v</i> is a variable.</remarks> public void EmitBreakRuntime() { int i; ILEmitter il = codeGenerator.IL; Label[] jumpTable = new Label[stack.Count + 1]; Label exitLabel = il.DefineLabel(); Debug.Assert(stack.Count != 0); for (i = 0; i <= stack.Count; i++) { jumpTable[i] = il.DefineLabel(); } // The value according to we switch is already present on the evaluation stack LocalBuilder break_level_count = il.DeclareLocal(typeof(Int32)); il.Emit(OpCodes.Dup); il.Stloc(break_level_count); il.Emit(OpCodes.Switch, jumpTable); // Default case il.Ldloc(break_level_count); codeGenerator.EmitPhpException(Methods.PhpException.InvalidBreakLevelCount); il.Emit(OpCodes.Br, exitLabel); il.MarkLabel(jumpTable[0]); EmitBranchToExit((StackItem)stack[stack.Count - 1]); for (i = 1; i <= stack.Count; i++) { il.MarkLabel(jumpTable[i]); EmitBranchToExit((StackItem)stack[stack.Count - i]); } il.MarkLabel(exitLabel); }
/// <summary> /// Emits code that loads type descriptors for all generic arguments and a call to /// <see cref="Operators.MakeGenericTypeInstantiation"/>. /// </summary> internal void EmitMakeGenericInstantiation(CodeGenerator /*!*/ codeGenerator, ResolveTypeFlags flags) { ILEmitter il = codeGenerator.IL; il.EmitOverloadedArgs(Types.DTypeDesc[0], genericParams.Count, Methods.Operators.MakeGenericTypeInstantiation.ExplicitOverloads, delegate(ILEmitter eil, int i) { genericParams[i].EmitLoadTypeDesc(codeGenerator, flags); }); if (genericParams.Count > 0) { il.Emit(OpCodes.Call, Methods.Operators.MakeGenericTypeInstantiation.Overload(genericParams.Count)); } }
public void DefineContextType() { linqContextBuilder = cg.IL.TypeBuilder.DefineNestedType(ContextTypeName + cg.IL.GetNextUniqueIndex(), TypeAttributes.Class | TypeAttributes.NestedPrivate | TypeAttributes.Sealed, typeof(PHP.Core.LinqContext), null); // .ctor: ConstructorBuilder ctor = linqContextBuilder.DefineConstructor(MethodAttributes.Assembly, CallingConventions.HasThis, Types.LinqContextArgs); ILEmitter il = new ILEmitter(ctor); il.Ldarg(0); il.Ldarg(1); il.Ldarg(2); il.Ldarg(3); il.Ldarg(4); il.Emit(OpCodes.Call, Constructors.LinqContext); il.Emit(OpCodes.Ret); linqContextCtor = ctor; }
public void EmitNewLinqContext() { ILEmitter il = cg.IL; linqContextLocal = il.DeclareLocal(linqContextBuilder); // linq_context = NEW <linq context>(<this>, <variables>, <script context>, <type desc>) cg.SelfPlace.EmitLoad(il); cg.RTVariablesTablePlace.EmitLoad(il); cg.ScriptContextPlace.EmitLoad(il); cg.TypeContextPlace.EmitLoad(il); il.Emit(OpCodes.Newobj, linqContextCtor); il.Stloc(linqContextLocal); }
/// <summary> /// Emits the catch-block. /// </summary> /// <param name="node">Instance.</param> /// <param name="codeGenerator">A code generator.</param> /// <param name="exceptionLocal">A local variable containing an instance of <see cref="Library.SPL.Exception"/>.</param> /// <param name="endLabel">A label in IL stream where the processing of the try-catch blocks ends.</param> /// <param name="nextCatchLabel">A label in IL stream where the next catch block processing begins.</param> public void Emit(CatchItem /*!*/ node, CodeGenerator /*!*/ codeGenerator, LocalBuilder /*!*/ exceptionLocal, Label endLabel, Label nextCatchLabel) { ILEmitter il = codeGenerator.IL; codeGenerator.MarkSequencePoint(node.Variable); // IF !InstanceOf(<class name>) GOTO next_catch; il.Ldloc(exceptionLocal); resolvedType.EmitInstanceOf(codeGenerator, null); il.Emit(OpCodes.Brfalse, nextCatchLabel); // variable = exception; node.Variable.Emit(codeGenerator); il.Ldloc(exceptionLocal); SimpleVarUseHelper.EmitAssign(node.Variable, codeGenerator); node.Statements.Emit(codeGenerator); // LEAVE end; il.Emit(OpCodes.Leave, endLabel); }
internal override void EmitStoreRefAssign(CodeGenerator codeGenerator) { ILEmitter il = codeGenerator.IL; if (codeGenerator.OptimizedLocals) { // For IndirectVarUse emit switch over all variables EmitSwitch(codeGenerator, new SwitchMethod(StoreLocalRefAssign)); } else { // Operators.SetVariable( <FROM EmitStoreRefPrepare> ) il.Emit(OpCodes.Call, Methods.Operators.SetVariableRef); } }
internal override PhpTypeCode Emit(CodeGenerator /*!*/ codeGenerator) { ILEmitter il = codeGenerator.IL; int indir = this.count - 2; // cast object to correct tuple type: // Tuple<Tuple<...Tuple<object, object>, .. >, object>, object> il.Emit(OpCodes.Ldarg_1); il.Emit(OpCodes.Castclass, LinqExterns.GetTupleInfo(indir).Type); // Find value at specified index (tup.First.First....First/Second); int timesFirst = index - ((index == count - 1) ? 1 : 0); for (int i = 0; i < timesFirst; i++) { il.Emit(OpCodes.Call, LinqExterns.GetTupleInfo(indir - i).SecondGetter); } // The last value is stored in Second, other values are stored in First il.Emit(OpCodes.Call, (index == count - 1)? LinqExterns.GetTupleInfo(indir - timesFirst).SecondGetter: LinqExterns.GetTupleInfo(indir - timesFirst).FirstGetter); return(PhpTypeCode.Object); }
internal override void EmitStoreAssign(CodeGenerator codeGenerator) { ILEmitter il = codeGenerator.IL; if (codeGenerator.OptimizedLocals) { // For IndirectVarUse emit switch over all variables EmitSwitch(codeGenerator, new SwitchMethod(StoreLocalAssign)); } else { // Template: // void Operators.SetVariable(table, "x", PhpVariable.Copy(Operators.getValue(table, "x"), CopyReason.Assigned)); il.Emit(OpCodes.Call, Methods.Operators.SetVariable); } }
/// <summary> /// Emits init field helpers (<c>__lastContext</c> field, <c><InitializeInstanceFields></c> /// method and <c>__InitializeStaticFields</c> into a class. /// </summary> internal static void EmitInitFieldHelpers(PhpType phpType) { // // <InitializeInstanceFields> // // <InitializeInstanceFields> method - will contain instance field initialization phpType.Builder.InstanceFieldInit = phpType.RealTypeBuilder.DefineMethod( InstanceFieldInitMethodName, #if SILVERLIGHT MethodAttributes.Public | MethodAttributes.HideBySig, #else MethodAttributes.Private | MethodAttributes.HideBySig, #endif CallingConventions.Standard, Types.Void, Types.ScriptContext); phpType.Builder.InstanceFieldInitEmitter = new ILEmitter(phpType.Builder.InstanceFieldInit); // // <InitializeStaticFields> // // <InitializeStaticFields> method has already been defined during the analysis phase - will contain (thread) // static field initialization ILEmitter cil = new ILEmitter(phpType.StaticFieldInitMethodBuilder); if (phpType.Builder.HasThreadStaticFields) { // __lastContext thread-static field - will contain the last SC that inited static fields for this thread FieldBuilder last_context = phpType.RealTypeBuilder.DefineField( "<lastScriptContext>", Types.ScriptContext[0], FieldAttributes.Private | FieldAttributes.Static); // SILVERLIGHT: Not sure what this does & what would be the right behavior... #if !SILVERLIGHT last_context.SetCustomAttribute(AttributeBuilders.ThreadStatic); #endif // Label init_needed_label = cil.DefineLabel(); // [ if (arg0 == __lastContext) ret ] cil.Emit(OpCodes.Ldarg_0); cil.Emit(OpCodes.Ldsfld, last_context); cil.Emit(OpCodes.Bne_Un_S, init_needed_label); cil.Emit(OpCodes.Ret); // [ __lastContext = arg0 ] cil.MarkLabel(init_needed_label); cil.Emit(OpCodes.Ldarg_0); cil.Emit(OpCodes.Stsfld, last_context); // the rest of the method is created when fields are emitted } }
/// <summary> /// Implements a <see cref="ISpecializationCacheArgs"/> interface in order to /// make the given <paramref name="typeBuilder"/> compatible with a /// <see cref="SpecializationCache{TLoader, TArgs, TDelegate}"/> instance. /// </summary> /// <param name="typeBuilder">The target type builder to use.</param> /// <param name="fields">The source fields used for implementation.</param> private static void ImplementSpecializationCacheArgs( TypeBuilder typeBuilder, FieldInfo[] fields) { var specializedType = typeof(SpecializedValue <>); var getArgMethod = typeBuilder.DefineMethod( nameof(ISpecializationCacheArgs.GetSpecializedArg), MethodAttributes.Public | MethodAttributes.Virtual, typeof(object), new Type[] { typeof(int) }); var emitter = new ILEmitter(getArgMethod.GetILGenerator()); // Declare labels and emit jump table var labels = new ILLabel[fields.Length]; for (int i = 0, e = fields.Length; i < e; ++i) { labels[i] = emitter.DeclareLabel(); } emitter.Emit(OpCodes.Ldarg_1); emitter.EmitSwitch(labels); for (int i = 0, e = fields.Length; i < e; ++i) { var field = fields[i]; emitter.MarkLabel(labels[i]); emitter.Emit(OpCodes.Ldarg_0); emitter.Emit(OpCodes.Ldfld, field); // Wrap in a specialized instance var fieldReturnType = specializedType.MakeGenericType(field.FieldType); var instanceConstructor = fieldReturnType.GetConstructor( new Type[] { field.FieldType }); emitter.EmitNewObject(instanceConstructor); emitter.Emit(OpCodes.Box, fieldReturnType); emitter.Emit(OpCodes.Ret); } // Return dummy argument emitter.Emit(OpCodes.Ldnull); emitter.Emit(OpCodes.Ret); emitter.Finish(); typeBuilder.AddInterfaceImplementation(typeof(ISpecializationCacheArgs)); }
/// <summary> /// Bake the container class if any. Close the call sites builder. /// </summary> public void Bake() { if (containerClass != null) { Debug.Assert(staticCtorEmitter != null); // finish static ctor: staticCtorEmitter.Emit(OpCodes.Ret); // bake the call sites container: containerClass.CreateType(); // avoid of using the builders anymore: containerClass = null; staticCtorEmitter = null; } }
internal override PhpTypeCode EmitGet(CodeGenerator /*!*/ codeGenerator, ConstructedType constructedType, bool runtimeVisibilityCheck, string fallbackName) { ILEmitter il = codeGenerator.IL; if (HasValue) { il.LoadLiteral(Value); return(PhpTypeCodeEnum.FromObject(Value)); } else { Debug.Assert(realField != null); il.Emit(OpCodes.Ldsfld, DType.MakeConstructed(realField, constructedType)); return(PhpTypeCodeEnum.FromType(realField.FieldType)); } }
public ILEmitter Emit(ILEmitter il, LocalBuilder hash) { var arrayType = _variable.VariableType; il.Emit(_variable.Load(Arg.Input)) // load array .Stloc(arrayType, out var array) .Brtrue_S(Ldloc(array), out var begin) .Ldc_I4(0) .Br(out var end) .MarkLabel(begin); if (_configuration.IgnoreCollectionOrder) { il.EmitArraySorting(_hasCustomComparer, arrayType.GetElementType(), array); } return(_arrayHashEmitter.Emit(il, arrayType, array, hash).MarkLabel(end)); }
internal override PhpTypeCode Emit(CodeGenerator /*!*/ codeGenerator) { // emit tuple value foreach (OrderingClause clause in OrderingItems) { clause.Expression.Emit(codeGenerator); } LastItem.Emit(codeGenerator); // emit tuple creation ILEmitter il = codeGenerator.IL; for (int indirection = 0; indirection < OrderingItems.Count; indirection++) { il.Emit(OpCodes.Newobj, LinqExterns.GetTupleInfo(indirection).Constructor); } return(PhpTypeCode.Object); }
internal override PhpTypeCode EmitIsset(CodeGenerator codeGenerator, bool empty) { // Template: "isset(x)" x != null // isset doesn't distinguish between the NULL and uninitialized variable // a reference is dereferenced, i.e. isset tells us whether the referenced variable is set Debug.Assert(access == AccessType.Read); // Cases 1, 4, 5, 6, 9 never reached Debug.Assert(codeGenerator.ChainBuilder.IsMember == false); // Case 3 never reached Debug.Assert(codeGenerator.ChainBuilder.IsArrayItem == false); codeGenerator.ChainBuilder.QuietRead = true; // 2,7,8 if (this.isMemberOf != null) { // 2: $b->a // 8: b[]->a codeGenerator.ChainBuilder.Create(); codeGenerator.ChainBuilder.Begin(); codeGenerator.ChainBuilder.QuietRead = true; EmitReadField(codeGenerator, false); codeGenerator.ChainBuilder.End(); return(PhpTypeCode.Object); } // 7: $a // Check whether this variable is set //codeGenerator.EmitVariableIsset(this); ILEmitter il = codeGenerator.IL; if (varName.IsThisVariableName && codeGenerator.LocationStack.LocationType == LocationTypes.MethodDecl) { CompilerLocationStack.MethodDeclContext context = codeGenerator.LocationStack.PeekMethodDecl(); if (!context.Method.IsStatic) { // $this is always set in instance methods il.Emit(OpCodes.Ldarg_0); return(PhpTypeCode.Object); } } this.EmitLoad(codeGenerator); return(PhpTypeCode.Object); }
/// <summary> /// Emits code that loads type descriptors for all generic arguments and a call to /// <see cref="Operators.MakeGenericTypeInstantiation"/>. /// </summary> internal void EmitMakeGenericInstantiation(TypeRef node, CodeGenerator /*!*/ codeGenerator, ResolveTypeFlags flags) { if (node.GenericParams == null || node.GenericParams.Count == 0) { return; } ILEmitter il = codeGenerator.IL; il.EmitOverloadedArgs(Types.DTypeDesc[0], node.GenericParams.Count, Methods.Operators.MakeGenericTypeInstantiation.ExplicitOverloads, delegate(ILEmitter eil, int i) { TypeRefHelper.EmitLoadTypeDesc(node.GenericParams[i], codeGenerator, flags); }); if (node.GenericParams.Count > 0) { il.Emit(OpCodes.Call, Methods.Operators.MakeGenericTypeInstantiation.Overload(node.GenericParams.Count)); } }
internal override void EmitLoadRef(CodeGenerator codeGenerator) { ILEmitter il = codeGenerator.IL; if (codeGenerator.OptimizedLocals) { // For IndirectVarUse emit switch over all variables. EmitSwitch(codeGenerator, new SwitchMethod(LoadLocalRef)); } else { // Template: // PhpReference Operators.GetVariableRef(IDictionary table, string name) //returns variable value; variable is of type PhpReference codeGenerator.EmitLoadScriptContext(); codeGenerator.EmitLoadRTVariablesTable(); EmitName(codeGenerator); il.Emit(OpCodes.Call, Methods.Operators.GetVariableRef); } }
/// <summary> /// Loads a specified reference local variable. /// </summary> internal void LoadLocalRef(CodeGenerator codeGenerator, VariablesTable.Entry variable, LocalBuilder variableName) { ILEmitter il = codeGenerator.IL; Debug.Assert(variable == null ^ variableName == null); if (variable != null) { Debug.Assert(variable.IsPhpReference); variable.Variable.EmitLoad(il); } else { codeGenerator.EmitLoadScriptContext(); codeGenerator.EmitLoadRTVariablesTable(); il.Ldloc(variableName); il.Emit(OpCodes.Call, Methods.Operators.GetVariableRef); } }
public ILEmitter Emit(ILEmitter il, LocalBuilder hash) { il.Emit(_variable.Load(Arg.Input)) .Stloc(_variable.VariableType, out var enumerable) .DefineLabel(out var end); if (!_variable.VariableType.IsValueType) { il.Brtrue_S(Ldloc(enumerable), out var begin) .Ldc_I4(0) .Br(end) .MarkLabel(begin); } if (_configuration.Get(_variable.OwnerType).IgnoreCollectionOrder) { return(EmitHashAsSortedArray(il, enumerable, hash).MarkLabel(end)); } il.CallMethod(_getEnumeratorMethod, LoadCaller(enumerable)) .Stloc(_enumeratorType, out var enumerator) .DefineLabel(out var loopStart); if (!_enumeratorType.IsValueType) { il.Brtrue_S(Ldloc(enumerator), loopStart) .Ldc_I4(0) .Br(end); } // todo: 1. think how to use try/finally block // the problem now with the inner `return` statements, it has to be `leave` instruction //il.BeginExceptionBlock(); Loop(il, enumerator, loopStart, hash); //il.BeginFinallyBlock(); EmitDisposeEnumerator(il, enumerator); //il.EndExceptionBlock(); return(il.Ldloc(hash).MarkLabel(end)); }