/// <summary> /// Emits binary operation XOR. /// </summary> TypeSymbol EmitBinaryXor(CodeGenerator cg) { // LOAD <(bool) leftSon> == <(bool) rightSon>; cg.EmitConvert(Left, cg.CoreTypes.Boolean); cg.EmitConvert(Right, cg.CoreTypes.Boolean); cg.EmitOpCode(ILOpCode.Ceq); cg.EmitOpCode(ILOpCode.Ldc_i4_0); cg.EmitOpCode(ILOpCode.Ceq); return cg.CoreTypes.Boolean; }
/// <summary> /// Emits <see name="_instance"/>, uses cached value if initialized already. /// </summary> TypeSymbol EmitInstance(CodeGenerator cg, Func<TypeSymbol> emitter) { Debug.Assert(cg != null); if (_instance_loc != null) { cg.Builder.EmitLocalLoad(_instance_loc); } else { _cg = cg; // return (<loc> = <instance>); _instance_loc = cg.GetTemporaryLocal(emitter()); cg.EmitOpCode(ILOpCode.Dup); cg.Builder.EmitLocalStore(_instance_loc); } return (TypeSymbol)_instance_loc.Type; }
internal override TypeSymbol Emit(CodeGenerator cg) { Debug.Assert(this.Access.IsNone || Access.IsRead); Debug.Assert(!this.Access.IsReadRef); Debug.Assert(!this.Access.IsWrite); Debug.Assert(this.Target.Access.IsRead && this.Target.Access.IsWrite); Debug.Assert(this.Value.Access.IsRead); Debug.Assert(this.Value is BoundLiteral); if (this.UsesOperatorMethod) { throw new NotImplementedException(); } TypeSymbol result_type = cg.CoreTypes.Void; LocalDefinition postfix_temp = null; var read = this.Access.IsRead; var target_place = this.Target.BindPlace(cg); Debug.Assert(target_place != null); using (var instance_holder = new InstanceCacheHolder()) { // prepare target for store operation target_place.EmitStorePrepare(cg, instance_holder); // load target value target_place.EmitLoadPrepare(cg, instance_holder); } var target_load_type = target_place.EmitLoad(cg); TypeSymbol op_type; if (read && IsPostfix) { // store original value of target // <temp> = TARGET postfix_temp = cg.GetTemporaryLocal(target_load_type); cg.EmitOpCode(ILOpCode.Dup); cg.Builder.EmitLocalStore(postfix_temp); } if (IsIncrement) { op_type = BoundBinaryEx.EmitAdd(cg, target_load_type, this.Value, target_place.TypeOpt); } else { Debug.Assert(IsDecrement); op_type = BoundBinaryEx.EmitSub(cg, target_load_type, this.Value, target_place.TypeOpt); } if (read) { if (IsPostfix) { // READ <temp> cg.Builder.EmitLocalLoad(postfix_temp); result_type = target_load_type; // cg.ReturnTemporaryLocal(postfix_temp); postfix_temp = null; } else { // dup resulting value // READ (++TARGET OR --TARGET) cg.Builder.EmitOpCode(ILOpCode.Dup); result_type = op_type; } } // target_place.EmitStore(cg, op_type); Debug.Assert(postfix_temp == null); Debug.Assert(!read || result_type.SpecialType != SpecialType.System_Void); // return result_type; }
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); }