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