Repository: compiler-explorer/compiler-explorer
Pull request #7099 (2024-11-14 10:45:23)

Add JDK 22.0.2 and 23.0.1
Archive OpenJDK releases: https://jdk.java.net/archive/
https://jdk.java.net/23/


Patch:
diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md
index ee2c8ee6b..c7ede3ae7 100644
--- a/CONTRIBUTORS.md
+++ b/CONTRIBUTORS.md
@@ -118,7 +118,6 @@ From oldest to newest contributor, we would like to thank:
 - [m8mble](https://github.com/m8mble)
 - [Anders-T](https://github.com/anders-torbjornsen)
 - [Adam Sandberg Eriksson](https://github.com/adamse)
-- [Ofek Shilon](https://github.com/ofekshilon)
 - [Ross Smyth](https://github.com/RossSmyth)
 - [Mike Urbach](https://github.com/mikeurbach)
 - [J. Ryan Stinnett](https://github.com/jryans)
diff --git a/app.ts b/app.ts
index b341934f5..d466b6a17 100755
--- a/app.ts
+++ b/app.ts
@@ -57,12 +57,11 @@ import {startWineInit} from './lib/exec.js';
 import {RemoteExecutionQuery} from './lib/execution/execution-query.js';
 import {initHostSpecialties} from './lib/execution/execution-triple.js';
 import {startExecutionWorkerThread} from './lib/execution/sqs-execution-queue.js';
+import {SourceController} from './lib/handlers/api/source-controller.js';
 import {CompileHandler} from './lib/handlers/compile.js';
 import * as healthCheck from './lib/handlers/health-check.js';
 import {NoScriptHandler} from './lib/handlers/noscript.js';
 import {RouteAPI, ShortLinkMetaData} from './lib/handlers/route-api.js';
-import {loadSiteTemplates} from './lib/handlers/site-templates.js';
-import {SourceHandler} from './lib/handlers/source.js';
 import {languages as allLanguages} from './lib/languages.js';
 import {logger, logToLoki, logToPapertrail, makeLogStream, suppressConsoleLog} from './lib/logger.js';
 import {setupMetricsServer} from './lib/metrics-server.js';
@@ -83,7 +82,7 @@ global.ce_base_directory = new URL('.', import.meta.url);
 
 (nopt as any).invalidHandler = (key: string, val: unknown, types: unknown[]) => {
     logger.error(
-        `Command line argument type error for "--${key}=${val}", 
+        `Command line argument type error for "--${key}=${val}",
         expected ${types.map((t: unknown) => typeof t).join(' | ')}`,
     );
 };
@@ -336,9 +335,13 @@ const httpRoot = urljoin(ceProps('httpRoot', '/'), '/');
 const staticUrl = ceProps<string | undefined>('staticUrl');
 const staticRoot = urljoin(staticUrl || urljoin(httpRoot, 'static'), '/');
 
-function staticHeaders(res: express.Response) {
+/**
+ * Sets appropriate headers for static resources. This is based on the staticMaxAgeSecs property from the
+ * compiler-explorer.properties file.
+ */
+export function addStaticHeaders(res: express.Response) {
     if (staticMaxAgeSecs) {
-        res.setHeader('Cache-Control', 'public, max-age=' + staticMaxAgeSecs + ', must-revalidate');
+        res.setHeader('Cache-Control', `public, max-age=${staticMaxAgeSecs}, must-revalidate`);
     }
 }
 
@@ -551,7 +554,7 @@ async function main() {
     const compileHandler = new CompileHandler(compilationEnvironment, awsProps);
     const storageType = getStorageTypeByKey(storageSolution);
     const storageHandler = new storageType(httpRoot, compilerProps, awsProps);
-    const sourceHandler = new SourceHandler(sources, staticHeaders);
+    const sourceHandler = new SourceController(sources);
     const compilerFinder = new CompilerFinder(compileHandler, compilerProps, awsProps, defArgs, clientOptionsHandler);
 
     logger.info('=======================================');
@@ -616,7 +619,7 @@ async function main() {
         defArgs,
         renderConfig,
         renderGoldenLayout,
-        staticHeaders,
+        staticHeaders: addStaticHeaders,
         contentPolicyHeader,
     };
 
@@ -701,8 +704,6 @@ async function main() {
 
     const sponsorConfig = loadSponsorsFromString(fs.readFileSync(configDir + '/sponsors.yaml', 'utf8'));
 
-    loadSiteTemplates(configDir);
-
     function renderConfig(extra: Record<string, any>, urlOptions?: any) {
         const urlOptionsAllowed = ['readOnly', 'hideEditorToolbars', 'language'];
         const filteredUrlOptions = _.mapObject(_.pick(urlOptions, urlOptionsAllowed), val => utils.toProperty(val));
@@ -739,7 +740,7 @@ async function main() {
         req: express.Request,
         res: express.Response,
     ) {
-        staticHeaders(res);
+        addStaticHeaders(res);
         contentPolicyHeader(res);
 
         const embedded = req.query.embedded === 'true' ? true : false;
@@ -760,7 +761,7 @@ async function main() {
     }
 
     const embeddedHandler = function (req: express.Request, res: express.Response) {
-        staticHeaders(res);
+        addStaticHeaders(res);
         contentPolicyHeader(res);
         res.render(
             'embed',
@@ -805,7 +806,7 @@ async function main() {
         )
         .use(compression())
         .get('/', (req, res) => {
-            staticHeaders(res);
+            addStaticHeaders(res);
             contentPolicyHeader(res);
             res.render(
                 'index',
@@ -822,7 +823,7 @@ async function main() {
         // legacy. not a 301 to prevent any redirect loops between old e links and embed.html
         .get('/embed.html', embeddedHandler)
         .get('/embed-ro', (req, res) => {
-            staticHeaders(res);
+            addStaticHeaders(res);
             contentPolicyHeader(res);
             res.render(
                 'embed',
@@ -837,22 +838,22 @@ async function main() {
             );
         })
         .get('/robots.txt', (req, res) => {
-            staticHeaders(res);
+            addStaticHeaders(res);
             res.end('User-agent: *\nSitemap: https://godbolt.org/sitemap.xml\nDisallow:');
         })
         .get('/sitemap.xml', (req, res) => {
-            staticHeaders(res);
+            addStaticHeaders(res);
             res.set('Content-Type', 'application/xml');
             res.render('sitemap');
         })
         .use(sFavicon(utils.resolvePathFromAppRoot('static/favicons', getFaviconFilename())))
         .get('/client-options.js', (req, res) => {
-            staticHeaders(res);
+            addStaticHeaders(res);
             res.set('Content-Type', 'application/javascript');
             res.end(`window.compilerExplorerOptions = ${clientOptionsHandler.getJSON()};`);
         })
         .use('/bits/:bits(\\w+).html', (req, res) => {
-            staticHeaders(res);
+            addStaticHeaders(res);
             contentPolicyHeader(res);
             res.render(
                 `bits/${sanitize(req.params.bits)}`,
@@ -866,7 +867,8 @@ async function main() {
             );
         })
         .use(bodyParser.json({limit: ceProps('bodyParserLimit', maxUploadSize)}))
-        .use('/source', sourceHandler.handle.bind(sourceHandler))
+        .use('/source/:source/list', sourceHandler.listEntries.bind(sourceHandler))
+        .use('/source/:source/load/:language/:filename', sourceHandler.loadEntry.bind(sourceHandler))
         .get('/g/:id', oldGoogleUrlHandler)
         // Deprecated old route for this -- TODO remove in late 2021
         .post('/shortener', routeApi.apiHandler.shortener.handle.bind(routeApi.apiHandler.shortener));
diff --git a/etc/config/android-java.amazon.properties b/etc/config/android-java.amazon.properties
index c7093a3f9..291557d12 100644
--- a/etc/config/android-java.amazon.properties
+++ b/etc/config/android-java.amazon.properties
@@ -141,7 +141,7 @@ compiler.java-dex2oat-3310.profmanPath=/opt/compiler-explorer/dex2oat-33.10/x86_
 
 defaultCompiler=java-dex2oat-latest
 
-libs=android-api-stubs:r8-keepanno
+libs=android-api-stubs:r8-keepanno:androidx-annotation
 
 libs.android-api-stubs.name=Android API stubs
 libs.android-api-stubs.versions=11662386
@@ -176,4 +176,33 @@ libs.r8-keepanno.versions.8336.path=/opt/compiler-explorer/r8-8.3.36-keepanno/ke
 libs.r8-keepanno.versions.8337.version=8.3.37
 libs.r8-keepanno.versions.8337.path=/opt/compiler-explorer/r8-8.3.37-keepanno/keepanno-annotations.jar
 
-defaultLibs=android-api-stubs.11662386:r8-keepanno.8535
+libs.androidx-annotation.name=androidx.annotation
+libs.androidx-annotation.versions=160:170:171:180:181:182:190:191
+libs.androidx-annotation.url=https://developer.android.com/reference/androidx/annotation/package-summary
+
+libs.androidx-annotation.versions.160.version=1.6.0
+libs.androidx-annotation.versions.160.path=/opt/compiler-explorer/androidx-annotation-1.6.0/annotation-jvm.jar
+
+libs.androidx-annotation.versions.170.version=1.7.0
+libs.androidx-annotation.versions.170.path=/opt/compiler-explorer/androidx-annotation-1.7.0/annotation-jvm.jar
+
+libs.androidx-annotation.versions.171.version=1.7.1
+libs.androidx-annotation.versions.171.path=/opt/compiler-explorer/androidx-annotation-1.7.1/annotation-jvm.jar
+
+libs.androidx-annotation.versions.180.version=1.8.0
+libs.androidx-annotation.versions.180.path=/opt/compiler-explorer/androidx-annotation-1.8.0/annotation-jvm.jar
+
+libs.androidx-annotation.versions.181.version=1.8.1
+libs.androidx-annotation.versions.181.path=/opt/compiler-explorer/androidx-annotation-1.8.1/annotation-jvm.jar
+
+libs.androidx-annotation.versions.182.version=1.8.2
+libs.androidx-annotation.versions.182.path=/opt/compiler-explorer/androidx-annotation-1.8.2/annotation-jvm.jar
+
+libs.androidx-annotation.versions.190.version=1.9.0
+libs.androidx-annotation.versions.190.path=/opt/compiler-explorer/androidx-annotation-1.9.0/annotation-jvm.jar
+
+libs.androidx-annotation.versions.191.version=1.9.1
+libs.androidx-annotation.versions.191.path=/opt/compiler-explorer/androidx-annotation-1.9.1/annotation-jvm.jar
+
+
+defaultLibs=android-api-stubs.11662386:r8-keepanno.8535:androidx-annotation.versions.191
diff --git a/etc/config/android-kotlin.amazon.properties b/etc/config/android-kotlin.amazon.properties
index 762501862..cecccfe5f 100644
--- a/etc/config/android-kotlin.amazon.properties
+++ b/etc/config/android-kotlin.amazon.properties
@@ -142,7 +142,7 @@ compiler.kotlin-dex2oat-3310.profmanPath=/opt/compiler-explorer/dex2oat-33.10/x8
 
 defaultCompiler=kotlin-dex2oat-latest
 
-libs=android-api-stubs:r8-keepanno
+libs=android-api-stubs:r8-keepanno:androidx-annotation
 
 libs.android-api-stubs.name=Android API stubs
 libs.android-api-stubs.versions=11662386
@@ -177,4 +177,33 @@ libs.r8-keepanno.versions.8336.path=/opt/compiler-explorer/r8-8.3.36-keepanno/ke
 libs.r8-keepanno.versions.8337.version=8.3.37
 libs.r8-keepanno.versions.8337.path=/opt/compiler-explorer/r8-8.3.37-keepanno/keepanno-annotations.jar
 
-defaultLibs=android-api-stubs.11662386:r8-keepanno.8535
+libs.androidx-annotation.name=androidx.annotation
+libs.androidx-annotation.versions=160:170:171:180:181:182:190:191
+libs.androidx-annotation.url=https://developer.android.com/reference/androidx/annotation/package-summary
+
+libs.androidx-annotation.versions.160.version=1.6.0
+libs.androidx-annotation.versions.160.path=/opt/compiler-explorer/androidx-annotation-1.6.0/annotation-jvm.jar
+
+libs.androidx-annotation.versions.170.version=1.7.0
+libs.androidx-annotation.versions.170.path=/opt/compiler-explorer/androidx-annotation-1.7.0/annotation-jvm.jar
+
+libs.androidx-annotation.versions.171.version=1.7.1
+libs.androidx-annotation.versions.171.path=/opt/compiler-explorer/androidx-annotation-1.7.1/annotation-jvm.jar
+
+libs.androidx-annotation.versions.180.version=1.8.0
+libs.androidx-annotation.versions.180.path=/opt/compiler-explorer/androidx-annotation-1.8.0/annotation-jvm.jar
+
+libs.androidx-annotation.versions.181.version=1.8.1
+libs.androidx-annotation.versions.181.path=/opt/compiler-explorer/androidx-annotation-1.8.1/annotation-jvm.jar
+
+libs.androidx-annotation.versions.182.version=1.8.2
+libs.androidx-annotation.versions.182.path=/opt/compiler-explorer/androidx-annotation-1.8.2/annotation-jvm.jar
+
+libs.androidx-annotation.versions.190.version=1.9.0
+libs.androidx-annotation.versions.190.path=/opt/compiler-explorer/androidx-annotation-1.9.0/annotation-jvm.jar
+
+libs.androidx-annotation.versions.191.version=1.9.1
+libs.androidx-annotation.versions.191.path=/opt/compiler-explorer/androidx-annotation-1.9.1/annotation-jvm.jar
+
+
+defaultLibs=android-api-stubs.11662386:r8-keepanno.8535:androidx-annotation.versions.191
diff --git a/etc/config/c++.amazon.properties b/etc/config/c++.amazon.properties
index 4d22cdb52..cf2810e60 100644
--- a/etc/config/c++.amazon.properties
+++ b/etc/config/c++.amazon.properties
@@ -3617,7 +3617,7 @@ compiler.gcc6502_1110.notification=This uses AVR-GCC 11.1.0 to compile C++ and u
 #################################
 # NVHPC nvc++
 
-group.nvcxx_x86_cxx.compilers=nvcxx_x86_cxx22_7:nvcxx_x86_cxx22_9:nvcxx_x86_cxx22_11:nvcxx_x86_cxx23_1:nvcxx_x86_cxx23_3:nvcxx_x86_cxx23_5:nvcxx_x86_cxx23_7:nvcxx_x86_cxx23_9:nvcxx_x86_cxx23_11:nvcxx_x86_cxx24_1:nvcxx_x86_cxx24_3:nvcxx_x86_cxx24_5:nvcxx_x86_cxx24_7:nvcxx_x86_cxx24_9
+group.nvcxx_x86_cxx.compilers=nvcxx_x86_cxx22_7:nvcxx_x86_cxx22_9:nvcxx_x86_cxx22_11:nvcxx_x86_cxx23_1:nvcxx_x86_cxx23_3:nvcxx_x86_cxx23_5:nvcxx_x86_cxx23_7:nvcxx_x86_cxx23_9:nvcxx_x86_cxx23_11:nvcxx_x86_cxx24_1:nvcxx_x86_cxx24_3:nvcxx_x86_cxx24_5:nvcxx_x86_cxx24_7:nvcxx_x86_cxx24_9:nvcxx_x86_cxx24_11
 group.nvcxx_x86_cxx.options=
 group.nvcxx_x86_cxx.binaryHideFuncRe=^(__.*|_(init|start|fini)|(de)?register_tm_clones|call_gmon_start|frame_dummy|\.plt.*|_dl_relocate_static_pie)$
 group.nvcxx_x86_cxx.needsMulti=false
@@ -3716,7 +3716,13 @@ compiler.nvcxx_x86_cxx24_9.nvdisasm=/opt/compiler-explorer/hpc_sdk/Linux_x86_64/
 compiler.nvcxx_x86_cxx24_9.exe=/opt/compiler-explorer/hpc_sdk/Linux_x86_64/24.9/compilers/bin/nvc++
 compiler.nvcxx_x86_cxx24_9.semver=24.9
 
-group.nvcxx_arm_cxx.compilers=nvcxx_arm_cxx22_7:nvcxx_arm_cxx22_9:nvcxx_arm_cxx22_11:nvcxx_arm_cxx23_1:nvcxx_arm_cxx23_3:nvcxx_arm_cxx23_5:nvcxx_arm_cxx23_7:nvcxx_arm_cxx23_9:nvcxx_arm_cxx23_11:nvcxx_arm_cxx24_1:nvcxx_arm_cxx24_3:nvcxx_arm_cxx24_5:nvcxx_arm_cxx24_7:nvcxx_arm_cxx24_9
+compiler.nvcxx_x86_cxx24_11.demangler=/opt/compiler-explorer/hpc_sdk/Linux_x86_64/24.11/compilers/bin/nvdecode
+compiler.nvcxx_x86_cxx24_11.cuobjdump=/opt/compiler-explorer/hpc_sdk/Linux_x86_64/24.11/cuda/12.6/bin/cuobjdump
+compiler.nvcxx_x86_cxx24_11.nvdisasm=/opt/compiler-explorer/hpc_sdk/Linux_x86_64/24.11/cuda/12.6/bin/nvdisasm
+compiler.nvcxx_x86_cxx24_11.exe=/opt/compiler-explorer/hpc_sdk/Linux_x86_64/24.11/compilers/bin/nvc++
+compiler.nvcxx_x86_cxx24_11.semver=24.11
+
+group.nvcxx_arm_cxx.compilers=nvcxx_arm_cxx22_7:nvcxx_arm_cxx22_9:nvcxx_arm_cxx22_11:nvcxx_arm_cxx23_1:nvcxx_arm_cxx23_3:nvcxx_arm_cxx23_5:nvcxx_arm_cxx23_7:nvcxx_arm_cxx23_9:nvcxx_arm_cxx23_11:nvcxx_arm_cxx24_1:nvcxx_arm_cxx24_3:nvcxx_arm_cxx24_5:nvcxx_arm_cxx24_7:nvcxx_arm_cxx24_9:nvcxx_arm_cxx24_11
 group.nvcxx_arm_cxx.options=
 group.nvcxx_arm_cxx.supportsBinary=true
 group.nvcxx_arm_cxx.binaryHideFuncRe=^(__.*|_(init|start|fini)|(de)?register_tm_clones|call_gmon_start|frame_dummy|\.plt.*|_dl_relocate_static_pie)$
@@ -3788,6 +3794,10 @@ compiler.nvcxx_arm_cxx24_9.demangler=/opt/compiler-explorer/hpc_sdk/Linux_aarch6
 compiler.nvcxx_arm_cxx24_9.exe=/opt/compiler-explorer/hpc_sdk/Linux_aarch64/24.9/compilers/bin/nvc++
 compiler.nvcxx_arm_cxx24_9.semver=24.9
 
+compiler.nvcxx_arm_cxx24_11.demangler=/opt/compiler-explorer/hpc_sdk/Linux_aarch64/24.11/compilers/bin/nvdecode
+compiler.nvcxx_arm_cxx24_11.exe=/opt/compiler-explorer/hpc_sdk/Linux_aarch64/24.11/compilers/bin/nvc++
+compiler.nvcxx_arm_cxx24_11.semver=24.11
+
 #################################
 # EDG compiler
 group.edg.compilers=&edg-gnu:&edg-default
@@ -5124,7 +5134,7 @@ libs.qt.versions.680.path=/app/qt/include/QtCore
 
 libs.quill.name=Quill
 libs.quill.description=C++ Low Latency Logging Library
-libs.quill.versions=611:700:721:730
+libs.quill.versions=611:700:721:730:750
 libs.quill.url=https://github.com/odygrd/quill
 libs.quill.versions.611.version=6.1.1
 libs.quill.versions.611.path=/opt/compiler-explorer/libs/quill/v6.1.1/quill/include
@@ -5134,6 +5144,8 @@ libs.quill.versions.721.version=7.2.1
 libs.quill.versions.721.path=/opt/compiler-explorer/libs/quill/v7.2.1/include
 libs.quill.versions.730.version=7.3.0
 libs.quill.versions.730.path=/opt/compiler-explorer/libs/quill/v7.3.0/include
+libs.quill.versions.750.version=7.5.0
+libs.quill.versions.750.path=/opt/compiler-explorer/libs/quill/v7.5.0/include
 
 libs.rangesv3.name=range-v3
 libs.rangesv3.versions=trunk:030:035:036:091:0100:0110:0120
diff --git a/etc/config/c.amazon.properties b/etc/config/c.amazon.properties
index f232521be..734817015 100644
--- a/etc/config/c.amazon.properties
+++ b/etc/config/c.amazon.properties
@@ -358,7 +358,7 @@ compiler.cclang_widberg.notification=Experimental Reverse Engineering Compiler;
 #################################
 # NVHPC nvc
 
-group.nvc_x86.compilers=nvc_x86_24_9
+group.nvc_x86.compilers=nvc_x86_24_9:nvc_x86_24_11
 group.nvc_x86.options=
 group.nvc_x86.binaryHideFuncRe=^(__.*|_(init|start|fini)|(de)?register_tm_clones|call_gmon_start|frame_dummy|\.plt.*|_dl_relocate_static_pie)$
 group.nvc_x86.needsMulti=false
@@ -379,6 +379,12 @@ compiler.nvc_x86_24_9.nvdisasm=/opt/compiler-explorer/hpc_sdk/Linux_x86_64/24.9/
 compiler.nvc_x86_24_9.exe=/opt/compiler-explorer/hpc_sdk/Linux_x86_64/24.9/compilers/bin/nvc
 compiler.nvc_x86_24_9.semver=24.9
 
+compiler.nvc_x86_24_11.demangler=/opt/compiler-explorer/hpc_sdk/Linux_x86_64/24.11/compilers/bin/nvdecode
+compiler.nvc_x86_24_11.cuobjdump=/opt/compiler-explorer/hpc_sdk/Linux_x86_64/24.11/cuda/12.6/bin/cuobjdump
+compiler.nvc_x86_24_11.nvdisasm=/opt/compiler-explorer/hpc_sdk/Linux_x86_64/24.11/cuda/12.6/bin/nvdisasm
+compiler.nvc_x86_24_11.exe=/opt/compiler-explorer/hpc_sdk/Linux_x86_64/24.11/compilers/bin/nvc
+compiler.nvc_x86_24_11.semver=24.11
+
 # Clang for Arm
 # Provides 32- and 64-bit menu items for clang-9 and trunk
 group.armcclang32.groupName=Arm 32-bit clang
diff --git a/etc/config/csharp.amazon.properties b/etc/config/csharp.amazon.properties
index 9169c92b4..6d486dbec 100644
--- a/etc/config/csharp.amazon.properties
+++ b/etc/config/csharp.amazon.properties
@@ -1,20 +1,20 @@
-compilers=&dotnetcoreclr:&dotnetcrossgen2:&dotnetmono:&dotnetnativeaot:&dotnetildasm:&dotnetlegacy
+compilers=&dotnetcoreclr:&dotnetcrossgen2:&dotnetmono:&dotnetnativeaot:&dotnetildasm:&dotnetilspy:&dotnetlegacy
 supportsBinary=true
 needsMulti=false
-defaultCompiler=dotnet80csharpcoreclr
+defaultCompiler=dotnet90csharpcoreclr
 executionEnvironmentClass=local-dotnet
 
-group.dotnetcoreclr.compilers=dotnettrunkcsharpcoreclr:dotnet80csharpcoreclr:dotnet70csharpcoreclr
+group.dotnetcoreclr.compilers=dotnettrunkcsharpcoreclr:dotnet90csharpcoreclr:dotnet80csharpcoreclr:dotnet70csharpcoreclr:dotnet60csharpcoreclr
 group.dotnetcoreclr.compilerCategories=coreclr
 group.dotnetcoreclr.compilerType=dotnetcoreclr
 group.dotnetcoreclr.groupName=.NET CoreCLR
 
-group.dotnetcrossgen2.compilers=dotnettrunkcsharpcrossgen2:dotnet80csharpcrossgen2:dotnet70csharpcrossgen2:dotnet60csharpcrossgen2
+group.dotnetcrossgen2.compilers=dotnettrunkcsharpcrossgen2:dotnet90csharpcrossgen2:dotnet80csharpcrossgen2:dotnet70csharpcrossgen2:dotnet60csharpcrossgen2
 group.dotnetcrossgen2.compilerCategories=crossgen2
 group.dotnetcrossgen2.compilerType=dotnetcrossgen2
 group.dotnetcrossgen2.groupName=.NET Crossgen2
 
-group.dotnetmono.compilers=dotnettrunkcsharpmono
+group.dotnetmono.compilers=dotnettrunkcsharpmono:dotnet90csharpmono:dotnet80csharpmono:dotnet70csharpmono:dotnet60csharpmono
 group.dotnetmono.compilerCategories=mono
 group.dotnetmono.compilerType=dotnetmono
 group.dotnetmono.groupName=.NET Mono
@@ -24,10 +24,15 @@ group.dotnetnativeaot.compilerCategories=nativeaot
 group.dotnetnativeaot.compilerType=dotnetnativeaot
 group.dotnetnativeaot.groupName=.NET NativeAOT
 
-group.dotnetildasm.compilers=dotnettrunkcsharpildasm
+group.dotnetildasm.compilers=dotnettrunkcsharpildasm:dotnet90csharpildasm:dotnet80csharpildasm:dotnet70csharpildasm:dotnet60csharpildasm
 group.dotnetildasm.compilerCategories=ildasm
 group.dotnetildasm.compilerType=dotnetildasm
-group.dotnetildasm.groupName=.NET IL Disassembler
+group.dotnetildasm.groupName=.NET ILDasm
+
+group.dotnetilspy.compilers=dotnettrunkcsharpilspy:dotnet90csharpilspy:dotnet80csharpilspy:dotnet70csharpilspy:dotnet60csharpilspy
+group.dotnetilspy.compilerCategories=ilspy
+group.dotnetilspy.compilerType=dotnetilspy
+group.dotnetilspy.groupName=.NET ILSpy
 
 group.dotnetlegacy.compilers=dotnettrunkcsharp:dotnet707csharp:dotnet703csharp:dotnet701csharp:dotnet6018csharp:dotnet6014csharp:dotnet6011csharp
 group.dotnetlegacy.compilerCategories=legacy
@@ -36,20 +41,32 @@ group.dotnetlegacy.groupName=Legacy
 
 # CoreCLR compilers
 
-compiler.dotnet70csharpcoreclr.exe=/opt/compiler-explorer/dotnet-v7.0.19/.dotnet/dotnet
-compiler.dotnet70csharpcoreclr.name=.NET CoreCLR 7.0
-compiler.dotnet70csharpcoreclr.clrDir=/opt/compiler-explorer/dotnet-v7.0.19
+compiler.dotnet60csharpcoreclr.exe=/opt/compiler-explorer/dotnet-v6.0.36/.dotnet/dotnet
+compiler.dotnet60csharpcoreclr.name=.NET 6.0 CoreCLR
+compiler.dotnet60csharpcoreclr.clrDir=/opt/compiler-explorer/dotnet-v6.0.36
+compiler.dotnet60csharpcoreclr.buildConfig=Release
+compiler.dotnet60csharpcoreclr.langVersion=latest
+
+compiler.dotnet70csharpcoreclr.exe=/opt/compiler-explorer/dotnet-v7.0.20/.dotnet/dotnet
+compiler.dotnet70csharpcoreclr.name=.NET 7.0 CoreCLR
+compiler.dotnet70csharpcoreclr.clrDir=/opt/compiler-explorer/dotnet-v7.0.20
 compiler.dotnet70csharpcoreclr.buildConfig=Release
 compiler.dotnet70csharpcoreclr.langVersion=latest
 
-compiler.dotnet80csharpcoreclr.exe=/opt/compiler-explorer/dotnet-v8.0.5/.dotnet/dotnet
-compiler.dotnet80csharpcoreclr.name=.NET CoreCLR 8.0
-compiler.dotnet80csharpcoreclr.clrDir=/opt/compiler-explorer/dotnet-v8.0.5
+compiler.dotnet80csharpcoreclr.exe=/opt/compiler-explorer/dotnet-v8.0.11/.dotnet/dotnet
+compiler.dotnet80csharpcoreclr.name=.NET 8.0 CoreCLR
+compiler.dotnet80csharpcoreclr.clrDir=/opt/compiler-explorer/dotnet-v8.0.11
 compiler.dotnet80csharpcoreclr.buildConfig=Release
 compiler.dotnet80csharpcoreclr.langVersion=latest
 
+compiler.dotnet90csharpcoreclr.exe=/opt/compiler-explorer/dotnet-v9.0.0/.dotnet/dotnet
+compiler.dotnet90csharpcoreclr.name=.NET 9.0 CoreCLR
+compiler.dotnet90csharpcoreclr.clrDir=/opt/compiler-explorer/dotnet-v9.0.0
+compiler.dotnet90csharpcoreclr.buildConfig=Release
+compiler.dotnet90csharpcoreclr.langVersion=latest
+
 compiler.dotnettrunkcsharpcoreclr.exe=/opt/compiler-explorer/dotnet-trunk/.dotnet/dotnet
-compiler.dotnettrunkcsharpcoreclr.name=.NET CoreCLR (main)
+compiler.dotnettrunkcsharpcoreclr.name=.NET (main) CoreCLR
 compiler.dotnettrunkcsharpcoreclr.clrDir=/opt/compiler-explorer/dotnet-trunk
 compiler.dotnettrunkcsharpcoreclr.buildConfig=Release
 compiler.dotnettrunkcsharpcoreclr.langVersion=preview
@@ -57,26 +74,32 @@ compiler.dotnettrunkcsharpcoreclr.isNightly=true
 
 # Crossgen2 compilers
 
-compiler.dotnet60csharpcrossgen2.exe=/opt/compiler-explorer/dotnet-v6.0.30/.dotnet/dotnet
-compiler.dotnet60csharpcrossgen2.name=.NET Crossgen2 6.0
-compiler.dotnet60csharpcrossgen2.clrDir=/opt/compiler-explorer/dotnet-v6.0.30
+compiler.dotnet60csharpcrossgen2.exe=/opt/compiler-explorer/dotnet-v6.0.36/.dotnet/dotnet
+compiler.dotnet60csharpcrossgen2.name=.NET 6.0 Crossgen2
+compiler.dotnet60csharpcrossgen2.clrDir=/opt/compiler-explorer/dotnet-v6.0.36
 compiler.dotnet60csharpcrossgen2.buildConfig=Release
 compiler.dotnet60csharpcrossgen2.langVersion=latest
 
-compiler.dotnet70csharpcrossgen2.exe=/opt/compiler-explorer/dotnet-v7.0.19/.dotnet/dotnet
-compiler.dotnet70csharpcrossgen2.name=.NET Crossgen2 7.0
-compiler.dotnet70csharpcrossgen2.clrDir=/opt/compiler-explorer/dotnet-v7.0.19
+compiler.dotnet70csharpcrossgen2.exe=/opt/compiler-explorer/dotnet-v7.0.20/.dotnet/dotnet
+compiler.dotnet70csharpcrossgen2.name=.NET 7.0 Crossgen2
+compiler.dotnet70csharpcrossgen2.clrDir=/opt/compiler-explorer/dotnet-v7.0.20
 compiler.dotnet70csharpcrossgen2.buildConfig=Release
 compiler.dotnet70csharpcrossgen2.langVersion=latest
 
-compiler.dotnet80csharpcrossgen2.exe=/opt/compiler-explorer/dotnet-v8.0.5/.dotnet/dotnet
-compiler.dotnet80csharpcrossgen2.name=.NET Crossgen2 8.0
-compiler.dotnet80csharpcrossgen2.clrDir=/opt/compiler-explorer/dotnet-v8.0.5
+compiler.dotnet80csharpcrossgen2.exe=/opt/compiler-explorer/dotnet-v8.0.11/.dotnet/dotnet
+compiler.dotnet80csharpcrossgen2.name=.NET 8.0 Crossgen2
+compiler.dotnet80csharpcrossgen2.clrDir=/opt/compiler-explorer/dotnet-v8.0.11
 compiler.dotnet80csharpcrossgen2.buildConfig=Release
 compiler.dotnet80csharpcrossgen2.langVersion=latest
 
+compiler.dotnet90csharpcrossgen2.exe=/opt/compiler-explorer/dotnet-v9.0.0/.dotnet/dotnet
+compiler.dotnet90csharpcrossgen2.name=.NET 9.0 Crossgen2
+compiler.dotnet90csharpcrossgen2.clrDir=/opt/compiler-explorer/dotnet-v9.0.0
+compiler.dotnet90csharpcrossgen2.buildConfig=Release
+compiler.dotnet90csharpcrossgen2.langVersion=latest
+
 compiler.dotnettrunkcsharpcrossgen2.exe=/opt/compiler-explorer/dotnet-trunk/.dotnet/dotnet
-compiler.dotnettrunkcsharpcrossgen2.name=.NET Crossgen2 (main)
+compiler.dotnettrunkcsharpcrossgen2.name=.NET (main) Crossgen2
 compiler.dotnettrunkcsharpcrossgen2.clrDir=/opt/compiler-explorer/dotnet-trunk
 compiler.dotnettrunkcsharpcrossgen2.buildConfig=Release
 compiler.dotnettrunkcsharpcrossgen2.langVersion=preview
@@ -84,8 +107,32 @@ compiler.dotnettrunkcsharpcrossgen2.isNightly=true
 
 # Mono compilers
 
+compiler.dotnet60csharpmono.exe=/opt/compiler-explorer/dotnet-v6.0.36/.dotnet/dotnet
+compiler.dotnet60csharpmono.name=.NET 6.0 Mono
+compiler.dotnet60csharpmono.clrDir=/opt/compiler-explorer/dotnet-v6.0.36
+compiler.dotnet60csharpmono.buildConfig=Release
+compiler.dotnet60csharpmono.langVersion=latest
+
+compiler.dotnet70csharpmono.exe=/opt/compiler-explorer/dotnet-v7.0.20/.dotnet/dotnet
+compiler.dotnet70csharpmono.name=.NET 7.0 Mono
+compiler.dotnet70csharpmono.clrDir=/opt/compiler-explorer/dotnet-v7.0.20
+compiler.dotnet70csharpmono.buildConfig=Release
+compiler.dotnet70csharpmono.langVersion=latest
+
+compiler.dotnet80csharpmono.exe=/opt/compiler-explorer/dotnet-v8.0.11/.dotnet/dotnet
+compiler.dotnet80csharpmono.name=.NET 8.0 Mono
+compiler.dotnet80csharpmono.clrDir=/opt/compiler-explorer/dotnet-v8.0.11
+compiler.dotnet80csharpmono.buildConfig=Release
+compiler.dotnet80csharpmono.langVersion=latest
+
+compiler.dotnet90csharpmono.exe=/opt/compiler-explorer/dotnet-v9.0.0/.dotnet/dotnet
+compiler.dotnet90csharpmono.name=.NET 9.0 Mono
+compiler.dotnet90csharpmono.clrDir=/opt/compiler-explorer/dotnet-v9.0.0
+compiler.dotnet90csharpmono.buildConfig=Release
+compiler.dotnet90csharpmono.langVersion=latest
+
 compiler.dotnettrunkcsharpmono.exe=/opt/compiler-explorer/dotnet-trunk/.dotnet/dotnet
-compiler.dotnettrunkcsharpmono.name=.NET Mono (main)
+compiler.dotnettrunkcsharpmono.name=.NET (main) Mono
 compiler.dotnettrunkcsharpmono.clrDir=/opt/compiler-explorer/dotnet-trunk
 compiler.dotnettrunkcsharpmono.buildConfig=Release
 compiler.dotnettrunkcsharpmono.langVersion=preview
@@ -94,21 +141,78 @@ compiler.dotnettrunkcsharpmono.isNightly=true
 # NativeAOT compilers
 
 compiler.dotnettrunkcsharpnativeaot.exe=/opt/compiler-explorer/dotnet-trunk/.dotnet/dotnet
-compiler.dotnettrunkcsharpnativeaot.name=.NET NativeAOT (main)
+compiler.dotnettrunkcsharpnativeaot.name=.NET (main) NativeAOT
 compiler.dotnettrunkcsharpnativeaot.clrDir=/opt/compiler-explorer/dotnet-trunk
 compiler.dotnettrunkcsharpnativeaot.buildConfig=Release
 compiler.dotnettrunkcsharpnativeaot.langVersion=preview
 compiler.dotnettrunkcsharpnativeaot.isNightly=true
 
-# IL disassembler compilers
+# ILDasm compilers
+
+compiler.dotnet60csharpildasm.exe=/opt/compiler-explorer/dotnet-v6.0.36/.dotnet/dotnet
+compiler.dotnet60csharpildasm.name=.NET 6.0 ILDasm
+compiler.dotnet60csharpildasm.clrDir=/opt/compiler-explorer/dotnet-v6.0.36
+compiler.dotnet60csharpildasm.buildConfig=Release
+compiler.dotnet60csharpildasm.langVersion=latest
+
+compiler.dotnet70csharpildasm.exe=/opt/compiler-explorer/dotnet-v7.0.20/.dotnet/dotnet
+compiler.dotnet70csharpildasm.name=.NET 7.0 ILDasm
+compiler.dotnet70csharpildasm.clrDir=/opt/compiler-explorer/dotnet-v7.0.20
+compiler.dotnet70csharpildasm.buildConfig=Release
+compiler.dotnet70csharpildasm.langVersion=latest
+
+compiler.dotnet80csharpildasm.exe=/opt/compiler-explorer/dotnet-v8.0.11/.dotnet/dotnet
+compiler.dotnet80csharpildasm.name=.NET 8.0 ILDasm
+compiler.dotnet80csharpildasm.clrDir=/opt/compiler-explorer/dotnet-v8.0.11
+compiler.dotnet80csharpildasm.buildConfig=Release
+compiler.dotnet80csharpildasm.langVersion=latest
+
+compiler.dotnet90csharpildasm.exe=/opt/compiler-explorer/dotnet-v9.0.0/.dotnet/dotnet
+compiler.dotnet90csharpildasm.name=.NET 9.0 ILDasm
+compiler.dotnet90csharpildasm.clrDir=/opt/compiler-explorer/dotnet-v9.0.0
+compiler.dotnet90csharpildasm.buildConfig=Release
+compiler.dotnet90csharpildasm.langVersion=latest
 
 compiler.dotnettrunkcsharpildasm.exe=/opt/compiler-explorer/dotnet-trunk/.dotnet/dotnet
-compiler.dotnettrunkcsharpildasm.name=.NET IL Disassembler (main)
+compiler.dotnettrunkcsharpildasm.name=.NET (main) ILDasm
 compiler.dotnettrunkcsharpildasm.clrDir=/opt/compiler-explorer/dotnet-trunk
 compiler.dotnettrunkcsharpildasm.buildConfig=Release
 compiler.dotnettrunkcsharpildasm.langVersion=preview
 compiler.dotnettrunkcsharpildasm.isNightly=true
 
+# ILSpy compilers
+
+compiler.dotnet60csharpilspy.exe=/opt/compiler-explorer/dotnet-v6.0.36/.dotnet/dotnet
+compiler.dotnet60csharpilspy.name=.NET 6.0 ILSpy
+compiler.dotnet60csharpilspy.clrDir=/opt/compiler-explorer/dotnet-v6.0.36
+compiler.dotnet60csharpilspy.buildConfig=Release
+compiler.dotnet60csharpilspy.langVersion=latest
+
+compiler.dotnet70csharpilspy.exe=/opt/compiler-explorer/dotnet-v7.0.20/.dotnet/dotnet
+compiler.dotnet70csharpilspy.name=.NET 7.0 ILSpy
+compiler.dotnet70csharpilspy.clrDir=/opt/compiler-explorer/dotnet-v7.0.20
+compiler.dotnet70csharpilspy.buildConfig=Release
+compiler.dotnet70csharpilspy.langVersion=latest
+
+compiler.dotnet80csharpilspy.exe=/opt/compiler-explorer/dotnet-v8.0.11/.dotnet/dotnet
+compiler.dotnet80csharpilspy.name=.NET 8.0 ILSpy
+compiler.dotnet80csharpilspy.clrDir=/opt/compiler-explorer/dotnet-v8.0.11
+compiler.dotnet80csharpilspy.buildConfig=Release
+compiler.dotnet80csharpilspy.langVersion=latest
+
+compiler.dotnet90csharpilspy.exe=/opt/compiler-explorer/dotnet-v9.0.0/.dotnet/dotnet
+compiler.dotnet90csharpilspy.name=.NET 9.0 ILSpy
+compiler.dotnet90csharpilspy.clrDir=/opt/compiler-explorer/dotnet-v9.0.0
+compiler.dotnet90csharpilspy.buildConfig=Release
+compiler.dotnet90csharpilspy.langVersion=latest
+
+compiler.dotnettrunkcsharpilspy.exe=/opt/compiler-explorer/dotnet-trunk/.dotnet/dotnet
+compiler.dotnettrunkcsharpilspy.name=.NET (main) ILSpy
+compiler.dotnettrunkcsharpilspy.clrDir=/opt/compiler-explorer/dotnet-trunk
+compiler.dotnettrunkcsharpilspy.buildConfig=Release
+compiler.dotnettrunkcsharpilspy.langVersion=preview
+compiler.dotnettrunkcsharpilspy.isNightly=true
+
 # Legacy compilers (for backwards compatibility, don't add new compilers here)
 
 compiler.dotnet6011csharp.exe=/opt/compiler-explorer/dotnet-v6.0.11/.dotnet/dotnet
diff --git a/etc/config/csharp.defaults.properties b/etc/config/csharp.defaults.properties
index 9169c92b4..6d486dbec 100644
--- a/etc/config/csharp.defaults.properties
+++ b/etc/config/csharp.defaults.properties
@@ -1,20 +1,20 @@
-compilers=&dotnetcoreclr:&dotnetcrossgen2:&dotnetmono:&dotnetnativeaot:&dotnetildasm:&dotnetlegacy
+compilers=&dotnetcoreclr:&dotnetcrossgen2:&dotnetmono:&dotnetnativeaot:&dotnetildasm:&dotnetilspy:&dotnetlegacy
 supportsBinary=true
 needsMulti=false
-defaultCompiler=dotnet80csharpcoreclr
+defaultCompiler=dotnet90csharpcoreclr
 executionEnvironmentClass=local-dotnet
 
-group.dotnetcoreclr.compilers=dotnettrunkcsharpcoreclr:dotnet80csharpcoreclr:dotnet70csharpcoreclr
+group.dotnetcoreclr.compilers=dotnettrunkcsharpcoreclr:dotnet90csharpcoreclr:dotnet80csharpcoreclr:dotnet70csharpcoreclr:dotnet60csharpcoreclr
 group.dotnetcoreclr.compilerCategories=coreclr
 group.dotnetcoreclr.compilerType=dotnetcoreclr
 group.dotnetcoreclr.groupName=.NET CoreCLR
 
-group.dotnetcrossgen2.compilers=dotnettrunkcsharpcrossgen2:dotnet80csharpcrossgen2:dotnet70csharpcrossgen2:dotnet60csharpcrossgen2
+group.dotnetcrossgen2.compilers=dotnettrunkcsharpcrossgen2:dotnet90csharpcrossgen2:dotnet80csharpcrossgen2:dotnet70csharpcrossgen2:dotnet60csharpcrossgen2
 group.dotnetcrossgen2.compilerCategories=crossgen2
 group.dotnetcrossgen2.compilerType=dotnetcrossgen2
 group.dotnetcrossgen2.groupName=.NET Crossgen2
 
-group.dotnetmono.compilers=dotnettrunkcsharpmono
+group.dotnetmono.compilers=dotnettrunkcsharpmono:dotnet90csharpmono:dotnet80csharpmono:dotnet70csharpmono:dotnet60csharpmono
 group.dotnetmono.compilerCategories=mono
 group.dotnetmono.compilerType=dotnetmono
 group.dotnetmono.groupName=.NET Mono
@@ -24,10 +24,15 @@ group.dotnetnativeaot.compilerCategories=nativeaot
 group.dotnetnativeaot.compilerType=dotnetnativeaot
 group.dotnetnativeaot.groupName=.NET NativeAOT
 
-group.dotnetildasm.compilers=dotnettrunkcsharpildasm
+group.dotnetildasm.compilers=dotnettrunkcsharpildasm:dotnet90csharpildasm:dotnet80csharpildasm:dotnet70csharpildasm:dotnet60csharpildasm
 group.dotnetildasm.compilerCategories=ildasm
 group.dotnetildasm.compilerType=dotnetildasm
-group.dotnetildasm.groupName=.NET IL Disassembler
+group.dotnetildasm.groupName=.NET ILDasm
+
+group.dotnetilspy.compilers=dotnettrunkcsharpilspy:dotnet90csharpilspy:dotnet80csharpilspy:dotnet70csharpilspy:dotnet60csharpilspy
+group.dotnetilspy.compilerCategories=ilspy
+group.dotnetilspy.compilerType=dotnetilspy
+group.dotnetilspy.groupName=.NET ILSpy
 
 group.dotnetlegacy.compilers=dotnettrunkcsharp:dotnet707csharp:dotnet703csharp:dotnet701csharp:dotnet6018csharp:dotnet6014csharp:dotnet6011csharp
 group.dotnetlegacy.compilerCategories=legacy
@@ -36,20 +41,32 @@ group.dotnetlegacy.groupName=Legacy
 
 # CoreCLR compilers
 
-compiler.dotnet70csharpcoreclr.exe=/opt/compiler-explorer/dotnet-v7.0.19/.dotnet/dotnet
-compiler.dotnet70csharpcoreclr.name=.NET CoreCLR 7.0
-compiler.dotnet70csharpcoreclr.clrDir=/opt/compiler-explorer/dotnet-v7.0.19
+compiler.dotnet60csharpcoreclr.exe=/opt/compiler-explorer/dotnet-v6.0.36/.dotnet/dotnet
+compiler.dotnet60csharpcoreclr.name=.NET 6.0 CoreCLR
+compiler.dotnet60csharpcoreclr.clrDir=/opt/compiler-explorer/dotnet-v6.0.36
+compiler.dotnet60csharpcoreclr.buildConfig=Release
+compiler.dotnet60csharpcoreclr.langVersion=latest
+
+compiler.dotnet70csharpcoreclr.exe=/opt/compiler-explorer/dotnet-v7.0.20/.dotnet/dotnet
+compiler.dotnet70csharpcoreclr.name=.NET 7.0 CoreCLR
+compiler.dotnet70csharpcoreclr.clrDir=/opt/compiler-explorer/dotnet-v7.0.20
 compiler.dotnet70csharpcoreclr.buildConfig=Release
 compiler.dotnet70csharpcoreclr.langVersion=latest
 
-compiler.dotnet80csharpcoreclr.exe=/opt/compiler-explorer/dotnet-v8.0.5/.dotnet/dotnet
-compiler.dotnet80csharpcoreclr.name=.NET CoreCLR 8.0
-compiler.dotnet80csharpcoreclr.clrDir=/opt/compiler-explorer/dotnet-v8.0.5
+compiler.dotnet80csharpcoreclr.exe=/opt/compiler-explorer/dotnet-v8.0.11/.dotnet/dotnet
+compiler.dotnet80csharpcoreclr.name=.NET 8.0 CoreCLR
+compiler.dotnet80csharpcoreclr.clrDir=/opt/compiler-explorer/dotnet-v8.0.11
 compiler.dotnet80csharpcoreclr.buildConfig=Release
 compiler.dotnet80csharpcoreclr.langVersion=latest
 
+compiler.dotnet90csharpcoreclr.exe=/opt/compiler-explorer/dotnet-v9.0.0/.dotnet/dotnet
+compiler.dotnet90csharpcoreclr.name=.NET 9.0 CoreCLR
+compiler.dotnet90csharpcoreclr.clrDir=/opt/compiler-explorer/dotnet-v9.0.0
+compiler.dotnet90csharpcoreclr.buildConfig=Release
+compiler.dotnet90csharpcoreclr.langVersion=latest
+
 compiler.dotnettrunkcsharpcoreclr.exe=/opt/compiler-explorer/dotnet-trunk/.dotnet/dotnet
-compiler.dotnettrunkcsharpcoreclr.name=.NET CoreCLR (main)
+compiler.dotnettrunkcsharpcoreclr.name=.NET (main) CoreCLR
 compiler.dotnettrunkcsharpcoreclr.clrDir=/opt/compiler-explorer/dotnet-trunk
 compiler.dotnettrunkcsharpcoreclr.buildConfig=Release
 compiler.dotnettrunkcsharpcoreclr.langVersion=preview
@@ -57,26 +74,32 @@ compiler.dotnettrunkcsharpcoreclr.isNightly=true
 
 # Crossgen2 compilers
 
-compiler.dotnet60csharpcrossgen2.exe=/opt/compiler-explorer/dotnet-v6.0.30/.dotnet/dotnet
-compiler.dotnet60csharpcrossgen2.name=.NET Crossgen2 6.0
-compiler.dotnet60csharpcrossgen2.clrDir=/opt/compiler-explorer/dotnet-v6.0.30
+compiler.dotnet60csharpcrossgen2.exe=/opt/compiler-explorer/dotnet-v6.0.36/.dotnet/dotnet
+compiler.dotnet60csharpcrossgen2.name=.NET 6.0 Crossgen2
+compiler.dotnet60csharpcrossgen2.clrDir=/opt/compiler-explorer/dotnet-v6.0.36
 compiler.dotnet60csharpcrossgen2.buildConfig=Release
 compiler.dotnet60csharpcrossgen2.langVersion=latest
 
-compiler.dotnet70csharpcrossgen2.exe=/opt/compiler-explorer/dotnet-v7.0.19/.dotnet/dotnet
-compiler.dotnet70csharpcrossgen2.name=.NET Crossgen2 7.0
-compiler.dotnet70csharpcrossgen2.clrDir=/opt/compiler-explorer/dotnet-v7.0.19
+compiler.dotnet70csharpcrossgen2.exe=/opt/compiler-explorer/dotnet-v7.0.20/.dotnet/dotnet
+compiler.dotnet70csharpcrossgen2.name=.NET 7.0 Crossgen2
+compiler.dotnet70csharpcrossgen2.clrDir=/opt/compiler-explorer/dotnet-v7.0.20
 compiler.dotnet70csharpcrossgen2.buildConfig=Release
 compiler.dotnet70csharpcrossgen2.langVersion=latest
 
-compiler.dotnet80csharpcrossgen2.exe=/opt/compiler-explorer/dotnet-v8.0.5/.dotnet/dotnet
-compiler.dotnet80csharpcrossgen2.name=.NET Crossgen2 8.0
-compiler.dotnet80csharpcrossgen2.clrDir=/opt/compiler-explorer/dotnet-v8.0.5
+compiler.dotnet80csharpcrossgen2.exe=/opt/compiler-explorer/dotnet-v8.0.11/.dotnet/dotnet
+compiler.dotnet80csharpcrossgen2.name=.NET 8.0 Crossgen2
+compiler.dotnet80csharpcrossgen2.clrDir=/opt/compiler-explorer/dotnet-v8.0.11
 compiler.dotnet80csharpcrossgen2.buildConfig=Release
 compiler.dotnet80csharpcrossgen2.langVersion=latest
 
+compiler.dotnet90csharpcrossgen2.exe=/opt/compiler-explorer/dotnet-v9.0.0/.dotnet/dotnet
+compiler.dotnet90csharpcrossgen2.name=.NET 9.0 Crossgen2
+compiler.dotnet90csharpcrossgen2.clrDir=/opt/compiler-explorer/dotnet-v9.0.0
+compiler.dotnet90csharpcrossgen2.buildConfig=Release
+compiler.dotnet90csharpcrossgen2.langVersion=latest
+
 compiler.dotnettrunkcsharpcrossgen2.exe=/opt/compiler-explorer/dotnet-trunk/.dotnet/dotnet
-compiler.dotnettrunkcsharpcrossgen2.name=.NET Crossgen2 (main)
+compiler.dotnettrunkcsharpcrossgen2.name=.NET (main) Crossgen2
 compiler.dotnettrunkcsharpcrossgen2.clrDir=/opt/compiler-explorer/dotnet-trunk
 compiler.dotnettrunkcsharpcrossgen2.buildConfig=Release
 compiler.dotnettrunkcsharpcrossgen2.langVersion=preview
@@ -84,8 +107,32 @@ compiler.dotnettrunkcsharpcrossgen2.isNightly=true
 
 # Mono compilers
 
+compiler.dotnet60csharpmono.exe=/opt/compiler-explorer/dotnet-v6.0.36/.dotnet/dotnet
+compiler.dotnet60csharpmono.name=.NET 6.0 Mono
+compiler.dotnet60csharpmono.clrDir=/opt/compiler-explorer/dotnet-v6.0.36
+compiler.dotnet60csharpmono.buildConfig=Release
+compiler.dotnet60csharpmono.langVersion=latest
+
+compiler.dotnet70csharpmono.exe=/opt/compiler-explorer/dotnet-v7.0.20/.dotnet/dotnet
+compiler.dotnet70csharpmono.name=.NET 7.0 Mono
+compiler.dotnet70csharpmono.clrDir=/opt/compiler-explorer/dotnet-v7.0.20
+compiler.dotnet70csharpmono.buildConfig=Release
+compiler.dotnet70csharpmono.langVersion=latest
+
+compiler.dotnet80csharpmono.exe=/opt/compiler-explorer/dotnet-v8.0.11/.dotnet/dotnet
+compiler.dotnet80csharpmono.name=.NET 8.0 Mono
+compiler.dotnet80csharpmono.clrDir=/opt/compiler-explorer/dotnet-v8.0.11
+compiler.dotnet80csharpmono.buildConfig=Release
+compiler.dotnet80csharpmono.langVersion=latest
+
+compiler.dotnet90csharpmono.exe=/opt/compiler-explorer/dotnet-v9.0.0/.dotnet/dotnet
+compiler.dotnet90csharpmono.name=.NET 9.0 Mono
+compiler.dotnet90csharpmono.clrDir=/opt/compiler-explorer/dotnet-v9.0.0
+compiler.dotnet90csharpmono.buildConfig=Release
+compiler.dotnet90csharpmono.langVersion=latest
+
 compiler.dotnettrunkcsharpmono.exe=/opt/compiler-explorer/dotnet-trunk/.dotnet/dotnet
-compiler.dotnettrunkcsharpmono.name=.NET Mono (main)
+compiler.dotnettrunkcsharpmono.name=.NET (main) Mono
 compiler.dotnettrunkcsharpmono.clrDir=/opt/compiler-explorer/dotnet-trunk
 compiler.dotnettrunkcsharpmono.buildConfig=Release
 compiler.dotnettrunkcsharpmono.langVersion=preview
@@ -94,21 +141,78 @@ compiler.dotnettrunkcsharpmono.isNightly=true
 # NativeAOT compilers
 
 compiler.dotnettrunkcsharpnativeaot.exe=/opt/compiler-explorer/dotnet-trunk/.dotnet/dotnet
-compiler.dotnettrunkcsharpnativeaot.name=.NET NativeAOT (main)
+compiler.dotnettrunkcsharpnativeaot.name=.NET (main) NativeAOT
 compiler.dotnettrunkcsharpnativeaot.clrDir=/opt/compiler-explorer/dotnet-trunk
 compiler.dotnettrunkcsharpnativeaot.buildConfig=Release
 compiler.dotnettrunkcsharpnativeaot.langVersion=preview
 compiler.dotnettrunkcsharpnativeaot.isNightly=true
 
-# IL disassembler compilers
+# ILDasm compilers
+
+compiler.dotnet60csharpildasm.exe=/opt/compiler-explorer/dotnet-v6.0.36/.dotnet/dotnet
+compiler.dotnet60csharpildasm.name=.NET 6.0 ILDasm
+compiler.dotnet60csharpildasm.clrDir=/opt/compiler-explorer/dotnet-v6.0.36
+compiler.dotnet60csharpildasm.buildConfig=Release
+compiler.dotnet60csharpildasm.langVersion=latest
+
+compiler.dotnet70csharpildasm.exe=/opt/compiler-explorer/dotnet-v7.0.20/.dotnet/dotnet
+compiler.dotnet70csharpildasm.name=.NET 7.0 ILDasm
+compiler.dotnet70csharpildasm.clrDir=/opt/compiler-explorer/dotnet-v7.0.20
+compiler.dotnet70csharpildasm.buildConfig=Release
+compiler.dotnet70csharpildasm.langVersion=latest
+
+compiler.dotnet80csharpildasm.exe=/opt/compiler-explorer/dotnet-v8.0.11/.dotnet/dotnet
+compiler.dotnet80csharpildasm.name=.NET 8.0 ILDasm
+compiler.dotnet80csharpildasm.clrDir=/opt/compiler-explorer/dotnet-v8.0.11
+compiler.dotnet80csharpildasm.buildConfig=Release
+compiler.dotnet80csharpildasm.langVersion=latest
+
+compiler.dotnet90csharpildasm.exe=/opt/compiler-explorer/dotnet-v9.0.0/.dotnet/dotnet
+compiler.dotnet90csharpildasm.name=.NET 9.0 ILDasm
+compiler.dotnet90csharpildasm.clrDir=/opt/compiler-explorer/dotnet-v9.0.0
+compiler.dotnet90csharpildasm.buildConfig=Release
+compiler.dotnet90csharpildasm.langVersion=latest
 
 compiler.dotnettrunkcsharpildasm.exe=/opt/compiler-explorer/dotnet-trunk/.dotnet/dotnet
-compiler.dotnettrunkcsharpildasm.name=.NET IL Disassembler (main)
+compiler.dotnettrunkcsharpildasm.name=.NET (main) ILDasm
 compiler.dotnettrunkcsharpildasm.clrDir=/opt/compiler-explorer/dotnet-trunk
 compiler.dotnettrunkcsharpildasm.buildConfig=Release
 compiler.dotnettrunkcsharpildasm.langVersion=preview
 compiler.dotnettrunkcsharpildasm.isNightly=true
 
+# ILSpy compilers
+
+compiler.dotnet60csharpilspy.exe=/opt/compiler-explorer/dotnet-v6.0.36/.dotnet/dotnet
+compiler.dotnet60csharpilspy.name=.NET 6.0 ILSpy
+compiler.dotnet60csharpilspy.clrDir=/opt/compiler-explorer/dotnet-v6.0.36
+compiler.dotnet60csharpilspy.buildConfig=Release
+compiler.dotnet60csharpilspy.langVersion=latest
+
+compiler.dotnet70csharpilspy.exe=/opt/compiler-explorer/dotnet-v7.0.20/.dotnet/dotnet
+compiler.dotnet70csharpilspy.name=.NET 7.0 ILSpy
+compiler.dotnet70csharpilspy.clrDir=/opt/compiler-explorer/dotnet-v7.0.20
+compiler.dotnet70csharpilspy.buildConfig=Release
+compiler.dotnet70csharpilspy.langVersion=latest
+
+compiler.dotnet80csharpilspy.exe=/opt/compiler-explorer/dotnet-v8.0.11/.dotnet/dotnet
+compiler.dotnet80csharpilspy.name=.NET 8.0 ILSpy
+compiler.dotnet80csharpilspy.clrDir=/opt/compiler-explorer/dotnet-v8.0.11
+compiler.dotnet80csharpilspy.buildConfig=Release
+compiler.dotnet80csharpilspy.langVersion=latest
+
+compiler.dotnet90csharpilspy.exe=/opt/compiler-explorer/dotnet-v9.0.0/.dotnet/dotnet
+compiler.dotnet90csharpilspy.name=.NET 9.0 ILSpy
+compiler.dotnet90csharpilspy.clrDir=/opt/compiler-explorer/dotnet-v9.0.0
+compiler.dotnet90csharpilspy.buildConfig=Release
+compiler.dotnet90csharpilspy.langVersion=latest
+
+compiler.dotnettrunkcsharpilspy.exe=/opt/compiler-explorer/dotnet-trunk/.dotnet/dotnet
+compiler.dotnettrunkcsharpilspy.name=.NET (main) ILSpy
+compiler.dotnettrunkcsharpilspy.clrDir=/opt/compiler-explorer/dotnet-trunk
+compiler.dotnettrunkcsharpilspy.buildConfig=Release
+compiler.dotnettrunkcsharpilspy.langVersion=preview
+compiler.dotnettrunkcsharpilspy.isNightly=true
+
 # Legacy compilers (for backwards compatibility, don't add new compilers here)
 
 compiler.dotnet6011csharp.exe=/opt/compiler-explorer/dotnet-v6.0.11/.dotnet/dotnet
diff --git a/etc/config/cuda.amazon.properties b/etc/config/cuda.amazon.properties
index fb3b21ae7..04e145ec9 100644
--- a/etc/config/cuda.amazon.properties
+++ b/etc/config/cuda.amazon.properties
@@ -9,7 +9,7 @@ supportsExecute=false
 # Details of GPUs/features supported by CUDA compilers can be found here:
 # gist.github.com/ax3l/9489132#clang--x-cuda
 
-group.nvcc.compilers=nvcc126u1:nvcc125u1:nvcc124u1:nvcc123u1:nvcc122u1:nvcc121:nvcc120u1:nvcc120:nvcc118:nvcc117u1:nvcc117:nvcc116u2:nvcc116u1:nvcc116:nvcc115u2:nvcc115u1:nvcc115:nvcc114u4:nvcc114u3:nvcc114u2:nvcc114u1:nvcc114:nvcc113u1:nvcc113:nvcc112u2:nvcc112u1:nvcc112:nvcc111u1:nvcc111:nvcc11u1:nvcc11:nvcc102:nvcc101u2:nvcc101u1:nvcc101:nvcc100:nvcc92:nvcc91
+group.nvcc.compilers=nvcc126u2:nvcc126u1:nvcc125u1:nvcc124u1:nvcc123u1:nvcc122u1:nvcc121:nvcc120u1:nvcc120:nvcc118:nvcc117u1:nvcc117:nvcc116u2:nvcc116u1:nvcc116:nvcc115u2:nvcc115u1:nvcc115:nvcc114u4:nvcc114u3:nvcc114u2:nvcc114u1:nvcc114:nvcc113u1:nvcc113:nvcc112u2:nvcc112u1:nvcc112:nvcc111u1:nvcc111:nvcc11u1:nvcc11:nvcc102:nvcc101u2:nvcc101u1:nvcc101:nvcc100:nvcc92:nvcc91
 group.nvcc.versionRe=^Cuda.*
 group.nvcc.compilerType=nvcc
 group.nvcc.isSemVer=true
@@ -246,6 +246,13 @@ compiler.nvcc126u1.options=--compiler-bindir /opt/compiler-explorer/gcc-10.2.0/b
 compiler.nvcc126u1.nvdisasm=/opt/compiler-explorer/cuda/12.6.1/bin/nvdisasm
 compiler.nvcc126u1.demangler=/opt/compiler-explorer/gcc-10.2.0/bin/c++filt
 compiler.nvcc126u1.objdumper=/opt/compiler-explorer/gcc-10.2.0/bin/objdump
+compiler.nvcc126u2.semver=12.6.2
+compiler.nvcc126u2.exe=/opt/compiler-explorer/cuda/12.6.2/bin/nvcc
+compiler.nvcc126u2.options=--compiler-bindir /opt/compiler-explorer/gcc-10.2.0/bin
+compiler.nvcc126u2.nvdisasm=/opt/compiler-explorer/cuda/12.6.2/bin/nvdisasm
+compiler.nvcc126u2.demangler=/opt/compiler-explorer/gcc-10.2.0/bin/c++filt
+compiler.nvcc126u2.objdumper=/opt/compiler-explorer/gcc-10.2.0/bin/objdump
+
 group.cuclang.compilers=cuclang700:cuclang800:cuclang900:cuclang1000:cuclang1001:cuclang1100:cuclang1600:cuclang1701:cuclang1810:cuclang1910:cltrunk
 group.cuclang.isSemVer=true
 group.cuclang.baseName=clang
diff --git a/etc/config/fortran.amazon.properties b/etc/config/fortran.amazon.properties
index f448a2a2d..66f70fed9 100644
--- a/etc/config/fortran.amazon.properties
+++ b/etc/config/fortran.amazon.properties
@@ -259,7 +259,7 @@ compiler.ifxlatest.options=-gxx-name=/opt/compiler-explorer/gcc-13.2.0/bin/g++
 #################################
 # NVHPC nvfortran
 
-group.nvfortran_x86.compilers=nvfortran_x86_24_9
+group.nvfortran_x86.compilers=nvfortran_x86_24_9:nvfortran_x86_24_11
 group.nvfortran_x86.options=
 group.nvfortran_x86.needsMulti=false
 group.nvfortran_x86.supportsBinary=true
@@ -276,6 +276,12 @@ compiler.nvfortran_x86_24_9.nvdisasm=/opt/compiler-explorer/hpc_sdk/Linux_x86_64
 compiler.nvfortran_x86_24_9.exe=/opt/compiler-explorer/hpc_sdk/Linux_x86_64/24.9/compilers/bin/nvfortran
 compiler.nvfortran_x86_24_9.semver=24.9
 
+compiler.nvfortran_x86_24_11.demangler=/opt/compiler-explorer/hpc_sdk/Linux_x86_64/24.11/compilers/bin/nvdecode
+compiler.nvfortran_x86_24_11.cuobjdump=/opt/compiler-explorer/hpc_sdk/Linux_x86_64/24.11/cuda/12.6/bin/cuobjdump
+compiler.nvfortran_x86_24_11.nvdisasm=/opt/compiler-explorer/hpc_sdk/Linux_x86_64/24.11/cuda/12.6/bin/nvdisasm
+compiler.nvfortran_x86_24_11.exe=/opt/compiler-explorer/hpc_sdk/Linux_x86_64/24.11/compilers/bin/nvfortran
+compiler.nvfortran_x86_24_11.semver=24.11
+
 ###############################
 # GCC Cross-Compilers
 group.cross.compilers=&gccarm:&gccaarch64:&ppcs:&gccrvs:&gccmips:&gccmips64:&gccmipsel:&gccmips64el:&gccs390x:&gccriscv:&gccriscv64:&gccloongarch64:&gccsparc:&gccsparc64:&gccsparcleon:&gcchppa
diff --git a/etc/config/fsharp.amazon.properties b/etc/config/fsharp.amazon.properties
index 500d40a0c..7b152c20b 100644
--- a/etc/config/fsharp.amazon.properties
+++ b/etc/config/fsharp.amazon.properties
@@ -1,20 +1,20 @@
-compilers=&dotnetcoreclr:&dotnetcrossgen2:&dotnetmono:&dotnetnativeaot:&dotnetildasm:&dotnetlegacy
+compilers=&dotnetcoreclr:&dotnetcrossgen2:&dotnetmono:&dotnetnativeaot:&dotnetildasm:&dotnetilspy:&dotnetlegacy
 supportsBinary=true
 needsMulti=false
-defaultCompiler=dotnet80fsharpcoreclr
+defaultCompiler=dotnet90fsharpcoreclr
 executionEnvironmentClass=local-dotnet
 
-group.dotnetcoreclr.compilers=dotnettrunkfsharpcoreclr:dotnet80fsharpcoreclr:dotnet70fsharpcoreclr
+group.dotnetcoreclr.compilers=dotnettrunkfsharpcoreclr:dotnet90fsharpcoreclr:dotnet80fsharpcoreclr:dotnet70fsharpcoreclr:dotnet60fsharpcoreclr
 group.dotnetcoreclr.compilerCategories=coreclr
 group.dotnetcoreclr.compilerType=dotnetcoreclr
 group.dotnetcoreclr.groupName=.NET CoreCLR
 
-group.dotnetcrossgen2.compilers=dotnettrunkfsharpcrossgen2:dotnet80fsharpcrossgen2:dotnet70fsharpcrossgen2:dotnet60fsharpcrossgen2
+group.dotnetcrossgen2.compilers=dotnettrunkfsharpcrossgen2:dotnet90fsharpcrossgen2:dotnet80fsharpcrossgen2:dotnet70fsharpcrossgen2:dotnet60fsharpcrossgen2
 group.dotnetcrossgen2.compilerCategories=crossgen2
 group.dotnetcrossgen2.compilerType=dotnetcrossgen2
 group.dotnetcrossgen2.groupName=.NET Crossgen2
 
-group.dotnetmono.compilers=dotnettrunkfsharpmono
+group.dotnetmono.compilers=dotnettrunkfsharpmono:dotnet90fsharpmono:dotnet80fsharpmono:dotnet70fsharpmono:dotnet60fsharpmono
 group.dotnetmono.compilerCategories=mono
 group.dotnetmono.compilerType=dotnetmono
 group.dotnetmono.groupName=.NET Mono
@@ -24,10 +24,15 @@ group.dotnetnativeaot.compilerCategories=nativeaot
 group.dotnetnativeaot.compilerType=dotnetnativeaot
 group.dotnetnativeaot.groupName=.NET NativeAOT
 
-group.dotnetildasm.compilers=dotnettrunkfsharpildasm
+group.dotnetildasm.compilers=dotnettrunkfsharpildasm:dotnet90fsharpildasm:dotnet80fsharpildasm:dotnet70fsharpildasm:dotnet60fsharpildasm
 group.dotnetildasm.compilerCategories=ildasm
 group.dotnetildasm.compilerType=dotnetildasm
-group.dotnetildasm.groupName=.NET IL Disassembler
+group.dotnetildasm.groupName=.NET ILDasm
+
+group.dotnetilspy.compilers=dotnettrunkfsharpilspy:dotnet90fsharpilspy:dotnet80fsharpilspy:dotnet70fsharpilspy:dotnet60fsharpilspy
+group.dotnetilspy.compilerCategories=ilspy
+group.dotnetilspy.compilerType=dotnetilspy
+group.dotnetilspy.groupName=.NET ILSpy
 
 group.dotnetlegacy.compilers=dotnettrunkfsharp:dotnet707fsharp:dotnet703fsharp:dotnet701fsharp:dotnet6018fsharp:dotnet6014fsharp:dotnet6011fsharp
 group.dotnetlegacy.compilerCategories=legacy
@@ -36,20 +41,32 @@ group.dotnetlegacy.groupName=Legacy
 
 # CoreCLR compilers
 
-compiler.dotnet70fsharpcoreclr.exe=/opt/compiler-explorer/dotnet-v7.0.19/.dotnet/dotnet
-compiler.dotnet70fsharpcoreclr.name=.NET CoreCLR 7.0
-compiler.dotnet70fsharpcoreclr.clrDir=/opt/compiler-explorer/dotnet-v7.0.19
+compiler.dotnet60fsharpcoreclr.exe=/opt/compiler-explorer/dotnet-v6.0.36/.dotnet/dotnet
+compiler.dotnet60fsharpcoreclr.name=.NET 6.0 CoreCLR
+compiler.dotnet60fsharpcoreclr.clrDir=/opt/compiler-explorer/dotnet-v6.0.36
+compiler.dotnet60fsharpcoreclr.buildConfig=Release
+compiler.dotnet60fsharpcoreclr.langVersion=latest
+
+compiler.dotnet70fsharpcoreclr.exe=/opt/compiler-explorer/dotnet-v7.0.20/.dotnet/dotnet
+compiler.dotnet70fsharpcoreclr.name=.NET 7.0 CoreCLR
+compiler.dotnet70fsharpcoreclr.clrDir=/opt/compiler-explorer/dotnet-v7.0.20
 compiler.dotnet70fsharpcoreclr.buildConfig=Release
 compiler.dotnet70fsharpcoreclr.langVersion=latest
 
-compiler.dotnet80fsharpcoreclr.exe=/opt/compiler-explorer/dotnet-v8.0.5/.dotnet/dotnet
-compiler.dotnet80fsharpcoreclr.name=.NET CoreCLR 8.0
-compiler.dotnet80fsharpcoreclr.clrDir=/opt/compiler-explorer/dotnet-v8.0.5
+compiler.dotnet80fsharpcoreclr.exe=/opt/compiler-explorer/dotnet-v8.0.11/.dotnet/dotnet
+compiler.dotnet80fsharpcoreclr.name=.NET 8.0 CoreCLR
+compiler.dotnet80fsharpcoreclr.clrDir=/opt/compiler-explorer/dotnet-v8.0.11
 compiler.dotnet80fsharpcoreclr.buildConfig=Release
 compiler.dotnet80fsharpcoreclr.langVersion=latest
 
+compiler.dotnet90fsharpcoreclr.exe=/opt/compiler-explorer/dotnet-v9.0.0/.dotnet/dotnet
+compiler.dotnet90fsharpcoreclr.name=.NET 9.0 CoreCLR
+compiler.dotnet90fsharpcoreclr.clrDir=/opt/compiler-explorer/dotnet-v9.0.0
+compiler.dotnet90fsharpcoreclr.buildConfig=Release
+compiler.dotnet90fsharpcoreclr.langVersion=latest
+
 compiler.dotnettrunkfsharpcoreclr.exe=/opt/compiler-explorer/dotnet-trunk/.dotnet/dotnet
-compiler.dotnettrunkfsharpcoreclr.name=.NET CoreCLR (main)
+compiler.dotnettrunkfsharpcoreclr.name=.NET (main) CoreCLR
 compiler.dotnettrunkfsharpcoreclr.clrDir=/opt/compiler-explorer/dotnet-trunk
 compiler.dotnettrunkfsharpcoreclr.buildConfig=Release
 compiler.dotnettrunkfsharpcoreclr.langVersion=preview
@@ -57,26 +74,32 @@ compiler.dotnettrunkfsharpcoreclr.isNightly=true
 
 # Crossgen2 compilers
 
-compiler.dotnet60fsharpcrossgen2.exe=/opt/compiler-explorer/dotnet-v6.0.30/.dotnet/dotnet
-compiler.dotnet60fsharpcrossgen2.name=.NET Crossgen2 6.0
-compiler.dotnet60fsharpcrossgen2.clrDir=/opt/compiler-explorer/dotnet-v6.0.30
+compiler.dotnet60fsharpcrossgen2.exe=/opt/compiler-explorer/dotnet-v6.0.36/.dotnet/dotnet
+compiler.dotnet60fsharpcrossgen2.name=.NET 6.0 Crossgen2
+compiler.dotnet60fsharpcrossgen2.clrDir=/opt/compiler-explorer/dotnet-v6.0.36
 compiler.dotnet60fsharpcrossgen2.buildConfig=Release
 compiler.dotnet60fsharpcrossgen2.langVersion=latest
 
-compiler.dotnet70fsharpcrossgen2.exe=/opt/compiler-explorer/dotnet-v7.0.19/.dotnet/dotnet
-compiler.dotnet70fsharpcrossgen2.name=.NET Crossgen2 7.0
-compiler.dotnet70fsharpcrossgen2.clrDir=/opt/compiler-explorer/dotnet-v7.0.19
+compiler.dotnet70fsharpcrossgen2.exe=/opt/compiler-explorer/dotnet-v7.0.20/.dotnet/dotnet
+compiler.dotnet70fsharpcrossgen2.name=.NET 7.0 Crossgen2
+compiler.dotnet70fsharpcrossgen2.clrDir=/opt/compiler-explorer/dotnet-v7.0.20
 compiler.dotnet70fsharpcrossgen2.buildConfig=Release
 compiler.dotnet70fsharpcrossgen2.langVersion=latest
 
-compiler.dotnet80fsharpcrossgen2.exe=/opt/compiler-explorer/dotnet-v8.0.5/.dotnet/dotnet
-compiler.dotnet80fsharpcrossgen2.name=.NET Crossgen2 8.0
-compiler.dotnet80fsharpcrossgen2.clrDir=/opt/compiler-explorer/dotnet-v8.0.5
+compiler.dotnet80fsharpcrossgen2.exe=/opt/compiler-explorer/dotnet-v8.0.11/.dotnet/dotnet
+compiler.dotnet80fsharpcrossgen2.name=.NET 8.0 Crossgen2
+compiler.dotnet80fsharpcrossgen2.clrDir=/opt/compiler-explorer/dotnet-v8.0.11
 compiler.dotnet80fsharpcrossgen2.buildConfig=Release
 compiler.dotnet80fsharpcrossgen2.langVersion=latest
 
+compiler.dotnet90fsharpcrossgen2.exe=/opt/compiler-explorer/dotnet-v9.0.0/.dotnet/dotnet
+compiler.dotnet90fsharpcrossgen2.name=.NET 9.0 Crossgen2
+compiler.dotnet90fsharpcrossgen2.clrDir=/opt/compiler-explorer/dotnet-v9.0.0
+compiler.dotnet90fsharpcrossgen2.buildConfig=Release
+compiler.dotnet90fsharpcrossgen2.langVersion=latest
+
 compiler.dotnettrunkfsharpcrossgen2.exe=/opt/compiler-explorer/dotnet-trunk/.dotnet/dotnet
-compiler.dotnettrunkfsharpcrossgen2.name=.NET Crossgen2 (main)
+compiler.dotnettrunkfsharpcrossgen2.name=.NET (main) Crossgen2
 compiler.dotnettrunkfsharpcrossgen2.clrDir=/opt/compiler-explorer/dotnet-trunk
 compiler.dotnettrunkfsharpcrossgen2.buildConfig=Release
 compiler.dotnettrunkfsharpcrossgen2.langVersion=preview
@@ -84,8 +107,32 @@ compiler.dotnettrunkfsharpcrossgen2.isNightly=true
 
 # Mono compilers
 
+compiler.dotnet60fsharpmono.exe=/opt/compiler-explorer/dotnet-v6.0.36/.dotnet/dotnet
+compiler.dotnet60fsharpmono.name=.NET 6.0 Mono
+compiler.dotnet60fsharpmono.clrDir=/opt/compiler-explorer/dotnet-v6.0.36
+compiler.dotnet60fsharpmono.buildConfig=Release
+compiler.dotnet60fsharpmono.langVersion=latest
+
+compiler.dotnet70fsharpmono.exe=/opt/compiler-explorer/dotnet-v7.0.20/.dotnet/dotnet
+compiler.dotnet70fsharpmono.name=.NET 7.0 Mono
+compiler.dotnet70fsharpmono.clrDir=/opt/compiler-explorer/dotnet-v7.0.20
+compiler.dotnet70fsharpmono.buildConfig=Release
+compiler.dotnet70fsharpmono.langVersion=latest
+
+compiler.dotnet80fsharpmono.exe=/opt/compiler-explorer/dotnet-v8.0.11/.dotnet/dotnet
+compiler.dotnet80fsharpmono.name=.NET 8.0 Mono
+compiler.dotnet80fsharpmono.clrDir=/opt/compiler-explorer/dotnet-v8.0.11
+compiler.dotnet80fsharpmono.buildConfig=Release
+compiler.dotnet80fsharpmono.langVersion=latest
+
+compiler.dotnet90fsharpmono.exe=/opt/compiler-explorer/dotnet-v9.0.0/.dotnet/dotnet
+compiler.dotnet90fsharpmono.name=.NET 9.0 Mono
+compiler.dotnet90fsharpmono.clrDir=/opt/compiler-explorer/dotnet-v9.0.0
+compiler.dotnet90fsharpmono.buildConfig=Release
+compiler.dotnet90fsharpmono.langVersion=latest
+
 compiler.dotnettrunkfsharpmono.exe=/opt/compiler-explorer/dotnet-trunk/.dotnet/dotnet
-compiler.dotnettrunkfsharpmono.name=.NET Mono (main)
+compiler.dotnettrunkfsharpmono.name=.NET (main) Mono
 compiler.dotnettrunkfsharpmono.clrDir=/opt/compiler-explorer/dotnet-trunk
 compiler.dotnettrunkfsharpmono.buildConfig=Release
 compiler.dotnettrunkfsharpmono.langVersion=preview
@@ -94,21 +141,78 @@ compiler.dotnettrunkfsharpmono.isNightly=true
 # NativeAOT compilers
 
 compiler.dotnettrunkfsharpnativeaot.exe=/opt/compiler-explorer/dotnet-trunk/.dotnet/dotnet
-compiler.dotnettrunkfsharpnativeaot.name=.NET NativeAOT (main)
+compiler.dotnettrunkfsharpnativeaot.name=.NET (main) NativeAOT
 compiler.dotnettrunkfsharpnativeaot.clrDir=/opt/compiler-explorer/dotnet-trunk
 compiler.dotnettrunkfsharpnativeaot.buildConfig=Release
 compiler.dotnettrunkfsharpnativeaot.langVersion=preview
 compiler.dotnettrunkfsharpnativeaot.isNightly=true
 
-# IL disassembler compilers
+# ILDasm compilers
+
+compiler.dotnet60fsharpildasm.exe=/opt/compiler-explorer/dotnet-v6.0.36/.dotnet/dotnet
+compiler.dotnet60fsharpildasm.name=.NET 6.0 ILDasm
+compiler.dotnet60fsharpildasm.clrDir=/opt/compiler-explorer/dotnet-v6.0.36
+compiler.dotnet60fsharpildasm.buildConfig=Release
+compiler.dotnet60fsharpildasm.langVersion=latest
+
+compiler.dotnet70fsharpildasm.exe=/opt/compiler-explorer/dotnet-v7.0.20/.dotnet/dotnet
+compiler.dotnet70fsharpildasm.name=.NET 7.0 ILDasm
+compiler.dotnet70fsharpildasm.clrDir=/opt/compiler-explorer/dotnet-v7.0.20
+compiler.dotnet70fsharpildasm.buildConfig=Release
+compiler.dotnet70fsharpildasm.langVersion=latest
+
+compiler.dotnet80fsharpildasm.exe=/opt/compiler-explorer/dotnet-v8.0.11/.dotnet/dotnet
+compiler.dotnet80fsharpildasm.name=.NET 8.0 ILDasm
+compiler.dotnet80fsharpildasm.clrDir=/opt/compiler-explorer/dotnet-v8.0.11
+compiler.dotnet80fsharpildasm.buildConfig=Release
+compiler.dotnet80fsharpildasm.langVersion=latest
+
+compiler.dotnet90fsharpildasm.exe=/opt/compiler-explorer/dotnet-v9.0.0/.dotnet/dotnet
+compiler.dotnet90fsharpildasm.name=.NET 9.0 ILDasm
+compiler.dotnet90fsharpildasm.clrDir=/opt/compiler-explorer/dotnet-v9.0.0
+compiler.dotnet90fsharpildasm.buildConfig=Release
+compiler.dotnet90fsharpildasm.langVersion=latest
 
 compiler.dotnettrunkfsharpildasm.exe=/opt/compiler-explorer/dotnet-trunk/.dotnet/dotnet
-compiler.dotnettrunkfsharpildasm.name=.NET IL Disassembler (main)
+compiler.dotnettrunkfsharpildasm.name=.NET (main) ILDasm
 compiler.dotnettrunkfsharpildasm.clrDir=/opt/compiler-explorer/dotnet-trunk
 compiler.dotnettrunkfsharpildasm.buildConfig=Release
 compiler.dotnettrunkfsharpildasm.langVersion=preview
 compiler.dotnettrunkfsharpildasm.isNightly=true
 
+# ILSpy compilers
+
+compiler.dotnet60fsharpilspy.exe=/opt/compiler-explorer/dotnet-v6.0.36/.dotnet/dotnet
+compiler.dotnet60fsharpilspy.name=.NET 6.0 ILSpy
+compiler.dotnet60fsharpilspy.clrDir=/opt/compiler-explorer/dotnet-v6.0.36
+compiler.dotnet60fsharpilspy.buildConfig=Release
+compiler.dotnet60fsharpilspy.langVersion=latest
+
+compiler.dotnet70fsharpilspy.exe=/opt/compiler-explorer/dotnet-v7.0.20/.dotnet/dotnet
+compiler.dotnet70fsharpilspy.name=.NET 7.0 ILSpy
+compiler.dotnet70fsharpilspy.clrDir=/opt/compiler-explorer/dotnet-v7.0.20
+compiler.dotnet70fsharpilspy.buildConfig=Release
+compiler.dotnet70fsharpilspy.langVersion=latest
+
+compiler.dotnet80fsharpilspy.exe=/opt/compiler-explorer/dotnet-v8.0.11/.dotnet/dotnet
+compiler.dotnet80fsharpilspy.name=.NET 8.0 ILSpy
+compiler.dotnet80fsharpilspy.clrDir=/opt/compiler-explorer/dotnet-v8.0.11
+compiler.dotnet80fsharpilspy.buildConfig=Release
+compiler.dotnet80fsharpilspy.langVersion=latest
+
+compiler.dotnet90fsharpilspy.exe=/opt/compiler-explorer/dotnet-v9.0.0/.dotnet/dotnet
+compiler.dotnet90fsharpilspy.name=.NET 9.0 ILSpy
+compiler.dotnet90fsharpilspy.clrDir=/opt/compiler-explorer/dotnet-v9.0.0
+compiler.dotnet90fsharpilspy.buildConfig=Release
+compiler.dotnet90fsharpilspy.langVersion=latest
+
+compiler.dotnettrunkfsharpilspy.exe=/opt/compiler-explorer/dotnet-trunk/.dotnet/dotnet
+compiler.dotnettrunkfsharpilspy.name=.NET (main) ILSpy
+compiler.dotnettrunkfsharpilspy.clrDir=/opt/compiler-explorer/dotnet-trunk
+compiler.dotnettrunkfsharpilspy.buildConfig=Release
+compiler.dotnettrunkfsharpilspy.langVersion=preview
+compiler.dotnettrunkfsharpilspy.isNightly=true
+
 # Legacy compilers (for backwards compatibility, don't add new compilers here)
 
 compiler.dotnet6011fsharp.exe=/opt/compiler-explorer/dotnet-v6.0.11/.dotnet/dotnet
diff --git a/etc/config/fsharp.defaults.properties b/etc/config/fsharp.defaults.properties
index 500d40a0c..7b152c20b 100644
--- a/etc/config/fsharp.defaults.properties
+++ b/etc/config/fsharp.defaults.properties
@@ -1,20 +1,20 @@
-compilers=&dotnetcoreclr:&dotnetcrossgen2:&dotnetmono:&dotnetnativeaot:&dotnetildasm:&dotnetlegacy
+compilers=&dotnetcoreclr:&dotnetcrossgen2:&dotnetmono:&dotnetnativeaot:&dotnetildasm:&dotnetilspy:&dotnetlegacy
 supportsBinary=true
 needsMulti=false
-defaultCompiler=dotnet80fsharpcoreclr
+defaultCompiler=dotnet90fsharpcoreclr
 executionEnvironmentClass=local-dotnet
 
-group.dotnetcoreclr.compilers=dotnettrunkfsharpcoreclr:dotnet80fsharpcoreclr:dotnet70fsharpcoreclr
+group.dotnetcoreclr.compilers=dotnettrunkfsharpcoreclr:dotnet90fsharpcoreclr:dotnet80fsharpcoreclr:dotnet70fsharpcoreclr:dotnet60fsharpcoreclr
 group.dotnetcoreclr.compilerCategories=coreclr
 group.dotnetcoreclr.compilerType=dotnetcoreclr
 group.dotnetcoreclr.groupName=.NET CoreCLR
 
-group.dotnetcrossgen2.compilers=dotnettrunkfsharpcrossgen2:dotnet80fsharpcrossgen2:dotnet70fsharpcrossgen2:dotnet60fsharpcrossgen2
+group.dotnetcrossgen2.compilers=dotnettrunkfsharpcrossgen2:dotnet90fsharpcrossgen2:dotnet80fsharpcrossgen2:dotnet70fsharpcrossgen2:dotnet60fsharpcrossgen2
 group.dotnetcrossgen2.compilerCategories=crossgen2
 group.dotnetcrossgen2.compilerType=dotnetcrossgen2
 group.dotnetcrossgen2.groupName=.NET Crossgen2
 
-group.dotnetmono.compilers=dotnettrunkfsharpmono
+group.dotnetmono.compilers=dotnettrunkfsharpmono:dotnet90fsharpmono:dotnet80fsharpmono:dotnet70fsharpmono:dotnet60fsharpmono
 group.dotnetmono.compilerCategories=mono
 group.dotnetmono.compilerType=dotnetmono
 group.dotnetmono.groupName=.NET Mono
@@ -24,10 +24,15 @@ group.dotnetnativeaot.compilerCategories=nativeaot
 group.dotnetnativeaot.compilerType=dotnetnativeaot
 group.dotnetnativeaot.groupName=.NET NativeAOT
 
-group.dotnetildasm.compilers=dotnettrunkfsharpildasm
+group.dotnetildasm.compilers=dotnettrunkfsharpildasm:dotnet90fsharpildasm:dotnet80fsharpildasm:dotnet70fsharpildasm:dotnet60fsharpildasm
 group.dotnetildasm.compilerCategories=ildasm
 group.dotnetildasm.compilerType=dotnetildasm
-group.dotnetildasm.groupName=.NET IL Disassembler
+group.dotnetildasm.groupName=.NET ILDasm
+
+group.dotnetilspy.compilers=dotnettrunkfsharpilspy:dotnet90fsharpilspy:dotnet80fsharpilspy:dotnet70fsharpilspy:dotnet60fsharpilspy
+group.dotnetilspy.compilerCategories=ilspy
+group.dotnetilspy.compilerType=dotnetilspy
+group.dotnetilspy.groupName=.NET ILSpy
 
 group.dotnetlegacy.compilers=dotnettrunkfsharp:dotnet707fsharp:dotnet703fsharp:dotnet701fsharp:dotnet6018fsharp:dotnet6014fsharp:dotnet6011fsharp
 group.dotnetlegacy.compilerCategories=legacy
@@ -36,20 +41,32 @@ group.dotnetlegacy.groupName=Legacy
 
 # CoreCLR compilers
 
-compiler.dotnet70fsharpcoreclr.exe=/opt/compiler-explorer/dotnet-v7.0.19/.dotnet/dotnet
-compiler.dotnet70fsharpcoreclr.name=.NET CoreCLR 7.0
-compiler.dotnet70fsharpcoreclr.clrDir=/opt/compiler-explorer/dotnet-v7.0.19
+compiler.dotnet60fsharpcoreclr.exe=/opt/compiler-explorer/dotnet-v6.0.36/.dotnet/dotnet
+compiler.dotnet60fsharpcoreclr.name=.NET 6.0 CoreCLR
+compiler.dotnet60fsharpcoreclr.clrDir=/opt/compiler-explorer/dotnet-v6.0.36
+compiler.dotnet60fsharpcoreclr.buildConfig=Release
+compiler.dotnet60fsharpcoreclr.langVersion=latest
+
+compiler.dotnet70fsharpcoreclr.exe=/opt/compiler-explorer/dotnet-v7.0.20/.dotnet/dotnet
+compiler.dotnet70fsharpcoreclr.name=.NET 7.0 CoreCLR
+compiler.dotnet70fsharpcoreclr.clrDir=/opt/compiler-explorer/dotnet-v7.0.20
 compiler.dotnet70fsharpcoreclr.buildConfig=Release
 compiler.dotnet70fsharpcoreclr.langVersion=latest
 
-compiler.dotnet80fsharpcoreclr.exe=/opt/compiler-explorer/dotnet-v8.0.5/.dotnet/dotnet
-compiler.dotnet80fsharpcoreclr.name=.NET CoreCLR 8.0
-compiler.dotnet80fsharpcoreclr.clrDir=/opt/compiler-explorer/dotnet-v8.0.5
+compiler.dotnet80fsharpcoreclr.exe=/opt/compiler-explorer/dotnet-v8.0.11/.dotnet/dotnet
+compiler.dotnet80fsharpcoreclr.name=.NET 8.0 CoreCLR
+compiler.dotnet80fsharpcoreclr.clrDir=/opt/compiler-explorer/dotnet-v8.0.11
 compiler.dotnet80fsharpcoreclr.buildConfig=Release
 compiler.dotnet80fsharpcoreclr.langVersion=latest
 
+compiler.dotnet90fsharpcoreclr.exe=/opt/compiler-explorer/dotnet-v9.0.0/.dotnet/dotnet
+compiler.dotnet90fsharpcoreclr.name=.NET 9.0 CoreCLR
+compiler.dotnet90fsharpcoreclr.clrDir=/opt/compiler-explorer/dotnet-v9.0.0
+compiler.dotnet90fsharpcoreclr.buildConfig=Release
+compiler.dotnet90fsharpcoreclr.langVersion=latest
+
 compiler.dotnettrunkfsharpcoreclr.exe=/opt/compiler-explorer/dotnet-trunk/.dotnet/dotnet
-compiler.dotnettrunkfsharpcoreclr.name=.NET CoreCLR (main)
+compiler.dotnettrunkfsharpcoreclr.name=.NET (main) CoreCLR
 compiler.dotnettrunkfsharpcoreclr.clrDir=/opt/compiler-explorer/dotnet-trunk
 compiler.dotnettrunkfsharpcoreclr.buildConfig=Release
 compiler.dotnettrunkfsharpcoreclr.langVersion=preview
@@ -57,26 +74,32 @@ compiler.dotnettrunkfsharpcoreclr.isNightly=true
 
 # Crossgen2 compilers
 
-compiler.dotnet60fsharpcrossgen2.exe=/opt/compiler-explorer/dotnet-v6.0.30/.dotnet/dotnet
-compiler.dotnet60fsharpcrossgen2.name=.NET Crossgen2 6.0
-compiler.dotnet60fsharpcrossgen2.clrDir=/opt/compiler-explorer/dotnet-v6.0.30
+compiler.dotnet60fsharpcrossgen2.exe=/opt/compiler-explorer/dotnet-v6.0.36/.dotnet/dotnet
+compiler.dotnet60fsharpcrossgen2.name=.NET 6.0 Crossgen2
+compiler.dotnet60fsharpcrossgen2.clrDir=/opt/compiler-explorer/dotnet-v6.0.36
 compiler.dotnet60fsharpcrossgen2.buildConfig=Release
 compiler.dotnet60fsharpcrossgen2.langVersion=latest
 
-compiler.dotnet70fsharpcrossgen2.exe=/opt/compiler-explorer/dotnet-v7.0.19/.dotnet/dotnet
-compiler.dotnet70fsharpcrossgen2.name=.NET Crossgen2 7.0
-compiler.dotnet70fsharpcrossgen2.clrDir=/opt/compiler-explorer/dotnet-v7.0.19
+compiler.dotnet70fsharpcrossgen2.exe=/opt/compiler-explorer/dotnet-v7.0.20/.dotnet/dotnet
+compiler.dotnet70fsharpcrossgen2.name=.NET 7.0 Crossgen2
+compiler.dotnet70fsharpcrossgen2.clrDir=/opt/compiler-explorer/dotnet-v7.0.20
 compiler.dotnet70fsharpcrossgen2.buildConfig=Release
 compiler.dotnet70fsharpcrossgen2.langVersion=latest
 
-compiler.dotnet80fsharpcrossgen2.exe=/opt/compiler-explorer/dotnet-v8.0.5/.dotnet/dotnet
-compiler.dotnet80fsharpcrossgen2.name=.NET Crossgen2 8.0
-compiler.dotnet80fsharpcrossgen2.clrDir=/opt/compiler-explorer/dotnet-v8.0.5
+compiler.dotnet80fsharpcrossgen2.exe=/opt/compiler-explorer/dotnet-v8.0.11/.dotnet/dotnet
+compiler.dotnet80fsharpcrossgen2.name=.NET 8.0 Crossgen2
+compiler.dotnet80fsharpcrossgen2.clrDir=/opt/compiler-explorer/dotnet-v8.0.11
 compiler.dotnet80fsharpcrossgen2.buildConfig=Release
 compiler.dotnet80fsharpcrossgen2.langVersion=latest
 
+compiler.dotnet90fsharpcrossgen2.exe=/opt/compiler-explorer/dotnet-v9.0.0/.dotnet/dotnet
+compiler.dotnet90fsharpcrossgen2.name=.NET 9.0 Crossgen2
+compiler.dotnet90fsharpcrossgen2.clrDir=/opt/compiler-explorer/dotnet-v9.0.0
+compiler.dotnet90fsharpcrossgen2.buildConfig=Release
+compiler.dotnet90fsharpcrossgen2.langVersion=latest
+
 compiler.dotnettrunkfsharpcrossgen2.exe=/opt/compiler-explorer/dotnet-trunk/.dotnet/dotnet
-compiler.dotnettrunkfsharpcrossgen2.name=.NET Crossgen2 (main)
+compiler.dotnettrunkfsharpcrossgen2.name=.NET (main) Crossgen2
 compiler.dotnettrunkfsharpcrossgen2.clrDir=/opt/compiler-explorer/dotnet-trunk
 compiler.dotnettrunkfsharpcrossgen2.buildConfig=Release
 compiler.dotnettrunkfsharpcrossgen2.langVersion=preview
@@ -84,8 +107,32 @@ compiler.dotnettrunkfsharpcrossgen2.isNightly=true
 
 # Mono compilers
 
+compiler.dotnet60fsharpmono.exe=/opt/compiler-explorer/dotnet-v6.0.36/.dotnet/dotnet
+compiler.dotnet60fsharpmono.name=.NET 6.0 Mono
+compiler.dotnet60fsharpmono.clrDir=/opt/compiler-explorer/dotnet-v6.0.36
+compiler.dotnet60fsharpmono.buildConfig=Release
+compiler.dotnet60fsharpmono.langVersion=latest
+
+compiler.dotnet70fsharpmono.exe=/opt/compiler-explorer/dotnet-v7.0.20/.dotnet/dotnet
+compiler.dotnet70fsharpmono.name=.NET 7.0 Mono
+compiler.dotnet70fsharpmono.clrDir=/opt/compiler-explorer/dotnet-v7.0.20
+compiler.dotnet70fsharpmono.buildConfig=Release
+compiler.dotnet70fsharpmono.langVersion=latest
+
+compiler.dotnet80fsharpmono.exe=/opt/compiler-explorer/dotnet-v8.0.11/.dotnet/dotnet
+compiler.dotnet80fsharpmono.name=.NET 8.0 Mono
+compiler.dotnet80fsharpmono.clrDir=/opt/compiler-explorer/dotnet-v8.0.11
+compiler.dotnet80fsharpmono.buildConfig=Release
+compiler.dotnet80fsharpmono.langVersion=latest
+
+compiler.dotnet90fsharpmono.exe=/opt/compiler-explorer/dotnet-v9.0.0/.dotnet/dotnet
+compiler.dotnet90fsharpmono.name=.NET 9.0 Mono
+compiler.dotnet90fsharpmono.clrDir=/opt/compiler-explorer/dotnet-v9.0.0
+compiler.dotnet90fsharpmono.buildConfig=Release
+compiler.dotnet90fsharpmono.langVersion=latest
+
 compiler.dotnettrunkfsharpmono.exe=/opt/compiler-explorer/dotnet-trunk/.dotnet/dotnet
-compiler.dotnettrunkfsharpmono.name=.NET Mono (main)
+compiler.dotnettrunkfsharpmono.name=.NET (main) Mono
 compiler.dotnettrunkfsharpmono.clrDir=/opt/compiler-explorer/dotnet-trunk
 compiler.dotnettrunkfsharpmono.buildConfig=Release
 compiler.dotnettrunkfsharpmono.langVersion=preview
@@ -94,21 +141,78 @@ compiler.dotnettrunkfsharpmono.isNightly=true
 # NativeAOT compilers
 
 compiler.dotnettrunkfsharpnativeaot.exe=/opt/compiler-explorer/dotnet-trunk/.dotnet/dotnet
-compiler.dotnettrunkfsharpnativeaot.name=.NET NativeAOT (main)
+compiler.dotnettrunkfsharpnativeaot.name=.NET (main) NativeAOT
 compiler.dotnettrunkfsharpnativeaot.clrDir=/opt/compiler-explorer/dotnet-trunk
 compiler.dotnettrunkfsharpnativeaot.buildConfig=Release
 compiler.dotnettrunkfsharpnativeaot.langVersion=preview
 compiler.dotnettrunkfsharpnativeaot.isNightly=true
 
-# IL disassembler compilers
+# ILDasm compilers
+
+compiler.dotnet60fsharpildasm.exe=/opt/compiler-explorer/dotnet-v6.0.36/.dotnet/dotnet
+compiler.dotnet60fsharpildasm.name=.NET 6.0 ILDasm
+compiler.dotnet60fsharpildasm.clrDir=/opt/compiler-explorer/dotnet-v6.0.36
+compiler.dotnet60fsharpildasm.buildConfig=Release
+compiler.dotnet60fsharpildasm.langVersion=latest
+
+compiler.dotnet70fsharpildasm.exe=/opt/compiler-explorer/dotnet-v7.0.20/.dotnet/dotnet
+compiler.dotnet70fsharpildasm.name=.NET 7.0 ILDasm
+compiler.dotnet70fsharpildasm.clrDir=/opt/compiler-explorer/dotnet-v7.0.20
+compiler.dotnet70fsharpildasm.buildConfig=Release
+compiler.dotnet70fsharpildasm.langVersion=latest
+
+compiler.dotnet80fsharpildasm.exe=/opt/compiler-explorer/dotnet-v8.0.11/.dotnet/dotnet
+compiler.dotnet80fsharpildasm.name=.NET 8.0 ILDasm
+compiler.dotnet80fsharpildasm.clrDir=/opt/compiler-explorer/dotnet-v8.0.11
+compiler.dotnet80fsharpildasm.buildConfig=Release
+compiler.dotnet80fsharpildasm.langVersion=latest
+
+compiler.dotnet90fsharpildasm.exe=/opt/compiler-explorer/dotnet-v9.0.0/.dotnet/dotnet
+compiler.dotnet90fsharpildasm.name=.NET 9.0 ILDasm
+compiler.dotnet90fsharpildasm.clrDir=/opt/compiler-explorer/dotnet-v9.0.0
+compiler.dotnet90fsharpildasm.buildConfig=Release
+compiler.dotnet90fsharpildasm.langVersion=latest
 
 compiler.dotnettrunkfsharpildasm.exe=/opt/compiler-explorer/dotnet-trunk/.dotnet/dotnet
-compiler.dotnettrunkfsharpildasm.name=.NET IL Disassembler (main)
+compiler.dotnettrunkfsharpildasm.name=.NET (main) ILDasm
 compiler.dotnettrunkfsharpildasm.clrDir=/opt/compiler-explorer/dotnet-trunk
 compiler.dotnettrunkfsharpildasm.buildConfig=Release
 compiler.dotnettrunkfsharpildasm.langVersion=preview
 compiler.dotnettrunkfsharpildasm.isNightly=true
 
+# ILSpy compilers
+
+compiler.dotnet60fsharpilspy.exe=/opt/compiler-explorer/dotnet-v6.0.36/.dotnet/dotnet
+compiler.dotnet60fsharpilspy.name=.NET 6.0 ILSpy
+compiler.dotnet60fsharpilspy.clrDir=/opt/compiler-explorer/dotnet-v6.0.36
+compiler.dotnet60fsharpilspy.buildConfig=Release
+compiler.dotnet60fsharpilspy.langVersion=latest
+
+compiler.dotnet70fsharpilspy.exe=/opt/compiler-explorer/dotnet-v7.0.20/.dotnet/dotnet
+compiler.dotnet70fsharpilspy.name=.NET 7.0 ILSpy
+compiler.dotnet70fsharpilspy.clrDir=/opt/compiler-explorer/dotnet-v7.0.20
+compiler.dotnet70fsharpilspy.buildConfig=Release
+compiler.dotnet70fsharpilspy.langVersion=latest
+
+compiler.dotnet80fsharpilspy.exe=/opt/compiler-explorer/dotnet-v8.0.11/.dotnet/dotnet
+compiler.dotnet80fsharpilspy.name=.NET 8.0 ILSpy
+compiler.dotnet80fsharpilspy.clrDir=/opt/compiler-explorer/dotnet-v8.0.11
+compiler.dotnet80fsharpilspy.buildConfig=Release
+compiler.dotnet80fsharpilspy.langVersion=latest
+
+compiler.dotnet90fsharpilspy.exe=/opt/compiler-explorer/dotnet-v9.0.0/.dotnet/dotnet
+compiler.dotnet90fsharpilspy.name=.NET 9.0 ILSpy
+compiler.dotnet90fsharpilspy.clrDir=/opt/compiler-explorer/dotnet-v9.0.0
+compiler.dotnet90fsharpilspy.buildConfig=Release
+compiler.dotnet90fsharpilspy.langVersion=latest
+
+compiler.dotnettrunkfsharpilspy.exe=/opt/compiler-explorer/dotnet-trunk/.dotnet/dotnet
+compiler.dotnettrunkfsharpilspy.name=.NET (main) ILSpy
+compiler.dotnettrunkfsharpilspy.clrDir=/opt/compiler-explorer/dotnet-trunk
+compiler.dotnettrunkfsharpilspy.buildConfig=Release
+compiler.dotnettrunkfsharpilspy.langVersion=preview
+compiler.dotnettrunkfsharpilspy.isNightly=true
+
 # Legacy compilers (for backwards compatibility, don't add new compilers here)
 
 compiler.dotnet6011fsharp.exe=/opt/compiler-explorer/dotnet-v6.0.11/.dotnet/dotnet
diff --git a/etc/config/il.amazon.properties b/etc/config/il.amazon.properties
index 53ffa53ae..81fe840ff 100644
--- a/etc/config/il.amazon.properties
+++ b/etc/config/il.amazon.properties
@@ -1,20 +1,20 @@
-compilers=&dotnetcoreclr:&dotnetcrossgen2:&dotnetmono:&dotnetnativeaot:&dotnetildasm
+compilers=&dotnetcoreclr:&dotnetcrossgen2:&dotnetmono:&dotnetnativeaot:&dotnetildasm:&dotnetilspy
 supportsBinary=true
 needsMulti=false
-defaultCompiler=dotnet80ilcoreclr
+defaultCompiler=dotnet90ilcoreclr
 executionEnvironmentClass=local-dotnet
 
-group.dotnetcoreclr.compilers=dotnettrunkilcoreclr:dotnet80ilcoreclr:dotnet70ilcoreclr
+group.dotnetcoreclr.compilers=dotnettrunkilcoreclr:dotnet90ilcoreclr:dotnet80ilcoreclr:dotnet70ilcoreclr:dotnet60ilcoreclr
 group.dotnetcoreclr.compilerCategories=coreclr
 group.dotnetcoreclr.compilerType=dotnetcoreclr
 group.dotnetcoreclr.groupName=.NET CoreCLR
 
-group.dotnetcrossgen2.compilers=dotnettrunkilcrossgen2:dotnet80ilcrossgen2:dotnet70ilcrossgen2:dotnet60ilcrossgen2
+group.dotnetcrossgen2.compilers=dotnettrunkilcrossgen2:dotnet90ilcrossgen2:dotnet80ilcrossgen2:dotnet70ilcrossgen2:dotnet60ilcrossgen2
 group.dotnetcrossgen2.compilerCategories=crossgen2
 group.dotnetcrossgen2.compilerType=dotnetcrossgen2
 group.dotnetcrossgen2.groupName=.NET Crossgen2
 
-group.dotnetmono.compilers=dotnettrunkilmono
+group.dotnetmono.compilers=dotnettrunkilmono:dotnet90ilmono:dotnet80ilmono:dotnet70ilmono:dotnet60ilmono
 group.dotnetmono.compilerCategories=mono
 group.dotnetmono.compilerType=dotnetmono
 group.dotnetmono.groupName=.NET Mono
@@ -24,27 +24,44 @@ group.dotnetnativeaot.compilerCategories=nativeaot
 group.dotnetnativeaot.compilerType=dotnetnativeaot
 group.dotnetnativeaot.groupName=.NET NativeAOT
 
-group.dotnetildasm.compilers=dotnettrunkilildasm
+group.dotnetildasm.compilers=dotnettrunkilildasm:dotnet90ilildasm:dotnet80ilildasm:dotnet70ilildasm:dotnet60ilildasm
 group.dotnetildasm.compilerCategories=ildasm
 group.dotnetildasm.compilerType=dotnetildasm
-group.dotnetildasm.groupName=.NET IL Disassembler
+group.dotnetildasm.groupName=.NET ILDasm
+
+group.dotnetilspy.compilers=dotnettrunkililspy:dotnet90ililspy:dotnet80ililspy:dotnet70ililspy:dotnet60ililspy
+group.dotnetilspy.compilerCategories=ilspy
+group.dotnetilspy.compilerType=dotnetilspy
+group.dotnetilspy.groupName=.NET ILSpy
 
 # CoreCLR compilers
 
-compiler.dotnet70ilcoreclr.exe=/opt/compiler-explorer/dotnet-v7.0.19/.dotnet/dotnet
-compiler.dotnet70ilcoreclr.name=.NET CoreCLR 7.0
-compiler.dotnet70ilcoreclr.clrDir=/opt/compiler-explorer/dotnet-v7.0.19
+compiler.dotnet60ilcoreclr.exe=/opt/compiler-explorer/dotnet-v6.0.36/.dotnet/dotnet
+compiler.dotnet60ilcoreclr.name=.NET 6.0 CoreCLR
+compiler.dotnet60ilcoreclr.clrDir=/opt/compiler-explorer/dotnet-v6.0.36
+compiler.dotnet60ilcoreclr.buildConfig=Release
+compiler.dotnet60ilcoreclr.langVersion=latest
+
+compiler.dotnet70ilcoreclr.exe=/opt/compiler-explorer/dotnet-v7.0.20/.dotnet/dotnet
+compiler.dotnet70ilcoreclr.name=.NET 7.0 CoreCLR
+compiler.dotnet70ilcoreclr.clrDir=/opt/compiler-explorer/dotnet-v7.0.20
 compiler.dotnet70ilcoreclr.buildConfig=Release
 compiler.dotnet70ilcoreclr.langVersion=latest
 
-compiler.dotnet80ilcoreclr.exe=/opt/compiler-explorer/dotnet-v8.0.5/.dotnet/dotnet
-compiler.dotnet80ilcoreclr.name=.NET CoreCLR 8.0
-compiler.dotnet80ilcoreclr.clrDir=/opt/compiler-explorer/dotnet-v8.0.5
+compiler.dotnet80ilcoreclr.exe=/opt/compiler-explorer/dotnet-v8.0.11/.dotnet/dotnet
+compiler.dotnet80ilcoreclr.name=.NET 8.0 CoreCLR
+compiler.dotnet80ilcoreclr.clrDir=/opt/compiler-explorer/dotnet-v8.0.11
 compiler.dotnet80ilcoreclr.buildConfig=Release
 compiler.dotnet80ilcoreclr.langVersion=latest
 
+compiler.dotnet90ilcoreclr.exe=/opt/compiler-explorer/dotnet-v9.0.0/.dotnet/dotnet
+compiler.dotnet90ilcoreclr.name=.NET 9.0 CoreCLR
+compiler.dotnet90ilcoreclr.clrDir=/opt/compiler-explorer/dotnet-v9.0.0
+compiler.dotnet90ilcoreclr.buildConfig=Release
+compiler.dotnet90ilcoreclr.langVersion=latest
+
 compiler.dotnettrunkilcoreclr.exe=/opt/compiler-explorer/dotnet-trunk/.dotnet/dotnet
-compiler.dotnettrunkilcoreclr.name=.NET CoreCLR (main)
+compiler.dotnettrunkilcoreclr.name=.NET (main) CoreCLR
 compiler.dotnettrunkilcoreclr.clrDir=/opt/compiler-explorer/dotnet-trunk
 compiler.dotnettrunkilcoreclr.buildConfig=Release
 compiler.dotnettrunkilcoreclr.langVersion=preview
@@ -52,26 +69,32 @@ compiler.dotnettrunkilcoreclr.isNightly=true
 
 # Crossgen2 compilers
 
-compiler.dotnet60ilcrossgen2.exe=/opt/compiler-explorer/dotnet-v6.0.30/.dotnet/dotnet
-compiler.dotnet60ilcrossgen2.name=.NET Crossgen2 6.0
-compiler.dotnet60ilcrossgen2.clrDir=/opt/compiler-explorer/dotnet-v6.0.30
+compiler.dotnet60ilcrossgen2.exe=/opt/compiler-explorer/dotnet-v6.0.36/.dotnet/dotnet
+compiler.dotnet60ilcrossgen2.name=.NET 6.0 Crossgen2
+compiler.dotnet60ilcrossgen2.clrDir=/opt/compiler-explorer/dotnet-v6.0.36
 compiler.dotnet60ilcrossgen2.buildConfig=Release
 compiler.dotnet60ilcrossgen2.langVersion=latest
 
-compiler.dotnet70ilcrossgen2.exe=/opt/compiler-explorer/dotnet-v7.0.19/.dotnet/dotnet
-compiler.dotnet70ilcrossgen2.name=.NET Crossgen2 7.0
-compiler.dotnet70ilcrossgen2.clrDir=/opt/compiler-explorer/dotnet-v7.0.19
+compiler.dotnet70ilcrossgen2.exe=/opt/compiler-explorer/dotnet-v7.0.20/.dotnet/dotnet
+compiler.dotnet70ilcrossgen2.name=.NET 7.0 Crossgen2
+compiler.dotnet70ilcrossgen2.clrDir=/opt/compiler-explorer/dotnet-v7.0.20
 compiler.dotnet70ilcrossgen2.buildConfig=Release
 compiler.dotnet70ilcrossgen2.langVersion=latest
 
-compiler.dotnet80ilcrossgen2.exe=/opt/compiler-explorer/dotnet-v8.0.5/.dotnet/dotnet
-compiler.dotnet80ilcrossgen2.name=.NET Crossgen2 8.0
-compiler.dotnet80ilcrossgen2.clrDir=/opt/compiler-explorer/dotnet-v8.0.5
+compiler.dotnet80ilcrossgen2.exe=/opt/compiler-explorer/dotnet-v8.0.11/.dotnet/dotnet
+compiler.dotnet80ilcrossgen2.name=.NET 8.0 Crossgen2
+compiler.dotnet80ilcrossgen2.clrDir=/opt/compiler-explorer/dotnet-v8.0.11
 compiler.dotnet80ilcrossgen2.buildConfig=Release
 compiler.dotnet80ilcrossgen2.langVersion=latest
 
+compiler.dotnet90ilcrossgen2.exe=/opt/compiler-explorer/dotnet-v9.0.0/.dotnet/dotnet
+compiler.dotnet90ilcrossgen2.name=.NET 9.0 Crossgen2
+compiler.dotnet90ilcrossgen2.clrDir=/opt/compiler-explorer/dotnet-v9.0.0
+compiler.dotnet90ilcrossgen2.buildConfig=Release
+compiler.dotnet90ilcrossgen2.langVersion=latest
+
 compiler.dotnettrunkilcrossgen2.exe=/opt/compiler-explorer/dotnet-trunk/.dotnet/dotnet
-compiler.dotnettrunkilcrossgen2.name=.NET Crossgen2 (main)
+compiler.dotnettrunkilcrossgen2.name=.NET (main) Crossgen2
 compiler.dotnettrunkilcrossgen2.clrDir=/opt/compiler-explorer/dotnet-trunk
 compiler.dotnettrunkilcrossgen2.buildConfig=Release
 compiler.dotnettrunkilcrossgen2.langVersion=preview
@@ -79,8 +102,32 @@ compiler.dotnettrunkilcrossgen2.isNightly=true
 
 # Mono compilers
 
+compiler.dotnet60ilmono.exe=/opt/compiler-explorer/dotnet-v6.0.36/.dotnet/dotnet
+compiler.dotnet60ilmono.name=.NET 6.0 Mono
+compiler.dotnet60ilmono.clrDir=/opt/compiler-explorer/dotnet-v6.0.36
+compiler.dotnet60ilmono.buildConfig=Release
+compiler.dotnet60ilmono.langVersion=latest
+
+compiler.dotnet70ilmono.exe=/opt/compiler-explorer/dotnet-v7.0.20/.dotnet/dotnet
+compiler.dotnet70ilmono.name=.NET 7.0 Mono
+compiler.dotnet70ilmono.clrDir=/opt/compiler-explorer/dotnet-v7.0.20
+compiler.dotnet70ilmono.buildConfig=Release
+compiler.dotnet70ilmono.langVersion=latest
+
+compiler.dotnet80ilmono.exe=/opt/compiler-explorer/dotnet-v8.0.11/.dotnet/dotnet
+compiler.dotnet80ilmono.name=.NET 8.0 Mono
+compiler.dotnet80ilmono.clrDir=/opt/compiler-explorer/dotnet-v8.0.11
+compiler.dotnet80ilmono.buildConfig=Release
+compiler.dotnet80ilmono.langVersion=latest
+
+compiler.dotnet90ilmono.exe=/opt/compiler-explorer/dotnet-v9.0.0/.dotnet/dotnet
+compiler.dotnet90ilmono.name=.NET 9.0 Mono
+compiler.dotnet90ilmono.clrDir=/opt/compiler-explorer/dotnet-v9.0.0
+compiler.dotnet90ilmono.buildConfig=Release
+compiler.dotnet90ilmono.langVersion=latest
+
 compiler.dotnettrunkilmono.exe=/opt/compiler-explorer/dotnet-trunk/.dotnet/dotnet
-compiler.dotnettrunkilmono.name=.NET Mono (main)
+compiler.dotnettrunkilmono.name=.NET (main) Mono
 compiler.dotnettrunkilmono.clrDir=/opt/compiler-explorer/dotnet-trunk
 compiler.dotnettrunkilmono.buildConfig=Release
 compiler.dotnettrunkilmono.langVersion=preview
@@ -89,17 +136,74 @@ compiler.dotnettrunkilmono.isNightly=true
 # NativeAOT compilers
 
 compiler.dotnettrunkilnativeaot.exe=/opt/compiler-explorer/dotnet-trunk/.dotnet/dotnet
-compiler.dotnettrunkilnativeaot.name=.NET NativeAOT (main)
+compiler.dotnettrunkilnativeaot.name=.NET (main) NativeAOT
 compiler.dotnettrunkilnativeaot.clrDir=/opt/compiler-explorer/dotnet-trunk
 compiler.dotnettrunkilnativeaot.buildConfig=Release
 compiler.dotnettrunkilnativeaot.langVersion=preview
 compiler.dotnettrunkilnativeaot.isNightly=true
 
-# IL disassembler compilers
+# ILDasm compilers
+
+compiler.dotnet60ilildasm.exe=/opt/compiler-explorer/dotnet-v6.0.36/.dotnet/dotnet
+compiler.dotnet60ilildasm.name=.NET 6.0 ILDasm
+compiler.dotnet60ilildasm.clrDir=/opt/compiler-explorer/dotnet-v6.0.36
+compiler.dotnet60ilildasm.buildConfig=Release
+compiler.dotnet60ilildasm.langVersion=latest
+
+compiler.dotnet70ilildasm.exe=/opt/compiler-explorer/dotnet-v7.0.20/.dotnet/dotnet
+compiler.dotnet70ilildasm.name=.NET 7.0 ILDasm
+compiler.dotnet70ilildasm.clrDir=/opt/compiler-explorer/dotnet-v7.0.20
+compiler.dotnet70ilildasm.buildConfig=Release
+compiler.dotnet70ilildasm.langVersion=latest
+
+compiler.dotnet80ilildasm.exe=/opt/compiler-explorer/dotnet-v8.0.11/.dotnet/dotnet
+compiler.dotnet80ilildasm.name=.NET 8.0 ILDasm
+compiler.dotnet80ilildasm.clrDir=/opt/compiler-explorer/dotnet-v8.0.11
+compiler.dotnet80ilildasm.buildConfig=Release
+compiler.dotnet80ilildasm.langVersion=latest
+
+compiler.dotnet90ilildasm.exe=/opt/compiler-explorer/dotnet-v9.0.0/.dotnet/dotnet
+compiler.dotnet90ilildasm.name=.NET 9.0 ILDasm
+compiler.dotnet90ilildasm.clrDir=/opt/compiler-explorer/dotnet-v9.0.0
+compiler.dotnet90ilildasm.buildConfig=Release
+compiler.dotnet90ilildasm.langVersion=latest
 
 compiler.dotnettrunkilildasm.exe=/opt/compiler-explorer/dotnet-trunk/.dotnet/dotnet
-compiler.dotnettrunkilildasm.name=.NET IL Disassembler (main)
+compiler.dotnettrunkilildasm.name=.NET (main) ILDasm
 compiler.dotnettrunkilildasm.clrDir=/opt/compiler-explorer/dotnet-trunk
 compiler.dotnettrunkilildasm.buildConfig=Release
 compiler.dotnettrunkilildasm.langVersion=preview
 compiler.dotnettrunkilildasm.isNightly=true
+
+# ILSpy compilers
+
+compiler.dotnet60ililspy.exe=/opt/compiler-explorer/dotnet-v6.0.36/.dotnet/dotnet
+compiler.dotnet60ililspy.name=.NET 6.0 ILSpy
+compiler.dotnet60ililspy.clrDir=/opt/compiler-explorer/dotnet-v6.0.36
+compiler.dotnet60ililspy.buildConfig=Release
+compiler.dotnet60ililspy.langVersion=latest
+
+compiler.dotnet70ililspy.exe=/opt/compiler-explorer/dotnet-v7.0.20/.dotnet/dotnet
+compiler.dotnet70ililspy.name=.NET 7.0 ILSpy
+compiler.dotnet70ililspy.clrDir=/opt/compiler-explorer/dotnet-v7.0.20
+compiler.dotnet70ililspy.buildConfig=Release
+compiler.dotnet70ililspy.langVersion=latest
+
+compiler.dotnet80ililspy.exe=/opt/compiler-explorer/dotnet-v8.0.11/.dotnet/dotnet
+compiler.dotnet80ililspy.name=.NET 8.0 ILSpy
+compiler.dotnet80ililspy.clrDir=/opt/compiler-explorer/dotnet-v8.0.11
+compiler.dotnet80ililspy.buildConfig=Release
+compiler.dotnet80ililspy.langVersion=latest
+
+compiler.dotnet90ililspy.exe=/opt/compiler-explorer/dotnet-v9.0.0/.dotnet/dotnet
+compiler.dotnet90ililspy.name=.NET 9.0 ILSpy
+compiler.dotnet90ililspy.clrDir=/opt/compiler-explorer/dotnet-v9.0.0
+compiler.dotnet90ililspy.buildConfig=Release
+compiler.dotnet90ililspy.langVersion=latest
+
+compiler.dotnettrunkililspy.exe=/opt/compiler-explorer/dotnet-trunk/.dotnet/dotnet
+compiler.dotnettrunkililspy.name=.NET (main) ILSpy
+compiler.dotnettrunkililspy.clrDir=/opt/compiler-explorer/dotnet-trunk
+compiler.dotnettrunkililspy.buildConfig=Release
+compiler.dotnettrunkililspy.langVersion=preview
+compiler.dotnettrunkililspy.isNightly=true
diff --git a/etc/config/il.defaults.properties b/etc/config/il.defaults.properties
index 53ffa53ae..81fe840ff 100644
--- a/etc/config/il.defaults.properties
+++ b/etc/config/il.defaults.properties
@@ -1,20 +1,20 @@
-compilers=&dotnetcoreclr:&dotnetcrossgen2:&dotnetmono:&dotnetnativeaot:&dotnetildasm
+compilers=&dotnetcoreclr:&dotnetcrossgen2:&dotnetmono:&dotnetnativeaot:&dotnetildasm:&dotnetilspy
 supportsBinary=true
 needsMulti=false
-defaultCompiler=dotnet80ilcoreclr
+defaultCompiler=dotnet90ilcoreclr
 executionEnvironmentClass=local-dotnet
 
-group.dotnetcoreclr.compilers=dotnettrunkilcoreclr:dotnet80ilcoreclr:dotnet70ilcoreclr
+group.dotnetcoreclr.compilers=dotnettrunkilcoreclr:dotnet90ilcoreclr:dotnet80ilcoreclr:dotnet70ilcoreclr:dotnet60ilcoreclr
 group.dotnetcoreclr.compilerCategories=coreclr
 group.dotnetcoreclr.compilerType=dotnetcoreclr
 group.dotnetcoreclr.groupName=.NET CoreCLR
 
-group.dotnetcrossgen2.compilers=dotnettrunkilcrossgen2:dotnet80ilcrossgen2:dotnet70ilcrossgen2:dotnet60ilcrossgen2
+group.dotnetcrossgen2.compilers=dotnettrunkilcrossgen2:dotnet90ilcrossgen2:dotnet80ilcrossgen2:dotnet70ilcrossgen2:dotnet60ilcrossgen2
 group.dotnetcrossgen2.compilerCategories=crossgen2
 group.dotnetcrossgen2.compilerType=dotnetcrossgen2
 group.dotnetcrossgen2.groupName=.NET Crossgen2
 
-group.dotnetmono.compilers=dotnettrunkilmono
+group.dotnetmono.compilers=dotnettrunkilmono:dotnet90ilmono:dotnet80ilmono:dotnet70ilmono:dotnet60ilmono
 group.dotnetmono.compilerCategories=mono
 group.dotnetmono.compilerType=dotnetmono
 group.dotnetmono.groupName=.NET Mono
@@ -24,27 +24,44 @@ group.dotnetnativeaot.compilerCategories=nativeaot
 group.dotnetnativeaot.compilerType=dotnetnativeaot
 group.dotnetnativeaot.groupName=.NET NativeAOT
 
-group.dotnetildasm.compilers=dotnettrunkilildasm
+group.dotnetildasm.compilers=dotnettrunkilildasm:dotnet90ilildasm:dotnet80ilildasm:dotnet70ilildasm:dotnet60ilildasm
 group.dotnetildasm.compilerCategories=ildasm
 group.dotnetildasm.compilerType=dotnetildasm
-group.dotnetildasm.groupName=.NET IL Disassembler
+group.dotnetildasm.groupName=.NET ILDasm
+
+group.dotnetilspy.compilers=dotnettrunkililspy:dotnet90ililspy:dotnet80ililspy:dotnet70ililspy:dotnet60ililspy
+group.dotnetilspy.compilerCategories=ilspy
+group.dotnetilspy.compilerType=dotnetilspy
+group.dotnetilspy.groupName=.NET ILSpy
 
 # CoreCLR compilers
 
-compiler.dotnet70ilcoreclr.exe=/opt/compiler-explorer/dotnet-v7.0.19/.dotnet/dotnet
-compiler.dotnet70ilcoreclr.name=.NET CoreCLR 7.0
-compiler.dotnet70ilcoreclr.clrDir=/opt/compiler-explorer/dotnet-v7.0.19
+compiler.dotnet60ilcoreclr.exe=/opt/compiler-explorer/dotnet-v6.0.36/.dotnet/dotnet
+compiler.dotnet60ilcoreclr.name=.NET 6.0 CoreCLR
+compiler.dotnet60ilcoreclr.clrDir=/opt/compiler-explorer/dotnet-v6.0.36
+compiler.dotnet60ilcoreclr.buildConfig=Release
+compiler.dotnet60ilcoreclr.langVersion=latest
+
+compiler.dotnet70ilcoreclr.exe=/opt/compiler-explorer/dotnet-v7.0.20/.dotnet/dotnet
+compiler.dotnet70ilcoreclr.name=.NET 7.0 CoreCLR
+compiler.dotnet70ilcoreclr.clrDir=/opt/compiler-explorer/dotnet-v7.0.20
 compiler.dotnet70ilcoreclr.buildConfig=Release
 compiler.dotnet70ilcoreclr.langVersion=latest
 
-compiler.dotnet80ilcoreclr.exe=/opt/compiler-explorer/dotnet-v8.0.5/.dotnet/dotnet
-compiler.dotnet80ilcoreclr.name=.NET CoreCLR 8.0
-compiler.dotnet80ilcoreclr.clrDir=/opt/compiler-explorer/dotnet-v8.0.5
+compiler.dotnet80ilcoreclr.exe=/opt/compiler-explorer/dotnet-v8.0.11/.dotnet/dotnet
+compiler.dotnet80ilcoreclr.name=.NET 8.0 CoreCLR
+compiler.dotnet80ilcoreclr.clrDir=/opt/compiler-explorer/dotnet-v8.0.11
 compiler.dotnet80ilcoreclr.buildConfig=Release
 compiler.dotnet80ilcoreclr.langVersion=latest
 
+compiler.dotnet90ilcoreclr.exe=/opt/compiler-explorer/dotnet-v9.0.0/.dotnet/dotnet
+compiler.dotnet90ilcoreclr.name=.NET 9.0 CoreCLR
+compiler.dotnet90ilcoreclr.clrDir=/opt/compiler-explorer/dotnet-v9.0.0
+compiler.dotnet90ilcoreclr.buildConfig=Release
+compiler.dotnet90ilcoreclr.langVersion=latest
+
 compiler.dotnettrunkilcoreclr.exe=/opt/compiler-explorer/dotnet-trunk/.dotnet/dotnet
-compiler.dotnettrunkilcoreclr.name=.NET CoreCLR (main)
+compiler.dotnettrunkilcoreclr.name=.NET (main) CoreCLR
 compiler.dotnettrunkilcoreclr.clrDir=/opt/compiler-explorer/dotnet-trunk
 compiler.dotnettrunkilcoreclr.buildConfig=Release
 compiler.dotnettrunkilcoreclr.langVersion=preview
@@ -52,26 +69,32 @@ compiler.dotnettrunkilcoreclr.isNightly=true
 
 # Crossgen2 compilers
 
-compiler.dotnet60ilcrossgen2.exe=/opt/compiler-explorer/dotnet-v6.0.30/.dotnet/dotnet
-compiler.dotnet60ilcrossgen2.name=.NET Crossgen2 6.0
-compiler.dotnet60ilcrossgen2.clrDir=/opt/compiler-explorer/dotnet-v6.0.30
+compiler.dotnet60ilcrossgen2.exe=/opt/compiler-explorer/dotnet-v6.0.36/.dotnet/dotnet
+compiler.dotnet60ilcrossgen2.name=.NET 6.0 Crossgen2
+compiler.dotnet60ilcrossgen2.clrDir=/opt/compiler-explorer/dotnet-v6.0.36
 compiler.dotnet60ilcrossgen2.buildConfig=Release
 compiler.dotnet60ilcrossgen2.langVersion=latest
 
-compiler.dotnet70ilcrossgen2.exe=/opt/compiler-explorer/dotnet-v7.0.19/.dotnet/dotnet
-compiler.dotnet70ilcrossgen2.name=.NET Crossgen2 7.0
-compiler.dotnet70ilcrossgen2.clrDir=/opt/compiler-explorer/dotnet-v7.0.19
+compiler.dotnet70ilcrossgen2.exe=/opt/compiler-explorer/dotnet-v7.0.20/.dotnet/dotnet
+compiler.dotnet70ilcrossgen2.name=.NET 7.0 Crossgen2
+compiler.dotnet70ilcrossgen2.clrDir=/opt/compiler-explorer/dotnet-v7.0.20
 compiler.dotnet70ilcrossgen2.buildConfig=Release
 compiler.dotnet70ilcrossgen2.langVersion=latest
 
-compiler.dotnet80ilcrossgen2.exe=/opt/compiler-explorer/dotnet-v8.0.5/.dotnet/dotnet
-compiler.dotnet80ilcrossgen2.name=.NET Crossgen2 8.0
-compiler.dotnet80ilcrossgen2.clrDir=/opt/compiler-explorer/dotnet-v8.0.5
+compiler.dotnet80ilcrossgen2.exe=/opt/compiler-explorer/dotnet-v8.0.11/.dotnet/dotnet
+compiler.dotnet80ilcrossgen2.name=.NET 8.0 Crossgen2
+compiler.dotnet80ilcrossgen2.clrDir=/opt/compiler-explorer/dotnet-v8.0.11
 compiler.dotnet80ilcrossgen2.buildConfig=Release
 compiler.dotnet80ilcrossgen2.langVersion=latest
 
+compiler.dotnet90ilcrossgen2.exe=/opt/compiler-explorer/dotnet-v9.0.0/.dotnet/dotnet
+compiler.dotnet90ilcrossgen2.name=.NET 9.0 Crossgen2
+compiler.dotnet90ilcrossgen2.clrDir=/opt/compiler-explorer/dotnet-v9.0.0
+compiler.dotnet90ilcrossgen2.buildConfig=Release
+compiler.dotnet90ilcrossgen2.langVersion=latest
+
 compiler.dotnettrunkilcrossgen2.exe=/opt/compiler-explorer/dotnet-trunk/.dotnet/dotnet
-compiler.dotnettrunkilcrossgen2.name=.NET Crossgen2 (main)
+compiler.dotnettrunkilcrossgen2.name=.NET (main) Crossgen2
 compiler.dotnettrunkilcrossgen2.clrDir=/opt/compiler-explorer/dotnet-trunk
 compiler.dotnettrunkilcrossgen2.buildConfig=Release
 compiler.dotnettrunkilcrossgen2.langVersion=preview
@@ -79,8 +102,32 @@ compiler.dotnettrunkilcrossgen2.isNightly=true
 
 # Mono compilers
 
+compiler.dotnet60ilmono.exe=/opt/compiler-explorer/dotnet-v6.0.36/.dotnet/dotnet
+compiler.dotnet60ilmono.name=.NET 6.0 Mono
+compiler.dotnet60ilmono.clrDir=/opt/compiler-explorer/dotnet-v6.0.36
+compiler.dotnet60ilmono.buildConfig=Release
+compiler.dotnet60ilmono.langVersion=latest
+
+compiler.dotnet70ilmono.exe=/opt/compiler-explorer/dotnet-v7.0.20/.dotnet/dotnet
+compiler.dotnet70ilmono.name=.NET 7.0 Mono
+compiler.dotnet70ilmono.clrDir=/opt/compiler-explorer/dotnet-v7.0.20
+compiler.dotnet70ilmono.buildConfig=Release
+compiler.dotnet70ilmono.langVersion=latest
+
+compiler.dotnet80ilmono.exe=/opt/compiler-explorer/dotnet-v8.0.11/.dotnet/dotnet
+compiler.dotnet80ilmono.name=.NET 8.0 Mono
+compiler.dotnet80ilmono.clrDir=/opt/compiler-explorer/dotnet-v8.0.11
+compiler.dotnet80ilmono.buildConfig=Release
+compiler.dotnet80ilmono.langVersion=latest
+
+compiler.dotnet90ilmono.exe=/opt/compiler-explorer/dotnet-v9.0.0/.dotnet/dotnet
+compiler.dotnet90ilmono.name=.NET 9.0 Mono
+compiler.dotnet90ilmono.clrDir=/opt/compiler-explorer/dotnet-v9.0.0
+compiler.dotnet90ilmono.buildConfig=Release
+compiler.dotnet90ilmono.langVersion=latest
+
 compiler.dotnettrunkilmono.exe=/opt/compiler-explorer/dotnet-trunk/.dotnet/dotnet
-compiler.dotnettrunkilmono.name=.NET Mono (main)
+compiler.dotnettrunkilmono.name=.NET (main) Mono
 compiler.dotnettrunkilmono.clrDir=/opt/compiler-explorer/dotnet-trunk
 compiler.dotnettrunkilmono.buildConfig=Release
 compiler.dotnettrunkilmono.langVersion=preview
@@ -89,17 +136,74 @@ compiler.dotnettrunkilmono.isNightly=true
 # NativeAOT compilers
 
 compiler.dotnettrunkilnativeaot.exe=/opt/compiler-explorer/dotnet-trunk/.dotnet/dotnet
-compiler.dotnettrunkilnativeaot.name=.NET NativeAOT (main)
+compiler.dotnettrunkilnativeaot.name=.NET (main) NativeAOT
 compiler.dotnettrunkilnativeaot.clrDir=/opt/compiler-explorer/dotnet-trunk
 compiler.dotnettrunkilnativeaot.buildConfig=Release
 compiler.dotnettrunkilnativeaot.langVersion=preview
 compiler.dotnettrunkilnativeaot.isNightly=true
 
-# IL disassembler compilers
+# ILDasm compilers
+
+compiler.dotnet60ilildasm.exe=/opt/compiler-explorer/dotnet-v6.0.36/.dotnet/dotnet
+compiler.dotnet60ilildasm.name=.NET 6.0 ILDasm
+compiler.dotnet60ilildasm.clrDir=/opt/compiler-explorer/dotnet-v6.0.36
+compiler.dotnet60ilildasm.buildConfig=Release
+compiler.dotnet60ilildasm.langVersion=latest
+
+compiler.dotnet70ilildasm.exe=/opt/compiler-explorer/dotnet-v7.0.20/.dotnet/dotnet
+compiler.dotnet70ilildasm.name=.NET 7.0 ILDasm
+compiler.dotnet70ilildasm.clrDir=/opt/compiler-explorer/dotnet-v7.0.20
+compiler.dotnet70ilildasm.buildConfig=Release
+compiler.dotnet70ilildasm.langVersion=latest
+
+compiler.dotnet80ilildasm.exe=/opt/compiler-explorer/dotnet-v8.0.11/.dotnet/dotnet
+compiler.dotnet80ilildasm.name=.NET 8.0 ILDasm
+compiler.dotnet80ilildasm.clrDir=/opt/compiler-explorer/dotnet-v8.0.11
+compiler.dotnet80ilildasm.buildConfig=Release
+compiler.dotnet80ilildasm.langVersion=latest
+
+compiler.dotnet90ilildasm.exe=/opt/compiler-explorer/dotnet-v9.0.0/.dotnet/dotnet
+compiler.dotnet90ilildasm.name=.NET 9.0 ILDasm
+compiler.dotnet90ilildasm.clrDir=/opt/compiler-explorer/dotnet-v9.0.0
+compiler.dotnet90ilildasm.buildConfig=Release
+compiler.dotnet90ilildasm.langVersion=latest
 
 compiler.dotnettrunkilildasm.exe=/opt/compiler-explorer/dotnet-trunk/.dotnet/dotnet
-compiler.dotnettrunkilildasm.name=.NET IL Disassembler (main)
+compiler.dotnettrunkilildasm.name=.NET (main) ILDasm
 compiler.dotnettrunkilildasm.clrDir=/opt/compiler-explorer/dotnet-trunk
 compiler.dotnettrunkilildasm.buildConfig=Release
 compiler.dotnettrunkilildasm.langVersion=preview
 compiler.dotnettrunkilildasm.isNightly=true
+
+# ILSpy compilers
+
+compiler.dotnet60ililspy.exe=/opt/compiler-explorer/dotnet-v6.0.36/.dotnet/dotnet
+compiler.dotnet60ililspy.name=.NET 6.0 ILSpy
+compiler.dotnet60ililspy.clrDir=/opt/compiler-explorer/dotnet-v6.0.36
+compiler.dotnet60ililspy.buildConfig=Release
+compiler.dotnet60ililspy.langVersion=latest
+
+compiler.dotnet70ililspy.exe=/opt/compiler-explorer/dotnet-v7.0.20/.dotnet/dotnet
+compiler.dotnet70ililspy.name=.NET 7.0 ILSpy
+compiler.dotnet70ililspy.clrDir=/opt/compiler-explorer/dotnet-v7.0.20
+compiler.dotnet70ililspy.buildConfig=Release
+compiler.dotnet70ililspy.langVersion=latest
+
+compiler.dotnet80ililspy.exe=/opt/compiler-explorer/dotnet-v8.0.11/.dotnet/dotnet
+compiler.dotnet80ililspy.name=.NET 8.0 ILSpy
+compiler.dotnet80ililspy.clrDir=/opt/compiler-explorer/dotnet-v8.0.11
+compiler.dotnet80ililspy.buildConfig=Release
+compiler.dotnet80ililspy.langVersion=latest
+
+compiler.dotnet90ililspy.exe=/opt/compiler-explorer/dotnet-v9.0.0/.dotnet/dotnet
+compiler.dotnet90ililspy.name=.NET 9.0 ILSpy
+compiler.dotnet90ililspy.clrDir=/opt/compiler-explorer/dotnet-v9.0.0
+compiler.dotnet90ililspy.buildConfig=Release
+compiler.dotnet90ililspy.langVersion=latest
+
+compiler.dotnettrunkililspy.exe=/opt/compiler-explorer/dotnet-trunk/.dotnet/dotnet
+compiler.dotnettrunkililspy.name=.NET (main) ILSpy
+compiler.dotnettrunkililspy.clrDir=/opt/compiler-explorer/dotnet-trunk
+compiler.dotnettrunkililspy.buildConfig=Release
+compiler.dotnettrunkililspy.langVersion=preview
+compiler.dotnettrunkililspy.isNightly=true
diff --git a/etc/config/java.amazon.properties b/etc/config/java.amazon.properties
index 05d3bbe47..0bb2fb1ec 100644
--- a/etc/config/java.amazon.properties
+++ b/etc/config/java.amazon.properties
@@ -1,4 +1,4 @@
-compilers=&java8:&java9:&java10:&java11:&java12:&java13:&java14:&java15:&java16:&java17:&java18:&java19:&java20:&java21:&java22
+compilers=&java8:&java9:&java10:&java11:&java12:&java13:&java14:&java15:&java16:&java17:&java18:&java19:&java20:&java21:&java22:&java23
 compilerType=java
 versionFlag=-version
 defaultCompiler=java2102
@@ -133,9 +133,20 @@ compiler.java2102.exe=/opt/compiler-explorer/jdk-21.0.2/bin/javac
 compiler.java2102.runtime=/opt/compiler-explorer/jdk-21.0.2/bin/java
 compiler.java2102.semver=21.0.2
 
-group.java22.compilers=java2200
+group.java22.compilers=java2200:java2202
 group.java22.groupName=OpenJDK 22
 group.java22.objdumper=/opt/compiler-explorer/jdk-22.0.0/bin/javap
 compiler.java2200.exe=/opt/compiler-explorer/jdk-22.0.0/bin/javac
 compiler.java2200.runtime=/opt/compiler-explorer/jdk-22.0.0/bin/java
 compiler.java2200.semver=22.0.0
+compiler.java2202.objdumper=/opt/compiler-explorer/jdk-22.0.2/bin/javap
+compiler.java2202.exe=/opt/compiler-explorer/jdk-22.0.2/bin/javac
+compiler.java2202.runtime=/opt/compiler-explorer/jdk-22.0.2/bin/java
+compiler.java2202.semver=22.0.2
+
+group.java23.compilers=java2301
+group.java23.groupName=OpenJDK 23
+group.java23.objdumper=/opt/compiler-explorer/jdk-23.0.1/bin/javap
+compiler.java2301.exe=/opt/compiler-explorer/jdk-23.0.1/bin/javac
+compiler.java2301.runtime=/opt/compiler-explorer/jdk-23.0.1/bin/java
+compiler.java2301.semver=23.0.1
diff --git a/etc/config/site-templates.conf b/etc/config/site-templates.conf
index 3ae57b057..c49abe710 100644
--- a/etc/config/site-templates.conf
+++ b/etc/config/site-templates.conf
@@ -1,11 +1,11 @@
-meta.screenshot_dimentions=1000x800
-Diff of Two Sources=https://godbolt.org/#z:OYLghAFBqd5TKALEBjA9gEwKYFFMCWALugE4A0BIEAZgQDbYB2AhgLbYgDkAjF%2BTXRMiAZVQtGIHgBYBQogFUAztgAKAD24AGfgCsp5eiyahUAUgBMAIUtXyKxqiIEh1ZpgDC6egFc2TA3cAGQImbAA5PwAjbFIQC3IAB3QlYhcmL19/A2TU5yEQsMi2GLiEh2wndJEiFlIiTL8AnntsR3ymGrqiQojo2Pj7WvrG7JalYZ7QvpKBiwBKe3QfUlROLksAZlDUXxwAajNNjwA3SpJSI9wzLQBBG9uT9AJMfcx0AH0ldA4PgHcyABrCChIjzI42O4PJ4vfaJUjoNZKJQfYjYNhKCAYJgTfYTTAgEBnJxkI4eUFXSwANn2xPmhwA7JDbvtWfsWD4SHiAF6HTYAEVplQAdKludgIODNsy2ftBKQIPjCWLsB8iPsCHzBVoIRq%2BR4ebqCLZbPSzEyHrLZe8vj9VQDSMDiWYAKxWY0u/lSmVs838h5%2Bh5cRb0bgu/gBLg6cjobgeE3WPHLVbYQ4WTZ8chEbTBxaAkAurSGbjSfhsAtFyPR2NcfhKEBF7NR4PkOCwFAYHD4YhkSjUOiMVgcbiZwTCMQSTgyOTCZRqTTN8j6BJGExoBN2CpVVwQdyjAIWFrBabFUogBlJFJpIT7%2BItXLXpi9U8DC9bjpdEbeJp31rtaqTM%2B/RxG%2Bky3oeQzdEBswgYs3wrGs3BbDseypmSxIXJSUJ3DCrw2t8vwOsCoLegGOHPK88KItgyKokQ6KYtiuJKkS5ykscFKbNcFg0nSjI%2Bqy8oQByXJomw%2BwgEKqBmhadxWmy%2BF2v8QIgvRbCkXJvoMv6ULaUGIZhhGOYxnGG5JghaHphY/BNjo8yLEg2AsDgcSSsWXCluQ5aFuQVb8DWdYNlmOb2eQ%2BbSC6wpUgAnDw0VaFSWhaC6FiHtFmzuZsRmLgFwXNosbbIGgPyJAwsR9liJVlXEuzGMAPCbFoLQDvRpD1hAUTGVEoR1AAniO/AYGwHDCAA8kw9D9YuOBsHVkjTQQpDnAQZz1ou2DqJUnLrJmoJtMZ9AEFEpB9V4ODGUQpAEOWvAtjQRjAEoABqBDYH8o2JMwA0zqI4iSNOY6KCoGjGfoLSrqYG6GEd9aQIs6CJB0a0ALSjVlf7LTue7fmM5DHkUwE5FeHS3vexPpNBZ7jG0mOdGBOPNBj2501BJ6E%2BM9NZIzEyswTMFSHByaIS0l3YDtLahlw4a%2BcZNbqAAHFSyNUtI%2By1SY%2BwNcKWjCjw%2BwQPG1i2OQ%2BzdhcaYZibXhsKVjCkBbPDzDZIWth2VV2xVQ22wM6v1Y1zUMK17WdYu3WsKQU2ZkNI1EONk3GTNc3rNGhBLVUq3GRtW30d9e2S9Gh3HadWDJzZV03Xwiz3Swj0vW9H1fbdP0Tv9siA3OIOLsuhh1euRvWNDUSw25CNI9wqPo%2B%2B6RuEwngM4Es%2BUwMZN5OkpOXqvBRs/z1P/kIn4NPPu%2B0wfS9xBz3Trzz9RnwLSwWYMoviwZUvZdW3AK0rKtqxDmubNrut9aGxsAPU2hBzZbASPsa23t7aQKdnlOyrsQCEBoDQCqgMW5TjbvIDuC4C5IHrODQhqCaBEF6p9IKpBCGDGoUoUh5DKFaBftLPyJkuD8gIGg/Ydc/ixH2J/ZWqtfZ/wAXrE4SgBGKyET/OqoidaZlsrmcgjlnIDDcvmF00hhSNXllodK0VorSAZAyPRDIqTuU8uWHgSUZY5W4IFBISjQqS2snY9%2BtZEHKLOG1ae0ggA
-Diff of Two Compilers=https://godbolt.org/#z:OYLghAFBqd5QCxAYwPYBMCmBRdBLAF1QCcAaPECAMzwBtMA7AQwFtMQByARg9KtQYEAysib0QXACx8BBAKoBnTAAUAHpwAMvAFYTStJg1DIApACYAQuYukl9ZATwDKjdAGFUtAK4sGIM6SuADJ4DJgAcj4ARpjEINIADqgKhE4MHt6%2B/qRJKY4CIWGRLDFx0naYDmlCBEzEBBk%2BfgEVVQI1dQSFEdGx8ba19Y1ZLYNdoT0lfZIAlLaoXsTI7BwA9KsA1AAqAJ4JmBs7C8QbaFgbCLGYpBskG7SoTOgbhhuYqqwJ9AB0JhoAgqECBsFABHLx1TAQIEbBg%2BGYbEwAdisAI26I2xEwBEWDFhPg2ACp8SwTABmVH/ZEAEQ4c1onAArLw/BwtKRUJw3NZrCDjstEWYyTxSARNHS5gBrECMjT6TiSFnijmcXgKEBysVsumkOCwJBoFgJOixciUQ3G%2BhxYBcMxcPh0AixdUQKLKqKhOo7Tgiw1sQQAeQYtG92tIWBYhmA4jD%2BCxVQAbph1WH3pUvE6fbwgZgGWHaHgosQvR4sMqCMQ8Cws3MqAZgAoAGp4TAAdwD%2B1ZIv4ghEYnYUhkgkUKnUYd09oMRhQPMs%2BkL6sgc1QCXyDBTAFoA2SNhvI0sEOTqQpJTsDJLMGrc5U1y4GO5PE09MEJsVSnpcqkBMM/PbP2vujfPp7VaNcOiGR8shA682gYcDxiKXo4hAsYfz0BQxkApCJDmBR%2BQHUUsRWHh6SZJUw05DhVAADgANg3WjJA2YBkGQDZbW%2BLgNggblLGsG5cEIO5zGFG4PCNE0ThErgZl4LUtDmCADVQCSrTNCALUklApxtSQNDlGhaCdYgXTdMMPWYYhQ19FT/QIIMQ2VCMoxjdk4xvPAkxTdk02QDNiOzQRc2VAsixLDAVnZCsqxrPh6ybFt207LMh2EURxEHHt5CUNRlV0AIdJnPi51CxcIGXVc0k3bdd33ZBDzJY9T3PS9bBg28IFcND7RfRCpmQnJki/dJIN/Qa8jSLD%2BvQ9rqlQ0aZvsMDMNfbCUM6bqBk6Kb3xk%2BZFmWPQK0wALSI4ZlSFZdlKJo%2BjGNOHT2Mkb4NBe7jeKsOcNkEogpKFe0NnEy1YkFMkzFk0VxUUpB8CoKh1KyvsMukLKR1y/MEHVSdMdhqgCD2dg5WITHsmJhRcfx/YNTOi6rt4SjqTwOGNmbNsQduhimJYtiOK4hMFA2Dn7uQR6pBel65KhqUZTlPNFUu5VKLVbJ5IleUODMcjrtVSHtRmOYkxMtJ4iAA
-C++ Cmake=https://godbolt.org/#z:OYLghAFBqd5QCxAFwE4FN0BoCWIIDGAtgIYDW6AgqsAM4gDkAtACIDCAspQNICiA%2BgCEAqgEkAMi34AVAJoAFXgFIAzCwBK6ADYB1HMgQt0AI1EA7AGYB7BlgJWiABxxb0qcSTPAAriWDpRABMQAiUAJkFwwTtvWmQHAHlvZEdkgDEXdDMSInQUBHR%2BdAAPdAJkkmNXLAtM%2Blh0QP0rVCCQADYazLaARgAWLtds3JBSHDMAOgJHRyxQBlscWnMCLW9AxsYABkXaDhJxgGUrb1QCPIYe3YTHLO3bLU9gNoWASiwIRubW4J7BgN%2BAFZ/sM8pxyOhxEtkLQJshisg5oxHKgrAArMrICC0BAkW60V5KLaUImUYgQ/hEcY4IjeIj8DAAR28OAwgQgADVeOpDqIEgA5ADUKgmgMJxNJJECgSKpXKyEqrmxuPxzJIGFJgq1gpxePQtAA9ARWat0FMZprtbr8QaMAQFV5XObHJatWNJtNHOKScSFTR0Mh%2BFpxmQgzhjKh1Th9cq9bQ1RridrBRYiMhAt7dis1htggwdrg9gczMdTud7oWbnd8w8nm1yRR3p8mvEfiAwv9ep1akMcnkMLQTmd9QaClotFY4QikQxSQAJbQTrCCgDuLS0gTAYFJpKYe6YpOkBUFvDMgVJWbMq3Wmxrhf2RyH5cu11uZgrjy89aiUSbX1bbQqJ2vwAJwgn2IA4JOnozpe165hWSwPiWT4XFclZvh%2BdZ5gwf4ti0bQDD2ALtls4EjFBEwILBhbZjeeYFkhxalsOjDoUsVbvnen7PDhrzvEs4IUPIqIYvaFZoiAfxmOgK4ZK4bRhD07xaIwgK2FxBZWIw0gYOggrhCo6HIPc/FYGQpGin0ADsIF9ICYRbICNl2c5WCqQwfQaRW2kLFg9BkSZNZNjAUChRASD2BsvD4aguD4MRoKjMWzo1FYZjIIcBAkK4UlEelyDCLQ6DyMUEkdO5TwhD%2BET%2BdomJQe%2BnxnmwVhrEQ749J0WSBFCMn8nSxhuCAQGOFYtD6I1rXtZ1nRjRNyCNX16ADUQQ2oCNdWuPajWHH6yDTXSs1bQ16V7eqyDLat62bXEF2HR1UmdHdqCXeMK2DcNKjvIOZYXIZ4zwfpqhsKmyBGi0ZoIKoygShKYQqIDObA2EYSUdDqM7sS4zIIK7oQK8BnWZESbamDIAgCiOMQOEYTyfp9gZVkMIgEogJsGYSjE1zLC08u/iBoEJAKgThIqCTJLWbzxK4e5aneXe2nuqlQU7E2kVWNFsXxRAiUQUJkLQrC8KItYGVZTleT9GlGVFSVZV3pJfw8SEpAUCdO3pfgPUPZ1WA9Vdn0bT0fzzZN6W%2B1JWBh4t6WB2tw0hx7sclvtkd/MV20p%2Bdr3xzdScvQdbVHVHhd54nyn%2BahjANoUVJmDSdIMugzKso0nLcryArCqK3qkii6KYrG%2BJ98SUoyiUZQVFU6AQAYhST/KiroK6gqUZ6q/K56o%2BUH6AthmYobBhGUYxvPspTwqM%2Br2DGYXip8tYJptjaQbUJxMb06q7LEUhJr6AxW%2BDrPWIwByoUNGOCcU5TYFQtrla2ZtCrFVKuVDsLtQgRCiMnRq3sWrF0en8AO71rrDTmuNcOZh07R3ISncuG1nr1U9qne6%2BC/aZ1Osw3OxCg4VULlQsu3CE70J%2BtXWcxIFzjisMuNcqANxbixpQfcB5iRHn0qec8MsH4MHUk/HyIAwF/QgYuScJssDf3Vn/LWQC8C60yEldeMwbaZWyvA/KttkEOwLJJIC6CarRHYUw3BgQqFEP6jwsCMcpqsKjpEuOgibpgQCdnNO0SM6MOSRdOhIBEkpJmqXfaWSQIiL%2BowAGV5kYGRUKDOIGAcgwx3AjJGN5KlsBqeMYA9S4aUDiMEEAbSvCCn3kLEWhMuYS2TD0imOALA1PQDkNeMyaaowMcOIxkjoG0zFuM7UsR2mClELjVQLAdTpimbMnIxhvAWH4PoNwwsWggwILiVA9TxarwwMgU4ZgTm9P6cACAByIDTIJMuQF/FVASx5vfOW2iFZaUgtBRx5iPgaysa2YBdiILoycXAq2bikH23KgMXxmDapJJwc1YJqT/ZnkKdQhaUS8mhxoUteJw1EnpN2rkkuaSs5csyWyjaOSWFMv8gUwV2TimsVnI0iwZ50AWEFGkBICR%2BBzgaSoDYtQZJKpVWqhRZSgYtL%2BZ0n03TTl9LQHsoZwsSAEwhQahGPVpnQo8jo5%2BWBtLYvMe8AoUphoE3MiAPoAAOCYfQI2RqjVGmFXksBEBAICMiHrfK2ACmY0yHxwrhQ1k4TIcUbH2Dza4DawAehbCAj2ZAbh6AQGMBWYw4x1QAE82K2EbdkVAzaEjGDEkFdCRbcgZQSGYLQra7wbEucANgOUtD0BfFgDYpBHQXALE0O0i0ABu%2BoKyL2SGhRYTMPIFmPpGLtrUNgVitQml87wLCPDoByaMK5OJtpxS4vFTi7YoMdptElkRarH3qFAJKYMsDbo2gwayPQVC4XeFYRwKd51MB6UcjBAHBCOUFEwBIKhsP3viC/CDqAcAbGAz9TlXtKUhNpRK5lDKI7UtiWYLJvKOE5yLqK8lZ1xVhKEfkkVPKxUCr4/nd4aBMBSS0e6vRDBBTFBDe0Jg7Q%2BiDIIAQQU5aJh4YgLpTABkEbKVsD6rAfqNgbUDRZQEIpnLtC2CBECYQQJbGsiGrYMHiWMDjQmvoWwrIhpUL55yAWgudBTYwNNIBAqZrgLAJAJwUjJGAbAj9eUv0ePKkBCT6BSNRxXJGRwbbpNwpfowJIiXcZWEVQppTKm1Maa0zp1qxa3AGZUN9YzplfVzPM/gLR3n2ztAmCHALYR2gjZUGNnoHZwt%2BXTci2LiAQB7vRTY9UdB5CeG0IcBAVgVweqLc4R4KdNsyS0DtvbXEB0OCO8NMt027A3fzfyCCflDv5vKxd/bb7F7UDoPo/U4DRzGOgf7OUe0mhcVsIg3FaXEHfs8bYJ2lUvDVVJdEID8AICgbTOB4aUGYNwc9YhxqyHUNqHQ1ELDOG8NMAIzYT1xHSM7sgO8VA3gMo0nQNIKwbVyNish6d7bu3vsLuy3lgrRWYUycVowXgcpkgtHk4p5TqngDqc0z0CYYRBQQDYH45cemUZGVeJ14K/XbAJva9p9rtu7d290bLubUWM3m6DYCLXgIvfe5997zoHlYOO/hX5EzFlbLhock5Fy9lHKAn94wMIlupJbGTbJs3astGJ6D6VkPXW8eoAml7PoQA%3D
-LLVM IR=https://godbolt.org/#g:!((g:!((g:!((h:codeEditor,i:(filename:'1',fontScale:14,fontUsePx:'0',j:1,lang:c%2B%2B,selection:(endColumn:18,endLineNumber:6,positionColumn:18,positionLineNumber:6,selectionStartColumn:18,selectionStartLineNumber:6,startColumn:18,startLineNumber:6),source:'int+sum(int*+arr,+int+n)+%7B%0A++++int+value+%3D+0%3B%0A++++for(int+i+%3D+0%3B+i+%3C+n%3B+i%2B%2B)+%7B%0A++++++++value+%2B%3D+arr%5Bi%5D%3B%0A++++%7D%0A++++return+value%3B%0A%7D'),l:'5',n:'0',o:'C%2B%2B+source+%231',t:'0')),k:25.411059109631243,l:'4',n:'0',o:'',s:0,t:'0'),(g:!((h:ir,i:(compilerName:'x86-64+clang+14.0.0',editorid:1,fontScale:14,fontUsePx:'0',j:1,selection:(endColumn:1,endLineNumber:1,positionColumn:1,positionLineNumber:1,selectionStartColumn:1,selectionStartLineNumber:1,startColumn:1,startLineNumber:1),treeid:'1'),l:'5',n:'0',o:'LLVM+IR+Viewer+x86-64+clang+14.0.0+(Editor+%231,+Compiler+%231)',t:'0')),header:(),k:42.23569365874194,l:'4',n:'0',o:'',s:0,t:'0'),(g:!((h:compiler,i:(compiler:clang1400,filters:(b:'0',binary:'1',commentOnly:'0',demangle:'0',directives:'0',execute:'1',intel:'0',libraryCode:'0',trim:'1'),flagsViewOpen:'1',fontScale:14,fontUsePx:'0',j:1,lang:c%2B%2B,libs:!(),options:'-O3+-march%3Dskylake',selection:(endColumn:1,endLineNumber:1,positionColumn:1,positionLineNumber:1,selectionStartColumn:1,selectionStartLineNumber:1,startColumn:1,startLineNumber:1),source:1,tree:'1'),l:'5',n:'0',o:'x86-64+clang+14.0.0+(C%2B%2B,+Editor+%231,+Compiler+%231)',t:'0')),k:32.353247231626824,l:'4',n:'0',o:'',s:0,t:'0')),l:'2',n:'0',o:'',t:'0')),version:4
-Preprocessor=https://godbolt.org/#g:!((g:!((g:!((h:codeEditor,i:(filename:'1',fontScale:14,fontUsePx:'0',j:1,lang:c%2B%2B,selection:(endColumn:1,endLineNumber:6,positionColumn:1,positionLineNumber:6,selectionStartColumn:1,selectionStartLineNumber:6,startColumn:1,startLineNumber:6),source:'%23define+MUL(x,+y)+(x+*+y)+%0A%0Aint+mystery(int+a,+int+b)+%7B%0A++++return+MUL(a+%2B+b,+2)%3B%0A%7D%0A'),l:'5',n:'0',o:'C%2B%2B+source+%231',t:'0')),k:30.466941342614383,l:'4',n:'0',o:'',s:0,t:'0'),(g:!((h:pp,i:(clang-format:'1',editorid:1,filter-headers:'0',fontScale:14,fontUsePx:'0',j:1,treeid:'1'),l:'5',n:'0',o:'Preprocessor+Output+x86-64+clang+14.0.0+(Editor+%231,+Compiler+%231)',t:'0')),header:(),k:42.496476357000276,l:'4',n:'0',o:'',s:0,t:'0'),(g:!((h:compiler,i:(compiler:clang1400,filters:(b:'0',binary:'1',commentOnly:'0',demangle:'0',directives:'0',execute:'1',intel:'0',libraryCode:'0',trim:'1'),flagsViewOpen:'1',fontScale:14,fontUsePx:'0',j:1,lang:c%2B%2B,libs:!(),options:'',selection:(endColumn:1,endLineNumber:1,positionColumn:1,positionLineNumber:1,selectionStartColumn:1,selectionStartLineNumber:1,startColumn:1,startLineNumber:1),source:1,tree:'1'),l:'5',n:'0',o:'x86-64+clang+14.0.0+(C%2B%2B,+Editor+%231,+Compiler+%231)',t:'0')),k:27.036582300385337,l:'4',m:100,n:'0',o:'',s:0,t:'0')),l:'2',n:'0',o:'',t:'0')),version:4
-Pascal IDE=https://godbolt.org/#z:OYLghAFBqd5TKALEAXATgU0wGgJYgQDGAtgIYDWmAgusAM4gDkTORA9iQA54A2m6ADJkAdsACuZYJgCSAExBcy9ImV5tx9VJwDy41F30AxPphFkSmZqwBmpxrExy829PJABaAIw47/dwBMvqbmliDkqEg24iJE9AD0EVExcQB0SvQ4oEwxLgDUSdGx9ACkAMwAQiUADNQ11HgiqAI2ZESY9fWamKW1ef0FZJFFcY2oNuVVtfWoAJ5cHX0DACoAskNIRin0eeUAInlEvMr0EMsyTS1tTjoARgBWmESoOHky65FbxQCU9QN5hluvDwRD%2B/wGI1QeHYIjyAGUAI6SLDEGFaPIicQkEBvS7SdDfHEXZr4yZg/pmORk6a1PDcfiWJpDaEiTq1SEsvJrDZfNKI5GYVEidGY7G4kkCQnizCkyr1W4yxrk%2BFIshYPIgfYYrF5ABU2pI1OolKN9UpqXqrDw9AuR3EciczGqVvo60acPY4nQ7WYXhdOgWIl9rGOYncGVUvG%2BOAgThc7DcCiCflkCjKwX4oSsmAAHhYuPxUnIuOgstZ8DbYrx7Y6mM6K26RB6vT66/7A06Q6JgO4WNHY85XO50yn3AAWDNmCxWQrbRIbEb0MY2dLKMssCu26sOhRthtkd2e71WJh%2BisBsydnChnu7pjfaPWgDC6yoAAV0OxHs9gzh7iAfBETAAHcTH8BQAFZo14ZgINYIM93YZhliwTBdgCMoz1QTsHxwCgQDKCDUmqMcAE4ADYAA4ymo6ovAAdi8ciJxgpgx3gq8kI3RhqhwbC237RAIBQDgHQAUUHBN8EIFMsxAXN80LYtSxsGFUDhSMrC8CdVKaABVehMDfHMr3/IIb0UZRIxwQz%2BGeFlCEpJ92GrEggx8SlBEaTAADksQVdAAIgnAuHYJcoRhZzXPckKwpcFkvKAvySACoKbMwOyIqbVA1VQKKsRi2yniyuEcvQVBEt8/yBDSrRcvytyAJssqKu85LUq8KCbKPVsS3YYB0AsPIFPpDo5Rpahul6ah/lnYplzyRo8jAJg5riedhm2ZdV3oFacGVNadiWlbDo25Jih2lbTVqAA3NVlV5RguQ%2BTZtiNBVgCVJZ%2BgAdXQFxMEEEQIBWgAJDLeHYV4foTXg5DABH72umaBkejUtW5T5tlSJ8sCGMaphR/oxJzFxnIddGygOR7Un5NVBTKX5xuNEQ5AtWp72vWCOMQ%2BS81GosSz4nCYxE9hxMk0sCAgWTp3CBc50O7aMl8NSNLULSdLUgyjJMvd/3TCyIzUdLMoc2NWYamLPLa6rAonULwpZK2msd%2BKYUq9qaonIr7JhUr6pcgqmt9kqWs9u2QB9lqXZ8OryojlLvejegepPXJUEGTb5qaCZmfqMYrnaNlqDmBZlXeHltl2KnFsudBWmL77wRKCCKiu%2BiKjIMgyiIW4AkozAPDKMpqluDwxy8UivA8MhKLHjwiFImxOv7mw5Ho0iqXovYrogvYS/BCEUiylUBSFEUsSJPFJWviV0CNf4TXz2lRsZHKspL81OdYuCcAQ%2BsSFTpK1zjtYWAloxIEwGQB0gUIDRnwsxVIpEILVEwuRJipFKID0IlzNirBsReGqLxABrAuKsB4uA50uFWIBAISAeiARiIQUotgwiARSKTwYvRf%2BnFyz8WoTGISKBcxPH0FJaWaoGBvlEBlOESB2DAQQmeDg3A%2BDMhhDIoCvB5GKOUawVRPB%2BCBRsFwIgZQAhBEMaYdAeh1IKKUb%2BURRBaAMHLM40qzgEK2DVppACWt9KGWMqZJqRsrIm2BLcBw8CcDsC4FlRgTAPCrD2BlLgSA8AULTr%2BLQXitFyIcfoviqEmrAUGlwYM0Fua8N5kwEmYjXB5BzJRciHhmJ5FMUQPIZRUhMICHkCAMiVAmy5KhdCmFvisAEfeSB0DYGECqfgnA2IAj0WQVw%2BizF6LVBYWw8iNTAHlkodMmhzAyg80ORuE50YboCCXDCKOQA%3D%3D
-Java IDE=https://godbolt.org/#g:!((g:!((g:!((h:tree,i:(cmakeArgs:'',compilerLanguageId:java,customOutputFilename:'',files:!((editorId:1,fileId:1,filename:shapes/Square.java,g:'',isIncluded:'0',isMainSource:'1',isOpen:'0',langId:''),(editorId:2,fileId:2,filename:example.java,g:'package+myapp%3B%0A%0Apublic+class+example+%7B%0A%0A%7D',isIncluded:'0',isMainSource:'0',isOpen:'0',langId:java)),isCMakeProject:'1',j:1,newFileId:5),l:'5',n:'0',o:'Tree+%231',t:'0')),header:(),k:29.896907216494846,l:'4',n:'0',o:'',s:0,t:'0'),(g:!((g:!((h:codeEditor,i:(filename:shapes/Square.java,fontScale:14,fontUsePx:'0',j:1,lang:java,selection:(endColumn:1,endLineNumber:1,positionColumn:1,positionLineNumber:1,selectionStartColumn:1,selectionStartLineNumber:1,startColumn:1,startLineNumber:1),source:'package+shapes%3B%0A%0Apublic+class+Square+%7B%0A++++public+int+square(int+num)+%7B%0A++++++++return+num+*+num%3B%0A++++%7D%0A%7D%0A'),l:'5',n:'0',o:shapes/Square.java,t:'0'),(h:codeEditor,i:(filename:example.java,fontScale:14,fontUsePx:'0',j:2,lang:java,selection:(endColumn:1,endLineNumber:2,positionColumn:1,positionLineNumber:2,selectionStartColumn:1,selectionStartLineNumber:2,startColumn:1,startLineNumber:2),source:'import+shapes.*%3B%0A%0Aclass+Main+%7B%0A++++public+static+void+main(String%5B%5D+args)+%7B%0A++++++++Square+sq+%3D+new+Square()%3B%0A++++++++int+val+%3D+sq.square(args.length)%3B%0A++++++++System.out.println(%22Answer:+%22+%2B+Integer.toString(val))%3B%0A++++%7D%0A%7D'),l:'5',n:'0',o:example.java,t:'0')),k:80.08193737395916,l:'4',m:60.81932773109243,n:'0',o:'',s:1,t:'0'),(g:!((h:executor,i:(argsPanelShown:'0',compilationPanelShown:'1',compiler:java1601,compilerOutShown:'0',execArgs:'hello+world',execStdin:'',fontScale:14,fontUsePx:'0',j:1,lang:java,libs:!(),options:'',source:'1',stdinPanelShown:'1',tree:1,wrap:'1'),l:'5',n:'0',o:'Executor+jdk+16.0.1+(Java,+Tree+%231)',t:'0')),header:(),l:'4',m:39.18067226890757,n:'0',o:'',s:0,t:'0')),k:70.10309278350515,l:'3',n:'0',o:'',t:'0')),l:'2',n:'0',o:'',t:'0')),version:4
-Ada IDE=https://godbolt.org/#z:OYLghAFBqd5QCxAFwE4FN0BoCWIIDGAtgIYDW6AgqsAM4gDkDWBA9kQA44A26qAMiQB2wAK4lg6AJIATECRkkWo2snYB5Ucg5aAYj3RCSRdI2YAzA/VjoZONalkgAjFku8nAJjcGjJkOgAHsYcvAB0CgBGWKBMuLRSQgTcojK2jAAMzDi0ALIkOEIAyqyiqASmDFnx6hyGmczcwsBOTACUWBC29qyOct7u0nIAzD68fqbmrKwRMrQxZvGJyanpVdl5BcWl5ZXOG7X161hNIq0MHV12Dk6jg04ALGOGxpPTs9GxG8spaXLHOXyhRKZQqjH2NTqQgaJ2a50u3RucgAtK57nIAKzPCYgQo6ZBhZCBZALBjOTzDACkGUoFIe1MozgynnpNO%2BSV%2Ba2qgK2IN24IOUIFsLOcgUJDaHRyAGF8hQAAqoVgAK3QBGQwuVLiwQnQAHd9B45AA2DrcRgY5jQ46sRgAFQw6AA1JSKRCNetJVgyC4ABxhB7OB4PACcxoyvoxAHZjc5hsNjSdGA9mEQXBkMjqYba4vRMx6spcYFBixAkGw0gBRa69XD4QY4qYzBTzKZCZBFAgkXguJ5t5AAVVo6HlgRhWu8p1A4qww946pwrGhXSEMmlrBSRGhrkMMn4hXQADlRERInwQN4OKxaPZF0J15vt1grzfkHf97rj6fz9452q30uRTICQqDIA%2BJ5Pn%2BC6AcBoEfkeJ5nqgF6zrBYEbhB2qqCByDwV%2BSEXh0tA7GCDB6vYCBOpQihhHaQTIAA%2BlI6iUsMABCTqcVxXEqM61EkLR9FMSx7EMgyHAkAQZASM6ujTE6OQMpx5iiEkAFCE6uQAJ4MboqkEE6ECUE6IBOokyDoJIqCsRxuimYa6AMXaWl1G0ToYMgZQaeZll8DZDK7k6cmsDZFxJgwlpZjaIBNrM8wFhcHQIOgCjnhAHQ%2BsMzhhMaYZxsanhBr6GaeIm5oMCmWBpp4GJhMyIbBsaDwZFGGLDL6ni%2BlF1Q5sweZYAlRbwGWIAVug1Y9KgdYQA2rwBMEnDhFEbhLh2XY9kGK3tkOI5jscWquFO8iKLO6Dzup%2BC7uBW4gBi3i7nhiHnlGz7XreS7XdCd2va%2B74Hvhz2nedd5AThn23b%2BZ3/iDaGPd%2ByEvdhoHg99SO4f9T0I0RJGVORyCUfxgnEsJNlOrxVE0XRxPMf5NJ45RwWk%2BTjOiTSHBKhUMhlM6lYLaEzqKTSnF2UFBhOS56C05QZ7AIUSlOocGkQLoWBmUIukGKrrqeHiWiEsS2ttFLnHyloDHwYZ2t2slTpCJjTrmEqRBBdMpnay6pWaTpelJIZoxBW0YAMFIpCSEbrOUIFvMhLwoVmhaVrZvNMfoB8A0NF6yWpch6XhZVabxmE0YZMarVMhiDyRhSibWj1iz9YNnSluWrBVjWU14DNvhzbFy39p23amJt/Y7aO44gKMR0zlBF0rmuGE3c4IZYA9GPwy4rgvu994L9uy9b%2BpcMEc4rgzzDYO7y4y9nzBOFH%2BeJ%2BoRfj5X0/cFr8fzjY6CuMURTAlU0YjTdi3FQHk0JoAkmEd6b/zCD5KyTkhLAI4uAmi8C%2BCIOpiJNiYk2aSWkpIJ0kRW5aRdqwBStB5YqTUneL2ul9KGWMqZdB1kQEiwcuLVy7l0CeVQN5dsvlUAUPlpxSgBADLMIEVZEyrEAAiToMjGyIZZOWQsuJ6gQAYQyQhWDIFgZA5iYRKyrgYuocwGteCGV0JKJ03BpgcBEVxAA4jw5WqsxEEHDjgtRnFAp2NYA4iO3EPJeSoh7DiHilGBW0vQpIUtAoszYmFcqkVa7MFtL3GQ0RBpJRSmkHO8cKqphAIGMIwwQwhl9FGX0ldcoxixGkrAvVZwgHzBnDKEMwiRmcMaXpnUoyeEGU1cKwxE7RTiI3OAsBm4gFKNoLQ002CcAMKgQ8c0GCBF9MaZETUnTACMHo8kYRPAWFWgPDafZVqjz2tUA6A1HQ4DkK4PUqASAcAFIU1JScGCaHmXo1g5gnSbO2bs/ZJBDmeGOYZdcyzeBCNdFlNozAcnegvCGIuWUKTlIxLGDI5Swx52KYMspUYQylRDAMkMGQQzDAyA075fVWnp09E3YaLdYV8EWewLgcKQBguQOSbwaQABuOAKgADUcD6kVsKdwFlUD0AgJEGEkRCggS0sKJZJh2zqCENwDVxw0ikBED2Q1OAMALmFegegxwghqi0JUbkAjyrVG4DgSIrzUBaXXGkGEaAcBpjJGFcwTQ6CSulUKINW01qD17NG6549DrNGOkoN1kRrC5wCepG1fUobQWXFdS%2BO5Vz32QpvN66lwblt%2BkuUtWE83qVBsjItQNoa33fp%2BTGWE0JVrfujTt68v73MwC4T5Yy64MCBVsnZDw9kHKdEczwhkHSYA9oi5F7SsBZ3yfgQp%2BcQBRijDlTwLVaWeCjNSkuIZ6XjMZW0z0HTOphCjPGX0wwYznoyD05kIzx3pMWCi8qJzur/omZuq1Cq7wlKAA%3D
-Android Java IDE=https://godbolt.org/#z:OYLghAFBqd5QCxAFwE4FN0BoCWIIDGAtgIYDW6AgqsAM4gDkAtACIDCAspQNICiA%2BgCEAqgEkAMi34AVAJoAFXgFIAzCxboARgFdgDLAQD2RAA44ANulTiSAO2DaSwdKIAmIO69SGcrpgCsSADcSA21aZGMAeW1kE1iAMQt0WxIidEZ9ADNk%2Blh0VxxI1DcQAEYsHMtSiqqUtIyTbzqAOibDLJbkAA9kLFAGfRxaUVsCc21XAsYyodoOEhxbAGVDbVQCDIZZ3FookxTGAAZ9cztgUsGASiwIAqLDEvcAJkrk0te61PSQdG60kyWFqBEL9TK7UbjSbTBgnXYLJardabY5zfaHWGnc6XBg3O6FYqlFRvaruAAsJPqP3aDhIqFcLQIWWAYMGELGEym7m2cwRKzWGy2O2G6NsqKwZ3sOKuN2GnHI6Hk3n86AIyBm%2Bn85SwtnQAHckqSQABWG7mRjG/RizFYQyMaQYdAAaiUzxUO3VmJlWAQ6BIU1Q%2BBuZBAzyOLQAbFGVM8I0cI2SybHjSpjRLGGSreK7Wz6EcsJ6TniYIgQEYprwCY9cPgvg0QO1Wo2ur1KoZbMhlgQSJZyhSsu3kMJaIruuKtRVJaBPN5fAFgqER5Y1Th2/gUq42IYJkQxRUN%2BIlugAHLaIiaKwgCkmQy0Iqr2xbnd7rA3u/IB%2BH3Wn8%2BXilL1UP3bZZkDpZAnzPF8AJXYDQNQZAvxPM8L0Df84PA7dIO1CIwMQn8UKvG5aAFFEGAACWWeRxGWABHRwMFUQQmFUZQVDYJYihYiArgANSUI5KAoqjaPo9BGOYlReFoOi6XQCBRCuUR%2BMoaiZIYlRBGU3F0wYS0dWzBtmmSNpmhbPpC20iAkHLdBKweVAawgOtqW8Wl6UZZk2w7LsewyMp%2B0HYdR3HEBiSnDxbC8Hw/BBRd0GXICxTuSKIN3ULiQPI98MvCo33vdtUrFFRiTyxK8OQnKsGgxKQLAwr0qq%2BLAIfWr4PK39AwqHD4Pq4qqvQ9qCLKIiSK2JgKHQEwnXGEhaFoJ0RNkl0AHZBCdeJNHMHACCdAAqRiVpYbTzV0rMbTtGl6IZJkWQsvFrMMCsqwcvAnOSb4Mj%2BAEgVirzO27Xt/L%2BoL5DHG0tVecKZ2i%2BdQWqh91xSzC0teTLvwqzrltfW98sfZGxVeUrPyyjHyix%2BHYLq/HQ0ahKWoGkmOrJ/qqefGnuoQxmhuWkbkS2AB6fmnWkABPA4nRFgVpse51fQwLAnUeJ1zEMf0nTsJ0vtMIFlMF3WhambpnlV5B1qMywmAcXwCml0wLBIRKQH1p1KFcVwXWeZ5G2M5semQV1nidSIPeeSFORtupaAD9XIumraCDIIPfSdDAsgwWgECdHRkEiWx1f9gTBaT51NEMHPjEVrJi9tsxLFQRXYniU2TDseKWidBIleQZPvcsJ0B1QUg%2BidEcxMLoWEBzkx6EFqYgniwwDlQFpod8RljH5yIzAIfml4H0gxnQfnNFm%2BKj179BaH5g/HHMcwRaYAgMAd9AmHSWb1jEt0phyXUmFQbQlhaBvzsLfe%2B%2BtnYACUAAcTolSGAAOJXSdBNKaAC%2B5LCbk7ceLs3Yh0unSa6zJo7BwDmHaE7tI7R08HHbaidu7OlTunTO2dc752rs7Uu5ciCV2rkYO2dcG5xFiOtVu5h26d3rvApBhCnThCcNgEemBnaTziDPfmepNEtDcq4aSol15EGvqAns/MjC2ByA4VADsHz83kc4ZSykZpzQWmpZ0ShVrKSdF49a2hNrbRHqBD8O0limz0bJCAISnS2DPFcFamkBLeMSSndAyB1h52iTw3aUSzyMU8d49xLAHHLUKQJY6Fozo7DtFrQE6BgQLgLKib0IZEwtCOAATjKG0540DirPDaSoeMQMTqZn0udcE9BXh3VuCWKyZZjC1ysI5fhCzAyxSYIbY2DsmBnGQJfPoVRdmoHoBATQ4pNBLDpCLDUWBzmpFQCLKImgVRqmufw9IHYoi2HvuKKYOhgBsB7OYegPIsBTAPsAXsNpCgYBXPPYFcI/iqliEKIYHZ4rii2poKx9ytxTHFGgHARBrnz1QKXEcGhwVbXsI0yoZw6A8RwPqUU1yBzeQBn5AKHYQZgzhBDCU5wIpRTnL9TFeQoAfUFbOPwJAzBMAiL42gWASUzDKFGN00CIyWQlagaB41MAt1sLYQwSrLwMB6SoZauIbiL0SsC/QhgSWoGtmKoiTUYJJQ3PVfckVBqVSJgVamuUcZlS5pVCmKx0Jetps1SmbVQ2dRZj1QNibOboyZsNAsjpyhmnKaMuEOYXaQOkE6DZJtlYvwiE6CADpMAe3dFcfQd1gyhWNC0Z4ZIyjLTJMaOMsYkwap0iM60%2BbxkgHzE2nSzwzojrZBOkld41xkiAA%3D%3D%3D
-Android Kotlin IDE=https://godbolt.org/#z:OYLghAFBqd5QCxAFwE4FN0BoCWIIDGAtgIYDW6AgqsAM4gDkAtACIDCAspQNICiA%2BgCEAqgEkAMi34AVAJoAFXgFIAzCxboARgFdgDLAQD2RAA44ANulTiSAO2DaSwdKIAmIO69SGcrpmUNkcxxbA21aZGMAeW1kE1iAMQt0WxIidEZ9ADNk%2Blh0VxxI1DcQAEYsHMtSiqqUtIyTbzqAOibDLJbkAA9kLFAGfRxaUVsCc21XAsYyodoOEhCAZUNtVAIMhlncWiiTFMYABn1zO2BSwYBKLAgCosMS9wAmSuTSl7rU9JB0brSTSwtMh9AZzUbjSbTBjHHYLZardabGHDPYHaEnM4XBjXW6FYqlFSvaruAAsRPq33aDhIqFcLQIWWA/UyO3BEym7i2czhthWaw2MzmqNsRwx9ixl2uw045HQ8m8ACt0ARkIKsArylhbOgAO5JYkgACs13MjEN%2BhF6KwhkY0gw6AA1Eoniptqr0ZKsAh0CQpqh8NcyCAnmUWgA2Q6G11lEkklRxmMATiwpoYJItoutLPohyw7uOOJgiBARimvDxD1w%2BE%2BDRA7Va9a6vUqhlsyCWBBIlnKZKyreQwlocu6mY1FVO9g8ti8Pj8ASCISwQ8sKpwrfwKVcbEMEyIIuTm/EIXQADltERNFYQISTIZaEU17Zt7v91hb/fkI%2Bj9qzxer4Tl2VT9WyWZAaWQZ9z1fQDVxAsDUGQb9T3PS9/QA%2BCIJ3KCQGTCJwKQ39UOva5aARAUGAACSWeRxCWABHRwMFUQQmFUZQVDYEIijYiBLgANSUQ5KComj6MY9BmNYlReFoBiaXQCBREuURBMoWi5KYlRBGxFMzQzLks3rZI2maJs%2BnzHSICQUt0HLe5UCrCAa0pbxqVpelGRbNsOy7DIYy8gch3kEcrQ1QkJ1ATxvF8fxAmCUIYOAkVbmnSC901Q9j0Iq8KnfB9WzSkVcrvfLbAIlCcqXdAVyS0DwMKzVEsfOqEPKv9/QqPCEIazqMLaoiyhIsjNn8TATAdcYSFoWgHTE%2BSnQAdkEB14k0YICAdAAqZjFpYHTU3NLVMxtKlGLpBkmQsnFrMMMsKwcvAnOSL4Ml%2Bf5AWBAKfO7fy%2BzbQdh1HYMUzOKcZxi%2Bd4qqmrHw3VKsPSipMp/CqOrDN8SqSnqMY/L8stR8p0aauD6oRoroaA5q%2Bvx9rCaXDDsa6xCaYGsMhv5TYAHpOYdaQAE99gdPmEQm27HW9DAsAdB4HXMQxfQdOwHTe0xAVU7n1Z5qZuieeXkBW5pkiYBxfAKUXTAsEgkpATWHUoVxXCdJ4niMwFGx6ZBnSeB1Iidp42UhR26loL3FenCb1rIH3vQdDAsgwWgEAdHRkEiWxFc9oTuejx1NECSIiGlrIc/NsxLFQaXYnifWTDsaqWgdBIZeQGPXcdPtUFIPoHSHCSs55hBU5MehuamAA3arDH2VAWii2d6WMTnIjMAhOenjvSDGdBOc0KbquPNvaE5zfHHMcw%2BaYAgMCt9AmHSKa1gkl0phybUmFQbRLFoO%2B7FP8/NdtgAJQABwOnlIYAA4mdB0FB0DjQ/pYB0IRq4237nbB2ftTo0nOoyUOvsvYBw5A6YOodPARxwAQKOLdHRxwTknFOacM4l1tnnVOxgi4lyMBbculc4ixBWnXcwDcm4V3AVA7BDpwhOGwD3TAttB5xBHpzHUKiWhuVcLJcSC8iDH1/l2TmRhbA5AcKgK2j5OZSOcKpVSq11oRymjNOaGBFqCFUg6dxxDtDp00fJCAthzwgAdKMZAlxAnBKdGoB0/jC6bSieeaxC0WCqX2npI6VobQqwBOgIE5lRSeiDCSBaLRYyGhJE8Q4C0FokhjGUKpuk0z6RhDaQYS5gZXRuEWKyJZjBlysI5LhvT/SQxCEwbWusrZMFOMgdAEQiTTNQPQCAmhMyaBCDSPmapVmpFQHzKImglQqjVFw9IbYoi2HPpmKYOhgBsC7OYegBkpib2AN2K0hQMCrgng8mEvxlSxE2NsEI0zUwwmCJoUxOztxTEzGgHARA1QT1QHnIcGhnnxQGAWSopw6B8RwLqYUao/rtk7D9Xs/YAbBSBi8CKYNopzjiouMFeQoAvVpbOJgJAzBMAiNoTQtAsCIpmGUMMYYXTALDJZVlqBgGjTgXYWwhgBVXgYMAlQKgFrYmuFPJKDz9CGERagU2zKSLVUpuuFKW4yYZWnP1SqeUsZWuKrjVstqOoU1gryBmjr3W1WpijWmvVSYvkan65CAbrhoEwOUE0qTLRNMYHbQB0gHRjL1rLG%2BEQHQQDtJgJ2rpLj6CuoGa8hwWiJhJImJ4YZKnAKeGU6twD6npjSfGlpOY8x5JjQwJ4jS9UsiLUqhZsMSRAA%3D
+meta.screenshot_dimensions=1000x800
+Diff of Two Sources=z:OYLghAFBqd5TKALEBjA9gEwKYFFMCWALugE4A0BIEAZgQDbYB2AhgLbYgDkAjF%2BTXRMiAZVQtGIHgBYBQogFUAztgAKAD24AGfgCsp5eiyahUAUgBMAIUtXyKxqiIEh1ZpgDC6egFc2TA3cAGQImbAA5PwAjbFIQC3IAB3QlYhcmL19/A2TU5yEQsMi2GLiEh2wndJEiFlIiTL8AnntsR3ymGrqiQojo2Pj7WvrG7JalYZ7QvpKBiwBKe3QfUlROLksAZlDUXxwAajNNjwA3SpJSI9wzLQBBG9uT9AJMfcx0AH0ldA4PgHcyABrCChIjzI42O4PJ4vfaJUjoNZKJQfYjYNhKCAYJgTfYTTAgEBnJxkI4eUFXSwANn2xPmhwA7JDbvtWfsWD4SHiAF6HTYAEVplQAdKludgIODNsy2ftBKQIPjCWLsB8iPsCHzBVoIRq%2BR4ebqCLZbPSzEyHrLZe8vj9VQDSMDiWYAKxWY0u/lSmVs838h5%2Bh5cRb0bgu/gBLg6cjobgeE3WPHLVbYQ4WTZ8chEbTBxaAkAurSGbjSfhsAtFyPR2NcfhKEBF7NR4PkOCwFAYHD4YhkSjUOiMVgcbiZwTCMQSTgyOTCZRqTTN8j6BJGExoBN2CpVVwQdyjAIWFrBabFUogBlJFJpIT7%2BItXLXpi9U8DC9bjpdEbeJp31rtaqTM%2B/RxG%2Bky3oeQzdEBswgYs3wrGs3BbDseypmSxIXJSUJ3DCrw2t8vwOsCoLegGOHPK88KItgyKokQ6KYtiuJKkS5ykscFKbNcFg0nSjI%2Bqy8oQByXJomw%2BwgEKqBmhadxWmy%2BF2v8QIgvRbCkXJvoMv6ULaUGIZhhGOYxnGG5JghaHphY/BNjo8yLEg2AsDgcSSsWXCluQ5aFuQVb8DWdYNlmOb2eQ%2BbSC6wpUgAnDw0VaFSWhaC6FiHtFmzuZsRmLgFwXNosbbIGgPyJAwsR9liJVlXEuzGMAPCbFoLQDvRpD1hAUTGVEoR1AAniO/AYGwHDCAA8kw9D9YuOBsHVkjTQQpDnAQZz1ou2DqJUnLrJmoJtMZ9AEFEpB9V4ODGUQpAEOWvAtjQRjAEoABqBDYH8o2JMwA0zqI4iSNOY6KCoGjGfoLSrqYG6GEd9aQIs6CJB0a0ALSjVlf7LTue7fmM5DHkUwE5FeHS3vexPpNBZ7jG0mOdGBOPNBj2501BJ6E%2BM9NZIzEyswTMFSHByaIS0l3YDtLahlw4a%2BcZNbqAAHFSyNUtI%2By1SY%2BwNcKWjCjw%2BwQPG1i2OQ%2BzdhcaYZibXhsKVjCkBbPDzDZIWth2VV2xVQ22wM6v1Y1zUMK17WdYu3WsKQU2ZkNI1EONk3GTNc3rNGhBLVUq3GRtW30d9e2S9Gh3HadWDJzZV03Xwiz3Swj0vW9H1fbdP0Tv9siA3OIOLsuhh1euRvWNDUSw25CNI9wqPo%2B%2B6RuEwngM4Es%2BUwMZN5OkpOXqvBRs/z1P/kIn4NPPu%2B0wfS9xBz3Trzz9RnwLSwWYMoviwZUvZdW3AK0rKtqxDmubNrut9aGxsAPU2hBzZbASPsa23t7aQKdnlOyrsQCEBoDQCqgMW5TjbvIDuC4C5IHrODQhqCaBEF6p9IKpBCGDGoUoUh5DKFaBftLPyJkuD8gIGg/Ydc/ixH2J/ZWqtfZ/wAXrE4SgBGKyET/OqoidaZlsrmcgjlnIDDcvmF00hhSNXllodK0VorSAZAyPRDIqTuU8uWHgSUZY5W4IFBISjQqS2snY9%2BtZEHKLOG1ae0ggA
+Diff of Two Compilers=z:OYLghAFBqd5QCxAYwPYBMCmBRdBLAF1QCcAaPECAMzwBtMA7AQwFtMQByARg9KtQYEAysib0QXACx8BBAKoBnTAAUAHpwAMvAFYTStJg1DIApACYAQuYukl9ZATwDKjdAGFUtAK4sGIM6SuADJ4DJgAcj4ARpjEINIADqgKhE4MHt6%2B/qRJKY4CIWGRLDFx0naYDmlCBEzEBBk%2BfgEVVQI1dQSFEdGx8ba19Y1ZLYNdoT0lfZIAlLaoXsTI7BwA9KsA1AAqAJ4JmBs7C8QbaFgbCLGYpBskG7SoTOgbhhuYqqwJ9AB0JhoAgqECBsFABHLx1TAQIEbBg%2BGYbEwAdisAI26I2xEwBEWDFhPg2ACp8SwTABmVH/ZEAEQ4c1onAArLw/BwtKRUJw3NZrCDjstEWYyTxSARNHS5gBrECMjT6TiSFnijmcXgKEBysVsumkOCwJBoFgJOixciUQ3G%2BhxYBcMxcPh0AixdUQKLKqKhOo7Tgiw1sQQAeQYtG92tIWBYhmA4jD%2BCxVQAbph1WH3pUvE6fbwgZgGWHaHgosQvR4sMqCMQ8Cws3MqAZgAoAGp4TAAdwD%2B1ZIv4ghEYnYUhkgkUKnUYd09oMRhQPMs%2BkL6sgc1QCXyDBTAFoA2SNhvI0sEOTqQpJTsDJLMGrc5U1y4GO5PE09MEJsVSnpcqkBMM/PbP2vujfPp7VaNcOiGR8shA682gYcDxiKXo4hAsYfz0BQxkApCJDmBR%2BQHUUsRWHh6SZJUw05DhVAADgANg3WjJA2YBkGQDZbW%2BLgNggblLGsG5cEIO5zGFG4PCNE0ThErgZl4LUtDmCADVQCSrTNCALUklApxtSQNDlGhaCdYgXTdMMPWYYhQ19FT/QIIMQ2VCMoxjdk4xvPAkxTdk02QDNiOzQRc2VAsixLDAVnZCsqxrPh6ybFt207LMh2EURxEHHt5CUNRlV0AIdJnPi51CxcIGXVc0k3bdd33ZBDzJY9T3PS9bBg28IFcND7RfRCpmQnJki/dJIN/Qa8jSLD%2BvQ9rqlQ0aZvsMDMNfbCUM6bqBk6Kb3xk%2BZFmWPQK0wALSI4ZlSFZdlKJo%2BjGNOHT2Mkb4NBe7jeKsOcNkEogpKFe0NnEy1YkFMkzFk0VxUUpB8CoKh1KyvsMukLKR1y/MEHVSdMdhqgCD2dg5WITHsmJhRcfx/YNTOi6rt4SjqTwOGNmbNsQduhimJYtiOK4hMFA2Dn7uQR6pBel65KhqUZTlPNFUu5VKLVbJ5IleUODMcjrtVSHtRmOYkxMtJ4iAA
+C++ Cmake=z:OYLghAFBqd5QCxAFwE4FN0BoCWIIDGAtgIYDW6AgqsAM4gDkAtACIDCAspQNICiA%2BgCEAqgEkAMi34AVAJoAFXgFIAzCwBK6ADYB1HMgQt0AI1EA7AGYB7BlgJWiABxxb0qcSTPAAriWDpRABMQAiUAJkFwwTtvWmQHAHlvZEdkgDEXdDMSInQUBHR%2BdAAPdAJkkmNXLAtM%2Blh0QP0rVCCQADYazLaARgAWLtds3JBSHDMAOgJHRyxQBlscWnMCLW9AxsYABkXaDhJxgGUrb1QCPIYe3YTHLO3bLU9gNoWASiwIRubW4J7BgN%2BAFZ/sM8pxyOhxEtkLQJshisg5oxHKgrAArMrICC0BAkW60V5KLaUImUYgQ/hEcY4IjeIj8DAAR28OAwgQgADVeOpDqIEgA5ADUKgmgMJxNJJECgSKpXKyEqrmxuPxzJIGFJgq1gpxePQtAA9ARWat0FMZprtbr8QaMAQFV5XObHJatWNJtNHOKScSFTR0Mh%2BFpxmQgzhjKh1Th9cq9bQ1RridrBRYiMhAt7dis1htggwdrg9gczMdTud7oWbnd8w8nm1yRR3p8mvEfiAwv9ep1akMcnkMLQTmd9QaClotFY4QikQxSQAJbQTrCCgDuLS0gTAYFJpKYe6YpOkBUFvDMgVJWbMq3Wmxrhf2RyH5cu11uZgrjy89aiUSbX1bbQqJ2vwAJwgn2IA4JOnozpe165hWSwPiWT4XFclZvh%2BdZ5gwf4ti0bQDD2ALtls4EjFBEwILBhbZjeeYFkhxalsOjDoUsVbvnen7PDhrzvEs4IUPIqIYvaFZoiAfxmOgK4ZK4bRhD07xaIwgK2FxBZWIw0gYOggrhCo6HIPc/FYGQpGin0ADsIF9ICYRbICNl2c5WCqQwfQaRW2kLFg9BkSZNZNjAUChRASD2BsvD4aguD4MRoKjMWzo1FYZjIIcBAkK4UlEelyDCLQ6DyMUEkdO5TwhD%2BET%2BdomJQe%2BnxnmwVhrEQ749J0WSBFCMn8nSxhuCAQGOFYtD6I1rXtZ1nRjRNyCNX16ADUQQ2oCNdWuPajWHH6yDTXSs1bQ16V7eqyDLat62bXEF2HR1UmdHdqCXeMK2DcNKjvIOZYXIZ4zwfpqhsKmyBGi0ZoIKoygShKYQqIDObA2EYSUdDqM7sS4zIIK7oQK8BnWZESbamDIAgCiOMQOEYTyfp9gZVkMIgEogJsGYSjE1zLC08u/iBoEJAKgThIqCTJLWbzxK4e5aneXe2nuqlQU7E2kVWNFsXxRAiUQUJkLQrC8KItYGVZTleT9GlGVFSVZV3pJfw8SEpAUCdO3pfgPUPZ1WA9Vdn0bT0fzzZN6W%2B1JWBh4t6WB2tw0hx7sclvtkd/MV20p%2Bdr3xzdScvQdbVHVHhd54nyn%2BahjANoUVJmDSdIMugzKso0nLcryArCqK3qkii6KYrG%2BJ98SUoyiUZQVFU6AQAYhST/KiroK6gqUZ6q/K56o%2BUH6AthmYobBhGUYxvPspTwqM%2Br2DGYXip8tYJptjaQbUJxMb06q7LEUhJr6AxW%2BDrPWIwByoUNGOCcU5TYFQtrla2ZtCrFVKuVDsLtQgRCiMnRq3sWrF0en8AO71rrDTmuNcOZh07R3ISncuG1nr1U9qne6%2BC/aZ1Osw3OxCg4VULlQsu3CE70J%2BtXWcxIFzjisMuNcqANxbixpQfcB5iRHn0qec8MsH4MHUk/HyIAwF/QgYuScJssDf3Vn/LWQC8C60yEldeMwbaZWyvA/KttkEOwLJJIC6CarRHYUw3BgQqFEP6jwsCMcpqsKjpEuOgibpgQCdnNO0SM6MOSRdOhIBEkpJmqXfaWSQIiL%2BowAGV5kYGRUKDOIGAcgwx3AjJGN5KlsBqeMYA9S4aUDiMEEAbSvCCn3kLEWhMuYS2TD0imOALA1PQDkNeMyaaowMcOIxkjoG0zFuM7UsR2mClELjVQLAdTpimbMnIxhvAWH4PoNwwsWggwILiVA9TxarwwMgU4ZgTm9P6cACAByIDTIJMuQF/FVASx5vfOW2iFZaUgtBRx5iPgaysa2YBdiILoycXAq2bikH23KgMXxmDapJJwc1YJqT/ZnkKdQhaUS8mhxoUteJw1EnpN2rkkuaSs5csyWyjaOSWFMv8gUwV2TimsVnI0iwZ50AWEFGkBICR%2BBzgaSoDYtQZJKpVWqhRZSgYtL%2BZ0n03TTl9LQHsoZwsSAEwhQahGPVpnQo8jo5%2BWBtLYvMe8AoUphoE3MiAPoAAOCYfQI2RqjVGmFXksBEBAICMiHrfK2ACmY0yHxwrhQ1k4TIcUbH2Dza4DawAehbCAj2ZAbh6AQGMBWYw4x1QAE82K2EbdkVAzaEjGDEkFdCRbcgZQSGYLQra7wbEucANgOUtD0BfFgDYpBHQXALE0O0i0ABu%2BoKyL2SGhRYTMPIFmPpGLtrUNgVitQml87wLCPDoByaMK5OJtpxS4vFTi7YoMdptElkRarH3qFAJKYMsDbo2gwayPQVC4XeFYRwKd51MB6UcjBAHBCOUFEwBIKhsP3viC/CDqAcAbGAz9TlXtKUhNpRK5lDKI7UtiWYLJvKOE5yLqK8lZ1xVhKEfkkVPKxUCr4/nd4aBMBSS0e6vRDBBTFBDe0Jg7Q%2BiDIIAQQU5aJh4YgLpTABkEbKVsD6rAfqNgbUDRZQEIpnLtC2CBECYQQJbGsiGrYMHiWMDjQmvoWwrIhpUL55yAWgudBTYwNNIBAqZrgLAJAJwUjJGAbAj9eUv0ePKkBCT6BSNRxXJGRwbbpNwpfowJIiXcZWEVQppTKm1Maa0zp1qxa3AGZUN9YzplfVzPM/gLR3n2ztAmCHALYR2gjZUGNnoHZwt%2BXTci2LiAQB7vRTY9UdB5CeG0IcBAVgVweqLc4R4KdNsyS0DtvbXEB0OCO8NMt027A3fzfyCCflDv5vKxd/bb7F7UDoPo/U4DRzGOgf7OUe0mhcVsIg3FaXEHfs8bYJ2lUvDVVJdEID8AICgbTOB4aUGYNwc9YhxqyHUNqHQ1ELDOG8NMAIzYT1xHSM7sgO8VA3gMo0nQNIKwbVyNish6d7bu3vsLuy3lgrRWYUycVowXgcpkgtHk4p5TqngDqc0z0CYYRBQQDYH45cemUZGVeJ14K/XbAJva9p9rtu7d290bLubUWM3m6DYCLXgIvfe5997zoHlYOO/hX5EzFlbLhock5Fy9lHKAn94wMIlupJbGTbJs3astGJ6D6VkPXW8eoAml7PoQA%3D
+LLVM IR=g:!((g:!((g:!((h:codeEditor,i:(filename:'1',fontScale:14,fontUsePx:'0',j:1,lang:c%2B%2B,selection:(endColumn:18,endLineNumber:6,positionColumn:18,positionLineNumber:6,selectionStartColumn:18,selectionStartLineNumber:6,startColumn:18,startLineNumber:6),source:'int+sum(int*+arr,+int+n)+%7B%0A++++int+value+%3D+0%3B%0A++++for(int+i+%3D+0%3B+i+%3C+n%3B+i%2B%2B)+%7B%0A++++++++value+%2B%3D+arr%5Bi%5D%3B%0A++++%7D%0A++++return+value%3B%0A%7D'),l:'5',n:'0',o:'C%2B%2B+source+%231',t:'0')),k:25.411059109631243,l:'4',n:'0',o:'',s:0,t:'0'),(g:!((h:ir,i:(compilerName:'x86-64+clang+14.0.0',editorid:1,fontScale:14,fontUsePx:'0',j:1,selection:(endColumn:1,endLineNumber:1,positionColumn:1,positionLineNumber:1,selectionStartColumn:1,selectionStartLineNumber:1,startColumn:1,startLineNumber:1),treeid:'1'),l:'5',n:'0',o:'LLVM+IR+Viewer+x86-64+clang+14.0.0+(Editor+%231,+Compiler+%231)',t:'0')),header:(),k:42.23569365874194,l:'4',n:'0',o:'',s:0,t:'0'),(g:!((h:compiler,i:(compiler:clang1400,filters:(b:'0',binary:'1',commentOnly:'0',demangle:'0',directives:'0',execute:'1',intel:'0',libraryCode:'0',trim:'1'),flagsViewOpen:'1',fontScale:14,fontUsePx:'0',j:1,lang:c%2B%2B,libs:!(),options:'-O3+-march%3Dskylake',selection:(endColumn:1,endLineNumber:1,positionColumn:1,positionLineNumber:1,selectionStartColumn:1,selectionStartLineNumber:1,startColumn:1,startLineNumber:1),source:1,tree:'1'),l:'5',n:'0',o:'x86-64+clang+14.0.0+(C%2B%2B,+Editor+%231,+Compiler+%231)',t:'0')),k:32.353247231626824,l:'4',n:'0',o:'',s:0,t:'0')),l:'2',n:'0',o:'',t:'0')),version:4
+Preprocessor=g:!((g:!((g:!((h:codeEditor,i:(filename:'1',fontScale:14,fontUsePx:'0',j:1,lang:c%2B%2B,selection:(endColumn:1,endLineNumber:6,positionColumn:1,positionLineNumber:6,selectionStartColumn:1,selectionStartLineNumber:6,startColumn:1,startLineNumber:6),source:'%23define+MUL(x,+y)+(x+*+y)+%0A%0Aint+mystery(int+a,+int+b)+%7B%0A++++return+MUL(a+%2B+b,+2)%3B%0A%7D%0A'),l:'5',n:'0',o:'C%2B%2B+source+%231',t:'0')),k:30.466941342614383,l:'4',n:'0',o:'',s:0,t:'0'),(g:!((h:pp,i:(clang-format:'1',editorid:1,filter-headers:'0',fontScale:14,fontUsePx:'0',j:1,treeid:'1'),l:'5',n:'0',o:'Preprocessor+Output+x86-64+clang+14.0.0+(Editor+%231,+Compiler+%231)',t:'0')),header:(),k:42.496476357000276,l:'4',n:'0',o:'',s:0,t:'0'),(g:!((h:compiler,i:(compiler:clang1400,filters:(b:'0',binary:'1',commentOnly:'0',demangle:'0',directives:'0',execute:'1',intel:'0',libraryCode:'0',trim:'1'),flagsViewOpen:'1',fontScale:14,fontUsePx:'0',j:1,lang:c%2B%2B,libs:!(),options:'',selection:(endColumn:1,endLineNumber:1,positionColumn:1,positionLineNumber:1,selectionStartColumn:1,selectionStartLineNumber:1,startColumn:1,startLineNumber:1),source:1,tree:'1'),l:'5',n:'0',o:'x86-64+clang+14.0.0+(C%2B%2B,+Editor+%231,+Compiler+%231)',t:'0')),k:27.036582300385337,l:'4',m:100,n:'0',o:'',s:0,t:'0')),l:'2',n:'0',o:'',t:'0')),version:4
+Pascal IDE=z:OYLghAFBqd5TKALEAXATgU0wGgJYgQDGAtgIYDWmAgusAM4gDkTORA9iQA54A2m6ADJkAdsACuZYJgCSAExBcy9ImV5tx9VJwDy41F30AxPphFkSmZqwBmpxrExy829PJABaAIw47/dwBMvqbmliDkqEg24iJE9AD0EVExcQB0SvQ4oEwxLgDUSdGx9ACkAMwAQiUADNQ11HgiqAI2ZESY9fWamKW1ef0FZJFFcY2oNuVVtfWoAJ5cHX0DACoAskNIRin0eeUAInlEvMr0EMsyTS1tTjoARgBWmESoOHky65FbxQCU9QN5hluvDwRD%2B/wGI1QeHYIjyAGUAI6SLDEGFaPIicQkEBvS7SdDfHEXZr4yZg/pmORk6a1PDcfiWJpDaEiTq1SEsvJrDZfNKI5GYVEidGY7G4kkCQnizCkyr1W4yxrk%2BFIshYPIgfYYrF5ABU2pI1OolKN9UpqXqrDw9AuR3EciczGqVvo60acPY4nQ7WYXhdOgWIl9rGOYncGVUvG%2BOAgThc7DcCiCflkCjKwX4oSsmAAHhYuPxUnIuOgstZ8DbYrx7Y6mM6K26RB6vT66/7A06Q6JgO4WNHY85XO50yn3AAWDNmCxWQrbRIbEb0MY2dLKMssCu26sOhRthtkd2e71WJh%2BisBsydnChnu7pjfaPWgDC6yoAAV0OxHs9gzh7iAfBETAAHcTH8BQAFZo14ZgINYIM93YZhliwTBdgCMoz1QTsHxwCgQDKCDUmqMcAE4ADYAA4ymo6ovAAdi8ciJxgpgx3gq8kI3RhqhwbC237RAIBQDgHQAUUHBN8EIFMsxAXN80LYtSxsGFUDhSMrC8CdVKaABVehMDfHMr3/IIb0UZRIxwQz%2BGeFlCEpJ92GrEggx8SlBEaTAADksQVdAAIgnAuHYJcoRhZzXPckKwpcFkvKAvySACoKbMwOyIqbVA1VQKKsRi2yniyuEcvQVBEt8/yBDSrRcvytyAJssqKu85LUq8KCbKPVsS3YYB0AsPIFPpDo5Rpahul6ah/lnYplzyRo8jAJg5riedhm2ZdV3oFacGVNadiWlbDo25Jih2lbTVqAA3NVlV5RguQ%2BTZtiNBVgCVJZ%2BgAdXQFxMEEEQIBWgAJDLeHYV4foTXg5DABH72umaBkejUtW5T5tlSJ8sCGMaphR/oxJzFxnIddGygOR7Un5NVBTKX5xuNEQ5AtWp72vWCOMQ%2BS81GosSz4nCYxE9hxMk0sCAgWTp3CBc50O7aMl8NSNLULSdLUgyjJMvd/3TCyIzUdLMoc2NWYamLPLa6rAonULwpZK2msd%2BKYUq9qaonIr7JhUr6pcgqmt9kqWs9u2QB9lqXZ8OryojlLvejegepPXJUEGTb5qaCZmfqMYrnaNlqDmBZlXeHltl2KnFsudBWmL77wRKCCKiu%2BiKjIMgyiIW4AkozAPDKMpqluDwxy8UivA8MhKLHjwiFImxOv7mw5Ho0iqXovYrogvYS/BCEUiylUBSFEUsSJPFJWviV0CNf4TXz2lRsZHKspL81OdYuCcAQ%2BsSFTpK1zjtYWAloxIEwGQB0gUIDRnwsxVIpEILVEwuRJipFKID0IlzNirBsReGqLxABrAuKsB4uA50uFWIBAISAeiARiIQUotgwiARSKTwYvRf%2BnFyz8WoTGISKBcxPH0FJaWaoGBvlEBlOESB2DAQQmeDg3A%2BDMhhDIoCvB5GKOUawVRPB%2BCBRsFwIgZQAhBEMaYdAeh1IKKUb%2BURRBaAMHLM40qzgEK2DVppACWt9KGWMqZJqRsrIm2BLcBw8CcDsC4FlRgTAPCrD2BlLgSA8AULTr%2BLQXitFyIcfoviqEmrAUGlwYM0Fua8N5kwEmYjXB5BzJRciHhmJ5FMUQPIZRUhMICHkCAMiVAmy5KhdCmFvisAEfeSB0DYGECqfgnA2IAj0WQVw%2BizF6LVBYWw8iNTAHlkodMmhzAyg80ORuE50YboCCXDCKOQA%3D%3D
+Java IDE=g:!((g:!((g:!((h:tree,i:(cmakeArgs:'',compilerLanguageId:java,customOutputFilename:'',files:!((editorId:1,fileId:1,filename:shapes/Square.java,g:'',isIncluded:'0',isMainSource:'1',isOpen:'0',langId:''),(editorId:2,fileId:2,filename:example.java,g:'package+myapp%3B%0A%0Apublic+class+example+%7B%0A%0A%7D',isIncluded:'0',isMainSource:'0',isOpen:'0',langId:java)),isCMakeProject:'1',j:1,newFileId:5),l:'5',n:'0',o:'Tree+%231',t:'0')),header:(),k:29.896907216494846,l:'4',n:'0',o:'',s:0,t:'0'),(g:!((g:!((h:codeEditor,i:(filename:shapes/Square.java,fontScale:14,fontUsePx:'0',j:1,lang:java,selection:(endColumn:1,endLineNumber:1,positionColumn:1,positionLineNumber:1,selectionStartColumn:1,selectionStartLineNumber:1,startColumn:1,startLineNumber:1),source:'package+shapes%3B%0A%0Apublic+class+Square+%7B%0A++++public+int+square(int+num)+%7B%0A++++++++return+num+*+num%3B%0A++++%7D%0A%7D%0A'),l:'5',n:'0',o:shapes/Square.java,t:'0'),(h:codeEditor,i:(filename:example.java,fontScale:14,fontUsePx:'0',j:2,lang:java,selection:(endColumn:1,endLineNumber:2,positionColumn:1,positionLineNumber:2,selectionStartColumn:1,selectionStartLineNumber:2,startColumn:1,startLineNumber:2),source:'import+shapes.*%3B%0A%0Aclass+Main+%7B%0A++++public+static+void+main(String%5B%5D+args)+%7B%0A++++++++Square+sq+%3D+new+Square()%3B%0A++++++++int+val+%3D+sq.square(args.length)%3B%0A++++++++System.out.println(%22Answer:+%22+%2B+Integer.toString(val))%3B%0A++++%7D%0A%7D'),l:'5',n:'0',o:example.java,t:'0')),k:80.08193737395916,l:'4',m:60.81932773109243,n:'0',o:'',s:1,t:'0'),(g:!((h:executor,i:(argsPanelShown:'0',compilationPanelShown:'1',compiler:java1601,compilerOutShown:'0',execArgs:'hello+world',execStdin:'',fontScale:14,fontUsePx:'0',j:1,lang:java,libs:!(),options:'',source:'1',stdinPanelShown:'1',tree:1,wrap:'1'),l:'5',n:'0',o:'Executor+jdk+16.0.1+(Java,+Tree+%231)',t:'0')),header:(),l:'4',m:39.18067226890757,n:'0',o:'',s:0,t:'0')),k:70.10309278350515,l:'3',n:'0',o:'',t:'0')),l:'2',n:'0',o:'',t:'0')),version:4
+Ada IDE=z:OYLghAFBqd5QCxAFwE4FN0BoCWIIDGAtgIYDW6AgqsAM4gDkDWBA9kQA44A26qAMiQB2wAK4lg6AJIATECRkkWo2snYB5Ucg5aAYj3RCSRdI2YAzA/VjoZONalkgAjFku8nAJjcGjJkOgAHsYcvAB0CgBGWKBMuLRSQgTcojK2jAAMzDi0ALIkOEIAyqyiqASmDFnx6hyGmczcwsBOTACUWBC29qyOct7u0nIAzD68fqbmrKwRMrQxZvGJyanpVdl5BcWl5ZXOG7X161hNIq0MHV12Dk6jg04ALGOGxpPTs9GxG8spaXLHOXyhRKZQqjH2NTqQgaJ2a50u3RucgAtK57nIAKzPCYgQo6ZBhZCBZALBjOTzDACkGUoFIe1MozgynnpNO%2BSV%2Ba2qgK2IN24IOUIFsLOcgUJDaHRyAGF8hQAAqoVgAK3QBGQwuVLiwQnQAHd9B45AA2DrcRgY5jQ46sRgAFQw6AA1JSKRCNetJVgyC4ABxhB7OB4PACcxoyvoxAHZjc5hsNjSdGA9mEQXBkMjqYba4vRMx6spcYFBixAkGw0gBRa69XD4QY4qYzBTzKZCZBFAgkXguJ5t5AAVVo6HlgRhWu8p1A4qww946pwrGhXSEMmlrBSRGhrkMMn4hXQADlRERInwQN4OKxaPZF0J15vt1grzfkHf97rj6fz9452q30uRTICQqDIA%2BJ5Pn%2BC6AcBoEfkeJ5nqgF6zrBYEbhB2qqCByDwV%2BSEXh0tA7GCDB6vYCBOpQihhHaQTIAA%2BlI6iUsMABCTqcVxXEqM61EkLR9FMSx7EMgyHAkAQZASM6ujTE6OQMpx5iiEkAFCE6uQAJ4MboqkEE6ECUE6IBOokyDoJIqCsRxuimYa6AMXaWl1G0ToYMgZQaeZll8DZDK7k6cmsDZFxJgwlpZjaIBNrM8wFhcHQIOgCjnhAHQ%2BsMzhhMaYZxsanhBr6GaeIm5oMCmWBpp4GJhMyIbBsaDwZFGGLDL6ni%2BlF1Q5sweZYAlRbwGWIAVug1Y9KgdYQA2rwBMEnDhFEbhLh2XY9kGK3tkOI5jscWquFO8iKLO6Dzup%2BC7uBW4gBi3i7nhiHnlGz7XreS7XdCd2va%2B74Hvhz2nedd5AThn23b%2BZ3/iDaGPd%2ByEvdhoHg99SO4f9T0I0RJGVORyCUfxgnEsJNlOrxVE0XRxPMf5NJ45RwWk%2BTjOiTSHBKhUMhlM6lYLaEzqKTSnF2UFBhOS56C05QZ7AIUSlOocGkQLoWBmUIukGKrrqeHiWiEsS2ttFLnHyloDHwYZ2t2slTpCJjTrmEqRBBdMpnay6pWaTpelJIZoxBW0YAMFIpCSEbrOUIFvMhLwoVmhaVrZvNMfoB8A0NF6yWpch6XhZVabxmE0YZMarVMhiDyRhSibWj1iz9YNnSluWrBVjWU14DNvhzbFy39p23amJt/Y7aO44gKMR0zlBF0rmuGE3c4IZYA9GPwy4rgvu994L9uy9b%2BpcMEc4rgzzDYO7y4y9nzBOFH%2BeJ%2BoRfj5X0/cFr8fzjY6CuMURTAlU0YjTdi3FQHk0JoAkmEd6b/zCD5KyTkhLAI4uAmi8C%2BCIOpiJNiYk2aSWkpIJ0kRW5aRdqwBStB5YqTUneL2ul9KGWMqZdB1kQEiwcuLVy7l0CeVQN5dsvlUAUPlpxSgBADLMIEVZEyrEAAiToMjGyIZZOWQsuJ6gQAYQyQhWDIFgZA5iYRKyrgYuocwGteCGV0JKJ03BpgcBEVxAA4jw5WqsxEEHDjgtRnFAp2NYA4iO3EPJeSoh7DiHilGBW0vQpIUtAoszYmFcqkVa7MFtL3GQ0RBpJRSmkHO8cKqphAIGMIwwQwhl9FGX0ldcoxixGkrAvVZwgHzBnDKEMwiRmcMaXpnUoyeEGU1cKwxE7RTiI3OAsBm4gFKNoLQ002CcAMKgQ8c0GCBF9MaZETUnTACMHo8kYRPAWFWgPDafZVqjz2tUA6A1HQ4DkK4PUqASAcAFIU1JScGCaHmXo1g5gnSbO2bs/ZJBDmeGOYZdcyzeBCNdFlNozAcnegvCGIuWUKTlIxLGDI5Swx52KYMspUYQylRDAMkMGQQzDAyA075fVWnp09E3YaLdYV8EWewLgcKQBguQOSbwaQABuOAKgADUcD6kVsKdwFlUD0AgJEGEkRCggS0sKJZJh2zqCENwDVxw0ikBED2Q1OAMALmFegegxwghqi0JUbkAjyrVG4DgSIrzUBaXXGkGEaAcBpjJGFcwTQ6CSulUKINW01qD17NG6549DrNGOkoN1kRrC5wCepG1fUobQWXFdS%2BO5Vz32QpvN66lwblt%2BkuUtWE83qVBsjItQNoa33fp%2BTGWE0JVrfujTt68v73MwC4T5Yy64MCBVsnZDw9kHKdEczwhkHSYA9oi5F7SsBZ3yfgQp%2BcQBRijDlTwLVaWeCjNSkuIZ6XjMZW0z0HTOphCjPGX0wwYznoyD05kIzx3pMWCi8qJzur/omZuq1Cq7wlKAA%3D
+Android Java IDE=z:OYLghAFBqd5QCxAFwE4FN0BoCWIIDGAtgIYDW6AgqsAM4gDkAtACIDCAspQNICiA%2BgCEAqgEkAMi34AVAJoAFXgFIAzCxboARgFdgDLAQD2RAA44ANulTiSAO2DaSwdKIAmIO69SGcrpgCsSADcSA21aZGMAeW1kE1iAMQt0WxIidEZ9ADNk%2Blh0VxxI1DcQAEYsHMtSiqqUtIyTbzqAOibDLJbkAA9kLFAGfRxaUVsCc21XAsYyodoOEhxbAGVDbVQCDIZZ3FookxTGAAZ9cztgUsGASiwIAqLDEvcAJkrk0te61PSQdG60kyWFqBEL9TK7UbjSbTBgnXYLJardabY5zfaHWGnc6XBg3O6FYqlFRvaruAAsJPqP3aDhIqFcLQIWWAYMGELGEym7m2cwRKzWGy2O2G6NsqKwZ3sOKuN2GnHI6Hk3n86AIyBm%2Bn85SwtnQAHckqSQABWG7mRjG/RizFYQyMaQYdAAaiUzxUO3VmJlWAQ6BIU1Q%2BBuZBAzyOLQAbFGVM8I0cI2SybHjSpjRLGGSreK7Wz6EcsJ6TniYIgQEYprwCY9cPgvg0QO1Wo2ur1KoZbMhlgQSJZyhSsu3kMJaIruuKtRVJaBPN5fAFgqER5Y1Th2/gUq42IYJkQxRUN%2BIlugAHLaIiaKwgCkmQy0Iqr2xbnd7rA3u/IB%2BH3Wn8%2BXilL1UP3bZZkDpZAnzPF8AJXYDQNQZAvxPM8L0Df84PA7dIO1CIwMQn8UKvG5aAFFEGAACWWeRxGWABHRwMFUQQmFUZQVDYJYihYiArgANSUI5KAoqjaPo9BGOYlReFoOi6XQCBRCuUR%2BMoaiZIYlRBGU3F0wYS0dWzBtmmSNpmhbPpC20iAkHLdBKweVAawgOtqW8Wl6UZZk2w7LsewyMp%2B0HYdR3HEBiSnDxbC8Hw/BBRd0GXICxTuSKIN3ULiQPI98MvCo33vdtUrFFRiTyxK8OQnKsGgxKQLAwr0qq%2BLAIfWr4PK39AwqHD4Pq4qqvQ9qCLKIiSK2JgKHQEwnXGEhaFoJ0RNkl0AHZBCdeJNHMHACCdAAqRiVpYbTzV0rMbTtGl6IZJkWQsvFrMMCsqwcvAnOSb4Mj%2BAEgVirzO27Xt/L%2BoL5DHG0tVecKZ2i%2BdQWqh91xSzC0teTLvwqzrltfW98sfZGxVeUrPyyjHyix%2BHYLq/HQ0ahKWoGkmOrJ/qqefGnuoQxmhuWkbkS2AB6fmnWkABPA4nRFgVpse51fQwLAnUeJ1zEMf0nTsJ0vtMIFlMF3WhambpnlV5B1qMywmAcXwCml0wLBIRKQH1p1KFcVwXWeZ5G2M5semQV1nidSIPeeSFORtupaAD9XIumraCDIIPfSdDAsgwWgECdHRkEiWx1f9gTBaT51NEMHPjEVrJi9tsxLFQRXYniU2TDseKWidBIleQZPvcsJ0B1QUg%2BidEcxMLoWEBzkx6EFqYgniwwDlQFpod8RljH5yIzAIfml4H0gxnQfnNFm%2BKj179BaH5g/HHMcwRaYAgMAd9AmHSWb1jEt0phyXUmFQbQlhaBvzsLfe%2B%2BtnYACUAAcTolSGAAOJXSdBNKaAC%2B5LCbk7ceLs3Yh0unSa6zJo7BwDmHaE7tI7R08HHbaidu7OlTunTO2dc752rs7Uu5ciCV2rkYO2dcG5xFiOtVu5h26d3rvApBhCnThCcNgEemBnaTziDPfmepNEtDcq4aSol15EGvqAns/MjC2ByA4VADsHz83kc4ZSykZpzQWmpZ0ShVrKSdF49a2hNrbRHqBD8O0limz0bJCAISnS2DPFcFamkBLeMSSndAyB1h52iTw3aUSzyMU8d49xLAHHLUKQJY6Fozo7DtFrQE6BgQLgLKib0IZEwtCOAATjKG0540DirPDaSoeMQMTqZn0udcE9BXh3VuCWKyZZjC1ysI5fhCzAyxSYIbY2DsmBnGQJfPoVRdmoHoBATQ4pNBLDpCLDUWBzmpFQCLKImgVRqmufw9IHYoi2HvuKKYOhgBsB7OYegPIsBTAPsAXsNpCgYBXPPYFcI/iqliEKIYHZ4rii2poKx9ytxTHFGgHARBrnz1QKXEcGhwVbXsI0yoZw6A8RwPqUU1yBzeQBn5AKHYQZgzhBDCU5wIpRTnL9TFeQoAfUFbOPwJAzBMAiL42gWASUzDKFGN00CIyWQlagaB41MAt1sLYQwSrLwMB6SoZauIbiL0SsC/QhgSWoGtmKoiTUYJJQ3PVfckVBqVSJgVamuUcZlS5pVCmKx0Jetps1SmbVQ2dRZj1QNibOboyZsNAsjpyhmnKaMuEOYXaQOkE6DZJtlYvwiE6CADpMAe3dFcfQd1gyhWNC0Z4ZIyjLTJMaOMsYkwap0iM60%2BbxkgHzE2nSzwzojrZBOkld41xkiAA%3D%3D%3D
+Android Kotlin IDE=z:OYLghAFBqd5QCxAFwE4FN0BoCWIIDGAtgIYDW6AgqsAM4gDkAtACIDCAspQNICiA%2BgCEAqgEkAMi34AVAJoAFXgFIAzCxboARgFdgDLAQD2RAA44ANulTiSAO2DaSwdKIAmIO69SGcrpmUNkcxxbA21aZGMAeW1kE1iAMQt0WxIidEZ9ADNk%2Blh0VxxI1DcQAEYsHMtSiqqUtIyTbzqAOibDLJbkAA9kLFAGfRxaUVsCc21XAsYyodoOEhCAZUNtVAIMhlncWiiTFMYABn1zO2BSwYBKLAgCosMS9wAmSuTSl7rU9JB0brSTSwtMh9AZzUbjSbTBjHHYLZardabGHDPYHaEnM4XBjXW6FYqlFSvaruAAsRPq33aDhIqFcLQIWWA/UyO3BEym7i2czhthWaw2MzmqNsRwx9ixl2uw045HQ8m8ACt0ARkIKsArylhbOgAO5JYkgACs13MjEN%2BhF6KwhkY0gw6AA1Eoniptqr0ZKsAh0CQpqh8NcyCAnmUWgA2Q6G11lEkklRxmMATiwpoYJItoutLPohyw7uOOJgiBARimvDxD1w%2BE%2BDRA7Va9a6vUqhlsyCWBBIlnKZKyreQwlocu6mY1FVO9g8ti8Pj8ASCISwQ8sKpwrfwKVcbEMEyIIuTm/EIXQADltERNFYQISTIZaEU17Zt7v91hb/fkI%2Bj9qzxer4Tl2VT9WyWZAaWQZ9z1fQDVxAsDUGQb9T3PS9/QA%2BCIJ3KCQGTCJwKQ39UOva5aARAUGAACSWeRxCWABHRwMFUQQmFUZQVDYEIijYiBLgANSUQ5KComj6MY9BmNYlReFoBiaXQCBREuURBMoWi5KYlRBGxFMzQzLks3rZI2maJs%2BnzHSICQUt0HLe5UCrCAa0pbxqVpelGRbNsOy7DIYy8gch3kEcrQ1QkJ1ATxvF8fxAmCUIYOAkVbmnSC901Q9j0Iq8KnfB9WzSkVcrvfLbAIlCcqXdAVyS0DwMKzVEsfOqEPKv9/QqPCEIazqMLaoiyhIsjNn8TATAdcYSFoWgHTE%2BSnQAdkEB14k0YICAdAAqZjFpYHTU3NLVMxtKlGLpBkmQsnFrMMMsKwcvAnOSL4Ml%2Bf5AWBAKfO7fy%2BzbQdh1HYMUzOKcZxi%2Bd4qqmrHw3VKsPSipMp/CqOrDN8SqSnqMY/L8stR8p0aauD6oRoroaA5q%2Bvx9rCaXDDsa6xCaYGsMhv5TYAHpOYdaQAE99gdPmEQm27HW9DAsAdB4HXMQxfQdOwHTe0xAVU7n1Z5qZuieeXkBW5pkiYBxfAKUXTAsEgkpATWHUoVxXCdJ4niMwFGx6ZBnSeB1Iidp42UhR26loL3FenCb1rIH3vQdDAsgwWgEAdHRkEiWxFc9oTuejx1NECSIiGlrIc/NsxLFQaXYnifWTDsaqWgdBIZeQGPXcdPtUFIPoHSHCSs55hBU5MehuamAA3arDH2VAWii2d6WMTnIjMAhOenjvSDGdBOc0KbquPNvaE5zfHHMcw%2BaYAgMCt9AmHSKa1gkl0phybUmFQbRLFoO%2B7FP8/NdtgAJQABwOnlIYAA4mdB0FB0DjQ/pYB0IRq4237nbB2ftTo0nOoyUOvsvYBw5A6YOodPARxwAQKOLdHRxwTknFOacM4l1tnnVOxgi4lyMBbculc4ixBWnXcwDcm4V3AVA7BDpwhOGwD3TAttB5xBHpzHUKiWhuVcLJcSC8iDH1/l2TmRhbA5AcKgK2j5OZSOcKpVSq11oRymjNOaGBFqCFUg6dxxDtDp00fJCAthzwgAdKMZAlxAnBKdGoB0/jC6bSieeaxC0WCqX2npI6VobQqwBOgIE5lRSeiDCSBaLRYyGhJE8Q4C0FokhjGUKpuk0z6RhDaQYS5gZXRuEWKyJZjBlysI5LhvT/SQxCEwbWusrZMFOMgdAEQiTTNQPQCAmhMyaBCDSPmapVmpFQHzKImglQqjVFw9IbYoi2HPpmKYOhgBsC7OYegBkpib2AN2K0hQMCrgng8mEvxlSxE2NsEI0zUwwmCJoUxOztxTEzGgHARA1QT1QHnIcGhnnxQGAWSopw6B8RwLqYUao/rtk7D9Xs/YAbBSBi8CKYNopzjiouMFeQoAvVpbOJgJAzBMAiNoTQtAsCIpmGUMMYYXTALDJZVlqBgGjTgXYWwhgBVXgYMAlQKgFrYmuFPJKDz9CGERagU2zKSLVUpuuFKW4yYZWnP1SqeUsZWuKrjVstqOoU1gryBmjr3W1WpijWmvVSYvkan65CAbrhoEwOUE0qTLRNMYHbQB0gHRjL1rLG%2BEQHQQDtJgJ2rpLj6CuoGa8hwWiJhJImJ4YZKnAKeGU6twD6npjSfGlpOY8x5JjQwJ4jS9UsiLUqhZsMSRAA%3D
diff --git a/etc/config/sponsors.yaml b/etc/config/sponsors.yaml
index 56e9c15a4..50515a3ea 100644
--- a/etc/config/sponsors.yaml
+++ b/etc/config/sponsors.yaml
@@ -469,3 +469,6 @@ levels:
       - Лев Роскошин
       - salusdano
       - Nitin A
+      - Aaron D. Marasco
+      - Tomas Karban
+      - Abdullah Al-Kheshen
diff --git a/etc/config/vb.amazon.properties b/etc/config/vb.amazon.properties
index fc3750646..48b021b2c 100644
--- a/etc/config/vb.amazon.properties
+++ b/etc/config/vb.amazon.properties
@@ -1,20 +1,20 @@
-compilers=&dotnetcoreclr:&dotnetcrossgen2:&dotnetmono:&dotnetnativeaot:&dotnetildasm:&dotnetlegacy
+compilers=&dotnetcoreclr:&dotnetcrossgen2:&dotnetmono:&dotnetnativeaot:&dotnetildasm:&dotnetilspy:&dotnetlegacy
 supportsBinary=true
 needsMulti=false
-defaultCompiler=dotnet80vbcoreclr
+defaultCompiler=dotnet90vbcoreclr
 executionEnvironmentClass=local-dotnet
 
-group.dotnetcoreclr.compilers=dotnettrunkvbcoreclr:dotnet80vbcoreclr:dotnet70vbcoreclr
+group.dotnetcoreclr.compilers=dotnettrunkvbcoreclr:dotnet90vbcoreclr:dotnet80vbcoreclr:dotnet70vbcoreclr:dotnet60vbcoreclr
 group.dotnetcoreclr.compilerCategories=coreclr
 group.dotnetcoreclr.compilerType=dotnetcoreclr
 group.dotnetcoreclr.groupName=.NET CoreCLR
 
-group.dotnetcrossgen2.compilers=dotnettrunkvbcrossgen2:dotnet80vbcrossgen2:dotnet70vbcrossgen2:dotnet60vbcrossgen2
+group.dotnetcrossgen2.compilers=dotnettrunkvbcrossgen2:dotnet90vbcrossgen2:dotnet80vbcrossgen2:dotnet70vbcrossgen2:dotnet60vbcrossgen2
 group.dotnetcrossgen2.compilerCategories=crossgen2
 group.dotnetcrossgen2.compilerType=dotnetcrossgen2
 group.dotnetcrossgen2.groupName=.NET Crossgen2
 
-group.dotnetmono.compilers=dotnettrunkvbmono
+group.dotnetmono.compilers=dotnettrunkvbmono:dotnet90vbmono:dotnet80vbmono:dotnet70vbmono:dotnet60vbmono
 group.dotnetmono.compilerCategories=mono
 group.dotnetmono.compilerType=dotnetmono
 group.dotnetmono.groupName=.NET Mono
@@ -24,10 +24,15 @@ group.dotnetnativeaot.compilerCategories=nativeaot
 group.dotnetnativeaot.compilerType=dotnetnativeaot
 group.dotnetnativeaot.groupName=.NET NativeAOT
 
-group.dotnetildasm.compilers=dotnettrunkvbildasm
+group.dotnetildasm.compilers=dotnettrunkvbildasm:dotnet90vbildasm:dotnet80vbildasm:dotnet70vbildasm:dotnet60vbildasm
 group.dotnetildasm.compilerCategories=ildasm
 group.dotnetildasm.compilerType=dotnetildasm
-group.dotnetildasm.groupName=.NET IL Disassembler
+group.dotnetildasm.groupName=.NET ILDasm
+
+group.dotnetilspy.compilers=dotnettrunkvbilspy:dotnet90vbilspy:dotnet80vbilspy:dotnet70vbilspy:dotnet60vbilspy
+group.dotnetilspy.compilerCategories=ilspy
+group.dotnetilspy.compilerType=dotnetilspy
+group.dotnetilspy.groupName=.NET ILSpy
 
 group.dotnetlegacy.compilers=dotnettrunkvb:dotnet707vb:dotnet703vb:dotnet701vb:dotnet6018vb:dotnet6014vb:dotnet6011vb
 group.dotnetlegacy.compilerCategories=legacy
@@ -36,79 +41,178 @@ group.dotnetlegacy.groupName=Legacy
 
 # CoreCLR compilers
 
-compiler.dotnet70vbcoreclr.exe=/opt/compiler-explorer/dotnet-v7.0.19/.dotnet/dotnet
-compiler.dotnet70vbcoreclr.name=.NET CoreCLR 7.0
-compiler.dotnet70vbcoreclr.clrDir=/opt/compiler-explorer/dotnet-v7.0.19
+compiler.dotnet60vbcoreclr.exe=/opt/compiler-explorer/dotnet-v6.0.36/.dotnet/dotnet
+compiler.dotnet60vbcoreclr.name=.NET 6.0 CoreCLR
+compiler.dotnet60vbcoreclr.clrDir=/opt/compiler-explorer/dotnet-v6.0.36
+compiler.dotnet60vbcoreclr.buildConfig=Release
+compiler.dotnet60vbcoreclr.langVersion=latest
+
+compiler.dotnet70vbcoreclr.exe=/opt/compiler-explorer/dotnet-v7.0.20/.dotnet/dotnet
+compiler.dotnet70vbcoreclr.name=.NET 7.0 CoreCLR
+compiler.dotnet70vbcoreclr.clrDir=/opt/compiler-explorer/dotnet-v7.0.20
 compiler.dotnet70vbcoreclr.buildConfig=Release
 compiler.dotnet70vbcoreclr.langVersion=latest
 
-compiler.dotnet80vbcoreclr.exe=/opt/compiler-explorer/dotnet-v8.0.5/.dotnet/dotnet
-compiler.dotnet80vbcoreclr.name=.NET CoreCLR 8.0
-compiler.dotnet80vbcoreclr.clrDir=/opt/compiler-explorer/dotnet-v8.0.5
+compiler.dotnet80vbcoreclr.exe=/opt/compiler-explorer/dotnet-v8.0.11/.dotnet/dotnet
+compiler.dotnet80vbcoreclr.name=.NET 8.0 CoreCLR
+compiler.dotnet80vbcoreclr.clrDir=/opt/compiler-explorer/dotnet-v8.0.11
 compiler.dotnet80vbcoreclr.buildConfig=Release
 compiler.dotnet80vbcoreclr.langVersion=latest
 
+compiler.dotnet90vbcoreclr.exe=/opt/compiler-explorer/dotnet-v9.0.0/.dotnet/dotnet
+compiler.dotnet90vbcoreclr.name=.NET 9.0 CoreCLR
+compiler.dotnet90vbcoreclr.clrDir=/opt/compiler-explorer/dotnet-v9.0.0
+compiler.dotnet90vbcoreclr.buildConfig=Release
+compiler.dotnet90vbcoreclr.langVersion=latest
+
 compiler.dotnettrunkvbcoreclr.exe=/opt/compiler-explorer/dotnet-trunk/.dotnet/dotnet
-compiler.dotnettrunkvbcoreclr.name=.NET CoreCLR (main)
+compiler.dotnettrunkvbcoreclr.name=.NET (main) CoreCLR
 compiler.dotnettrunkvbcoreclr.clrDir=/opt/compiler-explorer/dotnet-trunk
 compiler.dotnettrunkvbcoreclr.buildConfig=Release
-compiler.dotnettrunkvbcoreclr.langVersion=preview
+compiler.dotnettrunkvbcoreclr.langVersion=latest
 compiler.dotnettrunkvbcoreclr.isNightly=true
 
 # Crossgen2 compilers
 
-compiler.dotnet60vbcrossgen2.exe=/opt/compiler-explorer/dotnet-v6.0.30/.dotnet/dotnet
-compiler.dotnet60vbcrossgen2.name=.NET Crossgen2 6.0
-compiler.dotnet60vbcrossgen2.clrDir=/opt/compiler-explorer/dotnet-v6.0.30
+compiler.dotnet60vbcrossgen2.exe=/opt/compiler-explorer/dotnet-v6.0.36/.dotnet/dotnet
+compiler.dotnet60vbcrossgen2.name=.NET 6.0 Crossgen2
+compiler.dotnet60vbcrossgen2.clrDir=/opt/compiler-explorer/dotnet-v6.0.36
 compiler.dotnet60vbcrossgen2.buildConfig=Release
 compiler.dotnet60vbcrossgen2.langVersion=latest
 
-compiler.dotnet70vbcrossgen2.exe=/opt/compiler-explorer/dotnet-v7.0.19/.dotnet/dotnet
-compiler.dotnet70vbcrossgen2.name=.NET Crossgen2 7.0
-compiler.dotnet70vbcrossgen2.clrDir=/opt/compiler-explorer/dotnet-v7.0.19
+compiler.dotnet70vbcrossgen2.exe=/opt/compiler-explorer/dotnet-v7.0.20/.dotnet/dotnet
+compiler.dotnet70vbcrossgen2.name=.NET 7.0 Crossgen2
+compiler.dotnet70vbcrossgen2.clrDir=/opt/compiler-explorer/dotnet-v7.0.20
 compiler.dotnet70vbcrossgen2.buildConfig=Release
 compiler.dotnet70vbcrossgen2.langVersion=latest
 
-compiler.dotnet80vbcrossgen2.exe=/opt/compiler-explorer/dotnet-v8.0.5/.dotnet/dotnet
-compiler.dotnet80vbcrossgen2.name=.NET Crossgen2 8.0
-compiler.dotnet80vbcrossgen2.clrDir=/opt/compiler-explorer/dotnet-v8.0.5
+compiler.dotnet80vbcrossgen2.exe=/opt/compiler-explorer/dotnet-v8.0.11/.dotnet/dotnet
+compiler.dotnet80vbcrossgen2.name=.NET 8.0 Crossgen2
+compiler.dotnet80vbcrossgen2.clrDir=/opt/compiler-explorer/dotnet-v8.0.11
 compiler.dotnet80vbcrossgen2.buildConfig=Release
 compiler.dotnet80vbcrossgen2.langVersion=latest
 
+compiler.dotnet90vbcrossgen2.exe=/opt/compiler-explorer/dotnet-v9.0.0/.dotnet/dotnet
+compiler.dotnet90vbcrossgen2.name=.NET 9.0 Crossgen2
+compiler.dotnet90vbcrossgen2.clrDir=/opt/compiler-explorer/dotnet-v9.0.0
+compiler.dotnet90vbcrossgen2.buildConfig=Release
+compiler.dotnet90vbcrossgen2.langVersion=latest
+
 compiler.dotnettrunkvbcrossgen2.exe=/opt/compiler-explorer/dotnet-trunk/.dotnet/dotnet
-compiler.dotnettrunkvbcrossgen2.name=.NET Crossgen2 (main)
+compiler.dotnettrunkvbcrossgen2.name=.NET (main) Crossgen2
 compiler.dotnettrunkvbcrossgen2.clrDir=/opt/compiler-explorer/dotnet-trunk
 compiler.dotnettrunkvbcrossgen2.buildConfig=Release
-compiler.dotnettrunkvbcrossgen2.langVersion=preview
+compiler.dotnettrunkvbcrossgen2.langVersion=latest
 compiler.dotnettrunkvbcrossgen2.isNightly=true
 
 # Mono compilers
 
+compiler.dotnet60vbmono.exe=/opt/compiler-explorer/dotnet-v6.0.36/.dotnet/dotnet
+compiler.dotnet60vbmono.name=.NET 6.0 Mono
+compiler.dotnet60vbmono.clrDir=/opt/compiler-explorer/dotnet-v6.0.36
+compiler.dotnet60vbmono.buildConfig=Release
+compiler.dotnet60vbmono.langVersion=latest
+
+compiler.dotnet70vbmono.exe=/opt/compiler-explorer/dotnet-v7.0.20/.dotnet/dotnet
+compiler.dotnet70vbmono.name=.NET 7.0 Mono
+compiler.dotnet70vbmono.clrDir=/opt/compiler-explorer/dotnet-v7.0.20
+compiler.dotnet70vbmono.buildConfig=Release
+compiler.dotnet70vbmono.langVersion=latest
+
+compiler.dotnet80vbmono.exe=/opt/compiler-explorer/dotnet-v8.0.11/.dotnet/dotnet
+compiler.dotnet80vbmono.name=.NET 8.0 Mono
+compiler.dotnet80vbmono.clrDir=/opt/compiler-explorer/dotnet-v8.0.11
+compiler.dotnet80vbmono.buildConfig=Release
+compiler.dotnet80vbmono.langVersion=latest
+
+compiler.dotnet90vbmono.exe=/opt/compiler-explorer/dotnet-v9.0.0/.dotnet/dotnet
+compiler.dotnet90vbmono.name=.NET 9.0 Mono
+compiler.dotnet90vbmono.clrDir=/opt/compiler-explorer/dotnet-v9.0.0
+compiler.dotnet90vbmono.buildConfig=Release
+compiler.dotnet90vbmono.langVersion=latest
+
 compiler.dotnettrunkvbmono.exe=/opt/compiler-explorer/dotnet-trunk/.dotnet/dotnet
-compiler.dotnettrunkvbmono.name=.NET Mono (main)
+compiler.dotnettrunkvbmono.name=.NET (main) Mono
 compiler.dotnettrunkvbmono.clrDir=/opt/compiler-explorer/dotnet-trunk
 compiler.dotnettrunkvbmono.buildConfig=Release
-compiler.dotnettrunkvbmono.langVersion=preview
+compiler.dotnettrunkvbmono.langVersion=latest
 compiler.dotnettrunkvbmono.isNightly=true
 
 # NativeAOT compilers
 
 compiler.dotnettrunkvbnativeaot.exe=/opt/compiler-explorer/dotnet-trunk/.dotnet/dotnet
-compiler.dotnettrunkvbnativeaot.name=.NET NativeAOT (main)
+compiler.dotnettrunkvbnativeaot.name=.NET (main) NativeAOT
 compiler.dotnettrunkvbnativeaot.clrDir=/opt/compiler-explorer/dotnet-trunk
 compiler.dotnettrunkvbnativeaot.buildConfig=Release
-compiler.dotnettrunkvbnativeaot.langVersion=preview
+compiler.dotnettrunkvbnativeaot.langVersion=latest
 compiler.dotnettrunkvbnativeaot.isNightly=true
 
-# IL disassembler compilers
+# ILDasm compilers
+
+compiler.dotnet60vbildasm.exe=/opt/compiler-explorer/dotnet-v6.0.36/.dotnet/dotnet
+compiler.dotnet60vbildasm.name=.NET 6.0 ILDasm
+compiler.dotnet60vbildasm.clrDir=/opt/compiler-explorer/dotnet-v6.0.36
+compiler.dotnet60vbildasm.buildConfig=Release
+compiler.dotnet60vbildasm.langVersion=latest
+
+compiler.dotnet70vbildasm.exe=/opt/compiler-explorer/dotnet-v7.0.20/.dotnet/dotnet
+compiler.dotnet70vbildasm.name=.NET 7.0 ILDasm
+compiler.dotnet70vbildasm.clrDir=/opt/compiler-explorer/dotnet-v7.0.20
+compiler.dotnet70vbildasm.buildConfig=Release
+compiler.dotnet70vbildasm.langVersion=latest
+
+compiler.dotnet80vbildasm.exe=/opt/compiler-explorer/dotnet-v8.0.11/.dotnet/dotnet
+compiler.dotnet80vbildasm.name=.NET 8.0 ILDasm
+compiler.dotnet80vbildasm.clrDir=/opt/compiler-explorer/dotnet-v8.0.11
+compiler.dotnet80vbildasm.buildConfig=Release
+compiler.dotnet80vbildasm.langVersion=latest
+
+compiler.dotnet90vbildasm.exe=/opt/compiler-explorer/dotnet-v9.0.0/.dotnet/dotnet
+compiler.dotnet90vbildasm.name=.NET 9.0 ILDasm
+compiler.dotnet90vbildasm.clrDir=/opt/compiler-explorer/dotnet-v9.0.0
+compiler.dotnet90vbildasm.buildConfig=Release
+compiler.dotnet90vbildasm.langVersion=latest
 
 compiler.dotnettrunkvbildasm.exe=/opt/compiler-explorer/dotnet-trunk/.dotnet/dotnet
-compiler.dotnettrunkvbildasm.name=.NET IL Disassembler (main)
+compiler.dotnettrunkvbildasm.name=.NET (main) ILDasm
 compiler.dotnettrunkvbildasm.clrDir=/opt/compiler-explorer/dotnet-trunk
 compiler.dotnettrunkvbildasm.buildConfig=Release
-compiler.dotnettrunkvbildasm.langVersion=preview
+compiler.dotnettrunkvbildasm.langVersion=latest
 compiler.dotnettrunkvbildasm.isNightly=true
 
+# ILSpy compilers
+
+compiler.dotnet60vbilspy.exe=/opt/compiler-explorer/dotnet-v6.0.36/.dotnet/dotnet
+compiler.dotnet60vbilspy.name=.NET 6.0 ILSpy
+compiler.dotnet60vbilspy.clrDir=/opt/compiler-explorer/dotnet-v6.0.36
+compiler.dotnet60vbilspy.buildConfig=Release
+compiler.dotnet60vbilspy.langVersion=latest
+
+compiler.dotnet70vbilspy.exe=/opt/compiler-explorer/dotnet-v7.0.20/.dotnet/dotnet
+compiler.dotnet70vbilspy.name=.NET 7.0 ILSpy
+compiler.dotnet70vbilspy.clrDir=/opt/compiler-explorer/dotnet-v7.0.20
+compiler.dotnet70vbilspy.buildConfig=Release
+compiler.dotnet70vbilspy.langVersion=latest
+
+compiler.dotnet80vbilspy.exe=/opt/compiler-explorer/dotnet-v8.0.11/.dotnet/dotnet
+compiler.dotnet80vbilspy.name=.NET 8.0 ILSpy
+compiler.dotnet80vbilspy.clrDir=/opt/compiler-explorer/dotnet-v8.0.11
+compiler.dotnet80vbilspy.buildConfig=Release
+compiler.dotnet80vbilspy.langVersion=latest
+
+compiler.dotnet90vbilspy.exe=/opt/compiler-explorer/dotnet-v9.0.0/.dotnet/dotnet
+compiler.dotnet90vbilspy.name=.NET 9.0 ILSpy
+compiler.dotnet90vbilspy.clrDir=/opt/compiler-explorer/dotnet-v9.0.0
+compiler.dotnet90vbilspy.buildConfig=Release
+compiler.dotnet90vbilspy.langVersion=latest
+
+compiler.dotnettrunkvbilspy.exe=/opt/compiler-explorer/dotnet-trunk/.dotnet/dotnet
+compiler.dotnettrunkvbilspy.name=.NET (main) ILSpy
+compiler.dotnettrunkvbilspy.clrDir=/opt/compiler-explorer/dotnet-trunk
+compiler.dotnettrunkvbilspy.buildConfig=Release
+compiler.dotnettrunkvbilspy.langVersion=latest
+compiler.dotnettrunkvbilspy.isNightly=true
+
 # Legacy compilers (for backwards compatibility, don't add new compilers here)
 
 compiler.dotnet6011vb.exe=/opt/compiler-explorer/dotnet-v6.0.11/.dotnet/dotnet
@@ -151,5 +255,5 @@ compiler.dotnettrunkvb.exe=/opt/compiler-explorer/dotnet-trunk/.dotnet/dotnet
 compiler.dotnettrunkvb.name=.NET (main)
 compiler.dotnettrunkvb.clrDir=/opt/compiler-explorer/dotnet-trunk
 compiler.dotnettrunkvb.buildConfig=Release
-compiler.dotnettrunkvb.langVersion=preview
+compiler.dotnettrunkvb.langVersion=latest
 compiler.dotnettrunkvb.isNightly=true
diff --git a/etc/config/vb.defaults.properties b/etc/config/vb.defaults.properties
index d3f01bf4b..48b021b2c 100644
--- a/etc/config/vb.defaults.properties
+++ b/etc/config/vb.defaults.properties
@@ -1,20 +1,20 @@
-compilers=&dotnetcoreclr:&dotnetcrossgen2:&dotnetmono:&dotnetnativeaot:&dotnetildasm:&dotnetlegacy
+compilers=&dotnetcoreclr:&dotnetcrossgen2:&dotnetmono:&dotnetnativeaot:&dotnetildasm:&dotnetilspy:&dotnetlegacy
 supportsBinary=true
 needsMulti=false
-defaultCompiler=dotnet80vbcoreclr
+defaultCompiler=dotnet90vbcoreclr
 executionEnvironmentClass=local-dotnet
 
-group.dotnetcoreclr.compilers=dotnettrunkvbcoreclr:dotnet80vbcoreclr:dotnet70vbcoreclr
+group.dotnetcoreclr.compilers=dotnettrunkvbcoreclr:dotnet90vbcoreclr:dotnet80vbcoreclr:dotnet70vbcoreclr:dotnet60vbcoreclr
 group.dotnetcoreclr.compilerCategories=coreclr
 group.dotnetcoreclr.compilerType=dotnetcoreclr
 group.dotnetcoreclr.groupName=.NET CoreCLR
 
-group.dotnetcrossgen2.compilers=dotnettrunkvbcrossgen2:dotnet80vbcrossgen2:dotnet70vbcrossgen2:dotnet60vbcrossgen2
+group.dotnetcrossgen2.compilers=dotnettrunkvbcrossgen2:dotnet90vbcrossgen2:dotnet80vbcrossgen2:dotnet70vbcrossgen2:dotnet60vbcrossgen2
 group.dotnetcrossgen2.compilerCategories=crossgen2
 group.dotnetcrossgen2.compilerType=dotnetcrossgen2
 group.dotnetcrossgen2.groupName=.NET Crossgen2
 
-group.dotnetmono.compilers=dotnettrunkvbmono
+group.dotnetmono.compilers=dotnettrunkvbmono:dotnet90vbmono:dotnet80vbmono:dotnet70vbmono:dotnet60vbmono
 group.dotnetmono.compilerCategories=mono
 group.dotnetmono.compilerType=dotnetmono
 group.dotnetmono.groupName=.NET Mono
@@ -24,10 +24,15 @@ group.dotnetnativeaot.compilerCategories=nativeaot
 group.dotnetnativeaot.compilerType=dotnetnativeaot
 group.dotnetnativeaot.groupName=.NET NativeAOT
 
-group.dotnetildasm.compilers=dotnettrunkvbildasm
+group.dotnetildasm.compilers=dotnettrunkvbildasm:dotnet90vbildasm:dotnet80vbildasm:dotnet70vbildasm:dotnet60vbildasm
 group.dotnetildasm.compilerCategories=ildasm
 group.dotnetildasm.compilerType=dotnetildasm
-group.dotnetildasm.groupName=.NET IL Disassembler
+group.dotnetildasm.groupName=.NET ILDasm
+
+group.dotnetilspy.compilers=dotnettrunkvbilspy:dotnet90vbilspy:dotnet80vbilspy:dotnet70vbilspy:dotnet60vbilspy
+group.dotnetilspy.compilerCategories=ilspy
+group.dotnetilspy.compilerType=dotnetilspy
+group.dotnetilspy.groupName=.NET ILSpy
 
 group.dotnetlegacy.compilers=dotnettrunkvb:dotnet707vb:dotnet703vb:dotnet701vb:dotnet6018vb:dotnet6014vb:dotnet6011vb
 group.dotnetlegacy.compilerCategories=legacy
@@ -36,20 +41,32 @@ group.dotnetlegacy.groupName=Legacy
 
 # CoreCLR compilers
 
-compiler.dotnet70vbcoreclr.exe=/opt/compiler-explorer/dotnet-v7.0.19/.dotnet/dotnet
-compiler.dotnet70vbcoreclr.name=.NET CoreCLR 7.0
-compiler.dotnet70vbcoreclr.clrDir=/opt/compiler-explorer/dotnet-v7.0.19
+compiler.dotnet60vbcoreclr.exe=/opt/compiler-explorer/dotnet-v6.0.36/.dotnet/dotnet
+compiler.dotnet60vbcoreclr.name=.NET 6.0 CoreCLR
+compiler.dotnet60vbcoreclr.clrDir=/opt/compiler-explorer/dotnet-v6.0.36
+compiler.dotnet60vbcoreclr.buildConfig=Release
+compiler.dotnet60vbcoreclr.langVersion=latest
+
+compiler.dotnet70vbcoreclr.exe=/opt/compiler-explorer/dotnet-v7.0.20/.dotnet/dotnet
+compiler.dotnet70vbcoreclr.name=.NET 7.0 CoreCLR
+compiler.dotnet70vbcoreclr.clrDir=/opt/compiler-explorer/dotnet-v7.0.20
 compiler.dotnet70vbcoreclr.buildConfig=Release
 compiler.dotnet70vbcoreclr.langVersion=latest
 
-compiler.dotnet80vbcoreclr.exe=/opt/compiler-explorer/dotnet-v8.0.5/.dotnet/dotnet
-compiler.dotnet80vbcoreclr.name=.NET CoreCLR 8.0
-compiler.dotnet80vbcoreclr.clrDir=/opt/compiler-explorer/dotnet-v8.0.5
+compiler.dotnet80vbcoreclr.exe=/opt/compiler-explorer/dotnet-v8.0.11/.dotnet/dotnet
+compiler.dotnet80vbcoreclr.name=.NET 8.0 CoreCLR
+compiler.dotnet80vbcoreclr.clrDir=/opt/compiler-explorer/dotnet-v8.0.11
 compiler.dotnet80vbcoreclr.buildConfig=Release
 compiler.dotnet80vbcoreclr.langVersion=latest
 
+compiler.dotnet90vbcoreclr.exe=/opt/compiler-explorer/dotnet-v9.0.0/.dotnet/dotnet
+compiler.dotnet90vbcoreclr.name=.NET 9.0 CoreCLR
+compiler.dotnet90vbcoreclr.clrDir=/opt/compiler-explorer/dotnet-v9.0.0
+compiler.dotnet90vbcoreclr.buildConfig=Release
+compiler.dotnet90vbcoreclr.langVersion=latest
+
 compiler.dotnettrunkvbcoreclr.exe=/opt/compiler-explorer/dotnet-trunk/.dotnet/dotnet
-compiler.dotnettrunkvbcoreclr.name=.NET CoreCLR (main)
+compiler.dotnettrunkvbcoreclr.name=.NET (main) CoreCLR
 compiler.dotnettrunkvbcoreclr.clrDir=/opt/compiler-explorer/dotnet-trunk
 compiler.dotnettrunkvbcoreclr.buildConfig=Release
 compiler.dotnettrunkvbcoreclr.langVersion=latest
@@ -57,26 +74,32 @@ compiler.dotnettrunkvbcoreclr.isNightly=true
 
 # Crossgen2 compilers
 
-compiler.dotnet60vbcrossgen2.exe=/opt/compiler-explorer/dotnet-v6.0.30/.dotnet/dotnet
-compiler.dotnet60vbcrossgen2.name=.NET Crossgen2 6.0
-compiler.dotnet60vbcrossgen2.clrDir=/opt/compiler-explorer/dotnet-v6.0.30
+compiler.dotnet60vbcrossgen2.exe=/opt/compiler-explorer/dotnet-v6.0.36/.dotnet/dotnet
+compiler.dotnet60vbcrossgen2.name=.NET 6.0 Crossgen2
+compiler.dotnet60vbcrossgen2.clrDir=/opt/compiler-explorer/dotnet-v6.0.36
 compiler.dotnet60vbcrossgen2.buildConfig=Release
 compiler.dotnet60vbcrossgen2.langVersion=latest
 
-compiler.dotnet70vbcrossgen2.exe=/opt/compiler-explorer/dotnet-v7.0.19/.dotnet/dotnet
-compiler.dotnet70vbcrossgen2.name=.NET Crossgen2 7.0
-compiler.dotnet70vbcrossgen2.clrDir=/opt/compiler-explorer/dotnet-v7.0.19
+compiler.dotnet70vbcrossgen2.exe=/opt/compiler-explorer/dotnet-v7.0.20/.dotnet/dotnet
+compiler.dotnet70vbcrossgen2.name=.NET 7.0 Crossgen2
+compiler.dotnet70vbcrossgen2.clrDir=/opt/compiler-explorer/dotnet-v7.0.20
 compiler.dotnet70vbcrossgen2.buildConfig=Release
 compiler.dotnet70vbcrossgen2.langVersion=latest
 
-compiler.dotnet80vbcrossgen2.exe=/opt/compiler-explorer/dotnet-v8.0.5/.dotnet/dotnet
-compiler.dotnet80vbcrossgen2.name=.NET Crossgen2 8.0
-compiler.dotnet80vbcrossgen2.clrDir=/opt/compiler-explorer/dotnet-v8.0.5
+compiler.dotnet80vbcrossgen2.exe=/opt/compiler-explorer/dotnet-v8.0.11/.dotnet/dotnet
+compiler.dotnet80vbcrossgen2.name=.NET 8.0 Crossgen2
+compiler.dotnet80vbcrossgen2.clrDir=/opt/compiler-explorer/dotnet-v8.0.11
 compiler.dotnet80vbcrossgen2.buildConfig=Release
 compiler.dotnet80vbcrossgen2.langVersion=latest
 
+compiler.dotnet90vbcrossgen2.exe=/opt/compiler-explorer/dotnet-v9.0.0/.dotnet/dotnet
+compiler.dotnet90vbcrossgen2.name=.NET 9.0 Crossgen2
+compiler.dotnet90vbcrossgen2.clrDir=/opt/compiler-explorer/dotnet-v9.0.0
+compiler.dotnet90vbcrossgen2.buildConfig=Release
+compiler.dotnet90vbcrossgen2.langVersion=latest
+
 compiler.dotnettrunkvbcrossgen2.exe=/opt/compiler-explorer/dotnet-trunk/.dotnet/dotnet
-compiler.dotnettrunkvbcrossgen2.name=.NET Crossgen2 (main)
+compiler.dotnettrunkvbcrossgen2.name=.NET (main) Crossgen2
 compiler.dotnettrunkvbcrossgen2.clrDir=/opt/compiler-explorer/dotnet-trunk
 compiler.dotnettrunkvbcrossgen2.buildConfig=Release
 compiler.dotnettrunkvbcrossgen2.langVersion=latest
@@ -84,8 +107,32 @@ compiler.dotnettrunkvbcrossgen2.isNightly=true
 
 # Mono compilers
 
+compiler.dotnet60vbmono.exe=/opt/compiler-explorer/dotnet-v6.0.36/.dotnet/dotnet
+compiler.dotnet60vbmono.name=.NET 6.0 Mono
+compiler.dotnet60vbmono.clrDir=/opt/compiler-explorer/dotnet-v6.0.36
+compiler.dotnet60vbmono.buildConfig=Release
+compiler.dotnet60vbmono.langVersion=latest
+
+compiler.dotnet70vbmono.exe=/opt/compiler-explorer/dotnet-v7.0.20/.dotnet/dotnet
+compiler.dotnet70vbmono.name=.NET 7.0 Mono
+compiler.dotnet70vbmono.clrDir=/opt/compiler-explorer/dotnet-v7.0.20
+compiler.dotnet70vbmono.buildConfig=Release
+compiler.dotnet70vbmono.langVersion=latest
+
+compiler.dotnet80vbmono.exe=/opt/compiler-explorer/dotnet-v8.0.11/.dotnet/dotnet
+compiler.dotnet80vbmono.name=.NET 8.0 Mono
+compiler.dotnet80vbmono.clrDir=/opt/compiler-explorer/dotnet-v8.0.11
+compiler.dotnet80vbmono.buildConfig=Release
+compiler.dotnet80vbmono.langVersion=latest
+
+compiler.dotnet90vbmono.exe=/opt/compiler-explorer/dotnet-v9.0.0/.dotnet/dotnet
+compiler.dotnet90vbmono.name=.NET 9.0 Mono
+compiler.dotnet90vbmono.clrDir=/opt/compiler-explorer/dotnet-v9.0.0
+compiler.dotnet90vbmono.buildConfig=Release
+compiler.dotnet90vbmono.langVersion=latest
+
 compiler.dotnettrunkvbmono.exe=/opt/compiler-explorer/dotnet-trunk/.dotnet/dotnet
-compiler.dotnettrunkvbmono.name=.NET Mono (main)
+compiler.dotnettrunkvbmono.name=.NET (main) Mono
 compiler.dotnettrunkvbmono.clrDir=/opt/compiler-explorer/dotnet-trunk
 compiler.dotnettrunkvbmono.buildConfig=Release
 compiler.dotnettrunkvbmono.langVersion=latest
@@ -94,21 +141,78 @@ compiler.dotnettrunkvbmono.isNightly=true
 # NativeAOT compilers
 
 compiler.dotnettrunkvbnativeaot.exe=/opt/compiler-explorer/dotnet-trunk/.dotnet/dotnet
-compiler.dotnettrunkvbnativeaot.name=.NET NativeAOT (main)
+compiler.dotnettrunkvbnativeaot.name=.NET (main) NativeAOT
 compiler.dotnettrunkvbnativeaot.clrDir=/opt/compiler-explorer/dotnet-trunk
 compiler.dotnettrunkvbnativeaot.buildConfig=Release
 compiler.dotnettrunkvbnativeaot.langVersion=latest
 compiler.dotnettrunkvbnativeaot.isNightly=true
 
-# IL disassembler compilers
+# ILDasm compilers
+
+compiler.dotnet60vbildasm.exe=/opt/compiler-explorer/dotnet-v6.0.36/.dotnet/dotnet
+compiler.dotnet60vbildasm.name=.NET 6.0 ILDasm
+compiler.dotnet60vbildasm.clrDir=/opt/compiler-explorer/dotnet-v6.0.36
+compiler.dotnet60vbildasm.buildConfig=Release
+compiler.dotnet60vbildasm.langVersion=latest
+
+compiler.dotnet70vbildasm.exe=/opt/compiler-explorer/dotnet-v7.0.20/.dotnet/dotnet
+compiler.dotnet70vbildasm.name=.NET 7.0 ILDasm
+compiler.dotnet70vbildasm.clrDir=/opt/compiler-explorer/dotnet-v7.0.20
+compiler.dotnet70vbildasm.buildConfig=Release
+compiler.dotnet70vbildasm.langVersion=latest
+
+compiler.dotnet80vbildasm.exe=/opt/compiler-explorer/dotnet-v8.0.11/.dotnet/dotnet
+compiler.dotnet80vbildasm.name=.NET 8.0 ILDasm
+compiler.dotnet80vbildasm.clrDir=/opt/compiler-explorer/dotnet-v8.0.11
+compiler.dotnet80vbildasm.buildConfig=Release
+compiler.dotnet80vbildasm.langVersion=latest
+
+compiler.dotnet90vbildasm.exe=/opt/compiler-explorer/dotnet-v9.0.0/.dotnet/dotnet
+compiler.dotnet90vbildasm.name=.NET 9.0 ILDasm
+compiler.dotnet90vbildasm.clrDir=/opt/compiler-explorer/dotnet-v9.0.0
+compiler.dotnet90vbildasm.buildConfig=Release
+compiler.dotnet90vbildasm.langVersion=latest
 
 compiler.dotnettrunkvbildasm.exe=/opt/compiler-explorer/dotnet-trunk/.dotnet/dotnet
-compiler.dotnettrunkvbildasm.name=.NET IL Disassembler (main)
+compiler.dotnettrunkvbildasm.name=.NET (main) ILDasm
 compiler.dotnettrunkvbildasm.clrDir=/opt/compiler-explorer/dotnet-trunk
 compiler.dotnettrunkvbildasm.buildConfig=Release
 compiler.dotnettrunkvbildasm.langVersion=latest
 compiler.dotnettrunkvbildasm.isNightly=true
 
+# ILSpy compilers
+
+compiler.dotnet60vbilspy.exe=/opt/compiler-explorer/dotnet-v6.0.36/.dotnet/dotnet
+compiler.dotnet60vbilspy.name=.NET 6.0 ILSpy
+compiler.dotnet60vbilspy.clrDir=/opt/compiler-explorer/dotnet-v6.0.36
+compiler.dotnet60vbilspy.buildConfig=Release
+compiler.dotnet60vbilspy.langVersion=latest
+
+compiler.dotnet70vbilspy.exe=/opt/compiler-explorer/dotnet-v7.0.20/.dotnet/dotnet
+compiler.dotnet70vbilspy.name=.NET 7.0 ILSpy
+compiler.dotnet70vbilspy.clrDir=/opt/compiler-explorer/dotnet-v7.0.20
+compiler.dotnet70vbilspy.buildConfig=Release
+compiler.dotnet70vbilspy.langVersion=latest
+
+compiler.dotnet80vbilspy.exe=/opt/compiler-explorer/dotnet-v8.0.11/.dotnet/dotnet
+compiler.dotnet80vbilspy.name=.NET 8.0 ILSpy
+compiler.dotnet80vbilspy.clrDir=/opt/compiler-explorer/dotnet-v8.0.11
+compiler.dotnet80vbilspy.buildConfig=Release
+compiler.dotnet80vbilspy.langVersion=latest
+
+compiler.dotnet90vbilspy.exe=/opt/compiler-explorer/dotnet-v9.0.0/.dotnet/dotnet
+compiler.dotnet90vbilspy.name=.NET 9.0 ILSpy
+compiler.dotnet90vbilspy.clrDir=/opt/compiler-explorer/dotnet-v9.0.0
+compiler.dotnet90vbilspy.buildConfig=Release
+compiler.dotnet90vbilspy.langVersion=latest
+
+compiler.dotnettrunkvbilspy.exe=/opt/compiler-explorer/dotnet-trunk/.dotnet/dotnet
+compiler.dotnettrunkvbilspy.name=.NET (main) ILSpy
+compiler.dotnettrunkvbilspy.clrDir=/opt/compiler-explorer/dotnet-trunk
+compiler.dotnettrunkvbilspy.buildConfig=Release
+compiler.dotnettrunkvbilspy.langVersion=latest
+compiler.dotnettrunkvbilspy.isNightly=true
+
 # Legacy compilers (for backwards compatibility, don't add new compilers here)
 
 compiler.dotnet6011vb.exe=/opt/compiler-explorer/dotnet-v6.0.11/.dotnet/dotnet
diff --git a/etc/config/vyper.amazon.properties b/etc/config/vyper.amazon.properties
new file mode 100644
index 000000000..3a41e6841
--- /dev/null
+++ b/etc/config/vyper.amazon.properties
@@ -0,0 +1,22 @@
+compilers=&vyper
+defaultCompiler=vyper040
+
+group.vyper.compilers=vyper040:vyper0310:vyper039:vyper038:vyper037:vyper036
+group.vyper.compilerType=vyper
+group.vyper.instructionSet=evm
+group.vyper.versionFlag=--version
+group.vyper.isSemVer=true
+group.vyper.baseName=vyper
+
+compiler.vyper040.exe=/opt/compiler-explorer/vyper/v0.4.0/bin/vyper
+compiler.vyper040.semver=0.4.0
+compiler.vyper0310.exe=/opt/compiler-explorer/vyper/v0.3.10/bin/vyper
+compiler.vyper0310.semver=0.3.10
+compiler.vyper039.exe=/opt/compiler-explorer/vyper/v0.3.9/bin/vyper
+compiler.vyper039.semver=0.3.9
+compiler.vyper038.exe=/opt/compiler-explorer/vyper/v0.3.8/bin/vyper
+compiler.vyper038.semver=0.3.8
+compiler.vyper037.exe=/opt/compiler-explorer/vyper/v0.3.7/bin/vyper
+compiler.vyper037.semver=0.3.7
+compiler.vyper036.exe=/opt/compiler-explorer/vyper/v0.3.6/bin/vyper
+compiler.vyper036.semver=0.3.6
diff --git a/etc/config/vyper.defaults.properties b/etc/config/vyper.defaults.properties
new file mode 100644
index 000000000..ad05a86e8
--- /dev/null
+++ b/etc/config/vyper.defaults.properties
@@ -0,0 +1,9 @@
+compilers=vyper
+compilerType=vyper
+
+versionFlag=--version
+
+compiler.vyper.exe=/path/to/vyper
+compiler.vyper.isSemVer=true
+compiler.vyper.instructionSet=evm
+compiler.vyper.options=--optimize none
diff --git a/etc/scripts/generate_site_template_screenshots.ts b/etc/scripts/generate_site_template_screenshots.ts
index 8b6c17aef..053ace821 100644
--- a/etc/scripts/generate_site_template_screenshots.ts
+++ b/etc/scripts/generate_site_template_screenshots.ts
@@ -137,7 +137,7 @@ async function generate_screenshot(url: string, output_path: string, settings) {
         process.exit(1);
     }
     for(const [k, v] of meta_directives) {
-        if(k === "meta.screenshot_dimentions") {
+        if(k === "meta.screenshot_dimensions") {
             const [w, h] = v.split("x").map(x => parseInt(x));
             defaultViewport.width = w;
             defaultViewport.height = h;
diff --git a/examples/vyper/default.vy b/examples/vyper/default.vy
new file mode 100644
index 000000000..b1df67426
--- /dev/null
+++ b/examples/vyper/default.vy
@@ -0,0 +1,15 @@
+stored_number: uint256
+
+@external
+def set_number(num: uint256):
+    self.stored_number = num
+
+@external
+@view
+def get_number() -> uint256:
+    return self.stored_number
+
+@external
+@view
+def square(a: uint256) -> uint256:
+    return a * a
diff --git a/lib/base-compiler.ts b/lib/base-compiler.ts
index 683de0f60..451fc264a 100644
--- a/lib/base-compiler.ts
+++ b/lib/base-compiler.ts
@@ -31,6 +31,7 @@ import temp from 'temp';
 import _ from 'underscore';
 
 import {unique} from '../shared/common-utils.js';
+import {OptRemark} from '../static/panes/opt-view.interfaces.js';
 import {PPOptions} from '../static/panes/pp-view.interfaces.js';
 import {ParsedAsmResultLine} from '../types/asmresult/asmresult.interfaces.js';
 import {ClangirBackendOptions} from '../types/compilation/clangir.interfaces.js';
@@ -64,7 +65,7 @@ import type {
     OptPipelineBackendOptions,
     OptPipelineOutput,
 } from '../types/compilation/opt-pipeline-output.interfaces.js';
-import type {CompilerInfo, ICompiler, PreliminaryCompilerInfo} from '../types/compiler.interfaces.js';
+import type {CompilerInfo, PreliminaryCompilerInfo} from '../types/compiler.interfaces.js';
 import {
     BasicExecutionResult,
     ExecutableExecutionOptions,
@@ -110,7 +111,7 @@ import {InstructionSets} from './instructionsets.js';
 import {languages} from './languages.js';
 import {LlvmAstParser} from './llvm-ast.js';
 import {LlvmIrParser} from './llvm-ir.js';
-import {LLVMOptInfo, processRawOptRemarks} from './llvm-opt-transformer.js';
+import {processRawOptRemarks} from './llvm-opt-transformer.js';
 import {logger} from './logger.js';
 import {getObjdumperTypeByKey} from './objdumper/index.js';
 import {ClientOptionsType, OptionsHandlerLibrary, VersionInfo} from './options-handler.js';
@@ -179,8 +180,8 @@ export interface SimpleOutputFilenameCompiler {
     getOutputFilename(dirPath: string): string;
 }
 
-export class BaseCompiler implements ICompiler {
-    public compiler: CompilerInfo; // TODO: Some missing types still present in Compiler type
+export class BaseCompiler {
+    public compiler: CompilerInfo;
     public lang: Language;
     protected compileFilename: string;
     protected env: CompilationEnvironment;
@@ -2304,7 +2305,7 @@ export class BaseCompiler implements ICompiler {
         backendOptions: Record<string, any>,
         libraries: SelectedLibraryVersion[],
         tools: ActiveTool[],
-    ): Promise<[any, LLVMOptInfo[], StackUsage.StackUsageInfo[]]> {
+    ): Promise<[any, OptRemark[], StackUsage.StackUsageInfo[]]> {
         const inputFilenameSafe = this.filename(inputFilename);
 
         const outputFilename = this.getOutputFilename(dirPath, this.outputFilebase, key);
@@ -2857,7 +2858,7 @@ export class BaseCompiler implements ICompiler {
         // it for preprocessor output.
         if ((this.compiler.lang === 'c++' || this.compiler.lang === 'c') && options.includes('-E')) {
             for (const key in filters) {
-                filters[key] = false;
+                (filters as any)[key] = false; // `any` cast is needed because filters can contain non-boolean fields
             }
 
             if (filters.binaryObject && !this.compiler.supportsBinaryObject) {
@@ -3005,7 +3006,7 @@ export class BaseCompiler implements ICompiler {
         backendOptions: Record<string, any>,
         filters: ParseFiltersAndOutputOptions,
         options: string[],
-        optOutput: LLVMOptInfo[] | undefined,
+        optOutput: OptRemark[] | undefined,
         stackUsageOutput: StackUsage.StackUsageInfo[] | undefined,
         bypassCache: BypassCache,
         customBuildPath?: string,
@@ -3129,7 +3130,7 @@ export class BaseCompiler implements ICompiler {
 
     async processOptOutput(optPath: string) {
         const optRemarksRaw = await fs.readFile(optPath, 'utf8');
-        const output: LLVMOptInfo[] = processRawOptRemarks(optRemarksRaw, this.compileFilename);
+        const output: OptRemark[] = processRawOptRemarks(optRemarksRaw, this.compileFilename);
 
         if (this.compiler.demangler) {
             const result = JSON.stringify(output, null, 4);
@@ -3140,7 +3141,7 @@ export class BaseCompiler implements ICompiler {
             );
             if (demangleResult.stdout.length > 0 && !demangleResult.truncated) {
                 try {
-                    return JSON.parse(demangleResult.stdout) as LLVMOptInfo[];
+                    return JSON.parse(demangleResult.stdout) as OptRemark[];
                 } catch (exception) {
                     // swallow exception and return non-demangled output
                     logger.warn(`Caught exception ${exception} during opt demangle parsing`);
@@ -3333,7 +3334,7 @@ but nothing was dumped. Possible causes are:
     async postProcess(result: CompilationResult, outputFilename: string, filters: ParseFiltersAndOutputOptions) {
         const postProcess = _.compact(this.compiler.postProcess);
         const maxSize = this.env.ceProps('max-asm-size', 64 * 1024 * 1024);
-        const optPromise = result.optPath ? this.processOptOutput(unwrap(result.optPath)) : ([] as LLVMOptInfo[]);
+        const optPromise = result.optPath ? this.processOptOutput(unwrap(result.optPath)) : ([] as OptRemark[]);
         const stackUsagePromise = result.stackUsagePath
             ? this.processStackUsageOutput(result.stackUsagePath)
             : ([] as StackUsage.StackUsageInfo[]);
diff --git a/lib/cfg/cfg-parsers/llvm-ir.ts b/lib/cfg/cfg-parsers/llvm-ir.ts
index 644beac29..fc2c3a973 100644
--- a/lib/cfg/cfg-parsers/llvm-ir.ts
+++ b/lib/cfg/cfg-parsers/llvm-ir.ts
@@ -152,10 +152,11 @@ export class LlvmIrCfgParser extends BaseCFGParser {
                     //    i32 14, label %7
                     //    i32 60, label %2
                     //    i32 12, label %3
+                    //    i32 35, label %"core::Result<&[u8]>::exit53"
                     //    i32 4, label %4
                     //  ], !dbg !60
                     const end = lastInst--;
-                    while (!asmArr[lastInst].text.includes('[')) {
+                    while (!asmArr[lastInst].text.trim().startsWith('switch')) {
                         lastInst--;
                     }
                     return this.concatInstructions(asmArr, lastInst, end + 1);
diff --git a/lib/clientstate-normalizer.ts b/lib/clientstate-normalizer.ts
index fbfab23a0..072f69644 100644
--- a/lib/clientstate-normalizer.ts
+++ b/lib/clientstate-normalizer.ts
@@ -145,14 +145,15 @@ export class ClientStateNormalizer {
         }
     }
 
-    addToolToCompiler(compilerId, toolId, args, stdin) {
+    addToolToCompiler(compilerId: number, toolId: string, args: string[], stdin: string) {
         const glCompiler = this.findCompilerInGoldenLayout(this.rootContent!, compilerId);
         if (glCompiler) {
-            let compiler;
+            let compiler: ClientStateCompiler;
             if (glCompiler.componentState.source) {
                 const session = this.normalized.findOrCreateSession(glCompiler.componentState.source);
                 compiler = session.findOrCreateCompiler(compilerId);
-            } else if (glCompiler.componentState.tree) {
+            } else {
+                assert(glCompiler.componentState.tree);
                 const tree = this.normalized.findOrCreateTree(glCompiler.componentState.tree);
                 compiler = tree.findOrCreateCompiler(compilerId);
             }
@@ -516,9 +517,9 @@ class GoldenLayoutComponents {
     createToolComponent(
         session: ClientStateSession | null,
         compilerIndex: number,
-        toolId: number,
-        args,
-        stdin,
+        toolId: string,
+        args: string[],
+        stdin: string,
         customSessionId?,
     ): GoldenLayoutComponentStruct {
         return {
@@ -832,9 +833,9 @@ export class ClientStateGoldenifier extends GoldenLayoutComponents {
     newToolStackFromCompiler(
         session: ClientStateSession,
         compilerIndex: number,
-        toolId,
-        args,
-        stdin,
+        toolId: string,
+        args: string[],
+        stdin: string,
         width: number,
     ): BasicGoldenLayoutStruct {
         return this.newStackWithOneComponent(
diff --git a/lib/compilers/_all.ts b/lib/compilers/_all.ts
index 7d181e882..2a9a63528 100644
--- a/lib/compilers/_all.ts
+++ b/lib/compilers/_all.ts
@@ -57,6 +57,7 @@ export {
     DotNetCoreClrCompiler,
     DotNetCrossgen2Compiler,
     DotNetIlDasmCompiler,
+    DotNetIlSpyCompiler,
     DotNetLegacyCompiler,
     DotNetMonoCompiler,
     DotNetNativeAotCompiler,
@@ -137,6 +138,7 @@ export {TurboCCompiler} from './turboc.js';
 export {TypeScriptNativeCompiler} from './typescript-native.js';
 export {VCompiler} from './v.js';
 export {ValaCompiler} from './vala.js';
+export {VyperCompiler} from './vyper.js';
 export {V8Compiler} from './v8.js';
 export {Win32Compiler} from './win32.js';
 export {Win32Vc6Compiler} from './win32-vc6.js';
diff --git a/lib/compilers/cerberus.ts b/lib/compilers/cerberus.ts
index 94ef8a682..ccd8ab2c2 100644
--- a/lib/compilers/cerberus.ts
+++ b/lib/compilers/cerberus.ts
@@ -125,7 +125,7 @@ export class CerberusCompiler extends BaseCompiler {
         }
 
         const lines = result.asm.split('\n');
-        const plines = lines.map(l => ({text: l}));
+        const plines = lines.map((l: string) => ({text: l}));
         return {
             asm: plines,
             languageId: 'core',
diff --git a/lib/compilers/clang.ts b/lib/compilers/clang.ts
index af1e40073..74cc1a36a 100644
--- a/lib/compilers/clang.ts
+++ b/lib/compilers/clang.ts
@@ -27,6 +27,7 @@ import path from 'path';
 
 import _ from 'underscore';
 
+import {OptRemark} from '../../static/panes/opt-view.interfaces.js';
 import type {
     ActiveTool,
     BuildResult,
@@ -43,7 +44,6 @@ import {ArtifactType} from '../../types/tool.interfaces.js';
 import {addArtifactToResult} from '../artifact-utils.js';
 import {BaseCompiler} from '../base-compiler.js';
 import {CompilationEnvironment} from '../compilation-env.js';
-import {LLVMOptInfo} from '../llvm-opt-transformer.js';
 import {AmdgpuAsmParser} from '../parsers/asm-parser-amdgpu.js';
 import {HexagonAsmParser} from '../parsers/asm-parser-hexagon.js';
 import {SassAsmParser} from '../parsers/asm-parser-sass.js';
@@ -197,7 +197,7 @@ export class ClangCompiler extends BaseCompiler {
         backendOptions: Record<string, any>,
         filters: ParseFiltersAndOutputOptions,
         options: string[],
-        optOutput: LLVMOptInfo[] | undefined,
+        optOutput: OptRemark[] | undefined,
         stackUsageOutput: StackUsageInfo[] | undefined,
         bypassCache: BypassCache,
         customBuildPath?: string,
diff --git a/lib/compilers/d8.ts b/lib/compilers/d8.ts
index 69403abf9..5a818befd 100644
--- a/lib/compilers/d8.ts
+++ b/lib/compilers/d8.ts
@@ -51,6 +51,9 @@ export class D8Compiler extends BaseCompiler implements SimpleOutputFilenameComp
 
     minApiArgRegex: RegExp;
 
+    jvmSyspropArgRegex: RegExp;
+    syspropArgRegex: RegExp;
+
     javaId: string;
     kotlinId: string;
 
@@ -64,6 +67,9 @@ export class D8Compiler extends BaseCompiler implements SimpleOutputFilenameComp
 
         this.minApiArgRegex = /^--min-api$/;
 
+        this.jvmSyspropArgRegex = /^-J.*$/;
+        this.syspropArgRegex = /^-D.*$/;
+
         this.javaId = this.compilerProps<string>(`group.${this.compiler.group}.javaId`);
         this.kotlinId = this.compilerProps<string>(`group.${this.compiler.group}.kotlinId`);
 
@@ -154,16 +160,25 @@ export class D8Compiler extends BaseCompiler implements SimpleOutputFilenameComp
         const sourceFileOptionIndex = options.findIndex(option => {
             return option.endsWith('.java') || option.endsWith('.kt');
         });
-        const userOptions = options.slice(0, sourceFileOptionIndex);
+        let userOptions = options.slice(0, sourceFileOptionIndex);
+        const syspropOptions: string[] = [];
         for (const option of userOptions) {
             if (this.minApiArgRegex.test(option)) {
                 useDefaultMinApi = false;
+            } else if (this.jvmSyspropArgRegex.test(option)) {
+                syspropOptions.push(option.replace('-J', '-'));
+            } else if (this.syspropArgRegex.test(option)) {
+                syspropOptions.push(option);
             }
         }
+        userOptions = userOptions.filter(
+            option => !this.jvmSyspropArgRegex.test(option) && !this.syspropArgRegex.test(option),
+        );
 
         const files = await fs.readdir(preliminaryCompilePath, {encoding: 'utf8', recursive: true});
         const classFiles = files.filter(f => f.endsWith('.class'));
         const d8Options = [
+            ...syspropOptions,
             '-cp',
             this.compiler.exe, // R8 jar.
             'com.android.tools.r8.D8', // Main class name for the D8 compiler.
diff --git a/lib/compilers/dosbox-compiler.ts b/lib/compilers/dosbox-compiler.ts
index 0b317c705..eb27ef826 100644
--- a/lib/compilers/dosbox-compiler.ts
+++ b/lib/compilers/dosbox-compiler.ts
@@ -154,7 +154,7 @@ export class DosboxCompiler extends BaseCompiler {
 
         const stdoutFilename = path.join(tempDir, 'STDOUT.TXT');
         const stdout = await fs.readFile(stdoutFilename);
-        (result as any).stdout = stdout.toString('utf8');
+        result.stdout = stdout.toString('utf8');
 
         return result;
     }
diff --git a/lib/compilers/dotnet.ts b/lib/compilers/dotnet.ts
index 63bf6ea43..61b18ec6a 100644
--- a/lib/compilers/dotnet.ts
+++ b/lib/compilers/dotnet.ts
@@ -51,6 +51,7 @@ class DotNetCompiler extends BaseCompiler {
     private readonly crossgen2Path: string;
     private readonly ilcPath: string;
     private readonly ildasmPath: string;
+    private readonly toolsPath: string;
 
     constructor(compilerInfo: PreliminaryCompilerInfo, env: CompilationEnvironment) {
         super(compilerInfo, env);
@@ -65,6 +66,7 @@ class DotNetCompiler extends BaseCompiler {
         this.crossgen2Path = path.join(this.clrBuildDir, 'crossgen2', 'crossgen2');
         this.ilcPath = path.join(this.clrBuildDir, 'ilc-published', 'ilc');
         this.ildasmPath = path.join(this.clrBuildDir, 'ildasm');
+        this.toolsPath = path.join(this.clrBuildDir, 'dotnet-tools', '.store');
 
         this.asm = new DotNetAsmParser();
         this.disassemblyLoaderPath = path.join(this.clrBuildDir, 'DisassemblyLoader', 'DisassemblyLoader.dll');
@@ -271,7 +273,7 @@ class DotNetCompiler extends BaseCompiler {
                 break;
             }
             case 'il': {
-                compilerResult = await this.runIlasm(
+                compilerResult = await this.runIlAsm(
                     compilerInfo.compilerPath,
                     inputFilename,
                     outputFilename,
@@ -562,7 +564,7 @@ do()
         return await super.runCompiler(dotnetPath, [compilerInfo.compilerPath, ...options], inputFilename, execOptions);
     }
 
-    async runIlasm(
+    async runIlAsm(
         ilasmPath: string,
         inputFilename: string,
         outputFilename: string,
@@ -607,7 +609,8 @@ do()
         const programDllPath = path.join(programOutputPath, 'CompilerExplorer.dll');
         const envVarFileContents = ['DOTNET_EnableWriteXorExecute=0'];
         const isIlDasm = this.compiler.group === 'dotnetildasm';
-        const toolOptions: string[] = isIlDasm ? [] : ['--parallelism', '1'];
+        const isIlSpy = this.compiler.group === 'dotnetilspy';
+        const toolOptions: string[] = isIlDasm || isIlSpy ? [] : ['--parallelism', '1'];
         const toolSwitches: string[] = [];
 
         let overrideDiffable = false;
@@ -678,7 +681,7 @@ do()
             }
         }
 
-        if (!isIlDasm) {
+        if (!isIlDasm && !isIlSpy) {
             if (!overrideDiffable) {
                 if (compilerInfo.sdkMajorVersion < 8) {
                     toolOptions.push('--codegenopt', 'JitDiffableDasm=1');
@@ -728,6 +731,19 @@ do()
             if (ilDasmResult.code !== 0) {
                 return ilDasmResult;
             }
+        } else if (isIlSpy) {
+            const ilSpyResult = await this.runIlSpy(
+                execOptions,
+                programDllPath,
+                toolOptions,
+                toolSwitches,
+                this.getOutputFilename(programDir, this.outputFilebase),
+                compilerInfo.sdkMajorVersion <= 6,
+            );
+
+            if (ilSpyResult.code !== 0) {
+                return ilSpyResult;
+            }
         } else if (isCrossgen2) {
             const crossgen2Result = await this.runCrossgen2(
                 compiler,
@@ -758,17 +774,15 @@ do()
                 return ilcResult;
             }
         } else {
-            const envVarFilePath = path.join(programDir, '.env');
-            await fs.writeFile(envVarFilePath, envVarFileContents.join('\n'));
-
             const corerunResult = await this.runCorerunForDisasm(
                 execOptions,
                 this.clrBuildDir,
-                envVarFilePath,
+                envVarFileContents,
                 programDllPath,
                 corerunArgs,
                 this.getOutputFilename(programDir, this.outputFilebase),
                 isMono,
+                compilerInfo.sdkMajorVersion >= 7,
             );
 
             if (corerunResult.code !== 0) {
@@ -794,23 +808,34 @@ do()
     }
 
     async runCorerunForDisasm(
-        execOptions: ExecutionOptions,
+        execOptions: ExecutionOptionsWithEnv,
         coreRoot: string,
-        envPath: string,
+        envVars: string[],
         dllPath: string,
         options: string[],
         outputPath: string,
         isMono: boolean,
+        useEnvFile: boolean,
     ) {
         if (isMono) {
             coreRoot = path.join(coreRoot, 'mono');
         }
 
-        const corerunOptions = ['--clr-path', coreRoot, '--env', envPath].concat([
-            ...options,
-            this.disassemblyLoaderPath,
-            dllPath,
-        ]);
+        const corerunOptions = ['--clr-path', coreRoot].concat([...options, this.disassemblyLoaderPath, dllPath]);
+
+        if (useEnvFile) {
+            const envVarFilePath = path.join(path.dirname(outputPath), '.env');
+            await fs.writeFile(envVarFilePath, envVars.join('\n'));
+            corerunOptions.splice(0, 0, '--env', envVarFilePath);
+        } else {
+            for (const env of envVars) {
+                const delimiterIndex = env.indexOf('=');
+                if (delimiterIndex !== -1) {
+                    execOptions.env[env.substring(0, delimiterIndex)] = env.substring(delimiterIndex + 1);
+                }
+            }
+        }
+
         const compilerExecResult = await this.exec(this.corerunPath, corerunOptions, execOptions);
         const result = this.transformToCompilationResult(compilerExecResult, dllPath);
 
@@ -824,6 +849,38 @@ do()
         return result;
     }
 
+    async runIlSpy(
+        execOptions: ExecutionOptions,
+        dllPath: string,
+        toolOptions: string[],
+        toolSwitches: string[],
+        outputPath: string,
+        useDotNetHost: boolean,
+    ) {
+        const ilspyRoot = path.join(this.toolsPath, 'ilspycmd');
+        const ilspyVersionDirs = await fs.readdir(ilspyRoot);
+        const ilspyVersion = ilspyVersionDirs[0];
+        const ilspyToolsDir = path.join(ilspyRoot, ilspyVersion, 'ilspycmd', ilspyVersion, 'tools');
+        const targetFrameworkDirs = await fs.readdir(ilspyToolsDir);
+        const targetFramework = targetFrameworkDirs[0];
+        const ilspyPath = path.join(ilspyToolsDir, targetFramework, 'any', 'ilspycmd.dll');
+
+        // prettier-ignore
+        const ilspyOptions = [ilspyPath, dllPath, '--disable-updatecheck'].concat(toolOptions).concat(toolSwitches);
+        const compilerPath = useDotNetHost ? this.compiler.exe : this.corerunPath;
+        const compilerExecResult = await this.exec(compilerPath, ilspyOptions, execOptions);
+        const result = this.transformToCompilationResult(compilerExecResult, dllPath);
+
+        await fs.writeFile(
+            outputPath,
+            `// ilspy ${await this.getRuntimeVersion()}\n\n${result.stdout
+                .map(o => o.text)
+                .reduce((a, n) => `${a}\n${n}`, '')}`,
+        );
+
+        return result;
+    }
+
     async runIlDasm(
         execOptions: ExecutionOptions,
         dllPath: string,
@@ -1001,6 +1058,12 @@ export class DotNetIlDasmCompiler extends DotNetCompiler {
     }
 }
 
+export class DotNetIlSpyCompiler extends DotNetCompiler {
+    static get key() {
+        return 'dotnetilspy';
+    }
+}
+
 export class DotNetLegacyCompiler extends DotNetCompiler {
     static get key() {
         return 'dotnetlegacy';
diff --git a/lib/compilers/ldc.ts b/lib/compilers/ldc.ts
index 65ee6e599..edd7be844 100644
--- a/lib/compilers/ldc.ts
+++ b/lib/compilers/ldc.ts
@@ -112,7 +112,7 @@ export class LDCCompiler extends BaseCompiler {
 
         return this.loadASTOutput(
             await this.runCompiler(this.compiler.exe, newOptions, this.filename(inputFilename), execOptions),
-        ) as any;
+        );
     }
 
     async loadASTOutput(result: CompilationResult): Promise<ResultLine[]> {
diff --git a/lib/compilers/nim.ts b/lib/compilers/nim.ts
index dc2940c2e..75002dc07 100644
--- a/lib/compilers/nim.ts
+++ b/lib/compilers/nim.ts
@@ -27,6 +27,7 @@ import path from 'path';
 import fs from 'fs-extra';
 import _ from 'underscore';
 
+import {CompilationResult} from '../../types/compilation/compilation.interfaces.js';
 import type {PreliminaryCompilerInfo} from '../../types/compiler.interfaces.js';
 import type {ParseFiltersAndOutputOptions} from '../../types/features/filters.interfaces.js';
 import {unwrap} from '../assert.js';
@@ -91,14 +92,18 @@ export class NimCompiler extends BaseCompiler {
         return path.join(cacheDir, resultName);
     }
 
-    override async postProcess(result, outputFilename: string, filters: ParseFiltersAndOutputOptions) {
+    override async postProcess(
+        result: CompilationResult,
+        outputFilename: string,
+        filters: ParseFiltersAndOutputOptions,
+    ) {
         const options = result.compilationOptions;
         const cacheDir = this.cacheDir(outputFilename);
         try {
-            if (_.intersection(options, ['js', 'check']).length > 0) filters.binary = false;
+            if (_.intersection(options!, ['js', 'check']).length > 0) filters.binary = false;
             else {
                 filters.binary = true;
-                const objFile = this.getCacheFile(options, result.inputFilename, cacheDir);
+                const objFile = this.getCacheFile(options!, result.inputFilename!, cacheDir);
                 await fs.move(unwrap(objFile), outputFilename);
             }
             return super.postProcess(result, outputFilename, filters);
diff --git a/lib/compilers/r8.ts b/lib/compilers/r8.ts
index e1e57647d..1d0342737 100644
--- a/lib/compilers/r8.ts
+++ b/lib/compilers/r8.ts
@@ -132,17 +132,26 @@ export class R8Compiler extends D8Compiler implements SimpleOutputFilenameCompil
         const sourceFileOptionIndex = options.findIndex(option => {
             return option.endsWith('.java') || option.endsWith('.kt');
         });
-        const userOptions = options.slice(0, sourceFileOptionIndex);
+        let userOptions = options.slice(0, sourceFileOptionIndex);
+        const syspropOptions: string[] = [];
         for (const option of userOptions) {
             if (this.minApiArgRegex.test(option)) {
                 useDefaultMinApi = false;
+            } else if (this.jvmSyspropArgRegex.test(option)) {
+                syspropOptions.push(option.replace('-J', '-'));
+            } else if (this.syspropArgRegex.test(option)) {
+                syspropOptions.push(option);
             }
         }
+        userOptions = userOptions.filter(
+            option => !this.jvmSyspropArgRegex.test(option) && !this.syspropArgRegex.test(option),
+        );
 
         const files = await fs.readdir(preliminaryCompilePath);
         const classFiles = files.filter(f => f.endsWith('.class'));
         const r8Options = [
             '-Dcom.android.tools.r8.enableKeepAnnotations=1',
+            ...syspropOptions,
             '-cp',
             this.compiler.exe, // R8 jar.
             'com.android.tools.r8.R8',
diff --git a/lib/compilers/vyper.ts b/lib/compilers/vyper.ts
new file mode 100644
index 000000000..99ad3ea95
--- /dev/null
+++ b/lib/compilers/vyper.ts
@@ -0,0 +1,85 @@
+import path from 'path';
+
+import type {
+    AsmResultSource,
+    ParsedAsmResult,
+    ParsedAsmResultLine,
+} from '../../types/asmresult/asmresult.interfaces.js';
+import {BaseCompiler} from '../base-compiler.js';
+
+export class VyperCompiler extends BaseCompiler {
+    static get key() {
+        return 'vyper';
+    }
+
+    override getOutputFilename(dirPath: string) {
+        return path.join(dirPath, 'output.txt');
+    }
+
+    override optionsForFilter(): string[] {
+        return ['-f', 'opcodes,source_map', '-o', 'output.txt'];
+    }
+
+    override isCfgCompiler() {
+        // TODO: it is possible to extract CFG using rattle and pc_jump_map, might implement in the future
+        return false;
+    }
+
+    override async processAsm(result): Promise<ParsedAsmResult> {
+        if (result.code !== 0) {
+            const stderrOutput = result.stderr.map(entry => entry.text).join('\n');
+            return {asm: [{text: result.asm + '\n\n' + stderrOutput}]};
+        }
+
+        const [opcodesStr, sourceMapStr] = result.asm.split('\n');
+        const sourceMapObj = JSON.parse(sourceMapStr);
+
+        const segments: ParsedAsmResultLine[] = [];
+        const opcodesArray = opcodesStr.split(' ');
+
+        const pcPosMap = sourceMapObj['pc_pos_map'];
+
+        let pc = 0;
+
+        for (let i = 0; i < opcodesArray.length; i++) {
+            const opcode = opcodesArray[i];
+            let disassembly = opcode;
+
+            if (opcode.startsWith('PUSH') && opcode !== 'PUSH0' && i < opcodesArray.length - 1) {
+                disassembly += ` ${opcodesArray[i + 1]}`;
+                i++;
+            }
+
+            const source: AsmResultSource | null =
+                pc in pcPosMap
+                    ? {
+                          file: null,
+                          line: pcPosMap[pc][0],
+                          column: pcPosMap[pc][1],
+                          mainsource: true,
+                      }
+                    : null;
+
+            const asmResultLine: ParsedAsmResultLine = {
+                text: disassembly,
+                opcodes: [opcode],
+                address: pc,
+                disassembly,
+                source,
+            };
+
+            segments.push(asmResultLine);
+
+            if (opcode.startsWith('PUSH')) {
+                const pushBytes = parseInt(opcode.slice(4), 10);
+                pc += 1 + pushBytes;
+            } else {
+                pc += 1;
+            }
+        }
+
+        return {
+            asm: segments,
+        };
+    }
+}
diff --git a/lib/compilers/ylc.ts b/lib/compilers/ylc.ts
index 47e56c093..d1e9c386b 100644
--- a/lib/compilers/ylc.ts
+++ b/lib/compilers/ylc.ts
@@ -71,7 +71,7 @@ export class YLCCompiler extends BaseCompiler {
 
         return this.orderArguments(
             options,
-            '-in=' + inputFilename,
+            inputFilename,
             libIncludes,
             libOptions,
             libPathsAsFlags,
diff --git a/lib/handlers/api.ts b/lib/handlers/api.ts
index ef027e9b2..a90b3a228 100644
--- a/lib/handlers/api.ts
+++ b/lib/handlers/api.ts
@@ -141,8 +141,8 @@ export class ApiHandler {
             .all(methodNotAllowed);
         this.handle
             .route('/siteTemplates')
-            .get((req, res) => {
-                res.send(getSiteTemplates());
+            .get(async (req, res) => {
+                res.send(await getSiteTemplates());
             })
             .all(methodNotAllowed);
 
diff --git a/lib/handlers/source.ts b/lib/handlers/api/source-controller.ts
similarity index 54%
rename from lib/handlers/source.ts
rename to lib/handlers/api/source-controller.ts
index 9e49e60ca..065689401 100644
--- a/lib/handlers/source.ts
+++ b/lib/handlers/api/source-controller.ts
@@ -1,4 +1,4 @@
-// Copyright (c) 2017, Compiler Explorer Authors
+// Copyright (c) 2024, Compiler Explorer Authors
 // All rights reserved.
 //
 // Redistribution and use in source and binary forms, with or without
@@ -25,46 +25,42 @@
 import express from 'express';
 import _ from 'underscore';
 
-import {Source} from '../sources/index.js';
+import {addStaticHeaders} from '../../../app.js';
+import {Source} from '../../../types/source.interfaces.js';
 
-// TODO(supergrecko): Maybe provide a more elegant way to do this instead of accessing keys?
-const ALLOWED_ACTIONS = new Set(['list', 'load']);
+export class SourceController {
+    public constructor(private readonly sources: Source[]) {}
 
-export class SourceHandler {
-    public constructor(
-        private fileSources: Source[],
-        private addStaticHeaders: (res: express.Response) => void,
-    ) {}
-
-    private getSourceForHandler(handler: string): Source | null {
-        const records = _.indexBy(this.fileSources, 'urlpart');
-        return records[handler] || null;
-    }
-
-    private getActionForSource(source: Source, action: string): ((...args: unknown[]) => Promise<unknown>) | null {
-        return ALLOWED_ACTIONS.has(action) ? source[action] : null;
-    }
-
-    public handle(req: express.Request, res: express.Response, next: express.NextFunction): void {
-        // Split URLs with the scheme /source/browser/list into the source and the action to perform
-        const [_, handler, action, ...rest] = req.url.split('/');
-        const source = this.getSourceForHandler(handler);
+    /**
+     * Handle request to `/source/<source>/list` endpoint
+     */
+    public async listEntries(req: express.Request, res: express.Response) {
+        const source = this.getSourceForHandler(req.params.source);
         if (source === null) {
-            next();
+            res.sendStatus(404);
             return;
         }
-        const callback = this.getActionForSource(source, action);
-        if (callback === null) {
-            next();
+        const entries = await source.list();
+        addStaticHeaders(res);
+        res.json(entries);
+    }
+
+    /**
+     * Handle request to `/source/<source>/load/<language>/<filename>` endpoint
+     */
+    public async loadEntry(req: express.Request, res: express.Response) {
+        const source = this.getSourceForHandler(req.params.source);
+        if (source === null) {
+            res.sendStatus(404);
             return;
         }
-        callback(...rest)
-            .then(response => {
-                this.addStaticHeaders(res);
-                res.send(response);
-            })
-            .catch(err => {
-                res.send({err: err});
-            });
+        const entry = await source.load(req.params.language, req.params.filename);
+        addStaticHeaders(res);
+        res.json(entry);
+    }
+
+    private getSourceForHandler(handler: string): Source | null {
+        const records = _.indexBy(this.sources, 'urlpart');
+        return records[handler] || null;
     }
 }
diff --git a/lib/handlers/site-templates.ts b/lib/handlers/site-templates.ts
index 0e71d5c28..f65c54298 100644
--- a/lib/handlers/site-templates.ts
+++ b/lib/handlers/site-templates.ts
@@ -22,46 +22,36 @@
 // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 // POSSIBILITY OF SUCH DAMAGE.
 
-import * as fs from 'fs';
+import * as fsp from 'node:fs/promises';
+import path from 'node:path';
 
-import {SiteTemplatesType} from '../../types/features/site-templates.interfaces.js';
+import _ from 'underscore';
 
-const siteTemplates: SiteTemplatesType = {
-    meta: {},
-    templates: {},
-};
+import {SiteTemplatesType} from '../../types/features/site-templates.interfaces.js';
 
-function splitProperty(line: string) {
-    return [line.substring(0, line.indexOf('=')), line.substring(line.indexOf('=') + 1)];
-}
+let siteTemplates: SiteTemplatesType;
 
-function partition<T>(array: T[], filter: (value: T) => boolean): [T[], T[]] {
-    const pass: T[] = [],
-        fail: T[] = [];
-    for (const item of array) {
-        if (filter(item)) {
-            pass.push(item);
-        } else {
-            fail.push(item);
-        }
-    }
-    return [pass, fail];
-}
-
-export function loadSiteTemplates(configDir: string) {
-    const [meta, templates] = partition(
-        fs
-            .readFileSync(configDir + '/site-templates.conf', 'utf8')
-            .split('\n')
-            .filter(l => l !== '')
-            .map(splitProperty)
-            .map(pair => [pair[0], pair[1].replace(/^https:\/\/godbolt.org\/#/, '')]),
-        ([name, _]) => name.startsWith('meta.'),
-    );
-    siteTemplates.meta = Object.fromEntries(meta);
-    siteTemplates.templates = Object.fromEntries(templates);
+export async function getSiteTemplates(): Promise<SiteTemplatesType> {
+    siteTemplates ??= await loadSiteTemplates('etc/config');
+    return siteTemplates;
 }
 
-export function getSiteTemplates() {
-    return siteTemplates;
+/**
+ * Load all the site templates from the given config directory
+ *
+ * The configuration keys that start with "meta" are returned as metadata keys in the 0th element of the returned tuple
+ */
+async function loadSiteTemplates(configDir: string): Promise<SiteTemplatesType> {
+    const config = await fsp.readFile(path.join(configDir, 'site-templates.conf'), 'utf8');
+    const properties = config
+        .split('\n')
+        .filter(l => l.length > 0)
+        .map(property => {
+            // Rison does not have equal signs in its syntax, so we do not need to account for any trailing equal signs
+            // after the first one.
+            const [name, value] = property.split('=');
+            return [name, value] as const;
+        });
+    const [meta, templates] = _.partition(properties, ([name]) => name.startsWith('meta.'));
+    return {meta: Object.fromEntries(meta), templates: Object.fromEntries(templates)};
 }
diff --git a/lib/languages.ts b/lib/languages.ts
index e8d9a0be9..7bdff9de6 100644
--- a/lib/languages.ts
+++ b/lib/languages.ts
@@ -816,6 +816,17 @@ const definitions: Record<LanguageKey, LanguageDefinition> = {
         previewFilter: null,
         monacoDisassembly: null,
     },
+    vyper: {
+        name: 'Vyper',
+        monaco: 'python',
+        extensions: ['.vy'],
+        alias: [],
+        logoUrl: 'vyper.svg',
+        logoUrlDark: null,
+        formatter: null,
+        previewFilter: null,
+        monacoDisassembly: null,
+    },
     wasm: {
         name: 'WASM',
         monaco: 'wat',
diff --git a/lib/llvm-opt-transformer.ts b/lib/llvm-opt-transformer.ts
index 6e03994e3..6cfe2f027 100644
--- a/lib/llvm-opt-transformer.ts
+++ b/lib/llvm-opt-transformer.ts
@@ -19,30 +19,11 @@
 
 import {parseAllDocuments} from 'yaml';
 
-import {logger} from './logger.js';
-
-type OptType = 'Missed' | 'Passed' | 'Analysis';
-
-type OptInfo = {
-    optType: OptType;
-    displayString: string;
-};
+import {OptRemark} from '../static/panes/opt-view.interfaces.js';
 
-export type LLVMOptInfo = OptInfo & {
-    Pass: string;
-    Name: string;
-    DebugLoc: DebugLoc;
-    Function: string;
-    Args: Array<object>;
-};
-
-type DebugLoc = {
-    File: string;
-    Line: number;
-    Column: number;
-};
+import {logger} from './logger.js';
 
-function DisplayOptInfo(optInfo: LLVMOptInfo) {
+function DisplayOptInfo(optInfo: OptRemark) {
     let displayString = optInfo.Args.reduce((acc, x) => {
         let inc = '';
         for (const [key, value] of Object.entries(x)) {
@@ -60,8 +41,8 @@ function DisplayOptInfo(optInfo: LLVMOptInfo) {
     return displayString;
 }
 
-export function processRawOptRemarks(buffer: string, compileFileName: string = ''): LLVMOptInfo[] {
-    const output: LLVMOptInfo[] = [];
+export function processRawOptRemarks(buffer: string, compileFileName: string = ''): OptRemark[] {
+    const output: OptRemark[] = [];
     const remarksSet: Set<string> = new Set<string>();
     const remarks: any = parseAllDocuments(buffer);
     for (const doc of remarks) {
@@ -78,7 +59,7 @@ export function processRawOptRemarks(buffer: string, compileFileName: string = '
             remarksSet.add(strOpt);
             opt.optType = doc.contents.tag.substring(1); // remove leading '!'
             opt.displayString = DisplayOptInfo(opt);
-            output.push(opt as LLVMOptInfo);
+            output.push(opt as OptRemark);
         }
     }
 
diff --git a/lib/options-handler.ts b/lib/options-handler.ts
index 3a9fcc7aa..d29b520e0 100755
--- a/lib/options-handler.ts
+++ b/lib/options-handler.ts
@@ -32,12 +32,12 @@ import _ from 'underscore';
 import {AppDefaultArguments} from '../app.js';
 import {CompilerInfo} from '../types/compiler.interfaces.js';
 import type {LanguageKey} from '../types/languages.interfaces.js';
+import type {Source} from '../types/source.interfaces.js';
 import type {ToolTypeKey} from '../types/tool.interfaces.js';
 
 import {logger} from './logger.js';
 import type {PropertyGetter, PropertyValue} from './properties.interfaces.js';
 import {CompilerProps} from './properties.js';
-import {Source} from './sources/index.js';
 import {BaseTool, getToolTypeByKey} from './tooling/index.js';
 import {asSafeVer, getHash, splitArguments, splitIntoArray} from './utils.js';
 
diff --git a/lib/s3-handler.ts b/lib/s3-handler.ts
index 7e7bdc9a9..9b4d43fec 100644
--- a/lib/s3-handler.ts
+++ b/lib/s3-handler.ts
@@ -59,7 +59,8 @@ export class S3Bucket {
         }
     }
 
-    async delete(key, path): Promise<boolean> {
+    // Unused?
+    async delete(key: string, path: string): Promise<boolean> {
         try {
             await this.instance.deleteObject({Bucket: this.bucket, Key: `${path}/${key}`});
         } catch (x: any) {
diff --git a/lib/sources/builtin.ts b/lib/sources/builtin.ts
index 73531b0c0..00d5b073c 100644
--- a/lib/sources/builtin.ts
+++ b/lib/sources/builtin.ts
@@ -26,10 +26,9 @@ import fs from 'fs';
 import fsp from 'fs/promises';
 import path from 'path';
 
+import type {Source, SourceApiEntry, SourceEntry} from '../../types/source.interfaces.js';
 import * as props from '../properties.js';
 
-import type {Source, SourceEntry} from './index.js';
-
 const EXAMPLES_PATH = props.get('builtin', 'sourcePath', './examples/') as string;
 const NAME_SUBSTUTION_PATTERN = new RegExp('_', 'g');
 const ALL_EXAMPLES: SourceEntry[] = fs.readdirSync(EXAMPLES_PATH).flatMap(folder => {
@@ -62,7 +61,7 @@ export const builtin: Source = {
             return {file: 'Could not read file'};
         }
     },
-    async list(): Promise<Omit<SourceEntry, 'path'>[]> {
+    async list(): Promise<SourceApiEntry[]> {
         return ALL_EXAMPLES.map(e => ({
             lang: e.lang,
             name: e.name,
diff --git a/lib/sources/index.ts b/lib/sources/index.ts
index 47325edc8..4bbbcd96d 100644
--- a/lib/sources/index.ts
+++ b/lib/sources/index.ts
@@ -22,25 +22,6 @@
 // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 // POSSIBILITY OF SUCH DAMAGE.
 
-import {browser} from './browser.js';
 import {builtin} from './builtin.js';
 
-export interface SourceEntry {
-    /** The file name of the source file */
-    file: string;
-    /** The programming language the source file is written in */
-    lang: string;
-    /** The "nice" name of the source file, replacing _ with spaces */
-    name: string;
-    /** The path to the source file */
-    path: string;
-}
-
-export interface Source {
-    name: string;
-    urlpart: string;
-    list(): Promise<Omit<SourceEntry, 'path'>[]>;
-    load(language: string, filename: string): Promise<{file: string}>;
-}
-
-export const sources = [browser, builtin];
+export const sources = [builtin];
diff --git a/package-lock.json b/package-lock.json
index 1ac2344e2..d117b0e1c 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -6594,9 +6594,9 @@
       }
     },
     "node_modules/cross-spawn": {
-      "version": "7.0.3",
-      "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz",
-      "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==",
+      "version": "7.0.6",
+      "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz",
+      "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==",
       "dependencies": {
         "path-key": "^3.1.0",
         "shebang-command": "^2.0.0",
diff --git a/static/main.ts b/static/main.ts
index 8f75398a7..2a688a906 100644
--- a/static/main.ts
+++ b/static/main.ts
@@ -66,6 +66,7 @@ import {Printerinator} from './print-view.js';
 import {formatISODate, updateAndCalcTopBarHeight} from './utils.js';
 import {localStorage, sessionThenLocalStorage} from './local.js';
 import {setupRealDark, takeUsersOutOfRealDark} from './real-dark.js';
+import {ParseFiltersAndOutputOptions} from './features/filters.interfaces.js';
 
 const logos = require.context('../views/resources/logos', false, /\.(png|svg)$/);
 
@@ -256,15 +257,16 @@ function configFromEmbedded(embeddedUrl: string, defaultLangId: string) {
         throw new Error('Embed url decode error');
     }
     if (params && params.source && params.compiler) {
-        const filters = Object.fromEntries(((params.filters as string) || '').split(',').map(o => [o, true]));
-        // TODO(jeremy-rifkin): Fix types
+        const filters: ParseFiltersAndOutputOptions = Object.fromEntries(
+            ((params.filters as string) || '').split(',').map(o => [o, true]),
+        );
         return {
             content: [
                 {
                     type: 'row',
                     content: [
-                        Components.getEditorWith(1, params.source, filters as any, defaultLangId),
-                        Components.getCompilerWith(1, filters as any, params.options, params.compiler),
+                        Components.getEditorWith(1, params.source, filters, defaultLangId),
+                        Components.getCompilerWith(1, filters, params.options, params.compiler),
                     ],
                 },
             ],
diff --git a/static/modes/cpp-for-opencl-mode.ts b/static/modes/cpp-for-opencl-mode.ts
index 398757d95..a9e597307 100644
--- a/static/modes/cpp-for-opencl-mode.ts
+++ b/static/modes/cpp-for-opencl-mode.ts
@@ -36,7 +36,7 @@ import * as cppp from './cppp-mode.js';
 function definition(): monaco.languages.IMonarchLanguage {
     const cppForOpenCL = $.extend(true, {}, cppp); // deep copy
 
-    function addKeywords(keywords) {
+    function addKeywords(keywords: string[]) {
         // (Ruben) Done one by one as if you just push them all, Monaco complains that they're not strings, but as
         // far as I can tell, they indeed are all strings. This somehow fixes it. If you know how to fix it, plz go
         for (let i = 0; i < keywords.length; ++i) {
@@ -44,7 +44,7 @@ function definition(): monaco.languages.IMonarchLanguage {
         }
     }
 
-    function vectorTypes(basename) {
+    function vectorTypes(basename: string) {
         return [basename + '2', basename + '3', basename + '4', basename + '8', basename + '16'];
     }
     // Keywords for C++ for OpenCL
diff --git a/static/modes/cppcircle-mode.ts b/static/modes/cppcircle-mode.ts
index 270d6a7f7..13dd566af 100644
--- a/static/modes/cppcircle-mode.ts
+++ b/static/modes/cppcircle-mode.ts
@@ -35,7 +35,7 @@ import * as cppp from './cppp-mode.js';
 function definition(): monaco.languages.IMonarchLanguage {
     const cppcircle = $.extend(true, {}, cppp); // deep copy
 
-    function addKeywords(keywords) {
+    function addKeywords(keywords: string[]) {
         // (Ruben) Done one by one as if you just push them all, Monaco complains that they're not strings, but as
         // far as I can tell, they indeed are all strings. This somehow fixes it. If you know how to fix it, plz go
         for (let i = 0; i < keywords.length; ++i) {
diff --git a/static/modes/cppp-mode.ts b/static/modes/cppp-mode.ts
index d3535dfd7..db43e08af 100644
--- a/static/modes/cppp-mode.ts
+++ b/static/modes/cppp-mode.ts
@@ -34,20 +34,20 @@ import * as cpp from 'monaco-editor/esm/vs/basic-languages/cpp/cpp';
 function definition(): monaco.languages.IMonarchLanguage {
     const cppp = $.extend(true, {}, cpp.language); // deep copy
 
-    function removeKeyword(keyword) {
+    function removeKeyword(keyword: string) {
         const index = cppp.keywords.indexOf(keyword);
         if (index > -1) {
             cppp.keywords.splice(index, 1);
         }
     }
 
-    function removeKeywords(keywords) {
+    function removeKeywords(keywords: string[]) {
         for (let i = 0; i < keywords.length; ++i) {
             removeKeyword(keywords[i]);
         }
     }
 
-    function addKeywords(keywords) {
+    function addKeywords(keywords: string[]) {
         // (Ruben) Done one by one as if you just push them all, Monaco complains that they're not strings, but as
         // far as I can tell, they indeed are all strings. This somehow fixes it. If you know how to fix it, plz go
         for (let i = 0; i < keywords.length; ++i) {
diff --git a/static/modes/cuda-mode.ts b/static/modes/cuda-mode.ts
index c07d3ef88..fe7f71ead 100644
--- a/static/modes/cuda-mode.ts
+++ b/static/modes/cuda-mode.ts
@@ -35,7 +35,7 @@ import * as cppp from './cppp-mode.js';
 function definition(): monaco.languages.IMonarchLanguage {
     const cuda = $.extend(true, {}, cppp); // deep copy
 
-    function addKeywords(keywords) {
+    function addKeywords(keywords: string[]) {
         // (Ruben) Done one by one as if you just push them all, Monaco complains that they're not strings, but as
         // far as I can tell, they indeed are all strings. This somehow fixes it. If you know how to fix it, plz go
         for (let i = 0; i < keywords.length; ++i) {
diff --git a/static/modes/glsl-mode.ts b/static/modes/glsl-mode.ts
index 68861f23c..7a6533bb8 100644
--- a/static/modes/glsl-mode.ts
+++ b/static/modes/glsl-mode.ts
@@ -32,13 +32,13 @@ import * as cpp from 'monaco-editor/esm/vs/basic-languages/cpp/cpp';
 function definition(): monaco.languages.IMonarchLanguage {
     const glsl = $.extend(true, {}, cpp.language);
 
-    function addKeywords(keywords) {
+    function addKeywords(keywords: string[]) {
         for (let i = 0; i < keywords.length; ++i) {
             glsl.keywords.push(keywords[i]);
         }
     }
 
-    function matrixTypes(basename) {
+    function matrixTypes(basename: string) {
         return [
             `${basename}2`,
             `${basename}3`,
@@ -55,7 +55,7 @@ function definition(): monaco.languages.IMonarchLanguage {
         ];
     }
 
-    function vectorTypes(basename) {
+    function vectorTypes(basename: string) {
         return [`${basename}2`, `${basename}3`, `${basename}4`];
     }
 
@@ -88,7 +88,7 @@ function definition(): monaco.languages.IMonarchLanguage {
     addKeywords(vectorTypes('i8vec'));
     addKeywords(vectorTypes('u8vec'));
 
-    function samplerTypes(basename) {
+    function samplerTypes(basename: string) {
         return [`${basename}`, `${basename}Shadow`, `${basename}Array`, `${basename}ArrayShadow`];
     }
 
@@ -97,7 +97,7 @@ function definition(): monaco.languages.IMonarchLanguage {
     addKeywords(samplerTypes('sampler2D'));
     addKeywords(samplerTypes('samplerCube'));
 
-    function imageTypes(basename) {
+    function imageTypes(basename: string) {
         return [
             `${basename}1D`,
             `${basename}1DArray`,
diff --git a/static/modes/hlsl-mode.ts b/static/modes/hlsl-mode.ts
index 0f2ff76bc..7d78f30c1 100644
--- a/static/modes/hlsl-mode.ts
+++ b/static/modes/hlsl-mode.ts
@@ -32,13 +32,13 @@ import * as cpp from 'monaco-editor/esm/vs/basic-languages/cpp/cpp';
 function definition(): monaco.languages.IMonarchLanguage {
     const hlsl = $.extend(true, {}, cpp.language);
 
-    function addKeywords(keywords) {
+    function addKeywords(keywords: string[]) {
         for (let i = 0; i < keywords.length; ++i) {
             hlsl.keywords.push(keywords[i]);
         }
     }
 
-    function vectorMatrixTypes(basename) {
+    function vectorMatrixTypes(basename: string) {
         const types: string[] = [];
         for (let i = 1; i !== 5; ++i) {
             for (let j = 1; j !== 5; ++j) {
@@ -54,7 +54,7 @@ function definition(): monaco.languages.IMonarchLanguage {
     addKeywords(vectorMatrixTypes('float'));
     addKeywords(vectorMatrixTypes('int'));
 
-    function resource(name) {
+    function resource(name: string) {
         return [name, `RW${name}`];
     }
 
diff --git a/static/modes/openclc-mode.ts b/static/modes/openclc-mode.ts
index b27ccc2e8..e31f52abf 100644
--- a/static/modes/openclc-mode.ts
+++ b/static/modes/openclc-mode.ts
@@ -36,20 +36,20 @@ import * as nc from './nc-mode.js';
 function definition(): monaco.languages.IMonarchLanguage {
     const openclc = $.extend(true, {}, nc); // deep copy
 
-    function removeKeyword(keyword) {
+    function removeKeyword(keyword: string) {
         const index = openclc.keywords.indexOf(keyword);
         if (index > -1) {
             openclc.keywords.splice(index, 1);
         }
     }
 
-    function removeKeywords(keywords) {
+    function removeKeywords(keywords: string[]) {
         for (let i = 0; i < keywords.length; ++i) {
             removeKeyword(keywords[i]);
         }
     }
 
-    function addKeywords(keywords) {
+    function addKeywords(keywords: string[]) {
         // (Ruben) Done one by one as if you just push them all, Monaco complains that they're not strings, but as
         // far as I can tell, they indeed are all strings. This somehow fixes it. If you know how to fix it, plz go
         for (let i = 0; i < keywords.length; ++i) {
@@ -57,7 +57,7 @@ function definition(): monaco.languages.IMonarchLanguage {
         }
     }
 
-    function vectorTypes(basename) {
+    function vectorTypes(basename: string) {
         return [basename + '2', basename + '3', basename + '4', basename + '8', basename + '16'];
     }
 
diff --git a/static/panes/clangir-view.ts b/static/panes/clangir-view.ts
index 4bacfb229..ece62f2b7 100644
--- a/static/panes/clangir-view.ts
+++ b/static/panes/clangir-view.ts
@@ -106,7 +106,7 @@ export class Clangir extends MonacoPane<monaco.editor.IStandaloneCodeEditor, Cla
         };
         let changed = false;
         for (const k in newOptions) {
-            if (newOptions[k] !== this.lastOptions[k]) {
+            if (newOptions[k as keyof ClangirBackendOptions] !== this.lastOptions[k as keyof ClangirBackendOptions]) {
                 changed = true;
                 break;
             }
diff --git a/static/panes/compiler.ts b/static/panes/compiler.ts
index 632117969..cf984b3e0 100644
--- a/static/panes/compiler.ts
+++ b/static/panes/compiler.ts
@@ -96,7 +96,7 @@ const OpcodeCache = new LRUCache<string, CachedOpcode>({
     },
 });
 
-function patchOldFilters(filters) {
+function patchOldFilters(filters: Partial<Record<string, boolean>> | undefined): Record<string, boolean> | undefined {
     if (filters === undefined) return undefined;
     // Filters are of the form {filter: true|false¸ ...}. In older versions, we used
     // to suppress the {filter:false} form. This means we can't distinguish between
@@ -108,7 +108,7 @@ function patchOldFilters(filters) {
     ['binary', 'labels', 'directives', 'commentOnly', 'trim', 'intel', 'debugCalls'].forEach(oldFilter => {
         if (filters[oldFilter] === undefined) filters[oldFilter] = false;
     });
-    return filters;
+    return filters as Record<string, boolean>;
 }
 
 const languages = options.languages;
@@ -1210,7 +1210,7 @@ export class Compiler extends MonacoPane<monaco.editor.IStandaloneCodeEditor, Co
                 });
             }
         } else if (content.content) {
-            content.content.forEach(subcontent => {
+            content.content.forEach((subcontent: any) => {
                 tools = this.findTools(subcontent, tools);
             });
         }
@@ -2527,7 +2527,7 @@ export class Compiler extends MonacoPane<monaco.editor.IStandaloneCodeEditor, Co
         this.noBinaryFiltersButtons = this.domRoot.find('.nonbinary');
     }
 
-    override registerButtons(state) {
+    override registerButtons(state: CompilerCurrentState) {
         super.registerButtons(state);
         this.filters = new Toggles(this.domRoot.find('.filters'), patchOldFilters(state.filters));
 
diff --git a/static/panes/diff.ts b/static/panes/diff.ts
index c5b6b1b5b..32511cf7b 100644
--- a/static/panes/diff.ts
+++ b/static/panes/diff.ts
@@ -198,7 +198,7 @@ export class Diff extends MonacoPane<monaco.editor.IStandaloneDiffEditor, DiffSt
     compilers: Record<string | number, CompilerEntry> = {};
     lhs: DiffStateObject;
     rhs: DiffStateObject;
-    selectize: SelectizeType = {} as any; // will be filled in by the constructor
+    selectize: SelectizeType;
     constructor(hub: Hub, container: Container, state: MonacoPaneState & DiffState) {
         super(hub, container, state);
 
diff --git a/static/panes/gccdump-view.ts b/static/panes/gccdump-view.ts
index d52fd395e..90ebbff94 100644
--- a/static/panes/gccdump-view.ts
+++ b/static/panes/gccdump-view.ts
@@ -447,8 +447,7 @@ export class GccDump extends MonacoPane<monaco.editor.IStandaloneCodeEditor, Gcc
 
             ...parent,
         };
-        // TODO(jeremy-rifkin)
-        return state as any;
+        return state;
     }
 
     override close() {
diff --git a/static/panes/opt-view.interfaces.ts b/static/panes/opt-view.interfaces.ts
index dc27f6c59..b3fa0741e 100644
--- a/static/panes/opt-view.interfaces.ts
+++ b/static/panes/opt-view.interfaces.ts
@@ -23,7 +23,7 @@
 // POSSIBILITY OF SUCH DAMAGE.
 
 export interface OptState {
-    optOutput?: OptCodeEntry[];
+    optOutput?: OptRemark[];
     source: any; // TODO
     wrap: boolean;
 
@@ -39,15 +39,13 @@ type SourceLocation = {
     Column: number;
 };
 
-type OptType = 'Missed' | 'Passed' | 'Analysis';
-
-export type OptCodeEntry = {
-    // TODO: Not fully correct type yet, will do for now
+export type OptRemark = {
     DebugLoc: SourceLocation;
     Function: string;
     Pass: string;
     Name: string;
     text: string;
-    optType: OptType;
+    optType: 'Missed' | 'Passed' | 'Analysis';
     displayString: string;
+    Args: Array<object>;
 };
diff --git a/static/panes/opt-view.ts b/static/panes/opt-view.ts
index e9b9f129d..e9b2c46e9 100644
--- a/static/panes/opt-view.ts
+++ b/static/panes/opt-view.ts
@@ -28,7 +28,7 @@ import * as monaco from 'monaco-editor';
 import {Container} from 'golden-layout';
 
 import {MonacoPane} from './pane.js';
-import {OptState, OptCodeEntry} from './opt-view.interfaces.js';
+import {OptState, OptRemark} from './opt-view.interfaces.js';
 import {MonacoPaneState} from './pane.interfaces.js';
 
 import {extendConfig} from '../monaco-config.js';
@@ -55,7 +55,7 @@ export class Opt extends MonacoPane<monaco.editor.IStandaloneCodeEditor, OptStat
     private wrapTitle: JQuery<HTMLElement>;
 
     // Keep optRemarks as state, to avoid triggerring a recompile when options change
-    private optRemarks: OptCodeEntry[];
+    private optRemarks: OptRemark[];
     private srcAsOptview: OptviewLine[];
 
     constructor(hub: Hub, container: Container, state: OptState & MonacoPaneState) {
diff --git a/static/sentry.ts b/static/sentry.ts
index 407bd14dd..dd4fcf54f 100644
--- a/static/sentry.ts
+++ b/static/sentry.ts
@@ -65,6 +65,14 @@ export function SetupSentry() {
             dsn: options.sentryDsn,
             release: options.release,
             environment: options.sentryEnvironment,
+            ignoreErrors: [
+                /CancellationError\(monaco-editor/,
+                /new StandardMouseEvent\(monaco-editor/,
+                /Object Not Found Matching Id:2/,
+                /i is null _doHitTestWithCaretPositionFromPoint/,
+                /Illegal value for lineNumber/,
+                'SlowRequest',
+            ],
         });
         window.addEventListener('unhandledrejection', event => {
             SentryCapture(event.reason, 'Unhandled Promise Rejection');
diff --git a/static/sharing.ts b/static/sharing.ts
index 76ed7ecb9..4c2fe498a 100644
--- a/static/sharing.ts
+++ b/static/sharing.ts
@@ -58,6 +58,16 @@ const shareServices = {
         },
         text: 'Tweet',
     },
+    bluesky: {
+        embedValid: false,
+        logoClass: 'fab fa-bluesky',
+        cssClass: 'share-bluesky',
+        getLink: (title: string, url: string) => {
+            const text = `${title} ${url} via @compiler-explorer.com`;
+            return `https://bsky.app/intent/compose?text=${encodeURIComponent(text)}`;
+        },
+        text: 'Share on Bluesky',
+    },
     reddit: {
         embedValid: false,
         logoClass: 'fab fa-reddit',
diff --git a/static/styles/themes/dark-theme.scss b/static/styles/themes/dark-theme.scss
index f01ad2545..b0d513764 100644
--- a/static/styles/themes/dark-theme.scss
+++ b/static/styles/themes/dark-theme.scss
@@ -566,6 +566,11 @@ textarea.form-control {
     color: white !important;
 }
 
+.share-bluesky {
+    background-color: #0a7aff !important;
+    color: white !important;
+}
+
 #simplecook {
     background-color: #474747 !important;
 }
diff --git a/static/styles/themes/default-theme.scss b/static/styles/themes/default-theme.scss
index 3344c7baa..61386e580 100644
--- a/static/styles/themes/default-theme.scss
+++ b/static/styles/themes/default-theme.scss
@@ -259,6 +259,12 @@ a.navbar-brand img.logo.normal {
     color: white;
 }
 
+#socialshare .share-bluesky,
+.share-bluesky {
+    background-color: #0a7aff;
+    color: white;
+}
+
 #socialshare .share-reddit,
 .share-reddit {
     background-color: #ff4500;
diff --git a/static/styles/themes/one-dark-theme.scss b/static/styles/themes/one-dark-theme.scss
index af7e35e06..907240dc4 100644
--- a/static/styles/themes/one-dark-theme.scss
+++ b/static/styles/themes/one-dark-theme.scss
@@ -622,6 +622,11 @@ textarea.form-control {
     color: #eee !important;
 }
 
+.share-bluesky {
+    background-color: #0a7aff !important;
+    color: #eee !important;
+}
+
 #simplecook {
     background-color: #474747 !important;
 }
diff --git a/static/styles/themes/pink-theme.scss b/static/styles/themes/pink-theme.scss
index 16cbf45be..e9f040133 100644
--- a/static/styles/themes/pink-theme.scss
+++ b/static/styles/themes/pink-theme.scss
@@ -586,6 +586,11 @@ textarea.form-control {
     color: white !important;
 }
 
+.share-bluesky {
+    background-color: #0a7aff !important;
+    color: white !important;
+}
+
 #simplecook {
     background-color: #474747 !important;
 }
diff --git a/static/widgets/load-save.ts b/static/widgets/load-save.ts
index a80464b75..4ef87e336 100644
--- a/static/widgets/load-save.ts
+++ b/static/widgets/load-save.ts
@@ -30,6 +30,7 @@ import {Language} from '../../types/languages.interfaces.js';
 import {unwrap, unwrapString} from '../assert.js';
 import {escapeHTML} from '../../shared/common-utils.js';
 import {localStorage} from '../local.js';
+import {SourceApiEntry} from '../../types/source.interfaces';
 
 const history = require('../history');
 
@@ -71,8 +72,8 @@ export class LoadSave {
         localStorage.set('files', JSON.stringify(files));
     }
 
-    private async fetchBuiltins(): Promise<Record<string, any>[]> {
-        return new Promise<Record<string, any>[]>(resolve => {
+    private async fetchBuiltins(): Promise<SourceApiEntry[]> {
+        return new Promise(resolve => {
             $.getJSON(window.location.origin + this.base + 'source/builtin/list', resolve);
         });
     }
@@ -118,7 +119,7 @@ export class LoadSave {
 
     private async populateBuiltins() {
         const builtins = (await this.fetchBuiltins()).filter(entry => this.currentLanguage?.id === entry.lang);
-        return LoadSave.populate(
+        LoadSave.populate(
             unwrap(this.modal).find('.examples'),
             builtins.map(elem => {
                 return {
diff --git a/types/compilation/compilation.interfaces.ts b/types/compilation/compilation.interfaces.ts
index 4c1b0b8dc..9a30ce038 100644
--- a/types/compilation/compilation.interfaces.ts
+++ b/types/compilation/compilation.interfaces.ts
@@ -25,7 +25,7 @@
 import {BuildEnvDownloadInfo} from '../../lib/buildenvsetup/buildenv.interfaces.js';
 import {IAsmParser} from '../../lib/parsers/asm-parser.interfaces.js';
 import type {GccDumpViewSelectedPass} from '../../static/panes/gccdump-view.interfaces.js';
-import {OptCodeEntry} from '../../static/panes/opt-view.interfaces.js';
+import {OptRemark} from '../../static/panes/opt-view.interfaces.js';
 import type {PPOptions} from '../../static/panes/pp-view.interfaces.js';
 import {suCodeEntry} from '../../static/panes/stack-usage-view.interfaces.js';
 import {ParsedAsmResultLine} from '../asmresult/asmresult.interfaces.js';
@@ -183,7 +183,7 @@ export type CompilationResult = {
 
     ppOutput?: PPOutput;
 
-    optOutput?: OptCodeEntry[];
+    optOutput?: OptRemark[];
     optPath?: string;
 
     stackUsageOutput?: suCodeEntry[];
diff --git a/types/compiler.interfaces.ts b/types/compiler.interfaces.ts
index 98cea8251..23b548aab 100644
--- a/types/compiler.interfaces.ts
+++ b/types/compiler.interfaces.ts
@@ -22,20 +22,11 @@
 // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 // POSSIBILITY OF SUCH DAMAGE.
 
-import {
-    ActiveTool,
-    BypassCache,
-    CompilationResult,
-    ExecutionParams,
-    FiledataPair,
-} from './compilation/compilation.interfaces.js';
 import {AllCompilerOverrideOptions} from './compilation/compiler-overrides.interfaces.js';
-import {ICompilerArguments} from './compiler-arguments.interfaces.js';
 import {PossibleRuntimeTools} from './execution/execution.interfaces.js';
-import {ParseFiltersAndOutputOptions} from './features/filters.interfaces.js';
 import {InstructionSet} from './instructionsets.js';
-import {Language, LanguageKey} from './languages.interfaces.js';
-import {Library, SelectedLibraryVersion} from './libraries/libraries.interfaces.js';
+import {LanguageKey} from './languages.interfaces.js';
+import {Library} from './libraries/libraries.interfaces.js';
 import {Tool, ToolInfo} from './tool.interfaces.js';
 
 export type Remote = {
@@ -167,22 +158,3 @@ export type CompilerInfo = {
 export type PreliminaryCompilerInfo = Omit<CompilerInfo, 'version' | 'fullVersion' | 'baseName' | 'disabledFilters'> & {
     version?: string;
 };
-
-export interface ICompiler {
-    possibleArguments: ICompilerArguments;
-    lang: Language;
-    compile(
-        source: string,
-        options: string[],
-        backendOptions: Record<string, any>,
-        filters: ParseFiltersAndOutputOptions,
-        bypassCache: BypassCache,
-        tools: ActiveTool[],
-        executeParameters: ExecutionParams,
-        libraries: SelectedLibraryVersion[],
-        files: FiledataPair[],
-    ): Promise<any>;
-    cmake(files: FiledataPair[], key, bypassCache: BypassCache): Promise<CompilationResult>;
-    initialise(mtime: Date, clientOptions, isPrediscovered: boolean): Promise<ICompiler | null>;
-    getInfo(): CompilerInfo;
-}
diff --git a/types/features/site-templates.interfaces.ts b/types/features/site-templates.interfaces.ts
index 0a6b79b29..4f8b51023 100644
--- a/types/features/site-templates.interfaces.ts
+++ b/types/features/site-templates.interfaces.ts
@@ -22,8 +22,12 @@
 // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 // POSSIBILITY OF SUCH DAMAGE.
 
+export type SiteTemplatesMetadata = {
+    screenshot_dimensions?: string;
+};
+
 export type SiteTemplatesType = {
-    meta: Record<string, string>;
+    meta: SiteTemplatesMetadata;
     templates: Record<string, string>;
 };
 
diff --git a/types/languages.interfaces.ts b/types/languages.interfaces.ts
index a61631fc8..2ad7b675d 100644
--- a/types/languages.interfaces.ts
+++ b/types/languages.interfaces.ts
@@ -93,6 +93,7 @@ export type LanguageKey =
     | 'v'
     | 'vala'
     | 'vb'
+    | 'vyper'
     | 'wasm'
     | 'zig'
     | 'ylc';
diff --git a/lib/sources/browser.ts b/types/source.interfaces.ts
similarity index 71%
rename from lib/sources/browser.ts
rename to types/source.interfaces.ts
index 4ad7933eb..b3b3b382b 100644
--- a/lib/sources/browser.ts
+++ b/types/source.interfaces.ts
@@ -1,4 +1,4 @@
-// Copyright (c) 2012, Compiler Explorer Authors
+// Copyright (c) 2024, Compiler Explorer Authors
 // All rights reserved.
 //
 // Redistribution and use in source and binary forms, with or without
@@ -22,19 +22,22 @@
 // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 // POSSIBILITY OF SUCH DAMAGE.
 
-import type {Source, SourceEntry} from './index.js';
+export interface SourceEntry {
+    /** The file name of the source file */
+    file: string;
+    /** The programming language the source file is written in */
+    lang: string;
+    /** The "nice" name of the source file, replacing _ with spaces */
+    name: string;
+    /** The path to the source file */
+    path: string;
+}
 
-// This is a fake plugin. All of the functionality is in the browser code.
-export const browser: Source = {
-    name: 'Browser',
-    urlpart: 'browser',
-    list(): Promise<Omit<SourceEntry, 'path'>[]> {
-        return Promise.resolve([]);
-    },
-    load(language: string, filename: string): Promise<{file: string}> {
-        return Promise.resolve({file: ''});
-    },
-};
+export interface Source {
+    name: string;
+    urlpart: string;
+    list(): Promise<SourceApiEntry[]>;
+    load(language: string, filename: string): Promise<{file: string}>;
+}
 
-export const name = 'Browser';
-export const urlpart = 'browser';
+export type SourceApiEntry = Pick<SourceEntry, 'lang' | 'name' | 'file'>;
diff --git a/views/menu-other.pug b/views/menu-other.pug
index 3d1a1e5ca..9b1c47ee0 100644
--- a/views/menu-other.pug
+++ b/views/menu-other.pug
@@ -43,6 +43,10 @@ a.dropdown-item(href="https://hachyderm.io/@compiler_explorer" rel="me noopener"
     span.dropdown-icon.fas.fa-paper-plane
     | CE on Mastodon
     | &nbsp;
+a.dropdown-item(href="https://bsky.app/profile/compiler-explorer.com" rel="noopener")
+    span.dropdown-icon.fab.fa-bluesky
+    | CE on Bluesky
+    | &nbsp;
 a.dropdown-item(href="https://xania.org/MattGodbolt" rel="author" target="_blank")
     span.dropdown-icon.fas.fa-address-card
     | About the author
diff --git a/views/resources/logos/vyper.svg b/views/resources/logos/vyper.svg
new file mode 100644
index 000000000..d2c666074
--- /dev/null
+++ b/views/resources/logos/vyper.svg
@@ -0,0 +1,4 @@
+<svg width="338" height="376" viewBox="0 0 338 376" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M195.008 311.356L82.2221 198.603C77.6282 193.823 75.0968 187.356 75.0968 180.139V19.2101C75.0968 9.83746 65.7215 0.464804 56.3461 0.464804H18.7508C9.37539 0.464804 0 9.83746 0 19.2101V206.663C0 216.598 3.6564 226.158 10.6879 233.188L141.943 364.405C149.256 371.716 158.819 375.371 168.476 375.371H187.226C197.633 375.371 205.977 366.936 205.977 356.626V337.974C205.977 328.32 202.321 318.76 195.008 311.45V311.356Z" fill="#9F4CF2"/>
+<path d="M337.514 19.1164C337.514 9.65003 328.233 0.371094 318.764 0.371094H281.168C271.793 0.371094 262.418 9.74375 262.418 19.1164V179.951C262.418 187.168 259.605 193.635 254.917 198.509L217.134 236.281C209.822 243.592 206.165 253.152 206.165 262.806V281.551C206.165 291.955 214.603 300.296 224.916 300.296H243.667C253.23 300.296 262.886 296.641 270.199 289.33L326.451 233.094C333.483 226.065 337.421 216.505 337.421 206.57V19.1164H337.514Z" fill="#9F4CF2"/>
+</svg>


Test patch:
diff --git a/lib/compilers/fake-for-test.ts b/lib/compilers/fake-for-test.ts
index 0ac21db74..699e010d6 100644
--- a/lib/compilers/fake-for-test.ts
+++ b/lib/compilers/fake-for-test.ts
@@ -24,13 +24,18 @@
 
 import _ from 'underscore';
 
-import {BypassCache, ExecutionParams, FiledataPair} from '../../types/compilation/compilation.interfaces.js';
-import type {ICompiler, PreliminaryCompilerInfo} from '../../types/compiler.interfaces.js';
+import {
+    ActiveTool,
+    BypassCache,
+    ExecutionParams,
+    FiledataPair,
+} from '../../types/compilation/compilation.interfaces.js';
+import type {PreliminaryCompilerInfo} from '../../types/compiler.interfaces.js';
 import {ParseFiltersAndOutputOptions} from '../../types/features/filters.interfaces.js';
 import {SelectedLibraryVersion} from '../../types/libraries/libraries.interfaces.js';
 import {CompilerArguments} from '../compiler-arguments.js';
 
-export class FakeCompiler implements ICompiler {
+export class FakeCompiler {
     public possibleArguments: CompilerArguments;
     public lang: any;
     private compiler: any;
@@ -81,7 +86,7 @@ export class FakeCompiler implements ICompiler {
         backendOptions: Record<string, any>,
         filters: ParseFiltersAndOutputOptions,
         bypassCache: BypassCache,
-        tools,
+        tools: ActiveTool[],
         executeParameters: ExecutionParams,
         libraries: SelectedLibraryVersion[],
         files?: FiledataPair[],
diff --git a/test/handlers/site-templates-tests.ts b/test/handlers/site-templates-tests.ts
index 7ebc2b416..e9d0fa112 100644
--- a/test/handlers/site-templates-tests.ts
+++ b/test/handlers/site-templates-tests.ts
@@ -1,16 +1,12 @@
-import {beforeAll, describe, expect, it} from 'vitest';
+import {describe, expect, it} from 'vitest';
 
-import {getSiteTemplates, loadSiteTemplates} from '../../lib/handlers/site-templates.js';
+import {getSiteTemplates} from '../../lib/handlers/site-templates.js';
 
 describe('Site Templates Backend', () => {
-    beforeAll(() => {
-        loadSiteTemplates('etc/config');
-    });
-
-    it('should load site templates properly', () => {
-        const templates = getSiteTemplates();
+    it('should load site templates properly', async () => {
+        const templates = await getSiteTemplates();
         // not super comprehensive
-        expect(templates.meta).toHaveProperty('meta.screenshot_dimentions');
+        expect(templates.meta).toHaveProperty('meta.screenshot_dimensions');
         expect(Object.entries(templates.templates).length).toBeTruthy();
     });
 });
diff --git a/test/handlers/source-tests.ts b/test/handlers/source-tests.ts
index ef5106730..a8708a1a7 100644
--- a/test/handlers/source-tests.ts
+++ b/test/handlers/source-tests.ts
@@ -26,35 +26,40 @@ import express from 'express';
 import request from 'supertest';
 import {describe, expect, it} from 'vitest';
 
-import {SourceHandler} from '../../lib/handlers/source.js';
+import {SourceController} from '../../lib/handlers/api/source-controller.js';
 
 describe('Sources', () => {
     const app = express();
-    const handler = new SourceHandler(
-        [
-            {
-                name: 'moose',
-                urlpart: 'moose',
-                list: async () => [{file: 'file', lang: 'lang', name: 'name'}],
-                load: name => Promise.resolve({file: `File called ${name}`}),
-            },
-        ],
-        res => res.setHeader('Yibble', 'boing'),
-    );
-    app.use('/source', handler.handle.bind(handler));
+    const handler = new SourceController([
+        {
+            name: 'moose',
+            urlpart: 'moose',
+            list: async () => [{file: 'file', lang: 'lang', name: 'Grunkle'}],
+            load: (lang, name) => Promise.resolve({file: `File called ${name} in ${lang}`}),
+        },
+    ]);
+    app.use('/source/:source/list', handler.listEntries.bind(handler));
+    app.use('/source/:source/load/:language/:filename', handler.loadEntry.bind(handler));
 
     it('should list', async () => {
-        const res = await request(app)
+        await request(app)
             .get('/source/moose/list')
             .expect('Content-Type', /json/)
-            .expect(200, [{file: 'file', lang: 'lang', name: 'name'}]);
-        expect(res.headers['yibble']).toEqual('boing');
+            .expect(200, [{file: 'file', lang: 'lang', name: 'Grunkle'}]);
     });
+
     it('should fetch files', async () => {
+        await request(app)
+            .get('/source/moose/load/lang/Grunkle')
+            .expect('Content-Type', /json/)
+            .expect(200, {file: 'File called Grunkle in lang'});
+    });
+
+    it('should have a max-age cache control header', async () => {
         const res = await request(app)
-            .get('/source/moose/load/Grunkle')
+            .get('/source/moose/load/lang/Grunkle')
             .expect('Content-Type', /json/)
-            .expect(200, {file: 'File called Grunkle'});
-        expect(res.headers['yibble']).toEqual('boing');
+            .expect(200, {file: 'File called Grunkle in lang'});
+        expect(res.headers['cache-control']).toContain('public, max-age=');
     });
 });