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