codegen: partially emit code for field accesses
Resolve field names of field access expressions, generate the code for
the access target, and prepare emission of the appropriate LLHD
instruction. Currently the code panics because the `extract` instruction
is not yet implemented. See
@@ -879,6 +879,60 @@ where
};
(self.emit_nameless_inst(inst).into(), Mode::Value)
}
+ hir::ExprKind::Field(target_id, name) => {
+ let ty = self.type_of(target_id, env)?;
+ let struct_def = match ty {
+ &TypeKind::Struct(id) => id,
+ &TypeKind::Named(_, _, &TypeKind::Struct(id)) => id,
+ _ => {
+ let hir = self.hir_of(target_id)?;
+ self.emit(
+ DiagBuilder2::error(format!("{} is not a struct", hir.desc_full()))
+ .span(hir.human_span()),
+ );
+ return Err(());
+ }
+ };
+ let struct_fields = match self.hir_of(struct_def)? {
+ HirNode::Type(hir::Type {
+ kind: hir::TypeKind::Struct(ref fields),
+ ..
+ }) => fields,
+ _ => unreachable!(),
+ };
+ let index = struct_fields.iter().position(|&id| match self.hir_of(id) {
+ Ok(HirNode::VarDecl(vd)) => vd.name.value == name.value,
+ _ => false,
+ });
+ let index = match index {
+ Some(x) => x,
+ None => {
+ let hir = self.hir_of(target_id)?;
+ self.emit(
+ DiagBuilder2::error(format!(
+ "{} has no field `{}`",
+ hir.desc_full(),
+ name
+ ))
+ .span(name.span())
+ .add_note(format!("{} is a struct defined here:", hir.desc_full()))
+ .span(self.span(struct_def)),
+ );
+ return Err(());
+ }
+ };
+ let target = self.emit_rvalue_mode(target_id, env, Mode::Value)?;
+ unimplemented!(
+ "llhd extract instruction for field {} of target {:?}",
+ index,
+ target
+ );
+ // let llty = self.emit_type(ty, env)?;
+ // (
+ // self.emit_nameless_inst(llhd::ExtractInst(llty, target, index)),
+ // Mode::Value,
+ // )
+ }
_ => return self.unimp_msg("code generation for", hir),
};
match (mode, actual_mode) {
