/// <include file='Doc/Nodes.xml' path='doc/method[@name="Emit"]/*'/> internal override PhpTypeCode Emit(CodeGenerator/*!*/ codeGenerator) { PhpTypeCode result; // emits inclusion and Main() call: result = EmitDynamicInclusion(codeGenerator); // return value conversion: codeGenerator.EmitReturnValueHandling(this, false, ref result); return result; }
/// <include file='Doc/Nodes.xml' path='doc/method[@name="Emit"]/*'/> internal override PhpTypeCode Emit(CodeGenerator codeGenerator) { Debug.Assert(access == AccessType.Read || access == AccessType.ReadRef || access == AccessType.ReadUnknown || access == AccessType.None); Statistics.AST.AddNode("FunctionCall.Indirect"); PhpTypeCode result; result = codeGenerator.EmitRoutineOperatorCall(null, isMemberOf, null, null, nameExpr, callSignature, access); //EmitReturnValueCopy(codeGenerator.IL, result); // (J) already emitted by EmitRoutineOperatorCall codeGenerator.EmitReturnValueHandling(this, codeGenerator.ChainBuilder.LoadAddressOfFunctionReturnValue, ref result); return result; }
/// <include file='Doc/Nodes.xml' path='doc/method[@name="Emit"]/*'/> internal override PhpTypeCode Emit(CodeGenerator/*!*/ codeGenerator) { Debug.Assert(access == AccessType.Read || access == AccessType.ReadRef || access == AccessType.ReadUnknown || access == AccessType.None, "Invalid access type in FunctionCall"); Statistics.AST.AddNode("FunctionCall.Direct"); PhpTypeCode result; if (inlined != InlinedFunction.None) { result = EmitInlinedFunctionCall(codeGenerator); } else { if (alreadyEmittedPlace != null) { // continuation of HandleLongChain, // this DirectFcnCall was already emitted // and the result was stored into local variable. codeGenerator.IL.Emit(OpCodes.Ldloc, alreadyEmittedPlace); result = PhpTypeCodeEnum.FromType(alreadyEmittedPlace.LocalType); } else // this node actually represents a method call: if (isMemberOf != null) { // to avoid StackOverflowException due to long isMemberOf chain, // we will avoid recursion, and divide the chain into smaller pieces. HandleLongChain(codeGenerator); if (routine == null) { //result = codeGenerator.EmitRoutineOperatorCall(null, isMemberOf, qualifiedName.ToString(), null, null, callSignature, access); result = codeGenerator.CallSitesBuilder.EmitMethodCall( codeGenerator, Compiler.CodeGenerator.CallSitesBuilder.AccessToReturnType(access), isMemberOf, null, qualifiedName.ToString(), null, callSignature); } else result = routine.EmitCall( codeGenerator, null, callSignature, new ExpressionPlace(codeGenerator, isMemberOf), false, overloadIndex, null/*TODO when CFG*/, position, access, true); } else { // the node represents a function call: result = routine.EmitCall( codeGenerator, fallbackFunctionName, callSignature, null, false, overloadIndex, null, position, access, false); } } // (J) Emit Copy if necessary: // routine == null => Copy emitted by EmitRoutineOperatorCall // routine.ReturnValueDeepCopyEmitted => Copy emitted // otherwise emit Copy if we are going to read it by value if (routine != null && !routine.ReturnValueDeepCopyEmitted) EmitReturnValueCopy(codeGenerator.IL, result); // handles return value: codeGenerator.EmitReturnValueHandling(this, codeGenerator.ChainBuilder.LoadAddressOfFunctionReturnValue, ref result); return result; }
/// <include file='Doc/Nodes.xml' path='doc/method[@name="Emit"]/*'/> internal override PhpTypeCode Emit(CodeGenerator/*!*/ codeGenerator) { Statistics.AST.AddNode("StaticMethodCall.Indirect"); PhpTypeCode result = codeGenerator.EmitRoutineOperatorCall(type, null, null, null, methodNameVar, callSignature, access); //EmitReturnValueCopy(codeGenerator.IL, result); // (J) already emitted by EmitRoutineOperatorCall // handles return value: codeGenerator.EmitReturnValueHandling(this, codeGenerator.ChainBuilder.LoadAddressOfFunctionReturnValue, ref result); return result; }
/// <include file='Doc/Nodes.xml' path='doc/method[@name="Emit"]/*'/> internal override PhpTypeCode Emit(CodeGenerator/*!*/ codeGenerator) { Statistics.AST.AddNode("StaticMethodCall.Direct"); IPlace instance = null; // PHP allows for static invocations of instance method if (!method.IsUnknown && !method.IsStatic) { // if we are in an instance method and the $this for the callee is assignable from // current $this, then invoke the method directly with current $this if (codeGenerator.LocationStack.LocationType == LocationTypes.MethodDecl) { CompilerLocationStack.MethodDeclContext method_context = codeGenerator.LocationStack.PeekMethodDecl(); if (!method_context.Method.IsStatic && method.DeclaringType.IsAssignableFrom(method_context.Type)) { instance = IndexedPlace.ThisArg; } } } // class context is unknown or the class is m-decl or completely unknown at compile-time -> call the operator PhpTypeCode result = method.EmitCall(codeGenerator, null, callSignature, instance, runtimeVisibilityCheck, overloadIndex, type, position, access, false/* TODO: __call must be called virtually */); if (/*method == null || */!method.ReturnValueDeepCopyEmitted) // (J) Emit Copy only if method is known (=> known PhpRoutine do not emit Copy on return value) EmitReturnValueCopy(codeGenerator.IL, result); // only if we are going to read the resulting value // handles return value: codeGenerator.EmitReturnValueHandling(this, codeGenerator.ChainBuilder.LoadAddressOfFunctionReturnValue, ref result); return result; }
internal override PhpTypeCode Emit(CodeGenerator/*!*/ codeGenerator) { Statistics.AST.AddNode("NewEx"); PhpTypeCode result; if (classNameRef.ResolvedType != null && typeArgsResolved) { // constructor is resolvable (doesn't mean that known) // result = classNameRef.ResolvedType.EmitNew(codeGenerator, null, constructor, callSignature, runtimeVisibilityCheck); } else { // constructor is unresolvable (a variable is used in type name => type is unresolvable as well) // codeGenerator.EmitNewOperator(null, classNameRef, null, callSignature); result = PhpTypeCode.Object; } codeGenerator.EmitReturnValueHandling(this, false, ref result); return result; }
/// <include file='Doc/Nodes.xml' path='doc/method[@name="Emit"]/*'/> internal override PhpTypeCode Emit(CodeGenerator/*!*/ codeGenerator) { // not emitted in release mode: Debug.Assert(kind != EvalKinds.LambdaFunction, "Invalid eval kind."); Debug.Assert(kind != EvalKinds.Assert || codeGenerator.Context.Config.Compiler.Debug, "Assert should be cut off in release mode."); Debug.Assert(access == AccessType.None || access == AccessType.Read || access == AccessType.ReadRef); Debug.Assert(inlinedCode != null || codeGenerator.RTVariablesTablePlace != null, "Function should have variables table."); Statistics.AST.AddNode("EvalEx"); ILEmitter il = codeGenerator.IL; PhpTypeCode result; if (inlinedCode != null) { Debug.Assert(kind == EvalKinds.Assert, "Only assert can be inlined so far."); Label endif_label = il.DefineLabel(); Label else_label = il.DefineLabel(); // IF DynamicCode.PreAssert(context) THEN codeGenerator.EmitLoadScriptContext(); il.Emit(OpCodes.Call, Methods.DynamicCode.PreAssert); il.Emit(OpCodes.Brfalse, else_label); if (true) { // LOAD <evaluated assertion>; codeGenerator.EmitBoxing(((Expression)code).Emit(codeGenerator)); // CALL DynamicCode.PostAssert(context); codeGenerator.EmitLoadScriptContext(); il.Emit(OpCodes.Call, Methods.DynamicCode.PostAssert); // LOAD bool CheckAssertion(STACK, <inlined code>, context, <source path>, line, column); il.Emit(OpCodes.Ldstr, inlinedCode); codeGenerator.EmitLoadScriptContext(); il.Emit(OpCodes.Ldstr, codeGenerator.SourceUnit.SourceFile.RelativePath.ToString()); il.LdcI4(this.position.FirstLine); il.LdcI4(this.position.FirstColumn); codeGenerator.EmitLoadNamingContext(); il.Emit(OpCodes.Call, Methods.DynamicCode.CheckAssertion); // GOTO END IF; il.Emit(OpCodes.Br, endif_label); } // ELSE il.MarkLabel(else_label); if (true) { // LOAD true; il.Emit(OpCodes.Ldc_I4_1); } // END IF; il.MarkLabel(endif_label); result = PhpTypeCode.Object; } else { result = codeGenerator.EmitEval(kind, code, position, currentNamespace, aliases); } // handles return value according to the access type: codeGenerator.EmitReturnValueHandling(this, false, ref result); return result; }