public IIROperand Translate(ILASTExpression expr, IRTranslator tr) { Debug.Assert(expr.Arguments.Length == 1); var value = tr.Translate(expr.Arguments[0]); var valueType = value.Type; var retVar = tr.Context.AllocateVRegister(ASTType.I4); retVar.RawType = tr.Context.Method.Module.CorLibTypes.Byte; var rangechk = tr.VM.Runtime.VMCall.RANGECHK; var 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(byte.MinValue))); tr.Instructions.Add(new IRInstruction(IROpCode.PUSH, IRConstant.FromI8(byte.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, retVar, value)); break; case ASTType.R4: case ASTType.R8: var tmpVar = tr.Context.AllocateVRegister(ASTType.I8); var 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 == 2); var ret = tr.Context.AllocateVRegister(expr.Type.Value); if (expr.Type != null && (expr.Type.Value == ASTType.R4 || expr.Type.Value == ASTType.R8)) { tr.Instructions.Add(new IRInstruction(IROpCode.MOV) { Operand1 = ret, Operand2 = tr.Translate(expr.Arguments[0]) }); tr.Instructions.Add(new IRInstruction(IROpCode.SUB) { Operand1 = ret, Operand2 = tr.Translate(expr.Arguments[1]) }); } else { // A - B = A + (-B) = A + (~B + 1) = A + ~B + 1 var tmp = tr.Context.AllocateVRegister(expr.Type.Value); tr.Instructions.Add(new IRInstruction(IROpCode.MOV) { Operand1 = ret, Operand2 = tr.Translate(expr.Arguments[0]) }); tr.Instructions.Add(new IRInstruction(IROpCode.MOV) { Operand1 = tmp, Operand2 = tr.Translate(expr.Arguments[1]) }); tr.Instructions.Add(new IRInstruction(IROpCode.__NOT) { Operand1 = tmp }); tr.Instructions.Add(new IRInstruction(IROpCode.ADD) { Operand1 = ret, Operand2 = tmp }); tr.Instructions.Add(new IRInstruction(IROpCode.ADD) { Operand1 = ret, Operand2 = IRConstant.FromI4(1) }); } return(ret); }
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); var value = tr.Translate(expr.Arguments[0]); var retVar = tr.Context.AllocateVRegister(expr.Type.Value); var typeId = (int)(tr.VM.Data.GetId((ITypeDefOrRef)expr.Operand) | 0x80000000); var 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); }
public IIROperand Translate(ILASTExpression expr, IRTranslator tr) { Debug.Assert(expr.Arguments.Length == 2); tr.Instructions.Add(new IRInstruction(IROpCode.CMP) { Operand1 = tr.Translate(expr.Arguments[0]), Operand2 = tr.Translate(expr.Arguments[1]) }); // SF=OF & ZF=0 // (FL=S|O) or (FL=0), FL=S|O|Z var ret = tr.Context.AllocateVRegister(ASTType.I4); var fl = tr.Context.AllocateVRegister(ASTType.I4); tr.Instructions.Add(new IRInstruction(IROpCode.__GETF) { Operand1 = fl, Operand2 = IRConstant.FromI4(1 << tr.Arch.Flags.OVERFLOW | 1 << tr.Arch.Flags.SIGN | 1 << tr.Arch.Flags.ZERO) }); tr.Instructions.Add(new IRInstruction(IROpCode.MOV) { Operand1 = ret, Operand2 = fl }); TranslationHelpers.EmitCompareEq(tr, ASTType.I4, ret, IRConstant.FromI4(1 << tr.Arch.Flags.OVERFLOW | 1 << tr.Arch.Flags.SIGN)); tr.Instructions.Add(new IRInstruction(IROpCode.__GETF) { Operand1 = ret, Operand2 = IRConstant.FromI4(1 << tr.Arch.Flags.ZERO) }); tr.Instructions.Add(new IRInstruction(IROpCode.__AND) { Operand1 = fl, Operand2 = fl }); tr.Instructions.Add(new IRInstruction(IROpCode.__GETF) { Operand1 = fl, Operand2 = IRConstant.FromI4(1 << tr.Arch.Flags.ZERO) }); tr.Instructions.Add(new IRInstruction(IROpCode.__OR) { Operand1 = ret, Operand2 = fl }); return(ret); }
public IIROperand Translate(ILASTExpression expr, IRTranslator tr) { Debug.Assert(expr.Arguments.Length == 1); var retVar = tr.Context.AllocateVRegister(expr.Type.Value); var obj = tr.Translate(expr.Arguments[0]); var method = (IMethod)expr.Operand; var methodId = (int)tr.VM.Data.GetId(method); var ecallId = tr.VM.Runtime.VMCall.LDFTN; tr.Instructions.Add(new IRInstruction(IROpCode.PUSH, obj)); tr.Instructions.Add(new IRInstruction(IROpCode.VCALL, IRConstant.FromI4(ecallId), IRConstant.FromI4(methodId))); tr.Instructions.Add(new IRInstruction(IROpCode.POP, retVar)); return(retVar); }
public IIROperand Translate(ILASTExpression expr, IRTranslator tr) { Debug.Assert(expr.Arguments.Length == 1); var value = tr.Translate(expr.Arguments[0]); var 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); }
private static IIROperand PromoteConstantR4(IRConstant value) { if (value.Type.Value != ASTType.I4) { if (value.Type.Value != ASTType.R4) { throw new InvalidProgramException(); } } else { value.Type = ASTType.R4; value.Value = (float)(int)value.Value; } return(value); }
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.I4) // no conversion needed. { return(value); } IRVariable retVar = tr.Context.AllocateVRegister(ASTType.I4); int rangechk = tr.VM.Runtime.VMCall.RANGECHK; int ckovf = tr.VM.Runtime.VMCall.CKOVERFLOW; switch (valueType) { case ASTType.I8: case ASTType.Ptr: tr.Instructions.Add(new IRInstruction(IROpCode.PUSH, IRConstant.FromI8(int.MinValue))); tr.Instructions.Add(new IRInstruction(IROpCode.PUSH, IRConstant.FromI8(int.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, retVar, value)); 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.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); }
private static IIROperand PromoteConstant(IRConstant value, ASTType type) { switch (type) { case ASTType.I8: return(PromoteConstantI8(value)); case ASTType.R4: return(PromoteConstantR4(value)); case ASTType.R8: return(PromoteConstantR8(value)); default: return(value); } }
public IIROperand Translate(ILASTExpression expr, IRTranslator tr) { Debug.Assert(expr.Arguments.Length == 2); tr.Instructions.Add(new IRInstruction(IROpCode.CMP) { Operand1 = tr.Translate(expr.Arguments[0]), Operand2 = tr.Translate(expr.Arguments[1]) }); // CF=1 var ret = tr.Context.AllocateVRegister(ASTType.I4); tr.Instructions.Add(new IRInstruction(IROpCode.__GETF) { Operand1 = ret, Operand2 = IRConstant.FromI4(1 << tr.Arch.Flags.CARRY) }); return(ret); }
public IIROperand Translate(ILASTExpression expr, IRTranslator tr) { Debug.Assert(expr.Arguments.Length == 1); var value = tr.Translate(expr.Arguments[0]); var valueType = value.Type; if (valueType == ASTType.I8) // no conversion needed. { return(value); } var retVar = tr.Context.AllocateVRegister(ASTType.I8); var 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: var 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); }
public IIROperand Translate(ILASTExpression expr, IRTranslator tr) { Debug.Assert(expr.Arguments.Length == 2); var ret = tr.Context.AllocateVRegister(expr.Type.Value); tr.Instructions.Add(new IRInstruction(IROpCode.MOV) { Operand1 = ret, Operand2 = tr.Translate(expr.Arguments[0]) }); tr.Instructions.Add(new IRInstruction(IROpCode.__SETF) { Operand1 = IRConstant.FromI4(1 << tr.Arch.Flags.UNSIGNED) }); tr.Instructions.Add(new IRInstruction(IROpCode.SHR) { Operand1 = ret, Operand2 = tr.Translate(expr.Arguments[1]) }); return(ret); }
public IIROperand Translate(ILASTExpression expr, IRTranslator tr) { Debug.Assert(expr.Arguments.Length == 1); var val = tr.Translate(expr.Arguments[0]); TranslationHelpers.EmitCompareEq(tr, expr.Arguments[0].Type.Value, val, IRConstant.FromI4(0)); var tmp = tr.Context.AllocateVRegister(ASTType.I4); tr.Instructions.Add(new IRInstruction(IROpCode.__GETF) { Operand1 = tmp, Operand2 = IRConstant.FromI4(1 << tr.Arch.Flags.ZERO) }); tr.Instructions.Add(new IRInstruction(IROpCode.JNZ) { Operand1 = new IRBlockTarget((IBasicBlock)expr.Operand), Operand2 = tmp }); return(null); }
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; } }
public IIROperand Translate(ILASTExpression expr, IRTranslator tr) { Debug.Assert(expr.Arguments.Length == 1); IRVariable ret = tr.Context.AllocateVRegister(expr.Type.Value); if (expr.Type != null && (expr.Type.Value == ASTType.R4 || expr.Type.Value == ASTType.R8)) { tr.Instructions.Add(new IRInstruction(IROpCode.MOV) { Operand1 = ret, Operand2 = IRConstant.FromI4(0) }); tr.Instructions.Add(new IRInstruction(IROpCode.SUB) { Operand1 = ret, Operand2 = tr.Translate(expr.Arguments[0]) }); } else { // -A = ~A + 1 tr.Instructions.Add(new IRInstruction(IROpCode.MOV) { Operand1 = ret, Operand2 = tr.Translate(expr.Arguments[0]) }); tr.Instructions.Add(new IRInstruction(IROpCode.__NOT) { Operand1 = ret }); tr.Instructions.Add(new IRInstruction(IROpCode.ADD) { Operand1 = ret, Operand2 = IRConstant.FromI4(1) }); } return(ret); }
public override void Run(IRContext context) { bool changed = true; while (changed) { changed = false; foreach (var block in context.Function.BasicBlocks) { for (int i = 0; i < block.Instructions.Count; i++) { var instruction = block.Instructions[i]; IRVariable v = null; IRConstant irConst = null; foreach (var use in instruction.Uses) { var defs = block.FindDefs(i, use); if (defs.Length != 1) { continue; } if (defs[0] is IRAssignment assgn && assgn.Source is IRConstant irc) { irConst = irc; v = use; break; } } if (!(irConst is null)) { instruction.SubstituteUse(v, irConst); changed = true; } } } } }
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 static IIROperand PromoteConstantR8(IRConstant value) { if (value.Type.Value == ASTType.I4) { value.Type = ASTType.R8; value.Value = (double)(int)value.Value; } else if (value.Type.Value == ASTType.I8) { value.Type = ASTType.R8; value.Value = (double)(long)value.Value; } else if (value.Type.Value == ASTType.R4) { value.Type = ASTType.R8; value.Value = (double)(float)value.Value; } else if (value.Type.Value != ASTType.R8) { throw new InvalidProgramException(); } return(value); }
public IIROperand Translate(ILASTExpression expr, IRTranslator tr) { // TODO: overflow? Debug.Assert(expr.Arguments.Length == 1); var value = tr.Translate(expr.Arguments[0]); var valueType = value.Type; if (valueType == ASTType.Ptr || valueType == ASTType.I4) // no conversion needed. { return(value); } var retVar = tr.Context.AllocateVRegister(ASTType.Ptr); switch (valueType) { case ASTType.R4: case ASTType.R8: var tmp = tr.Context.AllocateVRegister(ASTType.I8); tr.Instructions.Add(new IRInstruction(IROpCode.__SETF) { Operand1 = IRConstant.FromI4(1 << tr.Arch.Flags.UNSIGNED) }); tr.Instructions.Add(new IRInstruction(IROpCode.ICONV, tmp, value)); tr.Instructions.Add(new IRInstruction(IROpCode.MOV, retVar, tmp)); break; case ASTType.I8: tr.Instructions.Add(new IRInstruction(IROpCode.MOV, retVar, value)); 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]); var targetType = ((ITypeDefOrRef)expr.Operand).ToTypeSig(); if (!targetType.GetElementType().IsPrimitive() && targetType.ElementType != ElementType.Object && !targetType.ToTypeDefOrRef().ResolveTypeDefThrow().IsEnum) { 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.UNBOX; 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 IIROperand Translate(ILASTExpression expr, IRTranslator tr) { IRVariable retVar = tr.Context.AllocateVRegister(expr.Type.Value); int refId = (int)tr.VM.Data.GetId((IMemberRef)expr.Operand); int ecallId = tr.VM.Runtime.VMCall.TOKEN; tr.Instructions.Add(new IRInstruction(IROpCode.VCALL, IRConstant.FromI4(ecallId), IRConstant.FromI4(refId))); tr.Instructions.Add(new IRInstruction(IROpCode.POP, retVar)); return(retVar); }
public IIROperand Translate(ILASTExpression expr, IRTranslator tr) => IRConstant.FromString((string)expr.Operand);
public IIROperand Translate(ILASTExpression expr, IRTranslator tr) => IRConstant.Null();
public IIROperand Translate(ILASTExpression expr, IRTranslator tr) => IRConstant.FromR8((double)expr.Operand);
public IIROperand Translate(ILASTExpression expr, IRTranslator tr) => IRConstant.FromR4((float)expr.Operand);
public IIROperand Translate(ILASTExpression expr, IRTranslator tr) { var typeId = (int)tr.Runtime.Descriptor.Data.GetId((ITypeDefOrRef)expr.Operand); var retVar = tr.Context.AllocateVRegister(expr.Type.Value); var ecallId = tr.VM.Runtime.VMCall.SIZEOF; tr.Instructions.Add(new IRInstruction(IROpCode.VCALL, IRConstant.FromI4(ecallId), IRConstant.FromI4(typeId))); tr.Instructions.Add(new IRInstruction(IROpCode.POP, retVar)); return(retVar); }
public IIROperand Translate(ILASTExpression expr, IRTranslator tr) { Debug.Assert(expr.Arguments.Length == 1); var addr = tr.Translate(expr.Arguments[0]); var typeId = (int)tr.VM.Data.GetId((ITypeDefOrRef)expr.Operand); var 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) { return(IRConstant.Null()); }
public IIROperand Translate(ILASTExpression expr, IRTranslator tr) { return(IRConstant.FromI8((long)expr.Operand)); }