// 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); }
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); }
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) }); } }
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; } } }
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); } } }
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; } }
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) }); } }
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) }); } }
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; } }
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; } }
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); }
void VisitInstr(IRInstrList instrs, IRInstruction instr, ref int index, IRTransformer tr) { instr.Operand1 = TransformMD(instr.Operand1, tr); instr.Operand2 = TransformMD(instr.Operand2, tr); }