예제 #1
0
 public void VisitCompilationUnit(CilCompilationUnit unit)
 {
     foreach (var child in unit.GetChildren())
     {
         child.AcceptVisitor(this);
     }
 }
예제 #2
0
        private void BindVariablesToSignatures(CilCompilationUnit unit)
        {
            foreach (var variable in unit.Variables)
            {
                _context.Variables.Add(variable, new VariableSignature(variable.VariableType));
            }

            foreach (var parameter in unit.Parameters)
            {
                int cilIndex = parameter.ParameterIndex - (_context.MethodBody.Method.Signature.HasThis ? 1 : 0);
                ParameterSignature parameterSig;

                if (cilIndex == -1)
                {
                    parameterSig = _context.MethodBody.ThisParameter;
                }
                else
                {
                    parameterSig = _context.MethodBody.Method.Signature.Parameters[cilIndex];
                    parameterSig.ParameterType = parameter.VariableType;
                }

                _context.Parameters.Add(parameter, parameterSig);
            }
        }
예제 #3
0
        private void CreateExceptionHandlers(CilCompilationUnit unit, CilInstructionCollection result)
        {
            foreach (var subGraph in unit.ControlFlowGraph.SubGraphs)
            {
                var ehFrame = (EHFrame)subGraph.UserData[EHFrame.EHFrameProperty];

                CilExceptionHandlerType type;
                switch (ehFrame.Type)
                {
                case EHType.CATCH:
                    type = CilExceptionHandlerType.Exception;
                    break;

                case EHType.FILTER:
                    type = CilExceptionHandlerType.Filter;
                    break;

                case EHType.FAULT:
                    type = CilExceptionHandlerType.Fault;
                    break;

                case EHType.FINALLY:
                    type = CilExceptionHandlerType.Finally;
                    break;

                default:
                    throw new ArgumentOutOfRangeException();
                }

                // Find first and last nodes of try block.
                var tryBody = (ICollection <Node>)subGraph.UserData[ControlFlowGraph.TryBlockProperty];
                var(tryStartNode, tryEndNode) = FindMinMaxNodes(tryBody);

                // Find first and last nodes of handler block.
                var handlerBody = (ICollection <Node>)subGraph.UserData[ControlFlowGraph.HandlerBlockProperty];
                var(handlerStartNode, handlerEndNode) = FindMinMaxNodes(handlerBody);

                // Create handler.
                var handler = new CilExceptionHandler();
                handler.HandlerType = type;

                handler.TryStart = new CilInstructionLabel(_blockEntries[tryStartNode]);
                handler.TryEnd   = GetHandlerEndLabel(result, tryEndNode, "try");

                handler.HandlerStart = new CilInstructionLabel(_blockEntries[handlerStartNode]);
                handler.HandlerEnd   = GetHandlerEndLabel(result, handlerEndNode, "handler");

                handler.ExceptionType = ehFrame.CatchType;

                if (ehFrame.Type == EHType.FILTER)
                {
                    var filterStartNode = (Node)subGraph.UserData[ControlFlowGraph.FilterStartProperty];
                    handler.FilterStart = new CilInstructionLabel(_blockEntries[filterStartNode]);
                }

                _context.ExceptionHandlers.Add(ehFrame, handler);
            }
        }
예제 #4
0
        private void CreateExceptionHandlers(CilCompilationUnit unit, CilInstructionCollection result)
        {
            foreach (var subGraph in unit.ControlFlowGraph.SubGraphs)
            {
                var ehFrame = (EHFrame)subGraph.UserData[EHFrame.EHFrameProperty];

                ExceptionHandlerType type;
                switch (ehFrame.Type)
                {
                case EHType.CATCH:
                    type = ExceptionHandlerType.Exception;
                    break;

                case EHType.FILTER:
                    type = ExceptionHandlerType.Filter;
                    break;

                case EHType.FAULT:
                    type = ExceptionHandlerType.Fault;
                    break;

                case EHType.FINALLY:
                    type = ExceptionHandlerType.Finally;
                    break;

                default:
                    throw new ArgumentOutOfRangeException();
                }

                // Find first and last nodes of try block.
                var tryBody = (ICollection <Node>)subGraph.UserData[ControlFlowGraph.TryBlockProperty];
                var(tryStartNode, tryEndNode) = FindMinMaxNodes(tryBody);

                // Find first and last nodes of handler block.
                var handlerBody = (ICollection <Node>)subGraph.UserData[ControlFlowGraph.HandlerBlockProperty];
                var(handlerStartNode, handlerEndNode) = FindMinMaxNodes(handlerBody);

                // Create handler.
                var handler = new ExceptionHandler(type)
                {
                    TryStart = _blockEntries[tryStartNode],
                    TryEnd   = result.GetByOffset(_blockExits[tryEndNode].Offset + _blockExits[tryEndNode].Size)
                               ?? throw new CilCodeGeneratorException(
                                         $"Could not infer end of try block in {_context.MethodBody.Method.Name}."),
                                     HandlerStart = _blockEntries[handlerStartNode],
                                     HandlerEnd   = result.GetByOffset(_blockExits[handlerEndNode].Offset + _blockExits[handlerEndNode].Size)
                                                    ?? throw new CilCodeGeneratorException(
                                                              $"Could not infer end of handler block in {_context.MethodBody.Method.Name}."),
                                                          CatchType = ehFrame.CatchType
                };

                _context.ExceptionHandlers.Add(ehFrame, handler);
            }
        }
예제 #5
0
        public virtual bool VisitCompilationUnit(CilCompilationUnit unit)
        {
            bool changed = false;

            foreach (var node in unit.ControlFlowGraph.Nodes)
            {
                var block = (CilAstBlock)node.UserData[CilAstBlock.AstBlockProperty];
                changed |= block.AcceptVisitor(this);
            }

            return(changed);
        }
예제 #6
0
        public virtual bool ApplyTransformation(RecompilerContext context, CilCompilationUnit unit)
        {
            bool changed = false;

            while (unit.AcceptVisitor(this))
            {
                changed = true;
                // Repeat until no more changes.
            }

            return(changed);
        }
예제 #7
0
        public IList <CilInstruction> VisitCompilationUnit(CilCompilationUnit unit)
        {
            // Add variable signatures to the end result.
            BindVariablesToSignatures(unit);

            var result = GenerateInstructions(unit);

            var instructions = new CilInstructionCollection(_context.MethodBody);

            instructions.AddRange(result);
            instructions.CalculateOffsets();

            CreateExceptionHandlers(unit, instructions);

            return(instructions);
        }
예제 #8
0
        public CilMethodBody Compile(MethodDefinition method, CilCompilationUnit unit)
        {
            var methodBody = new CilMethodBody(method);

            var context = new CodeGenerationContext(methodBody, _constants, unit.FlagVariable, _flagHelperType);

            var cilGenerator = new CilCodeGenerator(context);

            context.CodeGenerator = cilGenerator;

            // Traverse and recompile the AST.
            methodBody.Instructions.AddRange(unit.AcceptVisitor(cilGenerator));

            // Add variables to the method body.
            if (context.Variables.Count > 0)
            {
                foreach (var variable in context.Variables.Values)
                {
                    methodBody.LocalVariables.Add(variable);
                }
                methodBody.InitializeLocals = true;
            }

            methodBody.Instructions.OptimizeMacros();

            // Add all generated exception handlers to the method body.
            var handlers = context.ExceptionHandlers.Values.ToList();

            handlers.Sort(new EHComparer());
            foreach (var handler in handlers)
            {
                if (EnableExceptionHandlerValidation)
                {
                    AssertValidityExceptionHandler(method, handler);
                }
                methodBody.ExceptionHandlers.Add(handler);
            }

            if (!EnableStackVerification)
            {
                methodBody.ComputeMaxStackOnBuild = false;
                methodBody.MaxStack = ushort.MaxValue;
            }

            return(methodBody);
        }
예제 #9
0
        public override bool VisitCompilationUnit(CilCompilationUnit unit)
        {
            bool changed = false;

            // Go over each variable, and figure out the common base type of all the values that are assigned to it.
            // This is the new variable type.
            foreach (var variable in unit.Variables.Where(x => x.UsedBy.Count > 0))
            {
                changed |= TryInferVariableType(variable);
            }

            foreach (var parameter in unit.Parameters.Where(x => x.UsedBy.Count > 0 && !x.HasFixedType))
            {
                changed |= TryInferVariableType(parameter);
            }

            return(changed);
        }
예제 #10
0
        private IList <CilInstruction> GenerateInstructions(CilCompilationUnit unit)
        {
            // Define block headers to use as branch targets later.
            foreach (var node in unit.ControlFlowGraph.Nodes)
            {
                _context.BlockHeaders[node] = CilInstruction.Create(CilOpCodes.Nop);
            }

            var generator = new BlockGenerator(unit.ControlFlowGraph, this);
            var rootScope = generator.CreateBlock();

            var result = rootScope.GenerateInstructions();

            _blockEntries = generator.BlockEntries;
            _blockExits   = generator.BlockExits;

            return(result);
        }
예제 #11
0
        private void BindVariablesToSignatures(CilCompilationUnit unit)
        {
            foreach (var variable in unit.Variables)
            {
                _context.Variables.Add(variable, new CilLocalVariable(variable.VariableType));
            }

            foreach (var parameter in unit.Parameters)
            {
                var physicalParameter = _context.MethodBody.Owner.Parameters
                                        .GetBySignatureIndex(parameter.ParameterIndex);

                if (physicalParameter != _context.MethodBody.Owner.Parameters.ThisParameter)
                {
                    physicalParameter.ParameterType = parameter.VariableType;
                }

                _context.Parameters.Add(parameter, physicalParameter);
            }
        }
 public override bool ApplyTransformation(RecompilerContext context, CilCompilationUnit unit)
 {
     _context = context;
     return(base.ApplyTransformation(context, unit));
 }
예제 #13
0
 public void ApplyTransformation(RecompilerContext context, CilCompilationUnit unit)
 {
     _context = context;
     VisitCompilationUnit(unit);
 }
예제 #14
0
 void ICilAstTransform.ApplyTransformation(RecompilerContext context, CilCompilationUnit unit)
 {
     ApplyTransformation(context, unit);
 }
예제 #15
0
 public override bool ApplyTransformation(RecompilerContext context, CilCompilationUnit unit)
 {
     _context = context;
     _helper  = new TypeHelper(context.ReferenceImporter);
     return(base.ApplyTransformation(context, unit));
 }
예제 #16
0
 public CilTransformEventArgs(CilCompilationUnit unit, ICilAstTransform transform)
 {
     Transform = transform;
     Unit      = unit;
 }
예제 #17
0
 public string VisitCompilationUnit(CilCompilationUnit unit) => "unit";