internal override void EmitInit(CodeGenerator cg) { var srcparam = _symbol as SourceParameterSymbol; if (srcparam == null) { // an implicit parameter return; } // TODO: check callable, iterable // TODO: ? if (cg.HasUnoptimizedLocals && $this) <locals>["this"] = ... var srcplace = new ParamPlace(_symbol); var routine = srcparam.Routine; if (cg.HasUnoptimizedLocals) { Debug.Assert(cg.LocalsPlaceOpt != null); // copy parameter to <locals>[Name] // <locals>[name] = value cg.LocalsPlaceOpt.EmitLoad(cg.Builder); // <locals> cg.EmitIntStringKey(new BoundLiteral(this.Name)); // [key] if (srcparam.Syntax.PassedByRef) { var srcpt = srcplace.EmitLoad(cg.Builder); // PhpAlias Debug.Assert(srcpt == cg.CoreTypes.PhpAlias); cg.EmitConvert(srcpt, 0, cg.CoreTypes.PhpAlias); cg.EmitCall(ILOpCode.Call, cg.CoreMethods.PhpArray.SetItemAlias_IntStringKey_PhpAlias); } else { if (_symbol.IsParams) { // (PhhpValue)new PhpArray( params ) cg.EmitConvertToPhpValue(cg.ArrayToPhpArray(srcplace, true), 0); } else { if (_symbol.Type == cg.CoreTypes.PhpValue) { // <param>.GetValue() srcplace.EmitLoadAddress(cg.Builder); cg.EmitCall(ILOpCode.Call, cg.CoreMethods.PhpValue.GetValue); } else { // (PhpValue)<param> cg.EmitConvertToPhpValue(srcplace.EmitLoad(cg.Builder), 0); // PhpValue } // copy <value> if (cg.IsCopiable(_symbol.Type)) { cg.EmitDeepCopy(cg.CoreTypes.PhpValue); } } cg.EmitCall(ILOpCode.Call, cg.CoreMethods.PhpArray.Add_IntStringKey_PhpValue); } // _isUnoptimized = true; } else { // create local variable in case of parameter type is not enough for its use within routine if (_symbol.Type != cg.CoreTypes.PhpValue && _symbol.Type != cg.CoreTypes.PhpAlias) { var tmask = routine.ControlFlowGraph.GetLocalTypeMask(srcparam.Name); var clrtype = cg.DeclaringCompilation.GetTypeFromTypeRef(routine, tmask); if (clrtype != _symbol.Type) // Assert: only if clrtype is not covered by _symbol.Type { // TODO: performance warning _lazyLocal = new BoundLocal(new SynthesizedLocalSymbol(routine, srcparam.Name, clrtype)); _lazyLocal.EmitInit(cg); var localplace = _lazyLocal.Place(cg.Builder); localplace.EmitStorePrepare(cg.Builder); if (_symbol.IsParams) { Debug.Assert(_symbol.Type.IsSZArray()); Debug.Assert(clrtype == cg.CoreTypes.PhpArray); // <local> = new PhpArray(){ ... } cg.ArrayToPhpArray(srcplace, true); } else { // <local> = <param> cg.EmitConvert(srcplace.EmitLoad(cg.Builder), 0, clrtype); } localplace.EmitStore(cg.Builder); } } else { if (_symbol.Type == cg.CoreTypes.PhpValue) { srcplace.EmitStorePrepare(cg.Builder); // dereference & copy // <param> = <param>.GetValue().DeepCopy() srcplace.EmitLoadAddress(cg.Builder); cg.EmitDeepCopy(cg.EmitCall(ILOpCode.Call, cg.CoreMethods.PhpValue.GetValue)); srcplace.EmitStore(cg.Builder); } else if (cg.IsCopiable(_symbol.Type)) { srcplace.EmitStorePrepare(cg.Builder); // copy // <param> = DeepCopy(<param>) cg.EmitDeepCopy(srcplace.EmitLoad(cg.Builder)); srcplace.EmitStore(cg.Builder); } } } }
internal override void EmitInit(CodeGenerator cg) { // TODO: check callable, iterable // TODO: ? if (cg.HasUnoptimizedLocals && $this) <locals>["this"] = ... var srcparam = _symbol as SourceParameterSymbol; if (srcparam != null) { var srcplace = new ParamPlace(_symbol); var routine = srcparam.Routine; if (cg.HasUnoptimizedLocals) { Debug.Assert(cg.LocalsPlaceOpt != null); // copy parameter to <locals>[Name] // <locals>[name] = value cg.LocalsPlaceOpt.EmitLoad(cg.Builder); // <locals> cg.EmitIntStringKey(new BoundLiteral(this.Name)); // [key] cg.EmitConvertToPhpValue(srcplace.EmitLoad(cg.Builder), 0); // value cg.EmitCall(ILOpCode.Call, cg.CoreMethods.PhpArray.SetItemValue_IntStringKey_PhpValue); // _isUnoptimized = true; } else { // TODO: copy parameter by value in case of PhpValue, Array, PhpString // create local variable in case of parameter type is not enough for its use within routine if (_symbol.Type != cg.CoreTypes.PhpValue && _symbol.Type != cg.CoreTypes.PhpAlias) { var tmask = routine.ControlFlowGraph.GetLocalTypeMask(srcparam.Name); var clrtype = cg.DeclaringCompilation.GetTypeFromTypeRef(routine, tmask); if (clrtype != _symbol.Type) // Assert: only if clrtype is not covered by _symbol.Type { // TODO: performance warning _lazyLocal = new BoundLocal(new SynthesizedLocalSymbol(routine, srcparam.Name, clrtype)); _lazyLocal.EmitInit(cg); var localplace = _lazyLocal.Place(cg.Builder); // <local> = <param> localplace.EmitStorePrepare(cg.Builder); cg.EmitConvert(srcplace.EmitLoad(cg.Builder), 0, clrtype); localplace.EmitStore(cg.Builder); } } } } }