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; }
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>()); }
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)); }
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); }
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); }
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(); }
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; }
public CsMethod(CppMethod cppMethod) : base(cppMethod) { }
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; }
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); }
public CppMethodSpec(CppMethod method, CLRTypeSpec[] genericParameters) { CppMethod = method.Instantiate(null, genericParameters); GenericParameters = genericParameters; }
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"); } }
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)); } } }
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); } }
/// <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); }
public CsMethod(CppMethod cppMethod) { CppElement = cppMethod; }
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); }
public CppMethodSpec(CppMethod method) { CppMethod = method; }