private static BasicBlock InlineIR(this CALLInstruction call, IList<BasicBlockInstruction> preamble, BasicBlock backend, Dictionary<Subprogram, Dictionary<VirtualRegister, VirtualRegister>> inlineRegMaps) { Dictionary<VirtualRegister, VirtualRegister> inlineRegMap; if (!inlineRegMaps.TryGetValue(call.Target, out inlineRegMap)) { inlineRegMap = call.Target.LocalVariables.Select(lv => new KeyValuePair<VirtualRegister, VirtualRegister>(lv, new VirtualRegister(lv.UnderlyingType, lv.StateSpace))). ToDictionary(kvp => kvp.Key, kvp => kvp.Value); inlineRegMaps.Add(call.Target, inlineRegMap); } inlineRegMap = inlineRegMap.Concat(call.Target.FormalParameters.Zip(call.Arguments, (formal, actual) => new KeyValuePair<VirtualRegister, VirtualRegister>(formal, (actual is VirtualRegister) ? (actual as VirtualRegister) : (formal.StateSpace != StateSpaces.REG) ? new VirtualRegister(formal.UnderlyingType, formal.StateSpace) : new VirtualRegister(formal.DataType)))). ToDictionary(kvp => kvp.Key, kvp => kvp.Value); Dictionary<BasicBlock, BasicBlock> cfgmap = call.Target.GetBasicBlocks().Select(bb => { VirtualRegister flag = (bb.Trailer is JumpIfInstruction) ? (bb.Trailer as JumpIfInstruction).Flag.MapOperand(inlineRegMap) : null; ControlFlowInstruction trailer; switch (bb.Trailer.OpCode) { case IROpCodes.RET: trailer = new JMPInstruction() { Target = backend }; break; case IROpCodes.JMP: trailer = new JMPInstruction(); break; case IROpCodes.JT: trailer = new JTInstruction(flag); break; case IROpCodes.JF: trailer = new JFInstruction(flag); break; default: throw new NotSupportedException(); } return new KeyValuePair<BasicBlock, BasicBlock>(bb, new BasicBlock(bb.Code.Select(bbi => bbi.MapInstruction(inlineRegMap)).ToList(), trailer)); }).ToDictionary(kvp => kvp.Key, kvp => kvp.Value); foreach (KeyValuePair<BasicBlock, BasicBlock> bbmap in cfgmap) { if (bbmap.Key.Successor != null) bbmap.Value.Successor = cfgmap[bbmap.Key.Successor]; if (bbmap.Key.Target != null) bbmap.Value.Target = cfgmap[bbmap.Key.Target]; } BasicBlock root = cfgmap[call.Target.CFGRoot]; return new BasicBlock(preamble.Concat(root.Code).ToList(), root.Trailer); }
private static BasicBlock InlineIR(this BasicBlock bb, Func <Subprogram, bool> permitInline, Dictionary <VirtualRegister, VirtualRegister> copyRegMap, Dictionary <Subprogram, Dictionary <VirtualRegister, VirtualRegister> > inlineRegMaps, IList <Subprogram> subprograms, Dictionary <BasicBlock, BasicBlock> basicBlockMap) { BasicBlock result; if (!basicBlockMap.TryGetValue(bb, out result)) { VirtualRegister flag = (bb.Trailer is JumpIfInstruction) ? (bb.Trailer as JumpIfInstruction).Flag.MapOperand(copyRegMap) : null; ControlFlowInstruction trailer; switch (bb.Trailer.OpCode) { case IROpCodes.RET: trailer = new RETInstruction(); break; case IROpCodes.JMP: trailer = new JMPInstruction(); break; case IROpCodes.JT: trailer = new JTInstruction(flag); break; case IROpCodes.JF: trailer = new JFInstruction(flag); break; default: throw new NotSupportedException(); } BasicBlock backend; result = bb.Code.InlineIR(trailer, permitInline, copyRegMap, inlineRegMaps, subprograms, out backend); basicBlockMap.Add(bb, result); if (bb.Successor != null) { backend.Successor = bb.Successor.InlineIR(permitInline, copyRegMap, inlineRegMaps, subprograms, basicBlockMap); } if (bb.Target != null) { backend.Target = bb.Target.InlineIR(permitInline, copyRegMap, inlineRegMaps, subprograms, basicBlockMap); } } return(result); }
private static BasicBlock InlineIR(this BasicBlock bb, Func<Subprogram, bool> permitInline, Dictionary<VirtualRegister, VirtualRegister> copyRegMap, Dictionary<Subprogram, Dictionary<VirtualRegister, VirtualRegister>> inlineRegMaps, IList<Subprogram> subprograms, Dictionary<BasicBlock, BasicBlock> basicBlockMap) { BasicBlock result; if (!basicBlockMap.TryGetValue(bb, out result)) { VirtualRegister flag = (bb.Trailer is JumpIfInstruction) ? (bb.Trailer as JumpIfInstruction).Flag.MapOperand(copyRegMap) : null; ControlFlowInstruction trailer; switch (bb.Trailer.OpCode) { case IROpCodes.RET: trailer = new RETInstruction(); break; case IROpCodes.JMP: trailer = new JMPInstruction(); break; case IROpCodes.JT: trailer = new JTInstruction(flag); break; case IROpCodes.JF: trailer = new JFInstruction(flag); break; default: throw new NotSupportedException(); } BasicBlock backend; result = bb.Code.InlineIR(trailer, permitInline, copyRegMap, inlineRegMaps, subprograms, out backend); basicBlockMap.Add(bb, result); if (bb.Successor != null) backend.Successor = bb.Successor.InlineIR(permitInline, copyRegMap, inlineRegMaps, subprograms, basicBlockMap); if (bb.Target != null) backend.Target = bb.Target.InlineIR(permitInline, copyRegMap, inlineRegMaps, subprograms, basicBlockMap); } return result; }
private static BasicBlock InlineIR(this CALLInstruction call, IList <BasicBlockInstruction> preamble, BasicBlock backend, Dictionary <Subprogram, Dictionary <VirtualRegister, VirtualRegister> > inlineRegMaps) { Dictionary <VirtualRegister, VirtualRegister> inlineRegMap; if (!inlineRegMaps.TryGetValue(call.Target, out inlineRegMap)) { inlineRegMap = call.Target.LocalVariables.Select(lv => new KeyValuePair <VirtualRegister, VirtualRegister>(lv, new VirtualRegister(lv.UnderlyingType, lv.StateSpace))). ToDictionary(kvp => kvp.Key, kvp => kvp.Value); inlineRegMaps.Add(call.Target, inlineRegMap); } inlineRegMap = inlineRegMap.Concat(call.Target.FormalParameters.Zip(call.Arguments, (formal, actual) => new KeyValuePair <VirtualRegister, VirtualRegister>(formal, (actual is VirtualRegister) ? (actual as VirtualRegister) : (formal.StateSpace != StateSpaces.REG) ? new VirtualRegister(formal.UnderlyingType, formal.StateSpace) : new VirtualRegister(formal.DataType)))). ToDictionary(kvp => kvp.Key, kvp => kvp.Value); Dictionary <BasicBlock, BasicBlock> cfgmap = call.Target.GetBasicBlocks().Select(bb => { VirtualRegister flag = (bb.Trailer is JumpIfInstruction) ? (bb.Trailer as JumpIfInstruction).Flag.MapOperand(inlineRegMap) : null; ControlFlowInstruction trailer; switch (bb.Trailer.OpCode) { case IROpCodes.RET: trailer = new JMPInstruction() { Target = backend }; break; case IROpCodes.JMP: trailer = new JMPInstruction(); break; case IROpCodes.JT: trailer = new JTInstruction(flag); break; case IROpCodes.JF: trailer = new JFInstruction(flag); break; default: throw new NotSupportedException(); } return(new KeyValuePair <BasicBlock, BasicBlock>(bb, new BasicBlock(bb.Code.Select(bbi => bbi.MapInstruction(inlineRegMap)).ToList(), trailer))); }).ToDictionary(kvp => kvp.Key, kvp => kvp.Value); foreach (KeyValuePair <BasicBlock, BasicBlock> bbmap in cfgmap) { if (bbmap.Key.Successor != null) { bbmap.Value.Successor = cfgmap[bbmap.Key.Successor]; } if (bbmap.Key.Target != null) { bbmap.Value.Target = cfgmap[bbmap.Key.Target]; } } BasicBlock root = cfgmap[call.Target.CFGRoot]; return(new BasicBlock(preamble.Concat(root.Code).ToList(), root.Trailer)); }
public InstructionSelector(IList<Instruction> cilbbcode, Stack<Tuple<Tuple<GenericOperand, bool>, InstructionSelector>> stack, IList<FormalParameter> parameters, IList<VirtualRegister> variables, bool result, IList<SpecialRegister> srpool, IDictionary<MethodInfo, Subprogram> spmap, Func<Type, StateSpaces, DynamicRegister> regalloc) { this.stack = stack; this.regalloc = regalloc; bool skipnext = false; foreach (Instruction cilinstr in cilbbcode) { if (skipnext) { skipnext = false; continue; } if (Trailer != null) throw new ArgumentException("No instruction is permitted after trailing control flow one", "cilbbcode"); GenericOperand left = null; GenericOperand right = null; GenericOperand extra = null; VirtualRegister regleft = null; VirtualRegister regright = null; VirtualRegister target = null; FormalParameter arg = null; VirtualRegister loc = null; CILOpCodes cilopcode = (CILOpCodes)cilinstr.OpCode.Value; bool isArithmetic = cilopcode >= CILOpCodes.Add && cilopcode <= CILOpCodes.Xor; bool isCompare = cilopcode >= CILOpCodes.Ceq && cilopcode <= CILOpCodes.Clt_Un; bool isCompBranch = cilopcode >= CILOpCodes.Beq_S && cilopcode <= CILOpCodes.Blt_Un_S || cilopcode >= CILOpCodes.Beq && cilopcode <= CILOpCodes.Blt_Un; if (isArithmetic || isCompare || isCompBranch) { right = RetrieveOperand(); left = RetrieveOperand(); if (cilopcode == CILOpCodes.Mul && cilinstr.Next != null && (CILOpCodes)cilinstr.Next.OpCode.Value == CILOpCodes.Add) extra = RetrieveOperand(); Type targetType = ArithmeticMapping[left.DataType][right.DataType]; right = ConvertOperand(right, targetType); left = ConvertOperand(left, targetType); if (extra != null) extra = ConvertOperand(extra, targetType); ReleaseOperand(right); ReleaseOperand(left); if (extra != null) ReleaseOperand(extra); target = AllocateRegister(isArithmetic ? targetType : typeof(int)); if (!isCompBranch) PushByVal(target); } switch (cilopcode) { // Method arguments loading case CILOpCodes.Ldarg_0: case CILOpCodes.Ldarg_1: case CILOpCodes.Ldarg_2: case CILOpCodes.Ldarg_3: case CILOpCodes.Ldarg_S: case CILOpCodes.Ldarg: arg = parameters[(cilinstr.Operand == null) ? (cilopcode - CILOpCodes.Ldarg_0) : (cilinstr.Operand as ParameterInfo).Position]; if (arg.PassingStyle == PassingStyles.VAL) { target = AllocateRegister(arg.StateSpace != StateSpaces.REG ? arg.UnderlyingType : arg.DataType, arg.StateSpace); code.Add(new UnaryOperation(IROpCodes.MOV, target, arg)); PushByVal(target); } else PushByRef(arg); break; case CILOpCodes.Ldarga_S: case CILOpCodes.Ldarga: arg = parameters[(cilinstr.Operand as ParameterInfo).Position]; PushByRef(arg); break; // Local variables loading case CILOpCodes.Ldloc_0: case CILOpCodes.Ldloc_1: case CILOpCodes.Ldloc_2: case CILOpCodes.Ldloc_3: case CILOpCodes.Ldloc_S: case CILOpCodes.Ldloc: loc = variables[(cilinstr.Operand == null) ? (cilopcode - CILOpCodes.Ldloc_0) : (cilinstr.Operand as LocalVariableInfo).LocalIndex]; target = AllocateRegister(loc.UnderlyingType, loc.StateSpace); code.Add(new UnaryOperation(IROpCodes.MOV, target, loc)); PushByVal(target); break; case CILOpCodes.Ldloca_S: case CILOpCodes.Ldloca: loc = variables[(cilinstr.Operand as LocalVariableInfo).LocalIndex]; PushByRef(loc); break; // Method arguments storing case CILOpCodes.Starg_S: case CILOpCodes.Starg: arg = parameters[(cilinstr.Operand as ParameterInfo).Position]; right = RetrieveOperand(); if (arg.DataType != right.DataType) code.Add(new UnaryOperation(IROpCodes.CVT, arg, right)); else code.Add(new UnaryOperation(IROpCodes.MOV, arg, right)); ReleaseOperand(right); break; // Local variables storing case CILOpCodes.Stloc_0: case CILOpCodes.Stloc_1: case CILOpCodes.Stloc_2: case CILOpCodes.Stloc_3: case CILOpCodes.Stloc_S: case CILOpCodes.Stloc: loc = variables[(cilinstr.Operand == null) ? (cilopcode - CILOpCodes.Stloc_0) : (cilinstr.Operand as LocalVariableInfo).LocalIndex]; right = RetrieveOperand(); if (loc.DataType != right.DataType) code.Add(new UnaryOperation(IROpCodes.CVT, loc, right)); else code.Add(new UnaryOperation(IROpCodes.MOV, loc, right)); ReleaseOperand(right); break; // Constants storing case CILOpCodes.Ldnull: PushByRef(new ImmediateValue((int)0)); break; case CILOpCodes.Ldc_I4_M1: case CILOpCodes.Ldc_I4_0: case CILOpCodes.Ldc_I4_1: case CILOpCodes.Ldc_I4_2: case CILOpCodes.Ldc_I4_3: case CILOpCodes.Ldc_I4_4: case CILOpCodes.Ldc_I4_5: case CILOpCodes.Ldc_I4_6: case CILOpCodes.Ldc_I4_7: case CILOpCodes.Ldc_I4_8: case CILOpCodes.Ldc_I4_S: case CILOpCodes.Ldc_I4: case CILOpCodes.Ldc_I8: case CILOpCodes.Ldc_R4: case CILOpCodes.Ldc_R8: PushByRef(new ImmediateValue((cilinstr.Operand == null) ? (int)(cilopcode - CILOpCodes.Ldc_I4_0) : (ValueType)Convert.ChangeType(cilinstr.Operand, UpconvertMapping[cilinstr.Operand.GetType()]))); break; // Array elements loading case CILOpCodes.Ldelem_I1: case CILOpCodes.Ldelem_U1: case CILOpCodes.Ldelem_I2: case CILOpCodes.Ldelem_U2: case CILOpCodes.Ldelem_I4: case CILOpCodes.Ldelem_U4: case CILOpCodes.Ldelem_I8: case CILOpCodes.Ldelem_R4: case CILOpCodes.Ldelem_R8: case CILOpCodes.Ldelem: regright = MapToRegister(RetrieveOperand()); // index regleft = RetrieveOperand() as VirtualRegister; // array VirtualRegister address = CalculateAddress(regleft, regright); target = AllocateRegister(UpconvertMapping[regleft.UnderlyingType]); code.Add(new LDInstruction(target, address)); ReleaseOperand(address); PushByVal(target); break; case CILOpCodes.Ldelema: regright = MapToRegister(RetrieveOperand()); // index regleft = RetrieveOperand() as VirtualRegister; // array PushByVal(CalculateAddress(regleft, regright)); break; // Array elements storing case CILOpCodes.Stelem_I1: case CILOpCodes.Stelem_I2: case CILOpCodes.Stelem_I4: case CILOpCodes.Stelem_I8: case CILOpCodes.Stelem_R4: case CILOpCodes.Stelem_R8: case CILOpCodes.Stelem: GenericOperand val = RetrieveOperand(); // value regright = MapToRegister(RetrieveOperand()); // index regleft = RetrieveOperand() as VirtualRegister; // array IEnumerable<Type> compatible = regleft.UnderlyingType.CompatibleTypes().Where(type => type.SizeOf() >= sizeof(int)); target = !compatible.Contains(val.DataType) ? ConvertOperand(val, compatible.First()) as VirtualRegister : MapToRegister(val); address = CalculateAddress(regleft, regright); code.Add(new STInstruction(address, target)); ReleaseOperand(address); ReleaseOperand(target); break; // Indirect loads case CILOpCodes.Ldobj: case CILOpCodes.Ldind_I1: case CILOpCodes.Ldind_U1: case CILOpCodes.Ldind_I2: case CILOpCodes.Ldind_U2: case CILOpCodes.Ldind_I4: case CILOpCodes.Ldind_U4: case CILOpCodes.Ldind_I8: case CILOpCodes.Ldind_R4: case CILOpCodes.Ldind_R8: // pointer (induced by ldelema) / variable (induced by ldloca) / parameter (induced by ldarga or pass-by-ref ldarg) regright = RetrieveOperand() as VirtualRegister; if (regright.StateSpace == StateSpaces.REG) { target = AllocateRegister(regright.DataType); code.Add(new UnaryOperation(IROpCodes.MOV, target, regright)); } else { target = AllocateRegister(UpconvertMapping[regright.UnderlyingType]); code.Add(new LDInstruction(target, regright)); } ReleaseOperand(regright); PushByVal(target); break; case CILOpCodes.Ldind_Ref: regright = RetrieveOperand() as VirtualRegister; // pointer (induced by pass-by-ref ldarg) target = AllocateRegister(regright.UnderlyingType, regright.StateSpace); code.Add(new UnaryOperation(IROpCodes.MOV, target, regright)); ReleaseOperand(regright); PushByVal(target); break; // Indirect stores case CILOpCodes.Stobj: case CILOpCodes.Stind_I1: case CILOpCodes.Stind_I2: case CILOpCodes.Stind_I4: case CILOpCodes.Stind_I8: case CILOpCodes.Stind_R4: case CILOpCodes.Stind_R8: right = RetrieveOperand(); // value // pointer (induced by ldelema) / variable (induced by ldloca) / parameter (induced by ldarga or pass-by-ref ldarg) regleft = RetrieveOperand() as VirtualRegister; if (regleft.StateSpace == StateSpaces.REG) { if (regleft.DataType != right.DataType) code.Add(new UnaryOperation(IROpCodes.CVT, regleft, right)); else code.Add(new UnaryOperation(IROpCodes.MOV, regleft, right)); ReleaseOperand(right); } else { compatible = regleft.UnderlyingType.CompatibleTypes().Where(type => type.SizeOf() >= sizeof(int)); regright = !compatible.Contains(right.DataType) ? ConvertOperand(right, compatible.First()) as VirtualRegister : MapToRegister(right); code.Add(new STInstruction(regleft, regright)); ReleaseOperand(regright); } ReleaseOperand(regleft); break; case CILOpCodes.Stind_Ref: regright = RetrieveOperand() as VirtualRegister; // source pointer (induced by ldarg or pass-by-ref ldarg) regleft = RetrieveOperand() as VirtualRegister; // target pointer (induced by pass-by-ref ldarg) code.Add(new UnaryOperation(IROpCodes.MOV, regleft, regright)); ReleaseOperand(regleft); ReleaseOperand(regright); break; // Comparison branches case CILOpCodes.Beq: case CILOpCodes.Beq_S: code.Add(new BinaryOperation(IROpCodes.EQ, target, left, right)); goto case CILOpCodes.Brtrue; case CILOpCodes.Bne_Un: case CILOpCodes.Bne_Un_S: code.Add(new BinaryOperation(IROpCodes.NE, target, left, right)); goto case CILOpCodes.Brtrue; case CILOpCodes.Bge_S: case CILOpCodes.Bge_Un_S: case CILOpCodes.Bge: case CILOpCodes.Bge_Un: code.Add(new BinaryOperation(IROpCodes.GE, target, left, right)); goto case CILOpCodes.Brtrue; case CILOpCodes.Bgt_S: case CILOpCodes.Bgt_Un_S: case CILOpCodes.Bgt: case CILOpCodes.Bgt_Un: code.Add(new BinaryOperation(IROpCodes.GT, target, left, right)); goto case CILOpCodes.Brtrue; case CILOpCodes.Ble_S: case CILOpCodes.Ble_Un_S: case CILOpCodes.Ble: case CILOpCodes.Ble_Un: code.Add(new BinaryOperation(IROpCodes.LE, target, left, right)); goto case CILOpCodes.Brtrue; case CILOpCodes.Blt_S: case CILOpCodes.Blt_Un_S: case CILOpCodes.Blt: case CILOpCodes.Blt_Un: code.Add(new BinaryOperation(IROpCodes.LT, target, left, right)); goto case CILOpCodes.Brtrue; // Basic branches (the last instructions in basic block) case CILOpCodes.Br_S: case CILOpCodes.Br: Trailer = new JMPInstruction(); break; case CILOpCodes.Brfalse_S: case CILOpCodes.Brfalse: regleft = MapToRegister(ConvertOperand(RetrieveOperand(), typeof(int))); Trailer = new JFInstruction(regleft); ReleaseOperand(regleft); break; case CILOpCodes.Brtrue_S: case CILOpCodes.Brtrue: regleft = isCompBranch ? target : MapToRegister(ConvertOperand(RetrieveOperand(), typeof(int))); Trailer = new JTInstruction(regleft); ReleaseOperand(regleft); break; // Call stuff. case CILOpCodes.Call: MethodInfo method = cilinstr.Operand as MethodInfo; PropertyInfo property = method.DeclaringType.GetProperty(method.Name.Replace("get_", "")); if (property != null) { // Handle predefined value access. PredefinedValueAttribute pva = Attribute.GetCustomAttribute(property, typeof(PredefinedValueAttribute)) as PredefinedValueAttribute; if (pva != null) PushByVal(MapToRegister(srpool.Single(sr => sr.Value == pva.Value))); else throw new NotSupportedException(method.DeclaringType.FullName + "." + property.Name); } else { // Handle intrinsic function call. IntrinsicFunctionAttribute ifa = Attribute.GetCustomAttribute(method, typeof(IntrinsicFunctionAttribute)) as IntrinsicFunctionAttribute; if (ifa != null) { switch (ifa.OpCode) { case IROpCodes.SYNC: code.Add(new SYNCInstruction()); break; case IROpCodes.ABS: case IROpCodes.SQRT: case IROpCodes.RSQRT: case IROpCodes.SIN: case IROpCodes.COS: case IROpCodes.LG2: case IROpCodes.EX2: right = ConvertOperand(RetrieveOperand(), UpconvertMapping[method.ReturnType]); ReleaseOperand(right); target = AllocateRegister(right.DataType); code.Add(new UnaryOperation(ifa.OpCode, target, right)); PushByVal(target); break; case IROpCodes.MIN: case IROpCodes.MAX: right = ConvertOperand(RetrieveOperand(), UpconvertMapping[method.ReturnType]); left = ConvertOperand(RetrieveOperand(), right.DataType); ReleaseOperand(right); ReleaseOperand(left); target = AllocateRegister(right.DataType); code.Add(new BinaryOperation(ifa.OpCode, target, left, right)); PushByVal(target); break; default: throw new NotSupportedException(ifa.OpCode.ToString()); } } else { // Handle subprogram call. Subprogram sp; spmap.TryGetValue(method, out sp); if (sp == null) sp = method.BuildIR(srpool, spmap); List<GenericOperand> actualParameters = new List<GenericOperand>(); List<Tuple<VirtualRegister, VirtualRegister>> wrappedRefElements = new List<Tuple<VirtualRegister, VirtualRegister>>(); if (method.ReturnType != typeof(void)) { arg = sp.FormalParameters.Last(); target = AllocateRegister(arg.StateSpace != StateSpaces.REG ? arg.UnderlyingType : arg.DataType, arg.StateSpace); PushByVal(target); } foreach (FormalParameter fp in sp.FormalParameters.Reverse()) { GenericOperand ap = RetrieveOperand(); if (fp.StateSpace == StateSpaces.REG) { VirtualRegister regap = ap as VirtualRegister; if (regap != null && regap.StateSpace != StateSpaces.REG) { // Passing array element by reference. // Create wrapping register. regright = AllocateRegister(fp.DataType); // Load array element value to wrapping register. if (fp.PassingStyle == PassingStyles.REF) code.Add(new LDInstruction(regright, regap)); // Remember address-to-register mapping. wrappedRefElements.Add(new Tuple<VirtualRegister, VirtualRegister>(regap, regright)); // Replace original actual parameter with wrapping register. ap = regright; } else if (fp.PassingStyle == PassingStyles.VAL) { // Perform implicit parameter conversion. ap = ConvertOperand(ap, fp.DataType); } } actualParameters.Insert(0, ap); } code.Add(new CALLInstruction(sp, actualParameters)); // Update values of wrapped array elements. code.AddRange(wrappedRefElements.Select(we => new STInstruction(we.Item1, we.Item2))); foreach (VirtualRegister ap in actualParameters) ReleaseOperand(ap); foreach (Tuple<VirtualRegister, VirtualRegister> we in wrappedRefElements) ReleaseOperand(we.Item1); if (method.ReturnType != typeof(void)) { PushByVal(target); (target as DynamicRegister).Live = true; } } } break; // Arithmetic operations case CILOpCodes.Add: code.Add(new BinaryOperation(IROpCodes.ADD, target, left, right)); break; case CILOpCodes.Sub: code.Add(new BinaryOperation(IROpCodes.SUB, target, left, right)); break; case CILOpCodes.Mul: if (extra != null) { code.Add(new MADOperation(target, left, right, extra)); skipnext = true; } else code.Add(new BinaryOperation(IROpCodes.MUL, target, left, right)); break; case CILOpCodes.Div: case CILOpCodes.Div_Un: code.Add(new BinaryOperation(IROpCodes.DIV, target, left, right)); break; case CILOpCodes.Rem: case CILOpCodes.Rem_Un: code.Add(new BinaryOperation(IROpCodes.REM, target, left, right)); break; case CILOpCodes.And: code.Add(new BinaryOperation(IROpCodes.AND, target, left, right)); break; case CILOpCodes.Or: code.Add(new BinaryOperation(IROpCodes.OR, target, left, right)); break; case CILOpCodes.Xor: code.Add(new BinaryOperation(IROpCodes.XOR, target, left, right)); break; case CILOpCodes.Neg: right = RetrieveOperand(); right = ConvertOperand(right, NegMapping[right.DataType]); ReleaseOperand(right); target = AllocateRegister(right.DataType); code.Add(new UnaryOperation(IROpCodes.NEG, target, right)); PushByVal(target); break; case CILOpCodes.Not: right = RetrieveOperand(); right = ConvertOperand(right, NotMapping[right.DataType]); ReleaseOperand(right); target = AllocateRegister(right.DataType); code.Add(new UnaryOperation(IROpCodes.NOT, target, right)); PushByVal(target); break; // Convert operations case CILOpCodes.Conv_I1: case CILOpCodes.Conv_Ovf_I1: case CILOpCodes.Conv_Ovf_I1_Un: PushByVal(MapToRegister(ConvertOperand(RetrieveOperand(), typeof(sbyte)))); break; case CILOpCodes.Conv_I2: case CILOpCodes.Conv_Ovf_I2: case CILOpCodes.Conv_Ovf_I2_Un: PushByVal(MapToRegister(ConvertOperand(RetrieveOperand(), typeof(short)))); break; case CILOpCodes.Conv_I: case CILOpCodes.Conv_Ovf_I: case CILOpCodes.Conv_Ovf_I_Un: case CILOpCodes.Conv_U: case CILOpCodes.Conv_Ovf_U: case CILOpCodes.Conv_Ovf_U_Un: case CILOpCodes.Conv_I4: case CILOpCodes.Conv_Ovf_I4: case CILOpCodes.Conv_Ovf_I4_Un: PushByVal(MapToRegister(ConvertOperand(RetrieveOperand(), typeof(int)))); break; case CILOpCodes.Conv_I8: case CILOpCodes.Conv_Ovf_I8: case CILOpCodes.Conv_Ovf_I8_Un: PushByVal(MapToRegister(ConvertOperand(RetrieveOperand(), typeof(long)))); break; case CILOpCodes.Conv_U1: case CILOpCodes.Conv_Ovf_U1: case CILOpCodes.Conv_Ovf_U1_Un: PushByVal(MapToRegister(ConvertOperand(RetrieveOperand(), typeof(byte)))); break; case CILOpCodes.Conv_U2: case CILOpCodes.Conv_Ovf_U2: case CILOpCodes.Conv_Ovf_U2_Un: PushByVal(MapToRegister(ConvertOperand(RetrieveOperand(), typeof(ushort)))); break; case CILOpCodes.Conv_U4: case CILOpCodes.Conv_Ovf_U4: case CILOpCodes.Conv_Ovf_U4_Un: PushByVal(MapToRegister(ConvertOperand(RetrieveOperand(), typeof(uint)))); break; case CILOpCodes.Conv_U8: case CILOpCodes.Conv_Ovf_U8: case CILOpCodes.Conv_Ovf_U8_Un: PushByVal(MapToRegister(ConvertOperand(RetrieveOperand(), typeof(ulong)))); break; case CILOpCodes.Conv_R4: case CILOpCodes.Conv_R_Un: PushByVal(MapToRegister(ConvertOperand(RetrieveOperand(), typeof(float)))); break; case CILOpCodes.Conv_R8: PushByVal(MapToRegister(ConvertOperand(RetrieveOperand(), typeof(double)))); break; // Compare operations case CILOpCodes.Ceq: code.Add(new BinaryOperation(IROpCodes.EQ, target, left, right)); break; case CILOpCodes.Cgt: case CILOpCodes.Cgt_Un: code.Add(new BinaryOperation(IROpCodes.GT, target, left, right)); break; case CILOpCodes.Clt: case CILOpCodes.Clt_Un: code.Add(new BinaryOperation(IROpCodes.LT, target, left, right)); break; // Stack manipulation case CILOpCodes.Pop: ReleaseOperand(RetrieveOperand()); break; case CILOpCodes.Dup: bool byref = stack.Peek().Item1.Item2; right = RetrieveOperand(); if (byref) { PushByRef(right); PushByRef(right); } else { regright = right as VirtualRegister; PushByVal(regright); target = AllocateRegister(regright.UnderlyingType, regright.StateSpace); code.Add(new UnaryOperation(IROpCodes.MOV, target, regright)); PushByVal(target); } break; case CILOpCodes.Ret: if (result) { arg = parameters.Last(); right = RetrieveOperand(); if (arg.DataType != right.DataType) code.Add(new UnaryOperation(IROpCodes.CVT, arg, right)); else code.Add(new UnaryOperation(IROpCodes.MOV, arg, right)); ReleaseOperand(right); } Trailer = new RETInstruction(); break; case CILOpCodes.Nop: break; default: throw new NotSupportedException(cilinstr.OpCode.Name); } if (isCompare) code.Add(new UnaryOperation(IROpCodes.NEG, target, target)); } if (Trailer == null) Trailer = new JMPInstruction(); }