Compare commits

..

11 Commits

Author SHA1 Message Date
David Mak 4481d48709 core: Use C-style for loop logic for iterables
Index increment is now performed at the end of the loop body.
2023-09-06 20:09:38 +08:00
David Mak b4983526bd core: Remove redundant for.cond BB for iterable loops
Simplifies logic for creating basic blocks.
2023-09-06 20:09:37 +08:00
David Mak b4a9616648 core: Add assertion for when `range` has step of 0
Aligns with the behavior in Python.
2023-09-06 20:09:36 +08:00
David Mak e0de82993f core: Preserve value of variable shadowed by for loop
Previously, the final value of the target expression would be one after
the last element of the loop, which does not match Python's behavior.

This commit fixes this problem while also preserving the last assigned
value of the loop beyond the loop, matching Python's behavior.
2023-09-06 20:09:36 +08:00
David Mak 6805253515 core: Use AST var name for IR name
Aids debugging IR.
2023-09-06 20:09:36 +08:00
David Mak 19915bac79 core: Prepend statement type to basic block label names
Aids debugging IR.
2023-09-06 20:09:36 +08:00
David Mak 17b4686260 standalone: Adapt loop example to output loop variable 2023-09-06 18:56:45 +08:00
David Mak 6de0884dc1 core: Use anonymous name for variables if unspecified
The current default prefix is only derived from the instruction type,
which is not helpful during the comprehension of the IR. Changing to
anonymous names (e.g. %1) helps understand that the variable is only
needed as part of a larger (possibly named) expression.
2023-09-06 14:02:15 +08:00
David Mak f1b0e05b3d core: Rename IR variables
Because it is unclear which variables are expressions and
subexpressions, all variables which are previously anonymous are named
using (1) the control flow statement if available, (2) the possible name
of the variable as inferred from the variable name in Rust, and (3) the
"addr" prefix to indicate that the values are pointers. These three
strings are joint together using '.', forming "for.i.addr" for instance.
2023-09-06 14:02:15 +08:00
David Mak ff23968544 core: Add name parameter to gen_{var_alloc,store_target}
This allows variables in the IR to be assigned a custom name as opposed
to names with a default prefix.
2023-09-06 11:00:02 +08:00
Sebastien Bourdeauducq 049908044a flake: update dependencies 2023-09-04 11:00:15 +08:00
5 changed files with 29 additions and 51 deletions

View File

@ -2,11 +2,11 @@
"nodes": {
"nixpkgs": {
"locked": {
"lastModified": 1688868408,
"narHash": "sha256-RR9N5XTAxSBhK8MCvLq9uxfdkd7etC//seVXldy0k48=",
"lastModified": 1693636127,
"narHash": "sha256-ZlS/lFGzK7BJXX2YVGnP3yZi3T9OLOEtBCyMJsb91U8=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "510d721ce097150ae3b80f84b04b13b039186571",
"rev": "9075cba53e86dc318d159aee55dc9a7c9a4829c1",
"type": "github"
},
"original": {

View File

@ -84,7 +84,7 @@ impl<'b> CodeGenerator for ArtiqCodeGenerator<'b> {
.try_as_basic_value()
.left()
.unwrap();
let end_store = self.gen_store_target(ctx, &end)?;
let end_store = self.gen_store_target(ctx, &end, Some("end_store.addr"))?;
ctx.builder.build_store(end_store, max);
}
if let Some(start) = self.start.clone() {
@ -140,7 +140,7 @@ impl<'b> CodeGenerator for ArtiqCodeGenerator<'b> {
node: ExprKind::Name { id: start, ctx: name_ctx.clone() },
custom: Some(ctx.primitives.int64),
};
let start = self.gen_store_target(ctx, &start_expr)?;
let start = self.gen_store_target(ctx, &start_expr, Some("start.addr"))?;
ctx.builder.build_store(start, now);
Ok(Some(start_expr)) as Result<_, String>
},
@ -153,7 +153,7 @@ impl<'b> CodeGenerator for ArtiqCodeGenerator<'b> {
node: ExprKind::Name { id: end, ctx: name_ctx.clone() },
custom: Some(ctx.primitives.int64),
};
let end = self.gen_store_target(ctx, &end_expr)?;
let end = self.gen_store_target(ctx, &end_expr, Some("end.addr"))?;
ctx.builder.build_store(end, now);
self.end = Some(end_expr);
self.name_counter += 1;
@ -204,7 +204,7 @@ impl<'b> CodeGenerator for ArtiqCodeGenerator<'b> {
.try_as_basic_value()
.left()
.unwrap();
let outer_end = self.gen_store_target(ctx, old_end)?;
let outer_end = self.gen_store_target(ctx, old_end, Some("outer_end.addr"))?;
ctx.builder.build_store(outer_end, max);
}
self.start = old_start;

View File

@ -810,7 +810,7 @@ pub fn gen_comprehension<'ctx, 'a, G: CodeGenerator>(
let zero_size_t = size_t.const_zero();
let zero_32 = int32.const_zero();
let index = generator.gen_var_alloc(ctx, size_t.into())?;
let index = generator.gen_var_alloc(ctx, size_t.into(), Some("index.addr"))?;
ctx.builder.build_store(index, zero_size_t);
let elem_ty = ctx.get_llvm_type(generator, elt.custom.unwrap());
@ -853,7 +853,7 @@ pub fn gen_comprehension<'ctx, 'a, G: CodeGenerator>(
list_content =
ctx.build_gep_and_load(list, &[zero_size_t, zero_32]).into_pointer_value();
let i = generator.gen_store_target(ctx, target)?;
let i = generator.gen_store_target(ctx, target, Some("i.addr"))?;
ctx.builder.build_store(i, ctx.builder.build_int_sub(start, step, "start_init"));
ctx.builder.build_unconditional_branch(test_bb);
ctx.builder.position_at_end(test_bb);
@ -888,7 +888,7 @@ pub fn gen_comprehension<'ctx, 'a, G: CodeGenerator>(
list = allocate_list(generator, ctx, elem_ty, length);
list_content =
ctx.build_gep_and_load(list, &[zero_size_t, zero_32]).into_pointer_value();
let counter = generator.gen_var_alloc(ctx, size_t.into())?;
let counter = generator.gen_var_alloc(ctx, size_t.into(), Some("counter.addr"))?;
// counter = -1
ctx.builder.build_store(counter, size_t.const_int(u64::max_value(), true));
ctx.builder.build_unconditional_branch(test_bb);

View File

@ -83,49 +83,26 @@ pub trait CodeGenerator {
/// Allocate memory for a variable and return a pointer pointing to it.
/// The default implementation places the allocations at the start of the function.
fn gen_var_alloc_named<'ctx, 'a>(
&mut self,
ctx: &mut CodeGenContext<'ctx, 'a>,
ty: BasicTypeEnum<'ctx>,
name: &str,
) -> Result<PointerValue<'ctx>, String> {
gen_var(ctx, ty, Some(name))
}
/// Similar to [gen_var_alloc_named], but provides a default name for the created pointer
/// variable.
fn gen_var_alloc<'ctx, 'a>(
&mut self,
ctx: &mut CodeGenContext<'ctx, 'a>,
ty: BasicTypeEnum<'ctx>,
name: Option<&str>,
) -> Result<PointerValue<'ctx>, String> {
gen_var(ctx, ty, None)
gen_var(ctx, ty, name)
}
/// Return a pointer pointing to the target of the expression.
fn gen_store_target_named<'ctx, 'a>(
&mut self,
ctx: &mut CodeGenContext<'ctx, 'a>,
pattern: &Expr<Option<Type>>,
name: &str,
) -> Result<PointerValue<'ctx>, String>
where
Self: Sized,
{
gen_store_target(self, ctx, pattern, Some(name))
}
/// Similar to [gen_store_target_named], but provides a default name for the created pointer
/// variable.
fn gen_store_target<'ctx, 'a>(
&mut self,
ctx: &mut CodeGenContext<'ctx, 'a>,
pattern: &Expr<Option<Type>>,
name: Option<&str>,
) -> Result<PointerValue<'ctx>, String>
where
Self: Sized,
where
Self: Sized,
{
gen_store_target(self, ctx, pattern, None)
gen_store_target(self, ctx, pattern, name)
}
/// Generate code for an assignment expression.

View File

@ -30,7 +30,7 @@ pub fn gen_var<'ctx, 'a>(
let current = ctx.builder.get_insert_block().unwrap();
// position before the last branching instruction...
ctx.builder.position_before(&ctx.init_bb.get_last_instruction().unwrap());
let ptr = ctx.builder.build_alloca(ty, name.unwrap_or("tmp"));
let ptr = ctx.builder.build_alloca(ty, name.unwrap_or(""));
ctx.builder.position_at_end(current);
Ok(ptr)
}
@ -47,7 +47,7 @@ pub fn gen_store_target<'ctx, 'a, G: CodeGenerator>(
ExprKind::Name { id, .. } => match ctx.var_assignment.get(id) {
None => {
let ptr_ty = ctx.get_llvm_type(generator, pattern.custom.unwrap());
let ptr = generator.gen_var_alloc_named(ctx, ptr_ty, name.unwrap_or("tmp"))?;
let ptr = generator.gen_var_alloc(ctx, ptr_ty, name)?;
ctx.var_assignment.insert(*id, (ptr, None, 0));
ptr
}
@ -76,7 +76,7 @@ pub fn gen_store_target<'ctx, 'a, G: CodeGenerator>(
ctx.ctx.i32_type().const_zero(),
ctx.ctx.i32_type().const_int(index as u64, false),
],
name.unwrap_or("attr"),
name.unwrap_or(""),
)
}
}
@ -137,7 +137,7 @@ pub fn gen_store_target<'ctx, 'a, G: CodeGenerator>(
let arr_ptr = ctx
.build_gep_and_load(v, &[i32_type.const_zero(), i32_type.const_zero()])
.into_pointer_value();
ctx.builder.build_gep(arr_ptr, &[index], name.unwrap_or("loadarrgep"))
ctx.builder.build_gep(arr_ptr, &[index], name.unwrap_or(""))
}
}
_ => unreachable!(),
@ -193,11 +193,12 @@ pub fn gen_assign<'ctx, 'a, G: CodeGenerator>(
}
}
_ => {
let ptr = if let ExprKind::Name { id, .. } = &target.node {
generator.gen_store_target_named(ctx, target, format!("{}.addr", id.to_string()).as_str())?
let name = if let ExprKind::Name { id, .. } = &target.node {
format!("{}.addr", id.to_string())
} else {
generator.gen_store_target(ctx, target)?
String::from("target.addr")
};
let ptr = generator.gen_store_target(ctx, target, Some(name.as_str()))?;
if let ExprKind::Name { id, .. } = &target.node {
let (_, static_value, counter) = ctx.var_assignment.get_mut(id).unwrap();
@ -274,9 +275,9 @@ pub fn gen_for<'ctx, 'a, G: CodeGenerator>(
if is_iterable_range_expr {
let iter_val = iter_val.into_pointer_value();
// Internal variable for loop; Cannot be assigned
let i = generator.gen_var_alloc_named(ctx, int32.into(), "for.i.addr")?;
let i = generator.gen_var_alloc(ctx, int32.into(), Some("for.i.addr"))?;
// Variable declared in "target" expression of the loop; Can be reassigned *or* shadowed
let target_i = generator.gen_store_target_named(ctx, target, "for.target.addr")?;
let target_i = generator.gen_store_target(ctx, target, Some("for.target.addr"))?;
let (start, stop, step) = destructure_range(ctx, iter_val);
ctx.builder.build_store(i, start);
@ -320,7 +321,7 @@ pub fn gen_for<'ctx, 'a, G: CodeGenerator>(
} else {
let test_bb = backedge_bb_target;
let index_addr = generator.gen_var_alloc_named(ctx, size_t.into(), "for.index.addr")?;
let index_addr = generator.gen_var_alloc(ctx, size_t.into(), Some("for.index.addr"))?;
ctx.builder.build_store(index_addr, size_t.const_zero());
let len = ctx
.build_gep_and_load(
@ -712,7 +713,7 @@ pub fn gen_try<'ctx, 'a, G: CodeGenerator>(
let mut final_data = None;
let has_cleanup = !finalbody.is_empty();
if has_cleanup {
let final_state = generator.gen_var_alloc(ctx, ptr_type.into())?;
let final_state = generator.gen_var_alloc(ctx, ptr_type.into(), Some("try.final_state.addr"))?;
final_data = Some((final_state, Vec::new(), Vec::new()));
if let Some((continue_target, break_target)) = ctx.loop_target {
let break_proxy = ctx.ctx.append_basic_block(current_fun, "try.break");
@ -878,7 +879,7 @@ pub fn gen_try<'ctx, 'a, G: CodeGenerator>(
ctx.builder.position_at_end(handler_bb);
if let Some(name) = name {
let exn_ty = ctx.get_llvm_type(generator, type_.as_ref().unwrap().custom.unwrap());
let exn_store = generator.gen_var_alloc(ctx, exn_ty)?;
let exn_store = generator.gen_var_alloc(ctx, exn_ty, Some("try.exn_store.addr"))?;
ctx.var_assignment.insert(*name, (exn_store, None, 0));
ctx.builder.build_store(exn_store, exn.as_basic_value());
}