#![cfg(feature = "llvm-11-or-greater")] //! These tests simply ensure that we can parse all of the `.bc` files in LLVM 11's `test/Bitcode` directory without crashing. //! We only include the `.bc` files which are new or have changed since LLVM 10 (older ones are covered in other llvm_*_tests.rs). //! Human-readable `.ll` versions of these files can be found in the LLVM repo at `test/Bitcode` at the git tag `llvmorg-11.0.0`. 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"); } }; } macro_rules! llvm_test_should_panic { ($path:expr, $func:ident, $msg:expr) => { #[test] #[should_panic(expected = $msg)] #[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/DIEnumerator-10.0.ll.bc", di_enumerator); llvm_test!( "tests/llvm_bc/DIModule-clang-module.ll.bc", di_module_clang_module ); llvm_test!( "tests/llvm_bc/DIModule-fortran-module.ll.bc", di_module_fortran_module ); llvm_test!( "tests/llvm_bc/DITemplateParameter-5.0.ll.bc", di_template_parameter ); llvm_test!("tests/llvm_bc/dataLocation.ll.bc", data_location); llvm_test!("tests/llvm_bc/fortranSubrange.ll.bc", fortran_subrange); llvm_test!( "tests/llvm_bc/fortranSubrangeBackward.ll.bc", fortran_subrange_backward ); llvm_test!( "tests/llvm_bc/thinlto-function-summary-paramaccess.ll.bc", thinlto_function_summary_paramaccess ); llvm_test!( "tests/llvm_bc/upgrade-garbage-collection-for-objc.ll.bc", upgrade_garbage_collection_for_objc ); llvm_test!( "tests/llvm_bc/upgrade-garbage-collection-for-swift.ll.bc", upgrade_garbage_collection_for_swift ); #[cfg(feature = "llvm-13-or-lower")] // starting with LLVM 14, this file is optimized to not contain a Constant::ShuffleVector llvm_test_should_panic!( "tests/llvm_bc/vscale-round-trip.ll.bc", vscale_round_trip, "Constant::ShuffleVector, which is not supported" ); llvm_test_should_panic!( "tests/llvm_bc/vscale-shuffle.ll.bc", vscale_shuffle, "Constant::ShuffleVector, which is not supported" ); // also ensure that new-to-llvm-11 constructs -- specifically, BFloat types and // scalable vector types -- were parsed correctly // LLVM 11 doesn't appear to have any files in test/Bitcode that use the new // BFloat types, so we wrote our own and tested it in basic_bc. // That means this test file only worries about scalable vector types. #[cfg(feature = "llvm-13-or-lower")] // starting with LLVM 14, this file is optimized to not contain a Constant::ShuffleVector #[test] #[should_panic(expected = "Constant::ShuffleVector, which is not supported")] fn scalable_vector_insts() { let _ = env_logger::builder().is_test(true).try_init(); // capture log messages with test harness let path = Path::new("tests/llvm_bc/vscale-round-trip.ll.bc"); let module = Module::from_bc_path(&path).expect("Failed to parse module"); use llvm_ir::{instruction, Constant, ConstantRef, Name, Operand}; use std::convert::TryInto; let func = module .get_func_by_name("non_const_shufflevector") .expect("Failed to find function"); assert_eq!( module.type_of(&func.return_type), module.types.vector_of(module.types.i32(), 4, true), ); let shufflevector: &instruction::ShuffleVector = &func .basic_blocks .get(0) .unwrap() .instrs .get(0) .unwrap() .clone() .try_into() .expect("Expected a ShuffleVector instruction"); assert_eq!( module.type_of(shufflevector), module.types.vector_of(module.types.i32(), 4, true), ); assert_eq!( &shufflevector.operand0, &Operand::LocalOperand { name: Name::from("lhs"), ty: module.types.vector_of(module.types.i32(), 4, true), } ); assert_eq!( &shufflevector.operand1, &Operand::LocalOperand { name: Name::from("rhs"), ty: module.types.vector_of(module.types.i32(), 4, true), } ); assert_eq!( &shufflevector.mask, &ConstantRef::new(Constant::AggregateZero(module.types.vector_of( module.types.i32(), 4, true ))) ); } #[cfg(feature = "llvm-13-or-lower")] // starting with LLVM 14, this file is optimized to not contain a Constant::ShuffleVector #[test] #[should_panic(expected = "Constant::ShuffleVector, which is not supported")] fn scalable_vector_consts() { let _ = env_logger::builder().is_test(true).try_init(); // capture log messages with test harness let path = Path::new("tests/llvm_bc/vscale-round-trip.ll.bc"); let module = Module::from_bc_path(&path).expect("Failed to parse module"); use llvm_ir::{constant, terminator, Constant, ConstantRef, Operand}; use std::convert::TryInto; let func = module .get_func_by_name("const_shufflevector") .expect("Failed to find function"); assert_eq!( module.type_of(&func.return_type), module.types.vector_of(module.types.i32(), 4, true), ); let ret_inst: &terminator::Ret = &func .basic_blocks .get(0) .unwrap() .term .clone() .try_into() .expect("Expected a Ret instruction"); let ret_op: &Operand = &ret_inst.return_operand.as_ref().unwrap(); assert_eq!( module.type_of(ret_op), module.types.vector_of(module.types.i32(), 4, true), ); assert_eq!( ret_op, &Operand::ConstantOperand(ConstantRef::new(Constant::ShuffleVector( constant::ShuffleVector { operand0: ConstantRef::new(Constant::AggregateZero(module.types.vector_of( module.types.i32(), 2, true ))), operand1: ConstantRef::new(Constant::Undef(module.types.vector_of( module.types.i32(), 2, true ))), mask: ConstantRef::new(Constant::AggregateZero(module.types.vector_of( module.types.i32(), 4, true ))), } ))) ); }