Add lli support for running example test cases #327
|
@ -9,6 +9,7 @@
|
||||||
in rec {
|
in rec {
|
||||||
packages.x86_64-linux = rec {
|
packages.x86_64-linux = rec {
|
||||||
llvm-nac3 = pkgs.callPackage ./nix/llvm {};
|
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 (
|
nac3artiq = pkgs.python3Packages.toPythonModule (
|
||||||
pkgs.rustPlatform.buildRustPackage rec {
|
pkgs.rustPlatform.buildRustPackage rec {
|
||||||
name = "nac3artiq";
|
name = "nac3artiq";
|
||||||
|
@ -18,7 +19,7 @@
|
||||||
lockFile = ./Cargo.lock;
|
lockFile = ./Cargo.lock;
|
||||||
};
|
};
|
||||||
passthru.cargoLock = cargoLock;
|
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 ];
|
buildInputs = [ pkgs.python3 llvm-nac3 ];
|
||||||
checkInputs = [ (pkgs.python3.withPackages(ps: [ ps.numpy ])) ];
|
checkInputs = [ (pkgs.python3.withPackages(ps: [ ps.numpy ])) ];
|
||||||
checkPhase =
|
checkPhase =
|
||||||
|
@ -143,7 +144,8 @@
|
||||||
buildInputs = with pkgs; [
|
buildInputs = with pkgs; [
|
||||||
# build dependencies
|
# build dependencies
|
||||||
packages.x86_64-linux.llvm-nac3
|
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
|
pkgs.llvmPackages_14.llvm.out # IRRT
|
||||||
cargo
|
cargo
|
||||||
rustc
|
rustc
|
||||||
|
|
|
@ -29,7 +29,7 @@ fn main() {
|
||||||
"-o",
|
"-o",
|
||||||
"-",
|
"-",
|
||||||
];
|
];
|
||||||
let output = Command::new("clang")
|
let output = Command::new("clang-unwrapped")
|
||||||
.args(FLAG)
|
.args(FLAG)
|
||||||
.output()
|
.output()
|
||||||
.map(|o| {
|
.map(|o| {
|
||||||
|
|
|
@ -0,0 +1,21 @@
|
||||||
|
#!/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
|
||||||
|
./run_demo_lli.sh "$@" "$demo" > run_lli.log
|
||||||
|
diff -Nau interpreted.log run.log
|
||||||
|
diff -Nau interpreted.log run_lli.log
|
||||||
|
echo "ok"
|
||||||
|
|
||||||
|
rm -f interpreted.log run.log run_lli.log
|
|
@ -4,12 +4,8 @@ set -e
|
||||||
|
|
||||||
count=0
|
count=0
|
||||||
for demo in src/*.py; do
|
for demo in src/*.py; do
|
||||||
echo -n "checking $demo... "
|
./check_demo.sh "$@" "$demo"
|
||||||
./interpret_demo.py $demo > interpreted.log
|
((count += 1))
|
||||||
./run_demo.sh "$@" $demo > run.log
|
|
||||||
diff -Nau interpreted.log run.log
|
|
||||||
echo "ok"
|
|
||||||
let "count+=1"
|
|
||||||
done
|
done
|
||||||
|
|
||||||
echo "Ran $count demo checks - PASSED"
|
echo "Ran $count demo checks - PASSED"
|
||||||
|
|
|
@ -0,0 +1,89 @@
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#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();
|
||||||
|
}
|
|
@ -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<u8>) {
|
|
||||||
for e in x.as_ref().iter() {
|
|
||||||
print!("{}", char::from(*e));
|
|
||||||
}
|
|
||||||
println!();
|
|
||||||
}
|
|
||||||
|
|
||||||
#[no_mangle]
|
|
||||||
pub extern "C" fn output_int32_list(x: &cslice::CSlice<i32>) {
|
|
||||||
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();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -48,17 +48,21 @@ def patch(module):
|
||||||
else:
|
else:
|
||||||
sys.stdout.write(" .,-:;i+hHM$*#@ "[x])
|
sys.stdout.write(" .,-:;i+hHM$*#@ "[x])
|
||||||
|
|
||||||
|
def output_float(x):
|
||||||
|
print("%f" % x)
|
||||||
|
|
||||||
def extern(fun):
|
def extern(fun):
|
||||||
name = fun.__name__
|
name = fun.__name__
|
||||||
if name == "output_asciiart":
|
if name == "output_asciiart":
|
||||||
return output_asciiart
|
return output_asciiart
|
||||||
|
elif name == "output_float64":
|
||||||
|
return output_float
|
||||||
elif name in {
|
elif name in {
|
||||||
"output_int32",
|
"output_int32",
|
||||||
"output_int64",
|
"output_int64",
|
||||||
"output_int32_list",
|
"output_int32_list",
|
||||||
"output_uint32",
|
"output_uint32",
|
||||||
"output_uint64",
|
"output_uint64",
|
||||||
"output_float64",
|
|
||||||
"output_str",
|
"output_str",
|
||||||
}:
|
}:
|
||||||
return print
|
return print
|
||||||
|
|
|
@ -14,7 +14,9 @@ else
|
||||||
nac3standalone=../../target/x86_64-unknown-linux-gnu/release/nac3standalone
|
nac3standalone=../../target/x86_64-unknown-linux-gnu/release/nac3standalone
|
||||||
fi
|
fi
|
||||||
|
|
||||||
rm -f *.o
|
rm -f "*.o" demo
|
||||||
sb10q marked this conversation as resolved
|
|||||||
|
|
||||||
$nac3standalone "$@"
|
$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
|
./demo
|
||||||
|
|
|
@ -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
|
|
@ -14,6 +14,10 @@ def output_uint32(x: uint32):
|
||||||
def output_uint64(x: uint64):
|
def output_uint64(x: uint64):
|
||||||
...
|
...
|
||||||
|
|
||||||
|
@extern
|
||||||
|
def output_float64(x: float):
|
||||||
|
...
|
||||||
|
|
||||||
@extern
|
@extern
|
||||||
def output_int32_list(x: list[int32]):
|
def output_int32_list(x: list[int32]):
|
||||||
...
|
...
|
||||||
|
@ -38,6 +42,15 @@ def test_output_uint32():
|
||||||
def test_output_uint64():
|
def test_output_uint64():
|
||||||
output_uint64(uint64(256))
|
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():
|
def test_output_asciiart():
|
||||||
for i in range(17):
|
for i in range(17):
|
||||||
output_asciiart(i)
|
output_asciiart(i)
|
||||||
|
@ -54,6 +67,7 @@ def run() -> int32:
|
||||||
test_output_int64()
|
test_output_int64()
|
||||||
test_output_uint32()
|
test_output_uint32()
|
||||||
test_output_uint64()
|
test_output_uint64()
|
||||||
|
test_output_float64()
|
||||||
test_output_asciiart()
|
test_output_asciiart()
|
||||||
test_output_int32_list()
|
test_output_int32_list()
|
||||||
test_output_str_family()
|
test_output_str_family()
|
||||||
|
|
|
@ -354,7 +354,12 @@ fn main() {
|
||||||
|
|
||||||
main.link_in_module(other).unwrap();
|
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();
|
let mut function_iter = main.get_first_function();
|
||||||
while let Some(func) = function_iter {
|
while let Some(func) = function_iter {
|
||||||
|
|
Loading…
Reference in New Issue
Why? The next commands will overwrite them.
I just found it to be intuitive that if you are removing the object files, then the output executable should also be removed.