...
This commit is contained in:
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user