Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
75 commits
Select commit Hold shift + click to select a range
8177b89
add debuginfo to the readme.
Apr 26, 2025
d1a2b76
make sure types are declared base then derived, so that C can compile…
Apr 27, 2025
38559dd
if we are a reference type we will need <stdlib.h> and <string.h> to …
Apr 27, 2025
d922ea2
dotnet defined method parameters need IsPointer true also when its a…
Apr 27, 2025
5dfca9f
implement allocation of reference types with malloc and memset.
Apr 27, 2025
b7ffdd2
struct declarations must include the base type.
Apr 27, 2025
927eaf0
put pointer next to type.
Apr 27, 2025
4fd343f
implement casting reference types for function calls, where the argum…
Apr 27, 2025
a07e8e5
start implementing virtual methods.
Apr 29, 2025
09e879b
add Dans helloworld project.
Apr 29, 2025
f1fd53d
messy code for initialising virtual method table.
May 4, 2025
204ad50
use pointer casting for calling methods, and for virtual table assign…
May 4, 2025
bce37c4
Add "Create object" methods into the dependency graph and emit expres…
May 4, 2025
bbf1d4a
correct ordering of virtual methods and create methods in the depende…
May 4, 2025
c1a7635
fix bug in GetMethodOverrides
May 4, 2025
37974ea
fix dependency graph so virtual methods will be found even when the b…
May 4, 2025
287f05c
fix whitespace in generate CreateMethods.
May 4, 2025
95a1f3f
remove unused method.
May 4, 2025
ea3cec9
add some different virtual methods.
May 4, 2025
f8bbe3c
add todo.
May 4, 2025
56aa315
better util methods that can accurately compare method signatures.
May 4, 2025
de91cc5
small tidy ups and add comments.
May 4, 2025
058613f
fix resolving the virtual method table entry in the ReferenceTypeCrea…
May 4, 2025
f672619
fix reference type baseclass declaration lookup.
May 4, 2025
fdb7a26
make sure the system_object_ctor skip pops the stack.
May 4, 2025
d9f4dcb
only write the vtable if we are a referencetype for now.
May 4, 2025
b8b41cc
handle dotnet function pointer types.
May 4, 2025
2caa58b
dont emit virtual calls when its a valuetype.
May 4, 2025
3da5755
special handling for generic valuetypes.
May 4, 2025
69e43af
update helloworld program.
May 4, 2025
9d88f66
remove helloworld project.
May 4, 2025
6cf4772
Fixed function pointer test
KallDrexx May 5, 2025
863b014
Added missing sample builds
KallDrexx May 5, 2025
15c2e0a
ignore macos .DS_Store files.
May 5, 2025
96849f8
Merge branch 'prototype-classes-inheritance' of github.com:danwalmsle…
May 5, 2025
95c938d
only pop the stack for methods (not functions) for ignored methods.
May 5, 2025
aeb39a2
initial implementation of interfaces.
May 5, 2025
a5e753c
generate typeinfo for interfaces.
May 5, 2025
ef6f77f
fix the dependency graph to remove the reverse hack for the base clas…
May 5, 2025
7976c9f
implement dynamic cast to interface, and calling interface methods fr…
May 5, 2025
49ce38e
fix the dependency graph to remove the reverse hack for the base clas…
May 5, 2025
d492c54
implement Ldnull instruction.
May 5, 2025
e56f8aa
implement assignment of referencetype localvariable from another refe…
May 5, 2025
afda943
make helloworld more complex.
May 5, 2025
198248a
commit dntc.h for now.
May 5, 2025
35347ef
ensure calling interfaces and virtual methods pass the arguements.
May 5, 2025
9dab88f
add multiple interfaces.
May 5, 2025
a135f4e
fix extraneous pointer cast.
May 5, 2025
1069926
interfaces need to keep a pointer to the implementer to pass to metho…
May 6, 2025
e69baae
Added reference type sample, fixed bug with methods returning referen…
KallDrexx May 6, 2025
f6213a3
Add opt-in flag for reference type support, while support is still sp…
KallDrexx May 6, 2025
e68001d
ensure the base classes are placed in the dependency graph.
May 6, 2025
71d29f9
fix popping expression stack for skipped Object::ctor.
May 6, 2025
1744eb2
fix passing void type in call handler, instead of the actual type.
May 6, 2025
7ec2a0f
ensure the parameters are written in virtual call expressions.
May 6, 2025
aa852d2
fix popping the expression stack for ignored system.object::ctor.
May 6, 2025
cee816e
make the basic class support tests generate ctors and create methods …
May 6, 2025
eb10d15
fix addone macro test converting parameter to pointer type.
May 6, 2025
481cb0e
generated code updated with addOneMacro fixed.
May 6, 2025
9bb3f2f
fix test.
May 6, 2025
55bfeaa
printf value.
May 6, 2025
8627a9b
fix test.
May 6, 2025
81da758
Merge branch 'prototype-classes-inheritance' into prototype-interface…
May 6, 2025
9ee2aed
fix CustomFunction macros #define.
May 6, 2025
9db158b
commit fix for addOneMacro in test file.
May 6, 2025
8aac4be
Merge branch 'prototype-classes-inheritance' into prototype-interface…
May 6, 2025
1672d8c
ensure interfaces appear in the dependency graph even when the interf…
May 6, 2025
b28e480
implement some devirtualization, where possible.
May 6, 2025
bdbbeb3
cast return expressions.
May 6, 2025
30efd57
Merge branch 'main' into prototype-interfaces-dynamic-casting
May 6, 2025
0611ac5
remove devirtualization that can cause bugs.
May 6, 2025
cc22733
auto generate platform utility types and methods.
May 7, 2025
08b1ec4
Merge remote-tracking branch 'origin/main' into prototype-interfaces-…
May 9, 2025
697cdc2
Merge remote-tracking branch 'origin/main' into prototype-interfaces-…
May 17, 2025
0f60cbe
add typeinfofield to the new dntc_referencetype_base. fix casting met…
May 17, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions Dntc.Cli/Transpiler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
using Dntc.Common.Conversion;
using Dntc.Common.Conversion.Mutators;
using Dntc.Common.Definitions;
using Dntc.Common.Definitions.CustomDefinedTypes;
using Dntc.Common.Definitions.Definers;
using Dntc.Common.Definitions.Mutators;
using Dntc.Common.Definitions.ReferenceTypeSupport;
Expand Down Expand Up @@ -75,6 +76,7 @@ public async Task RunAsync()
definitionCatalog.Add(NativeDefinedType.StandardTypes.Values);
definitionCatalog.Add(NativeDefinedMethod.StandardMethods);
definitionCatalog.Add(CustomDefinedMethod.StandardCustomMethods);
definitionCatalog.Add(CustomDefinedType.StandardCustomTypes);
}

foreach (var plugin in plugins)
Expand Down
12 changes: 10 additions & 2 deletions Dntc.Common/Conversion/PlannedFileConverter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,11 @@ private IReadOnlyList<CStatementSet> GetMethodStatements(
}

var statements = new List<CStatementSet>();


if (dotNetDefinedMethod.Definition.HasBody == false)
{
return statements;
}
Instruction methodInstruction = dotNetDefinedMethod.Definition.Body.Instructions.First();

OnBeforeGenerateInstruction(statements, dotNetDefinedMethod, methodInstruction);
Expand All @@ -123,7 +127,11 @@ private IReadOnlyList<CStatementSet> GetMethodStatements(
var local = dotNetDefinedMethod.Locals[x];
var localType = _conversionCatalog.Find(local.Type);
var name = Utils.LocalName(dotNetDefinedMethod.Definition, x);
var variable = new Variable(localType, name, local.Type.IsPointer());
var variable = new Variable(localType, name,
local.Type.IsPointer() || localType.OriginalTypeDefinition is DotNetDefinedType
{
Definition.IsValueType: false
});

if (locals.Add(name))
{
Expand Down
7 changes: 6 additions & 1 deletion Dntc.Common/Conversion/TypeConversionInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,12 @@ private void SetupDotNetType(DotNetDefinedType type)
if (!type.Definition.IsValueType)
{
IsReferenceType = true;
ReferencedHeaders = [new HeaderName("<stdlib.h>"), new HeaderName("<string.h>")];
ReferencedHeaders =
[
new HeaderName("<stdlib.h>"),
new HeaderName("<string.h>"),
new HeaderName("<stddef.h>")
];
}
}

Expand Down
1 change: 1 addition & 0 deletions Dntc.Common/Definitions/CustomDefinedMethod.cs
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ protected CustomDefinedMethod(
[
new FloatMinDefinedMethod(),
new StaticConstructorInitializerDefinedMethod(),
new DynamicCastInterfaceDefinedMethod()
];

protected override IReadOnlyList<IlTypeName> GetReferencedTypesInternal() => [];
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
using Dntc.Common.Conversion;
using Dntc.Common.Definitions.CustomDefinedTypes;
using Dntc.Common.Definitions.ReferenceTypeSupport;
using Dntc.Common.Syntax.Statements;

namespace Dntc.Common.Definitions.CustomDefinedMethods;

public class DynamicCastInterfaceDefinedMethod() : CustomDefinedMethod(MethodId,
ReferenceTypeConstants.ReferenceTypeBaseId,
new IlNamespace("DntC.Platform.Utils"),
new HeaderName("dntc.h"),
null,
new CFunctionName("dynamic_cast_interface"),
[
new Parameter(ReferenceTypeConstants.ReferenceTypeBaseId, "instance", true),
new Parameter(NativeDefinedType.StandardTypes[typeof(uint)].IlName, "interface", false),
], false)
{
public static readonly IlMethodId MethodId = new("[Util: DynamicCastInterface]");

protected override IReadOnlyList<IlTypeName> GetReferencedTypesInternal()
{
return [TypeInfoDefinedType.TypeName];
}

public override CustomCodeStatementSet? GetCustomDeclaration()
{
var baseClass = ReferenceTypeConstants.ReferenceTypeBaseTypeName;


string content = @$"
static {baseClass}* dynamic_cast_interface({baseClass}* instance, uint32_t interface) {{
if (instance && instance->type_info) {{
TypeInfo* type_info = instance->type_info;
for (size_t i = 0; i < type_info->interface_count; ++i) {{
if (type_info->implemented_interfaces[i] == interface) {{
// Calculate the address of the interface implementation using the offset
return ({baseClass}*)((char*)instance + type_info->interface_offsets[i]);
}}
}}
}}
return NULL; // Interface is not implemented
}}
";
return new CustomCodeStatementSet(content);
}

public override CustomCodeStatementSet? GetCustomImplementation(ConversionCatalog catalog)
{
return null;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ public ReferenceTypeAllocationMethod(TypeDefinition typeDefinition)

foreach (var virtualMethod in _typeDefinition.Methods.Where(x => x.IsVirtual))
{
if (virtualMethod.IsReuseSlot)
if (virtualMethod.IsReuseSlot || virtualMethod.IsFinal)
{
InvokedMethods.Add(new InvokedMethod(new IlMethodId(virtualMethod.FullName)));
}
Expand All @@ -52,6 +52,7 @@ public ReferenceTypeAllocationMethod(TypeDefinition typeDefinition)
public override CStatementSet? GetCustomImplementation(ConversionCatalog catalog)
{
var typeInfo = catalog.Find(new IlTypeName(_typeDefinition.FullName));
var typeName = typeInfo.NameInC;
var typeNameExpression = new LiteralValueExpression(typeInfo.NameInC.Value, typeInfo);
var variable = new Variable(typeInfo, "result", true);
var statements = new List<CStatementSet>
Expand All @@ -61,7 +62,55 @@ public ReferenceTypeAllocationMethod(TypeDefinition typeDefinition)
};

var sb = new StringBuilder();
foreach (var virtualMethod in _typeDefinition.Methods.Where(x => x.IsVirtual))

sb.AppendLine($@" {typeName}* result = ({typeName}*) malloc(sizeof({typeName}));
memset(result, 0, sizeof({typeName}));");

var typeInfoName =typeName + "_TypeInfo";
sb.AppendLine($"\t((ReferenceType_Base*)result)->type_info = &{typeInfoName};");

var interfaceMethods = new HashSet<IlMethodId>();

foreach (var iface in _typeDefinition.Interfaces)
{
var ifaceType = catalog.Find(new IlTypeName(iface.InterfaceType.FullName));
sb.AppendLine($"\tresult->{ifaceType.NameInC}.implementer = result;");

foreach (var interfaceMethod in iface.InterfaceType.Resolve().Methods)
{
var implementingMethod = _typeDefinition.Methods.SingleOrDefault(x => interfaceMethod.SignatureCompatibleWith(x));

if (implementingMethod != null)
{
interfaceMethods.Add(new IlMethodId(implementingMethod.FullName));
var interfaceMethodInfo = catalog.Find(new IlMethodId(interfaceMethod.FullName));
var implementingMethodInfo = catalog.Find(new IlMethodId(implementingMethod.FullName));

sb.Append($"\tresult->{ifaceType.NameInC}.{interfaceMethodInfo.NameInC} = ");

sb.Append($"({interfaceMethodInfo.ReturnTypeInfo.NativeNameWithPossiblePointer()} (*)(");

for (var x = 0; x < interfaceMethodInfo.Parameters.Count; x++)
{
if (x > 0) sb.Append(", ");
var param = interfaceMethodInfo.Parameters[x];
var paramType = param.ConversionInfo.NameInC.Value;

if (x == 0)
{
paramType = "void";
}

var pointerSymbol = param.IsReference ? "*" : "";
sb.Append($"{paramType}{pointerSymbol}");
}

sb.AppendLine($")){implementingMethodInfo.NameInC};");
}
}
}

foreach (var virtualMethod in _typeDefinition.Methods.Where(x => x.IsVirtual && !interfaceMethods.Contains(new IlMethodId(x.FullName))))
{
if (virtualMethod.IsReuseSlot)
{
Expand Down
6 changes: 6 additions & 0 deletions Dntc.Common/Definitions/CustomDefinedType.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using Dntc.Common.Conversion;
using Dntc.Common.Definitions.CustomDefinedTypes;
using Dntc.Common.Syntax.Statements;

namespace Dntc.Common.Definitions;
Expand Down Expand Up @@ -32,4 +33,9 @@ protected CustomDefinedType(
}

public abstract CustomCodeStatementSet? GetCustomTypeDeclaration(ConversionCatalog catalog);

public static IReadOnlyList<CustomDefinedType> StandardCustomTypes { get; } =
[
new TypeInfoDefinedType()
];
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
using Dntc.Common.Conversion;
using Dntc.Common.Syntax.Expressions;
using Dntc.Common.Syntax.Statements;
using Mono.Cecil;

namespace Dntc.Common.Definitions.CustomDefinedTypes;

Expand Down
28 changes: 28 additions & 0 deletions Dntc.Common/Definitions/CustomDefinedTypes/TypeInfoDefinedType.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
using Dntc.Common.Conversion;
using Dntc.Common.Definitions.ReferenceTypeSupport.TypeInfo;
using Dntc.Common.Syntax.Statements;

namespace Dntc.Common.Definitions.CustomDefinedTypes;

public class TypeInfoDefinedType() : CustomDefinedType(TypeName,
new HeaderName("dntc.h"),
null,
new CTypeName("TypeInfo"),
[],
[])
{
public static readonly IlTypeName TypeName = TypeInfoConstants.TypeInfoTypeId;

public override CustomCodeStatementSet? GetCustomTypeDeclaration(ConversionCatalog catalog)
{
const string content = @"
typedef struct TypeInfo {
uint32_t* implemented_interfaces; // Array of implemented interfaces
size_t* interface_offsets; // Array of offsets for each interface
size_t interface_count; // Count of implemented interfaces
} TypeInfo;
";

return new CustomCodeStatementSet(content);
}
}
22 changes: 22 additions & 0 deletions Dntc.Common/Definitions/DefinitionCatalog.cs
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,28 @@ public IEnumerable<DefinedMethod> GetMethodOverrides(DefinedMethod method)
}
}
}

public IEnumerable<DefinedMethod> GetInterfaceMethods(DefinedMethod method)
{
if (method is DotNetDefinedMethod { Definition.IsVirtual: true } dntMethod)
{
var baseType = dntMethod.Definition.DeclaringType;

foreach (var type in _types.Values.OfType<DotNetDefinedType>().Where(x=>x.Definition.IsInterface))
{
if (baseType.ImplementsInterface(type.Definition))
{
foreach (var derivedMethod in type.Methods.Select(Get).OfType<DotNetDefinedMethod>())
{
if (derivedMethod.Definition.IsOverrideOf(dntMethod.Definition))
{
yield return _methods[derivedMethod.Id];
}
}
}
}
}
}

private void Add(TypeDefinition type)
{
Expand Down
54 changes: 29 additions & 25 deletions Dntc.Common/Definitions/DotNetDefinedMethod.cs
Original file line number Diff line number Diff line change
Expand Up @@ -191,39 +191,43 @@ private void Analyze()
}

var referencedHeaders = new HashSet<HeaderName>();
foreach (var instruction in Definition.Body.Instructions)

if (Definition.HasBody)
{
if (!KnownOpCodeHandlers.OpCodeHandlers.TryGetValue(instruction.OpCode.Code, out var handler))
foreach (var instruction in Definition.Body.Instructions)
{
var debugInfo = CecilUtils.LoggedSequencePointInfo(
CecilUtils.GetSequencePoint(
Definition,
instruction));
if (!KnownOpCodeHandlers.OpCodeHandlers.TryGetValue(instruction.OpCode.Code, out var handler))
{
var debugInfo = CecilUtils.LoggedSequencePointInfo(
CecilUtils.GetSequencePoint(
Definition,
instruction));

var message = $"No handler for op code '{instruction.OpCode.Code}' {debugInfo}";
throw new InvalidOperationException(message);
}
var message = $"No handler for op code '{instruction.OpCode.Code}' {debugInfo}";
throw new InvalidOperationException(message);
}

var results = handler.Analyze(new AnalyzeContext(instruction, this));
var results = handler.Analyze(new AnalyzeContext(instruction, this));

foreach (var method in results.CalledMethods)
{
_invokedMethods.Add(method);
}
foreach (var method in results.CalledMethods)
{
_invokedMethods.Add(method);
}

foreach (var referencedType in results.ReferencedTypes)
{
_referencedTypes.Add(referencedType);
}
foreach (var referencedType in results.ReferencedTypes)
{
_referencedTypes.Add(referencedType);
}

foreach (var header in results.ReferencedHeaders)
{
referencedHeaders.Add(header);
}
foreach (var header in results.ReferencedHeaders)
{
referencedHeaders.Add(header);
}

if (results.ReferencedGlobal != null)
{
_referencedGlobals.Add(new IlFieldId(results.ReferencedGlobal.FullName));
if (results.ReferencedGlobal != null)
{
_referencedGlobals.Add(new IlFieldId(results.ReferencedGlobal.FullName));
}
}
}

Expand Down
10 changes: 8 additions & 2 deletions Dntc.Common/Definitions/DotNetDefinedType.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using Dntc.Common.Definitions.ReferenceTypeSupport;
using Dntc.Common.Definitions.CustomDefinedTypes;
using Mono.Cecil;

namespace Dntc.Common.Definitions;
Expand Down Expand Up @@ -28,6 +29,8 @@ public DotNetDefinedType(TypeDefinition definition)
.Where(x => !x.IsStatic)
.Select(ConvertToField)
.ToArray();

var referencedTypes = new List<IlTypeName>();

if (!definition.IsValueType)
{
Expand All @@ -38,8 +41,7 @@ public DotNetDefinedType(TypeDefinition definition)
definition.BaseType.FullName != typeof(Enum).FullName)
{
var baseTypeName = new IlTypeName(definition.BaseType.FullName);

OtherReferencedTypes = [baseTypeName];
referencedTypes.Add(baseTypeName);
}
else
{
Expand All @@ -55,6 +57,10 @@ public DotNetDefinedType(TypeDefinition definition)
}
}

referencedTypes.AddRange(definition.Interfaces.Select(x => new IlTypeName(x.InterfaceType.FullName)));

OtherReferencedTypes = referencedTypes.ToArray();

Methods = definition.Methods
.Select(x => new IlMethodId(x.FullName))
.ToArray();
Expand Down
Loading
Loading