private TypeSpecTag GetOrReturnTypeSpec(ref TypeSpecTag typeSpecTag, string typeName)
 {
     if (typeSpecTag == null)
     {
         TypeNameTag nameTag = new TypeNameTag("mscorlib", "System", typeName);
         nameTag = m_compiler.TagRepository.InternTypeName(nameTag);
         TypeSpecTag typeSpec = new TypeSpecClassTag(nameTag, new TypeSpecTag[0]);
         typeSpecTag = m_compiler.TagRepository.InternTypeSpec(typeSpec);
     }
     return typeSpecTag;
 }
Exemple #2
0
        private CliClass(CliClass baseClass, Compiler compiler, TypeSpecTag[] argTypes)
        {
            if (!baseClass.m_isCreated)
                throw new Exception("Can't instantiate an open class that hasn't been processed");

            m_typeName = baseClass.m_typeName;
            m_parentClassSpec = (TypeSpecClassTag)baseClass.m_parentClassSpec.Instantiate(compiler.TagRepository, argTypes);
            m_parentClass = compiler.GetClosedClass(m_parentClassSpec);
            m_isSealed = baseClass.m_isSealed;
            m_isAbstract = baseClass.m_isAbstract;
            m_isStruct = baseClass.m_isStruct;
            m_typeSpec = (TypeSpecClassTag)compiler.TagRepository.InternTypeSpec(new TypeSpecClassTag(m_typeName, argTypes));

            m_isCreated = baseClass.m_isCreated;

            m_numGenericParameters = baseClass.m_numGenericParameters;

            List<HighField> staticFields = new List<HighField>();
            foreach (HighField fld in baseClass.m_staticFields)
                staticFields.Add(fld.Instantiate(compiler.TagRepository, argTypes));

            m_staticFields = staticFields.ToArray();

            List<HighMethod> methods = new List<HighMethod>();
            foreach (HighMethod method in baseClass.m_methods)
                methods.Add(method.Instantiate(compiler.TagRepository, argTypes));
            m_methods = methods.ToArray();

            List<HighField> instanceFields = new List<HighField>();
            foreach (HighField fld in baseClass.m_instanceFields)
                instanceFields.Add(fld.Instantiate(compiler.TagRepository, argTypes));
            m_instanceFields = instanceFields.ToArray();

            List<CliVtableSlot> vtableSlots = new List<CliVtableSlot>();
            foreach (CliVtableSlot slot in baseClass.m_vtable)
                vtableSlots.Add(slot.Instantiate(compiler, argTypes));
            m_vtable = vtableSlots.ToArray();

            List<CliInterfaceImpl> interfaceImpls = new List<CliInterfaceImpl>();
            foreach (CliInterfaceImpl ifcImpl in baseClass.m_interfaceImpls)
                interfaceImpls.Add(ifcImpl.Instantiate(compiler, argTypes));
            m_interfaceImpls = interfaceImpls.ToArray();

            List<TypeSpecClassTag> explicitInterfaces = new List<TypeSpecClassTag>();
            foreach (TypeSpecClassTag ifc in baseClass.m_explicitInterfaceSpecs)
                explicitInterfaces.Add((TypeSpecClassTag)ifc.Instantiate(compiler.TagRepository, argTypes));
            m_explicitInterfaceSpecs = explicitInterfaces.ToArray();

            m_declTagToMethod = baseClass.m_declTagToMethod;
            m_declTagToVTableSlot = baseClass.m_declTagToVTableSlot;
            m_ifcToIfcSlot = baseClass.m_ifcToIfcSlot;
            m_nameToInstanceFieldSlot = baseClass.m_nameToInstanceFieldSlot;
            m_nameToStaticFieldSlot = baseClass.m_nameToStaticFieldSlot;
        }
        public AssignabilityResolver(Compiler compiler)
        {
            m_compiler = compiler;

            m_objectType = ResolveSimpleType("System", "Object");
            m_arrayType = ResolveSimpleType("System", "Array");
            m_refSZArrayName = compiler.TagRepository.InternTypeName(new TypeNameTag("mscorlib", "Clarity", "RefSZArray"));
            m_valueSZArrayName = compiler.TagRepository.InternTypeName(new TypeNameTag("mscorlib", "Clarity", "ValueSZArray`1", 1, null));
            m_nullableSZArrayName = compiler.TagRepository.InternTypeName(new TypeNameTag("mscorlib", "Clarity", "NullableSZArray`1", 1, null));
            m_nullableName = compiler.TagRepository.InternTypeName(new TypeNameTag("mscorlib", "System", "Nullable`1", 1, null));

            m_ilistName = compiler.TagRepository.InternTypeName(new TypeNameTag("mscorlib", "System.Collections.Generic", "IList`1", 1, null));
            m_icollectionName = compiler.TagRepository.InternTypeName(new TypeNameTag("mscorlib", "System.Collections.Generic", "ICollection`1", 1, null));
            m_ienumerableName = compiler.TagRepository.InternTypeName(new TypeNameTag("mscorlib", "System.Collections.Generic", "IEnumerable`1", 1, null));
        }
Exemple #4
0
        private CliInterface(HighTypeDef typeDef, TypeSpecClassTag typeSpec, TypeSpecTag[] genericParameters, TypeSpecClassTag[] parentInterfaces, HighClassVtableSlot[] slots,
            Dictionary<MethodDeclTag, uint> slotTagToCliSlot, Dictionary<MethodDeclTag, uint> slotTagToRealSlot, uint numRealSlots,
            TypeSpecClassTag[] interfaceImpls)
        {
            m_typeDef = typeDef;
            m_typeSpec = typeSpec;
            m_genericParameters = genericParameters;
            m_slots = slots;
            m_slotTagToCliSlot = slotTagToCliSlot;
            m_slotTagToRealSlot = slotTagToRealSlot;
            m_numRealSlots = numRealSlots;
            m_interfaceImpls = interfaceImpls;

            m_isCreated = true;
        }
Exemple #5
0
        public RloInitPass(Compiler compiler, RloMethodBody methodBody, RloFindPredecessorsAndSuccessorsPass psPass)
            : base(compiler, methodBody)
        {
            m_psPass = psPass;
            m_addTypeVisitor = AddSsaTypes;

            TagRepository repo = compiler.TagRepository;

            m_boolType = GetBuiltinType(repo, "System", "Boolean");
            m_charType = GetBuiltinType(repo, "System", "Char");
            m_int8Type = GetBuiltinType(repo, "System", "SByte");
            m_int16Type = GetBuiltinType(repo, "System", "Int16");
            m_int32Type = GetBuiltinType(repo, "System", "Int32");
            m_int64Type = GetBuiltinType(repo, "System", "Int64");
            m_uint8Type = GetBuiltinType(repo, "System", "Byte");
            m_uint16Type = GetBuiltinType(repo, "System", "UInt16");
            m_uint32Type = GetBuiltinType(repo, "System", "UInt32");
            m_uint64Type = GetBuiltinType(repo, "System", "UInt64");
            m_float32Type = GetBuiltinType(repo, "System", "Single");
            m_float64Type = GetBuiltinType(repo, "System", "Double");
            m_nativeIntType = GetBuiltinType(repo, "System", "IntPtr");
            m_nativeUIntType = GetBuiltinType(repo, "System", "UIntPtr");
            m_objectType = GetBuiltinType(repo, "System", "Object");
            m_runtimeTypeHandleType = GetBuiltinType(repo, "System", "RuntimeTypeHandle");
            m_runtimeFieldHandleType = GetBuiltinType(repo, "System", "RuntimeFieldHandle");

            m_simplifiedNumberType = new Dictionary<TypeSpecTag, TypeSpecClassTag>();
            m_simplifiedNumberType.Add(m_boolType, m_int32Type);
            m_simplifiedNumberType.Add(m_charType, m_int32Type);
            m_simplifiedNumberType.Add(m_int8Type, m_int32Type);
            m_simplifiedNumberType.Add(m_int16Type, m_int32Type);
            m_simplifiedNumberType.Add(m_int32Type, m_int32Type);
            m_simplifiedNumberType.Add(m_int64Type, m_int64Type);
            m_simplifiedNumberType.Add(m_uint8Type, m_int32Type);
            m_simplifiedNumberType.Add(m_uint16Type, m_int32Type);
            m_simplifiedNumberType.Add(m_uint32Type, m_int32Type);
            m_simplifiedNumberType.Add(m_uint64Type, m_int64Type);
            m_simplifiedNumberType.Add(m_nativeIntType, m_nativeIntType);
            m_simplifiedNumberType.Add(m_nativeUIntType, m_nativeIntType);
            m_simplifiedNumberType.Add(m_float32Type, m_float64Type);
            m_simplifiedNumberType.Add(m_float64Type, m_float64Type);
        }
Exemple #6
0
        private List<MethodSpecTag> GenerateMethodSpecsForClass(Compiler compiler, TypeSpecClassTag typeSpec)
        {
            CliClass cls = compiler.GetClosedClass(typeSpec);

            List<MethodSpecTag> methodSpecs = new List<MethodSpecTag>();
            foreach (CliVtableSlot vtableSlot in cls.VTable)
            {
                if (vtableSlot.MethodSignature.NumGenericParameters > 0)
                {
                    methodSpecs.Add(null);
                    continue;
                }

                CliMethodIndex methodIndex = vtableSlot.MethodIndex;
                if (methodIndex == null)
                    throw new RpaCompileException("Can't generate vtable slot for abstract method");

                methodSpecs.Add(ResolveVirtualMethod(compiler, cls, methodIndex));
            }

            return methodSpecs;
        }
Exemple #7
0
        public RloMethodBody(Compiler compiler, HighMethod method, MethodSpecTag methodSpec, TypeSpecClassTag thisType, bool isStruct, RloInstantiationParameters instParams, MethodInstantiationPath methodInstantiationPath)
        {
            m_instantiationPath = methodInstantiationPath;
            m_methodSpec = methodSpec;

            HighMethodBody methodBody = method.MethodBody;
            TagRepository tagRepo = compiler.TagRepository;

            // Validate locals
            uint numParamArgs = (uint)method.MethodSignature.ParamTypes.Length;

            if (method.IsStatic)
            {
                if (methodBody.InstanceLocal != null)
                    throw new Exception("Instance local in static method");
            }
            else
            {
                HighLocal thisLocal = methodBody.InstanceLocal;
                if (thisLocal == null)
                    throw new Exception("Missing instance local in instance method");

                HighLocal.ETypeOfType expectedTypeOfType = isStruct ? HighLocal.ETypeOfType.ByRef : HighLocal.ETypeOfType.Value;
                if (thisLocal.TypeOfType != expectedTypeOfType || thisLocal.Type.Instantiate(tagRepo, instParams.TypeParams, instParams.MethodParams) != thisType)
                    throw new Exception("Invalid this type for method");
            }

            if (numParamArgs != (uint)methodBody.Args.Length)
                throw new Exception("Mismatched argument count in method body and signature");

            for (uint i = 0; i < numParamArgs; i++)
            {
                HighLocal bodyArg = methodBody.Args[i];
                MethodSignatureParam methodSigParam = method.MethodSignature.ParamTypes[i];
                MethodSignatureParamTypeOfType tot = methodSigParam.TypeOfType;

                HighLocal.ETypeOfType expectedTypeOfType;
                switch (tot.Value)
                {
                    case MethodSignatureParamTypeOfType.Values.ByRef:
                        expectedTypeOfType = HighLocal.ETypeOfType.ByRef;
                        break;
                    case MethodSignatureParamTypeOfType.Values.TypedByRef:
                        expectedTypeOfType = HighLocal.ETypeOfType.TypedByRef;
                        break;
                    case MethodSignatureParamTypeOfType.Values.Value:
                        expectedTypeOfType = HighLocal.ETypeOfType.Value;
                        break;
                    default:
                        throw new ArgumentException();
                }

                if (bodyArg.TypeOfType != expectedTypeOfType)
                    throw new Exception("Method body arg doesn't match signature");
            }

            HighLocal instanceLocal = methodBody.InstanceLocal;

            RloMethodConverter methodConverter = new RloMethodConverter(compiler.TagRepository, instParams, method.MethodSignature.RetType, instanceLocal, methodBody.Args, methodBody.Locals);
            RloRegionConverter regionConverter = new RloRegionConverter(methodConverter, methodBody.MainRegion, true);

            m_locals = methodConverter.Locals2;
            m_args = methodConverter.Args;
            m_instanceLocal = methodConverter.InstanceLocal;
            m_returnType = methodConverter.ReturnType;
            m_entryRegion = new HighRegion(regionConverter.EntryNode);
            m_methodSignature = method.MethodSignature;

            RloFindPredecessorsAndSuccessorsPass psPass = new RloFindPredecessorsAndSuccessorsPass(compiler, this);
            psPass.Run();

            RloCanonicalizeSsaTypesPass cstPass = new RloCanonicalizeSsaTypesPass(compiler, this);
            cstPass.Run();

            RloInitPass initPass = new RloInitPass(compiler, this, psPass);
            initPass.Run();

            RloInitExceptionsPass exceptionInitPass = new RloInitExceptionsPass(compiler, this);
            exceptionInitPass.Run();
        }
Exemple #8
0
        public bool Create(Compiler compiler)
        {
            HighTypeDef typeDef = m_typeDef;

            foreach (TypeSpecClassTag ii in typeDef.ParentInterfaces)
            {
                if (!compiler.HaveCliOpenInterface(ii.TypeName))
                    return false;
            }

            Dictionary<TypeSpecClassTag, int> uniqueDeps = new Dictionary<TypeSpecClassTag, int>();
            foreach (TypeSpecClassTag pi in typeDef.ParentInterfaces)
            {
                CliInterface ifc = compiler.GetClosedInterface(pi);
                if (!ifc.IsCreated)
                {
                    ifc = compiler.GetClosedInterface(pi);
                    throw new Exception();
                }

                foreach (TypeSpecClassTag pipi in ifc.InterfaceImpls2)
                    AddUniqueInterface(uniqueDeps, pipi);
                AddUniqueInterface(uniqueDeps, pi);
            }

            m_interfaceImpls = UnrollUniqueInterfaces(uniqueDeps);

            m_parentInterfaces = typeDef.ParentInterfaces;

            m_slots = typeDef.NewSlots;
            m_slotTagToCliSlot = new Dictionary<MethodDeclTag, uint>();
            m_slotTagToRealSlot = new Dictionary<MethodDeclTag, uint>();

            uint numGenericParameters = typeDef.NumGenericParameters;
            TypeSpecTag[] genericParameters = new TypeSpecTag[numGenericParameters];
            for (uint i = 0; i < numGenericParameters; i++)
            {
                TypeSpecGenericParamTypeTag paramType = new TypeSpecGenericParamTypeTag(TypeSpecGenericParamTypeTag.Values.Var);
                TypeSpecTag paramTag = new TypeSpecGenericParamTag(paramType, i);
                paramTag = compiler.TagRepository.InternTypeSpec(paramTag);

                genericParameters[i] = paramTag;
            }

            m_numRealSlots = 0;
            uint cliSlot = 0;
            foreach (HighClassVtableSlot slot in m_slots)
            {
                if (m_slotTagToCliSlot.ContainsKey(slot.SlotTag))
                    throw new Exception("Duplicate interface vtable slot");

                m_slotTagToCliSlot.Add(slot.SlotTag, cliSlot++);
                if (slot.Signature.NumGenericParameters > 0)
                    m_slotTagToRealSlot.Add(slot.SlotTag, m_numRealSlots);
            }

            m_typeSpec = new TypeSpecClassTag(m_typeDef.TypeName, genericParameters);
            m_typeSpec = (TypeSpecClassTag)compiler.TagRepository.InternTypeSpec(m_typeSpec);

            m_isCreated = true;

            return true;
        }
Exemple #9
0
        public CliInterface GetClosedInterface(TypeSpecClassTag typeSpec)
        {
            CliInterface ifc;
            if (m_closedInterfaces.TryGetValue(typeSpec, out ifc))
                return ifc;

            ifc = m_openInterfaces.Lookup(typeSpec.TypeName).Instantiate(this, typeSpec.ArgTypes);
            m_closedInterfaces.Add(typeSpec, ifc);
            return ifc;
        }
Exemple #10
0
 private static TypeSpecClassTag[] UnrollUniqueInterfaces(Dictionary<TypeSpecClassTag, int> uniqueDeps)
 {
     TypeSpecClassTag[] interfaceImpls = new TypeSpecClassTag[uniqueDeps.Count];
     foreach (KeyValuePair<TypeSpecClassTag, int> kvp in uniqueDeps)
         interfaceImpls[kvp.Value] = kvp.Key;
     return interfaceImpls;
 }
Exemple #11
0
 public CliClass GetClosedClass(TypeSpecClassTag typeSpec)
 {
     CliClass cls;
     if (m_closedClasses.TryGetValue(typeSpec, out cls))
         return cls;
     cls = m_openClasses.Lookup(typeSpec.TypeName).Instantiate(this, typeSpec.ArgTypes);
     m_closedClasses.Add(typeSpec, cls);
     return cls;
 }
Exemple #12
0
        private uint RecursiveDevirtualizeInterfaceMethod(CliClass cls, TypeSpecClassTag ifcSpec, uint ifcSlotIndex)
        {
            // First, look for an exact match, but only on this class level
            foreach (CliInterfaceImpl impl in cls.InterfaceImpls)
            {
                if (impl.Interface == ifcSpec)
                {
                    CliInterfaceImplSlot slot = impl.IfcSlotToClassVtableSlot[ifcSlotIndex];
                    // Only use the exact match if it has a new implementation.
                    // This is non-standard, but reflects .NET's behavior.
                    // See TestInheritedImplementationDeprioritization.
                    if (slot.HaveNewImpl)
                        return slot.ClassVTableSlot;
                    break;
                }
            }

            // Otherwise, check all interfaces
            uint? bestSlotTDO = null;
            CliInterfaceImplSlot? bestSlot = null;
            foreach (CliInterfaceImpl impl in cls.InterfaceImpls)
            {
                TypeSpecClassTag implInterface = impl.Interface;

                if (m_assignabilityResolver.ResolveGenericVariantAssignableTo(ifcSpec, implInterface) == AssignabilityResolver.ConversionType.InterfaceToInterface)
                {
                    CliInterfaceImplSlot slot = impl.IfcSlotToClassVtableSlot[ifcSlotIndex];
                    if (slot.HaveNewImpl)
                    {
                        uint tdo = cls.TypeDeclarationOrder[implInterface];
                        if (bestSlotTDO.HasValue == false || tdo < bestSlotTDO)
                        {
                            bestSlotTDO = tdo;
                            bestSlot = slot;
                        }
                    }
                }
            }

            if (bestSlot.HasValue)
                return bestSlot.Value.ClassVTableSlot;

            CliClass parentClass = cls.ParentClass;
            if (parentClass == null)
                throw new Exception("Internal error: Unresolvable interface method");

            return RecursiveDevirtualizeInterfaceMethod(parentClass, ifcSpec, ifcSlotIndex);
        }
Exemple #13
0
        public override TypeSpecTag Instantiate(TagRepository repo, TypeSpecTag[] argTypes)
        {
            if (m_argTypes.Length == 0)
                return this;

            List<TypeSpecTag> newArgTypes = new List<TypeSpecTag>();
            foreach (TypeSpecTag argType in m_argTypes)
                newArgTypes.Add(argType.Instantiate(repo, argTypes));

            TypeSpecClassTag newSpec = new TypeSpecClassTag(m_typeNameTag, newArgTypes.ToArray());
            return repo.InternTypeSpec(newSpec);
        }
 public TypeSpecMulticastDelegateTag(TypeSpecClassTag delegateClass)
 {
     m_delegateClass = delegateClass;
 }
Exemple #15
0
        private List<MethodHandle> GenerateVTableForBox(Compiler compiler, TypeSpecBoxTag typeSpec, VTableGenerationCache vtCache)
        {
            TypeSpecClassTag containedType = typeSpec.ContainedType;
            List<MethodSpecTag> baseSpecs = GenerateMethodSpecsForClass(compiler, containedType);

            IList<MethodSpecTag> vtMethodSpecs = vtCache.ValueTypeMethodSpecs;

            if (vtMethodSpecs == null)
            {
                TypeNameTag valueTypeName = new TypeNameTag("mscorlib", "System", "ValueType");
                valueTypeName = compiler.TagRepository.InternTypeName(valueTypeName);

                TypeSpecClassTag valueTypeSpec = new TypeSpecClassTag(valueTypeName, new TypeSpecTag[0]);
                valueTypeSpec = (TypeSpecClassTag)compiler.TagRepository.InternTypeSpec(valueTypeSpec);

                vtMethodSpecs = GenerateMethodSpecsForClass(compiler, valueTypeSpec);
                vtCache.ValueTypeMethodSpecs = vtMethodSpecs;
            }

            List<MethodHandle> methodHandles = new List<MethodHandle>();

            for (int slotIndex = 0; slotIndex < baseSpecs.Count; slotIndex++)
            {
                MethodSpecTag methodSpec = baseSpecs[slotIndex];
                if (methodSpec == null)
                {
                    methodHandles.Add(null);
                    continue;
                }

                if (slotIndex < vtMethodSpecs.Count && vtMethodSpecs[slotIndex] == methodSpec)
                {
                    MethodSpecTag slotSpec = vtMethodSpecs[slotIndex];
                    if (slotSpec == methodSpec)
                    {
                        MethodDeclTag slotDecl = vtMethodSpecs[slotIndex].MethodDecl;

                        // Generate implementations for value-sensitive slots
                        if (slotDecl.Name == "Equals")
                        {
                            methodHandles.Add(compiler.InstantiateMethod(new GeneratedMethods.GMBoxedValueTypeEquals(typeSpec, vtCache), m_instantiationPath));
                            continue;
                        }
                        else if (slotDecl.Name == "GetHashCode")
                        {
                            methodHandles.Add(compiler.InstantiateMethod(new GeneratedMethods.GMBoxedValueTypeGetHashCode(typeSpec, vtCache), m_instantiationPath));
                            continue;
                        }
                    }
                }

                // If not sensitive, then use the method spec and generate a box thunk
                methodHandles.Add(compiler.InstantiateMethod(new GeneratedMethods.GMBoxThunk(methodSpec), m_instantiationPath));
            }

            return methodHandles;
        }
Exemple #16
0
 private static void CheckArithOperand(HighSsaRegister reg, TypeSpecClassTag expectedType)
 {
     if (reg.ValueType != HighValueType.ConstantValue && reg.ValueType != HighValueType.ValueValue)
         throw new RpaCompileException("Unexpected value type in arith instruction");
     if (reg.Type != expectedType)
         throw new RpaCompileException("Unexpected operand type in arith instruction");
 }
Exemple #17
0
        private void ReadClassDefinitions(TagRepository rpa, CatalogReader catalog, BinaryReader reader)
        {
            m_parentClass = null;
            if (m_semantics == TypeSemantics.Class)
            {
                m_isSealed = reader.ReadBoolean();
                m_isAbstract = reader.ReadBoolean();

                uint parentClassIndex = reader.ReadUInt32();
                if (parentClassIndex == 0)
                {
                    if (m_typeName.AssemblyName != "mscorlib"
                        || m_typeName.TypeNamespace != "System"
                        || m_typeName.TypeName != "Object")
                        throw new Exception("Parentless class is not System.Object");
                }
                else
                {
                    TypeSpecTag parentClass = catalog.GetTypeSpec(parentClassIndex - 1);
                    TypeSpecClassTag clsTag = parentClass as TypeSpecClassTag;
                    if (clsTag == null)
                        throw new Exception("Parent class spec wasn't a class");

                    m_parentClass = clsTag;
                }
            }

            if (m_semantics == TypeSemantics.Struct || m_semantics == TypeSemantics.Enum)
            {
                m_isSealed = true;
                m_isAbstract = false;
            }

            if (m_semantics == TypeSemantics.Interface)
            {
                m_isSealed = false;
                m_isAbstract = true;

                ReadGenericParameterVariance(reader);
            }

            uint numInterfaces = reader.ReadUInt32();

            TypeSpecClassTag[] interfaces = new TypeSpecClassTag[numInterfaces];

            for (uint i = 0; i < numInterfaces; i++)
            {
                TypeSpecTag typeSpec = catalog.GetTypeSpec(reader.ReadUInt32());
                TypeSpecClassTag classTag = typeSpec as TypeSpecClassTag;
                if (classTag == null)
                    throw new RpaLoadException("Interface implementation is not a class tag");
                interfaces[i] = classTag;
            }
            m_parentInterfaces = interfaces;

            this.ReadVtableThunks(rpa, catalog, reader);

            if (m_semantics == TypeSemantics.Class || m_semantics == TypeSemantics.Struct)
            {
                uint numMethods = reader.ReadUInt32();

                m_methods = new HighMethod[numMethods];

                for (uint i = 0; i < numMethods; i++)
                {
                    HighMethod method = HighMethod.Read(rpa, catalog, reader, m_typeName);
                    m_methods[i] = method;
                }

                uint numInstanceFields = reader.ReadUInt32();

                m_instanceFields = new HighField[numInstanceFields];

                for (uint i = 0; i < numInstanceFields; i++)
                {
                    HighField field = HighField.Read(rpa, catalog, reader);
                    m_instanceFields[i] = field;
                }

                this.ReadInterfaceImplementations(rpa, catalog, reader);
            }
        }
Exemple #18
0
 private CliInterfaceImpl(CliInterfaceImpl baseImpl, Compiler compiler, TypeSpecTag[] argTypes)
 {
     m_interface = (TypeSpecClassTag)baseImpl.m_interface.Instantiate(compiler.TagRepository, argTypes);
     m_ifcSlotToClassVtableSlot = baseImpl.m_ifcSlotToClassVtableSlot;
 }
Exemple #19
0
 public CliInterfaceImpl(TypeSpecClassTag ifc, CliInterfaceImplSlot[] ifcSlotToClassVtableSlot)
 {
     m_interface = ifc;
     m_ifcSlotToClassVtableSlot = ifcSlotToClassVtableSlot;
 }
Exemple #20
0
 public TypeSpecBoxTag(TypeSpecClassTag containedType)
 {
     m_containedType = containedType;
 }
 public GMMulticastDelegateInvoke(TypeSpecClassTag dt, VTableGenerationCache vtCache)
 {
     m_dt = dt;
     m_vtCache = vtCache;
 }
Exemple #22
0
        private void ProcessInstruction(HighCfgNode cfgNode, HighInstruction instr, List<HighInstruction> newInstrs)
        {
            bool validationOnly = true;

            {
                IBranchingInstruction brInstr = instr as IBranchingInstruction;
                if (brInstr != null)
                {
                    brInstr.VisitSuccessors(delegate (ref HighCfgEdge edge)
                    {
                        HighCfgNode dest = edge.Dest.Value;
                        foreach (HighCfgNodeHandle pred in dest.Predecessors)
                            if (pred.Value == cfgNode)
                                return;
                        throw new RpaCompileException("Branching instruction jumps to undeclared predecessor");
                    });
                }
            }

            switch (instr.Opcode)
            {
                case HighInstruction.Opcodes.LoadLocal:
                    {
                        LoadLocalInstruction tInstr = (LoadLocalInstruction)instr;
                        HighSsaRegister dest = tInstr.Dest;
                        HighLocal local = tInstr.Local;

                        switch (local.TypeOfType)
                        {
                            case HighLocal.ETypeOfType.ByRef:
                                if (dest.ValueType != HighValueType.ManagedPtr)
                                    throw new RpaCompileException("Illegal LoadLocal");
                                break;
                            case HighLocal.ETypeOfType.TypedByRef:
                                throw new NotImplementedException();
                            case HighLocal.ETypeOfType.Value:
                                if (dest.ValueType != HighValueType.ValueValue && dest.ValueType != HighValueType.ReferenceValue)
                                    throw new RpaCompileException("Illegal LoadLocal");
                                break;
                            default:
                                throw new Exception();
                        }

                        if (dest.Type != local.Type)
                            throw new RpaCompileException("Type mismatch in LoadLocal");
                    }
                    break;
                case HighInstruction.Opcodes.AllocArray:
                    {
                        AllocArrayInstruction tInstr = (AllocArrayInstruction)instr;

                        HighSsaRegister dest = tInstr.Dest;
                        if (dest == null)
                            throw new RpaCompileException("AllocArray has no destination");
                        if (dest.ValueType != HighValueType.ReferenceValue || !(dest.Type is TypeSpecArrayTag))
                            throw new RpaCompileException("AllocArray destination is not an array");
                        TypeSpecArrayTag type = (TypeSpecArrayTag)dest.Type;
                        if (type.Rank != (uint)tInstr.Sizes.Length)
                            throw new RpaCompileException("AllocArray index count doesn't match destination type rank");

                        foreach (HighSsaRegister sz in tInstr.Sizes)
                        {
                            switch (sz.ValueType)
                            {
                                case HighValueType.ConstantValue:
                                case HighValueType.ValueValue:
                                    break;
                                default:
                                    throw new RpaCompileException("AllocArray index is invalid");
                            }

                            if (sz.Type != m_nativeIntType)
                                throw new RpaCompileException("AllocArray index is invalid");
                        }

                        this.Compiler.GetRloVTable(dest.Type, GenerateMethodInstantiationPath(tInstr.CodeLocation));
                    }
                    break;
                case HighInstruction.Opcodes.AllocObj:
                    {
                        AllocObjInstruction tInstr = (AllocObjInstruction)instr;

                        HighSsaRegister dest = tInstr.Dest;
                        if (dest == null)
                            throw new RpaCompileException("AllocObj has no destination");

                        if (dest.ValueType != HighValueType.ReferenceValue)
                            throw new RpaCompileException("AllocObj destination is not a reference type");

                        TypeSpecClassTag destType = dest.Type as TypeSpecClassTag;
                        if (destType == null)
                            throw new RpaCompileException("AllocObj destination type is not a class");

                        HighTypeDef typeDef = this.Compiler.GetTypeDef(destType.TypeName);
                        if (typeDef.Semantics != TypeSemantics.Class)
                            throw new RpaCompileException("AllocObj created non-class");
                        if (typeDef.IsAbstract)
                            throw new RpaCompileException("AllocObj created class is abstract");

                        this.Compiler.GetRloVTable(destType, GenerateMethodInstantiationPath(tInstr.CodeLocation));
                    }
                    break;
                case HighInstruction.Opcodes.Box:
                    {
                        BoxInstruction tInstr = (BoxInstruction)instr;

                        HighSsaRegister dest = tInstr.Dest;
                        HighSsaRegister src = tInstr.Src;
                        if (dest == null)
                            throw new RpaCompileException("Box has no destination");

                        if ((src.ValueType == HighValueType.ConstantValue || src.ValueType == HighValueType.ValueValue) && dest.ValueType == HighValueType.BoxedValue)
                        {
                            // Normally don't do anything, leave box as canonical
                            // In the case of Nullable`1 only, convert the box instruction
                            if (dest.Type != src.Type)
                            {
                                if (!(src.Type is TypeSpecClassTag))
                                    throw new RpaCompileException("Invalid box source type");
                                TypeSpecClassTag srcClass = (TypeSpecClassTag)src.Type;
                                TypeNameTag srcClassName = srcClass.TypeName;
                                if (srcClassName.ContainerType != null || srcClassName.AssemblyName != "mscorlib" || srcClassName.TypeNamespace != "System" || srcClassName.TypeName != "Nullable`1" || srcClass.ArgTypes.Length != 1)
                                    throw new RpaCompileException("Invalid box source type");
                                TypeSpecTag srcSubType = srcClass.ArgTypes[0];

                                if (dest.Type != srcSubType)
                                    throw new RpaCompileException("Nullable box type mixmatch");

                                validationOnly = false;

                                TypeNameTag clarityToolsName = new TypeNameTag("mscorlib", "Clarity", "Tools");
                                clarityToolsName = this.Compiler.TagRepository.InternTypeName(clarityToolsName);

                                TypeSpecClassTag clarityToolsClass = new TypeSpecClassTag(clarityToolsName, new TypeSpecTag[0]);
                                clarityToolsClass = (TypeSpecClassTag)this.Compiler.TagRepository.InternTypeSpec(clarityToolsClass);

                                TypeNameTag nullableName = new TypeNameTag("mscorlib", "System", "Nullable`1", 1, null);
                                nullableName = this.Compiler.TagRepository.InternTypeName(nullableName);

                                TypeSpecGenericParamTypeTag mArgType = new TypeSpecGenericParamTypeTag(TypeSpecGenericParamTypeTag.Values.MVar);
                                TypeSpecGenericParamTag m0Type = new TypeSpecGenericParamTag(mArgType, 0);
                                m0Type = (TypeSpecGenericParamTag)this.Compiler.TagRepository.InternTypeSpec(m0Type);

                                TypeSpecClassTag nullableM0Class = new TypeSpecClassTag(nullableName, new TypeSpecTag[] { m0Type });
                                nullableM0Class = (TypeSpecClassTag)this.Compiler.TagRepository.InternTypeSpec(nullableM0Class);

                                MethodSignatureParam[] bnDeclParams = new MethodSignatureParam[] { new MethodSignatureParam(nullableM0Class, new MethodSignatureParamTypeOfType(MethodSignatureParamTypeOfType.Values.Value)) };
                                MethodSignatureTag bnDeclSignature = new MethodSignatureTag(1, m_objectType, bnDeclParams);
                                bnDeclSignature = this.Compiler.TagRepository.InternMethodSignature(bnDeclSignature);

                                MethodDeclTag boxNullableDecl = new MethodDeclTag("BoxNullable", bnDeclSignature, clarityToolsName);
                                boxNullableDecl = this.Compiler.TagRepository.InternMethodDeclTag(boxNullableDecl);

                                MethodSpecTag bnMethodSpec = new MethodSpecTag(MethodSlotType.Static, new TypeSpecTag[] { srcSubType }, clarityToolsClass, boxNullableDecl);
                                bnMethodSpec = this.Compiler.TagRepository.InternMethodSpec(bnMethodSpec);

                                MethodHandle hdl = this.Compiler.InstantiateMethod(new MethodSpecMethodKey(bnMethodSpec), GenerateMethodInstantiationPath(tInstr.CodeLocation));

                                newInstrs.Add(new Instructions.CallRloStaticMethodInstruction(tInstr.CodeLocation, hdl, dest, new HighSsaRegister[] { src }));
                            }
                            else
                            {
                                TypeSpecBoxTag boxType = new TypeSpecBoxTag((TypeSpecClassTag)dest.Type);
                                boxType = (TypeSpecBoxTag)this.Compiler.TagRepository.InternTypeSpec(boxType);
                                this.Compiler.GetRloVTable(boxType, GenerateMethodInstantiationPath(tInstr.CodeLocation));
                            }
                        }
                        else if (src.ValueType == HighValueType.ReferenceValue && dest.ValueType == HighValueType.ReferenceValue)
                        {
                            if (dest.Type != src.Type)
                                throw new RpaCompileException("Box instruction destination is a different type from source");

                            // Source should never be ConstantString at this stage.
                            // Boxing a reference type converts to a copy
                            validationOnly = false;
                            newInstrs.Add(new Instructions.CopyInstruction(tInstr.CodeLocation, dest, src));
                        }
                    }
                    break;
                case HighInstruction.Opcodes.Arith:
                    {
                        ArithInstruction tInstr = (ArithInstruction)instr;
                        TypeSpecClassTag expectedClass = ExpectedClassForArithType(tInstr.ArithType);

                        if (tInstr.CheckOverflow)
                        {
                            switch (tInstr.ArithType)
                            {
                                case NumberArithType.Int32:
                                case NumberArithType.Int64:
                                case NumberArithType.NativeInt:
                                case NumberArithType.NativeUInt:
                                case NumberArithType.UInt32:
                                case NumberArithType.UInt64:
                                    break;
                                case NumberArithType.Float32:
                                case NumberArithType.Float64:
                                    throw new RpaCompileException("Check overflow flag on flowing point arith operation");
                                default:
                                    throw new Exception();
                            }
                        }

                        CheckArithDest(tInstr.Dest, expectedClass);
                        CheckArithOperand(tInstr.Left, expectedClass);
                        CheckArithOperand(tInstr.Right, expectedClass);
                    }
                    break;
                case HighInstruction.Opcodes.BranchCompareNumbers:
                    {
                        BranchCompareNumbersInstruction tInstr = (BranchCompareNumbersInstruction)instr;

                        TypeSpecClassTag expectedClass = ExpectedClassForArithType(tInstr.ArithType);

                        CheckArithOperand(tInstr.Left, expectedClass);
                        CheckArithOperand(tInstr.Right, expectedClass);
                    }
                    break;
                case HighInstruction.Opcodes.DynamicCast:
                    {
                        DynamicCastInstruction tInstr = (DynamicCastInstruction)instr;

                        if (tInstr.Dest != null)
                        {
                            switch (tInstr.Dest.ValueType)
                            {
                                case HighValueType.BoxedValue:
                                case HighValueType.ReferenceValue:
                                    break;
                                default:
                                    throw new RpaCompileException("Illegal destination type for dynamic cast instruction");
                            }
                        }

                        switch (tInstr.Src.ValueType)
                        {
                            case HighValueType.BoxedValue:
                            case HighValueType.ConstantString:
                            case HighValueType.Null:
                            case HighValueType.ReferenceValue:
                                break;
                            default:
                                throw new RpaCompileException("Illegal source type for dynamic cast instruction.");
                        }
                    }
                    break;
                case HighInstruction.Opcodes.ForceDynamicCast:
                    {
                        ForceDynamicCastInstruction tInstr = (ForceDynamicCastInstruction)instr;

                        if (tInstr.Dest != null)
                        {
                            switch (tInstr.Dest.ValueType)
                            {
                                case HighValueType.BoxedValue:
                                case HighValueType.ReferenceValue:
                                    break;
                                default:
                                    throw new RpaCompileException("Illegal destination type for force dynamic cast instruction");
                            }
                        }

                        switch (tInstr.Src.ValueType)
                        {
                            case HighValueType.BoxedValue:
                            case HighValueType.ConstantString:
                            case HighValueType.Null:
                            case HighValueType.ReferenceValue:
                                break;
                            default:
                                throw new RpaCompileException("Illegal source type for force dynamic cast instruction.");
                        }
                    }
                    break;
                case HighInstruction.Opcodes.GetArrayElementPtr:
                    {
                        GetArrayElementPtrInstruction tInstr = (GetArrayElementPtrInstruction)instr;

                        HighSsaRegister arraySrc = tInstr.ArraySrc;
                        if (arraySrc.ValueType != HighValueType.ReferenceValue)
                            throw new RpaCompileException("GetArrayElementPtr instruction array is not a reference");

                        TypeSpecArrayTag arrayType = arraySrc.Type as TypeSpecArrayTag;
                        if (arrayType == null)
                            throw new RpaCompileException("GetArrayElementPtr instruction arrays source is not an array");

                        if ((uint)tInstr.Indexes.Length != arrayType.Rank)
                            throw new RpaCompileException("GetArrayElementPtr instruction array source rank doesn't match index count");

                        HighSsaRegister dest = tInstr.Dest;
                        if (dest != null)
                        {
                            if (dest.ValueType != HighValueType.ManagedPtr)
                                throw new RpaCompileException("GetArrayElementPtr destination is not a managed pointer");
                            if (dest.Type != arrayType.SubscriptType)
                                throw new RpaCompileException("GetArrayElementPtr destination does not match subscript type");
                        }
                    }
                    break;
                case HighInstruction.Opcodes.CompareRefs:
                    {
                        CompareRefsInstruction tInstr = (CompareRefsInstruction)instr;
                        HighSsaRegister[] sources = new HighSsaRegister[2];
                        sources[0] = tInstr.SrcA;
                        sources[1] = tInstr.SrcB;

                        if (tInstr.Dest != null && tInstr.Dest.ValueType != HighValueType.ValueValue && tInstr.Dest.Type != m_int32Type)
                            throw new RpaCompileException("CompareRefs destination is not an int");

                        bool isSideConverted = false;
                        UpdateRefCompare(tInstr.CodeLocation, sources, newInstrs, out isSideConverted);

                        if (isSideConverted)
                        {
                            validationOnly = false;
                            newInstrs.Add(new CompareRefsInstruction(tInstr.CodeLocation, tInstr.Dest, sources[0], sources[1], tInstr.EqualValue, tInstr.NotEqualValue));
                        }
                    }
                    break;
                case HighInstruction.Opcodes.BranchCompareRefs:
                    {
                        BranchCompareRefsInstruction tInstr = (BranchCompareRefsInstruction)instr;
                        HighSsaRegister[] sources = new HighSsaRegister[2];
                        sources[0] = tInstr.SrcA;
                        sources[1] = tInstr.SrcB;

                        bool isSideConverted = false;
                        UpdateRefCompare(tInstr.CodeLocation, sources, newInstrs, out isSideConverted);

                        if (isSideConverted)
                        {
                            validationOnly = false;
                            newInstrs.Add(new BranchCompareRefsInstruction(tInstr.CodeLocation, sources[0], sources[1], tInstr.EqualEdge.Dest, tInstr.NotEqualEdge.Dest));
                        }
                    }
                    break;
                case HighInstruction.Opcodes.GetStaticFieldAddr:
                    {
                        GetStaticFieldAddrInstruction tInstr = (GetStaticFieldAddrInstruction)instr;

                        TypeSpecClassTag classSpec = tInstr.StaticType as TypeSpecClassTag;
                        if (classSpec == null)
                            throw new RpaCompileException("GetStaticFieldAddr type is not a class");
                        CliClass cls = this.Compiler.GetClosedClass(classSpec);

                        uint fieldIndex;
                        if (!cls.NameToStaticFieldSlot.TryGetValue(tInstr.FieldName, out fieldIndex))
                            throw new RpaCompileException("GetStaticFieldAddr could not match static field name");

                        HighSsaRegister dest = tInstr.Dest;
                        if (dest != null)
                        {
                            if (dest.ValueType != HighValueType.ManagedPtr)
                                throw new RpaCompileException("GetStaticFieldAddr dest is not a managed pointer");
                            if (dest.Type != cls.StaticFields[fieldIndex].Type)
                                throw new RpaCompileException("GetStaticFieldAddr dest type does not match field type");
                        }
                    }
                    break;
                case HighInstruction.Opcodes.BranchRefNull:
                    {
                        BranchRefNullInstruction tInstr = (BranchRefNullInstruction)instr;

                        HighSsaRegister src = tInstr.Src;
                        switch (src.ValueType)
                        {
                            case HighValueType.BoxedValue:
                            case HighValueType.ConstantString:
                            case HighValueType.Null:
                            case HighValueType.ReferenceValue:
                                break;
                            default:
                                throw new RpaCompileException("BranchRefNull source is not a reference");
                        }
                    }
                    break;
                case HighInstruction.Opcodes.GetTypeInfo:
                    {
                        GetTypeInfoInstruction tInstr = (GetTypeInfoInstruction)instr;

                        if (tInstr.Dest.ValueType != HighValueType.ValueValue || tInstr.Dest.Type != m_runtimeTypeHandleType)
                            throw new RpaCompileException("GetTypeInfo destination is not the correct type");
                    }
                    break;
                case HighInstruction.Opcodes.LoadPtr:
                    {
                        LoadPtrInstruction tInstr = (LoadPtrInstruction)instr;

                        if (tInstr.Dest != null)
                        {
                            switch (tInstr.Dest.ValueType)
                            {
                                case HighValueType.ReferenceValue:
                                case HighValueType.ValueValue:
                                    break;
                                default:
                                    throw new RpaCompileException("LoadPtr destination has an invalid value type");
                            }
                        }

                        if (tInstr.Src.ValueType != HighValueType.ManagedPtr)
                            throw new RpaCompileException("LoadPtr source is not a managed pointer");

                        if (tInstr.Src.Type != tInstr.Dest.Type)
                            throw new RpaCompileException("LoadPtr source type is not the same as dest type");
                    }
                    break;
                case HighInstruction.Opcodes.PtrField:
                    {
                        PtrFieldInstruction tInstr = (PtrFieldInstruction)instr;

                        HighSsaRegister dest = tInstr.Dest;
                        HighSsaRegister src = tInstr.Src;

                        if (src.ValueType != HighValueType.ManagedPtr)
                            throw new RpaCompileException("PtrField source not a field");

                        TypeSpecClassTag classSpec = src.Type as TypeSpecClassTag;
                        if (classSpec == null)
                            throw new RpaCompileException("PtrField source is not a class");

                        CliClass cls = this.Compiler.GetClosedClass(classSpec);
                        uint fieldIndex;
                        if (!cls.NameToInstanceFieldSlot.TryGetValue(tInstr.FieldName, out fieldIndex))
                            throw new RpaCompileException("PtrField field does not exist");

                        if (dest != null)
                        {
                            if (dest.ValueType != HighValueType.ManagedPtr)
                                throw new RpaCompileException("PtrField dest is not a field");
                            HighField fld = cls.InstanceFields[fieldIndex];
                            if (fld.Type != dest.Type)
                                throw new RpaCompileException("PtrField dest type does not match field type");
                        }
                    }
                    break;
                case HighInstruction.Opcodes.RefField:
                    {
                        RefFieldInstruction tInstr = (RefFieldInstruction)instr;

                        HighSsaRegister dest = tInstr.Dest;
                        HighSsaRegister src = tInstr.Src;

                        if (src.ValueType != HighValueType.ReferenceValue)
                            throw new RpaCompileException("RefField source not a field");

                        TypeSpecClassTag classSpec = src.Type as TypeSpecClassTag;
                        if (classSpec == null)
                            throw new RpaCompileException("RefField source is not a class");

                        CliClass cls = this.Compiler.GetClosedClass(classSpec);
                        uint fieldIndex;
                        if (!cls.NameToInstanceFieldSlot.TryGetValue(tInstr.FieldName, out fieldIndex))
                            throw new RpaCompileException("RefField field does not exist");

                        if (dest != null)
                        {
                            if (dest.ValueType != HighValueType.ManagedPtr)
                                throw new RpaCompileException("RefField dest is not a field");
                            HighField fld = cls.InstanceFields[fieldIndex];
                            if (fld.Type != dest.Type)
                                throw new RpaCompileException("RefField dest type does not match field type");
                        }
                    }
                    break;
                case HighInstruction.Opcodes.CallInstanceMethod:
                    {
                        CallInstanceMethodInstruction tInstr = (CallInstanceMethodInstruction)instr;
                        HighSsaRegister instance = tInstr.InstanceSrc;
                        HighSsaRegister[] parameters = tInstr.Parameters;
                        HighSsaRegister dest = tInstr.ReturnDest;

                        TypeSpecClassTag classSpec = tInstr.MethodSpec.DeclaringClass;

                        if (instance.Type != tInstr.MethodSpec.DeclaringClass)
                            throw new RpaCompileException("CallInstanceMethod target is not the same class as the method being called");

                        HighTypeDef typeDef = this.Compiler.GetTypeDef(classSpec.TypeName);

                        switch (typeDef.Semantics)
                        {
                            case TypeSemantics.Interface:
                                throw new RpaCompileException("CallInstanceMethod target is an interface");
                            case TypeSemantics.Class:
                            case TypeSemantics.Delegate:
                            case TypeSemantics.Enum:
                            case TypeSemantics.Struct:
                                break;
                            default:
                                throw new ArgumentException();
                        }

                        switch (instance.ValueType)
                        {
                            case HighValueType.ConstantString:
                            case HighValueType.ReferenceValue:
                            case HighValueType.ManagedPtr:
                                break;

                            // BoxedValues should never have methods called on them directly (use unbox first)
                            // Calls on null at this stage are illegal
                            default:
                                throw new RpaCompileException("CallInstanceMethod source type is invalid");
                        }

                        CliClass cliClass = this.Compiler.GetClosedClass(classSpec);
                        MethodSpecTag methodSpec = tInstr.MethodSpec;
                        if (methodSpec.MethodSlotType != MethodSlotType.Instance)
                            throw new RpaCompileException("CallInstanceMethod method is not an instance method");

                        uint methodSlot;
                        if (!cliClass.DeclTagToMethod.TryGetValue(methodSpec.MethodDecl, out methodSlot))
                            throw new RpaCompileException("CallInstanceMethod method wasn't found");
                        HighMethod method = cliClass.Methods[methodSlot];
                        if (method.IsStatic)
                            throw new RpaCompileException("CallInstanceMethod method is static");

                        CheckMethodCall(methodSpec, dest, parameters, method.MethodSignature);

                        MethodHandle methodHandle = this.Compiler.InstantiateMethod(new MethodSpecMethodKey(methodSpec), GenerateMethodInstantiationPath(tInstr.CodeLocation));

                        validationOnly = false;
                        newInstrs.Add(new Instructions.CallRloInstanceMethodInstruction(tInstr.CodeLocation, methodHandle, tInstr.ReturnDest, tInstr.InstanceSrc, tInstr.Parameters));
                    }
                    break;
                case HighInstruction.Opcodes.CallStaticMethod:
                    {
                        CallStaticMethodInstruction tInstr = (CallStaticMethodInstruction)instr;
                        HighSsaRegister[] parameters = tInstr.Parameters;
                        HighSsaRegister dest = tInstr.ReturnDest;

                        TypeSpecClassTag classSpec = tInstr.MethodSpec.DeclaringClass;

                        HighTypeDef typeDef = this.Compiler.GetTypeDef(classSpec.TypeName);

                        switch (typeDef.Semantics)
                        {
                            case TypeSemantics.Interface:
                                throw new RpaCompileException("CallStaticMethod target is an interface");
                            case TypeSemantics.Class:
                            case TypeSemantics.Delegate:
                            case TypeSemantics.Enum:
                            case TypeSemantics.Struct:
                                break;
                            default:
                                throw new ArgumentException();
                        }

                        CliClass cliClass = this.Compiler.GetClosedClass(classSpec);
                        MethodSpecTag methodSpec = tInstr.MethodSpec;
                        if (methodSpec.MethodSlotType != MethodSlotType.Static)
                            throw new RpaCompileException("CallStaticMethod method is not an instance method");

                        uint methodSlot;
                        if (!cliClass.DeclTagToMethod.TryGetValue(methodSpec.MethodDecl, out methodSlot))
                            throw new RpaCompileException("CallStaticMethod method wasn't found");
                        HighMethod method = cliClass.Methods[methodSlot];
                        if (!method.IsStatic)
                            throw new RpaCompileException("CallStaticMethod method is not static");

                        CheckMethodCall(methodSpec, dest, parameters, method.MethodSignature);

                        MethodHandle methodHandle = this.Compiler.InstantiateMethod(new MethodSpecMethodKey(methodSpec), GenerateMethodInstantiationPath(tInstr.CodeLocation));

                        validationOnly = false;
                        newInstrs.Add(new Instructions.CallRloStaticMethodInstruction(tInstr.CodeLocation, methodHandle, tInstr.ReturnDest, tInstr.Parameters));
                    }
                    break;
                case HighInstruction.Opcodes.CallVirtualMethod:
                    {
                        CallVirtualMethodInstruction tInstr = (CallVirtualMethodInstruction)instr;
                        HighSsaRegister instance = tInstr.InstanceSrc;
                        HighSsaRegister[] parameters = tInstr.Parameters;
                        HighSsaRegister dest = tInstr.ReturnDest;
                        MethodSpecTag methodSpec = tInstr.MethodSpec;

                        if (methodSpec.MethodSlotType != MethodSlotType.Virtual)
                            throw new RpaCompileException("CallVirtualMethod target is not virtual");

                        TypeSpecClassTag classSpec = methodSpec.DeclaringClass;

                        if (instance.Type != tInstr.MethodSpec.DeclaringClass)
                            throw new RpaCompileException("CallVirtualMethod target is not the same class as the method being called");

                        HighTypeDef typeDef = this.Compiler.GetTypeDef(classSpec.TypeName);

                        bool isInterface;
                        switch (typeDef.Semantics)
                        {
                            case TypeSemantics.Interface:
                                isInterface = true;
                                break;
                            case TypeSemantics.Class:
                            case TypeSemantics.Delegate:
                            case TypeSemantics.Enum:
                            case TypeSemantics.Struct:
                                isInterface = false;
                                break;
                            default:
                                throw new ArgumentException();
                        }

                        switch (instance.ValueType)
                        {
                            case HighValueType.ConstantString:
                            case HighValueType.ReferenceValue:
                            case HighValueType.ManagedPtr:
                                break;

                            // BoxedValues should never have methods called on them directly (use unbox first)
                            // Calls on null at this stage are illegal
                            default:
                                throw new RpaCompileException("CallVirtualMethod source type is invalid");
                        }

                        if (methodSpec.GenericParameters.Length != 0)
                            throw new RpaCompileException("Can't call an unconstrained generic virtual method");

                        CliVtableSlot vtableSlot;
                        uint vtableSlotIndex;
                        MethodSignatureTag methodSignature;

                        if (isInterface)
                        {
                            CliInterface ifc = this.Compiler.GetClosedInterface(classSpec);
                            vtableSlotIndex = ifc.CliSlotForSlotTag(methodSpec.MethodDecl);
                            methodSignature = ifc.Slots[vtableSlotIndex].Signature;
                        }
                        else
                        {
                            CliClass cliClass = this.Compiler.GetClosedClass(classSpec);
                            if (!cliClass.DeclTagToVTableSlot.TryGetValue(methodSpec.MethodDecl, out vtableSlotIndex))
                                throw new RpaCompileException("CallVirtualMethod method wasn't found");
                            methodSignature = cliClass.VTable[vtableSlotIndex].MethodSignature;
                        }

                        if (methodSpec.MethodSlotType != MethodSlotType.Virtual)
                            throw new RpaCompileException("CallVirtualMethod method is not an instance method");

                        CheckMethodCall(methodSpec, dest, parameters, methodSignature);

                        validationOnly = false;
                        if (isInterface)
                            newInstrs.Add(new Instructions.CallRloVirtualMethodInstruction(tInstr.CodeLocation, vtableSlotIndex, tInstr.ReturnDest, tInstr.InstanceSrc, tInstr.Parameters));
                        else
                            newInstrs.Add(new Instructions.CallRloInterfaceMethodInstruction(tInstr.CodeLocation, vtableSlotIndex, tInstr.ReturnDest, tInstr.InstanceSrc, tInstr.Parameters));
                    }
                    break;

                case HighInstruction.Opcodes.CallConstrainedVirtualMethod:
                    {
                        validationOnly = false;

                        CallConstrainedVirtualMethodInstruction tInstr = (CallConstrainedVirtualMethodInstruction)instr;
                        HighSsaRegister refInstance = tInstr.InstanceSrc;
                        HighSsaRegister[] parameters = tInstr.Parameters;
                        HighSsaRegister dest = tInstr.ReturnDest;
                        MethodSpecTag methodSpec = tInstr.MethodSpec;

                        if (methodSpec.MethodSlotType != MethodSlotType.Virtual)
                            throw new RpaCompileException("CallConstrainedVirtualMethod target is not virtual");

                        TypeSpecTag constraintType = tInstr.ConstraintType;

                        if (refInstance.ValueType != HighValueType.ManagedPtr)
                            throw new RpaCompileException("CallConstrainedVirtualMethod target is not a managed pointer");

                        if (refInstance.Type != constraintType)
                            throw new RpaCompileException("CallConstrainedVirtualMethod target type is different from constraint type");

                        TypeSpecTag instanceType = refInstance.Type;

                        bool isValueType;
                        bool isInterface;

                        switch (instanceType.SubType)
                        {
                            case TypeSpecTag.SubTypeCode.Array:
                                isValueType = false;
                                isInterface = false;
                                break;
                            case TypeSpecTag.SubTypeCode.Class:
                                {
                                    TypeSpecClassTag instanceClassTag = (TypeSpecClassTag)instanceType;
                                    HighTypeDef instanceTypeDef = this.Compiler.GetTypeDef(instanceClassTag.TypeName);

                                    switch (instanceTypeDef.Semantics)
                                    {
                                        case TypeSemantics.Class:
                                        case TypeSemantics.Delegate:
                                            isValueType = false;
                                            isInterface = false;
                                            break;
                                        case TypeSemantics.Interface:
                                            isValueType = false;
                                            isInterface = true;
                                            break;
                                        case TypeSemantics.Enum:
                                        case TypeSemantics.Struct:
                                            isValueType = true;
                                            isInterface = false;
                                            break;
                                        default:
                                            throw new NotSupportedException();
                                    }
                                }
                                break;
                            default:
                                throw new RpaCompileException("Invalid instance type in CallConstrainedVirtualMethod");
                        };

                        if (isValueType)
                        {
                            TypeSpecClassTag instanceClassTag = (TypeSpecClassTag)refInstance.Type;
                            CliClass cls = this.Compiler.GetClosedClass(instanceClassTag);

                            TypeSpecClassTag methodDeclaringClass = methodSpec.DeclaringClass;

                            HighTypeDef methodTypeDef = this.Compiler.GetTypeDef(methodDeclaringClass.TypeName);

                            HighMethod resolvedMethod;
                            uint vtableSlotIndex;
                            if (methodTypeDef.Semantics != TypeSemantics.Interface)
                            {
                                if (!cls.DeclTagToVTableSlot.TryGetValue(methodSpec.MethodDecl, out vtableSlotIndex))
                                    throw new RpaCompileException("CallConstrainedVirtualMethod virtual method was not found");
                            }
                            else
                            {
                                CliInterface ifc = this.Compiler.GetClosedInterface(methodDeclaringClass);
                                uint ifcSlot = ifc.CliSlotForSlotTag(methodSpec.MethodDecl);

                                vtableSlotIndex = this.Compiler.DevirtualizeInterfaceMethod(cls, methodDeclaringClass, ifcSlot);
                            }

                            CliMethodIndex methodIndex = cls.VTable[vtableSlotIndex].MethodIndex;

                            if (methodIndex == null)
                                throw new Exception("Invalid method index (???)");

                            uint depth = methodIndex.Depth;

                            if (depth == 0)
                            {
                                resolvedMethod = cls.Methods[methodIndex.Index];

                                if (resolvedMethod.MethodSignature.NumGenericParameters != 0)
                                    throw new NotImplementedException();

                                if (cls.TypeSpec != instanceType)
                                    throw new RpaCompileException("CallConstrainedVirtualMethod instance type doesn't match method (???)");

                                int numParameters = parameters.Length;
                                HighSsaRegister tempDest = null;
                                HighSsaRegister[] tempParameters = new HighSsaRegister[numParameters];

                                MethodSignatureTag signature = resolvedMethod.MethodSignature;

                                if (signature.ParamTypes.Length != numParameters)
                                    throw new RpaCompileException("CallConstrainedVirtualMethod method call parameter mismatch");

                                for (int i = 0; i < numParameters; i++)
                                {
                                    HighValueType hvt;
                                    MethodSignatureParam sigParam = signature.ParamTypes[i];
                                    switch (sigParam.TypeOfType.Value)
                                    {
                                        case MethodSignatureParamTypeOfType.Values.ByRef:
                                            hvt = HighValueType.ManagedPtr;
                                            break;
                                        case MethodSignatureParamTypeOfType.Values.Value:
                                            hvt = this.Compiler.TypeIsValueType(sigParam.Type) ? HighValueType.ValueValue : HighValueType.ReferenceValue;
                                            break;
                                        default:
                                            throw new NotImplementedException();
                                    }

                                    if (hvt == HighValueType.ReferenceValue)
                                    {
                                        HighSsaRegister tempParam = new HighSsaRegister(hvt, sigParam.Type, null);
                                        EmitPassiveRefConversion(tInstr.CodeLocation, tempParam, parameters[i], newInstrs);

                                        tempParameters[i] = tempParam;
                                    }
                                    else
                                        tempParameters[i] = parameters[i];
                                }

                                HighSsaRegister returnDest = tInstr.ReturnDest;
                                HighSsaRegister tempReturn = returnDest;

                                bool needReturnConversion = false;
                                if (signature.RetType is TypeSpecVoidTag)
                                {
                                    if (returnDest != null)
                                        throw new RpaCompileException("Return type is not void");
                                }
                                else if (returnDest != null)
                                {
                                    needReturnConversion = !this.Compiler.TypeIsValueType(signature.RetType);
                                    if (needReturnConversion)
                                        tempReturn = new HighSsaRegister(HighValueType.ReferenceValue, signature.RetType, null);
                                }

                                MethodSpecTag generatedMethodSpec = new MethodSpecTag(MethodSlotType.Instance, methodSpec.GenericParameters, cls.TypeSpec, resolvedMethod.MethodDeclTag);
                                generatedMethodSpec = this.Compiler.TagRepository.InternMethodSpec(generatedMethodSpec);

                                MethodHandle methodHandle = this.Compiler.InstantiateMethod(new MethodSpecMethodKey(generatedMethodSpec), GenerateMethodInstantiationPath(tInstr.CodeLocation));

                                CheckMethodCall(generatedMethodSpec, tempReturn, tempParameters, resolvedMethod.MethodSignature);

                                newInstrs.Add(new Instructions.CallRloInstanceMethodInstruction(tInstr.CodeLocation, methodHandle, tempReturn, refInstance, tempParameters));

                                if (needReturnConversion)
                                    EmitPassiveRefConversion(tInstr.CodeLocation, returnDest, tempReturn, newInstrs);
                            }
                            else
                            {
                                CliClass resolvedClass = cls;
                                while (depth > 0)
                                {
                                    resolvedClass = this.Compiler.GetClosedClass(resolvedClass.ParentClassSpec);
                                    depth--;
                                }

                                resolvedMethod = resolvedClass.Methods[methodIndex.Index];

                                // Method is on the parent of a value type, so it must be boxed
                                HighSsaRegister boxed = new HighSsaRegister(HighValueType.BoxedValue, instanceType, null);
                                newInstrs.Add(new Clarity.Rpa.Instructions.BoxInstruction(tInstr.CodeLocation, boxed, refInstance));

                                HighSsaRegister newInstanceSrc = new HighSsaRegister(HighValueType.ReferenceValue, resolvedClass.TypeSpec, null);
                                newInstrs.Add(new Instructions.ObjectToObjectInstruction(tInstr.CodeLocation, newInstanceSrc, boxed));

                                MethodSpecTag generatedMethodSpec = new MethodSpecTag(MethodSlotType.Instance, methodSpec.GenericParameters, resolvedClass.TypeSpec, resolvedMethod.MethodDeclTag);
                                generatedMethodSpec = this.Compiler.TagRepository.InternMethodSpec(generatedMethodSpec);

                                MethodHandle methodHandle = this.Compiler.InstantiateMethod(new MethodSpecMethodKey(generatedMethodSpec), GenerateMethodInstantiationPath(tInstr.CodeLocation));

                                CheckMethodCall(generatedMethodSpec, dest, parameters, resolvedMethod.MethodSignature);

                                newInstrs.Add(new Instructions.CallRloInstanceMethodInstruction(tInstr.CodeLocation, methodHandle, dest, newInstanceSrc, parameters));
                            }
                        }
                        else
                        {
                            HighSsaRegister loadedInstance = new HighSsaRegister(HighValueType.ReferenceValue, refInstance.Type, null);
                            newInstrs.Add(new LoadPtrInstruction(tInstr.CodeLocation, loadedInstance, refInstance));

                            if (methodSpec.GenericParameters.Length == 0)
                            {
                                HighSsaRegister instance = new HighSsaRegister(HighValueType.ReferenceValue, constraintType, null);
                                EmitPassiveRefConversion(tInstr.CodeLocation, instance, loadedInstance, newInstrs);

                                if (isInterface)
                                {
                                    CliInterface ifc = this.Compiler.GetClosedInterface((TypeSpecClassTag)constraintType);
                                    uint vtableSlotIndex = ifc.CliSlotForSlotTag(methodSpec.MethodDecl);
                                    MethodSignatureTag methodSignature = ifc.Slots[vtableSlotIndex].Signature;

                                    CheckMethodCall(methodSpec, dest, parameters, methodSignature);

                                    newInstrs.Add(new Instructions.CallRloInterfaceMethodInstruction(tInstr.CodeLocation, vtableSlotIndex, dest, instance, parameters));
                                }
                                else
                                {
                                    if (constraintType is TypeSpecClassTag || constraintType is TypeSpecArrayTag)
                                    {
                                        TypeSpecClassTag methodInstanceClass = methodSpec.DeclaringClass;
                                        if (this.Compiler.TypeIsValueType(methodInstanceClass))
                                            throw new RpaCompileException("CallConstrainedVirtualMethod method spec is from a value type");

                                        HighSsaRegister convertedInstance = new HighSsaRegister(HighValueType.ReferenceValue, methodInstanceClass, null);
                                        EmitPassiveRefConversion(tInstr.CodeLocation, convertedInstance, loadedInstance, newInstrs);

                                        if (this.Compiler.TypeIsInterface(methodInstanceClass))
                                        {
                                            CliInterface ifcClass = this.Compiler.GetClosedInterface(methodInstanceClass);
                                            uint vtableSlotIndex;
                                            vtableSlotIndex = ifcClass.CliSlotForSlotTag(methodSpec.MethodDecl);
                                            MethodSignatureTag methodSignature = ifcClass.Slots[vtableSlotIndex].Signature;

                                            CheckMethodCall(methodSpec, dest, parameters, methodSignature);

                                            newInstrs.Add(new Instructions.CallRloInterfaceMethodInstruction(tInstr.CodeLocation, vtableSlotIndex, dest, convertedInstance, parameters));
                                        }
                                        else
                                        {
                                            CliClass cliClass = this.Compiler.GetClosedClass(methodInstanceClass);
                                            uint vtableSlotIndex;
                                            if (!cliClass.DeclTagToVTableSlot.TryGetValue(methodSpec.MethodDecl, out vtableSlotIndex))
                                                throw new RpaCompileException("CallConstrainedVirtualMethod method wasn't found");
                                            MethodSignatureTag methodSignature = cliClass.VTable[vtableSlotIndex].MethodSignature;

                                            CheckMethodCall(methodSpec, dest, parameters, methodSignature);

                                            newInstrs.Add(new Instructions.CallRloVirtualMethodInstruction(tInstr.CodeLocation, vtableSlotIndex, dest, convertedInstance, parameters));
                                        }
                                    }
                                    else
                                        throw new RpaCompileException("Unexpected constraint type");
                                }
                            }
                            else
                            {
                                // Constrained generic call on a reference value
                                TypeSpecClassTag declaringClass = methodSpec.DeclaringClass;
                                HighTypeDef typeDef = this.Compiler.GetTypeDef(declaringClass.TypeName);

                                TypeSpecClassTag instanceClassTag = instanceType as TypeSpecClassTag;
                                if (instanceClassTag == null)
                                    throw new RpaCompileException("Constrained generic call site a non-class");

                                HighTypeDef instanceTypeDef = this.Compiler.GetTypeDef(instanceClassTag.TypeName);
                                if (instanceTypeDef.Semantics != TypeSemantics.Class)
                                {
                                    MethodInstantiationPath path = GenerateMethodInstantiationPath(tInstr.CodeLocation);
                                    throw new RpaCompileException("Constrained generic call on a non-class: " + path.ToString());
                                }

                                if (!instanceTypeDef.IsSealed)
                                {
                                    MethodInstantiationPath path = GenerateMethodInstantiationPath(tInstr.CodeLocation);
                                    throw new RpaCompileException("Constrained generic call on a class that isn't sealed: " + path.ToString());
                                }

                                CliClass instanceClass = this.Compiler.GetClosedClass(instanceClassTag);
                                uint vtableSlotIndex;

                                switch (typeDef.Semantics)
                                {
                                    case TypeSemantics.Interface:
                                        {
                                            CliInterface ifc = this.Compiler.GetClosedInterface(declaringClass);
                                            uint ifcSlot = ifc.CliSlotForSlotTag(methodSpec.MethodDecl);

                                            vtableSlotIndex = this.Compiler.DevirtualizeInterfaceMethod(instanceClass, declaringClass, ifcSlot);
                                        }
                                        break;
                                    case TypeSemantics.Class:
                                        {
                                            CliClass cls = this.Compiler.GetClosedClass(declaringClass);
                                            if (!cls.DeclTagToVTableSlot.TryGetValue(methodSpec.MethodDecl, out vtableSlotIndex))
                                                throw new RpaCompileException("CallConstrainedVirtualMethod vtable slot had no match");
                                        }
                                        break;
                                    default:
                                        throw new RpaCompileException("Unexpected semantics on generic call on reference type");
                                }

                                CliVtableSlot vtableSlot = instanceClass.VTable[vtableSlotIndex];
                                CliMethodIndex methodIndex = vtableSlot.MethodIndex;

                                uint depth = methodIndex.Depth;
                                CliClass instanceConversionTargetClass = instanceClass;
                                while (depth > 0)
                                {
                                    instanceConversionTargetClass = instanceConversionTargetClass.ParentClass;
                                    depth--;
                                }

                                HighMethod resolvedMethod = instanceConversionTargetClass.Methods[methodIndex.Index];

                                if (resolvedMethod.MethodSignature.NumGenericParameters != methodSpec.GenericParameters.Length)
                                    throw new RpaCompileException("Constrained generic call parameter type mismatch");

                                // Convert instance
                                HighSsaRegister convertedInstance = new HighSsaRegister(HighValueType.ReferenceValue, instanceConversionTargetClass.TypeSpec, null);
                                EmitPassiveRefConversion(tInstr.CodeLocation, convertedInstance, loadedInstance, newInstrs);

                                // Convert parameters
                                MethodSignatureTag methodSignature = resolvedMethod.MethodSignature.Instantiate(this.Compiler.TagRepository, new TypeSpecTag[0], methodSpec.GenericParameters);

                                int numParameters = methodSignature.ParamTypes.Length;
                                if (numParameters != parameters.Length)
                                    throw new RpaCompileException("Constrained generic call parameter count mismatch");

                                List<HighSsaRegister> convertedParameters = new List<HighSsaRegister>();
                                for (int i = 0; i < numParameters; i++)
                                {
                                    MethodSignatureParam param = methodSignature.ParamTypes[i];
                                    switch (param.TypeOfType.Value)
                                    {
                                        case MethodSignatureParamTypeOfType.Values.ByRef:
                                            convertedParameters.Add(parameters[i]);
                                            break;
                                        case MethodSignatureParamTypeOfType.Values.Value:
                                            {
                                                if (this.Compiler.TypeIsValueType(param.Type))
                                                    convertedParameters.Add(parameters[i]);
                                                else
                                                {
                                                    HighSsaRegister convertedParameter = new HighSsaRegister(HighValueType.ReferenceValue, param.Type, null);
                                                    EmitPassiveRefConversion(tInstr.CodeLocation, convertedParameter, parameters[i], newInstrs);
                                                    convertedParameters.Add(convertedParameter);
                                                }
                                            }
                                            break;
                                        default:
                                            throw new NotImplementedException();
                                    }
                                }

                                parameters = convertedParameters.ToArray();

                                HighSsaRegister unconvertedReturnDest = tInstr.ReturnDest;
                                HighSsaRegister convertedReturnDest = null;
                                if (unconvertedReturnDest != null)
                                {
                                    if (this.Compiler.TypeIsValueType(methodSignature.RetType))
                                        convertedReturnDest = unconvertedReturnDest;
                                    else
                                    {
                                        unconvertedReturnDest = new HighSsaRegister(HighValueType.ReferenceValue, methodSignature.RetType, null);
                                        convertedReturnDest = tInstr.ReturnDest;
                                    }
                                }

                                MethodSpecTag generatedMethodSpec = new MethodSpecTag(MethodSlotType.Instance, methodSpec.GenericParameters, instanceConversionTargetClass.TypeSpec, resolvedMethod.MethodDeclTag);
                                generatedMethodSpec = this.Compiler.TagRepository.InternMethodSpec(generatedMethodSpec);

                                MethodHandle methodHandle = this.Compiler.InstantiateMethod(new MethodSpecMethodKey(generatedMethodSpec), GenerateMethodInstantiationPath(tInstr.CodeLocation));

                                CheckMethodCall(generatedMethodSpec, unconvertedReturnDest, parameters, resolvedMethod.MethodSignature);

                                newInstrs.Add(new Instructions.CallRloInstanceMethodInstruction(tInstr.CodeLocation, methodHandle, unconvertedReturnDest, convertedInstance, parameters));

                                if (unconvertedReturnDest != convertedReturnDest)
                                    EmitPassiveRefConversion(tInstr.CodeLocation, convertedReturnDest, unconvertedReturnDest, newInstrs);
                            }
                        }
                    }
                    break;

                case HighInstruction.Opcodes.CompareNumbers:
                    {
                        CompareNumbersInstruction tInstr = (CompareNumbersInstruction)instr;

                        HighSsaRegister dest = tInstr.Dest;
                        if (dest == null)
                            throw new RpaCompileException("CompareNumbers has no destination");

                        if (dest.ValueType != HighValueType.ValueValue || dest.Type != m_boolType)
                            throw new RpaCompileException("CompareNumbers has an invalid destination type");

                        TypeSpecClassTag expectedType = ExpectedClassForArithType(tInstr.NumberType);

                        switch (tInstr.Left.ValueType)
                        {
                            case HighValueType.ConstantValue:
                            case HighValueType.ValueValue:
                                break;
                            default:
                                throw new RpaCompileException("CompareNumbers has an invalid operand");
                        }

                        switch (tInstr.Right.ValueType)
                        {
                            case HighValueType.ConstantValue:
                            case HighValueType.ValueValue:
                                break;
                            default:
                                throw new RpaCompileException("CompareNumbers has an invalid operand");
                        }

                        if (tInstr.Left.Type != expectedType || tInstr.Right.Type != expectedType)
                            throw new RpaCompileException("CompareNumbers operands are the wrong type");
                    }
                    break;
                case HighInstruction.Opcodes.GetArrayLength:
                    {
                        GetArrayLengthInstruction tInstr = (GetArrayLengthInstruction)instr;

                        HighSsaRegister dest = tInstr.Dest;
                        HighSsaRegister src = tInstr.Src;
                        if (dest != null)
                        {
                            if (dest.ValueType != HighValueType.ValueValue || dest.Type != m_nativeUIntType)
                                throw new RpaCompileException("GetArrayLength invalid destination type");
                        }

                        switch (src.ValueType)
                        {
                            case HighValueType.Null:
                                break;
                            case HighValueType.ReferenceValue:
                                {
                                    TypeSpecArrayTag srcType = src.Type as TypeSpecArrayTag;
                                    if (srcType == null)
                                        throw new RpaCompileException("GetArrayLength operand isn't an array");
                                    if (srcType.Rank != 1)
                                        throw new RpaCompileException("GetArrayLength operand isn't 1-rank");
                                }
                                break;
                            default:
                                throw new RpaCompileException("GetArrayLength operand isn't a reference");
                        }
                    }
                    break;
                case HighInstruction.Opcodes.ReturnValue:
                    {
                        ReturnValueInstruction tInstr = (ReturnValueInstruction)instr;

                        HighSsaRegister value = tInstr.Value;

                        TypeSpecTag retType = this.MethodBody.ReturnType;
                        if (retType is TypeSpecVoidTag)
                            throw new RpaCompileException("ReturnValue in a function that has no return type");

                        bool isValueType = this.Compiler.TypeIsValueType(retType);

                        bool expectValueType;
                        switch (tInstr.Value.ValueType)
                        {
                            case HighValueType.Null:
                            case HighValueType.ConstantString:
                            case HighValueType.ReferenceValue:
                                expectValueType = false;
                                break;
                            case HighValueType.ConstantValue:
                            case HighValueType.ValueValue:
                                expectValueType = true;
                                break;
                            default:
                                throw new RpaCompileException("ReturnValue invalid return value type");
                        }

                        if (expectValueType != isValueType)
                            throw new RpaCompileException("Incompatible return value type");

                        if (tInstr.Value.ValueType != HighValueType.Null && tInstr.Value.Type != retType)
                            throw new RpaCompileException("Incompatible return value type");
                    }
                    break;
                case HighInstruction.Opcodes.GetLocalPtr:
                    {
                        GetLocalPtrInstruction tInstr = (GetLocalPtrInstruction)instr;

                        HighLocal local = tInstr.Local;
                        if (local.TypeOfType != HighLocal.ETypeOfType.Value)
                            throw new RpaCompileException("GetLocalPtr local isn't a value");

                        HighSsaRegister dest = tInstr.Dest;
                        if (dest == null)
                            throw new RpaCompileException("GetLocalPtr has no destination");

                        if (dest.ValueType != HighValueType.ManagedPtr)
                            throw new RpaCompileException("GetLocalPtr destination isn't a managed pointer");

                        if (dest.Type != local.Type)
                            throw new RpaCompileException("GetLocalPtr destination isn't the same type as the local");
                    }
                    break;
                case HighInstruction.Opcodes.UnaryArith:
                    {
                        UnaryArithInstruction tInstr = (UnaryArithInstruction)instr;

                        if (tInstr.Dest == null)
                            throw new RpaCompileException("UnaryArith has no destination");

                        TypeSpecClassTag expectedClass = ExpectedClassForArithType(tInstr.ArithType);

                        switch (tInstr.Src.ValueType)
                        {
                            case HighValueType.ConstantValue:
                            case HighValueType.ValueValue:
                                break;
                            default:
                                throw new RpaCompileException("UnaryArith source type is invalid");
                        }

                        if (tInstr.Dest.ValueType != HighValueType.ValueValue)
                            throw new RpaCompileException("UnaryArith destination type is invalid");

                        if (tInstr.Src.Type != expectedClass || tInstr.Dest.Type != expectedClass)
                            throw new RpaCompileException("UnaryArith type doesn't match");
                    }
                    break;
                case HighInstruction.Opcodes.StoreLocal:
                    {
                        StoreLocalInstruction tInstr = (StoreLocalInstruction)instr;

                        HighLocal local = tInstr.Local;
                        HighSsaRegister src = tInstr.Src;
                        switch (local.TypeOfType)
                        {
                            case HighLocal.ETypeOfType.ByRef:
                                if (src.ValueType != HighValueType.ManagedPtr)
                                    throw new RpaCompileException("StoreLocal type mismatch");
                                if (src.Type != local.Type)
                                    throw new RpaCompileException("StoreLocal type mismatch");
                                break;
                            case HighLocal.ETypeOfType.Value:
                                {
                                    bool isValueType = this.Compiler.TypeIsValueType(local.Type);

                                    if (isValueType)
                                    {
                                        switch (src.ValueType)
                                        {
                                            case HighValueType.ConstantValue:
                                            case HighValueType.ValueValue:
                                                if (src.Type != local.Type)
                                                    throw new RpaCompileException("StoreLocal type mismatch");
                                                break;
                                            default:
                                                throw new RpaCompileException("StoreLocal source type is invalid");
                                        }
                                    }
                                    else
                                    {
                                        switch (src.ValueType)
                                        {
                                            case HighValueType.ConstantString:
                                            case HighValueType.ReferenceValue:
                                                if (src.Type != local.Type)
                                                    throw new RpaCompileException("StoreLocal type mismatch");
                                                break;
                                            case HighValueType.Null:
                                                break;
                                            default:
                                                throw new RpaCompileException("StoreLocal source type is invalid");
                                        }
                                    }
                                }
                                break;
                            case HighLocal.ETypeOfType.TypedByRef:
                                throw new NotImplementedException();
                            default:
                                throw new ArgumentException();
                        }
                    }
                    break;
                case HighInstruction.Opcodes.UnboxPtr:
                    {
                        UnboxPtrInstruction tInstr = (UnboxPtrInstruction)instr;

                        if (tInstr.Dest == null)
                            throw new RpaCompileException("UnboxPtr has no destination");

                        if (tInstr.Dest.ValueType != HighValueType.ManagedPtr)
                            throw new RpaCompileException("UnboxPtr destination isn't a managed pointer");

                        if (!this.Compiler.TypeIsValueType(tInstr.Dest.Type))
                            throw new RpaCompileException("UnboxPtr type isn't a value type");

                        switch (tInstr.Src.ValueType)
                        {
                            case HighValueType.BoxedValue:
                            case HighValueType.ConstantString:  // Grumble grumble
                            case HighValueType.Null:
                            case HighValueType.ReferenceValue:
                                break;
                            default:
                                throw new RpaCompileException("UnboxPtr source isn't a reference type");
                        }

                        if (tInstr.Src.Type != m_objectType)
                            throw new RpaCompileException("UnboxPtr source isn't System.Object");
                    }
                    break;
                case HighInstruction.Opcodes.ZeroFillPtr:
                    {
                        ZeroFillPtrInstruction tInstr = (ZeroFillPtrInstruction)instr;
                        if (tInstr.Target.ValueType != HighValueType.ManagedPtr)
                            throw new RpaCompileException("ZeroFillPtr target isn't a managed pointer");
                    }
                    break;
                case HighInstruction.Opcodes.UnboxValue:
                    {
                        UnboxValueInstruction tInstr = (UnboxValueInstruction)instr;

                        if (tInstr.Dest == null)
                            throw new RpaCompileException("UnboxValue has no destination");

                        switch (tInstr.Src.ValueType)
                        {
                            case HighValueType.BoxedValue:
                            case HighValueType.ConstantString:  // Grumble grumble
                            case HighValueType.Null:
                            case HighValueType.ReferenceValue:
                                break;
                            default:
                                throw new RpaCompileException("UnboxValue source isn't a reference type");
                        }

                        if (tInstr.Src.Type != m_objectType)
                            throw new RpaCompileException("UnboxValue source isn't System.Object");

                        validationOnly = true;

                        switch (tInstr.Dest.ValueType)
                        {
                            case HighValueType.ValueValue:
                                {
                                    HighSsaRegister ptr = new HighSsaRegister(HighValueType.ManagedPtr, tInstr.Dest.Type, null);
                                    newInstrs.Add(new UnboxPtrInstruction(tInstr.CodeLocation, ptr, tInstr.Src));
                                    newInstrs.Add(new LoadPtrInstruction(tInstr.CodeLocation, tInstr.Dest, ptr));
                                }
                                break;
                            case HighValueType.ReferenceValue:
                                newInstrs.Add(new ForceDynamicCastInstruction(tInstr.CodeLocation, tInstr.Dest, tInstr.Src, tInstr.Dest.Type));
                                break;
                            default:
                                throw new RpaCompileException("UnboxValue destination is invalid");
                        }
                    }
                    break;
                case HighInstruction.Opcodes.Switch:
                    {
                        SwitchInstruction tInstr = (SwitchInstruction)instr;

                        switch (tInstr.Value.ValueType)
                        {
                            case HighValueType.ConstantValue:
                            case HighValueType.ValueValue:
                                break;
                            default:
                                throw new RpaCompileException("Switch source is invalid");
                        }

                        if (tInstr.Value.Type != m_uint32Type)
                            throw new RpaCompileException("Switch source isn't a UInt32");
                    }
                    break;
                case HighInstruction.Opcodes.Throw:
                    {
                        ThrowInstruction tInstr = (ThrowInstruction)instr;

                        switch (tInstr.Exception.ValueType)
                        {
                            case HighValueType.BoxedValue:
                            case HighValueType.ConstantString:
                            case HighValueType.Null:
                            case HighValueType.ReferenceValue:
                                break;
                            default:
                                throw new RpaCompileException("Throw instruction doesn't throw an object");
                        }
                    }
                    break;
                case HighInstruction.Opcodes.StorePtr:
                    {
                        StorePtrInstruction tInstr = (StorePtrInstruction)instr;

                        if (tInstr.Ptr.ValueType != HighValueType.ManagedPtr)
                            throw new RpaCompileException("StorePtr destination isn't a managed pointer");

                        bool isValueType = this.Compiler.TypeIsValueType(tInstr.Ptr.Type);

                        switch (tInstr.Value.ValueType)
                        {
                            case HighValueType.ConstantString:
                            case HighValueType.ConstantValue:
                            case HighValueType.ReferenceValue:
                            case HighValueType.ValueValue:
                                if (tInstr.Value.Type != tInstr.Ptr.Type)
                                    throw new RpaCompileException("StorePtr type mismatch");
                                break;
                            case HighValueType.Null:
                                if (isValueType)
                                    throw new RpaCompileException("StorePtr type mismatch");
                                break;
                            default:
                                throw new RpaCompileException("StorePtr source is invalid");
                        }
                    }
                    break;
                case HighInstruction.Opcodes.GetFieldInfo:
                    {
                        GetFieldInfoInstruction tInstr = (GetFieldInfoInstruction)instr;

                        TypeSpecClassTag typeClassSpec = tInstr.Type as TypeSpecClassTag;
                        if (typeClassSpec == null)
                            throw new RpaCompileException("GetFieldInfo type isn't a class");

                        if (!this.Compiler.HaveCliOpenClass(typeClassSpec.TypeName))
                            throw new RpaCompileException("GetFieldInfo type name isn't a class");

                        CliClass cls = this.Compiler.GetClosedClass(typeClassSpec);

                        if (tInstr.Dest == null)
                            throw new RpaCompileException("GetFieldInfo has no destination");

                        if (tInstr.Dest.ValueType != HighValueType.ValueValue && tInstr.Type != m_runtimeFieldHandleType)
                            throw new RpaCompileException("GetFieldInfo destination is invalid");

                        IDictionary<string, uint> fieldDict = tInstr.IsStatic ? cls.NameToStaticFieldSlot : cls.NameToInstanceFieldSlot;

                        uint fieldIndex;
                        if (!fieldDict.TryGetValue(tInstr.FieldName, out fieldIndex))
                            throw new RpaCompileException("GetFieldInfo field not found");

                        validationOnly = false;
                        newInstrs.Add(new Instructions.GetRloFieldInfoInstruction(tInstr.CodeLocation, tInstr.Dest, tInstr.Type, fieldIndex, tInstr.IsStatic));
                    }
                    break;
                case HighInstruction.Opcodes.LoadValueField:
                    {
                        LoadValueFieldInstruction tInstr = (LoadValueFieldInstruction)instr;
                        validationOnly = false;

                        if (tInstr.Src.ValueType != HighValueType.ValueValue)
                            throw new RpaCompileException("LoadValueField source is invalid");

                        TypeSpecClassTag typeClassSpec = tInstr.Src.Type as TypeSpecClassTag;
                        if (typeClassSpec == null)
                            throw new RpaCompileException("LoadValueField type isn't a class");

                        if (!this.Compiler.HaveCliOpenClass(typeClassSpec.TypeName))
                            throw new RpaCompileException("LoadValueField type name isn't a class");

                        CliClass cls = this.Compiler.GetClosedClass(typeClassSpec);

                        uint fieldIndex;
                        if (!cls.NameToInstanceFieldSlot.TryGetValue(tInstr.FieldName, out fieldIndex))
                            throw new RpaCompileException("LoadValueField field not found");

                        HighField fld = cls.InstanceFields[fieldIndex];

                        switch (tInstr.Dest.ValueType)
                        {
                            case HighValueType.ValueValue:
                            case HighValueType.ReferenceValue:
                                break;
                            default:
                                throw new RpaCompileException("LoadValueField destination isn't a value");
                        }

                        if (tInstr.Dest.Type != fld.Type)
                            throw new RpaCompileException("LoadValueField destination type mismatch");

                        validationOnly = false;
                        newInstrs.Add(new Instructions.LoadValueRloFieldInstruction(tInstr.CodeLocation, tInstr.Dest, tInstr.Src, fieldIndex));
                    }
                    break;
                case HighInstruction.Opcodes.BindStaticDelegate:
                    {
                        BindStaticDelegateInstruction tInstr = (BindStaticDelegateInstruction)instr;

                        if (tInstr.Dest == null)
                            throw new RpaCompileException("BindStaticDelegate has no destination");

                        if (tInstr.Dest.ValueType != HighValueType.ReferenceValue)
                            throw new RpaCompileException("BindStaticDelegate target isn't a reference");

                        TypeSpecClassTag destClass = tInstr.Dest.Type as TypeSpecClassTag;
                        if (destClass == null)
                            throw new RpaCompileException("BindStaticDelegate destination isn't a class");

                        HighTypeDef typeDef = this.Compiler.GetTypeDef(destClass.TypeName);
                        if (typeDef.Semantics != TypeSemantics.Delegate)
                            throw new RpaCompileException("BindStaticDelegate destination isn't a delegate");

                        if (tInstr.MethodSpec.MethodSlotType != MethodSlotType.Static)
                            throw new RpaCompileException("BindStaticDelegate method spec isn't static");

                        TypeSpecDelegateTag dgTag = new TypeSpecDelegateTag(destClass, tInstr.MethodSpec);
                        dgTag = (TypeSpecDelegateTag)this.Compiler.TagRepository.InternTypeSpec(dgTag);

                        validationOnly = true;
                        HighSsaRegister sdInstance = new HighSsaRegister(HighValueType.ReferenceValue, dgTag, null);

                        newInstrs.Add(new AllocObjInstruction(tInstr.CodeLocation, sdInstance, dgTag));
                        newInstrs.Add(new Instructions.ObjectToObjectInstruction(tInstr.CodeLocation, tInstr.Dest, sdInstance));

                        this.Compiler.GetRloVTable(dgTag, GenerateMethodInstantiationPath(tInstr.CodeLocation));
                    }
                    break;
                case HighInstruction.Opcodes.BindInstanceDelegate:
                    {
                        BindInstanceDelegateInstruction tInstr = (BindInstanceDelegateInstruction)instr;

                        if (tInstr.Dest == null)
                            throw new RpaCompileException("BindInstanceDelegate has no destination");

                        if (tInstr.Dest.ValueType != HighValueType.ReferenceValue)
                            throw new RpaCompileException("BindInstanceDelegate target isn't a reference");

                        TypeSpecClassTag destClass = tInstr.Dest.Type as TypeSpecClassTag;
                        if (destClass == null)
                            throw new RpaCompileException("BindInstanceDelegate destination isn't a class");

                        HighTypeDef typeDef = this.Compiler.GetTypeDef(destClass.TypeName);
                        if (typeDef.Semantics != TypeSemantics.Delegate)
                            throw new RpaCompileException("BindInstanceDelegate destination isn't a delegate");

                        if (tInstr.MethodSpec.MethodSlotType != MethodSlotType.Instance)
                            throw new RpaCompileException("BindInstanceDelegate method spec isn't an instance method");

                        switch (tInstr.Object.ValueType)
                        {
                            case HighValueType.BoxedValue:
                            case HighValueType.ConstantString:
                            case HighValueType.Null:
                            case HighValueType.ReferenceValue:
                                break;
                            default:
                                throw new RpaCompileException("BindInstanceDelegate object is invalid");
                        }

                        if (tInstr.MethodSpec.DeclaringClass != tInstr.Object.Type)
                            throw new RpaCompileException("BindInstanceDelegate method spec type doesn't match source");

                        if (tInstr.MethodSpec.MethodSlotType != MethodSlotType.Instance)
                            throw new RpaCompileException("BindInstanceDelegate method spec isn't an instance method");

                        TypeSpecDelegateTag dgTag = new TypeSpecDelegateTag(destClass, tInstr.MethodSpec);
                        dgTag = (TypeSpecDelegateTag)this.Compiler.TagRepository.InternTypeSpec(dgTag);

                        validationOnly = true;
                        HighSsaRegister dgInstance = new HighSsaRegister(HighValueType.ReferenceValue, dgTag, null);

                        newInstrs.Add(new Instructions.AllocInstanceDelegateInstruction(tInstr.CodeLocation, dgTag, dgInstance, tInstr.Object));
                        newInstrs.Add(new Instructions.ObjectToObjectInstruction(tInstr.CodeLocation, tInstr.Dest, dgInstance));

                        this.Compiler.GetRloVTable(dgTag, GenerateMethodInstantiationPath(tInstr.CodeLocation));
                    }
                    break;
                case HighInstruction.Opcodes.BindVirtualDelegate:
                    {
                        BindVirtualDelegateInstruction tInstr = (BindVirtualDelegateInstruction)instr;

                        if (tInstr.Dest == null)
                            throw new RpaCompileException("BindVirtualDelegate has no destination");

                        if (tInstr.Dest.ValueType != HighValueType.ReferenceValue)
                            throw new RpaCompileException("BindVirtualDelegate target isn't a reference");

                        TypeSpecClassTag destClass = tInstr.Dest.Type as TypeSpecClassTag;
                        if (destClass == null)
                            throw new RpaCompileException("BindVirtualDelegate destination isn't a class");

                        HighTypeDef typeDef = this.Compiler.GetTypeDef(destClass.TypeName);
                        if (typeDef.Semantics != TypeSemantics.Delegate)
                            throw new RpaCompileException("BindVirtualDelegate destination isn't a delegate");

                        if (tInstr.MethodSpec.MethodSlotType != MethodSlotType.Virtual)
                            throw new RpaCompileException("BindVirtualDelegate method spec isn't an instance method");

                        switch (tInstr.Object.ValueType)
                        {
                            case HighValueType.BoxedValue:
                            case HighValueType.ConstantString:
                            case HighValueType.Null:
                            case HighValueType.ReferenceValue:
                                break;
                            default:
                                throw new RpaCompileException("BindInstanceDelegate object is invalid");
                        }

                        if (tInstr.MethodSpec.DeclaringClass != tInstr.Object.Type)
                            throw new RpaCompileException("BindInstanceDelegate method spec type doesn't match source");

                        if (tInstr.MethodSpec.MethodSlotType != MethodSlotType.Virtual)
                            throw new RpaCompileException("BindInstanceDelegate method spec isn't a virtual method");

                        TypeSpecDelegateTag dgTag = new TypeSpecDelegateTag(destClass, tInstr.MethodSpec);
                        dgTag = (TypeSpecDelegateTag)this.Compiler.TagRepository.InternTypeSpec(dgTag);

                        validationOnly = true;
                        HighSsaRegister dgInstance = new HighSsaRegister(HighValueType.ReferenceValue, dgTag, null);

                        newInstrs.Add(new Instructions.AllocInstanceDelegateInstruction(tInstr.CodeLocation, dgTag, dgInstance, tInstr.Object));
                        newInstrs.Add(new Instructions.ObjectToObjectInstruction(tInstr.CodeLocation, tInstr.Dest, dgInstance));

                        this.Compiler.GetRloVTable(dgTag, GenerateMethodInstantiationPath(tInstr.CodeLocation));
                    }
                    break;
                case HighInstruction.Opcodes.Catch:
                    {
                        CatchInstruction tInstr = (CatchInstruction)instr;
                        if (tInstr.Dest == null)
                            throw new RpaCompileException("Catch instruction has no destination");

                        if (tInstr.Dest.ValueType != HighValueType.ReferenceValue)
                            throw new RpaCompileException("Catch instruction destination is invalid");
                    }
                    break;
                case HighInstruction.Opcodes.NumberConvert:
                    {
                        validationOnly = false;

                        NumberConvertInstruction tInstr = (NumberConvertInstruction)instr;

                        if (tInstr.Dest == null)
                            throw new RpaCompileException("NumberConvert instruction destination is invalid");
                        if (tInstr.Dest.ValueType != HighValueType.ValueValue)
                            break;
                        switch (tInstr.Src.ValueType)
                        {
                            case HighValueType.ConstantValue:
                            case HighValueType.ValueValue:
                                break;
                            default:
                                throw new RpaCompileException("NumberConvert source is invalid");
                        }

                        EmitNumberConversion(tInstr.CodeLocation, tInstr.Dest, tInstr.Src, tInstr.CheckOverflow, newInstrs);
                    }
                    break;
                case HighInstruction.Opcodes.PassiveConvert:
                    {
                        PassiveConvertInstruction tInstr = (PassiveConvertInstruction)instr;

                        validationOnly = false;

                        if (tInstr.Dest == null)
                            throw new RpaCompileException("PassiveConvert has no destination");

                        bool srcIsValue;
                        switch (tInstr.Src.ValueType)
                        {
                            case HighValueType.ConstantValue:
                            case HighValueType.ValueValue:
                                srcIsValue = true;
                                break;
                            case HighValueType.BoxedValue:
                            case HighValueType.ConstantString:
                            case HighValueType.Null:
                            case HighValueType.ReferenceValue:
                                srcIsValue = false;
                                break;
                            default:
                                throw new RpaCompileException("PassiveConvert invalid source type");
                        }

                        bool destIsValue;
                        switch (tInstr.Dest.ValueType)
                        {
                            case HighValueType.BoxedValue:
                            case HighValueType.ReferenceValue:
                                destIsValue = false;
                                break;
                            case HighValueType.ValueValue:
                                destIsValue = true;
                                break;
                            default:
                                throw new RpaCompileException("PassiveConvert invalid dest type");
                        }

                        if (destIsValue != srcIsValue)
                            throw new RpaCompileException("PassiveConvert ref/value mismatch");

                        if (srcIsValue)
                            EmitPassiveValueConversion(tInstr.CodeLocation, tInstr.Dest, tInstr.Src, newInstrs);
                        else
                            EmitPassiveRefConversion(tInstr.CodeLocation, tInstr.Dest, tInstr.Src, newInstrs);
                    }
                    break;
                case HighInstruction.Opcodes.CallConstrainedMethod:
                    {
                        validationOnly = false;

                        CallConstrainedMethodInstruction tInstr = (CallConstrainedMethodInstruction)instr;
                        HighSsaRegister refInstance = tInstr.InstanceSrc;
                        HighSsaRegister[] parameters = tInstr.Parameters;
                        HighSsaRegister dest = tInstr.ReturnDest;
                        MethodSpecTag methodSpec = tInstr.MethodSpec;

                        if (methodSpec.MethodSlotType != MethodSlotType.Instance)
                            throw new RpaCompileException("CallConstrainedMethodInstruction target is not an instance method");

                        TypeSpecTag constraintType = tInstr.ConstraintType;

                        if (refInstance.ValueType != HighValueType.ManagedPtr)
                            throw new RpaCompileException("CallConstrainedMethodInstruction target is not a managed pointer");

                        if (refInstance.Type != constraintType)
                            throw new RpaCompileException("CallConstrainedMethodInstruction target type is different from constraint type");

                        TypeSpecTag instanceType = refInstance.Type;

                        bool isValueType;
                        bool isInterface;

                        switch (instanceType.SubType)
                        {
                            case TypeSpecTag.SubTypeCode.Array:
                                isValueType = false;
                                isInterface = false;
                                break;
                            case TypeSpecTag.SubTypeCode.Class:
                                {
                                    TypeSpecClassTag instanceClassTag = (TypeSpecClassTag)instanceType;
                                    HighTypeDef instanceTypeDef = this.Compiler.GetTypeDef(instanceClassTag.TypeName);

                                    switch (instanceTypeDef.Semantics)
                                    {
                                        case TypeSemantics.Class:
                                        case TypeSemantics.Delegate:
                                            isValueType = false;
                                            isInterface = false;
                                            break;
                                        case TypeSemantics.Interface:
                                            isValueType = false;
                                            isInterface = true;
                                            break;
                                        case TypeSemantics.Enum:
                                        case TypeSemantics.Struct:
                                            isValueType = true;
                                            isInterface = false;
                                            break;
                                        default:
                                            throw new NotSupportedException();
                                    }
                                }
                                break;
                            default:
                                throw new RpaCompileException("Invalid instance type in CallConstrainedVirtualMethod");
                        };

                        if (isValueType)
                        {
                            TypeSpecClassTag instanceClassTag = (TypeSpecClassTag)refInstance.Type;
                            CliClass cls = this.Compiler.GetClosedClass(instanceClassTag);

                            TypeSpecClassTag methodDeclaringClass = methodSpec.DeclaringClass;

                            HighTypeDef methodTypeDef = this.Compiler.GetTypeDef(methodDeclaringClass.TypeName);

                            HighMethod resolvedMethod;
                            uint methodIndex = 0;
                            if (methodTypeDef.Semantics != TypeSemantics.Class)
                                throw new RpaCompileException("CallConstrainedMethod declaring type isn't a class");

                            CliClass resolvedClass = cls;
                            while (resolvedClass != null)
                            {
                                if (resolvedClass.DeclTagToMethod.TryGetValue(methodSpec.MethodDecl, out methodIndex))
                                    break;
                                resolvedClass = resolvedClass.ParentClass;
                            }

                            if (resolvedClass == null)
                                throw new RpaCompileException("CallConstrainedMethod virtual method was not found");

                            resolvedMethod = resolvedClass.Methods[methodIndex];

                            HighSsaRegister boxed = new HighSsaRegister(HighValueType.BoxedValue, instanceType, null);
                            newInstrs.Add(new BoxInstruction(tInstr.CodeLocation, boxed, refInstance));

                            HighSsaRegister newInstanceSrc = new HighSsaRegister(HighValueType.ReferenceValue, resolvedClass.TypeSpec, null);
                            newInstrs.Add(new Instructions.ObjectToObjectInstruction(tInstr.CodeLocation, newInstanceSrc, boxed));

                            MethodSpecTag generatedMethodSpec = new MethodSpecTag(MethodSlotType.Instance, methodSpec.GenericParameters, resolvedClass.TypeSpec, resolvedMethod.MethodDeclTag);
                            generatedMethodSpec = this.Compiler.TagRepository.InternMethodSpec(generatedMethodSpec);

                            MethodHandle methodHandle = this.Compiler.InstantiateMethod(new MethodSpecMethodKey(generatedMethodSpec), GenerateMethodInstantiationPath(tInstr.CodeLocation));

                            CheckMethodCall(generatedMethodSpec, dest, parameters, resolvedMethod.MethodSignature);

                            newInstrs.Add(new Instructions.CallRloInstanceMethodInstruction(tInstr.CodeLocation, methodHandle, dest, newInstanceSrc, parameters));
                        }
                        else
                        {
                            HighSsaRegister loadedInstance = new HighSsaRegister(HighValueType.ReferenceValue, refInstance.Type, null);
                            newInstrs.Add(new LoadPtrInstruction(tInstr.CodeLocation, loadedInstance, refInstance));

                            if (methodSpec.GenericParameters.Length != 0)
                                throw new RpaCompileException("Generic method spec on a non-virtual method (???)");

                            HighSsaRegister instance = new HighSsaRegister(HighValueType.ReferenceValue, constraintType, null);
                            EmitPassiveRefConversion(tInstr.CodeLocation, instance, loadedInstance, newInstrs);

                            if (isInterface)
                            {
                                HighSsaRegister objReg = new HighSsaRegister(HighValueType.ReferenceValue, m_objectType, null);
                                newInstrs.Add(new Instructions.InterfaceToObjectInstruction(tInstr.CodeLocation, objReg, loadedInstance));

                                if (methodSpec.DeclaringClass != m_objectType)
                                    throw new RpaCompileException("Constrained method on an interface isn't System.Object");

                                uint methodIndex;
                                CliClass objClass = this.Compiler.GetClosedClass(m_objectType);
                                if (!objClass.DeclTagToMethod.TryGetValue(methodSpec.MethodDecl, out methodIndex))
                                    throw new RpaCompileException("Constrained method on System.Object not found");

                                HighMethod resolvedMethod = objClass.Methods[methodIndex];
                                MethodSignatureTag methodSignature = resolvedMethod.MethodSignature;

                                CheckMethodCall(methodSpec, dest, parameters, methodSignature);

                                MethodHandle methodHandle = this.Compiler.InstantiateMethod(new MethodSpecMethodKey(methodSpec), GenerateMethodInstantiationPath(tInstr.CodeLocation));
                                newInstrs.Add(new Instructions.CallRloInstanceMethodInstruction(tInstr.CodeLocation, methodHandle, dest, instance, parameters));
                            }
                            else
                            {
                                if (constraintType is TypeSpecClassTag || constraintType is TypeSpecArrayTag)
                                {
                                    TypeSpecClassTag methodInstanceClass = methodSpec.DeclaringClass;
                                    if (this.Compiler.TypeIsValueType(methodInstanceClass))
                                        throw new RpaCompileException("CallConstrainedMethod method spec is from a value type");

                                    HighSsaRegister convertedInstance = new HighSsaRegister(HighValueType.ReferenceValue, methodInstanceClass, null);
                                    EmitPassiveRefConversion(tInstr.CodeLocation, convertedInstance, loadedInstance, newInstrs);

                                    if (this.Compiler.TypeIsInterface(methodInstanceClass))
                                        throw new RpaCompileException("CallConstrainedMethod target class was an interface");
                                    else
                                    {
                                        CliClass cliClass = this.Compiler.GetClosedClass(methodInstanceClass);
                                        uint methodIndex;

                                        if (!cliClass.DeclTagToMethod.TryGetValue(methodSpec.MethodDecl, out methodIndex))
                                            throw new RpaCompileException("CallConstrainedMethod method wasn't found");

                                        HighMethod resolvedMethod = cliClass.Methods[methodIndex];
                                        MethodSignatureTag methodSignature = resolvedMethod.MethodSignature;

                                        MethodHandle methodHandle = this.Compiler.InstantiateMethod(new MethodSpecMethodKey(methodSpec), GenerateMethodInstantiationPath(tInstr.CodeLocation));
                                        CheckMethodCall(methodSpec, dest, parameters, methodSignature);

                                        newInstrs.Add(new Instructions.CallRloInstanceMethodInstruction(tInstr.CodeLocation, methodHandle, dest, convertedInstance, parameters));
                                    }
                                }
                                else
                                    throw new RpaCompileException("Unexpected constraint type");
                            }
                        }
                    }
                    break;

                case HighInstruction.Opcodes.Return:
                case HighInstruction.Opcodes.Branch:
                case HighInstruction.Opcodes.EnterProtectedBlock:
                case HighInstruction.Opcodes.LeaveRegion:
                    break;
                    //throw new NotImplementedException();
                default:
                    throw new ArgumentException();
            }

            if (validationOnly)
                newInstrs.Add(instr);
        }
Exemple #23
0
        private List<MethodHandle> GenerateVTableForClass(Compiler compiler, TypeSpecClassTag typeSpec)
        {
            List<MethodSpecTag> methodSpecs = GenerateMethodSpecsForClass(compiler, typeSpec);

            List<MethodHandle> methodHandles = new List<MethodHandle>();
            foreach (MethodSpecTag methodSpec in methodSpecs)
            {
                if (methodSpec == null)
                    methodHandles.Add(null);
                else
                    methodHandles.Add(compiler.InstantiateMethod(new MethodSpecMethodKey(methodSpec), m_instantiationPath));
            }

            return methodHandles;
        }
Exemple #24
0
        public bool Create(Compiler compiler)
        {
            HighTypeDef typeDef = compiler.GetTypeDef(m_typeName);

            TypeSpecClassTag parentClassSpec = null;
            HighClassVtableSlot[] newSlots;
            HighClassVtableSlot[] replacedSlots;
            HighInterfaceImplementation[] typeInterfaceImpls;

            if (typeDef.Semantics == TypeSemantics.Struct || typeDef.Semantics == TypeSemantics.Class)
            {
                if (typeDef.Semantics == TypeSemantics.Struct)
                {
                    m_isStruct = true;
                    TypeNameTag valueTypeName = new TypeNameTag("mscorlib", "System", "ValueType", 0, null);
                    valueTypeName = compiler.TagRepository.InternTypeName(valueTypeName);
                    TypeSpecClassTag vtClassTag = new TypeSpecClassTag(valueTypeName, new TypeSpecTag[0]);
                    vtClassTag = (TypeSpecClassTag)compiler.TagRepository.InternTypeSpec(vtClassTag);

                    parentClassSpec = vtClassTag;
                }
                else if (typeDef.Semantics == TypeSemantics.Class)
                {
                    m_isStruct = false;
                    parentClassSpec = typeDef.ParentClass;

                    RestrictedExtensionType thisRet = GetRestrictedExtensionType(m_typeName);

                    if (parentClassSpec == null)
                    {
                        if (thisRet != RestrictedExtensionType.Object)
                            throw new Exception("Parentless class is not [mscorlib]System.Object");
                    }
                    else
                    {
                        if (thisRet == RestrictedExtensionType.Object)
                            throw new Exception("[mscorlib]System.Object has a parent");

                        RestrictedExtensionType parentRet = GetRestrictedExtensionType(parentClassSpec.TypeName);

                        bool isExtensionOK = false;
                        switch (parentRet)
                        {
                            case RestrictedExtensionType.ValueType:
                                if (thisRet == RestrictedExtensionType.Enum)
                                    isExtensionOK = true;
                                break;
                            case RestrictedExtensionType.Delegate:
                                if (thisRet == RestrictedExtensionType.MulticastDelegate)
                                    isExtensionOK = true;
                                break;
                            case RestrictedExtensionType.Enum:
                            case RestrictedExtensionType.MulticastDelegate:
                            case RestrictedExtensionType.NullableSZArray:
                            case RestrictedExtensionType.RefSZArray:
                            case RestrictedExtensionType.ValueSZArray:
                                break;
                            case RestrictedExtensionType.Object:
                            case RestrictedExtensionType.None:
                                isExtensionOK = true;
                                break;
                            case RestrictedExtensionType.Array:
                                if (thisRet == RestrictedExtensionType.NullableSZArray || thisRet == RestrictedExtensionType.ValueSZArray || thisRet == RestrictedExtensionType.RefSZArray)
                                    isExtensionOK = true;
                                break;
                            default:
                                throw new ArgumentException();
                        }

                        if (!isExtensionOK)
                            throw new Exception("Invalid extension of a restricted class");
                    }
                }

                m_instanceFields = typeDef.InstanceFields;
                m_methods = typeDef.Methods;
                m_staticFields = typeDef.StaticFields;
                m_isSealed = typeDef.IsSealed;
                m_isAbstract = typeDef.IsAbstract;

                replacedSlots = typeDef.ReplacedSlots;
                newSlots = typeDef.NewSlots;
                typeInterfaceImpls = typeDef.InterfaceImpls;
            }
            else if (typeDef.Semantics == TypeSemantics.Delegate)
            {
                m_isStruct = false;

                TypeNameTag dgTypeName = new TypeNameTag("mscorlib", "System", typeDef.IsMulticastDelegate ? "MulticastDelegate" : "Delegate", 0, null);
                dgTypeName = compiler.TagRepository.InternTypeName(dgTypeName);
                TypeSpecClassTag dgClassTag = new TypeSpecClassTag(dgTypeName, new TypeSpecTag[0]);
                dgClassTag = (TypeSpecClassTag)compiler.TagRepository.InternTypeSpec(dgClassTag);

                parentClassSpec = dgClassTag;

                m_instanceFields = new HighField[0];
                m_methods = new HighMethod[0];
                m_staticFields = new HighField[0];
                m_isSealed = false;
                m_isAbstract = true;

                replacedSlots = new HighClassVtableSlot[0];

                MethodDeclTag invokeTag = new MethodDeclTag("Invoke", typeDef.DelegateSignature, m_typeName);
                invokeTag = compiler.TagRepository.InternMethodDeclTag(invokeTag);

                HighClassVtableSlot invokeSlot = new HighClassVtableSlot(invokeTag, typeDef.DelegateSignature, null, true, false);

                newSlots = new HighClassVtableSlot[1] { invokeSlot };

                typeInterfaceImpls = new HighInterfaceImplementation[0];
            }
            else if (typeDef.Semantics == TypeSemantics.Enum)
            {
                m_isStruct = false;

                TypeNameTag dgTypeName = new TypeNameTag("mscorlib", "System", "Enum", 0, null);
                dgTypeName = compiler.TagRepository.InternTypeName(dgTypeName);
                TypeSpecClassTag dgClassTag = new TypeSpecClassTag(dgTypeName, new TypeSpecTag[0]);
                dgClassTag = (TypeSpecClassTag)compiler.TagRepository.InternTypeSpec(dgClassTag);

                parentClassSpec = dgClassTag;

                string underlyingTypeName;
                switch (typeDef.UnderlyingType)
                {
                    case HighTypeDef.EnumUnderlyingType.Int8:
                        underlyingTypeName = "SByte";
                        break;
                    case HighTypeDef.EnumUnderlyingType.Int16:
                        underlyingTypeName = "Int16";
                        break;
                    case HighTypeDef.EnumUnderlyingType.Int32:
                        underlyingTypeName = "Int32";
                        break;
                    case HighTypeDef.EnumUnderlyingType.Int64:
                        underlyingTypeName = "Int64";
                        break;
                    case HighTypeDef.EnumUnderlyingType.UInt8:
                        underlyingTypeName = "Byte";
                        break;
                    case HighTypeDef.EnumUnderlyingType.UInt16:
                        underlyingTypeName = "Int16";
                        break;
                    case HighTypeDef.EnumUnderlyingType.UInt32:
                        underlyingTypeName = "UInt32";
                        break;
                    case HighTypeDef.EnumUnderlyingType.UInt64:
                        underlyingTypeName = "UInt64";
                        break;
                    default:
                        throw new Exception();
                }

                TypeNameTag underlyingTypeNameTag = new TypeNameTag("mscorlib", "System", underlyingTypeName);
                underlyingTypeNameTag = compiler.TagRepository.InternTypeName(underlyingTypeNameTag);

                TypeSpecClassTag underlyingTypeSpec = new TypeSpecClassTag(underlyingTypeNameTag, new TypeSpecTag[0]);
                underlyingTypeSpec = (TypeSpecClassTag)compiler.TagRepository.InternTypeSpec(underlyingTypeSpec);

                HighField fld = new HighField("value__", underlyingTypeSpec);

                m_instanceFields = new HighField[1] { fld };
                m_methods = new HighMethod[0];
                m_staticFields = new HighField[0];
                m_isSealed = true;
                m_isAbstract = false;

                replacedSlots = new HighClassVtableSlot[0];
                newSlots = new HighClassVtableSlot[0];
                typeInterfaceImpls = new HighInterfaceImplementation[0];
            }
            else
                throw new ArgumentException();

            if (parentClassSpec != null)
            {
                if (compiler.GetTypeDef(parentClassSpec.TypeName).Semantics != TypeSemantics.Class)
                    throw new RpaCompileException("Can't extend class with non-class semantics");

                if (!compiler.HaveCliOpenClass(parentClassSpec.TypeName))
                    return false;

                CliClass parentClass = compiler.GetClosedClass(parentClassSpec);

                if (parentClass.m_isSealed)
                    throw new RpaCompileException("Can't extend sealed CLI class");

                m_parentClass = parentClass;
            }

            m_numGenericParameters = typeDef.NumGenericParameters;

            // Update vtable
            {
                Dictionary<MethodDeclTag, uint> declTagToMethod = new Dictionary<MethodDeclTag, uint>();
                uint methodIndex = 0;
                foreach (HighMethod method in m_methods)
                {
                    if (declTagToMethod.ContainsKey(method.MethodDeclTag))
                        throw new Exception("Duplicate method declaration");

                    declTagToMethod.Add(method.MethodDeclTag, methodIndex++);
                }
                m_declTagToMethod = declTagToMethod;
            }

            m_declTagToVTableSlot = new Dictionary<MethodDeclTag, uint>();
            m_ifcToIfcSlot = new Dictionary<TypeSpecClassTag, uint>();
            List<CliVtableSlot> slots = new List<CliVtableSlot>();

            if (m_parentClass != null)
            {
                foreach (KeyValuePair<MethodDeclTag, uint> dttvs in m_parentClass.m_declTagToVTableSlot)
                    m_declTagToVTableSlot.Add(dttvs.Key, dttvs.Value);

                foreach (CliVtableSlot parentSlot in m_parentClass.m_vtable)
                {
                    CliMethodIndex methodIndex = parentSlot.MethodIndex;

                    if (methodIndex == null)
                        slots.Add(parentSlot);
                    else
                    {
                        CliMethodIndex newIndex = new CliMethodIndex(methodIndex.Depth + 1, methodIndex.Index);
                        slots.Add(new CliVtableSlot(newIndex, parentSlot.MethodSignature, parentSlot.IsSealed));
                    }
                }
            }

            foreach (HighClassVtableSlot slot in replacedSlots)
            {
                uint index;
                if (!m_declTagToVTableSlot.TryGetValue(slot.SlotTag, out index))
                    throw new Exception("Unmatched vtable slot replacement");
                CliVtableSlot existingSlot = slots[(int)index];
                if (existingSlot.IsSealed)
                    throw new Exception("Can't replace sealed vtable slot");

                if (existingSlot.MethodSignature != slot.Signature)
                    throw new Exception("VTable slot override signature doesn't match");

                CliMethodIndex methodIndex = null;
                if (!slot.IsAbstract)
                {
                    HighMethod method;
                    methodIndex = this.FindMethod(slot.ImplementingMethodTag, out method);
                    if (method.MethodSignature != slot.Signature)
                        throw new Exception("Signature of method used by vtable slot doesn't match vtable slot's signature");
                }

                slots[(int)index] = new CliVtableSlot(methodIndex, slot.Signature, slot.IsFinal);
            }

            foreach (HighClassVtableSlot slot in newSlots)
            {
                CliMethodIndex methodIndex = null;
                if (!slot.IsAbstract)
                {
                    HighMethod method;
                    methodIndex = this.FindMethod(slot.ImplementingMethodTag, out method);
                    if (method.MethodSignature != slot.Signature)
                        throw new Exception("Signature of method used by vtable slot doesn't match vtable slot's signature");
                }

                m_declTagToVTableSlot.Add(slot.SlotTag, (uint)slots.Count);
                slots.Add(new CliVtableSlot(methodIndex, slot.Signature, slot.IsFinal));
            }

            m_vtable = slots.ToArray();

            if (!m_isAbstract)
                foreach (CliVtableSlot slot in m_vtable)
                    if (slot.MethodIndex == null)
                        throw new RpaCompileException("Non-abstract class has unoverrided abstract methods");

            m_nameToInstanceFieldSlot = new Dictionary<string, uint>();
            for (uint i = 0; i < m_instanceFields.Length; i++)
            {
                string fldName = m_instanceFields[i].Name;
                if (m_nameToInstanceFieldSlot.ContainsKey(fldName))
                    throw new RpaCompileException("Duplicate field name");
                m_nameToInstanceFieldSlot.Add(fldName, i);
            }

            m_nameToStaticFieldSlot = new Dictionary<string, uint>();
            for (uint i = 0; i < m_staticFields.Length; i++)
            {
                string fldName = m_staticFields[i].Name;
                if (m_nameToStaticFieldSlot.ContainsKey(fldName))
                    throw new RpaCompileException("Duplicate field name");
                m_nameToStaticFieldSlot.Add(fldName, i);
            }

            HashSet<TypeSpecClassTag> explicitImpls = new HashSet<TypeSpecClassTag>();
            List<CliInterfaceImpl> interfaceImpls = new List<CliInterfaceImpl>();
            foreach (HighInterfaceImplementation ifcImpl in typeInterfaceImpls)
            {
                if (!explicitImpls.Add(ifcImpl.Interface))
                    throw new Exception("Duplicate interface implementation");

                interfaceImpls.Add(ResolveInterfaceImpl(compiler, ifcImpl));
            }

            m_interfaceImpls = interfaceImpls.ToArray();
            m_parentClassSpec = parentClassSpec;

            m_explicitInterfaceSpecs = typeDef.ParentInterfaces;
            if (m_explicitInterfaceSpecs == null)
                m_explicitInterfaceSpecs = new TypeSpecClassTag[0];

            List<TypeSpecTag> thisGenericParameters = new List<TypeSpecTag>();
            for (uint i = 0; i < m_numGenericParameters; i++)
            {
                TypeSpecGenericParamTypeTag gptt = new TypeSpecGenericParamTypeTag(TypeSpecGenericParamTypeTag.Values.Var);
                TypeSpecGenericParamTag gpTag = new TypeSpecGenericParamTag(gptt, i);
                gpTag = (TypeSpecGenericParamTag)compiler.TagRepository.InternTypeSpec(gpTag);

                thisGenericParameters.Add(gpTag);
            }

            TypeSpecClassTag thisClass = new TypeSpecClassTag(m_typeName, thisGenericParameters.ToArray());
            thisClass = (TypeSpecClassTag)compiler.TagRepository.InternTypeSpec(thisClass);

            m_typeSpec = thisClass;

            m_typeDeclarationOrder = new Dictionary<TypeSpecClassTag, uint>();
            ResolveTDOForClass(this);

            m_isCreated = true;

            return true;
        }
Exemple #25
0
        private List<MethodHandle> GenerateVTableForArray(Compiler compiler, TypeSpecArrayTag typeSpec)
        {
            TypeSpecClassTag baseClass;

            if (typeSpec.IsSZArray)
            {
                TypeSpecTag subscriptType = typeSpec.SubscriptType;
                if (compiler.TypeIsValueType(typeSpec.SubscriptType))
                {
                    TypeSpecClassTag subscriptClassTag = (TypeSpecClassTag)subscriptType;
                    TypeNameTag subscriptClassName = subscriptClassTag.TypeName;

                    if (subscriptClassName.FastIs("mscorlib", "System", "Nullable`1", 1, null))
                    {
                        TypeNameTag baseName = new TypeNameTag("mscorlib", "Clarity", "NullableSZArray`1", 1, null);
                        baseName = compiler.TagRepository.InternTypeName(baseName);

                        baseClass = new TypeSpecClassTag(baseName, subscriptClassTag.ArgTypes);
                        baseClass = (TypeSpecClassTag)compiler.TagRepository.InternTypeSpec(baseClass);
                    }
                    else
                    {
                        TypeNameTag baseName = new TypeNameTag("mscorlib", "Clarity", "ValueSZArray`1", 1, null);
                        baseName = compiler.TagRepository.InternTypeName(baseName);

                        baseClass = new TypeSpecClassTag(baseName, new TypeSpecTag[] { subscriptClassTag });
                        baseClass = (TypeSpecClassTag)compiler.TagRepository.InternTypeSpec(baseClass);
                    }
                }
                else
                {
                    TypeNameTag baseName = new TypeNameTag("mscorlib", "Clarity", "RefSZArray");
                    baseName = compiler.TagRepository.InternTypeName(baseName);

                    baseClass = new TypeSpecClassTag(baseName, new TypeSpecTag[0]);
                    baseClass = (TypeSpecClassTag)compiler.TagRepository.InternTypeSpec(baseClass);
                }
            }
            else
                throw new NotImplementedException("Multidimensional arrays not implemented");

            return GenerateVTableForClass(compiler, baseClass);
        }
        private static TypeSpecClassTag GetCachedClass(Compiler compiler, ref TypeSpecClassTag clsTagRef, string typeNamespace, string typeName)
        {
            TypeSpecClassTag clsTag = clsTagRef;
            if (clsTag != null)
                return clsTag;

            TypeNameTag name = new TypeNameTag("mscorlib", typeNamespace, typeName);
            name = compiler.TagRepository.InternTypeName(name);

            clsTag = new TypeSpecClassTag(name, new TypeSpecTag[0]);
            clsTag = (TypeSpecClassTag)compiler.TagRepository.InternTypeSpec(clsTag);

            clsTagRef = clsTag;
            return clsTag;
        }
        private TypeSpecClassTag ArrayClassForSubscript(TypeSpecTag subscriptType)
        {
            if (m_compiler.TypeIsValueType(subscriptType))
            {
                TypeSpecClassTag subscriptClass = (TypeSpecClassTag)subscriptType;
                if (subscriptClass.TypeName == m_nullableName)
                {
                    if (subscriptClass.ArgTypes.Length != 1)
                        throw new RpaCompileException("Malformed Nullable");
                    TypeSpecClassTag classTag = new TypeSpecClassTag(m_nullableSZArrayName, subscriptClass.ArgTypes);
                    classTag = (TypeSpecClassTag)m_compiler.TagRepository.InternTypeSpec(classTag);

                    return classTag;
                }
                else
                {
                    TypeSpecClassTag classTag = new TypeSpecClassTag(m_valueSZArrayName, new TypeSpecTag[1] { subscriptType });
                    classTag = (TypeSpecClassTag)m_compiler.TagRepository.InternTypeSpec(classTag);

                    return classTag;
                }
            }
            else
            {
                TypeSpecClassTag classTag = new TypeSpecClassTag(m_refSZArrayName, new TypeSpecTag[0]);
                classTag = (TypeSpecClassTag)m_compiler.TagRepository.InternTypeSpec(classTag);

                return classTag;
            }
        }
Exemple #28
0
 private static void AddUniqueInterface(Dictionary<TypeSpecClassTag, int> uniqueDeps, TypeSpecClassTag ifc)
 {
     if (uniqueDeps.ContainsKey(ifc))
         return;
     uniqueDeps.Add(ifc, uniqueDeps.Count);
 }
        private TypeSpecClassTag ResolveSimpleType(string typeNamespace, string typeName)
        {
            TypeNameTag typeNameTag = new TypeNameTag("mscorlib", typeNamespace, typeName, 0, null);
            typeNameTag = m_compiler.TagRepository.InternTypeName(typeNameTag);

            TypeSpecClassTag classTag = new TypeSpecClassTag(typeNameTag, new TypeSpecTag[0]);
            return (TypeSpecClassTag)m_compiler.TagRepository.InternTypeSpec(classTag);
        }
Exemple #30
0
        public uint DevirtualizeInterfaceMethod(CliClass cls, TypeSpecClassTag ifcSpec, uint ifcSlotIndex)
        {
            if (!cls.IsSealed)
                throw new ArgumentException("Can't devirtualize a non-sealed class");

            if (GetTypeDef(ifcSpec.TypeName).Semantics != TypeSemantics.Interface)
                throw new ArgumentException("Can't devirtualize an implementation of a non-interface");

            return RecursiveDevirtualizeInterfaceMethod(cls, ifcSpec, ifcSlotIndex);
        }