Skip to content
This repository was archived by the owner on Mar 5, 2025. It is now read-only.

Commit b5fc455

Browse files
committed
feat!: Namer optionally appends node index to mangled names.
1 parent 6effd7c commit b5fc455

File tree

7 files changed

+165
-125
lines changed

7 files changed

+165
-125
lines changed

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,14 @@ hugr = "0.5.1"
1616
anyhow = "1.0.83"
1717
itertools = "0.12.1"
1818
delegate = "0.12.0"
19-
petgraph = "*"
20-
lazy_static = "*"
19+
petgraph = "0.6.5"
20+
lazy_static = "1.4.0"
2121
downcast-rs= "1.2.1"
2222

2323
[dev-dependencies]
2424
insta = "1.39.0"
2525
rstest = "0.19.0"
26+
portgraph = "0.12.1"
2627

2728
[profile.dev.package]
2829
insta.opt-level = 3

src/emit.rs

Lines changed: 18 additions & 107 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,13 @@ use delegate::delegate;
33
use hugr::{
44
ops::{FuncDecl, FuncDefn, NamedOp as _, OpType},
55
types::PolyFuncType,
6-
HugrView, Node, NodeIndex,
6+
HugrView, Node,
77
};
88
use inkwell::{
99
context::Context,
1010
module::{Linkage, Module},
1111
types::{BasicTypeEnum, FunctionType},
12-
values::{BasicValueEnum, FunctionValue},
12+
values::FunctionValue,
1313
};
1414
use std::{collections::HashSet, hash::Hash, rc::Rc};
1515

@@ -21,72 +21,15 @@ use crate::{
2121
types::{LLVMSumType, TypeConverter},
2222
};
2323

24-
use self::func::{EmitFuncContext, RowPromise};
24+
use self::func::EmitFuncContext;
2525

26+
pub mod args;
2627
pub mod func;
28+
pub mod namer;
2729
mod ops;
2830

29-
/// A type used whenever emission is delegated to a function
30-
pub struct EmitOpArgs<'c, OT, H> {
31-
/// This [HugrView] and [Node] we are emitting
32-
pub node: FatNode<'c, OT, H>,
33-
/// The values that should be used for all Value input ports of the node
34-
pub inputs: Vec<BasicValueEnum<'c>>,
35-
/// The results of the node should be put here
36-
pub outputs: RowPromise<'c>,
37-
}
38-
39-
impl<'c, OT, H> EmitOpArgs<'c, OT, H> {
40-
/// Get the internal [FatNode]
41-
pub fn node(&self) -> FatNode<'c, OT, H> {
42-
self.node.clone()
43-
}
44-
}
45-
46-
impl<'c, H: HugrView> EmitOpArgs<'c, OpType, H> {
47-
/// Attempt to specialise the internal [FatNode].
48-
pub fn try_into_ot<OT: 'c>(self) -> Result<EmitOpArgs<'c, OT, H>, Self>
49-
where
50-
&'c OpType: TryInto<&'c OT>,
51-
{
52-
let EmitOpArgs {
53-
node,
54-
inputs,
55-
outputs,
56-
} = self;
57-
match node.try_into_ot() {
58-
Some(new_node) => Ok(EmitOpArgs {
59-
node: new_node,
60-
inputs,
61-
outputs,
62-
}),
63-
None => Err(EmitOpArgs {
64-
node,
65-
inputs,
66-
outputs,
67-
}),
68-
}
69-
}
70-
71-
/// Specialise the internal [FatNode].
72-
///
73-
/// Panics if `OT` is not the `get_optype` of the internal [Node].
74-
pub fn into_ot<'b, OTInto: PartialEq + 'c>(self, ot: &'b OTInto) -> EmitOpArgs<'c, OTInto, H>
75-
where
76-
for<'a> &'a OpType: TryInto<&'a OTInto>,
77-
{
78-
let EmitOpArgs {
79-
node,
80-
inputs,
81-
outputs,
82-
} = self;
83-
EmitOpArgs {
84-
node: node.into_ot(ot),
85-
inputs,
86-
outputs,
87-
}
88-
}
89-
}
31+
pub use args::EmitOpArgs;
32+
pub use namer::Namer;
9033

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

114-
/// A type with features for mangling the naming of symbols.
115-
///
116-
/// TODO This is mostly a placeholder
117-
#[derive(Clone)]
118-
pub struct Namer {
119-
prefix: String,
120-
}
121-
122-
impl Namer {
123-
/// Create a new `Namer` that for each symbol:
124-
/// * prefix `prefix`
125-
/// * postfixes ".{node.index()}"
126-
pub fn new(prefix: impl Into<String>) -> Self {
127-
Self {
128-
prefix: prefix.into(),
129-
}
130-
}
131-
132-
/// Mangle the the name of a [FuncDefn] or [FuncDecl].
133-
pub fn name_func(&self, name: impl AsRef<str>, node: Node) -> String {
134-
format!("{}{}.{}", &self.prefix, name.as_ref(), node.index())
135-
}
136-
}
137-
138-
impl Default for Namer {
139-
fn default() -> Self {
140-
Self::new("_hl.")
141-
}
142-
}
143-
14457
pub struct EmitModuleContext<'c, H: HugrView> {
14558
module: Module<'c>,
146-
extension_context: Rc<CodegenExtsMap<'c, H>>,
59+
extensions: Rc<CodegenExtsMap<'c, H>>,
14760
typer: Rc<TypeConverter<'c>>,
14861
namer: Rc<Namer>,
14962
}
@@ -174,13 +87,13 @@ impl<'c, H: HugrView> EmitModuleContext<'c, H> {
17487
pub fn new(
17588
module: Module<'c>,
17689
namer: Rc<Namer>,
177-
extension_context: Rc<CodegenExtsMap<'c, H>>,
90+
extensions: Rc<CodegenExtsMap<'c, H>>,
17891
typer: Rc<TypeConverter<'c>>,
17992
) -> Self {
18093
Self {
18194
module,
18295
namer,
183-
extension_context,
96+
extensions,
18497
typer,
18598
}
18699
}
@@ -194,7 +107,7 @@ impl<'c, H: HugrView> EmitModuleContext<'c, H> {
194107

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

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

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

349260
/// Creates a new `EmitHugr`. We take ownership of the [Module], and return it in [Self::finish].
350261
pub fn new(
351-
iw_context: &'c Context,
262+
context: &'c Context,
352263
module: Module<'c>,
353-
exts: Rc<CodegenExtsMap<'c, H>>,
264+
namer: Rc<Namer>,
265+
extensions: Rc<CodegenExtsMap<'c, H>>,
354266
) -> Self {
355-
assert_eq!(iw_context, &module.get_context());
267+
assert_eq!(context, &module.get_context());
356268
Self {
357-
// todos: Default::default(),
358269
emitted: Default::default(),
359270
module_context: EmitModuleContext::new(
360271
module,
361-
Default::default(),
362-
exts,
363-
TypeConverter::new(iw_context),
272+
namer,
273+
extensions,
274+
TypeConverter::new(context),
364275
),
365276
}
366277
}

src/emit/args.rs

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
use hugr::{ops::OpType, HugrView};
2+
use inkwell::values::BasicValueEnum;
3+
4+
use crate::fat::FatNode;
5+
6+
use super::func::RowPromise;
7+
8+
/// A type used whenever emission is delegated to a function, for example in
9+
/// [crate::emit::EmitOp].
10+
pub struct EmitOpArgs<'c, OT, H> {
11+
/// This [HugrView] and [Node] we are emitting
12+
pub node: FatNode<'c, OT, H>,
13+
/// The values that should be used for all Value input ports of the node
14+
pub inputs: Vec<BasicValueEnum<'c>>,
15+
/// The results of the node should be put here
16+
pub outputs: RowPromise<'c>,
17+
}
18+
19+
impl<'c, OT, H> EmitOpArgs<'c, OT, H> {
20+
/// Get the internal [FatNode]
21+
pub fn node(&self) -> FatNode<'c, OT, H> {
22+
self.node.clone()
23+
}
24+
}
25+
26+
impl<'c, H: HugrView> EmitOpArgs<'c, OpType, H> {
27+
/// Attempt to specialise the internal [FatNode].
28+
pub fn try_into_ot<OT: 'c>(self) -> Result<EmitOpArgs<'c, OT, H>, Self>
29+
where
30+
&'c OpType: TryInto<&'c OT>,
31+
{
32+
let EmitOpArgs {
33+
node,
34+
inputs,
35+
outputs,
36+
} = self;
37+
match node.try_into_ot() {
38+
Some(new_node) => Ok(EmitOpArgs {
39+
node: new_node,
40+
inputs,
41+
outputs,
42+
}),
43+
None => Err(EmitOpArgs {
44+
node,
45+
inputs,
46+
outputs,
47+
}),
48+
}
49+
}
50+
51+
/// Specialise the internal [FatNode].
52+
///
53+
/// Panics if `OT` is not the `get_optype` of the internal [Node].
54+
pub fn into_ot<OTInto: PartialEq + 'c>(self, ot: &OTInto) -> EmitOpArgs<'c, OTInto, H>
55+
where
56+
for<'a> &'a OpType: TryInto<&'a OTInto>,
57+
{
58+
let EmitOpArgs {
59+
node,
60+
inputs,
61+
outputs,
62+
} = self;
63+
EmitOpArgs {
64+
node: node.into_ot(ot),
65+
inputs,
66+
outputs,
67+
}
68+
}
69+
}

src/emit/namer.rs

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
use hugr::{Node, NodeIndex as _};
2+
3+
/// A type with features for mangling the naming of symbols.
4+
#[derive(Clone)]
5+
pub struct Namer {
6+
prefix: String,
7+
postfix_node: bool,
8+
}
9+
10+
impl Namer {
11+
/// The [Default] impl of `Namer` uses this as a prefix.
12+
pub const DEFAULT_PREFIX: &'static str = "_hl.";
13+
14+
/// Create a new `Namer` that for each symbol:
15+
/// * prefixes `prefix`
16+
/// * if post_fix_node is true, postfixes ".{node.index()}"
17+
///
18+
/// # Example
19+
///
20+
/// ```
21+
/// use hugr_llvm::emit::Namer;
22+
/// use hugr::Node;
23+
/// let node = Node::from(portgraph::NodeIndex::new(7));
24+
/// let namer = Namer::default();
25+
/// assert_eq!(namer.name_func("name", node), "_hl.name.7");
26+
///
27+
/// let namer = Namer::new("prefix.", false);
28+
/// assert_eq!(namer.name_func("name", node), "prefix.name")
29+
/// ```
30+
pub fn new(prefix: impl Into<String>, postfix_node: bool) -> Self {
31+
Self {
32+
prefix: prefix.into(),
33+
postfix_node,
34+
}
35+
}
36+
37+
/// Mangle the the name of a [FuncDefn] or [FuncDecl].
38+
pub fn name_func(&self, name: impl AsRef<str>, node: Node) -> String {
39+
let prefix = &self.prefix;
40+
let name = name.as_ref();
41+
let postfix = if self.postfix_node {
42+
format!(".{}", node.index())
43+
} else {
44+
String::new()
45+
};
46+
format!("{prefix}{name}{postfix}")
47+
}
48+
}
49+
50+
impl Default for Namer {
51+
fn default() -> Self {
52+
Self::new(Self::DEFAULT_PREFIX, true)
53+
}
54+
}

0 commit comments

Comments
 (0)