fixing slice slicing

Signed-off-by: Jakub Doka <jakub.doka2@gmail.com>
This commit is contained in:
Jakub Doka 2024-12-22 16:18:44 +01:00
parent 888b38ad4c
commit 939d0807fb
No known key found for this signature in database
GPG key ID: C6E9A89936B8C143
3 changed files with 38 additions and 12 deletions

View file

@ -798,6 +798,14 @@ main := fn(): uint {
### Purely Testing Examples ### Purely Testing Examples
#### subsclice_bug
```hb
main := fn(): void {
str := "abcd\0"
@eca(37, str[1..].ptr)
}
```
#### proper_ident_propagation #### proper_ident_propagation
```hb ```hb
A := fn($T: type): type return struct {a: T} A := fn($T: type): type return struct {a: T}

View file

@ -36,6 +36,9 @@ use {
const DEFAULT_ACLASS: usize = 0; const DEFAULT_ACLASS: usize = 0;
const GLOBAL_ACLASS: usize = 1; const GLOBAL_ACLASS: usize = 1;
const SLICE_PTR_OFF: Offset = 0;
const SLICE_LEN_OFF: Offset = 8;
macro_rules! inference { macro_rules! inference {
($ty:ident, $ctx:expr, $self:expr, $pos:expr, $subject:literal, $example:literal) => { ($ty:ident, $ctx:expr, $self:expr, $pos:expr, $subject:literal, $example:literal) => {
let Some($ty) = $ctx.ty else { let Some($ty) = $ctx.ty else {
@ -1273,7 +1276,7 @@ impl<'a> Codegen<'a> {
} }
ty::Kind::Slice(_) => { ty::Kind::Slice(_) => {
// Might change // 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) self.load_mem(off, ty::Id::UINT)
} }
ty::Kind::Ptr(_) => { 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); self.ci.nodes.lock(ptr.id);
let ty = self.tys.make_array(elem, ArrayLen::MAX); let ty = self.tys.make_array(elem, ArrayLen::MAX);
let mem = self.new_stack(pos, ty); 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); let region = self.offset(mem, off);
self.store_mem(region, value.ty, value.id); self.store_mem(region, value.ty, value.id);
} }
@ -1347,7 +1360,7 @@ impl<'a> Codegen<'a> {
} }
ty::Kind::Slice(s) => { ty::Kind::Slice(s) => {
let elem = self.tys.ins.slices[s].elem; 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 base = self.tys.make_ptr(elem);
let bs = self.load_mem(off, base); let bs = self.load_mem(off, base);
Some(self.offset_ptr(bs, elem, idx.id)) 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 slc = self.tys.make_array(ty::Id::U8, ArrayLen::MAX);
let mem = self.new_stack(pos, slc); 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); let region = self.offset(mem, off);
self.store_mem(region, value.ty, value.id); self.store_mem(region, value.ty, value.id);
} }
@ -2063,22 +2078,24 @@ impl<'a> Codegen<'a> {
let terminated = self.expr(body).is_none(); 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!() unreachable!()
}; };
if !terminated && let Some((_, prev)) = state { if !terminated && let Some((_, prev)) = *state {
self.error( self.error(
pos, pos,
"reached a constrol flow keyword inside an unrolled loop, \ "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", not dependant on a runtime value",
); );
return self.error(prev, "previous reachable control flow found here"); return self.error(prev, "previous reachable control flow found here");
} }
match state { match state.take() {
// loop never loops
Some((CtLoopState::Terminated, _)) => break, Some((CtLoopState::Terminated, _)) => break,
// loop loops forever
Some((CtLoopState::Continued, _)) | None => {} Some((CtLoopState::Continued, _)) | None => {}
} }
} }
@ -2621,8 +2638,8 @@ impl<'a> Codegen<'a> {
} }
ty::Kind::Slice(s) => { ty::Kind::Slice(s) => {
let (offset, ty) = match name { let (offset, ty) = match name {
"len" => (8, ty::Id::UINT), "len" => (SLICE_LEN_OFF, ty::Id::UINT),
"ptr" => (0, self.tys.make_ptr(self.tys.ins.slices[s].elem)), "ptr" => (SLICE_PTR_OFF, self.tys.make_ptr(self.tys.ins.slices[s].elem)),
_ => return None, _ => return None,
}; };
Some(Value::ptr(self.offset(vtarget.id, offset)).ty(ty)) 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) { fn generate(ident: &'static str, input: &'static str, output: &mut String) {
_ = log::set_logger(&crate::fs::Logger); _ = log::set_logger(&crate::fs::Logger);
log::set_max_level(log::LevelFilter::Info); 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 mut ctx = CodegenCtx::default();
let (ref files, embeds) = crate::test_parse_files(ident, input, &mut ctx.parser); let (ref files, embeds) = crate::test_parse_files(ident, input, &mut ctx.parser);
@ -4437,6 +4454,7 @@ mod tests {
fb_driver; fb_driver;
// Purely Testing Examples; // Purely Testing Examples;
subsclice_bug;
string_array; string_array;
proper_ident_propagation; proper_ident_propagation;
method_receiver_by_value; method_receiver_by_value;

View file