Better type mapping
This commit is contained in:
@@ -8,7 +8,9 @@ public class Generator
|
||||
private readonly HashSet<NubStructType> _structTypes;
|
||||
private readonly IndentedTextWriter _writer;
|
||||
private readonly Stack<List<DeferNode>> _deferStack = [];
|
||||
private readonly Stack<(string Name, NubFuncType FuncType)> _funcDefs = [];
|
||||
private int _tmpIndex;
|
||||
private int _funcDefIndex;
|
||||
|
||||
public Generator(List<DefinitionNode> definitions, HashSet<NubStructType> structTypes)
|
||||
{
|
||||
@@ -23,47 +25,69 @@ public class Generator
|
||||
return $"_t{++_tmpIndex}";
|
||||
}
|
||||
|
||||
private static string MapType(NubType nubType)
|
||||
private string MapType(NubType nubType)
|
||||
{
|
||||
return nubType switch
|
||||
{
|
||||
NubArrayType => "uintptr_t",
|
||||
NubArrayType arrayType => MapType(arrayType.ElementType),
|
||||
NubConstArrayType arrayType => MapType(arrayType.ElementType),
|
||||
NubBoolType => "bool",
|
||||
NubCStringType => "char*",
|
||||
NubCStringType => "char",
|
||||
NubFloatType floatType => floatType.Width switch
|
||||
{
|
||||
32 => "f32",
|
||||
64 => "f64",
|
||||
_ => throw new ArgumentOutOfRangeException()
|
||||
},
|
||||
NubFuncType => "uintptr_t",
|
||||
NubIntType intType => intType.Signed switch
|
||||
NubFuncType funcType => MapFuncType(funcType),
|
||||
NubIntType intType => (intType.Signed, intType.Width) switch
|
||||
{
|
||||
true => intType.Width switch
|
||||
{
|
||||
8 => "i8",
|
||||
16 => "i16",
|
||||
32 => "i32",
|
||||
64 => "i64",
|
||||
_ => throw new ArgumentOutOfRangeException()
|
||||
},
|
||||
false => intType.Width switch
|
||||
{
|
||||
8 => "u8",
|
||||
16 => "u16",
|
||||
32 => "u32",
|
||||
64 => "u64",
|
||||
_ => throw new ArgumentOutOfRangeException()
|
||||
},
|
||||
(false, 8) => "u8",
|
||||
(false, 16) => "u16",
|
||||
(false, 32) => "u32",
|
||||
(false, 64) => "u64",
|
||||
(true, 8) => "i8",
|
||||
(true, 16) => "i16",
|
||||
(true, 32) => "i32",
|
||||
(true, 64) => "i64",
|
||||
_ => throw new ArgumentOutOfRangeException()
|
||||
},
|
||||
NubPointerType => "uintptr_t",
|
||||
NubStringType => "uintptr_t",
|
||||
NubPointerType pointerType => MapType(pointerType.BaseType),
|
||||
NubStringType => throw new NotImplementedException(),
|
||||
NubStructType structType => StructName(structType.Module, structType.Name),
|
||||
NubVoidType => "void",
|
||||
_ => throw new ArgumentOutOfRangeException(nameof(nubType))
|
||||
};
|
||||
}
|
||||
|
||||
private string MapFuncType(NubFuncType funcType)
|
||||
{
|
||||
var name = $"_func_type_def{++_funcDefIndex}";
|
||||
_funcDefs.Push((name, funcType));
|
||||
return name;
|
||||
}
|
||||
|
||||
private string MapNameWithType(NubType nubType, string name)
|
||||
{
|
||||
var prefix = "";
|
||||
var postfix = "";
|
||||
|
||||
switch (nubType)
|
||||
{
|
||||
case NubCStringType or NubPointerType:
|
||||
prefix = "*";
|
||||
break;
|
||||
case NubArrayType:
|
||||
postfix = "[]";
|
||||
break;
|
||||
case NubConstArrayType constArrayType:
|
||||
postfix = $"[{constArrayType.Size}]";
|
||||
break;
|
||||
}
|
||||
|
||||
return $"{MapType(nubType)} {prefix}{name}{postfix}";
|
||||
}
|
||||
|
||||
private static string FuncName(string module, string name, string? externSymbol)
|
||||
{
|
||||
return externSymbol ?? $"{module}_{name}";
|
||||
@@ -81,46 +105,45 @@ public class Generator
|
||||
|
||||
public string Emit()
|
||||
{
|
||||
_writer.WriteLine("""
|
||||
typedef __builtin_va_list va_list;
|
||||
var header = """
|
||||
typedef __builtin_va_list va_list;
|
||||
|
||||
#define va_start(ap, last) __builtin_va_start(ap, last)
|
||||
#define va_arg(ap, type) __builtin_va_arg(ap, type)
|
||||
#define va_end(ap) __builtin_va_end(ap)
|
||||
#define va_copy(dest, src) __builtin_va_copy(dest, src)
|
||||
#define va_start(ap, last) __builtin_va_start(ap, last)
|
||||
#define va_arg(ap, type) __builtin_va_arg(ap, type)
|
||||
#define va_end(ap) __builtin_va_end(ap)
|
||||
#define va_copy(dest, src) __builtin_va_copy(dest, src)
|
||||
|
||||
#define NULL ((void*)0)
|
||||
#define NULL ((void*)0)
|
||||
|
||||
typedef unsigned long size_t;
|
||||
typedef unsigned long uintptr_t;
|
||||
typedef unsigned long size_t;
|
||||
typedef unsigned long uintptr_t;
|
||||
|
||||
#define offsetof(type, member) __builtin_offsetof(type, member)
|
||||
#define offsetof(type, member) __builtin_offsetof(type, member)
|
||||
|
||||
typedef unsigned char u8;
|
||||
typedef signed char i8;
|
||||
typedef unsigned short u16;
|
||||
typedef signed short i16;
|
||||
typedef unsigned int u32;
|
||||
typedef signed int i32;
|
||||
typedef unsigned long long u64;
|
||||
typedef signed long long i64;
|
||||
typedef unsigned char u8;
|
||||
typedef signed char i8;
|
||||
typedef unsigned short u16;
|
||||
typedef signed short i16;
|
||||
typedef unsigned int u32;
|
||||
typedef signed int i32;
|
||||
typedef unsigned long long u64;
|
||||
typedef signed long long i64;
|
||||
|
||||
typedef float f32;
|
||||
typedef double f64;
|
||||
typedef float f32;
|
||||
typedef double f64;
|
||||
|
||||
#define I8_C(x) x
|
||||
#define U8_C(x) x##U
|
||||
#define I8_C(x) x
|
||||
#define U8_C(x) x##U
|
||||
|
||||
#define I16_C(x) x
|
||||
#define U16_C(x) x##U
|
||||
#define I16_C(x) x
|
||||
#define U16_C(x) x##U
|
||||
|
||||
#define I32_C(x) x
|
||||
#define U32_C(x) x##U
|
||||
#define I32_C(x) x
|
||||
#define U32_C(x) x##U
|
||||
|
||||
#define I64_C(x) x##LL
|
||||
#define U64_C(x) x##ULL
|
||||
""");
|
||||
_writer.WriteLine();
|
||||
#define I64_C(x) x##LL
|
||||
#define U64_C(x) x##ULL
|
||||
""";
|
||||
|
||||
foreach (var structType in _structTypes)
|
||||
{
|
||||
@@ -130,7 +153,7 @@ public class Generator
|
||||
{
|
||||
foreach (var field in structType.Fields)
|
||||
{
|
||||
_writer.WriteLine($"{MapType(field.Type)} {field.Name};");
|
||||
_writer.WriteLine($"{MapNameWithType(field.Type, field.Name)};");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -144,11 +167,11 @@ public class Generator
|
||||
{
|
||||
appendNewLine = true;
|
||||
var parameters = funcNode.Signature.Parameters.Count != 0
|
||||
? string.Join(", ", funcNode.Signature.Parameters.Select(x => $"{MapType(x.Type)} {x.Name}"))
|
||||
? string.Join(", ", funcNode.Signature.Parameters.Select(x => MapNameWithType(x.Type, x.Name)))
|
||||
: "void";
|
||||
|
||||
var name = FuncName(funcNode.Module, funcNode.Name, funcNode.ExternSymbol);
|
||||
_writer.WriteLine($"{MapType(funcNode.Signature.ReturnType)} {name}({parameters});");
|
||||
_writer.WriteLine($"{MapNameWithType(funcNode.Signature.ReturnType, name)}({parameters});");
|
||||
}
|
||||
|
||||
if (appendNewLine)
|
||||
@@ -161,11 +184,11 @@ public class Generator
|
||||
foreach (var structFuncNode in structNode.Functions)
|
||||
{
|
||||
var parameters = structFuncNode.Signature.Parameters.Count != 0
|
||||
? string.Join(", ", structFuncNode.Signature.Parameters.Select(x => $"{MapType(x.Type)} {x.Name}"))
|
||||
? string.Join(", ", structFuncNode.Signature.Parameters.Select(x => MapNameWithType(x.Type, x.Name)))
|
||||
: "void";
|
||||
|
||||
var name = StructFuncName(structNode.Module, structNode.Name, structFuncNode.Name);
|
||||
_writer.WriteLine($"{MapType(structFuncNode.Signature.ReturnType)} {name}({parameters})");
|
||||
_writer.WriteLine($"{MapNameWithType(structFuncNode.Signature.ReturnType, name)}({parameters})");
|
||||
EmitBlock(structFuncNode.Body);
|
||||
_writer.WriteLine();
|
||||
}
|
||||
@@ -176,7 +199,7 @@ public class Generator
|
||||
if (funcNode.Body == null) continue;
|
||||
|
||||
var parameters = funcNode.Signature.Parameters.Count != 0
|
||||
? string.Join(", ", funcNode.Signature.Parameters.Select(x => $"{MapType(x.Type)} {x.Name}"))
|
||||
? string.Join(", ", funcNode.Signature.Parameters.Select(x => MapNameWithType(x.Type, x.Name)))
|
||||
: "void";
|
||||
|
||||
if (funcNode.ExternSymbol == null)
|
||||
@@ -185,12 +208,26 @@ public class Generator
|
||||
}
|
||||
|
||||
var name = FuncName(funcNode.Module, funcNode.Name, funcNode.ExternSymbol);
|
||||
_writer.WriteLine($"{MapType(funcNode.Signature.ReturnType)} {name}({parameters})");
|
||||
_writer.WriteLine($"{MapNameWithType(funcNode.Signature.ReturnType, name)}({parameters})");
|
||||
EmitBlock(funcNode.Body);
|
||||
_writer.WriteLine();
|
||||
}
|
||||
|
||||
return _writer.ToString();
|
||||
List<string> typedefs = [];
|
||||
|
||||
while (_funcDefs.TryPop(out var funcTypeDef))
|
||||
{
|
||||
var returnType = MapType(funcTypeDef.FuncType.ReturnType);
|
||||
var paramList = string.Join(", ", funcTypeDef.FuncType.Parameters.Select((type, i) => MapNameWithType(type, $"arg{i}")));
|
||||
if (funcTypeDef.FuncType.Parameters.Count == 0)
|
||||
{
|
||||
paramList = "void";
|
||||
}
|
||||
|
||||
typedefs.Add($"typedef {returnType} (*{funcTypeDef.Name})({paramList});");
|
||||
}
|
||||
|
||||
return header + "\n\n" + string.Join('\n', typedefs) + "\n\n" + _writer;
|
||||
}
|
||||
|
||||
private void EmitStatement(StatementNode statementNode)
|
||||
@@ -296,7 +333,7 @@ public class Generator
|
||||
if (_deferStack.Peek().Count != 0)
|
||||
{
|
||||
var tmp = NewTmp();
|
||||
_writer.WriteLine($"{MapType(returnNode.Value.Type)} {tmp} = {returnValue};");
|
||||
_writer.WriteLine($"{MapNameWithType(returnNode.Value.Type, tmp)} = {returnValue};");
|
||||
|
||||
var blockDefers = _deferStack.Peek();
|
||||
for (var i = blockDefers.Count - 1; i >= 0; i--)
|
||||
@@ -330,11 +367,11 @@ public class Generator
|
||||
if (variableDeclarationNode.Assignment != null)
|
||||
{
|
||||
var value = EmitExpression(variableDeclarationNode.Assignment);
|
||||
_writer.WriteLine($"{MapType(variableDeclarationNode.Type)} {variableDeclarationNode.Name} = {value};");
|
||||
_writer.WriteLine($"{MapNameWithType(variableDeclarationNode.Type, variableDeclarationNode.Name)} = {value};");
|
||||
}
|
||||
else
|
||||
{
|
||||
_writer.WriteLine($"{MapType(variableDeclarationNode.Type)} {variableDeclarationNode.Name};");
|
||||
_writer.WriteLine($"{MapNameWithType(variableDeclarationNode.Type, variableDeclarationNode.Name)};");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -383,14 +420,12 @@ public class Generator
|
||||
{
|
||||
var array = EmitExpression(arrayIndexAccessNode.Target);
|
||||
var index = EmitExpression(arrayIndexAccessNode.Index);
|
||||
return $"(({MapType(arrayIndexAccessNode.Type)}*){array})[{index}]";
|
||||
return $"{array}[{index}]";
|
||||
}
|
||||
|
||||
private string EmitArrayInitializer(ArrayInitializerNode arrayInitializerNode)
|
||||
{
|
||||
var capacity = EmitExpression(arrayInitializerNode.Capacity);
|
||||
var elementType = MapType(arrayInitializerNode.ElementType);
|
||||
return $"({elementType}[{capacity}]){{0}}";
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
private string EmitBinaryExpression(BinaryExpressionNode binaryExpressionNode)
|
||||
@@ -432,13 +467,32 @@ public class Generator
|
||||
private string EmitConvertFloat(ConvertFloatNode convertFloatNode)
|
||||
{
|
||||
var value = EmitExpression(convertFloatNode.Value);
|
||||
return $"({MapType(convertFloatNode.Type)}){value}";
|
||||
var targetCast = convertFloatNode.TargetType.Width switch
|
||||
{
|
||||
32 => "f32",
|
||||
64 => "f64",
|
||||
_ => throw new ArgumentOutOfRangeException()
|
||||
};
|
||||
|
||||
return $"({targetCast}){value}";
|
||||
}
|
||||
|
||||
private string EmitConvertInt(ConvertIntNode convertIntNode)
|
||||
{
|
||||
var value = EmitExpression(convertIntNode.Value);
|
||||
return $"({MapType(convertIntNode.Type)}){value}";
|
||||
var targetType = (convertIntNode.TargetType.Signed, convertIntNode.TargetType.Width) switch
|
||||
{
|
||||
(false, 8) => "u8",
|
||||
(false, 16) => "u16",
|
||||
(false, 32) => "u32",
|
||||
(false, 64) => "u64",
|
||||
(true, 8) => "i8",
|
||||
(true, 16) => "i16",
|
||||
(true, 32) => "i32",
|
||||
(true, 64) => "i64",
|
||||
_ => throw new ArgumentOutOfRangeException()
|
||||
};
|
||||
return $"({targetType}){value}";
|
||||
}
|
||||
|
||||
private string EmitCStringLiteral(CStringLiteralNode cStringLiteralNode)
|
||||
@@ -449,7 +503,7 @@ public class Generator
|
||||
private string EmitDereference(DereferenceNode dereferenceNode)
|
||||
{
|
||||
var pointer = EmitExpression(dereferenceNode.Target);
|
||||
return $"*({MapType(dereferenceNode.Type)}*){pointer}";
|
||||
return $"*{pointer}";
|
||||
}
|
||||
|
||||
private string EmitFloat32Literal(Float32LiteralNode float32LiteralNode)
|
||||
@@ -477,7 +531,19 @@ public class Generator
|
||||
private string EmitFloatToIntBuiltin(FloatToIntBuiltinNode floatToIntBuiltinNode)
|
||||
{
|
||||
var value = EmitExpression(floatToIntBuiltinNode.Value);
|
||||
return $"({MapType(floatToIntBuiltinNode.Type)}){value}";
|
||||
var targetType = (floatToIntBuiltinNode.TargetType.Signed, floatToIntBuiltinNode.TargetType.Width) switch
|
||||
{
|
||||
(false, 8) => "u8",
|
||||
(false, 16) => "u16",
|
||||
(false, 32) => "u32",
|
||||
(false, 64) => "u64",
|
||||
(true, 8) => "i8",
|
||||
(true, 16) => "i16",
|
||||
(true, 32) => "i32",
|
||||
(true, 64) => "i64",
|
||||
_ => throw new ArgumentOutOfRangeException()
|
||||
};
|
||||
return $"({targetType}){value}";
|
||||
}
|
||||
|
||||
private string EmitFuncCall(FuncCallNode funcCallNode)
|
||||
@@ -508,7 +574,7 @@ public class Generator
|
||||
private string EmitAddressOf(AddressOfNode addressOfNode)
|
||||
{
|
||||
var value = EmitExpression(addressOfNode.LValue);
|
||||
return $"(uintptr_t)&{value}";
|
||||
return $"&{value}";
|
||||
}
|
||||
|
||||
private string EmitLValueIdentifier(LValueIdentifierNode lValueIdentifierNode)
|
||||
@@ -523,6 +589,11 @@ public class Generator
|
||||
|
||||
private string EmitSizeBuiltin(SizeBuiltinNode sizeBuiltinNode)
|
||||
{
|
||||
if (sizeBuiltinNode.TargetType is NubConstArrayType constArrayType)
|
||||
{
|
||||
return $"sizeof({MapType(constArrayType.ElementType)}) * {constArrayType.Size}";
|
||||
}
|
||||
|
||||
return $"sizeof({MapType(sizeBuiltinNode.TargetType)})";
|
||||
}
|
||||
|
||||
@@ -539,9 +610,10 @@ public class Generator
|
||||
|
||||
private string EmitStructFuncCall(StructFuncCallNode structFuncCallNode)
|
||||
{
|
||||
var thisParameter = EmitExpression(structFuncCallNode.StructExpression);
|
||||
var name = StructFuncName(structFuncCallNode.Module, structFuncCallNode.StructName, structFuncCallNode.FuncName);
|
||||
var parameterNames = structFuncCallNode.Parameters.Select(EmitExpression).ToList();
|
||||
return $"{name}({string.Join(", ", parameterNames)})";
|
||||
return $"{name}({thisParameter}, {string.Join(", ", parameterNames)})";
|
||||
}
|
||||
|
||||
private string EmitStructInitializer(StructInitializerNode structInitializerNode)
|
||||
@@ -557,7 +629,7 @@ public class Generator
|
||||
? "0"
|
||||
: string.Join(", ", initValues);
|
||||
|
||||
return $"({MapType(structInitializerNode.Type)}){{{initString}}}";
|
||||
return $"({StructName(structInitializerNode.StructType.Module, structInitializerNode.StructType.Name)}){{{initString}}}";
|
||||
}
|
||||
|
||||
private string EmitUIntLiteral(UIntLiteralNode uIntLiteralNode)
|
||||
|
||||
Reference in New Issue
Block a user