internal override void EmitLoadAddress_StoreBack(CodeGenerator codeGenerator, bool duplicate_value) { ILEmitter il = codeGenerator.IL; // Skip $this->a if (varName.IsThisVariableName) // Take no action return; if (codeGenerator.VariableIsAutoGlobal(varName)) { // Take no action return; } if (codeGenerator.OptimizedLocals) { // Take no action return; } this.StoreTabledVariableBack(codeGenerator, duplicate_value); }
/// <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); } }
/// <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 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 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); } }
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); } }
internal override void EmitStoreRefPrepare(CodeGenerator codeGenerator) { ILEmitter il = codeGenerator.IL; if (varName.IsThisVariableName) { // error throwing code will be emitted in EmitVariableStoreRefAssign } else if (codeGenerator.VariableIsAutoGlobal(varName)) { // Check if the variable is auto-global codeGenerator.EmitAutoGlobalStoreRefPrepare(varName); } else if (codeGenerator.OptimizedLocals) { // Template: // WRITE ref ($x,value); // DO NOTHING !!!! // now load the value then store to local variable } else { // Template: // WRITE ref ($x,value); // by Martin // // ldarg.1 // ldstr "name" // LOAD value // call instance IDictionary.set_Item(object) codeGenerator.EmitLoadScriptContext(); codeGenerator.EmitLoadRTVariablesTable(); EmitName(codeGenerator); // now load value, then call EmitVariableStoreRefAssignGlobalContext() to emit stfld ... } }
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 ... } }