From 8801fc63e167032936758eeb7ad8216992bf09d8 Mon Sep 17 00:00:00 2001 From: David Mak Date: Mon, 25 Sep 2023 15:38:33 +0800 Subject: [PATCH 1/7] flake: Add clang alongside clang-unwrapped --- flake.nix | 6 ++++-- nac3core/build.rs | 2 +- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/flake.nix b/flake.nix index b6ad250e..0932e948 100644 --- a/flake.nix +++ b/flake.nix @@ -9,6 +9,7 @@ in rec { packages.x86_64-linux = rec { llvm-nac3 = pkgs.callPackage ./nix/llvm {}; + clang-unwrapped = pkgs.runCommandNoCC "clang-unwrapped" {} "mkdir -p $out/bin; ln -s ${pkgs.llvmPackages_14.clang-unwrapped}/bin/clang $out/bin/clang-unwrapped"; nac3artiq = pkgs.python3Packages.toPythonModule ( pkgs.rustPlatform.buildRustPackage rec { name = "nac3artiq"; @@ -18,7 +19,7 @@ lockFile = ./Cargo.lock; }; passthru.cargoLock = cargoLock; - nativeBuildInputs = [ pkgs.python3 pkgs.llvmPackages_14.clang-unwrapped pkgs.llvmPackages_14.llvm.out llvm-nac3 ]; + nativeBuildInputs = [ pkgs.python3 pkgs.llvmPackages_14.clang packages.x86_64-linux.clang-unwrapped pkgs.llvmPackages_14.llvm.out llvm-nac3 ]; buildInputs = [ pkgs.python3 llvm-nac3 ]; checkInputs = [ (pkgs.python3.withPackages(ps: [ ps.numpy ])) ]; checkPhase = @@ -143,7 +144,8 @@ buildInputs = with pkgs; [ # build dependencies packages.x86_64-linux.llvm-nac3 - llvmPackages_14.clang-unwrapped # IRRT + llvmPackages_14.clang # demo + packages.x86_64-linux.clang-unwrapped # IRRT pkgs.llvmPackages_14.llvm.out # IRRT cargo rustc diff --git a/nac3core/build.rs b/nac3core/build.rs index a032bb93..304d6026 100644 --- a/nac3core/build.rs +++ b/nac3core/build.rs @@ -29,7 +29,7 @@ fn main() { "-o", "-", ]; - let output = Command::new("clang") + let output = Command::new("clang-unwrapped") .args(FLAG) .output() .map(|o| { -- 2.44.2 From c010fd9a0919a1e18b76f68544174400fcadcccf Mon Sep 17 00:00:00 2001 From: David Mak Date: Fri, 29 Sep 2023 15:06:56 +0800 Subject: [PATCH 2/7] standalone: Add float64 output tests --- nac3standalone/demo/src/demo_test.py | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/nac3standalone/demo/src/demo_test.py b/nac3standalone/demo/src/demo_test.py index 3a99887a..f75f8690 100644 --- a/nac3standalone/demo/src/demo_test.py +++ b/nac3standalone/demo/src/demo_test.py @@ -14,6 +14,10 @@ def output_uint32(x: uint32): def output_uint64(x: uint64): ... +@extern +def output_float64(x: float): + ... + @extern def output_int32_list(x: list[int32]): ... @@ -38,6 +42,15 @@ def test_output_uint32(): def test_output_uint64(): output_uint64(uint64(256)) +def test_output_float64(): + output_float64(0.0) + output_float64(1.0) + output_float64(-1.0) + output_float64(128.0) + output_float64(-128.0) + output_float64(16.25) + output_float64(-16.25) + def test_output_asciiart(): for i in range(17): output_asciiart(i) @@ -54,6 +67,7 @@ def run() -> int32: test_output_int64() test_output_uint32() test_output_uint64() + test_output_float64() test_output_asciiart() test_output_int32_list() test_output_str_family() -- 2.44.2 From d8e5ca3d7f34430ddbc71fd31e8abd8c940efe85 Mon Sep 17 00:00:00 2001 From: David Mak Date: Fri, 29 Sep 2023 15:15:18 +0800 Subject: [PATCH 3/7] standalone: Refactor demo library to C Needed for use by lli. --- nac3standalone/demo/demo.c | 89 +++++++++++++++++++++ nac3standalone/demo/demo.rs | 111 -------------------------- nac3standalone/demo/interpret_demo.py | 6 +- nac3standalone/demo/run_demo.sh | 6 +- 4 files changed, 98 insertions(+), 114 deletions(-) create mode 100644 nac3standalone/demo/demo.c delete mode 100644 nac3standalone/demo/demo.rs diff --git a/nac3standalone/demo/demo.c b/nac3standalone/demo/demo.c new file mode 100644 index 00000000..4369b704 --- /dev/null +++ b/nac3standalone/demo/demo.c @@ -0,0 +1,89 @@ +#include +#include +#include +#include + +#if __SIZEOF_POINTER__ == 8 + #define usize uint64_t +#elif __SIZEOF_POINTER__ == 4 + #define usize uint32_t +#else + #error "Unsupported platform - Platform is not 32-bit or 64-bit" +#endif + +void output_int32(const int32_t x) { + printf("%d\n", x); +} + +void output_int64(const int64_t x) { + printf("%ld\n", x); +} + +void output_uint32(const uint32_t x) { + printf("%d\n", x); +} + +void output_uint64(const uint64_t x) { + printf("%ld\n", x); +} + +void output_float64(const double x) { + printf("%f\n", x); +} +void output_asciiart(const int32_t x) { + const char* chars = " .,-:;i+hHM$*#@ "; + if (x < 0) { + putchar('\n'); + } else { + putchar(chars[x]); + } +} + +struct cslice { + const void* data; + usize len; +}; + +void output_int32_list(struct cslice* slice) { + const int32_t* data = (const int32_t*) slice->data; + + putchar('['); + for (usize i = 0; i < slice->len; ++i) { + if (i == slice->len - 1) { + printf("%d", data[i]); + } else { + printf("%d, ", data[i]); + } + } + putchar(']'); + putchar('\n'); +} + +void output_str(struct cslice* slice) { + const char* data = (const char*) slice->data; + + for (usize i = 0; i < slice->len; ++i) { + putchar(data[i]); + } + putchar('\n'); +} + +uint32_t __nac3_personality(uint32_t state, uint32_t exception_object, uint32_t context) { + printf("__nac3_personality(state: %u, exception_object: %u, context: %u\n", state, exception_object, context); + exit(101); + __builtin_unreachable(); +} + +uint32_t __nac3_raise(uint32_t state, uint32_t exception_object, uint32_t context) { + printf("__nac3_raise(state: %u, exception_object: %u, context: %u\n", state, exception_object, context); + exit(101); + __builtin_unreachable(); +} + +void __nac3_end_catch(void) {} + +extern int32_t run(void); + +int main(void) { + run(); +} diff --git a/nac3standalone/demo/demo.rs b/nac3standalone/demo/demo.rs deleted file mode 100644 index 154236dc..00000000 --- a/nac3standalone/demo/demo.rs +++ /dev/null @@ -1,111 +0,0 @@ -use std::io; -use std::io::Write; -use std::process::exit; - -mod cslice { - // copied from https://github.com/dherman/cslice - use std::marker::PhantomData; - use std::slice; - - #[repr(C)] - #[derive(Clone, Copy)] - pub struct CSlice<'a, T> { - base: *const T, - len: usize, - marker: PhantomData<&'a ()>, - } - - impl<'a, T> AsRef<[T]> for CSlice<'a, T> { - fn as_ref(&self) -> &[T] { - unsafe { slice::from_raw_parts(self.base, self.len) } - } - } -} - -#[no_mangle] -pub extern "C" fn output_int32(x: i32) { - println!("{}", x); -} - -#[no_mangle] -pub extern "C" fn output_int64(x: i64) { - println!("{}", x); -} - -#[no_mangle] -pub extern "C" fn output_uint32(x: u32) { - println!("{}", x); -} - -#[no_mangle] -pub extern "C" fn output_uint64(x: u64) { - println!("{}", x); -} - -#[no_mangle] -pub extern "C" fn output_float64(x: f64) { - // debug output to preserve the digits after the decimal points - // to match python `print` function - println!("{:?}", x); -} - -#[no_mangle] -pub extern "C" fn output_asciiart(x: i32) { - let chars = " .,-:;i+hHM$*#@ "; - if x < 0 { - println!(""); - } else { - print!("{}", chars.chars().nth(x as usize).unwrap()); - } -} - -#[no_mangle] -pub extern "C" fn output_str(x: &cslice::CSlice) { - for e in x.as_ref().iter() { - print!("{}", char::from(*e)); - } - println!(); -} - -#[no_mangle] -pub extern "C" fn output_int32_list(x: &cslice::CSlice) { - print!("["); - let mut it = x.as_ref().iter().peekable(); - while let Some(e) = it.next() { - if it.peek().is_none() { - print!("{}", e); - } else { - print!("{}, ", e); - } - } - println!("]"); -} - -#[no_mangle] -pub extern "C" fn __nac3_personality(_state: u32, _exception_object: u32, _context: u32) -> u32 { - unimplemented!(); -} - -#[no_mangle] -pub extern "C" fn __nac3_raise(state: u32, exception_object: u32, context: u32) -> u32 { - writeln!(io::stderr(), - "__nac3_raise(state: {:#010x}, exception_object: {:#010x}, context: {:#010x})", - state, - exception_object, - context - ).unwrap(); - exit(101); -} - -#[no_mangle] -pub extern "C" fn __nac3_end_catch() {} - -extern "C" { - fn run() -> i32; -} - -fn main() { - unsafe { - run(); - } -} diff --git a/nac3standalone/demo/interpret_demo.py b/nac3standalone/demo/interpret_demo.py index dcee2002..69c0cf05 100755 --- a/nac3standalone/demo/interpret_demo.py +++ b/nac3standalone/demo/interpret_demo.py @@ -48,17 +48,21 @@ def patch(module): else: sys.stdout.write(" .,-:;i+hHM$*#@ "[x]) + def output_float(x): + print("%f" % x) + def extern(fun): name = fun.__name__ if name == "output_asciiart": return output_asciiart + elif name == "output_float64": + return output_float elif name in { "output_int32", "output_int64", "output_int32_list", "output_uint32", "output_uint64", - "output_float64", "output_str", }: return print diff --git a/nac3standalone/demo/run_demo.sh b/nac3standalone/demo/run_demo.sh index 61b79d6c..cffa79e5 100755 --- a/nac3standalone/demo/run_demo.sh +++ b/nac3standalone/demo/run_demo.sh @@ -14,7 +14,9 @@ else nac3standalone=../../target/x86_64-unknown-linux-gnu/release/nac3standalone fi -rm -f *.o +rm -f "*.o" demo + $nac3standalone "$@" -rustc -o demo demo.rs -Crelocation-model=static -Clink-arg=./module.o +clang -c -std=gnu11 -Wall -Wextra -O3 -o demo.o demo.c +clang -o demo module.o demo.o ./demo -- 2.44.2 From f9aceb24eee0c0bac54e21bdf331880ad192d3ce Mon Sep 17 00:00:00 2001 From: David Mak Date: Fri, 29 Sep 2023 15:17:45 +0800 Subject: [PATCH 4/7] standalone: Split check_demos into check_demo Allows individual tests to be executed. --- nac3standalone/demo/check_demo.sh | 17 +++++++++++++++++ nac3standalone/demo/check_demos.sh | 8 ++------ 2 files changed, 19 insertions(+), 6 deletions(-) create mode 100755 nac3standalone/demo/check_demo.sh diff --git a/nac3standalone/demo/check_demo.sh b/nac3standalone/demo/check_demo.sh new file mode 100755 index 00000000..5ea8e182 --- /dev/null +++ b/nac3standalone/demo/check_demo.sh @@ -0,0 +1,17 @@ +#!/usr/bin/env bash + +set -e + +if [ -z "$1" ]; then + echo "Requires at least one argument" + exit 1 +fi + +demo="${@:-1}" +set -- "${@:1:$(($# - 1))}" + +echo -n "Checking $demo... " +./interpret_demo.py "$demo" > interpreted.log +./run_demo.sh "$@" "$demo" > run.log +diff -Nau interpreted.log run.log +echo "ok" diff --git a/nac3standalone/demo/check_demos.sh b/nac3standalone/demo/check_demos.sh index d7fa8b16..ae21142b 100755 --- a/nac3standalone/demo/check_demos.sh +++ b/nac3standalone/demo/check_demos.sh @@ -4,12 +4,8 @@ set -e count=0 for demo in src/*.py; do - echo -n "checking $demo... " - ./interpret_demo.py $demo > interpreted.log - ./run_demo.sh "$@" $demo > run.log - diff -Nau interpreted.log run.log - echo "ok" - let "count+=1" + ./check_demo.sh "$@" "$demo" + ((count += 1)) done echo "Ran $count demo checks - PASSED" -- 2.44.2 From a0c206dc8d9e01e265904606d5581eb908ad22e3 Mon Sep 17 00:00:00 2001 From: David Mak Date: Fri, 29 Sep 2023 16:41:32 +0800 Subject: [PATCH 5/7] standalone: Emit IRRT IR --- nac3standalone/src/main.rs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/nac3standalone/src/main.rs b/nac3standalone/src/main.rs index 16f3aaef..8d724052 100644 --- a/nac3standalone/src/main.rs +++ b/nac3standalone/src/main.rs @@ -354,7 +354,12 @@ fn main() { main.link_in_module(other).unwrap(); } - main.link_in_module(load_irrt(&context)).unwrap(); + + let irrt = load_irrt(&context); + if emit_llvm { + irrt.write_bitcode_to_path(Path::new("irrt.bc")); + } + main.link_in_module(irrt).unwrap(); let mut function_iter = main.get_first_function(); while let Some(func) = function_iter { -- 2.44.2 From 7cb18d5267d3d08a5f75f3b1376d1aba55c9f25c Mon Sep 17 00:00:00 2001 From: David Mak Date: Fri, 29 Sep 2023 15:18:00 +0800 Subject: [PATCH 6/7] standalone: Add execution of test cases via lli --- nac3standalone/demo/check_demo.sh | 2 ++ nac3standalone/demo/run_demo_lli.sh | 21 +++++++++++++++++++++ 2 files changed, 23 insertions(+) create mode 100755 nac3standalone/demo/run_demo_lli.sh diff --git a/nac3standalone/demo/check_demo.sh b/nac3standalone/demo/check_demo.sh index 5ea8e182..31fbbacf 100755 --- a/nac3standalone/demo/check_demo.sh +++ b/nac3standalone/demo/check_demo.sh @@ -13,5 +13,7 @@ set -- "${@:1:$(($# - 1))}" echo -n "Checking $demo... " ./interpret_demo.py "$demo" > interpreted.log ./run_demo.sh "$@" "$demo" > run.log +./run_demo_lli.sh "$@" "$demo" > run_lli.log diff -Nau interpreted.log run.log +diff -Nau interpreted.log run_lli.log echo "ok" diff --git a/nac3standalone/demo/run_demo_lli.sh b/nac3standalone/demo/run_demo_lli.sh new file mode 100755 index 00000000..6efd4f5c --- /dev/null +++ b/nac3standalone/demo/run_demo_lli.sh @@ -0,0 +1,21 @@ +#!/usr/bin/env bash + +set -e + +if [ -z "$1" ]; then + echo "No argument supplied" + exit 1 +fi + +if [ -e ../../target/release/nac3standalone ]; then + nac3standalone=../../target/release/nac3standalone +else + # used by Nix builds + nac3standalone=../../target/x86_64-unknown-linux-gnu/release/nac3standalone +fi + +rm -f "*.o" "*.bc" demo + +$nac3standalone --emit-llvm "$@" +clang -c -std=gnu11 -Wall -Wextra -O3 -emit-llvm -o demo.bc demo.c +lli --extra-module demo.bc --extra-module irrt.bc main.bc -- 2.44.2 From cbdbe53db119aa52120a99640ab2c6d074a67a93 Mon Sep 17 00:00:00 2001 From: David Mak Date: Fri, 29 Sep 2023 16:43:48 +0800 Subject: [PATCH 7/7] standalone: Remove temporary logfiles after execution --- nac3standalone/demo/check_demo.sh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/nac3standalone/demo/check_demo.sh b/nac3standalone/demo/check_demo.sh index 31fbbacf..bcf9a69f 100755 --- a/nac3standalone/demo/check_demo.sh +++ b/nac3standalone/demo/check_demo.sh @@ -17,3 +17,5 @@ echo -n "Checking $demo... " diff -Nau interpreted.log run.log diff -Nau interpreted.log run_lli.log echo "ok" + +rm -f interpreted.log run.log run_lli.log -- 2.44.2