/// <summary> /// Performs the actual (asynchronous) code generation. /// </summary> /// <param name="method">The method.</param> /// <param name="isExternalRequest"> /// True, if processing of this method was requested by a user. /// </param> /// <param name="detectedMethods">The set of newly detected methods.</param> /// <param name="generatedMethod">The resolved IR method.</param> internal void GenerateCodeInternal( MethodBase method, bool isExternalRequest, HashSet <MethodBase> detectedMethods, out Method generatedMethod) { generatedMethod = Context.Declare(method, out bool created); if (!created & isExternalRequest) { return; } SequencePointEnumerator sequencePoints = DebugInformationManager?.LoadSequencePoints(method) ?? SequencePointEnumerator.Empty; var disassembler = new Disassembler(method, sequencePoints); var disassembledMethod = disassembler.Disassemble(); using (var builder = generatedMethod.CreateBuilder()) { var codeGenerator = new CodeGenerator( Frontend, builder, disassembledMethod, detectedMethods); codeGenerator.GenerateCode(); } Verifier.Verify(generatedMethod); // Evaluate inlining heuristic to adjust method declaration Inliner.SetupInliningAttributes( Context, generatedMethod, disassembledMethod); }
/// <summary> /// Performs the actual (asynchronous) code generation. /// </summary> /// <param name="method">The method.</param> /// <param name="isExternalRequest"> /// True, if processing of this method was requested by a user. /// </param> /// <param name="compilationStackLocation">The source location.</param> /// <param name="detectedMethods">The set of newly detected methods.</param> /// <param name="generatedMethod">The resolved IR method.</param> internal void GenerateCodeInternal( MethodBase method, bool isExternalRequest, CompilationStackLocation compilationStackLocation, Dictionary <MethodBase, CompilationStackLocation> detectedMethods, out Method generatedMethod) { ILocation location = null; try { generatedMethod = Context.Declare(method, out bool created); if (!created & isExternalRequest) { return; } location = generatedMethod; SequencePointEnumerator sequencePoints = DebugInformationManager?.LoadSequencePoints(method) ?? SequencePointEnumerator.Empty; var disassembler = new Disassembler( method, sequencePoints, compilationStackLocation); var disassembledMethod = disassembler.Disassemble(); using (var builder = generatedMethod.CreateBuilder()) { var codeGenerator = new CodeGenerator( Frontend, Context, builder, disassembledMethod, compilationStackLocation, detectedMethods); codeGenerator.GenerateCode(); builder.Complete(); } Verifier.Verify(generatedMethod); // Evaluate inlining heuristic to adjust method declaration Inliner.SetupInliningAttributes( Context, generatedMethod, disassembledMethod); } catch (InternalCompilerException) { // If we already have an internal compiler exception, re-throw it. throw; } catch (Exception e) { // Wrap generic exceptions with location information. location ??= new Method.MethodLocation(method); throw location.GetException(e); } }
/// <summary> /// Constructs a new ILGPU main context /// </summary> /// <param name="builder">The parent builder instance.</param> /// <param name="devices">The array of accelerator descriptions.</param> internal Context( Builder builder, ImmutableArray <Device> devices) { InstanceId = InstanceId.CreateNew(); TargetPlatform = Backend.RuntimePlatform; RuntimeSystem = new RuntimeSystem(); Properties = builder.InstantiateProperties(); // Initialize verifier Verifier = builder.EnableVerifier ? Verifier.Instance : Verifier.Empty; // Initialize main contexts TypeContext = new IRTypeContext(this); IRContext = new IRContext(this); // Initialize intrinsic manager IntrinsicManager = builder.IntrinsicManager; // Create frontend DebugInformationManager frontendDebugInformationManager = Properties.DebugSymbolsMode > DebugSymbolsMode.Disabled ? DebugInformationManager : null; ILFrontend = builder.EnableParallelCodeGenerationInFrontend ? new ILFrontend(this, frontendDebugInformationManager) : new ILFrontend(this, frontendDebugInformationManager, 1); // Create default IL backend DefautltILBackend = new DefaultILBackend(this); // Initialize default transformer ContextTransformer = Optimizer.CreateTransformer( Properties.OptimizationLevel, TransformerConfiguration.Transformed, Properties.InliningMode); // Initialize all devices Devices = devices; if (devices.IsDefaultOrEmpty) { // Add a default CPU device Devices = ImmutableArray.Create <Device>(CPUDevice.Default); } // Create a mapping deviceMapping = new Dictionary <AcceleratorType, List <Device> >(Devices.Length); foreach (var device in Devices) { if (!deviceMapping.TryGetValue(device.AcceleratorType, out var devs)) { devs = new List <Device>(8); deviceMapping.Add(device.AcceleratorType, devs); } devs.Add(device); } }
/// <summary> /// Clears internal caches. However, this does not affect individual accelerator /// caches. /// </summary> /// <param name="mode">The clear mode.</param> /// <remarks> /// This method is not thread-safe. /// </remarks> public override void ClearCache(ClearCacheMode mode) { IRContext.ClearCache(mode); TypeContext.ClearCache(mode); DebugInformationManager.ClearCache(mode); DefautltILBackend.ClearCache(mode); RuntimeSystem.ClearCache(mode); base.ClearCache(mode); }
/// <summary> /// Constructs a new ILGPU main context /// </summary> /// <param name="optimizationLevel">The optimization level.</param> /// <param name="flags">The context flags.</param> public Context(ContextFlags flags, OptimizationLevel optimizationLevel) { // Enable debug information automatically when a debugger is attached if (Debugger.IsAttached) { flags |= DefaultDebug; } InstanceId = InstanceId.CreateNew(); OptimizationLevel = optimizationLevel; Flags = flags.Prepare(); TargetPlatform = Backend.RuntimePlatform; RuntimeSystem = new RuntimeSystem(); // Initialize enhanced PTX backend feature flags if (optimizationLevel > OptimizationLevel.O1 && !Flags.HasFlags(ContextFlags.DefaultPTXBackendFeatures)) { Flags |= ContextFlags.EnhancedPTXBackendFeatures; } // Initialize verifier Verifier = flags.HasFlags(ContextFlags.EnableVerifier) ? Verifier.Instance : Verifier.Empty; // Initialize main contexts TypeContext = new IRTypeContext(this); IRContext = new IRContext(this); // Create frontend DebugInformationManager frontendDebugInformationManager = HasFlags(ContextFlags.EnableDebugSymbols) ? DebugInformationManager : null; ILFrontend = HasFlags(ContextFlags.EnableParallelCodeGenerationInFrontend) ? new ILFrontend(this, frontendDebugInformationManager) : new ILFrontend(this, frontendDebugInformationManager, 1); // Create default IL backend DefautltILBackend = new DefaultILBackend(this); // Initialize default transformer ContextTransformer = Optimizer.CreateTransformer( OptimizationLevel, TransformerConfiguration.Transformed, Flags); // Intrinsics IntrinsicManager = new IntrinsicImplementationManager(); InitIntrinsics(); }
/// <summary cref="DisposeBase.Dispose(bool)"/> protected override void Dispose(bool disposing) { if (disposing) { codeGenerationSemaphore.Dispose(); IRContext.Dispose(); ILFrontend.Dispose(); DefautltILBackend.Dispose(); DebugInformationManager.Dispose(); TypeContext.Dispose(); } base.Dispose(disposing); }
/// <summary> /// Constructs a new frontend that uses the given number of /// threads for code generation. /// </summary> /// <param name="debugInformationManager">The associated debug information manager.</param> /// <param name="numThreads">The number of threads.</param> public ILFrontend(DebugInformationManager debugInformationManager, int numThreads) { if (numThreads < 1) { throw new ArgumentOutOfRangeException(nameof(numThreads)); } DebugInformationManager = debugInformationManager; driverNotifier = new ManualResetEventSlim(false); threads = new Thread[numThreads]; for (int i = 0; i < numThreads; ++i) { var thread = new Thread(DoWork) { Name = "ILFrontendWorker" + i, IsBackground = true, }; threads[i] = thread; thread.Start(); } }
/// <summary> /// Constructs a new frontend with two threads. /// </summary> /// <param name="context">The context instance.</param> /// <param name="debugInformationManager"> /// The associated debug information manager. /// </param> public ILFrontend( Context context, DebugInformationManager debugInformationManager) : this(context, debugInformationManager, 2) { }
/// <summary> /// Constructs a new frontend with two threads. /// </summary> /// <param name="debugInformationManager">The associated debug information manager.</param> public ILFrontend(DebugInformationManager debugInformationManager) : this(debugInformationManager, 2) { }
/// <summary> /// Constructs a new ILGPU main context /// </summary> /// <param name="builder">The parent builder instance.</param> /// <param name="devices">The array of accelerator descriptions.</param> internal Context( Builder builder, ImmutableArray <Device> devices) { InstanceId = InstanceId.CreateNew(); TargetPlatform = Backend.RuntimePlatform; RuntimeSystem = new RuntimeSystem(); Properties = builder.InstantiateProperties(); // Initialize verifier Verifier = builder.EnableVerifier ? Verifier.Instance : Verifier.Empty; // Initialize main contexts TypeContext = new IRTypeContext(this); IRContext = new IRContext(this); // Initialize intrinsic manager IntrinsicManager = builder.IntrinsicManager; // Create frontend DebugInformationManager frontendDebugInformationManager = Properties.DebugSymbolsMode > DebugSymbolsMode.Disabled ? DebugInformationManager : null; ILFrontend = builder.EnableParallelCodeGenerationInFrontend ? new ILFrontend(this, frontendDebugInformationManager) : new ILFrontend(this, frontendDebugInformationManager, 1); // Create default IL backend DefautltILBackend = new DefaultILBackend(this); // Initialize default transformer ContextTransformer = Optimizer.CreateTransformer( Properties.OptimizationLevel, TransformerConfiguration.Transformed, Properties.InliningMode); // Initialize the default CPU device // NB: Ensure that the current accelerator is not changed when creating the // implicit CPU accelerator. Otherwise, we may unintentionally initialize // Accelerator.Current before an accelerator has been created by the user. var currentAccelerator = Accelerator.Current; CPUAccelerator = new CPUAccelerator( this, CPUDevice.Implicit, CPUAcceleratorMode.Parallel, ThreadPriority.Lowest); Debug.Assert(Accelerator.Current == currentAccelerator); // Initialize all devices Devices = devices; if (devices.IsDefaultOrEmpty) { // Add a default CPU device Devices = ImmutableArray.Create <Device>(CPUDevice.Default); } // Create a mapping deviceMapping = new Dictionary <AcceleratorType, List <Device> >(Devices.Length); foreach (var device in Devices) { if (!deviceMapping.TryGetValue(device.AcceleratorType, out var devs)) { devs = new List <Device>(8); deviceMapping.Add(device.AcceleratorType, devs); } devs.Add(device); } }