public void KillReg(SsaRegister reg, StreamWriter writer) { if (!IsRegScopable(reg)) return; bool anyMatch = false; foreach (Entry e in m_regStack) { if (e.SsaReg == reg) { e.Kill(); anyMatch = true; break; } } if (!anyMatch) throw new Exception("Killed an untracked register"); while (m_regStack.Count > 0) { Entry top = m_regStack.Peek(); if (top.IsAlive) break; m_regStack.Pop(); m_indent = m_indent.Substring(0, m_indent.Length - 1); writer.Write(m_indent); writer.WriteLine("}"); } }
public void LivenReg(SsaRegister reg, CppBuilder builder) { if (!IsRegScopable(reg)) return; AddReg(reg); }
public MidInstruction(OpcodeEnum opcode, CodeLocationTag codeLocation, SsaRegister regArg, SsaRegister regArg2) { Opcode = opcode; CodeLocation = codeLocation; RegArg = regArg; RegArg2 = regArg2; }
public MidInstruction(OpcodeEnum opcode, CodeLocationTag codeLocation, SsaRegister regArg, CfgOutboundEdge[] cfgEdgesArg) { Opcode = opcode; CodeLocation = codeLocation; RegArg = regArg; CfgEdgesArg = cfgEdgesArg; }
public MidInstruction(OpcodeEnum opcode, CodeLocationTag codeLocation, SsaRegister regArg, SsaRegister regArg2, string strArg, CLRTypeSpec typeSpecArg, CLRTypeSpec typeSpecArg2) { Opcode = opcode; CodeLocation = codeLocation; RegArg = regArg; RegArg2 = regArg2; StrArg = strArg; TypeSpecArg = typeSpecArg; TypeSpecArg2 = typeSpecArg2; }
public CfgOutboundEdgePrototype GenerateCfgEdge() { VType[] types = new VType[m_regs.Count]; SsaRegister[] ssaRegs = new SsaRegister[m_regs.Count]; for (int i = 0; i < types.Length; i++) { types[i] = m_regs[i].VType; ssaRegs[i] = m_regs[i]; } return new CfgOutboundEdgePrototype(types, ssaRegs); }
private void EmitCfgNode(CfgNode cfgNode) { // Build predecessor list List<CppTranslatedOutboundEdge> predecessorEdges = new List<CppTranslatedOutboundEdge>(); foreach (CfgNode pred in cfgNode.Predecessors) { // Find the successor edge CppTranslatedOutboundEdge edge = null; foreach (CfgOutboundEdge outEdge in pred.Successors) { if (outEdge.SuccessorNode == cfgNode) { edge = InternOutboundEdge(pred, outEdge); break; } } if (edge == null) throw new Exception("Mismatched CFG edge"); predecessorEdges.Add(edge); } List<Clarity.Rpa.HighInstruction> outInstructions = new List<Clarity.Rpa.HighInstruction>(); List<Clarity.Rpa.HighPhi> outPhis = new List<Clarity.Rpa.HighPhi>(); Clarity.Rpa.HighCfgNodeHandle highNode = m_nodesToEmittedNodes[cfgNode]; CppCfgNodeOutline outline = m_nodeOutlines[cfgNode]; List<SsaRegister> leakedRegs = new List<SsaRegister>(); int numContinuedRegs = 0; int debugInstrNum = -1; MidInstruction[] midInstrs = cfgNode.MidInstructions; bool fallthroughMerged = false; foreach (MidInstruction midInstr in midInstrs) { debugInstrNum++; switch (midInstr.Opcode) { case MidInstruction.OpcodeEnum.AllocObject: { Clarity.Rpa.HighSsaRegister dest = InternSsaRegister(midInstr.RegArg); Clarity.Rpa.TypeSpecTag type = RpaTagFactory.CreateTypeTag(midInstr.TypeSpecArg); outInstructions.Add(new Clarity.Rpa.Instructions.AllocObjInstruction(midInstr.CodeLocation, dest, type)); } break; case MidInstruction.OpcodeEnum.CallMethod: case MidInstruction.OpcodeEnum.CallConstructor: case MidInstruction.OpcodeEnum.ConstrainedCallMethod: { CppMethodSpec methodSpec = midInstr.MethodSpecArg; CppMethod cppMethod = methodSpec.CppMethod; CppClass thisClass = m_builder.GetCachedClass(cppMethod.DeclaredInClassSpec); SsaRegister returnReg = midInstr.RegArg; SsaRegister thisReg = midInstr.RegArg2; List<Clarity.Rpa.HighSsaRegister> parameters = new List<Clarity.Rpa.HighSsaRegister>(); if (!cppMethod.MethodDef.Static && midInstr.Opcode != MidInstruction.OpcodeEnum.ConstrainedCallMethod) thisReg = EmitPassiveConversion_PermitRefs(midInstr.CodeLocation, thisReg, cppMethod.DeclaredInClassSpec, outline, outInstructions); // CLARITYTODO: Verify that this works with generic method parameters for (int pIdx = 0; pIdx < midInstr.RegArgs.Length; pIdx++) { SsaRegister inReg = EmitPassiveConversion_PermitRefs(midInstr.CodeLocation, midInstr.RegArgs[pIdx], cppMethod.MethodSignature.ParamTypes[pIdx].Type, outline, outInstructions); parameters.Add(InternSsaRegister(inReg)); } Clarity.Rpa.HighSsaRegister outDestReg = null; if (returnReg != null) outDestReg = InternSsaRegister(returnReg); Clarity.Rpa.TypeSpecTag constraintTag = null; if (midInstr.Opcode == MidInstruction.OpcodeEnum.ConstrainedCallMethod) constraintTag = RpaTagFactory.CreateTypeTag(midInstr.TypeSpecArg); Clarity.Rpa.HighSsaRegister instanceReg = null; if (!cppMethod.MethodDef.Static) instanceReg = InternSsaRegister(thisReg); CLR.CLRMethodSignatureInstance methodSig = cppMethod.MethodSignature; int numParams = parameters.Count; if (numParams != methodSig.ParamTypes.Length) throw new Exception("Internal error: CallMethod param count mismatch"); if (midInstr.Opcode == MidInstruction.OpcodeEnum.CallMethod || midInstr.Opcode == MidInstruction.OpcodeEnum.CallConstructor) { if (cppMethod.MethodDef.Static) { outInstructions.Add(new Clarity.Rpa.Instructions.CallStaticMethodInstruction( midInstr.CodeLocation, outDestReg, RpaTagFactory.CreateMethodSpec(Clarity.Rpa.MethodSlotType.Static, methodSpec), parameters.ToArray() )); } else { outInstructions.Add(new Clarity.Rpa.Instructions.CallInstanceMethodInstruction( midInstr.CodeLocation, outDestReg, RpaTagFactory.CreateMethodSpec(Clarity.Rpa.MethodSlotType.Instance, methodSpec), instanceReg, parameters.ToArray() )); } } else if (midInstr.Opcode == MidInstruction.OpcodeEnum.ConstrainedCallMethod) { outInstructions.Add(new Clarity.Rpa.Instructions.CallConstrainedMethodInstruction( midInstr.CodeLocation, outDestReg, constraintTag, RpaTagFactory.CreateMethodSpec(Clarity.Rpa.MethodSlotType.Instance, methodSpec), instanceReg, parameters.ToArray() )); } } break; case MidInstruction.OpcodeEnum.CallVirtualMethod: case MidInstruction.OpcodeEnum.ConstrainedCallVirtualMethod: { CppMethodSpec methodSpec = midInstr.MethodSpecArg; CppMethod cppMethod = methodSpec.CppMethod; CppClass thisClass = m_builder.GetCachedClass(cppMethod.DeclaredInClassSpec); Clarity.Rpa.HighSsaRegister returnReg = InternSsaRegister(midInstr.RegArg); Clarity.Rpa.HighSsaRegister thisReg = null; List<Clarity.Rpa.HighSsaRegister> paramRegs = new List<Clarity.Rpa.HighSsaRegister>(); if (midInstr.Opcode != MidInstruction.OpcodeEnum.ConstrainedCallVirtualMethod) thisReg = InternSsaRegister(EmitPassiveConversion_PermitRefs(midInstr.CodeLocation, midInstr.RegArg2, cppMethod.DeclaredInClassSpec, outline, outInstructions)); else thisReg = InternSsaRegister(midInstr.RegArg2); for (int pIdx = 0; pIdx < midInstr.RegArgs.Length; pIdx++) paramRegs.Add(InternSsaRegister(EmitPassiveConversion_PermitRefs(midInstr.CodeLocation, midInstr.RegArgs[pIdx], cppMethod.MethodSignature.ParamTypes[pIdx].Type, outline, outInstructions))); CppVtableSlot vtableSlot = cppMethod.CreatesSlot; if (vtableSlot == null) vtableSlot = cppMethod.ReplacesStandardSlot; if (vtableSlot == null) throw new Exception("Internal error: Couldn't resolve vtable slot for method"); Clarity.Rpa.TypeSpecTag constraintType = null; if (midInstr.Opcode == MidInstruction.OpcodeEnum.ConstrainedCallVirtualMethod) constraintType = RpaTagFactory.CreateTypeTag(midInstr.TypeSpecArg); if (cppMethod.MethodDef.Static) throw new Exception(); CLR.CLRMethodSignatureInstance methodSig = cppMethod.MethodSignature; int numParams = paramRegs.Count; if (numParams != methodSig.ParamTypes.Length) throw new Exception("Internal error: CallMethod param count mismatch"); if (midInstr.Opcode == MidInstruction.OpcodeEnum.CallVirtualMethod) { outInstructions.Add(new Clarity.Rpa.Instructions.CallVirtualMethodInstruction( midInstr.CodeLocation, returnReg, RpaTagFactory.CreateMethodSpec(Clarity.Rpa.MethodSlotType.Virtual, methodSpec), thisReg, paramRegs.ToArray() )); } else if (midInstr.Opcode == MidInstruction.OpcodeEnum.ConstrainedCallVirtualMethod) outInstructions.Add(new Clarity.Rpa.Instructions.CallConstrainedVirtualMethodInstruction( midInstr.CodeLocation, returnReg, constraintType, RpaTagFactory.CreateMethodSpec(Clarity.Rpa.MethodSlotType.Virtual, methodSpec), thisReg, paramRegs.ToArray() )); } break; case MidInstruction.OpcodeEnum.KillReg: break; case MidInstruction.OpcodeEnum.LivenReg: { SsaRegister reg = midInstr.RegArg; reg.GenerateUniqueID(m_regAllocator); reg.MakeUsable(); } break; case MidInstruction.OpcodeEnum.Return: outInstructions.Add(new Clarity.Rpa.Instructions.ReturnInstruction(midInstr.CodeLocation)); break; case MidInstruction.OpcodeEnum.ReturnValue: { SsaRegister returnRegister = EmitPassiveConversion(midInstr.CodeLocation, midInstr.RegArg, midInstr.TypeSpecArg, outline, outInstructions); outInstructions.Add(new Clarity.Rpa.Instructions.ReturnValueInstruction( midInstr.CodeLocation, InternSsaRegister(returnRegister))); } break; case MidInstruction.OpcodeEnum.LoadReg_ManagedPtr: { Clarity.Rpa.HighLocal lcl = m_localLookup[midInstr.VRegArg]; Clarity.Rpa.HighSsaRegister dest = InternSsaRegister(midInstr.RegArg); outInstructions.Add(new Clarity.Rpa.Instructions.LoadLocalInstruction( midInstr.CodeLocation, dest, lcl )); } break; case MidInstruction.OpcodeEnum.LoadReg_Value: { CLR.CLRTypeSpec srcSpec = midInstr.VRegArg.VType.TypeSpec; CLR.CLRTypeSpec destSpec = midInstr.RegArg.VType.TypeSpec; if (srcSpec.Equals(destSpec)) { outInstructions.Add(new Clarity.Rpa.Instructions.LoadLocalInstruction( midInstr.CodeLocation, InternSsaRegister(midInstr.RegArg), m_localLookup[midInstr.VRegArg] )); } else { SsaRegister tempReg = new SsaRegister(midInstr.VRegArg.VType); tempReg.MakeUsable(); tempReg.GenerateUniqueID(m_regAllocator); outline.AddRegister(tempReg); outInstructions.Add(new Clarity.Rpa.Instructions.LoadLocalInstruction( midInstr.CodeLocation, InternSsaRegister(tempReg), m_localLookup[midInstr.VRegArg] )); outInstructions.Add(new Clarity.Rpa.Instructions.PassiveConvertInstruction( midInstr.CodeLocation, InternSsaRegister(midInstr.RegArg), InternSsaRegister(tempReg) )); } } break; case MidInstruction.OpcodeEnum.StoreReg_ManagedPtr: outInstructions.Add(new Clarity.Rpa.Instructions.StoreLocalInstruction( midInstr.CodeLocation, m_localLookup[midInstr.VRegArg], InternSsaRegister(midInstr.RegArg) )); break; case MidInstruction.OpcodeEnum.StoreReg_Value: { SsaRegister srcReg = EmitPassiveConversion(midInstr.CodeLocation, midInstr.RegArg, midInstr.VRegArg.VType.TypeSpec, outline, outInstructions); outInstructions.Add(new Clarity.Rpa.Instructions.StoreLocalInstruction( midInstr.CodeLocation, m_localLookup[midInstr.VRegArg], InternSsaRegister(srcReg) )); } break; case MidInstruction.OpcodeEnum.beq_ref: case MidInstruction.OpcodeEnum.bne_ref: { fallthroughMerged = true; CppTranslatedOutboundEdge edgeA = InternOutboundEdge(cfgNode, midInstr.CfgEdgeArg); CppTranslatedOutboundEdge edgeB = InternOutboundEdge(cfgNode, cfgNode.FallThroughEdge); CppTranslatedOutboundEdge trueEdge, falseEdge; if (midInstr.Opcode == MidInstruction.OpcodeEnum.beq_ref) { trueEdge = edgeA; falseEdge = edgeB; } else if (midInstr.Opcode == MidInstruction.OpcodeEnum.bne_ref) { trueEdge = edgeB; falseEdge = edgeA; } else throw new Exception(); Clarity.Rpa.HighSsaRegister regA = InternSsaRegister(midInstr.RegArg); Clarity.Rpa.HighSsaRegister regB = InternSsaRegister(midInstr.RegArg2); outInstructions.Add(new Clarity.Rpa.Instructions.BranchCompareRefsInstruction(midInstr.CodeLocation, regA, regB, trueEdge.NextNode, falseEdge.NextNode)); } break; case MidInstruction.OpcodeEnum.cne_ref: case MidInstruction.OpcodeEnum.ceq_ref: { int trueValue, falseValue; Clarity.Rpa.HighSsaRegister destReg = InternSsaRegister(midInstr.RegArg); if (midInstr.Opcode == MidInstruction.OpcodeEnum.ceq_ref) { trueValue = 1; falseValue = 0; } else if (midInstr.Opcode == MidInstruction.OpcodeEnum.cne_ref) { trueValue = 0; falseValue = 1; } else throw new Exception(); Clarity.Rpa.HighSsaRegister regA = InternSsaRegister(midInstr.RegArg2); Clarity.Rpa.HighSsaRegister regB = InternSsaRegister(midInstr.RegArg3); outInstructions.Add(new Clarity.Rpa.Instructions.CompareRefsInstruction(midInstr.CodeLocation, destReg, regA, regB, trueValue, falseValue)); } break; case MidInstruction.OpcodeEnum.beq_val: case MidInstruction.OpcodeEnum.bne_val: case MidInstruction.OpcodeEnum.bge: case MidInstruction.OpcodeEnum.bgt: case MidInstruction.OpcodeEnum.ble: case MidInstruction.OpcodeEnum.blt: case MidInstruction.OpcodeEnum.clt: case MidInstruction.OpcodeEnum.cgt: case MidInstruction.OpcodeEnum.ceq_numeric: { bool isBranch; SsaRegister leftReg, rightReg; switch (midInstr.Opcode) { case MidInstruction.OpcodeEnum.beq_val: case MidInstruction.OpcodeEnum.bne_val: case MidInstruction.OpcodeEnum.bge: case MidInstruction.OpcodeEnum.bgt: case MidInstruction.OpcodeEnum.ble: case MidInstruction.OpcodeEnum.blt: isBranch = true; leftReg = midInstr.RegArg; rightReg = midInstr.RegArg2; break; case MidInstruction.OpcodeEnum.clt: case MidInstruction.OpcodeEnum.cgt: case MidInstruction.OpcodeEnum.ceq_numeric: isBranch = false; leftReg = midInstr.RegArg2; rightReg = midInstr.RegArg3; break; default: throw new Exception(); } bool isUnsigned = midInstr.FlagArg; bool isReversed = false; NumericStackType nst = NumericStackTypeForNumericBinaryOp(leftReg, rightReg); if (isUnsigned && (nst == NumericStackType.Float32 || nst == NumericStackType.Float64)) { isUnsigned = false; isReversed = true; } CLR.CLRTypeSpec comparisonSpec = this.TypeSpecForNumericBinaryOp(leftReg, rightReg, isUnsigned); Clarity.Rpa.HighSsaRegister leftHighReg = InternSsaRegister(EmitPassiveConversion(midInstr.CodeLocation, leftReg, comparisonSpec, outline, outInstructions)); Clarity.Rpa.HighSsaRegister rightHighReg = InternSsaRegister(EmitPassiveConversion(midInstr.CodeLocation, rightReg, comparisonSpec, outline, outInstructions)); Clarity.Rpa.Instructions.NumberCompareOperation op; switch (midInstr.Opcode) { case MidInstruction.OpcodeEnum.blt: case MidInstruction.OpcodeEnum.clt: op = isReversed ? Clarity.Rpa.Instructions.NumberCompareOperation.GreaterOrEqual : Clarity.Rpa.Instructions.NumberCompareOperation.LessThan; break; case MidInstruction.OpcodeEnum.bgt: case MidInstruction.OpcodeEnum.cgt: op = isReversed ? Clarity.Rpa.Instructions.NumberCompareOperation.LessOrEqual : Clarity.Rpa.Instructions.NumberCompareOperation.GreaterThan; break; case MidInstruction.OpcodeEnum.ble: op = isReversed ? Clarity.Rpa.Instructions.NumberCompareOperation.GreaterThan : Clarity.Rpa.Instructions.NumberCompareOperation.LessOrEqual; break; case MidInstruction.OpcodeEnum.bge: op = isReversed ? Clarity.Rpa.Instructions.NumberCompareOperation.LessThan : Clarity.Rpa.Instructions.NumberCompareOperation.GreaterOrEqual; break; case MidInstruction.OpcodeEnum.beq_val: case MidInstruction.OpcodeEnum.ceq_numeric: op = isReversed ? Clarity.Rpa.Instructions.NumberCompareOperation.NotEqual : Clarity.Rpa.Instructions.NumberCompareOperation.Equal; break; case MidInstruction.OpcodeEnum.bne_val: op = isReversed ? Clarity.Rpa.Instructions.NumberCompareOperation.Equal : Clarity.Rpa.Instructions.NumberCompareOperation.NotEqual; break; default: throw new ArgumentException(); } Clarity.Rpa.Instructions.NumberArithType numType; switch (nst) { case NumericStackType.Float32: numType = Clarity.Rpa.Instructions.NumberArithType.Float32; break; case NumericStackType.Float64: numType = Clarity.Rpa.Instructions.NumberArithType.Float64; break; case NumericStackType.Int32: numType = isUnsigned ? Clarity.Rpa.Instructions.NumberArithType.UInt32 : Clarity.Rpa.Instructions.NumberArithType.Int32; break; case NumericStackType.Int64: numType = isUnsigned ? Clarity.Rpa.Instructions.NumberArithType.UInt64 : Clarity.Rpa.Instructions.NumberArithType.Int64; break; case NumericStackType.NativeInt: numType = isUnsigned ? Clarity.Rpa.Instructions.NumberArithType.NativeUInt : Clarity.Rpa.Instructions.NumberArithType.NativeInt; break; default: throw new ArgumentException(); } if (isBranch) { fallthroughMerged = true; CppTranslatedOutboundEdge trueEdge = InternOutboundEdge(cfgNode, midInstr.CfgEdgeArg); CppTranslatedOutboundEdge falseEdge = InternOutboundEdge(cfgNode, cfgNode.FallThroughEdge); if (isReversed) { CppTranslatedOutboundEdge temp = trueEdge; trueEdge = falseEdge; falseEdge = temp; } outInstructions.Add(new Clarity.Rpa.Instructions.BranchCompareNumbersInstruction( midInstr.CodeLocation, op, numType, leftHighReg, rightHighReg, trueEdge.NextNode, falseEdge.NextNode )); } else { int trueValue = 0; int falseValue = 1; if (isReversed) { trueValue = 0; falseValue = 1; } Clarity.Rpa.HighSsaRegister destReg = InternSsaRegister(midInstr.RegArg); outInstructions.Add(new Clarity.Rpa.Instructions.CompareNumbersInstruction( midInstr.CodeLocation, destReg, op, numType, leftHighReg, rightHighReg, trueValue, falseValue )); } } break; case MidInstruction.OpcodeEnum.LoadArgA_Value: { Clarity.Rpa.HighSsaRegister dest = InternSsaRegister(midInstr.RegArg); Clarity.Rpa.HighLocal src = m_localLookup[midInstr.VRegArg]; outInstructions.Add(new Clarity.Rpa.Instructions.GetLocalPtrInstruction( midInstr.CodeLocation, dest, src )); } break; case MidInstruction.OpcodeEnum.brzero: case MidInstruction.OpcodeEnum.brnotzero: { SsaRegister inReg = midInstr.RegArg; CLR.CLRTypeSpec targetType; object zeroValue; CLR.CLRTypeSpecClass cls = (CLR.CLRTypeSpecClass)inReg.VType.TypeSpec; string typeName = cls.TypeDef.TypeName; Clarity.Rpa.Instructions.NumberArithType arithType; if (typeName == "Char" || typeName == "Boolean" || typeName == "Byte" || typeName == "UInt16" || typeName == "UInt32") { targetType = TypeSpecForNumericStackType(NumericStackType.Int32, true); zeroValue = (uint)0; arithType = Clarity.Rpa.Instructions.NumberArithType.UInt32; } else if (typeName == "SByte" || typeName == "Int16" || typeName == "Int32") { targetType = TypeSpecForNumericStackType(NumericStackType.Int32, false); zeroValue = (int)0; arithType = Clarity.Rpa.Instructions.NumberArithType.Int32; } else if (typeName == "UInt64") { targetType = TypeSpecForNumericStackType(NumericStackType.Int64, true); zeroValue = (ulong)0; arithType = Clarity.Rpa.Instructions.NumberArithType.UInt64; } else if (typeName == "Int64") { targetType = TypeSpecForNumericStackType(NumericStackType.Int64, false); zeroValue = (long)0; arithType = Clarity.Rpa.Instructions.NumberArithType.Int64; } else if (typeName == "IntPtr") { targetType = TypeSpecForNumericStackType(NumericStackType.NativeInt, false); zeroValue = (long)0; arithType = Clarity.Rpa.Instructions.NumberArithType.NativeInt; } else if (typeName == "UIntPtr") { targetType = TypeSpecForNumericStackType(NumericStackType.NativeInt, true); zeroValue = (ulong)0; arithType = Clarity.Rpa.Instructions.NumberArithType.NativeUInt; } else if (typeName == "Single") { targetType = TypeSpecForNumericStackType(NumericStackType.Float32, false); zeroValue = (float)0; arithType = Clarity.Rpa.Instructions.NumberArithType.Float32; } else if (typeName == "Double") { targetType = TypeSpecForNumericStackType(NumericStackType.Float64, false); zeroValue = (double)0; arithType = Clarity.Rpa.Instructions.NumberArithType.Float64; } else throw new Exception(); fallthroughMerged = true; CppTranslatedOutboundEdge trueEdge = InternOutboundEdge(cfgNode, midInstr.CfgEdgeArg); CppTranslatedOutboundEdge falseEdge = InternOutboundEdge(cfgNode, cfgNode.FallThroughEdge); Clarity.Rpa.Instructions.NumberCompareOperation compareOp; if (midInstr.Opcode == MidInstruction.OpcodeEnum.brzero) compareOp = Clarity.Rpa.Instructions.NumberCompareOperation.Equal; else if (midInstr.Opcode == MidInstruction.OpcodeEnum.brnotzero) compareOp = Clarity.Rpa.Instructions.NumberCompareOperation.NotEqual; else throw new Exception(); SsaRegister converted = EmitPassiveConversion(midInstr.CodeLocation, inReg, targetType, outline, outInstructions); Clarity.Rpa.TypeSpecTag typeTag = RpaTagFactory.CreateTypeTag(targetType); outInstructions.Add(new Clarity.Rpa.Instructions.BranchCompareNumbersInstruction( midInstr.CodeLocation, compareOp, arithType, InternSsaRegister(converted), new Clarity.Rpa.HighSsaRegister(Clarity.Rpa.HighValueType.ConstantValue, typeTag, zeroValue), trueEdge.NextNode, falseEdge.NextNode )); } break; case MidInstruction.OpcodeEnum.brnull: case MidInstruction.OpcodeEnum.brnotnull: { fallthroughMerged = true; CppTranslatedOutboundEdge isNullEdge = InternOutboundEdge(cfgNode, midInstr.CfgEdgeArg); CppTranslatedOutboundEdge isNotNullEdge = InternOutboundEdge(cfgNode, cfgNode.FallThroughEdge); if (midInstr.Opcode == MidInstruction.OpcodeEnum.brnotnull) { CppTranslatedOutboundEdge temp = isNullEdge; isNullEdge = isNotNullEdge; isNotNullEdge = temp; } outInstructions.Add(new Clarity.Rpa.Instructions.BranchRefNullInstruction( midInstr.CodeLocation, InternSsaRegister(midInstr.RegArg), isNullEdge.NextNode, isNotNullEdge.NextNode )); } break; case MidInstruction.OpcodeEnum.LeakReg: { leakedRegs.Add(midInstr.RegArg); } break; case MidInstruction.OpcodeEnum.EntryReg: { SsaRegister reg = midInstr.RegArg; reg.GenerateUniqueID(m_regAllocator); reg.MakeUsable(); Clarity.Rpa.HighSsaRegister destReg = InternSsaRegister(reg); // Blocks can have constants on entry if all predecessors have the same value if (!destReg.IsConstant) { List<Clarity.Rpa.HighPhiLink> phiLinks = new List<Clarity.Rpa.HighPhiLink>(); foreach (CppTranslatedOutboundEdge predEdge in predecessorEdges) phiLinks.Add(new Clarity.Rpa.HighPhiLink(predEdge.PrevNode, predEdge.Regs[numContinuedRegs])); outPhis.Add(new Clarity.Rpa.HighPhi( InternSsaRegister(reg), phiLinks.ToArray() )); } numContinuedRegs++; } break; case MidInstruction.OpcodeEnum.Throw: { CLR.CLRTypeSpec objSpec = m_builder.Assemblies.InternVagueType(new CLR.CLRSigTypeSimple(CLR.CLRSigType.ElementType.OBJECT)); SsaRegister converted = EmitPassiveConversion(midInstr.CodeLocation, midInstr.RegArg, objSpec, outline, outInstructions); outInstructions.Add(new Clarity.Rpa.Instructions.ThrowInstruction( midInstr.CodeLocation, InternSsaRegister(converted) )); } break; case MidInstruction.OpcodeEnum.NewSZArray: { NumericStackType indexNst = StackTypeForTypeSpec(midInstr.RegArg2.VType.TypeSpec); CLR.CLRTypeSpec indexSpec = m_builder.Assemblies.InternVagueType(new CLR.CLRSigTypeSimple(CLR.CLRSigType.ElementType.I)); SsaRegister indexReg = EmitPassiveConversion(midInstr.CodeLocation, midInstr.RegArg2, indexSpec, outline, outInstructions); outInstructions.Add(new Clarity.Rpa.Instructions.AllocArrayInstruction( midInstr.CodeLocation, InternSsaRegister(midInstr.RegArg), new Clarity.Rpa.HighSsaRegister[] { InternSsaRegister(indexReg) }, RpaTagFactory.CreateTypeTag(midInstr.RegArg2.VType.TypeSpec) )); } break; case MidInstruction.OpcodeEnum.LoadField_ManagedPtr: { Clarity.Rpa.HighSsaRegister destReg = InternSsaRegister(midInstr.RegArg2); Clarity.Rpa.HighSsaRegister objReg = InternSsaRegister(midInstr.RegArg); Clarity.Rpa.HighSsaRegister addrReg = new Clarity.Rpa.HighSsaRegister(Clarity.Rpa.HighValueType.ManagedPtr, destReg.Type, null); outInstructions.Add(new Clarity.Rpa.Instructions.PtrFieldInstruction( midInstr.CodeLocation, addrReg, objReg, midInstr.StrArg )); outInstructions.Add(new Clarity.Rpa.Instructions.LoadPtrInstruction( midInstr.CodeLocation, destReg, addrReg )); } break; case MidInstruction.OpcodeEnum.LoadFieldA_ManagedPtr: { Clarity.Rpa.HighSsaRegister destReg = InternSsaRegister(midInstr.RegArg2); Clarity.Rpa.HighSsaRegister objReg = InternSsaRegister(midInstr.RegArg); outInstructions.Add(new Clarity.Rpa.Instructions.PtrFieldInstruction( midInstr.CodeLocation, destReg, objReg, midInstr.StrArg )); } break; case MidInstruction.OpcodeEnum.LoadField_Object: { Clarity.Rpa.HighSsaRegister destReg = InternSsaRegister(midInstr.RegArg2); Clarity.Rpa.HighSsaRegister objReg = InternSsaRegister(EmitPassiveConversion(midInstr.CodeLocation, midInstr.RegArg, midInstr.TypeSpecArg, outline, outInstructions)); Clarity.Rpa.HighSsaRegister addrReg = new Clarity.Rpa.HighSsaRegister(Clarity.Rpa.HighValueType.ManagedPtr, destReg.Type, null); outInstructions.Add(new Clarity.Rpa.Instructions.RefFieldInstruction( midInstr.CodeLocation, addrReg, objReg, midInstr.StrArg, RpaTagFactory.CreateTypeTag(midInstr.TypeSpecArg) )); outInstructions.Add(new Clarity.Rpa.Instructions.LoadPtrInstruction( midInstr.CodeLocation, destReg, addrReg )); } break; case MidInstruction.OpcodeEnum.LoadFieldA_Object: { Clarity.Rpa.HighSsaRegister destReg = InternSsaRegister(midInstr.RegArg2); Clarity.Rpa.HighSsaRegister objReg = InternSsaRegister(EmitPassiveConversion(midInstr.CodeLocation, midInstr.RegArg, midInstr.TypeSpecArg, outline, outInstructions)); outInstructions.Add(new Clarity.Rpa.Instructions.RefFieldInstruction( midInstr.CodeLocation, destReg, objReg, midInstr.StrArg, RpaTagFactory.CreateTypeTag(midInstr.TypeSpecArg) )); } break; case MidInstruction.OpcodeEnum.LoadField_Value: { Clarity.Rpa.HighSsaRegister destReg = InternSsaRegister(midInstr.RegArg2); Clarity.Rpa.HighSsaRegister objReg = InternSsaRegister(midInstr.RegArg); outInstructions.Add(new Clarity.Rpa.Instructions.LoadValueFieldInstruction( midInstr.CodeLocation, destReg, objReg, midInstr.StrArg )); } break; case MidInstruction.OpcodeEnum.LoadRegA: { Clarity.Rpa.HighLocal local = m_localLookup[midInstr.VRegArg]; Clarity.Rpa.HighSsaRegister dest = InternSsaRegister(midInstr.RegArg); outInstructions.Add(new Clarity.Rpa.Instructions.GetLocalPtrInstruction( midInstr.CodeLocation, InternSsaRegister(midInstr.RegArg), m_localLookup[midInstr.VRegArg] )); } break; case MidInstruction.OpcodeEnum.LoadArrayElem: { CLR.CLRTypeSpec indexSpec = m_builder.Assemblies.InternVagueType(new CLR.CLRSigTypeSimple(CLR.CLRSigType.ElementType.I)); Clarity.Rpa.HighSsaRegister arrayReg = InternSsaRegister(midInstr.RegArg); Clarity.Rpa.HighSsaRegister indexReg = InternSsaRegister(EmitPassiveConversion(midInstr.CodeLocation, midInstr.RegArg2, indexSpec, outline, outInstructions)); Clarity.Rpa.HighSsaRegister destReg = InternSsaRegister(midInstr.RegArg3); Clarity.Rpa.HighSsaRegister addrReg = new Clarity.Rpa.HighSsaRegister(Clarity.Rpa.HighValueType.ManagedPtr, destReg.Type, null); outInstructions.Add(new Clarity.Rpa.Instructions.GetArrayElementPtrInstruction( midInstr.CodeLocation, addrReg, arrayReg, new Clarity.Rpa.HighSsaRegister[] { indexReg } )); outInstructions.Add(new Clarity.Rpa.Instructions.LoadPtrInstruction( midInstr.CodeLocation, destReg, addrReg )); } break; case MidInstruction.OpcodeEnum.LoadArrayElemAddr: { CLR.CLRTypeSpec indexSpec = m_builder.Assemblies.InternVagueType(new CLR.CLRSigTypeSimple(CLR.CLRSigType.ElementType.I)); Clarity.Rpa.HighSsaRegister arrayReg = InternSsaRegister(midInstr.RegArg); Clarity.Rpa.HighSsaRegister indexReg = InternSsaRegister(EmitPassiveConversion(midInstr.CodeLocation, midInstr.RegArg2, indexSpec, outline, outInstructions)); Clarity.Rpa.HighSsaRegister destReg = InternSsaRegister(midInstr.RegArg3); outInstructions.Add(new Clarity.Rpa.Instructions.GetArrayElementPtrInstruction( midInstr.CodeLocation, destReg, arrayReg, new Clarity.Rpa.HighSsaRegister[] { indexReg } )); } break; case MidInstruction.OpcodeEnum.StoreField_ManagedPtr: { Clarity.Rpa.HighSsaRegister objReg = InternSsaRegister(midInstr.RegArg); Clarity.Rpa.HighSsaRegister valueReg = InternSsaRegister(EmitPassiveConversion(midInstr.CodeLocation, midInstr.RegArg2, midInstr.TypeSpecArg2, outline, outInstructions)); Clarity.Rpa.HighSsaRegister addrReg = new Clarity.Rpa.HighSsaRegister(Clarity.Rpa.HighValueType.ManagedPtr, valueReg.Type, null); outInstructions.Add(new Clarity.Rpa.Instructions.PtrFieldInstruction( midInstr.CodeLocation, addrReg, objReg, midInstr.StrArg)); outInstructions.Add(new Clarity.Rpa.Instructions.StorePtrInstruction( midInstr.CodeLocation, addrReg, valueReg )); } break; case MidInstruction.OpcodeEnum.StoreField_Object: { Clarity.Rpa.HighSsaRegister objReg = InternSsaRegister(EmitPassiveConversion(midInstr.CodeLocation, midInstr.RegArg, midInstr.TypeSpecArg, outline, outInstructions)); Clarity.Rpa.HighSsaRegister valueReg = InternSsaRegister(EmitPassiveConversion(midInstr.CodeLocation, midInstr.RegArg2, midInstr.TypeSpecArg2, outline, outInstructions)); Clarity.Rpa.HighSsaRegister addrReg = new Clarity.Rpa.HighSsaRegister(Clarity.Rpa.HighValueType.ManagedPtr, valueReg.Type, null); outInstructions.Add(new Clarity.Rpa.Instructions.RefFieldInstruction( midInstr.CodeLocation, addrReg, objReg, midInstr.StrArg, RpaTagFactory.CreateTypeTag(midInstr.TypeSpecArg) )); outInstructions.Add(new Clarity.Rpa.Instructions.StorePtrInstruction( midInstr.CodeLocation, addrReg, valueReg )); } break; case MidInstruction.OpcodeEnum.add: case MidInstruction.OpcodeEnum.sub: case MidInstruction.OpcodeEnum.mul: case MidInstruction.OpcodeEnum.div: case MidInstruction.OpcodeEnum.rem: case MidInstruction.OpcodeEnum.and: case MidInstruction.OpcodeEnum.or: case MidInstruction.OpcodeEnum.xor: case MidInstruction.OpcodeEnum.shl: case MidInstruction.OpcodeEnum.shr: // [.un] { bool isUnsigned = (midInstr.ArithArg & MidInstruction.ArithEnum.Flags_Un) != 0; bool isOvf = (midInstr.ArithArg & MidInstruction.ArithEnum.Flags_Ovf) != 0; NumericStackType nst = NumericStackTypeForNumericBinaryOp(midInstr.RegArg, midInstr.RegArg2); Clarity.Rpa.Instructions.NumberArithType arithType; switch(nst) { case NumericStackType.Float32: arithType = Clarity.Rpa.Instructions.NumberArithType.Float32; break; case NumericStackType.Float64: arithType = Clarity.Rpa.Instructions.NumberArithType.Float64; break; case NumericStackType.Int32: arithType = isUnsigned ? Clarity.Rpa.Instructions.NumberArithType.UInt32 : Clarity.Rpa.Instructions.NumberArithType.Int32; break; case NumericStackType.Int64: arithType = isUnsigned ? Clarity.Rpa.Instructions.NumberArithType.UInt64 : Clarity.Rpa.Instructions.NumberArithType.Int64; break; case NumericStackType.NativeInt: arithType = isUnsigned ? Clarity.Rpa.Instructions.NumberArithType.NativeUInt : Clarity.Rpa.Instructions.NumberArithType.NativeInt; break; default: throw new ArgumentException(); } CLR.CLRTypeSpec opSpec = TypeSpecForNumericStackType(nst, isUnsigned); Clarity.Rpa.Instructions.NumberArithOp arithOp; bool canThrow = isOvf; switch (midInstr.Opcode) { case MidInstruction.OpcodeEnum.add: arithOp = Clarity.Rpa.Instructions.NumberArithOp.Add; break; case MidInstruction.OpcodeEnum.sub: arithOp = Clarity.Rpa.Instructions.NumberArithOp.Subtract; break; case MidInstruction.OpcodeEnum.mul: arithOp = Clarity.Rpa.Instructions.NumberArithOp.Multiply; break; case MidInstruction.OpcodeEnum.div: arithOp = Clarity.Rpa.Instructions.NumberArithOp.Divide; break; case MidInstruction.OpcodeEnum.rem: arithOp = Clarity.Rpa.Instructions.NumberArithOp.Modulo; break; case MidInstruction.OpcodeEnum.and: arithOp = Clarity.Rpa.Instructions.NumberArithOp.BitAnd; break; case MidInstruction.OpcodeEnum.or: arithOp = Clarity.Rpa.Instructions.NumberArithOp.BitOr; break; case MidInstruction.OpcodeEnum.xor: arithOp = Clarity.Rpa.Instructions.NumberArithOp.BitXor; break; case MidInstruction.OpcodeEnum.shl: arithOp = Clarity.Rpa.Instructions.NumberArithOp.ShiftLeft; break; case MidInstruction.OpcodeEnum.shr: arithOp = Clarity.Rpa.Instructions.NumberArithOp.ShiftRight; break; default: throw new ArgumentException(); } SsaRegister left = EmitPassiveConversion(midInstr.CodeLocation, midInstr.RegArg, opSpec, outline, outInstructions); SsaRegister right = EmitPassiveConversion(midInstr.CodeLocation, midInstr.RegArg, opSpec, outline, outInstructions); outInstructions.Add(new Clarity.Rpa.Instructions.ArithInstruction( midInstr.CodeLocation, InternSsaRegister(midInstr.RegArg3), arithOp, arithType, InternSsaRegister(left), InternSsaRegister(right), isOvf )); } break; case MidInstruction.OpcodeEnum.neg: case MidInstruction.OpcodeEnum.not: { Clarity.Rpa.HighSsaRegister srcReg = InternSsaRegister(EmitPassiveConversion(midInstr.CodeLocation, midInstr.RegArg, midInstr.RegArg2.VType.TypeSpec, outline, outInstructions)); Clarity.Rpa.HighSsaRegister destReg = InternSsaRegister(midInstr.RegArg2); Clarity.Rpa.Instructions.NumberArithType arithType; switch (midInstr.ArithArg) { case MidInstruction.ArithEnum.ArithType_Int32: arithType = Clarity.Rpa.Instructions.NumberArithType.Int32; break; case MidInstruction.ArithEnum.ArithType_Int64: arithType = Clarity.Rpa.Instructions.NumberArithType.Int64; break; case MidInstruction.ArithEnum.ArithType_NativeInt: arithType = Clarity.Rpa.Instructions.NumberArithType.NativeInt; break; case MidInstruction.ArithEnum.ArithType_Float32: arithType = Clarity.Rpa.Instructions.NumberArithType.Float32; break; case MidInstruction.ArithEnum.ArithType_Float64: arithType = Clarity.Rpa.Instructions.NumberArithType.Float64; break; default: throw new Exception(); } Clarity.Rpa.Instructions.NumberUnaryArithOp arithOp; switch(midInstr.Opcode) { case MidInstruction.OpcodeEnum.neg: arithOp = Clarity.Rpa.Instructions.NumberUnaryArithOp.Negate; break; case MidInstruction.OpcodeEnum.not: arithOp = Clarity.Rpa.Instructions.NumberUnaryArithOp.BitNot; break; default: throw new Exception(); } outInstructions.Add(new Clarity.Rpa.Instructions.UnaryArithInstruction( midInstr.CodeLocation, destReg, arithOp, arithType, srcReg )); } break; case MidInstruction.OpcodeEnum.TryConvertObj: { outInstructions.Add(new Clarity.Rpa.Instructions.DynamicCastInstruction( midInstr.CodeLocation, InternSsaRegister(midInstr.RegArg2), InternSsaRegister(midInstr.RegArg), RpaTagFactory.CreateTypeTag(midInstr.RegArg2.VType.TypeSpec) )); } break; case MidInstruction.OpcodeEnum.Leave: { outInstructions.Add(new Clarity.Rpa.Instructions.LeaveRegionInstruction( midInstr.CodeLocation, midInstr.UIntArg )); } break; case MidInstruction.OpcodeEnum.DuplicateReg: AliasSsaRegister(InternSsaRegister(midInstr.RegArg), midInstr.RegArg2); break; case MidInstruction.OpcodeEnum.StoreStaticField: { Clarity.Rpa.TypeSpecTag staticType = RpaTagFactory.CreateTypeTag(midInstr.TypeSpecArg); string fieldName = midInstr.StrArg; Clarity.Rpa.HighSsaRegister srcReg = InternSsaRegister(EmitPassiveConversion(midInstr.CodeLocation, midInstr.RegArg, midInstr.TypeSpecArg2, outline, outInstructions)); Clarity.Rpa.HighSsaRegister addrReg = new Clarity.Rpa.HighSsaRegister(Clarity.Rpa.HighValueType.ManagedPtr, srcReg.Type, null); outInstructions.Add(new Clarity.Rpa.Instructions.GetStaticFieldAddrInstruction( midInstr.CodeLocation, addrReg, staticType, fieldName )); outInstructions.Add(new Clarity.Rpa.Instructions.StorePtrInstruction( midInstr.CodeLocation, addrReg, srcReg )); } break; case MidInstruction.OpcodeEnum.LoadIndirect: { SsaRegister srcReg = EmitPassiveConversion(midInstr.CodeLocation, midInstr.RegArg, midInstr.RegArg2.VType.TypeSpec, outline, outInstructions); SsaRegister destReg = midInstr.RegArg2; outInstructions.Add(new Clarity.Rpa.Instructions.LoadPtrInstruction( midInstr.CodeLocation, InternSsaRegister(destReg), InternSsaRegister(srcReg) )); } break; case MidInstruction.OpcodeEnum.LoadStaticField: { Clarity.Rpa.TypeSpecTag staticType = RpaTagFactory.CreateTypeTag(midInstr.TypeSpecArg); string fieldName = midInstr.StrArg; Clarity.Rpa.HighSsaRegister destReg = InternSsaRegister(midInstr.RegArg); Clarity.Rpa.HighSsaRegister addrReg = new Clarity.Rpa.HighSsaRegister(Clarity.Rpa.HighValueType.ManagedPtr, destReg.Type, null); outInstructions.Add(new Clarity.Rpa.Instructions.GetStaticFieldAddrInstruction( midInstr.CodeLocation, addrReg, staticType, fieldName )); outInstructions.Add(new Clarity.Rpa.Instructions.LoadPtrInstruction( midInstr.CodeLocation, destReg, addrReg )); } break; case MidInstruction.OpcodeEnum.LoadStaticFieldAddr: { Clarity.Rpa.TypeSpecTag staticType = RpaTagFactory.CreateTypeTag(midInstr.TypeSpecArg); string fieldName = midInstr.StrArg; Clarity.Rpa.HighSsaRegister addrReg = InternSsaRegister(midInstr.RegArg); outInstructions.Add(new Clarity.Rpa.Instructions.GetStaticFieldAddrInstruction( midInstr.CodeLocation, addrReg, staticType, fieldName )); } break; case MidInstruction.OpcodeEnum.Box: { outInstructions.Add(new Clarity.Rpa.Instructions.BoxInstruction( midInstr.CodeLocation, InternSsaRegister(midInstr.RegArg2), InternSsaRegister(midInstr.RegArg) )); } break; case MidInstruction.OpcodeEnum.ConvertNumber: { bool isOvf = ((midInstr.ArithArg & MidInstruction.ArithEnum.Flags_Ovf) != 0); bool isUn = ((midInstr.ArithArg & MidInstruction.ArithEnum.Flags_Un) != 0); SsaRegister srcReg = midInstr.RegArg; SsaRegister destReg = midInstr.RegArg2; NumericStackType sourceNST = StackTypeForTypeSpec(midInstr.RegArg.VType.TypeSpec); CLR.CLRTypeSpec srcSignAdjustedType = TypeSpecForNumericStackType(sourceNST, isUn); srcReg = EmitPassiveConversion(midInstr.CodeLocation, srcReg, srcSignAdjustedType, outline, outInstructions); outInstructions.Add(new Clarity.Rpa.Instructions.NumberConvertInstruction( midInstr.CodeLocation, InternSsaRegister(destReg), InternSsaRegister(srcReg), isOvf )); } break; case MidInstruction.OpcodeEnum.LoadArrayLength: { outInstructions.Add(new Clarity.Rpa.Instructions.GetArrayLengthInstruction( midInstr.CodeLocation, InternSsaRegister(midInstr.RegArg2), InternSsaRegister(midInstr.RegArg) )); } break; case MidInstruction.OpcodeEnum.LoadTypeInfoHandle: { outInstructions.Add(new Clarity.Rpa.Instructions.GetTypeInfoInstruction( midInstr.CodeLocation, InternSsaRegister(midInstr.RegArg), RpaTagFactory.CreateTypeTag(midInstr.TypeSpecArg) )); } break; case MidInstruction.OpcodeEnum.ConvertObj: { outInstructions.Add(new Clarity.Rpa.Instructions.ForceDynamicCastInstruction( midInstr.CodeLocation, InternSsaRegister(midInstr.RegArg2), InternSsaRegister(midInstr.RegArg), RpaTagFactory.CreateTypeTag(midInstr.RegArg2.VType.TypeSpec) )); } break; case MidInstruction.OpcodeEnum.StoreArrayElem: { CLR.CLRTypeSpec szArraySpec = midInstr.RegArg.VType.TypeSpec; CLR.CLRTypeSpec subscriptType = ((CLR.CLRTypeSpecSZArray)szArraySpec).SubType; SsaRegister arrayReg = midInstr.RegArg; SsaRegister indexReg = midInstr.RegArg2; SsaRegister valueReg = EmitPassiveConversion(midInstr.CodeLocation, midInstr.RegArg3, subscriptType, outline, outInstructions); Clarity.Rpa.HighSsaRegister arrayRegHigh = InternSsaRegister(arrayReg); Clarity.Rpa.HighSsaRegister indexRegHigh = InternSsaRegister(indexReg); Clarity.Rpa.HighSsaRegister valueRegHigh = InternSsaRegister(valueReg); Clarity.Rpa.HighSsaRegister addrReg = new Clarity.Rpa.HighSsaRegister(Clarity.Rpa.HighValueType.ManagedPtr, valueRegHigh.Type, null); outInstructions.Add(new Clarity.Rpa.Instructions.GetArrayElementPtrInstruction( midInstr.CodeLocation, addrReg, arrayRegHigh, new Clarity.Rpa.HighSsaRegister[] { indexRegHigh } )); outInstructions.Add(new Clarity.Rpa.Instructions.StorePtrInstruction( midInstr.CodeLocation, addrReg, valueRegHigh)); } break; case MidInstruction.OpcodeEnum.Switch: { CLR.CLRTypeSpec intType = m_builder.Assemblies.InternVagueType(new CLR.CLRSigTypeSimple(CLR.CLRSigType.ElementType.U4)); SsaRegister caseReg = EmitPassiveConversion(midInstr.CodeLocation, midInstr.RegArg, intType, outline, outInstructions); int numCases = midInstr.CfgEdgesArg.Length; Clarity.Rpa.HighCfgNodeHandle[] outNodes = new Clarity.Rpa.HighCfgNodeHandle[numCases]; for (int i = 0; i < numCases; i++) { CfgOutboundEdge edge = midInstr.CfgEdgesArg[i]; CfgNode caseNode = edge.SuccessorNode; CppTranslatedOutboundEdge outEdge = InternOutboundEdge(cfgNode, edge); outNodes[i] = outEdge.NextNode; } fallthroughMerged = true; CppTranslatedOutboundEdge defaultEdge = InternOutboundEdge(cfgNode, cfgNode.FallThroughEdge); outInstructions.Add(new Clarity.Rpa.Instructions.SwitchInstruction( midInstr.CodeLocation, InternSsaRegister(caseReg), outNodes, defaultEdge.NextNode )); } break; case MidInstruction.OpcodeEnum.StoreIndirect: { SsaRegister destReg = midInstr.RegArg; SsaRegister valueReg = EmitPassiveConversion(midInstr.CodeLocation, midInstr.RegArg2, midInstr.RegArg.VType.TypeSpec, outline, outInstructions); outInstructions.Add(new Clarity.Rpa.Instructions.StorePtrInstruction( midInstr.CodeLocation, InternSsaRegister(destReg), InternSsaRegister(valueReg) )); } break; case MidInstruction.OpcodeEnum.LoadFieldInfoHandle: { outInstructions.Add(new Clarity.Rpa.Instructions.GetFieldInfoInstruction( midInstr.CodeLocation, InternSsaRegister(midInstr.RegArg), RpaTagFactory.CreateTypeTag(midInstr.TypeSpecArg), midInstr.StrArg, midInstr.FlagArg )); } break; case MidInstruction.OpcodeEnum.UnboxPtr: { outInstructions.Add(new Clarity.Rpa.Instructions.UnboxPtrInstruction( midInstr.CodeLocation, InternSsaRegister(midInstr.RegArg2), InternSsaRegister(midInstr.RegArg) )); } break; case MidInstruction.OpcodeEnum.UnboxValue: { outInstructions.Add(new Clarity.Rpa.Instructions.UnboxValueInstruction( midInstr.CodeLocation, InternSsaRegister(midInstr.RegArg2), InternSsaRegister(midInstr.RegArg) )); } break; case MidInstruction.OpcodeEnum.ZeroFillPtr: outInstructions.Add(new Clarity.Rpa.Instructions.ZeroFillPtrInstruction( midInstr.CodeLocation, InternSsaRegister(midInstr.RegArg) )); break; case MidInstruction.OpcodeEnum.EnterProtectedBlock: { ExceptionHandlingCluster cluster = midInstr.EhClusterArg; Clarity.Rpa.HighRegion tryRegion; { CppRegionEmitter tryEmitter = new CppRegionEmitter(m_builder, cluster.TryRegion, m_regAllocator, m_localLookup); tryRegion = tryEmitter.Emit(); } List<HighCatchHandler> catchHandlers = new List<HighCatchHandler>(); List<HighRegion> otherRegions = new List<HighRegion>(); foreach (ExceptionHandlingRegion handlerRegion in cluster.ExceptionHandlingRegions) { CppRegionEmitter hdlEmitter = new CppRegionEmitter(m_builder, handlerRegion, m_regAllocator, m_localLookup); HighRegion hdlRegion = hdlEmitter.Emit(); switch (cluster.ClusterType) { case ExceptionHandlingCluster.ClusterTypeEnum.TryCatch: { HighCfgNode entryNode = hdlRegion.EntryNode.Value; // Inject a catch landing instruction and recreate the phi node. // This is safe because III.1.7.5 disallows backward branches with stack, // so the only valid way to reach a catch handler is by catching, never via // a predecessor. if (entryNode.Phis.Length != 1 || entryNode.Phis[0].Links.Length != 0) throw new Exception("Catch handler should start with an unlinked phi node"); HighSsaRegister exceptionReg = entryNode.Phis[0].Dest; CodeLocationTag codeLoc = entryNode.Instructions[0].CodeLocation; List<HighInstruction> catchLandingInstrs = new List<HighInstruction>(); HighSsaRegister catchDest = new HighSsaRegister(HighValueType.ReferenceValue, exceptionReg.Type, null); catchLandingInstrs.Add(new Clarity.Rpa.Instructions.CatchInstruction(codeLoc, catchDest, exceptionReg.Type)); catchLandingInstrs.Add(new Clarity.Rpa.Instructions.BranchInstruction(codeLoc, hdlRegion.EntryNode)); HighCfgNode landingNode = new HighCfgNode(new HighCfgNodeHandle[0], new HighPhi[0], catchLandingInstrs.ToArray()); HighCfgNodeHandle landingHandle = new HighCfgNodeHandle(landingNode); entryNode.Predecessors = new HighCfgNodeHandle[] { landingHandle }; entryNode.Phis[0].Links = new HighPhiLink[] { new HighPhiLink(landingHandle, catchDest) }; HighRegion replacementRegion = new HighRegion(landingHandle); catchHandlers.Add(new HighCatchHandler( RpaTagFactory.CreateTypeTag(handlerRegion.ExceptionType), replacementRegion )); } break; case ExceptionHandlingCluster.ClusterTypeEnum.TryFault: case ExceptionHandlingCluster.ClusterTypeEnum.TryFinally: otherRegions.Add(hdlRegion); break; default: throw new Exception(); } } List<Clarity.Rpa.HighEscapePathTerminator> terminators = new List<Clarity.Rpa.HighEscapePathTerminator>(); foreach (uint escapePath in cluster.EscapePaths) { CfgNode targetNode; if (m_region.EscapeTerminators.TryGetValue(escapePath, out targetNode)) { Clarity.Rpa.HighCfgNodeHandle terminatorNode = InternHighCfgNode(targetNode); terminators.Add(new Clarity.Rpa.HighEscapePathTerminator(escapePath, terminatorNode)); } } Clarity.Rpa.HighProtectedRegion protRegion; switch (cluster.ClusterType) { case ExceptionHandlingCluster.ClusterTypeEnum.TryCatch: protRegion = new Clarity.Rpa.HighTryCatchRegion(tryRegion, catchHandlers.ToArray()); break; case ExceptionHandlingCluster.ClusterTypeEnum.TryFault: protRegion = new Clarity.Rpa.HighTryFaultRegion(tryRegion, otherRegions[0]); break; case ExceptionHandlingCluster.ClusterTypeEnum.TryFinally: protRegion = new Clarity.Rpa.HighTryFinallyRegion(tryRegion, otherRegions[0]); break; default: throw new Exception(); } Clarity.Rpa.HighEHCluster highCluster = new Clarity.Rpa.HighEHCluster(protRegion, terminators.ToArray()); outInstructions.Add(new Clarity.Rpa.Instructions.EnterProtectedBlockInstruction( midInstr.CodeLocation, highCluster )); } break; case MidInstruction.OpcodeEnum.ExitFinally: outInstructions.Add(new Clarity.Rpa.Instructions.ReturnInstruction(midInstr.CodeLocation)); break; case MidInstruction.OpcodeEnum.BindDelegate: { SsaRegister objReg = midInstr.RegArg; CppMethodSpec methodSpec = (CppMethodSpec)midInstr.RegArg2.ConstantValue; SsaRegister destReg = midInstr.RegArg3; Clarity.Rpa.MethodSignatureTag sigTag = RpaTagFactory.CreateMethodSignature(methodSpec.CppMethod.MethodSignature); Clarity.Rpa.HighSsaRegister destRegHigh = InternSsaRegister(destReg); Clarity.Rpa.MethodSlotType slotType; if (methodSpec.CppMethod.Static) slotType = Clarity.Rpa.MethodSlotType.Static; else { objReg = EmitPassiveConversion(midInstr.CodeLocation, objReg, methodSpec.CppMethod.DeclaredInClassSpec, outline, outInstructions); if (midInstr.RegArg2.VType.ValType == VType.ValTypeEnum.DelegateSimpleMethod) slotType = Clarity.Rpa.MethodSlotType.Instance; else if (midInstr.RegArg2.VType.ValType == VType.ValTypeEnum.DelegateVirtualMethod) slotType = Clarity.Rpa.MethodSlotType.Virtual; else throw new ArgumentException(); } Clarity.Rpa.MethodSpecTag methodSpecTag = RpaTagFactory.CreateMethodSpec(slotType, methodSpec); if (methodSpec.CppMethod.Static) { outInstructions.Add(new Clarity.Rpa.Instructions.BindStaticDelegateInstruction( midInstr.CodeLocation, InternSsaRegister(destReg), methodSpecTag )); } else if (midInstr.RegArg2.VType.ValType == VType.ValTypeEnum.DelegateSimpleMethod) { outInstructions.Add(new Clarity.Rpa.Instructions.BindInstanceDelegateInstruction( midInstr.CodeLocation, InternSsaRegister(destReg), InternSsaRegister(objReg), methodSpecTag )); } else if (midInstr.RegArg2.VType.ValType == VType.ValTypeEnum.DelegateVirtualMethod) { outInstructions.Add(new Clarity.Rpa.Instructions.BindVirtualDelegateInstruction( midInstr.CodeLocation, InternSsaRegister(destReg), InternSsaRegister(objReg), methodSpecTag )); } } break; default: throw new ArgumentException("Invalid mid IL opcode"); } } if (cfgNode.FallThroughEdge != null && !fallthroughMerged) { CppTranslatedOutboundEdge outEdge = InternOutboundEdge(cfgNode, cfgNode.FallThroughEdge); outInstructions.Add(new Clarity.Rpa.Instructions.BranchInstruction(cfgNode.FallThroughEdge.CodeLocation, outEdge.NextNode)); } List<HighCfgNodeHandle> highPreds = new List<HighCfgNodeHandle>(); foreach (CppTranslatedOutboundEdge predEdge in predecessorEdges) highPreds.Add(predEdge.PrevNode); highNode.Value = new HighCfgNode(highPreds.ToArray(), outPhis.ToArray(), outInstructions.ToArray()); }
public void Compile() { CppMethod method = m_cfgNode.CfgBuilder.CppMethod; VReg[] locals = m_cfgNode.CfgBuilder.Locals; VReg[] args = m_cfgNode.CfgBuilder.Args; CfgBuilder cfgBuilder = m_cfgNode.CfgBuilder; CLR.CIL.Method cilMethod = method.MethodDef.Method; List<MidInstruction> midInstrs = new List<MidInstruction>(); bool[] everTargeted = new bool[cilMethod.Instructions.Length]; EvalStackTracker stackTracker = new EvalStackTracker(); Clarity.Rpa.CodeLocationTag codeLocation = new Clarity.Rpa.CodeLocationTag(method.VtableSlotTag, cilMethod.OffsetForInstruction(m_cfgNode.StartInstr)); foreach (VType entryType in m_cfgNode.EntryTypes) { SsaRegister reg = stackTracker.NewReg(entryType); reg.TrySpill(); stackTracker.Push(reg); midInstrs.Add(new MidInstruction(MidInstruction.OpcodeEnum.EntryReg, codeLocation, reg)); } int firstInstr = m_cfgNode.StartInstr; int nextInstr = firstInstr; bool isTerminalEdge = false; while (!isTerminalEdge) { int instrNum = nextInstr++; codeLocation = new Clarity.Rpa.CodeLocationTag(method.VtableSlotTag, cilMethod.OffsetForInstruction(instrNum)); if (instrNum != firstInstr && cfgBuilder.InstrIsJumpTarget(instrNum)) { CfgOutboundEdgePrototype edgeProto = stackTracker.GenerateCfgEdge(); OutputFallThroughEdge = new CfgOutboundEdge(codeLocation, cfgBuilder.AddCfgTarget(this, instrNum, edgeProto.OutboundTypes), edgeProto); break; } if (cfgBuilder.EhClusters.ContainsKey((uint)instrNum)) { if (stackTracker.Depth != 0) throw new ParseFailedException("Stack not empty at protected block entry point"); ExceptionHandlingCluster cluster = cfgBuilder.EhClusters[(uint)instrNum]; midInstrs.Add(new MidInstruction(MidInstruction.OpcodeEnum.EnterProtectedBlock, codeLocation, cluster)); VType[] emptyTypesList = new VType[0]; foreach (uint escapePath in cluster.EscapePaths) { if (escapePath >= m_ehRegion.StartInstr && escapePath <= m_ehRegion.EndInstr) { CfgNode targetNode = cfgBuilder.AddCfgTarget(this, (int)escapePath, emptyTypesList); m_ehRegion.AddLeaveTarget(escapePath, targetNode); } else m_ehRegion.AddEscapePath(escapePath); } break; } CLR.CIL.HLInstruction instr = cilMethod.Instructions[instrNum]; switch (instr.Opcode) { case CLR.CIL.HLOpcode.nop: break; case CLR.CIL.HLOpcode.newobj: { CppMethodSpec ctorMethodSpec = CppBuilder.ResolveMethodDefOrRef((CLRTableRow)instr.Arguments.ObjValue); if (ctorMethodSpec.GenericParameters != null) throw new ArgumentException(); CppMethod ctorMethod = ctorMethodSpec.CppMethod; int numParams = ctorMethod.MethodSignature.ParamTypes.Length; CLRTypeSpec instanceSpec = ctorMethod.DeclaredInClassSpec; VType.ValTypeEnum resultValType = CppCilExporter.ValTypeForTypeSpec(m_cppBuilder, instanceSpec); SsaRegister instanceReg = stackTracker.NewReg(new VType(resultValType, instanceSpec)); // Allocate the instance into an SSA reg midInstrs.Add(new MidInstruction(MidInstruction.OpcodeEnum.LivenReg, codeLocation, instanceReg)); stackTracker.SpillStack(); bool isDelegate = false; if (numParams == 2) { SsaRegister param2 = stackTracker.GetFromTop(0); if (param2.VType.ValType == VType.ValTypeEnum.DelegateSimpleMethod || param2.VType.ValType == VType.ValTypeEnum.DelegateVirtualMethod) isDelegate = true; } // Determine the parameter set. // Unlike when making calls, we don't spill here because we already spilled during the AllocObject call SsaRegister[] passedParams = new SsaRegister[numParams]; for (int p = 0; p < numParams; p++) { SsaRegister paramReg = stackTracker.GetFromTop(numParams - 1 - p); passedParams[p] = paramReg; } CppClass cls = CppBuilder.GetCachedClass(instanceSpec); SsaRegister valueOutRegister = null; VReg tempLocal = null; if (cls.IsValueType) { valueOutRegister = instanceReg; tempLocal = GetTemporary(new VType(VType.ValTypeEnum.ValueValue, instanceSpec)); SsaRegister tempClearAddr = new SsaRegister(new VType(VType.ValTypeEnum.ManagedPtr, instanceSpec)); midInstrs.Add(new MidInstruction(MidInstruction.OpcodeEnum.LivenReg, codeLocation, tempClearAddr)); midInstrs.Add(new MidInstruction(MidInstruction.OpcodeEnum.LoadRegA, codeLocation, tempLocal, tempClearAddr)); midInstrs.Add(new MidInstruction(MidInstruction.OpcodeEnum.ZeroFillPtr, codeLocation, tempClearAddr)); midInstrs.Add(new MidInstruction(MidInstruction.OpcodeEnum.KillReg, codeLocation, tempClearAddr)); SsaRegister tempUseAddr = new SsaRegister(new VType(VType.ValTypeEnum.ManagedPtr, instanceSpec)); midInstrs.Add(new MidInstruction(MidInstruction.OpcodeEnum.LivenReg, codeLocation, tempUseAddr)); midInstrs.Add(new MidInstruction(MidInstruction.OpcodeEnum.LoadRegA, codeLocation, tempLocal, tempUseAddr)); instanceReg = tempUseAddr; } if (isDelegate) midInstrs.Add(new MidInstruction(MidInstruction.OpcodeEnum.BindDelegate, codeLocation, passedParams[0], passedParams[1], instanceReg)); else { // Allocate object if (tempLocal == null) midInstrs.Add(new MidInstruction(MidInstruction.OpcodeEnum.AllocObject, codeLocation, instanceReg, instanceSpec)); // Make the actual ctor call midInstrs.Add(new MidInstruction(MidInstruction.OpcodeEnum.CallConstructor, codeLocation, ctorMethodSpec, null, null, instanceReg, passedParams)); } // Kill all of the parameter registers for (int p = 0; p < numParams; p++) midInstrs.Add(new MidInstruction(MidInstruction.OpcodeEnum.KillReg, codeLocation, stackTracker.Pop())); if (valueOutRegister != null) { midInstrs.Add(new MidInstruction(MidInstruction.OpcodeEnum.LoadReg_Value, codeLocation, tempLocal, valueOutRegister)); midInstrs.Add(new MidInstruction(MidInstruction.OpcodeEnum.KillReg, codeLocation, instanceReg)); instanceReg = valueOutRegister; } // Push the return value on to the stack stackTracker.Push(instanceReg); } break; case CLR.CIL.HLOpcode.ret: if (stackTracker.Depth == 1) { SsaRegister returnValue = stackTracker.Pop(); midInstrs.Add(new MidInstruction(MidInstruction.OpcodeEnum.ReturnValue, codeLocation, returnValue, method.MethodSignature.RetType)); midInstrs.Add(new MidInstruction(MidInstruction.OpcodeEnum.KillReg, codeLocation, returnValue)); } else if (stackTracker.Depth == 0) midInstrs.Add(new MidInstruction(MidInstruction.OpcodeEnum.Return, codeLocation)); else throw new ArgumentException(); isTerminalEdge = true; break; case CLR.CIL.HLOpcode.ldarg: { VReg argReg = args[instr.Arguments.U32Value]; SsaRegister evalReg = stackTracker.NewReg(argReg.VType); midInstrs.Add(new MidInstruction(MidInstruction.OpcodeEnum.LivenReg, codeLocation, evalReg)); string loadSrc = argReg.SlotName; switch (argReg.VType.ValType) { case VType.ValTypeEnum.ManagedPtr: midInstrs.Add(new MidInstruction(MidInstruction.OpcodeEnum.LoadReg_ManagedPtr, codeLocation, argReg, evalReg)); break; case VType.ValTypeEnum.ReferenceValue: case VType.ValTypeEnum.ValueValue: midInstrs.Add(new MidInstruction(MidInstruction.OpcodeEnum.LoadReg_Value, codeLocation, argReg, evalReg)); break; default: throw new ArgumentException(); } stackTracker.Push(evalReg); } break; case CLR.CIL.HLOpcode.ldarga: { VReg argReg = args[instr.Arguments.U32Value]; VType outEvalType; MidInstruction.OpcodeEnum opcode; switch (argReg.VType.ValType) { case VType.ValTypeEnum.ReferenceValue: case VType.ValTypeEnum.ValueValue: opcode = MidInstruction.OpcodeEnum.LoadArgA_Value; outEvalType = new VType(VType.ValTypeEnum.ManagedPtr, argReg.VType.TypeSpec); break; default: throw new ArgumentException(); } SsaRegister evalReg = stackTracker.NewReg(outEvalType); midInstrs.Add(new MidInstruction(MidInstruction.OpcodeEnum.LivenReg, codeLocation, evalReg)); midInstrs.Add(new MidInstruction(opcode, codeLocation, argReg, evalReg)); stackTracker.Push(evalReg); } break; case CLR.CIL.HLOpcode.starg: { VReg argReg = args[instr.Arguments.U32Value]; SsaRegister valueReg = stackTracker.Pop(); switch (valueReg.VType.ValType) { case VType.ValTypeEnum.ConstantReference: case VType.ValTypeEnum.ReferenceValue: case VType.ValTypeEnum.Null: case VType.ValTypeEnum.ValueValue: case VType.ValTypeEnum.ConstantValue: midInstrs.Add(new MidInstruction(MidInstruction.OpcodeEnum.StoreReg_Value, codeLocation, argReg, valueReg)); break; case VType.ValTypeEnum.ManagedPtr: midInstrs.Add(new MidInstruction(MidInstruction.OpcodeEnum.StoreReg_ManagedPtr, codeLocation, argReg, valueReg)); break; default: throw new ArgumentException(); } midInstrs.Add(new MidInstruction(MidInstruction.OpcodeEnum.KillReg, codeLocation, valueReg)); } break; case CLR.CIL.HLOpcode.call: case CLR.CIL.HLOpcode.callvirt: { bool devirtualize = false; CLRTypeSpec constraintType = null; if (instrNum != 0) { CLR.CIL.HLInstruction prevInstr = cilMethod.Instructions[instrNum - 1]; if (prevInstr.Opcode == CLR.CIL.HLOpcode.constrained_pfx) constraintType = m_cppBuilder.Assemblies.InternTypeDefOrRefOrSpec((CLRTableRow)prevInstr.Arguments.ObjValue); } CppMethodSpec calledMethodSpec = CppBuilder.ResolveMethodDefOrRef((CLRTableRow)instr.Arguments.ObjValue); CppMethod calledMethod = calledMethodSpec.CppMethod; if (!calledMethod.Virtual) devirtualize = true; int numParams = calledMethod.MethodSignature.ParamTypes.Length; SsaRegister returnReg = null; SsaRegister thisReg = null; if (!CppBuilder.TypeSpecIsVoid(calledMethod.MethodSignature.RetType)) { CLRTypeSpec retType = calledMethod.MethodSignature.RetType; returnReg = stackTracker.NewReg(new VType(CppCilExporter.ValTypeForTypeSpec(m_cppBuilder, retType), retType)); midInstrs.Add(new MidInstruction(MidInstruction.OpcodeEnum.LivenReg, codeLocation, returnReg)); } if (!calledMethod.Static) thisReg = stackTracker.GetFromTop(numParams); MidInstruction.OpcodeEnum midOpcode; if (instr.Opcode == CLR.CIL.HLOpcode.call || devirtualize) { if (constraintType != null) midOpcode = MidInstruction.OpcodeEnum.ConstrainedCallMethod; else midOpcode = MidInstruction.OpcodeEnum.CallMethod; } else if (instr.Opcode == CLR.CIL.HLOpcode.callvirt) { if (constraintType != null) midOpcode = MidInstruction.OpcodeEnum.ConstrainedCallVirtualMethod; else { midOpcode = MidInstruction.OpcodeEnum.CallVirtualMethod; if (calledMethod.NumGenericParameters > 0) { if (calledMethod.DeclaredInClass.Semantics == CLRTypeDefRow.TypeSemantics.Interface) throw new NotSupportedException(method.DeclaredInClassSpec.ToString() + "." + method.Name + " contains an unconstrained call to an interface virtual method, which is not supported."); else if (calledMethod.DeclaredInClass.Semantics == CLRTypeDefRow.TypeSemantics.Class) midOpcode = MidInstruction.OpcodeEnum.CallMethod; else throw new ArgumentException(); } } } else throw new ArgumentException(); SsaRegister[] passedParams = new SsaRegister[numParams]; for (int p = 0; p < numParams; p++) { SsaRegister paramReg = stackTracker.GetFromTop(numParams - 1 - p); passedParams[p] = paramReg; } // Pop the parameters first so that we don't have to spill them into the caller frame. // They won't actually be deadened until after the call. stackTracker.Pop(numParams); stackTracker.SpillStack(); // Emit the actual call midInstrs.Add(new MidInstruction(midOpcode, codeLocation, calledMethodSpec, constraintType, returnReg, thisReg, passedParams)); // Emit parameter deadens (in stack order) for (int p = 0; p < numParams; p++) midInstrs.Add(new MidInstruction(MidInstruction.OpcodeEnum.KillReg, codeLocation, passedParams[numParams - 1 - p])); // Emit "this" deaden and remove it from the stack if (thisReg != null) { midInstrs.Add(new MidInstruction(MidInstruction.OpcodeEnum.KillReg, codeLocation, thisReg)); if (stackTracker.Pop() != thisReg) throw new ArgumentException(); } // Push the return value if (returnReg != null) stackTracker.Push(returnReg); } break; case CLR.CIL.HLOpcode.stloc: { SsaRegister evalVar = stackTracker.Pop(); VReg localVar = locals[instr.Arguments.U32Value]; switch (localVar.VType.ValType) { case VType.ValTypeEnum.ValueValue: case VType.ValTypeEnum.ReferenceValue: midInstrs.Add(new MidInstruction(MidInstruction.OpcodeEnum.StoreReg_Value, codeLocation, localVar, evalVar)); break; case VType.ValTypeEnum.ManagedPtr: midInstrs.Add(new MidInstruction(MidInstruction.OpcodeEnum.StoreReg_ManagedPtr, codeLocation, localVar, evalVar)); break; default: throw new ArgumentException(); } midInstrs.Add(new MidInstruction(MidInstruction.OpcodeEnum.KillReg, codeLocation, evalVar)); } break; case CLR.CIL.HLOpcode.ldloc: { VReg localVar = locals[instr.Arguments.U32Value]; SsaRegister evalReg = stackTracker.NewReg(localVar.VType); midInstrs.Add(new MidInstruction(MidInstruction.OpcodeEnum.LivenReg, codeLocation, evalReg)); switch (localVar.VType.ValType) { case VType.ValTypeEnum.ManagedPtr: midInstrs.Add(new MidInstruction(MidInstruction.OpcodeEnum.LoadReg_ManagedPtr, codeLocation, localVar, evalReg)); break; case VType.ValTypeEnum.ValueValue: case VType.ValTypeEnum.ReferenceValue: midInstrs.Add(new MidInstruction(MidInstruction.OpcodeEnum.LoadReg_Value, codeLocation, localVar, evalReg)); break; default: throw new ArgumentException(); } stackTracker.Push(evalReg); } break; case CLR.CIL.HLOpcode.ldloca: { VReg localVar = locals[instr.Arguments.U32Value]; SsaRegister evalReg = stackTracker.NewReg(new VType(VType.ValTypeEnum.ManagedPtr, localVar.VType.TypeSpec)); midInstrs.Add(new MidInstruction(MidInstruction.OpcodeEnum.LivenReg, codeLocation, evalReg)); switch (localVar.VType.ValType) { case VType.ValTypeEnum.ValueValue: case VType.ValTypeEnum.ReferenceValue: midInstrs.Add(new MidInstruction(MidInstruction.OpcodeEnum.LoadRegA, codeLocation, localVar, evalReg)); break; default: throw new ArgumentException(); } stackTracker.Push(evalReg); } break; case CLR.CIL.HLOpcode.bne: // [.un] { SsaRegister value2 = stackTracker.Pop(); SsaRegister value1 = stackTracker.Pop(); bool isRefComparison = IsComparisonReference(value1.VType, value2.VType); CfgOutboundEdgePrototype edgeProto = stackTracker.GenerateCfgEdge(); CfgNode targetNode = cfgBuilder.AddCfgTarget(this, (int)instr.Arguments.U32Value, edgeProto.OutboundTypes); CfgNode fallThroughNode = cfgBuilder.AddCfgTarget(this, nextInstr, edgeProto.OutboundTypes); midInstrs.Add(new MidInstruction(isRefComparison ? MidInstruction.OpcodeEnum.bne_ref : MidInstruction.OpcodeEnum.bne_val, codeLocation, value1, value2, new CfgOutboundEdge(codeLocation, targetNode, edgeProto), (instr.Flags & CLR.CIL.HLOpFlags.Un) != 0)); midInstrs.Add(new MidInstruction(MidInstruction.OpcodeEnum.KillReg, codeLocation, value2)); midInstrs.Add(new MidInstruction(MidInstruction.OpcodeEnum.KillReg, codeLocation, value1)); OutputFallThroughEdge = new CfgOutboundEdge(codeLocation, fallThroughNode, edgeProto); isTerminalEdge = true; } break; case CLR.CIL.HLOpcode.beq: // [.un] { SsaRegister value2 = stackTracker.Pop(); SsaRegister value1 = stackTracker.Pop(); CfgOutboundEdgePrototype edgeProto = stackTracker.GenerateCfgEdge(); bool isRefComparison = IsComparisonReference(value1.VType, value2.VType); CfgNode targetNode = cfgBuilder.AddCfgTarget(this, (int)instr.Arguments.U32Value, edgeProto.OutboundTypes); CfgNode fallThroughNode = cfgBuilder.AddCfgTarget(this, nextInstr, edgeProto.OutboundTypes); midInstrs.Add(new MidInstruction(isRefComparison ? MidInstruction.OpcodeEnum.beq_ref : MidInstruction.OpcodeEnum.beq_val, codeLocation, value1, value2, new CfgOutboundEdge(codeLocation, targetNode, edgeProto), (instr.Flags & CLR.CIL.HLOpFlags.Un) != 0)); midInstrs.Add(new MidInstruction(MidInstruction.OpcodeEnum.KillReg, codeLocation, value2)); midInstrs.Add(new MidInstruction(MidInstruction.OpcodeEnum.KillReg, codeLocation, value1)); OutputFallThroughEdge = new CfgOutboundEdge(codeLocation, fallThroughNode, edgeProto); isTerminalEdge = true; } break; case CLR.CIL.HLOpcode.bge: // [.un] case CLR.CIL.HLOpcode.bgt: // [.un] case CLR.CIL.HLOpcode.ble: // [.un] case CLR.CIL.HLOpcode.blt: // [.un] { SsaRegister value2 = stackTracker.Pop(); SsaRegister value1 = stackTracker.Pop(); CfgOutboundEdgePrototype edgeProto = stackTracker.GenerateCfgEdge(); CfgNode targetNode = cfgBuilder.AddCfgTarget(this, (int)instr.Arguments.U32Value, edgeProto.OutboundTypes); CfgNode fallThroughNode = cfgBuilder.AddCfgTarget(this, nextInstr, edgeProto.OutboundTypes); midInstrs.Add(new MidInstruction(SimpleTranslateInstr(instr.Opcode), codeLocation, value1, value2, new CfgOutboundEdge(codeLocation, targetNode, edgeProto), (instr.Flags & CLR.CIL.HLOpFlags.Un) != 0)); midInstrs.Add(new MidInstruction(MidInstruction.OpcodeEnum.KillReg, codeLocation, value2)); midInstrs.Add(new MidInstruction(MidInstruction.OpcodeEnum.KillReg, codeLocation, value1)); OutputFallThroughEdge = new CfgOutboundEdge(codeLocation, fallThroughNode, edgeProto); isTerminalEdge = true; } break; case CLR.CIL.HLOpcode.br: { CfgOutboundEdgePrototype edgeProto = stackTracker.GenerateCfgEdge(); CfgNode targetNode = cfgBuilder.AddCfgTarget(this, (int)instr.Arguments.U32Value, edgeProto.OutboundTypes); OutputFallThroughEdge = new CfgOutboundEdge(codeLocation, targetNode, edgeProto); isTerminalEdge = true; } break; case CLR.CIL.HLOpcode.leave: { uint escapePath = instr.Arguments.U32Value; m_ehRegion.AddEscapePath(instr.Arguments.U32Value); midInstrs.Add(new MidInstruction(MidInstruction.OpcodeEnum.Leave, codeLocation, escapePath)); while (stackTracker.Depth > 0) midInstrs.Add(new MidInstruction(MidInstruction.OpcodeEnum.KillReg, codeLocation, stackTracker.Pop())); isTerminalEdge = true; } break; case CLR.CIL.HLOpcode.ceq: { SsaRegister value2 = stackTracker.Pop(); SsaRegister value1 = stackTracker.Pop(); SsaRegister returnValue = stackTracker.NewReg(new VType(VType.ValTypeEnum.ValueValue, m_commonTypeLookup.Boolean)); bool isRefComparison = IsComparisonReference(value1.VType, value2.VType); midInstrs.Add(new MidInstruction(MidInstruction.OpcodeEnum.LivenReg, codeLocation, returnValue)); midInstrs.Add(new MidInstruction(isRefComparison ? MidInstruction.OpcodeEnum.ceq_ref : MidInstruction.OpcodeEnum.ceq_numeric, codeLocation, returnValue, value1, value2, false)); midInstrs.Add(new MidInstruction(MidInstruction.OpcodeEnum.KillReg, codeLocation, value2)); midInstrs.Add(new MidInstruction(MidInstruction.OpcodeEnum.KillReg, codeLocation, value1)); stackTracker.Push(returnValue); } break; case CLR.CIL.HLOpcode.cgt: // [.un] { SsaRegister value2 = stackTracker.Pop(); SsaRegister value1 = stackTracker.Pop(); SsaRegister returnValue = stackTracker.NewReg(new VType(VType.ValTypeEnum.ValueValue, m_commonTypeLookup.Boolean)); // Per III.4, cgt.un is used for reference non-equality checks. // For some reason there isn't a cne instruction... bool isRefComparison = IsComparisonReference(value1.VType, value2.VType); midInstrs.Add(new MidInstruction(MidInstruction.OpcodeEnum.LivenReg, codeLocation, returnValue)); midInstrs.Add(new MidInstruction(isRefComparison ? MidInstruction.OpcodeEnum.cne_ref : MidInstruction.OpcodeEnum.cgt, codeLocation, returnValue, value1, value2, (instr.Flags & CLR.CIL.HLOpFlags.Un) != 0)); midInstrs.Add(new MidInstruction(MidInstruction.OpcodeEnum.KillReg, codeLocation, value2)); midInstrs.Add(new MidInstruction(MidInstruction.OpcodeEnum.KillReg, codeLocation, value1)); stackTracker.Push(returnValue); } break; case CLR.CIL.HLOpcode.clt: // [.un] { SsaRegister value2 = stackTracker.Pop(); SsaRegister value1 = stackTracker.Pop(); SsaRegister returnValue = stackTracker.NewReg(new VType(VType.ValTypeEnum.ValueValue, m_commonTypeLookup.Boolean)); midInstrs.Add(new MidInstruction(MidInstruction.OpcodeEnum.LivenReg, codeLocation, returnValue)); midInstrs.Add(new MidInstruction(SimpleTranslateInstr(instr.Opcode), codeLocation, returnValue, value1, value2, (instr.Flags & CLR.CIL.HLOpFlags.Un) != 0)); midInstrs.Add(new MidInstruction(MidInstruction.OpcodeEnum.KillReg, codeLocation, value2)); midInstrs.Add(new MidInstruction(MidInstruction.OpcodeEnum.KillReg, codeLocation, value1)); stackTracker.Push(returnValue); } break; case CLR.CIL.HLOpcode.ldc: { SsaRegister resultReg; switch (instr.Arguments.ArgsType) { case CLR.CIL.HLArguments.ArgsTypeEnum.I32: resultReg = SsaRegister.Constant(new VType(VType.ValTypeEnum.ConstantValue, m_commonTypeLookup.I32, instr.Arguments.S32Value)); break; case CLR.CIL.HLArguments.ArgsTypeEnum.I64: resultReg = SsaRegister.Constant(new VType(VType.ValTypeEnum.ConstantValue, m_commonTypeLookup.I64, instr.Arguments.S64Value)); break; case CLR.CIL.HLArguments.ArgsTypeEnum.F32: resultReg = SsaRegister.Constant(new VType(VType.ValTypeEnum.ConstantValue, m_commonTypeLookup.F32, instr.Arguments.F32Value)); break; case CLR.CIL.HLArguments.ArgsTypeEnum.F64: resultReg = SsaRegister.Constant(new VType(VType.ValTypeEnum.ConstantValue, m_commonTypeLookup.F64, instr.Arguments.F64Value)); break; default: throw new ArgumentException(); } midInstrs.Add(new MidInstruction(MidInstruction.OpcodeEnum.LivenReg, codeLocation, resultReg)); stackTracker.Push(resultReg); } break; case CLR.CIL.HLOpcode.brfalse: case CLR.CIL.HLOpcode.brtrue: { SsaRegister v = stackTracker.Pop(); CfgOutboundEdgePrototype edgeProto = stackTracker.GenerateCfgEdge(); CfgNode targetNode = cfgBuilder.AddCfgTarget(this, (int)instr.Arguments.U32Value, edgeProto.OutboundTypes); CfgNode fallThroughNode = cfgBuilder.AddCfgTarget(this, nextInstr, edgeProto.OutboundTypes); MidInstruction.OpcodeEnum opcode; switch (v.VType.ValType) { case VType.ValTypeEnum.ConstantValue: case VType.ValTypeEnum.ValueValue: if (instr.Opcode == CLR.CIL.HLOpcode.brtrue) opcode = MidInstruction.OpcodeEnum.brnotzero; else opcode = MidInstruction.OpcodeEnum.brzero; break; case VType.ValTypeEnum.ConstantReference: case VType.ValTypeEnum.Null: case VType.ValTypeEnum.ReferenceValue: if (instr.Opcode == CLR.CIL.HLOpcode.brtrue) opcode = MidInstruction.OpcodeEnum.brnotnull; else opcode = MidInstruction.OpcodeEnum.brnull; break; default: throw new Exception("Unsupported stack op type passed to brtrue or brfalse"); } midInstrs.Add(new MidInstruction(opcode, codeLocation, v, new CfgOutboundEdge(codeLocation, targetNode, edgeProto))); midInstrs.Add(new MidInstruction(MidInstruction.OpcodeEnum.KillReg, codeLocation, v)); OutputFallThroughEdge = new CfgOutboundEdge(codeLocation, fallThroughNode, edgeProto); isTerminalEdge = true; } break; case CLR.CIL.HLOpcode.ldnull: { SsaRegister constReg = SsaRegister.Constant(new VType(VType.ValTypeEnum.Null, m_commonTypeLookup.Object)); midInstrs.Add(new MidInstruction(MidInstruction.OpcodeEnum.LivenReg, codeLocation, constReg)); stackTracker.Push(constReg); } break; case CLR.CIL.HLOpcode.@throw: { SsaRegister ex = stackTracker.Pop(); midInstrs.Add(new MidInstruction(MidInstruction.OpcodeEnum.Throw, codeLocation, ex)); midInstrs.Add(new MidInstruction(MidInstruction.OpcodeEnum.KillReg, codeLocation, ex)); isTerminalEdge = true; } break; case CLR.CIL.HLOpcode.newarr: { CLRTableRow contentsType = (CLRTableRow)instr.Arguments.ObjValue; CLRTypeSpec contentsTypeSpec = m_cppBuilder.Assemblies.InternTypeDefOrRefOrSpec(contentsType); CLRTypeSpecSZArray arrayTS = new CLRTypeSpecSZArray(contentsTypeSpec); SsaRegister resultReg = stackTracker.NewReg(new VType(VType.ValTypeEnum.ReferenceValue, arrayTS)); // It's OK to pop num elems here since, as an integer, we don't care if it doesn't spill SsaRegister numElemsReg = stackTracker.Pop(); midInstrs.Add(new MidInstruction(MidInstruction.OpcodeEnum.LivenReg, codeLocation, resultReg)); stackTracker.SpillStack(); midInstrs.Add(new MidInstruction(MidInstruction.OpcodeEnum.NewSZArray, codeLocation, resultReg, numElemsReg)); midInstrs.Add(new MidInstruction(MidInstruction.OpcodeEnum.KillReg, codeLocation, numElemsReg)); stackTracker.Push(resultReg); } break; case CLR.CIL.HLOpcode.ldfld: { CppField field = ResolveField((CLRTableRow)instr.Arguments.ObjValue); CLRTypeSpec fieldValueSpec = field.Type; VType.ValTypeEnum valType = CppCilExporter.ValTypeForTypeSpec(m_cppBuilder, fieldValueSpec); SsaRegister valueReg = stackTracker.NewReg(new VType(valType, fieldValueSpec)); SsaRegister objReg = stackTracker.Pop(); VType.ValTypeEnum objValType = objReg.VType.ValType; midInstrs.Add(new MidInstruction(MidInstruction.OpcodeEnum.LivenReg, codeLocation, valueReg)); MidInstruction.OpcodeEnum opcode; if (objValType == VType.ValTypeEnum.ManagedPtr) opcode = MidInstruction.OpcodeEnum.LoadField_ManagedPtr; else if (objValType == VType.ValTypeEnum.ReferenceValue) opcode = MidInstruction.OpcodeEnum.LoadField_Object; else if (objValType == VType.ValTypeEnum.ValueValue) opcode = MidInstruction.OpcodeEnum.LoadField_Value; else throw new ArgumentException(); midInstrs.Add(new MidInstruction(opcode, codeLocation, objReg, valueReg, field.Name, field.DeclaredInClassSpec)); midInstrs.Add(new MidInstruction(MidInstruction.OpcodeEnum.KillReg, codeLocation, objReg)); stackTracker.Push(valueReg); } break; case CLR.CIL.HLOpcode.ldflda: { SsaRegister objReg = stackTracker.Pop(); CppField field = ResolveField((CLRTableRow)instr.Arguments.ObjValue); CLRTypeSpec fieldValueSpec = field.Type; VType.ValTypeEnum valType = VType.ValTypeEnum.ManagedPtr; bool isManagedPtr = (objReg.VType.ValType == VType.ValTypeEnum.ManagedPtr); if (isManagedPtr) valType = objReg.VType.ValType; SsaRegister valueReg = stackTracker.NewReg(new VType(valType, fieldValueSpec)); VType.ValTypeEnum objValType = objReg.VType.ValType; midInstrs.Add(new MidInstruction(MidInstruction.OpcodeEnum.LivenReg, codeLocation, valueReg)); MidInstruction.OpcodeEnum opcode; if (isManagedPtr) opcode = MidInstruction.OpcodeEnum.LoadFieldA_ManagedPtr; else if (objValType == VType.ValTypeEnum.ReferenceValue) opcode = MidInstruction.OpcodeEnum.LoadFieldA_Object; else throw new ArgumentException(); midInstrs.Add(new MidInstruction(opcode, codeLocation, objReg, valueReg, field.Name, field.DeclaredInClassSpec)); midInstrs.Add(new MidInstruction(MidInstruction.OpcodeEnum.KillReg, codeLocation, objReg)); stackTracker.Push(valueReg); } break; case CLR.CIL.HLOpcode.ldsfld: { CppField field = ResolveField((CLRTableRow)instr.Arguments.ObjValue); CLRTypeSpec fieldValueSpec = field.Type; VType.ValTypeEnum valType = CppCilExporter.ValTypeForTypeSpec(m_cppBuilder, fieldValueSpec); SsaRegister valueReg = stackTracker.NewReg(new VType(valType, fieldValueSpec)); midInstrs.Add(new MidInstruction(MidInstruction.OpcodeEnum.LivenReg, codeLocation, valueReg)); midInstrs.Add(new MidInstruction(MidInstruction.OpcodeEnum.LoadStaticField, codeLocation, valueReg, field.DeclaredInClassSpec, field.Name)); stackTracker.Push(valueReg); } break; case CLR.CIL.HLOpcode.ldsflda: { CppField field = ResolveField((CLRTableRow)instr.Arguments.ObjValue); CLRTypeSpec fieldValueSpec = field.Type; SsaRegister valueReg = stackTracker.NewReg(new VType(VType.ValTypeEnum.ManagedPtr, fieldValueSpec)); midInstrs.Add(new MidInstruction(MidInstruction.OpcodeEnum.LivenReg, codeLocation, valueReg)); midInstrs.Add(new MidInstruction(MidInstruction.OpcodeEnum.LoadStaticFieldAddr, codeLocation, valueReg, field.DeclaredInClassSpec, field.Name)); stackTracker.Push(valueReg); } break; case CLR.CIL.HLOpcode.ldelem: // [.type] case CLR.CIL.HLOpcode.ldelema: { // We just ignore the type suffix and get it from the array instead SsaRegister indexReg = stackTracker.Pop(); SsaRegister arrayReg = stackTracker.Pop(); CLRTypeSpecSZArray arraySpec = (CLRTypeSpecSZArray)arrayReg.VType.TypeSpec; CLRTypeSpec contentsSpec = arraySpec.SubType; VType.ValTypeEnum valType; MidInstruction.OpcodeEnum op; if (instr.Opcode == CLR.CIL.HLOpcode.ldelem) { valType = CppCilExporter.ValTypeForTypeSpec(m_cppBuilder, contentsSpec); op = MidInstruction.OpcodeEnum.LoadArrayElem; } else if (instr.Opcode == CLR.CIL.HLOpcode.ldelema) { valType = VType.ValTypeEnum.ManagedPtr; op = MidInstruction.OpcodeEnum.LoadArrayElemAddr; } else throw new ArgumentException(); SsaRegister contentsReg = stackTracker.NewReg(new VType(valType, contentsSpec)); midInstrs.Add(new MidInstruction(MidInstruction.OpcodeEnum.LivenReg, codeLocation, contentsReg)); midInstrs.Add(new MidInstruction(op, codeLocation, arrayReg, indexReg, contentsReg)); midInstrs.Add(new MidInstruction(MidInstruction.OpcodeEnum.KillReg, codeLocation, indexReg)); midInstrs.Add(new MidInstruction(MidInstruction.OpcodeEnum.KillReg, codeLocation, arrayReg)); stackTracker.Push(contentsReg); } break; case CLR.CIL.HLOpcode.stelem: // [.type] { // We just ignore the type suffix and get it from the array instead SsaRegister valueReg = stackTracker.Pop(); SsaRegister indexReg = stackTracker.Pop(); SsaRegister arrayReg = stackTracker.Pop(); midInstrs.Add(new MidInstruction(MidInstruction.OpcodeEnum.StoreArrayElem, codeLocation, arrayReg, indexReg, valueReg)); midInstrs.Add(new MidInstruction(MidInstruction.OpcodeEnum.KillReg, codeLocation, valueReg)); midInstrs.Add(new MidInstruction(MidInstruction.OpcodeEnum.KillReg, codeLocation, indexReg)); midInstrs.Add(new MidInstruction(MidInstruction.OpcodeEnum.KillReg, codeLocation, arrayReg)); } break; case CLR.CIL.HLOpcode.stfld: { SsaRegister valueReg = stackTracker.Pop(); SsaRegister objReg = stackTracker.Pop(); CppField field = ResolveField((CLRTableRow)instr.Arguments.ObjValue); CLRTypeSpec fieldValueSpec = field.Type; VType.ValTypeEnum valType = CppCilExporter.ValTypeForTypeSpec(m_cppBuilder, fieldValueSpec); VType.ValTypeEnum objValType = objReg.VType.ValType; if (objValType == VType.ValTypeEnum.ManagedPtr) midInstrs.Add(new MidInstruction(MidInstruction.OpcodeEnum.StoreField_ManagedPtr, codeLocation, objReg, valueReg, field.Name, field.DeclaredInClassSpec, fieldValueSpec)); else if (objValType == VType.ValTypeEnum.ReferenceValue) midInstrs.Add(new MidInstruction(MidInstruction.OpcodeEnum.StoreField_Object, codeLocation, objReg, valueReg, field.Name, field.DeclaredInClassSpec, fieldValueSpec)); else throw new ArgumentException(); midInstrs.Add(new MidInstruction(MidInstruction.OpcodeEnum.KillReg, codeLocation, valueReg)); midInstrs.Add(new MidInstruction(MidInstruction.OpcodeEnum.KillReg, codeLocation, objReg)); } break; case CLR.CIL.HLOpcode.stsfld: { SsaRegister valueReg = stackTracker.Pop(); CppField field = ResolveField((CLRTableRow)instr.Arguments.ObjValue); CLRTypeSpec fieldValueSpec = field.Type; midInstrs.Add(new MidInstruction(MidInstruction.OpcodeEnum.StoreStaticField, codeLocation, valueReg, field.DeclaredInClassSpec, fieldValueSpec, field.Name)); midInstrs.Add(new MidInstruction(MidInstruction.OpcodeEnum.KillReg, codeLocation, valueReg)); } break; case CLR.CIL.HLOpcode.ldstr: { SsaRegister constReg = SsaRegister.Constant(new VType(VType.ValTypeEnum.ConstantReference, m_commonTypeLookup.String, instr.Arguments.ObjValue)); midInstrs.Add(new MidInstruction(MidInstruction.OpcodeEnum.LivenReg, codeLocation, constReg)); stackTracker.Push(constReg); } break; case CLR.CIL.HLOpcode.add: // [.ovf][.un] case CLR.CIL.HLOpcode.sub: // [.ovf][.un] case CLR.CIL.HLOpcode.mul: // [.ovf][.un] case CLR.CIL.HLOpcode.div: // [.ovf][.un] case CLR.CIL.HLOpcode.rem: // [.ovf][.un] case CLR.CIL.HLOpcode.and: case CLR.CIL.HLOpcode.or: case CLR.CIL.HLOpcode.xor: { SsaRegister value2 = stackTracker.Pop(); SsaRegister value1 = stackTracker.Pop(); CLRTypeSpec promoted1 = ArithPromoteValue(value1.VType.TypeSpec); CLRTypeSpec promoted2 = ArithPromoteValue(value2.VType.TypeSpec); MidInstruction.ArithEnum arithMode = ArithModeForBinaryNumericOp(m_commonTypeLookup, promoted1, promoted2); if ((instr.Flags & CLR.CIL.HLOpFlags.Ovf) != 0) arithMode |= MidInstruction.ArithEnum.Flags_Ovf; if ((instr.Flags & CLR.CIL.HLOpFlags.Un) != 0) arithMode |= MidInstruction.ArithEnum.Flags_Un; CLRTypeSpec resultType = TypeSpecForArithModeResult(arithMode); SsaRegister resultReg = stackTracker.NewReg(new VType(VType.ValTypeEnum.ValueValue, resultType)); midInstrs.Add(new MidInstruction(MidInstruction.OpcodeEnum.LivenReg, codeLocation, resultReg)); midInstrs.Add(new MidInstruction(SimpleTranslateInstr(instr.Opcode), codeLocation, value1, value2, resultReg, arithMode)); midInstrs.Add(new MidInstruction(MidInstruction.OpcodeEnum.KillReg, codeLocation, value2)); midInstrs.Add(new MidInstruction(MidInstruction.OpcodeEnum.KillReg, codeLocation, value1)); stackTracker.Push(resultReg); } break; case CLR.CIL.HLOpcode.shl: case CLR.CIL.HLOpcode.shr: // [.un] { SsaRegister value2 = stackTracker.Pop(); SsaRegister value1 = stackTracker.Pop(); CLRTypeSpec promoted1 = ArithPromoteValue(value1.VType.TypeSpec); CLRTypeSpec promoted2 = ArithPromoteValue(value2.VType.TypeSpec); MidInstruction.ArithEnum arithMode = ArithModeForShiftOp(m_commonTypeLookup, promoted1, promoted2); if ((instr.Flags & CLR.CIL.HLOpFlags.Un) != 0) arithMode |= MidInstruction.ArithEnum.Flags_Un; CLRTypeSpec resultType = TypeSpecForArithModeResult(arithMode); SsaRegister resultReg = stackTracker.NewReg(new VType(VType.ValTypeEnum.ValueValue, resultType)); midInstrs.Add(new MidInstruction(MidInstruction.OpcodeEnum.LivenReg, codeLocation, resultReg)); midInstrs.Add(new MidInstruction(SimpleTranslateInstr(instr.Opcode), codeLocation, value1, value2, resultReg, arithMode)); midInstrs.Add(new MidInstruction(MidInstruction.OpcodeEnum.KillReg, codeLocation, value2)); midInstrs.Add(new MidInstruction(MidInstruction.OpcodeEnum.KillReg, codeLocation, value1)); stackTracker.Push(resultReg); } break; case CLR.CIL.HLOpcode.neg: case CLR.CIL.HLOpcode.not: { SsaRegister v = stackTracker.Pop(); CLRTypeSpec promoted = ArithPromoteValue(v.VType.TypeSpec); MidInstruction.ArithEnum arithMode = ArithModeForUnaryOp(promoted); CLRTypeSpec resultType = TypeSpecForArithModeResult(arithMode); SsaRegister resultReg = stackTracker.NewReg(new VType(VType.ValTypeEnum.ValueValue, resultType)); midInstrs.Add(new MidInstruction(MidInstruction.OpcodeEnum.LivenReg, codeLocation, resultReg)); midInstrs.Add(new MidInstruction(SimpleTranslateInstr(instr.Opcode), codeLocation, v, resultReg, arithMode)); midInstrs.Add(new MidInstruction(MidInstruction.OpcodeEnum.KillReg, codeLocation, v)); stackTracker.Push(resultReg); } break; case CLR.CIL.HLOpcode.isinst: { CLRTypeSpec type = m_cppBuilder.Assemblies.InternTypeDefOrRefOrSpec((CLRTableRow)instr.Arguments.ObjValue); SsaRegister inputReg = stackTracker.Pop(); SsaRegister resultReg = stackTracker.NewReg(new VType(VType.ValTypeEnum.ReferenceValue, type)); midInstrs.Add(new MidInstruction(MidInstruction.OpcodeEnum.LivenReg, codeLocation, resultReg)); midInstrs.Add(new MidInstruction(MidInstruction.OpcodeEnum.TryConvertObj, codeLocation, inputReg, resultReg)); midInstrs.Add(new MidInstruction(MidInstruction.OpcodeEnum.KillReg, codeLocation, inputReg)); stackTracker.Push(resultReg); } break; case CLR.CIL.HLOpcode.castclass: { CLRTypeSpec type = m_cppBuilder.Assemblies.InternTypeDefOrRefOrSpec((CLRTableRow)instr.Arguments.ObjValue); SsaRegister inputReg = stackTracker.Pop(); SsaRegister resultReg = stackTracker.NewReg(new VType(VType.ValTypeEnum.ReferenceValue, type)); midInstrs.Add(new MidInstruction(MidInstruction.OpcodeEnum.LivenReg, codeLocation, resultReg)); midInstrs.Add(new MidInstruction(MidInstruction.OpcodeEnum.ConvertObj, codeLocation, inputReg, resultReg)); midInstrs.Add(new MidInstruction(MidInstruction.OpcodeEnum.KillReg, codeLocation, inputReg)); stackTracker.Push(resultReg); } break; case CLR.CIL.HLOpcode.dup: { SsaRegister top = stackTracker.GetFromTop(0); SsaRegister duplicate = stackTracker.NewReg(top.VType); // WARNING: If you update this sequence, you must update ldvirtftn too! midInstrs.Add(new MidInstruction(MidInstruction.OpcodeEnum.LivenReg, codeLocation, duplicate)); midInstrs.Add(new MidInstruction(MidInstruction.OpcodeEnum.DuplicateReg, codeLocation, top, duplicate)); stackTracker.Push(duplicate); } break; case CLR.CIL.HLOpcode.ldind: // (.type) case CLR.CIL.HLOpcode.ldobj: { SsaRegister addr = stackTracker.Pop(); if (addr.VType.ValType != VType.ValTypeEnum.ManagedPtr) throw new ArgumentException(); SsaRegister val = stackTracker.NewReg(new VType(CppCilExporter.ValTypeForTypeSpec(m_cppBuilder, addr.VType.TypeSpec), addr.VType.TypeSpec)); midInstrs.Add(new MidInstruction(MidInstruction.OpcodeEnum.LivenReg, codeLocation, val)); midInstrs.Add(new MidInstruction(MidInstruction.OpcodeEnum.LoadIndirect, codeLocation, addr, val)); midInstrs.Add(new MidInstruction(MidInstruction.OpcodeEnum.KillReg, codeLocation, addr)); stackTracker.Push(val); } break; case CLR.CIL.HLOpcode.stind: // (.type) case CLR.CIL.HLOpcode.stobj: { SsaRegister val = stackTracker.Pop(); SsaRegister addr = stackTracker.Pop(); if (addr.VType.ValType != VType.ValTypeEnum.ManagedPtr) throw new ArgumentException(); midInstrs.Add(new MidInstruction(MidInstruction.OpcodeEnum.StoreIndirect, codeLocation, addr, val)); midInstrs.Add(new MidInstruction(MidInstruction.OpcodeEnum.KillReg, codeLocation, val)); midInstrs.Add(new MidInstruction(MidInstruction.OpcodeEnum.KillReg, codeLocation, addr)); } break; case CLR.CIL.HLOpcode.pop: { SsaRegister val = stackTracker.Pop(); midInstrs.Add(new MidInstruction(MidInstruction.OpcodeEnum.KillReg, codeLocation, val)); } break; case CLR.CIL.HLOpcode.box: { CLRTableRow typeTok = (CLRTableRow)instr.Arguments.ObjValue; stackTracker.SpillStack(); SsaRegister val = stackTracker.Pop(); if (val.VType.ValType != VType.ValTypeEnum.ConstantValue && val.VType.ValType != VType.ValTypeEnum.ValueValue) throw new ArgumentException(); CLRTypeSpec valueTypeSpec = val.VType.TypeSpec; if (valueTypeSpec is CLRTypeSpecGenericInstantiation) { CLRTypeSpecGenericInstantiation valueGI = (CLRTypeSpecGenericInstantiation)valueTypeSpec; CLRTypeSpecClass valueGIClass = valueGI.GenericType; CLRTypeDefRow typeDef = valueGIClass.TypeDef; if (typeDef.ContainerClass == null && typeDef.TypeNamespace == "System" && typeDef.TypeName == "Nullable`1") valueTypeSpec = valueGI.ArgTypes[0]; } SsaRegister boxed = stackTracker.NewReg(new VType(VType.ValTypeEnum.ReferenceValue, val.VType.TypeSpec)); midInstrs.Add(new MidInstruction(MidInstruction.OpcodeEnum.LivenReg, codeLocation, boxed)); midInstrs.Add(new MidInstruction(MidInstruction.OpcodeEnum.Box, codeLocation, val, boxed)); midInstrs.Add(new MidInstruction(MidInstruction.OpcodeEnum.KillReg, codeLocation, val)); stackTracker.Push(boxed); } break; case CLR.CIL.HLOpcode.conv: // [.ovf](.type)[.un] { CLRTypeSpec destType; MidInstruction.ArithEnum arithMode; switch (instr.TypeToken) { case CLR.CIL.HLOpType.I1: destType = m_commonTypeLookup.I8; arithMode = MidInstruction.ArithEnum.ArithType_Int32; break; case CLR.CIL.HLOpType.I2: destType = m_commonTypeLookup.I16; arithMode = MidInstruction.ArithEnum.ArithType_Int32; break; case CLR.CIL.HLOpType.I4: destType = m_commonTypeLookup.I32; arithMode = MidInstruction.ArithEnum.ArithType_Int32; break; case CLR.CIL.HLOpType.I8: destType = m_commonTypeLookup.I64; arithMode = MidInstruction.ArithEnum.ArithType_Int64; break; case CLR.CIL.HLOpType.U1: destType = m_commonTypeLookup.U8; arithMode = MidInstruction.ArithEnum.ArithType_Int32; break; case CLR.CIL.HLOpType.U2: destType = m_commonTypeLookup.U16; arithMode = MidInstruction.ArithEnum.ArithType_Int32; break; case CLR.CIL.HLOpType.U4: destType = m_commonTypeLookup.U32; arithMode = MidInstruction.ArithEnum.ArithType_Int32; break; case CLR.CIL.HLOpType.U8: destType = m_commonTypeLookup.U64; arithMode = MidInstruction.ArithEnum.ArithType_Int64; break; case CLR.CIL.HLOpType.R4: destType = m_commonTypeLookup.F32; arithMode = MidInstruction.ArithEnum.ArithType_Float32; break; case CLR.CIL.HLOpType.R: // Used by conv.r.un case CLR.CIL.HLOpType.R8: destType = m_commonTypeLookup.F64; arithMode = MidInstruction.ArithEnum.ArithType_Float64; break; case CLR.CIL.HLOpType.I: destType = m_commonTypeLookup.I; arithMode = MidInstruction.ArithEnum.ArithType_NativeInt; break; case CLR.CIL.HLOpType.U: destType = m_commonTypeLookup.U; arithMode = MidInstruction.ArithEnum.ArithType_NativeInt; break; default: throw new ArgumentException(); } if ((instr.Flags & CLR.CIL.HLOpFlags.Ovf) != 0) arithMode |= MidInstruction.ArithEnum.Flags_Ovf; if ((instr.Flags & CLR.CIL.HLOpFlags.Un) != 0) arithMode |= MidInstruction.ArithEnum.Flags_Un; SsaRegister srcReg = stackTracker.Pop(); SsaRegister destReg = stackTracker.NewReg(new VType(VType.ValTypeEnum.ValueValue, destType)); midInstrs.Add(new MidInstruction(MidInstruction.OpcodeEnum.LivenReg, codeLocation, destReg)); midInstrs.Add(new MidInstruction(MidInstruction.OpcodeEnum.ConvertNumber, codeLocation, srcReg, destReg, arithMode)); midInstrs.Add(new MidInstruction(MidInstruction.OpcodeEnum.KillReg, codeLocation, srcReg)); stackTracker.Push(destReg); } break; case CLR.CIL.HLOpcode.ldlen: { SsaRegister arrayReg = stackTracker.Pop(); SsaRegister resultReg = stackTracker.NewReg(new VType(VType.ValTypeEnum.ValueValue, m_commonTypeLookup.U)); midInstrs.Add(new MidInstruction(MidInstruction.OpcodeEnum.LivenReg, codeLocation, resultReg)); midInstrs.Add(new MidInstruction(MidInstruction.OpcodeEnum.LoadArrayLength, codeLocation, arrayReg, resultReg)); midInstrs.Add(new MidInstruction(MidInstruction.OpcodeEnum.KillReg, codeLocation, arrayReg)); stackTracker.Push(resultReg); } break; case CLR.CIL.HLOpcode.ldtoken: { CLRTableRow tokenRow = (CLRTableRow)instr.Arguments.ObjValue; CLRTypeSpec typeResolution = null; CppMethodSpec methodResolution = null; CppField fieldResolution = null; if (tokenRow is CLRTypeRefRow || tokenRow is CLRTypeDefRow || tokenRow is CLRTypeSpecRow) typeResolution = m_cppBuilder.Assemblies.InternTypeDefOrRefOrSpec(tokenRow); else if (tokenRow is CLRMemberRefRow) { CLRMemberRefRow memberRef = (CLRMemberRefRow)tokenRow; if (memberRef.FieldSig != null) fieldResolution = ResolveField(memberRef); else if (memberRef.MethodSig != null) methodResolution = CppBuilder.ResolveMethodDefOrRef(memberRef); else throw new ArgumentException(); } else if (tokenRow is CLRMethodDefRow) methodResolution = CppBuilder.ResolveMethodDefOrRef(tokenRow); else if (tokenRow is CLRFieldRow) fieldResolution = ResolveField(tokenRow); else throw new ArgumentException(); if (typeResolution != null) { CLRTypeSpec rtDefSpec = m_cppBuilder.Assemblies.InternTypeDefOrRefOrSpec(m_cppBuilder.Assemblies.RuntimeTypeHandleDef); SsaRegister reg = stackTracker.NewReg(new VType(VType.ValTypeEnum.ValueValue, rtDefSpec)); midInstrs.Add(new MidInstruction(MidInstruction.OpcodeEnum.LivenReg, codeLocation, reg)); midInstrs.Add(new MidInstruction(MidInstruction.OpcodeEnum.LoadTypeInfoHandle, codeLocation, reg, typeResolution)); stackTracker.Push(reg); } if (methodResolution != null) { // TODO: nameof support throw new NotImplementedException(); } if (fieldResolution != null) { // Necessary for nameof and static field InitializeArray CLRTypeSpec containerClassSpec = fieldResolution.DeclaredInClassSpec; string fieldName = fieldResolution.Name; CLRTypeSpec fldDefSpec = m_cppBuilder.Assemblies.InternTypeDefOrRefOrSpec(m_cppBuilder.Assemblies.RuntimeFieldHandleDef); SsaRegister reg = stackTracker.NewReg(new VType(VType.ValTypeEnum.ValueValue, fldDefSpec)); midInstrs.Add(new MidInstruction(MidInstruction.OpcodeEnum.LivenReg, codeLocation, reg)); midInstrs.Add(new MidInstruction(MidInstruction.OpcodeEnum.LoadFieldInfoHandle, codeLocation, reg, containerClassSpec, fieldName, fieldResolution.Field.Static)); stackTracker.Push(reg); } } break; case CLR.CIL.HLOpcode.@switch: { SsaRegister valueReg = stackTracker.Pop(); List<CfgOutboundEdge> targetOutboundEdges = new List<CfgOutboundEdge>(); CfgOutboundEdgePrototype cfgEdgeProto = stackTracker.GenerateCfgEdge(); foreach (uint targetInstr in (uint[])instr.Arguments.ObjValue) { CfgNode targetNode = cfgBuilder.AddCfgTarget(this, (int)targetInstr, cfgEdgeProto.OutboundTypes); targetOutboundEdges.Add(new CfgOutboundEdge(codeLocation, targetNode, cfgEdgeProto)); } CfgNode fallThroughNode = cfgBuilder.AddCfgTarget(this, nextInstr, cfgEdgeProto.OutboundTypes); midInstrs.Add(new MidInstruction(MidInstruction.OpcodeEnum.Switch, codeLocation, valueReg, targetOutboundEdges.ToArray())); midInstrs.Add(new MidInstruction(MidInstruction.OpcodeEnum.KillReg, codeLocation, valueReg)); OutputFallThroughEdge = new CfgOutboundEdge(codeLocation, fallThroughNode, cfgEdgeProto); isTerminalEdge = true; } break; case CLR.CIL.HLOpcode.unbox: { CLRTypeSpec typeTok = m_cppBuilder.Assemblies.InternTypeDefOrRefOrSpec((CLRTableRow)instr.Arguments.ObjValue); SsaRegister objReg = stackTracker.Pop(); SsaRegister valueReg = stackTracker.NewReg(new VType(VType.ValTypeEnum.ManagedPtr, typeTok)); midInstrs.Add(new MidInstruction(MidInstruction.OpcodeEnum.LivenReg, codeLocation, valueReg)); midInstrs.Add(new MidInstruction(MidInstruction.OpcodeEnum.UnboxPtr, codeLocation, objReg, valueReg)); midInstrs.Add(new MidInstruction(MidInstruction.OpcodeEnum.KillReg, codeLocation, objReg)); stackTracker.Push(valueReg); } break; case CLR.CIL.HLOpcode.unbox_any: { CLRTypeSpec typeTok = m_cppBuilder.Assemblies.InternTypeDefOrRefOrSpec((CLRTableRow)instr.Arguments.ObjValue); SsaRegister objReg = stackTracker.Pop(); SsaRegister valueReg = stackTracker.NewReg(new VType(VType.ValTypeEnum.ValueValue, typeTok)); midInstrs.Add(new MidInstruction(MidInstruction.OpcodeEnum.LivenReg, codeLocation, valueReg)); midInstrs.Add(new MidInstruction(MidInstruction.OpcodeEnum.UnboxValue, codeLocation, objReg, valueReg)); midInstrs.Add(new MidInstruction(MidInstruction.OpcodeEnum.KillReg, codeLocation, objReg)); stackTracker.Push(valueReg); } break; case CLR.CIL.HLOpcode.initobj: { SsaRegister objLoc = stackTracker.Pop(); midInstrs.Add(new MidInstruction(MidInstruction.OpcodeEnum.ZeroFillPtr, codeLocation, objLoc)); midInstrs.Add(new MidInstruction(MidInstruction.OpcodeEnum.KillReg, codeLocation, objLoc)); } break; case CLR.CIL.HLOpcode.ldftn: { CppMethodSpec boundMethodSpec = CppBuilder.ResolveMethodDefOrRef((CLRTableRow)instr.Arguments.ObjValue); SsaRegister ftnReg = SsaRegister.Constant(new VType(VType.ValTypeEnum.DelegateSimpleMethod, null, boundMethodSpec)); midInstrs.Add(new MidInstruction(MidInstruction.OpcodeEnum.LivenReg, codeLocation, ftnReg)); stackTracker.Push(ftnReg); } break; case CLR.CIL.HLOpcode.ldvirtftn: { SsaRegister throwawayObjReg = stackTracker.Pop(); CppMethodSpec boundVirtMethod = CppBuilder.ResolveMethodDefOrRef((CLRTableRow)instr.Arguments.ObjValue); SsaRegister ftnReg = SsaRegister.Constant(new VType(VType.ValTypeEnum.DelegateVirtualMethod, null, boundVirtMethod)); stackTracker.Push(ftnReg); // This reverses the preceding dup sequence if (cilMethod.Instructions[instrNum - 1].Opcode != CLR.CIL.HLOpcode.dup || firstInstr == instrNum) throw new ArgumentException(); // WARNING: This must be kept in sync with dup! midInstrs.RemoveRange(midInstrs.Count - 2, 2); midInstrs.Add(new MidInstruction(MidInstruction.OpcodeEnum.LivenReg, codeLocation, ftnReg)); } break; case CLR.CIL.HLOpcode.endfinally: { midInstrs.Add(new MidInstruction(MidInstruction.OpcodeEnum.ExitFinally, codeLocation)); while (stackTracker.Depth > 0) midInstrs.Add(new MidInstruction(MidInstruction.OpcodeEnum.KillReg, codeLocation, stackTracker.Pop())); isTerminalEdge = true; } break; case CLR.CIL.HLOpcode.constrained_pfx: case CLR.CIL.HLOpcode.readonly_pfx: break; case CLR.CIL.HLOpcode.jmp: case CLR.CIL.HLOpcode.calli: case CLR.CIL.HLOpcode.@break: case CLR.CIL.HLOpcode.cpobj: case CLR.CIL.HLOpcode.refanyval: case CLR.CIL.HLOpcode.ckfinite: case CLR.CIL.HLOpcode.mkrefany: case CLR.CIL.HLOpcode.arglist: case CLR.CIL.HLOpcode.localloc: case CLR.CIL.HLOpcode.endfilter: case CLR.CIL.HLOpcode.unaligned_pfx: case CLR.CIL.HLOpcode.volatile_pfx: case CLR.CIL.HLOpcode.tail_pfx: case CLR.CIL.HLOpcode.cpblk: case CLR.CIL.HLOpcode.initblk: case CLR.CIL.HLOpcode.no_pfx: case CLR.CIL.HLOpcode.rethrow: case CLR.CIL.HLOpcode.@sizeof: case CLR.CIL.HLOpcode.refanytype: throw new NotImplementedException("Unimplemented opcode: " + instr.Opcode.ToString()); break; } } // Post-terminal-edge cleanup // Leak any registers alive past the terminal edge while (stackTracker.Depth > 0) midInstrs.Add(new MidInstruction(MidInstruction.OpcodeEnum.LeakReg, codeLocation, stackTracker.Pop())); OutputInstructions = midInstrs.ToArray(); }
public MidInstruction(OpcodeEnum opcode, CodeLocationTag codeLocation, SsaRegister regArg, SsaRegister regArg2, CfgOutboundEdge cfgEdgeArg, bool flagArg) { Opcode = opcode; CodeLocation = codeLocation; RegArg = regArg; RegArg2 = regArg2; CfgEdgeArg = cfgEdgeArg; FlagArg = flagArg; }
public CfgNodeEdge(SsaRegister[] regs) { Registers = regs; }
public void AddRegister(SsaRegister reg) { m_ssaRegisterLookup[reg] = m_ssaRegisters.Count; m_ssaRegisters.Add(reg); }
public MidInstruction(OpcodeEnum opcode, CodeLocationTag codeLocation, SsaRegister regArg, SsaRegister regArg2, ArithEnum arithArg) { Opcode = opcode; CodeLocation = codeLocation; RegArg = regArg; RegArg2 = regArg2; ArithArg = arithArg; }
private Clarity.Rpa.HighSsaRegister InternSsaRegister(SsaRegister ssaRegister) { if (ssaRegister == null) return null; Clarity.Rpa.HighSsaRegister highSsa; if (!m_ssaToEmittedSsa.TryGetValue(ssaRegister, out highSsa)) { Clarity.Rpa.HighValueType valType; object constValue = null; switch (ssaRegister.VType.ValType) { case VType.ValTypeEnum.ManagedPtr: valType = Clarity.Rpa.HighValueType.ManagedPtr; break; case VType.ValTypeEnum.ConstantValue: constValue = ssaRegister.ConstantValue; valType = Clarity.Rpa.HighValueType.ConstantValue; break; case VType.ValTypeEnum.ConstantReference: constValue = ssaRegister.ConstantValue; valType = Clarity.Rpa.HighValueType.ConstantString; break; case VType.ValTypeEnum.ReferenceValue: valType = Clarity.Rpa.HighValueType.ReferenceValue; break; case VType.ValTypeEnum.Null: valType = Clarity.Rpa.HighValueType.Null; break; case VType.ValTypeEnum.ValueValue: valType = Clarity.Rpa.HighValueType.ValueValue; break; default: throw new ArgumentException(); } highSsa = new Clarity.Rpa.HighSsaRegister(valType, RpaTagFactory.CreateTypeTag(ssaRegister.VType.TypeSpec), constValue); m_ssaToEmittedSsa.Add(ssaRegister, highSsa); } return highSsa; }
public Entry(SsaRegister reg) { m_isAlive = true; m_reg = reg; }
public void Push(SsaRegister instanceReg) { m_regs.Add(instanceReg); }
public MidInstruction(OpcodeEnum opcode, CodeLocationTag codeLocation, SsaRegister regArg, uint uintArg) { Opcode = opcode; CodeLocation = codeLocation; RegArg = regArg; UIntArg = uintArg; }
private SsaRegister EmitPassiveConversion(Clarity.Rpa.CodeLocationTag codeLocation, SsaRegister sourceReg, CLRTypeSpec destType, CppCfgNodeOutline outline, IList<Clarity.Rpa.HighInstruction> instrs) { if (sourceReg.VType.ValType == VType.ValTypeEnum.DelegateSimpleMethod || sourceReg.VType.ValType == VType.ValTypeEnum.DelegateVirtualMethod) return sourceReg; if (sourceReg.VType.TypeSpec.Equals(destType)) return sourceReg; if (sourceReg.VType.ValType == VType.ValTypeEnum.Null) { SsaRegister nullReg = new SsaRegister(new VType(VType.ValTypeEnum.Null, destType)); nullReg.MakeUsable(); nullReg.GenerateUniqueID(m_regAllocator); outline.AddRegister(nullReg); return nullReg; } SsaRegister newReg; switch (sourceReg.VType.ValType) { case VType.ValTypeEnum.ConstantReference: case VType.ValTypeEnum.ReferenceValue: newReg = new SsaRegister(new VType(VType.ValTypeEnum.ReferenceValue, destType)); break; case VType.ValTypeEnum.ValueValue: case VType.ValTypeEnum.ConstantValue: newReg = new SsaRegister(new VType(VType.ValTypeEnum.ValueValue, destType)); break; default: throw new ArgumentException(); } newReg.MakeUsable(); newReg.GenerateUniqueID(m_regAllocator); instrs.Add(new Clarity.Rpa.Instructions.PassiveConvertInstruction( codeLocation, InternSsaRegister(newReg), InternSsaRegister(sourceReg) )); return newReg; }
private CLR.CLRTypeSpec StackTypeSpecForSsaReg(SsaRegister regA, bool isUnsigned) { NumericStackType stackTypeA = StackTypeForTypeSpec(regA.VType.TypeSpec); CLR.CLRSigType.ElementType elementType; switch (stackTypeA) { case NumericStackType.Float32: elementType = CLR.CLRSigType.ElementType.R4; break; case NumericStackType.Float64: elementType = CLR.CLRSigType.ElementType.R8; break; case NumericStackType.Int32: elementType = isUnsigned ? CLR.CLRSigType.ElementType.U4 : CLR.CLRSigType.ElementType.I4; break; case NumericStackType.Int64: elementType = isUnsigned ? CLR.CLRSigType.ElementType.U8 : CLR.CLRSigType.ElementType.I8; break; case NumericStackType.NativeInt: elementType = isUnsigned ? CLR.CLRSigType.ElementType.U : CLR.CLRSigType.ElementType.I; break; default: throw new ArgumentException(); } return m_builder.Assemblies.InternVagueType(new CLR.CLRSigTypeSimple(elementType)); }
private SsaRegister EmitPassiveConversion_PermitRefs(Clarity.Rpa.CodeLocationTag codeLocation, SsaRegister sourceReg, CLRTypeSpec destType, CppCfgNodeOutline outline, IList<Clarity.Rpa.HighInstruction> instrs) { switch (sourceReg.VType.ValType) { case VType.ValTypeEnum.ManagedPtr: if (sourceReg.VType.TypeSpec.Equals(destType)) return sourceReg; throw new ArgumentException(); default: return EmitPassiveConversion(codeLocation, sourceReg, destType, outline, instrs); } }
public SsaVRegMapping(SsaRegister ssaReg, VReg vReg) { m_ssaReg = ssaReg; m_vReg = vReg; }
private NumericStackType NumericStackTypeForNumericBinaryOp(SsaRegister regA, SsaRegister regB) { // III.1.5 table III.4 NumericStackType stackTypeA = StackTypeForTypeSpec(regA.VType.TypeSpec); NumericStackType stackTypeB = StackTypeForTypeSpec(regB.VType.TypeSpec); NumericStackType combinedType; if (stackTypeA == NumericStackType.Int32) { if (stackTypeB == NumericStackType.NativeInt) combinedType = NumericStackType.NativeInt; else if (stackTypeB == NumericStackType.Int32) combinedType = NumericStackType.Int32; else throw new Exception("Unexpected binary numeric operation operands"); } else if (stackTypeA == NumericStackType.Int64) { if (stackTypeB == NumericStackType.Int64) combinedType = NumericStackType.Int64; else throw new Exception("Unexpected binary numeric operation operands"); } else if (stackTypeA == NumericStackType.NativeInt) { if (stackTypeB == NumericStackType.NativeInt || stackTypeB == NumericStackType.Int32) combinedType = NumericStackType.NativeInt; else throw new Exception("Unexpected binary numeric operation operands"); } else if (stackTypeB == NumericStackType.Float32) { if (stackTypeB == NumericStackType.Float32) combinedType = NumericStackType.Float32; else if (stackTypeB == NumericStackType.Float64) combinedType = NumericStackType.Float32; else throw new Exception("Unexpected binary numeric operation operands"); } else if (stackTypeA == NumericStackType.Float64) { if (stackTypeB == NumericStackType.Float32 || stackTypeB == NumericStackType.Float64) combinedType = NumericStackType.Float64; else throw new Exception("Unexpected binary numeric operation operands"); } else throw new Exception("Unexpected binary numeric operation operands"); return combinedType; }
public MidInstruction(OpcodeEnum opcode, CodeLocationTag codeLocation, SsaRegister regArg, SsaRegister regArg2, SsaRegister regArg3, bool flagArg) { Opcode = opcode; CodeLocation = codeLocation; RegArg = regArg; RegArg2 = regArg2; RegArg3 = regArg3; FlagArg = FlagArg; }
private CLR.CLRTypeSpec TypeSpecForNumericBinaryOp(SsaRegister regA, SsaRegister regB, bool isUnsigned) { return TypeSpecForNumericStackType(NumericStackTypeForNumericBinaryOp(regA, regB), isUnsigned); }
public void RecycleReg(SsaRegister reg) { AddReg(reg); }
private void AliasSsaRegister(Clarity.Rpa.HighSsaRegister src, SsaRegister copy) { if (m_ssaToEmittedSsa.ContainsKey(copy)) throw new Exception(); m_ssaToEmittedSsa.Add(copy, src); }
private static bool IsRegScopable(SsaRegister reg) { if (reg.IsSpilled) return false; return CppRegisterAllocator.IsVTypeSpillable(reg.VType); }
public int GetRegisterID(SsaRegister reg) { return m_ssaRegisterLookup[reg]; }
private void AddReg(SsaRegister reg) { m_regStack.Push(new Entry(reg)); m_indent += "\t"; }
public CfgOutboundEdgePrototype(VType[] outboundTypes, SsaRegister[] outboundRegs) { m_outboundRegs = outboundRegs; m_outboundTypes = outboundTypes; }
public MidInstruction(OpcodeEnum opcode, CodeLocationTag codeLocation, CppMethodSpec methodSpecArg, CLRTypeSpec typeSpecArg, SsaRegister regArg, SsaRegister regArg2, SsaRegister[] regArgs) { Opcode = opcode; CodeLocation = codeLocation; TypeSpecArg = typeSpecArg; MethodSpecArg = methodSpecArg; RegArg = regArg; RegArg2 = regArg2; RegArgs = regArgs; }