public void GenDefineCode( int splitLines, out Dictionary <string, int> strSplitMap, out Dictionary <int, StringBuilder> codeMap, out string strTypeDefs) { List <string> sortedStrs = GetSortedStrings(); strSplitMap = new Dictionary <string, int>(); codeMap = new Dictionary <int, StringBuilder>(); HashSet <int> lenSet = new HashSet <int>(); uint strTypeID = TypeGen.TypeMgr.GetTypeByName("System.String").GetCppTypeID(); int index = 0; int counter = 0; StringBuilder currSb = new StringBuilder(); codeMap.Add(index, currSb); foreach (var str in sortedStrs) { lenSet.Add(str.Length); strSplitMap.Add(str, index); currSb.Append(GenStringCode(str, strTypeID)); ++counter; if (counter >= splitLines) { counter = 0; ++index; currSb = new StringBuilder(); codeMap.Add(index, currSb); } } Reset(); var prt = new CodePrinter(); foreach (var len in lenSet) { prt.AppendFormatLine("struct il2cppString_{0}\n{{", len + 1); ++prt.Indents; prt.AppendLine("IL2CPP_OBJECT_BODY;"); prt.AppendFormatLine("int len;\nuint16_t str[{0}];", len + 1); --prt.Indents; prt.AppendLine("};"); } strTypeDefs = prt.ToString(); }
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 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); }
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)); } }
private static string GenMetaBytesLiteral(CodePrinter prt, string postfix, byte[] data, string mdataName) { string varName = string.Format("{0}_{1}", mdataName, postfix); prt.AppendFormatLine("static const uint8_t {0}_InitData[] = {1};", mdataName, Helper.ByteArrayToCode(data)); return(varName); }
private string GenStringCode(List <string> strList, uint strTypeID) { CodePrinter prt = new CodePrinter(); foreach (string str in strList) { StringProp prop = StringMap[str]; string strAry = StringToArrayOrRaw(str, out bool isRaw); prt.AppendFormatLine("// {0}", EscapeString(str)); prt.AppendFormatLine("static const struct {{ cls_Object obj; int32_t len; {5} str[{0}]; }} {1} {{ {{{2}}}, {3}, {4} }};", str.Length + 1, GetConstName(prop.ConstIndex), strTypeID, str.Length, strAry, isRaw ? "char16_t" : "uint16_t"); } return(prt.ToString()); }
private static string GenMetaStringLiteral(CodePrinter prt, string postfix, string str, string mdataName) { string strNameData = StringGenerator.StringToArrayOrRaw(str, out bool isRaw); string varName = string.Format("{0}_{1}", mdataName, postfix); prt.AppendFormatLine("static const {0} {1}[] = {2};", isRaw ? "char16_t" : "uint16_t", varName, strNameData); return(varName); }
private void GenIsinstCode(TypeX currType, out string codeDecl, out string codeImpl) { List <TypeX> sortedTypes = new List <TypeX>(); if (currType.IsInstanced) { sortedTypes.Add(currType); } foreach (var tyX in currType.DerivedTypes) { if (tyX.IsInstanced) { sortedTypes.Add(tyX); } } sortedTypes.Sort((x, y) => x.GetCppTypeID().CompareTo(y.GetCppTypeID())); CodePrinter prt = new CodePrinter(); prt.AppendFormat("bool isinst_{0}(uint32_t typeID)", currType.GetCppName()); codeDecl = prt + ";\n"; prt.AppendLine("\n{"); ++prt.Indents; prt.AppendLine("switch (typeID)\n{"); ++prt.Indents; foreach (var tyX in sortedTypes) { prt.AppendFormatLine("// {0}\ncase {1}:", tyX.PrettyName(), tyX.GetCppTypeID()); } ++prt.Indents; prt.AppendLine("return true;"); prt.Indents -= 2; prt.AppendLine("}"); prt.AppendLine("return false;"); --prt.Indents; prt.AppendLine("}"); codeImpl = prt.ToString(); }
private CompileUnit GenInitUnit(Dictionary <string, string> transMap) { CompileUnit unit = new CompileUnit(); unit.Name = "il2cppInit"; CodePrinter prtGC = new CodePrinter(); CodePrinter prtInit = new CodePrinter(); bool addedRoots = false; foreach (var kv in InitFldsMap) { unit.ImplDepends.Add(transMap[kv.Key]); foreach (var item in kv.Value) { if (item.Item2) { prtGC.AppendFormatLine("IL2CPP_ADD_ROOT({0}),", item.Item1); addedRoots = true; } prtInit.AppendFormatLine("{0} = {{}};", item.Item1); } } CodePrinter prtFunc = new CodePrinter(); prtFunc.AppendLine("void il2cpp_InitVariables()\n{"); ++prtFunc.Indents; if (addedRoots) { prtFunc.AppendLine("il2cppRootItem roots[] =\n{"); ++prtFunc.Indents; prtFunc.Append(prtGC.ToString()); --prtFunc.Indents; prtFunc.AppendLine("};"); prtFunc.AppendLine("il2cpp_CommitRoots(roots, sizeof(roots) / sizeof(roots[0]));"); } prtFunc.Append(prtInit.ToString()); --prtFunc.Indents; prtFunc.AppendLine("}"); unit.ImplCode = prtFunc.ToString(); return(unit); }
public CompileUnit Generate() { CompileUnit unit = new CompileUnit(); string strTypeName = GenContext.GetTypeName(CurrType, false); unit.Name = strTypeName; // 重排字段 var fields = LayoutFields(out var sfields); string nameKey = CurrType.GetNameKey(); bool currIsObject = nameKey == "Object"; // 生成类结构 CodePrinter prtDecl = new CodePrinter(); if (!CurrType.IsEnumType) { prtDecl.AppendFormatLine("// {0}", Helper.EscapeString(nameKey)); ushort packSize = CurrType.Def.HasClassLayout ? CurrType.Def.PackingSize : (ushort)0; if (packSize > 2 && !Helper.IsPowerOfTwo(packSize)) { throw new TypeLoadException(); } if (packSize != 0) { prtDecl.AppendLine("#if defined(IL2CPP_MSVC_LIKE)"); prtDecl.AppendFormatLine("#pragma pack(push, {0})", packSize); prtDecl.AppendLine("#endif"); } var baseType = CurrType.BaseType; // 值类型不继承任何基类 if (CurrType.IsValueType) { baseType = null; } // 接口类型继承 object if (baseType == null && CurrType.Def.IsInterface) { baseType = GenContext.GetTypeByName("Object"); } if (baseType != null) { string strBaseTypeName = GenContext.GetTypeName(baseType); unit.DeclDepends.Add(strBaseTypeName); prtDecl.AppendFormatLine("struct {0} : {1}", strTypeName, strBaseTypeName); } else { prtDecl.AppendFormatLine("struct {0}", strTypeName); } prtDecl.AppendLine("{"); ++prtDecl.Indents; // 生成对象内置字段 if (CurrType.IsArrayType) { var arrayInfo = CurrType.ArrayInfo; if (!arrayInfo.IsSZArray) { uint rank = arrayInfo.Rank; for (int i = 0; i < rank; ++i) { prtDecl.AppendFormatLine("int32_t LowerBound{0};\nuint32_t Size{0};", i); } } } else { if (currIsObject) { prtDecl.AppendLine("uint32_t TypeID;"); prtDecl.AppendLine("uint8_t Flags[4];"); } else if (nameKey == "System.Array") { prtDecl.AppendLine("uint32_t Length;"); prtDecl.AppendLine("uint32_t ElemSize : 24;"); prtDecl.AppendLine("uint32_t Rank : 8;"); } } bool isExplicitLayout = CurrType.Def.IsExplicitLayout; uint classSize = CurrType.Def.ClassSize; bool hasStructSize = CurrType.Def.HasClassLayout && classSize != 0; if (isExplicitLayout || hasStructSize) { prtDecl.AppendLine("union\n{"); ++prtDecl.Indents; if (!isExplicitLayout && fields.Count != 0) { prtDecl.AppendLine("struct\n{"); ++prtDecl.Indents; } } int fldCounter = 0; // 生成字段 foreach (var fldX in fields) { RefValueTypeDecl(unit, fldX.FieldType); bool isFieldExLayout = isExplicitLayout && fldX.Def.FieldOffset != 0; if (isFieldExLayout) { prtDecl.AppendLine("struct\n{"); ++prtDecl.Indents; prtDecl.AppendFormatLine("uint8_t padding_{0}[{1}];", fldCounter, fldX.Def.FieldOffset); } prtDecl.AppendLine("// " + fldX.GetReplacedNameKey()); prtDecl.AppendFormatLine("{0} {1};", GenContext.GetTypeName(fldX.FieldType), GenContext.GetFieldName(fldX)); if (isFieldExLayout) { --prtDecl.Indents; prtDecl.AppendLine("};"); } ++fldCounter; } if (isExplicitLayout || hasStructSize) { if (!isExplicitLayout && fields.Count != 0) { --prtDecl.Indents; prtDecl.AppendLine("};"); } if (hasStructSize) { prtDecl.AppendFormatLine("uint8_t padding_struct[{0}];", classSize); } --prtDecl.Indents; prtDecl.AppendLine("};"); } --prtDecl.Indents; if (packSize != 0) { prtDecl.AppendFormatLine("}} IL2CPP_PACKED_TAIL({0});", packSize); } else { prtDecl.AppendLine("};"); } if (packSize != 0) { prtDecl.AppendLine("#if defined(IL2CPP_MSVC_LIKE)"); prtDecl.AppendLine("#pragma pack(pop)"); prtDecl.AppendLine("#endif"); } } CodePrinter prtImpl = new CodePrinter(); // 生成静态字段 foreach (var sfldX in sfields) { RefValueTypeDecl(unit, sfldX.FieldType); string sfldName = GenContext.GetFieldName(sfldX); string fldDecl = string.Format("{0} {1};", GenContext.GetTypeName(sfldX.FieldType), sfldName); prtDecl.AppendFormatLine("// {0} -> {1}", Helper.EscapeString(sfldX.DeclType.GetNameKey()), Helper.EscapeString(sfldX.GetReplacedNameKey())); prtDecl.AppendLine("extern " + fldDecl); prtImpl.AppendLine(fldDecl); bool hasRef = GenContext.IsRefOrContainsRef(GenContext.GetTypeBySig(sfldX.FieldType)); GenContext.AddStaticField(strTypeName, sfldName, hasRef); } // 生成类型判断函数 GenIsTypeFunc(prtDecl, prtImpl, currIsObject); // 生成方法 foreach (MethodX metX in CurrType.Methods) { var metGen = new MethodGenerator(GenContext, metX); metGen.Generate(); AppendRuntimeFlags(metX, prtDecl); prtDecl.AppendFormatLine("// {0}{1}{2} -> {3}", Helper.IsExtern(metX.Def) ? "extern " : null, metX.Def.IsInternalCall ? "internalcall " : null, Helper.EscapeString(metX.DeclType.GetNameKey()), Helper.EscapeString(metX.GetReplacedNameKey())); prtDecl.Append(metGen.DeclCode); unit.DeclDepends.UnionWith(metGen.DeclDepends); prtImpl.Append(metGen.ImplCode); unit.ImplDepends.UnionWith(metGen.ImplDepends); unit.StringDepends.UnionWith(metGen.StringDepends); } GenerateMetadata(prtDecl, prtImpl); unit.DeclCode = prtDecl.ToString(); unit.ImplCode = prtImpl.ToString(); return(unit); }
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); }
public CompileUnit Generate() { CompileUnit unit = new CompileUnit(); unit.Name = GenContext.GetTypeName(CurrType); // 重排字段 var fields = LayoutFields(out var sfields); // 生成类结构 CodePrinter prtDecl = new CodePrinter(); if (!CurrType.IsEnumType) { prtDecl.AppendFormatLine("// {0}", CurrType.GetNameKey()); var baseType = CurrType.BaseType; // 值类型不继承任何基类 if (CurrType.IsValueType) { baseType = null; } // 接口类型继承 object if (baseType == null && CurrType.Def.IsInterface) { baseType = GenContext.TypeMgr.GetTypeByName("Object"); } if (baseType != null) { string strBaseTypeName = GenContext.GetTypeName(baseType); unit.DeclDepends.Add(strBaseTypeName); prtDecl.AppendFormatLine("struct {0} : {1}", GenContext.GetTypeName(CurrType), strBaseTypeName); } else { prtDecl.AppendFormatLine("struct {0}", GenContext.GetTypeName(CurrType)); } prtDecl.AppendLine("{"); ++prtDecl.Indents; // 生成对象内置字段 if (CurrType.IsArrayType) { var arrayInfo = CurrType.ArrayInfo; if (arrayInfo.IsSZArray) { prtDecl.AppendLine("int32_t Length;"); } else { uint rank = arrayInfo.Rank; for (int i = 0; i < rank; ++i) { prtDecl.AppendFormatLine("int32_t LowerBound{0};\nint32_t Size{0};", i); } } } else { string nameKey = CurrType.GetNameKey(); if (nameKey == "Object") { prtDecl.AppendLine("uint32_t TypeID;"); } else if (nameKey == "System.Array") { prtDecl.AppendLine("int32_t Rank;"); } } // 生成字段 foreach (var fldX in fields) { RefValueTypeDecl(unit, fldX.FieldType); prtDecl.AppendLine("// " + fldX.GetReplacedNameKey()); prtDecl.AppendFormatLine("{0} {1};", GenContext.GetTypeName(fldX.FieldType), GenContext.GetFieldName(fldX)); } --prtDecl.Indents; prtDecl.AppendLine("};"); } CodePrinter prtImpl = new CodePrinter(); // 生成类型判断函数 GenerateIsType(prtDecl, prtImpl); // 生成静态字段 foreach (var sfldX in sfields) { RefValueTypeDecl(unit, sfldX.FieldType); string fldDecl = string.Format("{0} {1};", GenContext.GetTypeName(sfldX.FieldType), GenContext.GetFieldName(sfldX)); prtDecl.AppendFormatLine("// {0} -> {1}", sfldX.DeclType.GetNameKey(), sfldX.GetReplacedNameKey()); prtDecl.AppendLine("extern " + fldDecl); prtImpl.AppendLine(fldDecl); } // 生成方法 foreach (MethodX metX in CurrType.Methods) { var metGen = new MethodGenerator(GenContext, metX); metGen.Generate(); prtDecl.AppendFormatLine("// {0} -> {1}", metX.DeclType.GetNameKey(), metX.GetReplacedNameKey()); prtDecl.Append(metGen.DeclCode); unit.DeclDepends.UnionWith(metGen.DeclDepends); prtImpl.Append(metGen.ImplCode); unit.ImplDepends.UnionWith(metGen.ImplDepends); unit.StringDepends.UnionWith(metGen.StringDepends); } unit.DeclCode = prtDecl.ToString(); unit.ImplCode = prtImpl.ToString(); return(unit); }
private void GenerateIsType(CodePrinter prtDecl, CodePrinter prtImpl) { if (CurrType.IsValueType) { return; } CodePrinter prt = new CodePrinter(); prt.AppendFormat("uint8_t istype_{0}(uint32_t typeID)", GenContext.GetTypeName(CurrType)); string strDecl = prt.ToString() + ";\n"; prt.AppendLine("\n{"); ++prt.Indents; var derivedRange = new List <TypeX>(CurrType.DerivedTypes); derivedRange.Add(CurrType); List <TypeX> derTypes = new List <TypeX>(); foreach (var derTyX in derivedRange) { // 跳过不分配在堆上的类型 if (!derTyX.IsInstantiated || derTyX.IsValueType || derTyX.Def.IsInterface) { continue; } derTypes.Add(derTyX); } if (derTypes.Count > 0) { prt.AppendLine("switch (typeID)\n{"); ++prt.Indents; derTypes.Sort((lhs, rhs) => GenContext.GetTypeID(lhs).CompareTo(GenContext.GetTypeID(rhs))); foreach (var derTyX in derTypes) { prt.AppendFormatLine("// {0}", derTyX.GetNameKey()); prt.AppendFormatLine("case {0}:", GenContext.GetTypeID(derTyX)); } ++prt.Indents; prt.AppendLine("return 1;"); --prt.Indents; --prt.Indents; prt.AppendLine("}"); } prt.AppendLine("return 0;"); --prt.Indents; prt.AppendLine("}"); prtDecl.Append(strDecl); prtImpl.Append(prt.ToString()); }
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); }
private TypeCppCode GenDeclCode(TypeX currType) { CodePrinter prt = new CodePrinter(); // 构造类型注释 prt.AppendFormatLine("// {0}", currType.PrettyName()); // 构造类型结构体代码 string typeName; string baseTypeName = null; if (currType.BaseType != null && !currType.Def.IsValueType) { baseTypeName = currType.BaseType.GetCppName(); typeName = currType.GetCppName(); prt.AppendFormatLine("struct {0} : {1}\n{{", typeName, baseTypeName); } else if (currType.Def.ToTypeSig().IsObjectSig()) { typeName = currType.GetCppName(); prt.AppendFormatLine("struct {0} : il2cppObject\n{{", typeName); } else { Debug.Assert( currType.Def.IsValueType || currType.Def.IsInterface); typeName = currType.GetCppName(); prt.AppendFormatLine("struct {0}\n{{", typeName); } // 添加代码映射 TypeCppCode cppCode = new TypeCppCode(typeName); CodeMap.Add(typeName, cppCode); // 添加基类型依赖 if (baseTypeName != null) { cppCode.DeclDependNames.Add(baseTypeName); } ++prt.Indents; // 构造结构体成员 List <FieldX> staticFields = new List <FieldX>(); foreach (var fldX in currType.Fields) { if (fldX.Def.IsStatic) { staticFields.Add(fldX); continue; } string fieldTypeName = fldX.FieldType.GetCppName(TypeMgr); prt.AppendFormatLine("// {0}\n{1} {2};", fldX.PrettyName(), fieldTypeName, fldX.GetCppName()); // 添加字段类型依赖 if (fldX.FieldType.IsValueType) { cppCode.DeclDependNames.Add(fieldTypeName); } } --prt.Indents; prt.AppendLine("};"); // 构造装箱类型 if (currType.Def.IsValueType) { prt.AppendFormatLine("struct box_{0} : il2cppObject\n{{", typeName); ++prt.Indents; prt.AppendFormatLine("{0} value;", currType.ToTypeSig().GetCppName(TypeMgr)); --prt.Indents; prt.AppendLine("};"); } // 构造静态字段全局变量 StringBuilder sbImpl = new StringBuilder(); foreach (var sfldX in staticFields) { string sfldTypeName = sfldX.FieldType.GetCppName(TypeMgr); string sfldCppName = sfldX.GetCppName(); string sfldPrettyName = sfldX.PrettyName(true); string sfldDef = string.Format("{0} {1};\n", sfldTypeName, sfldCppName); prt.AppendFormat("// {0}\nextern {1}", sfldPrettyName, sfldDef); sbImpl.AppendFormat("// {0}\n{1}", sfldPrettyName, sfldDef); StaticInitDecl.Append("extern " + sfldDef); StaticInitBody.AppendFormat("{0} = {1};\n", sfldCppName, sfldX.FieldType.GetInitValue(TypeMgr)); // 添加字段类型依赖 if (sfldX.FieldType.IsValueType) { cppCode.DeclDependNames.Add(sfldTypeName); cppCode.ImplDependNames.Add(sfldTypeName); } } // 静态构造函数防止多次调用的标记 if (currType.CctorMethod != null) { string onceName = string.Format("onceflag_{0}", typeName); string onceDef = string.Format("int8_t {0};\n", onceName); string locktidName = string.Format("locktid_{0}", typeName); string locktidDef = string.Format("uintptr_t {0};\n", locktidName); prt.Append("extern " + onceDef); prt.Append("extern " + locktidDef); sbImpl.Append(onceDef); sbImpl.Append(locktidDef); StaticInitDecl.Append("extern " + onceDef); StaticInitDecl.Append("extern " + locktidDef); StaticInitBody.AppendFormat("{0} = 0;\n", onceName); StaticInitBody.AppendFormat("{0} = 0;\n", locktidName); } cppCode.DeclCode.Append(prt); cppCode.ImplCode.Append(sbImpl); return(cppCode); }
public CompileUnit Generate() { CompileUnit unit = new CompileUnit(); unit.Name = GenContext.GetTypeName(CurrType, false); // 重排字段 var fields = LayoutFields(out var sfields); string nameKey = CurrType.GetNameKey(); bool currIsObject = nameKey == "Object"; // 生成类结构 CodePrinter prtDecl = new CodePrinter(); if (!CurrType.IsEnumType) { prtDecl.AppendFormatLine("// {0}", nameKey); var baseType = CurrType.BaseType; // 值类型不继承任何基类 if (CurrType.IsValueType) { baseType = null; } // 接口类型继承 object if (baseType == null && CurrType.Def.IsInterface) { baseType = GenContext.TypeMgr.GetTypeByName("Object"); } if (baseType != null) { string strBaseTypeName = GenContext.GetTypeName(baseType); unit.DeclDepends.Add(strBaseTypeName); prtDecl.AppendFormatLine("struct {0} : {1}", GenContext.GetTypeName(CurrType), strBaseTypeName); } else { prtDecl.AppendFormatLine("struct {0}", GenContext.GetTypeName(CurrType)); } prtDecl.AppendLine("{"); ++prtDecl.Indents; // 生成对象内置字段 if (CurrType.IsArrayType) { var arrayInfo = CurrType.ArrayInfo; if (!arrayInfo.IsSZArray) { uint rank = arrayInfo.Rank; for (int i = 0; i < rank; ++i) { prtDecl.AppendFormatLine("int32_t LowerBound{0};\nuint32_t Size{0};", i); } } } else { if (currIsObject) { prtDecl.AppendLine("uint32_t TypeID;"); prtDecl.AppendLine("uint8_t Flags[4];"); } else if (nameKey == "System.Array") { prtDecl.AppendLine("uintptr_t Length;"); prtDecl.AppendLine("uint32_t Rank;"); prtDecl.AppendLine("uint32_t ElemSize;"); } } bool isExplicitLayout = CurrType.Def.IsExplicitLayout; uint classSize = CurrType.Def.ClassSize; bool hasStructSize = CurrType.Def.HasClassLayout && classSize != 0; if (isExplicitLayout || hasStructSize) { prtDecl.AppendLine("union\n{"); ++prtDecl.Indents; if (!isExplicitLayout && fields.Count != 0) { prtDecl.AppendLine("struct\n{"); ++prtDecl.Indents; } } int fldCounter = 0; // 生成字段 foreach (var fldX in fields) { RefValueTypeDecl(unit, fldX.FieldType); bool isFieldExLayout = isExplicitLayout && fldX.Def.FieldOffset != 0; if (isFieldExLayout) { prtDecl.AppendLine("struct\n{"); ++prtDecl.Indents; prtDecl.AppendFormatLine("uint8_t padding_{0}[{1}];", fldCounter, fldX.Def.FieldOffset); } prtDecl.AppendLine("// " + fldX.GetReplacedNameKey()); prtDecl.AppendFormatLine("{0} {1};", GenContext.GetTypeName(fldX.FieldType), GenContext.GetFieldName(fldX)); if (isFieldExLayout) { --prtDecl.Indents; prtDecl.AppendLine("};"); } ++fldCounter; } if (isExplicitLayout || hasStructSize) { if (!isExplicitLayout && fields.Count != 0) { --prtDecl.Indents; prtDecl.AppendLine("};"); } if (hasStructSize) { prtDecl.AppendFormatLine("uint8_t padding_struct[{0}];", classSize); } --prtDecl.Indents; prtDecl.AppendLine("};"); } --prtDecl.Indents; prtDecl.AppendLine("};"); } CodePrinter prtImpl = new CodePrinter(); // 生成类型判断函数 GenerateIsType(prtDecl, prtImpl, currIsObject); // 生成静态字段 foreach (var sfldX in sfields) { RefValueTypeDecl(unit, sfldX.FieldType); string fldDecl = string.Format("{0} {1};", GenContext.GetTypeName(sfldX.FieldType), GenContext.GetFieldName(sfldX)); prtDecl.AppendFormatLine("// {0} -> {1}", sfldX.DeclType.GetNameKey(), sfldX.GetReplacedNameKey()); prtDecl.AppendLine("extern " + fldDecl); prtImpl.AppendLine(fldDecl); } // 生成方法 foreach (MethodX metX in CurrType.Methods) { var metGen = new MethodGenerator(GenContext, metX); metGen.Generate(); AppendRuntimeFlags(metX, prtDecl); prtDecl.AppendFormatLine("// {0}{1}{2} -> {3}", !metX.Def.HasBody && !metX.Def.IsAbstract ? "extern " : null, metX.Def.IsInternalCall ? "internalcall " : null, metX.DeclType.GetNameKey(), metX.GetReplacedNameKey()); prtDecl.Append(metGen.DeclCode); unit.DeclDepends.UnionWith(metGen.DeclDepends); prtImpl.Append(metGen.ImplCode); unit.ImplDepends.UnionWith(metGen.ImplDepends); unit.StringDepends.UnionWith(metGen.StringDepends); } unit.DeclCode = prtDecl.ToString(); unit.ImplCode = prtImpl.ToString(); return(unit); }
private void GenIsTypeFunc(CodePrinter prtDecl, CodePrinter prtImpl, bool currIsObject) { if (CurrType.IsValueType || !CurrType.NeedGenIsType) { return; } CodePrinter prt = new CodePrinter(); prt.AppendFormat("uint8_t {0}(uint32_t typeID)", GenContext.GetIsTypeFuncName(CurrType)); string strDecl = prt.ToString() + ";\n"; prt.AppendLine("\n{"); ++prt.Indents; var derivedRange = new List <TypeX>(CurrType.DerivedTypes); derivedRange.Add(CurrType); var derivedEnumTypes = CurrType.UnBoxedType?.DerivedEnumTypes; if (derivedEnumTypes != null) { derivedRange.AddRange(derivedEnumTypes); } List <TypeX> derTypes = new List <TypeX>(); foreach (var derTyX in derivedRange) { // 跳过不分配在堆上的类型 if (!derTyX.IsInstantiated || derTyX.Def.IsInterface) { continue; } // 如果当前类型是 object, 则跳过值类型 if (currIsObject && derTyX.IsValueType) { continue; } derTypes.Add(derTyX); } if (derTypes.Count > 0) { prt.AppendLine("switch (typeID)\n{"); ++prt.Indents; derTypes.Sort((lhs, rhs) => GenContext.GetTypeID(lhs).CompareTo(GenContext.GetTypeID(rhs))); foreach (var derTyX in derTypes) { prt.AppendFormatLine("// {0}", Helper.EscapeString(derTyX.GetNameKey())); prt.AppendFormatLine("case {0}:", GenContext.GetTypeID(derTyX)); } ++prt.Indents; prt.AppendLine("return 1;"); --prt.Indents; --prt.Indents; prt.AppendLine("}"); } prt.AppendLine("return 0;"); --prt.Indents; prt.AppendLine("}"); prtDecl.Append(strDecl); prtImpl.Append(prt.ToString()); }
private void GenerateMetadata(CodePrinter prtDecl, CodePrinter prtImpl) { if (CurrType.GenMetadata) { string strMDataName = GenContext.GetMetaName(CurrType, true); string strDecl = string.Format("il2cppTypeInfo {0}", GenContext.GetMetaName(CurrType)); prtDecl.AppendFormatLine("extern {0};", strDecl); string varName = GenMetaStringLiteral(prtImpl, "Name", CurrType.Def.Name, strMDataName); string varNamespace = GenMetaStringLiteral(prtImpl, "Namespace", CurrType.Def.Namespace, strMDataName); prtImpl.AppendFormatLine("{0} =", strDecl); prtImpl.AppendLine("{"); ++prtImpl.Indents; prtImpl.AppendFormatLine("(uint16_t*){0},", varName); prtImpl.AppendFormatLine("(uint16_t*){0},", varNamespace); --prtImpl.Indents; prtImpl.AppendLine("};"); } foreach (var metX in CurrType.Methods) { if (metX.GenMetadata) { string strMDataName = GenContext.GetMetaName(metX, true); string strDecl = string.Format("il2cppMethodInfo {0}", GenContext.GetMetaName(metX)); prtDecl.AppendFormatLine("extern {0};", strDecl); string varName = GenMetaStringLiteral(prtImpl, "Name", metX.Def.Name, strMDataName); prtImpl.AppendFormatLine("{0} =", strDecl); prtImpl.AppendLine("{"); ++prtImpl.Indents; prtImpl.AppendFormatLine("(uint16_t*){0},", varName); --prtImpl.Indents; prtImpl.AppendLine("};"); } } foreach (var fldX in CurrType.Fields) { if (fldX.GenMetadata) { string strMDataName = GenContext.GetMetaName(fldX, true); string strDecl = string.Format("il2cppFieldInfo {0}", GenContext.GetMetaName(fldX)); prtDecl.AppendFormatLine("extern {0};", strDecl); string varName = GenMetaStringLiteral(prtImpl, "Name", fldX.Def.Name, strMDataName); var initValue = fldX.Def.InitialValue; bool hasInitValue = initValue != null && initValue.Length > 0; string varInitData = null; if (hasInitValue) { varInitData = GenMetaBytesLiteral(prtImpl, "InitData", initValue, strMDataName); } prtImpl.AppendFormatLine("{0} =", strDecl); prtImpl.AppendLine("{"); ++prtImpl.Indents; prtImpl.AppendFormatLine("(uint16_t*){0},", varName); prtImpl.AppendLine("nullptr,"); prtImpl.AppendLine("nullptr,"); prtImpl.AppendLine("nullptr,"); prtImpl.AppendLine("{"); ++prtImpl.Indents; if (hasInitValue) { prtImpl.AppendFormatLine("{0},\n{1}", varInitData, initValue.Length); } else { prtImpl.AppendLine("nullptr,\n0"); } --prtImpl.Indents; prtImpl.AppendLine("},"); prtImpl.AppendFormatLine("{0},", (uint)fldX.Def.Attributes); if (fldX.IsInstance && !CurrType.IsEnumType) { prtImpl.AppendFormatLine("IL2CPP_OFFSETOF(&{0}::{1})", GenContext.GetTypeName(CurrType), GenContext.GetFieldName(fldX)); } else { prtImpl.AppendLine("0"); } --prtImpl.Indents; prtImpl.AppendLine("};"); } } }