This commit is contained in:
nub31
2025-11-03 19:54:41 +01:00
parent 47fef6bc9f
commit 36622755a9
2 changed files with 78 additions and 18 deletions

View File

@@ -22,16 +22,26 @@ public class LlvmGenerator
var writer = new IndentedTextWriter();
_module = topLevelNodes.OfType<ModuleNode>().First().NameToken.Value;
writer.WriteLine($"; Module {_module}");
writer.WriteLine();
writer.WriteLine("declare void @llvm.memcpy.p0.p0.i64(ptr, ptr, i64, i1)");
writer.WriteLine();
writer.WriteLine($$"""
; Module {{_module}}
target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128"
target triple = "x86_64-pc-linux-gnu"
%nub.slice = type { i64, ptr }
%nub.string = type { i64, ptr }
declare void @llvm.memcpy.p0.p0.i64(ptr, ptr, i64, i1)
""");
var declaredExternFunctions = new HashSet<string>();
writer.WriteLine("; == Function declarations ==");
foreach (var module in repository.GetAll())
{
writer.WriteLine($"; ==== {module.Name} ====");
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
@@ -45,22 +55,31 @@ public class LlvmGenerator
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();
writer.WriteLine($"declare {CreateFunctionPrototype(prototype, module.Name)}");
}
}
writer.WriteLine();
writer.WriteLine("; == Struct declarations ==");
foreach (var module in repository.GetAll())
{
writer.WriteLine($"; ==== {module.Name} ====");
foreach (var structType in module.StructTypes)
{
var fieldTypes = structType.Fields.Select(x => MapType(x.Type));
writer.WriteLine($"%{StructName(structType.Module, structType.Name)} = type {{ {string.Join(", ", fieldTypes)} }}");
}
}
writer.WriteLine();
foreach (var structNode in topLevelNodes.OfType<StructNode>())
{
var types = structNode.Fields.Select(x => MapType(x.Type));
writer.WriteLine($"%{StructName(structNode)} = type {{ {string.Join(", ", types)} }}");
writer.WriteLine();
_tmpIndex = 0;
_labelIndex = 0;
writer.WriteLine("; == Struct constructors ==");
writer.WriteLine($"define void @{StructName(structNode)}.new(ptr %self) {{");
using (writer.Indent())
{
@@ -83,6 +102,7 @@ public class LlvmGenerator
writer.WriteLine();
}
writer.WriteLine("; == Function definitions ==");
foreach (var funcNode in topLevelNodes.OfType<FuncNode>())
{
if (funcNode.Body == null) continue;
@@ -90,8 +110,7 @@ public class LlvmGenerator
_tmpIndex = 0;
_labelIndex = 0;
var parameters = funcNode.Prototype.Parameters.Select(x => $"{MapType(x.Type)} %{x.NameToken.Value}");
writer.WriteLine($"define {MapType(funcNode.Prototype.ReturnType)} @{FuncName(_module, funcNode.Prototype.NameToken.Value, funcNode.Prototype.ExternSymbolToken?.Value)}({string.Join(", ", parameters)}) {{");
writer.WriteLine($"define {CreateFunctionPrototype(funcNode.Prototype, _module)} {{");
using (writer.Indent())
{
@@ -108,6 +127,7 @@ public class LlvmGenerator
writer.WriteLine();
}
writer.WriteLine("; == String literals ==");
foreach (var stringLiteral in _stringLiterals)
{
writer.WriteLine($"{stringLiteral.Name} = private unnamed_addr constant [{stringLiteral.Size} x i8] c\"{stringLiteral.Text}\\00\", align 1");
@@ -116,6 +136,46 @@ public class LlvmGenerator
return writer.ToString();
}
private string CreateFunctionPrototype(FuncPrototypeNode prototypeNode, string module)
{
var parameterStrings = new List<string>();
foreach (var parameter in prototypeNode.Parameters)
{
var llvmType = MapType(parameter.Type);
var name = parameter.NameToken.Value;
if (parameter.Type is NubStructType)
{
var alignment = parameter.Type.GetAlignment();
parameterStrings.Add($"{llvmType}* byval({llvmType}) align {alignment} %{name}");
}
else
{
parameterStrings.Add($"{llvmType} %{name}");
}
}
var funcName = FuncName(module, prototypeNode.NameToken.Value, prototypeNode.ExternSymbolToken?.Value);
var returnType = MapType(prototypeNode.ReturnType);
if (prototypeNode.ReturnType is NubStructType)
{
var alignment = prototypeNode.ReturnType.GetAlignment();
var parameters = "";
if (parameterStrings.Count != 0)
{
parameters = ", " + string.Join(", ", parameterStrings);
}
return $"ccc void @{funcName}({returnType}* sret({returnType}) align {alignment}{parameters})";
}
else
{
return $"ccc {returnType} @{funcName}({string.Join(", ", parameterStrings)})";
}
}
private void EmitStatement(IndentedTextWriter writer, StatementNode statementNode)
{
switch (statementNode)
@@ -860,11 +920,11 @@ public class LlvmGenerator
if (funcCallNode.Type is NubVoidType)
{
writer.WriteLine($"call {MapType(funcCallNode.Type)} {functionPtr}({string.Join(", ", parameterStrings)})");
writer.WriteLine($"call ccc {MapType(funcCallNode.Type)} {functionPtr}({string.Join(", ", parameterStrings)})");
}
else
{
writer.WriteLine($"{result} = call {MapType(funcCallNode.Type)} {functionPtr}({string.Join(", ", parameterStrings)})");
writer.WriteLine($"{result} = call ccc {MapType(funcCallNode.Type)} {functionPtr}({string.Join(", ", parameterStrings)})");
}
return new Tmp(result, funcCallNode.Type, false);

View File

@@ -15,7 +15,7 @@ extern "main" func main(argc: i64, argv: [?]^i8)
puts(x)
}
func test(arr: [?]i64)
func test(test: Test): Test
{
return test
}