public HighMethodBody(HighRegion region, HighLocal instanceLocal, HighLocal[] args, HighLocal[] locals, bool haveDebugInfo) { m_region = region; m_instanceLocal = instanceLocal; m_args = args; m_locals = locals; m_haveDebugInfo = haveDebugInfo; }
public RloMethodBody(HighLocal instanceLocal, HighLocal[] args, HighLocal[] locals, TypeSpecTag returnType, HighRegion entryRegion, MethodSignatureTag methodSignature, MethodInstantiationPath instPath) { m_instanceLocal = instanceLocal; m_args = args; m_locals = locals; m_returnType = returnType; m_entryRegion = entryRegion; m_instantiationPath = instPath; m_methodSignature = methodSignature; }
public override RloMethod GenerateMethod(Compiler compiler, MethodInstantiationPath instantiationPath) { HighLocal[] args = new HighLocal[0]; HighLocal[] locals = new HighLocal[0]; HighLocal instanceLocal = new HighLocal(m_dt, HighLocal.ETypeOfType.Value); TypeSpecClassTag delegateClass = m_dt.DelegateType; TypeSpecMulticastDelegateTag mdgSpec = new TypeSpecMulticastDelegateTag(delegateClass); mdgSpec = (TypeSpecMulticastDelegateTag)compiler.TagRepository.InternTypeSpec(mdgSpec); TypeSpecTag delegateType = m_vtCache.GetSystemDelegateType(compiler); HighSsaRegister thisRef = new HighSsaRegister(HighValueType.ReferenceValue, m_dt, null); HighSsaRegister result = new HighSsaRegister(HighValueType.ReferenceValue, mdgSpec, null); HighSsaRegister convertedResult = new HighSsaRegister(HighValueType.ReferenceValue, delegateType, null); MethodSignatureTag methodSignature = new MethodSignatureTag(0, delegateType, new MethodSignatureParam[0]); methodSignature = compiler.TagRepository.InternMethodSignature(methodSignature); HighCfgNodeHandle entryHdl = new HighCfgNodeHandle(); HighCfgNodeHandle returnResultHdl = new HighCfgNodeHandle(); { List<HighInstruction> instrs = new List<HighInstruction>(); instrs.Add(new Rpa.Instructions.LoadLocalInstruction(null, thisRef, instanceLocal)); Instructions.ConvertDelegateToMulticastInstruction convertInstr = new Instructions.ConvertDelegateToMulticastInstruction(null, result, thisRef, mdgSpec); convertInstr.ContinuationEdge = new HighCfgEdge(convertInstr, returnResultHdl); instrs.Add(convertInstr); entryHdl.Value = new HighCfgNode(instrs.ToArray()); } { List<HighInstruction> instrs = new List<HighInstruction>(); instrs.Add(new Instructions.ObjectToObjectInstruction(null, convertedResult, result)); instrs.Add(new Rpa.Instructions.ReturnValueInstruction(null, convertedResult)); returnResultHdl.Value = new HighCfgNode(instrs.ToArray()); } compiler.GetRloVTable(mdgSpec, instantiationPath); HighRegion region = new HighRegion(entryHdl); RloMethodBody methodBody = new RloMethodBody(instanceLocal, args, locals, m_vtCache.GetSystemDelegateType(compiler), region, methodSignature, instantiationPath); return new RloMethod(methodBody); }
public RloRegionConverter(RloMethodConverter methodConverter, HighRegion region, bool checkInstructions) { m_ssaTranslate = TranslateSSA; m_localTranslate = TranslateLocal; m_cfgNodeTranslate = TranslateCfgNode; m_cfgEdgeTranslate = TranslateCfgEdge; m_typeSpecTranslate = TranslateTypeSpec; m_methodSpecTranslate = TranslateMethodSpec; m_methodConverter = methodConverter; m_checkInstructions = checkInstructions; m_entryNode = GetNode(region.EntryNode.Value); while (m_unconvertedNodes.Count > 0) { KeyValuePair<HighCfgNode, HighCfgNodeHandle> workItem = m_unconvertedNodes.Dequeue(); ConvertNode(workItem.Key, workItem.Value); } }
protected override void ReadHandlers(TagRepository rpa, CatalogReader catalog, HighMethodBodyParseContext methodBody, CodeLocationTag baseLocation, bool haveDebugInfo, BinaryReader reader) { m_finallyRegion = HighRegion.Read(rpa, catalog, methodBody, baseLocation, haveDebugInfo, reader); }
public HighTryFinallyRegion(HighRegion tryRegion, HighRegion finallyRegion) : base(tryRegion) { m_finallyRegion = finallyRegion; }
public HighTryFinallyRegion(HighRegion tryRegion) : base(tryRegion) { }
public HighTryFaultRegion(HighRegion tryRegion, HighRegion faultRegion) : base(tryRegion) { m_faultRegion = faultRegion; }
private HighCfgNode ProcessSubRegion(HighRegion region, RegionStack regionStack, bool isTry) { HighCfgNode cfgNode = region.EntryNode.Value; RegionProcessor processor = new RegionProcessor(m_initPass, regionStack, isTry, false); processor.QueueNode(cfgNode); processor.Run(); return cfgNode; }
public HighTryCatchRegion(HighRegion tryRegion, HighCatchHandler[] catchHandlers) : base(tryRegion) { m_catchHandlers = catchHandlers; }
public void Read(TagRepository rpa, CatalogReader catalog, HighMethodBodyParseContext methodBody, CodeLocationTag baseLocation, bool haveDebugInfo, BinaryReader reader) { m_catchType = catalog.GetTypeSpec(reader.ReadUInt32()); m_region = HighRegion.Read(rpa, catalog, methodBody, baseLocation, haveDebugInfo, reader); }
public RloMethodBody(Compiler compiler, HighMethod method, MethodSpecTag methodSpec, TypeSpecClassTag thisType, bool isStruct, RloInstantiationParameters instParams, MethodInstantiationPath methodInstantiationPath) { m_instantiationPath = methodInstantiationPath; m_methodSpec = methodSpec; HighMethodBody methodBody = method.MethodBody; TagRepository tagRepo = compiler.TagRepository; // Validate locals uint numParamArgs = (uint)method.MethodSignature.ParamTypes.Length; if (method.IsStatic) { if (methodBody.InstanceLocal != null) throw new Exception("Instance local in static method"); } else { HighLocal thisLocal = methodBody.InstanceLocal; if (thisLocal == null) throw new Exception("Missing instance local in instance method"); HighLocal.ETypeOfType expectedTypeOfType = isStruct ? HighLocal.ETypeOfType.ByRef : HighLocal.ETypeOfType.Value; if (thisLocal.TypeOfType != expectedTypeOfType || thisLocal.Type.Instantiate(tagRepo, instParams.TypeParams, instParams.MethodParams) != thisType) throw new Exception("Invalid this type for method"); } if (numParamArgs != (uint)methodBody.Args.Length) throw new Exception("Mismatched argument count in method body and signature"); for (uint i = 0; i < numParamArgs; i++) { HighLocal bodyArg = methodBody.Args[i]; MethodSignatureParam methodSigParam = method.MethodSignature.ParamTypes[i]; MethodSignatureParamTypeOfType tot = methodSigParam.TypeOfType; HighLocal.ETypeOfType expectedTypeOfType; switch (tot.Value) { case MethodSignatureParamTypeOfType.Values.ByRef: expectedTypeOfType = HighLocal.ETypeOfType.ByRef; break; case MethodSignatureParamTypeOfType.Values.TypedByRef: expectedTypeOfType = HighLocal.ETypeOfType.TypedByRef; break; case MethodSignatureParamTypeOfType.Values.Value: expectedTypeOfType = HighLocal.ETypeOfType.Value; break; default: throw new ArgumentException(); } if (bodyArg.TypeOfType != expectedTypeOfType) throw new Exception("Method body arg doesn't match signature"); } HighLocal instanceLocal = methodBody.InstanceLocal; RloMethodConverter methodConverter = new RloMethodConverter(compiler.TagRepository, instParams, method.MethodSignature.RetType, instanceLocal, methodBody.Args, methodBody.Locals); RloRegionConverter regionConverter = new RloRegionConverter(methodConverter, methodBody.MainRegion, true); m_locals = methodConverter.Locals2; m_args = methodConverter.Args; m_instanceLocal = methodConverter.InstanceLocal; m_returnType = methodConverter.ReturnType; m_entryRegion = new HighRegion(regionConverter.EntryNode); m_methodSignature = method.MethodSignature; RloFindPredecessorsAndSuccessorsPass psPass = new RloFindPredecessorsAndSuccessorsPass(compiler, this); psPass.Run(); RloCanonicalizeSsaTypesPass cstPass = new RloCanonicalizeSsaTypesPass(compiler, this); cstPass.Run(); RloInitPass initPass = new RloInitPass(compiler, this, psPass); initPass.Run(); RloInitExceptionsPass exceptionInitPass = new RloInitExceptionsPass(compiler, this); exceptionInitPass.Run(); }
private HighProtectedRegion ConvertProtectedRegion(HighProtectedRegion oldProtRegion) { HighRegion oldTryRegion = oldProtRegion.TryRegion; HighCfgNodeHandle tryEntryNode = GetNode(oldTryRegion.EntryNode.Value); HighRegion newTryRegion = new HighRegion(tryEntryNode); HighTryCatchRegion tryCatchRegion = oldProtRegion as HighTryCatchRegion; if (tryCatchRegion != null) { List<HighCatchHandler> catchHandlers = new List<HighCatchHandler>(); foreach (HighCatchHandler catchHandler in tryCatchRegion.CatchHandlers) { TypeSpecTag catchType = m_methodConverter.InstantiateType(catchHandler.CatchType); HighRegion region = new HighRegion(GetNode(catchHandler.Region.EntryNode.Value)); catchHandlers.Add(new HighCatchHandler(catchType, region)); } return new HighTryCatchRegion(newTryRegion, catchHandlers.ToArray()); } HighTryFaultRegion tryFaultRegion = oldProtRegion as HighTryFaultRegion; if (tryFaultRegion != null) { HighRegion region = new HighRegion(GetNode(tryFaultRegion.FaultRegion.EntryNode.Value)); return new HighTryFaultRegion(newTryRegion, region); } HighTryFinallyRegion tryFinallyRegion = oldProtRegion as HighTryFinallyRegion; if (tryFinallyRegion != null) { HighRegion region = new HighRegion(GetNode(tryFinallyRegion.FinallyRegion.EntryNode.Value)); return new HighTryFinallyRegion(newTryRegion, region); } throw new Exception(); }
public override RloMethod GenerateMethod(Compiler compiler, MethodInstantiationPath instantiationPath) { TypeSpecDelegateTag delegateType = m_dt; TypeSpecClassTag delegateClassType = delegateType.DelegateType; MethodSpecTag methodSpec = delegateType.MethodSpec; TypeSpecClassTag targetType = methodSpec.DeclaringClass; CliClass delegateCls = compiler.GetClosedClass(delegateClassType); TypeNameTag delegateTypeName = delegateCls.TypeName; HighTypeDef delegateTypeDef = compiler.GetTypeDef(delegateTypeName); if (delegateTypeDef.Semantics != TypeSemantics.Delegate) throw new RpaCompileException("Delegate-bound class is not a delegate"); HighTypeDef targetTypeDef = compiler.GetTypeDef(targetType.TypeName); CliClass targetCls = null; CliInterface targetIfc = null; bool isInterface; switch (targetTypeDef.Semantics) { case TypeSemantics.Class: case TypeSemantics.Delegate: case TypeSemantics.Enum: case TypeSemantics.Struct: isInterface = false; targetCls = compiler.GetClosedClass(targetType); break; case TypeSemantics.Interface: isInterface = true; targetIfc = compiler.GetClosedInterface(targetType); break; default: throw new ArgumentException(); } MethodSignatureTag declSignature = delegateTypeDef.DelegateSignature; MethodDeclTag invokeDeclTag = new MethodDeclTag("Invoke", declSignature, delegateTypeName); invokeDeclTag = compiler.TagRepository.InternMethodDeclTag(invokeDeclTag); uint vtableSlotIndex = delegateCls.DeclTagToVTableSlot[invokeDeclTag]; CliVtableSlot vtableSlot = delegateCls.VTable[vtableSlotIndex]; MethodSignatureTag delegateMethodSignature = vtableSlot.MethodSignature; MethodSignatureTag targetMethodSignature; switch (methodSpec.MethodSlotType) { case MethodSlotType.Instance: case MethodSlotType.Static: { if (isInterface) throw new RpaCompileException("Wrong method spec type for interface"); HighMethod method = targetCls.Methods[targetCls.DeclTagToMethod[methodSpec.MethodDecl]]; targetMethodSignature = method.MethodSignature.Instantiate(compiler.TagRepository, methodSpec.DeclaringClass.ArgTypes, methodSpec.GenericParameters); } break; case MethodSlotType.Virtual: { if (isInterface) { HighClassVtableSlot vtSlot = targetIfc.Slots[targetIfc.CliSlotForSlotTag(methodSpec.MethodDecl)]; targetMethodSignature = vtSlot.Signature.Instantiate(compiler.TagRepository, methodSpec.DeclaringClass.ArgTypes, methodSpec.GenericParameters); } else { CliVtableSlot calledVtableSlot = targetCls.VTable[targetCls.DeclTagToVTableSlot[methodSpec.MethodDecl]]; if (calledVtableSlot.MethodSignature.NumGenericParameters > 0) throw new RpaCompileException("Can't generate delegate thunk to virtual generic"); targetMethodSignature = calledVtableSlot.MethodSignature.Instantiate(compiler.TagRepository, methodSpec.DeclaringClass.ArgTypes, methodSpec.GenericParameters); } } break; default: throw new Exception(); } List<HighInstruction> instrs = new List<HighInstruction>(); HighLocal thisLocal = new HighLocal(m_dt, HighLocal.ETypeOfType.Value); HighLocal[] locals = new HighLocal[0]; List<HighLocal> args = new List<HighLocal>(); int numParams = delegateMethodSignature.ParamTypes.Length; if (numParams != targetMethodSignature.ParamTypes.Length) throw new RpaCompileException("Delegate parameter count mismatch"); List<HighSsaRegister> convertedParameters = new List<HighSsaRegister>(); for (int i = 0; i < numParams; i++) { MethodSignatureParam delegateSigParam = delegateMethodSignature.ParamTypes[i]; MethodSignatureParam targetSigParam = targetMethodSignature.ParamTypes[i]; TypeSpecTag delegateSigType = delegateSigParam.Type; TypeSpecTag targetSigType = targetSigParam.Type; if (delegateSigParam.TypeOfType.Value != targetSigParam.TypeOfType.Value) throw new RpaCompileException("Delegate parameter type-of-type mismatch"); switch (delegateSigParam.TypeOfType.Value) { case MethodSignatureParamTypeOfType.Values.ByRef: { if (delegateSigType != targetSigType) throw new RpaCompileException("Delegate parameter type mismatch"); HighSsaRegister ssa = new HighSsaRegister(HighValueType.ManagedPtr, delegateSigType, null); HighLocal arg = new HighLocal(delegateSigParam.Type, HighLocal.ETypeOfType.ByRef); args.Add(arg); instrs.Add(new Rpa.Instructions.LoadLocalInstruction(null, ssa, arg)); convertedParameters.Add(ssa); } break; case MethodSignatureParamTypeOfType.Values.Value: { if (delegateSigType == targetSigType) { HighSsaRegister ssa = new HighSsaRegister(HighValueType.ValueValue, delegateSigParam.Type, null); HighLocal arg = new HighLocal(delegateSigParam.Type, HighLocal.ETypeOfType.Value); args.Add(arg); instrs.Add(new Rpa.Instructions.LoadLocalInstruction(null, ssa, arg)); convertedParameters.Add(ssa); } else { if (compiler.TypeIsValueType(delegateSigType) || compiler.TypeIsValueType(targetSigType)) throw new RpaCompileException("Delegate parameter type mismatch"); HighSsaRegister delegateParamSsa = new HighSsaRegister(HighValueType.ReferenceValue, delegateSigType, null); HighLocal arg = new HighLocal(delegateSigParam.Type, HighLocal.ETypeOfType.Value); args.Add(arg); instrs.Add(new Rpa.Instructions.LoadLocalInstruction(null, delegateParamSsa, arg)); HighSsaRegister targetParamSsa = GenerateConvertReference(compiler, delegateParamSsa, targetSigType, instrs); convertedParameters.Add(targetParamSsa); } } break; case MethodSignatureParamTypeOfType.Values.TypedByRef: throw new NotImplementedException(); default: throw new Exception(); } } HighSsaRegister methodReturnValue; if (targetMethodSignature.RetType is TypeSpecVoidTag) methodReturnValue = null; else { bool isValueType = compiler.TypeIsValueType(targetMethodSignature.RetType); methodReturnValue = new HighSsaRegister(isValueType ? HighValueType.ValueValue : HighValueType.ReferenceValue, targetMethodSignature.RetType, null); } HighInstruction callInstr; switch (methodSpec.MethodSlotType) { case MethodSlotType.Instance: { HighSsaRegister instanceReg; HighSsaRegister thisReg = new HighSsaRegister(HighValueType.ReferenceValue, m_dt, null); instrs.Add(new Rpa.Instructions.LoadLocalInstruction(null, thisReg, thisLocal)); if (compiler.TypeIsValueType(methodSpec.DeclaringClass)) { HighSsaRegister boxedReg = new HighSsaRegister(HighValueType.BoxedValue, methodSpec.DeclaringClass, null); instrs.Add(new Instructions.LoadDelegateTargetInstruction(null, boxedReg, thisReg)); instanceReg = new HighSsaRegister(HighValueType.ManagedPtr, methodSpec.DeclaringClass, null); instrs.Add(new Rpa.Instructions.UnboxPtrInstruction(null, instanceReg, boxedReg)); } else { instanceReg = new HighSsaRegister(HighValueType.BoxedValue, methodSpec.DeclaringClass, null); instrs.Add(new Instructions.LoadDelegateTargetInstruction(null, instanceReg, thisReg)); } MethodHandle methodHandle = compiler.InstantiateMethod(new MethodSpecMethodKey(methodSpec), instantiationPath); callInstr = new Instructions.CallRloInstanceMethodInstruction(null, methodHandle, methodReturnValue, instanceReg, convertedParameters.ToArray()); } break; case MethodSlotType.Virtual: { HighSsaRegister instanceReg; HighSsaRegister thisReg = new HighSsaRegister(HighValueType.ReferenceValue, m_dt, null); instrs.Add(new Rpa.Instructions.LoadLocalInstruction(null, thisReg, thisLocal)); if (compiler.TypeIsValueType(methodSpec.DeclaringClass)) { HighSsaRegister boxedReg = new HighSsaRegister(HighValueType.BoxedValue, methodSpec.DeclaringClass, null); instrs.Add(new Instructions.LoadDelegateTargetInstruction(null, boxedReg, thisReg)); instanceReg = new HighSsaRegister(HighValueType.ManagedPtr, methodSpec.DeclaringClass, null); instrs.Add(new Rpa.Instructions.UnboxPtrInstruction(null, instanceReg, boxedReg)); } else { instanceReg = new HighSsaRegister(HighValueType.BoxedValue, methodSpec.DeclaringClass, null); instrs.Add(new Instructions.LoadDelegateTargetInstruction(null, instanceReg, thisReg)); } if (isInterface) { uint cliSlot = targetIfc.CliSlotForSlotTag(methodSpec.MethodDecl); callInstr = new Instructions.CallRloInterfaceMethodInstruction(null, cliSlot, methodReturnValue, instanceReg, convertedParameters.ToArray()); } else { uint targetVtableSlot = targetCls.DeclTagToVTableSlot[methodSpec.MethodDecl]; callInstr = new Instructions.CallRloVirtualMethodInstruction(null, targetVtableSlot, methodReturnValue, instanceReg, convertedParameters.ToArray()); } } break; case MethodSlotType.Static: { MethodHandle methodHandle = compiler.InstantiateMethod(new MethodSpecMethodKey(methodSpec), instantiationPath); callInstr = new Instructions.CallRloStaticMethodInstruction(null, methodHandle, methodReturnValue, convertedParameters.ToArray()); } break; default: throw new Exception(); } List<HighInstruction> returnInstrs = new List<HighInstruction>(); if (methodReturnValue == null) { if (!(delegateMethodSignature.RetType is TypeSpecVoidTag)) throw new RpaCompileException("Delegate return type mismatch"); returnInstrs.Add(new Rpa.Instructions.ReturnInstruction(null)); } else { if (delegateMethodSignature.RetType is TypeSpecVoidTag) throw new RpaCompileException("Delegate return type mismatch"); TypeSpecTag delegateRetType = delegateMethodSignature.RetType; TypeSpecTag targetRetType = targetMethodSignature.RetType; if (delegateMethodSignature.RetType == targetMethodSignature.RetType) returnInstrs.Add(new Rpa.Instructions.ReturnValueInstruction(null, methodReturnValue)); else { if (compiler.TypeIsValueType(targetRetType) || compiler.TypeIsValueType(delegateRetType)) throw new RpaCompileException("Delegate return type mismatch"); HighSsaRegister retReg = GenerateConvertReference(compiler, methodReturnValue, delegateRetType, returnInstrs); returnInstrs.Add(new Rpa.Instructions.ReturnValueInstruction(null, retReg)); } } HighCfgNode returnNode = new HighCfgNode(returnInstrs.ToArray()); callInstr.ContinuationEdge = new HighCfgEdge(callInstr, new HighCfgNodeHandle(returnNode)); instrs.Add(callInstr); HighCfgNode entryNode = new HighCfgNode(instrs.ToArray()); HighRegion region = new HighRegion(new HighCfgNodeHandle(entryNode)); RloMethodBody methodBody = new RloMethodBody(thisLocal, args.ToArray(), locals, delegateMethodSignature.RetType, region, delegateMethodSignature, instantiationPath); return new RloMethod(methodBody); }
public override RloMethod GenerateMethod(Compiler compiler, MethodInstantiationPath instantiationPath) { VTableGenerationCache vtCache = m_vtCache; HighTypeDef typeDef = compiler.GetTypeDef(m_bt.ContainedType.TypeName); switch (typeDef.Semantics) { case TypeSemantics.Enum: case TypeSemantics.Struct: break; default: throw new ArgumentException("Unknown method type"); } CliClass cls = compiler.GetClosedClass(m_bt.ContainedType); HighLocal instanceLocal = new HighLocal(m_bt, HighLocal.ETypeOfType.Value); HighLocal[] args = new HighLocal[] { new HighLocal(vtCache.GetSystemObjectType(compiler), HighLocal.ETypeOfType.Value) }; HighLocal[] locals = new HighLocal[0]; HighCfgNodeHandle returnFalseHdl = new HighCfgNodeHandle(); HighCfgNodeHandle entryHdl = new HighCfgNodeHandle(); HighCfgNodeHandle getOtherTypeHdl = new HighCfgNodeHandle(); HighCfgNodeHandle checkTypeHdl = new HighCfgNodeHandle(); HighCfgNodeHandle unboxThisHdl = new HighCfgNodeHandle(); HighCfgNodeHandle unboxOtherHdl = new HighCfgNodeHandle(); HighCfgNodeHandle nextFieldCheckHdl = new HighCfgNodeHandle(); HighSsaRegister thisRef = new HighSsaRegister(HighValueType.ReferenceValue, vtCache.GetSystemObjectType(compiler), null); HighSsaRegister otherRef = new HighSsaRegister(HighValueType.ReferenceValue, vtCache.GetSystemObjectType(compiler), null); HighSsaRegister thisType = new HighSsaRegister(HighValueType.ReferenceValue, vtCache.GetSystemTypeType(compiler), null); HighSsaRegister otherType = new HighSsaRegister(HighValueType.ReferenceValue, vtCache.GetSystemTypeType(compiler), null); HighSsaRegister unboxedThisPtr = new HighSsaRegister(HighValueType.ManagedPtr, m_bt.ContainedType, null); HighSsaRegister unboxedOtherPtr = new HighSsaRegister(HighValueType.ManagedPtr, m_bt.ContainedType, null); TypeSpecClassTag boolType = vtCache.GetSystemBoolType(compiler); { List<HighInstruction> instrs = new List<HighInstruction>(); instrs.Add(new Rpa.Instructions.LoadLocalInstruction(null, thisRef, instanceLocal)); instrs.Add(new Rpa.Instructions.LoadLocalInstruction(null, otherRef, args[0])); instrs.Add(new Rpa.Instructions.BranchRefNullInstruction(null, otherRef, returnFalseHdl, getOtherTypeHdl)); entryHdl.Value = new HighCfgNode(new HighCfgNodeHandle[0], new HighPhi[0], instrs.ToArray()); } { List<HighInstruction> instrs = new List<HighInstruction>(); Instructions.CallRloInstanceMethodInstruction callInstr = new Instructions.CallRloInstanceMethodInstruction(null, vtCache.GetSystemObjectGetType(compiler), otherType, otherRef, new HighSsaRegister[0]); callInstr.ContinuationEdge = new HighCfgEdge(callInstr, checkTypeHdl); instrs.Add(callInstr); getOtherTypeHdl.Value = new HighCfgNode(new HighCfgNodeHandle[0], new HighPhi[0], instrs.ToArray()); } { List<HighInstruction> instrs = new List<HighInstruction>(); instrs.Add(new Rpa.Instructions.GetTypeInfoInstruction(null, thisType, m_bt.ContainedType)); instrs.Add(new Rpa.Instructions.BranchCompareRefsInstruction(null, thisType, otherType, unboxThisHdl, returnFalseHdl)); checkTypeHdl.Value = new HighCfgNode(new HighCfgNodeHandle[0], new HighPhi[0], instrs.ToArray()); } { List<HighInstruction> instrs = new List<HighInstruction>(); Rpa.Instructions.UnboxPtrInstruction unboxInstr = new Rpa.Instructions.UnboxPtrInstruction(null, unboxedThisPtr, thisRef); unboxInstr.ContinuationEdge = new HighCfgEdge(unboxInstr, unboxOtherHdl); instrs.Add(unboxInstr); unboxThisHdl.Value = new HighCfgNode(new HighCfgNodeHandle[0], new HighPhi[0], instrs.ToArray()); } { List<HighInstruction> instrs = new List<HighInstruction>(); Rpa.Instructions.UnboxPtrInstruction unboxInstr = new Rpa.Instructions.UnboxPtrInstruction(null, unboxedOtherPtr, otherRef); unboxInstr.ContinuationEdge = new HighCfgEdge(unboxInstr, nextFieldCheckHdl); instrs.Add(unboxInstr); unboxOtherHdl.Value = new HighCfgNode(new HighCfgNodeHandle[0], new HighPhi[0], instrs.ToArray()); } if ((vtCache.GetClassPodFlags(compiler, cls) & VTableGenerationCache.PodFlags.Equality) != VTableGenerationCache.PodFlags.None) { HighCfgNodeHandle nextHdl = new HighCfgNodeHandle(); List<HighInstruction> instrs = new List<HighInstruction>(); instrs.Add(new Instructions.BranchComparePodInstruction(null, unboxedThisPtr, unboxedOtherPtr, nextHdl, returnFalseHdl)); nextFieldCheckHdl.Value = new HighCfgNode(new HighCfgNodeHandle[0], new HighPhi[0], instrs.ToArray()); nextFieldCheckHdl = nextHdl; } else { foreach (HighField fld in cls.InstanceFields) { HighCfgNodeHandle nextHdl = new HighCfgNodeHandle(); TypeSpecTag fldType = fld.Type; HighSsaRegister thisFldPtr = new HighSsaRegister(HighValueType.ManagedPtr, fldType, null); HighSsaRegister otherFldPtr = new HighSsaRegister(HighValueType.ManagedPtr, fldType, null); { List<HighInstruction> instrs = new List<HighInstruction>(); instrs.Add(new Rpa.Instructions.PtrFieldInstruction(null, thisFldPtr, unboxedThisPtr, fld.Name)); instrs.Add(new Rpa.Instructions.PtrFieldInstruction(null, otherFldPtr, unboxedOtherPtr, fld.Name)); if (compiler.TypeIsValueType(fldType) && (((m_vtCache.GetClassPodFlags(compiler, compiler.GetClosedClass((TypeSpecClassTag)fldType))) & VTableGenerationCache.PodFlags.Equality) != VTableGenerationCache.PodFlags.None)) { instrs.Add(new Instructions.BranchComparePodInstruction(null, thisFldPtr, otherFldPtr, nextHdl, returnFalseHdl)); } else { HighCfgNodeHandle checkResultHdl = new HighCfgNodeHandle(); HighSsaRegister result = new HighSsaRegister(HighValueType.ValueValue, vtCache.GetSystemBoolType(compiler), null); HighSsaRegister resultInt = new HighSsaRegister(HighValueType.ValueValue, vtCache.GetSystemBoolType(compiler), null); HighSsaRegister zeroConstant = new HighSsaRegister(HighValueType.ConstantValue, vtCache.GetSystemInt32Type(compiler), 0); TypeSpecClassTag clarityToolsClass = vtCache.GetClarityToolsType(compiler); MethodDeclTag compareFieldsDeclTag = vtCache.GetCompareFieldsDeclTag(compiler); MethodSpecTag compareMethodSpec = new MethodSpecTag(MethodSlotType.Static, new TypeSpecTag[] { fldType }, clarityToolsClass, compareFieldsDeclTag); MethodHandle compareHdl = compiler.InstantiateMethod(new MethodSpecMethodKey(compareMethodSpec), instantiationPath); Instructions.CallRloStaticMethodInstruction callInstr = new Instructions.CallRloStaticMethodInstruction(null, compareHdl, result, new HighSsaRegister[] { thisFldPtr, otherFldPtr }); callInstr.ContinuationEdge = new HighCfgEdge(callInstr, checkResultHdl); instrs.Add(callInstr); List<HighInstruction> checkResultsInstrs = new List<HighInstruction>(); checkResultsInstrs.Add(new Instructions.RloConvertNumberInstruction(null, resultInt, result, Instructions.RloConvertNumberInstruction.NumConversionType.ZeroExtend, 32, 8)); checkResultsInstrs.Add(new Rpa.Instructions.BranchCompareNumbersInstruction(null, Rpa.Instructions.NumberCompareOperation.Equal, Rpa.Instructions.NumberArithType.Int32, resultInt, zeroConstant, returnFalseHdl, nextHdl)); checkResultHdl.Value = new HighCfgNode(new HighCfgNodeHandle[0], new HighPhi[0], checkResultsInstrs.ToArray()); } nextFieldCheckHdl.Value = new HighCfgNode(new HighCfgNodeHandle[0], new HighPhi[0], instrs.ToArray()); } nextFieldCheckHdl = nextHdl; } // Generate terminators { HighSsaRegister falseConstant = new HighSsaRegister(HighValueType.ConstantValue, boolType, false); List<HighInstruction> instrs = new List<HighInstruction>(); instrs.Add(new Rpa.Instructions.ReturnValueInstruction(null, falseConstant)); returnFalseHdl.Value = new HighCfgNode(new HighCfgNodeHandle[0], new HighPhi[0], instrs.ToArray()); } { HighSsaRegister trueConstant = new HighSsaRegister(HighValueType.ConstantValue, boolType, false); List<HighInstruction> instrs = new List<HighInstruction>(); instrs.Add(new Rpa.Instructions.ReturnValueInstruction(null, trueConstant)); nextFieldCheckHdl.Value = new HighCfgNode(new HighCfgNodeHandle[0], new HighPhi[0], instrs.ToArray()); } } MethodSignatureTag methodSignature = new MethodSignatureTag(0, m_vtCache.GetSystemBoolType(compiler), new MethodSignatureParam[] { new MethodSignatureParam(m_vtCache.GetSystemObjectType(compiler), new MethodSignatureParamTypeOfType(MethodSignatureParamTypeOfType.Values.Value)) }); methodSignature = compiler.TagRepository.InternMethodSignature(methodSignature); HighRegion region = new HighRegion(entryHdl); RloMethodBody body = new RloMethodBody(instanceLocal, args, locals, boolType, region, methodSignature, instantiationPath); return new RloMethod(body); }
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 HighCatchHandler(TypeSpecTag catchType, HighRegion region) { m_catchType = catchType; m_region = region; }
public override RloMethod GenerateMethod(Compiler compiler, MethodInstantiationPath instantiationPath) { TypeSpecClassTag delegateClassType = m_dt; CliClass delegateCls = compiler.GetClosedClass(delegateClassType); TypeNameTag delegateTypeName = delegateCls.TypeName; HighTypeDef delegateTypeDef = compiler.GetTypeDef(delegateTypeName); if (delegateTypeDef.Semantics != TypeSemantics.Delegate) throw new RpaCompileException("Delegate-bound class is not a delegate"); MethodSignatureTag declSignature = delegateTypeDef.DelegateSignature; MethodDeclTag invokeDeclTag = new MethodDeclTag("Invoke", declSignature, delegateTypeName); invokeDeclTag = compiler.TagRepository.InternMethodDeclTag(invokeDeclTag); uint vtableSlotIndex = delegateCls.DeclTagToVTableSlot[invokeDeclTag]; CliVtableSlot vtableSlot = delegateCls.VTable[vtableSlotIndex]; MethodSignatureTag delegateMethodSignature = vtableSlot.MethodSignature; TypeSpecMulticastDelegateTag mdType = new TypeSpecMulticastDelegateTag(m_dt); mdType = (TypeSpecMulticastDelegateTag)compiler.TagRepository.InternTypeSpec(mdType); List<HighSsaRegister> loadedParams = new List<HighSsaRegister>(); HighLocal thisLocal = new HighLocal(mdType, HighLocal.ETypeOfType.Value); List<HighLocal> args = new List<HighLocal>(); HighSsaRegister thisReg = new HighSsaRegister(HighValueType.ReferenceValue, mdType, null); List<HighInstruction> entryInstrs = new List<HighInstruction>(); entryInstrs.Add(new Rpa.Instructions.LoadLocalInstruction(null, thisReg, thisLocal)); foreach (MethodSignatureParam param in delegateMethodSignature.ParamTypes) { switch (param.TypeOfType.Value) { case MethodSignatureParamTypeOfType.Values.ByRef: { HighSsaRegister paramSsa = new HighSsaRegister(HighValueType.ManagedPtr, param.Type, null); HighLocal local = new HighLocal(param.Type, HighLocal.ETypeOfType.ByRef); args.Add(local); entryInstrs.Add(new Rpa.Instructions.LoadLocalInstruction(null, paramSsa, local)); loadedParams.Add(paramSsa); } break; case MethodSignatureParamTypeOfType.Values.Value: { bool isValueType = compiler.TypeIsValueType(param.Type); HighSsaRegister paramSsa = new HighSsaRegister(isValueType ? HighValueType.ValueValue : HighValueType.ReferenceValue, param.Type, null); HighLocal local = new HighLocal(param.Type, HighLocal.ETypeOfType.Value); args.Add(local); entryInstrs.Add(new Rpa.Instructions.LoadLocalInstruction(null, paramSsa, local)); loadedParams.Add(paramSsa); } break; case MethodSignatureParamTypeOfType.Values.TypedByRef: throw new NotImplementedException(); default: throw new Exception(); } } HighSsaRegister returnValue = null; if (!(delegateMethodSignature.RetType is TypeSpecVoidTag)) { bool isValueType = compiler.TypeIsValueType(delegateMethodSignature.RetType); returnValue = new HighSsaRegister(isValueType ? HighValueType.ValueValue : HighValueType.ReferenceValue, delegateMethodSignature.RetType, null); } TypeSpecClassTag nativeUIntType = m_vtCache.GetSystemUIntPtrType(compiler); HighSsaRegister numDelegatesValue = new HighSsaRegister(HighValueType.ValueValue, nativeUIntType, null); HighSsaRegister zeroNativeUIntConstant = new HighSsaRegister(HighValueType.ConstantValue, nativeUIntType, (ulong)0); HighCfgNodeHandle entryHdl = new HighCfgNodeHandle(); HighCfgNodeHandle loopCallHdl = new HighCfgNodeHandle(); HighCfgNodeHandle loopIncrementHdl = new HighCfgNodeHandle(); HighCfgNodeHandle returnHdl = new HighCfgNodeHandle(); HighSsaRegister postIncrementReg = new HighSsaRegister(HighValueType.ValueValue, nativeUIntType, null); entryInstrs.Add(new Instructions.GetMulticastDelegateInvocationCountInstruction(null, numDelegatesValue, thisReg)); entryInstrs.Add(new Rpa.Instructions.BranchInstruction(null, loopCallHdl)); entryHdl.Value = new HighCfgNode(entryInstrs.ToArray()); HighSsaRegister currentCountReg = new HighSsaRegister(HighValueType.ValueValue, nativeUIntType, null); { List<HighInstruction> instrs = new List<HighInstruction>(); HighSsaRegister delegateValue = new HighSsaRegister(HighValueType.ReferenceValue, m_dt, null); HighInstruction callInstr = new Instructions.CallRloVirtualMethodInstruction(null, vtableSlotIndex, returnValue, thisReg, loadedParams.ToArray()); callInstr.ContinuationEdge = new HighCfgEdge(callInstr, loopIncrementHdl); instrs.Add(callInstr); HighPhiLink[] loopLinks = new HighPhiLink[] { new HighPhiLink(entryHdl, zeroNativeUIntConstant), new HighPhiLink(loopIncrementHdl, postIncrementReg) }; HighCfgNodeHandle[] loopPredecessors = new HighCfgNodeHandle[] { entryHdl, loopIncrementHdl, }; HighPhi phi = new HighPhi(currentCountReg, loopLinks); loopCallHdl.Value = new HighCfgNode(loopPredecessors, new HighPhi[] { phi }, instrs.ToArray()); } { List<HighInstruction> instrs = new List<HighInstruction>(); HighSsaRegister oneConstant = new HighSsaRegister(HighValueType.ConstantValue, nativeUIntType, (ulong)1); instrs.Add(new Rpa.Instructions.ArithInstruction(null, postIncrementReg, Rpa.Instructions.NumberArithOp.Add, Rpa.Instructions.NumberArithType.NativeUInt, currentCountReg, oneConstant, false)); instrs.Add(new Rpa.Instructions.BranchCompareNumbersInstruction(null, Rpa.Instructions.NumberCompareOperation.LessThan, Rpa.Instructions.NumberArithType.NativeUInt, currentCountReg, numDelegatesValue, loopCallHdl, returnHdl)); loopIncrementHdl.Value = new HighCfgNode(instrs.ToArray()); } { List<HighInstruction> instrs = new List<HighInstruction>(); if (returnValue == null) instrs.Add(new Rpa.Instructions.ReturnInstruction(null)); else instrs.Add(new Rpa.Instructions.ReturnValueInstruction(null, returnValue)); returnHdl.Value = new HighCfgNode(instrs.ToArray()); } HighRegion region = new HighRegion(entryHdl); RloMethodBody methodBody = new RloMethodBody(thisLocal, args.ToArray(), new HighLocal[0], delegateMethodSignature.RetType, region, delegateMethodSignature, instantiationPath); return new RloMethod(methodBody); }
public HighTryCatchRegion(HighRegion tryRegion) : base(tryRegion) { }
public HighTryFaultRegion(HighRegion tryRegion) : base(tryRegion) { }
public override RloMethod GenerateMethod(Compiler compiler, MethodInstantiationPath instantiationPath) { HighLocal[] locals = new HighLocal[0]; HighLocal[] args = new HighLocal[0]; HighLocal instanceLocal = new HighLocal(m_bt, HighLocal.ETypeOfType.Value); Stack<HighField> fieldStack = new Stack<HighField>(); uint getHashCodeSlot = m_vtCache.GetGetHashCodeVTableSlot(compiler); HighSsaRegister result = new HighSsaRegister(HighValueType.ValueValue, m_vtCache.GetSystemInt32Type(compiler), null); MethodSignatureTag methodSignature = new MethodSignatureTag(0, m_vtCache.GetSystemInt32Type(compiler), new MethodSignatureParam[0]); methodSignature = compiler.TagRepository.InternMethodSignature(methodSignature); if (RecursiveFindHashableField(compiler, m_bt.ContainedType, fieldStack)) { // Found a field that can be hashed Queue<HighField> fieldQueue = new Queue<HighField>(); while (fieldStack.Count > 0) fieldQueue.Enqueue(fieldStack.Pop()); HighSsaRegister thisRef = new HighSsaRegister(HighValueType.BoxedValue, m_bt.ContainedType, null); HighSsaRegister thisPtr = new HighSsaRegister(HighValueType.ManagedPtr, m_bt.ContainedType, null); HighCfgNodeHandle unboxHdl = new HighCfgNodeHandle(); HighCfgNodeHandle locateAndHashFieldHdl = new HighCfgNodeHandle(); { List<HighInstruction> instrs = new List<HighInstruction>(); instrs.Add(new Rpa.Instructions.LoadLocalInstruction(null, thisRef, instanceLocal)); Rpa.Instructions.UnboxPtrInstruction unboxInstr = new Rpa.Instructions.UnboxPtrInstruction(null, thisPtr, thisRef); unboxInstr.ContinuationEdge = new HighCfgEdge(unboxInstr, locateAndHashFieldHdl); instrs.Add(unboxInstr); unboxHdl.Value = new HighCfgNode(new HighCfgNodeHandle[0], new HighPhi[0], instrs.ToArray()); } HighSsaRegister hashablePtr = thisPtr; List<HighInstruction> lahInstrs = new List<HighInstruction>(); while (fieldQueue.Count > 0) { HighField fld = fieldQueue.Dequeue(); HighSsaRegister nextFldPtr = new HighSsaRegister(HighValueType.ManagedPtr, fld.Type, null); lahInstrs.Add(new Rpa.Instructions.PtrFieldInstruction(null, nextFldPtr, hashablePtr, fld.Name)); hashablePtr = nextFldPtr; } if (compiler.TypeIsValueType(hashablePtr.Type)) { HighCfgNodeHandle returnResultHdl = new HighCfgNodeHandle(); CliClass cls = compiler.GetClosedClass((TypeSpecClassTag)hashablePtr.Type); CliMethodIndex vtableHashCodeIndex = cls.VTable[getHashCodeSlot].MethodIndex; if (vtableHashCodeIndex.Depth == 0) { HighMethod method = cls.Methods[vtableHashCodeIndex.Index]; Instructions.CallRloVirtualMethodInstruction callInstr = new Instructions.CallRloVirtualMethodInstruction(null, getHashCodeSlot, result, hashablePtr, new HighSsaRegister[0]); callInstr.ContinuationEdge = new HighCfgEdge(callInstr, returnResultHdl); lahInstrs.Add(callInstr); } else { // Base class GetHashCode, but field was found as hashable, which means it's POD MethodDeclTag hashBytesDecl = m_vtCache.GetHashBytesDeclTag(compiler); MethodSpecTag methodSpec = new MethodSpecTag(MethodSlotType.Static, new TypeSpecTag[] { hashablePtr.Type }, m_vtCache.GetClarityToolsType(compiler), hashBytesDecl); methodSpec = compiler.TagRepository.InternMethodSpec(methodSpec); MethodHandle methodHandle = compiler.InstantiateMethod(new MethodSpecMethodKey(methodSpec), instantiationPath); Instructions.CallRloStaticMethodInstruction callInstr = new Instructions.CallRloStaticMethodInstruction(null, methodHandle, result, new HighSsaRegister[] { hashablePtr }); callInstr.ContinuationEdge = new HighCfgEdge(callInstr, returnResultHdl); lahInstrs.Add(callInstr); } // Add return block { List<HighInstruction> rrInstrs = new List<HighInstruction>(); rrInstrs.Add(new Rpa.Instructions.ReturnValueInstruction(null, result)); returnResultHdl.Value = new HighCfgNode(new HighCfgNodeHandle[0], new HighPhi[0], rrInstrs.ToArray()); } } else { HighCfgNodeHandle fldNullHdl = new HighCfgNodeHandle(); HighCfgNodeHandle callGetHashCodeHdl = new HighCfgNodeHandle(); HighCfgNodeHandle returnResultHdl = new HighCfgNodeHandle(); HighSsaRegister fldValue = new HighSsaRegister(HighValueType.ReferenceValue, hashablePtr.Type, null); lahInstrs.Add(new Rpa.Instructions.LoadPtrInstruction(null, fldValue, hashablePtr)); lahInstrs.Add(new Rpa.Instructions.BranchRefNullInstruction(null, fldValue, fldNullHdl, callGetHashCodeHdl)); { HighSsaRegister zeroConstant = new HighSsaRegister(HighValueType.ConstantValue, m_vtCache.GetSystemInt32Type(compiler), 0); List<HighInstruction> instrs = new List<HighInstruction>(); instrs.Add(new Rpa.Instructions.ReturnValueInstruction(null, zeroConstant)); fldNullHdl.Value = new HighCfgNode(instrs.ToArray()); } { List<HighInstruction> instrs = new List<HighInstruction>(); Instructions.CallRloVirtualMethodInstruction callInstr = new Instructions.CallRloVirtualMethodInstruction(null, getHashCodeSlot, result, fldValue, new HighSsaRegister[0]); callInstr.ContinuationEdge = new HighCfgEdge(callInstr, returnResultHdl); callGetHashCodeHdl.Value = new HighCfgNode(instrs.ToArray()); } { List<HighInstruction> instrs = new List<HighInstruction>(); instrs.Add(new Rpa.Instructions.ReturnValueInstruction(null, result)); returnResultHdl.Value = new HighCfgNode(instrs.ToArray()); } } HighCfgNodeHandle entryHdl = new HighCfgNodeHandle(new HighCfgNode(lahInstrs.ToArray())); HighRegion region = new HighRegion(entryHdl); RloMethodBody methodBody = new RloMethodBody(instanceLocal, args, locals, m_vtCache.GetSystemInt32Type(compiler), region, methodSignature, instantiationPath); return new RloMethod(methodBody); } else { // No fields can be POD hashed, hash the type instead HighSsaRegister type = new HighSsaRegister(HighValueType.ReferenceValue, m_vtCache.GetSystemTypeType(compiler), null); HighCfgNodeHandle entryHdl = new HighCfgNodeHandle(); HighCfgNodeHandle returnResultHdl = new HighCfgNodeHandle(); { List<HighInstruction> instrs = new List<HighInstruction>(); instrs.Add(new Rpa.Instructions.GetTypeInfoInstruction(null, type, m_bt.ContainedType)); Instructions.CallRloVirtualMethodInstruction callInstr = new Instructions.CallRloVirtualMethodInstruction(null, getHashCodeSlot, result, type, new HighSsaRegister[0]); callInstr.ContinuationEdge = new HighCfgEdge(callInstr, returnResultHdl); instrs.Add(callInstr); entryHdl.Value = new HighCfgNode(instrs.ToArray()); } { List<HighInstruction> instrs = new List<HighInstruction>(); instrs.Add(new Rpa.Instructions.ReturnValueInstruction(null, result)); returnResultHdl.Value = new HighCfgNode(instrs.ToArray()); } HighRegion region = new HighRegion(entryHdl); RloMethodBody methodBody = new RloMethodBody(instanceLocal, args, locals, m_vtCache.GetSystemInt32Type(compiler), region, methodSignature, instantiationPath); return new RloMethod(methodBody); } }
public HighProtectedRegion(HighRegion tryRegion) { m_tryRegion = tryRegion; }