private void ProcessParameters(StringBuilder nm, BackReferenceList backReferences, ParameterInfo[] parameters, int argStart, BackReferenceList argumentBackReferences) { for (int i = argStart; i < parameters.Length; i++) { var mangleType = GetMangleType(parameters[i], parameters[i].ParameterType); if (mangleType.Modifiers.Contains(CppModifiers.Delegate)) { var sb = new StringBuilder(); sb.Append("P6AX"); var method = parameters[i].ParameterType.GetMethod("Invoke"); var delegateParams = method.GetParameters(); ProcessParameters(sb, backReferences, delegateParams, 0, argumentBackReferences); var code = sb.ToString(); nm.Append(argumentBackReferences.Add(code, true)); nm.Append("Z"); continue; } /* Basically what is going on is that we are pre-scanning the elements of the * parameter to see if any new backreferences were created. If there were we need * to add the updated typeCode to are arguments backreference since they will be * used in any proceeding lookups. If they are the same we just do things normally. * * We could improve this by creating a method to do the pre-scan but we would have * to do some fanangling so this works for now. */ var originalTypeCode = GetTypeCode(mangleType, backReferences); var typeCode = GetTypeCode(mangleType, backReferences); if (originalTypeCode == typeCode) { nm.Append(argumentBackReferences.Add(typeCode, false)); } else { argumentBackReferences.Add(typeCode, false); nm.Append(originalTypeCode); } } }
protected override string GetMangledMethodName(CppTypeInfo typeInfo, MethodInfo methodInfo) { var methodName = methodInfo.Name; var type = typeInfo.GetMangleType(); var className = type.ElementTypeName; var backReferences = new BackReferenceList(); MethodType methodType = GetMethodType(typeInfo, methodInfo); ParameterInfo [] parameters = methodInfo.GetParameters(); StringBuilder nm = new StringBuilder("?", 30); if (methodType == MethodType.NativeCtor) { nm.Append("?0"); } else if (methodType == MethodType.NativeDtor) { nm.Append("?1"); } else { nm.Append(backReferences.Add(methodName)); } var templates = type.Modifiers.OfType <CppModifiers.TemplateModifier>().FirstOrDefault(); if (templates != null) { nm.Append("?$"); } nm.Append(backReferences.Add(className)); // FIXME: This has to include not only the name of the immediate containing class, // but also all names of containing classes and namespaces up the hierarchy. if (type.Namespaces != null) { foreach (var ns in type.Namespaces.Reverse()) { nm.Append(backReferences.Add(ns)); } } // Add our template types after the class name if (templates != null) { templates.Types.All(mangleType => { var originalTypeCode = GetTypeCode(mangleType, backReferences); var typeCode = GetTypeCode(mangleType, backReferences); if (originalTypeCode == typeCode) { nm.Append(backReferences.Add(typeCode, false)); } else { backReferences.Add(typeCode, false); nm.Append(originalTypeCode); } return(true); }); nm.Append("@"); } nm.Append("@"); // function modifiers are a matrix of consecutive uppercase letters // depending on access type and virtual (far)/static (far)/far modifiers // first, access type char funcModifier = 'Q'; // (public) if (IsProtected(methodInfo)) { funcModifier = 'I'; } else if (IsPrivate(methodInfo)) // (probably don't need this) { funcModifier = 'A'; } // now, offset based on other modifiers if (IsStatic(methodInfo)) { funcModifier += (char)2; } else if (IsVirtual(methodInfo)) { funcModifier += (char)4; } nm.Append(funcModifier); // FIXME: deal with other storage classes for "this" i.e. the "volatile" in -> int foo () volatile; if (!IsStatic(methodInfo)) { if (IsConst(methodInfo)) { nm.Append('B'); } else { nm.Append('A'); } } switch (GetCallingConvention(methodInfo)) { case CallingConvention.Cdecl: nm.Append('A'); break; case CallingConvention.ThisCall: nm.Append('E'); break; case CallingConvention.StdCall: nm.Append('G'); break; case CallingConvention.FastCall: nm.Append('I'); break; } // FIXME: handle const, volatile modifiers on return type // FIXME: the manual says this is only omitted for simple types.. are we doing the right thing here? if (methodType == MethodType.NativeCtor || methodType == MethodType.NativeDtor) { nm.Append('@'); } else { CppType returnType = GetMangleType(methodInfo.ReturnTypeCustomAttributes, methodInfo.ReturnType); // TODO: Should this actually be done in CppType.ToManagedType // I wasn't sure how it would affect Itanium mangled names bool hadPointer = false; if (methodInfo.ReturnTypeCustomAttributes.IsDefined(typeof(ByValAttribute), false)) { hadPointer = returnType.Modifiers.Remove(CppModifiers.Pointer); if (returnType.ElementType == CppTypes.Class || returnType.ElementType == CppTypes.Struct || returnType.ElementType == CppTypes.Union) { nm.Append("?A"); } } nm.Append(GetTypeCode(returnType, backReferences)); if (hadPointer) { returnType.Modifiers.Add(CppModifiers.Pointer); } } int argStart = (IsStatic(methodInfo)? 0 : 1); if (parameters.Length == argStart) { // no args (other than C++ "this" object) nm.Append("XZ"); return(nm.ToString()); } ProcessParameters(nm, backReferences, parameters, argStart, new BackReferenceList()); nm.Append("@Z"); return(nm.ToString()); }
private static string GetTypeCodeOrBackReference(string elementTypeName, BackReferenceList backReferences) { return(backReferences.Add(elementTypeName)); }