Пример #1
0
        public static CSharpElement ConvertEnumItem(CSharpConverter converter, CppEnumItem cppEnumItem, CSharpElement context)
        {
            // If the context is not an enum, we don't support this scenario.
            if (!(context is CSharpEnum csEnum))
            {
                return(null);
            }

            var enumItemName = converter.GetCSharpName(cppEnumItem, context);
            var csEnumItem   = new CSharpEnumItem(enumItemName)
            {
                CppElement = cppEnumItem
            };

            csEnum.Members.Add(csEnumItem);
            csEnumItem.Comment = converter.GetCSharpComment(cppEnumItem, context);

            // Process any enum item value expression (e.g ENUM_ITEM = 1 << 2)
            if (cppEnumItem.ValueExpression != null)
            {
                var integerValue = converter.ConvertExpression(cppEnumItem.ValueExpression);

                csEnumItem.Value = $"unchecked(({csEnum.IntegerBaseType}){(string.IsNullOrEmpty(integerValue) ? cppEnumItem.Value + "" : integerValue)})";

                // Tag the enum has flags
                if (!csEnum.IsFlags && csEnumItem.Value.Contains("<<"))
                {
                    csEnum.IsFlags = true;
                }

                if (csEnum.IsFlags)
                {
                    csEnumItem.Value = csEnumItem.Value.Replace("<<", $" << ({csEnum.IntegerBaseType})");
                }
            }

            if (converter.Options.GenerateEnumItemAsFields && context.Parent is CSharpClass csClass)
            {
                var csEnumItemAsField = new CSharpField(enumItemName)
                {
                    Modifiers = CSharpModifiers.Const,
                    FieldType = csEnum,
                    Comment   = csEnumItem.Comment,
                    InitValue = $"{csEnum.Name}.{csEnumItem.Name}"
                };
                converter.ApplyDefaultVisibility(csEnumItemAsField, csClass);

                csClass.Members.Add(csEnumItemAsField);
            }

            return(csEnumItem);
        }
Пример #2
0
        private static void ProcessElfEnum(CSharpConverterOptions cppOptions, CSharpCompilation csCompilation, string enumPrefix, string enumClassName)
        {
            var ns = csCompilation.Members.OfType <CSharpGeneratedFile>().First().Members.OfType <CSharpNamespace>().First();

            var rawElfClass = ns.Members.OfType <CSharpClass>().First();

            var enumRawFields = rawElfClass.Members.OfType <CSharpField>().Where(x => (x.Modifiers & CSharpModifiers.Const) != 0 && x.Name.StartsWith(enumPrefix)).ToList();

            var enumClass = new CSharpStruct(enumClassName)
            {
                Modifiers = CSharpModifiers.Partial | CSharpModifiers.ReadOnly
            };

            ns.Members.Add(enumClass);

            bool isReloc = enumPrefix == "R_";

            var filteredFields = new List <CSharpField>();

            foreach (var enumRawField in enumRawFields)
            {
                var rawName = enumRawField.Name;

                string relocArch = null;

                if (isReloc)
                {
                    foreach (var mapReloc in MapRelocMachineToArch)
                    {
                        if (rawName.StartsWith(mapReloc.Key))
                        {
                            relocArch = mapReloc.Value;
                            break;
                        }
                    }

                    if (relocArch == null)
                    {
                        continue;
                    }
                }

                // NUM fields
                if (rawName.EndsWith("_NUM"))
                {
                    continue;
                }

                filteredFields.Add(enumRawField);

                var csFieldName = isReloc ? rawName : rawName.Substring(enumPrefix.Length); // discard EM_
                if (csFieldName.StartsWith("386"))
                {
                    csFieldName = $"I{csFieldName}";
                }
                else
                {
                    switch (csFieldName)
                    {
                    case "88K":
                        csFieldName = "M88K";
                        break;

                    case "860":
                        csFieldName = "I860";
                        break;

                    case "960":
                        csFieldName = "I960";
                        break;

                    default:
                        // assume Motorola
                        if (csFieldName.StartsWith("68"))
                        {
                            csFieldName = $"M{csFieldName}";
                        }

                        break;
                    }
                }

                if (char.IsDigit(csFieldName[0]))
                {
                    throw new InvalidOperationException($"The enum name `{rawName}` starts with a number and needs to be modified");
                }

                csFieldName = CSharpHelper.EscapeName(csFieldName);

                var enumField = new CSharpField(csFieldName)
                {
                    Modifiers  = CSharpModifiers.Static | CSharpModifiers.ReadOnly,
                    FieldType  = enumClass,
                    Visibility = CSharpVisibility.Public,
                    Comment    = enumRawField.Comment,
                    InitValue  = relocArch != null ?
                                 $"new {enumClass.Name}(ElfArch.{relocArch}, {cppOptions.DefaultClassLib}.{rawName})" :
                                 $"new {enumClass.Name}({cppOptions.DefaultClassLib}.{rawName})"
                };

                enumClass.Members.Add(enumField);
            }

            var toStringInternal = new CSharpMethod()
            {
                Name       = "ToStringInternal",
                Visibility = CSharpVisibility.Private,
                ReturnType = CSharpPrimitiveType.String
            };

            enumClass.Members.Add(toStringInternal);

            toStringInternal.Body = (writer, element) =>
            {
                var values = new HashSet <object>();
                if (isReloc)
                {
                    writer.WriteLine("switch (((ulong)Value << 16) | Arch.Value)");
                }
                else
                {
                    writer.WriteLine("switch (Value)");
                }
                writer.OpenBraceBlock();
                foreach (var rawField in filteredFields)
                {
                    var cppField = ((CppField)rawField.CppElement);
                    if (isReloc)
                    {
                        string relocMachine = null;
                        foreach (var mapReloc in MapRelocMachineToMachine)
                        {
                            if (rawField.Name.StartsWith(mapReloc.Key))
                            {
                                relocMachine = mapReloc.Value;
                                break;
                            }
                        }

                        if (relocMachine == null)
                        {
                            continue;
                        }

                        if (!values.Add(relocMachine + "$" + cppField.InitValue.Value))
                        {
                            continue;
                        }

                        writer.WriteLine($"case ((ulong){cppOptions.DefaultClassLib}.{rawField.Name} << 16) | {cppOptions.DefaultClassLib}.{relocMachine} : return \"{rawField.Name}\";");
                    }
                    else
                    {
                        if (!values.Add(cppField.InitValue.Value))
                        {
                            continue;
                        }

                        string descriptionText = rawField.Name;

                        if (cppField.Comment != null)
                        {
                            descriptionText += " - " + cppField.Comment.ToString().Replace("\"", "\\\"");
                        }
                        descriptionText = descriptionText.Replace("\r\n", "").Replace("\n", "");
                        writer.WriteLine($"case {cppOptions.DefaultClassLib}.{rawField.Name}: return \"{descriptionText}\";");
                    }
                }

                writer.WriteLine($"default: return \"Unknown {enumClassName}\";");
                writer.CloseBraceBlock();
            };
        }
Пример #3
0
        private static void GenerateDwarfAttributes(CSharpNamespace ns)
        {
            var alreadyDone = new HashSet <string>();

            var csHelper = new CSharpClass("DwarfHelper")
            {
                Modifiers  = CSharpModifiers.Static | CSharpModifiers.Partial,
                Visibility = CSharpVisibility.Public
            };

            ns.Members.Add(csHelper);

            var csField = new CSharpField("AttributeToEncoding")
            {
                Modifiers  = CSharpModifiers.Static | CSharpModifiers.ReadOnly,
                Visibility = CSharpVisibility.Private,
                FieldType  = new CSharpArrayType(new CSharpFreeType("DwarfAttributeEncoding"))
            };

            csHelper.Members.Add(csField);

            var fieldArrayBuilder = new StringBuilder();

            fieldArrayBuilder.AppendLine("new DwarfAttributeEncoding[] {");

            int currentAttributeIndex = 0;

            foreach (var attrEncoding in MapAttributeToEncoding)
            {
                var attrEncodingParts = attrEncoding.Split(' ', StringSplitOptions.RemoveEmptyEntries);
                var attributeName     = attrEncodingParts[0];
                var attributeIndex    = int.Parse(attrEncodingParts[1].Substring(2), System.Globalization.NumberStyles.HexNumber);
                var rawName           = attributeName.Substring("DW_AT_".Length);
                //var csharpName = CSharpifyName(rawName);

                string attrType = "object";
                var    kind     = AttributeKind.Managed;

                if (attributeName == "DW_AT_accessibility")
                {
                    attrType = "DwarfAccessibility";
                    kind     = AttributeKind.ValueType;
                }
                else if (attributeName == "DW_AT_visibility")
                {
                    attrType = "DwarfVisibility";
                    kind     = AttributeKind.ValueType;
                }
                else if (attributeName == "DW_AT_virtuality")
                {
                    attrType = "DwarfVirtuality";
                    kind     = AttributeKind.ValueType;
                }
                else if (attributeName == "DW_AT_language")
                {
                    attrType = "DwarfLanguageKind";
                    kind     = AttributeKind.ValueType;
                }
                else if (attributeName == "DW_AT_identifier_case")
                {
                    attrType = "DwarfIdentifierCaseKind";
                    kind     = AttributeKind.ValueType;
                }
                else if (attributeName == "DW_AT_calling_convention")
                {
                    attrType = "DwarfCallingConvention";
                    kind     = AttributeKind.ValueType;
                }
                else if (attributeName == "DW_AT_inline")
                {
                    attrType = "DwarfInlineKind";
                    kind     = AttributeKind.ValueType;
                }
                else if (attributeName == "DW_AT_ordering")
                {
                    attrType = "DwarfArrayOrderingKind";
                    kind     = AttributeKind.ValueType;
                }
                else if (attributeName == "DW_AT_discr_list")
                {
                    attrType = "DwarfDiscriminantListKind";
                    kind     = AttributeKind.ValueType;
                }
                else if (attrEncodingParts.Length == 3)
                {
                    switch (attrEncodingParts[2])
                    {
                    case "string":
                        attrType = "string";
                        break;

                    case "flag":
                        attrType = "bool";
                        kind     = AttributeKind.ValueType;
                        break;

                    case "reference":
                        attrType = "DwarfDIE";
                        break;

                    case "address":
                        attrType = "ulong";
                        kind     = AttributeKind.ValueType;
                        break;

                    case "constant":
                        attrType = "DwarfConstant";
                        kind     = AttributeKind.ValueType;
                        break;

                    case "lineptr":
                        attrType = "DwarfLineProgramTable";
                        break;

                    case "exprloc":
                        attrType = "DwarfExpression";
                        break;

                    case "loclist":
                    case "loclistptr":
                        attrType = "DwarfLocation";
                        break;

                    case "addrptr":
                    case "macptr":
                    case "rnglist":
                    case "rangelistptr":
                    case "rnglistsptr":
                    case "stroffsetsptr":
                        attrType = "ulong";
                        kind     = AttributeKind.ValueType;
                        break;
                    }
                }
                else if (attrEncodingParts.Length > 3)
                {
                    var key = string.Join(" ", attrEncodingParts.Skip(2).ToArray());
                    alreadyDone.Add(key);

                    Console.WriteLine(attrEncoding);

                    bool hasConstant = false;
                    for (int i = 2; i < attrEncodingParts.Length; i++)
                    {
                        switch (attrEncodingParts[i])
                        {
                        case "loclist":
                        case "loclistptr":
                            attrType = "DwarfLocation";
                            kind     = AttributeKind.ValueType;
                            goto next;

                        case "constant":
                            hasConstant = true;
                            break;
                        }
                    }

                    if (hasConstant)
                    {
                        attrType = "DwarfConstant";
                        kind     = AttributeKind.ValueType;
                    }
                }

next:

                MapAttributeCompactNameToType.Add(attributeName.Replace("_", string.Empty), new AttributeMapping(rawName, attrType, kind));

                const int PaddingEncodingName = 50;

                for (; currentAttributeIndex < attributeIndex; currentAttributeIndex++)
                {
                    fieldArrayBuilder.AppendLine($"        {"DwarfAttributeEncoding.None",-PaddingEncodingName}, // 0x{currentAttributeIndex:x2} (undefined)");
                }

                for (int i = 2; i < attrEncodingParts.Length; i++)
                {
                    string name;
                    switch (attrEncodingParts[i])
                    {
                    case "string":
                        name = "String";
                        break;

                    case "flag":
                        name = "Flag";
                        break;

                    case "block":
                        name = "Block";
                        break;

                    case "reference":
                        name = "Reference";
                        break;

                    case "address":
                        name = "Address";
                        break;

                    case "constant":
                        name = "Constant";
                        break;

                    case "lineptr":
                        name = "LinePointer";
                        break;

                    case "exprloc":
                        name = "ExpressionLocation";
                        break;

                    case "loclist":
                        name = "LocationList";
                        break;

                    case "loclistptr":
                        name = "LocationListPointer";
                        break;

                    case "loclistsptr":
                        name = "LocationListsPointer";
                        break;

                    case "addrptr":
                        name = "AddressPointer";
                        break;

                    case "macptr":
                        name = "MacroPointer";
                        break;

                    case "rnglist":
                        name = "RangeList";
                        break;

                    case "rangelistptr":
                        name = "RangeListPointer";
                        break;

                    case "rnglistsptr":
                        name = "RangeListsPointer";
                        break;

                    case "stroffsetsptr":
                        name = "StringOffsetPointer";
                        break;

                    default:
                        throw new InvalidOperationException($"Unknown encoding {attrEncodingParts[i]}");
                    }

                    bool isLast = i + 1 == attrEncodingParts.Length;

                    fieldArrayBuilder.Append($"        {"DwarfAttributeEncoding." + name + (isLast ? "" : " | "),-PaddingEncodingName}");

                    if (isLast)
                    {
                        fieldArrayBuilder.Append($", // 0x{currentAttributeIndex:x2} {attributeName} ");
                    }
                    fieldArrayBuilder.AppendLine();
                }

                currentAttributeIndex++;
            }

            fieldArrayBuilder.Append("    }");
            csField.InitValue = fieldArrayBuilder.ToString();

            Console.WriteLine();
            foreach (var key in alreadyDone.ToArray().OrderBy(x => x))
            {
                Console.WriteLine(key);
            }
        }
Пример #4
0
 /// <summary>
 /// Initializes a new instance of the <see cref="FieldGenerator"/> class for the specified <see cref="IndentedStreamWriter"/>
 /// </summary>
 /// <param name="field">Field to generate</param>
 /// <param name="writer"><see cref="IndentedStreamWriter"/> used to write to</param>
 public FieldGenerator(CSharpField field, IndentedStreamWriter writer) : base(writer) => _field = field;