This commit is contained in:
nub31
2025-10-21 20:22:18 +02:00
parent 3dab4c7e60
commit 4a01fbc306
10 changed files with 237 additions and 935 deletions

View File

@@ -7,26 +7,19 @@ public class Generator
{
private readonly CompilationUnit _compilationUnit;
public Generator(CompilationUnit compilationUnit)
{
_compilationUnit = compilationUnit;
LLVM.LinkInMCJIT();
LLVM.InitializeX86TargetInfo();
LLVM.InitializeX86Target();
LLVM.InitializeX86TargetMC();
LLVM.InitializeX86AsmPrinter();
_module = LLVMModuleRef.CreateWithName("test");
}
private bool _done;
private readonly Dictionary<string, LLVMTypeRef> _namedTypes = new();
private readonly Dictionary<string, LLVMValueRef> _namedValues = [];
private readonly LLVMModuleRef _module;
private LLVMBuilderRef _builder;
private LLVMValueRef _currentFunction;
private Dictionary<string, LLVMValueRef> _namedValues = [];
public Generator(CompilationUnit compilationUnit, string fileName)
{
_compilationUnit = compilationUnit;
_module = LLVMModuleRef.CreateWithName(fileName);
}
private LLVMTypeRef MapType(NubType nubType)
{
@@ -34,7 +27,7 @@ public class Generator
{
NubArrayType nubArrayType => LLVMTypeRef.CreatePointer(MapType(nubArrayType.ElementType), 0),
NubBoolType => LLVMTypeRef.Int1,
NubConstArrayType nubConstArrayType => LLVMTypeRef.CreateArray(MapType(nubConstArrayType.ElementType), (uint)nubConstArrayType.Size),
NubConstArrayType nubConstArrayType => LLVMTypeRef.CreatePointer(MapType(nubConstArrayType.ElementType), 0),
NubCStringType => LLVMTypeRef.CreatePointer(LLVMTypeRef.Int8, 0),
NubFloatType nubFloatType => nubFloatType.Width switch
{
@@ -92,11 +85,11 @@ public class Generator
return llvmType;
}
public string Generate()
public LLVMModuleRef Generate()
{
if (_done)
{
return _module.PrintToString();
return _module;
}
_done = true;
@@ -107,14 +100,13 @@ public class Generator
EmitFunction(funcNode);
}
if (_module.TryVerify(LLVMVerifierFailureAction.LLVMPrintMessageAction, out string error))
if (!_module.TryVerify(LLVMVerifierFailureAction.LLVMPrintMessageAction, out var error))
{
return _module.PrintToString();
}
else
{
throw new InvalidOperationException($"Invalid LLVM module: {error}");
Console.WriteLine($"Invalid LLVM module: {error}");
// throw new InvalidOperationException($"Invalid LLVM module: {error}");
}
return _module;
}
private void EmitFunction(FuncNode funcNode)
@@ -140,7 +132,7 @@ public class Generator
var llvmParam = _currentFunction.GetParam((uint)i);
llvmParam.Name = param.Name;
var alloca = _builder.BuildAlloca(MapType(param.Type), param.Name);
var alloca = _builder.BuildAlloca(MapType(param.Type));
_builder.BuildStore(llvmParam, alloca);
_namedValues[param.Name] = alloca;
}
@@ -197,7 +189,9 @@ public class Generator
private void EmitAssignment(AssignmentNode assignmentNode)
{
throw new NotImplementedException();
var target = EmitLValue(assignmentNode.Target);
var value = EmitExpression(assignmentNode.Value);
_builder.BuildStore(value, target);
}
private void EmitBreak(BreakNode breakNode)
@@ -222,17 +216,41 @@ public class Generator
private void EmitReturn(ReturnNode returnNode)
{
throw new NotImplementedException();
if (returnNode.Value == null)
{
_builder.BuildRetVoid();
}
else
{
var returnValue = EmitExpression(returnNode.Value);
_builder.BuildRet(returnValue);
}
}
private void EmitStatementFuncCall(StatementFuncCallNode statementFuncCallNode)
{
throw new NotImplementedException();
EmitFuncCall(statementFuncCallNode.FuncCall);
}
private void EmitVariableDeclaration(VariableDeclarationNode variableDeclarationNode)
{
throw new NotImplementedException();
if (variableDeclarationNode.Assignment is LValueExpressionNode lValueExpressionNode)
{
var value = EmitLValue(lValueExpressionNode);
_namedValues[variableDeclarationNode.Name] = value;
return;
}
var allocaType = MapType(variableDeclarationNode.Type);
var alloca = _builder.BuildAlloca(allocaType);
if (variableDeclarationNode.Assignment != null)
{
var initValue = EmitExpression(variableDeclarationNode.Assignment);
_builder.BuildStore(initValue, alloca);
}
_namedValues[variableDeclarationNode.Name] = alloca;
}
private void EmitWhile(WhileNode whileNode)
@@ -242,66 +260,165 @@ public class Generator
private LLVMValueRef EmitExpression(ExpressionNode expressionNode)
{
return expressionNode switch
switch (expressionNode)
{
case LValueExpressionNode lvalue:
{
var value = EmitLValue(lvalue);
return _builder.BuildLoad2(MapType(lvalue.Type), value);
}
case RValueExpressionNode rvalue:
{
return EmitRValue(rvalue);
}
default:
{
throw new ArgumentOutOfRangeException(nameof(expressionNode));
}
}
}
private LLVMValueRef EmitLValue(LValueExpressionNode lValueNode)
{
return lValueNode switch
{
ArrayIndexAccessNode arrayIndexAccessNode => EmitArrayIndexAccess(arrayIndexAccessNode),
ConstArrayIndexAccessNode constArrayIndexAccessNode => EmitConstArrayIndexAccess(constArrayIndexAccessNode),
DereferenceNode dereferenceNode => EmitDereference(dereferenceNode),
LValueIdentifierNode lValueIdentifierNode => EmitLValueIdentifier(lValueIdentifierNode),
SliceIndexAccessNode sliceIndexAccessNode => EmitSliceIndexAccess(sliceIndexAccessNode),
StructFieldAccessNode structFieldAccessNode => EmitStructFieldAccess(structFieldAccessNode),
StructInitializerNode structInitializerNode => EmitStructInitializer(structInitializerNode),
_ => throw new ArgumentOutOfRangeException(nameof(lValueNode))
};
}
private LLVMValueRef EmitRValue(RValueExpressionNode rValueNode)
{
return rValueNode switch
{
AddressOfNode addressOfNode => EmitAddressOf(addressOfNode),
ArrayInitializerNode arrayInitializerNode => EmitArrayInitializer(arrayInitializerNode),
BinaryExpressionNode binaryExpressionNode => EmitBinaryExpression(binaryExpressionNode),
BoolLiteralNode boolLiteralNode => EmitBoolLiteral(boolLiteralNode),
ConstArrayIndexAccessNode constArrayIndexAccessNode => EmitConstArrayIndexAccess(constArrayIndexAccessNode),
ConstArrayInitializerNode constArrayInitializerNode => EmitConstArrayInitializer(constArrayInitializerNode),
ConvertFloatNode convertFloatNode => EmitConvertFloat(convertFloatNode),
ConvertIntNode convertIntNode => EmitConvertInt(convertIntNode),
CStringLiteralNode cStringLiteralNode => EmitCStringLiteral(cStringLiteralNode),
DereferenceNode dereferenceNode => EmitDereference(dereferenceNode),
Float32LiteralNode float32LiteralNode => EmitFloat32Literal(float32LiteralNode),
Float64LiteralNode float64LiteralNode => EmitFloat64Literal(float64LiteralNode),
FloatToIntBuiltinNode floatToIntBuiltinNode => EmitFloatToIntBuiltin(floatToIntBuiltinNode),
FuncCallNode funcCallNode => EmitFuncCall(funcCallNode),
FuncIdentifierNode funcIdentifierNode => EmitFuncIdentifier(funcIdentifierNode),
IntLiteralNode intLiteralNode => EmitIntLiteral(intLiteralNode),
AddressOfNode addressOfNode => EmitAddressOf(addressOfNode),
LValueIdentifierNode lValueIdentifierNode => EmitLValueIdentifier(lValueIdentifierNode),
RValueIdentifierNode rValueIdentifierNode => EmitRValueIdentifier(rValueIdentifierNode),
SizeBuiltinNode sizeBuiltinNode => EmitSizeBuiltin(sizeBuiltinNode),
SliceIndexAccessNode sliceIndexAccessNode => EmitSliceIndexAccess(sliceIndexAccessNode),
StringLiteralNode stringLiteralNode => EmitStringLiteral(stringLiteralNode),
StructFieldAccessNode structFieldAccessNode => EmitStructFieldAccess(structFieldAccessNode),
StructInitializerNode structInitializerNode => EmitStructInitializer(structInitializerNode),
UIntLiteralNode uIntLiteralNode => EmitUIntLiteral(uIntLiteralNode),
UnaryExpressionNode unaryExpressionNode => EmitUnaryExpression(unaryExpressionNode),
_ => throw new ArgumentOutOfRangeException(nameof(expressionNode))
_ => throw new ArgumentOutOfRangeException(nameof(rValueNode))
};
}
private LLVMValueRef EmitArrayIndexAccess(ArrayIndexAccessNode arrayIndexAccessNode)
{
throw new NotImplementedException();
var arrayType = (NubArrayType)arrayIndexAccessNode.Target.Type;
var elementType = MapType(arrayType.ElementType);
var target = EmitExpression(arrayIndexAccessNode.Target);
var index = EmitExpression(arrayIndexAccessNode.Index);
return _builder.BuildGEP2(elementType, target, [index]);
}
private LLVMValueRef EmitArrayInitializer(ArrayInitializerNode arrayInitializerNode)
{
throw new NotImplementedException();
var capacity = EmitExpression(arrayInitializerNode.Capacity);
return _builder.BuildArrayAlloca(MapType(arrayInitializerNode.ElementType), capacity);
}
private LLVMValueRef EmitBinaryExpression(BinaryExpressionNode binaryExpressionNode)
{
throw new NotImplementedException();
var left = EmitExpression(binaryExpressionNode.Left);
var right = EmitExpression(binaryExpressionNode.Right);
var leftType = binaryExpressionNode.Left.Type;
if (leftType is NubIntType)
{
return binaryExpressionNode.Operator switch
{
BinaryOperator.Plus => _builder.BuildAdd(left, right),
BinaryOperator.Minus => _builder.BuildSub(left, right),
BinaryOperator.Multiply => _builder.BuildMul(left, right),
BinaryOperator.Divide => _builder.BuildSDiv(left, right),
BinaryOperator.Modulo => _builder.BuildSRem(left, right),
BinaryOperator.Equal => _builder.BuildICmp(LLVMIntPredicate.LLVMIntEQ, left, right),
BinaryOperator.NotEqual => _builder.BuildICmp(LLVMIntPredicate.LLVMIntNE, left, right),
BinaryOperator.LessThan => _builder.BuildICmp(LLVMIntPredicate.LLVMIntSLT, left, right),
BinaryOperator.LessThanOrEqual => _builder.BuildICmp(LLVMIntPredicate.LLVMIntSLE, left, right),
BinaryOperator.GreaterThan => _builder.BuildICmp(LLVMIntPredicate.LLVMIntSGT, left, right),
BinaryOperator.GreaterThanOrEqual => _builder.BuildICmp(LLVMIntPredicate.LLVMIntSGE, left, right),
BinaryOperator.BitwiseAnd => _builder.BuildAnd(left, right),
BinaryOperator.BitwiseOr => _builder.BuildOr(left, right),
BinaryOperator.BitwiseXor => _builder.BuildXor(left, right),
BinaryOperator.LeftShift => _builder.BuildShl(left, right),
BinaryOperator.RightShift => _builder.BuildAShr(left, right),
_ => throw new NotSupportedException($"Binary operator {binaryExpressionNode.Operator} not supported for int")
};
}
if (leftType is NubFloatType)
{
return binaryExpressionNode.Operator switch
{
BinaryOperator.Plus => _builder.BuildFAdd(left, right),
BinaryOperator.Minus => _builder.BuildFSub(left, right),
BinaryOperator.Multiply => _builder.BuildFMul(left, right),
BinaryOperator.Divide => _builder.BuildFDiv(left, right),
BinaryOperator.Modulo => _builder.BuildFRem(left, right),
BinaryOperator.Equal => _builder.BuildFCmp(LLVMRealPredicate.LLVMRealOEQ, left, right),
BinaryOperator.NotEqual => _builder.BuildFCmp(LLVMRealPredicate.LLVMRealONE, left, right),
BinaryOperator.LessThan => _builder.BuildFCmp(LLVMRealPredicate.LLVMRealOLT, left, right),
BinaryOperator.LessThanOrEqual => _builder.BuildFCmp(LLVMRealPredicate.LLVMRealOLE, left, right),
BinaryOperator.GreaterThan => _builder.BuildFCmp(LLVMRealPredicate.LLVMRealOGT, left, right),
BinaryOperator.GreaterThanOrEqual => _builder.BuildFCmp(LLVMRealPredicate.LLVMRealOGE, left, right),
_ => throw new NotSupportedException($"Binary operator {binaryExpressionNode.Operator} not supported for float")
};
}
if (leftType is NubBoolType)
{
return binaryExpressionNode.Operator switch
{
BinaryOperator.LogicalAnd => _builder.BuildAnd(left, right),
BinaryOperator.LogicalOr => _builder.BuildOr(left, right),
BinaryOperator.Equal => _builder.BuildICmp(LLVMIntPredicate.LLVMIntEQ, left, right),
BinaryOperator.NotEqual => _builder.BuildICmp(LLVMIntPredicate.LLVMIntNE, left, right),
_ => throw new NotSupportedException($"Binary operator {binaryExpressionNode.Operator} not supported for bool")
};
}
throw new NotSupportedException($"Binary operations for type {leftType} not supported");
}
private LLVMValueRef EmitBoolLiteral(BoolLiteralNode boolLiteralNode)
{
throw new NotImplementedException();
return LLVMValueRef.CreateConstInt(LLVMTypeRef.Int1, boolLiteralNode.Value ? 1ul : 0ul);
}
private LLVMValueRef EmitConstArrayIndexAccess(ConstArrayIndexAccessNode constArrayIndexAccessNode)
{
throw new NotImplementedException();
}
var arrayType = (NubConstArrayType)constArrayIndexAccessNode.Target.Type;
private LLVMValueRef EmitConstArrayInitializer(ConstArrayInitializerNode constArrayInitializerNode)
{
throw new NotImplementedException();
var target = EmitExpression(constArrayIndexAccessNode.Target);
var index = EmitExpression(constArrayIndexAccessNode.Index);
return _builder.BuildGEP2(MapType(arrayType), target, [LLVMValueRef.CreateConstInt(LLVMTypeRef.Int64, 0), index]);
}
private LLVMValueRef EmitConvertFloat(ConvertFloatNode convertFloatNode)
@@ -316,7 +433,7 @@ public class Generator
private LLVMValueRef EmitCStringLiteral(CStringLiteralNode cStringLiteralNode)
{
throw new NotImplementedException();
return _builder.BuildGlobalStringPtr(cStringLiteralNode.Value, "str");
}
private LLVMValueRef EmitDereference(DereferenceNode dereferenceNode)
@@ -326,12 +443,12 @@ public class Generator
private LLVMValueRef EmitFloat32Literal(Float32LiteralNode float32LiteralNode)
{
throw new NotImplementedException();
return LLVMValueRef.CreateConstReal(LLVMTypeRef.Float, float32LiteralNode.Value);
}
private LLVMValueRef EmitFloat64Literal(Float64LiteralNode float64LiteralNode)
{
throw new NotImplementedException();
return LLVMValueRef.CreateConstReal(LLVMTypeRef.Double, float64LiteralNode.Value);
}
private LLVMValueRef EmitFloatToIntBuiltin(FloatToIntBuiltinNode floatToIntBuiltinNode)
@@ -341,17 +458,19 @@ public class Generator
private LLVMValueRef EmitFuncCall(FuncCallNode funcCallNode)
{
throw new NotImplementedException();
var function = EmitExpression(funcCallNode.Expression);
var args = funcCallNode.Parameters.Select(EmitExpression).ToArray();
return _builder.BuildCall2(MapType(funcCallNode.Expression.Type), function, args);
}
private LLVMValueRef EmitFuncIdentifier(FuncIdentifierNode funcIdentifierNode)
{
throw new NotImplementedException();
return _module.GetNamedFunction(funcIdentifierNode.Name);
}
private LLVMValueRef EmitIntLiteral(IntLiteralNode intLiteralNode)
{
throw new NotImplementedException();
return LLVMValueRef.CreateConstInt(MapType(intLiteralNode.Type), (ulong)intLiteralNode.Value, true);
}
private LLVMValueRef EmitAddressOf(AddressOfNode addressOfNode)
@@ -361,12 +480,12 @@ public class Generator
private LLVMValueRef EmitLValueIdentifier(LValueIdentifierNode lValueIdentifierNode)
{
throw new NotImplementedException();
return _namedValues[lValueIdentifierNode.Name];
}
private LLVMValueRef EmitRValueIdentifier(RValueIdentifierNode rValueIdentifierNode)
{
throw new NotImplementedException();
return _builder.BuildLoad2(MapType(rValueIdentifierNode.Type), _namedValues[rValueIdentifierNode.Name], rValueIdentifierNode.Name);
}
private LLVMValueRef EmitSizeBuiltin(SizeBuiltinNode sizeBuiltinNode)
@@ -386,21 +505,43 @@ public class Generator
private LLVMValueRef EmitStructFieldAccess(StructFieldAccessNode structFieldAccessNode)
{
throw new NotImplementedException();
var type = (NubStructType)structFieldAccessNode.Target.Type;
var target = EmitLValue(structFieldAccessNode.Target);
var fieldIndex = type.Fields.FindIndex(x => x.Name == structFieldAccessNode.Field);
return _builder.BuildStructGEP2(MapType(structFieldAccessNode.Target.Type), target, (uint)fieldIndex);
}
private LLVMValueRef EmitStructInitializer(StructInitializerNode structInitializerNode)
{
throw new NotImplementedException();
var type = MapType(structInitializerNode.StructType);
var ptr = _builder.BuildAlloca(type);
foreach (var initializer in structInitializerNode.Initializers)
{
var value = EmitExpression(initializer.Value);
var fieldIndex = structInitializerNode.StructType.Fields.FindIndex(x => x.Name == initializer.Key);
var fieldPtr = _builder.BuildStructGEP2(type, ptr, (uint)fieldIndex);
_builder.BuildStore(value, fieldPtr);
}
return ptr;
}
private LLVMValueRef EmitUIntLiteral(UIntLiteralNode uIntLiteralNode)
{
throw new NotImplementedException();
return LLVMValueRef.CreateConstInt(MapType(uIntLiteralNode.Type), uIntLiteralNode.Value);
}
private LLVMValueRef EmitUnaryExpression(UnaryExpressionNode unaryExpressionNode)
{
throw new NotImplementedException();
var operand = EmitExpression(unaryExpressionNode.Operand);
return unaryExpressionNode.Operator switch
{
UnaryOperator.Negate when unaryExpressionNode.Operand.Type is NubIntType => _builder.BuildNeg(operand),
UnaryOperator.Negate when unaryExpressionNode.Operand.Type is NubFloatType => _builder.BuildFNeg(operand),
UnaryOperator.Invert => _builder.BuildNot(operand),
_ => throw new NotImplementedException($"Unary operator {unaryExpressionNode.Operator} not implemented")
};
}
}