chained dereference
This commit is contained in:
@@ -3912,7 +3912,7 @@ pub const CodeGen = struct {
|
||||
fn genFieldAssignment(self: *CodeGen, asgn: ast.Assignment) !c.LLVMValueRef {
|
||||
const fa = asgn.target.data.field_access;
|
||||
|
||||
// Non-identifier object (e.g. a.first.next = val — chained pointer field assignment)
|
||||
// Non-identifier object (e.g. a.b.c = val — chained field assignment)
|
||||
if (fa.object.data != .identifier) {
|
||||
const obj_ty = self.inferType(fa.object);
|
||||
if (obj_ty.isPointer()) {
|
||||
@@ -3931,6 +3931,18 @@ pub const CodeGen = struct {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
if (obj_ty.isStruct()) {
|
||||
// Chained struct field: expr.field = val where expr is a struct (e.g. self.inner.len = 0)
|
||||
const sname = obj_ty.struct_type;
|
||||
const info = try self.getStructInfo(sname);
|
||||
const fi = try self.findFieldIndex(info.field_names, fa.field, sname);
|
||||
const field_ty = info.field_types[fi];
|
||||
const intermediate_ptr = try self.genAddressOf(fa.object);
|
||||
const gep = self.structGEP(info.llvm_type, intermediate_ptr, @intCast(fi), "chain_sfield_ptr");
|
||||
const rhs = try self.genExprAsType(asgn.value, field_ty);
|
||||
self.storeOrCompound(asgn.op, gep, rhs, field_ty, "chain_scur");
|
||||
return null;
|
||||
}
|
||||
return self.emitError("field assignment target must be a variable");
|
||||
}
|
||||
const obj_name = fa.object.data.identifier.name;
|
||||
@@ -4604,6 +4616,25 @@ pub const CodeGen = struct {
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Chained field access: a.b.c — recursively get address of intermediate
|
||||
const intermediate_ptr = try self.genAddressOf(fa.object);
|
||||
const obj_ty = self.inferType(fa.object);
|
||||
if (obj_ty.isStruct()) {
|
||||
const sname = obj_ty.struct_type;
|
||||
const info = try self.getStructInfo(sname);
|
||||
const idx = try self.findFieldIndex(info.field_names, fa.field, sname);
|
||||
return self.structGEP(info.llvm_type, intermediate_ptr, @intCast(idx), "addr_chain_field");
|
||||
}
|
||||
if (obj_ty.isPointer()) {
|
||||
const pointee_name = obj_ty.pointer_type.pointee_name;
|
||||
if (self.lookupStructInfo(pointee_name)) |info| {
|
||||
const loaded_ptr = c.LLVMBuildLoad2(self.builder,
|
||||
self.ptrType(), intermediate_ptr, "chain_ptr_load");
|
||||
const idx = try self.findFieldIndex(info.field_names, fa.field, pointee_name);
|
||||
return self.structGEP(info.llvm_type, loaded_ptr, @intCast(idx), "addr_chain_pfield");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return self.emitError("address-of requires a variable, index, or field expression");
|
||||
|
||||
Reference in New Issue
Block a user