Пример #1
0
        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);
                }
            }
        }
Пример #2
0
        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());
        }
Пример #3
0
 private static string GetTypeCodeOrBackReference(string elementTypeName, BackReferenceList backReferences)
 {
     return(backReferences.Add(elementTypeName));
 }