// 解析所有引用 public void ResolveAll() { while (PendingMethods.Count > 0) { do { MethodX metX = PendingMethods.Dequeue(); // 跳过不需要处理的方法 if (metX.IsSkipProcessing) { continue; } // 跳过已处理的方法 if (metX.IsProcessed) { continue; } // 设置已处理标记 metX.IsProcessed = true; // 展开指令列表 BuildInstructions(metX); }while (PendingMethods.Count > 0); // 解析协逆变 ResolveVariances(); // 解析虚调用 ResolveVCalls(); } }
private static TypeX GetMethodGenType(MethodX metX, GeneratorContext genContext, int genArg = 0) { Debug.Assert(metX.HasGenArgs && metX.GenArgs.Count > genArg); TypeX genType = genContext.GetTypeBySig(metX.GenArgs[genArg]); Debug.Assert(genType != null); return(genType); }
public string GetMethodName(MethodDef metDef, out string unitName) { MethodX metX = GenContext.TypeMgr.ResolveMethodDef(metDef); string typeName = GenContext.GetTypeName(metX.DeclType); unitName = TransMap[typeName]; return(GenContext.GetMethodName(metX, MethodGenerator.PrefixMet)); }
public void AddOverrideImpl(MethodX impl) { if (OverrideImpls == null) { OverrideImpls = new HashSet <MethodX>(); } OverrideImpls.Add(impl); }
public void SetMethod(MethodX metX) { if (metX.HasGenArgs) { OwnerMethod = metX.Def; MethodGenArgs = metX.GenArgs; } }
private void AppendRuntimeFlags(MethodX metX, CodePrinter prt) { string typeName = metX.DeclType.GetNameKey(); if (typeName == "il2cpprt.ThrowHelper") { prt.AppendFormatLine("#define IL2CPP_BRIDGE_HAS_{0}", GenContext.GetMethodName(metX, null)); } }
public static bool GenInternalMethod(MethodX metX, CodePrinter prt, GeneratorContext genContext) { string typeName = metX.DeclType.GetNameKey(); string metName = metX.Def.Name; if (typeName == "String") { if (metName == "get_Length") { FieldX fldLen = metX.DeclType.Fields.FirstOrDefault( fld => fld.FieldType.ElementType == dnlib.DotNet.ElementType.I4); prt.AppendFormatLine(@"return arg_0->{0};", genContext.GetFieldName(fldLen)); return(true); } else if (metName == "get_Chars") { FieldX fldLen = metX.DeclType.Fields.FirstOrDefault( fld => fld.FieldType.ElementType == dnlib.DotNet.ElementType.I4); FieldX fldFirstChar = metX.DeclType.Fields.FirstOrDefault( fld => fld.FieldType.ElementType == dnlib.DotNet.ElementType.Char); prt.AppendFormatLine("IL2CPP_CHECK_RANGE(0, arg_0->{0}, arg_1);", genContext.GetFieldName(fldLen)); prt.AppendFormatLine("return ((uint16_t*)&arg_0->{0})[arg_1];", genContext.GetFieldName(fldFirstChar)); return(true); } } /* * else if (typeName == "System.ValueType") * { * if (metName == "GetHashCode") * { * prt.AppendLine("return (int32_t)0x14AE055C;"); * return true; * } * } * else if (typeName == "System.Runtime.CompilerServices.RuntimeHelpers") * { * if (metName == "GetHashCode") * { * prt.AppendLine("uintptr_t val = (uintptr_t)arg_0;"); * prt.AppendLine("return (int32_t)((uint32_t)val ^ (uint32_t)(val >> 32));"); * return true; * } * }*/ return(false); }
public static string GetCppName(this MethodX metX, string prefix) { if (metX.CppName_ == null) { if (metX.Def.IsInternalCall) { metX.CppName_ = "icall_" + ToCppName(metX.Name, false); } else { metX.CppName_ = ToCppName(metX.Name); } } return(prefix + metX.CppName_); }
public static bool GenInternalMethod(MethodX metX, CodePrinter prt, GeneratorContext genContext) { string typeName = metX.DeclType.GetNameKey(); string metName = metX.Def.Name; if (typeName == "String") { if (metName == "get_Length") { FieldX fldLen = metX.DeclType.Fields.FirstOrDefault( fld => fld.FieldType.ElementType == dnlib.DotNet.ElementType.I4); prt.AppendFormatLine(@"return arg_0->{0};", genContext.GetFieldName(fldLen)); return(true); } else if (metName == "get_Chars") { FieldX fldLen = metX.DeclType.Fields.FirstOrDefault( fld => fld.FieldType.ElementType == dnlib.DotNet.ElementType.I4); FieldX fldFirstChar = metX.DeclType.Fields.FirstOrDefault( fld => fld.FieldType.ElementType == dnlib.DotNet.ElementType.Char); prt.AppendFormatLine("IL2CPP_CHECK_RANGE(0, arg_0->{0}, arg_1);", genContext.GetFieldName(fldLen)); prt.AppendFormatLine("return ((uint16_t*)&arg_0->{0})[arg_1];", genContext.GetFieldName(fldFirstChar)); return(true); } } else if (typeName == "System.Runtime.CompilerServices.RuntimeHelpers") { if (metX.Def.Name == "IsReferenceOrContainsReferences") { Debug.Assert(metX.HasGenArgs && metX.GenArgs.Count == 1); TypeX targetType = genContext.GetTypeBySig(metX.GenArgs[0]); prt.AppendFormatLine("return {0};", genContext.IsRefOrContainsRef(targetType) ? "1" : "0"); return(true); } } return(false); }
public string GetMethodName(MethodX metX, string prefix) { string strName = metX.GeneratedMethodName; if (strName == null) { int hashCode = Helper.CombineHash( metX.GetNameKey().GetHashCode(), metX.GetReplacedNameKey().GetHashCode(), metX.DeclType.GetNameKey().GetHashCode()); strName = NameHash(hashCode) + '_' + GetNameWithGen(metX.DeclType.Def.Name, metX.DeclType.GenArgs) + "__" + GetNameWithGen(metX.Def.Name, metX.GenArgs); metX.GeneratedMethodName = strName = GetNotUsedMethodName(EscapeName(strName)); } return(prefix + strName); }
public static string PrettyName(this MethodX self, bool hasDeclType = false) { StringBuilder sb = new StringBuilder(); if (self.Def.IsStatic) { sb.Append("static "); } PrettyName(sb, self.ReturnType, true); sb.AppendFormat(" {0}{1}", hasDeclType ? self.DeclType.PrettyName() + "::" : "", self.Def.Name); PrettyGenArgs(sb, self.GenArgs); sb.Append('('); int i = 0; if (!self.Def.IsStatic) { i = 1; } bool last = false; for (; i < self.ParamTypes.Count; ++i) { if (last) { sb.Append(','); } last = true; var arg = self.ParamTypes[i]; PrettyName(sb, arg, true); } sb.Append(')'); return(sb.ToString()); }
public MethodX GenFinalizerMethod(TypeManager typeMgr) { if (!IsFinalizerGenerated) { IsFinalizerGenerated = true; // 跳过 Object 类的终结器 if (GetNameKey() != "Object") { MethodDef finMetDef = Def.Methods.FirstOrDefault(met => !met.IsStatic && met.Name == "Finalize"); if (finMetDef != null) { FinalizerMethod = typeMgr.AddMethod(new MethodX(this, finMetDef)); } } if (FinalizerMethod == null) { FinalizerMethod = BaseType?.GenFinalizerMethod(typeMgr); } } return(FinalizerMethod); }
public static bool GenInternalMethod(MethodX metX, CodePrinter prt, GeneratorContext genContext) { string typeName = metX.DeclType.GetNameKey(); string metName = metX.Def.Name; if (typeName == "String") { if (metName == "get_Length") { FieldX fldLen = metX.DeclType.Fields.FirstOrDefault( fld => fld.FieldType.ElementType == dnlib.DotNet.ElementType.I4); prt.AppendFormatLine(@"return arg_0->{0};", genContext.GetFieldName(fldLen)); return(true); } else if (metName == "get_Chars") { FieldX fldLen = metX.DeclType.Fields.FirstOrDefault( fld => fld.FieldType.ElementType == dnlib.DotNet.ElementType.I4); FieldX fldFirstChar = metX.DeclType.Fields.FirstOrDefault( fld => fld.FieldType.ElementType == dnlib.DotNet.ElementType.Char); prt.AppendFormatLine("IL2CPP_CHECK_RANGE(0, arg_0->{0}, arg_1);", genContext.GetFieldName(fldLen)); prt.AppendFormatLine("return ((uint16_t*)&arg_0->{0})[arg_1];", genContext.GetFieldName(fldFirstChar)); return(true); } } else if (typeName == "System.Array") { if (metName == "get_Rank") { prt.AppendLine( @"if (arg_0->Rank == 0) return 1; return arg_0->Rank;"); return(true); } else if (metName == "get_Length") { prt.AppendLine( @"if (arg_0->Rank == 0) return ((int32_t*)&arg_0[1])[0]; else { int32_t length = 1; for (int32_t i = 0, sz = arg_0->Rank; i < sz; ++i) length *= ((int32_t*)&arg_0[1])[i * 2 + 1]; return length; }"); return(true); } else if (metName == "get_LongLength") { prt.AppendLine( @"if (arg_0->Rank == 0) return ((int32_t*)&arg_0[1])[0]; else { int64_t length = 1; for (int32_t i = 0, sz = arg_0->Rank; i < sz; ++i) length *= ((int32_t*)&arg_0[1])[i * 2 + 1]; return length; }"); return(true); } else if (metName == "GetLength") { prt.AppendLine( @"if (arg_0->Rank == 0) { IL2CPP_CHECK_RANGE(0, 1, arg_1); return ((int32_t*)&arg_0[1])[0]; } else { IL2CPP_CHECK_RANGE(0, arg_0->Rank, arg_1); return ((int32_t*)&arg_0[1])[arg_1 * 2 + 1]; }"); return(true); } else if (metName == "GetLowerBound") { prt.AppendLine( @"if (arg_0->Rank == 0) { IL2CPP_CHECK_RANGE(0, 1, arg_1); return 0; } else { IL2CPP_CHECK_RANGE(0, arg_0->Rank, arg_1); return ((int32_t*)&arg_0[1])[arg_1 * 2]; }"); return(true); } else if (metName == "GetUpperBound") { prt.AppendLine( @"if (arg_0->Rank == 0) { IL2CPP_CHECK_RANGE(0, 1, arg_1); return ((int32_t*)&arg_0[1])[0] - 1; } else { IL2CPP_CHECK_RANGE(0, arg_0->Rank, arg_1); return ((int32_t*)&arg_0[1])[arg_1 * 2] + ((int32_t*)&arg_0[1])[arg_1 * 2 + 1] - 1; }"); return(true); } } else if (typeName == "System.Environment") { if (metName == "GetResourceFromDefault") { prt.AppendLine("return arg_0;"); return(true); } } return(false); }
public static bool GenInternalMethod(MethodGenerator metGen, CodePrinter prt) { MethodX metX = metGen.CurrMethod; GeneratorContext genContext = metGen.GenContext; string typeName = metX.DeclType.GetNameKey(); string metName = metX.Def.Name; string metSigName = metX.GetNameKey(); if (typeName == "Object") { if (metName == "GetInternalTypeID") { prt.AppendLine("return (int32_t)arg_0->TypeID;"); return(true); } } else if (typeName == "String") { FieldX fldLen = metX.DeclType.Fields.FirstOrDefault( fld => fld.FieldType.ElementType == dnlib.DotNet.ElementType.I4); FieldX fldFirstChar = metX.DeclType.Fields.FirstOrDefault( fld => fld.FieldType.ElementType == dnlib.DotNet.ElementType.Char); if (metName == "get_Length") { prt.AppendFormatLine(@"return arg_0->{0};", genContext.GetFieldName(fldLen)); return(true); } else if (metName == "get_Chars") { prt.AppendFormatLine("IL2CPP_CHECK_RANGE(0, arg_0->{0}, arg_1);", genContext.GetFieldName(fldLen)); prt.AppendFormatLine("return ((uint16_t*)&arg_0->{0})[arg_1];", genContext.GetFieldName(fldFirstChar)); return(true); } else if (metName == "InternalMarvin32HashString") { prt.AppendFormatLine("return il2cpp_HashString(&arg_0->{0}, arg_0->{1});", genContext.GetFieldName(fldFirstChar), genContext.GetFieldName(fldLen)); return(true); } else if (metName == "FastAllocateString") { prt.AppendFormatLine( "cls_String* str = (cls_String*)IL2CPP_NEW(sizeof(cls_String) + sizeof(uint16_t) * arg_0, {0}, 1);", genContext.GetStringTypeID()); prt.AppendFormatLine("str->{0} = arg_0;", genContext.GetFieldName(fldLen)); prt.AppendLine("return str;"); return(true); } else if (metSigName == ".ctor|Void(Char*,Int32,Int32)|20") { prt.AppendFormatLine("arg_0->{0} = arg_3;", genContext.GetFieldName(fldLen)); prt.AppendFormatLine("IL2CPP_MEMCPY(&arg_0->{0}, arg_1 + arg_2, sizeof(uint16_t) * arg_3);", genContext.GetFieldName(fldFirstChar)); return(true); } } else if (typeName == "System.Array") { if (metName == "get_Rank") { prt.AppendLine("if (arg_0->Rank == 0)"); ++prt.Indents; prt.AppendLine("return 1;"); --prt.Indents; prt.AppendLine("return arg_0->Rank;"); return(true); } else if (metName == "get_Length") { prt.AppendLine("return il2cpp_Array__GetLength(arg_0);"); return(true); } else if (metName == "get_LongLength") { prt.AppendLine("return il2cpp_Array__GetLongLength(arg_0);"); return(true); } else if (metName == "GetLength") { prt.AppendLine("return il2cpp_Array__GetLength(arg_0, arg_1);"); return(true); } else if (metName == "GetLowerBound") { prt.AppendLine("return il2cpp_Array__GetLowerBound(arg_0, arg_1);"); return(true); } else if (metName == "GetUpperBound") { prt.AppendLine("return il2cpp_Array__GetUpperBound(arg_0, arg_1);"); return(true); } else if (metName == "Copy") { prt.AppendLine("return il2cpp_Array__Copy(arg_0, arg_1, arg_2, arg_3, arg_4);"); return(true); } else if (metName == "Clear") { prt.AppendLine("return il2cpp_Array__Clear(arg_0, arg_1, arg_2);"); return(true); } } else if (typeName == "System.Runtime.CompilerServices.RuntimeHelpers") { if (metName == "IsReferenceOrContainsReferences") { var targetType = GetMethodGenType(metX, genContext); prt.AppendFormatLine("return {0};", genContext.IsRefOrContainsRef(targetType) ? "1" : "0"); return(true); } else if (metName == "CanCompareBits") { var targetType = GetMethodGenType(metX, genContext); bool canCompareBits = true; foreach (var fldX in targetType.Fields) { if (!Helper.IsBasicValueType(fldX.FieldType.ElementType)) { canCompareBits = false; break; } } prt.AppendFormatLine("return {0};", canCompareBits ? "1" : "0"); return(true); } else if (metName == "GetInternalTypeID") { var targetType = GetMethodGenType(metX, genContext); prt.AppendFormatLine("return {0};", genContext.GetTypeID(targetType)); return(true); } else if (metName == "FastCompareBits") { var argTySig = metX.ParamTypes[0].Next; metGen.RefValueTypeImpl(argTySig); if (Helper.IsBasicValueType(argTySig.ElementType) || genContext.GetTypeBySig(argTySig).IsEnumType) { prt.AppendLine("return *arg_0 == *arg_1 ? 1 : 0;"); } else { prt.AppendLine("return IL2CPP_MEMCMP(arg_0, arg_1, sizeof(*arg_0)) == 0 ? 1 : 0;"); } return(true); } else if (metName == "InitializeArray") { TypeX tyArg1 = genContext.GetTypeBySig(metX.ParamTypes[1]); Debug.Assert(tyArg1 != null); FieldX rtFldX = tyArg1.Fields.First(); prt.AppendFormatLine("il2cpp_Array__Init(arg_0, (il2cppFieldInfo*)arg_1.{0});", genContext.GetFieldName(rtFldX)); return(true); } else if (metName == "Equals") { prt.AppendLine("return arg_0 == arg_1 ? 1 : 0;"); return(true); } else if (metName == "GetHashCode") { prt.AppendLine("uintptr_t val = (uintptr_t)arg_0;"); prt.AppendLine("return (int32_t)((uint32_t)val ^ (uint32_t)(val >> 32) ^ (uint32_t)0x14AE055C);"); return(true); } } else if (typeName == "System.Runtime.CompilerServices.JitHelpers") { if (metName == "GetRawSzArrayData") { prt.AppendLine("IL2CPP_ASSERT(arg_0->Rank == 0);"); prt.AppendLine("return (uint8_t*)&arg_0[1];"); return(true); } } else if (typeName == "Internal.Runtime.CompilerServices.Unsafe") { if (metName == "As") { prt.AppendFormatLine("return ({0})arg_0;", genContext.GetTypeName(metX.ReturnType)); return(true); } } else if (typeName == "System.Buffer") { if (metName == "__Memmove") { prt.AppendLine("IL2CPP_MEMMOVE(arg_0, arg_1, arg_2);"); return(true); } } else if (typeName == "System.Math") { if (metName == "Abs") { prt.AppendLine("return il2cpp_Abs(arg_0);"); return(true); } else if (metName == "Sqrt") { prt.AppendLine("return il2cpp_Sqrt(arg_0);"); return(true); } else if (metName == "Sin") { prt.AppendLine("return il2cpp_Sin(arg_0);"); return(true); } else if (metName == "Cos") { prt.AppendLine("return il2cpp_Cos(arg_0);"); return(true); } else if (metName == "Tan") { prt.AppendLine("return il2cpp_Tan(arg_0);"); return(true); } else if (metName == "Pow") { prt.AppendLine("return il2cpp_Pow(arg_0, arg_1);"); return(true); } } else if (typeName == "System.Threading.Monitor") { if (metName == "ReliableEnter") { prt.AppendLine("il2cpp_SpinLock(arg_0->Flags[0]);"); prt.AppendLine("*arg_1 = 1;"); return(true); } else if (metName == "Exit") { prt.AppendLine("il2cpp_SpinUnlock(arg_0->Flags[0]);"); return(true); } } else if (typeName == "System.Threading.Interlocked") { if (metName == "CompareExchange") { prt.AppendLine("return il2cpp_CompareExchange(arg_0, arg_1, arg_2);"); return(true); } } else if (typeName == "System.GC") { if (metName == "_Collect") { prt.AppendLine("il2cpp_GC_Collect();"); return(true); } } return(false); }
private void ResolveOperand(InstInfo inst, IGenericReplacer replacer) { // 重定向数组指令 switch (inst.OpCode.Code) { case Code.Newarr: { // newobj T[]::.ctor(int) TypeSig elemSig = ((ITypeDefOrRef)inst.Operand).ToTypeSig(); inst.OpCode = OpCodes.Newobj; inst.Operand = new MemberRefUser( Context.CorLibModule, ".ctor", MethodSig.CreateInstance(Context.CorLibTypes.Void, Context.CorLibTypes.Int32), new TypeSpecUser(new SZArraySig(elemSig))); break; } case Code.Ldlen: { // call int Array::get_Length() inst.OpCode = OpCodes.Call; inst.Operand = new MemberRefUser( Context.CorLibModule, "get_Length", MethodSig.CreateInstance(Context.CorLibTypes.Int32), Context.CorLibTypes.GetTypeRef("System", "Array")); break; } case Code.Ldelema: { // call T& T[]::Address(int) TypeSig elemSig = ((ITypeDefOrRef)inst.Operand).ToTypeSig(); inst.OpCode = OpCodes.Call; inst.Operand = new MemberRefUser( Context.CorLibModule, "Address", MethodSig.CreateInstance(new ByRefSig(elemSig), Context.CorLibTypes.Int32), new TypeSpecUser(new SZArraySig(elemSig))); break; } case Code.Ldelem_I1: case Code.Ldelem_U1: case Code.Ldelem_I2: case Code.Ldelem_U2: case Code.Ldelem_I4: case Code.Ldelem_U4: case Code.Ldelem_I8: case Code.Ldelem_I: case Code.Ldelem_R4: case Code.Ldelem_R8: case Code.Ldelem_Ref: case Code.Ldelem: { TypeSig elemSig = null; switch (inst.OpCode.Code) { case Code.Ldelem_I1: elemSig = Context.CorLibTypes.SByte; break; case Code.Ldelem_U1: elemSig = Context.CorLibTypes.Byte; break; case Code.Ldelem_I2: elemSig = Context.CorLibTypes.Int16; break; case Code.Ldelem_U2: elemSig = Context.CorLibTypes.UInt16; break; case Code.Ldelem_I4: elemSig = Context.CorLibTypes.Int32; break; case Code.Ldelem_U4: elemSig = Context.CorLibTypes.UInt32; break; case Code.Ldelem_I8: elemSig = Context.CorLibTypes.Int64; break; case Code.Ldelem_I: elemSig = Context.CorLibTypes.IntPtr; break; case Code.Ldelem_R4: elemSig = Context.CorLibTypes.Single; break; case Code.Ldelem_R8: elemSig = Context.CorLibTypes.Double; break; case Code.Ldelem_Ref: elemSig = Context.CorLibTypes.Object; break; case Code.Ldelem: elemSig = ((ITypeDefOrRef)inst.Operand).ToTypeSig(); break; } // call T T[]::Get(int) inst.OpCode = OpCodes.Call; inst.Operand = new MemberRefUser( Context.CorLibModule, "Get", MethodSig.CreateInstance(elemSig, Context.CorLibTypes.Int32), new TypeSpecUser(new SZArraySig(elemSig))); break; } case Code.Stelem_I1: case Code.Stelem_I2: case Code.Stelem_I4: case Code.Stelem_I8: case Code.Stelem_I: case Code.Stelem_R4: case Code.Stelem_R8: case Code.Stelem_Ref: case Code.Stelem: { TypeSig elemSig = null; switch (inst.OpCode.Code) { case Code.Stelem_I1: elemSig = Context.CorLibTypes.SByte; break; case Code.Stelem_I2: elemSig = Context.CorLibTypes.Int16; break; case Code.Stelem_I4: elemSig = Context.CorLibTypes.Int32; break; case Code.Stelem_I8: elemSig = Context.CorLibTypes.Int64; break; case Code.Stelem_I: elemSig = Context.CorLibTypes.IntPtr; break; case Code.Stelem_R4: elemSig = Context.CorLibTypes.Single; break; case Code.Stelem_R8: elemSig = Context.CorLibTypes.Double; break; case Code.Stelem_Ref: elemSig = Context.CorLibTypes.Object; break; case Code.Stelem: elemSig = ((ITypeDefOrRef)inst.Operand).ToTypeSig(); break; } // call void T[]::Set(int,T) inst.OpCode = OpCodes.Call; inst.Operand = new MemberRefUser( Context.CorLibModule, "Set", MethodSig.CreateInstance(Context.CorLibTypes.Void, Context.CorLibTypes.Int32, elemSig), new TypeSpecUser(new SZArraySig(elemSig))); break; } } switch (inst.OpCode.OperandType) { case OperandType.InlineMethod: { MethodX resMetX; switch (inst.Operand) { case MethodDef metDef: resMetX = ResolveMethodDef(metDef); break; case MemberRef memRef: resMetX = ResolveMethodRef(memRef, replacer); break; case MethodSpec metSpec: resMetX = ResolveMethodSpec(metSpec, replacer); break; default: throw new ArgumentOutOfRangeException(); } bool isReAddMethod = false; if (inst.OpCode.Code == Code.Newobj) { Debug.Assert(!resMetX.Def.IsStatic); Debug.Assert(resMetX.Def.IsConstructor); // 设置实例化标记 resMetX.DeclType.IsInstantiated = true; // 生成静态构造和终结器 GenStaticCctor(resMetX.DeclType); GenFinalizer(resMetX.DeclType); } else if (inst.OpCode.Code == Code.Callvirt || inst.OpCode.Code == Code.Ldvirtftn) { if (resMetX.IsVirtual) { AddVCallEntry(resMetX); } else { // 非虚方法重定向指令 inst.OpCode = inst.OpCode.Code == Code.Callvirt ? OpCodes.Call : OpCodes.Ldftn; } } else if (resMetX.IsVirtual && (inst.OpCode.Code == Code.Call || inst.OpCode.Code == Code.Ldftn)) { // 处理方法替换 if (resMetX.DeclType.QueryCallReplace(this, resMetX.Def, out TypeX implTyX, out var implDef)) { resMetX.IsSkipProcessing = true; Debug.Assert(implTyX != null); MethodX implMetX = MakeMethodX(implTyX, implDef, resMetX.GenArgs); resMetX = implMetX; } else { isReAddMethod = true; } } else { isReAddMethod = true; } if (isReAddMethod) { // 尝试重新加入处理队列 AddPendingMethod(resMetX); } if (resMetX.IsStatic) { // 生成静态构造 GenStaticCctor(resMetX.DeclType); } inst.Operand = resMetX; return; }
private void BuildInstructions(MethodX metX) { Debug.Assert(metX.InstList == null); if (!metX.Def.HasBody || !metX.Def.Body.HasInstructions) { return; } IGenericReplacer replacer = new GenericReplacer(metX.DeclType, metX); var defInstList = metX.Def.Body.Instructions; int numInsts = defInstList.Count; InstInfo[] instList = new InstInfo[numInsts]; Dictionary <uint, int> offsetMap = new Dictionary <uint, int>(); List <InstInfo> branchInsts = new List <InstInfo>(); // 构建指令列表 for (int ip = 0; ip < numInsts; ++ip) { var defInst = defInstList[ip]; var inst = instList[ip] = new InstInfo(); inst.OpCode = defInst.OpCode; inst.Operand = defInst.Operand; inst.Offset = ip; offsetMap.Add(defInst.Offset, ip); switch (inst.OpCode.OperandType) { case OperandType.InlineBrTarget: case OperandType.ShortInlineBrTarget: case OperandType.InlineSwitch: branchInsts.Add(inst); break; default: ResolveOperand(inst, replacer); break; } } // 重定向跳转位置 foreach (var inst in branchInsts) { if (inst.Operand is Instruction defInst) { int target; inst.Operand = target = offsetMap[defInst.Offset]; instList[target].IsBrTarget = true; } else if (inst.Operand is Instruction[] defInsts) { int[] insts = new int[defInsts.Length]; for (int i = 0; i < defInsts.Length; ++i) { int target; insts[i] = target = offsetMap[defInsts[i].Offset]; instList[target].IsBrTarget = true; } inst.Operand = insts; } } metX.InstList = instList; }
public static bool GenInternalMethod(MethodX metX, CodePrinter prt, GeneratorContext genContext) { string typeName = metX.DeclType.GetNameKey(); string metName = metX.Def.Name; if (typeName == "String") { if (metName == "get_Length") { FieldX fldLen = metX.DeclType.Fields.FirstOrDefault( fld => fld.FieldType.ElementType == dnlib.DotNet.ElementType.I4); prt.AppendFormatLine(@"return arg_0->{0};", genContext.GetFieldName(fldLen)); return(true); } else if (metName == "get_Chars") { FieldX fldLen = metX.DeclType.Fields.FirstOrDefault( fld => fld.FieldType.ElementType == dnlib.DotNet.ElementType.I4); FieldX fldFirstChar = metX.DeclType.Fields.FirstOrDefault( fld => fld.FieldType.ElementType == dnlib.DotNet.ElementType.Char); prt.AppendFormatLine("IL2CPP_CHECK_RANGE(0, arg_0->{0}, arg_1);", genContext.GetFieldName(fldLen)); prt.AppendFormatLine("return ((uint16_t*)&arg_0->{0})[arg_1];", genContext.GetFieldName(fldFirstChar)); return(true); } else if (metName == "InternalMarvin32HashString") { FieldX fldLen = metX.DeclType.Fields.FirstOrDefault( fld => fld.FieldType.ElementType == dnlib.DotNet.ElementType.I4); FieldX fldFirstChar = metX.DeclType.Fields.FirstOrDefault( fld => fld.FieldType.ElementType == dnlib.DotNet.ElementType.Char); prt.AppendFormatLine("return il2cpp_HashString(&arg_0->{0}, arg_0->{1});", genContext.GetFieldName(fldFirstChar), genContext.GetFieldName(fldLen)); return(true); } } else if (typeName == "System.Runtime.CompilerServices.RuntimeHelpers") { if (metName == "IsReferenceOrContainsReferences") { Debug.Assert(metX.HasGenArgs && metX.GenArgs.Count == 1); TypeX targetType = genContext.GetTypeBySig(metX.GenArgs[0]); prt.AppendFormatLine("return {0};", genContext.IsRefOrContainsRef(targetType) ? "1" : "0"); return(true); } else if (metName == "InitializeArray") { TypeX tyArg1 = genContext.GetTypeBySig(metX.ParamTypes[1]); Debug.Assert(tyArg1 != null); FieldX rtFldX = tyArg1.Fields.First(); prt.AppendFormatLine("il2cpp_Array__Init(arg_0, (il2cppFieldInfo*)arg_1.{0});", genContext.GetFieldName(rtFldX)); return(true); } } else if (typeName == "System.Math") { if (metName == "Sqrt") { prt.AppendLine("return il2cpp_Sqrt(arg_0);"); return(true); } } return(false); }
public GenericReplacer(TypeX ownerTyX, MethodX ownerMetX) { OwnerType = ownerTyX; OwnerMethod = ownerMetX; }
public void AddMethod(string key, MethodX metX) { MethodMap.Add(key, metX); }
public bool GetMethod(string key, out MethodX metX) { return(MethodMap.TryGetValue(key, out metX)); }
public string GetMetaName(MethodX metX, bool isData = false) { return(string.Format("{0}{1}", isData ? "mdata_" : "meta_", GetMethodName(metX, metX.IsStatic ? "smet_" : "met_"))); }
// 导出方法表结构 /*public void DumpMethodTables(StringBuilder sb) * { * foreach (var kv in Context.TypeMgr.MethodTableMap) * { * sb.AppendFormat("[{0}]\n", kv.Key); * bool flag = false; * foreach (var kv2 in kv.Value.VSlotMap) * { * string expSigName = kv2.Key; * var entries = kv2.Value.Entries; * VirtualImpl impl = kv2.Value.Impl; * * // 跳过无覆盖的方法 * if (entries.Count == 1 && * impl.IsValid() && * entries.TryGetValue(impl.ImplTable, out var defSet) && * defSet.Count == 1 && * defSet.First() == impl.ImplMethod) * { * continue; * } * * sb.AppendFormat(" - {0}: {1}\n", expSigName, impl); * foreach (var kv3 in entries) * { * foreach (var mdef in kv3.Value) * sb.AppendFormat(" - {0} -> {1}\n", kv3.Key, mdef); * } * sb.Append('\n'); * flag = true; * } * if (!flag) * sb.Append('\n'); * } * }*/ public void DumpTypes(StringBuilder sb) { foreach (TypeX tyX in Context.TypeMgr.Types) { sb.AppendFormat("[{0} {1}] {2}\n", tyX.IsValueType ? "struct" : "class", tyX.GetNameKey(), TypeAttrToString(tyX.Def.Attributes)); if (tyX.IsInstantiated) { sb.Append(" - Instantiated\n"); } if (tyX.BaseType != null) { sb.AppendFormat(" - Base: {0}\n", tyX.BaseType); } if (tyX.Interfaces.IsCollectionValid()) { sb.Append(" - Interfaces:\n"); foreach (TypeX infTyX in tyX.Interfaces) { sb.AppendFormat(" - {0}\n", infTyX); } } if (tyX.HasVariances) { sb.Append(" - Variances: "); foreach (var vt in tyX.Variances) { sb.AppendFormat("{0} ", vt); } sb.Append('\n'); } if (tyX.HasVarianceBaseTypes) { sb.Append(" - VarianceBaseTypes:\n"); foreach (TypeX vaTyX in tyX.VarianceBaseTypes) { sb.AppendFormat(" - {0}\n", vaTyX); } } if (tyX.DerivedTypes.IsCollectionValid()) { sb.Append(" - DerivedTypes:\n"); foreach (TypeX derivedTyX in tyX.DerivedTypes) { sb.AppendFormat(" - {0}\n", derivedTyX); } } if (tyX.Fields.IsCollectionValid()) { sb.Append(" - Fields:\n"); foreach (FieldX fldX in tyX.Fields) { sb.AppendFormat(" - {0}, {1}, {2}\n", fldX.GetNameKey() + '|' + ((uint)fldX.Def.Attributes).ToString("X"), fldX.GetReplacedNameKey(), FieldAttrToString(fldX.Def.Attributes)); } } if (tyX.Methods.IsCollectionValid()) { sb.Append(" - Methods:\n"); foreach (MethodX metX in tyX.Methods) { sb.AppendFormat(" - {0}, {1}{2}, {3}{4} {5}\n", metX.GetNameKey() + '|' + ((uint)metX.Def.Attributes).ToString("X"), metX.GetReplacedNameKey(), metX.IsProcessed ? "" : " = 0", MethodAttrToString(metX.Def.Attributes), metX.Def.ImplAttributes, metX.Def.SemanticsAttributes); if (metX.HasOverrideImpls) { foreach (var kv in metX.OverrideImpls) { MethodX overMetX = kv.Key; sb.AppendFormat(" - {0}, {1}\n", overMetX.DeclType.GetNameKey() + " -> " + overMetX.GetNameKey() + '|' + ((uint)overMetX.Def.Attributes).ToString("X"), overMetX.GetReplacedNameKey()); } } } } /*if (tyX.IsInstantiated && * tyX.VTable != null) * { * if (Helper.IsCollectionValid(tyX.VTable.Table)) * { * sb.Append(" - VTable:\n"); * foreach (var kv2 in tyX.VTable.Table) * { * sb.AppendFormat(" - [{0}]\n", kv2.Key); * foreach (var kv3 in kv2.Value) * { * if (kv3.Key == kv3.Value.Item2) * continue; * * sb.AppendFormat(" - {0}: {1} -> {2}\n", * kv3.Key, * kv3.Value.Item1, * kv3.Value.Item2); * } * } * } * * if (Helper.IsCollectionValid(tyX.VTable.MethodReplaceMap)) * { * sb.Append(" - ReplaceMap:\n"); * foreach (var kv2 in tyX.VTable.MethodReplaceMap) * { * sb.AppendFormat(" - {0} => {1}\n", kv2.Key.FullName, kv2.Value.Item2.FullName); * } * } * * if (Helper.IsCollectionValid(tyX.VTable.FallbackTable)) * { * sb.Append(" - FallbackTable:\n"); * foreach (var kv2 in tyX.VTable.FallbackTable) * { * sb.AppendFormat(" - {0} => {1}\n", kv2.Key, kv2.Value.FullName); * } * } * }*/ sb.Append('\n'); } }
private void BuildInstructions(MethodX metX) { Debug.Assert(metX.InstList == null); if (!metX.Def.HasBody || !metX.Def.Body.HasInstructions) { return; } IGenericReplacer replacer = new GenericReplacer(metX.DeclType, metX); var defInstList = metX.Def.Body.Instructions; int numInsts = defInstList.Count; InstInfo[] instList = new InstInfo[numInsts]; Dictionary <uint, int> offsetMap = new Dictionary <uint, int>(); List <InstInfo> branchInsts = new List <InstInfo>(); // 构建指令列表 for (int ip = 0; ip < numInsts; ++ip) { var defInst = defInstList[ip]; var inst = instList[ip] = new InstInfo(); inst.OpCode = defInst.OpCode; inst.Operand = defInst.Operand; inst.Offset = ip; offsetMap.Add(defInst.Offset, ip); switch (inst.OpCode.OperandType) { case OperandType.InlineBrTarget: case OperandType.ShortInlineBrTarget: case OperandType.InlineSwitch: branchInsts.Add(inst); break; default: ResolveOperand(inst, replacer); break; } } // 重定向跳转位置 foreach (var inst in branchInsts) { if (inst.Operand is Instruction defInst) { int target; inst.Operand = target = offsetMap[defInst.Offset]; instList[target].IsBrTarget = true; } else if (inst.Operand is Instruction[] defInsts) { int[] insts = new int[defInsts.Length]; for (int i = 0; i < defInsts.Length; ++i) { int target; insts[i] = target = offsetMap[defInsts[i].Offset]; instList[target].IsBrTarget = true; } inst.Operand = insts; } } // 展开异常处理信息 if (metX.Def.Body.HasExceptionHandlers) { List <Tuple <int, ExHandlerInfo> > sortedHandlers = new List <Tuple <int, ExHandlerInfo> >(); int idx = 0; foreach (var eh in metX.Def.Body.ExceptionHandlers) { ExHandlerInfo info = new ExHandlerInfo(); info.TryStart = offsetMap[eh.TryStart.Offset]; info.TryEnd = offsetMap[eh.TryEnd.Offset]; if (eh.FilterStart != null) { info.FilterStart = offsetMap[eh.FilterStart.Offset]; } else { info.FilterStart = -1; } info.HandlerStart = offsetMap[eh.HandlerStart.Offset]; if (eh.HandlerEnd != null) { info.HandlerEnd = offsetMap[eh.HandlerEnd.Offset]; } else { info.HandlerEnd = instList.Length; } if (eh.CatchType != null) { info.CatchType = ResolveTypeDefOrRef(eh.CatchType, replacer); } info.HandlerType = eh.HandlerType; sortedHandlers.Add(new Tuple <int, ExHandlerInfo>(idx++, info)); } // 根据 try 位置排序, 如果相同则根据定义顺序排序 sortedHandlers.Sort((lhs, rhs) => { int cmp = lhs.Item2.TryStart.CompareTo(rhs.Item2.TryStart); if (cmp == 0) { cmp = rhs.Item2.TryEnd.CompareTo(lhs.Item2.TryEnd); if (cmp == 0) { return(lhs.Item1.CompareTo(rhs.Item1)); } } return(cmp); }); // 合并同范围的异常处理器 List <ExHandlerInfo> handlers = new List <ExHandlerInfo>(); ExHandlerInfo headInfo = null; int count = sortedHandlers.Count; for (int i = 0; i < count; ++i) { ExHandlerInfo currInfo = sortedHandlers[i].Item2; if (headInfo != null && headInfo.NeedCombine(currInfo)) { headInfo.CombinedHandlers.Add(currInfo); } else { headInfo = currInfo; Debug.Assert(headInfo.CombinedHandlers.Count == 0); headInfo.CombinedHandlers.Add(headInfo); handlers.Add(headInfo); } instList[currInfo.HandlerOrFilterStart].IsBrTarget = true; } metX.ExHandlerList = handlers; } metX.InstList = instList; }
private void ResolveOperand(InstInfo inst, IGenericReplacer replacer) { switch (inst.OpCode.OperandType) { case OperandType.InlineMethod: { MethodX resMetX; switch (inst.Operand) { case MethodDef metDef: resMetX = ResolveMethodDef(metDef); break; case MemberRef memRef: resMetX = ResolveMethodRef(memRef, replacer); break; case MethodSpec metSpec: resMetX = ResolveMethodSpec(metSpec, replacer); break; default: throw new ArgumentOutOfRangeException(); } bool isReAddMethod = false; if (inst.OpCode.Code == Code.Newobj) { Debug.Assert(!resMetX.Def.IsStatic); Debug.Assert(resMetX.Def.IsConstructor); // 设置实例化标记 resMetX.DeclType.IsInstantiated = true; // 生成静态构造和终结器 GenStaticCctor(resMetX.DeclType); GenFinalizer(resMetX.DeclType); // 解析虚表 resMetX.DeclType.ResolveVTable(); } else if (resMetX.IsVirtual && (inst.OpCode.Code == Code.Callvirt || inst.OpCode.Code == Code.Ldvirtftn)) { // 处理非入口虚调用重定向 if (!resMetX.Def.IsNewSlot) { if (GetNewSlotMethodChecked(resMetX.DeclType, resMetX.Def, out var slotTypeName, out var slotMetDef)) { resMetX.IsSkipProcessing = true; TypeX slotTyX = GetTypeByName(slotTypeName); Debug.Assert(slotTyX != null); MethodX slotMetX = MakeMethodX(slotTyX, slotMetDef, resMetX.GenArgs); resMetX = slotMetX; } } AddVCallEntry(resMetX); } else if (resMetX.IsVirtual && (inst.OpCode.Code == Code.Call || inst.OpCode.Code == Code.Ldftn)) { // 处理方法替换 if (resMetX.DeclType.IsMethodReplaced(resMetX.Def, out var repTypeName, out var repMetDef)) { resMetX.IsSkipProcessing = true; TypeX repTyX = GetTypeByName(repTypeName); Debug.Assert(repTyX != null); MethodX repMetX = MakeMethodX(repTyX, repMetDef, resMetX.GenArgs); resMetX = repMetX; } else { isReAddMethod = true; } } else { isReAddMethod = true; } if (isReAddMethod) { // 尝试重新加入处理队列 AddPendingMethod(resMetX); } if (resMetX.IsStatic) { // 生成静态构造 GenStaticCctor(resMetX.DeclType); } inst.Operand = resMetX; return; }