init llvm

This commit is contained in:
nub31
2025-10-21 18:03:27 +02:00
parent c3d774fd78
commit 3dab4c7e60
5 changed files with 955 additions and 535 deletions

View File

@@ -45,116 +45,126 @@ if (diagnostics.Any(diagnostic => diagnostic.Severity == DiagnosticSeverity.Erro
return 1;
}
var cPaths = new List<string>();
Directory.CreateDirectory(".build");
for (var i = 0; i < nubFiles.Length; i++)
{
var file = nubFiles[i];
var compilationUnit = compilationUnits[i];
var generator = new Generator(compilationUnit);
var directory = Path.GetDirectoryName(file);
if (!string.IsNullOrWhiteSpace(directory))
{
Directory.CreateDirectory(Path.Combine(".build", directory));
}
var path = Path.Combine(".build", Path.ChangeExtension(file, "c"));
File.WriteAllText(path, generator.Emit());
cPaths.Add(path);
Console.WriteLine(generator.Generate());
}
var objectPaths = new List<string>();
return 0;
foreach (var cPath in cPaths)
{
var objectPath = Path.ChangeExtension(cPath, "o");
using var compileProcess = Process.Start("gcc", [
"-ffreestanding", "-nostartfiles", "-std=c23",
"-g", "-lm",
"-c", "-o", objectPath,
cPath,
]);
compileProcess.WaitForExit();
if (compileProcess.ExitCode != 0)
{
Console.Error.WriteLine($"gcc failed with exit code {compileProcess.ExitCode}");
return 1;
}
objectPaths.Add(objectPath);
}
if (modules.TryGetValue("main", out var mainModule))
{
var mainFunction = mainModule
.Functions(true)
.FirstOrDefault(x => x.Prototype.ExternSymbol == "main");
if (mainFunction is { Prototype.ExternSymbol: not null })
{
var runtime = $"""
.intel_syntax noprefix
.text
.globl _start
_start:
mov rdi, [rsp] # argc
mov rsi, [rsp + 8] # argv
call {mainFunction.Prototype.ExternSymbol}
mov rdi, rax # Move return value into rdi
mov rax, 60 # syscall: exit
syscall
""";
var runtimePath = Path.Combine(".build", "runtime.s");
File.WriteAllText(runtimePath, runtime);
using var assembleProcess = Process.Start(new ProcessStartInfo("as", ["-g", "-c", runtimePath, "-o", Path.Combine(".build", "runtime.o")]));
if (assembleProcess == null) return 1;
assembleProcess.WaitForExit();
if (assembleProcess.ExitCode != 0)
{
Console.Error.WriteLine($"gcc failed with exit code {assembleProcess.ExitCode}");
return 1;
}
if (assembleProcess.ExitCode != 0) return 1;
using var linkProcess = Process.Start(new ProcessStartInfo("gcc", [
"-ffreestanding", "-nostartfiles", "-std=c23",
"-g", "-lm",
"-o", Path.Combine(".build", "out"),
..objectPaths,
Path.Combine(".build", "runtime.o"),
..objectFileArgs
]));
if (linkProcess == null) return 1;
linkProcess.WaitForExit();
if (linkProcess.ExitCode != 0)
{
Console.Error.WriteLine($"gcc failed with exit code {linkProcess.ExitCode}");
return 1;
}
Console.WriteLine("Build successful: .build/out");
}
else
{
Console.WriteLine("No main function found in module main, skipping link step");
}
}
else
{
Console.WriteLine("No main function found in module main, skipping link step");
}
return 0;
// var cPaths = new List<string>();
//
// Directory.CreateDirectory(".build");
//
// for (var i = 0; i < nubFiles.Length; i++)
// {
// var file = nubFiles[i];
// var compilationUnit = compilationUnits[i];
//
// var generator = new Generator(compilationUnit);
// var directory = Path.GetDirectoryName(file);
// if (!string.IsNullOrWhiteSpace(directory))
// {
// Directory.CreateDirectory(Path.Combine(".build", directory));
// }
//
// var path = Path.Combine(".build", Path.ChangeExtension(file, "c"));
// File.WriteAllText(path, generator.Emit());
// cPaths.Add(path);
// }
//
// var objectPaths = new List<string>();
//
// foreach (var cPath in cPaths)
// {
// var objectPath = Path.ChangeExtension(cPath, "o");
// using var compileProcess = Process.Start("gcc", [
// "-ffreestanding", "-nostartfiles", "-std=c23",
// "-g", "-lm",
// "-c", "-o", objectPath,
// cPath,
// ]);
//
// compileProcess.WaitForExit();
//
// if (compileProcess.ExitCode != 0)
// {
// Console.Error.WriteLine($"gcc failed with exit code {compileProcess.ExitCode}");
// return 1;
// }
//
// objectPaths.Add(objectPath);
// }
//
// if (modules.TryGetValue("main", out var mainModule))
// {
// var mainFunction = mainModule
// .Functions(true)
// .FirstOrDefault(x => x.Prototype.ExternSymbol == "main");
//
// if (mainFunction is { Prototype.ExternSymbol: not null })
// {
// var runtime = $"""
// .intel_syntax noprefix
//
// .text
// .globl _start
// _start:
// mov rdi, [rsp] # argc
// mov rsi, [rsp + 8] # argv
// call {mainFunction.Prototype.ExternSymbol}
// mov rdi, rax # Move return value into rdi
// mov rax, 60 # syscall: exit
// syscall
//
// """;
//
// var runtimePath = Path.Combine(".build", "runtime.s");
// File.WriteAllText(runtimePath, runtime);
//
// using var assembleProcess = Process.Start(new ProcessStartInfo("as", ["-g", "-c", runtimePath, "-o", Path.Combine(".build", "runtime.o")]));
// if (assembleProcess == null) return 1;
// assembleProcess.WaitForExit();
//
// if (assembleProcess.ExitCode != 0)
// {
// Console.Error.WriteLine($"gcc failed with exit code {assembleProcess.ExitCode}");
// return 1;
// }
//
// if (assembleProcess.ExitCode != 0) return 1;
//
// using var linkProcess = Process.Start(new ProcessStartInfo("gcc", [
// "-ffreestanding", "-nostartfiles", "-std=c23",
// "-g", "-lm",
// "-o", Path.Combine(".build", "out"),
// ..objectPaths,
// Path.Combine(".build", "runtime.o"),
// ..objectFileArgs
// ]));
//
// if (linkProcess == null) return 1;
// linkProcess.WaitForExit();
//
// if (linkProcess.ExitCode != 0)
// {
// Console.Error.WriteLine($"gcc failed with exit code {linkProcess.ExitCode}");
// return 1;
// }
//
// Console.WriteLine("Build successful: .build/out");
// }
// else
// {
// Console.WriteLine("No main function found in module main, skipping link step");
// }
// }
// else
// {
// Console.WriteLine("No main function found in module main, skipping link step");
// }
//
// return 0;

View File

@@ -1,6 +1,6 @@
using NubLang.Ast;
namespace NubLang.Generation;
namespace NubLang.Generation.C;
public static class CType
{

View File

@@ -0,0 +1,581 @@
using NubLang.Ast;
using NubLang.Syntax;
namespace NubLang.Generation.C;
public class Generator
{
private readonly CompilationUnit _compilationUnit;
private readonly IndentedTextWriter _writer;
private readonly Stack<List<DeferNode>> _deferStack = [];
private int _tmpIndex;
public Generator(CompilationUnit compilationUnit)
{
_compilationUnit = compilationUnit;
_writer = new IndentedTextWriter();
}
// todo(nub31): Handle name collisions
private string NewTmp()
{
return $"_t{++_tmpIndex}";
}
private static string FuncName(string module, string name, string? externSymbol)
{
return externSymbol ?? $"{module}_{name}";
}
private static string StructName(string module, string name)
{
return $"{module}_{name}";
}
public string Emit()
{
_writer.WriteLine("#include <stdint.h>");
_writer.WriteLine("#include <stdarg.h>");
_writer.WriteLine("#include <stddef.h>");
_writer.WriteLine();
foreach (var structType in _compilationUnit.ImportedStructTypes)
{
_writer.WriteLine("typedef struct");
_writer.WriteLine("{");
using (_writer.Indent())
{
foreach (var field in structType.Fields)
{
_writer.WriteLine($"{CType.Create(field.Type, field.Name)};");
}
}
_writer.WriteLine($"}} {StructName(structType.Module, structType.Name)};");
_writer.WriteLine();
}
// note(nub31): Forward declarations
foreach (var prototype in _compilationUnit.ImportedFunctions)
{
EmitLine(prototype.Tokens.FirstOrDefault());
var parameters = prototype.Parameters.Count != 0
? string.Join(", ", prototype.Parameters.Select(x => CType.Create(x.Type, x.Name)))
: "void";
var name = FuncName(prototype.Module, prototype.Name, prototype.ExternSymbol);
_writer.WriteLine($"{CType.Create(prototype.ReturnType, name)}({parameters});");
_writer.WriteLine();
}
// note(nub31): declare extern functions
foreach (var funcNode in _compilationUnit.Functions)
{
if (funcNode.Body != null) continue;
EmitLine(funcNode.Tokens.FirstOrDefault());
var parameters = funcNode.Prototype.Parameters.Count != 0
? string.Join(", ", funcNode.Prototype.Parameters.Select(x => CType.Create(x.Type, x.Name)))
: "void";
var name = FuncName(funcNode.Module, funcNode.Name, funcNode.Prototype.ExternSymbol);
_writer.WriteLine($"{CType.Create(funcNode.Prototype.ReturnType, name)}({parameters});");
}
_writer.WriteLine();
// note(nub31): Normal functions
foreach (var funcNode in _compilationUnit.Functions)
{
if (funcNode.Body == null) continue;
EmitLine(funcNode.Tokens.FirstOrDefault());
var parameters = funcNode.Prototype.Parameters.Count != 0
? string.Join(", ", funcNode.Prototype.Parameters.Select(x => CType.Create(x.Type, x.Name)))
: "void";
if (funcNode.Prototype.ExternSymbol == null)
{
_writer.Write("static ");
}
var name = FuncName(funcNode.Module, funcNode.Name, funcNode.Prototype.ExternSymbol);
_writer.WriteLine($"{CType.Create(funcNode.Prototype.ReturnType, name)}({parameters})");
EmitBlock(funcNode.Body);
_writer.WriteLine();
}
return _writer.ToString();
}
private void EmitStatement(StatementNode statementNode)
{
EmitLine(statementNode.Tokens.FirstOrDefault());
switch (statementNode)
{
case AssignmentNode assignmentNode:
EmitAssignment(assignmentNode);
break;
case BlockNode blockNode:
EmitBlock(blockNode);
break;
case BreakNode breakNode:
EmitBreak(breakNode);
break;
case ContinueNode continueNode:
EmitContinue(continueNode);
break;
case DeferNode deferNode:
EmitDefer(deferNode);
break;
case IfNode ifNode:
EmitIf(ifNode);
break;
case ReturnNode returnNode:
EmitReturn(returnNode);
break;
case StatementFuncCallNode statementFuncCallNode:
EmitStatementFuncCall(statementFuncCallNode);
break;
case VariableDeclarationNode variableDeclarationNode:
EmitVariableDeclaration(variableDeclarationNode);
break;
case WhileNode whileNode:
EmitWhile(whileNode);
break;
default:
throw new ArgumentOutOfRangeException(nameof(statementNode));
}
}
private void EmitLine(Token? token)
{
if (token == null) return;
var file = token.Span.FilePath;
var line = token.Span.Start.Line;
_writer.WriteLine($"#line {line} \"{file}\"");
}
private void EmitAssignment(AssignmentNode assignmentNode)
{
var target = EmitExpression(assignmentNode.Target);
var value = EmitExpression(assignmentNode.Value);
_writer.WriteLine($"{target} = {value};");
}
private void EmitBreak(BreakNode _)
{
_writer.WriteLine("break;");
}
private void EmitContinue(ContinueNode _)
{
_writer.WriteLine("continue;");
}
private void EmitDefer(DeferNode deferNode)
{
_deferStack.Peek().Add(deferNode);
}
private void EmitIf(IfNode ifNode, bool elseIf = false)
{
var condition = EmitExpression(ifNode.Condition);
_writer.WriteLine($"{(elseIf ? "else " : "")}if ({condition})");
EmitBlock(ifNode.Body);
ifNode.Else?.Match
(
elseIfNode => EmitIf(elseIfNode, true),
elseNode =>
{
_writer.WriteLine("else");
EmitBlock(elseNode);
}
);
}
private void EmitReturn(ReturnNode returnNode)
{
if (returnNode.Value == null)
{
var blockDefers = _deferStack.Peek();
for (var i = blockDefers.Count - 1; i >= 0; i--)
{
EmitStatement(blockDefers[i].Statement);
}
_writer.WriteLine("return;");
}
else
{
var returnValue = EmitExpression(returnNode.Value);
if (_deferStack.Peek().Count != 0)
{
var tmp = NewTmp();
_writer.WriteLine($"{CType.Create(returnNode.Value.Type, tmp)} = {returnValue};");
var blockDefers = _deferStack.Peek();
for (var i = blockDefers.Count - 1; i >= 0; i--)
{
EmitStatement(blockDefers[i].Statement);
}
EmitLine(returnNode.Tokens.FirstOrDefault());
_writer.WriteLine($"return {tmp};");
}
else
{
EmitLine(returnNode.Tokens.FirstOrDefault());
_writer.WriteLine($"return {returnValue};");
}
}
}
private void EmitStatementFuncCall(StatementFuncCallNode statementFuncCallNode)
{
var funcCall = EmitFuncCall(statementFuncCallNode.FuncCall);
_writer.WriteLine($"{funcCall};");
}
private void EmitVariableDeclaration(VariableDeclarationNode variableDeclarationNode)
{
if (variableDeclarationNode.Assignment != null)
{
var value = EmitExpression(variableDeclarationNode.Assignment);
_writer.WriteLine($"{CType.Create(variableDeclarationNode.Type, variableDeclarationNode.Name)} = {value};");
}
else
{
_writer.WriteLine($"{CType.Create(variableDeclarationNode.Type, variableDeclarationNode.Name)};");
}
}
private void EmitWhile(WhileNode whileNode)
{
var condition = EmitExpression(whileNode.Condition);
_writer.WriteLine($"while ({condition})");
EmitBlock(whileNode.Body);
}
private string EmitExpression(ExpressionNode expressionNode)
{
var expr = expressionNode switch
{
ArrayIndexAccessNode arrayIndexAccessNode => EmitArrayIndexAccess(arrayIndexAccessNode),
ArrayInitializerNode arrayInitializerNode => EmitArrayInitializer(arrayInitializerNode),
BinaryExpressionNode binaryExpressionNode => EmitBinaryExpression(binaryExpressionNode),
BoolLiteralNode boolLiteralNode => EmitBoolLiteral(boolLiteralNode),
ConstArrayIndexAccessNode constArrayIndexAccessNode => EmitConstArrayIndexAccess(constArrayIndexAccessNode),
ConstArrayInitializerNode constArrayInitializerNode => EmitConstArrayInitializer(constArrayInitializerNode),
// ConvertConstArrayToArrayNode convertConstArrayToArrayNode => EmitConvertConstArrayToArray(convertConstArrayToArrayNode),
ConvertFloatNode convertFloatNode => EmitConvertFloat(convertFloatNode),
ConvertIntNode convertIntNode => EmitConvertInt(convertIntNode),
CStringLiteralNode cStringLiteralNode => EmitCStringLiteral(cStringLiteralNode),
DereferenceNode dereferenceNode => EmitDereference(dereferenceNode),
Float32LiteralNode float32LiteralNode => EmitFloat32Literal(float32LiteralNode),
Float64LiteralNode float64LiteralNode => EmitFloat64Literal(float64LiteralNode),
FloatToIntBuiltinNode floatToIntBuiltinNode => EmitFloatToIntBuiltin(floatToIntBuiltinNode),
FuncCallNode funcCallNode => EmitFuncCall(funcCallNode),
FuncIdentifierNode funcIdentifierNode => EmitFuncIdentifier(funcIdentifierNode),
IntLiteralNode intLiteralNode => EmitIntLiteral(intLiteralNode),
AddressOfNode addressOfNode => EmitAddressOf(addressOfNode),
LValueIdentifierNode lValueIdentifierNode => EmitLValueIdentifier(lValueIdentifierNode),
RValueIdentifierNode rValueIdentifierNode => EmitRValueIdentifier(rValueIdentifierNode),
SizeBuiltinNode sizeBuiltinNode => EmitSizeBuiltin(sizeBuiltinNode),
SliceIndexAccessNode sliceIndexAccessNode => EmitSliceArrayIndexAccess(sliceIndexAccessNode),
StringLiteralNode stringLiteralNode => EmitStringLiteral(stringLiteralNode),
StructFieldAccessNode structFieldAccessNode => EmitStructFieldAccess(structFieldAccessNode),
StructInitializerNode structInitializerNode => EmitStructInitializer(structInitializerNode),
UIntLiteralNode uIntLiteralNode => EmitUIntLiteral(uIntLiteralNode),
UnaryExpressionNode unaryExpressionNode => EmitUnaryExpression(unaryExpressionNode),
_ => throw new ArgumentOutOfRangeException(nameof(expressionNode))
};
if (expressionNode is ConstArrayInitializerNode)
{
return expr;
}
return $"({expr})";
}
private string EmitArrayIndexAccess(ArrayIndexAccessNode arrayIndexAccessNode)
{
var array = EmitExpression(arrayIndexAccessNode.Target);
var index = EmitExpression(arrayIndexAccessNode.Index);
return $"{array}[{index}]";
}
private string EmitArrayInitializer(ArrayInitializerNode arrayInitializerNode)
{
var type = (NubArrayType)arrayInitializerNode.Type;
var capacity = EmitExpression(arrayInitializerNode.Capacity);
var tmp = NewTmp();
_writer.WriteLine($"{CType.Create(type.ElementType)} {tmp}[{capacity}];");
return tmp;
}
private string EmitBinaryExpression(BinaryExpressionNode binaryExpressionNode)
{
var left = EmitExpression(binaryExpressionNode.Left);
var right = EmitExpression(binaryExpressionNode.Right);
var op = binaryExpressionNode.Operator switch
{
BinaryOperator.Plus => "+",
BinaryOperator.Minus => "-",
BinaryOperator.Multiply => "*",
BinaryOperator.Divide => "/",
BinaryOperator.Modulo => "%",
BinaryOperator.Equal => "==",
BinaryOperator.NotEqual => "!=",
BinaryOperator.LessThan => "<",
BinaryOperator.LessThanOrEqual => "<=",
BinaryOperator.GreaterThan => ">",
BinaryOperator.GreaterThanOrEqual => ">=",
BinaryOperator.LogicalAnd => "&&",
BinaryOperator.LogicalOr => "||",
BinaryOperator.BitwiseAnd => "&",
BinaryOperator.BitwiseOr => "|",
BinaryOperator.BitwiseXor => "^",
BinaryOperator.LeftShift => "<<",
BinaryOperator.RightShift => ">>",
_ => throw new ArgumentOutOfRangeException()
};
return $"{left} {op} {right}";
}
private string EmitBoolLiteral(BoolLiteralNode boolLiteralNode)
{
return boolLiteralNode.Value ? "true" : "false";
}
private string EmitConstArrayIndexAccess(ConstArrayIndexAccessNode constArrayIndexAccessNode)
{
var array = EmitExpression(constArrayIndexAccessNode.Target);
var index = EmitExpression(constArrayIndexAccessNode.Index);
// todo(nub31): We can emit bounds checking here
return $"{array}[{index}]";
}
private string EmitConstArrayInitializer(ConstArrayInitializerNode constArrayInitializerNode)
{
return "{0}";
}
// private string EmitConvertConstArrayToArray(ConvertConstArrayToArrayNode convertConstArrayToArrayNode)
// {
// var value = EmitExpression(convertConstArrayToArrayNode.Value);
// return $"({CType.Create(convertConstArrayToArrayNode.Type)}){value}";
// }
private string EmitConvertFloat(ConvertFloatNode convertFloatNode)
{
var value = EmitExpression(convertFloatNode.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);
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)
{
return $"\"{cStringLiteralNode.Value}\"";
}
private string EmitDereference(DereferenceNode dereferenceNode)
{
var pointer = EmitExpression(dereferenceNode.Target);
return $"*{pointer}";
}
private string EmitFloat32Literal(Float32LiteralNode float32LiteralNode)
{
var str = float32LiteralNode.Value.ToString("G9", System.Globalization.CultureInfo.InvariantCulture);
if (!str.Contains('.') && !str.Contains('e') && !str.Contains('E'))
{
str += ".0";
}
return str + "f";
}
private string EmitFloat64Literal(Float64LiteralNode float64LiteralNode)
{
var str = float64LiteralNode.Value.ToString("G17", System.Globalization.CultureInfo.InvariantCulture);
if (!str.Contains('.') && !str.Contains('e') && !str.Contains('E'))
{
str += ".0";
}
return str;
}
private string EmitFloatToIntBuiltin(FloatToIntBuiltinNode floatToIntBuiltinNode)
{
var value = EmitExpression(floatToIntBuiltinNode.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)
{
var name = EmitExpression(funcCallNode.Expression);
var parameterNames = funcCallNode.Parameters.Select(x => EmitExpression(x)).ToList();
return $"{name}({string.Join(", ", parameterNames)})";
}
private string EmitFuncIdentifier(FuncIdentifierNode funcIdentifierNode)
{
return FuncName(funcIdentifierNode.Module, funcIdentifierNode.Name, funcIdentifierNode.ExternSymbol);
}
private string EmitIntLiteral(IntLiteralNode intLiteralNode)
{
var type = (NubIntType)intLiteralNode.Type;
return type.Width switch
{
8 or 16 or 32 => intLiteralNode.Value.ToString(),
64 => intLiteralNode.Value + "LL",
_ => throw new ArgumentOutOfRangeException()
};
}
private string EmitAddressOf(AddressOfNode addressOfNode)
{
var value = EmitExpression(addressOfNode.LValue);
return $"&{value}";
}
private string EmitLValueIdentifier(LValueIdentifierNode lValueIdentifierNode)
{
return lValueIdentifierNode.Name;
}
private string EmitRValueIdentifier(RValueIdentifierNode rValueIdentifierNode)
{
return rValueIdentifierNode.Name;
}
private string EmitSizeBuiltin(SizeBuiltinNode sizeBuiltinNode)
{
return $"sizeof({CType.Create(sizeBuiltinNode.TargetType)})";
}
private string EmitSliceArrayIndexAccess(SliceIndexAccessNode sliceIndexAccessNode)
{
var value = EmitExpression(sliceIndexAccessNode.Target);
var index = EmitExpression(sliceIndexAccessNode.Index);
// todo(nub31): We can emit bounds checking here
return $"{value}.data[{index}]";
}
private string EmitStringLiteral(StringLiteralNode stringLiteralNode)
{
throw new NotImplementedException();
}
private string EmitStructFieldAccess(StructFieldAccessNode structFieldAccessNode)
{
var structExpr = EmitExpression(structFieldAccessNode.Target);
return $"{structExpr}.{structFieldAccessNode.Field}";
}
private string EmitStructInitializer(StructInitializerNode structInitializerNode)
{
var initValues = new List<string>();
foreach (var initializer in structInitializerNode.Initializers)
{
var value = EmitExpression(initializer.Value);
initValues.Add($".{initializer.Key} = {value}");
}
var initString = initValues.Count == 0
? "0"
: string.Join(", ", initValues);
return $"({CType.Create(structInitializerNode.Type)}){{{initString}}}";
}
private string EmitUIntLiteral(UIntLiteralNode uIntLiteralNode)
{
var type = (NubIntType)uIntLiteralNode.Type;
return type.Width switch
{
8 or 16 or 32 => uIntLiteralNode.Value + "U",
64 => uIntLiteralNode.Value + "ULL",
_ => throw new ArgumentOutOfRangeException()
};
}
private string EmitUnaryExpression(UnaryExpressionNode unaryExpressionNode)
{
var value = EmitExpression(unaryExpressionNode.Operand);
return unaryExpressionNode.Operator switch
{
UnaryOperator.Negate => $"-{value}",
UnaryOperator.Invert => $"!{value}",
_ => throw new ArgumentOutOfRangeException()
};
}
private void EmitBlock(BlockNode blockNode)
{
EmitLine(blockNode.Tokens.FirstOrDefault());
_writer.WriteLine("{");
using (_writer.Indent())
{
_deferStack.Push([]);
foreach (var statementNode in blockNode.Statements)
{
EmitStatement(statementNode);
}
var blockDefers = _deferStack.Pop();
for (var i = blockDefers.Count - 1; i >= 0; i--)
{
EmitStatement(blockDefers[i].Statement);
}
}
EmitLine(blockNode.Tokens.LastOrDefault());
_writer.WriteLine("}");
}
}

View File

@@ -1,117 +1,164 @@
using LLVMSharp.Interop;
using NubLang.Ast;
using NubLang.Syntax;
namespace NubLang.Generation;
public class Generator
{
private readonly CompilationUnit _compilationUnit;
private readonly IndentedTextWriter _writer;
private readonly Stack<List<DeferNode>> _deferStack = [];
private int _tmpIndex;
public Generator(CompilationUnit compilationUnit)
{
_compilationUnit = compilationUnit;
_writer = new IndentedTextWriter();
LLVM.LinkInMCJIT();
LLVM.InitializeX86TargetInfo();
LLVM.InitializeX86Target();
LLVM.InitializeX86TargetMC();
LLVM.InitializeX86AsmPrinter();
_module = LLVMModuleRef.CreateWithName("test");
}
// todo(nub31): Handle name collisions
private string NewTmp()
{
return $"_t{++_tmpIndex}";
}
private bool _done;
private readonly Dictionary<string, LLVMTypeRef> _namedTypes = new();
private readonly LLVMModuleRef _module;
private static string FuncName(string module, string name, string? externSymbol)
{
return externSymbol ?? $"{module}_{name}";
}
private LLVMBuilderRef _builder;
private LLVMValueRef _currentFunction;
private Dictionary<string, LLVMValueRef> _namedValues = [];
private static string StructName(string module, string name)
private LLVMTypeRef MapType(NubType nubType)
{
return $"{module}_{name}";
}
public string Emit()
{
_writer.WriteLine("#include <stdint.h>");
_writer.WriteLine("#include <stdarg.h>");
_writer.WriteLine("#include <stddef.h>");
_writer.WriteLine();
foreach (var structType in _compilationUnit.ImportedStructTypes)
return nubType switch
{
_writer.WriteLine("typedef struct");
_writer.WriteLine("{");
using (_writer.Indent())
NubArrayType nubArrayType => LLVMTypeRef.CreatePointer(MapType(nubArrayType.ElementType), 0),
NubBoolType => LLVMTypeRef.Int1,
NubConstArrayType nubConstArrayType => LLVMTypeRef.CreateArray(MapType(nubConstArrayType.ElementType), (uint)nubConstArrayType.Size),
NubCStringType => LLVMTypeRef.CreatePointer(LLVMTypeRef.Int8, 0),
NubFloatType nubFloatType => nubFloatType.Width switch
{
foreach (var field in structType.Fields)
{
_writer.WriteLine($"{CType.Create(field.Type, field.Name)};");
}
}
32 => LLVMTypeRef.Float,
64 => LLVMTypeRef.Double,
_ => throw new ArgumentOutOfRangeException(nameof(nubFloatType.Width))
},
NubFuncType nubFuncType => LLVMTypeRef.CreateFunction(MapType(nubFuncType.ReturnType), nubFuncType.Parameters.Select(MapType).ToArray()),
NubIntType nubIntType => LLVMTypeRef.CreateInt((uint)nubIntType.Width),
NubPointerType nubPointerType => LLVMTypeRef.CreatePointer(MapType(nubPointerType.BaseType), 0),
NubSliceType nubSliceType => GetOrCreateSliceType(nubSliceType),
NubStringType => GetOrCreateStringType(),
NubStructType nubStructType => GetOrCreateStructType(nubStructType),
NubVoidType => LLVMTypeRef.Void,
_ => throw new ArgumentOutOfRangeException(nameof(nubType))
};
}
_writer.WriteLine($"}} {StructName(structType.Module, structType.Name)};");
_writer.WriteLine();
}
// note(nub31): Forward declarations
foreach (var prototype in _compilationUnit.ImportedFunctions)
private LLVMTypeRef GetOrCreateStructType(NubStructType structType)
{
var key = $"struct.{structType.Module}.{structType.Name}";
if (!_namedTypes.TryGetValue(key, out var llvmType))
{
EmitLine(prototype.Tokens.FirstOrDefault());
var parameters = prototype.Parameters.Count != 0
? string.Join(", ", prototype.Parameters.Select(x => CType.Create(x.Type, x.Name)))
: "void";
var name = FuncName(prototype.Module, prototype.Name, prototype.ExternSymbol);
_writer.WriteLine($"{CType.Create(prototype.ReturnType, name)}({parameters});");
_writer.WriteLine();
llvmType = _module.Context.CreateNamedStruct(structType.Name);
_namedTypes[key] = llvmType;
var fields = structType.Fields.Select(f => MapType(f.Type)).ToArray();
llvmType.StructSetBody(fields, false);
}
// note(nub31): declare extern functions
return llvmType;
}
private LLVMTypeRef GetOrCreateSliceType(NubSliceType sliceType)
{
var key = $"slice.{sliceType.ElementType}";
if (!_namedTypes.TryGetValue(key, out var llvmType))
{
llvmType = LLVMTypeRef.CreateStruct([LLVMTypeRef.CreatePointer(MapType(sliceType.ElementType), 0), LLVMTypeRef.Int64], false);
_namedTypes[key] = llvmType;
}
return llvmType;
}
private LLVMTypeRef GetOrCreateStringType()
{
const string key = "string";
if (!_namedTypes.TryGetValue(key, out var llvmType))
{
llvmType = _module.Context.CreateNamedStruct("string");
llvmType.StructSetBody([LLVMTypeRef.CreatePointer(LLVMTypeRef.Int8, 0), LLVMTypeRef.Int64], false);
_namedTypes[key] = llvmType;
}
return llvmType;
}
public string Generate()
{
if (_done)
{
return _module.PrintToString();
}
_done = true;
_builder = _module.Context.CreateBuilder();
foreach (var funcNode in _compilationUnit.Functions)
{
if (funcNode.Body != null) continue;
EmitLine(funcNode.Tokens.FirstOrDefault());
var parameters = funcNode.Prototype.Parameters.Count != 0
? string.Join(", ", funcNode.Prototype.Parameters.Select(x => CType.Create(x.Type, x.Name)))
: "void";
var name = FuncName(funcNode.Module, funcNode.Name, funcNode.Prototype.ExternSymbol);
_writer.WriteLine($"{CType.Create(funcNode.Prototype.ReturnType, name)}({parameters});");
EmitFunction(funcNode);
}
_writer.WriteLine();
// note(nub31): Normal functions
foreach (var funcNode in _compilationUnit.Functions)
if (_module.TryVerify(LLVMVerifierFailureAction.LLVMPrintMessageAction, out string error))
{
if (funcNode.Body == null) continue;
EmitLine(funcNode.Tokens.FirstOrDefault());
var parameters = funcNode.Prototype.Parameters.Count != 0
? string.Join(", ", funcNode.Prototype.Parameters.Select(x => CType.Create(x.Type, x.Name)))
: "void";
if (funcNode.Prototype.ExternSymbol == null)
{
_writer.Write("static ");
}
var name = FuncName(funcNode.Module, funcNode.Name, funcNode.Prototype.ExternSymbol);
_writer.WriteLine($"{CType.Create(funcNode.Prototype.ReturnType, name)}({parameters})");
EmitBlock(funcNode.Body);
_writer.WriteLine();
return _module.PrintToString();
}
else
{
throw new InvalidOperationException($"Invalid LLVM module: {error}");
}
return _writer.ToString();
}
private void EmitStatement(StatementNode statementNode)
private void EmitFunction(FuncNode funcNode)
{
EmitLine(statementNode.Tokens.FirstOrDefault());
switch (statementNode)
var parameters = funcNode.Prototype.Parameters.Select(x => MapType(x.Type)).ToArray();
var functionType = LLVMTypeRef.CreateFunction(MapType(funcNode.Prototype.ReturnType), parameters);
_currentFunction = _module.AddFunction(funcNode.Name, functionType);
if (funcNode.Body == null)
{
return;
}
_namedValues.Clear();
var entryBlock = _currentFunction.AppendBasicBlock("entry");
_builder.PositionAtEnd(entryBlock);
for (var i = 0; i < funcNode.Prototype.Parameters.Count; i++)
{
var param = funcNode.Prototype.Parameters[i];
var llvmParam = _currentFunction.GetParam((uint)i);
llvmParam.Name = param.Name;
var alloca = _builder.BuildAlloca(MapType(param.Type), param.Name);
_builder.BuildStore(llvmParam, alloca);
_namedValues[param.Name] = alloca;
}
EmitBlock(funcNode.Body);
}
private void EmitBlock(BlockNode blockNode)
{
foreach (var statement in blockNode.Statements)
{
EmitStatement(statement);
}
}
private void EmitStatement(StatementNode statement)
{
switch (statement)
{
case AssignmentNode assignmentNode:
EmitAssignment(assignmentNode);
@@ -144,123 +191,58 @@ public class Generator
EmitWhile(whileNode);
break;
default:
throw new ArgumentOutOfRangeException(nameof(statementNode));
throw new ArgumentOutOfRangeException(nameof(statement));
}
}
private void EmitLine(Token? token)
{
if (token == null) return;
var file = token.Span.FilePath;
var line = token.Span.Start.Line;
_writer.WriteLine($"#line {line} \"{file}\"");
}
private void EmitAssignment(AssignmentNode assignmentNode)
{
var target = EmitExpression(assignmentNode.Target);
var value = EmitExpression(assignmentNode.Value);
_writer.WriteLine($"{target} = {value};");
throw new NotImplementedException();
}
private void EmitBreak(BreakNode _)
private void EmitBreak(BreakNode breakNode)
{
_writer.WriteLine("break;");
throw new NotImplementedException();
}
private void EmitContinue(ContinueNode _)
private void EmitContinue(ContinueNode continueNode)
{
_writer.WriteLine("continue;");
throw new NotImplementedException();
}
private void EmitDefer(DeferNode deferNode)
{
_deferStack.Peek().Add(deferNode);
throw new NotImplementedException();
}
private void EmitIf(IfNode ifNode, bool elseIf = false)
private void EmitIf(IfNode ifNode)
{
var condition = EmitExpression(ifNode.Condition);
_writer.WriteLine($"{(elseIf ? "else " : "")}if ({condition})");
EmitBlock(ifNode.Body);
ifNode.Else?.Match
(
elseIfNode => EmitIf(elseIfNode, true),
elseNode =>
{
_writer.WriteLine("else");
EmitBlock(elseNode);
}
);
throw new NotImplementedException();
}
private void EmitReturn(ReturnNode returnNode)
{
if (returnNode.Value == null)
{
var blockDefers = _deferStack.Peek();
for (var i = blockDefers.Count - 1; i >= 0; i--)
{
EmitStatement(blockDefers[i].Statement);
}
_writer.WriteLine("return;");
}
else
{
var returnValue = EmitExpression(returnNode.Value);
if (_deferStack.Peek().Count != 0)
{
var tmp = NewTmp();
_writer.WriteLine($"{CType.Create(returnNode.Value.Type, tmp)} = {returnValue};");
var blockDefers = _deferStack.Peek();
for (var i = blockDefers.Count - 1; i >= 0; i--)
{
EmitStatement(blockDefers[i].Statement);
}
EmitLine(returnNode.Tokens.FirstOrDefault());
_writer.WriteLine($"return {tmp};");
}
else
{
EmitLine(returnNode.Tokens.FirstOrDefault());
_writer.WriteLine($"return {returnValue};");
}
}
throw new NotImplementedException();
}
private void EmitStatementFuncCall(StatementFuncCallNode statementFuncCallNode)
{
var funcCall = EmitFuncCall(statementFuncCallNode.FuncCall);
_writer.WriteLine($"{funcCall};");
throw new NotImplementedException();
}
private void EmitVariableDeclaration(VariableDeclarationNode variableDeclarationNode)
{
if (variableDeclarationNode.Assignment != null)
{
var value = EmitExpression(variableDeclarationNode.Assignment);
_writer.WriteLine($"{CType.Create(variableDeclarationNode.Type, variableDeclarationNode.Name)} = {value};");
}
else
{
_writer.WriteLine($"{CType.Create(variableDeclarationNode.Type, variableDeclarationNode.Name)};");
}
throw new NotImplementedException();
}
private void EmitWhile(WhileNode whileNode)
{
var condition = EmitExpression(whileNode.Condition);
_writer.WriteLine($"while ({condition})");
EmitBlock(whileNode.Body);
throw new NotImplementedException();
}
private string EmitExpression(ExpressionNode expressionNode)
private LLVMValueRef EmitExpression(ExpressionNode expressionNode)
{
var expr = expressionNode switch
return expressionNode switch
{
ArrayIndexAccessNode arrayIndexAccessNode => EmitArrayIndexAccess(arrayIndexAccessNode),
ArrayInitializerNode arrayInitializerNode => EmitArrayInitializer(arrayInitializerNode),
@@ -268,7 +250,6 @@ public class Generator
BoolLiteralNode boolLiteralNode => EmitBoolLiteral(boolLiteralNode),
ConstArrayIndexAccessNode constArrayIndexAccessNode => EmitConstArrayIndexAccess(constArrayIndexAccessNode),
ConstArrayInitializerNode constArrayInitializerNode => EmitConstArrayInitializer(constArrayInitializerNode),
// ConvertConstArrayToArrayNode convertConstArrayToArrayNode => EmitConvertConstArrayToArray(convertConstArrayToArrayNode),
ConvertFloatNode convertFloatNode => EmitConvertFloat(convertFloatNode),
ConvertIntNode convertIntNode => EmitConvertInt(convertIntNode),
CStringLiteralNode cStringLiteralNode => EmitCStringLiteral(cStringLiteralNode),
@@ -283,7 +264,7 @@ public class Generator
LValueIdentifierNode lValueIdentifierNode => EmitLValueIdentifier(lValueIdentifierNode),
RValueIdentifierNode rValueIdentifierNode => EmitRValueIdentifier(rValueIdentifierNode),
SizeBuiltinNode sizeBuiltinNode => EmitSizeBuiltin(sizeBuiltinNode),
SliceIndexAccessNode sliceIndexAccessNode => EmitSliceArrayIndexAccess(sliceIndexAccessNode),
SliceIndexAccessNode sliceIndexAccessNode => EmitSliceIndexAccess(sliceIndexAccessNode),
StringLiteralNode stringLiteralNode => EmitStringLiteral(stringLiteralNode),
StructFieldAccessNode structFieldAccessNode => EmitStructFieldAccess(structFieldAccessNode),
StructInitializerNode structInitializerNode => EmitStructInitializer(structInitializerNode),
@@ -291,291 +272,135 @@ public class Generator
UnaryExpressionNode unaryExpressionNode => EmitUnaryExpression(unaryExpressionNode),
_ => throw new ArgumentOutOfRangeException(nameof(expressionNode))
};
if (expressionNode is ConstArrayInitializerNode)
{
return expr;
}
return $"({expr})";
}
private string EmitArrayIndexAccess(ArrayIndexAccessNode arrayIndexAccessNode)
{
var array = EmitExpression(arrayIndexAccessNode.Target);
var index = EmitExpression(arrayIndexAccessNode.Index);
return $"{array}[{index}]";
}
private string EmitArrayInitializer(ArrayInitializerNode arrayInitializerNode)
{
var type = (NubArrayType)arrayInitializerNode.Type;
var capacity = EmitExpression(arrayInitializerNode.Capacity);
var tmp = NewTmp();
_writer.WriteLine($"{CType.Create(type.ElementType)} {tmp}[{capacity}];");
return tmp;
}
private string EmitBinaryExpression(BinaryExpressionNode binaryExpressionNode)
{
var left = EmitExpression(binaryExpressionNode.Left);
var right = EmitExpression(binaryExpressionNode.Right);
var op = binaryExpressionNode.Operator switch
{
BinaryOperator.Plus => "+",
BinaryOperator.Minus => "-",
BinaryOperator.Multiply => "*",
BinaryOperator.Divide => "/",
BinaryOperator.Modulo => "%",
BinaryOperator.Equal => "==",
BinaryOperator.NotEqual => "!=",
BinaryOperator.LessThan => "<",
BinaryOperator.LessThanOrEqual => "<=",
BinaryOperator.GreaterThan => ">",
BinaryOperator.GreaterThanOrEqual => ">=",
BinaryOperator.LogicalAnd => "&&",
BinaryOperator.LogicalOr => "||",
BinaryOperator.BitwiseAnd => "&",
BinaryOperator.BitwiseOr => "|",
BinaryOperator.BitwiseXor => "^",
BinaryOperator.LeftShift => "<<",
BinaryOperator.RightShift => ">>",
_ => throw new ArgumentOutOfRangeException()
};
return $"{left} {op} {right}";
}
private string EmitBoolLiteral(BoolLiteralNode boolLiteralNode)
{
return boolLiteralNode.Value ? "true" : "false";
}
private string EmitConstArrayIndexAccess(ConstArrayIndexAccessNode constArrayIndexAccessNode)
{
var array = EmitExpression(constArrayIndexAccessNode.Target);
var index = EmitExpression(constArrayIndexAccessNode.Index);
// todo(nub31): We can emit bounds checking here
return $"{array}[{index}]";
}
private string EmitConstArrayInitializer(ConstArrayInitializerNode constArrayInitializerNode)
{
return "{0}";
}
// private string EmitConvertConstArrayToArray(ConvertConstArrayToArrayNode convertConstArrayToArrayNode)
// {
// var value = EmitExpression(convertConstArrayToArrayNode.Value);
// return $"({CType.Create(convertConstArrayToArrayNode.Type)}){value}";
// }
private string EmitConvertFloat(ConvertFloatNode convertFloatNode)
{
var value = EmitExpression(convertFloatNode.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);
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)
{
return $"\"{cStringLiteralNode.Value}\"";
}
private string EmitDereference(DereferenceNode dereferenceNode)
{
var pointer = EmitExpression(dereferenceNode.Target);
return $"*{pointer}";
}
private string EmitFloat32Literal(Float32LiteralNode float32LiteralNode)
{
var str = float32LiteralNode.Value.ToString("G9", System.Globalization.CultureInfo.InvariantCulture);
if (!str.Contains('.') && !str.Contains('e') && !str.Contains('E'))
{
str += ".0";
}
return str + "f";
}
private string EmitFloat64Literal(Float64LiteralNode float64LiteralNode)
{
var str = float64LiteralNode.Value.ToString("G17", System.Globalization.CultureInfo.InvariantCulture);
if (!str.Contains('.') && !str.Contains('e') && !str.Contains('E'))
{
str += ".0";
}
return str;
}
private string EmitFloatToIntBuiltin(FloatToIntBuiltinNode floatToIntBuiltinNode)
{
var value = EmitExpression(floatToIntBuiltinNode.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)
{
var name = EmitExpression(funcCallNode.Expression);
var parameterNames = funcCallNode.Parameters.Select(x => EmitExpression(x)).ToList();
return $"{name}({string.Join(", ", parameterNames)})";
}
private string EmitFuncIdentifier(FuncIdentifierNode funcIdentifierNode)
{
return FuncName(funcIdentifierNode.Module, funcIdentifierNode.Name, funcIdentifierNode.ExternSymbol);
}
private string EmitIntLiteral(IntLiteralNode intLiteralNode)
{
var type = (NubIntType)intLiteralNode.Type;
return type.Width switch
{
8 or 16 or 32 => intLiteralNode.Value.ToString(),
64 => intLiteralNode.Value + "LL",
_ => throw new ArgumentOutOfRangeException()
};
}
private string EmitAddressOf(AddressOfNode addressOfNode)
{
var value = EmitExpression(addressOfNode.LValue);
return $"&{value}";
}
private string EmitLValueIdentifier(LValueIdentifierNode lValueIdentifierNode)
{
return lValueIdentifierNode.Name;
}
private string EmitRValueIdentifier(RValueIdentifierNode rValueIdentifierNode)
{
return rValueIdentifierNode.Name;
}
private string EmitSizeBuiltin(SizeBuiltinNode sizeBuiltinNode)
{
return $"sizeof({CType.Create(sizeBuiltinNode.TargetType)})";
}
private string EmitSliceArrayIndexAccess(SliceIndexAccessNode sliceIndexAccessNode)
{
var value = EmitExpression(sliceIndexAccessNode.Target);
var index = EmitExpression(sliceIndexAccessNode.Index);
// todo(nub31): We can emit bounds checking here
return $"{value}.data[{index}]";
}
private string EmitStringLiteral(StringLiteralNode stringLiteralNode)
private LLVMValueRef EmitArrayIndexAccess(ArrayIndexAccessNode arrayIndexAccessNode)
{
throw new NotImplementedException();
}
private string EmitStructFieldAccess(StructFieldAccessNode structFieldAccessNode)
private LLVMValueRef EmitArrayInitializer(ArrayInitializerNode arrayInitializerNode)
{
var structExpr = EmitExpression(structFieldAccessNode.Target);
return $"{structExpr}.{structFieldAccessNode.Field}";
throw new NotImplementedException();
}
private string EmitStructInitializer(StructInitializerNode structInitializerNode)
private LLVMValueRef EmitBinaryExpression(BinaryExpressionNode binaryExpressionNode)
{
var initValues = new List<string>();
foreach (var initializer in structInitializerNode.Initializers)
{
var value = EmitExpression(initializer.Value);
initValues.Add($".{initializer.Key} = {value}");
}
var initString = initValues.Count == 0
? "0"
: string.Join(", ", initValues);
return $"({CType.Create(structInitializerNode.Type)}){{{initString}}}";
throw new NotImplementedException();
}
private string EmitUIntLiteral(UIntLiteralNode uIntLiteralNode)
private LLVMValueRef EmitBoolLiteral(BoolLiteralNode boolLiteralNode)
{
var type = (NubIntType)uIntLiteralNode.Type;
return type.Width switch
{
8 or 16 or 32 => uIntLiteralNode.Value + "U",
64 => uIntLiteralNode.Value + "ULL",
_ => throw new ArgumentOutOfRangeException()
};
throw new NotImplementedException();
}
private string EmitUnaryExpression(UnaryExpressionNode unaryExpressionNode)
private LLVMValueRef EmitConstArrayIndexAccess(ConstArrayIndexAccessNode constArrayIndexAccessNode)
{
var value = EmitExpression(unaryExpressionNode.Operand);
return unaryExpressionNode.Operator switch
{
UnaryOperator.Negate => $"-{value}",
UnaryOperator.Invert => $"!{value}",
_ => throw new ArgumentOutOfRangeException()
};
throw new NotImplementedException();
}
private void EmitBlock(BlockNode blockNode)
private LLVMValueRef EmitConstArrayInitializer(ConstArrayInitializerNode constArrayInitializerNode)
{
EmitLine(blockNode.Tokens.FirstOrDefault());
_writer.WriteLine("{");
using (_writer.Indent())
{
_deferStack.Push([]);
throw new NotImplementedException();
}
foreach (var statementNode in blockNode.Statements)
{
EmitStatement(statementNode);
}
private LLVMValueRef EmitConvertFloat(ConvertFloatNode convertFloatNode)
{
throw new NotImplementedException();
}
var blockDefers = _deferStack.Pop();
for (var i = blockDefers.Count - 1; i >= 0; i--)
{
EmitStatement(blockDefers[i].Statement);
}
}
private LLVMValueRef EmitConvertInt(ConvertIntNode convertIntNode)
{
throw new NotImplementedException();
}
EmitLine(blockNode.Tokens.LastOrDefault());
_writer.WriteLine("}");
private LLVMValueRef EmitCStringLiteral(CStringLiteralNode cStringLiteralNode)
{
throw new NotImplementedException();
}
private LLVMValueRef EmitDereference(DereferenceNode dereferenceNode)
{
throw new NotImplementedException();
}
private LLVMValueRef EmitFloat32Literal(Float32LiteralNode float32LiteralNode)
{
throw new NotImplementedException();
}
private LLVMValueRef EmitFloat64Literal(Float64LiteralNode float64LiteralNode)
{
throw new NotImplementedException();
}
private LLVMValueRef EmitFloatToIntBuiltin(FloatToIntBuiltinNode floatToIntBuiltinNode)
{
throw new NotImplementedException();
}
private LLVMValueRef EmitFuncCall(FuncCallNode funcCallNode)
{
throw new NotImplementedException();
}
private LLVMValueRef EmitFuncIdentifier(FuncIdentifierNode funcIdentifierNode)
{
throw new NotImplementedException();
}
private LLVMValueRef EmitIntLiteral(IntLiteralNode intLiteralNode)
{
throw new NotImplementedException();
}
private LLVMValueRef EmitAddressOf(AddressOfNode addressOfNode)
{
throw new NotImplementedException();
}
private LLVMValueRef EmitLValueIdentifier(LValueIdentifierNode lValueIdentifierNode)
{
throw new NotImplementedException();
}
private LLVMValueRef EmitRValueIdentifier(RValueIdentifierNode rValueIdentifierNode)
{
throw new NotImplementedException();
}
private LLVMValueRef EmitSizeBuiltin(SizeBuiltinNode sizeBuiltinNode)
{
throw new NotImplementedException();
}
private LLVMValueRef EmitSliceIndexAccess(SliceIndexAccessNode sliceIndexAccessNode)
{
throw new NotImplementedException();
}
private LLVMValueRef EmitStringLiteral(StringLiteralNode stringLiteralNode)
{
throw new NotImplementedException();
}
private LLVMValueRef EmitStructFieldAccess(StructFieldAccessNode structFieldAccessNode)
{
throw new NotImplementedException();
}
private LLVMValueRef EmitStructInitializer(StructInitializerNode structInitializerNode)
{
throw new NotImplementedException();
}
private LLVMValueRef EmitUIntLiteral(UIntLiteralNode uIntLiteralNode)
{
throw new NotImplementedException();
}
private LLVMValueRef EmitUnaryExpression(UnaryExpressionNode unaryExpressionNode)
{
throw new NotImplementedException();
}
}

View File

@@ -7,4 +7,8 @@
<IsAotCompatible>true</IsAotCompatible>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="LLVMSharp.Interop" Version="20.1.2" />
</ItemGroup>
</Project>