예제 #1
0
        public void LivenReg(SsaRegister reg, CppBuilder builder)
        {
            if (!IsRegScopable(reg))
                return;

            AddReg(reg);
        }
예제 #2
0
 public CppAssignabilityResolver(CppBuilder builder, CfgNodeCompiler.CommonTypeLookup commonTypes, CLRTypeDefRow inClass, CLRMethodDefRow inMethod)
 {
     m_builder = builder;
     m_commonTypes = commonTypes;
     m_inClass = inClass;
     m_inMethod = inMethod;
 }
예제 #3
0
 public static VType.ValTypeEnum ValTypeForTypeSpec(CppBuilder cppBuilder, CLRTypeSpec typeSpec)
 {
     if (typeSpec is CLRTypeSpecClass)
     {
         CppClass cls = cppBuilder.GetCachedClass(typeSpec);
         if (cls.IsValueType)
             return VType.ValTypeEnum.ValueValue;
         return VType.ValTypeEnum.ReferenceValue;
     }
     else if (typeSpec is CLRTypeSpecGenericInstantiation)
     {
         CLRTypeSpecGenericInstantiation giSpec = (CLRTypeSpecGenericInstantiation)typeSpec;
         CppClass cls = cppBuilder.GetCachedClass(new CLRTypeSpecClass(giSpec.GenericType.TypeDef));
         if (cls.IsValueType)
             return VType.ValTypeEnum.ValueValue;
         return VType.ValTypeEnum.ReferenceValue;
     }
     else if (typeSpec is CLRTypeSpecSZArray)
     {
         return VType.ValTypeEnum.ReferenceValue;
     }
     else if (typeSpec is CLRTypeSpecComplexArray)
     {
         return VType.ValTypeEnum.ReferenceValue;
     }
     else if (typeSpec is CLRTypeSpecVarOrMVar)
     {
         // Generic parameters are always treated like value types even if they're provably ref types
         return VType.ValTypeEnum.ValueValue;
     }
     else
         throw new ArgumentException();
 }
예제 #4
0
 public CppRegisterAllocator(CppBuilder builder)
 {
     m_registers = new List<VReg>();
     m_ssaID = 1;
     m_cfgNodeIDs = new Dictionary<CfgNode, int>();
     m_builder = builder;
     m_staticInitTokens = new List<CLR.CLRTypeSpec>();
 }
예제 #5
0
 public CfgNodeCompiler(CfgNode cfgNode)
 {
     m_cppBuilder = cfgNode.CfgBuilder.CppBuilder;
     m_commonTypeLookup = new CommonTypeLookup(m_cppBuilder);
     m_cfgNode = cfgNode;
     m_ehRegion = cfgNode.CfgBuilder.Region;
     m_escapePaths = new SortedSet<uint>();
     m_temporaries = cfgNode.CfgBuilder.Temporaries;
 }
예제 #6
0
파일: VReg.cs 프로젝트: elasota/clarity
        public VReg(CppBuilder builder, string prefix, VType vType, int slot, UsageEnum usage)
        {
            VType = vType;
            Slot = slot;
            Usage = usage;
            m_isAlive = false;
            DetermineTraceability(builder);

            m_basicName = prefix + slot.ToString();
            m_slotName = m_basicName;
        }
예제 #7
0
파일: Program.cs 프로젝트: elasota/clarity
        static void Main(string[] args)
        {
            CLR.CLRAssemblyCollection assemblies = new CLR.CLRAssemblyCollection();

            string exportDir = args[0];
            string stubDir = args[1];

            Dictionary<CLR.CLRAssembly, string> pdbPaths = new Dictionary<CLR.CLRAssembly, string>();

            for (int assmIndex = 2; assmIndex < args.Length; assmIndex++)
            {
                string path = args[assmIndex];
                Console.WriteLine("Loading assembly " + path);
                CLR.CLRAssembly clrAssembly;
                using (System.IO.FileStream fs = new System.IO.FileStream(path, System.IO.FileMode.Open, System.IO.FileAccess.Read))
                {
                    StreamParser parser = new StreamParser(fs, false);
                    CLR.CLRAssembly assembly = new CLR.CLRAssembly(parser);

                    string pdbPath = path.Substring(0, path.Length - 3) + "pdb";
                    if (System.IO.File.Exists(pdbPath))
                        pdbPaths.Add(assembly, pdbPath);

                    assemblies.Add(assembly);
                }
            }

            Console.WriteLine("Resolving...");
            assemblies.ResolveAll();

            Console.WriteLine("Exporting...");
            CppExport.CppBuilder builder = new CppExport.CppBuilder(exportDir + "\\", stubDir + "\\", assemblies, pdbPaths);
            Console.WriteLine("Done");

            /*
            Console.WriteLine("Compacting...");
            TCLR.TCLRAssemblyBuilder builder = new TCLR.TCLRAssemblyBuilder();
            builder.ImportAssembly(clrAssembly, false);

            string tclrAssemblyPath = path;
            if (tclrAssemblyPath.EndsWith(".dll"))
                tclrAssemblyPath = tclrAssemblyPath.Substring(0, tclrAssemblyPath.Length - 4);
            tclrAssemblyPath += ".cca";
            Console.WriteLine("Writing Clarity compact assembly " + tclrAssemblyPath);

            using (System.IO.FileStream fs = new System.IO.FileStream(tclrAssemblyPath, System.IO.FileMode.Create, System.IO.FileAccess.Write))
            {
                builder.Export(fs);
            }
            */
        }
예제 #8
0
        public CppRegionEmitter(CppBuilder builder, ExceptionHandlingRegion region, CppRegisterAllocator regAllocator, IDictionary<VReg, Clarity.Rpa.HighLocal> localLookup)
        {
            m_localLookup = localLookup;
            m_region = region;
            m_builder = builder;
            m_regAllocator = regAllocator;
            m_nodesToEmittedNodes = new Dictionary<CfgNode, HighCfgNodeHandle>();
            m_nodeOutlines = new Dictionary<CfgNode, CppCfgNodeOutline>();
            m_ssaToEmittedSsa = new Dictionary<SsaRegister, HighSsaRegister>();
            m_translatedOutboundEdges = new Dictionary<CfgOutboundEdge, CppTranslatedOutboundEdge>();

            m_pendingNodes = new Queue<CfgNode>();

            InternHighCfgNode(region.RootCfgNode);
        }
예제 #9
0
        public CppMidCompiler(CppBuilder builder, CppClass cls, CppMethod method, ExceptionHandlingRegion mainRegion, string frameVarName, VReg[] args, VReg[] locals, VReg[] temporaries)
        {
            m_builder = builder;
            m_cls = cls;
            m_method = method;
            m_mainRegion = mainRegion;
            m_args = args;
            m_locals = locals;
            m_temporaries = temporaries;
            m_frameVarName = frameVarName;

            m_instructionStream = new MemoryStream();
            m_instructionWriter = new StreamWriter(m_instructionStream);
            m_regAllocator = new CppRegisterAllocator(builder);
        }
예제 #10
0
        public CfgBuilder(ExceptionHandlingRegion region, CppBuilder builder, CppClass cls, CppMethod method, VReg[] args, VReg[] locals, IList<VReg> temporaries)
        {
            m_builder = builder;
            m_cls = cls;
            m_method = method;
            m_args = args;
            m_locals = locals;
            m_temporaries = temporaries;
            m_instrs = method.MethodDef.Method.Instructions;
            m_inClass = cls.TypeDef;
            m_inMethod = method.MethodDef;
            m_region = region;

            m_startInstr = (int)region.StartInstr;
            m_endInstr = (int)region.EndInstr;
            m_ehClusters = region.Clusters;

            LocateBranchTargets();
            ConstructCfg();
            CreateSuccessionGraph();
        }
예제 #11
0
파일: CppClass.cs 프로젝트: elasota/clarity
        public void ResolveInherit(CppBuilder builder, CppClass parentClass, IEnumerable<CLRTypeSpec> interfaces, CLRTypeSpec parentTypeSpec)
        {
            // There are a LOT of tricky slotting cases here.
            // See TestNewSlotImplementation, TestSlotDivergence, and TestImplementNonVirtual for some sample cases.
            //
            // Roughly how this works:
            // 1.) Override vtable slots based on matching:
            //     - If a method is ReuseSlot, then it overrides a slot no matter what
            //     - If a method is NewSlot, then it creates a slot
            // 2.) Implement MethodImpls and interfaces as cross-slot thunks
            //
            // Two notable complications with this:
            //
            // In Clarity, we only implement the specified interface once in a given class's heirarchy, but
            // reimplemented interfaces need to emit new mappings because the reimplementation can change how the
            // interface is implemented.  For example, if a parent class implements an interface method by match,
            // and then a derived class hides that method with a newslot and reimplements the interface, then the
            // interface must link to the newslot method.
            //
            // This is further complicated by the II.12.2 dispatch rules, which have errors.
            //
            // We might be able to optimize this a bit if we can detect that a method reimplementation is the
            // same as the one that already exists.
            //
            // The second complication is that Roslyn sometimes emits useless but apparently legal .override
            // directives that "override" a parent class implementation with the same method that already overrides
            // it from reuseslot matching.

            ParentTypeSpec = parentTypeSpec;

            if (parentClass != null)
            {
                m_allVtableSlots.AddRange(parentClass.m_allVtableSlots);

                List<CppVtableSlot> parentOverrideVisibleSlots = new List<CppVtableSlot>(parentClass.m_overrideVisibleVtableSlots);

                foreach (CppMethod method in m_methods)
                {
                    if (method.Virtual)
                    {
                        if (method.CreatesSlot != null)
                            RemoveOverrides(parentOverrideVisibleSlots, method.CreatesSlot);

                        if (method.Overrides)
                        {
                            List<int> overrideIndexes = FindOverrideIndexes(parentOverrideVisibleSlots, method.Name, method.MethodSignature);
                            if (overrideIndexes.Count != 1)
                                throw new ParseFailedException("Method did not override exactly one slot");
                            method.ReplacesStandardSlot = parentOverrideVisibleSlots[overrideIndexes[0]];
                        }
                    }
                }

                if (m_newImplementationVisibleVtableSlots.Count != 0)
                    throw new Exception();

                foreach (CppMethod method in m_methods)
                {
                    if (method.Virtual && method.MethodDef.MemberAccess == CLRMethodDefRow.MethodMemberAccess.Public)
                    {
                        if (method.Overrides)
                            m_newImplementationVisibleVtableSlots.Add(method.ReplacesStandardSlot);
                        else
                            m_newImplementationVisibleVtableSlots.Add(method.CreatesSlot);
                    }
                }

                m_overrideVisibleVtableSlots.AddRange(parentOverrideVisibleSlots);
            }

            if (parentClass != null)
            {
                // Remove already-implemented interfaces from this class's set, but keep reimplementations
                // to resolve them again
                List<CLRTypeSpec> dedupedInterfaces = new List<CLRTypeSpec>();
                List<CLRTypeSpec> reimplementedInterfaces = new List<CLRTypeSpec>();
                List<CLRTypeSpec> allInheritedInterfaces = new List<CLRTypeSpec>();

                allInheritedInterfaces.AddRange(parentClass.m_newlyImplementedInterfaces);
                allInheritedInterfaces.AddRange(parentClass.m_inheritedImplementedInterfaces);
                foreach (CLRTypeSpec ifc in m_newlyImplementedInterfaces)
                {
                    if (allInheritedInterfaces.Contains(ifc))
                        reimplementedInterfaces.Add(ifc);
                    else
                        dedupedInterfaces.Add(ifc);
                }

                m_newlyImplementedInterfaces = dedupedInterfaces;
                m_reimplementedInterfaces = reimplementedInterfaces;

                m_inheritedFields.AddRange(parentClass.m_inheritedFields);
                m_inheritedFields.AddRange(parentClass.m_fields);

                m_inheritedImplementedInterfaces = allInheritedInterfaces;

                m_inheritedPassiveIfcConversions.AddRange(parentClass.m_passiveIfcConversions);
                m_inheritedPassiveIfcConversions.AddRange(parentClass.m_inheritedPassiveIfcConversions);

                IsValueType = (parentClass.FullName == "System.ValueType" && this.FullName != "System.Enum") || parentClass.FullName == "System.Enum";
                IsEnum = parentClass.FullName == "System.Enum";

                IsMulticastDelegate = (parentClass.FullName == "System.MulticastDelegate");
                IsDelegate = IsMulticastDelegate || (parentClass.FullName == "System.Delegate" && this.FullName != "System.MulticastDelegate");
                HaveInheritedStaticFields = (parentClass.HaveInheritedStaticFields || parentClass.HaveNewStaticFields);

                if (IsDelegate)
                {
                    foreach (CppMethod method in m_methods)
                    {
                        if (method.Name == "Invoke")
                        {
                            DelegateSignature = method.MethodSignature;
                            break;
                        }
                    }

                    if (DelegateSignature == null)
                        throw new ParseFailedException("Malformed delegate");
                }
            }
        }
예제 #12
0
파일: CppClass.cs 프로젝트: elasota/clarity
        public void CheckInterfaceLegality(CppBuilder cppBuilder)
        {
            if (this.TypeDef.IsSealed)
                return;

            foreach (CLRTypeSpec ifcType in m_newlyImplementedInterfaces)
            {
                CppClass ifcClass = cppBuilder.GetCachedClass(ifcType);
                if (ifcClass.HaveAnyGenericMethods)
                    throw new Exception(this.TypeDef.TypeNamespace + "." + this.TypeDef.TypeName + " must be sealed because it implements " + ifcType.ToString() + ", which contains virtual generic methods.");
            }
        }
예제 #13
0
파일: CppClass.cs 프로젝트: elasota/clarity
        // IMPORTANT: This must match "type declaration order" in the spec.
        // Clarity doesn't implement TDO itself, it depends on the new interfaces list being in TDO.
        public void AddExplicitInterface(CppBuilder builder, CLRTypeSpec ifcTypeSpec)
        {
            CppClass ifcType = builder.GetCachedClass(ifcTypeSpec);

            // CS0695 guarantees that type substitution will never result in multiple interfaces
            // resolving to the same passive conversion, so this strategy should be OK
            m_explicitInterfaces.Add(ifcTypeSpec);

            // NOTE: This function is called BEFORE inheritance resolution, which may remove some newly implemented
            // interfaces and convert them to reimplemented.
            foreach (CLRTypeSpec ifc in ifcType.m_newlyImplementedInterfaces)
                AddExplicitInterface(builder, ifc);

            // Only add each explicit interface once
            foreach (CLRTypeSpec ifc in m_newlyImplementedInterfaces)
                if (ifc.Equals(ifcTypeSpec))
                    return;

            // Unique, add it
            m_newlyImplementedInterfaces.Add(ifcTypeSpec);
        }
예제 #14
0
            public CommonTypeLookup(CppBuilder builder)
            {
                CLRAssemblyCollection assm = builder.Assemblies;

                I = assm.InternVagueType(new CLRSigTypeSimple(CLRSigType.ElementType.I));
                I8 = assm.InternVagueType(new CLRSigTypeSimple(CLRSigType.ElementType.I1));
                I16 = assm.InternVagueType(new CLRSigTypeSimple(CLRSigType.ElementType.I2));
                I32 = assm.InternVagueType(new CLRSigTypeSimple(CLRSigType.ElementType.I4));
                I64 = assm.InternVagueType(new CLRSigTypeSimple(CLRSigType.ElementType.I8));
                U = assm.InternVagueType(new CLRSigTypeSimple(CLRSigType.ElementType.U));
                U8 = assm.InternVagueType(new CLRSigTypeSimple(CLRSigType.ElementType.U1));
                U16 = assm.InternVagueType(new CLRSigTypeSimple(CLRSigType.ElementType.U2));
                U32 = assm.InternVagueType(new CLRSigTypeSimple(CLRSigType.ElementType.U4));
                U64 = assm.InternVagueType(new CLRSigTypeSimple(CLRSigType.ElementType.U8));
                F32 = assm.InternVagueType(new CLRSigTypeSimple(CLRSigType.ElementType.R4));
                F64 = assm.InternVagueType(new CLRSigTypeSimple(CLRSigType.ElementType.R8));
                Object = assm.InternVagueType(new CLRSigTypeSimple(CLRSigType.ElementType.OBJECT));
                String = assm.InternVagueType(new CLRSigTypeSimple(CLRSigType.ElementType.STRING));
                Char = assm.InternVagueType(new CLRSigTypeSimple(CLRSigType.ElementType.CHAR));
                Boolean = assm.InternVagueType(new CLRSigTypeSimple(CLRSigType.ElementType.BOOLEAN));
                Array = assm.InternVagueType(new CLRSigTypeSimple(CLRSigType.ElementType.ARRAY));
                ValueType = assm.InternVagueType(new CLRSigTypeSimple(CLRSigType.ElementType.VALUETYPE));
            }
예제 #15
0
파일: VReg.cs 프로젝트: elasota/clarity
 private void DetermineTraceability(CppBuilder builder)
 {
     switch (this.VType.ValType)
     {
         case VType.ValTypeEnum.ValueValue:
             m_traceability = builder.GetCachedTraceability(this.VType.TypeSpec);
             break;
         case VType.ValTypeEnum.ReferenceValue:
         case VType.ValTypeEnum.ManagedPtr:
             m_traceability = CppTraceabilityEnum.DefinitelyTraced;
             break;
         default:
             throw new ArgumentException();
     }
 }
예제 #16
0
        public static void WriteMethodCode(Clarity.Rpa.HighFileBuilder fileBuilder, BinaryWriter writer, CppBuilder builder, CppClass cls, CppMethod method)
        {
            List<VReg> args = new List<VReg>();
            if (!method.Static)
            {
                CppClass thisClass = builder.GetCachedClass(method.DeclaredInClassSpec);
                CLRTypeSpec thisTypeSpec = method.DeclaredInClassSpec;
                VType vt = new VType(thisClass.IsValueType ? VType.ValTypeEnum.ManagedPtr : VType.ValTypeEnum.ReferenceValue, thisTypeSpec);
                args.Add(new VReg(builder, "bThis", vt, args.Count, VReg.UsageEnum.Argument));
            }

            foreach (CLRMethodSignatureInstanceParam param in method.MethodSignature.ParamTypes)
            {
                CLRTypeSpec spec = param.Type;
                VType vt;
                switch (param.TypeOfType)
                {
                    case CLRSigParamOrRetType.TypeOfTypeEnum.ByRef:
                        vt = new VType(VType.ValTypeEnum.ManagedPtr, spec);
                        break;
                    case CLRSigParamOrRetType.TypeOfTypeEnum.Value:
                        vt = new VType(ValTypeForTypeSpec(builder, spec), spec);
                        break;
                    default:
                        throw new ArgumentException();
                }
                args.Add(new VReg(builder, "bParam", vt, args.Count, VReg.UsageEnum.Argument));
            }

            List<VReg> locals = new List<VReg>();

            CLRSigLocalVarSig localVarSig = method.MethodDef.Method.LocalVarSig;
            if (localVarSig != null)
            {
                foreach (CLRSigLocalVar localVar in localVarSig.LocalVars)
                {
                    if (localVar.Constraints != null && localVar.Constraints.Length > 0)
                        throw new NotSupportedException("Local var constraints are not supported");
                    if (localVar.CustomMods != null && localVar.CustomMods.Length > 0)
                        throw new NotSupportedException("Local var custom mods are not supported");

                    CLRTypeSpec localTypeSpec = builder.Assemblies.InternVagueType(localVar.Type);

                    VReg vreg = null;
                    switch (localVar.VarKind)
                    {
                        case CLRSigLocalVar.LocalVarKind.ByRef:
                            vreg = new VReg(builder, "bLocal", new VType(VType.ValTypeEnum.ManagedPtr, localTypeSpec), locals.Count, VReg.UsageEnum.Local);
                            break;
                        case CLRSigLocalVar.LocalVarKind.Default:
                            vreg = new VReg(builder, "bLocal", new VType(CppCilExporter.ValTypeForTypeSpec(builder, localTypeSpec), localTypeSpec), locals.Count, VReg.UsageEnum.Local);
                            break;
                        default:
                            throw new NotImplementedException();
                    }

                    locals.Add(vreg);
                }
            }

            foreach (VReg vReg in locals)
                vReg.Liven();
            foreach (VReg vReg in args)
                vReg.Liven();

            List<VReg> temporaries = new List<VReg>();

            ExceptionHandlingRegion mainRegion = new ExceptionHandlingRegion(null, builder, method, 0, (uint)method.MethodDef.Method.Instructions.Length - 1, null);
            {
                CfgBuilder cfgBuilder = new CfgBuilder(mainRegion, builder, cls, method, args.ToArray(), locals.ToArray(), temporaries);
                mainRegion.RootCfgNode = cfgBuilder.RootNode;
            }

            CppMidCompiler midCompiler = new CppMidCompiler(builder, cls, method, mainRegion, "bTLFrame", args.ToArray(), locals.ToArray(), temporaries.ToArray());

            midCompiler.EmitAll(fileBuilder, writer);

            //MidCompile(builder, cls, method, mainRegion, args.ToArray(), locals.ToArray(), writer.BaseStream);

            foreach (VReg vReg in locals)
            {
                if (!vReg.IsAlive || vReg.IsZombie)
                    throw new Exception("Internal error: local vreg was killed");
            }
            foreach (VReg vReg in args)
            {
                if (!vReg.IsAlive || vReg.IsZombie)
                    throw new Exception("Internal error: arg vreg was killed");
            }
        }