access record fields progress

This commit is contained in:
Dan Bruder 2020-03-12 10:37:07 -04:00
parent 8e11d69c45
commit bfd9150af4
4 changed files with 62 additions and 33 deletions

View file

@ -194,16 +194,59 @@ pub fn build_expr<'a, B: Backend>(
builder.ins().stack_store(val, slot, Offset32::new(offset)); builder.ins().stack_store(val, slot, Offset32::new(offset));
} }
let ir_type = type_from_layout(cfg, layout); builder
builder.ins().stack_addr(ir_type, slot, Offset32::new(0)) .ins()
.stack_addr(cfg.pointer_type(), slot, Offset32::new(0))
}
Access {
label,
field_layout,
struct_layout: Layout::Struct(fields),
record,
} => {
let cfg = env.cfg;
// Reconstruct the struct to determine the combined layout
// TODO get rid of clones
let mut reconstructed_struct_layout =
Vec::with_capacity_in(fields.len() + 1, env.arena);
for field in fields.iter() {
reconstructed_struct_layout.push(field.clone());
}
reconstructed_struct_layout.push((label.clone(), field_layout.clone()));
reconstructed_struct_layout.sort_by(|a, b| {
a.0.partial_cmp(&b.0)
.expect("TODO: failed to sort struct fields in crane access")
});
// Find the offset we are trying to access
let mut offset = 0;
for (local_label, layout) in reconstructed_struct_layout.iter() {
if local_label == label {
break;
}
let field_size = match layout {
Layout::Builtin(Builtin::Int64) => std::mem::size_of::<i64>(),
_ => panic!(
"Missing struct field size in offset calculation for struct access for {:?}",
layout
),
};
offset += field_size;
}
let offset = i32::try_from(offset)
.expect("TODO gracefully handle usize -> i32 conversion in struct access");
let mem_flags = MemFlags::new();
let record = build_expr(env, scope, module, builder, record, procs);
builder
.ins()
.load(cfg.pointer_type(), mem_flags, record, Offset32::new(offset))
} }
// Access {
// label,
// field_layout,
// struct_layout,
// } => {
// panic!("I don't yet know how to crane build {:?}", expr);
// }
Str(str_literal) => { Str(str_literal) => {
if str_literal.is_empty() { if str_literal.is_empty() {
panic!("TODO build an empty string in Crane"); panic!("TODO build an empty string in Crane");

View file

@ -10,20 +10,7 @@ pub fn type_from_layout(cfg: TargetFrontendConfig, layout: &Layout<'_>) -> Type
use roc_mono::layout::Layout::*; use roc_mono::layout::Layout::*;
match layout { match layout {
Pointer(_) | FunctionPointer(_, _) => cfg.pointer_type(), Pointer(_) | FunctionPointer(_, _) | Struct(_) => cfg.pointer_type(),
Struct(fields) => {
// This will change as we add more fields and field types to the tests
let naive_all_ints = fields.iter().all(|ref field| match field.1 {
Builtin(Int64) => true,
_ => false,
});
if naive_all_ints && fields.len() == 3 {
types::I64.by(4).unwrap()
} else {
panic!("TODO layout_to_crane_type for Struct");
}
}
Builtin(builtin) => match builtin { Builtin(builtin) => match builtin {
Int64 => types::I64, Int64 => types::I64,
Float64 => types::F64, Float64 => types::F64,

View file

@ -873,9 +873,7 @@ mod test_gen {
// assert_evals_to!( // assert_evals_to!(
// indoc!( // indoc!(
// r#" // r#"
// point = { x: 15, y: 17, z: 19 } // { y: 17, x: 15, z: 19 }.x
// point.x
// "# // "#
// ), // ),
// 15, // 15,
@ -885,20 +883,17 @@ mod test_gen {
// assert_evals_to!( // assert_evals_to!(
// indoc!( // indoc!(
// r#" // r#"
// point = { x: 15, y: 17, z: 19 } // { x: 15, y: 17, z: 19 }.y
// point.y
// "# // "#
// ), // ),
// 17, // 17,
// i64 // i64
// ); // );
// assert_evals_to!( // assert_evals_to!(
// indoc!( // indoc!(
// r#" // r#"
// point = { x: 15, y: 17, z: 19 } // { x: 15, y: 17, z: 19 }.z
// point.z
// "# // "#
// ), // ),
// 19, // 19,

View file

@ -101,6 +101,7 @@ pub enum Expr<'a> {
label: Lowercase, label: Lowercase,
field_layout: Layout<'a>, field_layout: Layout<'a>,
struct_layout: Layout<'a>, struct_layout: Layout<'a>,
record: &'a Expr<'a>,
}, },
Array { Array {
@ -398,7 +399,7 @@ fn from_can<'a>(
ext_var, ext_var,
field_var, field_var,
field, field,
.. loc_expr,
} => { } => {
let subs = env.subs; let subs = env.subs;
let arena = env.arena; let arena = env.arena;
@ -419,10 +420,13 @@ fn from_can<'a>(
} }
}; };
let record = arena.alloc(from_can(env, loc_expr.value, procs, None));
Expr::Access { Expr::Access {
label: field, label: field,
field_layout, field_layout,
struct_layout, struct_layout,
record,
} }
} }