示例#1
0
 public CsProperty(CppMethod cppCallable, string name, CsMethod getter, CsMethod setter, bool isPropertyParam = false) : base(cppCallable, name)
 {
     Getter          = getter;
     Setter          = setter;
     IsPropertyParam = isPropertyParam;
     IsPersistent    = getter?.IsPersistent ?? IsPersistent;
 }
示例#2
0
        public void RemoveParentDoesNotRemoveAllParents()
        {
            var config = new Config.ConfigFile
            {
                Id        = nameof(RemoveParentDoesNotRemoveAllParents),
                Assembly  = nameof(RemoveParentDoesNotRemoveAllParents),
                Namespace = nameof(RemoveParentDoesNotRemoveAllParents),
                Includes  =
                {
                    new Config.IncludeRule
                    {
                        Attach    = true,
                        File      = "cppEnum.h",
                        Namespace = nameof(RemoveParentDoesNotRemoveAllParents)
                    }
                },
                Mappings =
                {
                    new Config.RemoveRule
                    {
                        Method = @"#.*ToRemove"
                    }
                }
            };

            var cppModel = new CppModule();

            var cppInclude = new CppInclude
            {
                Name = "cppEnum"
            };

            var cppIface = new CppInterface
            {
                Name = "TestInterface"
            };

            cppInclude.Add(cppIface);

            var cppMethod = new CppMethod
            {
                Name = "Method"
            };

            cppMethod.Add(new CppParameter
            {
                Name = "ParamToRemove"
            });
            cppModel.Add(cppInclude);

            var(solution, _) = MapModel(cppModel, config);

            var members = solution.EnumerateDescendants();

            Assert.NotEmpty(members.OfType <CsInterface>());
            Assert.Empty(members.OfType <CsParameter>());
        }
示例#3
0
        public override bool VisitCppMethod(CppMethod cppMethod)
        {
            Declaration declaration;

            cppElementToDeclarationMapping.TryGetValue(cppMethod.Parent, out declaration);

            switch (cppMethod.GetType().Name)
            {
            case "CppFunction":
                TranslationUnit unit     = declaration != null ? declaration as TranslationUnit : FindDeclParent <TranslationUnit>(cppMethod.Parent);
                Function        function = new Function();

                function.Name       = cppMethod.Name;
                function.Namespace  = unit.FindNamespace(cppMethod.Namespace);
                function.ReturnType = GetQualifiedType(cppMethod.ReturnType);

                unit.Functions.Add(function);
                cppElementToDeclarationMapping.Add(cppMethod, function);
                break;

            default:
                Class  @class = declaration != null ? declaration as Class : FindDeclParent <Class>(cppMethod.Parent);
                Method method = new Method();

                method.Kind      = CXXMethodKind.Normal;
                method.Name      = cppMethod.Name;
                method.Namespace = @class.Namespace;

                try
                {
                    method.Access = (AccessSpecifier)Enum.Parse(typeof(AccessSpecifier), cppMethod.Access, true);
                }
                catch (ArgumentException)
                {
                    method.Access = AccessSpecifier.Internal;
                }

                method.IsOverride = cppMethod.Override;
                method.IsVirtual  = cppMethod.Virtual;

                method.ReturnType = GetQualifiedType(cppMethod.ReturnType);

                @class.Methods.Add(method);
                cppElementToDeclarationMapping.Add(cppMethod, method);
                break;
            }

            return(base.VisitCppMethod(cppMethod));
        }
示例#4
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);
        }
示例#5
0
        private CXChildVisitResult VisitMethodParameter(CXCursor cursor, CXCursor parent, IntPtr data)
        {
            CppMethod method = units[parent] as CppMethod;

            if (method == null)
            {
                return(CXChildVisitResult.CXChildVisit_Continue);
            }

            string name = clang.getCString(clang.getCursorSpelling(cursor));
            Type   type = FromCXType(clang.getCursorType(cursor), method.Templates.Concat(new[] { method.Parent as Type }));

            method.parameters.Add(name, type);

            return(CXChildVisitResult.CXChildVisit_Continue);
        }
示例#6
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();
        }
示例#7
0
        public CsMethod(CppMethod cppMethod, string name) : base(cppMethod, name)
        {
            var tag = cppMethod?.Rule;

            AllowProperty         = tag?.Property ?? AllowProperty;
            IsPersistent          = tag?.Persist ?? IsPersistent;
            Hidden                = tag?.Hidden ?? Hidden;
            CustomVtbl            = tag?.CustomVtbl ?? CustomVtbl;
            IsKeepImplementPublic = tag?.IsKeepImplementPublic ?? IsKeepImplementPublic;

            if (cppMethod == null)
            {
                return;
            }

            // Apply any offset to the method's vtable
            var offset = tag.LayoutOffsetTranslate;

            Offset        = cppMethod.Offset + offset;
            WindowsOffset = cppMethod.WindowsOffset + offset;
        }
示例#8
0
 public CsMethod(CppMethod cppMethod)
     : base(cppMethod)
 {
 }
示例#9
0
        public void AddMethod(CLRAssemblyCollection assemblies, CLRMethodDefRow method)
        {
            CppMethod cppMethod = new CppMethod(assemblies, m_typeDef, method);
            m_methods.Add(cppMethod);
            if (cppMethod.Virtual && !cppMethod.Overrides)
            {
                m_overrideVisibleVtableSlots.Add(cppMethod.CreatesSlot);
                m_allVtableSlots.Add(cppMethod.CreatesSlot);
            }

            if (cppMethod.NumGenericParameters > 0)
                HaveAnyGenericMethods = true;
        }
示例#10
0
        public void DefineWithNativeImplementationDefinesNativeImplementationType()
        {
            var config = new ConfigFile
            {
                Id        = nameof(Simple),
                Namespace = nameof(Simple),
                Includes  =
                {
                    new IncludeRule
                    {
                        File      = "interface.h",
                        Attach    = true,
                        Namespace = nameof(Simple)
                    }
                },
                Extension =
                {
                    new DefineExtensionRule
                    {
                        Interface            = "Imported.Param",
                        NativeImplementation = "Imported.ParamNative"
                    }
                },
                Bindings =
                {
                    new BindRule("int",   "System.Int32"),
                    new BindRule("Param", "Imported.Param")
                }
            };

            var iface = new CppInterface
            {
                Name             = "Interface",
                TotalMethodCount = 1
            };

            var method = new CppMethod
            {
                Name        = "method",
                ReturnValue = new CppReturnValue
                {
                    TypeName = "int"
                }
            };

            method.Add(new CppParameter
            {
                Name     = "param",
                TypeName = "Param",
                Pointer  = "*"
            });

            iface.Add(method);

            var include = new CppInclude
            {
                Name = "interface"
            };

            include.Add(iface);

            var module = new CppModule();

            module.Add(include);

            var(solution, _) = MapModel(module, config);

            Assert.Single(solution.EnumerateDescendants().OfType <CsParameter>());

            var param = solution.EnumerateDescendants().OfType <CsParameter>().First();

            Assert.IsType <CsInterface>(param.PublicType);

            Assert.NotNull(((CsInterface)param.PublicType).NativeImplementation);

            Assert.False(Logger.HasErrors);
        }
示例#11
0
 public CppMethodSpec(CppMethod method, CLRTypeSpec[] genericParameters)
 {
     CppMethod = method.Instantiate(null, genericParameters);
     GenericParameters = genericParameters;
 }
示例#12
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");
            }
        }
示例#13
0
        private void WriteVtableThunk(Clarity.Rpa.HighFileBuilder fileBuilder, BinaryWriter writer, CppClass cls, CppMethod method, CppVtableSlot slot)
        {
            CLRMethodSignatureInstance slotSig = slot.Signature;

            writer.Write(fileBuilder.IndexMethodDeclTag(slot.VtableSlotTag));
            writer.Write(fileBuilder.IndexMethodSignatureTag(RpaTagFactory.CreateMethodSignature(slot.Signature)));

            if (cls.TypeDef.Semantics != CLRTypeDefRow.TypeSemantics.Interface)
            {
                writer.Write(method.Abstract);

                if (!method.Abstract)
                {
                    if (method.NumGenericParameters == 0)
                        writer.Write(method.Final);

                    if (method.Static)
                        throw new Exception("VTable slot implemented by static method");

                    writer.Write(fileBuilder.IndexMethodDeclTag(method.VtableSlotTag));
                }
            }
        }
示例#14
0
        private void ExportMethodCode(Clarity.Rpa.HighFileBuilder fileBuilder, BinaryWriter writer, CppClass cls, CppMethod method)
        {
            if (method.Abstract)
                throw new ArgumentException("Can't export code of an abstract method");

            if (method.MethodDef.Method == null)
                writer.Write(true);
            else
            {
                writer.Write(false);

                if (!method.Abstract && method.MethodDef.Method != null)
                    CppCilExporter.WriteMethodCode(fileBuilder, writer, this, cls, method);
            }
        }
示例#15
0
        /// <summary>
        /// Parse C++ class or interface from given <see cref="XElement"/>
        /// </summary>
        private T ParseClassOrInterface <T>(XElement xElement) where T : CppBase, new()
        {
            // If element is already transformed, return it
            T cppBaseType = xElement.Annotation <T>();

            if (cppBaseType != null)
            {
                return(cppBaseType);
            }

            // Else, create a new CppInterface
            cppBaseType      = new T();
            cppBaseType.Name = xElement.Attribute("name").Value;
            cppBaseType.Id   = xElement.Attribute("id").Value;
            xElement.AddAnnotation(cppBaseType);

            // Calculate offsets using inheritance
            int offsetMethod      = 0;
            int offsetConstructor = 0;

            XAttribute           basesAttribute = xElement.Attribute("bases");
            IEnumerable <string> bases          = basesAttribute != null?basesAttribute.Value.Split(' ') : Enumerable.Empty <string>();

            foreach (string xElementBaseId in bases)
            {
                if (string.IsNullOrEmpty(xElementBaseId))
                {
                    continue;
                }

                XElement   xElementBase   = mapIdToXElement[xElementBaseId];
                CppElement cppElementBase = ParseElement(xElementBase);

                if (string.IsNullOrEmpty(cppBaseType.ParentName))
                {
                    cppBaseType.ParentName = cppElementBase.Name;
                }

                // Get methods count from base class or interface
                offsetMethod      += ((cppElementBase is CppBase) ? ((CppBase)cppElementBase).TotalMethodCount : 0);
                offsetConstructor += ((cppElementBase is CppBase) ? ((CppBase)cppElementBase).TotalConstructorCount : 0);
            }

            List <CppConstructor> constructors = new List <CppConstructor>();
            List <CppMethod>      methods      = new List <CppMethod>();

            // Parse methods
            foreach (XElement element in xElement.Elements())
            {
                string     overrides          = String.Empty;
                XAttribute overridesAttribute = element.Attribute("overrides");
                if (overridesAttribute != null)
                {
                    overrides = overridesAttribute.Value;
                }

                string     pureVirtual          = String.Empty;
                XAttribute pureVirtualAttribute = element.Attribute("pure_virtual");
                if (pureVirtualAttribute != null)
                {
                    pureVirtual = pureVirtualAttribute.Value;
                }

                string     access          = String.Empty;
                XAttribute accessAttribute = element.Attribute("access");
                if (accessAttribute != null)
                {
                    access = accessAttribute.Value;
                }

                // Parse method with pure virtual (=0) and that do not override any other methods
                if (element.Name.LocalName == "Method")
                {
                    CppMethod cppMethod = ParseMethodOrFunction <CppMethod>(element);

                    if (!string.IsNullOrWhiteSpace(pureVirtual))
                    {
                        cppMethod.Virtual = true;
                    }

                    if (!string.IsNullOrWhiteSpace(overrides))
                    {
                        cppMethod.Override = true;
                    }

                    if (!string.IsNullOrWhiteSpace(access))
                    {
                        cppMethod.Access = access;
                    }

                    methods.Add(cppMethod);
                }
                else if (element.Name.LocalName == "Constructor")
                {
                    CppConstructor cppConstructor = ParseConstructor(element);

                    if (!string.IsNullOrWhiteSpace(access))
                    {
                        cppConstructor.Access = access;
                    }

                    constructors.Add(cppConstructor);
                }
            }

            // The Visual C++ compiler breaks the rules of the COM ABI when overloaded methods are used.
            // It will group the overloads together in memory and lay them out in the reverse of their declaration order.
            // Since GCC always lays them out in the order declared, we have to modify the order of the methods to match Visual C++.
            // See http://support.microsoft.com/kb/131104 for more information.
            for (int i = 0; i < methods.Count; i++)
            {
                string name = methods[i].Name;

                // Look for overloads of this function
                for (int j = i + 1; j < methods.Count; j++)
                {
                    var nextMethod = methods[j];
                    if (nextMethod.Name == name)
                    {
                        // Remove this one from its current position further into the vtable
                        methods.RemoveAt(j);

                        // Put this one before all other overloads (aka reverse declaration order)
                        int k = i - 1;
                        while (k >= 0 && methods[k].Name == name)
                        {
                            k--;
                        }
                        methods.Insert(k + 1, nextMethod);
                        i++;
                    }
                }
            }

            // Add the methods to the cppbase with the correct offsets
            foreach (CppMethod cppMethod in methods)
            {
                cppMethod.Offset = offsetMethod++;
                cppBaseType.Add(cppMethod);
            }

            // Add the constructor to the cppbase with the correct offsets
            foreach (CppConstructor cppConstructor in constructors)
            {
                cppConstructor.Offset = offsetConstructor++;
                cppBaseType.Add(cppConstructor);
            }

            cppBaseType.TotalConstructorCount = offsetConstructor;
            cppBaseType.TotalMethodCount      = offsetMethod;

            return(cppBaseType);
        }
示例#16
0
 public CsMethod(CppMethod cppMethod)
 {
     CppElement = cppMethod;
 }
示例#17
0
        private CXChildVisitResult VisitMethod(CXCursor cursor, CXCursor parent, IntPtr data)
        {
            Unit         unitParent = units[parent];
            string       unitName   = clang.getCString(clang.getCursorSpelling(cursor));
            CXCursorKind unitKind   = clang.getCursorKind(cursor);

            CppMethod unit;

            if (unitKind == CXCursorKind.CXCursor_Constructor && unitParent is CppType)
            {
                unit = new CppConstructor(unitParent as CppType);
            }
            else if (unitKind == CXCursorKind.CXCursor_Destructor && unitParent is CppType)
            {
                unit = new CppDestructor(unitParent as CppType);
            }
            else
            {
                unit = new CppMethod(unitParent, unitName);
            }

            // Find modifiers
            if (unitParent is Type && modifiers.ContainsKey(unitParent as Type))
            {
                unit.modifiers = modifiers[unitParent as Type];
            }
            if (clang.CXXMethod_isStatic(cursor) > 0)
            {
                unit.modifiers |= Modifiers.Static;
            }

            // Find result type
            if (unitKind != CXCursorKind.CXCursor_Constructor && unitKind != CXCursorKind.CXCursor_Destructor)
            {
                CXType result = clang.getCursorResultType(cursor);
                unit.result = FromCXType(result, GetAllTemplates(unitParent).Concat(new[] { unitParent as Type }));
            }

            // Merge with properties

            /*if (unitName.StartsWith("Get") || unitName.StartsWith("Set"))
             * {
             * CppField property = properties.FirstOrDefault(p => p.Name == unitName.Substring(3) && p.Parent == unitParent) as CppField;
             *      if (property != null)
             *      {
             *              if (unitName.StartsWith("Get"))
             * property.getAccessor = unit;
             *              else
             * property.setAccessor = unit;
             *      }
             * }*/

            // Parse templates
            int startPosition = unitName.IndexOf('<');
            int stopPosition  = startPosition == -1 ? -1 : unitName.IndexOf('>', startPosition);

            if (startPosition >= 0 && stopPosition >= 0)
            {
                string[] typeStrings = unitName.Substring(startPosition, stopPosition - startPosition).Split(',').Select(t => t.Trim()).ToArray();

                foreach (string typeString in typeStrings)
                {
                    unit.templates.Add(CppType.GetReference(typeString));
                }

                if (unitParent is Type)
                {
                    foreach (Type type in (unitParent as Type).Templates)
                    {
                        unit.templates.RemoveAll(t => t.Equals(type));
                    }
                }
            }

            units.Add(cursor, unit);

            if (unitParent is CppType)
            {
                (unitParent as CppType).methods.Add(unit);
            }

            return(CXChildVisitResult.CXChildVisit_Recurse);
        }
示例#18
0
 public CppMethodSpec(CppMethod method)
 {
     CppMethod = method;
 }