public Scope(CodeGenerator generator, ILBuilder il, bool isFunction, BoundBody body, BoundClosureField argumentsClosureField, ITypeBuilder typeBuilder, Scope parent) { IL = il; ArgumentsClosureField = argumentsClosureField; Generator = generator; _isFunction = isFunction; _body = body; if (argumentsClosureField != null) ArgumentsEmitter = new ClosureFieldEmitter(generator, argumentsClosureField); TypeBuilder = typeBuilder; Parent = parent; _isStatic = TypeBuilder is IScriptBuilder; if (body.MappedArguments != null) _arguments = body.MappedArguments.ToDictionary(p => p.Argument, p => p.Mapped); BreakTargets = new Stack<NamedLabel>(); ContinueTargets = new Stack<NamedLabel>(); }
protected override void Operation(ILBuilder il) { il.Math.And(); }
public CodeGenerator( MethodSymbol method, BoundStatement boundBody, ILBuilder builder, PEModuleBuilder moduleBuilder, DiagnosticBag diagnostics, OptimizationLevel optimizations, bool emittingPdb) { Debug.Assert((object)method != null); Debug.Assert(boundBody != null); Debug.Assert(builder != null); Debug.Assert(moduleBuilder != null); Debug.Assert(diagnostics != null); _method = method; _boundBody = boundBody; _builder = builder; _module = moduleBuilder; _diagnostics = diagnostics; if (!method.GenerateDebugInfo) { // Always optimize synthesized methods that don't contain user code. // // Specifically, always optimize synthesized explicit interface implementation methods // (aka bridge methods) with by-ref returns because peverify produces errors if we // return a ref local (which the return local will be in such cases). _ilEmitStyle = ILEmitStyle.Release; } else { if (optimizations == OptimizationLevel.Debug) { _ilEmitStyle = ILEmitStyle.Debug; } else { _ilEmitStyle = IsDebugPlus() ? ILEmitStyle.DebugFriendlyRelease : ILEmitStyle.Release; } } // Emit sequence points unless // - the PDBs are not being generated // - debug information for the method is not generated since the method does not contain // user code that can be stepped through, or changed during EnC. // // This setting only affects generating PDB sequence points, it shall not affect generated IL in any way. _emitPdbSequencePoints = emittingPdb && method.GenerateDebugInfo; try { _boundBody = Optimizer.Optimize( boundBody, debugFriendly: _ilEmitStyle != ILEmitStyle.Release, stackLocals: out _stackLocals); } catch (BoundTreeVisitor.CancelledByStackGuardException ex) { ex.AddAnError(diagnostics); _boundBody = boundBody; } var sourceMethod = method as SourceMemberMethodSymbol; (BlockSyntax blockBody, ArrowExpressionClauseSyntax expressionBody) = sourceMethod?.Bodies ?? default; _methodBodySyntaxOpt = (SyntaxNode)blockBody ?? expressionBody ?? sourceMethod?.SyntaxNode; }
internal void SetMethodTestData(IMethodSymbol method, ILBuilder builder) { TestData.Add(method, new CompilationTestData.MethodData(builder, method)); }
internal override IPlace Place(ILBuilder il) { // TODO: place of superglobal variable return(null); }
internal override IBoundReference BindPlace(ILBuilder il, BoundAccess access, TypeRefMask thint) { return(new BoundLocalPlace(Place(il), access, thint)); }
/// <summary> /// Gets <see cref="IBoundReference"/> providing load and store operations. /// </summary> internal abstract IBoundReference BindPlace(ILBuilder il, BoundAccess access, TypeRefMask thint);
internal override IBoundReference BindPlace(ILBuilder il, BoundAccess access, TypeRefMask thint) { return(new BoundIndirectVariablePlace(_nameExpr, access)); }
internal override IPlace Place(ILBuilder il) => _place;
public override void Generate(ILBuilder il, ICompiler compiler) { using (var objNum = il.NewLocal <ushort>()) { // Read objNum var done = il.NewLabel(); compiler.EmitLoadValidObject(objectOp, done, reuse: ReuseFirstOperand); objNum.Store(); using (var propNum = il.NewLocal <ushort>()) using (var value = il.NewLocal <byte>()) using (var propAddress = il.NewLocal <ushort>()) { // Read propNum compiler.EmitLoadOperand(propertyOp); propNum.Store(); il.DebugWrite("propNum: {0}", propNum); int mask = compiler.Version < 4 ? 0x1f : 0x3f; // Read first property address into propAddress compiler.EmitLoadFirstPropertyAddress(objNum); propAddress.Store(); var loopStart = il.NewLabel(); var loopDone = il.NewLabel(); il.DebugIndent(); loopStart.Mark(); // Read first property byte and store in value compiler.EmitLoadMemoryByte(propAddress); value.Store(); // if ((value & mask) <= propNum) break; value.Load(); il.Math.And(mask); #if DEBUG using (var temp = il.NewLocal <ushort>()) { temp.Store(); il.DebugWrite("property number at address: {0} {1:x4}", temp, propAddress); temp.Load(); } #endif propNum.Load(); loopDone.BranchIf(Condition.AtMost, @short: true); // Read next property address into propAddress propAddress.Load(); compiler.EmitLoadNextPropertyAddress(); propAddress.Store(); // Branch to start of loop loopStart.Branch(); loopDone.Mark(); il.DebugUnindent(); // if ((value & mask) != propNum) throw; var propNumFound = il.NewLabel(); value.Load(); il.Math.And(mask); propNum.Load(); propNumFound.BranchIf(Condition.Equal, @short: true); il.RuntimeError("Object {0} does not contain property {1}", objNum, propNum); propNumFound.Mark(); il.DebugWrite("Found property {0} at address {1:x4}", propNum, propAddress); // propAddress++; propAddress.Load(); il.Math.Add(1); il.Convert.ToUInt16(); propAddress.Store(); var sizeIsWord = il.NewLabel(); // if ((this.version <= 3 && (value & 0xe0) != 0) && (this.version >= 4) && (value & 0xc0) != 0) int sizeMask = compiler.Version < 4 ? 0xe0 : 0xc0; value.Load(); il.Math.And(sizeMask); sizeIsWord.BranchIf(Condition.True, @short: true); // write byte using (var temp = il.NewLocal <byte>()) { compiler.EmitLoadOperand(valueOp); il.Convert.ToUInt8(); temp.Store(); compiler.EmitStoreMemoryByte(propAddress, temp); il.DebugWrite("Wrote byte {0:x2} to {1:x4}", temp, propAddress); done.Branch(@short: true); } // write word sizeIsWord.Mark(); using (var temp = il.NewLocal <ushort>()) { compiler.EmitLoadOperand(valueOp); temp.Store(); compiler.EmitStoreMemoryWord(propAddress, temp); il.DebugWrite("Wrote word {0:x2} to {1:x4}", temp, propAddress); } } done.Mark(); } }
internal override IBoundReference BindPlace(ILBuilder il, BoundAccess access, TypeRefMask thint) { return(new BoundThisPlace(_routine, access)); }
protected override void Operation(ILBuilder il) { il.Math.Remainder(); }
public void EmitStore(ILBuilder il) => il.EmitLocalStore(_def);
public void EmitStorePrepare(ILBuilder il) { }
public void EmitLoadAddress(ILBuilder il) => il.EmitLocalAddress(_def);
private IPlace LocalPlace(ILBuilder il) => _place;
internal override IBoundReference BindPlace(ILBuilder il, BoundAccess access, TypeRefMask thint) { return(new BoundLocalPlace(Place(il), access, _routine.TypeRefContext.GetThisTypeMask())); }
internal override IPlace Place(ILBuilder il) => null;
public HelperEmitter(AssemblyBuilder assemblyBuilder) { m_assemblyBuilder = assemblyBuilder; m_ilBuilder = new ILBuilder(assemblyBuilder.metadataContext.ilTokenProvider); }
/// <summary> /// Gets <see cref="IPlace"/> of the variable. /// </summary> internal abstract IPlace Place(ILBuilder il);
internal static MethodBody CreateSynthesizedBody(PEModuleBuilder moduleBuilder, IMethodSymbol routine, ILBuilder il) { var compilation = moduleBuilder.Compilation; var localSlotManager = il.LocalSlotManager; var optimizations = compilation.Options.OptimizationLevel; try { il.Realize(); // var localVariables = il.LocalSlotManager.LocalsInOrder(); if (localVariables.Length > 0xFFFE) { //diagnosticsForThisMethod.Add(ErrorCode.ERR_TooManyLocals, method.Locations.First()); } //if (diagnosticsForThisMethod.HasAnyErrors()) //{ // // we are done here. Since there were errors we should not emit anything. // return null; //} //// We will only save the IL builders when running tests. //if (moduleBuilder.SaveTestData) //{ // moduleBuilder.SetMethodTestData(method, builder.GetSnapshot()); //} // Only compiler-generated MoveNext methods have iterator scopes. See if this is one. var stateMachineHoistedLocalScopes = default(ImmutableArray <StateMachineHoistedLocalScope>); //if (isStateMachineMoveNextMethod) //{ // stateMachineHoistedLocalScopes = builder.GetHoistedLocalScopes(); //} var stateMachineHoistedLocalSlots = default(ImmutableArray <EncHoistedLocalInfo>); var stateMachineAwaiterSlots = default(ImmutableArray <Cci.ITypeReference>); //if (optimizations == OptimizationLevel.Debug && stateMachineTypeOpt != null) //{ // Debug.Assert(method.IsAsync || method.IsIterator); // GetStateMachineSlotDebugInfo(moduleBuilder, moduleBuilder.GetSynthesizedFields(stateMachineTypeOpt), variableSlotAllocatorOpt, diagnosticsForThisMethod, out stateMachineHoistedLocalSlots, out stateMachineAwaiterSlots); // Debug.Assert(!diagnostics.HasAnyErrors()); //} return(new MethodBody( il.RealizedIL, il.MaxStack, (Cci.IMethodDefinition)routine, new DebugId(0, moduleBuilder.CurrentGenerationOrdinal), localVariables, il.RealizedSequencePoints, null, il.RealizedExceptionHandlers, il.AreLocalsZeroed, hasStackalloc: false, // No support for stackalloc in PHP il.GetAllScopes(), il.HasDynamicLocal, null, // importScopeOpt, ImmutableArray <LambdaDebugInfo> .Empty, // lambdaDebugInfo, ImmutableArray <ClosureDebugInfo> .Empty, // closureDebugInfo, null, //stateMachineTypeOpt?.Name, stateMachineHoistedLocalScopes, stateMachineHoistedLocalSlots, stateMachineAwaiterSlots, null, // stateMachineMoveNextDebugInfoOpt null)); // dynamicAnalysisDataOpt } finally { // Basic blocks contain poolable builders for IL and sequence points. Free those back // to their pools. il.FreeBasicBlocks(); //// Remember diagnostics. //diagnostics.AddRange(diagnosticsForThisMethod); //diagnosticsForThisMethod.Free(); } }
internal override IBoundReference BindPlace(ILBuilder il, BoundAccess access, TypeRefMask thint) { Debug.Assert(_name.IsAutoGlobal); return(new BoundSuperglobalPlace(_name, access)); }
protected abstract void Operation(ILBuilder il);
internal override IPlace Place(ILBuilder il) => LocalPlace(il);
protected virtual void PostOperation(ILocal result, ILBuilder il, ICompiler compiler) { }
private HomeItemViewModel Parse(string source, long timer, bool generateAssembly = false) { string error = null; var vm = new HomeItemViewModel { Source = source, Timer = timer }; var input = InputModule.create(vm.Source); var tokensResult = Lexer.tokenize(input); if (tokensResult.IsError) { error = tokensResult.ErrorValue; goto End; } var tokens = tokensResult.ResultValue; var programResult = Parser.parse(tokens); if (programResult.IsError) { error = programResult.ErrorValue; goto End; } var program = programResult.ResultValue; vm.Ast = JsonConvert.SerializeObject(_astBuilder.Build(program)); var symbolTableResult = SymbolCollector.create(program); if (symbolTableResult.IsError) { error = symbolTableResult.ErrorValue; goto End; } var symbolTable = symbolTableResult.ResultValue; var typeCheckerResult = TypeChecker.check(symbolTable, program); if (typeCheckerResult.IsError) { error = typeCheckerResult.ErrorValue; goto End; } var variableInitializationCheckerResult = VariableInitializationChecker.check(program); if (variableInitializationCheckerResult.IsError) { error = variableInitializationCheckerResult.ErrorValue; goto End; } var writeLineFunc = FuncConvert.ToFSharpFunc <int>(i => vm.PrintfnLog += i + "\n"); var environment = EnvironmentModule.create(symbolTable, program, writeLineFunc, vm.Timer); var interpreterResult = Interpreter.interpret(environment); if (interpreterResult.IsError) { error = interpreterResult.ErrorValue; goto End; } var assemblyResult = ILBuilder.build(symbolTable, program); if (assemblyResult.IsError) { error = assemblyResult.ErrorValue; goto End; } var assembly = assemblyResult.ResultValue; vm.Il = JsonConvert.SerializeObject(_ilBuilder.Build(assembly)); if (generateAssembly) { var applicationResult = CodeGenerator.generate(assembly); if (applicationResult.IsError) { error = applicationResult.ErrorValue; goto End; } vm.Application = applicationResult.ResultValue; } End: if (error != null) { vm.Error = error; } return(vm); }
internal static MethodBody GenerateMethodBody(TypeCompilationState compilationState, MethodSymbol method, BoundStatement block, DiagnosticBag diagnostics, bool optimize, DebugDocumentProvider debugDocumentProvider, ImmutableArray <NamespaceScope> namespaceScopes) { // Note: don't call diagnostics.HasAnyErrors() in release; could be expensive if compilation has many warnings. Debug.Assert(!diagnostics.HasAnyErrors(), "Running code generator when errors exist might be dangerous; code generator not well hardened"); bool emitSequencePoints = !namespaceScopes.IsDefault && !method.IsAsync; var module = compilationState.ModuleBuilder; var compilation = module.Compilation; var localSlotManager = module.CreateLocalSlotManager(method); ILBuilder builder = new ILBuilder(module, localSlotManager, optimize); DiagnosticBag diagnosticsForThisMethod = DiagnosticBag.GetInstance(); try { AsyncMethodBodyDebugInfo asyncDebugInfo = null; if ((object)method.AsyncKickoffMethod == null) // is this the MoveNext of an async method? { CodeGen.CodeGenerator.Run( method, block, builder, module, diagnosticsForThisMethod, optimize, emitSequencePoints); } else { int asyncCatchHandlerOffset; ImmutableArray <int> asyncYieldPoints; ImmutableArray <int> asyncResumePoints; CodeGen.CodeGenerator.Run( method, block, builder, module, diagnosticsForThisMethod, optimize, emitSequencePoints, out asyncCatchHandlerOffset, out asyncYieldPoints, out asyncResumePoints); asyncDebugInfo = new AsyncMethodBodyDebugInfo(method.AsyncKickoffMethod, asyncCatchHandlerOffset, asyncYieldPoints, asyncResumePoints); } var localVariables = builder.LocalSlotManager.LocalsInOrder(); if (localVariables.Length > 0xFFFE) { diagnosticsForThisMethod.Add(ErrorCode.ERR_TooManyLocals, method.Locations.First()); } if (diagnosticsForThisMethod.HasAnyErrors()) { // we are done here. Since there were errors we should not emit anything. return(null); } // We will only save the IL builders when running tests. if (module.SaveTestData) { module.SetMethodTestData(method, builder.GetSnapshot()); } // Only compiler-generated MoveNext methods have iterator scopes. See if this is one. bool hasIteratorScopes = method.Locations.IsEmpty && method.Name == "MoveNext" && (method.ExplicitInterfaceImplementations.Contains(compilation.GetSpecialTypeMember(SpecialMember.System_Collections_IEnumerator__MoveNext) as MethodSymbol) || method.ExplicitInterfaceImplementations.Contains(compilation.GetWellKnownTypeMember(WellKnownMember.System_Runtime_CompilerServices_IAsyncStateMachine_MoveNext) as MethodSymbol)); var iteratorScopes = hasIteratorScopes ? builder.GetIteratorScopes() : ImmutableArray <LocalScope> .Empty; var iteratorOrAsyncImplementation = compilationState.GetIteratorOrAsyncImplementationClass(method); return(new MethodBody( builder.RealizedIL, builder.MaxStack, method, localVariables, builder.RealizedSequencePoints, debugDocumentProvider, builder.RealizedExceptionHandlers, builder.GetAllScopes(), Microsoft.Cci.CustomDebugInfoKind.CSharpStyle, builder.HasDynamicLocal, namespaceScopes, (object)iteratorOrAsyncImplementation == null ? null : iteratorOrAsyncImplementation.MetadataName, iteratorScopes, asyncMethodDebugInfo: asyncDebugInfo )); } finally { // Basic blocks contain poolable builders for IL and sequence points. Free those back // to their pools. builder.FreeBasicBlocks(); // Remember diagnostics. diagnostics.AddRange(diagnosticsForThisMethod); diagnosticsForThisMethod.Free(); } }
private static ImmutableArray <ILVisualizer.LocalInfo> ToLocalDefinitions(ImmutableArray <LocalInfo <TypeSymbol> > localInfos, ILBuilder builder) { if (localInfos.IsEmpty) { return(ImmutableArray.Create <ILVisualizer.LocalInfo>()); } var result = new ILVisualizer.LocalInfo[localInfos.Length]; for (int i = 0; i < result.Length; i++) { var typeRef = localInfos[i].Type; var builderLocal = builder.LocalSlotManager.LocalsInOrder()[i]; result[i] = new ILVisualizer.LocalInfo(builderLocal.Name, typeRef, localInfos[i].IsPinned, localInfos[i].IsByRef); } return(result.AsImmutableOrNull()); }
public static TypeSymbol EmitConvertToPhpValue(TypeSymbol from, TypeRefMask fromHint, ILBuilder il, Emit.PEModuleBuilder module, DiagnosticBag diagnostic) { Contract.ThrowIfNull(from); var compilation = module.Compilation; switch (from.SpecialType) { case SpecialType.System_Boolean: il.EmitCall(module, diagnostic, ILOpCode.Call, compilation.CoreMethods.PhpValue.Create_Boolean); break; case SpecialType.System_Int32: il.EmitOpCode(ILOpCode.Conv_i8); // Int32 -> Int64 goto case SpecialType.System_Int64; // PhpValue.Create((long)<stack>) case SpecialType.System_Int64: il.EmitCall(module, diagnostic, ILOpCode.Call, compilation.CoreMethods.PhpValue.Create_Long); break; case SpecialType.System_Double: il.EmitCall(module, diagnostic, ILOpCode.Call, compilation.CoreMethods.PhpValue.Create_Double); break; case SpecialType.System_Void: Emit_PhpValue_Void(il, module, diagnostic); break; default: if (from == compilation.CoreTypes.PhpAlias) { il.EmitCall(module, diagnostic, ILOpCode.Call, compilation.CoreMethods.PhpValue.Create_PhpAlias) .Expect(compilation.CoreTypes.PhpValue); break; } else if (from == compilation.CoreTypes.PhpValue) { // nop break; } else if (from == compilation.CoreTypes.String) { il.EmitCall(module, diagnostic, ILOpCode.Call, compilation.CoreMethods.PhpValue.Create_String) .Expect(compilation.CoreTypes.PhpValue); break; } else if (from == compilation.CoreTypes.PhpString) { il.EmitCall(module, diagnostic, ILOpCode.Call, compilation.CoreMethods.PhpValue.Create_PhpString) .Expect(compilation.CoreTypes.PhpValue); break; } else if (from == compilation.CoreTypes.PhpNumber) { il.EmitCall(module, diagnostic, ILOpCode.Call, compilation.CoreMethods.PhpValue.Create_PhpNumber) .Expect(compilation.CoreTypes.PhpValue); break; } else if (from.IsOfType(compilation.CoreTypes.PhpArray)) { il.EmitCall(module, diagnostic, ILOpCode.Call, compilation.CoreMethods.PhpValue.Create_PhpArray) .Expect(compilation.CoreTypes.PhpValue); break; } else if (from == compilation.CoreTypes.IntStringKey) { il.EmitCall(module, diagnostic, ILOpCode.Call, compilation.CoreMethods.PhpValue.Create_IntStringKey) .Expect(compilation.CoreTypes.PhpValue); break; } else if (from.IsReferenceType) { il.EmitCall(module, diagnostic, ILOpCode.Call, compilation.CoreMethods.PhpValue.FromClass_Object) .Expect(compilation.CoreTypes.PhpValue); break; } else { throw new NotImplementedException($"{from.Name}"); } } // return(compilation.CoreTypes.PhpValue); }
/// <summary> /// Generates method body that calls another method. /// Used for wrapping a method call into a method, e.g. an entry point. /// </summary> internal static MethodBody GenerateMethodBody( PEModuleBuilder moduleBuilder, MethodSymbol routine, Action <ILBuilder> builder, VariableSlotAllocator variableSlotAllocatorOpt, DiagnosticBag diagnostics, bool emittingPdb) { var compilation = moduleBuilder.Compilation; var localSlotManager = new LocalSlotManager(variableSlotAllocatorOpt); var optimizations = compilation.Options.OptimizationLevel; DebugDocumentProvider debugDocumentProvider = null; if (emittingPdb) { debugDocumentProvider = (path, basePath) => moduleBuilder.GetOrAddDebugDocument(path, basePath, CreateDebugDocumentForFile); } ILBuilder il = new ILBuilder(moduleBuilder, localSlotManager, optimizations); try { Cci.AsyncMethodBodyDebugInfo asyncDebugInfo = null; builder(il); // il.Realize(); // var localVariables = il.LocalSlotManager.LocalsInOrder(); if (localVariables.Length > 0xFFFE) { //diagnosticsForThisMethod.Add(ErrorCode.ERR_TooManyLocals, method.Locations.First()); } //if (diagnosticsForThisMethod.HasAnyErrors()) //{ // // we are done here. Since there were errors we should not emit anything. // return null; //} //// We will only save the IL builders when running tests. //if (moduleBuilder.SaveTestData) //{ // moduleBuilder.SetMethodTestData(method, builder.GetSnapshot()); //} // Only compiler-generated MoveNext methods have iterator scopes. See if this is one. var stateMachineHoistedLocalScopes = default(ImmutableArray <Cci.StateMachineHoistedLocalScope>); //if (isStateMachineMoveNextMethod) //{ // stateMachineHoistedLocalScopes = builder.GetHoistedLocalScopes(); //} var stateMachineHoistedLocalSlots = default(ImmutableArray <EncHoistedLocalInfo>); var stateMachineAwaiterSlots = default(ImmutableArray <Cci.ITypeReference>); //if (optimizations == OptimizationLevel.Debug && stateMachineTypeOpt != null) //{ // Debug.Assert(method.IsAsync || method.IsIterator); // GetStateMachineSlotDebugInfo(moduleBuilder, moduleBuilder.GetSynthesizedFields(stateMachineTypeOpt), variableSlotAllocatorOpt, diagnosticsForThisMethod, out stateMachineHoistedLocalSlots, out stateMachineAwaiterSlots); // Debug.Assert(!diagnostics.HasAnyErrors()); //} return(new MethodBody( il.RealizedIL, il.MaxStack, (Cci.IMethodDefinition)routine.PartialDefinitionPart ?? routine, variableSlotAllocatorOpt?.MethodId ?? new DebugId(0, moduleBuilder.CurrentGenerationOrdinal), localVariables, il.RealizedSequencePoints, debugDocumentProvider, il.RealizedExceptionHandlers, il.GetAllScopes(), il.HasDynamicLocal, null, // importScopeOpt, ImmutableArray <LambdaDebugInfo> .Empty, // lambdaDebugInfo, ImmutableArray <ClosureDebugInfo> .Empty, // closureDebugInfo, null, //stateMachineTypeOpt?.Name, stateMachineHoistedLocalScopes, stateMachineHoistedLocalSlots, stateMachineAwaiterSlots, asyncDebugInfo)); } finally { // Basic blocks contain poolable builders for IL and sequence points. Free those back // to their pools. il.FreeBasicBlocks(); //// Remember diagnostics. //diagnostics.AddRange(diagnosticsForThisMethod); //diagnosticsForThisMethod.Free(); } }
public TypeSymbol EmitLoad(ILBuilder il) { il.EmitLocalLoad(_def); return((TypeSymbol)_def.Type); }