forcing structs to always be on stack

This commit is contained in:
mlokr 2024-09-17 17:59:03 +02:00
parent 4a9b9de87f
commit 5d77ae93b4
No known key found for this signature in database
GPG key ID: DEA147DDEE644993
2 changed files with 32 additions and 16 deletions

View file

@ -363,7 +363,17 @@ OemIdent := struct {
dos_version_name: [u8; 8], dos_version_name: [u8; 8],
} }
Stru := struct {
a: u16,
b: u16,
}
small_struct := fn(): Stru {
return .{a: 0, b: 0}
}
main := fn(major: int, minor: int): OemIdent { main := fn(major: int, minor: int): OemIdent {
small_struct()
ver := [u8].(0, 0, 0, 0, 0, 0, 0, 0) ver := [u8].(0, 0, 0, 0, 0, 0, 0, 0)
return OemIdent.(ver, ver) return OemIdent.(ver, ver)
} }

View file

@ -1086,7 +1086,7 @@ impl Codegen {
Some(Value::new(self.tys.make_ptr(ty::U8.into()), reg)) Some(Value::new(self.tys.make_ptr(ty::U8.into()), reg))
} }
E::Ctor { pos, ty, fields, .. } => { E::Ctor { pos, ty, fields, .. } => {
let (ty, loc) = self.prepare_struct_ctor(pos, ctx, ty, fields.len()); let (ty, loc) = self.prepare_struct_ctor(pos, &mut ctx, ty, fields.len());
let ty::Kind::Struct(stru) = ty.expand() else { let ty::Kind::Struct(stru) = ty.expand() else {
self.report( self.report(
@ -1103,10 +1103,16 @@ impl Codegen {
let value = self.expr_ctx(value, Ctx::default().with_loc(loc).with_ty(ty))?; let value = self.expr_ctx(value, Ctx::default().with_loc(loc).with_ty(ty))?;
self.ci.free_loc(value.loc); self.ci.free_loc(value.loc);
} }
if let Some(dst_loc) = ctx.loc {
self.store_typed(loc, &dst_loc, ty);
return Some(Value { ty, loc: dst_loc });
} else {
return Some(Value { ty, loc }); return Some(Value { ty, loc });
} }
}
E::Tupl { pos, ty, fields, .. } => { E::Tupl { pos, ty, fields, .. } => {
let (ty, loc) = self.prepare_struct_ctor(pos, ctx, ty, fields.len()); let (ty, loc) = self.prepare_struct_ctor(pos, &mut ctx, ty, fields.len());
match ty.expand() { match ty.expand() {
ty::Kind::Struct(stru) => { ty::Kind::Struct(stru) => {
@ -1141,8 +1147,13 @@ impl Codegen {
), ),
} }
if let Some(dst_loc) = ctx.loc {
self.store_typed(loc, &dst_loc, ty);
return Some(Value { ty, loc: dst_loc });
} else {
return Some(Value { ty, loc }); return Some(Value { ty, loc });
} }
}
E::Field { target, name: field } => { E::Field { target, name: field } => {
let checkpoint = self.ci.snap(); let checkpoint = self.ci.snap();
let mut tal = self.expr(target)?; let mut tal = self.expr(target)?;
@ -1375,11 +1386,9 @@ impl Codegen {
Some(self.ci.inline_ret_loc.as_ref()) Some(self.ci.inline_ret_loc.as_ref())
} }
0 => None, 0 => None,
1..=8 => Some(Loc::reg(1)), 1..=16 => Some(Loc::reg(1)),
9..=16 => None,
_ => Some(Loc::reg(self.ci.ret_reg.as_ref()).into_derefed()), _ => Some(Loc::reg(self.ci.ret_reg.as_ref()).into_derefed()),
}; };
let loc_is_none = loc.is_none();
let value = if let Some(val) = val { let value = if let Some(val) = val {
self.expr_ctx(val, Ctx { ty: self.ci.ret, loc })? self.expr_ctx(val, Ctx { ty: self.ci.ret, loc })?
} else { } else {
@ -1391,12 +1400,6 @@ impl Codegen {
Some(ret) => _ = self.assert_ty(pos, value.ty, ret, "return type"), Some(ret) => _ = self.assert_ty(pos, value.ty, ret, "return type"),
} }
if let 9..=16 = size
&& loc_is_none
{
self.store_sized(value.loc, Loc::reg(1), size);
}
self.ci.ret_relocs.push(Reloc::new(self.ci.code.len(), 1, 4)); self.ci.ret_relocs.push(Reloc::new(self.ci.code.len(), 1, 4));
self.ci.emit(jmp(0)); self.ci.emit(jmp(0));
None None
@ -1899,7 +1902,7 @@ impl Codegen {
fn prepare_struct_ctor( fn prepare_struct_ctor(
&mut self, &mut self,
pos: Pos, pos: Pos,
ctx: Ctx, ctx: &mut Ctx,
ty: Option<&Expr>, ty: Option<&Expr>,
field_len: usize, field_len: usize,
) -> (ty::Id, Loc) { ) -> (ty::Id, Loc) {
@ -1935,8 +1938,11 @@ impl Codegen {
} }
let size = self.tys.size_of(ty); let size = self.tys.size_of(ty);
let loc = ctx.loc.unwrap_or_else(|| Loc::stack(self.ci.stack.allocate(size))); if ctx.loc.as_ref().map_or(true, |l| l.is_reg()) {
(ty, loc) (ty, Loc::stack(self.ci.stack.allocate(size)))
} else {
(ty, ctx.loc.take().unwrap_or_else(|| Loc::stack(self.ci.stack.allocate(size))))
}
} }
fn struct_op( fn struct_op(