From 21516c587ac1bc8f4f70be6a5decbcb31b432510 Mon Sep 17 00:00:00 2001 From: David Mak Date: Mon, 23 Oct 2023 10:22:03 +0800 Subject: [PATCH 1/5] cargo: Update dependencies --- Cargo.lock | 33 +++++++++++++++++++++++++++------ 1 file changed, 27 insertions(+), 6 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 028486a..5936512 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4,9 +4,9 @@ version = 3 [[package]] name = "ahash" -version = "0.7.6" +version = "0.7.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fcb51a0695d8f838b1ee009b3fbf66bda078cd64590202a864a8f3e8c4315c47" +checksum = "5a824f2aa7e75a0c98c5a504fceb80649e9c35265d44525b5f94de4771a395cd" dependencies = [ "getrandom", "once_cell", @@ -15,14 +15,15 @@ dependencies = [ [[package]] name = "ahash" -version = "0.8.3" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c99f64d1e06488f620f932677e24bc6e2897582980441ae90a671415bd7ec2f" +checksum = "cd7d5a2cecb58716e47d67d5703a249964b14c7be1ec3cad3affc295b2d1c35d" dependencies = [ "cfg-if", "getrandom", "once_cell", "version_check", + "zerocopy", ] [[package]] @@ -387,7 +388,7 @@ version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e" dependencies = [ - "ahash 0.7.6", + "ahash 0.7.7", ] [[package]] @@ -674,7 +675,7 @@ dependencies = [ name = "nac3parser" version = "0.1.2" dependencies = [ - "ahash 0.8.3", + "ahash 0.8.5", "insta", "lalrpop", "lalrpop-util", @@ -1547,3 +1548,23 @@ checksum = "56c1936c4cc7a1c9ab21a1ebb602eb942ba868cbd44a99cb7cdc5892335e1c85" dependencies = [ "linked-hash-map", ] + +[[package]] +name = "zerocopy" +version = "0.7.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c19fae0c8a9efc6a8281f2e623db8af1db9e57852e04cde3e754dd2dc29340f" +dependencies = [ + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.7.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc56589e9ddd1f1c28d4b4b5c773ce232910a6bb67a70133d61c9e347585efe9" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.38", +] -- 2.44.1 From 6d746626c28350a5a3caa3218c63d593b77cf6a7 Mon Sep 17 00:00:00 2001 From: David Mak Date: Thu, 19 Oct 2023 11:54:56 +0800 Subject: [PATCH 2/5] artiq: Use gen_block when generating "with sequential" --- nac3artiq/src/codegen.rs | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/nac3artiq/src/codegen.rs b/nac3artiq/src/codegen.rs index 1128643..939ea1c 100644 --- a/nac3artiq/src/codegen.rs +++ b/nac3artiq/src/codegen.rs @@ -215,12 +215,7 @@ impl<'b> CodeGenerator for ArtiqCodeGenerator<'b> { return Ok(()); } else if id == &"sequential".into() { let start = self.start.take(); - for stmt in body.iter() { - self.gen_stmt(ctx, stmt)?; - if ctx.is_terminated() { - break; - } - } + gen_block(self, ctx, body.iter())?; self.start = start; return Ok(()); } -- 2.44.1 From be6bd9e604fd73076667bc6c9580b5de5f61e21c Mon Sep 17 00:00:00 2001 From: David Mak Date: Mon, 23 Oct 2023 13:35:29 +0800 Subject: [PATCH 3/5] artiq: Improve IR value naming and add documentation --- nac3artiq/src/codegen.rs | 25 +++++++++- nac3artiq/src/timeline.rs | 100 ++++++++++++++++++++++---------------- 2 files changed, 83 insertions(+), 42 deletions(-) diff --git a/nac3artiq/src/codegen.rs b/nac3artiq/src/codegen.rs index 939ea1c..dc15d56 100644 --- a/nac3artiq/src/codegen.rs +++ b/nac3artiq/src/codegen.rs @@ -28,9 +28,17 @@ use std::{ pub struct ArtiqCodeGenerator<'a> { name: String, + + /// The size of a `size_t` variable in bits. size_t: u32, + + /// Monotonic counter for naming `start`/`stop` variables used by `with parallel` blocks. name_counter: u32, + + /// Variable for tracking the start of a `with parallel` block. start: Option>>, + + /// Variable for tracking the end of a `with parallel` block. end: Option>>, timeline: &'a (dyn TimeFns + Sync), } @@ -102,6 +110,7 @@ impl<'b> CodeGenerator for ArtiqCodeGenerator<'b> { if let StmtKind::With { items, body, .. } = &stmt.node { if items.len() == 1 && items[0].optional_vars.is_none() { let item = &items[0]; + // Behavior of parallel and sequential: // Each function call (indirectly, can be inside a sequential block) within a parallel // block will update the end variable to the maximum now_mu in the block. @@ -119,11 +128,15 @@ impl<'b> CodeGenerator for ArtiqCodeGenerator<'b> { if id == &"parallel".into() { let old_start = self.start.take(); let old_end = self.end.take(); + let now = if let Some(old_start) = &old_start { - self.gen_expr(ctx, old_start)?.unwrap().to_basic_value_enum(ctx, self, old_start.custom.unwrap())? + self.gen_expr(ctx, old_start)? + .unwrap() + .to_basic_value_enum(ctx, self, old_start.custom.unwrap())? } else { self.timeline.emit_now_mu(ctx) }; + // Emulate variable allocation, as we need to use the CodeGenContext // HashMap to store our variable due to lifetime limitation // Note: we should be able to store variables directly if generic @@ -157,8 +170,11 @@ impl<'b> CodeGenerator for ArtiqCodeGenerator<'b> { ctx.builder.build_store(end, now); self.end = Some(end_expr); self.name_counter += 1; + gen_block(self, ctx, body.iter())?; + let current = ctx.builder.get_insert_block().unwrap(); + // if the current block is terminated, move before the terminator // we want to set the timeline before reaching the terminator // TODO: This may be unsound if there are multiple exit paths in the @@ -172,6 +188,7 @@ impl<'b> CodeGenerator for ArtiqCodeGenerator<'b> { } else { false }; + // set duration let end_expr = self.end.take().unwrap(); let end_val = self @@ -183,6 +200,7 @@ impl<'b> CodeGenerator for ArtiqCodeGenerator<'b> { if old_start.is_none() { self.timeline.emit_at_mu(ctx, end_val); } + // inside a parallel block, should update the outer max now_mu if let Some(old_end) = &old_end { let outer_end_val = self @@ -207,20 +225,25 @@ impl<'b> CodeGenerator for ArtiqCodeGenerator<'b> { 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; self.end = old_end; + if reset_position { ctx.builder.position_at_end(current); } + return Ok(()); } else if id == &"sequential".into() { let start = self.start.take(); gen_block(self, ctx, body.iter())?; self.start = start; + return Ok(()); } } } + // not parallel/sequential gen_with(self, ctx, stmt) } else { diff --git a/nac3artiq/src/timeline.rs b/nac3artiq/src/timeline.rs index 47f9536..e3fc124 100644 --- a/nac3artiq/src/timeline.rs +++ b/nac3artiq/src/timeline.rs @@ -1,9 +1,16 @@ use inkwell::{values::BasicValueEnum, AddressSpace, AtomicOrdering}; use nac3core::codegen::CodeGenContext; +/// Functions for manipulating the timeline. pub trait TimeFns { + + /// Emits LLVM IR for `now_mu`. fn emit_now_mu<'ctx, 'a>(&self, ctx: &mut CodeGenContext<'ctx, 'a>) -> BasicValueEnum<'ctx>; + + /// Emits LLVM IR for `at_mu`. fn emit_at_mu<'ctx, 'a>(&self, ctx: &mut CodeGenContext<'ctx, 'a>, t: BasicValueEnum<'ctx>); + + /// Emits LLVM IR for `delay_mu`. fn emit_delay_mu<'ctx, 'a>(&self, ctx: &mut CodeGenContext<'ctx, 'a>, dt: BasicValueEnum<'ctx>); } @@ -20,23 +27,25 @@ impl TimeFns for NowPinningTimeFns64 { .get_global("now") .unwrap_or_else(|| ctx.module.add_global(i64_type, None, "now")); let now_hiptr = - ctx.builder.build_bitcast(now, i32_type.ptr_type(AddressSpace::default()), "now_hiptr"); + ctx.builder.build_bitcast(now, i32_type.ptr_type(AddressSpace::default()), "now.hi.addr"); + if let BasicValueEnum::PointerValue(now_hiptr) = now_hiptr { let now_loptr = unsafe { - ctx.builder.build_gep(now_hiptr, &[i32_type.const_int(2, false)], "now_gep") + ctx.builder.build_gep(now_hiptr, &[i32_type.const_int(2, false)], "now.lo.addr") }; + if let (BasicValueEnum::IntValue(now_hi), BasicValueEnum::IntValue(now_lo)) = ( - ctx.builder.build_load(now_hiptr, "now_hi"), - ctx.builder.build_load(now_loptr, "now_lo"), + ctx.builder.build_load(now_hiptr, "now.hi"), + ctx.builder.build_load(now_loptr, "now.lo"), ) { - let zext_hi = ctx.builder.build_int_z_extend(now_hi, i64_type, "now_zext_hi"); + let zext_hi = ctx.builder.build_int_z_extend(now_hi, i64_type, ""); let shifted_hi = ctx.builder.build_left_shift( zext_hi, i64_type.const_int(32, false), - "now_shifted_zext_hi", + "", ); - let zext_lo = ctx.builder.build_int_z_extend(now_lo, i64_type, "now_zext_lo"); - ctx.builder.build_or(shifted_hi, zext_lo, "now_or").into() + let zext_lo = ctx.builder.build_int_z_extend(now_lo, i64_type, ""); + ctx.builder.build_or(shifted_hi, zext_lo, "now_mu").into() } else { unreachable!(); } @@ -48,14 +57,15 @@ impl TimeFns for NowPinningTimeFns64 { fn emit_at_mu<'ctx, 'a>(&self, ctx: &mut CodeGenContext<'ctx, 'a>, t: BasicValueEnum<'ctx>) { let i32_type = ctx.ctx.i32_type(); let i64_type = ctx.ctx.i64_type(); + let i64_32 = i64_type.const_int(32, false); if let BasicValueEnum::IntValue(time) = t { let time_hi = ctx.builder.build_int_truncate( - ctx.builder.build_right_shift(time, i64_32, false, "now_lshr"), + ctx.builder.build_right_shift(time, i64_32, false, "time.hi"), i32_type, - "now_trunc", + "", ); - let time_lo = ctx.builder.build_int_truncate(time, i32_type, "now_trunc"); + let time_lo = ctx.builder.build_int_truncate(time, i32_type, "time.lo"); let now = ctx .module .get_global("now") @@ -63,11 +73,12 @@ impl TimeFns for NowPinningTimeFns64 { let now_hiptr = ctx.builder.build_bitcast( now, i32_type.ptr_type(AddressSpace::default()), - "now_bitcast", + "now.hi.addr", ); + if let BasicValueEnum::PointerValue(now_hiptr) = now_hiptr { let now_loptr = unsafe { - ctx.builder.build_gep(now_hiptr, &[i32_type.const_int(2, false)], "now_gep") + ctx.builder.build_gep(now_hiptr, &[i32_type.const_int(2, false)], "now.lo.addr") }; ctx.builder .build_store(now_hiptr, time_hi) @@ -97,41 +108,43 @@ impl TimeFns for NowPinningTimeFns64 { .get_global("now") .unwrap_or_else(|| ctx.module.add_global(i64_type, None, "now")); let now_hiptr = - ctx.builder.build_bitcast(now, i32_type.ptr_type(AddressSpace::default()), "now_hiptr"); + ctx.builder.build_bitcast(now, i32_type.ptr_type(AddressSpace::default()), "now.hi.addr"); + if let BasicValueEnum::PointerValue(now_hiptr) = now_hiptr { let now_loptr = unsafe { - ctx.builder.build_gep(now_hiptr, &[i32_type.const_int(2, false)], "now_loptr") + ctx.builder.build_gep(now_hiptr, &[i32_type.const_int(2, false)], "now.lo.addr") }; + if let ( BasicValueEnum::IntValue(now_hi), BasicValueEnum::IntValue(now_lo), BasicValueEnum::IntValue(dt), ) = ( - ctx.builder.build_load(now_hiptr, "now_hi"), - ctx.builder.build_load(now_loptr, "now_lo"), + ctx.builder.build_load(now_hiptr, "now.hi"), + ctx.builder.build_load(now_loptr, "now.lo"), dt, ) { - let zext_hi = ctx.builder.build_int_z_extend(now_hi, i64_type, "now_zext_hi"); + let zext_hi = ctx.builder.build_int_z_extend(now_hi, i64_type, ""); let shifted_hi = ctx.builder.build_left_shift( zext_hi, i64_type.const_int(32, false), - "now_shifted_zext_hi", + "", ); - let zext_lo = ctx.builder.build_int_z_extend(now_lo, i64_type, "now_zext_lo"); - let now_val = ctx.builder.build_or(shifted_hi, zext_lo, "now_or"); + let zext_lo = ctx.builder.build_int_z_extend(now_lo, i64_type, ""); + let now_val = ctx.builder.build_or(shifted_hi, zext_lo, "now"); - let time = ctx.builder.build_int_add(now_val, dt, "now_add"); + let time = ctx.builder.build_int_add(now_val, dt, "time"); let time_hi = ctx.builder.build_int_truncate( ctx.builder.build_right_shift( time, i64_type.const_int(32, false), false, - "now_lshr", + "", ), i32_type, - "now_trunc", + "time.hi", ); - let time_lo = ctx.builder.build_int_truncate(time, i32_type, "now_trunc"); + let time_lo = ctx.builder.build_int_truncate(time, i32_type, "time.lo"); ctx.builder .build_store(now_hiptr, time_hi) @@ -162,11 +175,12 @@ impl TimeFns for NowPinningTimeFns { .get_global("now") .unwrap_or_else(|| ctx.module.add_global(i64_type, None, "now")); let now_raw = ctx.builder.build_load(now.as_pointer_value(), "now"); + if let BasicValueEnum::IntValue(now_raw) = now_raw { let i64_32 = i64_type.const_int(32, false); - let now_lo = ctx.builder.build_left_shift(now_raw, i64_32, "now_shl"); - let now_hi = ctx.builder.build_right_shift(now_raw, i64_32, false, "now_lshr"); - ctx.builder.build_or(now_lo, now_hi, "now_or").into() + let now_lo = ctx.builder.build_left_shift(now_raw, i64_32, "now.lo"); + let now_hi = ctx.builder.build_right_shift(now_raw, i64_32, false, "now.hi"); + ctx.builder.build_or(now_lo, now_hi, "now_mu").into() } else { unreachable!(); } @@ -176,11 +190,12 @@ impl TimeFns for NowPinningTimeFns { let i32_type = ctx.ctx.i32_type(); let i64_type = ctx.ctx.i64_type(); let i64_32 = i64_type.const_int(32, false); + if let BasicValueEnum::IntValue(time) = t { let time_hi = ctx.builder.build_int_truncate( - ctx.builder.build_right_shift(time, i64_32, false, "now_lshr"), + ctx.builder.build_right_shift(time, i64_32, false, ""), i32_type, - "now_trunc", + "time.hi", ); let time_lo = ctx.builder.build_int_truncate(time, i32_type, "now_trunc"); let now = ctx @@ -190,11 +205,12 @@ impl TimeFns for NowPinningTimeFns { let now_hiptr = ctx.builder.build_bitcast( now, i32_type.ptr_type(AddressSpace::default()), - "now_bitcast", + "now.hi.addr", ); + if let BasicValueEnum::PointerValue(now_hiptr) = now_hiptr { let now_loptr = unsafe { - ctx.builder.build_gep(now_hiptr, &[i32_type.const_int(1, false)], "now_gep") + ctx.builder.build_gep(now_hiptr, &[i32_type.const_int(1, false)], "now.lo.addr") }; ctx.builder .build_store(now_hiptr, time_hi) @@ -224,26 +240,28 @@ impl TimeFns for NowPinningTimeFns { .module .get_global("now") .unwrap_or_else(|| ctx.module.add_global(i64_type, None, "now")); - let now_raw = ctx.builder.build_load(now.as_pointer_value(), "now"); + let now_raw = ctx.builder.build_load(now.as_pointer_value(), ""); + if let (BasicValueEnum::IntValue(now_raw), BasicValueEnum::IntValue(dt)) = (now_raw, dt) { - let now_lo = ctx.builder.build_left_shift(now_raw, i64_32, "now_shl"); - let now_hi = ctx.builder.build_right_shift(now_raw, i64_32, false, "now_lshr"); - let now_val = ctx.builder.build_or(now_lo, now_hi, "now_or"); - let time = ctx.builder.build_int_add(now_val, dt, "now_add"); + let now_lo = ctx.builder.build_left_shift(now_raw, i64_32, "now.lo"); + let now_hi = ctx.builder.build_right_shift(now_raw, i64_32, false, "now.hi"); + let now_val = ctx.builder.build_or(now_lo, now_hi, "now_val"); + let time = ctx.builder.build_int_add(now_val, dt, "time"); let time_hi = ctx.builder.build_int_truncate( - ctx.builder.build_right_shift(time, i64_32, false, "now_lshr"), + ctx.builder.build_right_shift(time, i64_32, false, "time.hi"), i32_type, "now_trunc", ); - let time_lo = ctx.builder.build_int_truncate(time, i32_type, "now_trunc"); + let time_lo = ctx.builder.build_int_truncate(time, i32_type, "time.lo"); let now_hiptr = ctx.builder.build_bitcast( now, i32_type.ptr_type(AddressSpace::default()), - "now_bitcast", + "now.hi.addr", ); + if let BasicValueEnum::PointerValue(now_hiptr) = now_hiptr { let now_loptr = unsafe { - ctx.builder.build_gep(now_hiptr, &[i32_type.const_int(1, false)], "now_gep") + ctx.builder.build_gep(now_hiptr, &[i32_type.const_int(1, false)], "now.lo.addr") }; ctx.builder .build_store(now_hiptr, time_hi) -- 2.44.1 From 286218daa53a95f826523094c348f92be3acdbd9 Mon Sep 17 00:00:00 2001 From: David Mak Date: Mon, 23 Oct 2023 15:42:39 +0800 Subject: [PATCH 4/5] Add CodeGenerator::gen_block and refactor to use it --- nac3artiq/src/codegen.rs | 6 +++--- nac3core/src/codegen/generator.rs | 13 +++++++++++++ nac3core/src/codegen/mod.rs | 3 +-- nac3core/src/codegen/stmt.rs | 24 ++++++++++++------------ 4 files changed, 29 insertions(+), 17 deletions(-) diff --git a/nac3artiq/src/codegen.rs b/nac3artiq/src/codegen.rs index dc15d56..ccf11eb 100644 --- a/nac3artiq/src/codegen.rs +++ b/nac3artiq/src/codegen.rs @@ -1,7 +1,7 @@ use nac3core::{ codegen::{ expr::gen_call, - stmt::{gen_block, gen_with}, + stmt::gen_with, CodeGenContext, CodeGenerator, }, symbol_resolver::ValueEnum, @@ -171,7 +171,7 @@ impl<'b> CodeGenerator for ArtiqCodeGenerator<'b> { self.end = Some(end_expr); self.name_counter += 1; - gen_block(self, ctx, body.iter())?; + self.gen_block(ctx, body.iter())?; let current = ctx.builder.get_insert_block().unwrap(); @@ -236,7 +236,7 @@ impl<'b> CodeGenerator for ArtiqCodeGenerator<'b> { return Ok(()); } else if id == &"sequential".into() { let start = self.start.take(); - gen_block(self, ctx, body.iter())?; + self.gen_block(ctx, body.iter())?; self.start = start; return Ok(()); diff --git a/nac3core/src/codegen/generator.rs b/nac3core/src/codegen/generator.rs index 431f345..b8b2729 100644 --- a/nac3core/src/codegen/generator.rs +++ b/nac3core/src/codegen/generator.rs @@ -169,6 +169,7 @@ pub trait CodeGenerator { } /// Generate code for a statement + /// /// Return true if the statement must early return fn gen_stmt<'ctx, 'a>( &mut self, @@ -181,6 +182,18 @@ pub trait CodeGenerator { gen_stmt(self, ctx, stmt) } + /// Generates code for a block statement. + fn gen_block<'ctx, 'a, 'b, I: Iterator>>>( + &mut self, + ctx: &mut CodeGenContext<'ctx, 'a>, + stmts: I, + ) -> Result<(), String> + where + Self: Sized, + { + gen_block(self, ctx, stmts) + } + /// See [bool_to_i1]. fn bool_to_i1<'ctx, 'a>( &self, diff --git a/nac3core/src/codegen/mod.rs b/nac3core/src/codegen/mod.rs index ddce7bc..ae12b34 100644 --- a/nac3core/src/codegen/mod.rs +++ b/nac3core/src/codegen/mod.rs @@ -1,5 +1,4 @@ use crate::{ - codegen::stmt::gen_block, symbol_resolver::{StaticValue, SymbolResolver}, toplevel::{TopLevelContext, TopLevelDef}, typecheck::{ @@ -859,7 +858,7 @@ pub fn gen_func<'ctx, G: CodeGenerator>( ) -> Result<(Builder<'ctx>, Module<'ctx>, FunctionValue<'ctx>), (Builder<'ctx>, String)> { let body = task.body.clone(); gen_func_impl(context, generator, registry, builder, module, task, |generator, ctx| { - gen_block(generator, ctx, body.iter()) + generator.gen_block(ctx, body.iter()) }) } diff --git a/nac3core/src/codegen/stmt.rs b/nac3core/src/codegen/stmt.rs index e985818..10facc2 100644 --- a/nac3core/src/codegen/stmt.rs +++ b/nac3core/src/codegen/stmt.rs @@ -303,7 +303,7 @@ pub fn gen_for<'ctx, 'a, G: CodeGenerator>( ctx.builder.position_at_end(body_bb); ctx.builder.build_store(target_i, ctx.builder.build_load(i, "").into_int_value()); - gen_block(generator, ctx, body.iter())?; + generator.gen_block(ctx, body.iter())?; // Test if next element is still in range let next_i = ctx.builder.build_int_add( @@ -345,7 +345,7 @@ pub fn gen_for<'ctx, 'a, G: CodeGenerator>( .into_pointer_value(); let val = ctx.build_gep_and_load(arr_ptr, &[index], Some("val")); generator.gen_assign(ctx, target, val.into())?; - gen_block(generator, ctx, body.iter())?; + generator.gen_block(ctx, body.iter())?; let index = ctx.builder.build_load(index_addr, "for.index").into_int_value(); let inc = ctx.builder.build_int_add(index, size_t.const_int(1, true), ""); @@ -365,7 +365,7 @@ pub fn gen_for<'ctx, 'a, G: CodeGenerator>( if !orelse.is_empty() { ctx.builder.position_at_end(orelse_bb); - gen_block(generator, ctx, orelse.iter())?; + generator.gen_block(ctx, orelse.iter())?; if !ctx.is_terminated() { ctx.builder.build_unconditional_branch(cont_bb); } @@ -419,7 +419,7 @@ pub fn gen_while<'ctx, 'a, G: CodeGenerator>( unreachable!() }; ctx.builder.position_at_end(body_bb); - gen_block(generator, ctx, body.iter())?; + generator.gen_block(ctx, body.iter())?; for (k, (_, _, counter)) in var_assignment.iter() { let (_, static_val, counter2) = ctx.var_assignment.get_mut(k).unwrap(); if counter != counter2 { @@ -431,7 +431,7 @@ pub fn gen_while<'ctx, 'a, G: CodeGenerator>( } if !orelse.is_empty() { ctx.builder.position_at_end(orelse_bb); - gen_block(generator, ctx, orelse.iter())?; + generator.gen_block(ctx, orelse.iter())?; if !ctx.is_terminated() { ctx.builder.build_unconditional_branch(cont_bb); } @@ -483,7 +483,7 @@ pub fn gen_if<'ctx, 'a, G: CodeGenerator>( unreachable!() }; ctx.builder.position_at_end(body_bb); - gen_block(generator, ctx, body.iter())?; + generator.gen_block(ctx, body.iter())?; for (k, (_, _, counter)) in var_assignment.iter() { let (_, static_val, counter2) = ctx.var_assignment.get_mut(k).unwrap(); if counter != counter2 { @@ -499,7 +499,7 @@ pub fn gen_if<'ctx, 'a, G: CodeGenerator>( } if !orelse.is_empty() { ctx.builder.position_at_end(orelse_bb); - gen_block(generator, ctx, orelse.iter())?; + generator.gen_block(ctx, orelse.iter())?; if !ctx.is_terminated() { if cont_bb.is_none() { cont_bb = Some(ctx.ctx.append_basic_block(current, "cont")); @@ -788,9 +788,9 @@ pub fn gen_try<'ctx, 'a, G: CodeGenerator>( } let old_clauses = ctx.outer_catch_clauses.replace((all_clauses, dispatcher, exn)); let old_unwind = ctx.unwind_target.replace(landingpad); - gen_block(generator, ctx, body.iter())?; + generator.gen_block(ctx, body.iter())?; if ctx.builder.get_insert_block().unwrap().get_terminator().is_none() { - gen_block(generator, ctx, orelse.iter())?; + generator.gen_block(ctx, orelse.iter())?; } let body = ctx.builder.get_insert_block().unwrap(); // reset old_clauses and old_unwind @@ -892,7 +892,7 @@ pub fn gen_try<'ctx, 'a, G: CodeGenerator>( ctx.var_assignment.insert(*name, (exn_store, None, 0)); ctx.builder.build_store(exn_store, exn.as_basic_value()); } - gen_block(generator, ctx, body.iter())?; + generator.gen_block(ctx, body.iter())?; let current = ctx.builder.get_insert_block().unwrap(); // only need to call end catch if not terminated // otherwise, we already handled in return/break/continue/raise @@ -975,7 +975,7 @@ pub fn gen_try<'ctx, 'a, G: CodeGenerator>( // exception path let cleanup = cleanup.unwrap(); ctx.builder.position_at_end(cleanup); - gen_block(generator, ctx, finalbody.iter())?; + generator.gen_block(ctx, finalbody.iter())?; if !ctx.is_terminated() { ctx.build_call_or_invoke(resume, &[], "resume"); ctx.builder.build_unreachable(); @@ -987,7 +987,7 @@ pub fn gen_try<'ctx, 'a, G: CodeGenerator>( final_targets.push(tail); let finalizer = ctx.ctx.append_basic_block(current_fun, "try.finally"); ctx.builder.position_at_end(finalizer); - gen_block(generator, ctx, finalbody.iter())?; + generator.gen_block(ctx, finalbody.iter())?; if !ctx.is_terminated() { let dest = ctx.builder.build_load(final_state, "final_dest"); ctx.builder.build_indirect_branch(dest, &final_targets); -- 2.44.1 From 305836305cef0a0e61add1446dbc9f9770f39e72 Mon Sep 17 00:00:00 2001 From: David Mak Date: Tue, 24 Oct 2023 19:08:23 +0800 Subject: [PATCH 5/5] WIP --- nac3artiq/src/codegen.rs | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/nac3artiq/src/codegen.rs b/nac3artiq/src/codegen.rs index ccf11eb..d4aaf7a 100644 --- a/nac3artiq/src/codegen.rs +++ b/nac3artiq/src/codegen.rs @@ -75,7 +75,11 @@ impl<'b> CodeGenerator for ArtiqCodeGenerator<'b> { params: Vec<(Option, ValueEnum<'ctx>)>, ) -> Result>, String> { let result = gen_call(self, ctx, obj, fun, params)?; - if let Some(end) = self.end.clone() { + + if let ( + Some(start), + Some(end) + ) = (self.start.clone(), self.end.clone()) { let old_end = self.gen_expr(ctx, &end)?.unwrap().to_basic_value_enum(ctx, self, end.custom.unwrap())?; let now = self.timeline.emit_now_mu(ctx); let smax = ctx.module.get_function("llvm.smax.i64").unwrap_or_else(|| { @@ -94,11 +98,11 @@ impl<'b> CodeGenerator for ArtiqCodeGenerator<'b> { .unwrap(); 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() { + let start_val = self.gen_expr(ctx, &start)?.unwrap().to_basic_value_enum(ctx, self, start.custom.unwrap())?; self.timeline.emit_at_mu(ctx, start_val); } + Ok(result) } @@ -235,9 +239,7 @@ impl<'b> CodeGenerator for ArtiqCodeGenerator<'b> { return Ok(()); } else if id == &"sequential".into() { - let start = self.start.take(); self.gen_block(ctx, body.iter())?; - self.start = start; return Ok(()); } -- 2.44.1