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 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 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 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); }
public InitLocalsPass(RloMethodBody methodBody) { m_methodBody = methodBody; }