GithubHelp home page GithubHelp logo

mochilibraries / biohazrd Goto Github PK

View Code? Open in Web Editor NEW
59.0 4.0 8.0 1.29 MB

A framework for automatically generating binding wrappers for C/C++ libraries

License: MIT License

C# 99.92% C 0.08%
biohazrd clang libclang dotnet interop clangsharp

biohazrd's People

Contributors

pathogendavid avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

biohazrd's Issues

Handle file system case-sensitivity in TranslatedLibraryBuidler

TranslatedLibraryBuilder treats file paths as case-insensitive regardless of the case-sensitivity of the file system. This was done to avoid problems arising between a difference in casing between what is provided to TranslatedLibraryBuilder, the file system, and the #include directives in the C++ source. (We regularly compare filenames for the sake of resolving which Clang cursors correspond to which input files -- or to determine if the cursor is out-of-scope.)

We do not expect well-formed C++ code to involve incorrect casing or to have multiple files with the same casing as both practices are non-portable. (The former is a warning -Wnonportable-include-path in Clang.) As such, this is not really a high priority as it's only really problematic with poorly-written C++ libraries on Linux or unusual macOS/Windows systems.

The ideal solution would be to normalize paths to their actual casing once dotnet/runtime#14321 is realized.

I am hesitant to conditionally use case-sensitive comparisons based on the OSPlatform because case-sensitivity is an attribute of the file system, not the OS. (ext4 even allows case-sensitivity as an attribute of a directory.)

Improve translation of anonymous enums used to type a field.

Right now an anonymous (legacy-style) enum is translated as loose constants in all situations, including when it is used to type a field. For example:

class AnonymousEnumWithField
{
public:
    enum
    {
        Red,
        Green,
        Blue
    } AnonymousEnumField;

    int FieldAfterEnum;
};

While this is accurate to how they work in C++, it isn't a particularly friendly translation. We should provide a transformation that fixes up the enum to meet C# expectations.

Don't leak return buffer semantics outside of trampolines

These aren't consistent between calling conventions/platforms, so leaking this implementation detail will cause API breakage between platforms.

Not sure how this can be solved for virtual methods when they're overridden from C#.

Add support for preprocessor constants

This should most likely be optional. If memory serves, asking Clang to retain preprocessor info slows things down noticeably.

Identifying numeric/string constants vs macros will probably have to be fairly heuristic, especially if we want to capture constants built from macros.

Add support for nullptr_t

This type is unlikely to ever show up in declarations, but it is possible.

Using auto with a static field

static auto AutoNullPtr = nullptr;
VarDecl VarDecl Var - AutoNullPtr Mangled=AutoNullPtr
^---- Variable type: AutoType (CXType_Auto) 'nullptr_t' SizeOf=8
  BuiltinType (CXType_NullPtr) 'nullptr_t' SizeOf=8
  CXXNullPtrLiteralExpr CXXNullPtrLiteralExpr - 

Using nullptr_t explicitly

#include <cstddef>
static std::nullptr_t NullPtr = nullptr;
VarDecl VarDecl Var - NullPtr Mangled=NullPtr
^---- Variable type: ElaboratedType (CXType_Elaborated) 'std::nullptr_t' SizeOf=8
  TypedefType (CXType_Typedef) 'std::nullptr_t' SizeOf=8
    BuiltinType (CXType_NullPtr) 'nullptr_t' SizeOf=8
  Ref NamespaceRef - std
  Ref TypeRef - std::nullptr_t
  CXXNullPtrLiteralExpr CXXNullPtrLiteralExpr - 

Using decltype(nullptr)

static decltype(nullptr) DeclTypeNullPtr = nullptr;
VarDecl VarDecl Var - DeclTypeNullPtr Mangled=DeclTypeNullPtr
^---- Variable type: DecltypeType (CXType_Unexposed) 'decltype(nullptr)' SizeOf=8
  BuiltinType (CXType_NullPtr) 'nullptr_t' SizeOf=8
  CXXNullPtrLiteralExpr CXXNullPtrLiteralExpr - 
  CXXNullPtrLiteralExpr CXXNullPtrLiteralExpr -

Revisit having all declarations being enumerable

(This will probably happen before the prototype refactor is complete, but I'm creating this issue since it doesn't block anything and I don't want to forget.)

Right now all TranslatedDeclaration are IEnumerable<TranslatedDeclaration>. This certainly makes it easier to enumerate children when a declaration has them, but the vast majority of declarations can't even have children. Instead, perhaps we should only implement IEnumerable<TranslatedDeclaration> when the declaration can actually have children and use is in contexts where enumeration is required.

If we do this, the VisitorContext/TransformationContext will need to be updated to reflect this new paradigm. I'm thinking the following:

  • Rename Parent to Siblings
  • Rename ParentDeclaration to Parent

Consider implementing a recursive declaration enumerator that provides context

Right now the EnumerateRecursive extension method flattens the entire declaration hierarchy without providing context. However, some simpler enumerations could benefit from context information without having to jump all the way to implementing a DeclarationVisitor. It should be relatively easy to provide a version of EnumerateRecursive that yields a (VisitorContext, TranslatedDeclaration) tuple instead of just contextless declarations.

If this version was added, it should probably only be provided for TranslatedLibrary rather than any random IEnumerable<TranslatedDeclaration>. (Either that or there should be two versions: One for TranslatedLibrary and one for IEnumerable<TranslatedDeclaration> that takes an initial VisitorContext.)

Revisit exporting non-method static functions

In the original prototype, GenerateModuleDefinitionTransformation had this logic:

// Static non-method functions cannot be exported
if (methodDeclaration is null && functionDeclaration.StorageClass == CX_StorageClass.CX_SC_Static)
{ return null; }

Unfortunately I did not elaborate why and I'm not sure this is actually true. I think maybe I incorrectly made this assumption when I was investigating why module definitions weren't solving all the problems I had with exporting inline functions and this check is no longer valid.

Investigate using CXXMethodDecl::getThisObjectType

It's not immediately clear if this is ever different from the record type that contains the method (or maybe I'm misunderstanding its purpose.) It caught my eye as something that might be able to improve correctness in weird situations we aren't handling yet when it was added to libClangSharp beta2.

Translate Doxygen comments as XML documentation

Clang is has a basic understanding of Doxygen comments and attaches them to the appropriate declarations. We should parse these comments and turn them into XML documentation on the generated output.

Implement/improve translation of constant-sized arrays

Constant-sized arrays are currently not supported for fields. (They were in the prototype, but it was a huge hack.)

Additionally, constant-sized arrays are translated as bare pointers. This discards the array's element count, which isn't super ideal since there's no reasonable way to discover it.

We should synthesize types to represent the various sized constant arrays.

Useful resources:

(Note that the issues around the size of the element struct changing do not affect Biohazrd because our assemblies are already architecture and platform-dependent.)

Making dumping Clang information configurable

In the prototype this was controlled by GlobalConfiguration.DumpClangDetails. During the refactor, it was changed to only emit on debug builds for simplicity. Instead, we should allow configuring whether or not it is emitted.

Clang type classes meta issue

We only handle a handful of the possible Type variants exposed by ClangSharp. Below is a list of all of them, we need to eventually investigate all of the unchecked ones to determine what they are and whether we need to handle them:

  • AdjustedType
    • DecayedType
  • ArrayType
    • ConstantArrayType
      • Parameters
      • Fields
    • DependentSizedArrayType - These are arrays sized by a template parameter
    • IncompleteArrayType - Unsized arrays (IE: int x[])
      • Parameters
      • Can these appear in other places?
    • VariableArrayType
  • AtomicType
  • AttributedType #124
  • BlockPointerType
  • BuiltinType -- BuiltinType is not handled in any one location, and not all types are supported. We do use it to filter, but we have to use Type.Kind to get the actual builtin type. See #46 for details.
  • ComplexType
  • DecltypeType -- decltype(T)
  • DeducedType
    • AutoType -- The magic auto type
    • DeducedTemplateSpecializationType
  • DependentAddressSpaceType
  • DependentSizedExtVectorType
  • DependentVectorType
  • ExtVectorType
  • FunctionType
    • FunctionNoProtoType
    • FunctionProtoType
  • InjectedClassNameType
  • MacroQualifiedType
  • MemberPointerType
  • ObjCObjectPointerType Out of scope: Objective C
  • ObjCObjectType Out of scope: Objective C
    • ObjCInterfaceType Out of scope: Objective C
  • ObjCTypeParamType Out of scope: Objective C
  • PackExpansionType
  • ParenType
  • PipeType
  • PointerType
  • ReferenceType
  • SubstTemplateTypeParmPackType
  • SubstTemplateTypeParmType
  • TagType
    • EnumType
    • RecordType
  • TemplateSpecializationType
  • TemplateTypeParmType
  • TypedefType -- If the Clang decl is attached to a TranslatedDeclaration, we translate as a type reference. Otherwise we ignore the typedef and translate as the canonical type.
  • TypeOfExprType
  • TypeOfType
  • TypeWithKeyword
    • DependentNameType
    • DependentTemplateSpecializationType
    • ElaboratedType - These are namespace-qualified types (like physx::PxU32)
  • UnaryTransformType
  • UnresolvedUsingType
  • VectorType

I suspect many of them probably can't even appear in declaration contexts, but we should check for sure and explicitly error if they appear.

Add support for initializing vtable pointer of types without constructors

For types without constructors, the C++ compiler may initialize the vtable pointer wherever the type is initialized.

This was encountered with PxDefaultAllocator.

Here's a simple example: (Godbolt)

class AbstractBase
{
public:
    virtual void* allocate(int size);
};

class DefaultImpl : public AbstractBase
{
public:
    void* allocate(int size)
    {
        return nullptr;
    }
};

void UseAllocator(AbstractBase* allocator)
{
    allocator->allocate(100);
}

void Test()
{
    DefaultImpl impl;
    UseAllocator(&impl);
}

With GCC x86-64 10.2, Test is generated as follows:

Test():
        push    rbp
        mov     rbp, rsp
        sub     rsp, 16
        mov     eax, OFFSET FLAT:vtable for DefaultImpl+16
        mov     QWORD PTR [rbp-8], rax
        lea     rax, [rbp-8]
        mov     rdi, rax
        call    UseAllocator(AbstractBase*)
        nop
        leave
        ret

The easiest solution here is probably to use C trampolines for object construction (when necessary?)

Revisit aliased base type vtable pointers

Right now a vtable pointer gets synthesized in the child type when a parent holds the vtable pointer. This is probably OK since it allows specifying the child's more-specific vtable layout for the field, but I'm not sure if I'm happy with how it gets synthesized. It might not be a bad idea to revisit this.

Translate non-trivial enum constant values as documentation comments

We use the constant values computed by Clang for enum constants. The only "nice" thing we do is try to use hex if the original C++ declaration used hex.

For more complex enum constants, we should embed the original expression as a documentation comment on the constant. This would be especially nice in the case of composite flag constants.

IE:

enum class Colors
{
    Red = 1,
    Green = 1 << 1,
    Blue = 1 << 2,
    Yellow = Red | Green
    // ...
}

becomes

[Flags]
enum Colors
{
    Red = 1,
    /// <remarks>Original C++ value: <c>1 &lt;&lt; 1</c></remarks>
    Green = 2,
    /// <remarks>Original C++ value: <c>1 &lt;&lt; 2</c></remarks>
    Blue = 4,
    /// <remarks>Original C++ value: <c>Red | Green</c></remarks>
    Yellow = 3
}

We can use logic similar to our hex-declaration-detection to determine whether or not a constant declaration is trivial.

Can constant-sized arrays ever be passed by value?

Right now constant-sized arrays specified as parameters are always passed as a pointer to the first element. Is this accurate? Can they be passed by value when a similar struct would?

IE:

void SomeFunc(int32_t x[1])
{
    // ...
}

void SomeFunc(int32_t x[2]) // on x64
{
    // ...
}

Query Clang for the which vTable entry is the 0th entry

Things like the RTTI pointer are stored in the vTable before the entry where the vTable pointer points. Right now we just assume the vTable pointer points to the first occurrence of a function pointer in the table. This is probably fine, but in the interest of correctness we should figure out where this information is hidden within Clang.

If I remember right, -fdump-vtable-layouts points it out for the Microsoft ABI but not Linux. I think I investigated how it was determining it but it was non-trivial and I decided to make an assumption for now instead.

Note that right now CSharpLibraryGenerator is what is handling this assumption. Ideally this should be encoded in TranslatedVTable instead.

TypeTransformationBase has a hole for unrecognized declarations

Right now TypeTransformationBase will ignore type references in declarations it doesn't recognize. This is not ideal since it might not be immediately obvious that it needs to be aware of special declarations.

Without an architecture change, the easiest thing would be either:

  • Use reflection to throw when unrecognized types have TypeReference fields. (Debug builds only?)
  • Use reflection to implement the transformation (blegh.)

Improve output generation of anonymous unions

The fields of an anonymous union should be inlined into the containing record so they act like they do in C++. (Right now they get emitted as a nested type and field with an automatically generated names.)

Add support for half floats

__fp16 can be used in ARM NEON and I imagine it should be compatible with System.Half.

__fp16 corresponds to CXType_Half. Can/should we support CXType_Float16 (_Float16) too? It's unclear why they're separate in the first place. (They share the same "singleton type" within Clang, it's not immediately clear what that means for us.)

Once classes become withable change relevant types back from record.

Right now we use C#9 records for several types to allow using with to clone+mutate them since with can only be used with records. The LDM has expressed interest in adding with support for for clonable non-record types, but it doesn't sound like it'll happen in the C#9 timeframe.

Since we don't need/want the value-equality semantics of records, we should really just ditch them once C# supports with elsewhere. (Potentially with a source generator used to generate the boilerplate required to support it.

Add support for constants

IE:

const int SomeConst = 100;

One consideration to be made for these types: I believe C++ guarantees that &SomeConst is the same across all translation units. (If not, I bet most compilers do this anyway.) Making this guarantee means we can't let the constant be a C# const since C# does not allow taking the address of a constant. (And even if it did, the address would be different.)

There are essentially three ways to represent C++-style constants in C#:

  • A) Export a pointer to the const and use NativeLibrary.GetExport
    • This is how non-const globals work today.
    • โŒ This isn't ideal because it requires a stub.
    • โŒ This has negative performance implications (neither Roslyn nor the JIT would recognize this as a constant.)
    • โŒ The const-ness of the variable will not be exposed in C# land.
      • It's basically not a const anymore, although we could use an analyzer.
      • This means it could be modified by mistake, which would cause a runtime exception on some platforms.
    • โœ” This satisfies the previously mentioned pointer guarantee.
    • โœ” Supports types that C# doesn't support as const.
  • B) Expose the const as an actual C# constant
    • โŒ Only works with the few types C# allows as a constant
    • โŒ Can't take a pointer to them (for libraries that care.)
    • โœ” Is a compile-time constant
    • โŒ Would be problematic if the value of the constant is platform-dependent
  • C) Expose the const as a static readonly field
    • โœ” Works with all types that we can translate
    • โœ” Is a JIT-time constant
    • โŒ Has negative performance implications
    • โŒ There are some situations where compile-time constants are needed.
    • โŒ You can take the address of a static readonly field, but we can't provide pointer same-ness guarantees.
      • Could restrict this with an analyzer, but realistically this rarely matters. Maybe make it opt-in for libraries that care.

I think the right solution here is C, but will revisit when I go to implement.

Clang built-in types meta issue

This issue tracks the support for individual Clang built-in types. (For type classes, see #38)

The list below was gathered from CXTypeKind using the range CXType_FirstBuiltin..CXType_LastBuiltin. (Clang also considers some OpenCL stuff to be builtins, but they're out of scope for us.)

The documentation on the libclang side of things is pretty barren, BuiltinTypes.def is much more verbose. (Note that not all types defined in BuiltinTypes.def are exposed by libclang. It may be worthwhile to enumerate these too.)

Character types

  • Char_S -- char (with -fsigned-char) always translated as byte since a bare char usually indicates a C-style string and .NET's encoding utilities use byte
  • Char_U -- char (with -fno-signed-char)
  • Char8 -- char8_t UTF-8 character (C++20 feature) should translate to System.Char8 once both are released.
  • Char16 -- char16_t, translated as C# char
  • WChar -- wchar_t (16-bit -- on Windows platforms)
  • WChar -- wchar_t (32-bit -- on Itanium platforms) #45
  • Char32 -- char32_t #45

Unsigned integer types

  • UChar -- unsigned char / uint8_t
  • UShort
  • UInt
  • ULong
  • ULongLong
  • UInt128

Signed integer types

  • SChar -- signed char / int8_t
  • Short
  • Int
  • Long
  • LongLong
  • Int128

Floating point types

  • Float16 -- _Float16
  • Half -- half (OpenCL) / __fp16 (ARM NEON) #44
  • Float
  • Double
  • Float128 -- __float128
  • LongDouble

Other

  • Bool
  • NullPtr -- #43
  • Void
  • Dependent The impression I get from the description of this type is that it won't appear in valid code.
  • Overload Similarly, this description implies this is used internally within Clang and won't appear in valid code.

Out of scope: Fixed point types

In addition to _Accum, Clang also internally supports similar _Fract and _Sat types which aren't even exposed in libclang.
These are apparently for use on processors which support fixed-point types

I am assuming these will definitely be out of scope for Biohazrd. If a library needs these, I assume they will need special library/language-specific transformation.

I assume we could kludge them into same-sized builtins, but without real samples I'm not a fan of doing that.
(Anyone who happens across a library that uses these can use KludgeUnknownClangTypesIntoBuiltinTypesTransformation until they figure out their library-specific translation.)

  • Accum
  • UAccum
  • ShortAccum
  • UShortAccum
  • LongAccum
  • ULongAccum

Out of scope

  • ObjCClass
  • ObjCId
  • ObjCSel
  • All CXType_OCL* types

Come up with a better name for TypeReductionTransformation

This name is based on the old prototype function that served a similar role. However, this transformation is also responsible for replacing basic ClangTypeReferences with Biohazrd-equivalents like CXType_Void -> VoidTypeReference and FunctionProtoType -> FunctionPointerTypeReference

Function pointers could be construed as some sort of reduction, but I think it'd be better for this to be the transformation that handles converting Clang type references to common Biohazrd equivalents instead.

Alternatively, maybe this transformation needs to be broken up anyway. I can see the array stuff not always being desirable.

Add support for calling constructors on abstract types

Calling constructors on abstract types is necessary when extending an abstract type from C#.

Right now they are skipped by the module definition generator since that's how it was in the prototype. Not sure if I did this because I wasn't thinking about extending abstract types from C# or if I was just trying to avoid dealing with them at the time. Either way, we need a strategy for calling inline constructors on abstract types, which will be trickier than with concrete inline constructors.

Add basic editorconfig awareness to CodeWriter

Edit: I was about to close this as out-of-scope, but I think my intent was to support the barebones basic stuff like indent styles and encoding, which should be simple enough to support.

I do not think Biohazrd should attempt to support the .NET extensions to editorconfig. There's just too many things that can be configured, and it'd unnecessarily complicate the emit logic in Biohazrd. Biohazrd emits code that is compliant with typical C# coding standards. (Well, as compliant as it can be considering it's mapping C/C++ code so the naming conventions are usually murdered.)

If someone wants their generated code to match their personal coding standards more closely, I think it's best that it's done as a post-process. I think Roslyn provides support for auto-formatting C# documents like that, but I've never touched it. If someone wants this I'm willing to entertain extensibility points in Biohazrd to allow such a post-process step.

Add support for variable arguments (non-va_list)

No attempt at supporting variable arguments was made in the original prototype. Supporting these will be non-trivial because if I remember right, the runtime doesn't officially support P/Invoke with variable arguments outside of Windows.

Add support for `char32_t` and `wchar_t` on Itanium platforms

char32_t represents UTF-32 codepoints. They aren't supported yet purely out of lack of need and unclear best translation.

How these might translate to C# is somewhat unclear. Older methods such as Char.ConvertFromUtf32 use int for UTF32 codepoints.

In theory System.Text.Rune might be a good choice here, but it doesn't allow surrogates. I'm unsure if there's a legitimate reason for codepoints from the surrogate range to appear in UTF-32. However, we would be allows C++ to make invalid runes since the Rune constructor protects against surrogates.

More research needs to be done to determine if a reasonable ideal default translation can be supported in Biohazrd. Until then it most likely makes more sense for people to provide their own purpose-built translation. (If you make one, please comment on how you did it and how it worked out for you!)

Add bit field support

The libclang Pathogen extensions provide information about bit fields, but we don't really use it beyond marking the fields are unusable.

I think the best approach here is to make an additional TranslatedBitField type to represent them rather than trying to wedge them into TranslatedNormalField. That way the relative edge-case bit field stuff can live separate from the extremely common case of normal fields.

C# does not support bit fields, so we'd need to implement them manually using properties. This should be fine since the only thing this really does is prevent taking a reference to the bit field, which isn't something you can do regardless.

Write an analyzer to protect against accidentally calling Transform or TransformType when TransformRecursively or TransformTypeRecursively was intended

#17 alleviates most cases where this mistake can be made, but neither of these methods should generally be called anyway.

Basically the rules are:

  • Transform must only be called by TransformRecursively or an override of Transform
  • TransformRecursively must only be called by Transform(TranslatedLibrary) or a Transform*Children method

Alternatively we might consider renaming Transform to make it less attractive.

Add support for (inlined) destructors

There isn't a way I'm aware of to convince MSVC or Clang to export an inline destructor without modifying its definition.

Destructors were disabled from module definition generation entirely (even non-inline ones) in the prototype and it's unclear exactly why that is.

Worth noting: Virtual destructors are always available in the output.

Implement extensible metadata

Ideally it should be simple to attach extra information to a declaration in a transformer without needing to introduce a new type. This could be useful for attaching optional, extra information to a declaration that might not be meaningful to all contexts and doesn't necessitate creating a whole new declaration.

For example, this could replace some C#-specific functionality like TranslatedFunction.HideFromIntellisense. It'd also allow these sorts of things to be used with other declarations.

I am thinking there should be two variants of this metadata:

  • Tagged/simple data
  • Self-keyed/complex data

Complex data is represented by a user-defined struct. Only one of each struct can be attached to a declaration. Simple data is keyed on either an empty type or a magic string. (I'm inclined to prefer the former.)

Tentative design:

public record TranslatedDeclaration
{
    // ...
    public TranslatedMetadata Extra { get; init; }
    // ...
}

// Support extending TranslatedLibrary too?
public record TranslatedLibrary
{
    // ...
    public TranslatedMetadata Extra { get; init; }
    // ...
}

// This interface is used for simple data keys and ensures people don't accidentally mix up TValue.
public interface IMetadataKey<TValue> { }

// Like all of the translated object model, this is an immutable type.
public sealed class TranslatedMetadata
{
    // ==========================================
    // Self-keyed/complex overloads
    // ==========================================
    // Use an analyzer to warn if T is IMetadataKey<TValue>
    public T? TryGet<T>()
        where T : class
        => throw null;

    public bool TryGet<T>(out T value)
        => throw null;

    // ==========================================
    // Tagged/simple overloads
    // ==========================================
    public TValue TryGet<TKey, TValue>()
        where TKey : IMetadataKey<TValue>
        where TValue : class
        => throw null;

    public bool TryGet<TKey, TValue>(out TValue value)
        where TKey : IMetadataKey<TValue>
        => throw null;

    // ==========================================
    // Remove
    // ==========================================
    public TranslatedMetadata RemoveKey<TKey>
        => throw null;

    // ==========================================
    // Update
    // ==========================================
    public TranslatedMetadata Update<TKey>(TKey newValue)
        => throw null;

    public TranslatedMetadata Update<TKey, TValue>(TValue newValue)
        where TKey : IMetadataKey<TValue>
        => throw null;
    
    // ... similar methods for Add(value)
}

TranslatedMetadata is essentially a dictionary where the type of the key determines the type of the value.

Use a source generator to generate boilerplate for TransformerBase

This generator should ideally be written so that non-standard declarations can be added easily. Custom declaration and type reference support is handled through special interfaces. So we don't need to worry about supporting them. (Although we could automagically implement these interfaces.)

Add missing C# verification

  • Ensure no ClangSharpTypereference are present anywhere in the entire tree
  • Ensure no VoidTypeReference are present for fields, parameters, or underlying enum types. (Probably easier to check if they're allowed rather than when they're not.)
  • Ensure all TranslatedTypeReference actually resolve #109
  • Ensure TranslatedRecord.Members doesn't have any unexpected declarations.
  • Ensure TranslatedVTableField.Accessibility is <= TranslatedVTable.Accessibility
  • Ensure the relevant entries of a vTable were not moved or removed. (VTables are translated with sequential layout so this breaks the vTable. Adding to the end should be OK though.) (Requires #112)
  • Verify that implicit values of enums are contiguous
    • Right now this is being done at output generation time.
  • Verify all identifiers are legal in C#. (We handle by replacing the illegal characters with obnoxiously long __UNICODE_0123__, so this should only be a warning. See CSharpCodeWriter.IsLegalIdentifier)

Automate calling convention testing

A medium/long-term goal of Biohazrd is to automate verification of the calling convention to ensure that everything is kosher across the entire API surface.

Diagnostics revamp

One of the large parts of Biohazrd that was spared during the big prototype refactor was diagnostics. I changed how/where they get emitted, but they're still very Clang-cerntric and a bit annoying to work with.

  • Diagnostics should be associable with a TranslatedDeclaration when they aren't being attached to the declaration. (IE: during generation.)
  • Diagnostics emitted during generation should always be reflected in the output.
    • Certain diagnostics should be marked as not destroying the output but that they make the output invalid so that ObsoleteAttribute can be applied to generated types. (For instance: The definition of an enum can be translated if the underlying type is unsupported, but the enum shouldn't be usable.)
  • Diagnostics should be emitted in a way that a Roslyn Analyzer can consume them and show them in the IDE. (This might be an alternative to the previous subtask.)
  • Diagnostics should get IDs so they can be filtered.
  • Handle this diagnostic context: #238
  • Diagnostics should be able to be associated with the library as a whole.
  • Replace tests which validate diagnostic messages with testing diagnostic IDs.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.