diff --git a/hugr-llvm/src/extension/collections/array.rs b/hugr-llvm/src/extension/collections/array.rs index 39d721a29..0cf530e9f 100644 --- a/hugr-llvm/src/extension/collections/array.rs +++ b/hugr-llvm/src/extension/collections/array.rs @@ -18,6 +18,7 @@ use inkwell::values::{ use inkwell::IntPredicate; use itertools::Itertools; +use crate::emit::emit_value; use crate::{ emit::{deaggregate_call_result, EmitFuncContext, RowPromise}, sum::LLVMSumType, @@ -52,6 +53,15 @@ pub trait ArrayCodegen: Clone { elem_ty.array_type(size as u32) } + /// Emit a [hugr_core::std_extensions::collections::array::ArrayValue]. + fn emit_array_value<'c, H: HugrView>( + &self, + ctx: &mut EmitFuncContext<'c, '_, H>, + value: &array::ArrayValue, + ) -> Result> { + emit_array_value(self, ctx, value) + } + /// Emit a [hugr_core::std_extensions::collections::array::ArrayOp]. fn emit_array_op<'c, H: HugrView>( &self, @@ -129,6 +139,10 @@ impl CodegenExtension for ArrayCodegenExtension { Ok(ccg.array_type(&ts, elem_ty, *n).as_basic_type_enum()) } }) + .custom_const::({ + let ccg = self.0.clone(); + move |context, k| ccg.emit_array_value(context, k) + }) .simple_extension_op::({ let ccg = self.0.clone(); move |context, args, _| { @@ -244,6 +258,31 @@ fn build_loop<'c, T, H: HugrView>( Ok(val) } +pub fn emit_array_value<'c, H: HugrView>( + ccg: &impl ArrayCodegen, + ctx: &mut EmitFuncContext<'c, '_, H>, + value: &array::ArrayValue, +) -> Result> { + let ts = ctx.typing_session(); + let llvm_array_ty = ccg + .array_type( + &ts, + ts.llvm_type(value.get_element_type())?, + value.get_contents().len() as u64, + ) + .as_basic_type_enum() + .into_array_type(); + let mut array_v = llvm_array_ty.get_undef(); + for (i, v) in value.get_contents().iter().enumerate() { + let llvm_v = emit_value(ctx, v)?; + array_v = ctx + .builder() + .build_insert_value(array_v, llvm_v, i as u32, "")? + .into_array_value(); + } + Ok(array_v.into()) +} + pub fn emit_array_op<'c, H: HugrView>( ccg: &impl ArrayCodegen, ctx: &mut EmitFuncContext<'c, '_, H>, @@ -739,6 +778,23 @@ mod test { check_emission!(hugr, llvm_ctx); } + #[rstest] + fn emit_array_value(mut llvm_ctx: TestContext) { + let hugr = SimpleHugrConfig::new() + .with_extensions(STD_REG.to_owned()) + .with_outs(vec![array_type(2, usize_t())]) + .finish(|mut builder| { + let vs = vec![ConstUsize::new(1).into(), ConstUsize::new(2).into()]; + let arr = builder.add_load_value(array::ArrayValue::new(usize_t(), vs)); + builder.finish_with_outputs([arr]).unwrap() + }); + llvm_ctx.add_extensions(|cge| { + cge.add_default_prelude_extensions() + .add_default_array_extensions() + }); + check_emission!(hugr, llvm_ctx); + } + fn exec_registry() -> ExtensionRegistry { ExtensionRegistry::new([ int_types::EXTENSION.to_owned(), diff --git a/hugr-llvm/src/extension/collections/snapshots/hugr_llvm__extension__collections__array__test__emit_array_value@llvm14.snap b/hugr-llvm/src/extension/collections/snapshots/hugr_llvm__extension__collections__array__test__emit_array_value@llvm14.snap new file mode 100644 index 000000000..3a718f7f2 --- /dev/null +++ b/hugr-llvm/src/extension/collections/snapshots/hugr_llvm__extension__collections__array__test__emit_array_value@llvm14.snap @@ -0,0 +1,14 @@ +--- +source: hugr-llvm/src/extension/collections/array.rs +expression: mod_str +--- +; ModuleID = 'test_context' +source_filename = "test_context" + +define [2 x i64] @_hl.main.1() { +alloca_block: + br label %entry_block + +entry_block: ; preds = %alloca_block + ret [2 x i64] [i64 1, i64 2] +} diff --git a/hugr-llvm/src/extension/collections/snapshots/hugr_llvm__extension__collections__array__test__emit_array_value@pre-mem2reg@llvm14.snap b/hugr-llvm/src/extension/collections/snapshots/hugr_llvm__extension__collections__array__test__emit_array_value@pre-mem2reg@llvm14.snap new file mode 100644 index 000000000..5befaf3df --- /dev/null +++ b/hugr-llvm/src/extension/collections/snapshots/hugr_llvm__extension__collections__array__test__emit_array_value@pre-mem2reg@llvm14.snap @@ -0,0 +1,20 @@ +--- +source: hugr-llvm/src/extension/collections/array.rs +expression: mod_str +--- +; ModuleID = 'test_context' +source_filename = "test_context" + +define [2 x i64] @_hl.main.1() { +alloca_block: + %"0" = alloca [2 x i64], align 8 + %"5_0" = alloca [2 x i64], align 8 + br label %entry_block + +entry_block: ; preds = %alloca_block + store [2 x i64] [i64 1, i64 2], [2 x i64]* %"5_0", align 4 + %"5_01" = load [2 x i64], [2 x i64]* %"5_0", align 4 + store [2 x i64] %"5_01", [2 x i64]* %"0", align 4 + %"02" = load [2 x i64], [2 x i64]* %"0", align 4 + ret [2 x i64] %"02" +}