private Cci.IFieldDefinition ResolvedFieldImpl(PEModuleBuilder moduleBeingBuilt) { Debug.Assert(this.IsDefinitionOrDistinct()); if (this.IsDefinition && object.ReferenceEquals(this.ContainingModule, moduleBeingBuilt.SourceModule)) { return this; } return null; }
/// <summary> /// Synthesizes method overloads in case there are optional parameters which explicit default value cannot be resolved as a <see cref="ConstantValue"/>. /// </summary> /// <remarks> /// foo($a = [], $b = [1, 2, 3]) /// + foo() => foo([], [1, 2, 3) /// + foo($a) => foo($a, [1, 2, 3]) /// </remarks> protected void SynthesizeOverloadsWithOptionalParameters(PEModuleBuilder module, DiagnosticBag diagnostic) { var ps = this.Parameters; for (int i = 0; i < ps.Length; i++) { var p = ps[i] as SourceParameterSymbol; if (p != null && p.Initializer != null && p.ExplicitDefaultConstantValue == null) // => ConstantValue couldn't be resolved for optional parameter { // create ghost stub foo(p0, .. pi-1) => foo(p0, .. , pN) CreateGhostOverload(module, diagnostic, i); } } }
internal static MethodBody GenerateMethodBody( PEModuleBuilder moduleBuilder, SourceRoutineSymbol routine, int methodOrdinal, //ImmutableArray<LambdaDebugInfo> lambdaDebugInfo, //ImmutableArray<ClosureDebugInfo> closureDebugInfo, //StateMachineTypeSymbol stateMachineTypeOpt, VariableSlotAllocator variableSlotAllocatorOpt, DiagnosticBag diagnostics, //ImportChain importChainOpt, bool emittingPdb) { return GenerateMethodBody(moduleBuilder, routine, (builder) => { DiagnosticBag diagnosticsForThisMethod = DiagnosticBag.GetInstance(); var optimization = moduleBuilder.Compilation.Options.OptimizationLevel; var codeGen = new CodeGenerator(routine, builder, moduleBuilder, diagnosticsForThisMethod, optimization, emittingPdb); //if (diagnosticsForThisMethod.HasAnyErrors()) //{ // // we are done here. Since there were errors we should not emit anything. // return null; //} // We need to save additional debugging information for MoveNext of an async state machine. //var stateMachineMethod = method as SynthesizedStateMachineMethod; //bool isStateMachineMoveNextMethod = stateMachineMethod != null && method.Name == WellKnownMemberNames.MoveNextMethodName; //if (isStateMachineMoveNextMethod && stateMachineMethod.StateMachineType.KickoffMethod.IsAsync) //{ // int asyncCatchHandlerOffset; // ImmutableArray<int> asyncYieldPoints; // ImmutableArray<int> asyncResumePoints; // codeGen.Generate(out asyncCatchHandlerOffset, out asyncYieldPoints, out asyncResumePoints); // var kickoffMethod = stateMachineMethod.StateMachineType.KickoffMethod; // // The exception handler IL offset is used by the debugger to treat exceptions caught by the marked catch block as "user unhandled". // // This is important for async void because async void exceptions generally result in the process being terminated, // // but without anything useful on the call stack. Async Task methods on the other hand return exceptions as the result of the Task. // // So it is undesirable to consider these exceptions "user unhandled" since there may well be user code that is awaiting the task. // // This is a heuristic since it's possible that there is no user code awaiting the task. // asyncDebugInfo = new Cci.AsyncMethodBodyDebugInfo(kickoffMethod, kickoffMethod.ReturnsVoid ? asyncCatchHandlerOffset : -1, asyncYieldPoints, asyncResumePoints); //} //else { codeGen.Generate(); } }, variableSlotAllocatorOpt, diagnostics, emittingPdb); }
private SourceCompiler(PhpCompilation compilation, PEModuleBuilder moduleBuilder, bool emittingPdb, DiagnosticBag diagnostics) { Contract.ThrowIfNull(compilation); Contract.ThrowIfNull(moduleBuilder); Contract.ThrowIfNull(diagnostics); _compilation = compilation; _moduleBuilder = moduleBuilder; _emittingPdb = emittingPdb; _diagnostics = diagnostics; // parallel worklist algorithm _worklist = new Worklist<BoundBlock>(AnalyzeBlock); // semantic model }
/// <summary> /// Creates ghost stub that calls current method. /// </summary> protected void CreateGhostOverload(PEModuleBuilder module, DiagnosticBag diagnostic, TypeSymbol ghostreturn, IEnumerable<ParameterSymbol> ghostparams, MethodSymbol explicitOverride = null) { var ghost = new SynthesizedMethodSymbol( this.ContainingType, this.Name, this.IsStatic, explicitOverride != null, ghostreturn, this.DeclaredAccessibility) { ExplicitOverride = explicitOverride, }; ghost.SetParameters(ghostparams.Select(p => new SynthesizedParameterSymbol(ghost, p.Type, p.Ordinal, p.RefKind, p.Name)).ToArray()); // save method symbol to module module.SynthesizedManager.AddMethod(this.ContainingType, ghost); // generate method body GenerateGhostBody(module, diagnostic, ghost); }
void CreateGhostOverload(PEModuleBuilder module, DiagnosticBag diagnostic, int pcount) { Debug.Assert(this.Parameters.Length > pcount); CreateGhostOverload(module, diagnostic, this.ReturnType, this.Parameters.Take(pcount), null); }
public static void EmitSymbolToken(this ILBuilder il, PEModuleBuilder module, DiagnosticBag diagnostics, MethodSymbol symbol, SyntaxNode syntaxNode) { il.EmitToken(module.Translate(symbol, syntaxNode, diagnostics, true), syntaxNode, diagnostics); }
/// <summary> /// Creates ghost stubs, /// i.e. methods with a different signature calling this routine to comply with CLR standards. /// </summary> internal virtual void SynthesizeGhostStubs(PEModuleBuilder module, DiagnosticBag diagnostic) { SynthesizeOverloadsWithOptionalParameters(module, diagnostic); }
internal override void SynthesizeGhostStubs(PEModuleBuilder module, DiagnosticBag diagnostic) { base.SynthesizeGhostStubs(module, diagnostic); // not matching override has to have a ghost stub var overriden = (MethodSymbol)this.OverriddenMethod; // OverrideHelper.ResolveOverride(this); if (overriden != null && !this.SignaturesMatch(overriden)) { /* * class A { * TReturn1 foo(A, B); * } * class B : A { * TReturn2 foo(A2, B2); * * // SYNTHESIZED GHOST: * override TReturn foo(A, B){ return (TReturn)foo((A2)A, (B2)B); * } */ CreateGhostOverload(module, diagnostic, overriden.ReturnType, overriden.Parameters, overriden); } }
/// <summary> /// Main method wrapper in case it does not return PhpValue. /// </summary> void SynthesizeMainMethodWrapper(PEModuleBuilder module, DiagnosticBag diagnostics) { if (this.ReturnType != DeclaringCompilation.CoreTypes.PhpValue) { // PhpValue <Main>`0(parameters) var wrapper = new SynthesizedMethodSymbol( this.ContainingFile, WellKnownPchpNames.GlobalRoutineName + "`0", true, false, DeclaringCompilation.CoreTypes.PhpValue, Accessibility.Public); wrapper.SetParameters(this.Parameters.Select(p => new SynthesizedParameterSymbol(wrapper, p.Type, p.Ordinal, p.RefKind, p.Name)).ToArray()); // save method symbol to module module.SynthesizedManager.AddMethod(this.ContainingFile, wrapper); // generate method body module.CreateMainMethodWrapper(wrapper, this, diagnostics); } }
/// <summary> /// Emits call to given method. /// </summary> /// <returns>Method return type.</returns> public static TypeSymbol EmitCall(this ILBuilder il, PEModuleBuilder module, DiagnosticBag diagnostics, ILOpCode code, MethodSymbol method) { Contract.ThrowIfNull(method); Debug.Assert(code == ILOpCode.Call || code == ILOpCode.Calli || code == ILOpCode.Callvirt || code == ILOpCode.Newobj); var stack = method.GetCallStackBehavior(); if (code == ILOpCode.Newobj) stack += 1 + 1; // there is no <this>, + it pushes <newinst> on stack il.EmitOpCode(code, stack); il.EmitToken(module.Translate(method, diagnostics, false), null, diagnostics); return (code == ILOpCode.Newobj) ? method.ContainingType : method.ReturnType; }
public static void EmitLoadToken(this ILBuilder il, PEModuleBuilder module, DiagnosticBag diagnostics, MethodSymbol method, SyntaxNode syntaxNodeOpt) { il.EmitOpCode(ILOpCode.Ldtoken); EmitSymbolToken(il, module, diagnostics, method, syntaxNodeOpt); }
internal override NamedTypeSymbol FixedImplementationType(PEModuleBuilder emitModule) { EnsureSignatureIsLoaded(); return _lazyFixedImplementationType; }
public static void CompileSources( PhpCompilation compilation, PEModuleBuilder moduleBuilder, bool emittingPdb, bool hasDeclarationErrors, DiagnosticBag diagnostics, CancellationToken cancellationToken) { var compiler = new SourceCompiler(compilation, moduleBuilder, emittingPdb, diagnostics); // 1.Bind Syntax & Symbols to Operations (CFG) // a.equivalent to building CFG // b.most generic types(and empty type - mask) compiler.WalkMethods(compiler.EnqueueRoutine); compiler.WalkTypes(compiler.EnqueueFieldsInitializer); // 2.Analyze Operations // a.declared variables // b.build global variables/constants table // c.type analysis(converge type - mask), resolve symbols // d.lower semantics, update bound tree, repeat compiler.AnalyzeMethods(); // 3. Emit method bodies // a. declared routines // b. synthesized symbols compiler.EmitMethodBodies(); compiler.EmitSynthesized(); compiler.CompileReflectionEnumerators(cancellationToken); // 4. Entry Point (.exe) compiler.CompileEntryPoint(cancellationToken); }
public SynthesizedManager(PEModuleBuilder module) { Contract.ThrowIfNull(module); _module = module; }
private Cci.ITypeDefinition AsTypeDefinitionImpl(PEModuleBuilder moduleBeingBuilt) { Debug.Assert(this.IsDefinitionOrDistinct()); if (this.IsDefinition && // can't be generic instantiation object.ReferenceEquals(this.ContainingModule, moduleBeingBuilt.SourceModule)) // must be declared in the module we are building { return this; } return null; }
private Cci.INestedTypeDefinition AsNestedTypeDefinitionImpl(PEModuleBuilder moduleBeingBuilt) { Debug.Assert(this.IsDefinitionOrDistinct()); if ((object)this.ContainingType != null && this.IsDefinition && object.ReferenceEquals(this.ContainingModule, moduleBeingBuilt.SourceModule)) { return this; } return null; }
/// <summary> /// Generates ghost method body that calls <c>this</c> method. /// </summary> protected void GenerateGhostBody(PEModuleBuilder module, DiagnosticBag diagnostic, SynthesizedMethodSymbol ghost) { var body = MethodGenerator.GenerateMethodBody(module, ghost, (il) => { var cg = new CodeGenerator(il, module, diagnostic, OptimizationLevel.Release, false, this.ContainingType, this.GetContextPlace(), this.GetThisPlace()); // return (T){routine}(p0, ..., pN); cg.EmitConvert(cg.EmitThisCall(this, ghost), 0, ghost.ReturnType); cg.EmitRet(ghost.ReturnType); }, null, diagnostic, false); module.SetMethodBody(ghost, body); }
internal override void SynthesizeGhostStubs(PEModuleBuilder module, DiagnosticBag diagnostic) { // <Main>'0 this.SynthesizeMainMethodWrapper(module, diagnostic); // base.SynthesizeGhostStubs(module, diagnostic); }
private void SetupWin32Resources(PEModuleBuilder moduleBeingBuilt, Stream win32Resources, DiagnosticBag diagnostics) { if (win32Resources == null) return; switch (DetectWin32ResourceForm(win32Resources)) { case Win32ResourceForm.COFF: //moduleBeingBuilt.Win32ResourceSection = MakeWin32ResourcesFromCOFF(win32Resources, diagnostics); break; case Win32ResourceForm.RES: //moduleBeingBuilt.Win32Resources = MakeWin32ResourceList(win32Resources, diagnostics); break; default: //diagnostics.Add(ErrorCode.ERR_BadWin32Res, NoLocation.Singleton, "Unrecognized file format."); break; } }
public static void EmitSymbolToken(this ILBuilder il, PEModuleBuilder module, DiagnosticBag diagnostics, FieldSymbol symbol, SyntaxNode syntaxNode) { il.EmitToken(symbol, syntaxNode, diagnostics); }
/// <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 SpecializedGenericMethodInstanceReference(MethodSymbol underlyingMethod) : base(underlyingMethod) { Debug.Assert(PEModuleBuilder.IsGenericType(underlyingMethod.ContainingType) && underlyingMethod.ContainingType.IsDefinition); _genericMethod = new SpecializedMethodReference(underlyingMethod); }