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 {
14521452 IrInstructionIdSliceType,
14531453 IrInstructionIdAsm,
14541454 IrInstructionIdCompileVar,
1455 IrInstructionIdSizeOf,
14551456};
14561457
14571458struct IrInstruction {
......@@ -1742,6 +1743,12 @@ struct IrInstructionCompileVar {
17421743 IrInstruction *name;
17431744};
17441745
1746struct IrInstructionSizeOf {
1747 IrInstruction base;
1748
1749 IrInstruction *type_value;
1750};
1751
17451752enum LValPurpose {
17461753 LValPurposeNone,
17471754 LValPurposeAssign,
src/codegen.cpp+1
......@@ -1444,6 +1444,7 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
14441444 case IrInstructionIdArrayType:
14451445 case IrInstructionIdSliceType:
14461446 case IrInstructionIdCompileVar:
1447 case IrInstructionIdSizeOf:
14471448 zig_unreachable();
14481449 case IrInstructionIdReturn:
14491450 return ir_render_return(g, executable, (IrInstructionReturn *)instruction);
src/ir.cpp+75-20
......@@ -222,6 +222,10 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionCompileVar *) {
222222 return IrInstructionIdCompileVar;
223223}
224224
225static constexpr IrInstructionId ir_instruction_id(IrInstructionSizeOf *) {
226 return IrInstructionIdSizeOf;
227}
228
225229template<typename T>
226230static T *ir_create_instruction(IrExecutable *exec, AstNode *source_node) {
227231 T *special_instruction = allocate<T>(1);
......@@ -865,6 +869,15 @@ static IrInstruction *ir_build_compile_var(IrBuilder *irb, AstNode *source_node,
865869 return &instruction->base;
866870}
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
868881static void ir_gen_defers_for_block(IrBuilder *irb, BlockContext *inner_block, BlockContext *outer_block,
869882 bool gen_error_defers, bool gen_maybe_defers)
870883{
......@@ -1356,9 +1369,17 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, AstNode *node) {
13561369
13571370 return ir_build_compile_var(irb, node, arg0_value);
13581371 }
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 }
13591381 case BuiltinFnIdMemcpy:
13601382 case BuiltinFnIdMemset:
1361 case BuiltinFnIdSizeof:
13621383 case BuiltinFnIdAlignof:
13631384 case BuiltinFnIdMaxValue:
13641385 case BuiltinFnIdMinValue:
......@@ -4417,6 +4438,56 @@ static TypeTableEntry *ir_analyze_instruction_compile_var(IrAnalyze *ira,
44174438 zig_unreachable();
44184439}
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
44204491static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstruction *instruction) {
44214492 switch (instruction->id) {
44224493 case IrInstructionIdInvalid:
......@@ -4471,6 +4542,8 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi
44714542 return ir_analyze_instruction_array_type(ira, (IrInstructionArrayType *)instruction);
44724543 case IrInstructionIdCompileVar:
44734544 return ir_analyze_instruction_compile_var(ira, (IrInstructionCompileVar *)instruction);
4545 case IrInstructionIdSizeOf:
4546 return ir_analyze_instruction_size_of(ira, (IrInstructionSizeOf *)instruction);
44744547 case IrInstructionIdSwitchBr:
44754548 case IrInstructionIdCast:
44764549 case IrInstructionIdContainerInitList:
......@@ -4580,6 +4653,7 @@ bool ir_has_side_effects(IrInstruction *instruction) {
45804653 case IrInstructionIdArrayType:
45814654 case IrInstructionIdSliceType:
45824655 case IrInstructionIdCompileVar:
4656 case IrInstructionIdSizeOf:
45834657 return false;
45844658 case IrInstructionIdAsm:
45854659 {
......@@ -5248,24 +5322,6 @@ IrInstruction *ir_exec_const_result(IrExecutable *exec) {
52485322//
52495323// return builtin_fn->return_type;
52505324// }
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// }
52695325// case BuiltinFnIdAlignof:
52705326// {
52715327// 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
80448100// LLVMBuildCall(g->builder, builtin_fn->fn_val, params, 5, "");
80458101// return nullptr;
80468102// }
8047// case BuiltinFnIdSizeof:
80488103// case BuiltinFnIdAlignof:
80498104// case BuiltinFnIdMinValue:
80508105// case BuiltinFnIdMaxValue:
src/ir_print.cpp+11-1
......@@ -36,7 +36,8 @@ static void ir_print_const_value(IrPrint *irp, TypeTableEntry *type_entry, Const
3636 }
3737 switch (type_entry->id) {
3838 case TypeTableEntryIdInvalid:
39 zig_unreachable();
39 fprintf(irp->f, "(invalid)");
40 break;
4041 case TypeTableEntryIdVoid:
4142 fprintf(irp->f, "{}");
4243 break;
......@@ -490,6 +491,12 @@ static void ir_print_compile_var(IrPrint *irp, IrInstructionCompileVar *instruct
490491 fprintf(irp->f, ")");
491492}
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
493500static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
494501 ir_print_prefix(irp, instruction);
495502 switch (instruction->id) {
......@@ -582,6 +589,9 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
582589 case IrInstructionIdCompileVar:
583590 ir_print_compile_var(irp, (IrInstructionCompileVar *)instruction);
584591 break;
592 case IrInstructionIdSizeOf:
593 ir_print_size_of(irp, (IrInstructionSizeOf *)instruction);
594 break;
585595 case IrInstructionIdSwitchBr:
586596 zig_panic("TODO print more IR instructions");
587597 }