EmitLoadContext() public method

Emits context onto the evaluation stack.
public EmitLoadContext ( ) : TypeSymbol
return TypeSymbol
Beispiel #1
0
        /// <summary>
        /// Emits load of statics holder.
        /// </summary>
        internal TypeSymbol EmitLoadStatics(CodeGenerator cg)
        {
            var statics = TryGetStatics();

            if (statics != null && statics.GetMembers().OfType<IFieldSymbol>().Any())
            {
                // Template: <ctx>.GetStatics<_statics>()
                cg.EmitLoadContext();
                return cg.EmitCall(ILOpCode.Callvirt, cg.CoreMethods.Context.GetStatic_T.Symbol.Construct(statics))
                    .Expect(statics);
            }

            return null;
        }
Beispiel #2
0
        /// <summary>
        /// Emits load of <c>PhpTypeInfo</c>.
        /// </summary>
        /// <param name="cg">Code generator instance.</param>
        /// <param name="throwOnError">Emits PHP error in case type is not declared.</param>
        /// <remarks>Emits <c>NULL</c> in case type is not declared.</remarks>
        internal void EmitLoadTypeInfo(CodeGenerator cg, bool throwOnError = false)
        {
            Debug.Assert(cg != null);

            Debug.Assert(throwOnError == false, "Not Implemented!");    // TODO: if (throwOnError) { if (DUP == null) PhpException.TypeNotDeclared(<typename>)

            if (this.ResolvedType != null)
            {
                // CALL GetPhpTypeInfo<T>()
                cg.EmitCall(ILOpCode.Call, cg.CoreMethods.Dynamic.GetPhpTypeInfo_T.Symbol.Construct(this.ResolvedType));
            }
            else
            {
                // CALL <ctx>.GetDeclaredType(<typename>)
                cg.EmitLoadContext();
                this.EmitClassName(cg);
                cg.EmitCall(ILOpCode.Call, cg.CoreMethods.Context.GetDeclaredType_string);
            }
        }
Beispiel #3
0
        internal override TypeSymbol Emit(CodeGenerator cg)
        {
            TypeSymbol result;
            var isvoid = this.Access.IsNone;

            Debug.Assert(_arguments.Length == 1);
            Debug.Assert(_arguments[0].Value.Access.IsRead);
            Debug.Assert(Access.IsRead || Access.IsNone);

            var method = this.Target;
            if (method != null) // => IsResolved
            {
                // emit condition for include_once/require_once
                if (IsOnceSemantic)
                {
                    var tscript = method.ContainingType;

                    result = isvoid
                        ? cg.CoreTypes.Void.Symbol
                        : cg.DeclaringCompilation.GetTypeFromTypeRef(cg.Routine.TypeRefContext, this.TypeRefMask);

                    // Template: (<ctx>.CheckIncludeOnce<TScript>()) ? <Main>() : TRUE
                    // Template<isvoid>: if (<ctx>.CheckIncludeOnce<TScript>()) <Main>()
                    var falseLabel = new object();
                    var endLabel = new object();

                    cg.EmitLoadContext();
                    cg.EmitCall(ILOpCode.Callvirt, cg.CoreMethods.Context.CheckIncludeOnce_TScript.Symbol.Construct(tscript));

                    cg.Builder.EmitBranch(ILOpCode.Brfalse, falseLabel);

                    // ? (PhpValue)<Main>(...)
                    cg.EmitCallMain(method);
                    if (isvoid)
                    {
                        cg.EmitPop(method.ReturnType);
                    }
                    else
                    {
                        cg.EmitConvert(method.ReturnType, 0, result);
                    }
                    cg.Builder.EmitBranch(ILOpCode.Br, endLabel);

                    if (!isvoid)
                    {
                        cg.Builder.AdjustStack(-1); // workarounds assert in ILBuilder.MarkLabel, we're doing something wrong with ILBuilder
                    }

                    // : PhpValue.Create(true)
                    cg.Builder.MarkLabel(falseLabel);
                    if (!isvoid)
                    {
                        cg.Builder.EmitBoolConstant(true);
                        cg.EmitConvert(cg.CoreTypes.Boolean, 0, result);
                    }

                    //
                    cg.Builder.MarkLabel(endLabel);
                }
                else
                {
                    // <Main>
                    result = cg.EmitCallMain(method);
                }
            }
            else
            {
                Debug.Assert(cg.LocalsPlaceOpt != null);

                // Template: <ctx>.Include(dir, path, locals, @this, bool once = false, bool throwOnError = false)
                cg.EmitLoadContext();
                cg.Builder.EmitStringConstant(cg.Routine.ContainingFile.DirectoryRelativePath);
                cg.EmitConvert(_arguments[0].Value, cg.CoreTypes.String);
                cg.LocalsPlaceOpt.EmitLoad(cg.Builder); // scope of local variables, corresponds to $GLOBALS in global scope.
                cg.EmitThisOrNull();    // $this
                cg.Builder.EmitBoolConstant(IsOnceSemantic);
                cg.Builder.EmitBoolConstant(IsRequireSemantic);
                return cg.EmitCall(ILOpCode.Callvirt, cg.CoreMethods.Context.Include_string_string_PhpArray_object_bool_bool);
            }

            //
            return result;
        }
Beispiel #4
0
        internal override TypeSymbol Emit(CodeGenerator cg)
        {
            if (TargetMethod != null)
            {
                return EmitDirectCall(cg, ILOpCode.Newobj, TargetMethod);
            }
            else
            {
                if (_typeref.ResolvedType != null)
                {
                    // context.Create<T>(params)
                    var create_t = cg.CoreTypes.Context.Symbol.GetMembers("Create")
                        .OfType<MethodSymbol>()
                        .Where(s => s.Arity == 1 && s.ParameterCount == 1 && s.Parameters[0].IsParams)
                        .Single()
                        .Construct(_typeref.ResolvedType);

                    cg.EmitLoadContext();   // Context
                    cg.Emit_NewArray(cg.CoreTypes.PhpValue, _arguments.Select(a => a.Value).ToArray());  // PhpValue[]

                    return cg.EmitCall(ILOpCode.Call, create_t);
                }
                else
                {
                    // ctx.Create(classname, params)
                    var create = cg.CoreTypes.Context.Symbol.GetMembers("Create")
                        .OfType<MethodSymbol>()
                        .Where(s => s.Arity == 0 && s.ParameterCount == 2 && s.Parameters[0].Type.PrimitiveTypeCode == Microsoft.Cci.PrimitiveTypeCode.String && s.Parameters[1].IsParams && ((ArrayTypeSymbol)s.Parameters[1].Type).ElementType == cg.CoreTypes.PhpValue)
                        .Single();

                    cg.EmitLoadContext();   // Context
                    _typeref.EmitClassName(cg);   // String
                    cg.Emit_NewArray(cg.CoreTypes.PhpValue, _arguments.Select(a => a.Value).ToArray());  // PhpValue[]

                    return cg.EmitCall(ILOpCode.Call, create);
                }
            }
        }
Beispiel #5
0
        internal override TypeSymbol EmitCallsiteCall(CodeGenerator cg)
        {
            if (_name.IsDirect)
            {
                return base.EmitCallsiteCall(cg);
            }
            else
            {
                Debug.Assert(_name.NameExpression != null);

                // faster to emit PhpCallback.Invoke

                // NameExpression.AsCallback().Invoke(Context, PhpValue[])

                cg.EmitConvert(_name.NameExpression, cg.CoreTypes.IPhpCallable);    // (IPhpCallable)Name
                cg.EmitLoadContext();       // Context
                cg.Emit_NewArray(cg.CoreTypes.PhpValue, _arguments.Select(a => a.Value).ToArray()); // PhpValue[]

                return cg.EmitCall(ILOpCode.Callvirt, cg.CoreTypes.IPhpCallable.Symbol.LookupMember<MethodSymbol>("Invoke"));
            }
        }
Beispiel #6
0
        internal virtual TypeSymbol EmitCallsiteCall(CodeGenerator cg)
        {
            // callsite

            var nameOpt = this.CallsiteName;
            var callsite = cg.Factory.StartCallSite("call_" + nameOpt);

            var callsiteargs = new List<TypeSymbol>(_arguments.Length);
            var return_type = this.Access.IsRead
                    ? this.Access.IsReadRef
                        ? cg.CoreTypes.PhpAlias.Symbol
                        : (this.Access.TargetType ?? cg.CoreTypes.PhpValue.Symbol)
                    : cg.CoreTypes.Void.Symbol;

            // callsite
            var fldPlace = callsite.Place;

            // LOAD callsite.Target
            callsite.EmitLoadTarget(cg.Builder);

            // LOAD callsite arguments

            // (callsite, [target], ctx, [name], ...)
            fldPlace.EmitLoad(cg.Builder);

            if (Instance != null)
            {
                callsiteargs.Add(cg.Emit(Instance));   // instance
            }
            else if (TypeNameExpr != null)
            {
                cg.EmitConvert(TypeNameExpr, cg.CoreTypes.String);
                callsiteargs.Add(cg.CoreTypes.String);   // type
            }

            callsiteargs.Add(cg.EmitLoadContext());     // ctx

            if (RoutineNameExpr != null)
            {
                callsiteargs.Add(cg.Emit(RoutineNameExpr));   // name
            }

            foreach (var a in _arguments)
            {
                callsiteargs.Add(cg.Emit(a.Value));
            }

            // Target()
            var functype = cg.Factory.GetCallSiteDelegateType(
                null, RefKind.None,
                callsiteargs.AsImmutable(),
                default(ImmutableArray<RefKind>),
                null,
                return_type);

            cg.EmitCall(ILOpCode.Callvirt, functype.DelegateInvokeMethod);

            // Create CallSite ...
            callsite.Construct(functype, cctor_cg => BuildCallsiteCreate(cctor_cg, return_type));

            //
            return return_type;
        }
Beispiel #7
0
        void EmitInvoke(MethodSymbol invoke, Emit.PEModuleBuilder module)
        {
            if (invoke == null)
            {
                return;
            }

            module.SetMethodBody(invoke, MethodGenerator.GenerateMethodBody(module, invoke, il =>
            {
                var cg = new CodeGenerator(il, module, DiagnosticBag.GetInstance(), OptimizationLevel.Release, false, this, new ParamPlace(invoke.Parameters[0]), new ArgPlace(this, 0));
                //var __invoke = (MethodSymbol)GetMembers(Pchp.Syntax.Name.SpecialMethodNames.Invoke.Value).Single(s => s is MethodSymbol);

                // TODO: call __invoke() directly

                // context.Call<T>(T, TypeMethods.MagicMethods, params PhpValue[])
                var call_t = cg.CoreTypes.Context.Symbol.GetMembers("Call")
                    .OfType<MethodSymbol>()
                    .Where(s => s.Arity == 1 && s.ParameterCount == 3 && s.Parameters[2].IsParams)
                    .Single()
                    .Construct(this);

                // return context.Call<T>(this, __invoke, args)
                cg.EmitLoadContext();
                cg.EmitThis();
                cg.Builder.EmitIntConstant((int)Core.Reflection.TypeMethods.MagicMethods.__invoke);
                cg.Builder.EmitLoadArgumentOpcode(2);
                cg.EmitCall(ILOpCode.Call, call_t);
                cg.EmitRet(invoke.ReturnType);

            }, null, DiagnosticBag.GetInstance(), false));
        }
        /// <summary>
        /// Emits the given conversion. 'from' and 'to' matches the classified conversion.
        /// </summary>
        public static void EmitConversion(this CodeGenerator cg, CommonConversion conversion, TypeSymbol from, TypeSymbol to, TypeSymbol op = null, bool @checked = false)
        {
            // {from}, {op} is loaded on stack

            //

            if (conversion.Exists == false)
            {
                throw cg.NotImplementedException($"Conversion from '{from}' to '{to}' ");
            }

            if (conversion.IsNullable)
            {
                if (from.IsNullableType(out var ttype))
                {
                    if (op != null)
                    {
                        // TODO
                        throw new ArgumentException(nameof(op));
                    }

                    var lbltrue = new NamedLabel("has value");
                    var lblend  = new NamedLabel("end");
                    var tmp     = cg.GetTemporaryLocal(from, true);
                    cg.Builder.EmitLocalStore(tmp);

                    // Template: tmp.HasValue ? convert(tmp.Value) : default
                    cg.Builder.EmitLocalAddress(tmp);
                    cg.EmitCall(ILOpCode.Call, cg.DeclaringCompilation.System_Nullable_T_HasValue(from));
                    cg.Builder.EmitBranch(ILOpCode.Brtrue, lbltrue);

                    // default:
                    cg.EmitLoadDefault(to);
                    cg.Builder.EmitBranch(ILOpCode.Br, lblend);
                    // cg.Builder.AdjustStack(-1); // ?

                    // lbltrue:
                    cg.Builder.MarkLabel(lbltrue);
                    // Template: convert( tmp.GetValueOrDefault() )
                    cg.Builder.EmitLocalAddress(tmp);
                    cg.EmitCall(ILOpCode.Call, cg.DeclaringCompilation.System_Nullable_T_GetValueOrDefault(from)).Expect(ttype);
                    EmitConversion(cg, conversion.WithIsNullable(false), ttype, to, op, @checked);

                    // lblend:
                    cg.Builder.MarkLabel(lblend);

                    return;
                }

                if (to.IsNullableType(out ttype)) // NOTE: not used yet
                {
                    // new Nullable<TType>( convert(from) )
                    EmitConversion(cg, conversion.WithIsNullable(false), from, ttype, op, @checked);
                    cg.EmitCall(ILOpCode.Newobj, ((NamedTypeSymbol)to).InstanceConstructors[0]); // new Nullable<T>( STACK )
                    return;
                }

                throw Roslyn.Utilities.ExceptionUtilities.Unreachable;
            }

            if (conversion.IsIdentity)
            {
                if (op != null)
                {
                    throw new ArgumentException(nameof(op));
                }

                if (to.SpecialType == SpecialType.System_Void)
                {
                    // POP
                    cg.EmitPop(from);
                }

                // nop
            }
            else if (conversion.IsNumeric)
            {
                if (op != null)
                {
                    throw new ArgumentException(nameof(op));
                }

                EmitNumericConversion(cg, from, to, @checked: @checked);
            }
            else if (conversion.IsReference)
            {
                if (op != null)
                {
                    throw new ArgumentException(nameof(op));
                }

                // TODO: ensure from/to is a valid reference type
                cg.EmitCastClass(to);
            }
            else if (conversion.IsUserDefined)
            {
                var method    = (MethodSymbol)conversion.MethodSymbol;
                var ps        = method.Parameters;
                int pconsumed = 0;

                if (method.HasThis)
                {
                    if (from.IsValueType)
                    {
                        if (op != null || from.IsVoid())
                        {
                            throw new ArgumentException(nameof(op));
                        }

                        cg.EmitStructAddr(from);
                    }
                }
                else
                {
                    if (ps[0].RefKind != RefKind.None)
                    {
                        throw new InvalidOperationException();
                    }
                    if (from != ps[0].Type)
                    {
                        if (op != null)
                        {
                            if (!ps[0].Type.IsAssignableFrom(from))
                            {
                                throw new ArgumentException(nameof(op));
                            }
                        }
                        else
                        {
                            EmitImplicitConversion(cg, from, ps[0].Type, @checked: @checked);
                        }
                    }
                    pconsumed++;
                }

                if (op != null)
                {
                    if (ps.Length > pconsumed)
                    {
                        EmitImplicitConversion(cg, op, ps[pconsumed].Type, @checked: @checked);
                    }
                    pconsumed++;
                }

                // Context ctx,
                if (ps.Length > pconsumed && SpecialParameterSymbol.IsContextParameter(ps[pconsumed]))
                {
                    cg.EmitLoadContext();
                    pconsumed++;
                }

                if (ps.Length != pconsumed)
                {
                    throw new InvalidOperationException();
                }

                EmitImplicitConversion(cg, cg.EmitCall(method.IsVirtual ? ILOpCode.Callvirt : ILOpCode.Call, method), to, @checked: true);
            }
            else
            {
                throw new NotImplementedException();
            }
        }
        /// <summary>
        /// Emits the given conversion. 'from' and 'to' matches the classified conversion.
        /// </summary>
        public static void EmitConversion(this CodeGenerator cg, CommonConversion conversion, TypeSymbol from, TypeSymbol to, TypeSymbol op = null, bool @checked = false)
        {
            // {from}, {op} is loaded on stack

            //

            if (conversion.Exists == false)
            {
                throw cg.NotImplementedException($"Conversion from '{from}' to '{to}' ");
            }

            if (conversion.IsIdentity)
            {
                if (op != null)
                {
                    throw new ArgumentException(nameof(op));
                }

                if (to.SpecialType == SpecialType.System_Void)
                {
                    // POP
                    cg.EmitPop(from);
                }

                // nop
            }
            else if (conversion.IsNumeric)
            {
                if (op != null)
                {
                    throw new ArgumentException(nameof(op));
                }

                EmitNumericConversion(cg, from, to, @checked: @checked);
            }
            else if (conversion.IsReference)
            {
                if (op != null)
                {
                    throw new ArgumentException(nameof(op));
                }

                // TODO: ensure from/to is a valid reference type
                cg.EmitCastClass(to);
            }
            else if (conversion.IsUserDefined)
            {
                var method    = (MethodSymbol)conversion.MethodSymbol;
                var ps        = method.Parameters;
                int pconsumed = 0;

                if (method.HasThis)
                {
                    if (from.IsValueType)
                    {
                        if (op != null)
                        {
                            throw new ArgumentException(nameof(op));
                        }

                        cg.EmitStructAddr(from);
                    }
                }
                else
                {
                    if (ps[0].RefKind != RefKind.None)
                    {
                        throw new InvalidOperationException();
                    }
                    if (from != ps[0].Type)
                    {
                        if (op != null)
                        {
                            if (!ps[0].Type.IsAssignableFrom(from))
                            {
                                throw new ArgumentException(nameof(op));
                            }
                        }
                        else
                        {
                            EmitImplicitConversion(cg, from, ps[0].Type, @checked: @checked);
                        }
                    }
                    pconsumed++;
                }

                if (op != null)
                {
                    if (ps.Length > pconsumed)
                    {
                        EmitImplicitConversion(cg, op, ps[pconsumed].Type, @checked: @checked);
                    }
                    pconsumed++;
                }

                // Context ctx,
                if (ps.Length > pconsumed && SpecialParameterSymbol.IsContextParameter(ps[pconsumed]))
                {
                    cg.EmitLoadContext();
                    pconsumed++;
                }

                if (ps.Length != pconsumed)
                {
                    throw new InvalidOperationException();
                }

                EmitImplicitConversion(cg, cg.EmitCall(method.IsVirtual ? ILOpCode.Callvirt : ILOpCode.Call, method), to, @checked: true);
            }
            else
            {
                throw new NotImplementedException();
            }
        }
Beispiel #10
0
 public void EmitStorePrepare(CodeGenerator cg, InstanceCacheHolder instanceOpt = null)
 {
     // Context
     cg.EmitLoadContext();
 }
Beispiel #11
0
 public TypeSymbol EmitLoad(CodeGenerator cg)
 {
     cg.EmitLoadContext();
     return cg.EmitCall(ILOpCode.Call, ResolveSuperglobalProperty(cg).GetMethod);
 }
Beispiel #12
0
        public TypeSymbol EmitLoad(CodeGenerator cg)
        {
            Debug.Assert(Access.IsRead);

            var type = Field.Type;

            // Ensure Object (..->Field->.. =)
            if (Access.EnsureObject)
            {
                if (type == cg.CoreTypes.PhpAlias)
                {
                    EmitOpCode_Load(cg);    // PhpAlias
                    return cg.EmitCall(ILOpCode.Call, cg.CoreMethods.PhpAlias.EnsureObject)
                        .Expect(SpecialType.System_Object);
                }
                else if (type == cg.CoreTypes.PhpValue)
                {
                    EmitOpCode_LoadAddress(cg); // &PhpValue
                    return cg.EmitCall(ILOpCode.Call, cg.CoreMethods.PhpValue.EnsureObject)
                        .Expect(SpecialType.System_Object);
                }
                else
                {
                    if (type.IsReferenceType)
                    {
                        // TODO: ensure it is not null
                        EmitOpCode_Load(cg);
                        return type;
                    }
                    else
                    {
                        // return new stdClass(ctx)
                        throw new NotImplementedException();
                    }
                }
            }
            // Ensure Array (xxx->Field[] =)
            else if (Access.EnsureArray)
            {
                if (type == cg.CoreTypes.PhpAlias)
                {
                    EmitOpCode_Load(cg);
                    return cg.EmitCall(ILOpCode.Call, cg.CoreMethods.PhpAlias.EnsureArray)
                        .Expect(cg.CoreTypes.IPhpArray);
                }
                else if (type == cg.CoreTypes.PhpValue)
                {
                    EmitOpCode_LoadAddress(cg);
                    return cg.EmitCall(ILOpCode.Call, cg.CoreMethods.PhpValue.EnsureArray)
                            .Expect(cg.CoreTypes.IPhpArray);
                }
                else if (type.IsOfType(cg.CoreTypes.IPhpArray))
                {
                    EmitOpCode_LoadAddress(cg); // ensure value is not null
                    if (type == cg.CoreTypes.PhpArray)
                    {
                        return cg.EmitCall(ILOpCode.Call, cg.CoreMethods.Operators.EnsureArray_PhpArrayRef)
                           .Expect(cg.CoreTypes.PhpArray);
                    }
                    else
                    {
                        return cg.EmitCall(ILOpCode.Call, cg.CoreMethods.Operators.EnsureArray_IPhpArrayRef)
                            .Expect(cg.CoreTypes.IPhpArray);
                    }
                }

                throw new NotImplementedException();
            }
            // Ensure Alias (&...->Field)
            else if (Access.IsReadRef)
            {
                if (type == cg.CoreTypes.PhpAlias)
                {
                    // TODO: <place>.AddRef()
                    EmitOpCode_Load(cg);
                    return type;
                }
                else if (type == cg.CoreTypes.PhpValue)
                {
                    // return <place>.EnsureAlias()
                    EmitOpCode_LoadAddress(cg); // &PhpValue
                    return cg.EmitCall(ILOpCode.Call, cg.CoreMethods.PhpValue.EnsureAlias)
                        .Expect(cg.CoreTypes.PhpAlias);
                }
                else
                {
                    Debug.Assert(false, "value cannot be aliased");

                    // new PhpAlias((PhpValue)<place>, 1)
                    EmitOpCode_Load(cg);
                    cg.EmitConvertToPhpValue(type, 0);
                    return cg.Emit_PhpValue_MakeAlias();
                }
            }
            // Read (...->Field) & Dereference eventually
            else
            {
                if (type == cg.CoreTypes.PhpAlias)
                {
                    EmitOpCode_Load(cg);

                    if (Access.TargetType != null)
                    {
                        // convert PhpValue to target type without loading whole value and storing to temporary variable
                        switch (Access.TargetType.SpecialType)
                        {
                            default:
                                if (Access.TargetType == cg.CoreTypes.PhpArray)
                                {
                                    // <PhpAlias>.Value.ToArray()
                                    cg.Builder.EmitOpCode(ILOpCode.Ldflda);
                                    cg.EmitSymbolToken(cg.CoreMethods.PhpAlias.Value, null);
                                    return cg.EmitCall(ILOpCode.Call, cg.CoreMethods.PhpValue.ToArray);
                                }
                                break;
                        }
                    }

                    return cg.Emit_PhpAlias_GetValue();
                }
                else if (type == cg.CoreTypes.PhpValue)
                {
                    if (Access.TargetType != null)
                    {
                        // convert PhpValue to target type without loading whole value and storing to temporary variable
                        switch (Access.TargetType.SpecialType)
                        {
                            case SpecialType.System_Double:
                                EmitOpCode_LoadAddress(cg); // &PhpValue.ToDouble()
                                return cg.EmitCall(ILOpCode.Call, cg.CoreMethods.PhpValue.ToDouble);
                            case SpecialType.System_Int64:
                                EmitOpCode_LoadAddress(cg); // &PhpValue.ToLong()
                                return cg.EmitCall(ILOpCode.Call, cg.CoreMethods.PhpValue.ToLong);
                            case SpecialType.System_Boolean:
                                EmitOpCode_LoadAddress(cg); // &PhpValue.ToBoolean()
                                return cg.EmitCall(ILOpCode.Call, cg.CoreMethods.PhpValue.ToBoolean);
                            case SpecialType.System_String:
                                EmitOpCode_LoadAddress(cg); // &PhpValue.ToString(ctx)
                                cg.EmitLoadContext();
                                return cg.EmitCall(ILOpCode.Call, cg.CoreMethods.PhpValue.ToString_Context);
                            case SpecialType.System_Object:
                                EmitOpCode_LoadAddress(cg); // &PhpValue.ToClass()
                                return cg.EmitCall(ILOpCode.Call, cg.CoreMethods.PhpValue.ToClass);
                            default:
                                if (Access.TargetType == cg.CoreTypes.PhpArray)
                                {
                                    EmitOpCode_LoadAddress(cg); // &PhpValue.ToArray()
                                    return cg.EmitCall(ILOpCode.Call, cg.CoreMethods.PhpValue.ToArray);
                                }
                                break;
                        }
                    }

                    // TODO: dereference if applicable (=> PhpValue.Alias.Value)
                    EmitOpCode_Load(cg);
                    return type;
                }
                else
                {
                    EmitOpCode_Load(cg);
                    return type;
                }
            }
        }
Beispiel #13
0
 protected override TypeSymbol LoadVariablesArray(CodeGenerator cg)
 {
     if (cg.IsGlobalScope)
     {
         // <locals>
         Debug.Assert(cg.LocalsPlaceOpt != null);
         return cg.LocalsPlaceOpt.EmitLoad(cg.Builder)
             .Expect(cg.CoreTypes.PhpArray);
     }
     else
     {
         // $GLOBALS
         cg.EmitLoadContext();
         return cg.EmitCall(ILOpCode.Call, cg.CoreMethods.Context.Globals.Getter);   // <ctx>.Globals
     }
 }
Beispiel #14
0
        internal override void Emit(CodeGenerator cg)
        {
            cg.EmitSequencePoint(this.PhpSyntax);

            foreach (var v in _variables)
            {
                var getmethod = cg.CoreMethods.Context.GetStatic_T.Symbol.Construct(v._holder);
                var place = v._holderPlace;

                // Template: x = ctx.GetStatic<holder_x>()
                place.EmitStorePrepare(cg.Builder);

                cg.EmitLoadContext();
                cg.EmitCall(ILOpCode.Callvirt, getmethod);

                place.EmitStore(cg.Builder);

                // holder initialization routine
                EmitInit(cg.Module, cg.Diagnostics, cg.DeclaringCompilation, v._holder, (BoundExpression)v.InitialValue);

            }
        }
Beispiel #15
0
        internal override TypeSymbol Emit(CodeGenerator cg)
        {
            switch (this.Type)
            {
                case PseudoConstUse.Types.File:

                    // <ctx>.FilePath<TScript>()
                    cg.EmitLoadContext();
                    return cg.EmitCall(ILOpCode.Callvirt, cg.CoreMethods.Context.ScriptPath_TScript.Symbol.Construct(cg.Routine.ContainingFile))
                        .Expect(SpecialType.System_String);

                default:

                    // the other pseudoconstants should be resolved by flow analysis
                    throw ExceptionUtilities.Unreachable;
            }
        }
Beispiel #16
0
        void EmitPhpNew(SynthesizedPhpNewMethodSymbol phpnew, Emit.PEModuleBuilder module)
        {
            if (phpnew == null) return; // static class

            module.SetMethodBody(phpnew, MethodGenerator.GenerateMethodBody(module, phpnew, (Action<Microsoft.CodeAnalysis.CodeGen.ILBuilder>)(il =>
            {
                Debug.Assert(SpecialParameterSymbol.IsContextParameter(phpnew.Parameters[0]));

                var cg = new CodeGenerator(il, module, DiagnosticBag.GetInstance(), OptimizationLevel.Release, false, this, new ParamPlace(phpnew.Parameters[0]), new ArgPlace(this, 0));

                // initialize <ctx> field,
                // if field is declared within this type
                var ctxField = this.ContextStore;
                if (ctxField != null && object.ReferenceEquals((object)ctxField.ContainingType, this))
                {
                    var ctxFieldPlace = new FieldPlace(cg.ThisPlaceOpt, (IFieldSymbol)ctxField);

                    // Debug.Assert(<ctx> != null)
                    cg.EmitDebugAssertNotNull(cg.ContextPlaceOpt, "Context cannot be null.");

                    // <this>.<ctx> = <ctx>
                    ctxFieldPlace.EmitStorePrepare(il);
                    cg.EmitLoadContext();
                    ctxFieldPlace.EmitStore(il);
                }

                // initialize class fields
                foreach (var fld in this.GetFieldsToEmit().OfType<SourceFieldSymbol>().Where(fld => !fld.RequiresHolder && !fld.IsStatic && !fld.IsConst))
                {
                    fld.EmitInit(cg);
                }

                // base..phpnew ?? base..ctor
                var basenew = phpnew.BasePhpNew;
                Debug.Assert(basenew != null);
                cg.EmitPop(cg.EmitThisCall(basenew, phpnew));

                Debug.Assert(phpnew.ReturnsVoid);
                cg.EmitRet(phpnew.ReturnType);

            }), null, DiagnosticBag.GetInstance(), false));
        }
Beispiel #17
0
        internal override TypeSymbol Emit(CodeGenerator cg)
        {
            Debug.Assert(!Access.IsWrite);

            if (this.Access.IsNone)
            {
                return cg.CoreTypes.Void;
            }

            if (this.ConstantValue.HasValue)
            {
                return cg.EmitLoadConstant(this.ConstantValue.Value, this.Access.TargetType);
            }

            if (_boundExpressionOpt != null)
            {
                _boundExpressionOpt.EmitLoadPrepare(cg);
                return _boundExpressionOpt.EmitLoad(cg);
            }

            var idxfield = cg.Module.SynthesizedManager
                .GetOrCreateSynthesizedField(cg.Module.ScriptType, cg.CoreTypes.Int32, $"c<{this.Name}>idx", Accessibility.Internal, true, false);

            // <ctx>.GetConstant(<name>, ref <Index of constant>)
            cg.EmitLoadContext();
            cg.Builder.EmitStringConstant(this.Name);
            cg.EmitFieldAddress(idxfield);
            return cg.EmitCall(ILOpCode.Callvirt, cg.CoreMethods.Context.GetConstant_string_int32)
                .Expect(cg.CoreTypes.PhpValue);
        }
Beispiel #18
0
        internal override void Emit(CodeGenerator cg)
        {
            // first brace sequence point
            var body = cg.Routine.Syntax.BodySpanOrInvalid();
            if (body.IsValid && cg.IsDebug)
            {
                cg.EmitSequencePoint(new Span(body.Start, 1));
                cg.EmitOpCode(ILOpCode.Nop);
            }
            else
            {
                cg.Builder.DefineInitialHiddenSequencePoint();
            }

            //
            if (cg.IsDebug)
            {
                if (cg.Routine.IsStatic)
                {
                    // Debug.Assert(<context> != null);
                    cg.EmitDebugAssertNotNull(cg.ContextPlaceOpt, "Context cannot be null.");
                }

                // TODO: emit parameters checks
            }

            //
            var locals = cg.Routine.LocalsTable;

            // in case of script, declare the script, functions and types
            if (cg.Routine is Symbols.SourceGlobalMethodSymbol)
            {
                // <ctx>.OnInclude<TScript>()
                cg.EmitLoadContext();
                cg.EmitCall(ILOpCode.Callvirt, cg.CoreMethods.Context.OnInclude_TScript.Symbol.Construct(cg.Routine.ContainingType));

                // <ctx>.DeclareFunction()
                cg.Routine.ContainingFile.Functions
                    .Where(f => !f.IsConditional)
                    .ForEach(cg.EmitDeclareFunction);
                // <ctx>.DeclareType()
                cg.DeclaringCompilation.SourceSymbolTables.GetTypes()
                    .OfType<Symbols.SourceTypeSymbol>()
                    .Where(t => !t.Syntax.IsConditional && t.ContainingFile == cg.Routine.ContainingFile)   // non conditional declaration within this file
                    .ForEach(cg.EmitDeclareType);
            }
            else
            {
                if (cg.HasUnoptimizedLocals)
                {
                    // <locals> = new PhpArray(HINTCOUNT)
                    cg.LocalsPlaceOpt.EmitStorePrepare(cg.Builder);
                    cg.Builder.EmitIntConstant(locals.Count);    // HINTCOUNT
                    cg.EmitCall(ILOpCode.Newobj, cg.CoreMethods.Ctors.PhpArray_int);
                    cg.LocalsPlaceOpt.EmitStore(cg.Builder);
                }
            }

            // variables/parameters initialization
            foreach (var loc in locals.Variables)
            {
                loc.EmitInit(cg);
            }

            //
            base.Emit(cg);
        }