Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions LLVMSharp.slnx
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,17 @@
<File Path="packages/libLLVMSharp/libLLVMSharp/NOTICE.txt" />
<File Path="packages/libLLVMSharp/libLLVMSharp/runtime.json" />
</Folder>
<Folder Name="/samples/">
<File Path="samples/KaleidoscopeTutorial/Directory.Build.props" />
<File Path="samples/KaleidoscopeTutorial/README.md" />
<Project Path="samples/KaleidoscopeTutorial/Kaleidoscope.Common/Kaleidoscope.Common.csproj" />
<Project Path="samples/KaleidoscopeTutorial/Chapter3/Chapter3.csproj" />
<Project Path="samples/KaleidoscopeTutorial/Chapter4/Chapter4.csproj" />
<Project Path="samples/KaleidoscopeTutorial/Chapter5/Chapter5.csproj" />
<Project Path="samples/KaleidoscopeTutorial/Chapter6/Chapter6.csproj" />
<Project Path="samples/KaleidoscopeTutorial/Chapter7/Chapter7.csproj" />
<Project Path="samples/KaleidoscopeTutorial/Chapter8/Chapter8.csproj" />
</Folder>
<Folder Name="/scripts/">
<File Path="scripts/build.ps1" />
<File Path="scripts/build.sh" />
Expand Down Expand Up @@ -89,5 +100,6 @@
<File Path="tests/Directory.Build.props" />
<File Path="tests/Directory.Build.targets" />
<Project Path="tests/LLVMSharp.UnitTests/LLVMSharp.UnitTests.csproj" />
<Project Path="tests/LLVMSharp.KaleidoscopeTests/LLVMSharp.KaleidoscopeTests.csproj" />
</Folder>
</Solution>
8 changes: 8 additions & 0 deletions samples/KaleidoscopeTutorial/Chapter3/Chapter3.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\Kaleidoscope.Common\Kaleidoscope.Common.csproj" />
</ItemGroup>
</Project>
153 changes: 153 additions & 0 deletions samples/KaleidoscopeTutorial/Chapter3/CodeGenVisitor.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
// Copyright (c) .NET Foundation and Contributors. All Rights Reserved. Licensed under the MIT License (MIT). See License.md in the repository root for more information.

using Kaleidoscope.AST;
using LLVMSharp.Interop;

namespace Kaleidoscope.Chapter3;

/// <summary>
/// Chapter 3 — "Code generation to LLVM IR". Lowers the core expression language (numbers, variables,
/// the built-in <c>+ - * &lt;</c> operators, calls) and function definitions to LLVM IR. Later chapters
/// inherit this class and override only the nodes they add.
/// </summary>
public class CodeGenVisitor : CodeGenVisitorBase
{
protected override LLVMValueRef CodegenNumber(NumberExprAST node)
{
return LLVMValueRef.CreateConstReal(Module.Context.DoubleType, node.Value);
}

protected override LLVMValueRef CodegenVariable(VariableExprAST node)
{
if (NamedValues.TryGetValue(node.Name, out LLVMValueRef value))
{
return value;
}

throw new InvalidOperationException($"Unknown variable name '{node.Name}'");
}

protected override LLVMValueRef CodegenBinary(BinaryExprAST node)
{
LLVMValueRef left = Codegen(node.Lhs);
LLVMValueRef right = Codegen(node.Rhs);

switch (node.Op)
{
case '+':
{
return Builder.BuildFAdd(left, right, "addtmp");
}

case '-':
{
return Builder.BuildFSub(left, right, "subtmp");
}

case '*':
{
return Builder.BuildFMul(left, right, "multmp");
}

case '<':
{
LLVMValueRef comparison = Builder.BuildFCmp(LLVMRealPredicate.LLVMRealULT, left, right, "cmptmp");

// Convert the i1 result to a double (0.0 or 1.0), Kaleidoscope's only value type.
return Builder.BuildUIToFP(comparison, Module.Context.DoubleType, "booltmp");
}

default:
{
throw new InvalidOperationException($"invalid binary operator '{node.Op}'");
}
}
}

protected override LLVMValueRef CodegenCall(CallExprAST node)
{
LLVMValueRef callee = GetFunction(node.Callee);
if (callee.Handle == IntPtr.Zero)
{
throw new InvalidOperationException($"Unknown function '{node.Callee}' referenced");
}

if (callee.ParamsCount != node.Arguments.Count)
{
throw new InvalidOperationException("Incorrect # arguments passed");
}

var arguments = new LLVMValueRef[node.Arguments.Count];
for (int i = 0; i < arguments.Length; i++)
{
arguments[i] = Codegen(node.Arguments[i]);
}

// Recover the callee's function type from the value itself; BuildCall2 needs it explicitly.
LLVMTypeRef functionType = GetFunctionType(callee);
return Builder.BuildCall2(functionType, callee, arguments, "calltmp");
}

public override LLVMValueRef CodegenPrototype(PrototypeAST node)
{
LLVMTypeRef doubleType = Module.Context.DoubleType;

var parameterTypes = new LLVMTypeRef[node.Arguments.Count];
Array.Fill(parameterTypes, doubleType);

LLVMTypeRef functionType = LLVMTypeRef.CreateFunction(doubleType, parameterTypes);
LLVMValueRef function = Module.AddFunction(node.Name, functionType);

for (int i = 0; i < node.Arguments.Count; i++)
{
function.GetParam((uint)i).Name = node.Arguments[i];
}

return function;
}

public override LLVMValueRef CodegenFunction(FunctionAST node)
{
// Remember the prototype (so recursive references resolve) then get-or-declare the function.
RegisterPrototype(node.Proto);
LLVMValueRef function = GetFunction(node.Proto.Name);

if (function.BasicBlocksCount != 0)
{
throw new InvalidOperationException($"Function '{node.Proto.Name}' cannot be redefined");
}

LLVMBasicBlockRef entry = function.AppendBasicBlock("entry");
Builder.PositionAtEnd(entry);

CreateParameterBindings(function, node.Proto);

try
{
LLVMValueRef body = Codegen(node.Body);
Builder.BuildRet(body);
function.VerifyFunction(LLVMVerifierFailureAction.LLVMPrintMessageAction);
return function;
}
catch
{
// Remove the half-built function so the REPL can keep going after an error.
function.DeleteFunction();
throw;
}
}

/// <summary>
/// Binds the function's parameters into <see cref="CodeGenVisitorBase.NamedValues"/> before the body
/// is generated. Chapter 3 binds the SSA parameter values directly; chapter 7 overrides this to give
/// each parameter a stack slot so it can be reassigned.
/// </summary>
protected virtual void CreateParameterBindings(LLVMValueRef function, PrototypeAST proto)
{
NamedValues.Clear();
for (int i = 0; i < proto.Arguments.Count; i++)
{
NamedValues[proto.Arguments[i]] = function.GetParam((uint)i);
}
}
}
44 changes: 44 additions & 0 deletions samples/KaleidoscopeTutorial/Chapter3/DumpDriver.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
// Copyright (c) .NET Foundation and Contributors. All Rights Reserved. Licensed under the MIT License (MIT). See License.md in the repository root for more information.

using Kaleidoscope.AST;
using LLVMSharp.Interop;

namespace Kaleidoscope.Chapter3;

/// <summary>
/// Chapter 3's driver: it generates IR into one module and prints it. There is no execution yet — the
/// point of this chapter is just to see the generated LLVM IR. Chapter 4 keeps the same code generator
/// but adds a JIT so top-level expressions actually run.
/// </summary>
public sealed class DumpDriver : ReplDriver
{
private readonly CodeGenVisitor _visitor;

public DumpDriver(Lexer lexer, Parser parser, CodeGenVisitor visitor, LLVMModuleRef module)
: base(lexer, parser)
{
_visitor = visitor;
_visitor.SetModule(module);
}

protected override void OnDefinition(FunctionAST function)
{
LLVMValueRef ir = _visitor.CodegenFunction(function);
Console.WriteLine("Read function definition:");
Console.WriteLine(ir);
}

protected override void OnExtern(PrototypeAST prototype)
{
LLVMValueRef ir = _visitor.CodegenExtern(prototype);
Console.WriteLine("Read extern:");
Console.WriteLine(ir);
}

protected override void OnTopLevelExpression(FunctionAST function)
{
LLVMValueRef ir = _visitor.CodegenFunction(function);
Console.WriteLine("Read top-level expression:");
Console.WriteLine(ir);
}
}
37 changes: 0 additions & 37 deletions samples/KaleidoscopeTutorial/Chapter3/Kaleidoscope.sln

This file was deleted.

This file was deleted.

This file was deleted.

17 changes: 0 additions & 17 deletions samples/KaleidoscopeTutorial/Chapter3/Kaleidoscope/AST/ExprAST.cs

This file was deleted.

15 changes: 0 additions & 15 deletions samples/KaleidoscopeTutorial/Chapter3/Kaleidoscope/AST/ExprType.cs

This file was deleted.

Loading
Loading