stage2: implement zirCoerceResultPtr
and remove Module.simplePtrType and Module.ptrType in favor of `Type.ptr`.
This commit is contained in:
@@ -4460,82 +4460,6 @@ pub fn failWithOwnedErrorMsg(mod: *Module, scope: *Scope, err_msg: *ErrorMsg) Co
|
||||
return error.AnalysisFail;
|
||||
}
|
||||
|
||||
pub fn simplePtrType(
|
||||
arena: *Allocator,
|
||||
elem_ty: Type,
|
||||
mutable: bool,
|
||||
size: std.builtin.TypeInfo.Pointer.Size,
|
||||
@"addrspace": std.builtin.AddressSpace,
|
||||
) Allocator.Error!Type {
|
||||
return ptrType(
|
||||
arena,
|
||||
elem_ty,
|
||||
null,
|
||||
0,
|
||||
@"addrspace",
|
||||
0,
|
||||
0,
|
||||
mutable,
|
||||
false,
|
||||
false,
|
||||
size,
|
||||
);
|
||||
}
|
||||
|
||||
pub fn ptrType(
|
||||
arena: *Allocator,
|
||||
elem_ty: Type,
|
||||
sentinel: ?Value,
|
||||
@"align": u32,
|
||||
@"addrspace": std.builtin.AddressSpace,
|
||||
bit_offset: u16,
|
||||
host_size: u16,
|
||||
mutable: bool,
|
||||
@"allowzero": bool,
|
||||
@"volatile": bool,
|
||||
size: std.builtin.TypeInfo.Pointer.Size,
|
||||
) Allocator.Error!Type {
|
||||
assert(host_size == 0 or bit_offset < host_size * 8);
|
||||
|
||||
if (sentinel != null or @"align" != 0 or @"addrspace" != .generic or
|
||||
bit_offset != 0 or host_size != 0 or @"allowzero" or @"volatile")
|
||||
{
|
||||
return Type.Tag.pointer.create(arena, .{
|
||||
.pointee_type = elem_ty,
|
||||
.sentinel = sentinel,
|
||||
.@"align" = @"align",
|
||||
.@"addrspace" = @"addrspace",
|
||||
.bit_offset = bit_offset,
|
||||
.host_size = host_size,
|
||||
.@"allowzero" = @"allowzero",
|
||||
.mutable = mutable,
|
||||
.@"volatile" = @"volatile",
|
||||
.size = size,
|
||||
});
|
||||
}
|
||||
|
||||
if (!mutable and size == .Slice and elem_ty.eql(Type.initTag(.u8))) {
|
||||
return Type.initTag(.const_slice_u8);
|
||||
}
|
||||
|
||||
// TODO stage1 type inference bug
|
||||
const T = Type.Tag;
|
||||
|
||||
const type_payload = try arena.create(Type.Payload.ElemType);
|
||||
type_payload.* = .{
|
||||
.base = .{
|
||||
.tag = switch (size) {
|
||||
.One => if (mutable) T.single_mut_pointer else T.single_const_pointer,
|
||||
.Many => if (mutable) T.many_mut_pointer else T.many_const_pointer,
|
||||
.C => if (mutable) T.c_mut_pointer else T.c_const_pointer,
|
||||
.Slice => if (mutable) T.mut_slice else T.const_slice,
|
||||
},
|
||||
},
|
||||
.data = elem_ty,
|
||||
};
|
||||
return Type.initPayload(&type_payload.base);
|
||||
}
|
||||
|
||||
pub fn optionalType(arena: *Allocator, child_type: Type) Allocator.Error!Type {
|
||||
switch (child_type.tag()) {
|
||||
.single_const_pointer => return Type.Tag.optional_single_const_pointer.create(
|
||||
|
||||
306
src/Sema.zig
306
src/Sema.zig
@@ -979,10 +979,38 @@ fn zirBitcastResultPtr(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) C
|
||||
}
|
||||
|
||||
fn zirCoerceResultPtr(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
|
||||
_ = inst;
|
||||
const tracy = trace(@src());
|
||||
defer tracy.end();
|
||||
return sema.mod.fail(&block.base, sema.src, "TODO implement zirCoerceResultPtr", .{});
|
||||
|
||||
const src: LazySrcLoc = sema.src;
|
||||
const bin_inst = sema.code.instructions.items(.data)[inst].bin;
|
||||
const pointee_ty = try sema.resolveType(block, src, bin_inst.lhs);
|
||||
const ptr = sema.resolveInst(bin_inst.rhs);
|
||||
|
||||
// Create a runtime bitcast instruction with exactly the type the pointer wants.
|
||||
const ptr_ty = try Type.ptr(sema.arena, .{
|
||||
.pointee_type = pointee_ty,
|
||||
.@"addrspace" = target_util.defaultAddressSpace(sema.mod.getTarget(), .local),
|
||||
});
|
||||
try sema.requireRuntimeBlock(block, src);
|
||||
const bitcasted_ptr = try block.addTyOp(.bitcast, ptr_ty, ptr);
|
||||
|
||||
if (Air.refToIndex(ptr)) |ptr_inst| {
|
||||
if (sema.air_instructions.items(.tag)[ptr_inst] == .constant) {
|
||||
const air_datas = sema.air_instructions.items(.data);
|
||||
const ptr_val = sema.air_values.items[air_datas[ptr_inst].ty_pl.payload];
|
||||
if (ptr_val.castTag(.inferred_alloc)) |inferred_alloc| {
|
||||
// Add the stored instruction to the set we will use to resolve peer types
|
||||
// for the inferred allocation.
|
||||
// This instruction will not make it to codegen; it is only to participate
|
||||
// in the `stored_inst_list` of the `inferred_alloc`.
|
||||
const operand = try block.addTyOp(.bitcast, pointee_ty, .void_value);
|
||||
try inferred_alloc.data.stored_inst_list.append(sema.arena, operand);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return bitcasted_ptr;
|
||||
}
|
||||
|
||||
pub fn analyzeStructDecl(
|
||||
@@ -1427,13 +1455,10 @@ fn zirRetPtr(
|
||||
return sema.analyzeComptimeAlloc(block, sema.fn_ret_ty);
|
||||
}
|
||||
|
||||
const ptr_type = try Module.simplePtrType(
|
||||
sema.arena,
|
||||
sema.fn_ret_ty,
|
||||
true,
|
||||
.One,
|
||||
target_util.defaultAddressSpace(sema.mod.getTarget(), .local),
|
||||
);
|
||||
const ptr_type = try Type.ptr(sema.arena, .{
|
||||
.pointee_type = sema.fn_ret_ty,
|
||||
.@"addrspace" = target_util.defaultAddressSpace(sema.mod.getTarget(), .local),
|
||||
});
|
||||
return block.addTy(.alloc, ptr_type);
|
||||
}
|
||||
|
||||
@@ -1581,13 +1606,10 @@ fn zirAlloc(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileError
|
||||
const ty_src: LazySrcLoc = .{ .node_offset_var_decl_ty = inst_data.src_node };
|
||||
const var_decl_src = inst_data.src();
|
||||
const var_type = try sema.resolveType(block, ty_src, inst_data.operand);
|
||||
const ptr_type = try Module.simplePtrType(
|
||||
sema.arena,
|
||||
var_type,
|
||||
true,
|
||||
.One,
|
||||
target_util.defaultAddressSpace(sema.mod.getTarget(), .local),
|
||||
);
|
||||
const ptr_type = try Type.ptr(sema.arena, .{
|
||||
.pointee_type = var_type,
|
||||
.@"addrspace" = target_util.defaultAddressSpace(sema.mod.getTarget(), .local),
|
||||
});
|
||||
try sema.requireRuntimeBlock(block, var_decl_src);
|
||||
return block.addTy(.alloc, ptr_type);
|
||||
}
|
||||
@@ -1604,13 +1626,10 @@ fn zirAllocMut(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileEr
|
||||
return sema.analyzeComptimeAlloc(block, var_type);
|
||||
}
|
||||
try sema.validateVarType(block, ty_src, var_type);
|
||||
const ptr_type = try Module.simplePtrType(
|
||||
sema.arena,
|
||||
var_type,
|
||||
true,
|
||||
.One,
|
||||
target_util.defaultAddressSpace(sema.mod.getTarget(), .local),
|
||||
);
|
||||
const ptr_type = try Type.ptr(sema.arena, .{
|
||||
.pointee_type = var_type,
|
||||
.@"addrspace" = target_util.defaultAddressSpace(sema.mod.getTarget(), .local),
|
||||
});
|
||||
try sema.requireRuntimeBlock(block, var_decl_src);
|
||||
return block.addTy(.alloc, ptr_type);
|
||||
}
|
||||
@@ -1670,13 +1689,10 @@ fn zirResolveInferredAlloc(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Inde
|
||||
try sema.mod.declareDeclDependency(sema.owner_decl, decl);
|
||||
|
||||
const final_elem_ty = try decl.ty.copy(sema.arena);
|
||||
const final_ptr_ty = try Module.simplePtrType(
|
||||
sema.arena,
|
||||
final_elem_ty,
|
||||
true,
|
||||
.One,
|
||||
target_util.defaultAddressSpace(sema.mod.getTarget(), .local),
|
||||
);
|
||||
const final_ptr_ty = try Type.ptr(sema.arena, .{
|
||||
.pointee_type = final_elem_ty,
|
||||
.@"addrspace" = target_util.defaultAddressSpace(sema.mod.getTarget(), .local),
|
||||
});
|
||||
const final_ptr_ty_inst = try sema.addType(final_ptr_ty);
|
||||
sema.air_instructions.items(.data)[ptr_inst].ty_pl.ty = final_ptr_ty_inst;
|
||||
|
||||
@@ -1698,13 +1714,10 @@ fn zirResolveInferredAlloc(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Inde
|
||||
try sema.validateVarType(block, ty_src, final_elem_ty);
|
||||
}
|
||||
// Change it to a normal alloc.
|
||||
const final_ptr_ty = try Module.simplePtrType(
|
||||
sema.arena,
|
||||
final_elem_ty,
|
||||
true,
|
||||
.One,
|
||||
target_util.defaultAddressSpace(sema.mod.getTarget(), .local),
|
||||
);
|
||||
const final_ptr_ty = try Type.ptr(sema.arena, .{
|
||||
.pointee_type = final_elem_ty,
|
||||
.@"addrspace" = target_util.defaultAddressSpace(sema.mod.getTarget(), .local),
|
||||
});
|
||||
sema.air_instructions.set(ptr_inst, .{
|
||||
.tag = .alloc,
|
||||
.data = .{ .ty = final_ptr_ty },
|
||||
@@ -1858,14 +1871,11 @@ fn zirStoreToBlockPtr(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) Co
|
||||
}
|
||||
const ptr = sema.resolveInst(bin_inst.lhs);
|
||||
const value = sema.resolveInst(bin_inst.rhs);
|
||||
const ptr_ty = try Module.simplePtrType(
|
||||
sema.arena,
|
||||
sema.typeOf(value),
|
||||
true,
|
||||
.One,
|
||||
const ptr_ty = try Type.ptr(sema.arena, .{
|
||||
.pointee_type = sema.typeOf(value),
|
||||
// TODO figure out which address space is appropriate here
|
||||
target_util.defaultAddressSpace(sema.mod.getTarget(), .local),
|
||||
);
|
||||
.@"addrspace" = target_util.defaultAddressSpace(sema.mod.getTarget(), .local),
|
||||
});
|
||||
// TODO detect when this store should be done at compile-time. For example,
|
||||
// if expressions should force it when the condition is compile-time known.
|
||||
const src: LazySrcLoc = .unneeded;
|
||||
@@ -1912,14 +1922,10 @@ fn zirStoreToInferredPtr(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index)
|
||||
// for the inferred allocation.
|
||||
try inferred_alloc.data.stored_inst_list.append(sema.arena, operand);
|
||||
// Create a runtime bitcast instruction with exactly the type the pointer wants.
|
||||
const ptr_ty = try Module.simplePtrType(
|
||||
sema.arena,
|
||||
operand_ty,
|
||||
true,
|
||||
.One,
|
||||
// TODO figure out which address space is appropriate here
|
||||
target_util.defaultAddressSpace(sema.mod.getTarget(), .local),
|
||||
);
|
||||
const ptr_ty = try Type.ptr(sema.arena, .{
|
||||
.pointee_type = operand_ty,
|
||||
.@"addrspace" = target_util.defaultAddressSpace(sema.mod.getTarget(), .local),
|
||||
});
|
||||
const bitcasted_ptr = try block.addTyOp(.bitcast, ptr_ty, ptr);
|
||||
return sema.storePtr(block, src, bitcasted_ptr, operand);
|
||||
}
|
||||
@@ -3845,13 +3851,11 @@ fn zirOptionalPayloadPtr(
|
||||
}
|
||||
|
||||
const child_type = try opt_type.optionalChildAlloc(sema.arena);
|
||||
const child_pointer = try Module.simplePtrType(
|
||||
sema.arena,
|
||||
child_type,
|
||||
!optional_ptr_ty.isConstPtr(),
|
||||
.One,
|
||||
optional_ptr_ty.ptrAddressSpace(),
|
||||
);
|
||||
const child_pointer = try Type.ptr(sema.arena, .{
|
||||
.pointee_type = child_type,
|
||||
.mutable = !optional_ptr_ty.isConstPtr(),
|
||||
.@"addrspace" = optional_ptr_ty.ptrAddressSpace(),
|
||||
});
|
||||
|
||||
if (try sema.resolveDefinedValue(block, src, optional_ptr)) |pointer_val| {
|
||||
if (try pointer_val.pointerDeref(sema.arena)) |val| {
|
||||
@@ -3966,13 +3970,11 @@ fn zirErrUnionPayloadPtr(
|
||||
return sema.mod.fail(&block.base, src, "expected error union type, found {}", .{operand_ty.elemType()});
|
||||
|
||||
const payload_ty = operand_ty.elemType().errorUnionPayload();
|
||||
const operand_pointer_ty = try Module.simplePtrType(
|
||||
sema.arena,
|
||||
payload_ty,
|
||||
!operand_ty.isConstPtr(),
|
||||
.One,
|
||||
operand_ty.ptrAddressSpace(),
|
||||
);
|
||||
const operand_pointer_ty = try Type.ptr(sema.arena, .{
|
||||
.pointee_type = payload_ty,
|
||||
.mutable = !operand_ty.isConstPtr(),
|
||||
.@"addrspace" = operand_ty.ptrAddressSpace(),
|
||||
});
|
||||
|
||||
if (try sema.resolveDefinedValue(block, src, operand)) |pointer_val| {
|
||||
if (try pointer_val.pointerDeref(sema.arena)) |val| {
|
||||
@@ -7306,19 +7308,14 @@ fn zirPtrTypeSimple(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) Comp
|
||||
|
||||
const inst_data = sema.code.instructions.items(.data)[inst].ptr_type_simple;
|
||||
const elem_type = try sema.resolveType(block, .unneeded, inst_data.elem_type);
|
||||
const ty = try Module.ptrType(
|
||||
sema.arena,
|
||||
elem_type,
|
||||
null,
|
||||
0,
|
||||
.generic,
|
||||
0,
|
||||
0,
|
||||
inst_data.is_mutable,
|
||||
inst_data.is_allowzero,
|
||||
inst_data.is_volatile,
|
||||
inst_data.size,
|
||||
);
|
||||
const ty = try Type.ptr(sema.arena, .{
|
||||
.pointee_type = elem_type,
|
||||
.@"addrspace" = .generic,
|
||||
.mutable = inst_data.is_mutable,
|
||||
.@"allowzero" = inst_data.is_allowzero,
|
||||
.@"volatile" = inst_data.is_volatile,
|
||||
.size = inst_data.size,
|
||||
});
|
||||
return sema.addType(ty);
|
||||
}
|
||||
|
||||
@@ -7367,19 +7364,18 @@ fn zirPtrType(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileErr
|
||||
|
||||
const elem_type = try sema.resolveType(block, .unneeded, extra.data.elem_type);
|
||||
|
||||
const ty = try Module.ptrType(
|
||||
sema.arena,
|
||||
elem_type,
|
||||
sentinel,
|
||||
abi_align,
|
||||
address_space,
|
||||
bit_start,
|
||||
bit_end,
|
||||
inst_data.flags.is_mutable,
|
||||
inst_data.flags.is_allowzero,
|
||||
inst_data.flags.is_volatile,
|
||||
inst_data.size,
|
||||
);
|
||||
const ty = try Type.ptr(sema.arena, .{
|
||||
.pointee_type = elem_type,
|
||||
.sentinel = sentinel,
|
||||
.@"align" = abi_align,
|
||||
.@"addrspace" = address_space,
|
||||
.bit_offset = bit_start,
|
||||
.host_size = bit_end,
|
||||
.mutable = inst_data.flags.is_mutable,
|
||||
.@"allowzero" = inst_data.flags.is_allowzero,
|
||||
.@"volatile" = inst_data.flags.is_volatile,
|
||||
.size = inst_data.size,
|
||||
});
|
||||
return sema.addType(ty);
|
||||
}
|
||||
|
||||
@@ -8456,19 +8452,15 @@ fn zirMemcpy(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileErro
|
||||
});
|
||||
}
|
||||
const src_ptr_info = uncasted_src_ptr_ty.ptrInfo().data;
|
||||
const wanted_src_ptr_ty = try Module.ptrType(
|
||||
sema.arena,
|
||||
dest_ptr_ty.elemType2(),
|
||||
null,
|
||||
src_ptr_info.@"align",
|
||||
src_ptr_info.@"addrspace",
|
||||
0,
|
||||
0,
|
||||
false,
|
||||
src_ptr_info.@"allowzero",
|
||||
src_ptr_info.@"volatile",
|
||||
.Many,
|
||||
);
|
||||
const wanted_src_ptr_ty = try Type.ptr(sema.arena, .{
|
||||
.pointee_type = dest_ptr_ty.elemType2(),
|
||||
.@"align" = src_ptr_info.@"align",
|
||||
.@"addrspace" = src_ptr_info.@"addrspace",
|
||||
.mutable = false,
|
||||
.@"allowzero" = src_ptr_info.@"allowzero",
|
||||
.@"volatile" = src_ptr_info.@"volatile",
|
||||
.size = .Many,
|
||||
});
|
||||
const src_ptr = try sema.coerce(block, wanted_src_ptr_ty, uncasted_src_ptr, src_src);
|
||||
const len = try sema.coerce(block, Type.initTag(.usize), sema.resolveInst(extra.byte_count), len_src);
|
||||
|
||||
@@ -8922,13 +8914,10 @@ fn panicWithMsg(
|
||||
const panic_fn = try sema.getBuiltin(block, src, "panic");
|
||||
const unresolved_stack_trace_ty = try sema.getBuiltinType(block, src, "StackTrace");
|
||||
const stack_trace_ty = try sema.resolveTypeFields(block, src, unresolved_stack_trace_ty);
|
||||
const ptr_stack_trace_ty = try Module.simplePtrType(
|
||||
arena,
|
||||
stack_trace_ty,
|
||||
true,
|
||||
.One,
|
||||
target_util.defaultAddressSpace(sema.mod.getTarget(), .global_constant), // TODO might need a place that is more dynamic
|
||||
);
|
||||
const ptr_stack_trace_ty = try Type.ptr(arena, .{
|
||||
.pointee_type = stack_trace_ty,
|
||||
.@"addrspace" = target_util.defaultAddressSpace(sema.mod.getTarget(), .global_constant), // TODO might need a place that is more dynamic
|
||||
});
|
||||
const null_stack_trace = try sema.addConstant(
|
||||
try Module.optionalType(arena, ptr_stack_trace_ty),
|
||||
Value.initTag(.null_value),
|
||||
@@ -9407,13 +9396,11 @@ fn structFieldPtr(
|
||||
const field_index = struct_obj.fields.getIndex(field_name) orelse
|
||||
return sema.failWithBadFieldAccess(block, struct_obj, field_name_src, field_name);
|
||||
const field = struct_obj.fields.values()[field_index];
|
||||
const ptr_field_ty = try Module.simplePtrType(
|
||||
arena,
|
||||
field.ty,
|
||||
struct_ptr_ty.ptrIsMutable(),
|
||||
.One,
|
||||
struct_ptr_ty.ptrAddressSpace(),
|
||||
);
|
||||
const ptr_field_ty = try Type.ptr(arena, .{
|
||||
.pointee_type = field.ty,
|
||||
.mutable = struct_ptr_ty.ptrIsMutable(),
|
||||
.@"addrspace" = struct_ptr_ty.ptrAddressSpace(),
|
||||
});
|
||||
|
||||
if (try sema.resolveDefinedValue(block, src, struct_ptr)) |struct_ptr_val| {
|
||||
return sema.addConstant(
|
||||
@@ -9512,13 +9499,11 @@ fn unionFieldPtr(
|
||||
return sema.failWithBadUnionFieldAccess(block, union_obj, field_name_src, field_name);
|
||||
|
||||
const field = union_obj.fields.values()[field_index];
|
||||
const ptr_field_ty = try Module.simplePtrType(
|
||||
arena,
|
||||
field.ty,
|
||||
union_ptr_ty.ptrIsMutable(),
|
||||
.One,
|
||||
union_ptr_ty.ptrAddressSpace(),
|
||||
);
|
||||
const ptr_field_ty = try Type.ptr(arena, .{
|
||||
.pointee_type = field.ty,
|
||||
.mutable = union_ptr_ty.ptrIsMutable(),
|
||||
.@"addrspace" = union_ptr_ty.ptrAddressSpace(),
|
||||
});
|
||||
|
||||
if (try sema.resolveDefinedValue(block, src, union_ptr)) |union_ptr_val| {
|
||||
// TODO detect inactive union field and emit compile error
|
||||
@@ -9694,13 +9679,11 @@ fn elemPtrArray(
|
||||
) CompileError!Air.Inst.Ref {
|
||||
const array_ptr_ty = sema.typeOf(array_ptr);
|
||||
const pointee_type = array_ptr_ty.elemType().elemType();
|
||||
const result_ty = try Module.simplePtrType(
|
||||
sema.arena,
|
||||
pointee_type,
|
||||
array_ptr_ty.ptrIsMutable(),
|
||||
.One,
|
||||
array_ptr_ty.ptrAddressSpace(),
|
||||
);
|
||||
const result_ty = try Type.ptr(sema.arena, .{
|
||||
.pointee_type = pointee_type,
|
||||
.mutable = array_ptr_ty.ptrIsMutable(),
|
||||
.@"addrspace" = array_ptr_ty.ptrAddressSpace(),
|
||||
});
|
||||
|
||||
if (try sema.resolveDefinedValue(block, src, array_ptr)) |array_ptr_val| {
|
||||
if (try sema.resolveDefinedValue(block, elem_index_src, elem_index)) |index_val| {
|
||||
@@ -10243,11 +10226,19 @@ fn analyzeDeclRef(sema: *Sema, decl: *Decl) CompileError!Air.Inst.Ref {
|
||||
const decl_tv = try decl.typedValue();
|
||||
if (decl_tv.val.castTag(.variable)) |payload| {
|
||||
const variable = payload.data;
|
||||
const ty = try Module.simplePtrType(sema.arena, decl_tv.ty, variable.is_mutable, .One, decl.@"addrspace");
|
||||
const ty = try Type.ptr(sema.arena, .{
|
||||
.pointee_type = decl_tv.ty,
|
||||
.mutable = variable.is_mutable,
|
||||
.@"addrspace" = decl.@"addrspace",
|
||||
});
|
||||
return sema.addConstant(ty, try Value.Tag.decl_ref.create(sema.arena, decl));
|
||||
}
|
||||
return sema.addConstant(
|
||||
try Module.simplePtrType(sema.arena, decl_tv.ty, false, .One, decl.@"addrspace"),
|
||||
try Type.ptr(sema.arena, .{
|
||||
.pointee_type = decl_tv.ty,
|
||||
.mutable = false,
|
||||
.@"addrspace" = decl.@"addrspace",
|
||||
}),
|
||||
try Value.Tag.decl_ref.create(sema.arena, decl),
|
||||
);
|
||||
}
|
||||
@@ -10271,8 +10262,15 @@ fn analyzeRef(
|
||||
|
||||
try sema.requireRuntimeBlock(block, src);
|
||||
const address_space = target_util.defaultAddressSpace(sema.mod.getTarget(), .local);
|
||||
const ptr_type = try Module.simplePtrType(sema.arena, operand_ty, false, .One, address_space);
|
||||
const mut_ptr_type = try Module.simplePtrType(sema.arena, operand_ty, true, .One, address_space);
|
||||
const ptr_type = try Type.ptr(sema.arena, .{
|
||||
.pointee_type = operand_ty,
|
||||
.mutable = false,
|
||||
.@"addrspace" = address_space,
|
||||
});
|
||||
const mut_ptr_type = try Type.ptr(sema.arena, .{
|
||||
.pointee_type = operand_ty,
|
||||
.@"addrspace" = address_space,
|
||||
});
|
||||
const alloc = try block.addTy(.alloc, mut_ptr_type);
|
||||
try sema.storePtr(block, src, alloc, operand);
|
||||
|
||||
@@ -10428,19 +10426,16 @@ fn analyzeSlice(
|
||||
}
|
||||
}
|
||||
}
|
||||
const return_type = try Module.ptrType(
|
||||
sema.arena,
|
||||
return_elem_type,
|
||||
if (end_opt == .none) slice_sentinel else null,
|
||||
0, // TODO alignment
|
||||
if (ptr_child.zigTypeTag() == .Pointer) ptr_child.ptrAddressSpace() else .generic,
|
||||
0,
|
||||
0,
|
||||
!ptr_child.isConstPtr(),
|
||||
ptr_child.isAllowzeroPtr(),
|
||||
ptr_child.isVolatilePtr(),
|
||||
return_ptr_size,
|
||||
);
|
||||
const return_type = try Type.ptr(sema.arena, .{
|
||||
.pointee_type = return_elem_type,
|
||||
.sentinel = if (end_opt == .none) slice_sentinel else null,
|
||||
.@"align" = 0, // TODO alignment
|
||||
.@"addrspace" = if (ptr_child.zigTypeTag() == .Pointer) ptr_child.ptrAddressSpace() else .generic,
|
||||
.mutable = !ptr_child.isConstPtr(),
|
||||
.@"allowzero" = ptr_child.isAllowzeroPtr(),
|
||||
.@"volatile" = ptr_child.isVolatilePtr(),
|
||||
.size = return_ptr_size,
|
||||
});
|
||||
_ = return_type;
|
||||
|
||||
return sema.mod.fail(&block.base, src, "TODO implement analysis of slice", .{});
|
||||
@@ -11626,13 +11621,10 @@ fn analyzeComptimeAlloc(
|
||||
block: *Scope.Block,
|
||||
var_type: Type,
|
||||
) CompileError!Air.Inst.Ref {
|
||||
const ptr_type = try Module.simplePtrType(
|
||||
sema.arena,
|
||||
var_type,
|
||||
true,
|
||||
.One,
|
||||
target_util.defaultAddressSpace(sema.mod.getTarget(), .global_constant),
|
||||
);
|
||||
const ptr_type = try Type.ptr(sema.arena, .{
|
||||
.pointee_type = var_type,
|
||||
.@"addrspace" = target_util.defaultAddressSpace(sema.mod.getTarget(), .global_constant),
|
||||
});
|
||||
|
||||
var anon_decl = try block.startAnonDecl();
|
||||
defer anon_decl.deinit();
|
||||
|
||||
61
src/type.zig
61
src/type.zig
@@ -3652,12 +3652,12 @@ pub const Type = extern union {
|
||||
}
|
||||
|
||||
pub fn create(comptime t: Tag, ally: *Allocator, data: Data(t)) error{OutOfMemory}!file_struct.Type {
|
||||
const ptr = try ally.create(t.Type());
|
||||
ptr.* = .{
|
||||
const p = try ally.create(t.Type());
|
||||
p.* = .{
|
||||
.base = .{ .tag = t },
|
||||
.data = data,
|
||||
};
|
||||
return file_struct.Type{ .ptr_otherwise = &ptr.base };
|
||||
return file_struct.Type{ .ptr_otherwise = &p.base };
|
||||
}
|
||||
|
||||
pub fn Data(comptime t: Tag) type {
|
||||
@@ -3747,19 +3747,23 @@ pub const Type = extern union {
|
||||
pub const base_tag = Tag.pointer;
|
||||
|
||||
base: Payload = Payload{ .tag = base_tag },
|
||||
data: struct {
|
||||
data: Data,
|
||||
|
||||
pub const Data = struct {
|
||||
pointee_type: Type,
|
||||
sentinel: ?Value,
|
||||
sentinel: ?Value = null,
|
||||
/// If zero use pointee_type.AbiAlign()
|
||||
@"align": u32,
|
||||
@"align": u32 = 0,
|
||||
/// See src/target.zig defaultAddressSpace function for how to obtain
|
||||
/// an appropriate value for this field.
|
||||
@"addrspace": std.builtin.AddressSpace,
|
||||
bit_offset: u16,
|
||||
host_size: u16,
|
||||
@"allowzero": bool,
|
||||
mutable: bool,
|
||||
@"volatile": bool,
|
||||
size: std.builtin.TypeInfo.Pointer.Size,
|
||||
},
|
||||
bit_offset: u16 = 0,
|
||||
host_size: u16 = 0,
|
||||
@"allowzero": bool = false,
|
||||
mutable: bool = true, // TODO change this to const, not mutable
|
||||
@"volatile": bool = false,
|
||||
size: std.builtin.TypeInfo.Pointer.Size = .One,
|
||||
};
|
||||
};
|
||||
|
||||
pub const ErrorUnion = struct {
|
||||
@@ -3815,6 +3819,37 @@ pub const Type = extern union {
|
||||
data: *Module.EnumSimple,
|
||||
};
|
||||
};
|
||||
|
||||
pub fn ptr(arena: *Allocator, d: Payload.Pointer.Data) !Type {
|
||||
assert(d.host_size == 0 or d.bit_offset < d.host_size * 8);
|
||||
|
||||
if (d.sentinel != null or d.@"align" != 0 or d.@"addrspace" != .generic or
|
||||
d.bit_offset != 0 or d.host_size != 0 or d.@"allowzero" or d.@"volatile")
|
||||
{
|
||||
return Type.Tag.pointer.create(arena, d);
|
||||
}
|
||||
|
||||
if (!d.mutable and d.size == .Slice and d.pointee_type.eql(Type.initTag(.u8))) {
|
||||
return Type.initTag(.const_slice_u8);
|
||||
}
|
||||
|
||||
// TODO stage1 type inference bug
|
||||
const T = Type.Tag;
|
||||
|
||||
const type_payload = try arena.create(Type.Payload.ElemType);
|
||||
type_payload.* = .{
|
||||
.base = .{
|
||||
.tag = switch (d.size) {
|
||||
.One => if (d.mutable) T.single_mut_pointer else T.single_const_pointer,
|
||||
.Many => if (d.mutable) T.many_mut_pointer else T.many_const_pointer,
|
||||
.C => if (d.mutable) T.c_mut_pointer else T.c_const_pointer,
|
||||
.Slice => if (d.mutable) T.mut_slice else T.const_slice,
|
||||
},
|
||||
},
|
||||
.data = d.pointee_type,
|
||||
};
|
||||
return Type.initPayload(&type_payload.base);
|
||||
}
|
||||
};
|
||||
|
||||
pub const CType = enum {
|
||||
|
||||
@@ -52,3 +52,41 @@ fn testFoo(foo: StructFoo) !void {
|
||||
fn testMutation(foo: *StructFoo) void {
|
||||
foo.c = 100;
|
||||
}
|
||||
|
||||
test "struct byval assign" {
|
||||
var foo1: StructFoo = undefined;
|
||||
var foo2: StructFoo = undefined;
|
||||
|
||||
foo1.a = 1234;
|
||||
foo2.a = 0;
|
||||
try expect(foo2.a == 0);
|
||||
foo2 = foo1;
|
||||
try expect(foo2.a == 1234);
|
||||
}
|
||||
|
||||
const Node = struct {
|
||||
val: Val,
|
||||
next: *Node,
|
||||
};
|
||||
|
||||
const Val = struct {
|
||||
x: i32,
|
||||
};
|
||||
|
||||
test "struct initializer" {
|
||||
const val = Val{ .x = 42 };
|
||||
try expect(val.x == 42);
|
||||
}
|
||||
|
||||
const MemberFnTestFoo = struct {
|
||||
x: i32,
|
||||
fn member(foo: MemberFnTestFoo) i32 {
|
||||
return foo.x;
|
||||
}
|
||||
};
|
||||
|
||||
test "call member function directly" {
|
||||
const instance = MemberFnTestFoo{ .x = 1234 };
|
||||
const result = MemberFnTestFoo.member(instance);
|
||||
try expect(result == 1234);
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ const expect = std.testing.expect;
|
||||
const expectEqual = std.testing.expectEqual;
|
||||
const expectEqualSlices = std.testing.expectEqualSlices;
|
||||
const maxInt = std.math.maxInt;
|
||||
|
||||
top_level_field: i32,
|
||||
|
||||
test "top level fields" {
|
||||
@@ -58,22 +59,6 @@ test "struct point to self" {
|
||||
try expect(node.next.next.next.val.x == 1);
|
||||
}
|
||||
|
||||
test "struct byval assign" {
|
||||
var foo1: StructFoo = undefined;
|
||||
var foo2: StructFoo = undefined;
|
||||
|
||||
foo1.a = 1234;
|
||||
foo2.a = 0;
|
||||
try expect(foo2.a == 0);
|
||||
foo2 = foo1;
|
||||
try expect(foo2.a == 1234);
|
||||
}
|
||||
|
||||
test "struct initializer" {
|
||||
const val = Val{ .x = 42 };
|
||||
try expect(val.x == 42);
|
||||
}
|
||||
|
||||
test "fn call of struct field" {
|
||||
const Foo = struct {
|
||||
ptr: fn () i32,
|
||||
@@ -91,22 +76,16 @@ test "fn call of struct field" {
|
||||
try expect(S.callStructField(Foo{ .ptr = S.aFunc }) == 13);
|
||||
}
|
||||
|
||||
test "store member function in variable" {
|
||||
const instance = MemberFnTestFoo{ .x = 1234 };
|
||||
const memberFn = MemberFnTestFoo.member;
|
||||
const result = memberFn(instance);
|
||||
try expect(result == 1234);
|
||||
}
|
||||
const MemberFnTestFoo = struct {
|
||||
x: i32,
|
||||
fn member(foo: MemberFnTestFoo) i32 {
|
||||
return foo.x;
|
||||
}
|
||||
};
|
||||
|
||||
test "call member function directly" {
|
||||
test "store member function in variable" {
|
||||
const instance = MemberFnTestFoo{ .x = 1234 };
|
||||
const result = MemberFnTestFoo.member(instance);
|
||||
const memberFn = MemberFnTestFoo.member;
|
||||
const result = memberFn(instance);
|
||||
try expect(result == 1234);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user