Beispiel #1
0
        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);
        }
Beispiel #2
0
        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);
        }
Beispiel #3
0
        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);
        }
Beispiel #4
0
        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);
        }