parent
1cb19d1a46
commit
d5e788072d
|
@ -322,6 +322,7 @@ enum LazyValueId {
|
|||
LazyValueIdSliceType,
|
||||
LazyValueIdFnType,
|
||||
LazyValueIdErrUnionType,
|
||||
LazyValueIdArrayType,
|
||||
};
|
||||
|
||||
struct LazyValue {
|
||||
|
@ -355,6 +356,15 @@ struct LazyValueSliceType {
|
|||
bool is_allowzero;
|
||||
};
|
||||
|
||||
struct LazyValueArrayType {
|
||||
LazyValue base;
|
||||
|
||||
IrAnalyze *ira;
|
||||
IrInstruction *sentinel; // can be null
|
||||
IrInstruction *elem_type;
|
||||
uint64_t length;
|
||||
};
|
||||
|
||||
struct LazyValuePtrType {
|
||||
LazyValue base;
|
||||
|
||||
|
|
|
@ -1147,6 +1147,21 @@ Error type_val_resolve_zero_bits(CodeGen *g, ZigValue *type_val, ZigType *parent
|
|||
parent_type_val, is_zero_bits);
|
||||
}
|
||||
}
|
||||
case LazyValueIdArrayType: {
|
||||
LazyValueArrayType *lazy_array_type =
|
||||
reinterpret_cast<LazyValueArrayType *>(type_val->data.x_lazy);
|
||||
|
||||
if (lazy_array_type->length < 1) {
|
||||
*is_zero_bits = true;
|
||||
return ErrorNone;
|
||||
}
|
||||
|
||||
if ((err = type_val_resolve_zero_bits(g, lazy_array_type->elem_type->value,
|
||||
parent_type, nullptr, is_zero_bits)))
|
||||
return err;
|
||||
|
||||
return ErrorNone;
|
||||
}
|
||||
case LazyValueIdOptType:
|
||||
case LazyValueIdSliceType:
|
||||
case LazyValueIdErrUnionType:
|
||||
|
@ -1181,6 +1196,7 @@ Error type_val_resolve_is_opaque_type(CodeGen *g, ZigValue *type_val, bool *is_o
|
|||
case LazyValueIdFnType:
|
||||
case LazyValueIdOptType:
|
||||
case LazyValueIdErrUnionType:
|
||||
case LazyValueIdArrayType:
|
||||
*is_opaque_type = false;
|
||||
return ErrorNone;
|
||||
}
|
||||
|
@ -1208,6 +1224,10 @@ static ReqCompTime type_val_resolve_requires_comptime(CodeGen *g, ZigValue *type
|
|||
LazyValueOptType *lazy_opt_type = reinterpret_cast<LazyValueOptType *>(type_val->data.x_lazy);
|
||||
return type_val_resolve_requires_comptime(g, lazy_opt_type->payload_type->value);
|
||||
}
|
||||
case LazyValueIdArrayType: {
|
||||
LazyValueArrayType *lazy_array_type = reinterpret_cast<LazyValueArrayType *>(type_val->data.x_lazy);
|
||||
return type_val_resolve_requires_comptime(g, lazy_array_type->elem_type->value);
|
||||
}
|
||||
case LazyValueIdFnType: {
|
||||
LazyValueFnType *lazy_fn_type = reinterpret_cast<LazyValueFnType *>(type_val->data.x_lazy);
|
||||
if (lazy_fn_type->is_generic)
|
||||
|
@ -1305,6 +1325,7 @@ start_over:
|
|||
return ErrorNone;
|
||||
case LazyValueIdOptType:
|
||||
case LazyValueIdErrUnionType:
|
||||
case LazyValueIdArrayType:
|
||||
if ((err = ir_resolve_lazy(g, source_node, type_val)))
|
||||
return err;
|
||||
goto start_over;
|
||||
|
@ -1340,6 +1361,11 @@ Error type_val_resolve_abi_align(CodeGen *g, ZigValue *type_val, uint32_t *abi_a
|
|||
LazyValueOptType *lazy_opt_type = reinterpret_cast<LazyValueOptType *>(type_val->data.x_lazy);
|
||||
return type_val_resolve_abi_align(g, lazy_opt_type->payload_type->value, abi_align);
|
||||
}
|
||||
case LazyValueIdArrayType: {
|
||||
LazyValueArrayType *lazy_array_type =
|
||||
reinterpret_cast<LazyValueArrayType *>(type_val->data.x_lazy);
|
||||
return type_val_resolve_abi_align(g, lazy_array_type->elem_type->value, abi_align);
|
||||
}
|
||||
case LazyValueIdErrUnionType: {
|
||||
LazyValueErrUnionType *lazy_err_union_type =
|
||||
reinterpret_cast<LazyValueErrUnionType *>(type_val->data.x_lazy);
|
||||
|
@ -1370,6 +1396,13 @@ static OnePossibleValue type_val_resolve_has_one_possible_value(CodeGen *g, ZigV
|
|||
case LazyValueIdOptType: // it has the optional bit
|
||||
case LazyValueIdFnType:
|
||||
return OnePossibleValueNo;
|
||||
case LazyValueIdArrayType: {
|
||||
LazyValueArrayType *lazy_array_type =
|
||||
reinterpret_cast<LazyValueArrayType *>(type_val->data.x_lazy);
|
||||
if (lazy_array_type->length < 1)
|
||||
return OnePossibleValueYes;
|
||||
return type_val_resolve_has_one_possible_value(g, lazy_array_type->elem_type->value);
|
||||
}
|
||||
case LazyValueIdPtrType: {
|
||||
Error err;
|
||||
bool zero_bits;
|
||||
|
|
137
src/ir.cpp
137
src/ir.cpp
|
@ -20551,73 +20551,28 @@ static IrInstruction *ir_analyze_instruction_asm(IrAnalyze *ira, IrInstructionAs
|
|||
static IrInstruction *ir_analyze_instruction_array_type(IrAnalyze *ira,
|
||||
IrInstructionArrayType *array_type_instruction)
|
||||
{
|
||||
Error err;
|
||||
IrInstruction *result = ir_const(ira, &array_type_instruction->base, ira->codegen->builtin_types.entry_type);
|
||||
result->value->special = ConstValSpecialLazy;
|
||||
|
||||
IrInstruction *size_value = array_type_instruction->size->child;
|
||||
uint64_t size;
|
||||
if (!ir_resolve_usize(ira, size_value, &size))
|
||||
LazyValueArrayType *lazy_array_type = allocate<LazyValueArrayType>(1, "LazyValueArrayType");
|
||||
lazy_array_type->ira = ira; ira_ref(ira);
|
||||
result->value->data.x_lazy = &lazy_array_type->base;
|
||||
lazy_array_type->base.id = LazyValueIdArrayType;
|
||||
|
||||
lazy_array_type->elem_type = array_type_instruction->child_type->child;
|
||||
if (ir_resolve_type_lazy(ira, lazy_array_type->elem_type) == nullptr)
|
||||
return ira->codegen->invalid_instruction;
|
||||
|
||||
IrInstruction *child_type_value = array_type_instruction->child_type->child;
|
||||
ZigType *child_type = ir_resolve_type(ira, child_type_value);
|
||||
if (type_is_invalid(child_type))
|
||||
if (!ir_resolve_usize(ira, array_type_instruction->size->child, &lazy_array_type->length))
|
||||
return ira->codegen->invalid_instruction;
|
||||
|
||||
ZigValue *sentinel_val;
|
||||
if (array_type_instruction->sentinel != nullptr) {
|
||||
IrInstruction *uncasted_sentinel = array_type_instruction->sentinel->child;
|
||||
if (type_is_invalid(uncasted_sentinel->value->type))
|
||||
lazy_array_type->sentinel = array_type_instruction->sentinel->child;
|
||||
if (ir_resolve_const(ira, lazy_array_type->sentinel, LazyOk) == nullptr)
|
||||
return ira->codegen->invalid_instruction;
|
||||
IrInstruction *sentinel = ir_implicit_cast(ira, uncasted_sentinel, child_type);
|
||||
if (type_is_invalid(sentinel->value->type))
|
||||
return ira->codegen->invalid_instruction;
|
||||
sentinel_val = ir_resolve_const(ira, sentinel, UndefBad);
|
||||
if (sentinel_val == nullptr)
|
||||
return ira->codegen->invalid_instruction;
|
||||
} else {
|
||||
sentinel_val = nullptr;
|
||||
}
|
||||
|
||||
switch (child_type->id) {
|
||||
case ZigTypeIdInvalid: // handled above
|
||||
zig_unreachable();
|
||||
case ZigTypeIdUnreachable:
|
||||
case ZigTypeIdUndefined:
|
||||
case ZigTypeIdNull:
|
||||
case ZigTypeIdArgTuple:
|
||||
case ZigTypeIdOpaque:
|
||||
ir_add_error_node(ira, array_type_instruction->base.source_node,
|
||||
buf_sprintf("array of type '%s' not allowed", buf_ptr(&child_type->name)));
|
||||
return ira->codegen->invalid_instruction;
|
||||
case ZigTypeIdMetaType:
|
||||
case ZigTypeIdVoid:
|
||||
case ZigTypeIdBool:
|
||||
case ZigTypeIdInt:
|
||||
case ZigTypeIdFloat:
|
||||
case ZigTypeIdPointer:
|
||||
case ZigTypeIdArray:
|
||||
case ZigTypeIdStruct:
|
||||
case ZigTypeIdComptimeFloat:
|
||||
case ZigTypeIdComptimeInt:
|
||||
case ZigTypeIdEnumLiteral:
|
||||
case ZigTypeIdOptional:
|
||||
case ZigTypeIdErrorUnion:
|
||||
case ZigTypeIdErrorSet:
|
||||
case ZigTypeIdEnum:
|
||||
case ZigTypeIdUnion:
|
||||
case ZigTypeIdFn:
|
||||
case ZigTypeIdBoundFn:
|
||||
case ZigTypeIdVector:
|
||||
case ZigTypeIdFnFrame:
|
||||
case ZigTypeIdAnyFrame:
|
||||
{
|
||||
if ((err = type_resolve(ira->codegen, child_type, ResolveStatusSizeKnown)))
|
||||
return ira->codegen->invalid_instruction;
|
||||
ZigType *result_type = get_array_type(ira->codegen, child_type, size, sentinel_val);
|
||||
return ir_const_type(ira, &array_type_instruction->base, result_type);
|
||||
}
|
||||
}
|
||||
zig_unreachable();
|
||||
return result;
|
||||
}
|
||||
|
||||
static IrInstruction *ir_analyze_instruction_size_of(IrAnalyze *ira, IrInstructionSizeOf *instruction) {
|
||||
|
@ -29016,6 +28971,72 @@ static Error ir_resolve_lazy_raw(AstNode *source_node, ZigValue *val) {
|
|||
// We can't free the lazy value here, because multiple other ZigValues might be pointing to it.
|
||||
return ErrorNone;
|
||||
}
|
||||
case LazyValueIdArrayType: {
|
||||
LazyValueArrayType *lazy_array_type = reinterpret_cast<LazyValueArrayType *>(val->data.x_lazy);
|
||||
IrAnalyze *ira = lazy_array_type->ira;
|
||||
|
||||
ZigType *elem_type = ir_resolve_type(ira, lazy_array_type->elem_type);
|
||||
if (type_is_invalid(elem_type))
|
||||
return ErrorSemanticAnalyzeFail;
|
||||
|
||||
switch (elem_type->id) {
|
||||
case ZigTypeIdInvalid: // handled above
|
||||
zig_unreachable();
|
||||
case ZigTypeIdUnreachable:
|
||||
case ZigTypeIdUndefined:
|
||||
case ZigTypeIdNull:
|
||||
case ZigTypeIdArgTuple:
|
||||
case ZigTypeIdOpaque:
|
||||
ir_add_error(ira, lazy_array_type->elem_type,
|
||||
buf_sprintf("array of type '%s' not allowed",
|
||||
buf_ptr(&elem_type->name)));
|
||||
return ErrorSemanticAnalyzeFail;
|
||||
case ZigTypeIdMetaType:
|
||||
case ZigTypeIdVoid:
|
||||
case ZigTypeIdBool:
|
||||
case ZigTypeIdInt:
|
||||
case ZigTypeIdFloat:
|
||||
case ZigTypeIdPointer:
|
||||
case ZigTypeIdArray:
|
||||
case ZigTypeIdStruct:
|
||||
case ZigTypeIdComptimeFloat:
|
||||
case ZigTypeIdComptimeInt:
|
||||
case ZigTypeIdEnumLiteral:
|
||||
case ZigTypeIdOptional:
|
||||
case ZigTypeIdErrorUnion:
|
||||
case ZigTypeIdErrorSet:
|
||||
case ZigTypeIdEnum:
|
||||
case ZigTypeIdUnion:
|
||||
case ZigTypeIdFn:
|
||||
case ZigTypeIdBoundFn:
|
||||
case ZigTypeIdVector:
|
||||
case ZigTypeIdFnFrame:
|
||||
case ZigTypeIdAnyFrame:
|
||||
break;
|
||||
}
|
||||
|
||||
if ((err = type_resolve(ira->codegen, elem_type, ResolveStatusSizeKnown)))
|
||||
return err;
|
||||
|
||||
ZigValue *sentinel_val = nullptr;
|
||||
if (lazy_array_type->sentinel != nullptr) {
|
||||
if (type_is_invalid(lazy_array_type->sentinel->value->type))
|
||||
return ErrorSemanticAnalyzeFail;
|
||||
IrInstruction *sentinel = ir_implicit_cast(ira, lazy_array_type->sentinel, elem_type);
|
||||
if (type_is_invalid(sentinel->value->type))
|
||||
return ErrorSemanticAnalyzeFail;
|
||||
sentinel_val = ir_resolve_const(ira, sentinel, UndefBad);
|
||||
if (sentinel_val == nullptr)
|
||||
return ErrorSemanticAnalyzeFail;
|
||||
}
|
||||
|
||||
assert(val->type->id == ZigTypeIdMetaType);
|
||||
val->data.x_type = get_array_type(ira->codegen, elem_type, lazy_array_type->length, sentinel_val);
|
||||
val->special = ConstValSpecialStatic;
|
||||
|
||||
// We can't free the lazy value here, because multiple other ZigValues might be pointing to it.
|
||||
return ErrorNone;
|
||||
}
|
||||
case LazyValueIdOptType: {
|
||||
LazyValueOptType *lazy_opt_type = reinterpret_cast<LazyValueOptType *>(val->data.x_lazy);
|
||||
IrAnalyze *ira = lazy_opt_type->ira;
|
||||
|
|
|
@ -813,3 +813,12 @@ test "anon struct literal field value initialized with fn call" {
|
|||
S.doTheTest();
|
||||
comptime S.doTheTest();
|
||||
}
|
||||
|
||||
test "self-referencing struct via array member" {
|
||||
const T = struct {
|
||||
children: [1]*@This(),
|
||||
};
|
||||
var x: T = undefined;
|
||||
x = T{ .children = .{&x} };
|
||||
expect(x.children[0] == &x);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue