Пример #1
0
        // 解析所有引用
        public void ResolveAll()
        {
            while (PendingMethods.Count > 0)
            {
                do
                {
                    MethodX metX = PendingMethods.Dequeue();

                    // 跳过不需要处理的方法
                    if (metX.IsSkipProcessing)
                    {
                        continue;
                    }

                    // 跳过已处理的方法
                    if (metX.IsProcessed)
                    {
                        continue;
                    }

                    // 设置已处理标记
                    metX.IsProcessed = true;

                    // 展开指令列表
                    BuildInstructions(metX);
                }while (PendingMethods.Count > 0);

                // 解析协逆变
                ResolveVariances();
                // 解析虚调用
                ResolveVCalls();
            }
        }
Пример #2
0
        private static TypeX GetMethodGenType(MethodX metX, GeneratorContext genContext, int genArg = 0)
        {
            Debug.Assert(metX.HasGenArgs && metX.GenArgs.Count > genArg);
            TypeX genType = genContext.GetTypeBySig(metX.GenArgs[genArg]);

            Debug.Assert(genType != null);
            return(genType);
        }
Пример #3
0
        public string GetMethodName(MethodDef metDef, out string unitName)
        {
            MethodX metX     = GenContext.TypeMgr.ResolveMethodDef(metDef);
            string  typeName = GenContext.GetTypeName(metX.DeclType);

            unitName = TransMap[typeName];
            return(GenContext.GetMethodName(metX, MethodGenerator.PrefixMet));
        }
Пример #4
0
 public void AddOverrideImpl(MethodX impl)
 {
     if (OverrideImpls == null)
     {
         OverrideImpls = new HashSet <MethodX>();
     }
     OverrideImpls.Add(impl);
 }
Пример #5
0
 public void SetMethod(MethodX metX)
 {
     if (metX.HasGenArgs)
     {
         OwnerMethod   = metX.Def;
         MethodGenArgs = metX.GenArgs;
     }
 }
Пример #6
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));
            }
        }
Пример #7
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);
        }
Пример #8
0
        public static string GetCppName(this MethodX metX, string prefix)
        {
            if (metX.CppName_ == null)
            {
                if (metX.Def.IsInternalCall)
                {
                    metX.CppName_ = "icall_" + ToCppName(metX.Name, false);
                }
                else
                {
                    metX.CppName_ = ToCppName(metX.Name);
                }
            }

            return(prefix + metX.CppName_);
        }
Пример #9
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);
        }
Пример #10
0
        public string GetMethodName(MethodX metX, string prefix)
        {
            string strName = metX.GeneratedMethodName;

            if (strName == null)
            {
                int hashCode = Helper.CombineHash(
                    metX.GetNameKey().GetHashCode(),
                    metX.GetReplacedNameKey().GetHashCode(),
                    metX.DeclType.GetNameKey().GetHashCode());

                strName = NameHash(hashCode) + '_' +
                          GetNameWithGen(metX.DeclType.Def.Name, metX.DeclType.GenArgs) + "__" +
                          GetNameWithGen(metX.Def.Name, metX.GenArgs);

                metX.GeneratedMethodName = strName = GetNotUsedMethodName(EscapeName(strName));
            }
            return(prefix + strName);
        }
Пример #11
0
        public static string PrettyName(this MethodX self, bool hasDeclType = false)
        {
            StringBuilder sb = new StringBuilder();

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

            PrettyName(sb, self.ReturnType, true);

            sb.AppendFormat(" {0}{1}",
                            hasDeclType ? self.DeclType.PrettyName() + "::" : "",
                            self.Def.Name);

            PrettyGenArgs(sb, self.GenArgs);

            sb.Append('(');
            int i = 0;

            if (!self.Def.IsStatic)
            {
                i = 1;
            }

            bool last = false;

            for (; i < self.ParamTypes.Count; ++i)
            {
                if (last)
                {
                    sb.Append(',');
                }
                last = true;
                var arg = self.ParamTypes[i];
                PrettyName(sb, arg, true);
            }
            sb.Append(')');

            return(sb.ToString());
        }
Пример #12
0
        public MethodX GenFinalizerMethod(TypeManager typeMgr)
        {
            if (!IsFinalizerGenerated)
            {
                IsFinalizerGenerated = true;

                // 跳过 Object 类的终结器
                if (GetNameKey() != "Object")
                {
                    MethodDef finMetDef = Def.Methods.FirstOrDefault(met => !met.IsStatic && met.Name == "Finalize");
                    if (finMetDef != null)
                    {
                        FinalizerMethod = typeMgr.AddMethod(new MethodX(this, finMetDef));
                    }
                }

                if (FinalizerMethod == null)
                {
                    FinalizerMethod = BaseType?.GenFinalizerMethod(typeMgr);
                }
            }
            return(FinalizerMethod);
        }
Пример #13
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);
        }
Пример #14
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);
        }
Пример #15
0
        private void ResolveOperand(InstInfo inst, IGenericReplacer replacer)
        {
            // 重定向数组指令
            switch (inst.OpCode.Code)
            {
            case Code.Newarr:
            {
                // newobj T[]::.ctor(int)
                TypeSig elemSig = ((ITypeDefOrRef)inst.Operand).ToTypeSig();
                inst.OpCode  = OpCodes.Newobj;
                inst.Operand = new MemberRefUser(
                    Context.CorLibModule,
                    ".ctor",
                    MethodSig.CreateInstance(Context.CorLibTypes.Void, Context.CorLibTypes.Int32),
                    new TypeSpecUser(new SZArraySig(elemSig)));
                break;
            }

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

                default:
                    throw new ArgumentOutOfRangeException();
                }

                bool isReAddMethod = false;

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

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

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

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

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

                inst.Operand = resMetX;
                return;
            }
Пример #16
0
        private void BuildInstructions(MethodX metX)
        {
            Debug.Assert(metX.InstList == null);

            if (!metX.Def.HasBody || !metX.Def.Body.HasInstructions)
            {
                return;
            }

            IGenericReplacer replacer = new GenericReplacer(metX.DeclType, metX);

            var defInstList = metX.Def.Body.Instructions;
            int numInsts    = defInstList.Count;

            InstInfo[] instList = new InstInfo[numInsts];

            Dictionary <uint, int> offsetMap   = new Dictionary <uint, int>();
            List <InstInfo>        branchInsts = new List <InstInfo>();

            // 构建指令列表
            for (int ip = 0; ip < numInsts; ++ip)
            {
                var defInst = defInstList[ip];
                var inst    = instList[ip] = new InstInfo();
                inst.OpCode  = defInst.OpCode;
                inst.Operand = defInst.Operand;
                inst.Offset  = ip;

                offsetMap.Add(defInst.Offset, ip);
                switch (inst.OpCode.OperandType)
                {
                case OperandType.InlineBrTarget:
                case OperandType.ShortInlineBrTarget:
                case OperandType.InlineSwitch:
                    branchInsts.Add(inst);
                    break;

                default:
                    ResolveOperand(inst, replacer);
                    break;
                }
            }

            // 重定向跳转位置
            foreach (var inst in branchInsts)
            {
                if (inst.Operand is Instruction defInst)
                {
                    int target;
                    inst.Operand = target = offsetMap[defInst.Offset];
                    instList[target].IsBrTarget = true;
                }
                else if (inst.Operand is Instruction[] defInsts)
                {
                    int[] insts = new int[defInsts.Length];
                    for (int i = 0; i < defInsts.Length; ++i)
                    {
                        int target;
                        insts[i] = target = offsetMap[defInsts[i].Offset];
                        instList[target].IsBrTarget = true;
                    }
                    inst.Operand = insts;
                }
            }

            metX.InstList = instList;
        }
Пример #17
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);
        }
Пример #18
0
 public GenericReplacer(TypeX ownerTyX, MethodX ownerMetX)
 {
     OwnerType   = ownerTyX;
     OwnerMethod = ownerMetX;
 }
Пример #19
0
 public void AddMethod(string key, MethodX metX)
 {
     MethodMap.Add(key, metX);
 }
Пример #20
0
 public bool GetMethod(string key, out MethodX metX)
 {
     return(MethodMap.TryGetValue(key, out metX));
 }
Пример #21
0
 public string GetMetaName(MethodX metX, bool isData = false)
 {
     return(string.Format("{0}{1}",
                          isData ? "mdata_" : "meta_",
                          GetMethodName(metX, metX.IsStatic ? "smet_" : "met_")));
 }
Пример #22
0
        // 导出方法表结构

        /*public void DumpMethodTables(StringBuilder sb)
         * {
         *      foreach (var kv in Context.TypeMgr.MethodTableMap)
         *      {
         *              sb.AppendFormat("[{0}]\n", kv.Key);
         *              bool flag = false;
         *              foreach (var kv2 in kv.Value.VSlotMap)
         *              {
         *                      string expSigName = kv2.Key;
         *                      var entries = kv2.Value.Entries;
         *                      VirtualImpl impl = kv2.Value.Impl;
         *
         *                      // 跳过无覆盖的方法
         *                      if (entries.Count == 1 &&
         *                              impl.IsValid() &&
         *                              entries.TryGetValue(impl.ImplTable, out var defSet) &&
         *                              defSet.Count == 1 &&
         *                              defSet.First() == impl.ImplMethod)
         *                      {
         *                              continue;
         *                      }
         *
         *                      sb.AppendFormat(" - {0}: {1}\n", expSigName, impl);
         *                      foreach (var kv3 in entries)
         *                      {
         *                              foreach (var mdef in kv3.Value)
         *                                      sb.AppendFormat("   - {0} -> {1}\n", kv3.Key, mdef);
         *                      }
         *                      sb.Append('\n');
         *                      flag = true;
         *              }
         *              if (!flag)
         *                      sb.Append('\n');
         *      }
         * }*/

        public void DumpTypes(StringBuilder sb)
        {
            foreach (TypeX tyX in Context.TypeMgr.Types)
            {
                sb.AppendFormat("[{0} {1}] {2}\n",
                                tyX.IsValueType ? "struct" : "class",
                                tyX.GetNameKey(),
                                TypeAttrToString(tyX.Def.Attributes));

                if (tyX.IsInstantiated)
                {
                    sb.Append(" - Instantiated\n");
                }

                if (tyX.BaseType != null)
                {
                    sb.AppendFormat(" - Base: {0}\n", tyX.BaseType);
                }
                if (tyX.Interfaces.IsCollectionValid())
                {
                    sb.Append(" - Interfaces:\n");
                    foreach (TypeX infTyX in tyX.Interfaces)
                    {
                        sb.AppendFormat("   - {0}\n", infTyX);
                    }
                }
                if (tyX.HasVariances)
                {
                    sb.Append(" - Variances: ");
                    foreach (var vt in tyX.Variances)
                    {
                        sb.AppendFormat("{0} ", vt);
                    }
                    sb.Append('\n');
                }
                if (tyX.HasVarianceBaseTypes)
                {
                    sb.Append(" - VarianceBaseTypes:\n");
                    foreach (TypeX vaTyX in tyX.VarianceBaseTypes)
                    {
                        sb.AppendFormat("   - {0}\n", vaTyX);
                    }
                }
                if (tyX.DerivedTypes.IsCollectionValid())
                {
                    sb.Append(" - DerivedTypes:\n");
                    foreach (TypeX derivedTyX in tyX.DerivedTypes)
                    {
                        sb.AppendFormat("   - {0}\n", derivedTyX);
                    }
                }

                if (tyX.Fields.IsCollectionValid())
                {
                    sb.Append(" - Fields:\n");
                    foreach (FieldX fldX in tyX.Fields)
                    {
                        sb.AppendFormat("   - {0}, {1}, {2}\n",
                                        fldX.GetNameKey() + '|' + ((uint)fldX.Def.Attributes).ToString("X"),
                                        fldX.GetReplacedNameKey(),
                                        FieldAttrToString(fldX.Def.Attributes));
                    }
                }

                if (tyX.Methods.IsCollectionValid())
                {
                    sb.Append(" - Methods:\n");
                    foreach (MethodX metX in tyX.Methods)
                    {
                        sb.AppendFormat("   - {0}, {1}{2}, {3}{4} {5}\n",
                                        metX.GetNameKey() + '|' + ((uint)metX.Def.Attributes).ToString("X"),
                                        metX.GetReplacedNameKey(),
                                        metX.IsProcessed ? "" : " = 0",
                                        MethodAttrToString(metX.Def.Attributes),
                                        metX.Def.ImplAttributes,
                                        metX.Def.SemanticsAttributes);

                        if (metX.HasOverrideImpls)
                        {
                            foreach (var kv in metX.OverrideImpls)
                            {
                                MethodX overMetX = kv.Key;
                                sb.AppendFormat("     - {0}, {1}\n",
                                                overMetX.DeclType.GetNameKey() + " -> " + overMetX.GetNameKey() + '|' + ((uint)overMetX.Def.Attributes).ToString("X"),
                                                overMetX.GetReplacedNameKey());
                            }
                        }
                    }
                }

                /*if (tyX.IsInstantiated &&
                 *      tyX.VTable != null)
                 * {
                 *      if (Helper.IsCollectionValid(tyX.VTable.Table))
                 *      {
                 *              sb.Append(" - VTable:\n");
                 *              foreach (var kv2 in tyX.VTable.Table)
                 *              {
                 *                      sb.AppendFormat("   - [{0}]\n", kv2.Key);
                 *                      foreach (var kv3 in kv2.Value)
                 *                      {
                 *                              if (kv3.Key == kv3.Value.Item2)
                 *                                      continue;
                 *
                 *                              sb.AppendFormat("     - {0}: {1} -> {2}\n",
                 *                                      kv3.Key,
                 *                                      kv3.Value.Item1,
                 *                                      kv3.Value.Item2);
                 *                      }
                 *              }
                 *      }
                 *
                 *      if (Helper.IsCollectionValid(tyX.VTable.MethodReplaceMap))
                 *      {
                 *              sb.Append(" - ReplaceMap:\n");
                 *              foreach (var kv2 in tyX.VTable.MethodReplaceMap)
                 *              {
                 *                      sb.AppendFormat("   - {0} => {1}\n", kv2.Key.FullName, kv2.Value.Item2.FullName);
                 *              }
                 *      }
                 *
                 *      if (Helper.IsCollectionValid(tyX.VTable.FallbackTable))
                 *      {
                 *              sb.Append(" - FallbackTable:\n");
                 *              foreach (var kv2 in tyX.VTable.FallbackTable)
                 *              {
                 *                      sb.AppendFormat("   - {0} => {1}\n", kv2.Key, kv2.Value.FullName);
                 *              }
                 *      }
                 * }*/

                sb.Append('\n');
            }
        }
Пример #23
0
        private void BuildInstructions(MethodX metX)
        {
            Debug.Assert(metX.InstList == null);

            if (!metX.Def.HasBody || !metX.Def.Body.HasInstructions)
            {
                return;
            }

            IGenericReplacer replacer = new GenericReplacer(metX.DeclType, metX);

            var defInstList = metX.Def.Body.Instructions;
            int numInsts    = defInstList.Count;

            InstInfo[] instList = new InstInfo[numInsts];

            Dictionary <uint, int> offsetMap   = new Dictionary <uint, int>();
            List <InstInfo>        branchInsts = new List <InstInfo>();

            // 构建指令列表
            for (int ip = 0; ip < numInsts; ++ip)
            {
                var defInst = defInstList[ip];
                var inst    = instList[ip] = new InstInfo();
                inst.OpCode  = defInst.OpCode;
                inst.Operand = defInst.Operand;
                inst.Offset  = ip;

                offsetMap.Add(defInst.Offset, ip);
                switch (inst.OpCode.OperandType)
                {
                case OperandType.InlineBrTarget:
                case OperandType.ShortInlineBrTarget:
                case OperandType.InlineSwitch:
                    branchInsts.Add(inst);
                    break;

                default:
                    ResolveOperand(inst, replacer);
                    break;
                }
            }

            // 重定向跳转位置
            foreach (var inst in branchInsts)
            {
                if (inst.Operand is Instruction defInst)
                {
                    int target;
                    inst.Operand = target = offsetMap[defInst.Offset];
                    instList[target].IsBrTarget = true;
                }
                else if (inst.Operand is Instruction[] defInsts)
                {
                    int[] insts = new int[defInsts.Length];
                    for (int i = 0; i < defInsts.Length; ++i)
                    {
                        int target;
                        insts[i] = target = offsetMap[defInsts[i].Offset];
                        instList[target].IsBrTarget = true;
                    }
                    inst.Operand = insts;
                }
            }

            // 展开异常处理信息
            if (metX.Def.Body.HasExceptionHandlers)
            {
                List <Tuple <int, ExHandlerInfo> > sortedHandlers = new List <Tuple <int, ExHandlerInfo> >();
                int idx = 0;
                foreach (var eh in metX.Def.Body.ExceptionHandlers)
                {
                    ExHandlerInfo info = new ExHandlerInfo();
                    info.TryStart = offsetMap[eh.TryStart.Offset];
                    info.TryEnd   = offsetMap[eh.TryEnd.Offset];

                    if (eh.FilterStart != null)
                    {
                        info.FilterStart = offsetMap[eh.FilterStart.Offset];
                    }
                    else
                    {
                        info.FilterStart = -1;
                    }

                    info.HandlerStart = offsetMap[eh.HandlerStart.Offset];

                    if (eh.HandlerEnd != null)
                    {
                        info.HandlerEnd = offsetMap[eh.HandlerEnd.Offset];
                    }
                    else
                    {
                        info.HandlerEnd = instList.Length;
                    }

                    if (eh.CatchType != null)
                    {
                        info.CatchType = ResolveTypeDefOrRef(eh.CatchType, replacer);
                    }

                    info.HandlerType = eh.HandlerType;
                    sortedHandlers.Add(new Tuple <int, ExHandlerInfo>(idx++, info));
                }
                // 根据 try 位置排序, 如果相同则根据定义顺序排序
                sortedHandlers.Sort((lhs, rhs) =>
                {
                    int cmp = lhs.Item2.TryStart.CompareTo(rhs.Item2.TryStart);
                    if (cmp == 0)
                    {
                        cmp = rhs.Item2.TryEnd.CompareTo(lhs.Item2.TryEnd);
                        if (cmp == 0)
                        {
                            return(lhs.Item1.CompareTo(rhs.Item1));
                        }
                    }
                    return(cmp);
                });

                // 合并同范围的异常处理器
                List <ExHandlerInfo> handlers = new List <ExHandlerInfo>();

                ExHandlerInfo headInfo = null;
                int           count    = sortedHandlers.Count;
                for (int i = 0; i < count; ++i)
                {
                    ExHandlerInfo currInfo = sortedHandlers[i].Item2;
                    if (headInfo != null && headInfo.NeedCombine(currInfo))
                    {
                        headInfo.CombinedHandlers.Add(currInfo);
                    }
                    else
                    {
                        headInfo = currInfo;
                        Debug.Assert(headInfo.CombinedHandlers.Count == 0);
                        headInfo.CombinedHandlers.Add(headInfo);
                        handlers.Add(headInfo);
                    }

                    instList[currInfo.HandlerOrFilterStart].IsBrTarget = true;
                }

                metX.ExHandlerList = handlers;
            }

            metX.InstList = instList;
        }
Пример #24
0
        private void ResolveOperand(InstInfo inst, IGenericReplacer replacer)
        {
            switch (inst.OpCode.OperandType)
            {
            case OperandType.InlineMethod:
            {
                MethodX resMetX;
                switch (inst.Operand)
                {
                case MethodDef metDef:
                    resMetX = ResolveMethodDef(metDef);
                    break;

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

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

                default:
                    throw new ArgumentOutOfRangeException();
                }

                bool isReAddMethod = false;

                if (inst.OpCode.Code == Code.Newobj)
                {
                    Debug.Assert(!resMetX.Def.IsStatic);
                    Debug.Assert(resMetX.Def.IsConstructor);
                    // 设置实例化标记
                    resMetX.DeclType.IsInstantiated = true;
                    // 生成静态构造和终结器
                    GenStaticCctor(resMetX.DeclType);
                    GenFinalizer(resMetX.DeclType);

                    // 解析虚表
                    resMetX.DeclType.ResolveVTable();
                }
                else if (resMetX.IsVirtual &&
                         (inst.OpCode.Code == Code.Callvirt ||
                          inst.OpCode.Code == Code.Ldvirtftn))
                {
                    // 处理非入口虚调用重定向
                    if (!resMetX.Def.IsNewSlot)
                    {
                        if (GetNewSlotMethodChecked(resMetX.DeclType, resMetX.Def, out var slotTypeName, out var slotMetDef))
                        {
                            resMetX.IsSkipProcessing = true;

                            TypeX slotTyX = GetTypeByName(slotTypeName);
                            Debug.Assert(slotTyX != null);

                            MethodX slotMetX = MakeMethodX(slotTyX, slotMetDef, resMetX.GenArgs);

                            resMetX = slotMetX;
                        }
                    }
                    AddVCallEntry(resMetX);
                }
                else if (resMetX.IsVirtual &&
                         (inst.OpCode.Code == Code.Call ||
                          inst.OpCode.Code == Code.Ldftn))
                {
                    // 处理方法替换
                    if (resMetX.DeclType.IsMethodReplaced(resMetX.Def, out var repTypeName, out var repMetDef))
                    {
                        resMetX.IsSkipProcessing = true;

                        TypeX repTyX = GetTypeByName(repTypeName);
                        Debug.Assert(repTyX != null);

                        MethodX repMetX = MakeMethodX(repTyX, repMetDef, resMetX.GenArgs);

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

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

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

                inst.Operand = resMetX;
                return;
            }