Beispiel #1
0
        /// <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);
        }
Beispiel #2
0
        /// <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);
            }
        }
Beispiel #3
0
        /// <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);
            }
        }
Beispiel #4
0
        /// <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);
        }
Beispiel #5
0
        /// <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();
        }
Beispiel #6
0
        /// <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);
        }
Beispiel #7
0
 /// <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();
     }
 }
Beispiel #8
0
 /// <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)
 {
 }
Beispiel #9
0
 /// <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)
 {
 }
Beispiel #10
0
        /// <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);
            }
        }