/// <summary> /// Creates a CIL instruction stream builder. /// </summary> /// <param name="selector"> /// The instruction selector to use. /// </param> public static CilInstructionStreamBuilder Create(CilInstructionSelector selector) { return(new CilInstructionStreamBuilder(selector)); }
/// <summary> /// Compiles the source body to a CIL method body. /// </summary> /// <returns>A CIL method body.</returns> public Mono.Cecil.Cil.MethodBody Compile() { // Create a method body. var result = new Mono.Cecil.Cil.MethodBody(Method); // Figure out which 'alloca' values can be replaced // by local variables. Usually, that's all of them. var sourceGraph = SourceBody.Implementation; var allocaToVarMap = AllocasToVariables(sourceGraph); // Select instructions. var selector = new CilInstructionSelector(Method, TypeEnvironment, allocaToVarMap); var streamBuilder = new LinearInstructionStreamBuilder <CilCodegenInstruction>( selector); var codegenInsns = streamBuilder.ToInstructionStream(sourceGraph); codegenInsns = OptimizeRegisterAccesses(codegenInsns); // Find the set of loaded values so we can allocate registers to them. var loadedValues = new HashSet <ValueTag>( codegenInsns .SelectMany(insn => insn.Traversal) .OfType <CilLoadRegisterInstruction>() .Select(insn => insn.Value)); loadedValues.UnionWith( codegenInsns .SelectMany(insn => insn.Traversal) .OfType <CilAddressOfRegisterInstruction>() .Select(insn => insn.Value)); // Allocate registers to values. var regAllocator = new CilRegisterAllocator( loadedValues, GetPreallocatedRegisters(sourceGraph), Method.Module); var regAllocation = regAllocator.Analyze(sourceGraph); // Synthesize the actual method body. var processor = result.GetILProcessor(); var emitter = new CodegenEmitter(processor, regAllocation); emitter.Emit(codegenInsns); // Add local variables to method body. Put most popular // locals first to minimize the number of long-form ldloc/stloc // instructions. result.InitLocals = true; foreach (var pair in emitter.RegisterUseCounts.OrderByDescending(pair => pair.Value)) { result.Variables.Add(pair.Key); } foreach (var local in allocaToVarMap.Values) { result.Variables.Add(local); } foreach (var temp in selector.Temporaries) { result.Variables.Add(temp); } // Apply peephole optimizations to the generated method body. CilPeepholeOptimizer.Optimize(result); // Apply Cecil's macro optimizations to the generated method body. MethodBodyRocks.Optimize(result); return(result); }
/// <summary> /// Creates a CIL instruction stream builder. /// </summary> /// <param name="selector">An instruction selector.</param> private CilInstructionStreamBuilder(CilInstructionSelector selector) : base(selector) { }