EmitSequencePoint() private method

private EmitSequencePoint ( LangElement element ) : void
element LangElement
return void
コード例 #1
0
ファイル: BoundEdge.cs プロジェクト: iolevel/peachpie
        internal override void Generate(CodeGenerator cg)
        {
            Contract.ThrowIfNull(Condition);

            if (IsLoop) // perf
            {
                cg.Builder.EmitBranch(ILOpCode.Br, this.Condition);

                // {
                cg.GenerateScope(TrueTarget, NextBlock.Ordinal);
                // }

                // if (Condition)
                cg.EmitSequencePoint(this.Condition.PhpSyntax);
                cg.Builder.MarkLabel(this.Condition);
                cg.EmitConvert(this.Condition, cg.CoreTypes.Boolean);
                cg.Builder.EmitBranch(ILOpCode.Brtrue, TrueTarget);
            }
            else
            {
                // if (Condition)
                cg.EmitSequencePoint(this.Condition.PhpSyntax);
                cg.EmitConvert(this.Condition, cg.CoreTypes.Boolean);
                cg.Builder.EmitBranch(ILOpCode.Brfalse, FalseTarget);

                // {
                cg.GenerateScope(TrueTarget, NextBlock.Ordinal);
                // }
            }

            cg.Scope.ContinueWith(FalseTarget);
        }
コード例 #2
0
ファイル: BoundEdge.cs プロジェクト: iolevel/peachpie
 internal override void Generate(CodeGenerator cg)
 {
     if (cg.IsDebug && this.PhpSyntax != null)
     {
         cg.EmitSequencePoint(this.PhpSyntax);
         cg.Builder.EmitOpCode(ILOpCode.Nop);
     }
     cg.Scope.ContinueWith(NextBlock);
 }
コード例 #3
0
ファイル: BoundStatement.cs プロジェクト: iolevel/peachpie
        internal override void Emit(CodeGenerator cg)
        {
            cg.EmitSequencePoint(this.PhpSyntax);

            var rtype = cg.Routine.ReturnType;
            var rvoid = rtype.SpecialType == SpecialType.System_Void;

            //
            if (this.Returned == null)
            {
                if (rvoid)
                {
                    // <void>
                }
                else
                {
                    // <default>
                    cg.EmitLoadDefault(rtype, cg.Routine.ResultTypeMask);
                }
            }
            else
            {
                if (rvoid)
                {
                    // <expr>;
                    cg.EmitPop(this.Returned.Emit(cg));
                }
                else
                {
                    // return (T)<expr>;
                    cg.EmitConvert(this.Returned, rtype);
                }
            }

            // .ret
            cg.EmitRet(rtype);
        }
コード例 #4
0
ファイル: BoundEdge.cs プロジェクト: iolevel/peachpie
        internal override void Generate(CodeGenerator cg)
        {
            // four cases:
            // 1. just single or none case label that can be replaced with single IF
            // 2. switch over integers, using native CIL switch
            // 3. switch over strings, using C# static Dictionary and CIL switch
            // 4. PHP style switch which is just a bunch of IFs

            if (this.CaseBlocks.Length == 0 || this.CaseBlocks[0].IsDefault)
            {
                Debug.Assert(this.CaseBlocks.Length <= 1);

                // no SWITCH or IF needed

                cg.EmitPop(this.SwitchValue.WithAccess(BoundAccess.None).Emit(cg)); // None Access, also using BoundExpression.Emit directly to avoid CodeGenerator type specialization which is not needed
                if (this.CaseBlocks.Length == 1)
                {
                    cg.GenerateScope(this.CaseBlocks[0], NextBlock.Ordinal);
                }
            }
            else
            {
                // CIL Switch:
                bool allconsts = this.CaseBlocks.All(c => c.IsDefault || c.CaseValue.ConstantValue.HasValue);
                bool allconstints = allconsts && this.CaseBlocks.All(c => c.IsDefault || IsInt32(c.CaseValue.ConstantValue.Value));
                //bool allconststrings = allconsts && this.CaseBlocks.All(c => c.IsDefault || IsString(c.CaseValue.ConstantValue.Value));

                var default_block = this.DefaultBlock;

                // <switch_loc> = <SwitchValue>;
                TypeSymbol switch_type;
                LocalDefinition switch_loc;

                // Switch Header
                if (allconstints)
                {
                    switch_type = cg.CoreTypes.Int32;
                    cg.EmitSequencePoint(this.SwitchValue.PhpSyntax);
                    cg.EmitConvert(this.SwitchValue, switch_type);
                    switch_loc = cg.GetTemporaryLocal(switch_type);
                    cg.Builder.EmitLocalStore(switch_loc);

                    // switch (labels)
                    cg.Builder.EmitIntegerSwitchJumpTable(GetSwitchCaseLabels(CaseBlocks), default_block ?? NextBlock, switch_loc, switch_type.PrimitiveTypeCode);
                }
                //else if (allconststrings)
                //{

                //}
                else
                {
                    // legacy jump table
                    // IF (case_i) GOTO label_i;

                    cg.EmitSequencePoint(this.SwitchValue.PhpSyntax);
                    switch_type = cg.Emit(this.SwitchValue);
                    switch_loc = cg.GetTemporaryLocal(switch_type);
                    cg.Builder.EmitLocalStore(switch_loc);

                    //
                    for (int i = 0; i < this.CaseBlocks.Length; i++)
                    {
                        var this_block = this.CaseBlocks[i];
                        if (this_block.CaseValue != null)
                        {
                            // <CaseValue>:
                            cg.EmitSequencePoint(this_block.CaseValue.PhpSyntax);
                            
                            // if (<switch_loc> == c.CaseValue) goto this_block;
                            cg.Builder.EmitLocalLoad(switch_loc);
                            BoundBinaryEx.EmitEquality(cg, switch_type, this_block.CaseValue);
                            cg.Builder.EmitBranch(ILOpCode.Brtrue, this_block);
                        }
                    }

                    // default:
                    cg.Builder.EmitBranch(ILOpCode.Br, default_block ?? NextBlock);
                }

                // FREE <switch_loc>
                cg.ReturnTemporaryLocal(switch_loc);

                // Switch Body
                this.CaseBlocks.ForEach((i, this_block) =>
                {
                    var next_case = (i + 1 < this.CaseBlocks.Length) ? this.CaseBlocks[i + 1] : null;

                    // {
                    cg.GenerateScope(this_block, (next_case ?? NextBlock).Ordinal);
                    // }
                });
            }

            //
            cg.Scope.ContinueWith(NextBlock);
        }
コード例 #5
0
ファイル: BoundEdge.cs プロジェクト: iolevel/peachpie
        internal override void Generate(CodeGenerator cg)
        {
            Debug.Assert(this.Enumeree != null);

            // get the enumerator,
            // bind actual MoveNext() and CurrentValue and CurrentKey

            // Template: using(
            // a) enumerator = enumeree.GetEnumerator()
            // b) enumerator = Operators.GetEnumerator(enumeree)
            // ) ...

            cg.EmitSequencePoint(this.Enumeree.PhpSyntax);

            var enumereeType = cg.Emit(this.Enumeree);
            Debug.Assert(enumereeType.SpecialType != SpecialType.System_Void);

            var getEnumeratorMethod = enumereeType.LookupMember<MethodSymbol>(WellKnownMemberNames.GetEnumeratorMethodName);

            TypeSymbol enumeratorType;

            if (enumereeType.IsOfType(cg.CoreTypes.PhpArray))
            {
                cg.Builder.EmitBoolConstant(_aliasedValues);
                
                // PhpArray.GetForeachtEnumerator(bool)
                enumeratorType = cg.EmitCall(ILOpCode.Callvirt, cg.CoreMethods.PhpArray.GetForeachEnumerator_Boolean);  // TODO: IPhpArray
            }
            // TODO: IPhpEnumerable
            // TODO: IPhpArray
            // TODO: Iterator
            else if (getEnumeratorMethod != null && getEnumeratorMethod.ParameterCount == 0 && enumereeType.IsReferenceType)
            {
                // enumeree.GetEnumerator()
                enumeratorType = cg.EmitCall(getEnumeratorMethod.IsVirtual ? ILOpCode.Callvirt : ILOpCode.Call, getEnumeratorMethod);
            }
            else
            {
                cg.EmitConvertToPhpValue(enumereeType, 0);
                cg.Builder.EmitBoolConstant(_aliasedValues);
                cg.EmitCallerRuntimeTypeHandle();

                // Operators.GetForeachEnumerator(PhpValue, bool, RuntimeTypeHandle)
                enumeratorType = cg.EmitCall(ILOpCode.Call, cg.CoreMethods.Operators.GetForeachEnumerator_PhpValue_Bool_RuntimeTypeHandle);
            }

            //
            _current = enumeratorType.LookupMember<PropertySymbol>(WellKnownMemberNames.CurrentPropertyName);   // TODO: Err if no Current
            _currentValue = enumeratorType.LookupMember<PropertySymbol>(_aliasedValues ? "CurrentValueAliased" : "CurrentValue");
            _currentKey = enumeratorType.LookupMember<PropertySymbol>("CurrentKey");
            _disposeMethod = enumeratorType.LookupMember<MethodSymbol>("Dispose", m => m.ParameterCount == 0 && !m.IsStatic);

            //
            _enumeratorLoc = cg.GetTemporaryLocal(enumeratorType);
            cg.Builder.EmitLocalStore(_enumeratorLoc);

            // bind methods
            _moveNextMethod = enumeratorType.LookupMember<MethodSymbol>(WellKnownMemberNames.MoveNextMethodName);    // TODO: Err if there is no MoveNext()
            Debug.Assert(_moveNextMethod.ReturnType.SpecialType == SpecialType.System_Boolean);
            Debug.Assert(_moveNextMethod.IsStatic == false);

            if (_disposeMethod != null)
            {
                /* Template: try { body } finally { enumerator.Dispose }
                 */

                // try {
                cg.Builder.AssertStackEmpty();
                cg.Builder.OpenLocalScope(ScopeType.TryCatchFinally);
                cg.Builder.OpenLocalScope(ScopeType.Try);

                //
                EmitBody(cg);

                // }
                cg.Builder.CloseLocalScope();   // /Try

                // finally {
                cg.Builder.OpenLocalScope(ScopeType.Finally);

                // enumerator.Dispose() & cleanup
                EmitDisposeAndClean(cg);

                // }
                cg.Builder.CloseLocalScope();   // /Finally
                cg.Builder.CloseLocalScope();   // /TryCatchFinally
            }
            else
            {
                EmitBody(cg);
                EmitDisposeAndClean(cg);
            }
        }
コード例 #6
0
ファイル: BoundStatement.cs プロジェクト: iolevel/peachpie
        internal override void Emit(CodeGenerator cg)
        {
            cg.EmitSequencePoint(this.PhpSyntax);

            //
            var t = cg.Emit(Thrown);

            if (t.IsReferenceType)
            {
                if (!t.IsEqualToOrDerivedFrom(cg.CoreTypes.Exception))
                {
                    throw new NotImplementedException();    // Wrap to System.Exception
                }
            }
            else
            {
                //if (t == cg.CoreTypes.PhpValue)
                //{

                //}

                throw new NotImplementedException();    // Wrap to System.Exception
            }

            // throw <stack>;
            cg.Builder.EmitThrow(false);
        }
コード例 #7
0
ファイル: BoundStatement.cs プロジェクト: iolevel/peachpie
 internal override void Emit(CodeGenerator cg)
 {
     cg.EmitSequencePoint(this.PhpSyntax);
     cg.EmitPop(this.Expression.Emit(cg));
 }
コード例 #8
0
ファイル: BoundStatement.cs プロジェクト: iolevel/peachpie
        internal override void Emit(CodeGenerator cg)
        {
            cg.EmitSequencePoint(this.PhpSyntax);

            this.VarReferences.ForEach(cg.EmitUnset);
        }
コード例 #9
0
ファイル: BoundStatement.cs プロジェクト: iolevel/peachpie
        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);

            }
        }
コード例 #10
0
ファイル: BoundStatement.cs プロジェクト: iolevel/peachpie
        internal override void Emit(CodeGenerator cg)
        {
            cg.EmitSequencePoint(this.TypeDecl.HeadingSpan);

            // <ctx>.DeclareType<T>()
            cg.EmitDeclareType(this.Type);
        }
コード例 #11
0
ファイル: BoundStatement.cs プロジェクト: iolevel/peachpie
        internal override void Emit(CodeGenerator cg)
        {
            cg.EmitSequencePoint(this.FunctionDecl.HeadingSpan);

            // <ctx>.DeclareFunction ...
            cg.EmitDeclareFunction(this.Function);
        }
コード例 #12
0
ファイル: BoundBlock.cs プロジェクト: iolevel/peachpie
        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);
        }