From 2a9cbf29b99aac370666d2d98f10451d1ae904f8 Mon Sep 17 00:00:00 2001
From: Alan Hayward <alan.hayward@arm.com>
Date: Thu, 14 Dec 2023 11:34:06 +0000
Subject: [PATCH] Add emitUnitTests.sh

The enables the automation of running the emit unit tests for Linux/Mac
---
 src/coreclr/scripts/emitUnitTests.sh          | 115 ++++++++++++++++++
 .../scripts/emitUnitTests/emitUnitTests.cs    |  12 ++
 .../emitUnitTests/emitUnitTests.csproj        |  10 ++
 3 files changed, 137 insertions(+)
 create mode 100755 src/coreclr/scripts/emitUnitTests.sh
 create mode 100644 src/coreclr/scripts/emitUnitTests/emitUnitTests.cs
 create mode 100644 src/coreclr/scripts/emitUnitTests/emitUnitTests.csproj

diff --git a/src/coreclr/scripts/emitUnitTests.sh b/src/coreclr/scripts/emitUnitTests.sh
new file mode 100755
index 00000000000000..3fc413e4bb786e
--- /dev/null
+++ b/src/coreclr/scripts/emitUnitTests.sh
@@ -0,0 +1,115 @@
+#!/bin/bash
+
+# On Linux/Mac, run the emit unit tests and compare the output against capstone.
+#
+# args:
+# -s : Setup the tools. Checkout and build capstone. Build the dummy app.
+# -c : Sets CORE_ROOT used to run the tests.
+# -g : The Group of tests to run. Used for DOTNET_JitDumpEmitUnitTests.
+# -v : Use regex to search the generated clr output. Useful when adding new instructions during development.
+#
+
+# Show all commands run and exit on any errors
+
+set -xeuo pipefail
+
+# Parse command line
+
+usage="$0 [-s] [-c core_root] [-g group] [-v ins_regex]"
+group=all
+search=
+setup=
+verbose=
+while getopts sc:g:v: line
+do
+    case $line in
+    c) export CORE_ROOT=$OPTARG;;
+    g) group=$OPTARG;;
+    s) setup=1;;
+    v) verbose=$OPTARG;;
+    *) echo $usage; exit 2;;
+    esac
+done
+
+arch=$(uname -m)
+if [ "$arch" == 'aarch64' ]; then
+  clr_arch=arm64
+elif [ "$arch" == 'x86_64' ]; then
+  arch=x64
+  clr_arch=x64
+fi
+
+artifacts_dir="$(pwd)/../../../artifacts/bin/emitUnitTests"
+
+# Setup capstone
+
+capstone_directory=$artifacts_dir/capstone
+
+if [ -n "$setup" ] || [ ! -d "$capstone_directory" ]; then
+    rm -fr "$capstone_directory"
+    git clone --quiet --depth 1 -b capstone-jit2-formatting https://github.com/TIHan/capstone.git "$capstone_directory"
+    cd "$capstone_directory"
+    ./make.sh
+    cd -
+fi
+
+cstool=$(realpath "$capstone_directory/cstool/cstool")
+
+# Setup dummy app
+
+app_dir="$artifacts_dir/$clr_arch/Release/publish"
+
+if [ -n "$setup" ] || [ ! -d "$app_dir" ]; then
+    cd emitUnitTests
+    dotnet publish -c Release
+    cd -
+fi
+
+app_dll="$app_dir/emitUnitTests.dll"
+app_dll=$(realpath $app_dll)
+
+# Set env
+
+output_dir=$(mktemp -d)
+
+export DOTNET_JitRawHexCode=Main
+export DOTNET_JitRawHexCodeFile=$output_dir/clr_hex.txt
+export DOTNET_JitDump=Main
+export DOTNET_JitDumpEmitUnitTests=$group
+
+# Run the dummy app in clr
+
+$CORE_ROOT/corerun $app_dll > $output_dir/clr_output.txt
+
+# Extract the instructions from the clr output, from the first NOP to the first set of 2 NOPS.
+
+egrep "IN.*: 00" $output_dir/clr_output.txt \
+| cut -f 8- -d ' ' | tr -s ' \t' ' ' \
+| awk '{ if ($1=="nop") { go=1; if (prev=="nop") fin=1; } if (go && !fin) print $0; prev=$1 }' \
+> $output_dir/clr_instrs.txt
+
+# Run the raw hex through capstone
+
+$cstool $arch $output_dir/clr_hex.txt > $output_dir/capstone_output.txt
+
+# Extract the instructions from the capstone output, from the first NOP to the first set of 2 NOPS.
+
+cat $output_dir/capstone_output.txt \
+| cut -f 3- -d ' ' | tr -s ' \t' ' ' \
+| awk '{ if ($1=="nop") { go=1; if (prev=="nop") fin=1; } if (go && !fin) print $0; prev=$1 }' \
+> $output_dir/capstone_instrs.txt
+
+# Show some of the output
+
+if [ -n "$verbose" ]; then
+    egrep "$verbose" $output_dir/clr_instrs.txt
+else
+    (head -n 5; tail -n 5) < $output_dir/clr_instrs.txt
+fi
+
+# Diff capstone and clr
+
+diff $output_dir/clr_instrs.txt $output_dir/capstone_instrs.txt
+
+rm -fr $output_dir
+echo PASSED
diff --git a/src/coreclr/scripts/emitUnitTests/emitUnitTests.cs b/src/coreclr/scripts/emitUnitTests/emitUnitTests.cs
new file mode 100644
index 00000000000000..bdc6d483913384
--- /dev/null
+++ b/src/coreclr/scripts/emitUnitTests/emitUnitTests.cs
@@ -0,0 +1,12 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+namespace EmitUnitTests
+{
+    public class EmitUnitTests
+    {
+        public static void Main(string[] args)
+        {
+        }
+    }
+}
diff --git a/src/coreclr/scripts/emitUnitTests/emitUnitTests.csproj b/src/coreclr/scripts/emitUnitTests/emitUnitTests.csproj
new file mode 100644
index 00000000000000..5eab951011b3a9
--- /dev/null
+++ b/src/coreclr/scripts/emitUnitTests/emitUnitTests.csproj
@@ -0,0 +1,10 @@
+<Project Sdk="Microsoft.NET.Sdk">
+
+  <PropertyGroup>
+    <OutputType>Exe</OutputType>
+     <TargetFramework>$(NetCoreAppToolCurrent)</TargetFramework>
+    <ImplicitUsings>enable</ImplicitUsings>
+    <Nullable>enable</Nullable>
+  </PropertyGroup>
+
+</Project>
