//! These tests simply ensure that we can parse all of the `.bc` files in LLVM 9's `test/Bitcode` directory without crashing.
//! We only include the `.bc` files which are new or have changed since LLVM 8 (older ones are covered in llvm_8_tests.rs).
//! Human-readable `.ll` versions of these files can be found in the LLVM repo at `test/Bitcode` on the git branch `release/9.x`.

use llvm_ir::Module;
use std::path::Path;

macro_rules! llvm_test {
    ($path:expr, $func:ident) => {
        #[test]
        #[allow(non_snake_case)]
        fn $func() {
            let _ = env_logger::builder().is_test(true).try_init(); // capture log messages with test harness
            let path = Path::new($path);
            let _ = Module::from_bc_path(&path).expect("Failed to parse module");
        }
    };
}

llvm_test!("tests/llvm_bc/DISubprogram-v5.ll.bc", DISubprogram_v5);
llvm_test!("tests/llvm_bc/callbr.ll.bc", callbr);
//llvm_test!("tests/llvm_bc/invalid.ll.bc", invalid);  // we omit this .bc file because it is intentionally invalid.  Note that it existed in LLVM 8 but has changed; the checked-in version as of this writing is the LLVM 8 version
llvm_test!("tests/llvm_bc/objectsize-upgrade-7.0.ll.bc", objectsize_upgrade_7_0);
//llvm_test!("tests/llvm_bc/upgrade-clang-arc-use.ll.bc", upgrade_clang_arc_use);  // this file is weird because it includes an opaque struct type which is numbered, not named.  This shouldn't ever occur in real code (?), so we omit this test case
llvm_test!("tests/llvm_bc/upgrade-global-dtors.ll.bc", upgrade_global_dtors);
llvm_test!("tests/llvm_bc/upgrade-vecreduce-intrinsics.ll.bc", upgrade_vecreduce_intrinsics);

// also ensure that certain new-to-llvm-9 constructs were parsed correctly
use llvm_ir::{terminator, Name};
use std::convert::TryInto;

#[test]
fn callbr_parsing() {
    let _ = env_logger::builder().is_test(true).try_init(); // capture log messages with test harness
    let path = Path::new("tests/llvm_bc/callbr.ll.bc");
    let module = Module::from_bc_path(&path).expect("Failed to parse module");
    let func = module
        .get_func_by_name("test_asm_goto")
        .expect("Failed to find function");
    let bb = func.get_bb_by_name(&Name::from("entry")).expect("Failed to find entry bb");
    let callbr: &terminator::CallBr = &bb.term.clone().try_into().unwrap_or_else(|_| panic!("Expected a callbr, got {:?}", &bb.term));
    assert!(callbr.function.is_left());
    assert_eq!(callbr.return_label, Name::from("normal"));
}
