Example #1
0
            private void Emit(CilInstruction instruction)
            {
                // Emit the actual instruction.
                Processor.Append(instruction);

                // Mark pending branch targets.
                foreach (var tag in pendingTargets)
                {
                    branchTargets[tag] = instruction;
                }
                pendingTargets.Clear();
            }
Example #2
0
            private void Emit(CilCodegenInstruction instruction)
            {
                if (instruction is CilMarkTargetInstruction)
                {
                    pendingTargets.Add(((CilMarkTargetInstruction)instruction).Target);
                }
                else if (instruction is CilOpInstruction)
                {
                    var opInsn = (CilOpInstruction)instruction;

                    // Emit the instruction.
                    Emit(opInsn.Op);

                    // Add an entry to the patch list if necessary.
                    if (opInsn.Patch != null)
                    {
                        patches.Add(opInsn);
                    }
                }
                else if (instruction is CilExceptionHandlerInstruction)
                {
                    var handlerInsn = (CilExceptionHandlerInstruction)instruction;

                    // Create the actual exception handler.
                    var handler = new Mono.Cecil.Cil.ExceptionHandler(handlerInsn.Type);
                    if (handlerInsn.Type == Mono.Cecil.Cil.ExceptionHandlerType.Catch)
                    {
                        handler.CatchType = handlerInsn.CatchType;
                    }
                    Processor.Body.ExceptionHandlers.Add(handler);

                    // Emit the try block's contents. Record the last instruction
                    // prior to the try block. We'll use it to find the first instruction
                    // inside the try block when we add a handler to the
                    var preTryInstruction = Processor.Body.Instructions.LastOrDefault();
                    foreach (var insn in handlerInsn.TryBlock)
                    {
                        Emit(insn);
                    }

                    // Similarly, record the last instruction of the 'try' block and then
                    // proceed by emitting the handler block.
                    var lastTryInstruction = Processor.Body.Instructions.LastOrDefault();
                    foreach (var insn in handlerInsn.HandlerBlock)
                    {
                        Emit(insn);
                    }

                    // Populate the exception handler's start/end fields.
                    handler.TryStart = preTryInstruction == null
                        ? Processor.Body.Instructions.First()
                        : preTryInstruction.Next;

                    handler.TryEnd = lastTryInstruction == null
                        ? Processor.Body.Instructions.First()
                        : lastTryInstruction.Next;

                    handler.HandlerStart = handler.TryEnd;
                    handler.HandlerEnd   = Processor.Create(OpCodes.Nop);
                    Processor.Append(handler.HandlerEnd);
                }
                else if (instruction is CilLoadRegisterInstruction)
                {
                    var loadInsn = (CilLoadRegisterInstruction)instruction;
                    var reg      = RegisterAllocation.GetRegister(loadInsn.Value);
                    if (reg.IsParameter)
                    {
                        Emit(CilInstruction.Create(OpCodes.Ldarg, reg.ParameterOrNull));
                    }
                    else
                    {
                        IncrementUseCount(reg.VariableOrNull);
                        Emit(CilInstruction.Create(OpCodes.Ldloc, reg.VariableOrNull));
                    }
                }
                else if (instruction is CilAddressOfRegisterInstruction)
                {
                    var addressOfInsn = (CilAddressOfRegisterInstruction)instruction;
                    var reg           = RegisterAllocation.GetRegister(addressOfInsn.Value);
                    if (reg.IsParameter)
                    {
                        Emit(CilInstruction.Create(OpCodes.Ldarga, reg.ParameterOrNull));
                    }
                    else
                    {
                        IncrementUseCount(reg.VariableOrNull);
                        Emit(CilInstruction.Create(OpCodes.Ldloca, reg.VariableOrNull));
                    }
                }
                else
                {
                    var storeInsn = (CilStoreRegisterInstruction)instruction;
                    if (RegisterAllocation.Allocation.ContainsKey(storeInsn.Value))
                    {
                        var reg = RegisterAllocation.GetRegister(storeInsn.Value);
                        if (reg.IsParameter)
                        {
                            Emit(CilInstruction.Create(OpCodes.Starg, reg.ParameterOrNull));
                        }
                        else
                        {
                            IncrementUseCount(reg.VariableOrNull);
                            Emit(CilInstruction.Create(OpCodes.Stloc, reg.VariableOrNull));
                        }
                    }
                    else
                    {
                        Emit(CilInstruction.Create(OpCodes.Pop));
                    }
                }
            }
Example #3
0
            private void Emit(CilCodegenInstruction instruction)
            {
                if (instruction is CilMarkTargetInstruction)
                {
                    pendingTargets.Add(((CilMarkTargetInstruction)instruction).Target);
                }
                else if (instruction is CilOpInstruction)
                {
                    var opInsn = (CilOpInstruction)instruction;

                    // Emit the instruction.
                    Emit(opInsn.Op);

                    // Add an entry to the patch list if necessary.
                    if (opInsn.Patch != null)
                    {
                        patches.Add(opInsn);
                    }
                }
                else if (instruction is CilTryStartMarker)
                {
                    var tag = new BasicBlockTag("try-start");
                    pendingTargets.Add(tag);
                    pendingTryHandlers.Push(tag);
                }
                else if (instruction is CilHandlerStartMarker)
                {
                    var tryStart   = pendingTryHandlers.Pop();
                    var catchStart = new BasicBlockTag("catch-start");
                    pendingTargets.Add(catchStart);
                    pendingHandlers.Push(
                        Tuple.Create(
                            tryStart,
                            catchStart,
                            ((CilHandlerStartMarker)instruction).Handler));
                }
                else if (instruction is CilHandlerEndMarker)
                {
                    var handlerTriple = pendingHandlers.Pop();

                    var tryStart     = handlerTriple.Item1;
                    var handlerStart = handlerTriple.Item2;
                    var handler      = handlerTriple.Item3;
                    Processor.Body.ExceptionHandlers.Add(handler);

                    // Populate the exception handler's start/end fields.
                    handler.TryStart     = branchTargets[tryStart];
                    handler.TryEnd       = branchTargets[handlerStart];
                    handler.HandlerStart = handler.TryEnd;
                    handler.HandlerEnd   = Processor.Create(OpCodes.Nop);
                    Processor.Append(handler.HandlerEnd);
                }
                else if (instruction is CilLoadRegisterInstruction)
                {
                    var loadInsn = (CilLoadRegisterInstruction)instruction;
                    var reg      = RegisterAllocation.GetRegister(loadInsn.Value);
                    if (reg.IsParameter)
                    {
                        Emit(CilInstruction.Create(OpCodes.Ldarg, reg.ParameterOrNull));
                    }
                    else
                    {
                        IncrementUseCount(reg.VariableOrNull);
                        Emit(CilInstruction.Create(OpCodes.Ldloc, reg.VariableOrNull));
                    }
                }
                else if (instruction is CilAddressOfRegisterInstruction)
                {
                    var addressOfInsn = (CilAddressOfRegisterInstruction)instruction;
                    var reg           = RegisterAllocation.GetRegister(addressOfInsn.Value);
                    if (reg.IsParameter)
                    {
                        Emit(CilInstruction.Create(OpCodes.Ldarga, reg.ParameterOrNull));
                    }
                    else
                    {
                        IncrementUseCount(reg.VariableOrNull);
                        Emit(CilInstruction.Create(OpCodes.Ldloca, reg.VariableOrNull));
                    }
                }
                else
                {
                    var storeInsn = (CilStoreRegisterInstruction)instruction;
                    if (RegisterAllocation.Allocation.ContainsKey(storeInsn.Value))
                    {
                        var reg = RegisterAllocation.GetRegister(storeInsn.Value);
                        if (reg.IsParameter)
                        {
                            Emit(CilInstruction.Create(OpCodes.Starg, reg.ParameterOrNull));
                        }
                        else
                        {
                            IncrementUseCount(reg.VariableOrNull);
                            Emit(CilInstruction.Create(OpCodes.Stloc, reg.VariableOrNull));
                        }
                    }
                    else
                    {
                        Emit(CilInstruction.Create(OpCodes.Pop));
                    }
                }
            }