/// <summary> /// Constructs a new disassembler. /// </summary> /// <param name="methodBase">The target method.</param> /// <param name="sequencePointEnumerator"> /// The associated sequence-point enumerator. /// </param> /// <param name="compilationStackLocation">The source location (optional).</param> public Disassembler( MethodBase methodBase, SequencePointEnumerator sequencePointEnumerator, CompilationStackLocation compilationStackLocation = null) { MethodBase = methodBase ?? throw new ArgumentNullException(nameof(methodBase)); MethodGenericArguments = MethodBase is MethodInfo ? MethodBase.GetGenericArguments() : Array.Empty <Type>(); TypeGenericArguments = MethodBase.DeclaringType.GetGenericArguments(); MethodBody = MethodBase.GetMethodBody(); if (MethodBody == null) { throw new NotSupportedException(string.Format( ErrorMessages.NativeMethodNotSupported, MethodBase.Name)); } il = MethodBody.GetILAsByteArray(); instructions = ImmutableArray.CreateBuilder <ILInstruction>(il.Length); debugInformationEnumerator = sequencePointEnumerator; this.compilationStackLocation = compilationStackLocation; CurrentLocation = new Method.MethodLocation(methodBase); }
/// <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); } }
public ProcessingEntry( MethodBase method, CompilationStackLocation compilationStackLocation, CodeGenerationResult result) { Method = method; CompilationStackLocation = compilationStackLocation; Result = result; }
/// <summary> /// Creates a call instruction to the given method with the given arguments. /// </summary> /// <param name="method">The target method to invoke.</param> /// <param name="arguments">The call arguments.</param> private void CreateCall( MethodBase method, ref ValueList arguments) { var intrinsicContext = new InvocationContext( this, CompilationStackLocation.Append(Location), Block, Method, method, ref arguments); // Check for internal remappings first RemappedIntrinsics.RemapIntrinsic(ref intrinsicContext); // Early rejection for runtime-dependent methods VerifyNotRuntimeMethod(intrinsicContext.Method); // Handle device functions if (!Intrinsics.HandleIntrinsic(ref intrinsicContext, out var result)) { var targetFunction = DeclareMethod(intrinsicContext.Method); result = Builder.CreateCall( Location, targetFunction, ref arguments); } // Setup result if (result.IsValid && !result.Type.IsVoidType) { var flags = method.GetReturnType().IsUnsignedInt() ? ConvertFlags.SourceUnsigned : ConvertFlags.None; Block.Push(LoadOntoEvaluationStack(result, flags)); } }