Skip to content
Open
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
10 changes: 10 additions & 0 deletions libs/@local/hashql/mir/src/body/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,16 @@ pub enum Source<'heap> {
/// The body of an intrinsic function is typically empty, as the intrinsic
/// operation is handled directly by the compiler or runtime.
Intrinsic(DefId),

/// A filter closure for graph read operations.
///
/// This variant represents MIR generated from a closure expression used to
/// filter entities during a graph read operation. The [`HirId`] identifies
/// the filter closure expression in the HIR.
///
/// Filter bodies are never inlined and are executed during graph traversal
/// to determine which entities should be included in the read results.
GraphReadFilter(HirId),
}

/// The MIR body of a HashQL function or query.
Expand Down
13 changes: 0 additions & 13 deletions libs/@local/hashql/mir/src/pass/analysis/callgraph/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -182,19 +182,6 @@ impl<A: Allocator> CallGraph<'_, A> {
})
}

#[inline]
pub fn filters(&self) -> impl Iterator<Item = DefId> {
self.inner
.nodes()
.ids()
.filter(|&node| {
self.inner
.incoming_edges(node)
.any(|edge| matches!(edge.data, CallKind::Filter(_)))
})
.map(|node| DefId::new(node.as_u32()))
}

#[inline]
pub fn is_leaf(&self, def: DefId) -> bool {
let def = NodeId::new(def.as_usize());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -274,7 +274,7 @@ impl<'ctx, 'heap, A: Allocator> BodyAnalysis<'ctx, 'heap, A> {
let inline = match body.source {
Source::Ctor(_) => InlineDirective::Always,
Source::Closure(_, _) | Source::Thunk(_, _) => InlineDirective::Heuristic,
Source::Intrinsic(_) => InlineDirective::Never,
Source::Intrinsic(_) | Source::GraphReadFilter(_) => InlineDirective::Never,
};

// Detect loops using SCC analysis on the CFG.
Expand Down
8 changes: 5 additions & 3 deletions libs/@local/hashql/mir/src/pass/transform/inline/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ use self::{
};
use crate::{
body::{
Body,
Body, Source,
basic_block::{BasicBlock, BasicBlockId},
local::{Local, LocalDecl},
location::Location,
Expand Down Expand Up @@ -523,8 +523,10 @@ impl<A: BumpAllocator> Inline<A> {
}

let mut filters = DenseBitSet::new_empty(bodies.len());
for filter in graph.filters() {
filters.insert(filter);
for body in bodies {
if matches!(body.source, Source::GraphReadFilter(_)) {
filters.insert(body.id);
}
}

let costs = analysis.finish();
Expand Down
6 changes: 5 additions & 1 deletion libs/@local/hashql/mir/src/pretty/text.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,10 @@ use crate::{
const fn source_keyword(source: Source<'_>) -> &'static str {
match source {
Source::Thunk(..) => "thunk",
Source::Ctor(_) | Source::Closure(..) | Source::Intrinsic(_) => "fn",
Source::Ctor(_)
| Source::Closure(..)
| Source::GraphReadFilter(..)
| Source::Intrinsic(_) => "fn",
}
}

Expand Down Expand Up @@ -272,6 +275,7 @@ where
write!(self.writer, "{{ctor#{symbol}}}")
}
Source::Closure(id, binder) => named_symbol("closure", id, binder),
Source::GraphReadFilter(id) => named_symbol("graph::read::filter", id, None),
Source::Thunk(id, binder) => named_symbol("thunk", id, binder),
Source::Intrinsic(def_id) => {
write!(self.writer, "{{intrinsic#{def_id}}}")
Expand Down
11 changes: 7 additions & 4 deletions libs/@local/hashql/mir/src/reify/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -183,9 +183,12 @@ impl<'ctx, 'mir, 'hir, 'env, 'heap> Reifier<'ctx, 'mir, 'hir, 'env, 'heap> {
// In the future we might want to specialize `ctor` in a way that allows us to move them to
// be thin calls (although that would require that we move functions into a separate type
// from closures).
let env = if matches!(source, Source::Closure(_, _) | Source::Ctor(_)) {
let env = if matches!(
source,
Source::Closure(_, _) | Source::Ctor(_) | Source::GraphReadFilter(_)
) {
let r#type = if let Some((_, type_id)) = captures {
debug_assert_matches!(source, Source::Closure(..));
debug_assert_matches!(source, Source::Closure(..) | Source::GraphReadFilter(..));
type_id
} else {
// In case there are no captures, the environment will always be a unit type (aka
Expand Down Expand Up @@ -289,16 +292,16 @@ impl<'ctx, 'mir, 'hir, 'env, 'heap> Reifier<'ctx, 'mir, 'hir, 'env, 'heap> {
fn lower_closure(
self,
hir: HirPtr,
source: Source<'heap>,
captures: &MixedBitSet<VarId>,
env_type: TypeId,
binder: Option<Binder<'heap>>,
closure: Closure<'heap>,
closure_type: ClosureType<'heap>,
) -> DefId {
debug_assert_eq!(closure_type.params.len(), closure.signature.params.len());

self.lower_impl(
Source::Closure(hir.id, binder),
source,
hir.span,
closure
.signature
Expand Down
3 changes: 2 additions & 1 deletion libs/@local/hashql/mir/src/reify/rvalue.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ use super::{
};
use crate::{
body::{
Source,
constant::Constant,
local::Local,
operand::Operand,
Expand Down Expand Up @@ -291,7 +292,7 @@ impl<'mir, 'heap> Reifier<'_, 'mir, '_, '_, 'heap> {
r#type: _,
value: env,
},
) = self.transform_closure(block, hir, Some(binder), closure);
) = self.transform_closure(block, hir, Source::Closure(hir.id, Some(binder)), closure);

// We first need to figure out the environment that we need to capture, these are variables
// that are referenced out of scope (upvars).
Expand Down
8 changes: 7 additions & 1 deletion libs/@local/hashql/mir/src/reify/terminator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ use super::{
};
use crate::{
body::{
Source,
basic_block::BasicBlockId,
local::Local,
terminator::{
Expand Down Expand Up @@ -56,7 +57,12 @@ impl<'mir, 'heap> Reifier<'_, 'mir, '_, '_, 'heap> {
return GraphReadBody::Filter(DefId::MAX, Local::MAX);
};

let (ptr, env) = self.transform_closure(block, filter.ptr(), None, closure);
let (ptr, env) = self.transform_closure(
block,
filter.ptr(),
Source::GraphReadFilter(filter.ptr().id),
closure,
);
GraphReadBody::Filter(ptr.value, env.value)
}
}
Expand Down
7 changes: 4 additions & 3 deletions libs/@local/hashql/mir/src/reify/transform.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,15 @@ use hashql_hir::{
HirPtr, Node,
closure::Closure,
kind::NodeKind,
r#let::{Binder, Binding, Let},
r#let::{Binding, Let},
},
visit::Visitor as _,
};

use super::{Reifier, current::CurrentBlock, error::local_variable_unmapped, unwrap_closure_type};
use crate::{
body::{
Source,
local::{Local, LocalDecl},
operand::Operand,
place::Place,
Expand All @@ -32,7 +33,7 @@ impl<'mir, 'heap> Reifier<'_, 'mir, '_, '_, 'heap> {
&mut self,
block: &mut CurrentBlock<'mir, 'heap>,
hir: HirPtr,
binder: Option<Binder<'heap>>,
source: Source<'heap>,
closure: Closure<'heap>,
) -> (Typed<DefId>, Typed<Local>) {
let mut dependencies = VariableDependencies::from_set(self.state.var_pool.acquire());
Expand Down Expand Up @@ -80,7 +81,7 @@ impl<'mir, 'heap> Reifier<'_, 'mir, '_, '_, 'heap> {
let closure_type_id = self.context.hir.map.monomorphized_type_id(hir.id);
let closure_type = unwrap_closure_type(closure_type_id, self.context.mir.env);
let compiler = Reifier::new(self.context, self.state);
let ptr = compiler.lower_closure(hir, &captures, env_type, binder, closure, closure_type);
let ptr = compiler.lower_closure(hir, source, &captures, env_type, closure, closure_type);

block.push_statement(Statement {
span: hir.span,
Expand Down

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

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

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

4 changes: 2 additions & 2 deletions libs/@local/hashql/mir/tests/ui/reify/graph-read.stdout

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

Loading