This commit is contained in:
nub31
2025-11-03 12:52:17 +01:00
parent 40d500fddd
commit 085f7a1a6a
17 changed files with 368 additions and 190 deletions

View File

@@ -1,5 +1,6 @@
using System.Text;
using NubLang.Ast;
using NubLang.Modules;
using NubLang.Types;
namespace NubLang.Generation;
@@ -12,7 +13,7 @@ public class LlvmGenerator
private List<(string Name, int Size, string Text)> _stringLiterals = [];
private Stack<(string breakLabel, string continueLabel)> _loopStack = [];
public string Emit(List<TopLevelNode> topLevelNodes)
public string Emit(List<TopLevelNode> topLevelNodes, ModuleRepository repository)
{
_stringLiterals = [];
_loopStack = [];
@@ -26,6 +27,30 @@ public class LlvmGenerator
writer.WriteLine("declare void @llvm.memcpy.p0.p0.i64(ptr, ptr, i64, i1)");
writer.WriteLine();
var declaredExternFunctions = new HashSet<string>();
foreach (var module in repository.GetAll())
{
foreach (var prototype in module.FunctionPrototypes)
{
// note(nub31): If we are in the current module and the function has a body, we skip it to prevent duplicate definition
if (module.Name == _module && topLevelNodes.OfType<FuncNode>().First(x => x.NameToken.Value == prototype.NameToken.Value).Body != null)
{
continue;
}
if (prototype.ExternSymbolToken != null && !declaredExternFunctions.Add(prototype.ExternSymbolToken.Value))
{
continue;
}
var parameters = prototype.Parameters.Select(x => $"{MapType(x.Type)} %{x.NameToken.Value}");
var funcName = FuncName(module.Name, prototype.NameToken.Value, prototype.ExternSymbolToken?.Value);
writer.WriteLine($"declare {MapType(prototype.ReturnType)} @{funcName}({string.Join(", ", parameters)})");
writer.WriteLine();
}
}
foreach (var structNode in topLevelNodes.OfType<StructNode>())
{
var types = structNode.Fields.Select(x => MapType(x.Type));
@@ -57,15 +82,6 @@ public class LlvmGenerator
writer.WriteLine();
}
foreach (var funcNode in topLevelNodes.OfType<FuncNode>())
{
if (funcNode.Body != null) continue;
var parameters = funcNode.Prototype.Parameters.Select(x => $"{MapType(x.Type)} %{x.NameToken.Value}");
writer.WriteLine($"declare {MapType(funcNode.Prototype.ReturnType)} @{FuncName(funcNode.Prototype)}({string.Join(", ", parameters)})");
writer.WriteLine();
}
foreach (var funcNode in topLevelNodes.OfType<FuncNode>())
{
if (funcNode.Body == null) continue;
@@ -335,7 +351,8 @@ public class LlvmGenerator
Float32LiteralNode float32LiteralNode => EmitFloat32Literal(writer, float32LiteralNode),
Float64LiteralNode float64LiteralNode => EmitFloat64Literal(writer, float64LiteralNode),
FuncCallNode funcCallNode => EmitFuncCall(writer, funcCallNode),
ModuleFuncIdentifierNode funcIdentifierNode => EmitFuncIdentifier(writer, funcIdentifierNode),
ModuleFuncIdentifierNode moduleFuncIdentifierNode => EmitModuleFuncIdentifier(writer, moduleFuncIdentifierNode),
LocalFuncIdentifierNode localFuncIdentifierNode => EmitLocalFuncIdentifier(writer, localFuncIdentifierNode),
I16LiteralNode i16LiteralNode => EmitI16Literal(writer, i16LiteralNode),
I32LiteralNode i32LiteralNode => EmitI32Literal(writer, i32LiteralNode),
I64LiteralNode i64LiteralNode => EmitI64Literal(writer, i64LiteralNode),
@@ -769,12 +786,18 @@ public class LlvmGenerator
return new Tmp(result, funcCallNode.Type, false);
}
private Tmp EmitFuncIdentifier(IndentedTextWriter writer, ModuleFuncIdentifierNode moduleFuncIdentifierNode)
private Tmp EmitModuleFuncIdentifier(IndentedTextWriter writer, ModuleFuncIdentifierNode moduleFuncIdentifierNode)
{
var name = FuncName(moduleFuncIdentifierNode.ModuleToken.Value, moduleFuncIdentifierNode.NameToken.Value, moduleFuncIdentifierNode.ExternSymbolToken?.Value);
return new Tmp($"@{name}", moduleFuncIdentifierNode.Type, false);
}
private Tmp EmitLocalFuncIdentifier(IndentedTextWriter writer, LocalFuncIdentifierNode localFuncIdentifierNode)
{
var name = FuncName(_module, localFuncIdentifierNode.NameToken.Value, localFuncIdentifierNode.ExternSymbolToken?.Value);
return new Tmp($"@{name}", localFuncIdentifierNode.Type, false);
}
private Tmp EmitI16Literal(IndentedTextWriter writer, I16LiteralNode i16LiteralNode)
{
return new Tmp(i16LiteralNode.Value.ToString(), i16LiteralNode.Type, false);