// Direct call
        private void ProcessDCall(IRInstrList instrs, IRInstruction instr, int index, IRTransformer tr, MethodDef method)
        {
            var retVar   = (IRVariable)instr.Operand2;
            var callinfo = (InstrCallInfo)instr.Annotation;

            callinfo.Method = method; // Ensure it's resolved

            var callInstrs = new List <IRInstruction>();

            callInstrs.Add(new IRInstruction(IROpCode.CALL, new IRMetaTarget(method)
            {
                LateResolve = true
            })
            {
                Annotation = instr.Annotation,
                ILAST      = instr.ILAST
            });
            if (retVar != null)
            {
                callInstrs.Add(new IRInstruction(IROpCode.MOV, retVar, new IRRegister(DarksVMRegisters.R0, retVar.Type))
                {
                    Annotation = instr.Annotation,
                    ILAST      = instr.ILAST
                });
            }
            int stackAdjust = -callinfo.Arguments.Length;

            callInstrs.Add(new IRInstruction(IROpCode.ADD, IRRegister.SP, IRConstant.FromI4(stackAdjust))
            {
                Annotation = instr.Annotation,
                ILAST      = instr.ILAST
            });

            instrs.Replace(index, callInstrs);
        }
Пример #2
0
        public ILInstrList Translate(IRInstrList instrs)
        {
            Instructions = new ILInstrList();

            var i = 0;

            foreach (var instr in instrs)
            {
                ITranslationHandler handler;
                if (!handlers.TryGetValue(instr.OpCode, out handler))
                {
                    throw new NotSupportedException(instr.OpCode.ToString());
                }
                try
                {
                    handler.Translate(instr, this);
                }
                catch (Exception ex)
                {
                    throw new Exception(string.Format("Failed to translate ir {0}.", instr.ILAST), ex);
                }
                while (i < Instructions.Count)
                {
                    Instructions[i].IR = instr;
                    i++;
                }
            }

            var ret = Instructions;

            Instructions = null;
            return(ret);
        }
        private void VisitInstr(IRInstrList instrs, IRInstruction instr, ref int index, IRTransformer tr)
        {
            switch (instr.OpCode)
            {
            case IROpCode.MOV:
            case IROpCode.NOR:
            case IROpCode.CMP:
            case IROpCode.ADD:
            case IROpCode.MUL:
            case IROpCode.DIV:
            case IROpCode.REM:
            case IROpCode.__OR:
            case IROpCode.__AND:
            case IROpCode.__XOR:
            case IROpCode.__GETF:
                break;

            default:
                return;
            }
            Debug.Assert(instr.Operand1 != null && instr.Operand2 != null);
            if (instr.Operand1 is IRConstant)
            {
                instr.Operand1 = PromoteConstant((IRConstant)instr.Operand1, instr.Operand2.Type);
            }
            if (instr.Operand2 is IRConstant)
            {
                instr.Operand2 = PromoteConstant((IRConstant)instr.Operand2, instr.Operand1.Type);
            }
        }
        private void VisitInstr(IRInstrList instrs, IRInstruction instr, ref int index, IRTransformer tr)
        {
            if (instr.OpCode != IROpCode.__CALL && instr.OpCode != IROpCode.__CALLVIRT &&
                instr.OpCode != IROpCode.__NEWOBJ)
            {
                return;
            }

            MethodDef method   = ((IMethod)((IRMetaTarget)instr.Operand1).MetadataItem).ResolveMethodDef();
            var       callInfo = (InstrCallInfo)instr.Annotation;

            if (method == null ||
                method.Module != tr.Context.Method.Module || // TODO: cross-module direct call
                !tr.VM.Settings.IsVirtualized(method) ||
                instr.OpCode != IROpCode.__CALL)
            {
                callInfo.IsECall = true;
                this.ProcessECall(instrs, instr, index, tr);
            }
            else
            {
                callInfo.IsECall = false;
                this.ProcessDCall(instrs, instr, index, tr, method);
            }
        }
        // External call
        private void ProcessECall(IRInstrList instrs, IRInstruction instr, int index, IRTransformer tr)
        {
            var method = (IMethod)((IRMetaTarget)instr.Operand1).MetadataItem;
            var retVar = (IRVariable)instr.Operand2;

            uint          opCode        = 0;
            ITypeDefOrRef constrainType = ((InstrCallInfo)instr.Annotation).ConstrainType;

            if (instr.OpCode == IROpCode.__CALL)
            {
                opCode = tr.VM.Runtime.VCallOps.ECALL_CALL;
            }
            else if (instr.OpCode == IROpCode.__CALLVIRT)
            {
                if (constrainType != null)
                {
                    opCode = tr.VM.Runtime.VCallOps.ECALL_CALLVIRT_CONSTRAINED;
                }
                else
                {
                    opCode = tr.VM.Runtime.VCallOps.ECALL_CALLVIRT;
                }
            }
            else if (instr.OpCode == IROpCode.__NEWOBJ)
            {
                opCode = tr.VM.Runtime.VCallOps.ECALL_NEWOBJ;
            }

            int methodId   = (int)(tr.VM.Data.GetId(method) | (opCode << 30));
            int ecallId    = tr.VM.Runtime.VMCall.ECALL;
            var callInstrs = new List <IRInstruction>();

            if (constrainType != null)
            {
                callInstrs.Add(new IRInstruction(IROpCode.PUSH)
                {
                    Operand1   = IRConstant.FromI4((int)tr.VM.Data.GetId(constrainType)),
                    Annotation = instr.Annotation,
                    ILAST      = instr.ILAST
                });
            }
            callInstrs.Add(new IRInstruction(IROpCode.VCALL)
            {
                Operand1   = IRConstant.FromI4(ecallId),
                Operand2   = IRConstant.FromI4(methodId),
                Annotation = instr.Annotation,
                ILAST      = instr.ILAST
            });
            if (retVar != null)
            {
                callInstrs.Add(new IRInstruction(IROpCode.POP, retVar)
                {
                    Annotation = instr.Annotation,
                    ILAST      = instr.ILAST
                });
            }
            instrs.Replace(index, callInstrs);
        }
Пример #6
0
 void VisitInstr(IRInstrList instrs, IRInstruction instr, ref int index, IRTransformer tr)
 {
     if (instr.OpCode == IROpCode.__LEA)
     {
         var source = (IRPointer)instr.Operand2;
         var target = instr.Operand1;
         Debug.Assert(source.Register == IRRegister.BP);
         instrs.Replace(index, new[] {
             new IRInstruction(IROpCode.MOV, target, IRRegister.BP, instr),
             new IRInstruction(IROpCode.ADD, target, IRConstant.FromI4(source.Offset), instr)
         });
     }
 }
Пример #7
0
        private void VisitInstr(IRInstrList instrs, IRInstruction instr, ref int index, IRTransformer tr)
        {
            switch (instr.OpCode)
            {
            case IROpCode.__NOT:
                instrs.Replace(index, new[]
                {
                    new IRInstruction(IROpCode.NOR, instr.Operand1, instr.Operand1, instr)
                });
                break;

            case IROpCode.__AND:
            {
                IRVariable tmp = tr.Context.AllocateVRegister(instr.Operand2.Type);
                instrs.Replace(index, new[]
                    {
                        new IRInstruction(IROpCode.MOV, tmp, instr.Operand2, instr),
                        new IRInstruction(IROpCode.NOR, instr.Operand1, instr.Operand1, instr),
                        new IRInstruction(IROpCode.NOR, tmp, tmp, instr),
                        new IRInstruction(IROpCode.NOR, instr.Operand1, tmp, instr)
                    });
                break;
            }

            case IROpCode.__OR:
                instrs.Replace(index, new[]
                {
                    new IRInstruction(IROpCode.NOR, instr.Operand1, instr.Operand2, instr),
                    new IRInstruction(IROpCode.NOR, instr.Operand1, instr.Operand1, instr)
                });
                break;

            case IROpCode.__XOR:
            {
                IRVariable tmp1 = tr.Context.AllocateVRegister(instr.Operand2.Type);
                IRVariable tmp2 = tr.Context.AllocateVRegister(instr.Operand2.Type);
                instrs.Replace(index, new[]
                    {
                        new IRInstruction(IROpCode.MOV, tmp1, instr.Operand1, instr),
                        new IRInstruction(IROpCode.NOR, tmp1, instr.Operand2, instr),
                        new IRInstruction(IROpCode.MOV, tmp2, instr.Operand2, instr),
                        new IRInstruction(IROpCode.NOR, instr.Operand1, instr.Operand1, instr),
                        new IRInstruction(IROpCode.NOR, tmp2, tmp2, instr),
                        new IRInstruction(IROpCode.NOR, instr.Operand1, tmp2, instr),
                        new IRInstruction(IROpCode.NOR, instr.Operand1, tmp1, instr)
                    });
                break;
            }
            }
        }
Пример #8
0
 void VisitInstr(IRInstrList instrs, IRInstruction instr, ref int index, IRTransformer tr)
 {
     if (instr.OpCode == IROpCode.RET)
     {
         instrs.Replace(index, new[] {
             new IRInstruction(IROpCode.JMP, new IRBlockTarget(epilog))
         });
         if (!tr.Block.Targets.Contains(epilog))
         {
             tr.Block.Targets.Add(epilog);
             epilog.Sources.Add(tr.Block);
         }
     }
 }
Пример #9
0
        void CompileCode(Node node)
        {
            string name   = ((Token)node[1]).Image;
            var    instrs = new IRInstrList();

            for (int i = 0; i < node.Count; i++)
            {
                var child = node[i];
                if (child.Id == (int)IRConstants.INSTR)
                {
                    instrs.Add(ReadInstr(child));
                }
            }
            codes[name] = new BasicBlock <IRInstrList>(0, instrs);
        }
        private void VisitInstr(IRInstrList instrs, IRInstruction instr, ref int index, IRTransformer tr)
        {
            if (!(instr.Annotation is InstrCallInfo callInfo) || callInfo.ReturnValue == null)
            {
                return;
            }

            if (instr.Operand1 is IRRegister && ((IRRegister)instr.Operand1).SourceVariable == callInfo.ReturnValue)
            {
                callInfo.ReturnRegister = (IRRegister)instr.Operand1;
            }
            else if (instr.Operand1 is IRPointer && ((IRPointer)instr.Operand1).SourceVariable == callInfo.ReturnValue)
            {
                callInfo.ReturnSlot = (IRPointer)instr.Operand1;
            }
        }
Пример #11
0
 void VisitInstr(IRInstrList instrs, IRInstruction instr, ref int index, IRTransformer tr)
 {
     if (instr.OpCode == IROpCode.__GETF)
     {
         instrs.Replace(index, new[] {
             new IRInstruction(IROpCode.MOV, instr.Operand1, IRRegister.FL, instr),
             new IRInstruction(IROpCode.__AND, instr.Operand1, instr.Operand2, instr)
         });
     }
     else if (instr.OpCode == IROpCode.__SETF)
     {
         instrs.Replace(index, new[] {
             new IRInstruction(IROpCode.__OR, IRRegister.FL, instr.Operand1, instr)
         });
     }
 }
Пример #12
0
 private void VisitInstr(IRInstrList instrs, IRInstruction instr, ref int index, IRTransformer tr)
 {
     if (instr.OpCode == IROpCode.__NOT)
     {
         instrs.Replace(index, new[]
         {
             new IRInstruction(IROpCode.NOR, instr.Operand1, instr.Operand1, instr)
         });
     }
     else if (instr.OpCode == IROpCode.__AND)
     {
         var tmp = tr.Context.AllocateVRegister(instr.Operand2.Type);
         instrs.Replace(index, new[]
         {
             new IRInstruction(IROpCode.MOV, tmp, instr.Operand2, instr),
             new IRInstruction(IROpCode.NOR, instr.Operand1, instr.Operand1, instr),
             new IRInstruction(IROpCode.NOR, tmp, tmp, instr),
             new IRInstruction(IROpCode.NOR, instr.Operand1, tmp, instr)
         });
     }
     else if (instr.OpCode == IROpCode.__OR)
     {
         instrs.Replace(index, new[]
         {
             new IRInstruction(IROpCode.NOR, instr.Operand1, instr.Operand2, instr),
             new IRInstruction(IROpCode.NOR, instr.Operand1, instr.Operand1, instr)
         });
     }
     else if (instr.OpCode == IROpCode.__XOR)
     {
         var tmp1 = tr.Context.AllocateVRegister(instr.Operand2.Type);
         var tmp2 = tr.Context.AllocateVRegister(instr.Operand2.Type);
         instrs.Replace(index, new[]
         {
             new IRInstruction(IROpCode.MOV, tmp1, instr.Operand1, instr),
             new IRInstruction(IROpCode.NOR, tmp1, instr.Operand2, instr),
             new IRInstruction(IROpCode.MOV, tmp2, instr.Operand2, instr),
             new IRInstruction(IROpCode.NOR, instr.Operand1, instr.Operand1, instr),
             new IRInstruction(IROpCode.NOR, tmp2, tmp2, instr),
             new IRInstruction(IROpCode.NOR, instr.Operand1, tmp2, instr),
             new IRInstruction(IROpCode.NOR, instr.Operand1, tmp1, instr)
         });
     }
 }
Пример #13
0
 void VisitInstr(IRInstrList instrs, IRInstruction instr, ref int index, IRTransformer tr)
 {
     if (instr.OpCode == IROpCode.__ENTRY && !doneEntry)
     {
         instrs.Replace(index, new[] {
             instr,
             new IRInstruction(IROpCode.PUSH, IRRegister.BP),
             new IRInstruction(IROpCode.MOV, IRRegister.BP, IRRegister.SP),
             new IRInstruction(IROpCode.ADD, IRRegister.SP, IRConstant.FromI4(allocator.LocalSize))
         });
         doneEntry = true;
     }
     else if (instr.OpCode == IROpCode.__EXIT && !doneExit)
     {
         instrs.Replace(index, new[] {
             new IRInstruction(IROpCode.MOV, IRRegister.SP, IRRegister.BP),
             new IRInstruction(IROpCode.POP, IRRegister.BP),
             instr
         });
         doneExit = true;
     }
 }
Пример #14
0
        private void VisitInstr(IRInstrList instrs, IRInstruction instr, ref int index, IRTransformer tr)
        {
            if (instr.OpCode != IROpCode.__LEAVE)
            {
                return;
            }

            var targetScopes = tr.RootScope.SearchBlock(((IRBlockTarget)instr.Operand1).Target);

            var escapeTarget = FindCommonAncestor(thisScopes, targetScopes);
            var leaveInstrs  = new List <IRInstruction>();

            for (var i = thisScopes.Length - 1; i >= 0; i--)
            {
                if (thisScopes[i] == escapeTarget)
                {
                    break;
                }
                if (thisScopes[i].Type != ScopeType.Try)
                {
                    continue;
                }

                IBasicBlock handler = null, filter = null;
                SearchForHandlers(tr.RootScope, thisScopes[i].ExceptionHandler, ref handler, ref filter);
                if (handler == null)
                {
                    throw new InvalidProgramException();
                }

                leaveInstrs.Add(new IRInstruction(IROpCode.LEAVE, new IRBlockTarget(handler))
                {
                    Annotation = new EHInfo(thisScopes[i].ExceptionHandler)
                });
            }
            instr.OpCode = IROpCode.JMP;
            leaveInstrs.Add(instr);
            instrs.Replace(index, leaveInstrs);
        }
        private void VisitInstr(IRInstrList instrs, IRInstruction instr, ref int index, IRTransformer tr)
        {
            if (instr.OpCode == IROpCode.__ENTRY && !this.done)
            {
                var init = new List <IRInstruction>();
                init.Add(instr);
                foreach (dnlib.DotNet.Emit.Local local in tr.Context.Method.Body.Variables)
                {
                    if (local.Type.IsValueType && !local.Type.IsPrimitive)
                    {
                        IRVariable adr = tr.Context.AllocateVRegister(ASTType.ByRef);
                        init.Add(new IRInstruction(IROpCode.__LEA, adr, tr.Context.ResolveLocal(local)));

                        int typeId  = (int)tr.VM.Data.GetId(local.Type.RemovePinnedAndModifiers().ToTypeDefOrRef());
                        int ecallId = tr.VM.Runtime.VMCall.INITOBJ;
                        init.Add(new IRInstruction(IROpCode.PUSH, adr));
                        init.Add(new IRInstruction(IROpCode.VCALL, IRConstant.FromI4(ecallId), IRConstant.FromI4(typeId)));
                    }
                }
                instrs.Replace(index, init);
                this.done = true;
            }
        }
Пример #16
0
        private IRInstrList Translate(BasicBlock <ILASTTree> block)
        {
            this.Block        = block;
            this.Instructions = new IRInstrList();

            bool seenJump = false;

            foreach (IILASTStatement st in block.Content)
            {
                if (st is ILASTPhi)
                {
                    ILASTVariable variable = ((ILASTPhi)st).Variable;
                    this.Instructions.Add(new IRInstruction(IROpCode.POP)
                    {
                        Operand1 = this.Context.ResolveVRegister(variable),
                        ILAST    = st
                    });
                }
                else if (st is ILASTAssignment assignment)
                {
                    IIROperand valueVar = this.Translate(assignment.Value);
                    this.Instructions.Add(new IRInstruction(IROpCode.MOV)
                    {
                        Operand1 = this.Context.ResolveVRegister(assignment.Variable),
                        Operand2 = valueVar,
                        ILAST    = st
                    });
                }
                else if (st is ILASTExpression expr)
                {
                    var opCode = expr.ILCode.ToOpCode();
                    if (!seenJump && (opCode.FlowControl == FlowControl.Cond_Branch ||
                                      opCode.FlowControl == FlowControl.Branch ||
                                      opCode.FlowControl == FlowControl.Return ||
                                      opCode.FlowControl == FlowControl.Throw))
                    {
                        // Add stack remain before jumps
                        foreach (ILASTVariable remain in block.Content.StackRemains)
                        {
                            this.Instructions.Add(new IRInstruction(IROpCode.PUSH)
                            {
                                Operand1 = this.Context.ResolveVRegister(remain),
                                ILAST    = st
                            });
                        }
                        seenJump = true;
                    }
                    this.Translate((ILASTExpression)st);
                }
                else
                {
                    throw new NotSupportedException();
                }
            }
            Debug.Assert(seenJump);

            IRInstrList ret = this.Instructions;

            this.Instructions = null;
            return(ret);
        }
Пример #17
0
 void VisitInstr(IRInstrList instrs, IRInstruction instr, ref int index, IRTransformer tr)
 {
     instr.Operand1 = TransformMD(instr.Operand1, tr);
     instr.Operand2 = TransformMD(instr.Operand2, tr);
 }