diff --git a/.github/workflows/rust.yaml b/.github/workflows/rust.yaml index e3c395660..6a1951d3a 100644 --- a/.github/workflows/rust.yaml +++ b/.github/workflows/rust.yaml @@ -26,6 +26,9 @@ on: name: Workflow checks for rust code +env: + LLVM_VERSION: 18.0 + jobs: test: runs-on: ubuntu-latest @@ -33,19 +36,32 @@ jobs: matrix: test-code: - "cd bril-rs && make test TURNTARGS=-v" - - "cd bril-rs && make features" - "cd brilirs && make test TURNTARGS=-v" - "cd brilirs && make benchmark TURNTARGS=-v" - "cd brilift && cargo build --release && make rt.o && make test TURNTARGS=-v" - "cd brilift && cargo build --release && make rt.o && make benchmark TURNTARGS=-v" + # Code requiring additional dependencies are separated out + include: + - test-code: "cd bril-rs && make features" + needs_cargo_hack: true + - test-code: "cd bril-rs/brillvm && make build" + needs_llvm: true steps: - uses: actions/checkout@v4 - uses: dtolnay/rust-toolchain@v1 with: toolchain: stable + - name: Install LLVM and Clang + if: matrix.needs_llvm + run: | + wget https://apt.llvm.org/llvm.sh + chmod +x llvm.sh + sudo ./llvm.sh ${{ env.LLVM_VERSION }} all + - name: Install cargo-hack for feature-flag checking run: cargo install cargo-hack + if: matrix.needs_cargo_hack - uses: actions/setup-python@v4 with: @@ -65,7 +81,8 @@ jobs: repository: cucapra/turnt path: './turnt' - name: Install Turnt part 2 - run: cd turnt ; flit install --symlink + run: flit install --symlink + working-directory: ./turnt - name: Problem matcher run: echo '::add-matcher::.github/tap-matcher.json' @@ -88,10 +105,11 @@ jobs: toolchain: stable - name: Install LLVM and Clang - uses: KyleMayes/install-llvm-action@v1 if: matrix.path == 'bril-rs/brillvm/Cargo.toml' - with: - version: "16.0" + run: | + wget https://apt.llvm.org/llvm.sh + chmod +x llvm.sh + sudo ./llvm.sh ${{ env.LLVM_VERSION }} all - name: cargo check run: cargo check --manifest-path ${{ matrix.path }} --all-targets diff --git a/bril-rs/Cargo.toml b/bril-rs/Cargo.toml index 950244a4a..30768f58b 100644 --- a/bril-rs/Cargo.toml +++ b/bril-rs/Cargo.toml @@ -6,7 +6,6 @@ edition = "2021" description = "A rust representation of the Bril language" readme = "README.md" repository = "https://github.com/sampsyo/bril" -# license = "MIT" license-file = "../LICENSE" categories = ["command-line-utilities", "compilers", "data-structures", "parser-implementations"] keywords = ["compiler", "bril", "parser", "data-structures", "language"] diff --git a/bril-rs/brillvm/.cargo/config b/bril-rs/brillvm/.cargo/config deleted file mode 100644 index 59c989e69..000000000 --- a/bril-rs/brillvm/.cargo/config +++ /dev/null @@ -1,11 +0,0 @@ -[target.x86_64-apple-darwin] -rustflags = [ - "-C", "link-arg=-undefined", - "-C", "link-arg=dynamic_lookup", -] - -[target.aarch64-apple-darwin] -rustflags = [ - "-C", "link-arg=-undefined", - "-C", "link-arg=dynamic_lookup", -] \ No newline at end of file diff --git a/bril-rs/brillvm/Cargo.toml b/bril-rs/brillvm/Cargo.toml index 8b430580a..46fc5fba4 100644 --- a/bril-rs/brillvm/Cargo.toml +++ b/bril-rs/brillvm/Cargo.toml @@ -16,32 +16,15 @@ default-run = "main" [dependencies] clap = { version = "4.4", features = ["derive"] } -inkwell = { version = "0.2", features = ["llvm16-0"] } -libc-print = "0.1" - -# For overriding parking_lot_core to latest version from 0.9.7 -# To pull in the removal of `window-sys` which was causing duplicate dependencies -[patch.crates-io] -parking_lot_core = { git = "https://github.com/Amanieu/parking_lot" } +inkwell = { git = "https://github.com/TheDan64/inkwell.git", features = [ + "llvm18-0", +] } [dependencies.bril-rs] path = ".." features = ["float", "ssa", "memory"] -[[bin]] -name = "rt" -path = "bin/rt.rs" - # Need to set a default `main` to build `rt` bin [[bin]] name = "main" path = "src/main.rs" - -# To properly set up the rt library for linking with LLVM -[profile.dev] -panic = "abort" -lto = true - -[profile.release] -panic = "abort" -lto = true diff --git a/bril-rs/brillvm/Makefile b/bril-rs/brillvm/Makefile index 08b7a1419..4322334f3 100644 --- a/bril-rs/brillvm/Makefile +++ b/bril-rs/brillvm/Makefile @@ -9,6 +9,9 @@ BENCHMARKS := ../../benchmarks/core/*.bril \ ../../benchmarks/mem/*.bril \ ../../benchmarks/mixed/*.bril +build: + cargo build + clean: cargo clean rm rt.bc @@ -16,11 +19,12 @@ clean: .PHONY: rt rt: - cargo rustc --bin rt --release -- --emit=llvm-bc && mv target/release/deps/rt-*.bc rt.bc + cd runtime && cargo rustc --release -- --emit=llvm-bc && mv target/release/deps/runtime-*.bc ../rt.bc example: # bril2json < ../../benchmarks/mem/sieve.bril | cargo run -- -i 100 - bril2json < ../../benchmarks/mixed/cholesky.bril | cargo run -- -i +# bril2json < ../../benchmarks/mixed/cholesky.bril | cargo run -- -i + bril2json < ../../test/interp/ssa/ssa-two-phi.bril | cargo run -- -i true .PHONY: test test: diff --git a/bril-rs/brillvm/README.md b/bril-rs/brillvm/README.md index c70ad51d2..cc9ea5afd 100644 --- a/bril-rs/brillvm/README.md +++ b/bril-rs/brillvm/README.md @@ -56,3 +56,15 @@ This tool relies on the `llvm-sys` crate to find the correct version of LLVM to ```shell LLVM_SYS_150_PREFIX="/opt/homebrew/Cellar/llvm/15.0.7_1/" ``` + +### zstd not found + +```shell +ld: Library 'zstd' not found +``` + +Mac specific: Assuming you have zstd installed via `brew install zstd`, googling +around has found that you might need +`export LIBRARY_PATH=$LIBRARY_PATH:$(brew --prefix zstd)/lib/`. Apparently this +also hit the ruby community at some point so, they have many issues with similar +resolutions to this problem. diff --git a/bril-rs/brillvm/runtime/Cargo.toml b/bril-rs/brillvm/runtime/Cargo.toml new file mode 100644 index 000000000..64e8d7fa6 --- /dev/null +++ b/bril-rs/brillvm/runtime/Cargo.toml @@ -0,0 +1,18 @@ +[package] +name = "runtime" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +libc-print = "0.1" + +# To properly set up the rt library for linking with LLVM +[profile.dev] +panic = "abort" +lto = true + +[profile.release] +panic = "abort" +lto = true \ No newline at end of file diff --git a/bril-rs/brillvm/runtime/build.rs b/bril-rs/brillvm/runtime/build.rs new file mode 100644 index 000000000..b3b098f5c --- /dev/null +++ b/bril-rs/brillvm/runtime/build.rs @@ -0,0 +1,11 @@ +fn main() { + #[cfg(target_os = "linux")] + println!("cargo:rustc-link-arg=-nostdlib"); + #[cfg(target_os = "macos")] + println!("cargo:rustc-link-arg=-undefined"); + #[cfg(target_os = "macos")] + println!("cargo:rustc-link-arg=dynamic_lookup"); + + #[cfg(not(any(target_os = "linux", target_os = "macos")))] + assert!(false) +} diff --git a/bril-rs/brillvm/bin/rt.rs b/bril-rs/brillvm/runtime/src/main.rs similarity index 100% rename from bril-rs/brillvm/bin/rt.rs rename to bril-rs/brillvm/runtime/src/main.rs diff --git a/bril-rs/brillvm/src/llvm.rs b/bril-rs/brillvm/src/llvm.rs index 62c10838b..133614ba5 100644 --- a/bril-rs/brillvm/src/llvm.rs +++ b/bril-rs/brillvm/src/llvm.rs @@ -5,7 +5,7 @@ use inkwell::{ builder::Builder, context::Context, module::Module, - types::{BasicMetadataTypeEnum, BasicType, BasicTypeEnum, FunctionType, PointerType}, + types::{BasicMetadataTypeEnum, BasicType, BasicTypeEnum, FunctionType}, values::{BasicValue, BasicValueEnum, FloatValue, FunctionValue, IntValue, PointerValue}, AddressSpace, FloatPredicate, IntPredicate, }; @@ -23,7 +23,7 @@ where Type::Int => fn_map(context.i64_type().into()), Type::Bool => fn_map(context.bool_type().into()), Type::Float => fn_map(context.f64_type().into()), - Type::Pointer(_) => fn_map(build_pointertype(context, ty).into()), + Type::Pointer(_) => fn_map(context.ptr_type(AddressSpace::default()).into()), } } @@ -34,13 +34,6 @@ fn unwrap_bril_ptrtype(ty: &Type) -> &Type { } } -/// Converts a Bril Pointer type into an LLVM Pointer type -fn build_pointertype<'a>(context: &'a Context, ty: &Type) -> PointerType<'a> { - llvm_type_map(context, unwrap_bril_ptrtype(ty), |t| { - t.ptr_type(AddressSpace::default()) - }) -} - /// Converts a Bril function signature into an LLVM function type fn build_functiontype<'a>( context: &'a Context, @@ -65,7 +58,7 @@ fn build_load<'a>( name: &str, ) -> BasicValueEnum<'a> { llvm_type_map(context, &ptr.ty, |pointee_ty| { - builder.build_load(pointee_ty, ptr.ptr, name) + builder.build_load(pointee_ty, ptr.ptr, name).unwrap() }) } @@ -80,7 +73,7 @@ impl<'a> WrappedPointer<'a> { fn new(builder: &'a Builder, context: &'a Context, name: &str, ty: &Type) -> Self { Self { ty: ty.clone(), - ptr: llvm_type_map(context, ty, |ty| builder.build_alloca(ty, name)), + ptr: llvm_type_map(context, ty, |ty| builder.build_alloca(ty, name).unwrap()), } } } @@ -147,13 +140,15 @@ fn build_op<'a, 'b>( args: &'b [String], dest: &'b String, ) { - builder.build_store( - heap.get(dest).ptr, - op(args - .iter() - .map(|n| build_load(context, builder, &heap.get(n), &fresh.fresh_var())) - .collect()), - ); + builder + .build_store( + heap.get(dest).ptr, + op(args + .iter() + .map(|n| build_load(context, builder, &heap.get(n), &fresh.fresh_var())) + .collect()), + ) + .unwrap(); } // Like `build_op` but where there is no return value @@ -204,10 +199,12 @@ fn build_instruction<'a, 'b>( value: Literal::Int(i), } => { #[allow(clippy::cast_precision_loss)] - builder.build_store( - heap.get(dest).ptr, - context.f64_type().const_float(*i as f64), - ); + builder + .build_store( + heap.get(dest).ptr, + context.f64_type().const_float(*i as f64), + ) + .unwrap(); } Instruction::Constant { dest, @@ -216,10 +213,12 @@ fn build_instruction<'a, 'b>( value: Literal::Int(i), } => { #[allow(clippy::cast_sign_loss)] - builder.build_store( - heap.get(dest).ptr, - context.i64_type().const_int(*i as u64, true), - ); + builder + .build_store( + heap.get(dest).ptr, + context.i64_type().const_int(*i as u64, true), + ) + .unwrap(); } Instruction::Constant { dest, @@ -227,10 +226,12 @@ fn build_instruction<'a, 'b>( const_type: _, value: Literal::Bool(b), } => { - builder.build_store( - heap.get(dest).ptr, - context.bool_type().const_int((*b).into(), false), - ); + builder + .build_store( + heap.get(dest).ptr, + context.bool_type().const_int((*b).into(), false), + ) + .unwrap(); } Instruction::Constant { dest, @@ -238,7 +239,9 @@ fn build_instruction<'a, 'b>( const_type: _, value: Literal::Float(f), } => { - builder.build_store(heap.get(dest).ptr, context.f64_type().const_float(*f)); + builder + .build_store(heap.get(dest).ptr, context.f64_type().const_float(*f)) + .unwrap(); } Instruction::Value { args, @@ -261,6 +264,7 @@ fn build_instruction<'a, 'b>( v[1].try_into().unwrap(), &ret_name, ) + .unwrap() .into() }, args, @@ -288,6 +292,7 @@ fn build_instruction<'a, 'b>( v[1].try_into().unwrap(), &ret_name, ) + .unwrap() .into() }, args, @@ -315,6 +320,7 @@ fn build_instruction<'a, 'b>( v[1].try_into().unwrap(), &ret_name, ) + .unwrap() .into() }, args, @@ -342,6 +348,7 @@ fn build_instruction<'a, 'b>( v[1].try_into().unwrap(), &ret_name, ) + .unwrap() .into() }, args, @@ -370,6 +377,7 @@ fn build_instruction<'a, 'b>( v[1].try_into().unwrap(), &ret_name, ) + .unwrap() .into() }, args, @@ -398,6 +406,7 @@ fn build_instruction<'a, 'b>( v[1].try_into().unwrap(), &ret_name, ) + .unwrap() .into() }, args, @@ -426,6 +435,7 @@ fn build_instruction<'a, 'b>( v[1].try_into().unwrap(), &ret_name, ) + .unwrap() .into() }, args, @@ -454,6 +464,7 @@ fn build_instruction<'a, 'b>( v[1].try_into().unwrap(), &ret_name, ) + .unwrap() .into() }, args, @@ -482,6 +493,7 @@ fn build_instruction<'a, 'b>( v[1].try_into().unwrap(), &ret_name, ) + .unwrap() .into() }, args, @@ -505,6 +517,7 @@ fn build_instruction<'a, 'b>( |v| { builder .build_not::(v[0].try_into().unwrap(), &ret_name) + .unwrap() .into() }, args, @@ -532,6 +545,7 @@ fn build_instruction<'a, 'b>( v[1].try_into().unwrap(), &ret_name, ) + .unwrap() .into() }, args, @@ -559,6 +573,7 @@ fn build_instruction<'a, 'b>( v[1].try_into().unwrap(), &ret_name, ) + .unwrap() .into() }, args, @@ -595,6 +610,7 @@ fn build_instruction<'a, 'b>( .as_slice(), &ret_name, ) + .unwrap() .try_as_basic_value() .left() .unwrap() @@ -632,6 +648,7 @@ fn build_instruction<'a, 'b>( v[1].try_into().unwrap(), &ret_name, ) + .unwrap() .into() }, args, @@ -659,6 +676,7 @@ fn build_instruction<'a, 'b>( v[1].try_into().unwrap(), &ret_name, ) + .unwrap() .into() }, args, @@ -686,6 +704,7 @@ fn build_instruction<'a, 'b>( v[1].try_into().unwrap(), &ret_name, ) + .unwrap() .into() }, args, @@ -713,6 +732,7 @@ fn build_instruction<'a, 'b>( v[1].try_into().unwrap(), &ret_name, ) + .unwrap() .into() }, args, @@ -741,6 +761,7 @@ fn build_instruction<'a, 'b>( v[1].try_into().unwrap(), &ret_name, ) + .unwrap() .into() }, args, @@ -769,6 +790,7 @@ fn build_instruction<'a, 'b>( v[1].try_into().unwrap(), &ret_name, ) + .unwrap() .into() }, args, @@ -797,6 +819,7 @@ fn build_instruction<'a, 'b>( v[1].try_into().unwrap(), &ret_name, ) + .unwrap() .into() }, args, @@ -825,6 +848,7 @@ fn build_instruction<'a, 'b>( v[1].try_into().unwrap(), &ret_name, ) + .unwrap() .into() }, args, @@ -853,6 +877,7 @@ fn build_instruction<'a, 'b>( v[1].try_into().unwrap(), &ret_name, ) + .unwrap() .into() }, args, @@ -866,14 +891,16 @@ fn build_instruction<'a, 'b>( op: EffectOps::Return, } => { if args.is_empty() { - builder.build_return(None); + builder.build_return(None).unwrap(); } else { - builder.build_return(Some(&build_load( - context, - builder, - &heap.get(&args[0]), - &fresh.fresh_var(), - ))); + builder + .build_return(Some(&build_load( + context, + builder, + &heap.get(&args[0]), + &fresh.fresh_var(), + ))) + .unwrap(); } } Instruction::Effect { @@ -895,14 +922,16 @@ fn build_instruction<'a, 'b>( heap, fresh, |v| { - builder.build_call( - function, - v.iter() - .map(|val| (*val).into()) - .collect::>() - .as_slice(), - &ret_name, - ); + builder + .build_call( + function, + v.iter() + .map(|val| (*val).into()) + .collect::>() + .as_slice(), + &ret_name, + ) + .unwrap(); }, args, ); @@ -932,33 +961,40 @@ fn build_instruction<'a, 'b>( let v = build_load(context, builder, &wrapped_ptr, &fresh.fresh_var()); match wrapped_ptr.ty { Type::Int => { - builder.build_call(print_int, &[v.into()], "print_int"); + builder + .build_call(print_int, &[v.into()], "print_int") + .unwrap(); } Type::Bool => { - builder.build_call( - print_bool, - &[builder - .build_int_cast::( - v.try_into().unwrap(), - context.bool_type(), - "bool_cast", - ) - .into()], - "print_bool", - ); + builder + .build_call( + print_bool, + &[builder + .build_int_cast::( + v.try_into().unwrap(), + context.bool_type(), + "bool_cast", + ) + .unwrap() + .into()], + "print_bool", + ) + .unwrap(); } Type::Float => { - builder.build_call(print_float, &[v.into()], "print_float"); + builder + .build_call(print_float, &[v.into()], "print_float") + .unwrap(); } Type::Pointer(_) => { unreachable!() } }; if i < len - 1 { - builder.build_call(print_sep, &[], "print_sep"); + builder.build_call(print_sep, &[], "print_sep").unwrap(); } }); - builder.build_call(print_end, &[], "print_end"); + builder.build_call(print_end, &[], "print_end").unwrap(); } Instruction::Effect { args: _, @@ -966,9 +1002,11 @@ fn build_instruction<'a, 'b>( labels, op: EffectOps::Jump, } => { - builder.build_unconditional_branch(block_map_get( - context, llvm_func, block_map, &labels[0], - )); + builder + .build_unconditional_branch(block_map_get( + context, llvm_func, block_map, &labels[0], + )) + .unwrap(); } Instruction::Effect { args, @@ -984,11 +1022,9 @@ fn build_instruction<'a, 'b>( heap, fresh, |v| { - builder.build_conditional_branch( - v[0].try_into().unwrap(), - then_block, - else_block, - ); + builder + .build_conditional_branch(v[0].try_into().unwrap(), then_block, else_block) + .unwrap(); }, args, ); @@ -1007,10 +1043,18 @@ fn build_instruction<'a, 'b>( .map(|l| block_map_get(context, llvm_func, block_map, l)) .collect::>(); - let phi = builder.build_phi( - build_pointertype(context, &Type::Pointer(Box::new(op_type.clone()))), - &name, - ); + // Phi nodes must always go before all other instructions + // Note, this changes the order of user provided phi nodes + // If this bril code follows LLVM's phi node restrictions, then + // there should be no observable sideeffects + let current_block = builder.get_insert_block().unwrap(); + if let Some(instruction) = current_block.get_first_instruction() { + builder.position_before(&instruction); + } + + let phi = builder + .build_phi(context.ptr_type(AddressSpace::default()), &name) + .unwrap(); let pointers = args.iter().map(|a| heap.get(a).ptr).collect::>(); @@ -1024,18 +1068,24 @@ fn build_instruction<'a, 'b>( .as_slice(), ); - builder.build_store( - heap.get(dest).ptr, - build_load( - context, - builder, - &WrappedPointer { - ty: op_type.clone(), - ptr: phi.as_basic_value().into_pointer_value(), - }, - &fresh.fresh_var(), - ), - ); + // Because we set the position to the start of the block, we should + // reset it afterwards + builder.position_at_end(current_block); + + builder + .build_store( + heap.get(dest).ptr, + build_load( + context, + builder, + &WrappedPointer { + ty: op_type.clone(), + ptr: phi.as_basic_value().into_pointer_value(), + }, + &fresh.fresh_var(), + ), + ) + .unwrap(); } Instruction::Value { args, @@ -1079,7 +1129,11 @@ fn build_instruction<'a, 'b>( builder, heap, fresh, - |v| builder.build_load(pointee_ty, v[0].try_into().unwrap(), &name), + |v| { + builder + .build_load(pointee_ty, v[0].try_into().unwrap(), &name) + .unwrap() + }, args, dest, ); @@ -1109,6 +1163,7 @@ fn build_instruction<'a, 'b>( &[v[1].try_into().unwrap()], &name, ) + .unwrap() .into() }) }, @@ -1128,7 +1183,7 @@ fn build_instruction<'a, 'b>( heap, fresh, |v| { - builder.build_store(v[0].try_into().unwrap(), v[1]); + builder.build_store(v[0].try_into().unwrap(), v[1]).unwrap(); }, args, ); @@ -1145,7 +1200,7 @@ fn build_instruction<'a, 'b>( heap, fresh, |v| { - builder.build_free(v[0].try_into().unwrap()); + builder.build_free(v[0].try_into().unwrap()).unwrap(); }, args, ); @@ -1224,7 +1279,7 @@ pub fn create_module_from_program<'a>( llvm_func.get_param_iter().enumerate().for_each(|(i, arg)| { let Argument { name, arg_type } = &args[i]; let ptr = heap.add(&builder, context, name, arg_type).ptr; - builder.build_store(ptr, arg); + builder.build_store(ptr, arg).unwrap(); }); instrs.iter().for_each(|i| match i { @@ -1262,12 +1317,14 @@ pub fn create_module_from_program<'a>( // Check if wee need to insert a jump since all llvm blocks must be terminated if !is_terminating_instr(&last_instr) { - builder.build_unconditional_branch(block_map_get( - context, - llvm_func, - &mut block_map, - label, - )); + builder + .build_unconditional_branch(block_map_get( + context, + llvm_func, + &mut block_map, + label, + )) + .unwrap(); } // Start a new block @@ -1297,7 +1354,7 @@ pub fn create_module_from_program<'a>( // Make sure every function is terminated with a return if not already if !is_terminating_instr(&last_instr) { - builder.build_return(None); + builder.build_return(None).unwrap(); } }); @@ -1307,11 +1364,7 @@ pub fn create_module_from_program<'a>( let entry_func_type = context.i32_type().fn_type( &[ context.i32_type().into(), - context - .i8_type() - .ptr_type(AddressSpace::default()) - .ptr_type(AddressSpace::default()) - .into(), + context.ptr_type(AddressSpace::default()).into(), ], false, ); @@ -1339,37 +1392,40 @@ pub fn create_module_from_program<'a>( function.get_param_iter().enumerate().for_each(|(i, _)| { let Argument { name, arg_type } = &args[i]; let ptr = heap.add(&builder, context, name, arg_type).ptr; - let arg_str = builder.build_load( - context.i8_type().ptr_type(AddressSpace::default()), - unsafe { - builder.build_in_bounds_gep( - context - .i8_type() - .ptr_type(AddressSpace::default()) - .ptr_type(AddressSpace::default()), - argv, - &[context.i64_type().const_int((i + 1) as u64, true)], - "calculate offset", - ) - }, - "load arg", - ); + let arg_str = builder + .build_load( + context.ptr_type(AddressSpace::default()), + unsafe { + builder.build_in_bounds_gep( + context.ptr_type(AddressSpace::default()), + argv, + &[context.i64_type().const_int((i + 1) as u64, true)], + "calculate offset", + ) + } + .unwrap(), + "load arg", + ) + .unwrap(); let arg = match arg_type { Type::Int => builder .build_call(parse_int, &[arg_str.into()], "parse_int") + .unwrap() .try_as_basic_value() .unwrap_left(), Type::Bool => builder .build_call(parse_bool, &[arg_str.into()], "parse_bool") + .unwrap() .try_as_basic_value() .unwrap_left(), Type::Float => builder .build_call(parse_float, &[arg_str.into()], "parse_float") + .unwrap() .try_as_basic_value() .unwrap_left(), Type::Pointer(_) => unreachable!(), }; - builder.build_store(ptr, arg); + builder.build_store(ptr, arg).unwrap(); }); build_effect_op( @@ -1378,14 +1434,16 @@ pub fn create_module_from_program<'a>( &heap, &mut fresh, |v| { - builder.build_call( - function, - v.iter() - .map(|val| (*val).into()) - .collect::>() - .as_slice(), - "call main", - ); + builder + .build_call( + function, + v.iter() + .map(|val| (*val).into()) + .collect::>() + .as_slice(), + "call main", + ) + .unwrap(); }, &args .iter() @@ -1393,7 +1451,9 @@ pub fn create_module_from_program<'a>( .collect::>(), ); } - builder.build_return(Some(&context.i32_type().const_int(0, true))); + builder + .build_return(Some(&context.i32_type().const_int(0, true))) + .unwrap(); // Return the module runtime_module diff --git a/test/interp/ssa/ssa-two-phi.bril b/test/interp/ssa/ssa-two-phi.bril new file mode 100644 index 000000000..126595086 --- /dev/null +++ b/test/interp/ssa/ssa-two-phi.bril @@ -0,0 +1,13 @@ +# ARGS: true +@main(cond: bool) { +.top: + a: int = const 5; + br cond .here .there; +.here: + b: int = const 7; +.there: + c: int = phi a .top b .here; + d: int = phi a .top b .here; + print c; + print d; +} diff --git a/test/interp/ssa/ssa-two-phi.out b/test/interp/ssa/ssa-two-phi.out new file mode 100644 index 000000000..49019db80 --- /dev/null +++ b/test/interp/ssa/ssa-two-phi.out @@ -0,0 +1,2 @@ +7 +7