...
This commit is contained in:
@@ -22,16 +22,26 @@ public class LlvmGenerator
|
|||||||
var writer = new IndentedTextWriter();
|
var writer = new IndentedTextWriter();
|
||||||
|
|
||||||
_module = topLevelNodes.OfType<ModuleNode>().First().NameToken.Value;
|
_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>();
|
var declaredExternFunctions = new HashSet<string>();
|
||||||
|
|
||||||
|
writer.WriteLine("; == Function declarations ==");
|
||||||
foreach (var module in repository.GetAll())
|
foreach (var module in repository.GetAll())
|
||||||
{
|
{
|
||||||
|
writer.WriteLine($"; ==== {module.Name} ====");
|
||||||
foreach (var prototype in module.FunctionPrototypes)
|
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
|
// 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;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
var parameters = prototype.Parameters.Select(x => $"{MapType(x.Type)} %{x.NameToken.Value}");
|
writer.WriteLine($"declare {CreateFunctionPrototype(prototype, module.Name)}");
|
||||||
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();
|
||||||
|
|
||||||
|
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>())
|
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;
|
_tmpIndex = 0;
|
||||||
_labelIndex = 0;
|
_labelIndex = 0;
|
||||||
|
|
||||||
|
writer.WriteLine("; == Struct constructors ==");
|
||||||
writer.WriteLine($"define void @{StructName(structNode)}.new(ptr %self) {{");
|
writer.WriteLine($"define void @{StructName(structNode)}.new(ptr %self) {{");
|
||||||
using (writer.Indent())
|
using (writer.Indent())
|
||||||
{
|
{
|
||||||
@@ -83,6 +102,7 @@ public class LlvmGenerator
|
|||||||
writer.WriteLine();
|
writer.WriteLine();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
writer.WriteLine("; == Function definitions ==");
|
||||||
foreach (var funcNode in topLevelNodes.OfType<FuncNode>())
|
foreach (var funcNode in topLevelNodes.OfType<FuncNode>())
|
||||||
{
|
{
|
||||||
if (funcNode.Body == null) continue;
|
if (funcNode.Body == null) continue;
|
||||||
@@ -90,8 +110,7 @@ public class LlvmGenerator
|
|||||||
_tmpIndex = 0;
|
_tmpIndex = 0;
|
||||||
_labelIndex = 0;
|
_labelIndex = 0;
|
||||||
|
|
||||||
var parameters = funcNode.Prototype.Parameters.Select(x => $"{MapType(x.Type)} %{x.NameToken.Value}");
|
writer.WriteLine($"define {CreateFunctionPrototype(funcNode.Prototype, _module)} {{");
|
||||||
writer.WriteLine($"define {MapType(funcNode.Prototype.ReturnType)} @{FuncName(_module, funcNode.Prototype.NameToken.Value, funcNode.Prototype.ExternSymbolToken?.Value)}({string.Join(", ", parameters)}) {{");
|
|
||||||
|
|
||||||
using (writer.Indent())
|
using (writer.Indent())
|
||||||
{
|
{
|
||||||
@@ -108,6 +127,7 @@ public class LlvmGenerator
|
|||||||
writer.WriteLine();
|
writer.WriteLine();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
writer.WriteLine("; == String literals ==");
|
||||||
foreach (var stringLiteral in _stringLiterals)
|
foreach (var stringLiteral in _stringLiterals)
|
||||||
{
|
{
|
||||||
writer.WriteLine($"{stringLiteral.Name} = private unnamed_addr constant [{stringLiteral.Size} x i8] c\"{stringLiteral.Text}\\00\", align 1");
|
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();
|
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)
|
private void EmitStatement(IndentedTextWriter writer, StatementNode statementNode)
|
||||||
{
|
{
|
||||||
switch (statementNode)
|
switch (statementNode)
|
||||||
@@ -860,11 +920,11 @@ public class LlvmGenerator
|
|||||||
|
|
||||||
if (funcCallNode.Type is NubVoidType)
|
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
|
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);
|
return new Tmp(result, funcCallNode.Type, false);
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ extern "main" func main(argc: i64, argv: [?]^i8)
|
|||||||
puts(x)
|
puts(x)
|
||||||
}
|
}
|
||||||
|
|
||||||
func test(arr: [?]i64)
|
func test(test: Test): Test
|
||||||
{
|
{
|
||||||
|
return test
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user