Пример #1
0
        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));
            }
        }
Пример #2
0
        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();
        }
Пример #3
0
        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);
        }
Пример #4
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.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);
        }
Пример #5
0
        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();
        }
Пример #6
0
        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);
        }
Пример #7
0
        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);
        }
Пример #8
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);
        }
Пример #9
0
        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());
        }
Пример #10
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.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);
        }
Пример #11
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);
        }
Пример #12
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);
        }
Пример #13
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);
        }
Пример #14
0
        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());
        }
Пример #15
0
        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);
        }
Пример #16
0
        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);
        }
Пример #17
0
        private void GenerateCompileUnits()
        {
            List <TypeCppCode> codeSorter = new List <TypeCppCode>(CodeMap.Values);

            // 构建类型代码依赖关联
            foreach (var cppCode in codeSorter)
            {
                foreach (string typeName in cppCode.DeclDependNames)
                {
                    if (GetCodeFromMap(typeName, out var typeCode))
                    {
                        cppCode.DeclDependTypes.Add(typeCode);
                    }
                }
                cppCode.DeclDependNames = null;

                foreach (string typeName in cppCode.ImplDependNames)
                {
                    if (GetCodeFromMap(typeName, out var typeCode))
                    {
                        cppCode.ImplDependTypes.Add(typeCode);
                    }
                }
                cppCode.ImplDependNames = null;
            }
            CodeMap.Clear();

            // 统计依赖计数
            foreach (var cppCode in codeSorter)
            {
                // 预生成排序索引
                cppCode.GetSortedID();

                foreach (var typeCode in cppCode.DeclDependTypes)
                {
                    ++typeCode.DependCounter;
                }

                foreach (var typeCode in cppCode.ImplDependTypes)
                {
                    ++typeCode.DependCounter;
                }
            }

            // 排序代码
            codeSorter.Sort((x, y) =>
            {
                int cmp = x.GetSortedID().CompareTo(y.GetSortedID());
                if (cmp == 0)
                {
                    cmp = y.DependCounter.CompareTo(x.DependCounter);
                }
                return(cmp);
            });

            // 划分编译单元
            foreach (var cppCode in codeSorter)
            {
                var unit = GetCompileUnit();
                unit.AddCode(cppCode);
                cppCode.CompileUnit = unit;
            }

            StringGen.GenDefineCode(
                100,
                out var strSplitMap,
                out var strCodeMap,
                out string strTypeDefs);

            // 生成代码
            HashSet <string> dependSet = new HashSet <string>();

            foreach (var unit in CompileUnits)
            {
                // 防止包含自身
                dependSet.Add(unit.Name);

                unit.DeclCode.Append("#pragma once\n");
                unit.DeclCode.Append("#include \"il2cpp.h\"\n");

                foreach (var cppCode in unit.CodeList)
                {
                    // 生成头文件依赖包含
                    foreach (var typeCode in cppCode.DeclDependTypes)
                    {
                        string unitName = typeCode.CompileUnit.Name;
                        if (!dependSet.Contains(unitName))
                        {
                            dependSet.Add(unitName);
                            unit.DeclCode.AppendFormat("#include \"{0}.h\"\n",
                                                       unitName);
                        }
                    }
                }
                foreach (var cppCode in unit.CodeList)
                {
                    // 拼接声明代码
                    unit.DeclCode.Append(cppCode.DeclCode);
                    cppCode.DeclCode        = null;
                    cppCode.DeclDependTypes = null;
                }

                foreach (var cppCode in unit.CodeList)
                {
                    // 生成源文件依赖包含
                    foreach (var typeCode in cppCode.ImplDependTypes)
                    {
                        string unitName = typeCode.CompileUnit.Name;
                        if (!dependSet.Contains(unitName))
                        {
                            dependSet.Add(unitName);
                            unit.ImplCode.AppendFormat("#include \"{0}.h\"\n",
                                                       unitName);
                        }
                    }

                    // 生成字符串包含
                    if (strSplitMap != null &&
                        cppCode.DependStrings.Count > 0)
                    {
                        HashSet <int> strUnitSet = new HashSet <int>();
                        foreach (string str in cppCode.DependStrings)
                        {
                            strUnitSet.Add(strSplitMap[str]);
                        }
                        cppCode.DependStrings = null;

                        foreach (var strUnitId in strUnitSet)
                        {
                            string strUnit = "StringUnit_" + strUnitId;
                            unit.ImplCode.AppendFormat("#include \"{0}.h\"\n",
                                                       strUnit);
                        }
                    }
                }
                foreach (var cppCode in unit.CodeList)
                {
                    // 拼接实现代码
                    unit.ImplCode.Append(cppCode.ImplCode);
                    cppCode.ImplCode        = null;
                    cppCode.ImplDependTypes = null;
                }

                // 如果包含内容则追加头文件
                if (unit.ImplCode.Length > 0)
                {
                    unit.ImplCode.Insert(0, string.Format("#include \"{0}.h\"\n", unit.Name));
                }

                unit.CodeList = null;
                dependSet.Clear();
            }

            if (strTypeDefs.Length > 0)
            {
                foreach (var item in strCodeMap)
                {
                    var strUnit = new CppCompileUnit("StringUnit_" + item.Key);
                    CompileUnits.Add(strUnit);
                    strUnit.DeclCode.Append("#pragma once\n");
                    strUnit.DeclCode.Append("#include \"StringTypes.h\"\n");
                    strUnit.DeclCode.Append(item.Value);
                }

                var strTypeDefUnit = new CppCompileUnit("StringTypes");
                CompileUnits.Add(strTypeDefUnit);
                strTypeDefUnit.DeclCode.Append("#pragma once\n");
                strTypeDefUnit.DeclCode.Append("#include \"il2cpp.h\"\n");
                strTypeDefUnit.DeclCode.Append(strTypeDefs);
            }

            // 添加初始化静态变量的函数
            if (StaticInitBody.Length > 0)
            {
                var firstUnit = CompileUnits[0];

                string initDecl = "void il2cpp_InitStaticVars()";
                firstUnit.DeclCode.Append(initDecl + ";\n");

                CodePrinter staticInitPrt = new CodePrinter();
                staticInitPrt.Append(StaticInitDecl.ToString());
                staticInitPrt.Append(initDecl);
                staticInitPrt.AppendLine("\n{");
                ++staticInitPrt.Indents;
                staticInitPrt.Append(StaticInitBody.ToString());
                --staticInitPrt.Indents;
                staticInitPrt.AppendLine("}");

                firstUnit.ImplCode.Append(staticInitPrt);
            }
        }
Пример #18
0
        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);
        }
Пример #19
0
        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());
        }
Пример #20
0
        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("};");
                }
            }
        }