Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

alloca access #1957

Draft
wants to merge 4 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 4 additions & 8 deletions hugr-llvm/src/emit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -333,15 +333,11 @@ impl<'c, 'a, H: HugrView<Node = Node>> EmitHugr<'c, 'a, H> {
}
let func = self.module_context.get_func_defn(node)?;
let mut func_ctx = EmitFuncContext::new(self.module_context, func)?;
let params_rmb = func_ctx.new_row_mail_box(node.signature.body().input.iter(), "params")?;
params_rmb.write(func_ctx.builder(), func.get_params())?;
let ret_rmb = func_ctx.new_row_mail_box(node.signature.body().output.iter(), "ret")?;
ops::emit_dataflow_parent(
&mut func_ctx,
EmitOpArgs {
node,
inputs: func.get_params(),
outputs: ret_rmb.promise(),
},
)?;
let args = EmitOpArgs::try_new(func_ctx.builder(), node, params_rmb, ret_rmb.promise())?;
self::ops::emit_dataflow_parent(&mut func_ctx, args)?;
let builder = func_ctx.builder();
match &ret_rmb.read::<Vec<_>>(builder, [])?[..] {
[] => builder.build_return(None)?,
Expand Down
40 changes: 37 additions & 3 deletions hugr-llvm/src/emit/args.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
use anyhow::Result;
use hugr_core::{ops::OpType, HugrView, Node};
use inkwell::values::BasicValueEnum;
use inkwell::{
builder::Builder,
values::{BasicValueEnum, PointerValue},
};

use crate::utils::fat::FatNode;

use super::func::RowPromise;
use super::func::{RowMailBox, RowPromise};

/// A type used whenever emission is delegated to a function, for example in
/// [crate::custom::extension_op::ExtensionOpMap::emit_extension_op].
Expand All @@ -14,13 +18,38 @@ pub struct EmitOpArgs<'c, 'hugr, OT, H> {
pub inputs: Vec<BasicValueEnum<'c>>,
/// The results of the node should be put here
pub outputs: RowPromise<'c>,

input_mailbox: RowMailBox<'c>,
}

impl<'hugr, OT, H> EmitOpArgs<'_, 'hugr, OT, H> {
impl<'c, 'hugr, OT, H> EmitOpArgs<'c, 'hugr, OT, H> {
pub fn try_new(
builder: &Builder<'c>,
node: FatNode<'hugr, OT, H>,
input_mailbox: RowMailBox<'c>,
outputs: RowPromise<'c>,
) -> Result<Self> {
let inputs = input_mailbox.read_vec(builder, [])?;
Ok(Self {
node,
inputs,
outputs,
input_mailbox,
})
}

/// Get the internal [FatNode]
pub fn node(&self) -> FatNode<'hugr, OT, H> {
self.node
}

pub fn input_alloca(&self, i: usize) -> PointerValue<'c> {
self.input_mailbox[i].alloca()
}

pub fn output_alloca(&self, i: usize) -> PointerValue<'c> {
self.outputs[i].alloca()
}
}

impl<'c, 'hugr, H: HugrView<Node = Node>> EmitOpArgs<'c, 'hugr, OpType, H> {
Expand All @@ -33,17 +62,20 @@ impl<'c, 'hugr, H: HugrView<Node = Node>> EmitOpArgs<'c, 'hugr, OpType, H> {
node,
inputs,
outputs,
input_mailbox,
} = self;
match node.try_into_ot() {
Some(new_node) => Ok(EmitOpArgs {
node: new_node,
inputs,
outputs,
input_mailbox,
}),
None => Err(EmitOpArgs {
node,
inputs,
outputs,
input_mailbox,
}),
}
}
Expand All @@ -60,11 +92,13 @@ impl<'c, 'hugr, H: HugrView<Node = Node>> EmitOpArgs<'c, 'hugr, OpType, H> {
node,
inputs,
outputs,
input_mailbox,
} = self;
EmitOpArgs {
node: node.into_ot(ot),
inputs,
outputs,
input_mailbox,
}
}
}
2 changes: 1 addition & 1 deletion hugr-llvm/src/emit/func.rs
Original file line number Diff line number Diff line change
Expand Up @@ -196,7 +196,7 @@ impl<'c, 'a, H: HugrView<Node = Node>> EmitFuncContext<'c, 'a, H> {
))
}

fn build_prologue<T>(&mut self, f: impl FnOnce(&Builder<'c>) -> T) -> T {
pub(crate) fn build_prologue<T>(&mut self, f: impl FnOnce(&Builder<'c>) -> T) -> T {
let b = self.prologue_block();
self.build_positioned(b, |x| f(&x.builder))
}
Expand Down
22 changes: 21 additions & 1 deletion hugr-llvm/src/emit/func/mailbox.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use std::{borrow::Cow, rc::Rc};
use std::{borrow::Cow, ops, rc::Rc};

use anyhow::{bail, Result};
use delegate::delegate;
Expand Down Expand Up @@ -48,6 +48,10 @@ impl<'c> ValueMailBox<'c> {
ValuePromise(self.clone())
}

pub fn alloca(&self) -> PointerValue<'c> {
self.ptr
}

pub fn read<'a>(
&'a self,
builder: &Builder<'c>,
Expand Down Expand Up @@ -175,6 +179,14 @@ impl<'c> FromIterator<ValueMailBox<'c>> for RowMailBox<'c> {
}
}

impl<'c> ops::Index<usize> for RowMailBox<'c> {
type Output = ValueMailBox<'c>;

fn index(&self, index: usize) -> &Self::Output {
&self.0[index]
}
}

/// A promise to write values into a `RowMailBox`
#[must_use]
#[allow(clippy::len_without_is_empty)]
Expand All @@ -199,3 +211,11 @@ impl<'c> RowPromise<'c> {
}
}
}

impl<'c> ops::Index<usize> for RowPromise<'c> {
type Output = ValueMailBox<'c>;

fn index(&self, index: usize) -> &Self::Output {
&self.0[index]
}
}
64 changes: 26 additions & 38 deletions hugr-llvm/src/emit/ops.rs
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ where
.map(|x| node.hugr().fat_optype(x))
.try_for_each(|node| {
let inputs_rmb = context.node_ins_rmb(node)?;
let inputs = inputs_rmb.read(context.builder(), [])?;
let inputs = inputs_rmb.read_vec(context.builder(), [])?;
let outputs = context.node_outs_rmb(node)?.promise();
match node.as_ref() {
OpType::Input(_) => {
Expand All @@ -89,14 +89,11 @@ where
let o = self.take_output()?;
o.finish(context.builder(), inputs)
}
_ => emit_optype(
context,
EmitOpArgs {
node,
inputs,
outputs,
},
),
_ => {
let args =
EmitOpArgs::try_new(context.builder(), node, inputs_rmb, outputs)?;
emit_optype(context, args)
}
}
})
}
Expand Down Expand Up @@ -166,21 +163,21 @@ fn emit_tag<'c, H: HugrView<Node = Node>>(

fn emit_conditional<'c, H: HugrView<Node = Node>>(
context: &mut EmitFuncContext<'c, '_, H>,
EmitOpArgs {
node,
inputs,
outputs,
}: EmitOpArgs<'c, '_, Conditional, H>,
args: EmitOpArgs<'c, '_, Conditional, H>,
) -> Result<()> {
let exit_rmb =
context.new_row_mail_box(node.dataflow_signature().unwrap().output.iter(), "exit_rmb")?;
let node = args.node();
let exit_rmb = context.new_row_mail_box(
args.node().dataflow_signature().unwrap().output.iter(),
"exit_rmb",
)?;
let exit_block = context.build_positioned_new_block(
format!("cond_exit_{}", node.node().index()),
None,
|context, bb| {
let builder = context.builder();
outputs.finish(builder, exit_rmb.read_vec(builder, [])?)?;
Ok::<_, anyhow::Error>(bb)
args.outputs
.finish(builder, exit_rmb.read_vec(builder, [])?)?;
anyhow::Ok(bb)
},
)?;

Expand All @@ -192,27 +189,21 @@ fn emit_conditional<'c, H: HugrView<Node = Node>>(
let node = n.try_into_ot::<Case>().ok_or(anyhow!("not a case node"))?;
let rmb = context.new_row_mail_box(node.get_io().unwrap().0.types.iter(), &label)?;
context.build_positioned_new_block(&label, Some(exit_block), |context, bb| {
let inputs = rmb.read_vec(context.builder(), [])?;
emit_dataflow_parent(
context,
EmitOpArgs {
node,
inputs,
outputs: exit_rmb.promise(),
},
)?;
let args =
EmitOpArgs::try_new(context.builder(), n, rmb.clone(), exit_rmb.promise())?;
emit_dataflow_parent(context, args)?;
context.builder().build_unconditional_branch(exit_block)?;
Ok((rmb, bb))
})
})
.collect::<Result<Vec<_>>>()?;

let sum_type = get_exactly_one_sum_type(node.in_value_types().next().map(|x| x.1))?;
let sum_input = LLVMSumValue::try_new(inputs[0], context.llvm_sum_type(sum_type)?)?;
let sum_input = LLVMSumValue::try_new(args.inputs[0], context.llvm_sum_type(sum_type)?)?;
let builder = context.builder();
sum_input.build_destructure(builder, |builder, tag, mut vs| {
let (rmb, bb) = &rmbs_blocks[tag];
vs.extend(&inputs[1..]);
vs.extend(&args.inputs[1..]);
rmb.write(builder, vs)?;
builder.build_unconditional_branch(*bb)?;
Ok(())
Expand Down Expand Up @@ -330,15 +321,13 @@ fn emit_tail_loop<'c, H: HugrView<Node = Node>>(
};

context.build_positioned(body_bb, move |context| {
let inputs = body_i_rmb.read_vec(context.builder(), [])?;
emit_dataflow_parent(
context,
EmitOpArgs {
node,
inputs,
outputs: body_o_rmb.promise(),
},
let body_args = EmitOpArgs::try_new(
context.builder(),
node,
body_i_rmb.clone(),
body_o_rmb.promise(),
)?;
emit_dataflow_parent(context, body_args)?;
let dataflow_outputs = body_o_rmb.read_vec(context.builder(), [])?;
let control_val = LLVMSumValue::try_new(dataflow_outputs[0], control_llvm_sum_type)?;
let mut outputs = Some(args.outputs);
Expand Down Expand Up @@ -367,7 +356,6 @@ fn emit_optype<'c, H: HugrView<Node = Node>>(
match node.as_ref() {
OpType::Tag(ref tag) => emit_tag(context, args.into_ot(tag)),
OpType::DFG(_) => emit_dataflow_parent(context, args),

OpType::ExtensionOp(ref co) => context.emit_extension_op(args.into_ot(co)),
OpType::LoadConstant(ref lc) => emit_load_constant(context, args.into_ot(lc)),
OpType::Call(ref cl) => emit_call(context, args.into_ot(cl)),
Expand Down
46 changes: 22 additions & 24 deletions hugr-llvm/src/emit/ops/cfg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -107,23 +107,25 @@ impl<'c, 'hugr, H: HugrView<Node = Node>> CfgEmitter<'c, 'hugr, H> {

// emit each child by delegating to the `impl EmitOp<_>` of self.
for child_node in self.node.children() {
let (inputs, outputs) = (vec![], RowMailBox::new_empty().promise());
let (inputs, outputs) = (RowMailBox::new_empty(), RowMailBox::new_empty().promise());
match child_node.as_ref() {
OpType::DataflowBlock(ref dfb) => self.emit_dataflow_block(
context,
EmitOpArgs {
node: child_node.into_ot(dfb),
EmitOpArgs::try_new(
context.builder(),
child_node.into_ot(dfb),
inputs,
outputs,
},
)?,
),
OpType::ExitBlock(ref eb) => self.emit_exit_block(
context,
EmitOpArgs {
node: child_node.into_ot(eb),
EmitOpArgs::try_new(
context.builder(),
child_node.into_ot(eb),
inputs,
outputs,
},
)?,
),

// Const is allowed, but requires no work here. FuncDecl is
Expand All @@ -147,36 +149,32 @@ impl<'c, 'hugr, H: HugrView<Node = Node>> CfgEmitter<'c, 'hugr, H> {
fn emit_dataflow_block(
&mut self,
context: &mut EmitFuncContext<'c, '_, H>,
EmitOpArgs {
node,
inputs: _,
outputs: _,
}: EmitOpArgs<'c, 'hugr, DataflowBlock, H>,
args: EmitOpArgs<'c, 'hugr, DataflowBlock, H>,
) -> Result<()> {
let node = args.node();

// our entry basic block and our input RowMailBox
let (bb, inputs_rmb) = self.get_block_data(&node)?;
let (bb, inputs_rmb) = self.get_block_data(&args.node())?;
// the basic block and mailbox of each of our successors
let successor_data = node
let successor_data = args
.node()
.output_neighbours()
.map(|succ| self.get_block_data(&succ))
.collect::<Result<Vec<_>>>()?;

context.build_positioned(bb, |context| {
let (_, o) = node.get_io().unwrap();
let (_, o) = args.node().get_io().unwrap();
// get the rowmailbox for our output node
let outputs_rmb = context.node_ins_rmb(o)?;
// read the values from our input node
let inputs = inputs_rmb.read_vec(context.builder(), [])?;

// emit all our children and read the values from the rowmailbox of our output node
emit_dataflow_parent(
context,
EmitOpArgs {
node,
inputs,
outputs: outputs_rmb.promise(),
},
let args = EmitOpArgs::try_new(
context.builder(),
args.node,
inputs_rmb,
outputs_rmb.promise(),
)?;
emit_dataflow_parent(context, args)?;
let outputs = outputs_rmb.read_vec(context.builder(), [])?;

// We create a helper block per-tag. We switch to the helper block,
Expand Down
Loading
Loading