Пример #1
0
 public string GetMetaName(FieldX fldX, bool isData = false)
 {
     return(string.Format("{0}{1}{2}",
                          isData ? "mdata_" : "meta_",
                          fldX.IsStatic ? null : GetTypeName(fldX.DeclType, false) + '_',
                          GetFieldName(fldX)));
 }
Пример #2
0
        public string GetFieldName(FieldX fldX)
        {
            string strName = fldX.GeneratedFieldName;

            if (strName == null)
            {
                string prefix = fldX.IsStatic ? "sfld_" : "fld_";

                string middle = null;
                if (fldX.IsStatic)
                {
                    int hashCode = Helper.CombineHash(
                        fldX.GetNameKey().GetHashCode(),
                        fldX.GetReplacedNameKey().GetHashCode(),
                        fldX.DeclType.GetNameKey().GetHashCode(),
                        (int)fldX.Def.Rid);

                    middle = NameHash(hashCode) + '_' +
                             GetNameWithGen(fldX.DeclType.Def.Name, fldX.DeclType.GenArgs);
                }
                else
                {
                    middle = fldX.GetDefOrder().ToString();
                }

                strName = prefix + middle + '_' + fldX.Def.Name;

                fldX.GeneratedFieldName = strName = EscapeName(strName);
            }
            return(strName);
        }
Пример #3
0
 public static string GetCppName(this FieldX fldX)
 {
     if (fldX.CppName_ == null)
     {
         fldX.CppName_ = fldX.Def.IsStatic ?
                         "sfld_" + ToCppName(fldX.DeclType.FullName + "::" + fldX.Def.Name) :
                         "fld_" + ToCppName(fldX.Def.Name);
     }
     return(fldX.CppName_);
 }
Пример #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
        public static string PrettyName(this FieldX self, bool hasDeclType = false)
        {
            StringBuilder sb = new StringBuilder();

            if (self.Def.IsStatic)
            {
                sb.Append("static ");
            }

            PrettyName(sb, self.FieldType, true);
            sb.AppendFormat(" {0}{1}",
                            hasDeclType ? self.DeclType.PrettyName() + "::" : "",
                            self.Def.Name);
            return(sb.ToString());
        }
Пример #6
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);
        }
Пример #7
0
        public string GetFieldName(FieldX fldX)
        {
            string strName = fldX.GeneratedFieldName;

            if (strName == null)
            {
                string prefix = fldX.IsStatic ? "sfld_" : "fld_";

                if (!fldX.DeclType.HasGenArgs && fldX.DeclType.Def.DefinitionAssembly.IsCorLib())
                {
                    string middle = null;
                    if (fldX.IsStatic)
                    {
                        middle = GetNameWithGen(fldX.DeclType.Def.Name, fldX.DeclType.GenArgs) +
                                 "__";
                    }

                    strName = prefix + middle + fldX.Def.Name;
                }
                else
                {
                    string middle = null;
                    if (fldX.IsStatic)
                    {
                        int hashCode = Helper.CombineHash(
                            fldX.GetNameKey().GetHashCode(),
                            fldX.GetReplacedNameKey().GetHashCode(),
                            fldX.DeclType.GetNameKey().GetHashCode());
                        middle = NameHash(hashCode) + '_' +
                                 GetNameWithGen(fldX.DeclType.Def.Name, fldX.DeclType.GenArgs);
                    }
                    else
                    {
                        middle = NameHash((int)fldX.Def.Rid);
                    }

                    strName = prefix + middle + "__" + fldX.Def.Name;
                }

                fldX.GeneratedFieldName = strName = EscapeName(strName);
            }
            return(strName);
        }
Пример #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.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);
        }
Пример #9
0
 public void AddField(string key, FieldX fldX)
 {
     FieldMap.Add(key, fldX);
 }
Пример #10
0
 public bool GetField(string key, out FieldX fldX)
 {
     return(FieldMap.TryGetValue(key, out fldX));
 }
Пример #11
0
        private void ResolveOperand(InstInfo inst, IGenericReplacer replacer)
        {
            // 预处理指令
            switch (inst.OpCode.Code)
            {
            case Code.Ldstr:
                // 解析 System.String 类型
                if (!IsStringTypeResolved)
                {
                    IsStringTypeResolved = true;
                    if (!TypeMap.ContainsKey("String"))
                    {
                        TypeX strTyX = ResolveTypeDefOrRef(Context.CorLibTypes.String.ToTypeDefOrRef(), null);
                        foreach (FieldDef fldDef in strTyX.Def.Fields)
                        {
                            if (!fldDef.IsStatic)
                            {
                                FieldX fldX = new FieldX(strTyX, fldDef);
                                AddField(fldX);
                            }
                        }
                        strTyX.IsInstantiated = true;
                    }
                }
                break;

            case Code.Newarr:
            {
                // newobj T[]::.ctor(int)
                TypeSig elemSig = ((ITypeDefOrRef)inst.Operand).ToTypeSig();
                inst.OpCode  = OpCodes.Newobj;
                inst.Operand = new MemberRefUser(
                    Context.CorLibModule,
                    ".ctor",
                    MethodSig.CreateInstance(Context.CorLibTypes.Void, Context.CorLibTypes.Int32),
                    new TypeSpecUser(new SZArraySig(elemSig)));
                break;
            }

            case Code.Ldlen:
            {
                // call int Array::get_Length()
                inst.OpCode  = OpCodes.Call;
                inst.Operand = new MemberRefUser(
                    Context.CorLibModule,
                    "get_Length",
                    MethodSig.CreateInstance(Context.CorLibTypes.Int32),
                    Context.CorLibTypes.GetTypeRef("System", "Array"));
                break;
            }

            case Code.Ldelema:
            {
                // call T& T[]::Address(int)
                TypeSig elemSig = ((ITypeDefOrRef)inst.Operand).ToTypeSig();
                inst.OpCode  = OpCodes.Call;
                inst.Operand = new MemberRefUser(
                    Context.CorLibModule,
                    "Address",
                    MethodSig.CreateInstance(new ByRefSig(elemSig), Context.CorLibTypes.Int32),
                    new TypeSpecUser(new SZArraySig(elemSig)));
                break;
            }

            case Code.Ldelem_I1:
            case Code.Ldelem_U1:
            case Code.Ldelem_I2:
            case Code.Ldelem_U2:
            case Code.Ldelem_I4:
            case Code.Ldelem_U4:
            case Code.Ldelem_I8:
            case Code.Ldelem_I:
            case Code.Ldelem_R4:
            case Code.Ldelem_R8:
            case Code.Ldelem_Ref:
            case Code.Ldelem:
            {
                TypeSig elemSig = null;
                switch (inst.OpCode.Code)
                {
                case Code.Ldelem_I1:
                    elemSig = Context.CorLibTypes.SByte;
                    break;

                case Code.Ldelem_U1:
                    elemSig = Context.CorLibTypes.Byte;
                    break;

                case Code.Ldelem_I2:
                    elemSig = Context.CorLibTypes.Int16;
                    break;

                case Code.Ldelem_U2:
                    elemSig = Context.CorLibTypes.UInt16;
                    break;

                case Code.Ldelem_I4:
                    elemSig = Context.CorLibTypes.Int32;
                    break;

                case Code.Ldelem_U4:
                    elemSig = Context.CorLibTypes.UInt32;
                    break;

                case Code.Ldelem_I8:
                    elemSig = Context.CorLibTypes.Int64;
                    break;

                case Code.Ldelem_I:
                    elemSig = Context.CorLibTypes.IntPtr;
                    break;

                case Code.Ldelem_R4:
                    elemSig = Context.CorLibTypes.Single;
                    break;

                case Code.Ldelem_R8:
                    elemSig = Context.CorLibTypes.Double;
                    break;

                case Code.Ldelem_Ref:
                    elemSig = Context.CorLibTypes.Object;
                    break;

                case Code.Ldelem:
                    elemSig = ((ITypeDefOrRef)inst.Operand).ToTypeSig();
                    break;
                }
                // call T T[]::Get(int)
                inst.OpCode  = OpCodes.Call;
                inst.Operand = new MemberRefUser(
                    Context.CorLibModule,
                    "Get",
                    MethodSig.CreateInstance(elemSig, Context.CorLibTypes.Int32),
                    new TypeSpecUser(new SZArraySig(elemSig)));
                break;
            }

            case Code.Stelem_I1:
            case Code.Stelem_I2:
            case Code.Stelem_I4:
            case Code.Stelem_I8:
            case Code.Stelem_I:
            case Code.Stelem_R4:
            case Code.Stelem_R8:
            case Code.Stelem_Ref:
            case Code.Stelem:
            {
                TypeSig elemSig = null;
                switch (inst.OpCode.Code)
                {
                case Code.Stelem_I1:
                    elemSig = Context.CorLibTypes.SByte;
                    break;

                case Code.Stelem_I2:
                    elemSig = Context.CorLibTypes.Int16;
                    break;

                case Code.Stelem_I4:
                    elemSig = Context.CorLibTypes.Int32;
                    break;

                case Code.Stelem_I8:
                    elemSig = Context.CorLibTypes.Int64;
                    break;

                case Code.Stelem_I:
                    elemSig = Context.CorLibTypes.IntPtr;
                    break;

                case Code.Stelem_R4:
                    elemSig = Context.CorLibTypes.Single;
                    break;

                case Code.Stelem_R8:
                    elemSig = Context.CorLibTypes.Double;
                    break;

                case Code.Stelem_Ref:
                    elemSig = Context.CorLibTypes.Object;
                    break;

                case Code.Stelem:
                    elemSig = ((ITypeDefOrRef)inst.Operand).ToTypeSig();
                    break;
                }
                // call void T[]::Set(int,T)
                inst.OpCode  = OpCodes.Call;
                inst.Operand = new MemberRefUser(
                    Context.CorLibModule,
                    "Set",
                    MethodSig.CreateInstance(Context.CorLibTypes.Void, Context.CorLibTypes.Int32, elemSig),
                    new TypeSpecUser(new SZArraySig(elemSig)));
                break;
            }
            }

            switch (inst.OpCode.OperandType)
            {
            case OperandType.InlineMethod:
            {
                MethodX resMetX;
                switch (inst.Operand)
                {
                case MethodDef metDef:
                    resMetX = ResolveMethodDef(metDef);
                    break;

                case MemberRef memRef:
                    resMetX = ResolveMethodRef(memRef, replacer);
                    break;

                case MethodSpec metSpec:
                    resMetX = ResolveMethodSpec(metSpec, replacer);
                    break;

                default:
                    throw new ArgumentOutOfRangeException();
                }

                bool isReAddMethod = false;

                if (inst.OpCode.Code == Code.Newobj)
                {
                    Debug.Assert(!resMetX.Def.IsStatic);
                    Debug.Assert(resMetX.Def.IsConstructor);
                    // 设置实例化标记
                    resMetX.DeclType.IsInstantiated = true;
                    // 生成静态构造和终结器
                    GenStaticCctor(resMetX.DeclType);
                    GenFinalizer(resMetX.DeclType);
                }
                else if (inst.OpCode.Code == Code.Callvirt ||
                         inst.OpCode.Code == Code.Ldvirtftn)
                {
                    if (resMetX.IsVirtual)
                    {
                        AddVCallEntry(resMetX);
                    }
                    else
                    {
                        // 非虚方法重定向指令
                        inst.OpCode = inst.OpCode.Code == Code.Callvirt ?
                                      OpCodes.Call : OpCodes.Ldftn;
                    }
                }
                else if (resMetX.IsVirtual &&
                         (inst.OpCode.Code == Code.Call ||
                          inst.OpCode.Code == Code.Ldftn))
                {
                    // 处理方法替换
                    if (resMetX.DeclType.QueryCallReplace(this, resMetX.Def, out TypeX implTyX, out var implDef))
                    {
                        resMetX.IsSkipProcessing = true;

                        Debug.Assert(implTyX != null);
                        MethodX implMetX = MakeMethodX(implTyX, implDef, resMetX.GenArgs);

                        resMetX = implMetX;
                    }
                    else
                    {
                        isReAddMethod = true;
                    }
                }
                else
                {
                    isReAddMethod = true;
                }

                if (isReAddMethod)
                {
                    // 尝试重新加入处理队列
                    AddPendingMethod(resMetX);
                }

                if (resMetX.IsStatic)
                {
                    // 生成静态构造
                    GenStaticCctor(resMetX.DeclType);
                }

                inst.Operand = resMetX;
                return;
            }
Пример #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);
        }