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

Modal harmony #148

Merged
merged 45 commits into from
Apr 19, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
45 commits
Select commit Hold shift + click to select a range
23c593b
comment the reasoning about sharing
nikomatsakis Feb 13, 2022
0c894ab
change how graphviz renders things
nikomatsakis Feb 13, 2022
275c2c7
introduce a `take_object` helper method
nikomatsakis Feb 13, 2022
c497b4b
wip: debug when temporaries are created
nikomatsakis Feb 20, 2022
181014d
extract helper fn for reporting expired place
nikomatsakis Feb 20, 2022
6a09eb3
check value returned is valid before storing it
nikomatsakis Feb 20, 2022
ff94a61
remove intermediate temporary for x = y
nikomatsakis Feb 20, 2022
c508302
remove intermediate temporaries for call arguments
nikomatsakis Feb 20, 2022
11c03e9
sharing a fully owned thing now *invalidates*
nikomatsakis Feb 13, 2022
593efd5
use SpannedWord more often to carry spans
nikomatsakis Feb 14, 2022
bc78d82
thread specifier information through the code
nikomatsakis Feb 14, 2022
3951b1a
rename storage_mode -> storage
nikomatsakis Feb 14, 2022
4f6555b
thread specifiers through validated, bir
nikomatsakis Feb 14, 2022
fec4030
rename "give share" back to "share"
nikomatsakis Feb 14, 2022
a09bc5a
rename Assign
nikomatsakis Feb 14, 2022
dc6c629
rename Assign to AssignExpr
nikomatsakis Feb 14, 2022
ab2bfb5
implement assignment from place to place
nikomatsakis Feb 15, 2022
c600db5
factor out a helper function
nikomatsakis Feb 15, 2022
778a23b
prepare arguments for parameter storage specifiers
nikomatsakis Feb 15, 2022
99954d8
introduce AssignFromPlace
nikomatsakis Feb 15, 2022
5d434d9
leases act as either reads or writes, depending
nikomatsakis Feb 16, 2022
ad477fa
break out `stringify_object` helper fn
nikomatsakis Feb 17, 2022
98ee437
introduce reservations into the machine
nikomatsakis Feb 17, 2022
318769c
add the ability to reserve a place
nikomatsakis Feb 17, 2022
87cb8f1
introduce reserve validated expression
nikomatsakis Feb 18, 2022
0844c66
reserve paths given to a fn call, paths for tuples
nikomatsakis Feb 21, 2022
e05bd71
rework target-places and assignments
nikomatsakis Feb 22, 2022
8016442
take specifiers into account when validating
nikomatsakis Feb 23, 2022
08e0042
take specifiers into account when validating
nikomatsakis Feb 23, 2022
bf05087
test field specifiers
nikomatsakis Feb 23, 2022
5ab9446
improve debug printouts
nikomatsakis Feb 27, 2022
225af9a
add comment
nikomatsakis Feb 27, 2022
f71d2ec
share an expr, not place; impl `our leased` mode
nikomatsakis Feb 27, 2022
68773ed
useful debug printouts
nikomatsakis Feb 27, 2022
c6409e5
confirm reservation for our leased; add test
nikomatsakis Feb 27, 2022
b45c41e
generate AssignPlace for `x := <place>` expr
nikomatsakis Feb 27, 2022
d732574
rework how we lower assignments
nikomatsakis Mar 1, 2022
2d5d296
make leasing a shared value => clone
nikomatsakis Mar 1, 2022
04b7fbf
fix `+=` desugaring to lease lhs
nikomatsakis Mar 2, 2022
f457e74
enforce that we use Assign just for temporaries
nikomatsakis Mar 2, 2022
7d2f774
enforce specifiers match what is required
nikomatsakis Mar 3, 2022
009447b
improve error messages for specifiers
nikomatsakis Mar 3, 2022
ed6a896
change default from `any` to `our leased`
nikomatsakis Mar 4, 2022
8079764
add tests w/ current temporary lifetime behavior
nikomatsakis Mar 4, 2022
44adcbd
fix ref files
nikomatsakis Apr 19, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
100 changes: 84 additions & 16 deletions components/dada-brew/src/brew.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use dada_ir::{
bir::{self, BirData},
validated::{self, ExprOrigin},
},
storage_mode::Atomic,
storage::Atomic,
};
use salsa::DebugWithDb;

Expand Down Expand Up @@ -85,7 +85,7 @@ impl Cursor {
validated::ExprData::Continue(from_expr) => {
self.push_breakpoint_start(brewery, origin);
let loop_context = brewery.loop_context(*from_expr);
self.push_breakpoint_end(brewery, None, origin);
self.push_breakpoint_end(brewery, None::<bir::Place>, origin);
self.terminate_and_goto(brewery, loop_context.continue_block, origin);
}

Expand All @@ -103,22 +103,49 @@ impl Cursor {

validated::ExprData::Error => {
self.push_breakpoint_start(brewery, origin);
self.push_breakpoint_end(brewery, None, origin);
self.push_breakpoint_end(brewery, None::<bir::Place>, origin);
self.terminate_and_diverge(brewery, bir::TerminatorData::Error, origin)
}

validated::ExprData::Assign(place, value_expr) => {
validated::ExprData::AssignTemporary(place, value_expr) => {
// temporaries are always created with "any" specifier, which ensures
// that we will never have to apply specifier to `value_expr`
assert_eq!(brewery.validated_tables()[*place].specifier, None);

// we only ever use this for temporaries, user-created values use `AssignFromPlace`
assert!(matches!(
brewery.origin(*place),
validated::LocalVariableOrigin::Temporary(_)
));

self.push_breakpoint_start(brewery, origin);
let (place, origins) = self.brew_place(brewery, *place);
let place = self.brew_target_variable(brewery, *place, origin);
self.brew_expr_and_assign_to(brewery, place, *value_expr);
self.push_breakpoint_ends(brewery, None, origins, origin)
self.push_breakpoint_end(brewery, None::<bir::Place>, origin)
}

validated::ExprData::AssignFromPlace(target_place, source_place) => {
let (target_place, target_origins) = self.brew_target_place(brewery, *target_place);
let (source_place, source_origins) = self.brew_place(brewery, *source_place);
self.push_breakpoint_starts(
brewery,
target_origins.iter().chain(source_origins.iter()).copied(),
origin,
);
self.push_assignment_from_place(brewery, target_place, source_place, origin);
self.push_breakpoint_ends(
brewery,
None::<bir::Place>,
target_origins.into_iter().chain(source_origins),
origin,
)
}

validated::ExprData::Declare(vars, subexpr) => {
self.push_breakpoint_start(brewery, origin);
self.brew_expr_for_side_effects(brewery, *subexpr);
self.pop_declared_variables(brewery, vars, origin);
self.push_breakpoint_end(brewery, None, origin);
self.push_breakpoint_end(brewery, None::<bir::Place>, origin);
}

validated::ExprData::Await(_)
Expand All @@ -134,6 +161,7 @@ impl Cursor {
| validated::ExprData::FloatLiteral(_)
| validated::ExprData::StringLiteral(_)
| validated::ExprData::Call(_, _)
| validated::ExprData::Reserve(_)
| validated::ExprData::Share(_)
| validated::ExprData::Lease(_)
| validated::ExprData::Give(_)
Expand All @@ -145,6 +173,8 @@ impl Cursor {
self.pop_temporary_scope(brewery, temporary_scope);
}

/// Compiles expr into a temporary `t` and returns `Some(t)`.
/// Returns `None` if this is dead code.
pub(crate) fn brew_expr_to_temporary(
&mut self,
brewery: &mut Brewery<'_>,
Expand All @@ -154,7 +184,7 @@ impl Cursor {
// Spill into a temporary
let temp_place = add_temporary_place(brewery, origin);
self.brew_expr_and_assign_to(brewery, temp_place, expr);
Some(temp_place)
Some(brewery.place_from_target_place(temp_place))
}

/// Compiles an expression down to the value it produces.
Expand All @@ -164,7 +194,7 @@ impl Cursor {
pub(crate) fn brew_expr_and_assign_to(
&mut self,
brewery: &mut Brewery<'_>,
target: bir::Place,
target: bir::TargetPlace,
expr: validated::Expr,
) {
let origin = brewery.origin(expr);
Expand Down Expand Up @@ -238,10 +268,18 @@ impl Cursor {
);
}

validated::ExprData::Share(place) => {
validated::ExprData::Share(operand) => {
if let Some(temp) = self.brew_expr_to_temporary(brewery, *operand) {
self.push_breakpoint_start(brewery, origin);
self.push_assignment(brewery, target, bir::ExprData::Share(temp), origin);
self.push_breakpoint_end(brewery, Some(target), origin);
}
}

validated::ExprData::Reserve(place) => {
let (place, origins) = self.brew_place(brewery, *place);
self.push_breakpoint_starts(brewery, origins.iter().copied(), origin);
self.push_assignment(brewery, target, bir::ExprData::GiveShare(place), origin);
self.push_assignment(brewery, target, bir::ExprData::Reserve(place), origin);
self.push_breakpoint_ends(brewery, Some(target), origins, origin);
}

Expand Down Expand Up @@ -375,8 +413,7 @@ impl Cursor {
}
}

validated::ExprData::Assign(_, _) => {
self.push_breakpoint_start(brewery, origin);
validated::ExprData::AssignTemporary(..) | validated::ExprData::AssignFromPlace(..) => {
self.brew_expr_for_side_effects(brewery, expr);
self.push_assignment(brewery, target, bir::ExprData::Unit, origin);
}
Expand Down Expand Up @@ -429,7 +466,7 @@ impl Cursor {
self.push_breakpoint_start(brewery, origin);
self.brew_expr_and_assign_to(brewery, target, *subexpr);
self.pop_declared_variables(brewery, vars, origin);
self.push_breakpoint_end(brewery, None, origin);
self.push_breakpoint_end(brewery, None::<bir::Place>, origin);
}

validated::ExprData::Error
Expand Down Expand Up @@ -485,21 +522,52 @@ impl Cursor {
}
}
}

pub(crate) fn brew_target_place(
&mut self,
brewery: &mut Brewery<'_>,
place: validated::TargetPlace,
) -> (bir::TargetPlace, Vec<ExprOrigin>) {
let origin = brewery.origin(place);
match brewery.validated_tables()[place] {
validated::TargetPlaceData::LocalVariable(validated_var) => {
let place = self.brew_target_variable(brewery, validated_var, origin);
(place, vec![origin])
}
validated::TargetPlaceData::Dot(base, field) => {
let (base, mut origins) = self.brew_place(brewery, base);
let place = brewery.add(bir::TargetPlaceData::Dot(base, field), origin);
origins.push(origin);
(place, origins)
}
}
}
pub(crate) fn brew_target_variable(
&mut self,
brewery: &mut Brewery<'_>,
validated_var: validated::LocalVariable,
origin: ExprOrigin,
) -> bir::TargetPlace {
let bir_var = brewery.variable(validated_var);
brewery.add(bir::TargetPlaceData::LocalVariable(bir_var), origin)
}
}

fn add_temporary(brewery: &mut Brewery, origin: ExprOrigin) -> bir::LocalVariable {
let temporary = brewery.add(
bir::LocalVariableData {
name: None,
specifier: None,
atomic: Atomic::No,
},
validated::LocalVariableOrigin::Temporary(origin.into()),
);
tracing::debug!("created temporary: temp{{{:?}}}", u32::from(temporary));
brewery.push_temporary(temporary);
temporary
}

fn add_temporary_place(brewery: &mut Brewery, origin: ExprOrigin) -> bir::Place {
fn add_temporary_place(brewery: &mut Brewery, origin: ExprOrigin) -> bir::TargetPlace {
let temporary_var = add_temporary(brewery, origin);
brewery.add(bir::PlaceData::LocalVariable(temporary_var), origin)
brewery.add(bir::TargetPlaceData::LocalVariable(temporary_var), origin)
}
18 changes: 16 additions & 2 deletions components/dada-brew/src/brewery.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ use dada_ir::{
pub struct Brewery<'me> {
db: &'me dyn crate::Db,
code: Code,
breakpoints: &'me [syntax::Expr],
pub(crate) breakpoints: &'me [syntax::Expr],
validated_tree_data: &'me validated::TreeData,
validated_origins: &'me validated::Origins,
tables: &'me mut bir::Tables,
Expand Down Expand Up @@ -43,7 +43,7 @@ pub struct Brewery<'me> {
pub struct LoopContext {
pub continue_block: bir::BasicBlock,
pub break_block: bir::BasicBlock,
pub loop_value: bir::Place,
pub loop_value: bir::TargetPlace,
}

impl<'me> Brewery<'me> {
Expand Down Expand Up @@ -154,6 +154,18 @@ impl<'me> Brewery<'me> {
add(self.tables, self.origins, data, origin)
}

/// Converts a target-place into a place.
pub fn place_from_target_place(&mut self, place: bir::TargetPlace) -> bir::Place {
match self.tables[place] {
bir::TargetPlaceData::LocalVariable(lv) => {
self.add(bir::PlaceData::LocalVariable(lv), self.origins[place])
}
bir::TargetPlaceData::Dot(owner_place, name) => {
self.add(bir::PlaceData::Dot(owner_place, name), self.origins[place])
}
}
}

/// Find the loop context for a given loop expression.
///
/// Panics if that loop context has not been pushed.
Expand Down Expand Up @@ -185,6 +197,7 @@ impl<'me> Brewery<'me> {
///
/// See the comments on the `temporaries` field for more information.
pub fn push_temporary(&mut self, lv: bir::LocalVariable) {
tracing::debug!("pushing temporary: {:?}", lv);
self.temporaries.push(lv);
}

Expand Down Expand Up @@ -217,6 +230,7 @@ fn map_variables(
origins,
bir::LocalVariableData {
name: validated_var_data.name,
specifier: validated_var_data.specifier,
atomic: validated_var_data.atomic,
},
validated_var_origin,
Expand Down
44 changes: 40 additions & 4 deletions components/dada-brew/src/cursor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -140,13 +140,26 @@ impl Cursor {
pub(crate) fn push_assignment(
&mut self,
brewery: &mut Brewery<'_>,
target: bir::Place,
target: bir::TargetPlace,
value: bir::ExprData,
origin: ExprOrigin,
) {
if self.end_block.is_some() {
let value = brewery.add(value, origin);
let statement = brewery.add(bir::StatementData::Assign(target, value), origin);
let statement = brewery.add(bir::StatementData::AssignExpr(target, value), origin);
self.push_statement(brewery, statement);
}
}

pub(crate) fn push_assignment_from_place(
&mut self,
brewery: &mut Brewery<'_>,
target: bir::TargetPlace,
source: bir::Place,
origin: ExprOrigin,
) {
if self.end_block.is_some() {
let statement = brewery.add(bir::StatementData::AssignPlace(target, source), origin);
self.push_statement(brewery, statement);
}
}
Expand All @@ -167,6 +180,11 @@ impl Cursor {
/// If `origin` is a breakpoint expression, push a "breakpoint-start"
/// statement onto the current basic block.
pub(crate) fn push_breakpoint_start(&mut self, brewery: &mut Brewery<'_>, origin: ExprOrigin) {
tracing::debug!(
"push_breakpoint_start: origin={:?} breakpoints={:?}",
origin,
brewery.breakpoints
);
if !origin.synthesized && self.end_block.is_some() {
if let Some(breakpoint_index) = brewery.expr_is_breakpoint(origin.syntax_expr) {
let filename = brewery.code().filename(brewery.db());
Expand All @@ -186,10 +204,11 @@ impl Cursor {
pub(crate) fn push_breakpoint_ends(
&mut self,
brewery: &mut Brewery<'_>,
place: Option<bir::Place>,
place: Option<impl AnyPlace>,
origins: impl IntoIterator<Item = ExprOrigin>,
origin: ExprOrigin,
) {
let place = place.map(|p| p.into_place(brewery));
for o in origins.into_iter().chain(Some(origin)) {
self.push_breakpoint_end_with_distinct_origin(brewery, origin.syntax_expr, place, o);
}
Expand All @@ -200,9 +219,10 @@ impl Cursor {
pub(crate) fn push_breakpoint_end(
&mut self,
brewery: &mut Brewery<'_>,
place: Option<bir::Place>,
place: Option<impl AnyPlace>,
origin: ExprOrigin,
) {
let place = place.map(|p| p.into_place(brewery));
self.push_breakpoint_end_with_distinct_origin(brewery, origin.syntax_expr, place, origin);
}

Expand Down Expand Up @@ -245,3 +265,19 @@ impl Cursor {
Some((place, *name))
}
}

pub(crate) trait AnyPlace {
fn into_place(self, brewery: &mut Brewery<'_>) -> bir::Place;
}

impl AnyPlace for bir::Place {
fn into_place(self, _brewery: &mut Brewery<'_>) -> bir::Place {
self
}
}

impl AnyPlace for bir::TargetPlace {
fn into_place(self, brewery: &mut Brewery<'_>) -> bir::Place {
brewery.place_from_target_place(self)
}
}
2 changes: 1 addition & 1 deletion components/dada-db/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ impl Db {
for item in filename.items(self) {
if let Item::Function(function) = item {
let function_name = function.name(self);
if name == function_name {
if name == function_name.word(self) {
return Some(*function);
}
}
Expand Down
Loading