Skip to content

Commit

Permalink
feat!: Namer optionally appends node index to mangled names.
Browse files Browse the repository at this point in the history
  • Loading branch information
doug-q committed Jun 18, 2024
1 parent 6effd7c commit b5fc455
Show file tree
Hide file tree
Showing 7 changed files with 165 additions and 125 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 3 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,14 @@ hugr = "0.5.1"
anyhow = "1.0.83"
itertools = "0.12.1"
delegate = "0.12.0"
petgraph = "*"
lazy_static = "*"
petgraph = "0.6.5"
lazy_static = "1.4.0"
downcast-rs= "1.2.1"

[dev-dependencies]
insta = "1.39.0"
rstest = "0.19.0"
portgraph = "0.12.1"

[profile.dev.package]
insta.opt-level = 3
Expand Down
125 changes: 18 additions & 107 deletions src/emit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,13 @@ use delegate::delegate;
use hugr::{
ops::{FuncDecl, FuncDefn, NamedOp as _, OpType},
types::PolyFuncType,
HugrView, Node, NodeIndex,
HugrView, Node,
};
use inkwell::{
context::Context,
module::{Linkage, Module},
types::{BasicTypeEnum, FunctionType},
values::{BasicValueEnum, FunctionValue},
values::FunctionValue,
};
use std::{collections::HashSet, hash::Hash, rc::Rc};

Expand All @@ -21,72 +21,15 @@ use crate::{
types::{LLVMSumType, TypeConverter},
};

use self::func::{EmitFuncContext, RowPromise};
use self::func::EmitFuncContext;

pub mod args;
pub mod func;
pub mod namer;
mod ops;

/// A type used whenever emission is delegated to a function
pub struct EmitOpArgs<'c, OT, H> {
/// This [HugrView] and [Node] we are emitting
pub node: FatNode<'c, OT, H>,
/// The values that should be used for all Value input ports of the node
pub inputs: Vec<BasicValueEnum<'c>>,
/// The results of the node should be put here
pub outputs: RowPromise<'c>,
}

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

impl<'c, H: HugrView> EmitOpArgs<'c, OpType, H> {
/// Attempt to specialise the internal [FatNode].
pub fn try_into_ot<OT: 'c>(self) -> Result<EmitOpArgs<'c, OT, H>, Self>
where
&'c OpType: TryInto<&'c OT>,
{
let EmitOpArgs {
node,
inputs,
outputs,
} = self;
match node.try_into_ot() {
Some(new_node) => Ok(EmitOpArgs {
node: new_node,
inputs,
outputs,
}),
None => Err(EmitOpArgs {
node,
inputs,
outputs,
}),
}
}

/// Specialise the internal [FatNode].
///
/// Panics if `OT` is not the `get_optype` of the internal [Node].
pub fn into_ot<'b, OTInto: PartialEq + 'c>(self, ot: &'b OTInto) -> EmitOpArgs<'c, OTInto, H>
where
for<'a> &'a OpType: TryInto<&'a OTInto>,
{
let EmitOpArgs {
node,
inputs,
outputs,
} = self;
EmitOpArgs {
node: node.into_ot(ot),
inputs,
outputs,
}
}
}
pub use args::EmitOpArgs;
pub use namer::Namer;

/// A trait used to abstract over emission.
///
Expand All @@ -111,39 +54,9 @@ impl<OT, H: HugrView> EmitOp<'_, OT, H> for NullEmitLlvm {
}
}

/// A type with features for mangling the naming of symbols.
///
/// TODO This is mostly a placeholder
#[derive(Clone)]
pub struct Namer {
prefix: String,
}

impl Namer {
/// Create a new `Namer` that for each symbol:
/// * prefix `prefix`
/// * postfixes ".{node.index()}"
pub fn new(prefix: impl Into<String>) -> Self {
Self {
prefix: prefix.into(),
}
}

/// Mangle the the name of a [FuncDefn] or [FuncDecl].
pub fn name_func(&self, name: impl AsRef<str>, node: Node) -> String {
format!("{}{}.{}", &self.prefix, name.as_ref(), node.index())
}
}

impl Default for Namer {
fn default() -> Self {
Self::new("_hl.")
}
}

pub struct EmitModuleContext<'c, H: HugrView> {
module: Module<'c>,
extension_context: Rc<CodegenExtsMap<'c, H>>,
extensions: Rc<CodegenExtsMap<'c, H>>,
typer: Rc<TypeConverter<'c>>,
namer: Rc<Namer>,
}
Expand Down Expand Up @@ -174,13 +87,13 @@ impl<'c, H: HugrView> EmitModuleContext<'c, H> {
pub fn new(
module: Module<'c>,
namer: Rc<Namer>,
extension_context: Rc<CodegenExtsMap<'c, H>>,
extensions: Rc<CodegenExtsMap<'c, H>>,
typer: Rc<TypeConverter<'c>>,
) -> Self {
Self {
module,
namer,
extension_context,
extensions,
typer,
}
}
Expand All @@ -194,7 +107,7 @@ impl<'c, H: HugrView> EmitModuleContext<'c, H> {

/// Returns a reference to the inner [CodegenExtsMap].
pub fn extensions(&self) -> Rc<CodegenExtsMap<'c, H>> {
self.extension_context.clone()
self.extensions.clone()
}

/// Returns a [TypingSession] constructed from it's members.
Expand Down Expand Up @@ -328,8 +241,6 @@ impl<'c, H> Clone for Emission<'c, H> {

/// Emits [HugrView]s into an LLVM [Module].
pub struct EmitHugr<'c, H: HugrView> {
// funcs: HashMap<Node, FunctionValue<'c>>,
// globals: HashMap<Node, GlobalValue<'c>>,
emitted: EmissionSet<'c, H>,
module_context: EmitModuleContext<'c, H>,
}
Expand All @@ -348,19 +259,19 @@ impl<'c, H: HugrView> EmitHugr<'c, H> {

/// Creates a new `EmitHugr`. We take ownership of the [Module], and return it in [Self::finish].
pub fn new(
iw_context: &'c Context,
context: &'c Context,
module: Module<'c>,
exts: Rc<CodegenExtsMap<'c, H>>,
namer: Rc<Namer>,
extensions: Rc<CodegenExtsMap<'c, H>>,
) -> Self {
assert_eq!(iw_context, &module.get_context());
assert_eq!(context, &module.get_context());
Self {
// todos: Default::default(),
emitted: Default::default(),
module_context: EmitModuleContext::new(
module,
Default::default(),
exts,
TypeConverter::new(iw_context),
namer,
extensions,
TypeConverter::new(context),
),
}
}
Expand Down
69 changes: 69 additions & 0 deletions src/emit/args.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
use hugr::{ops::OpType, HugrView};
use inkwell::values::BasicValueEnum;

use crate::fat::FatNode;

use super::func::RowPromise;

/// A type used whenever emission is delegated to a function, for example in
/// [crate::emit::EmitOp].
pub struct EmitOpArgs<'c, OT, H> {
/// This [HugrView] and [Node] we are emitting
pub node: FatNode<'c, OT, H>,
/// The values that should be used for all Value input ports of the node
pub inputs: Vec<BasicValueEnum<'c>>,
/// The results of the node should be put here
pub outputs: RowPromise<'c>,
}

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

impl<'c, H: HugrView> EmitOpArgs<'c, OpType, H> {
/// Attempt to specialise the internal [FatNode].
pub fn try_into_ot<OT: 'c>(self) -> Result<EmitOpArgs<'c, OT, H>, Self>
where
&'c OpType: TryInto<&'c OT>,
{
let EmitOpArgs {
node,
inputs,
outputs,
} = self;
match node.try_into_ot() {
Some(new_node) => Ok(EmitOpArgs {
node: new_node,
inputs,
outputs,
}),
None => Err(EmitOpArgs {
node,
inputs,
outputs,
}),
}
}

/// Specialise the internal [FatNode].
///
/// Panics if `OT` is not the `get_optype` of the internal [Node].
pub fn into_ot<OTInto: PartialEq + 'c>(self, ot: &OTInto) -> EmitOpArgs<'c, OTInto, H>
where
for<'a> &'a OpType: TryInto<&'a OTInto>,
{
let EmitOpArgs {
node,
inputs,
outputs,
} = self;
EmitOpArgs {
node: node.into_ot(ot),
inputs,
outputs,
}
}
}
54 changes: 54 additions & 0 deletions src/emit/namer.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
use hugr::{Node, NodeIndex as _};

/// A type with features for mangling the naming of symbols.
#[derive(Clone)]
pub struct Namer {
prefix: String,
postfix_node: bool,
}

impl Namer {
/// The [Default] impl of `Namer` uses this as a prefix.
pub const DEFAULT_PREFIX: &'static str = "_hl.";

/// Create a new `Namer` that for each symbol:
/// * prefixes `prefix`
/// * if post_fix_node is true, postfixes ".{node.index()}"
///
/// # Example
///
/// ```
/// use hugr_llvm::emit::Namer;
/// use hugr::Node;
/// let node = Node::from(portgraph::NodeIndex::new(7));
/// let namer = Namer::default();
/// assert_eq!(namer.name_func("name", node), "_hl.name.7");
///
/// let namer = Namer::new("prefix.", false);
/// assert_eq!(namer.name_func("name", node), "prefix.name")
/// ```
pub fn new(prefix: impl Into<String>, postfix_node: bool) -> Self {
Self {
prefix: prefix.into(),
postfix_node,
}
}

/// Mangle the the name of a [FuncDefn] or [FuncDecl].
pub fn name_func(&self, name: impl AsRef<str>, node: Node) -> String {
let prefix = &self.prefix;
let name = name.as_ref();
let postfix = if self.postfix_node {
format!(".{}", node.index())
} else {
String::new()
};
format!("{prefix}{name}{postfix}")
}
}

impl Default for Namer {
fn default() -> Self {
Self::new(Self::DEFAULT_PREFIX, true)
}
}
Loading

0 comments on commit b5fc455

Please sign in to comment.