File: Compiler\HardwareIntrinsicILProvider.cs
Web Access
Project: src\src\runtime\src\coreclr\tools\aot\ILCompiler.Compiler\ILCompiler.Compiler.csproj (ILCompiler.Compiler)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System;
using System.Collections.Generic;

using Internal.IL;
using Internal.IL.Stubs;
using Internal.JitInterface;
using Internal.TypeSystem;

namespace ILCompiler
{
    public sealed class HardwareIntrinsicILProvider : ILProvider
    {
        private readonly InstructionSetSupport _isaSupport;
        private readonly TypeSystemContext _context;
        private readonly FieldDesc _isSupportedField;
        private readonly ILProvider _nestedProvider;
        private readonly Dictionary<string, InstructionSet> _instructionSetMap;

        public HardwareIntrinsicILProvider(InstructionSetSupport isaSupport, FieldDesc isSupportedField, ILProvider nestedProvider)
        {
            _isaSupport = isaSupport;
            _context = isSupportedField.Context;
            _isSupportedField = isSupportedField;
            _nestedProvider = nestedProvider;

            _instructionSetMap = new Dictionary<string, InstructionSet>();
            foreach (var instructionSetInfo in InstructionSetFlags.ArchitectureToValidInstructionSets(_context.Target.Architecture))
            {
                if (instructionSetInfo.ManagedName != "")
                    _instructionSetMap.Add(instructionSetInfo.ManagedName, instructionSetInfo.InstructionSet);
            }
        }

        public override MethodIL GetMethodIL(MethodDesc method)
        {
            TypeDesc owningType = method.OwningType;
            string intrinsicId = InstructionSetSupport.GetHardwareIntrinsicId(_context.Target.Architecture, owningType);
            if (!string.IsNullOrEmpty(intrinsicId)
                && HardwareIntrinsicHelpers.IsIsSupportedMethod(method))
            {
                InstructionSet instructionSet = _instructionSetMap[intrinsicId];

                bool isSupported = _isaSupport.IsInstructionSetSupported(instructionSet);
                bool isOptimisticallySupported = _isaSupport.OptimisticFlags.HasInstructionSet(instructionSet);

                // If this is an instruction set that is optimistically supported, but is not one of the
                // intrinsics that are known to be always available, emit IL that checks the support level
                // at runtime.
                if (!isSupported && isOptimisticallySupported)
                {
                    return HardwareIntrinsicHelpers.EmitIsSupportedIL(method, _isSupportedField, instructionSet);
                }
                else
                {
                    ILOpcode flag = isSupported ? ILOpcode.ldc_i4_1 : ILOpcode.ldc_i4_0;
                    return new ILStubMethodIL(method,
                        new byte[] { (byte)flag, (byte)ILOpcode.ret },
                        Array.Empty<LocalVariableDefinition>(),
                        null);
                }
            }

            return _nestedProvider.GetMethodIL(method);
        }
    }
}