authorgravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2020-01-16 17:12:43+02:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-01-16 13:13:45-05:00
logdf03fcf5f07e0d5d16e5b837658265f6c468cbe4
treeba012a63f4ca49632a8f74a8941b913e8a63c3e3
parentf609ce4f6551d772dcb6480c573ccad7645056cb

implement `@bitSizeOf`


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#}
68176817
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 as8057 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#}
80498062
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 {
358358
359 IrAnalyze *ira;359 IrAnalyze *ira;
360 IrInstruction *target_type;360 IrInstruction *target_type;
361
362 bool bit_size;
361};363};
362364
363struct LazyValueSliceType {365struct 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};
17581761
1759struct BuiltinFnEntry {1762struct BuiltinFnEntry {
...@@ -3146,6 +3149,7 @@ struct IrInstructionAsmGen {...@@ -3146,6 +3149,7 @@ struct IrInstructionAsmGen {
3146struct IrInstructionSizeOf {3149struct IrInstructionSizeOf {
3147 IrInstruction base;3150 IrInstruction base;
31483151
3152 bool bit_size;
3149 IrInstruction *type_value;3153 IrInstruction *type_value;
3150};3154};
31513155
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}
83038304
8304static const char *bool_to_str(bool b) {8305static 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}
23942394
2395static IrInstruction *ir_build_size_of(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *type_value) {2395static 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;
23982399
2399 ir_ref_instruction(type_value, irb->current_basic_block);2400 ir_ref_instruction(type_value, irb->current_basic_block);
24002401
...@@ -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;
52575259
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;
2106821071
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) {
2941529418
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);
2941929425
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}
10401040
1041static void ir_print_size_of(IrPrint *irp, IrInstructionSizeOf *instruction) {1041static 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 {
124test "lazy @sizeOf result is checked for definedness" {124test "lazy @sizeOf result is checked for definedness" {
125 const f = fn1;125 const f = fn1;
126}126}
127
128test "@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}