mirror of
https://github.com/ziglang/zig.git
synced 2026-02-13 04:48:20 +00:00
stage1: small memory optimization for simple pointer types
Avoid storing extra IR instruction data for simple pointer types.
This commit is contained in:
parent
a6f5aa71ac
commit
5e5b35f107
@ -391,6 +391,8 @@ enum LazyValueId {
|
||||
LazyValueIdAlignOf,
|
||||
LazyValueIdSizeOf,
|
||||
LazyValueIdPtrType,
|
||||
LazyValueIdPtrTypeSimple,
|
||||
LazyValueIdPtrTypeSimpleConst,
|
||||
LazyValueIdOptType,
|
||||
LazyValueIdSliceType,
|
||||
LazyValueIdFnType,
|
||||
@ -467,6 +469,13 @@ struct LazyValuePtrType {
|
||||
bool is_allowzero;
|
||||
};
|
||||
|
||||
struct LazyValuePtrTypeSimple {
|
||||
LazyValue base;
|
||||
|
||||
IrAnalyze *ira;
|
||||
IrInstGen *elem_type;
|
||||
};
|
||||
|
||||
struct LazyValueOptType {
|
||||
LazyValue base;
|
||||
|
||||
@ -2625,6 +2634,8 @@ enum IrInstSrcId {
|
||||
IrInstSrcIdHasField,
|
||||
IrInstSrcIdSetEvalBranchQuota,
|
||||
IrInstSrcIdPtrType,
|
||||
IrInstSrcIdPtrTypeSimple,
|
||||
IrInstSrcIdPtrTypeSimpleConst,
|
||||
IrInstSrcIdAlignCast,
|
||||
IrInstSrcIdImplicitCast,
|
||||
IrInstSrcIdResolveResult,
|
||||
@ -3296,6 +3307,12 @@ struct IrInstSrcArrayType {
|
||||
IrInstSrc *child_type;
|
||||
};
|
||||
|
||||
struct IrInstSrcPtrTypeSimple {
|
||||
IrInstSrc base;
|
||||
|
||||
IrInstSrc *child_type;
|
||||
};
|
||||
|
||||
struct IrInstSrcPtrType {
|
||||
IrInstSrc base;
|
||||
|
||||
|
||||
@ -1237,6 +1237,22 @@ Error type_val_resolve_zero_bits(CodeGen *g, ZigValue *type_val, ZigType *parent
|
||||
parent_type_val, is_zero_bits);
|
||||
}
|
||||
}
|
||||
case LazyValueIdPtrTypeSimple:
|
||||
case LazyValueIdPtrTypeSimpleConst: {
|
||||
LazyValuePtrTypeSimple *lazy_ptr_type = reinterpret_cast<LazyValuePtrTypeSimple *>(type_val->data.x_lazy);
|
||||
|
||||
if (parent_type_val == lazy_ptr_type->elem_type->value) {
|
||||
// Does a struct which contains a pointer field to itself have bits? Yes.
|
||||
*is_zero_bits = false;
|
||||
return ErrorNone;
|
||||
} else {
|
||||
if (parent_type_val == nullptr) {
|
||||
parent_type_val = type_val;
|
||||
}
|
||||
return type_val_resolve_zero_bits(g, lazy_ptr_type->elem_type->value, parent_type,
|
||||
parent_type_val, is_zero_bits);
|
||||
}
|
||||
}
|
||||
case LazyValueIdArrayType: {
|
||||
LazyValueArrayType *lazy_array_type =
|
||||
reinterpret_cast<LazyValueArrayType *>(type_val->data.x_lazy);
|
||||
@ -1285,6 +1301,8 @@ Error type_val_resolve_is_opaque_type(CodeGen *g, ZigValue *type_val, bool *is_o
|
||||
zig_unreachable();
|
||||
case LazyValueIdSliceType:
|
||||
case LazyValueIdPtrType:
|
||||
case LazyValueIdPtrTypeSimple:
|
||||
case LazyValueIdPtrTypeSimpleConst:
|
||||
case LazyValueIdFnType:
|
||||
case LazyValueIdOptType:
|
||||
case LazyValueIdErrUnionType:
|
||||
@ -1313,6 +1331,11 @@ static ReqCompTime type_val_resolve_requires_comptime(CodeGen *g, ZigValue *type
|
||||
LazyValuePtrType *lazy_ptr_type = reinterpret_cast<LazyValuePtrType *>(type_val->data.x_lazy);
|
||||
return type_val_resolve_requires_comptime(g, lazy_ptr_type->elem_type->value);
|
||||
}
|
||||
case LazyValueIdPtrTypeSimple:
|
||||
case LazyValueIdPtrTypeSimpleConst: {
|
||||
LazyValuePtrTypeSimple *lazy_ptr_type = reinterpret_cast<LazyValuePtrTypeSimple *>(type_val->data.x_lazy);
|
||||
return type_val_resolve_requires_comptime(g, lazy_ptr_type->elem_type->value);
|
||||
}
|
||||
case LazyValueIdOptType: {
|
||||
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);
|
||||
@ -1413,6 +1436,24 @@ start_over:
|
||||
}
|
||||
return ErrorNone;
|
||||
}
|
||||
case LazyValueIdPtrTypeSimple:
|
||||
case LazyValueIdPtrTypeSimpleConst: {
|
||||
LazyValuePtrTypeSimple *lazy_ptr_type = reinterpret_cast<LazyValuePtrTypeSimple *>(type_val->data.x_lazy);
|
||||
bool is_zero_bits;
|
||||
if ((err = type_val_resolve_zero_bits(g, lazy_ptr_type->elem_type->value, nullptr,
|
||||
nullptr, &is_zero_bits)))
|
||||
{
|
||||
return err;
|
||||
}
|
||||
if (is_zero_bits) {
|
||||
*abi_size = 0;
|
||||
*size_in_bits = 0;
|
||||
} else {
|
||||
*abi_size = g->builtin_types.entry_usize->abi_size;
|
||||
*size_in_bits = g->builtin_types.entry_usize->size_in_bits;
|
||||
}
|
||||
return ErrorNone;
|
||||
}
|
||||
case LazyValueIdFnType:
|
||||
*abi_size = g->builtin_types.entry_usize->abi_size;
|
||||
*size_in_bits = g->builtin_types.entry_usize->size_in_bits;
|
||||
@ -1449,6 +1490,8 @@ Error type_val_resolve_abi_align(CodeGen *g, AstNode *source_node, ZigValue *typ
|
||||
zig_unreachable();
|
||||
case LazyValueIdSliceType:
|
||||
case LazyValueIdPtrType:
|
||||
case LazyValueIdPtrTypeSimple:
|
||||
case LazyValueIdPtrTypeSimpleConst:
|
||||
case LazyValueIdFnType:
|
||||
*abi_align = g->builtin_types.entry_usize->abi_align;
|
||||
return ErrorNone;
|
||||
@ -1506,7 +1549,9 @@ static OnePossibleValue type_val_resolve_has_one_possible_value(CodeGen *g, ZigV
|
||||
return OnePossibleValueYes;
|
||||
return type_val_resolve_has_one_possible_value(g, lazy_array_type->elem_type->value);
|
||||
}
|
||||
case LazyValueIdPtrType: {
|
||||
case LazyValueIdPtrType:
|
||||
case LazyValueIdPtrTypeSimple:
|
||||
case LazyValueIdPtrTypeSimpleConst: {
|
||||
Error err;
|
||||
bool zero_bits;
|
||||
if ((err = type_val_resolve_zero_bits(g, type_val, nullptr, nullptr, &zero_bits))) {
|
||||
@ -5758,6 +5803,8 @@ static bool can_mutate_comptime_var_state(ZigValue *value) {
|
||||
case LazyValueIdAlignOf:
|
||||
case LazyValueIdSizeOf:
|
||||
case LazyValueIdPtrType:
|
||||
case LazyValueIdPtrTypeSimple:
|
||||
case LazyValueIdPtrTypeSimpleConst:
|
||||
case LazyValueIdOptType:
|
||||
case LazyValueIdSliceType:
|
||||
case LazyValueIdFnType:
|
||||
|
||||
@ -487,6 +487,9 @@ static void destroy_instruction_src(IrInstSrc *inst) {
|
||||
return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcTagName *>(inst));
|
||||
case IrInstSrcIdPtrType:
|
||||
return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcPtrType *>(inst));
|
||||
case IrInstSrcIdPtrTypeSimple:
|
||||
case IrInstSrcIdPtrTypeSimpleConst:
|
||||
return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcPtrTypeSimple *>(inst));
|
||||
case IrInstSrcIdDeclRef:
|
||||
return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcDeclRef *>(inst));
|
||||
case IrInstSrcIdPanic:
|
||||
@ -2609,11 +2612,35 @@ static IrInstGen *ir_build_br_gen(IrAnalyze *ira, IrInst *source_instr, IrBasicB
|
||||
return &inst->base;
|
||||
}
|
||||
|
||||
static IrInstSrc *ir_build_ptr_type_simple(IrBuilderSrc *irb, Scope *scope, AstNode *source_node,
|
||||
IrInstSrc *child_type, bool is_const)
|
||||
{
|
||||
IrInstSrcPtrTypeSimple *inst = heap::c_allocator.create<IrInstSrcPtrTypeSimple>();
|
||||
inst->base.id = is_const ? IrInstSrcIdPtrTypeSimpleConst : IrInstSrcIdPtrTypeSimple;
|
||||
inst->base.base.scope = scope;
|
||||
inst->base.base.source_node = source_node;
|
||||
inst->base.base.debug_id = exec_next_debug_id(irb->exec);
|
||||
inst->base.owner_bb = irb->current_basic_block;
|
||||
ir_instruction_append(irb->current_basic_block, &inst->base);
|
||||
|
||||
inst->child_type = child_type;
|
||||
|
||||
ir_ref_instruction(child_type, irb->current_basic_block);
|
||||
|
||||
return &inst->base;
|
||||
}
|
||||
|
||||
static IrInstSrc *ir_build_ptr_type(IrBuilderSrc *irb, Scope *scope, AstNode *source_node,
|
||||
IrInstSrc *child_type, bool is_const, bool is_volatile, PtrLen ptr_len,
|
||||
IrInstSrc *sentinel, IrInstSrc *align_value,
|
||||
uint32_t bit_offset_start, uint32_t host_int_bytes, bool is_allow_zero)
|
||||
{
|
||||
if (!is_volatile && ptr_len == PtrLenSingle && sentinel == nullptr && align_value == nullptr &&
|
||||
bit_offset_start == 0 && host_int_bytes == 0 && is_allow_zero == 0)
|
||||
{
|
||||
return ir_build_ptr_type_simple(irb, scope, source_node, child_type, is_const);
|
||||
}
|
||||
|
||||
IrInstSrcPtrType *inst = ir_build_instruction<IrInstSrcPtrType>(irb, scope, source_node);
|
||||
inst->sentinel = sentinel;
|
||||
inst->align_value = align_value;
|
||||
@ -30878,6 +30905,24 @@ static IrInstGen *ir_analyze_instruction_ptr_to_int(IrAnalyze *ira, IrInstSrcPtr
|
||||
return ir_build_ptr_to_int_gen(ira, &instruction->base.base, target);
|
||||
}
|
||||
|
||||
static IrInstGen *ir_analyze_instruction_ptr_type_simple(IrAnalyze *ira,
|
||||
IrInstSrcPtrTypeSimple *instruction, bool is_const)
|
||||
{
|
||||
IrInstGen *result = ir_const(ira, &instruction->base.base, ira->codegen->builtin_types.entry_type);
|
||||
result->value->special = ConstValSpecialLazy;
|
||||
|
||||
LazyValuePtrTypeSimple *lazy_ptr_type = heap::c_allocator.create<LazyValuePtrTypeSimple>();
|
||||
lazy_ptr_type->ira = ira; ira_ref(ira);
|
||||
result->value->data.x_lazy = &lazy_ptr_type->base;
|
||||
lazy_ptr_type->base.id = is_const ? LazyValueIdPtrTypeSimpleConst : LazyValueIdPtrTypeSimple;
|
||||
|
||||
lazy_ptr_type->elem_type = instruction->child_type->child;
|
||||
if (ir_resolve_type_lazy(ira, lazy_ptr_type->elem_type) == nullptr)
|
||||
return ira->codegen->invalid_inst_gen;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static IrInstGen *ir_analyze_instruction_ptr_type(IrAnalyze *ira, IrInstSrcPtrType *instruction) {
|
||||
IrInstGen *result = ir_const(ira, &instruction->base.base, ira->codegen->builtin_types.entry_type);
|
||||
result->value->special = ConstValSpecialLazy;
|
||||
@ -32384,6 +32429,10 @@ static IrInstGen *ir_analyze_instruction_base(IrAnalyze *ira, IrInstSrc *instruc
|
||||
return ir_analyze_instruction_set_eval_branch_quota(ira, (IrInstSrcSetEvalBranchQuota *)instruction);
|
||||
case IrInstSrcIdPtrType:
|
||||
return ir_analyze_instruction_ptr_type(ira, (IrInstSrcPtrType *)instruction);
|
||||
case IrInstSrcIdPtrTypeSimple:
|
||||
return ir_analyze_instruction_ptr_type_simple(ira, (IrInstSrcPtrTypeSimple *)instruction, false);
|
||||
case IrInstSrcIdPtrTypeSimpleConst:
|
||||
return ir_analyze_instruction_ptr_type_simple(ira, (IrInstSrcPtrTypeSimple *)instruction, true);
|
||||
case IrInstSrcIdAlignCast:
|
||||
return ir_analyze_instruction_align_cast(ira, (IrInstSrcAlignCast *)instruction);
|
||||
case IrInstSrcIdImplicitCast:
|
||||
@ -32757,6 +32806,8 @@ bool ir_inst_src_has_side_effects(IrInstSrc *instruction) {
|
||||
case IrInstSrcIdPanic:
|
||||
case IrInstSrcIdSetEvalBranchQuota:
|
||||
case IrInstSrcIdPtrType:
|
||||
case IrInstSrcIdPtrTypeSimple:
|
||||
case IrInstSrcIdPtrTypeSimpleConst:
|
||||
case IrInstSrcIdSetAlignStack:
|
||||
case IrInstSrcIdExport:
|
||||
case IrInstSrcIdExtern:
|
||||
@ -33264,6 +33315,54 @@ 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 LazyValueIdPtrTypeSimple: {
|
||||
LazyValuePtrTypeSimple *lazy_ptr_type = reinterpret_cast<LazyValuePtrTypeSimple *>(val->data.x_lazy);
|
||||
IrAnalyze *ira = lazy_ptr_type->ira;
|
||||
|
||||
ZigType *elem_type = ir_resolve_type(ira, lazy_ptr_type->elem_type);
|
||||
if (type_is_invalid(elem_type))
|
||||
return ErrorSemanticAnalyzeFail;
|
||||
|
||||
if (elem_type->id == ZigTypeIdUnreachable) {
|
||||
ir_add_error(ira, &lazy_ptr_type->elem_type->base,
|
||||
buf_create_from_str("pointer to noreturn not allowed"));
|
||||
return ErrorSemanticAnalyzeFail;
|
||||
}
|
||||
|
||||
assert(val->type->id == ZigTypeIdMetaType);
|
||||
val->data.x_type = get_pointer_to_type_extra2(ira->codegen, elem_type,
|
||||
false, false, PtrLenSingle, 0,
|
||||
0, 0,
|
||||
false, VECTOR_INDEX_NONE, nullptr, nullptr);
|
||||
val->special = ConstValSpecialStatic;
|
||||
|
||||
// We can't free the lazy value here, because multiple other ZigValues might be pointing to it.
|
||||
return ErrorNone;
|
||||
}
|
||||
case LazyValueIdPtrTypeSimpleConst: {
|
||||
LazyValuePtrTypeSimple *lazy_ptr_type = reinterpret_cast<LazyValuePtrTypeSimple *>(val->data.x_lazy);
|
||||
IrAnalyze *ira = lazy_ptr_type->ira;
|
||||
|
||||
ZigType *elem_type = ir_resolve_type(ira, lazy_ptr_type->elem_type);
|
||||
if (type_is_invalid(elem_type))
|
||||
return ErrorSemanticAnalyzeFail;
|
||||
|
||||
if (elem_type->id == ZigTypeIdUnreachable) {
|
||||
ir_add_error(ira, &lazy_ptr_type->elem_type->base,
|
||||
buf_create_from_str("pointer to noreturn not allowed"));
|
||||
return ErrorSemanticAnalyzeFail;
|
||||
}
|
||||
|
||||
assert(val->type->id == ZigTypeIdMetaType);
|
||||
val->data.x_type = get_pointer_to_type_extra2(ira->codegen, elem_type,
|
||||
true, false, PtrLenSingle, 0,
|
||||
0, 0,
|
||||
false, VECTOR_INDEX_NONE, nullptr, nullptr);
|
||||
val->special = ConstValSpecialStatic;
|
||||
|
||||
// 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;
|
||||
|
||||
@ -300,6 +300,10 @@ const char* ir_inst_src_type_str(IrInstSrcId id) {
|
||||
return "SrcSetEvalBranchQuota";
|
||||
case IrInstSrcIdPtrType:
|
||||
return "SrcPtrType";
|
||||
case IrInstSrcIdPtrTypeSimple:
|
||||
return "SrcPtrTypeSimple";
|
||||
case IrInstSrcIdPtrTypeSimpleConst:
|
||||
return "SrcPtrTypeSimpleConst";
|
||||
case IrInstSrcIdAlignCast:
|
||||
return "SrcAlignCast";
|
||||
case IrInstSrcIdImplicitCast:
|
||||
@ -2245,6 +2249,15 @@ static void ir_print_ptr_type(IrPrintSrc *irp, IrInstSrcPtrType *instruction) {
|
||||
ir_print_other_inst_src(irp, instruction->child_type);
|
||||
}
|
||||
|
||||
static void ir_print_ptr_type_simple(IrPrintSrc *irp, IrInstSrcPtrTypeSimple *instruction,
|
||||
bool is_const)
|
||||
{
|
||||
fprintf(irp->f, "&");
|
||||
const char *const_str = is_const ? "const " : "";
|
||||
fprintf(irp->f, "*%s", const_str);
|
||||
ir_print_other_inst_src(irp, instruction->child_type);
|
||||
}
|
||||
|
||||
static void ir_print_decl_ref(IrPrintSrc *irp, IrInstSrcDeclRef *instruction) {
|
||||
const char *ptr_str = (instruction->lval != LValNone) ? "ptr " : "";
|
||||
fprintf(irp->f, "declref %s%s", ptr_str, buf_ptr(instruction->tld->name));
|
||||
@ -2917,6 +2930,12 @@ static void ir_print_inst_src(IrPrintSrc *irp, IrInstSrc *instruction, bool trai
|
||||
case IrInstSrcIdPtrType:
|
||||
ir_print_ptr_type(irp, (IrInstSrcPtrType *)instruction);
|
||||
break;
|
||||
case IrInstSrcIdPtrTypeSimple:
|
||||
ir_print_ptr_type_simple(irp, (IrInstSrcPtrTypeSimple *)instruction, false);
|
||||
break;
|
||||
case IrInstSrcIdPtrTypeSimpleConst:
|
||||
ir_print_ptr_type_simple(irp, (IrInstSrcPtrTypeSimple *)instruction, true);
|
||||
break;
|
||||
case IrInstSrcIdDeclRef:
|
||||
ir_print_decl_ref(irp, (IrInstSrcDeclRef *)instruction);
|
||||
break;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user