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 @@ + + + + Exe + $(NetCoreAppToolCurrent) + enable + enable + + +