|
|
@@ -14,7 +14,7 @@ namespace Natsu.Compiler
|
|
|
{
|
|
|
static void Main(string[] args)
|
|
|
{
|
|
|
- var fileName = @"..\..\..\..\..\out\bin\netcoreapp3.0\Chino.Kernel.dll";
|
|
|
+ var path = @"..\..\..\..\..\out\bin\netcoreapp3.0\Chino.Kernel.dll";
|
|
|
var resolver = new AssemblyResolver();
|
|
|
var modCtx = new ModuleContext(resolver);
|
|
|
resolver.DefaultModuleContext = modCtx;
|
|
|
@@ -22,16 +22,25 @@ namespace Natsu.Compiler
|
|
|
resolver.FindExactMatch = false;
|
|
|
resolver.UseGAC = false;
|
|
|
resolver.PreSearchPaths.Add(Path.GetFullPath(@"..\..\..\..\..\out\bin\netcoreapp3.0"));
|
|
|
+ resolver.PreSearchPaths.Add(Path.GetFullPath(@"C:\Users\sunny\.nuget\packages\bitfields\0.1.0\lib\netstandard1.0"));
|
|
|
|
|
|
- var module = ModuleDefMD.Load(fileName);
|
|
|
+ var modules = new HashSet<ModuleDef>();
|
|
|
|
|
|
- foreach (var ass in module.GetAssemblyRefs())
|
|
|
+ void AddAssemblies(ModuleDef module)
|
|
|
{
|
|
|
- var r = resolver.ResolveThrow(ass, module);
|
|
|
- var generator = new Generator(r.Modules[0]);
|
|
|
- generator.Generate();
|
|
|
+ modules.Add(module);
|
|
|
+
|
|
|
+ foreach (var ass in module.GetAssemblyRefs())
|
|
|
+ {
|
|
|
+ var r = resolver.ResolveThrow(ass, module);
|
|
|
+ foreach (var m in r.Modules)
|
|
|
+ AddAssemblies(m);
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
+ AddAssemblies(ModuleDefMD.Load(path));
|
|
|
+
|
|
|
+ foreach (var module in modules)
|
|
|
{
|
|
|
var generator = new Generator(module);
|
|
|
generator.Generate();
|
|
|
@@ -59,8 +68,6 @@ namespace Natsu.Compiler
|
|
|
{
|
|
|
var typeDesc = new TypeDesc(type);
|
|
|
_typeDescs.Add(type, typeDesc);
|
|
|
- if (type.NestedTypes.Count != 0)
|
|
|
- throw new NotImplementedException();
|
|
|
|
|
|
if (type.FullName == "System.SZArray`1")
|
|
|
_szArrayType = typeDesc;
|
|
|
@@ -76,13 +83,21 @@ namespace Natsu.Compiler
|
|
|
writer.WriteLine("// Generated by natsu clr compiler.");
|
|
|
writer.WriteLine("#pragma once");
|
|
|
if (_module.Assembly.Name == "System.Private.CorLib")
|
|
|
+ {
|
|
|
writer.WriteLine("#include <natsu.runtime.h>");
|
|
|
+ }
|
|
|
else
|
|
|
- writer.WriteLine("#include <System.Private.CorLib.h>");
|
|
|
+ {
|
|
|
+ foreach (var ass in _module.GetAssemblyRefs())
|
|
|
+ writer.WriteLine($"#include <{ass.Name}.h>");
|
|
|
+ }
|
|
|
+
|
|
|
writer.WriteLine();
|
|
|
|
|
|
writer.WriteLine($"namespace {EscapeModuleName(_module)}");
|
|
|
writer.WriteLine("{");
|
|
|
+ WriteTypeForwards(writer);
|
|
|
+ writer.WriteLine();
|
|
|
WriteTypeForwardDeclares(writer);
|
|
|
writer.WriteLine();
|
|
|
WriteTypeDeclares(writer);
|
|
|
@@ -162,10 +177,7 @@ namespace Natsu.Compiler
|
|
|
if (type.FullName == "System.ValueType")
|
|
|
return null;
|
|
|
var baseType = type.BaseType;
|
|
|
- if (baseType?.DefinitionAssembly.Name != "System.Private.CorLib")
|
|
|
- return baseType?.ResolveTypeDefThrow();
|
|
|
- else
|
|
|
- return baseType;
|
|
|
+ return baseType;
|
|
|
}
|
|
|
|
|
|
private void AddTypeRef(TypeDesc declareDesc, TypeSig fieldType, bool force)
|
|
|
@@ -179,6 +191,7 @@ namespace Natsu.Compiler
|
|
|
case ElementType.Var:
|
|
|
case ElementType.ByRef:
|
|
|
case ElementType.Ptr:
|
|
|
+ case ElementType.CModReqd:
|
|
|
break;
|
|
|
case ElementType.Boolean:
|
|
|
case ElementType.Char:
|
|
|
@@ -220,15 +233,57 @@ namespace Natsu.Compiler
|
|
|
{
|
|
|
if (typeDef != null && (force || typeDef.IsValueType))
|
|
|
{
|
|
|
- var targetDesc = _typeDescs[typeDef];
|
|
|
- if (declareDesc != targetDesc)
|
|
|
+ if (_typeDescs.TryGetValue(typeDef, out var targetDesc))
|
|
|
{
|
|
|
- declareDesc.UsedTypes.Add(targetDesc);
|
|
|
- targetDesc.UsedByTypes.Add(declareDesc);
|
|
|
+ if (declareDesc != targetDesc)
|
|
|
+ {
|
|
|
+ declareDesc.UsedTypes.Add(targetDesc);
|
|
|
+ targetDesc.UsedByTypes.Add(declareDesc);
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ private void WriteTypeForwards(StreamWriter writer)
|
|
|
+ {
|
|
|
+ var types = _module.ExportedTypes.Where(x => x.Attributes == TypeAttributes.Forwarder).ToList();
|
|
|
+ var index = 0;
|
|
|
+ foreach (var type in types)
|
|
|
+ {
|
|
|
+ WriteTypeForward(writer, 0, type);
|
|
|
+ if (index++ != types.Count - 1)
|
|
|
+ writer.WriteLine();
|
|
|
+ }
|
|
|
+
|
|
|
+ if (types.Any())
|
|
|
+ writer.WriteLine();
|
|
|
+ }
|
|
|
+
|
|
|
+ private void WriteTypeForward(StreamWriter writer, int ident, dnlib.DotNet.ExportedType type)
|
|
|
+ {
|
|
|
+ var nss = type.Namespace.Split('.', StringSplitOptions.RemoveEmptyEntries)
|
|
|
+ .Select(EscapeNamespaceName).ToList();
|
|
|
+
|
|
|
+ writer.Ident(ident);
|
|
|
+ foreach (var ns in nss)
|
|
|
+ writer.Write($"namespace {ns} {{ ");
|
|
|
+
|
|
|
+ if (type.ContainsGenericParameter)
|
|
|
+ throw new NotImplementedException();
|
|
|
+
|
|
|
+ //if (type.HasGenericParameters)
|
|
|
+ //{
|
|
|
+ // var typeNames = type.TypeDef.GenericParameters.Select(x => "class " + x.Name.String).ToList();
|
|
|
+ // writer.Ident(ident).Write($"template <{string.Join(", ", typeNames)}> ");
|
|
|
+ //}
|
|
|
+
|
|
|
+ var fowardName = "::" + EscapeModuleName(type.Implementation.Name) + "::" + EscapeTypeName(type.ToTypeRef(), true, false);
|
|
|
+ writer.Ident(ident).Write($"using {type.Name} = {fowardName};");
|
|
|
+
|
|
|
+ foreach (var ns in nss)
|
|
|
+ writer.Write(" }");
|
|
|
+ }
|
|
|
+
|
|
|
#region Forward Declares
|
|
|
private void WriteTypeForwardDeclares(StreamWriter writer)
|
|
|
{
|
|
|
@@ -348,10 +403,10 @@ namespace Natsu.Compiler
|
|
|
writer.WriteLine();
|
|
|
}
|
|
|
|
|
|
- private string EscapeTypeName(ITypeDefOrRef type, bool isBaseType, bool hasModuleName)
|
|
|
+ private string EscapeTypeName(ITypeDefOrRef type, TypeDefOrRefSig sig, bool isBaseType, bool hasModuleName)
|
|
|
{
|
|
|
var sb = new StringBuilder();
|
|
|
- if (!isBaseType && !type.IsValueType)
|
|
|
+ if (!isBaseType && !sig.IsValueType)
|
|
|
sb.Append("::natsu::gc_obj_ref<");
|
|
|
|
|
|
if (hasModuleName)
|
|
|
@@ -376,6 +431,43 @@ namespace Natsu.Compiler
|
|
|
sb.Append(">");
|
|
|
}
|
|
|
|
|
|
+ if (!isBaseType && !sig.IsValueType)
|
|
|
+ sb.Append(">");
|
|
|
+
|
|
|
+ return sb.ToString();
|
|
|
+ }
|
|
|
+
|
|
|
+ private string EscapeTypeName(ITypeDefOrRef type, bool isBaseType, bool hasModuleName)
|
|
|
+ {
|
|
|
+ if (type is TypeSpec typeSpec)
|
|
|
+ {
|
|
|
+ return EscapeTypeName(typeSpec.TypeSig, null, isBaseType);
|
|
|
+ }
|
|
|
+
|
|
|
+ var sb = new StringBuilder();
|
|
|
+ if (!isBaseType && !type.IsValueType)
|
|
|
+ sb.Append("::natsu::gc_obj_ref<");
|
|
|
+
|
|
|
+ if (hasModuleName)
|
|
|
+ sb.Append("::" + EscapeModuleName(type.DefinitionAssembly) + "::");
|
|
|
+ var nss = type.Namespace.Split('.', StringSplitOptions.RemoveEmptyEntries)
|
|
|
+ .Select(EscapeNamespaceName).ToList();
|
|
|
+ foreach (var ns in nss)
|
|
|
+ sb.Append($"{ns}::");
|
|
|
+ sb.Append(EscapeTypeName(type.Name));
|
|
|
+ if (false && type.NumberOfGenericParameters != 0)
|
|
|
+ {
|
|
|
+ sb.Append("<");
|
|
|
+ if (type is TypeDef typeDef)
|
|
|
+ {
|
|
|
+ sb.Append(string.Join(", ", typeDef.GenericParameters.Select(x => x.Name)));
|
|
|
+ }
|
|
|
+ else
|
|
|
+ throw new NotImplementedException();
|
|
|
+
|
|
|
+ sb.Append(">");
|
|
|
+ }
|
|
|
+
|
|
|
if (!isBaseType && !type.IsValueType)
|
|
|
sb.Append(">");
|
|
|
|
|
|
@@ -422,14 +514,14 @@ namespace Natsu.Compiler
|
|
|
writer.WriteLine($"){surfix};");
|
|
|
}
|
|
|
|
|
|
- private string EscapeTypeName(TypeSig fieldType, TypeDef declaringType = null)
|
|
|
+ private string EscapeTypeName(TypeSig fieldType, TypeDef declaringType = null, bool isBaseType = false)
|
|
|
{
|
|
|
var sb = new StringBuilder();
|
|
|
- EscapeTypeName(sb, fieldType, declaringType);
|
|
|
+ EscapeTypeName(sb, fieldType, declaringType, isBaseType);
|
|
|
return sb.ToString();
|
|
|
}
|
|
|
|
|
|
- private void EscapeTypeName(StringBuilder sb, TypeSig cntSig, TypeDef declaringType = null)
|
|
|
+ private void EscapeTypeName(StringBuilder sb, TypeSig cntSig, TypeDef declaringType = null, bool isBaseType = false)
|
|
|
{
|
|
|
switch (cntSig.ElementType)
|
|
|
{
|
|
|
@@ -458,7 +550,7 @@ namespace Natsu.Compiler
|
|
|
if (sig.TypeDef == declaringType)
|
|
|
sb.Append(GetConstantTypeName(cntSig.ElementType));
|
|
|
else
|
|
|
- sb.Append(EscapeTypeName(sig.TypeDefOrRef, isBaseType: false, hasModuleName: true));
|
|
|
+ sb.Append(EscapeTypeName(sig.TypeDefOrRef, sig, isBaseType: isBaseType, hasModuleName: true));
|
|
|
break;
|
|
|
default:
|
|
|
throw new NotSupportedException();
|
|
|
@@ -472,10 +564,10 @@ namespace Natsu.Compiler
|
|
|
switch (cntSig)
|
|
|
{
|
|
|
case TypeDefOrRefSig sig:
|
|
|
- if (sig.IsValueType && sig.TypeDef == declaringType)
|
|
|
+ if (sig.IsValueType && declaringType != null && sig.TypeDef == declaringType)
|
|
|
sb.Append(GetConstantTypeName(cntSig.ElementType));
|
|
|
else
|
|
|
- sb.Append(EscapeTypeName(sig.TypeDefOrRef, isBaseType: false, hasModuleName: true));
|
|
|
+ sb.Append(EscapeTypeName(sig.TypeDefOrRef, sig, isBaseType: isBaseType, hasModuleName: true));
|
|
|
break;
|
|
|
default:
|
|
|
throw new NotSupportedException();
|
|
|
@@ -517,6 +609,9 @@ namespace Natsu.Compiler
|
|
|
case ElementType.Pinned:
|
|
|
EscapeTypeName(sb, cntSig.Next, declaringType);
|
|
|
break;
|
|
|
+ case ElementType.CModReqd:
|
|
|
+ EscapeTypeName(sb, cntSig.Next, declaringType);
|
|
|
+ break;
|
|
|
default:
|
|
|
throw new NotSupportedException();
|
|
|
}
|
|
|
@@ -796,7 +891,7 @@ namespace Natsu.Compiler
|
|
|
{
|
|
|
var target = stack.Pop();
|
|
|
string expr = target.expression + (IsTargetValueType(target.type) ? "." : "->") + EscapeIdentifier(field.Name);
|
|
|
- stack.Push(new ByRefSig(field.FieldSig.Type), expr);
|
|
|
+ stack.Push(new ByRefSig(field.FieldSig.Type), $"::natsu::gc_ref_from_ref({expr})");
|
|
|
}
|
|
|
|
|
|
void ConvertStfld(IField field)
|
|
|
@@ -864,6 +959,11 @@ namespace Natsu.Compiler
|
|
|
stack.Push(local.Type, $"_l{local.Index}");
|
|
|
}
|
|
|
|
|
|
+ void ConvertLdloc_a(Local local)
|
|
|
+ {
|
|
|
+ stack.Push(new ByRefSig(local.Type), $"::natsu::gc_ref_from_ref(_l{local.Index})");
|
|
|
+ }
|
|
|
+
|
|
|
void ConvertStloc_I(int index)
|
|
|
{
|
|
|
ConvertStloc(method.Body.Variables[index]);
|
|
|
@@ -1058,10 +1158,16 @@ namespace Natsu.Compiler
|
|
|
stack.Push(_corLibTypes.UIntPtr, $"static_cast<uintptr_t>({PointerToU(v1)})");
|
|
|
}
|
|
|
|
|
|
+ void ConvertConv_U1()
|
|
|
+ {
|
|
|
+ var v1 = stack.Pop();
|
|
|
+ stack.Push(_corLibTypes.Byte, $"static_cast<uint8_t>({PointerToU(v1)})");
|
|
|
+ }
|
|
|
+
|
|
|
void ConvertConv_U8()
|
|
|
{
|
|
|
var v1 = stack.Pop();
|
|
|
- stack.Push(_corLibTypes.Byte, $"static_cast<uint64_t>({PointerToU(v1)})");
|
|
|
+ stack.Push(_corLibTypes.UInt64, $"static_cast<uint64_t>({PointerToU(v1)})");
|
|
|
}
|
|
|
|
|
|
string PointerToU((TypeSig type, string expression) src)
|
|
|
@@ -1174,6 +1280,20 @@ namespace Natsu.Compiler
|
|
|
stack.Push(v1.type, $"{v1.expression} ^ {v2.expression}");
|
|
|
}
|
|
|
|
|
|
+ void ConvertAnd()
|
|
|
+ {
|
|
|
+ var v2 = stack.Pop();
|
|
|
+ var v1 = stack.Pop();
|
|
|
+ stack.Push(v1.type, $"{v1.expression} & {v2.expression}");
|
|
|
+ }
|
|
|
+
|
|
|
+ void ConvertOr()
|
|
|
+ {
|
|
|
+ var v2 = stack.Pop();
|
|
|
+ var v1 = stack.Pop();
|
|
|
+ stack.Push(v1.type, $"{v1.expression} | {v2.expression}");
|
|
|
+ }
|
|
|
+
|
|
|
void ConvertMul()
|
|
|
{
|
|
|
var v2 = stack.Pop();
|
|
|
@@ -1291,6 +1411,9 @@ namespace Natsu.Compiler
|
|
|
case Code.Ldloc_S:
|
|
|
ConvertLdloc((Local)op.Operand);
|
|
|
break;
|
|
|
+ case Code.Ldloca_S:
|
|
|
+ ConvertLdloc_a((Local)op.Operand);
|
|
|
+ break;
|
|
|
case Code.Stloc_0:
|
|
|
ConvertStloc_I(0);
|
|
|
break;
|
|
|
@@ -1354,6 +1477,9 @@ namespace Natsu.Compiler
|
|
|
case Code.Conv_U:
|
|
|
ConvertConv_U();
|
|
|
break;
|
|
|
+ case Code.Conv_U1:
|
|
|
+ ConvertConv_U1();
|
|
|
+ break;
|
|
|
case Code.Conv_U8:
|
|
|
ConvertConv_U8();
|
|
|
break;
|
|
|
@@ -1411,12 +1537,20 @@ namespace Natsu.Compiler
|
|
|
case Code.Xor:
|
|
|
ConvertXor();
|
|
|
break;
|
|
|
+ case Code.And:
|
|
|
+ ConvertAnd();
|
|
|
+ break;
|
|
|
+ case Code.Or:
|
|
|
+ ConvertOr();
|
|
|
+ break;
|
|
|
case Code.Mul:
|
|
|
ConvertMul();
|
|
|
break;
|
|
|
case Code.Throw:
|
|
|
ConvertThrow();
|
|
|
break;
|
|
|
+ case Code.Volatile:
|
|
|
+ break;
|
|
|
default:
|
|
|
throw new NotSupportedException(op.ToString());
|
|
|
}
|