From 939d0807fb5e53d2ff25e7040e254a1b5b063a56 Mon Sep 17 00:00:00 2001 From: Jakub Doka Date: Sun, 22 Dec 2024 16:18:44 +0100 Subject: [PATCH] fixing slice slicing Signed-off-by: Jakub Doka --- lang/README.md | 8 +++++ lang/src/son.rs | 42 ++++++++++++++++++-------- lang/tests/son_tests_subsclice_bug.txt | 0 3 files changed, 38 insertions(+), 12 deletions(-) create mode 100644 lang/tests/son_tests_subsclice_bug.txt diff --git a/lang/README.md b/lang/README.md index d7df52c..3db8e54 100644 --- a/lang/README.md +++ b/lang/README.md @@ -798,6 +798,14 @@ main := fn(): uint { ### Purely Testing Examples +#### subsclice_bug +```hb +main := fn(): void { + str := "abcd\0" + @eca(37, str[1..].ptr) +} +``` + #### proper_ident_propagation ```hb A := fn($T: type): type return struct {a: T} diff --git a/lang/src/son.rs b/lang/src/son.rs index 41597ff..754f7df 100644 --- a/lang/src/son.rs +++ b/lang/src/son.rs @@ -36,6 +36,9 @@ use { const DEFAULT_ACLASS: usize = 0; const GLOBAL_ACLASS: usize = 1; +const SLICE_PTR_OFF: Offset = 0; +const SLICE_LEN_OFF: Offset = 8; + macro_rules! inference { ($ty:ident, $ctx:expr, $self:expr, $pos:expr, $subject:literal, $example:literal) => { let Some($ty) = $ctx.ty else { @@ -1273,7 +1276,7 @@ impl<'a> Codegen<'a> { } ty::Kind::Slice(_) => { // Might change - let off = self.offset(bs.id, 8); + let off = self.offset(bs.id, SLICE_LEN_OFF); self.load_mem(off, ty::Id::UINT) } ty::Kind::Ptr(_) => { @@ -1314,13 +1317,23 @@ impl<'a> Codegen<'a> { } }; - let ptr = self.offset_ptr(bs.id, elem, start); + let ptr = match bs.ty.expand() { + ty::Kind::Slice(s) if let Some(_) = self.tys.ins.slices[s].len() => bs, + ty::Kind::Slice(_) => { + // Might change + let off = self.offset(bs.id, SLICE_PTR_OFF); + let base = self.tys.make_ptr(elem); + Value::new(self.load_mem(off, base)).ty(base) + } + ty::Kind::Ptr(_) => bs, + _ => unreachable!(), + }; self.ci.nodes.lock(ptr.id); let ty = self.tys.make_array(elem, ArrayLen::MAX); let mem = self.new_stack(pos, ty); - for (off, value) in [(0u32, ptr), (8, len)] { + for (off, value) in [(SLICE_PTR_OFF, ptr), (SLICE_LEN_OFF, len)] { let region = self.offset(mem, off); self.store_mem(region, value.ty, value.id); } @@ -1347,7 +1360,7 @@ impl<'a> Codegen<'a> { } ty::Kind::Slice(s) => { let elem = self.tys.ins.slices[s].elem; - let off = self.offset(bs.id, 0); + let off = self.offset(bs.id, SLICE_PTR_OFF); let base = self.tys.make_ptr(elem); let bs = self.load_mem(off, base); Some(self.offset_ptr(bs, elem, idx.id)) @@ -1438,7 +1451,9 @@ impl<'a> Codegen<'a> { let slc = self.tys.make_array(ty::Id::U8, ArrayLen::MAX); let mem = self.new_stack(pos, slc); - for (off, value) in [(0u32, Value::ptr(global).ty(ty)), (8, len)] { + for (off, value) in + [(SLICE_PTR_OFF, Value::ptr(global).ty(ty)), (SLICE_LEN_OFF, len)] + { let region = self.offset(mem, off); self.store_mem(region, value.ty, value.id); } @@ -2063,22 +2078,24 @@ impl<'a> Codegen<'a> { let terminated = self.expr(body).is_none(); - let Some(&Loop::Comptime { state, .. }) = self.ci.loops.last() else { + let Some(Loop::Comptime { state, .. }) = self.ci.loops.last_mut() else { unreachable!() }; - if !terminated && let Some((_, prev)) = state { + if !terminated && let Some((_, prev)) = *state { self.error( pos, "reached a constrol flow keyword inside an unrolled loop, \ - as well ast the end of the loop, make sure control flow is \ + as well as the end of the loop, make sure control flow is \ not dependant on a runtime value", ); return self.error(prev, "previous reachable control flow found here"); } - match state { + match state.take() { + // loop never loops Some((CtLoopState::Terminated, _)) => break, + // loop loops forever Some((CtLoopState::Continued, _)) | None => {} } } @@ -2621,8 +2638,8 @@ impl<'a> Codegen<'a> { } ty::Kind::Slice(s) => { let (offset, ty) = match name { - "len" => (8, ty::Id::UINT), - "ptr" => (0, self.tys.make_ptr(self.tys.ins.slices[s].elem)), + "len" => (SLICE_LEN_OFF, ty::Id::UINT), + "ptr" => (SLICE_PTR_OFF, self.tys.make_ptr(self.tys.ins.slices[s].elem)), _ => return None, }; Some(Value::ptr(self.offset(vtarget.id, offset)).ty(ty)) @@ -4367,7 +4384,7 @@ mod tests { fn generate(ident: &'static str, input: &'static str, output: &mut String) { _ = log::set_logger(&crate::fs::Logger); log::set_max_level(log::LevelFilter::Info); - //log::set_max_level(log::LevelFilter::Trace); + log::set_max_level(log::LevelFilter::Trace); let mut ctx = CodegenCtx::default(); let (ref files, embeds) = crate::test_parse_files(ident, input, &mut ctx.parser); @@ -4437,6 +4454,7 @@ mod tests { fb_driver; // Purely Testing Examples; + subsclice_bug; string_array; proper_ident_propagation; method_receiver_by_value; diff --git a/lang/tests/son_tests_subsclice_bug.txt b/lang/tests/son_tests_subsclice_bug.txt new file mode 100644 index 0000000..e69de29