public static void PopOperand(this ILTranslator tr, IIROperand operand) { if (operand is IRRegister) { var reg = ILRegister.LookupRegister(((IRRegister)operand).Register); tr.Instructions.Add(new ILInstruction(ILOpCode.POP, reg)); } else if (operand is IRPointer pointer) { var reg = ILRegister.LookupRegister(pointer.Register.Register); tr.Instructions.Add(new ILInstruction(pointer.Register.GetPUSHR(), reg)); if (pointer.Offset != 0) { tr.Instructions.Add(new ILInstruction(ILOpCode.PUSHI_DWORD, ILImmediate.Create(pointer.Offset, ASTType.I4))); if (pointer.Register.Type == ASTType.I4) { tr.Instructions.Add(new ILInstruction(ILOpCode.ADD_DWORD)); } else { tr.Instructions.Add(new ILInstruction(ILOpCode.ADD_QWORD)); } } tr.Instructions.Add(new ILInstruction(pointer.GetSIND())); } else { throw new NotSupportedException(); } }
private void VisitInstr(ILInstrList instrs, ILInstruction instr, ref int index, ILPostTransformer tr) { if (instr.OpCode != ILOpCode.__BEGINCALL && instr.OpCode != ILOpCode.__ENDCALL) { return; } var callInfo = (InstrCallInfo)instr.Annotation; if (callInfo.IsECall) { instrs.RemoveAt(index); index--; return; } var saving = new HashSet <DarksVMRegisters>(saveRegs); var retVar = (IRVariable)callInfo.ReturnValue; // R0 = return register, need to save if retVar register is not R0 //Debug.Assert(!(retVar == null ^ (callInfo.ReturnRegister == null ^ callInfo.ReturnSlot == null))); if (retVar != null) { if (callInfo.ReturnSlot == null) { var retReg = callInfo.ReturnRegister.Register; saving.Remove(retReg); if (retReg != DarksVMRegisters.R0) { saving.Add(DarksVMRegisters.R0); } } else { saving.Add(DarksVMRegisters.R0); } } else { saving.Add(DarksVMRegisters.R0); } if (instr.OpCode == ILOpCode.__BEGINCALL) { instrs.Replace(index, saving .Select(reg => new ILInstruction(ILOpCode.PUSHR_OBJECT, ILRegister.LookupRegister(reg), instr))); } else { instrs.Replace(index, saving .Select(reg => new ILInstruction(ILOpCode.POP, ILRegister.LookupRegister(reg), instr)) .Reverse()); } index--; }
public static void PushOperand(this ILTranslator tr, IIROperand operand) { if (operand is IRRegister) { var reg = ILRegister.LookupRegister(((IRRegister)operand).Register); tr.Instructions.Add(new ILInstruction(((IRRegister)operand).GetPUSHR(), reg)); } else if (operand is IRPointer pointer) { var reg = ILRegister.LookupRegister(pointer.Register.Register); tr.Instructions.Add(new ILInstruction(pointer.Register.GetPUSHR(), reg)); if (pointer.Offset != 0) { tr.Instructions.Add(new ILInstruction(ILOpCode.PUSHI_DWORD, ILImmediate.Create(pointer.Offset, ASTType.I4))); switch (pointer.Register.Type) { case ASTType.I4: tr.Instructions.Add(new ILInstruction(ILOpCode.ADD_DWORD)); break; default: tr.Instructions.Add(new ILInstruction(ILOpCode.ADD_QWORD)); break; } } tr.Instructions.Add(new ILInstruction(pointer.GetLIND())); } else if (operand is IRConstant constant) { if (constant.Value != null) { tr.Instructions.Add(new ILInstruction(constant.Type.Value.GetPUSHI(), ILImmediate.Create(constant.Value, constant.Type.Value))); } else { tr.Instructions.Add(new ILInstruction(ILOpCode.PUSHI_DWORD, ILImmediate.Create(0, ASTType.O))); } } else if (operand is IRMetaTarget) { var method = (MethodDef)((IRMetaTarget)operand).MetadataItem; tr.Instructions.Add(new ILInstruction(ILOpCode.PUSHI_DWORD, new ILMethodTarget(method))); } else if (operand is IRBlockTarget) { CFG.IBasicBlock target = ((IRBlockTarget)operand).Target; tr.Instructions.Add(new ILInstruction(ILOpCode.PUSHI_DWORD, new ILBlockTarget(target))); } else if (operand is IRJumpTable) { CFG.IBasicBlock[] targets = ((IRJumpTable)operand).Targets; tr.Instructions.Add(new ILInstruction(ILOpCode.PUSHI_DWORD, new ILJumpTable(targets))); } else if (operand is IRDataTarget) { RT.BinaryChunk target = ((IRDataTarget)operand).Target; tr.Instructions.Add(new ILInstruction(ILOpCode.PUSHI_DWORD, new ILDataTarget(target))); } else { throw new NotSupportedException(); } }
void VisitInstr(ILInstrList instrs, ILInstruction instr, ref int index, ILPostTransformer tr) { if (instr.OpCode != ILOpCode.__BEGINCALL && instr.OpCode != ILOpCode.__ENDCALL) { return; } var callInfo = (InstrCallInfo)instr.Annotation; if (callInfo.IsECall) { instrs.RemoveAt(index); index--; return; } var saving = new HashSet <VMRegisters>(saveRegs); var retVar = (IRVariable)callInfo.ReturnValue; // R0 = return register, need to save if retVar register is not R07 if (retVar == null ^ (callInfo.ReturnRegister == null ^ callInfo.ReturnSlot == null)) { ConsoleColor c = Console.ForegroundColor; Console.ForegroundColor = ConsoleColor.Red; Console.WriteLine("Debug.Assert [SaveRegistersTransform.cs] L36"); Console.WriteLine($"Method target->{callInfo.Method.FullName}"); Console.ForegroundColor = c; } if (retVar != null) { if (callInfo.ReturnSlot == null) { var retReg = callInfo.ReturnRegister.Register; saving.Remove(retReg); if (retReg != VMRegisters.R0) { saving.Add(VMRegisters.R0); } } else { saving.Add(VMRegisters.R0); } } else { saving.Add(VMRegisters.R0); } if (instr.OpCode == ILOpCode.__BEGINCALL) { instrs.Replace(index, saving .Select(reg => new ILInstruction(ILOpCode.PUSHR_OBJECT, ILRegister.LookupRegister(reg), instr))); } else { instrs.Replace(index, saving .Select(reg => new ILInstruction(ILOpCode.POP, ILRegister.LookupRegister(reg), instr)) .Reverse()); } index--; }