authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-08-23 13:28:26-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-08-23 13:28:26-04:00
log20049caaba0354754811ae0d36a773c31cf4578a
tree427b71702899faf087d5d97237f8021e88b9ee35
parent3865b6ad8f8ba71dca06c81828ec2e29f3019879
signaturelock-open Commit is signed but in an unrecognized format.

add lazy value for fn prototypes

this case now works: ```zig const Node = struct { field: fn (*Node) *Node, }; ```

4 files changed, 183 insertions(+), 63 deletions(-)

src/all_types.hpp+19-6
......@@ -303,11 +303,12 @@ enum LazyValueId {
303303 LazyValueIdAlignOf,
304304 LazyValueIdPtrType,
305305 LazyValueIdSliceType,
306 LazyValueIdFnType,
306307};
307308
308309struct LazyValue {
309 LazyValueId id;
310310 IrExecutable *exec;
311 LazyValueId id;
311312};
312313
313314struct LazyValueAlignOf {
......@@ -317,23 +318,35 @@ struct LazyValueAlignOf {
317318
318319struct LazyValueSliceType {
319320 LazyValue base;
320 ZigType *elem_type;
321 ConstExprValue *align_val; // can be null
322321 bool is_const;
323322 bool is_volatile;
324323 bool is_allowzero;
324
325 ZigType *elem_type;
326 ConstExprValue *align_val; // can be null
325327};
326328
327329struct LazyValuePtrType {
328330 LazyValue base;
331 bool is_const;
332 bool is_volatile;
333 bool is_allowzero;
334
329335 ZigType *elem_type;
330336 ConstExprValue *align_val; // can be null
331337 PtrLen ptr_len;
332338 uint32_t bit_offset_in_host;
333339 uint32_t host_int_bytes;
334 bool is_const;
335 bool is_volatile;
336 bool is_allowzero;
340};
341
342struct LazyValueFnType {
343 LazyValue base;
344 bool is_generic;
345
346 AstNode *proto_node;
347 ConstExprValue **param_types;
348 ConstExprValue *align_val; // can be null
349 ConstExprValue *return_type;
337350};
338351
339352struct ConstExprValue {
src/analyze.cpp+42-4
......@@ -986,11 +986,16 @@ static Error type_val_resolve_zero_bits(CodeGen *g, ConstExprValue *type_val, Zi
986986 case LazyValueIdSliceType:
987987 *is_zero_bits = false;
988988 return ErrorNone;
989 case LazyValueIdFnType: {
990 LazyValueFnType *lazy_fn_type = reinterpret_cast<LazyValueFnType *>(type_val->data.x_lazy);
991 *is_zero_bits = lazy_fn_type->is_generic;
992 return ErrorNone;
993 }
989994 }
990995 zig_unreachable();
991996}
992997
993static Error type_val_resolve_is_opaque_type(CodeGen *g, ConstExprValue *type_val, bool *is_opaque_type) {
998Error type_val_resolve_is_opaque_type(CodeGen *g, ConstExprValue *type_val, bool *is_opaque_type) {
994999 if (type_val->special != ConstValSpecialLazy) {
9951000 assert(type_val->special == ConstValSpecialStatic);
9961001 *is_opaque_type = (type_val->data.x_type->id == ZigTypeIdOpaque);
......@@ -1002,6 +1007,7 @@ static Error type_val_resolve_is_opaque_type(CodeGen *g, ConstExprValue *type_va
10021007 zig_unreachable();
10031008 case LazyValueIdSliceType:
10041009 case LazyValueIdPtrType:
1010 case LazyValueIdFnType:
10051011 *is_opaque_type = false;
10061012 return ErrorNone;
10071013 }
......@@ -1028,6 +1034,34 @@ static ReqCompTime type_val_resolve_requires_comptime(CodeGen *g, ConstExprValue
10281034 return ReqCompTimeInvalid;
10291035 return type_requires_comptime(g, lazy_ptr_type->elem_type, parent_type);
10301036 }
1037 case LazyValueIdFnType: {
1038 LazyValueFnType *lazy_fn_type = reinterpret_cast<LazyValueFnType *>(type_val->data.x_lazy);
1039 if (lazy_fn_type->is_generic)
1040 return ReqCompTimeYes;
1041 switch (type_val_resolve_requires_comptime(g, lazy_fn_type->return_type, parent_type)) {
1042 case ReqCompTimeInvalid:
1043 return ReqCompTimeInvalid;
1044 case ReqCompTimeYes:
1045 return ReqCompTimeYes;
1046 case ReqCompTimeNo:
1047 break;
1048 }
1049 size_t param_count = lazy_fn_type->proto_node->data.fn_proto.params.length;
1050 for (size_t i = 0; i < param_count; i += 1) {
1051 AstNode *param_node = lazy_fn_type->proto_node->data.fn_proto.params.at(i);
1052 bool param_is_var_args = param_node->data.param_decl.is_var_args;
1053 if (param_is_var_args) break;
1054 switch (type_val_resolve_requires_comptime(g, lazy_fn_type->param_types[i], parent_type)) {
1055 case ReqCompTimeInvalid:
1056 return ReqCompTimeInvalid;
1057 case ReqCompTimeYes:
1058 return ReqCompTimeYes;
1059 case ReqCompTimeNo:
1060 break;
1061 }
1062 }
1063 return ReqCompTimeNo;
1064 }
10311065 }
10321066 zig_unreachable();
10331067}
......@@ -1047,6 +1081,7 @@ static Error type_val_resolve_abi_align(CodeGen *g, ConstExprValue *type_val, si
10471081 zig_unreachable();
10481082 case LazyValueIdSliceType:
10491083 case LazyValueIdPtrType:
1084 case LazyValueIdFnType:
10501085 *abi_align = g->builtin_types.entry_usize->abi_align;
10511086 return ErrorNone;
10521087 }
......@@ -1061,8 +1096,9 @@ static OnePossibleValue type_val_resolve_has_one_possible_value(CodeGen *g, Cons
10611096 case LazyValueIdInvalid:
10621097 case LazyValueIdAlignOf:
10631098 zig_unreachable();
1064 case LazyValueIdSliceType:
1065 return OnePossibleValueNo; // it has the len field
1099 case LazyValueIdSliceType: // it has the len field
1100 case LazyValueIdFnType:
1101 return OnePossibleValueNo;
10661102 case LazyValueIdPtrType: {
10671103 Error err;
10681104 bool zero_bits;
......@@ -2395,10 +2431,12 @@ static Error resolve_struct_alignment(CodeGen *g, ZigType *struct_type) {
23952431 } else if (packed) {
23962432 field->align = 1;
23972433 } else {
2398 if ((err = type_val_resolve_abi_align(g, field->type_val, &field->align))) {
2434 size_t result_abi_align;
2435 if ((err = type_val_resolve_abi_align(g, field->type_val, &result_abi_align))) {
23992436 struct_type->data.structure.resolve_status = ResolveStatusInvalid;
24002437 return err;
24012438 }
2439 field->align = result_abi_align;
24022440 }
24032441
24042442 if (field->align > struct_type->abi_align) {
src/analyze.hpp+2
......@@ -247,4 +247,6 @@ ConstExprValue *analyze_const_value_allow_lazy(CodeGen *g, Scope *scope, AstNode
247247void resolve_llvm_types_fn(CodeGen *g, ZigFn *fn);
248248bool fn_is_async(ZigFn *fn);
249249
250Error type_val_resolve_is_opaque_type(CodeGen *g, ConstExprValue *type_val, bool *is_opaque_type);
251
250252#endif
src/ir.cpp+120-53
......@@ -22869,84 +22869,65 @@ static IrInstruction *ir_analyze_instruction_fn_proto(IrAnalyze *ira, IrInstruct
2286922869 AstNode *proto_node = instruction->base.source_node;
2287022870 assert(proto_node->type == NodeTypeFnProto);
2287122871
22872 IrInstruction *result = ir_const(ira, &instruction->base, ira->codegen->builtin_types.entry_type);
22873 result->value.special = ConstValSpecialLazy;
22874
22875 LazyValueFnType *lazy_fn_type = allocate<LazyValueFnType>(1);
22876 result->value.data.x_lazy = &lazy_fn_type->base;
22877 lazy_fn_type->base.id = LazyValueIdFnType;
22878 lazy_fn_type->base.exec = ira->new_irb.exec;
22879
2287222880 if (proto_node->data.fn_proto.auto_err_set) {
2287322881 ir_add_error(ira, &instruction->base,
2287422882 buf_sprintf("inferring error set of return type valid only for function definitions"));
2287522883 return ira->codegen->invalid_instruction;
2287622884 }
2287722885
22878 FnTypeId fn_type_id = {0};
22879 init_fn_type_id(&fn_type_id, proto_node, proto_node->data.fn_proto.params.length);
22886 size_t param_count = proto_node->data.fn_proto.params.length;
22887 lazy_fn_type->proto_node = proto_node;
22888 lazy_fn_type->param_types = allocate<ConstExprValue *>(param_count);
2288022889
22881 for (; fn_type_id.next_param_index < fn_type_id.param_count; fn_type_id.next_param_index += 1) {
22882 AstNode *param_node = proto_node->data.fn_proto.params.at(fn_type_id.next_param_index);
22890 for (size_t param_index = 0; param_index < param_count; param_index += 1) {
22891 AstNode *param_node = proto_node->data.fn_proto.params.at(param_index);
2288322892 assert(param_node->type == NodeTypeParamDecl);
2288422893
2288522894 bool param_is_var_args = param_node->data.param_decl.is_var_args;
2288622895 if (param_is_var_args) {
22887 if (fn_type_id.cc == CallingConventionC) {
22888 fn_type_id.param_count = fn_type_id.next_param_index;
22889 continue;
22890 } else if (fn_type_id.cc == CallingConventionUnspecified) {
22891 return ir_const_type(ira, &instruction->base, get_generic_fn_type(ira->codegen, &fn_type_id));
22896 if (proto_node->data.fn_proto.cc == CallingConventionC) {
22897 break;
22898 } else if (proto_node->data.fn_proto.cc == CallingConventionUnspecified) {
22899 lazy_fn_type->is_generic = true;
22900 return result;
2289222901 } else {
2289322902 zig_unreachable();
2289422903 }
2289522904 }
22896 FnTypeParamInfo *param_info = &fn_type_id.param_info[fn_type_id.next_param_index];
22897 param_info->is_noalias = param_node->data.param_decl.is_noalias;
2289822905
22899 if (instruction->param_types[fn_type_id.next_param_index] == nullptr) {
22900 param_info->type = nullptr;
22901 return ir_const_type(ira, &instruction->base, get_generic_fn_type(ira->codegen, &fn_type_id));
22902 } else {
22903 IrInstruction *param_type_value = instruction->param_types[fn_type_id.next_param_index]->child;
22904 ZigType *param_type = ir_resolve_type(ira, param_type_value);
22905 if (type_is_invalid(param_type))
22906 return ira->codegen->invalid_instruction;
22907 switch (type_requires_comptime(ira->codegen, param_type, nullptr)) {
22908 case ReqCompTimeYes:
22909 if (!calling_convention_allows_zig_types(fn_type_id.cc)) {
22910 ir_add_error(ira, param_type_value,
22911 buf_sprintf("parameter of type '%s' not allowed in function with calling convention '%s'",
22912 buf_ptr(&param_type->name), calling_convention_name(fn_type_id.cc)));
22913 return ira->codegen->invalid_instruction;
22914 }
22915 param_info->type = param_type;
22916 fn_type_id.next_param_index += 1;
22917 return ir_const_type(ira, &instruction->base, get_generic_fn_type(ira->codegen, &fn_type_id));
22918 case ReqCompTimeInvalid:
22919 return ira->codegen->invalid_instruction;
22920 case ReqCompTimeNo:
22921 break;
22922 }
22923 if (!type_has_bits(param_type) && !calling_convention_allows_zig_types(fn_type_id.cc)) {
22924 ir_add_error(ira, param_type_value,
22925 buf_sprintf("parameter of type '%s' has 0 bits; not allowed in function with calling convention '%s'",
22926 buf_ptr(&param_type->name), calling_convention_name(fn_type_id.cc)));
22927 return ira->codegen->invalid_instruction;
22928 }
22929 param_info->type = param_type;
22906 if (instruction->param_types[param_index] == nullptr) {
22907 lazy_fn_type->is_generic = true;
22908 return result;
2293022909 }
2293122910
22911 IrInstruction *param_type_value = instruction->param_types[param_index]->child;
22912 if (type_is_invalid(param_type_value->value.type))
22913 return ira->codegen->invalid_instruction;
22914 ConstExprValue *param_type_val = ir_resolve_const(ira, param_type_value, LazyOk);
22915 if (param_type_val == nullptr)
22916 return ira->codegen->invalid_instruction;
22917 lazy_fn_type->param_types[param_index] = param_type_val;
2293222918 }
2293322919
2293422920 if (instruction->align_value != nullptr) {
22935 if (!ir_resolve_align(ira, instruction->align_value->child, &fn_type_id.alignment))
22921 lazy_fn_type->align_val = ir_resolve_const(ira, instruction->align_value->child, LazyOk);
22922 if (lazy_fn_type->align_val == nullptr)
2293622923 return ira->codegen->invalid_instruction;
2293722924 }
2293822925
22939 IrInstruction *return_type_value = instruction->return_type->child;
22940 fn_type_id.return_type = ir_resolve_type(ira, return_type_value);
22941 if (type_is_invalid(fn_type_id.return_type))
22942 return ira->codegen->invalid_instruction;
22943 if (fn_type_id.return_type->id == ZigTypeIdOpaque) {
22944 ir_add_error(ira, instruction->return_type,
22945 buf_sprintf("return type cannot be opaque"));
22946 return ira->codegen->invalid_instruction;
22947 }
22926 lazy_fn_type->return_type = ir_resolve_const(ira, instruction->return_type->child, LazyOk);
22927 if (lazy_fn_type->return_type == nullptr)
22928 return ira->codegen->invalid_instruction;
2294822929
22949 return ir_const_type(ira, &instruction->base, get_fn_type(ira->codegen, &fn_type_id));
22930 return result;
2295022931}
2295122932
2295222933static IrInstruction *ir_analyze_instruction_test_comptime(IrAnalyze *ira, IrInstructionTestComptime *instruction) {
......@@ -25492,6 +25473,82 @@ bool ir_has_side_effects(IrInstruction *instruction) {
2549225473 zig_unreachable();
2549325474}
2549425475
25476static ZigType *ir_resolve_lazy_fn_type(CodeGen *codegen, IrExecutable *exec, AstNode *source_node,
25477 LazyValueFnType *lazy_fn_type)
25478{
25479 AstNode *proto_node = lazy_fn_type->proto_node;
25480
25481 FnTypeId fn_type_id = {0};
25482 init_fn_type_id(&fn_type_id, proto_node, proto_node->data.fn_proto.params.length);
25483
25484 for (; fn_type_id.next_param_index < fn_type_id.param_count; fn_type_id.next_param_index += 1) {
25485 AstNode *param_node = proto_node->data.fn_proto.params.at(fn_type_id.next_param_index);
25486 assert(param_node->type == NodeTypeParamDecl);
25487
25488 bool param_is_var_args = param_node->data.param_decl.is_var_args;
25489 if (param_is_var_args) {
25490 if (fn_type_id.cc == CallingConventionC) {
25491 fn_type_id.param_count = fn_type_id.next_param_index;
25492 continue;
25493 } else if (fn_type_id.cc == CallingConventionUnspecified) {
25494 return get_generic_fn_type(codegen, &fn_type_id);
25495 } else {
25496 zig_unreachable();
25497 }
25498 }
25499 FnTypeParamInfo *param_info = &fn_type_id.param_info[fn_type_id.next_param_index];
25500 param_info->is_noalias = param_node->data.param_decl.is_noalias;
25501
25502 if (lazy_fn_type->param_types[fn_type_id.next_param_index] == nullptr) {
25503 param_info->type = nullptr;
25504 return get_generic_fn_type(codegen, &fn_type_id);
25505 } else {
25506 ZigType *param_type = ir_resolve_const_type(codegen, exec, source_node,
25507 lazy_fn_type->param_types[fn_type_id.next_param_index]);
25508 if (type_is_invalid(param_type))
25509 return nullptr;
25510 switch (type_requires_comptime(codegen, param_type, nullptr)) {
25511 case ReqCompTimeYes:
25512 if (!calling_convention_allows_zig_types(fn_type_id.cc)) {
25513 exec_add_error_node(codegen, exec, source_node,
25514 buf_sprintf("parameter of type '%s' not allowed in function with calling convention '%s'",
25515 buf_ptr(&param_type->name), calling_convention_name(fn_type_id.cc)));
25516 return nullptr;
25517 }
25518 param_info->type = param_type;
25519 fn_type_id.next_param_index += 1;
25520 return get_generic_fn_type(codegen, &fn_type_id);
25521 case ReqCompTimeInvalid:
25522 return nullptr;
25523 case ReqCompTimeNo:
25524 break;
25525 }
25526 if (!type_has_bits(param_type) && !calling_convention_allows_zig_types(fn_type_id.cc)) {
25527 exec_add_error_node(codegen, exec, source_node,
25528 buf_sprintf("parameter of type '%s' has 0 bits; not allowed in function with calling convention '%s'",
25529 buf_ptr(&param_type->name), calling_convention_name(fn_type_id.cc)));
25530 return nullptr;
25531 }
25532 param_info->type = param_type;
25533 }
25534 }
25535
25536 if (lazy_fn_type->align_val != nullptr) {
25537 if (!ir_resolve_const_align(codegen, exec, source_node, lazy_fn_type->align_val, &fn_type_id.alignment))
25538 return nullptr;
25539 }
25540
25541 fn_type_id.return_type = ir_resolve_const_type(codegen, exec, source_node, lazy_fn_type->return_type);
25542 if (type_is_invalid(fn_type_id.return_type))
25543 return nullptr;
25544 if (fn_type_id.return_type->id == ZigTypeIdOpaque) {
25545 exec_add_error_node(codegen, exec, source_node, buf_create_from_str("return type cannot be opaque"));
25546 return nullptr;
25547 }
25548
25549 return get_fn_type(codegen, &fn_type_id);
25550}
25551
2549525552static Error ir_resolve_lazy_raw(CodeGen *codegen, AstNode *source_node, ConstExprValue *val) {
2549625553 Error err;
2549725554 if (val->special != ConstValSpecialLazy)
......@@ -25551,6 +25608,16 @@ static Error ir_resolve_lazy_raw(CodeGen *codegen, AstNode *source_node, ConstEx
2555125608 val->special = ConstValSpecialStatic;
2555225609 return ErrorNone;
2555325610 }
25611 case LazyValueIdFnType: {
25612 ZigType *fn_type = ir_resolve_lazy_fn_type(codegen, exec, source_node,
25613 reinterpret_cast<LazyValueFnType *>(val->data.x_lazy));
25614 if (fn_type == nullptr)
25615 return ErrorSemanticAnalyzeFail;
25616 val->special = ConstValSpecialStatic;
25617 assert(val->type->id == ZigTypeIdMetaType);
25618 val->data.x_type = fn_type;
25619 return ErrorNone;
25620 }
2555425621 }
2555525622 zig_unreachable();
2555625623}