mirror of
https://github.com/ziglang/zig.git
synced 2026-01-02 03:25:01 +00:00
stage2: union field value
This commit is contained in:
parent
d6f048c456
commit
6329f4e47a
40
src/Sema.zig
40
src/Sema.zig
@ -300,7 +300,7 @@ pub const Block = struct {
|
||||
.ty = ty,
|
||||
.payload = try block.sema.addExtra(Air.StructField{
|
||||
.struct_operand = struct_ptr,
|
||||
.field_index = @intCast(u32, field_index),
|
||||
.field_index = field_index,
|
||||
}),
|
||||
} },
|
||||
});
|
||||
@ -315,6 +315,24 @@ pub const Block = struct {
|
||||
});
|
||||
}
|
||||
|
||||
pub fn addStructFieldVal(
|
||||
block: *Block,
|
||||
struct_val: Air.Inst.Ref,
|
||||
field_index: u32,
|
||||
field_ty: Type,
|
||||
) !Air.Inst.Ref {
|
||||
return block.addInst(.{
|
||||
.tag = .struct_field_val,
|
||||
.data = .{ .ty_pl = .{
|
||||
.ty = try block.sema.addType(field_ty),
|
||||
.payload = try block.sema.addExtra(Air.StructField{
|
||||
.struct_operand = struct_val,
|
||||
.field_index = field_index,
|
||||
}),
|
||||
} },
|
||||
});
|
||||
}
|
||||
|
||||
pub fn addInst(block: *Block, inst: Air.Inst) error{OutOfMemory}!Air.Inst.Ref {
|
||||
return Air.indexToRef(try block.addInstAsIndex(inst));
|
||||
}
|
||||
@ -11261,8 +11279,10 @@ fn structFieldVal(
|
||||
const struct_ty = try sema.resolveTypeFields(block, src, unresolved_struct_ty);
|
||||
const struct_obj = struct_ty.castTag(.@"struct").?.data;
|
||||
|
||||
const field_index = struct_obj.fields.getIndex(field_name) orelse
|
||||
const field_index_big = struct_obj.fields.getIndex(field_name) orelse
|
||||
return sema.failWithBadFieldAccess(block, struct_obj, field_name_src, field_name);
|
||||
const field_index = @intCast(u32, field_index_big);
|
||||
|
||||
const field = struct_obj.fields.values()[field_index];
|
||||
|
||||
if (try sema.resolveMaybeUndefVal(block, src, struct_byval)) |struct_val| {
|
||||
@ -11273,16 +11293,7 @@ fn structFieldVal(
|
||||
}
|
||||
|
||||
try sema.requireRuntimeBlock(block, src);
|
||||
return block.addInst(.{
|
||||
.tag = .struct_field_val,
|
||||
.data = .{ .ty_pl = .{
|
||||
.ty = try sema.addType(field.ty),
|
||||
.payload = try sema.addExtra(Air.StructField{
|
||||
.struct_operand = struct_byval,
|
||||
.field_index = @intCast(u32, field_index),
|
||||
}),
|
||||
} },
|
||||
});
|
||||
return block.addStructFieldVal(struct_byval, field_index, field.ty);
|
||||
}
|
||||
|
||||
fn unionFieldPtr(
|
||||
@ -11341,8 +11352,9 @@ fn unionFieldVal(
|
||||
const union_ty = try sema.resolveTypeFields(block, src, unresolved_union_ty);
|
||||
const union_obj = union_ty.cast(Type.Payload.Union).?.data;
|
||||
|
||||
const field_index = union_obj.fields.getIndex(field_name) orelse
|
||||
const field_index_big = union_obj.fields.getIndex(field_name) orelse
|
||||
return sema.failWithBadUnionFieldAccess(block, union_obj, field_name_src, field_name);
|
||||
const field_index = @intCast(u32, field_index_big);
|
||||
|
||||
const field = union_obj.fields.values()[field_index];
|
||||
|
||||
@ -11355,7 +11367,7 @@ fn unionFieldVal(
|
||||
}
|
||||
|
||||
try sema.requireRuntimeBlock(block, src);
|
||||
return sema.fail(block, src, "TODO implement runtime union field access", .{});
|
||||
return block.addStructFieldVal(union_byval, field_index, field.ty);
|
||||
}
|
||||
|
||||
fn elemPtr(
|
||||
|
||||
@ -2236,17 +2236,34 @@ pub const FuncGen = struct {
|
||||
const struct_field = self.air.extraData(Air.StructField, ty_pl.payload).data;
|
||||
const struct_ty = self.air.typeOf(struct_field.struct_operand);
|
||||
const struct_llvm_val = try self.resolveInst(struct_field.struct_operand);
|
||||
const field_index = llvmFieldIndex(struct_ty, struct_field.field_index);
|
||||
if (isByRef(struct_ty)) {
|
||||
const field_ptr = self.builder.buildStructGEP(struct_llvm_val, field_index, "");
|
||||
const field_ty = struct_ty.structFieldType(struct_field.field_index);
|
||||
if (isByRef(field_ty)) {
|
||||
return field_ptr;
|
||||
} else {
|
||||
return self.builder.buildLoad(field_ptr, "");
|
||||
}
|
||||
const field_index = struct_field.field_index;
|
||||
const field_ty = struct_ty.structFieldType(field_index);
|
||||
if (!field_ty.hasCodeGenBits()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
assert(isByRef(struct_ty));
|
||||
|
||||
const field_ptr = switch (struct_ty.zigTypeTag()) {
|
||||
.Struct => blk: {
|
||||
const llvm_field_index = llvmFieldIndex(struct_ty, field_index);
|
||||
break :blk self.builder.buildStructGEP(struct_llvm_val, llvm_field_index, "");
|
||||
},
|
||||
.Union => blk: {
|
||||
const llvm_field_ty = try self.dg.llvmType(field_ty);
|
||||
const target = self.dg.module.getTarget();
|
||||
const layout = struct_ty.unionGetLayout(target);
|
||||
const payload_index = @boolToInt(layout.tag_align >= layout.payload_align);
|
||||
const union_field_ptr = self.builder.buildStructGEP(struct_llvm_val, payload_index, "");
|
||||
break :blk self.builder.buildBitCast(union_field_ptr, llvm_field_ty.pointerType(0), "");
|
||||
},
|
||||
else => unreachable,
|
||||
};
|
||||
|
||||
if (isByRef(field_ty)) {
|
||||
return field_ptr;
|
||||
} else {
|
||||
return self.builder.buildExtractValue(struct_llvm_val, field_index, "");
|
||||
return self.builder.buildLoad(field_ptr, "");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user