mirror of
https://github.com/ziglang/zig.git
synced 2024-11-26 23:22:44 +00:00
LLVM: aggregate_init supports structs
in addition to tuples
This commit is contained in:
parent
446324a1d8
commit
220708e7c3
@ -394,11 +394,11 @@ pub const Block = struct {
|
||||
|
||||
fn addAggregateInit(
|
||||
block: *Block,
|
||||
vector_ty: Type,
|
||||
aggregate_ty: Type,
|
||||
elements: []const Air.Inst.Ref,
|
||||
) !Air.Inst.Ref {
|
||||
const sema = block.sema;
|
||||
const ty_ref = try sema.addType(vector_ty);
|
||||
const ty_ref = try sema.addType(aggregate_ty);
|
||||
try sema.air_extra.ensureUnusedCapacity(sema.gpa, elements.len);
|
||||
const extra_index = @intCast(u32, sema.air_extra.items.len);
|
||||
sema.appendRefsAssumeCapacity(elements);
|
||||
|
@ -2106,7 +2106,7 @@ pub const DeclGen = struct {
|
||||
fn llvmFieldIndex(
|
||||
dg: *DeclGen,
|
||||
ty: Type,
|
||||
field_index: u32,
|
||||
field_index: usize,
|
||||
ptr_pl_buf: *Type.Payload.Pointer,
|
||||
) ?c_uint {
|
||||
const target = dg.module.getTarget();
|
||||
@ -4921,38 +4921,37 @@ pub const FuncGen = struct {
|
||||
return vector;
|
||||
},
|
||||
.Struct => {
|
||||
const tuple = result_ty.castTag(.tuple).?.data;
|
||||
var ptr_ty_buf: Type.Payload.Pointer = undefined;
|
||||
|
||||
if (isByRef(result_ty)) {
|
||||
const llvm_u32 = self.context.intType(32);
|
||||
const alloca_inst = self.buildAlloca(llvm_result_ty);
|
||||
// TODO in debug builds init to undef so that the padding will be 0xaa
|
||||
// even if we fully populate the fields.
|
||||
const target = self.dg.module.getTarget();
|
||||
alloca_inst.setAlignment(result_ty.abiAlignment(target));
|
||||
|
||||
var indices: [2]*const llvm.Value = .{ llvm_u32.constNull(), undefined };
|
||||
var llvm_i: u32 = 0;
|
||||
|
||||
for (elements) |elem, i| {
|
||||
if (tuple.values[i].tag() != .unreachable_value) continue;
|
||||
const field_ty = tuple.types[i];
|
||||
if (result_ty.structFieldValueComptime(i) != null) continue;
|
||||
|
||||
const llvm_elem = try self.resolveInst(elem);
|
||||
const llvm_i = self.dg.llvmFieldIndex(result_ty, i, &ptr_ty_buf).?;
|
||||
indices[1] = llvm_u32.constInt(llvm_i, .False);
|
||||
llvm_i += 1;
|
||||
const field_ptr = self.builder.buildInBoundsGEP(alloca_inst, &indices, indices.len, "");
|
||||
const store_inst = self.builder.buildStore(llvm_elem, field_ptr);
|
||||
store_inst.setAlignment(field_ty.abiAlignment(target));
|
||||
store_inst.setAlignment(result_ty.structFieldAlign(i, target));
|
||||
}
|
||||
|
||||
return alloca_inst;
|
||||
} else {
|
||||
var result = llvm_result_ty.getUndef();
|
||||
var llvm_i: u32 = 0;
|
||||
for (elements) |elem, i| {
|
||||
if (tuple.values[i].tag() != .unreachable_value) continue;
|
||||
if (result_ty.structFieldValueComptime(i) != null) continue;
|
||||
|
||||
const llvm_elem = try self.resolveInst(elem);
|
||||
const llvm_i = self.dg.llvmFieldIndex(result_ty, i, &ptr_ty_buf).?;
|
||||
result = self.builder.buildInsertValue(result, llvm_elem, llvm_i, "");
|
||||
llvm_i += 1;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
49
src/type.zig
49
src/type.zig
@ -4479,6 +4479,55 @@ pub const Type = extern union {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn structFieldAlign(ty: Type, index: usize, target: Target) u32 {
|
||||
switch (ty.tag()) {
|
||||
.@"struct" => {
|
||||
const struct_obj = ty.castTag(.@"struct").?.data;
|
||||
assert(struct_obj.layout != .Packed);
|
||||
return struct_obj.fields.values()[index].normalAlignment(target);
|
||||
},
|
||||
.@"union", .union_tagged => {
|
||||
const union_obj = ty.cast(Payload.Union).?.data;
|
||||
return union_obj.fields.values()[index].normalAlignment(target);
|
||||
},
|
||||
.tuple => return ty.castTag(.tuple).?.data.types[index].abiAlignment(target),
|
||||
.anon_struct => return ty.castTag(.anon_struct).?.data.types[index].abiAlignment(target),
|
||||
else => unreachable,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn structFieldValueComptime(ty: Type, index: usize) ?Value {
|
||||
switch (ty.tag()) {
|
||||
.@"struct" => {
|
||||
const struct_obj = ty.castTag(.@"struct").?.data;
|
||||
assert(struct_obj.layout != .Packed);
|
||||
const field = struct_obj.fields.values()[index];
|
||||
if (field.is_comptime) {
|
||||
return field.default_val;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
},
|
||||
.tuple => {
|
||||
const val = ty.castTag(.tuple).?.data.values[index];
|
||||
if (val.tag() == .unreachable_value) {
|
||||
return null;
|
||||
} else {
|
||||
return val;
|
||||
}
|
||||
},
|
||||
.anon_struct => {
|
||||
const val = ty.castTag(.anon_struct).?.data.values[index];
|
||||
if (val.tag() == .unreachable_value) {
|
||||
return null;
|
||||
} else {
|
||||
return val;
|
||||
}
|
||||
},
|
||||
else => unreachable,
|
||||
}
|
||||
}
|
||||
|
||||
pub const FieldOffset = struct {
|
||||
field: usize,
|
||||
offset: u64,
|
||||
|
Loading…
Reference in New Issue
Block a user