| author | |
| committer | |
| log | df03fcf5f07e0d5d16e5b837658265f6c468cbe4 |
| tree | ba012a63f4ca49632a8f74a8941b913e8a63c3e3 |
| parent | f609ce4f6551d772dcb6480c573ccad7645056cb |
6 files changed, 43 insertions(+), 5 deletions(-)
doc/langref.html.in+14-1| ... | @@ -6815,6 +6815,19 @@ async fn func(y: *i32) void { | ... | @@ -6815,6 +6815,19 @@ async fn func(y: *i32) void { |
| 6815 | </p> | 6815 | </p> |
| 6816 | {#header_close#} | 6816 | {#header_close#} |
| 6817 | 6817 | ||
| 6818 | {#header_open|@bitSizeOf#} | ||
| 6819 | <pre>{#syntax#}@bitSizeOf(comptime T: type) comptime_int{#endsyntax#}</pre> | ||
| 6820 | <p> | ||
| 6821 | This function returns the number of bits it takes to store {#syntax#}T{#endsyntax#} in memory. | ||
| 6822 | The result is a target-specific compile time constant. | ||
| 6823 | </p> | ||
| 6824 | <p> | ||
| 6825 | This function measures the size at runtime. For types that are disallowed at runtime, such as | ||
| 6826 | {#syntax#}comptime_int{#endsyntax#} and {#syntax#}type{#endsyntax#}, the result is {#syntax#}0{#endsyntax#}. | ||
| 6827 | </p> | ||
| 6828 | {#see_also|@sizeOf|@typeInfo#} | ||
| 6829 | {#header_close#} | ||
| 6830 | |||
| 6818 | {#header_open|@breakpoint#} | 6831 | {#header_open|@breakpoint#} |
| 6819 | <pre>{#syntax#}@breakpoint(){#endsyntax#}</pre> | 6832 | <pre>{#syntax#}@breakpoint(){#endsyntax#}</pre> |
| 6820 | <p> | 6833 | <p> |
| ... | @@ -8044,7 +8057,7 @@ test "@setRuntimeSafety" { | ... | @@ -8044,7 +8057,7 @@ test "@setRuntimeSafety" { |
| 8044 | This function measures the size at runtime. For types that are disallowed at runtime, such as | 8057 | This function measures the size at runtime. For types that are disallowed at runtime, such as |
| 8045 | {#syntax#}comptime_int{#endsyntax#} and {#syntax#}type{#endsyntax#}, the result is {#syntax#}0{#endsyntax#}. | 8058 | {#syntax#}comptime_int{#endsyntax#} and {#syntax#}type{#endsyntax#}, the result is {#syntax#}0{#endsyntax#}. |
| 8046 | </p> | 8059 | </p> |
| 8047 | {#see_also|@typeInfo#} | 8060 | {#see_also|@bitSizeOf|@typeInfo#} |
| 8048 | {#header_close#} | 8061 | {#header_close#} |
| 8049 | 8062 | ||
| 8050 | {#header_open|@sliceToBytes#} | 8063 | {#header_open|@sliceToBytes#} |
src/all_types.hpp+4| ... | @@ -358,6 +358,8 @@ struct LazyValueSizeOf { | ... | @@ -358,6 +358,8 @@ struct LazyValueSizeOf { |
| 358 | 358 | ||
| 359 | IrAnalyze *ira; | 359 | IrAnalyze *ira; |
| 360 | IrInstruction *target_type; | 360 | IrInstruction *target_type; |
| 361 | |||
| 362 | bool bit_size; | ||
| 361 | }; | 363 | }; |
| 362 | 364 | ||
| 363 | struct LazyValueSliceType { | 365 | struct LazyValueSliceType { |
| ... | @@ -1754,6 +1756,7 @@ enum BuiltinFnId { | ... | @@ -1754,6 +1756,7 @@ enum BuiltinFnId { |
| 1754 | BuiltinFnIdFrameSize, | 1756 | BuiltinFnIdFrameSize, |
| 1755 | BuiltinFnIdAs, | 1757 | BuiltinFnIdAs, |
| 1756 | BuiltinFnIdCall, | 1758 | BuiltinFnIdCall, |
| 1759 | BuiltinFnIdBitSizeof, | ||
| 1757 | }; | 1760 | }; |
| 1758 | 1761 | ||
| 1759 | struct BuiltinFnEntry { | 1762 | struct BuiltinFnEntry { |
| ... | @@ -3146,6 +3149,7 @@ struct IrInstructionAsmGen { | ... | @@ -3146,6 +3149,7 @@ struct IrInstructionAsmGen { |
| 3146 | struct IrInstructionSizeOf { | 3149 | struct IrInstructionSizeOf { |
| 3147 | IrInstruction base; | 3150 | IrInstruction base; |
| 3148 | 3151 | ||
| 3152 | bool bit_size; | ||
| 3149 | IrInstruction *type_value; | 3153 | IrInstruction *type_value; |
| 3150 | }; | 3154 | }; |
| 3151 | 3155 |
src/codegen.cpp+1| ... | @@ -8299,6 +8299,7 @@ static void define_builtin_fns(CodeGen *g) { | ... | @@ -8299,6 +8299,7 @@ static void define_builtin_fns(CodeGen *g) { |
| 8299 | create_builtin_fn(g, BuiltinFnIdFrameSize, "frameSize", 1); | 8299 | create_builtin_fn(g, BuiltinFnIdFrameSize, "frameSize", 1); |
| 8300 | create_builtin_fn(g, BuiltinFnIdAs, "as", 2); | 8300 | create_builtin_fn(g, BuiltinFnIdAs, "as", 2); |
| 8301 | create_builtin_fn(g, BuiltinFnIdCall, "call", 3); | 8301 | create_builtin_fn(g, BuiltinFnIdCall, "call", 3); |
| 8302 | create_builtin_fn(g, BuiltinFnIdBitSizeof, "bitSizeOf", 1); | ||
| 8302 | } | 8303 | } |
| 8303 | 8304 | ||
| 8304 | static const char *bool_to_str(bool b) { | 8305 | static const char *bool_to_str(bool b) { |
src/ir.cpp+9-3| ... | @@ -2392,9 +2392,10 @@ static IrInstruction *ir_build_asm_gen(IrAnalyze *ira, Scope *scope, AstNode *so | ... | @@ -2392,9 +2392,10 @@ static IrInstruction *ir_build_asm_gen(IrAnalyze *ira, Scope *scope, AstNode *so |
| 2392 | return &instruction->base; | 2392 | return &instruction->base; |
| 2393 | } | 2393 | } |
| 2394 | 2394 | ||
| 2395 | static IrInstruction *ir_build_size_of(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *type_value) { | 2395 | static IrInstruction *ir_build_size_of(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *type_value, bool bit_size) { |
| 2396 | IrInstructionSizeOf *instruction = ir_build_instruction<IrInstructionSizeOf>(irb, scope, source_node); | 2396 | IrInstructionSizeOf *instruction = ir_build_instruction<IrInstructionSizeOf>(irb, scope, source_node); |
| 2397 | instruction->type_value = type_value; | 2397 | instruction->type_value = type_value; |
| 2398 | instruction->bit_size = bit_size; | ||
| 2398 | 2399 | ||
| 2399 | ir_ref_instruction(type_value, irb->current_basic_block); | 2400 | ir_ref_instruction(type_value, irb->current_basic_block); |
| 2400 | 2401 | ||
| ... | @@ -5249,13 +5250,14 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo | ... | @@ -5249,13 +5250,14 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo |
| 5249 | return ir_lval_wrap(irb, scope, set_float_mode, lval, result_loc); | 5250 | return ir_lval_wrap(irb, scope, set_float_mode, lval, result_loc); |
| 5250 | } | 5251 | } |
| 5251 | case BuiltinFnIdSizeof: | 5252 | case BuiltinFnIdSizeof: |
| 5253 | case BuiltinFnIdBitSizeof: | ||
| 5252 | { | 5254 | { |
| 5253 | AstNode *arg0_node = node->data.fn_call_expr.params.at(0); | 5255 | AstNode *arg0_node = node->data.fn_call_expr.params.at(0); |
| 5254 | IrInstruction *arg0_value = ir_gen_node(irb, arg0_node, scope); | 5256 | IrInstruction *arg0_value = ir_gen_node(irb, arg0_node, scope); |
| 5255 | if (arg0_value == irb->codegen->invalid_instruction) | 5257 | if (arg0_value == irb->codegen->invalid_instruction) |
| 5256 | return arg0_value; | 5258 | return arg0_value; |
| 5257 | 5259 | ||
| 5258 | IrInstruction *size_of = ir_build_size_of(irb, scope, node, arg0_value); | 5260 | IrInstruction *size_of = ir_build_size_of(irb, scope, node, arg0_value, builtin_fn->id == BuiltinFnIdBitSizeof); |
| 5259 | return ir_lval_wrap(irb, scope, size_of, lval, result_loc); | 5261 | return ir_lval_wrap(irb, scope, size_of, lval, result_loc); |
| 5260 | } | 5262 | } |
| 5261 | case BuiltinFnIdImport: | 5263 | case BuiltinFnIdImport: |
| ... | @@ -21065,6 +21067,7 @@ static IrInstruction *ir_analyze_instruction_size_of(IrAnalyze *ira, IrInstructi | ... | @@ -21065,6 +21067,7 @@ static IrInstruction *ir_analyze_instruction_size_of(IrAnalyze *ira, IrInstructi |
| 21065 | lazy_size_of->ira = ira; ira_ref(ira); | 21067 | lazy_size_of->ira = ira; ira_ref(ira); |
| 21066 | result->value->data.x_lazy = &lazy_size_of->base; | 21068 | result->value->data.x_lazy = &lazy_size_of->base; |
| 21067 | lazy_size_of->base.id = LazyValueIdSizeOf; | 21069 | lazy_size_of->base.id = LazyValueIdSizeOf; |
| 21070 | lazy_size_of->bit_size = instruction->bit_size; | ||
| 21068 | 21071 | ||
| 21069 | lazy_size_of->target_type = instruction->type_value->child; | 21072 | lazy_size_of->target_type = instruction->type_value->child; |
| 21070 | if (ir_resolve_type_lazy(ira, lazy_size_of->target_type) == nullptr) | 21073 | if (ir_resolve_type_lazy(ira, lazy_size_of->target_type) == nullptr) |
| ... | @@ -29415,7 +29418,10 @@ static Error ir_resolve_lazy_raw(AstNode *source_node, ZigValue *val) { | ... | @@ -29415,7 +29418,10 @@ static Error ir_resolve_lazy_raw(AstNode *source_node, ZigValue *val) { |
| 29415 | 29418 | ||
| 29416 | val->special = ConstValSpecialStatic; | 29419 | val->special = ConstValSpecialStatic; |
| 29417 | assert(val->type->id == ZigTypeIdComptimeInt || val->type->id == ZigTypeIdInt); | 29420 | assert(val->type->id == ZigTypeIdComptimeInt || val->type->id == ZigTypeIdInt); |
| 29418 | bigint_init_unsigned(&val->data.x_bigint, abi_size); | 29421 | if (lazy_size_of->bit_size) |
| 29422 | bigint_init_unsigned(&val->data.x_bigint, size_in_bits); | ||
| 29423 | else | ||
| 29424 | bigint_init_unsigned(&val->data.x_bigint, abi_size); | ||
| 29419 | 29425 | ||
| 29420 | // We can't free the lazy value here, because multiple other ZigValues might be pointing to it. | 29426 | // We can't free the lazy value here, because multiple other ZigValues might be pointing to it. |
| 29421 | return ErrorNone; | 29427 | return ErrorNone; |
src/ir_print.cpp+4-1| ... | @@ -1039,7 +1039,10 @@ static void ir_print_asm_gen(IrPrint *irp, IrInstructionAsmGen *instruction) { | ... | @@ -1039,7 +1039,10 @@ static void ir_print_asm_gen(IrPrint *irp, IrInstructionAsmGen *instruction) { |
| 1039 | } | 1039 | } |
| 1040 | 1040 | ||
| 1041 | static void ir_print_size_of(IrPrint *irp, IrInstructionSizeOf *instruction) { | 1041 | static void ir_print_size_of(IrPrint *irp, IrInstructionSizeOf *instruction) { |
| 1042 | fprintf(irp->f, "@sizeOf("); | 1042 | if (instruction->bit_size) |
| 1043 | fprintf(irp->f, "@bitSizeOf("); | ||
| 1044 | else | ||
| 1045 | fprintf(irp->f, "@sizeOf("); | ||
| 1043 | ir_print_other_instruction(irp, instruction->type_value); | 1046 | ir_print_other_instruction(irp, instruction->type_value); |
| 1044 | fprintf(irp->f, ")"); | 1047 | fprintf(irp->f, ")"); |
| 1045 | } | 1048 | } |
test/stage1/behavior/sizeof_and_typeof.zig+11| ... | @@ -124,3 +124,14 @@ fn fn1(alpha: bool) void { | ... | @@ -124,3 +124,14 @@ fn fn1(alpha: bool) void { |
| 124 | test "lazy @sizeOf result is checked for definedness" { | 124 | test "lazy @sizeOf result is checked for definedness" { |
| 125 | const f = fn1; | 125 | const f = fn1; |
| 126 | } | 126 | } |
| 127 | |||
| 128 | test "@bitSizeOf" { | ||
| 129 | expect(@bitSizeOf(u2) == 2); | ||
| 130 | expect(@bitSizeOf(u8) == @sizeOf(u8) * 8); | ||
| 131 | expect(@bitSizeOf(struct { | ||
| 132 | a: u2 | ||
| 133 | }) == 8); | ||
| 134 | expect(@bitSizeOf(packed struct { | ||
| 135 | a: u2 | ||
| 136 | }) == 2); | ||
| 137 | } |