public IIROperand Translate(ILASTExpression expr, IRTranslator tr) { Debug.Assert(expr.Arguments.Length == 1); var value = tr.Translate(expr.Arguments[0]); var targetType = ((ITypeDefOrRef)expr.Operand).ToTypeSig(); 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.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) { 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.__XOR) { Operand1 = ret, Operand2 = tr.Translate(expr.Arguments[1]) }); return(ret); }
public IIROperand Translate(ILASTExpression expr, IRTranslator tr) { var local = tr.Context.ResolveLocal((Local)expr.Operand); var ret = tr.Context.AllocateVRegister(local.Type); tr.Instructions.Add(new IRInstruction(IROpCode.MOV, ret, local)); if (local.RawType.ElementType == ElementType.I1 || local.RawType.ElementType == ElementType.I2) { ret.RawType = local.RawType; var r = tr.Context.AllocateVRegister(local.Type); tr.Instructions.Add(new IRInstruction(IROpCode.SX, r, ret)); ret = r; } return(ret); }
public IIROperand Translate(ILASTExpression expr, IRTranslator tr) { IRVariable param = tr.Context.ResolveParameter((Parameter)expr.Operand); IRVariable ret = tr.Context.AllocateVRegister(param.Type); tr.Instructions.Add(new IRInstruction(IROpCode.MOV, ret, param)); if (param.RawType.ElementType == ElementType.I1 || param.RawType.ElementType == ElementType.I2) { ret.RawType = param.RawType; IRVariable r = tr.Context.AllocateVRegister(param.Type); tr.Instructions.Add(new IRInstruction(IROpCode.SX, r, ret)); ret = r; } return(ret); }
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.UInt16; 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(ushort.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 void TransformLDELEM(ILASTExpression expr, ModuleDef module, ITypeDefOrRef type) { TypeRef array = module.CorLibTypes.GetTypeRef("System", "Array"); var getValSig = MethodSig.CreateInstance(module.CorLibTypes.Object, module.CorLibTypes.Int32); var getValRef = new MemberRefUser(module, "GetValue", getValSig, array); var getValue = new ILASTExpression { ILCode = Code.Call, Operand = getValRef, Arguments = expr.Arguments }; expr.ILCode = Code.Unbox_Any; expr.Operand = type.IsValueType ? module.CorLibTypes.Object.ToTypeDefOrRef() : type; expr.Type = TypeInference.ToASTType(type.ToTypeSig()); expr.Arguments = new IILASTNode[] { getValue }; }
ASTType?ProcessExpression(ILASTExpression expr) { foreach (var arg in expr.Arguments) { if (arg is ILASTExpression) { var argExpr = (ILASTExpression)arg; argExpr.Type = ProcessExpression(argExpr).Value; } } var exprType = InferType(expr); if (exprType != null) { expr.Type = exprType.Value; } return(exprType); }
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); }
static void Transform(ILASTExpression expr, ILASTTransformer tr) { if (expr.ILCode != Code.Ldstr) { return; } var operand = (string)expr.Operand; expr.ILCode = Code.Box; expr.Operand = tr.Method.Module.CorLibTypes.String.ToTypeDefOrRef(); expr.Arguments = new IILASTNode[] { new ILASTExpression { ILCode = Code.Ldc_I4, Operand = (int)tr.VM.Data.GetId(operand), Arguments = new IILASTNode[0] } }; }
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) { if (expr.Arguments.Length == 1) { var 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) { 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); }
private static ASTType?InferType(ILASTExpression expr) { if (expr.Type != null) { return(expr.Type); } var opCode = expr.ILCode.ToOpCode(); switch (opCode.StackBehaviourPush) { case StackBehaviour.Push1: return(InferPush1(expr)); case StackBehaviour.Pushi: return(InferPushI(expr)); case StackBehaviour.Pushi8: return(InferPushI8(expr)); case StackBehaviour.Pushr4: return(InferPushR4(expr)); case StackBehaviour.Pushr8: return(InferPushR8(expr)); case StackBehaviour.Pushref: return(InferPushRef(expr)); case StackBehaviour.Varpush: return(InferVarPush(expr)); case StackBehaviour.Push1_push1: Debug.Assert(expr.Arguments.Length == 1); return(expr.Arguments[0].Type); case StackBehaviour.Push0: default: return(null); } }
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); }
public IIROperand Translate(ILASTExpression expr, IRTranslator tr) { Debug.Assert(expr.Arguments.Length == 2); IRVariable 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 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); }
private static ASTType?InferVarPush(ILASTExpression expr) { var method = (IMethod)expr.Operand; if (method.MethodSig.RetType.ElementType == ElementType.Void) { return(null); } var genArgs = new GenericArguments(); if (method is MethodSpec) { genArgs.PushMethodArgs(((MethodSpec)method).GenericInstMethodSig.GenericArguments); } if (method.DeclaringType.TryGetGenericInstSig() != null) { genArgs.PushTypeArgs(method.DeclaringType.TryGetGenericInstSig().GenericArguments); } return(TypeInference.ToASTType(genArgs.ResolveType(method.MethodSig.RetType))); }
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); }
private static ASTType?InferPushI(ILASTExpression expr) { switch (expr.ILCode) { case Code.Ldftn: case Code.Ldind_I: case Code.Ldelem_I: case Code.Ldvirtftn: case Code.Localloc: case Code.Conv_U: case Code.Conv_Ovf_U: case Code.Conv_Ovf_U_Un: case Code.Conv_I: case Code.Conv_Ovf_I: case Code.Conv_Ovf_I_Un: return(ASTType.Ptr); case Code.Ldarga: case Code.Ldelema: case Code.Ldflda: case Code.Ldloca: case Code.Ldsflda: return(ASTType.ByRef); case Code.Ldtoken: case Code.Arglist: case Code.Unbox: case Code.Refanytype: case Code.Refanyval: case Code.Isinst: return(ASTType.O); default: return(ASTType.I4); } }
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) { return(IRConstant.Null()); }
public IIROperand Translate(ILASTExpression expr, IRTranslator tr) { return(IRConstant.FromI8((long)expr.Operand)); }
private ILASTTree BuildAST(CILInstrList instrs, ILASTVariable[] beginStack) { var tree = new ILASTTree(); var evalStack = new Stack <ILASTVariable>(beginStack); Func <int, IILASTNode[]> popArgs = numArgs => { var args = new IILASTNode[numArgs]; for (int i = numArgs - 1; i >= 0; i--) { args[i] = evalStack.Pop(); } return(args); }; var prefixes = new List <Instruction>(); foreach (Instruction instr in instrs) { if (instr.OpCode.OpCodeType == OpCodeType.Prefix) { prefixes.Add(instr); continue; } int pushes, pops; ILASTExpression expr; if (instr.OpCode.Code == Code.Dup) { pushes = pops = 1; ILASTVariable arg = evalStack.Peek(); expr = new ILASTExpression { ILCode = Code.Dup, Operand = null, Arguments = new IILASTNode[] { arg } }; } else { instr.CalculateStackUsage(this.method.ReturnType.ElementType != ElementType.Void, out pushes, out pops); Debug.Assert(pushes == 0 || pushes == 1); if (pops == -1) { evalStack.Clear(); pops = 0; } expr = new ILASTExpression { ILCode = instr.OpCode.Code, Operand = instr.Operand, Arguments = popArgs(pops) }; if (expr.Operand is Instruction || expr.Operand is Instruction[]) { this.instrReferences.Add(expr); } } expr.CILInstr = instr; if (prefixes.Count > 0) { expr.Prefixes = prefixes.ToArray(); prefixes.Clear(); } if (pushes == 1) { var variable = new ILASTVariable { Name = string.Format("s_{0:x4}", instr.Offset), VariableType = ILASTVariableType.StackVar }; evalStack.Push(variable); tree.Add(new ILASTAssignment { Variable = variable, Value = expr }); } else { tree.Add(expr); } } tree.StackRemains = evalStack.Reverse().ToArray(); return(tree); }
static void Transform(ILASTExpression expr, ModuleDef module) { switch (expr.ILCode) { case Code.Ldlen: { expr.ILCode = Code.Call; var array = module.CorLibTypes.GetTypeRef("System", "Array"); var lenSig = MethodSig.CreateInstance(module.CorLibTypes.Int32); var methodRef = new MemberRefUser(module, "get_Length", lenSig, array); expr.Operand = methodRef; break; } case Code.Newarr: { expr.ILCode = Code.Newobj; var array = new SZArraySig(((ITypeDefOrRef)expr.Operand).ToTypeSig()).ToTypeDefOrRef(); var ctorSig = MethodSig.CreateInstance(module.CorLibTypes.Void, module.CorLibTypes.Int32); var ctorRef = new MemberRefUser(module, ".ctor", ctorSig, array); expr.Operand = ctorRef; break; } case Code.Ldelema: { expr.ILCode = Code.Call; var elemType = ((ITypeDefOrRef)expr.Operand).ToTypeSig(); var array = new SZArraySig(elemType).ToTypeDefOrRef(); var addrSig = MethodSig.CreateInstance(new ByRefSig(elemType), module.CorLibTypes.Int32); var addrRef = new MemberRefUser(module, "Address", addrSig, array); expr.Operand = addrRef; break; } case Code.Ldelem: TransformLDELEM(expr, module, (ITypeDefOrRef)expr.Operand); break; case Code.Ldelem_I1: TransformLDELEM(expr, module, module.CorLibTypes.SByte.ToTypeDefOrRef()); break; case Code.Ldelem_U1: TransformLDELEM(expr, module, module.CorLibTypes.Byte.ToTypeDefOrRef()); break; case Code.Ldelem_I2: TransformLDELEM(expr, module, module.CorLibTypes.Int16.ToTypeDefOrRef()); break; case Code.Ldelem_U2: TransformLDELEM(expr, module, module.CorLibTypes.UInt16.ToTypeDefOrRef()); break; case Code.Ldelem_I4: TransformLDELEM(expr, module, module.CorLibTypes.Int32.ToTypeDefOrRef()); break; case Code.Ldelem_U4: TransformLDELEM(expr, module, module.CorLibTypes.UInt32.ToTypeDefOrRef()); break; case Code.Ldelem_I8: TransformLDELEM(expr, module, module.CorLibTypes.Int64.ToTypeDefOrRef()); break; case Code.Ldelem_R4: TransformLDELEM(expr, module, module.CorLibTypes.Single.ToTypeDefOrRef()); break; case Code.Ldelem_R8: TransformLDELEM(expr, module, module.CorLibTypes.Double.ToTypeDefOrRef()); break; case Code.Ldelem_I: TransformLDELEM(expr, module, module.CorLibTypes.IntPtr.ToTypeDefOrRef()); break; case Code.Ldelem_Ref: TransformLDELEM(expr, module, module.CorLibTypes.Object.ToTypeDefOrRef()); break; } }
public IIROperand Translate(ILASTExpression expr, IRTranslator tr) { throw new NotSupportedException(); }
public IIROperand Translate(ILASTExpression expr, IRTranslator tr) => IRConstant.Null();
public IIROperand Translate(ILASTExpression expr, IRTranslator tr) => IRConstant.FromString((string)expr.Operand);
public IIROperand Translate(ILASTExpression expr, IRTranslator tr) { tr.Instructions.Add(new IRInstruction(IROpCode.__EHRET)); tr.Block.Flags |= BlockFlags.ExitEHReturn; return(null); }