Skip to main content

Kaleidoscope tutorial with C# using LLVMSharp and llvm 18

· 3 min read

A few years ago I worked on reproducing the Kaleidoscope tutorial using LLVMSharp, a library that exposes C# bindings for LLVM. I updated multiple times the project to support the latest versions of llvm and the LLVMSharp bindings. In the last week I was busy moving to llvm 18 and I encountered a few difficulties.

First, the newest version of LLVMSharp available on nuget is 16.0.0, however the corresponding repo is updated to support version 18.0.0 of llvm. Luckily for me, there is a nighly nuget feed where a release candidate of LLVMSharp supporting version 18.0.0 is available. Please note that at the time of writing the latest llvm version is 19, LLVMSharp is updated inconsistently and it has been since the beginning for what I could see.

Now, once I decided to go with llvm 18 and found the right source for the package, the next big issue was the removal of the PassManagerBuilder.h starting from version 17.0.0 as detailed in the release notes. There is a documentation on how to use the new pass manager here using C++ but LLVMSharp is exposing the C api of llvm. There is a point were C apis are mentioned in the new docs

The C API also supports most of this, see llvm-c/Transforms/PassBuilder.h.

Given that:

  1. I'm not an expert on llvm
  2. I'm not an expert on C nor C++

It wasn't obvious to me how to use the new pass manager. I did quite some research on internet and on github trying to find samples and how-tos, with little luck tbh.

One source that I think is good quality but overall too complex for me was the source code for the C3 language, they are using the C api of llvm and indeed using the new PassBuilder. However while the compiler is written in C using the C apis of llvm, the bit about the pass manager has a C++ wrapper. So I'm out of luck on this.

Finally, I found a working approach in the place were I should have looked first (but didn't!), the llvm project itself. They have unit tests for the new PassManager, with that it was easy to get something working.

The approach that I'm following now with llvm 18 is not exactly the same as the one with llvm 16, because before I had a function pass manager and I was applying the passes on each single function, now I'm applying the passes to the whole module. I don't know what's the status now (at version 19.0.x of llvm) and I don't know if it was already possible to keep the old approach but I wasn't able to do it. For my scopes, it is enough what I have now.

The passes need to be passed as a comma separated string to the LLVMRunPasses function, here the list of the current available passes. The code using llvm 16 was having both analysis passes and transform passes for no other reason that I was mimicking what was done in the original Kaleidoscope tutorial.

The LLVMRunPasses didn't accept the only analysis pass I had basic-aa but accepted all the transforms. This is somehow understandable as the pass manager comes from llvm-c/Transforms/PassBuilder.h. I guess for analysis passes there is another infrastructure.

Now my kaleidoscope repo is updated and functional, still able to run the mandelbrot example.

Trying to implement Lox as Racket language module

· 5 min read

Given my previous attempt of having a basic scaffolding for creating a new racket language, I thought it was worth a shot at implementing Lox from the Crafting interpreters book as a Racket language module.

Racket has a huge ecosystem and extensive documentation, based on my own research and preferences I decided to use a lex/yacc source generator available in Racket itself and documented here https://docs.racket-lang.org/lex-yacc-example/index.html. There are plenty of resources on how to build languages with Racket, both free and paid.

I used only free resources and my feeling is that the amount of information required to approach this project is A LOT, I needed to get familiar with lisp syntax, libraries for parsing, macros, Racket language modules, a different set of tools for coding/debugging.

Another feeling I have is that the documentation, even if it's extensive, it's not providing all the information required to build new languages for Racket or at very least this information is hard to find. I didn't find it, despite trying multiple times.

Fedora, switch audio channels with pipewire and wireplumber 0.5

· One min read

This is an update on this post, on wireplumber v0.5 lua configuration files are not supported anymore. To switch channels on v0.5 you have to create the following file

.config/wireplumber/wireplumber.conf.d/51-change-channels.conf
monitor.alsa.rules = [
{
matches = [
{
node.name = "<name of the node>"
}
]
actions = {
update-props = {
audio.position = "FR,FL"
}
}
}
]

Check the previous post to understand how to retrieve the name of the node, if needed.

Use cilium service mesh on AKS

· 6 min read
warning

On 2025-08-02 I updated the repo corresponding to this post to use updated versions of Kubernetes, Cilium and Gateway API. The post is not updated accordingly. I did follow again the procedure explained here to confirm that everything is still working as expected. Most notable change is that we don't need experimental channel of Gateway API except for one resource, as described in Cilium v1.17.0 docs.

Azure BYOCNI configuration allows the use of cilium as CNI, in addition to that it is possible to configure cilium service mesh.

Cilium service mesh has several functionalities such as ingress controller, gateway api, mtls etc... my objective here is to use k8s gateway api. In order to enable cilium service mesh we have to replace kube-proxy with cilium itself, to do so we need to enable the kube proxy configuration feature on aks, which is currently in preview.

Cilium supports gateway api v1 from version 1.15, which is the one that I'm installing today. In particular I will install gateway api v1 experimental channel. This will allow to configure the underlying infrastructure (an azure load balancer) if needed.

Fedora, switch audio channels with pipewire

· 4 min read
warning

The lua configuration files are valid only for wireplumber v<0.5. Please check here for the configuration required on v=0.5. This post remains valid for what concerns retrieving the node name required in the config file.

I bought a pair Creative Pebble V3 and given my desk setup and the cables of the 2 speakers, I needed to switch left and right audio channels in order to setup correctly the speakers.

Now, I'm running Fedora Workstation and I never had to troubleshoot, manage, or change any audio settings besides adjusting volume when needed. I found out this task is not as easy as it seems, probably for a mixture of lack of documentation and lack of skills on my side.

TreeSitter C# bindings - new languages

· 3 min read

I updated my TreeSitter.Bindings packages to support additional languages. I wanted to check how solid the bindings were and if I could implement a more complex sample with the respect to the json one I started with.

The tree-sitter documentation provides a multilanguage sample which involves three languages:

  • embedded template
  • ruby
  • html

Flux and SOPS on AKS with workload identity

· 8 min read

Setting up sops with flux and workload identity on AKS is not a complex procedure however there is a lack of proper documentation for some steps.

I was working on setting this up on Azure Kubernetes Service and getting stuck at the point where I had to actually decrypt a secret from a sample deployment.

The key point to understand is that the application responsible for decrypting the secrets is the kustomize-controller. We aim then to have a managed identity assigned to the service-account of the kustomize-controller deployed by flux and to enable workload identity on both the service account and the pods. This requires some azure specific labels and annotations to be added to the k8s resources.

I aim to provide a recap on how to deploy all of this with links to the relevant documentation and add the sample yaml needed to assign and use the identity.

Implementing APIs with the visitor pattern

· 4 min read

I want to leverage my visitor pattern source generator to implement a simple minimal api.

I aim to:

  • Have a request and a request handler for my endpoint. I will not use mediatr or any similar library and I will not use any real storage, only some in memory data structure to showcase the visitor pattern approach.
  • The request handler Handle method returns an interface, every subtype represents a different type of result, a success, and one type for each error (provided) emitted by the handled.
  • For each subtype we want to be able to return a possibly different http response.

TreeSitter C# bindings

· 6 min read

In a previous experiment I made I used the LLVMSharp library and I was quite curious on how the bindings are made. In the readme is it stated they are generated using che ClangSharp library, this one auto-generate hitself from the headers of Clang C header.

This functionality is exposed through a dotnet tool: ClangSharpPInvokeGenerator. So I wanted to try and hack my way into parsing the tree-sitter headers and use the generated code to run a very small sample using C#, in particular I was aiming for the one that's in the getting started section of the docs

Visitor pattern source generator

· 5 min read

I am a big fan of the visitor pattern, I think it is a very good approach for adding behaviors to a group of classes without modifying all of them.

For example if we are building a compiler we may have an abstract syntax tree that represents the code that the compiler is compiling. Two different visitors can be, for example:

  • a type checker
  • a code emitter