authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-11-20 02:11:36-05:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-11-20 02:11:36-05:00
logb47e2fa0604a5c785d9ed7d16c8086ecf99357f7
tree03b78e69349eaa6c355b5bbcef693bd3fdae9817
parent6c8b919d17fd456671710087c199bfd7d5a13c38

IR: support sizeOf builtin


4 files changed, 94 insertions(+), 21 deletions(-)

src/all_types.hpp+7
...@@ -1452,6 +1452,7 @@ enum IrInstructionId {...@@ -1452,6 +1452,7 @@ enum IrInstructionId {
1452 IrInstructionIdSliceType,1452 IrInstructionIdSliceType,
1453 IrInstructionIdAsm,1453 IrInstructionIdAsm,
1454 IrInstructionIdCompileVar,1454 IrInstructionIdCompileVar,
1455 IrInstructionIdSizeOf,
1455};1456};
14561457
1457struct IrInstruction {1458struct IrInstruction {
...@@ -1742,6 +1743,12 @@ struct IrInstructionCompileVar {...@@ -1742,6 +1743,12 @@ struct IrInstructionCompileVar {
1742 IrInstruction *name;1743 IrInstruction *name;
1743};1744};
17441745
1746struct IrInstructionSizeOf {
1747 IrInstruction base;
1748
1749 IrInstruction *type_value;
1750};
1751
1745enum LValPurpose {1752enum LValPurpose {
1746 LValPurposeNone,1753 LValPurposeNone,
1747 LValPurposeAssign,1754 LValPurposeAssign,
src/codegen.cpp+1
...@@ -1444,6 +1444,7 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,...@@ -1444,6 +1444,7 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
1444 case IrInstructionIdArrayType:1444 case IrInstructionIdArrayType:
1445 case IrInstructionIdSliceType:1445 case IrInstructionIdSliceType:
1446 case IrInstructionIdCompileVar:1446 case IrInstructionIdCompileVar:
1447 case IrInstructionIdSizeOf:
1447 zig_unreachable();1448 zig_unreachable();
1448 case IrInstructionIdReturn:1449 case IrInstructionIdReturn:
1449 return ir_render_return(g, executable, (IrInstructionReturn *)instruction);1450 return ir_render_return(g, executable, (IrInstructionReturn *)instruction);
src/ir.cpp+75-20
...@@ -222,6 +222,10 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionCompileVar *) {...@@ -222,6 +222,10 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionCompileVar *) {
222 return IrInstructionIdCompileVar;222 return IrInstructionIdCompileVar;
223}223}
224224
225static constexpr IrInstructionId ir_instruction_id(IrInstructionSizeOf *) {
226 return IrInstructionIdSizeOf;
227}
228
225template<typename T>229template<typename T>
226static T *ir_create_instruction(IrExecutable *exec, AstNode *source_node) {230static T *ir_create_instruction(IrExecutable *exec, AstNode *source_node) {
227 T *special_instruction = allocate<T>(1);231 T *special_instruction = allocate<T>(1);
...@@ -865,6 +869,15 @@ static IrInstruction *ir_build_compile_var(IrBuilder *irb, AstNode *source_node,...@@ -865,6 +869,15 @@ static IrInstruction *ir_build_compile_var(IrBuilder *irb, AstNode *source_node,
865 return &instruction->base;869 return &instruction->base;
866}870}
867871
872static 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
868static void ir_gen_defers_for_block(IrBuilder *irb, BlockContext *inner_block, BlockContext *outer_block,881static void ir_gen_defers_for_block(IrBuilder *irb, BlockContext *inner_block, BlockContext *outer_block,
869 bool gen_error_defers, bool gen_maybe_defers)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,9 +1369,17 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, AstNode *node) {
13561369
1357 return ir_build_compile_var(irb, node, arg0_value);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 case BuiltinFnIdMemcpy:1381 case BuiltinFnIdMemcpy:
1360 case BuiltinFnIdMemset:1382 case BuiltinFnIdMemset:
1361 case BuiltinFnIdSizeof:
1362 case BuiltinFnIdAlignof:1383 case BuiltinFnIdAlignof:
1363 case BuiltinFnIdMaxValue:1384 case BuiltinFnIdMaxValue:
1364 case BuiltinFnIdMinValue:1385 case BuiltinFnIdMinValue:
...@@ -4417,6 +4438,56 @@ static TypeTableEntry *ir_analyze_instruction_compile_var(IrAnalyze *ira,...@@ -4417,6 +4438,56 @@ static TypeTableEntry *ir_analyze_instruction_compile_var(IrAnalyze *ira,
4417 zig_unreachable();4438 zig_unreachable();
4418}4439}
44194440
4441static 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
4420static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstruction *instruction) {4491static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstruction *instruction) {
4421 switch (instruction->id) {4492 switch (instruction->id) {
4422 case IrInstructionIdInvalid:4493 case IrInstructionIdInvalid:
...@@ -4471,6 +4542,8 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi...@@ -4471,6 +4542,8 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi
4471 return ir_analyze_instruction_array_type(ira, (IrInstructionArrayType *)instruction);4542 return ir_analyze_instruction_array_type(ira, (IrInstructionArrayType *)instruction);
4472 case IrInstructionIdCompileVar:4543 case IrInstructionIdCompileVar:
4473 return ir_analyze_instruction_compile_var(ira, (IrInstructionCompileVar *)instruction);4544 return ir_analyze_instruction_compile_var(ira, (IrInstructionCompileVar *)instruction);
4545 case IrInstructionIdSizeOf:
4546 return ir_analyze_instruction_size_of(ira, (IrInstructionSizeOf *)instruction);
4474 case IrInstructionIdSwitchBr:4547 case IrInstructionIdSwitchBr:
4475 case IrInstructionIdCast:4548 case IrInstructionIdCast:
4476 case IrInstructionIdContainerInitList:4549 case IrInstructionIdContainerInitList:
...@@ -4580,6 +4653,7 @@ bool ir_has_side_effects(IrInstruction *instruction) {...@@ -4580,6 +4653,7 @@ bool ir_has_side_effects(IrInstruction *instruction) {
4580 case IrInstructionIdArrayType:4653 case IrInstructionIdArrayType:
4581 case IrInstructionIdSliceType:4654 case IrInstructionIdSliceType:
4582 case IrInstructionIdCompileVar:4655 case IrInstructionIdCompileVar:
4656 case IrInstructionIdSizeOf:
4583 return false;4657 return false;
4584 case IrInstructionIdAsm:4658 case IrInstructionIdAsm:
4585 {4659 {
...@@ -5248,24 +5322,6 @@ IrInstruction *ir_exec_const_result(IrExecutable *exec) {...@@ -5248,24 +5322,6 @@ IrInstruction *ir_exec_const_result(IrExecutable *exec) {
5248//5322//
5249// return builtin_fn->return_type;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// case BuiltinFnIdAlignof:5325// case BuiltinFnIdAlignof:
5270// {5326// {
5271// AstNode *type_node = node->data.fn_call_expr.params.at(0);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,7 +8100,6 @@ static void analyze_goto_pass2(CodeGen *g, ImportTableEntry *import, AstNode *no
8044// LLVMBuildCall(g->builder, builtin_fn->fn_val, params, 5, "");8100// LLVMBuildCall(g->builder, builtin_fn->fn_val, params, 5, "");
8045// return nullptr;8101// return nullptr;
8046// }8102// }
8047// case BuiltinFnIdSizeof:
8048// case BuiltinFnIdAlignof:8103// case BuiltinFnIdAlignof:
8049// case BuiltinFnIdMinValue:8104// case BuiltinFnIdMinValue:
8050// case BuiltinFnIdMaxValue:8105// case BuiltinFnIdMaxValue:
src/ir_print.cpp+11-1
...@@ -36,7 +36,8 @@ static void ir_print_const_value(IrPrint *irp, TypeTableEntry *type_entry, Const...@@ -36,7 +36,8 @@ static void ir_print_const_value(IrPrint *irp, TypeTableEntry *type_entry, Const
36 }36 }
37 switch (type_entry->id) {37 switch (type_entry->id) {
38 case TypeTableEntryIdInvalid:38 case TypeTableEntryIdInvalid:
39 zig_unreachable();39 fprintf(irp->f, "(invalid)");
40 break;
40 case TypeTableEntryIdVoid:41 case TypeTableEntryIdVoid:
41 fprintf(irp->f, "{}");42 fprintf(irp->f, "{}");
42 break;43 break;
...@@ -490,6 +491,12 @@ static void ir_print_compile_var(IrPrint *irp, IrInstructionCompileVar *instruct...@@ -490,6 +491,12 @@ static void ir_print_compile_var(IrPrint *irp, IrInstructionCompileVar *instruct
490 fprintf(irp->f, ")");491 fprintf(irp->f, ")");
491}492}
492493
494static void ir_print_size_of(IrPrint *irp, IrInstructionSizeOf *instruction) {
495 fprintf(irp->f, "@sizeOf(");
496 ir_print_other_instruction(irp, instruction->type_value);
497 fprintf(irp->f, ")");
498}
499
493static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {500static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
494 ir_print_prefix(irp, instruction);501 ir_print_prefix(irp, instruction);
495 switch (instruction->id) {502 switch (instruction->id) {
...@@ -582,6 +589,9 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {...@@ -582,6 +589,9 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
582 case IrInstructionIdCompileVar:589 case IrInstructionIdCompileVar:
583 ir_print_compile_var(irp, (IrInstructionCompileVar *)instruction);590 ir_print_compile_var(irp, (IrInstructionCompileVar *)instruction);
584 break;591 break;
592 case IrInstructionIdSizeOf:
593 ir_print_size_of(irp, (IrInstructionSizeOf *)instruction);
594 break;
585 case IrInstructionIdSwitchBr:595 case IrInstructionIdSwitchBr:
586 zig_panic("TODO print more IR instructions");596 zig_panic("TODO print more IR instructions");
587 }597 }