public IIROperand Translate(ILASTExpression expr, IRTranslator tr) { Debug.Assert(expr.Arguments.Length == 1); IIROperand value = tr.Translate(expr.Arguments[0]); ASTType valueType = value.Type; IRVariable retVar = tr.Context.AllocateVRegister(ASTType.R8); switch (valueType) { case ASTType.I4: IRVariable tmpVar = tr.Context.AllocateVRegister(ASTType.I8); tr.Instructions.Add(new IRInstruction(IROpCode.SX, tmpVar, value)); tr.Instructions.Add(new IRInstruction(IROpCode.__SETF) { Operand1 = IRConstant.FromI4(1 << tr.Arch.Flags.UNSIGNED) }); tr.Instructions.Add(new IRInstruction(IROpCode.FCONV, retVar, tmpVar)); break; case ASTType.I8: tr.Instructions.Add(new IRInstruction(IROpCode.__SETF) { Operand1 = IRConstant.FromI4(1 << tr.Arch.Flags.UNSIGNED) }); tr.Instructions.Add(new IRInstruction(IROpCode.FCONV, retVar, value)); break; default: throw new NotSupportedException(); } return(retVar); }
public IIROperand Translate(ILASTExpression expr, IRTranslator tr) { // TODO: overflow? Debug.Assert(expr.Arguments.Length == 1); IIROperand value = tr.Translate(expr.Arguments[0]); ASTType valueType = value.Type; if (valueType == ASTType.Ptr || valueType == ASTType.I4) // no conversion needed. { return(value); } IRVariable retVar = tr.Context.AllocateVRegister(ASTType.Ptr); switch (valueType) { case ASTType.I8: tr.Instructions.Add(new IRInstruction(IROpCode.MOV, retVar, value)); break; case ASTType.R4: case ASTType.R8: IRVariable tmp = tr.Context.AllocateVRegister(ASTType.I8); tr.Instructions.Add(new IRInstruction(IROpCode.ICONV, tmp, value)); tr.Instructions.Add(new IRInstruction(IROpCode.MOV, retVar, tmp)); break; default: throw new NotSupportedException(); } return(retVar); }
public IIROperand Translate(ILASTExpression expr, IRTranslator tr) { var callInfo = new InstrCallInfo("CALLVIRT") { Method = (IMethod)expr.Operand }; if (expr.Prefixes != null && expr.Prefixes[0].OpCode == OpCodes.Constrained) { callInfo.ConstrainType = (ITypeDefOrRef)expr.Prefixes[0].Operand; } tr.Instructions.Add(new IRInstruction(IROpCode.__BEGINCALL) { Annotation = callInfo }); var args = new IIROperand[expr.Arguments.Length]; for (var i = 0; i < args.Length; i++) { args[i] = tr.Translate(expr.Arguments[i]); tr.Instructions.Add(new IRInstruction(IROpCode.PUSH) { Operand1 = args[i], Annotation = callInfo }); } callInfo.Arguments = args; IIROperand retVal = null; if (expr.Type != null) { retVal = tr.Context.AllocateVRegister(expr.Type.Value); tr.Instructions.Add(new IRInstruction(IROpCode.__CALLVIRT) { Operand1 = new IRMetaTarget(callInfo.Method), Operand2 = retVal, Annotation = callInfo }); } else { tr.Instructions.Add(new IRInstruction(IROpCode.__CALLVIRT) { Operand1 = new IRMetaTarget(callInfo.Method), Annotation = callInfo }); } callInfo.ReturnValue = retVal; tr.Instructions.Add(new IRInstruction(IROpCode.__ENDCALL) { Annotation = callInfo }); return(retVal); }
internal IIROperand Translate(IILASTNode node) { if (node is ILASTExpression expr) { try { if (!handlers.TryGetValue(expr.ILCode, out ITranslationHandler handler)) { throw new NotSupportedException(expr.ILCode.ToString()); } int i = this.Instructions.Count; IIROperand operand = handler.Translate(expr, this); while (i < this.Instructions.Count) { this.Instructions[i].ILAST = expr; i++; } return(operand); } catch (Exception ex) { throw new Exception($"Failed to translate expr {expr.CILInstr} @ {expr.CILInstr.GetOffset():x4}.", ex); } } if (node is ILASTVariable) { return(this.Context.ResolveVRegister((ILASTVariable)node)); } throw new NotSupportedException(); }
public IRInstruction(IROpCode opCode, IIROperand op1, IIROperand op2, object annotation) { OpCode = opCode; Operand1 = op1; Operand2 = op2; Annotation = annotation; }
public IIROperand Translate(ILASTExpression expr, IRTranslator tr) { Debug.Assert(expr.Arguments.Length == 1); IIROperand value = tr.Translate(expr.Arguments[0]); var targetType = ((ITypeDefOrRef)expr.Operand).ToTypeSig(); TypeDef boxType = ((ITypeDefOrRef)expr.Operand).ResolveTypeDef(); if (!targetType.GetElementType().IsPrimitive() && (boxType == null || !boxType.IsEnum)) { if (targetType.ElementType != ElementType.String) // Box is used to resolve string ID { return(value); } } IRVariable retVar = tr.Context.AllocateVRegister(expr.Type.Value); int typeId = (int)tr.VM.Data.GetId((ITypeDefOrRef)expr.Operand); int ecallId = tr.VM.Runtime.VMCall.BOX; tr.Instructions.Add(new IRInstruction(IROpCode.PUSH, value)); tr.Instructions.Add(new IRInstruction(IROpCode.VCALL, IRConstant.FromI4(ecallId), IRConstant.FromI4(typeId))); tr.Instructions.Add(new IRInstruction(IROpCode.POP, retVar)); return(retVar); }
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 IIROperand AllocateOperand(IIROperand operand, RegisterPool pool) { if (operand is IRVariable) { var variable = (IRVariable)operand; StackSlot?slot; var reg = AllocateVariable(pool, variable, out slot); if (reg != null) { return new IRRegister(reg.Value) { SourceVariable = variable, Type = variable.Type } } ; variable.Annotation = slot.Value; return(new IRPointer { Register = IRRegister.BP, Offset = slot.Value.Offset, SourceVariable = variable, Type = variable.Type }); } return(operand); }
public IIROperand Translate(ILASTExpression expr, IRTranslator tr) { Debug.Assert(expr.Arguments.Length == 1); IIROperand value = tr.Translate(expr.Arguments[0]); ASTType valueType = value.Type; IRVariable retVar = tr.Context.AllocateVRegister(ASTType.I4); retVar.RawType = tr.Context.Method.Module.CorLibTypes.Byte; switch (valueType) { case ASTType.I4: case ASTType.I8: case ASTType.Ptr: tr.Instructions.Add(new IRInstruction(IROpCode.MOV, retVar, value)); break; case ASTType.R4: case ASTType.R8: IRVariable tmp = tr.Context.AllocateVRegister(ASTType.I8); tr.Instructions.Add(new IRInstruction(IROpCode.ICONV, tmp, value)); tr.Instructions.Add(new IRInstruction(IROpCode.MOV, retVar, tmp)); break; default: throw new NotSupportedException(); } return(retVar); }
public IIROperand Translate(ILASTExpression expr, IRTranslator tr) { Debug.Assert(expr.Arguments.Length == 1); IIROperand value = tr.Translate(expr.Arguments[0]); // TODO: no exception possible? return(value); }
public IRInstruction(IROpCode opCode, IIROperand op1, IIROperand op2, IRInstruction origin) { OpCode = opCode; Operand1 = op1; Operand2 = op2; Annotation = origin.Annotation; ILAST = origin.ILAST; }
private void AddTryStart(IRTransformer tr) { var tryStartInstrs = new List <IRInstruction>(); for (var i = 0; i < thisScopes.Length; i++) { var scope = thisScopes[i]; if (scope.Type != ScopeType.Try) { continue; } if (scope.GetBasicBlocks().First() != tr.Block) { continue; } // Search for handler/filter IBasicBlock handler = null, filter = null; SearchForHandlers(tr.RootScope, scope.ExceptionHandler, ref handler, ref filter); Debug.Assert(handler != null && (scope.ExceptionHandler.HandlerType != ExceptionHandlerType.Filter || filter != null)); // Add instructions tryStartInstrs.Add(new IRInstruction(IROpCode.PUSH, new IRBlockTarget(handler))); IIROperand tryOperand = null; int ehType; if (scope.ExceptionHandler.HandlerType == ExceptionHandlerType.Catch) { tryOperand = IRConstant.FromI4((int)tr.VM.Data.GetId(scope.ExceptionHandler.CatchType)); ehType = tr.VM.Runtime.RTFlags.EH_CATCH; } else if (scope.ExceptionHandler.HandlerType == ExceptionHandlerType.Filter) { tryOperand = new IRBlockTarget(filter); ehType = tr.VM.Runtime.RTFlags.EH_FILTER; } else if (scope.ExceptionHandler.HandlerType == ExceptionHandlerType.Fault) { ehType = tr.VM.Runtime.RTFlags.EH_FAULT; } else if (scope.ExceptionHandler.HandlerType == ExceptionHandlerType.Finally) { ehType = tr.VM.Runtime.RTFlags.EH_FINALLY; } else { throw new InvalidProgramException(); } tryStartInstrs.Add(new IRInstruction(IROpCode.TRY, IRConstant.FromI4(ehType), tryOperand) { Annotation = new EHInfo(scope.ExceptionHandler) }); } tr.Instructions.InsertRange(0, tryStartInstrs); }
public static void EmitCompareEq(IRTranslator tr, ASTType type, IIROperand a, IIROperand b) { if (type == ASTType.O || type == ASTType.ByRef || type == ASTType.R4 || type == ASTType.R8) { tr.Instructions.Add(new IRInstruction(IROpCode.CMP, a, b)); } else { // I4/I8/Ptr Debug.Assert(type == ASTType.I4 || type == ASTType.I8 || type == ASTType.Ptr); tr.Instructions.Add(new IRInstruction(IROpCode.CMP, a, b)); } }
IIROperand AllocateOperand(IIROperand operand, RegisterPool pool) { if (operand is IRVariable) { var variable = (IRVariable)operand; StackSlot?slot; var reg = AllocateVariable(pool, variable, out slot); if (reg != null) { return new IRRegister(reg.Value) { SourceVariable = variable, Type = variable.Type } } ; variable.Annotation = slot.Value; return(new IRPointer { Register = IRRegister.BP, Offset = slot.Value.Offset, SourceVariable = variable, Type = variable.Type }); } return(operand); } VMRegisters?AllocateVariable(RegisterPool pool, IRVariable var, out StackSlot?stackSlot) { stackSlot = pool.CheckSpill(var); if (stackSlot == null) { var allocReg = var.Annotation == null ? (VMRegisters?)null : (VMRegisters)var.Annotation; if (allocReg == null) { allocReg = pool.Allocate(var); } if (allocReg != null) { if (var.Annotation == null) { var.Annotation = allocReg.Value; } return(allocReg); } // Spill variable stackSlot = pool.SpillVariable(var); } return(null); } }
public IIROperand Translate(ILASTExpression expr, IRTranslator tr) { Debug.Assert(expr.Arguments.Length == 1); IIROperand val = tr.Translate(expr.Arguments[0]); int fieldId = (int)tr.VM.Data.GetId((IField)expr.Operand); int ecallId = tr.VM.Runtime.VMCall.STFLD; tr.Instructions.Add(new IRInstruction(IROpCode.PUSH, IRConstant.Null())); tr.Instructions.Add(new IRInstruction(IROpCode.PUSH, val)); tr.Instructions.Add(new IRInstruction(IROpCode.VCALL, IRConstant.FromI4(ecallId), IRConstant.FromI4(fieldId))); return(null); }
public IIROperand Translate(ILASTExpression expr, IRTranslator tr) { Debug.Assert(expr.Arguments.Length == 1); IIROperand val = tr.Translate(expr.Arguments[0]); tr.Instructions.Add(new IRInstruction(IROpCode.SWT) { Operand1 = new IRJumpTable((IBasicBlock[])expr.Operand), Operand2 = val }); return(null); }
public IIROperand Translate(ILASTExpression expr, IRTranslator tr) { Debug.Assert(expr.Arguments.Length == 1); IIROperand addr = tr.Translate(expr.Arguments[0]); IRVariable retVar = tr.Context.AllocateVRegister(expr.Type.Value); tr.Instructions.Add(new IRInstruction(IROpCode.__LDOBJ, addr, retVar) { Annotation = new PointerInfo("LDOBJ", (ITypeDefOrRef)expr.Operand) }); return(retVar); }
public IIROperand Translate(ILASTExpression expr, IRTranslator tr) { Debug.Assert(expr.Arguments.Length == 2); IIROperand addr = tr.Translate(expr.Arguments[0]); IIROperand value = tr.Translate(expr.Arguments[1]); tr.Instructions.Add(new IRInstruction(IROpCode.__STOBJ, addr, value) { Annotation = new PointerInfo("STOBJ", (ITypeDefOrRef)expr.Operand) }); return(null); }
public IIROperand Translate(ILASTExpression expr, IRTranslator tr) { Debug.Assert(expr.Arguments.Length == 1); IIROperand addr = tr.Translate(expr.Arguments[0]); int typeId = (int)tr.VM.Data.GetId((ITypeDefOrRef)expr.Operand); int ecallId = tr.VM.Runtime.VMCall.INITOBJ; tr.Instructions.Add(new IRInstruction(IROpCode.PUSH, addr)); tr.Instructions.Add(new IRInstruction(IROpCode.VCALL, IRConstant.FromI4(ecallId), IRConstant.FromI4(typeId))); return(null); }
public IIROperand Translate(ILASTExpression expr, IRTranslator tr) { Debug.Assert(expr.Arguments.Length == 1); IIROperand size = tr.Translate(expr.Arguments[0]); IRVariable retVar = tr.Context.AllocateVRegister(expr.Type.Value); int ecallId = tr.VM.Runtime.VMCall.LOCALLOC; tr.Instructions.Add(new IRInstruction(IROpCode.VCALL, IRConstant.FromI4(ecallId), size)); tr.Instructions.Add(new IRInstruction(IROpCode.POP, retVar)); return(retVar); }
public IIROperand Translate(ILASTExpression expr, IRTranslator tr) { Debug.Assert(expr.Arguments.Length == 1); IIROperand value = tr.Translate(expr.Arguments[0]); ASTType valueType = value.Type; IRVariable t = tr.Context.AllocateVRegister(ASTType.I4); IRVariable retVar = tr.Context.AllocateVRegister(ASTType.I4); t.RawType = tr.Context.Method.Module.CorLibTypes.Int16; int rangechk = tr.VM.Runtime.VMCall.RANGECHK; int ckovf = tr.VM.Runtime.VMCall.CKOVERFLOW; switch (valueType) { case ASTType.I4: case ASTType.I8: case ASTType.Ptr: tr.Instructions.Add(new IRInstruction(IROpCode.PUSH, IRConstant.FromI8(ushort.MinValue))); tr.Instructions.Add(new IRInstruction(IROpCode.PUSH, IRConstant.FromI8(short.MaxValue))); tr.Instructions.Add(new IRInstruction(IROpCode.VCALL, IRConstant.FromI4(rangechk), value)); tr.Instructions.Add(new IRInstruction(IROpCode.VCALL, IRConstant.FromI4(ckovf))); tr.Instructions.Add(new IRInstruction(IROpCode.MOV, t, value)); tr.Instructions.Add(new IRInstruction(IROpCode.SX, retVar, t)); break; case ASTType.R4: case ASTType.R8: IRVariable tmpVar = tr.Context.AllocateVRegister(ASTType.I8); IRVariable fl = tr.Context.AllocateVRegister(ASTType.I4); tr.Instructions.Add(new IRInstruction(IROpCode.__SETF) { Operand1 = IRConstant.FromI4(1 << tr.Arch.Flags.UNSIGNED) }); tr.Instructions.Add(new IRInstruction(IROpCode.ICONV, tmpVar, value)); tr.Instructions.Add(new IRInstruction(IROpCode.__GETF) { Operand1 = fl, Operand2 = IRConstant.FromI4(1 << tr.Arch.Flags.OVERFLOW) }); tr.Instructions.Add(new IRInstruction(IROpCode.VCALL, IRConstant.FromI4(ckovf), fl)); value = tmpVar; goto case ASTType.I8; default: throw new NotSupportedException(); } return(retVar); }
public IIROperand Translate(ILASTExpression expr, IRTranslator tr) { Debug.Assert(expr.Arguments.Length == 1); IIROperand obj = tr.Translate(expr.Arguments[0]); IRVariable retVar = tr.Context.AllocateVRegister(expr.Type.Value); int fieldId = (int)(tr.VM.Data.GetId((IField)expr.Operand) | 0x80000000); int ecallId = tr.VM.Runtime.VMCall.LDFLD; tr.Instructions.Add(new IRInstruction(IROpCode.PUSH, obj)); tr.Instructions.Add(new IRInstruction(IROpCode.VCALL, IRConstant.FromI4(ecallId), IRConstant.FromI4(fieldId))); tr.Instructions.Add(new IRInstruction(IROpCode.POP, retVar)); return(retVar); }
private void VisitInstr(IRInstrList instrs, IRInstruction instr, ref int index, IRTransformer tr) { if (instr.OpCode == IROpCode.__LEA) { var source = (IRPointer)instr.Operand2; IIROperand 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) }); } }
public IIROperand Translate(ILASTExpression expr, IRTranslator tr) { Debug.Assert(expr.Arguments.Length == 1); IIROperand value = tr.Translate(expr.Arguments[0]); IRVariable retVar = tr.Context.AllocateVRegister(expr.Type.Value); int typeId = (int)tr.VM.Data.GetId((ITypeDefOrRef)expr.Operand); int ecallId = tr.VM.Runtime.VMCall.CAST; tr.Instructions.Add(new IRInstruction(IROpCode.PUSH, value)); tr.Instructions.Add(new IRInstruction(IROpCode.VCALL, IRConstant.FromI4(ecallId), IRConstant.FromI4(typeId))); tr.Instructions.Add(new IRInstruction(IROpCode.POP, retVar)); return(retVar); }
private IIROperand TransformMD(IIROperand operand, IRTransformer tr) { if (operand is IRMetaTarget target) { if (!target.LateResolve) { if (!(target.MetadataItem is IMemberRef)) { throw new NotSupportedException(); } return(IRConstant.FromI4((int)tr.VM.Data.GetId((IMemberRef)target.MetadataItem))); } } return(operand); }
public IIROperand Translate(ILASTExpression expr, IRTranslator tr) { Debug.Assert(expr.Arguments.Length == 1); IIROperand value = tr.Translate(expr.Arguments[0]); int ecallId = tr.VM.Runtime.VMCall.CKFINITE; if (value.Type == ASTType.R4) { tr.Instructions.Add(new IRInstruction(IROpCode.__SETF) { Operand1 = IRConstant.FromI4(1 << tr.Arch.Flags.UNSIGNED) }); } tr.Instructions.Add(new IRInstruction(IROpCode.VCALL, IRConstant.FromI4(ecallId), value)); return(value); }
public static void EmitCompareEq(IRTranslator tr, ASTType type, IIROperand a, IIROperand b) { switch (type) { case ASTType.O: case ASTType.ByRef: case ASTType.R4: case ASTType.R8: tr.Instructions.Add(new IRInstruction(IROpCode.CMP, a, b)); break; default: // I4/I8/Ptr Debug.Assert(type == ASTType.I4 || type == ASTType.I8 || type == ASTType.Ptr); tr.Instructions.Add(new IRInstruction(IROpCode.CMP, a, b)); break; } }
public IIROperand Translate(ILASTExpression expr, IRTranslator tr) { if (expr.Arguments.Length == 1) { IIROperand value = tr.Translate(expr.Arguments[0]); tr.Instructions.Add(new IRInstruction(IROpCode.MOV) { Operand1 = new IRRegister(DarksVMRegisters.R0, value.Type), Operand2 = value }); } else { Debug.Assert(expr.Arguments.Length == 0); } tr.Instructions.Add(new IRInstruction(IROpCode.RET)); return(null); }
public IIROperand Translate(ILASTExpression expr, IRTranslator tr) { var callInfo = new InstrCallInfo("NEWOBJ") { Method = (IMethod)expr.Operand }; tr.Instructions.Add(new IRInstruction(IROpCode.__BEGINCALL) { Annotation = callInfo }); var args = new IIROperand[expr.Arguments.Length]; for (var i = 0; i < args.Length; i++) { args[i] = tr.Translate(expr.Arguments[i]); tr.Instructions.Add(new IRInstruction(IROpCode.PUSH) { Operand1 = args[i], Annotation = callInfo }); } callInfo.Arguments = args; var retVal = tr.Context.AllocateVRegister(expr.Type.Value); tr.Instructions.Add(new IRInstruction(IROpCode.__NEWOBJ) { Operand1 = new IRMetaTarget(callInfo.Method), Operand2 = retVal, Annotation = callInfo }); callInfo.ReturnValue = retVal; tr.Instructions.Add(new IRInstruction(IROpCode.__ENDCALL) { Annotation = callInfo }); return(retVal); }
public IIROperand Translate(ILASTExpression expr, IRTranslator tr) { Debug.Assert(expr.Arguments.Length == 1); IIROperand value = tr.Translate(expr.Arguments[0]); ASTType valueType = value.Type; if (valueType == ASTType.I8) // no conversion needed. { return(value); } IRVariable retVar = tr.Context.AllocateVRegister(ASTType.I8); int ckovf = tr.VM.Runtime.VMCall.CKOVERFLOW; switch (valueType) { case ASTType.I4: tr.Instructions.Add(new IRInstruction(IROpCode.SX, retVar, value)); break; case ASTType.Ptr: tr.Instructions.Add(new IRInstruction(IROpCode.MOV, retVar, value)); break; case ASTType.R4: case ASTType.R8: IRVariable fl = tr.Context.AllocateVRegister(ASTType.I4); tr.Instructions.Add(new IRInstruction(IROpCode.ICONV, retVar, value)); tr.Instructions.Add(new IRInstruction(IROpCode.__GETF) { Operand1 = fl, Operand2 = IRConstant.FromI4(1 << tr.Arch.Flags.OVERFLOW) }); tr.Instructions.Add(new IRInstruction(IROpCode.VCALL, IRConstant.FromI4(ckovf), fl)); break; default: throw new NotSupportedException(); } return(retVar); }