Exemplo n.º 1
0
 /// <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));
 }
Exemplo n.º 2
0
        /// <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);
        }
Exemplo n.º 3
0
 /// <summary>
 /// Creates a CIL instruction stream builder.
 /// </summary>
 /// <param name="selector">An instruction selector.</param>
 private CilInstructionStreamBuilder(CilInstructionSelector selector)
     : base(selector)
 {
 }