///// <summary> ///// Prepares local variable for a store operation. ///// </summary> //internal void StoreLocalPrepare(CodeGenerator codeGenerator, VariablesTable.Entry variable, LocalBuilder variableName) //{ // Debug.Assert(variable == null ^ variableName == null); //} /// <summary> /// Unsets a specified variable. /// </summary> internal void UnsetLocal(CodeGenerator codeGenerator, VariablesTable.Entry variable, LocalBuilder variableName) { ILEmitter il = codeGenerator.IL; Debug.Assert(variable == null ^ variableName == null); if (variable != null) { if (variable.IsPhpReference) { // <variable> = new PhpReference(); il.Emit(OpCodes.Newobj, Constructors.PhpReference_Void); variable.Variable.EmitStore(il); } else { il.Emit(OpCodes.Ldnull); variable.Variable.EmitStore(il); } } else { // CALL Operators.SetVariable(<local variables table>,<name>,null); codeGenerator.EmitLoadScriptContext(); codeGenerator.EmitLoadRTVariablesTable(); il.Ldloc(variableName); il.Emit(OpCodes.Ldnull); il.Emit(OpCodes.Call, Methods.Operators.SetVariable); } }
/// <summary> /// Emit reference load of variable named <paramref name="varName"/>. /// </summary> internal static void EmitLoadRef(CodeGenerator /*!*/ codeGenerator, VariableName varName) { ILEmitter il = codeGenerator.IL; // Check if the variable is auto-global if (codeGenerator.VariableIsAutoGlobal(varName)) { codeGenerator.EmitAutoGlobalLoadRef(varName); return; } if (codeGenerator.OptimizedLocals) { // Template: for DirectVarUse // "LOAD ref $x;" // // ldloc loc // Local variable should be of type PhpReference VariablesTable.Entry entry = codeGenerator.CurrentVariablesTable[varName]; entry.Variable.EmitLoad(il); } else { // Template: // PhpReference Operators.GetVariableRef(IDictionary table, string name) codeGenerator.EmitLoadScriptContext(); codeGenerator.EmitLoadRTVariablesTable(); il.Emit(OpCodes.Ldstr, varName.Value); il.Emit(OpCodes.Call, Methods.Operators.GetVariableRef); } }
internal override void EmitStoreRefAssign(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.EmitAutoGlobalStoreRefAssign(varName); } else if (codeGenerator.OptimizedLocals) { VariablesTable.Entry entry = codeGenerator.CurrentVariablesTable[varName]; entry.Variable.EmitStore(il); } else { // call instance IDictionary.set_Item(object, object) // OBSOLETE: il.Emit(OpCodes.Callvirt, Methods.IDictionary_SetItem); il.Emit(OpCodes.Call, Methods.Operators.SetVariableRef); } }
/// <summary> /// Loads a value of a specified variable. If the variable is of type <see cref="PhpReference"/>, it is dereferenced. /// </summary> internal void LoadLocal(CodeGenerator codeGenerator, VariablesTable.Entry variable, LocalBuilder variableName) { ILEmitter il = codeGenerator.IL; Debug.Assert(variable == null ^ variableName == null); if (variable != null) { // LOAD DEREF <variable>; variable.Variable.EmitLoad(il); if (variable.IsPhpReference) { il.Emit(OpCodes.Ldfld, Fields.PhpReference_Value); } } else { // LOAD Operators.GetVariable[Unchecked](<script context>, <local variables table>, <variable name>); codeGenerator.EmitLoadScriptContext(); codeGenerator.EmitLoadRTVariablesTable(); il.Ldloc(variableName); if (codeGenerator.ChainBuilder.QuietRead) { il.Emit(OpCodes.Call, Methods.Operators.GetVariableUnchecked); } else { il.Emit(OpCodes.Call, Methods.Operators.GetVariable); } } }
/// <summary> /// Stores a reference on the top of the stack to a specified variable. /// </summary> internal void StoreLocalRefAssign(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.EmitStore(il); } else { // temp = STACK LocalBuilder temp = il.GetTemporaryLocal(Types.PhpReference[0], true); il.Stloc(temp); // CALL Operators.SetVariableRef(<local variables table>,<name>,temp); codeGenerator.EmitLoadScriptContext(); codeGenerator.EmitLoadRTVariablesTable(); il.Ldloc(variableName); il.Ldloc(temp); il.Emit(OpCodes.Call, Methods.Operators.SetVariableRef); } }
/// <summary> /// Emit load of variable named <paramref name="varName"/>. /// </summary> internal static PhpTypeCode EmitLoad(CodeGenerator codeGenerator, VariableName varName) { ILEmitter il = codeGenerator.IL; // Check if the variable is auto-global if (codeGenerator.VariableIsAutoGlobal(varName)) { codeGenerator.EmitAutoGlobalLoad(varName); return(PhpTypeCode.Object); } // Variable is local if (codeGenerator.OptimizedLocals) { // Template: // ldloc loc // ***** // If the specidied variable is of type PhpReference // ldfld PhpReference.value // ***** VariablesTable.Entry entry = codeGenerator.CurrentVariablesTable[varName]; entry.Variable.EmitLoad(il); if (entry.IsPhpReference) { il.Emit(OpCodes.Ldfld, Fields.PhpReference_Value); } return(PhpTypeCode.Object); } // LOAD Operators.GetVariable[Unchecked](<script context>, <local variable table>, <name>); codeGenerator.EmitLoadScriptContext(); codeGenerator.EmitLoadRTVariablesTable(); il.Emit(OpCodes.Ldstr, varName.Value); if (codeGenerator.ChainBuilder.QuietRead) { il.Emit(OpCodes.Call, Methods.Operators.GetVariableUnchecked); } else { il.Emit(OpCodes.Call, Methods.Operators.GetVariable); } return(PhpTypeCode.Object); }
/// <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); } }
/// <summary> /// Loads an address of a variable on the stack. /// </summary> internal override void EmitLoadAddress(CodeGenerator codeGenerator) { ILEmitter il = codeGenerator.IL; if (codeGenerator.VariableIsAutoGlobal(varName)) { codeGenerator.EmitAutoGlobalLoadAddress(varName); return; } if (codeGenerator.OptimizedLocals) { // Template: for DirectVarUse // ***** // If the specidied variable is of type PhpReference // ldloc loc // ldflda PhpReference.value // ***** // Otherwise // ldloca loc // ***** VariablesTable.Entry entry = codeGenerator.CurrentVariablesTable[varName]; if (entry.IsPhpReference) { // Load variable (of type PhpReference) from IPlace entry.Variable.EmitLoad(il); // ... and get address (ref) of its Value field il.Emit(OpCodes.Ldflda, Fields.PhpReference_Value); } else { // Load address of variable from IPlace entry.Variable.EmitLoadAddress(il); } return; } else { // Template: // object Operators.GetVariableUnchecked(IDictionary table, string name) //returns variable value this.LoadTabledVariableAddress(codeGenerator); } }
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); } }
internal override void EmitStorePrepare(CodeGenerator codeGenerator) { ILEmitter il = codeGenerator.IL; if (varName.IsThisVariableName) { // Error throwing code will be emitted in EmitVariableStoreAssign } else if (codeGenerator.VariableIsAutoGlobal(varName)) { // Check if the variable is auto-global codeGenerator.EmitAutoGlobalStorePrepare(varName); } 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) { entry.Variable.EmitLoad(il); } // Otherwise do nothing // Now load the value, then call EmitVariableStoreAssignOptimized() to store the value ... } else { // Template: // void Operators.SetVariable(table, "x", PhpVariable.Copy(Operators.getValue(table, "x"), CopyReason.Assigned)); codeGenerator.EmitLoadScriptContext(); codeGenerator.EmitLoadRTVariablesTable(); EmitName(codeGenerator); // Now load the value, then call SetVariable() to store the value ... } }
/// <summary> /// Loads and address of a specified variable. /// </summary> internal void LoadLocalAddress(CodeGenerator codeGenerator, VariablesTable.Entry variable, LocalBuilder variableName) { ILEmitter il = codeGenerator.IL; Debug.Assert(variable == null ^ variableName == null); if (variable != null) { if (variable.IsPhpReference) { // LOAD ADDR <variable>.value; variable.Variable.EmitLoad(il); il.Emit(OpCodes.Ldflda, Fields.PhpReference_Value); } else { variable.Variable.EmitLoadAddress(il); } } else { LoadTabledVariableAddress(codeGenerator); } }
internal override void EmitUnset(CodeGenerator codeGenerator) { //Template: "unset(x)" x = null 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; EmitUnsetField(codeGenerator); codeGenerator.ChainBuilder.End(); return; } // 7: $a // Check if the variable is auto-global ILEmitter il = codeGenerator.IL; if (codeGenerator.VariableIsAutoGlobal(varName)) { codeGenerator.EmitAutoGlobalStorePrepare(varName); il.Emit(OpCodes.Ldnull); codeGenerator.EmitAutoGlobalStoreAssign(); return; } // Unset this variable if (codeGenerator.OptimizedLocals) { // Template: // unset(x) x = null // unset(p) p.value = null <- this case isn't valid. When p is reference just create a new PhpReference VariablesTable.Entry entry = codeGenerator.CurrentVariablesTable[varName]; if (entry.IsPhpReference) { il.Emit(OpCodes.Newobj, Constructors.PhpReference_Void); entry.Variable.EmitStore(il); } else { il.Emit(OpCodes.Ldnull); entry.Variable.EmitStore(il); } } else { // CALL Operators.UnsetVariable(<script context>, <local variable table>, <variable name>); codeGenerator.EmitLoadScriptContext(); codeGenerator.EmitLoadRTVariablesTable(); EmitName(codeGenerator); il.Emit(OpCodes.Call, Methods.Operators.UnsetVariable); } }
/// <summary> /// Stores a value on the top of the stack to a specified variable. /// </summary> internal static void StoreLocalAssign(IndirectVarUse node, 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); } }