| ... | ... | @@ -222,6 +222,10 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionCompileVar *) { |
| 222 | 222 | return IrInstructionIdCompileVar; |
| 223 | 223 | } |
| 224 | 224 | |
| 225 | static constexpr IrInstructionId ir_instruction_id(IrInstructionSizeOf *) { |
| 226 | return IrInstructionIdSizeOf; |
| 227 | } |
| 228 | |
| 225 | 229 | template<typename T> |
| 226 | 230 | static T *ir_create_instruction(IrExecutable *exec, AstNode *source_node) { |
| 227 | 231 | T *special_instruction = allocate<T>(1); |
| ... | ... | @@ -865,6 +869,15 @@ static IrInstruction *ir_build_compile_var(IrBuilder *irb, AstNode *source_node, |
| 865 | 869 | return &instruction->base; |
| 866 | 870 | } |
| 867 | 871 | |
| 872 | static IrInstruction *ir_build_size_of(IrBuilder *irb, AstNode *source_node, IrInstruction *type_value) { |
| 873 | IrInstructionSizeOf *instruction = ir_build_instruction<IrInstructionSizeOf>(irb, source_node); |
| 874 | instruction->type_value = type_value; |
| 875 | |
| 876 | ir_ref_instruction(type_value); |
| 877 | |
| 878 | return &instruction->base; |
| 879 | } |
| 880 | |
| 868 | 881 | static void ir_gen_defers_for_block(IrBuilder *irb, BlockContext *inner_block, BlockContext *outer_block, |
| 869 | 882 | bool gen_error_defers, bool gen_maybe_defers) |
| 870 | 883 | { |
| ... | ... | @@ -1356,9 +1369,17 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, AstNode *node) { |
| 1356 | 1369 | |
| 1357 | 1370 | return ir_build_compile_var(irb, node, arg0_value); |
| 1358 | 1371 | } |
| 1372 | case BuiltinFnIdSizeof: |
| 1373 | { |
| 1374 | AstNode *arg0_node = node->data.fn_call_expr.params.at(0); |
| 1375 | IrInstruction *arg0_value = ir_gen_node(irb, arg0_node, node->block_context); |
| 1376 | if (arg0_value == irb->codegen->invalid_instruction) |
| 1377 | return arg0_value; |
| 1378 | |
| 1379 | return ir_build_size_of(irb, node, arg0_value); |
| 1380 | } |
| 1359 | 1381 | case BuiltinFnIdMemcpy: |
| 1360 | 1382 | case BuiltinFnIdMemset: |
| 1361 | | case BuiltinFnIdSizeof: |
| 1362 | 1383 | case BuiltinFnIdAlignof: |
| 1363 | 1384 | case BuiltinFnIdMaxValue: |
| 1364 | 1385 | case BuiltinFnIdMinValue: |
| ... | ... | @@ -4417,6 +4438,56 @@ static TypeTableEntry *ir_analyze_instruction_compile_var(IrAnalyze *ira, |
| 4417 | 4438 | zig_unreachable(); |
| 4418 | 4439 | } |
| 4419 | 4440 | |
| 4441 | static TypeTableEntry *ir_analyze_instruction_size_of(IrAnalyze *ira, |
| 4442 | IrInstructionSizeOf *size_of_instruction) |
| 4443 | { |
| 4444 | IrInstruction *type_value = size_of_instruction->type_value->other; |
| 4445 | TypeTableEntry *type_entry = ir_resolve_type(ira, type_value); |
| 4446 | TypeTableEntry *canon_type_entry = get_underlying_type(type_entry); |
| 4447 | switch (canon_type_entry->id) { |
| 4448 | case TypeTableEntryIdInvalid: |
| 4449 | return ira->codegen->builtin_types.entry_invalid; |
| 4450 | case TypeTableEntryIdTypeDecl: |
| 4451 | zig_unreachable(); |
| 4452 | case TypeTableEntryIdVar: |
| 4453 | case TypeTableEntryIdUnreachable: |
| 4454 | case TypeTableEntryIdUndefLit: |
| 4455 | case TypeTableEntryIdNullLit: |
| 4456 | case TypeTableEntryIdBlock: |
| 4457 | case TypeTableEntryIdNumLitFloat: |
| 4458 | case TypeTableEntryIdNumLitInt: |
| 4459 | case TypeTableEntryIdGenericFn: |
| 4460 | case TypeTableEntryIdMetaType: |
| 4461 | case TypeTableEntryIdFn: |
| 4462 | case TypeTableEntryIdNamespace: |
| 4463 | add_node_error(ira->codegen, size_of_instruction->base.source_node, |
| 4464 | buf_sprintf("no size available for type '%s'", buf_ptr(&type_entry->name))); |
| 4465 | // TODO if this is a typedecl, add error note showing the declaration of the type decl |
| 4466 | return ira->codegen->builtin_types.entry_invalid; |
| 4467 | case TypeTableEntryIdVoid: |
| 4468 | case TypeTableEntryIdBool: |
| 4469 | case TypeTableEntryIdInt: |
| 4470 | case TypeTableEntryIdFloat: |
| 4471 | case TypeTableEntryIdPointer: |
| 4472 | case TypeTableEntryIdArray: |
| 4473 | case TypeTableEntryIdStruct: |
| 4474 | case TypeTableEntryIdMaybe: |
| 4475 | case TypeTableEntryIdErrorUnion: |
| 4476 | case TypeTableEntryIdPureError: |
| 4477 | case TypeTableEntryIdEnum: |
| 4478 | case TypeTableEntryIdUnion: |
| 4479 | { |
| 4480 | uint64_t size_in_bytes = type_size(ira->codegen, type_entry); |
| 4481 | bool depends_on_compile_var = false; // TODO types should be able to depend on compile var |
| 4482 | ConstExprValue *out_val = ir_build_const_from(ira, &size_of_instruction->base, |
| 4483 | depends_on_compile_var); |
| 4484 | bignum_init_unsigned(&out_val->data.x_bignum, size_in_bytes); |
| 4485 | return ira->codegen->builtin_types.entry_num_lit_int; |
| 4486 | } |
| 4487 | } |
| 4488 | zig_unreachable(); |
| 4489 | } |
| 4490 | |
| 4420 | 4491 | static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstruction *instruction) { |
| 4421 | 4492 | switch (instruction->id) { |
| 4422 | 4493 | case IrInstructionIdInvalid: |
| ... | ... | @@ -4471,6 +4542,8 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi |
| 4471 | 4542 | return ir_analyze_instruction_array_type(ira, (IrInstructionArrayType *)instruction); |
| 4472 | 4543 | case IrInstructionIdCompileVar: |
| 4473 | 4544 | return ir_analyze_instruction_compile_var(ira, (IrInstructionCompileVar *)instruction); |
| 4545 | case IrInstructionIdSizeOf: |
| 4546 | return ir_analyze_instruction_size_of(ira, (IrInstructionSizeOf *)instruction); |
| 4474 | 4547 | case IrInstructionIdSwitchBr: |
| 4475 | 4548 | case IrInstructionIdCast: |
| 4476 | 4549 | case IrInstructionIdContainerInitList: |
| ... | ... | @@ -4580,6 +4653,7 @@ bool ir_has_side_effects(IrInstruction *instruction) { |
| 4580 | 4653 | case IrInstructionIdArrayType: |
| 4581 | 4654 | case IrInstructionIdSliceType: |
| 4582 | 4655 | case IrInstructionIdCompileVar: |
| 4656 | case IrInstructionIdSizeOf: |
| 4583 | 4657 | return false; |
| 4584 | 4658 | case IrInstructionIdAsm: |
| 4585 | 4659 | { |
| ... | ... | @@ -5248,24 +5322,6 @@ IrInstruction *ir_exec_const_result(IrExecutable *exec) { |
| 5248 | 5322 | // |
| 5249 | 5323 | // return builtin_fn->return_type; |
| 5250 | 5324 | // } |
| 5251 | | // case BuiltinFnIdSizeof: |
| 5252 | | // { |
| 5253 | | // AstNode *type_node = node->data.fn_call_expr.params.at(0); |
| 5254 | | // TypeTableEntry *type_entry = analyze_type_expr(g, import, context, type_node); |
| 5255 | | // if (type_entry->id == TypeTableEntryIdInvalid) { |
| 5256 | | // return g->builtin_types.entry_invalid; |
| 5257 | | // } else if (type_entry->id == TypeTableEntryIdUnreachable) { |
| 5258 | | // add_node_error(g, first_executing_node(type_node), |
| 5259 | | // buf_sprintf("no size available for type '%s'", buf_ptr(&type_entry->name))); |
| 5260 | | // return g->builtin_types.entry_invalid; |
| 5261 | | // } else { |
| 5262 | | // uint64_t size_in_bytes = type_size(g, type_entry); |
| 5263 | | // bool depends_on_compile_var = (type_entry == g->builtin_types.entry_usize || |
| 5264 | | // type_entry == g->builtin_types.entry_isize); |
| 5265 | | // return resolve_expr_const_val_as_unsigned_num_lit(g, node, expected_type, |
| 5266 | | // size_in_bytes, depends_on_compile_var); |
| 5267 | | // } |
| 5268 | | // } |
| 5269 | 5325 | // case BuiltinFnIdAlignof: |
| 5270 | 5326 | // { |
| 5271 | 5327 | // AstNode *type_node = node->data.fn_call_expr.params.at(0); |
| ... | ... | @@ -8044,7 +8100,6 @@ static void analyze_goto_pass2(CodeGen *g, ImportTableEntry *import, AstNode *no |
| 8044 | 8100 | // LLVMBuildCall(g->builder, builtin_fn->fn_val, params, 5, ""); |
| 8045 | 8101 | // return nullptr; |
| 8046 | 8102 | // } |
| 8047 | | // case BuiltinFnIdSizeof: |
| 8048 | 8103 | // case BuiltinFnIdAlignof: |
| 8049 | 8104 | // case BuiltinFnIdMinValue: |
| 8050 | 8105 | // case BuiltinFnIdMaxValue: |