authorgravatar for robin@voetter.nlRobin Voetter <robin@voetter.nl> 2019-08-30 13:02:28+02:00
committergravatar for robin@voetter.nlRobin Voetter <robin@voetter.nl> 2019-08-30 13:02:28+02:00
logca2aa4880f468f12bcbe3d6cd315729dd361eff2
tree92bdee1022a3497b2f048e450b23d4e585a649f8
parent4b8325f3815c7fa774bb06ef5d190f039723222b
parent10541c8fc88875cb51df0a5fdeda20847133e676

Merge remote-tracking branch 'upstream/master' into arm-support-improvement


18 files changed, 851 insertions(+), 212 deletions(-)

README.md+1-1
...@@ -55,7 +55,7 @@ brew install cmake llvm@8...@@ -55,7 +55,7 @@ brew install cmake llvm@8
55brew outdated llvm@8 || brew upgrade llvm@855brew outdated llvm@8 || brew upgrade llvm@8
56mkdir build56mkdir build
57cd build57cd build
58cmake .. -DCMAKE_PREFIX_PATH=/usr/local/Cellar/llvm/8.0.0_158cmake .. -DCMAKE_PREFIX_PATH=$(brew --prefix llvm)
59make install59make install
60```60```
6161
src/all_types.hpp+23
...@@ -36,6 +36,7 @@ struct IrInstruction;...@@ -36,6 +36,7 @@ struct IrInstruction;
36struct IrInstructionCast;36struct IrInstructionCast;
37struct IrInstructionAllocaGen;37struct IrInstructionAllocaGen;
38struct IrInstructionCallGen;38struct IrInstructionCallGen;
39struct IrInstructionAwaitGen;
39struct IrBasicBlock;40struct IrBasicBlock;
40struct ScopeDecls;41struct ScopeDecls;
41struct ZigWindowsSDK;42struct ZigWindowsSDK;
...@@ -308,10 +309,12 @@ struct ConstGlobalRefs {...@@ -308,10 +309,12 @@ struct ConstGlobalRefs {
308enum LazyValueId {309enum LazyValueId {
309 LazyValueIdInvalid,310 LazyValueIdInvalid,
310 LazyValueIdAlignOf,311 LazyValueIdAlignOf,
312 LazyValueIdSizeOf,
311 LazyValueIdPtrType,313 LazyValueIdPtrType,
312 LazyValueIdOptType,314 LazyValueIdOptType,
313 LazyValueIdSliceType,315 LazyValueIdSliceType,
314 LazyValueIdFnType,316 LazyValueIdFnType,
317 LazyValueIdErrUnionType,
315};318};
316319
317struct LazyValue {320struct LazyValue {
...@@ -325,6 +328,13 @@ struct LazyValueAlignOf {...@@ -325,6 +328,13 @@ struct LazyValueAlignOf {
325 IrInstruction *target_type;328 IrInstruction *target_type;
326};329};
327330
331struct LazyValueSizeOf {
332 LazyValue base;
333
334 IrAnalyze *ira;
335 IrInstruction *target_type;
336};
337
328struct LazyValueSliceType {338struct LazyValueSliceType {
329 LazyValue base;339 LazyValue base;
330340
...@@ -372,6 +382,14 @@ struct LazyValueFnType {...@@ -372,6 +382,14 @@ struct LazyValueFnType {
372 bool is_generic;382 bool is_generic;
373};383};
374384
385struct LazyValueErrUnionType {
386 LazyValue base;
387
388 IrAnalyze *ira;
389 IrInstruction *err_set_type;
390 IrInstruction *payload_type;
391};
392
375struct ConstExprValue {393struct ConstExprValue {
376 ZigType *type;394 ZigType *type;
377 ConstValSpecial special;395 ConstValSpecial special;
...@@ -1205,6 +1223,7 @@ struct ZigTypeStruct {...@@ -1205,6 +1223,7 @@ struct ZigTypeStruct {
1205 HashMap<Buf *, TypeStructField *, buf_hash, buf_eql_buf> fields_by_name;1223 HashMap<Buf *, TypeStructField *, buf_hash, buf_eql_buf> fields_by_name;
1206 RootStruct *root_struct;1224 RootStruct *root_struct;
1207 uint32_t *host_int_bytes; // available for packed structs, indexed by gen_index1225 uint32_t *host_int_bytes; // available for packed structs, indexed by gen_index
1226 size_t llvm_full_type_queue_index;
12081227
1209 uint32_t src_field_count;1228 uint32_t src_field_count;
1210 uint32_t gen_field_count;1229 uint32_t gen_field_count;
...@@ -1468,6 +1487,7 @@ struct ZigFn {...@@ -1468,6 +1487,7 @@ struct ZigFn {
1468 AstNode **param_source_nodes;1487 AstNode **param_source_nodes;
1469 Buf **param_names;1488 Buf **param_names;
1470 IrInstruction *err_code_spill;1489 IrInstruction *err_code_spill;
1490 AstNode *assumed_non_async;
14711491
1472 AstNode *fn_no_inline_set_node;1492 AstNode *fn_no_inline_set_node;
1473 AstNode *fn_static_eval_set_node;1493 AstNode *fn_static_eval_set_node;
...@@ -1485,6 +1505,7 @@ struct ZigFn {...@@ -1485,6 +1505,7 @@ struct ZigFn {
14851505
1486 ZigList<GlobalExport> export_list;1506 ZigList<GlobalExport> export_list;
1487 ZigList<IrInstructionCallGen *> call_list;1507 ZigList<IrInstructionCallGen *> call_list;
1508 ZigList<IrInstructionAwaitGen *> await_list;
14881509
1489 LLVMValueRef valgrind_client_request_array;1510 LLVMValueRef valgrind_client_request_array;
14901511
...@@ -1852,6 +1873,7 @@ struct CodeGen {...@@ -1852,6 +1873,7 @@ struct CodeGen {
1852 ZigList<ErrorTableEntry *> errors_by_index;1873 ZigList<ErrorTableEntry *> errors_by_index;
1853 ZigList<CacheHash *> caches_to_release;1874 ZigList<CacheHash *> caches_to_release;
1854 size_t largest_err_name_len;1875 size_t largest_err_name_len;
1876 ZigList<ZigType *> type_resolve_stack;
18551877
1856 ZigPackage *std_package;1878 ZigPackage *std_package;
1857 ZigPackage *panic_package;1879 ZigPackage *panic_package;
...@@ -3698,6 +3720,7 @@ struct IrInstructionAwaitGen {...@@ -3698,6 +3720,7 @@ struct IrInstructionAwaitGen {
36983720
3699 IrInstruction *frame;3721 IrInstruction *frame;
3700 IrInstruction *result_loc;3722 IrInstruction *result_loc;
3723 ZigFn *target_fn;
3701};3724};
37023725
3703struct IrInstructionResume {3726struct IrInstructionResume {
src/analyze.cpp+194-43
...@@ -31,6 +31,7 @@ static void analyze_fn_body(CodeGen *g, ZigFn *fn_table_entry);...@@ -31,6 +31,7 @@ static void analyze_fn_body(CodeGen *g, ZigFn *fn_table_entry);
31static void resolve_llvm_types(CodeGen *g, ZigType *type, ResolveStatus wanted_resolve_status);31static void resolve_llvm_types(CodeGen *g, ZigType *type, ResolveStatus wanted_resolve_status);
32static void preview_use_decl(CodeGen *g, TldUsingNamespace *using_namespace, ScopeDecls *dest_decls_scope);32static void preview_use_decl(CodeGen *g, TldUsingNamespace *using_namespace, ScopeDecls *dest_decls_scope);
33static void resolve_use_decl(CodeGen *g, TldUsingNamespace *tld_using_namespace, ScopeDecls *dest_decls_scope);33static void resolve_use_decl(CodeGen *g, TldUsingNamespace *tld_using_namespace, ScopeDecls *dest_decls_scope);
34static void analyze_fn_async(CodeGen *g, ZigFn *fn, bool resolve_frame);
3435
35// nullptr means not analyzed yet; this one means currently being analyzed36// nullptr means not analyzed yet; this one means currently being analyzed
36static const AstNode *inferred_async_checking = reinterpret_cast<AstNode *>(0x1);37static const AstNode *inferred_async_checking = reinterpret_cast<AstNode *>(0x1);
...@@ -973,7 +974,7 @@ ConstExprValue *analyze_const_value(CodeGen *g, Scope *scope, AstNode *node, Zig...@@ -973,7 +974,7 @@ ConstExprValue *analyze_const_value(CodeGen *g, Scope *scope, AstNode *node, Zig
973 nullptr, nullptr, node, type_name, nullptr, nullptr, undef);974 nullptr, nullptr, node, type_name, nullptr, nullptr, undef);
974}975}
975976
976static Error type_val_resolve_zero_bits(CodeGen *g, ConstExprValue *type_val, ZigType *parent_type,977Error type_val_resolve_zero_bits(CodeGen *g, ConstExprValue *type_val, ZigType *parent_type,
977 ConstExprValue *parent_type_val, bool *is_zero_bits)978 ConstExprValue *parent_type_val, bool *is_zero_bits)
978{979{
979 Error err;980 Error err;
...@@ -997,6 +998,7 @@ static Error type_val_resolve_zero_bits(CodeGen *g, ConstExprValue *type_val, Zi...@@ -997,6 +998,7 @@ static Error type_val_resolve_zero_bits(CodeGen *g, ConstExprValue *type_val, Zi
997 switch (type_val->data.x_lazy->id) {998 switch (type_val->data.x_lazy->id) {
998 case LazyValueIdInvalid:999 case LazyValueIdInvalid:
999 case LazyValueIdAlignOf:1000 case LazyValueIdAlignOf:
1001 case LazyValueIdSizeOf:
1000 zig_unreachable();1002 zig_unreachable();
1001 case LazyValueIdPtrType: {1003 case LazyValueIdPtrType: {
1002 LazyValuePtrType *lazy_ptr_type = reinterpret_cast<LazyValuePtrType *>(type_val->data.x_lazy);1004 LazyValuePtrType *lazy_ptr_type = reinterpret_cast<LazyValuePtrType *>(type_val->data.x_lazy);
...@@ -1015,6 +1017,7 @@ static Error type_val_resolve_zero_bits(CodeGen *g, ConstExprValue *type_val, Zi...@@ -1015,6 +1017,7 @@ static Error type_val_resolve_zero_bits(CodeGen *g, ConstExprValue *type_val, Zi
1015 }1017 }
1016 case LazyValueIdOptType:1018 case LazyValueIdOptType:
1017 case LazyValueIdSliceType:1019 case LazyValueIdSliceType:
1020 case LazyValueIdErrUnionType:
1018 *is_zero_bits = false;1021 *is_zero_bits = false;
1019 return ErrorNone;1022 return ErrorNone;
1020 case LazyValueIdFnType: {1023 case LazyValueIdFnType: {
...@@ -1035,11 +1038,13 @@ Error type_val_resolve_is_opaque_type(CodeGen *g, ConstExprValue *type_val, bool...@@ -1035,11 +1038,13 @@ Error type_val_resolve_is_opaque_type(CodeGen *g, ConstExprValue *type_val, bool
1035 switch (type_val->data.x_lazy->id) {1038 switch (type_val->data.x_lazy->id) {
1036 case LazyValueIdInvalid:1039 case LazyValueIdInvalid:
1037 case LazyValueIdAlignOf:1040 case LazyValueIdAlignOf:
1041 case LazyValueIdSizeOf:
1038 zig_unreachable();1042 zig_unreachable();
1039 case LazyValueIdSliceType:1043 case LazyValueIdSliceType:
1040 case LazyValueIdPtrType:1044 case LazyValueIdPtrType:
1041 case LazyValueIdFnType:1045 case LazyValueIdFnType:
1042 case LazyValueIdOptType:1046 case LazyValueIdOptType:
1047 case LazyValueIdErrUnionType:
1043 *is_opaque_type = false;1048 *is_opaque_type = false;
1044 return ErrorNone;1049 return ErrorNone;
1045 }1050 }
...@@ -1053,6 +1058,7 @@ static ReqCompTime type_val_resolve_requires_comptime(CodeGen *g, ConstExprValue...@@ -1053,6 +1058,7 @@ static ReqCompTime type_val_resolve_requires_comptime(CodeGen *g, ConstExprValue
1053 switch (type_val->data.x_lazy->id) {1058 switch (type_val->data.x_lazy->id) {
1054 case LazyValueIdInvalid:1059 case LazyValueIdInvalid:
1055 case LazyValueIdAlignOf:1060 case LazyValueIdAlignOf:
1061 case LazyValueIdSizeOf:
1056 zig_unreachable();1062 zig_unreachable();
1057 case LazyValueIdSliceType: {1063 case LazyValueIdSliceType: {
1058 LazyValueSliceType *lazy_slice_type = reinterpret_cast<LazyValueSliceType *>(type_val->data.x_lazy);1064 LazyValueSliceType *lazy_slice_type = reinterpret_cast<LazyValueSliceType *>(type_val->data.x_lazy);
...@@ -1094,18 +1100,21 @@ static ReqCompTime type_val_resolve_requires_comptime(CodeGen *g, ConstExprValue...@@ -1094,18 +1100,21 @@ static ReqCompTime type_val_resolve_requires_comptime(CodeGen *g, ConstExprValue
1094 }1100 }
1095 return ReqCompTimeNo;1101 return ReqCompTimeNo;
1096 }1102 }
1103 case LazyValueIdErrUnionType: {
1104 LazyValueErrUnionType *lazy_err_union_type =
1105 reinterpret_cast<LazyValueErrUnionType *>(type_val->data.x_lazy);
1106 return type_val_resolve_requires_comptime(g, &lazy_err_union_type->payload_type->value);
1107 }
1097 }1108 }
1098 zig_unreachable();1109 zig_unreachable();
1099}1110}
11001111
1101static Error type_val_resolve_abi_size(CodeGen *g, AstNode *source_node, ConstExprValue *type_val,1112Error type_val_resolve_abi_size(CodeGen *g, AstNode *source_node, ConstExprValue *type_val,
1102 size_t *abi_size, size_t *size_in_bits)1113 size_t *abi_size, size_t *size_in_bits)
1103{1114{
1104 Error err;1115 Error err;
1105 if (type_val->data.x_lazy->id == LazyValueIdOptType) {1116
1106 if ((err = ir_resolve_lazy(g, source_node, type_val)))1117start_over:
1107 return err;
1108 }
1109 if (type_val->special != ConstValSpecialLazy) {1118 if (type_val->special != ConstValSpecialLazy) {
1110 assert(type_val->special == ConstValSpecialStatic);1119 assert(type_val->special == ConstValSpecialStatic);
1111 ZigType *ty = type_val->data.x_type;1120 ZigType *ty = type_val->data.x_type;
...@@ -1118,18 +1127,51 @@ static Error type_val_resolve_abi_size(CodeGen *g, AstNode *source_node, ConstEx...@@ -1118,18 +1127,51 @@ static Error type_val_resolve_abi_size(CodeGen *g, AstNode *source_node, ConstEx
1118 switch (type_val->data.x_lazy->id) {1127 switch (type_val->data.x_lazy->id) {
1119 case LazyValueIdInvalid:1128 case LazyValueIdInvalid:
1120 case LazyValueIdAlignOf:1129 case LazyValueIdAlignOf:
1130 case LazyValueIdSizeOf:
1121 zig_unreachable();1131 zig_unreachable();
1122 case LazyValueIdSliceType:1132 case LazyValueIdSliceType: {
1123 *abi_size = g->builtin_types.entry_usize->abi_size * 2;1133 LazyValueSliceType *lazy_slice_type = reinterpret_cast<LazyValueSliceType *>(type_val->data.x_lazy);
1124 *size_in_bits = g->builtin_types.entry_usize->size_in_bits * 2;1134 bool is_zero_bits;
1135 if ((err = type_val_resolve_zero_bits(g, &lazy_slice_type->elem_type->value, nullptr,
1136 nullptr, &is_zero_bits)))
1137 {
1138 return err;
1139 }
1140 if (is_zero_bits) {
1141 *abi_size = g->builtin_types.entry_usize->abi_size;
1142 *size_in_bits = g->builtin_types.entry_usize->size_in_bits;
1143 } else {
1144 *abi_size = g->builtin_types.entry_usize->abi_size * 2;
1145 *size_in_bits = g->builtin_types.entry_usize->size_in_bits * 2;
1146 }
1125 return ErrorNone;1147 return ErrorNone;
1126 case LazyValueIdPtrType:1148 }
1149 case LazyValueIdPtrType: {
1150 LazyValuePtrType *lazy_ptr_type = reinterpret_cast<LazyValuePtrType *>(type_val->data.x_lazy);
1151 bool is_zero_bits;
1152 if ((err = type_val_resolve_zero_bits(g, &lazy_ptr_type->elem_type->value, nullptr,
1153 nullptr, &is_zero_bits)))
1154 {
1155 return err;
1156 }
1157 if (is_zero_bits) {
1158 *abi_size = 0;
1159 *size_in_bits = 0;
1160 } else {
1161 *abi_size = g->builtin_types.entry_usize->abi_size;
1162 *size_in_bits = g->builtin_types.entry_usize->size_in_bits;
1163 }
1164 return ErrorNone;
1165 }
1127 case LazyValueIdFnType:1166 case LazyValueIdFnType:
1128 *abi_size = g->builtin_types.entry_usize->abi_size;1167 *abi_size = g->builtin_types.entry_usize->abi_size;
1129 *size_in_bits = g->builtin_types.entry_usize->size_in_bits;1168 *size_in_bits = g->builtin_types.entry_usize->size_in_bits;
1130 return ErrorNone;1169 return ErrorNone;
1131 case LazyValueIdOptType:1170 case LazyValueIdOptType:
1132 zig_unreachable();1171 case LazyValueIdErrUnionType:
1172 if ((err = ir_resolve_lazy(g, source_node, type_val)))
1173 return err;
1174 goto start_over;
1133 }1175 }
1134 zig_unreachable();1176 zig_unreachable();
1135}1177}
...@@ -1151,6 +1193,7 @@ Error type_val_resolve_abi_align(CodeGen *g, ConstExprValue *type_val, uint32_t...@@ -1151,6 +1193,7 @@ Error type_val_resolve_abi_align(CodeGen *g, ConstExprValue *type_val, uint32_t
1151 switch (type_val->data.x_lazy->id) {1193 switch (type_val->data.x_lazy->id) {
1152 case LazyValueIdInvalid:1194 case LazyValueIdInvalid:
1153 case LazyValueIdAlignOf:1195 case LazyValueIdAlignOf:
1196 case LazyValueIdSizeOf:
1154 zig_unreachable();1197 zig_unreachable();
1155 case LazyValueIdSliceType:1198 case LazyValueIdSliceType:
1156 case LazyValueIdPtrType:1199 case LazyValueIdPtrType:
...@@ -1161,6 +1204,19 @@ Error type_val_resolve_abi_align(CodeGen *g, ConstExprValue *type_val, uint32_t...@@ -1161,6 +1204,19 @@ Error type_val_resolve_abi_align(CodeGen *g, ConstExprValue *type_val, uint32_t
1161 LazyValueOptType *lazy_opt_type = reinterpret_cast<LazyValueOptType *>(type_val->data.x_lazy);1204 LazyValueOptType *lazy_opt_type = reinterpret_cast<LazyValueOptType *>(type_val->data.x_lazy);
1162 return type_val_resolve_abi_align(g, &lazy_opt_type->payload_type->value, abi_align);1205 return type_val_resolve_abi_align(g, &lazy_opt_type->payload_type->value, abi_align);
1163 }1206 }
1207 case LazyValueIdErrUnionType: {
1208 LazyValueErrUnionType *lazy_err_union_type =
1209 reinterpret_cast<LazyValueErrUnionType *>(type_val->data.x_lazy);
1210 uint32_t payload_abi_align;
1211 if ((err = type_val_resolve_abi_align(g, &lazy_err_union_type->payload_type->value,
1212 &payload_abi_align)))
1213 {
1214 return err;
1215 }
1216 *abi_align = (payload_abi_align > g->err_tag_type->abi_align) ?
1217 payload_abi_align : g->err_tag_type->abi_align;
1218 return ErrorNone;
1219 }
1164 }1220 }
1165 zig_unreachable();1221 zig_unreachable();
1166}1222}
...@@ -1172,6 +1228,7 @@ static OnePossibleValue type_val_resolve_has_one_possible_value(CodeGen *g, Cons...@@ -1172,6 +1228,7 @@ static OnePossibleValue type_val_resolve_has_one_possible_value(CodeGen *g, Cons
1172 switch (type_val->data.x_lazy->id) {1228 switch (type_val->data.x_lazy->id) {
1173 case LazyValueIdInvalid:1229 case LazyValueIdInvalid:
1174 case LazyValueIdAlignOf:1230 case LazyValueIdAlignOf:
1231 case LazyValueIdSizeOf:
1175 zig_unreachable();1232 zig_unreachable();
1176 case LazyValueIdSliceType: // it has the len field1233 case LazyValueIdSliceType: // it has the len field
1177 case LazyValueIdOptType: // it has the optional bit1234 case LazyValueIdOptType: // it has the optional bit
...@@ -1189,6 +1246,18 @@ static OnePossibleValue type_val_resolve_has_one_possible_value(CodeGen *g, Cons...@@ -1189,6 +1246,18 @@ static OnePossibleValue type_val_resolve_has_one_possible_value(CodeGen *g, Cons
1189 return OnePossibleValueNo;1246 return OnePossibleValueNo;
1190 }1247 }
1191 }1248 }
1249 case LazyValueIdErrUnionType: {
1250 LazyValueErrUnionType *lazy_err_union_type =
1251 reinterpret_cast<LazyValueErrUnionType *>(type_val->data.x_lazy);
1252 switch (type_val_resolve_has_one_possible_value(g, &lazy_err_union_type->err_set_type->value)) {
1253 case OnePossibleValueInvalid:
1254 return OnePossibleValueInvalid;
1255 case OnePossibleValueNo:
1256 return OnePossibleValueNo;
1257 case OnePossibleValueYes:
1258 return type_val_resolve_has_one_possible_value(g, &lazy_err_union_type->payload_type->value);
1259 }
1260 }
1192 }1261 }
1193 zig_unreachable();1262 zig_unreachable();
1194}1263}
...@@ -4105,8 +4174,14 @@ static void add_async_error_notes(CodeGen *g, ErrorMsg *msg, ZigFn *fn) {...@@ -4105,8 +4174,14 @@ static void add_async_error_notes(CodeGen *g, ErrorMsg *msg, ZigFn *fn) {
4105 assert(fn->inferred_async_node != inferred_async_checking);4174 assert(fn->inferred_async_node != inferred_async_checking);
4106 assert(fn->inferred_async_node != inferred_async_none);4175 assert(fn->inferred_async_node != inferred_async_none);
4107 if (fn->inferred_async_fn != nullptr) {4176 if (fn->inferred_async_fn != nullptr) {
4108 ErrorMsg *new_msg = add_error_note(g, msg, fn->inferred_async_node,4177 ErrorMsg *new_msg;
4109 buf_sprintf("async function call here"));4178 if (fn->inferred_async_node->type == NodeTypeAwaitExpr) {
4179 new_msg = add_error_note(g, msg, fn->inferred_async_node,
4180 buf_create_from_str("await here is a suspend point"));
4181 } else {
4182 new_msg = add_error_note(g, msg, fn->inferred_async_node,
4183 buf_sprintf("async function call here"));
4184 }
4110 return add_async_error_notes(g, new_msg, fn->inferred_async_fn);4185 return add_async_error_notes(g, new_msg, fn->inferred_async_fn);
4111 } else if (fn->inferred_async_node->type == NodeTypeFnProto) {4186 } else if (fn->inferred_async_node->type == NodeTypeFnProto) {
4112 add_error_note(g, msg, fn->inferred_async_node,4187 add_error_note(g, msg, fn->inferred_async_node,
...@@ -4116,7 +4191,7 @@ static void add_async_error_notes(CodeGen *g, ErrorMsg *msg, ZigFn *fn) {...@@ -4116,7 +4191,7 @@ static void add_async_error_notes(CodeGen *g, ErrorMsg *msg, ZigFn *fn) {
4116 buf_sprintf("suspends here"));4191 buf_sprintf("suspends here"));
4117 } else if (fn->inferred_async_node->type == NodeTypeAwaitExpr) {4192 } else if (fn->inferred_async_node->type == NodeTypeAwaitExpr) {
4118 add_error_note(g, msg, fn->inferred_async_node,4193 add_error_note(g, msg, fn->inferred_async_node,
4119 buf_sprintf("await is a suspend point"));4194 buf_sprintf("await here is a suspend point"));
4120 } else if (fn->inferred_async_node->type == NodeTypeFnCallExpr &&4195 } else if (fn->inferred_async_node->type == NodeTypeFnCallExpr &&
4121 fn->inferred_async_node->data.fn_call_expr.is_builtin)4196 fn->inferred_async_node->data.fn_call_expr.is_builtin)
4122 {4197 {
...@@ -4128,6 +4203,64 @@ static void add_async_error_notes(CodeGen *g, ErrorMsg *msg, ZigFn *fn) {...@@ -4128,6 +4203,64 @@ static void add_async_error_notes(CodeGen *g, ErrorMsg *msg, ZigFn *fn) {
4128 }4203 }
4129}4204}
41304205
4206// ErrorNone - not async
4207// ErrorIsAsync - yes async
4208// ErrorSemanticAnalyzeFail - compile error emitted result is invalid
4209static Error analyze_callee_async(CodeGen *g, ZigFn *fn, ZigFn *callee, AstNode *call_node,
4210 bool must_not_be_async)
4211{
4212 if (callee->type_entry->data.fn.fn_type_id.cc != CallingConventionUnspecified)
4213 return ErrorNone;
4214 if (callee->anal_state == FnAnalStateReady) {
4215 analyze_fn_body(g, callee);
4216 if (callee->anal_state == FnAnalStateInvalid) {
4217 return ErrorSemanticAnalyzeFail;
4218 }
4219 }
4220 bool callee_is_async;
4221 if (callee->anal_state == FnAnalStateComplete) {
4222 analyze_fn_async(g, callee, true);
4223 if (callee->anal_state == FnAnalStateInvalid) {
4224 return ErrorSemanticAnalyzeFail;
4225 }
4226 callee_is_async = fn_is_async(callee);
4227 } else {
4228 // If it's already been determined, use that value. Otherwise
4229 // assume non-async, emit an error later if it turned out to be async.
4230 if (callee->inferred_async_node == nullptr ||
4231 callee->inferred_async_node == inferred_async_checking)
4232 {
4233 callee->assumed_non_async = call_node;
4234 callee_is_async = false;
4235 } else {
4236 callee_is_async = callee->inferred_async_node != inferred_async_none;
4237 }
4238 }
4239 if (callee_is_async) {
4240 fn->inferred_async_node = call_node;
4241 fn->inferred_async_fn = callee;
4242 if (must_not_be_async) {
4243 ErrorMsg *msg = add_node_error(g, fn->proto_node,
4244 buf_sprintf("function with calling convention '%s' cannot be async",
4245 calling_convention_name(fn->type_entry->data.fn.fn_type_id.cc)));
4246 add_async_error_notes(g, msg, fn);
4247 return ErrorSemanticAnalyzeFail;
4248 }
4249 if (fn->assumed_non_async != nullptr) {
4250 ErrorMsg *msg = add_node_error(g, fn->proto_node,
4251 buf_sprintf("unable to infer whether '%s' should be async",
4252 buf_ptr(&fn->symbol_name)));
4253 add_error_note(g, msg, fn->assumed_non_async,
4254 buf_sprintf("assumed to be non-async here"));
4255 add_async_error_notes(g, msg, fn);
4256 fn->anal_state = FnAnalStateInvalid;
4257 return ErrorSemanticAnalyzeFail;
4258 }
4259 return ErrorIsAsync;
4260 }
4261 return ErrorNone;
4262}
4263
4131// This function resolves functions being inferred async.4264// This function resolves functions being inferred async.
4132static void analyze_fn_async(CodeGen *g, ZigFn *fn, bool resolve_frame) {4265static void analyze_fn_async(CodeGen *g, ZigFn *fn, bool resolve_frame) {
4133 if (fn->inferred_async_node == inferred_async_checking) {4266 if (fn->inferred_async_node == inferred_async_checking) {
...@@ -4154,42 +4287,40 @@ static void analyze_fn_async(CodeGen *g, ZigFn *fn, bool resolve_frame) {...@@ -4154,42 +4287,40 @@ static void analyze_fn_async(CodeGen *g, ZigFn *fn, bool resolve_frame) {
41544287
4155 for (size_t i = 0; i < fn->call_list.length; i += 1) {4288 for (size_t i = 0; i < fn->call_list.length; i += 1) {
4156 IrInstructionCallGen *call = fn->call_list.at(i);4289 IrInstructionCallGen *call = fn->call_list.at(i);
4157 ZigFn *callee = call->fn_entry;4290 if (call->fn_entry == nullptr) {
4158 if (callee == nullptr) {
4159 // TODO function pointer call here, could be anything4291 // TODO function pointer call here, could be anything
4160 continue;4292 continue;
4161 }4293 }
41624294 switch (analyze_callee_async(g, fn, call->fn_entry, call->base.source_node, must_not_be_async)) {
4163 if (callee->type_entry->data.fn.fn_type_id.cc != CallingConventionUnspecified)4295 case ErrorSemanticAnalyzeFail:
4164 continue;
4165 if (callee->anal_state == FnAnalStateReady) {
4166 analyze_fn_body(g, callee);
4167 if (callee->anal_state == FnAnalStateInvalid) {
4168 fn->anal_state = FnAnalStateInvalid;4296 fn->anal_state = FnAnalStateInvalid;
4169 return;4297 return;
4170 }4298 case ErrorNone:
4171 }4299 continue;
4172 assert(callee->anal_state == FnAnalStateComplete);4300 case ErrorIsAsync:
4173 analyze_fn_async(g, callee, true);4301 if (resolve_frame) {
4174 if (callee->anal_state == FnAnalStateInvalid) {4302 resolve_async_fn_frame(g, fn);
4175 fn->anal_state = FnAnalStateInvalid;4303 }
4176 return;4304 return;
4305 default:
4306 zig_unreachable();
4177 }4307 }
4178 if (fn_is_async(callee)) {4308 }
4179 fn->inferred_async_node = call->base.source_node;4309 for (size_t i = 0; i < fn->await_list.length; i += 1) {
4180 fn->inferred_async_fn = callee;4310 IrInstructionAwaitGen *await = fn->await_list.at(i);
4181 if (must_not_be_async) {4311 switch (analyze_callee_async(g, fn, await->target_fn, await->base.source_node, must_not_be_async)) {
4182 ErrorMsg *msg = add_node_error(g, fn->proto_node,4312 case ErrorSemanticAnalyzeFail:
4183 buf_sprintf("function with calling convention '%s' cannot be async",
4184 calling_convention_name(fn->type_entry->data.fn.fn_type_id.cc)));
4185 add_async_error_notes(g, msg, fn);
4186 fn->anal_state = FnAnalStateInvalid;4313 fn->anal_state = FnAnalStateInvalid;
4187 return;4314 return;
4188 }4315 case ErrorNone:
4189 if (resolve_frame) {4316 continue;
4190 resolve_async_fn_frame(g, fn);4317 case ErrorIsAsync:
4191 }4318 if (resolve_frame) {
4192 return;4319 resolve_async_fn_frame(g, fn);
4320 }
4321 return;
4322 default:
4323 zig_unreachable();
4193 }4324 }
4194 }4325 }
4195 fn->inferred_async_node = inferred_async_none;4326 fn->inferred_async_node = inferred_async_none;
...@@ -4447,6 +4578,8 @@ void semantic_analyze(CodeGen *g) {...@@ -4447,6 +4578,8 @@ void semantic_analyze(CodeGen *g) {
4447 ZigFn *fn = g->fn_defs.at(g->fn_defs_index);4578 ZigFn *fn = g->fn_defs.at(g->fn_defs_index);
4448 g->trace_err = nullptr;4579 g->trace_err = nullptr;
4449 analyze_fn_async(g, fn, true);4580 analyze_fn_async(g, fn, true);
4581 if (fn->anal_state == FnAnalStateInvalid)
4582 continue;
4450 if (fn_is_async(fn) && fn->non_async_node != nullptr) {4583 if (fn_is_async(fn) && fn->non_async_node != nullptr) {
4451 ErrorMsg *msg = add_node_error(g, fn->proto_node,4584 ErrorMsg *msg = add_node_error(g, fn->proto_node,
4452 buf_sprintf("'%s' cannot be async", buf_ptr(&fn->symbol_name)));4585 buf_sprintf("'%s' cannot be async", buf_ptr(&fn->symbol_name)));
...@@ -5599,6 +5732,11 @@ static Error resolve_async_frame(CodeGen *g, ZigType *frame_type) {...@@ -5599,6 +5732,11 @@ static Error resolve_async_frame(CodeGen *g, ZigType *frame_type) {
5599 return ErrorSemanticAnalyzeFail;5732 return ErrorSemanticAnalyzeFail;
5600 }5733 }
5601 analyze_fn_async(g, callee, true);5734 analyze_fn_async(g, callee, true);
5735 if (callee->inferred_async_node == inferred_async_checking) {
5736 assert(g->errors.length != 0);
5737 frame_type->data.frame.locals_struct = g->builtin_types.entry_invalid;
5738 return ErrorSemanticAnalyzeFail;
5739 }
5602 if (!fn_is_async(callee))5740 if (!fn_is_async(callee))
5603 continue;5741 continue;
56045742
...@@ -7238,7 +7376,13 @@ static void resolve_llvm_types_struct(CodeGen *g, ZigType *struct_type, ResolveS...@@ -7238,7 +7376,13 @@ static void resolve_llvm_types_struct(CodeGen *g, ZigType *struct_type, ResolveS
7238 di_scope, di_file, line);7376 di_scope, di_file, line);
72397377
7240 struct_type->data.structure.resolve_status = ResolveStatusLLVMFwdDecl;7378 struct_type->data.structure.resolve_status = ResolveStatusLLVMFwdDecl;
7241 if (ResolveStatusLLVMFwdDecl >= wanted_resolve_status) return;7379 if (ResolveStatusLLVMFwdDecl >= wanted_resolve_status) {
7380 struct_type->data.structure.llvm_full_type_queue_index = g->type_resolve_stack.length;
7381 g->type_resolve_stack.append(struct_type);
7382 return;
7383 } else {
7384 struct_type->data.structure.llvm_full_type_queue_index = SIZE_MAX;
7385 }
7242 }7386 }
72437387
7244 size_t field_count = struct_type->data.structure.src_field_count;7388 size_t field_count = struct_type->data.structure.src_field_count;
...@@ -7442,6 +7586,13 @@ static void resolve_llvm_types_struct(CodeGen *g, ZigType *struct_type, ResolveS...@@ -7442,6 +7586,13 @@ static void resolve_llvm_types_struct(CodeGen *g, ZigType *struct_type, ResolveS
7442 ZigLLVMReplaceTemporary(g->dbuilder, struct_type->llvm_di_type, replacement_di_type);7586 ZigLLVMReplaceTemporary(g->dbuilder, struct_type->llvm_di_type, replacement_di_type);
7443 struct_type->llvm_di_type = replacement_di_type;7587 struct_type->llvm_di_type = replacement_di_type;
7444 struct_type->data.structure.resolve_status = ResolveStatusLLVMFull;7588 struct_type->data.structure.resolve_status = ResolveStatusLLVMFull;
7589 if (struct_type->data.structure.llvm_full_type_queue_index != SIZE_MAX) {
7590 ZigType *last = g->type_resolve_stack.last();
7591 assert(last->id == ZigTypeIdStruct);
7592 last->data.structure.llvm_full_type_queue_index = struct_type->data.structure.llvm_full_type_queue_index;
7593 g->type_resolve_stack.swap_remove(struct_type->data.structure.llvm_full_type_queue_index);
7594 struct_type->data.structure.llvm_full_type_queue_index = SIZE_MAX;
7595 }
7445}7596}
74467597
7447static void resolve_llvm_types_enum(CodeGen *g, ZigType *enum_type, ResolveStatus wanted_resolve_status) {7598static void resolve_llvm_types_enum(CodeGen *g, ZigType *enum_type, ResolveStatus wanted_resolve_status) {
src/analyze.hpp+4
...@@ -247,6 +247,10 @@ void resolve_llvm_types_fn(CodeGen *g, ZigFn *fn);...@@ -247,6 +247,10 @@ void resolve_llvm_types_fn(CodeGen *g, ZigFn *fn);
247bool fn_is_async(ZigFn *fn);247bool fn_is_async(ZigFn *fn);
248248
249Error type_val_resolve_abi_align(CodeGen *g, ConstExprValue *type_val, uint32_t *abi_align);249Error type_val_resolve_abi_align(CodeGen *g, ConstExprValue *type_val, uint32_t *abi_align);
250Error type_val_resolve_abi_size(CodeGen *g, AstNode *source_node, ConstExprValue *type_val,
251 size_t *abi_size, size_t *size_in_bits);
252Error type_val_resolve_zero_bits(CodeGen *g, ConstExprValue *type_val, ZigType *parent_type,
253 ConstExprValue *parent_type_val, bool *is_zero_bits);
250ZigType *resolve_union_field_type(CodeGen *g, TypeUnionField *union_field);254ZigType *resolve_union_field_type(CodeGen *g, TypeUnionField *union_field);
251ZigType *resolve_struct_field_type(CodeGen *g, TypeStructField *struct_field);255ZigType *resolve_struct_field_type(CodeGen *g, TypeStructField *struct_field);
252256
src/codegen.cpp+82-35
...@@ -3052,8 +3052,10 @@ static LLVMValueRef ir_render_ptr_of_array_to_slice(CodeGen *g, IrExecutable *ex...@@ -3052,8 +3052,10 @@ static LLVMValueRef ir_render_ptr_of_array_to_slice(CodeGen *g, IrExecutable *ex
3052 IrInstructionPtrOfArrayToSlice *instruction)3052 IrInstructionPtrOfArrayToSlice *instruction)
3053{3053{
3054 ZigType *actual_type = instruction->operand->value.type;3054 ZigType *actual_type = instruction->operand->value.type;
3055 LLVMValueRef expr_val = ir_llvm_value(g, instruction->operand);3055 ZigType *slice_type = instruction->base.value.type;
3056 assert(expr_val);3056 ZigType *slice_ptr_type = slice_type->data.structure.fields[slice_ptr_index].type_entry;
3057 size_t ptr_index = slice_type->data.structure.fields[slice_ptr_index].gen_index;
3058 size_t len_index = slice_type->data.structure.fields[slice_len_index].gen_index;
30573059
3058 LLVMValueRef result_loc = ir_llvm_value(g, instruction->result_loc);3060 LLVMValueRef result_loc = ir_llvm_value(g, instruction->result_loc);
30593061
...@@ -3061,15 +3063,21 @@ static LLVMValueRef ir_render_ptr_of_array_to_slice(CodeGen *g, IrExecutable *ex...@@ -3061,15 +3063,21 @@ static LLVMValueRef ir_render_ptr_of_array_to_slice(CodeGen *g, IrExecutable *ex
3061 ZigType *array_type = actual_type->data.pointer.child_type;3063 ZigType *array_type = actual_type->data.pointer.child_type;
3062 assert(array_type->id == ZigTypeIdArray);3064 assert(array_type->id == ZigTypeIdArray);
30633065
3064 LLVMValueRef ptr_field_ptr = LLVMBuildStructGEP(g->builder, result_loc, slice_ptr_index, "");3066 if (type_has_bits(actual_type)) {
3065 LLVMValueRef indices[] = {3067 LLVMValueRef ptr_field_ptr = LLVMBuildStructGEP(g->builder, result_loc, ptr_index, "");
3066 LLVMConstNull(g->builtin_types.entry_usize->llvm_type),3068 LLVMValueRef indices[] = {
3067 LLVMConstInt(g->builtin_types.entry_usize->llvm_type, 0, false),3069 LLVMConstNull(g->builtin_types.entry_usize->llvm_type),
3068 };3070 LLVMConstInt(g->builtin_types.entry_usize->llvm_type, 0, false),
3069 LLVMValueRef slice_start_ptr = LLVMBuildInBoundsGEP(g->builder, expr_val, indices, 2, "");3071 };
3070 gen_store_untyped(g, slice_start_ptr, ptr_field_ptr, 0, false);3072 LLVMValueRef expr_val = ir_llvm_value(g, instruction->operand);
3073 LLVMValueRef slice_start_ptr = LLVMBuildInBoundsGEP(g->builder, expr_val, indices, 2, "");
3074 gen_store_untyped(g, slice_start_ptr, ptr_field_ptr, 0, false);
3075 } else if (ir_want_runtime_safety(g, &instruction->base)) {
3076 LLVMValueRef ptr_field_ptr = LLVMBuildStructGEP(g->builder, result_loc, ptr_index, "");
3077 gen_undef_init(g, slice_ptr_type->abi_align, slice_ptr_type, ptr_field_ptr);
3078 }
30713079
3072 LLVMValueRef len_field_ptr = LLVMBuildStructGEP(g->builder, result_loc, slice_len_index, "");3080 LLVMValueRef len_field_ptr = LLVMBuildStructGEP(g->builder, result_loc, len_index, "");
3073 LLVMValueRef len_value = LLVMConstInt(g->builtin_types.entry_usize->llvm_type,3081 LLVMValueRef len_value = LLVMConstInt(g->builtin_types.entry_usize->llvm_type,
3074 array_type->data.array.len, false);3082 array_type->data.array.len, false);
3075 gen_store_untyped(g, len_value, len_field_ptr, 0, false);3083 gen_store_untyped(g, len_value, len_field_ptr, 0, false);
...@@ -3916,7 +3924,7 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr...@@ -3916,7 +3924,7 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr
3916 LLVMBuildStore(g->builder, awaiter_init_val, awaiter_ptr);3924 LLVMBuildStore(g->builder, awaiter_init_val, awaiter_ptr);
39173925
3918 if (ret_has_bits) {3926 if (ret_has_bits) {
3919 LLVMValueRef ret_ptr = LLVMBuildStructGEP(g->builder, frame_result_loc, frame_ret_start + 2, "");3927 ret_ptr = LLVMBuildStructGEP(g->builder, frame_result_loc, frame_ret_start + 2, "");
3920 LLVMValueRef ret_ptr_ptr = LLVMBuildStructGEP(g->builder, frame_result_loc, frame_ret_start, "");3928 LLVMValueRef ret_ptr_ptr = LLVMBuildStructGEP(g->builder, frame_result_loc, frame_ret_start, "");
3921 LLVMBuildStore(g->builder, ret_ptr, ret_ptr_ptr);3929 LLVMBuildStore(g->builder, ret_ptr, ret_ptr_ptr);
39223930
...@@ -4059,6 +4067,9 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr...@@ -4059,6 +4067,9 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr
4059 LLVMValueRef store_instr = LLVMBuildStore(g->builder, result, result_loc);4067 LLVMValueRef store_instr = LLVMBuildStore(g->builder, result, result_loc);
4060 LLVMSetAlignment(store_instr, get_ptr_align(g, instruction->result_loc->value.type));4068 LLVMSetAlignment(store_instr, get_ptr_align(g, instruction->result_loc->value.type));
4061 return result_loc;4069 return result_loc;
4070 } else if (!callee_is_async && instruction->is_async) {
4071 LLVMBuildStore(g->builder, result, ret_ptr);
4072 return result_loc;
4062 } else {4073 } else {
4063 return result;4074 return result;
4064 }4075 }
...@@ -5490,6 +5501,44 @@ static LLVMValueRef ir_render_suspend_finish(CodeGen *g, IrExecutable *executabl...@@ -5490,6 +5501,44 @@ static LLVMValueRef ir_render_suspend_finish(CodeGen *g, IrExecutable *executabl
5490 return nullptr;5501 return nullptr;
5491}5502}
54925503
5504static LLVMValueRef gen_await_early_return(CodeGen *g, IrInstruction *source_instr,
5505 LLVMValueRef target_frame_ptr, ZigType *result_type, ZigType *ptr_result_type,
5506 LLVMValueRef result_loc, bool non_async)
5507{
5508 LLVMTypeRef usize_type_ref = g->builtin_types.entry_usize->llvm_type;
5509 LLVMValueRef their_result_ptr = nullptr;
5510 if (type_has_bits(result_type) && (non_async || result_loc != nullptr)) {
5511 LLVMValueRef their_result_ptr_ptr = LLVMBuildStructGEP(g->builder, target_frame_ptr, frame_ret_start, "");
5512 their_result_ptr = LLVMBuildLoad(g->builder, their_result_ptr_ptr, "");
5513 if (result_loc != nullptr) {
5514 LLVMTypeRef ptr_u8 = LLVMPointerType(LLVMInt8Type(), 0);
5515 LLVMValueRef dest_ptr_casted = LLVMBuildBitCast(g->builder, result_loc, ptr_u8, "");
5516 LLVMValueRef src_ptr_casted = LLVMBuildBitCast(g->builder, their_result_ptr, ptr_u8, "");
5517 bool is_volatile = false;
5518 uint32_t abi_align = get_abi_alignment(g, result_type);
5519 LLVMValueRef byte_count_val = LLVMConstInt(usize_type_ref, type_size(g, result_type), false);
5520 ZigLLVMBuildMemCpy(g->builder,
5521 dest_ptr_casted, abi_align,
5522 src_ptr_casted, abi_align, byte_count_val, is_volatile);
5523 }
5524 }
5525 if (codegen_fn_has_err_ret_tracing_arg(g, result_type)) {
5526 LLVMValueRef their_trace_ptr_ptr = LLVMBuildStructGEP(g->builder, target_frame_ptr,
5527 frame_index_trace_arg(g, result_type), "");
5528 LLVMValueRef src_trace_ptr = LLVMBuildLoad(g->builder, their_trace_ptr_ptr, "");
5529 LLVMValueRef dest_trace_ptr = get_cur_err_ret_trace_val(g, source_instr->scope);
5530 LLVMValueRef args[] = { dest_trace_ptr, src_trace_ptr };
5531 ZigLLVMBuildCall(g->builder, get_merge_err_ret_traces_fn_val(g), args, 2,
5532 get_llvm_cc(g, CallingConventionUnspecified), ZigLLVM_FnInlineAuto, "");
5533 }
5534 if (non_async && type_has_bits(result_type)) {
5535 LLVMValueRef result_ptr = (result_loc == nullptr) ? their_result_ptr : result_loc;
5536 return get_handle_value(g, result_ptr, result_type, ptr_result_type);
5537 } else {
5538 return nullptr;
5539 }
5540}
5541
5493static LLVMValueRef ir_render_await(CodeGen *g, IrExecutable *executable, IrInstructionAwaitGen *instruction) {5542static LLVMValueRef ir_render_await(CodeGen *g, IrExecutable *executable, IrInstructionAwaitGen *instruction) {
5494 LLVMTypeRef usize_type_ref = g->builtin_types.entry_usize->llvm_type;5543 LLVMTypeRef usize_type_ref = g->builtin_types.entry_usize->llvm_type;
5495 LLVMValueRef zero = LLVMConstNull(usize_type_ref);5544 LLVMValueRef zero = LLVMConstNull(usize_type_ref);
...@@ -5497,6 +5546,14 @@ static LLVMValueRef ir_render_await(CodeGen *g, IrExecutable *executable, IrInst...@@ -5497,6 +5546,14 @@ static LLVMValueRef ir_render_await(CodeGen *g, IrExecutable *executable, IrInst
5497 ZigType *result_type = instruction->base.value.type;5546 ZigType *result_type = instruction->base.value.type;
5498 ZigType *ptr_result_type = get_pointer_to_type(g, result_type, true);5547 ZigType *ptr_result_type = get_pointer_to_type(g, result_type, true);
54995548
5549 LLVMValueRef result_loc = (instruction->result_loc == nullptr) ?
5550 nullptr : ir_llvm_value(g, instruction->result_loc);
5551
5552 if (instruction->target_fn != nullptr && !fn_is_async(instruction->target_fn)) {
5553 return gen_await_early_return(g, &instruction->base, target_frame_ptr, result_type,
5554 ptr_result_type, result_loc, true);
5555 }
5556
5500 // Prepare to be suspended5557 // Prepare to be suspended
5501 LLVMBasicBlockRef resume_bb = gen_suspend_begin(g, "AwaitResume");5558 LLVMBasicBlockRef resume_bb = gen_suspend_begin(g, "AwaitResume");
5502 LLVMBasicBlockRef end_bb = LLVMAppendBasicBlock(g->cur_fn_val, "AwaitEnd");5559 LLVMBasicBlockRef end_bb = LLVMAppendBasicBlock(g->cur_fn_val, "AwaitEnd");
...@@ -5504,9 +5561,8 @@ static LLVMValueRef ir_render_await(CodeGen *g, IrExecutable *executable, IrInst...@@ -5504,9 +5561,8 @@ static LLVMValueRef ir_render_await(CodeGen *g, IrExecutable *executable, IrInst
5504 // At this point resuming the function will continue from resume_bb.5561 // At this point resuming the function will continue from resume_bb.
5505 // This code is as if it is running inside the suspend block.5562 // This code is as if it is running inside the suspend block.
55065563
5564
5507 // supply the awaiter return pointer5565 // supply the awaiter return pointer
5508 LLVMValueRef result_loc = (instruction->result_loc == nullptr) ?
5509 nullptr : ir_llvm_value(g, instruction->result_loc);
5510 if (type_has_bits(result_type)) {5566 if (type_has_bits(result_type)) {
5511 LLVMValueRef awaiter_ret_ptr_ptr = LLVMBuildStructGEP(g->builder, target_frame_ptr, frame_ret_start + 1, "");5567 LLVMValueRef awaiter_ret_ptr_ptr = LLVMBuildStructGEP(g->builder, target_frame_ptr, frame_ret_start + 1, "");
5512 if (result_loc == nullptr) {5568 if (result_loc == nullptr) {
...@@ -5554,28 +5610,8 @@ static LLVMValueRef ir_render_await(CodeGen *g, IrExecutable *executable, IrInst...@@ -5554,28 +5610,8 @@ static LLVMValueRef ir_render_await(CodeGen *g, IrExecutable *executable, IrInst
5554 // Early return: The async function has already completed. We must copy the result and5610 // Early return: The async function has already completed. We must copy the result and
5555 // the error return trace if applicable.5611 // the error return trace if applicable.
5556 LLVMPositionBuilderAtEnd(g->builder, early_return_block);5612 LLVMPositionBuilderAtEnd(g->builder, early_return_block);
5557 if (type_has_bits(result_type) && result_loc != nullptr) {5613 gen_await_early_return(g, &instruction->base, target_frame_ptr, result_type, ptr_result_type,
5558 LLVMValueRef their_result_ptr_ptr = LLVMBuildStructGEP(g->builder, target_frame_ptr, frame_ret_start, "");5614 result_loc, false);
5559 LLVMValueRef their_result_ptr = LLVMBuildLoad(g->builder, their_result_ptr_ptr, "");
5560 LLVMTypeRef ptr_u8 = LLVMPointerType(LLVMInt8Type(), 0);
5561 LLVMValueRef dest_ptr_casted = LLVMBuildBitCast(g->builder, result_loc, ptr_u8, "");
5562 LLVMValueRef src_ptr_casted = LLVMBuildBitCast(g->builder, their_result_ptr, ptr_u8, "");
5563 bool is_volatile = false;
5564 uint32_t abi_align = get_abi_alignment(g, result_type);
5565 LLVMValueRef byte_count_val = LLVMConstInt(usize_type_ref, type_size(g, result_type), false);
5566 ZigLLVMBuildMemCpy(g->builder,
5567 dest_ptr_casted, abi_align,
5568 src_ptr_casted, abi_align, byte_count_val, is_volatile);
5569 }
5570 if (codegen_fn_has_err_ret_tracing_arg(g, result_type)) {
5571 LLVMValueRef their_trace_ptr_ptr = LLVMBuildStructGEP(g->builder, target_frame_ptr,
5572 frame_index_trace_arg(g, result_type), "");
5573 LLVMValueRef src_trace_ptr = LLVMBuildLoad(g->builder, their_trace_ptr_ptr, "");
5574 LLVMValueRef dest_trace_ptr = get_cur_err_ret_trace_val(g, instruction->base.scope);
5575 LLVMValueRef args[] = { dest_trace_ptr, src_trace_ptr };
5576 ZigLLVMBuildCall(g->builder, get_merge_err_ret_traces_fn_val(g), args, 2,
5577 get_llvm_cc(g, CallingConventionUnspecified), ZigLLVM_FnInlineAuto, "");
5578 }
5579 LLVMBuildBr(g->builder, end_bb);5615 LLVMBuildBr(g->builder, end_bb);
55805616
5581 LLVMPositionBuilderAtEnd(g->builder, resume_bb);5617 LLVMPositionBuilderAtEnd(g->builder, resume_bb);
...@@ -6837,6 +6873,7 @@ static void set_global_tls(CodeGen *g, ZigVar *var, LLVMValueRef global_value) {...@@ -6837,6 +6873,7 @@ static void set_global_tls(CodeGen *g, ZigVar *var, LLVMValueRef global_value) {
6837}6873}
68386874
6839static void do_code_gen(CodeGen *g) {6875static void do_code_gen(CodeGen *g) {
6876 Error err;
6840 assert(!g->errors.length);6877 assert(!g->errors.length);
68416878
6842 generate_error_name_table(g);6879 generate_error_name_table(g);
...@@ -6850,6 +6887,8 @@ static void do_code_gen(CodeGen *g) {...@@ -6850,6 +6887,8 @@ static void do_code_gen(CodeGen *g) {
6850 // Generate debug info for it but that's it.6887 // Generate debug info for it but that's it.
6851 ConstExprValue *const_val = var->const_value;6888 ConstExprValue *const_val = var->const_value;
6852 assert(const_val->special != ConstValSpecialRuntime);6889 assert(const_val->special != ConstValSpecialRuntime);
6890 if ((err = ir_resolve_lazy(g, var->decl_node, const_val)))
6891 zig_unreachable();
6853 if (const_val->type != var->var_type) {6892 if (const_val->type != var->var_type) {
6854 zig_panic("TODO debug info for var with ptr casted value");6893 zig_panic("TODO debug info for var with ptr casted value");
6855 }6894 }
...@@ -6867,6 +6906,8 @@ static void do_code_gen(CodeGen *g) {...@@ -6867,6 +6906,8 @@ static void do_code_gen(CodeGen *g) {
6867 // Generate debug info for it but that's it.6906 // Generate debug info for it but that's it.
6868 ConstExprValue *const_val = var->const_value;6907 ConstExprValue *const_val = var->const_value;
6869 assert(const_val->special != ConstValSpecialRuntime);6908 assert(const_val->special != ConstValSpecialRuntime);
6909 if ((err = ir_resolve_lazy(g, var->decl_node, const_val)))
6910 zig_unreachable();
6870 if (const_val->type != var->var_type) {6911 if (const_val->type != var->var_type) {
6871 zig_panic("TODO debug info for var with ptr casted value");6912 zig_panic("TODO debug info for var with ptr casted value");
6872 }6913 }
...@@ -7200,6 +7241,12 @@ static void do_code_gen(CodeGen *g) {...@@ -7200,6 +7241,12 @@ static void do_code_gen(CodeGen *g) {
7200 LLVMSetModuleInlineAsm(g->module, buf_ptr(&g->global_asm));7241 LLVMSetModuleInlineAsm(g->module, buf_ptr(&g->global_asm));
7201 }7242 }
72027243
7244 while (g->type_resolve_stack.length != 0) {
7245 ZigType *ty = g->type_resolve_stack.last();
7246 if (type_resolve(g, ty, ResolveStatusLLVMFull))
7247 zig_unreachable();
7248 }
7249
7203 ZigLLVMDIBuilderFinalize(g->dbuilder);7250 ZigLLVMDIBuilderFinalize(g->dbuilder);
72047251
7205 if (g->verbose_llvm_ir) {7252 if (g->verbose_llvm_ir) {
src/error.cpp+2
...@@ -55,6 +55,8 @@ const char *err_str(Error err) {...@@ -55,6 +55,8 @@ const char *err_str(Error err) {
55 case ErrorBrokenPipe: return "broken pipe";55 case ErrorBrokenPipe: return "broken pipe";
56 case ErrorNoSpaceLeft: return "no space left";56 case ErrorNoSpaceLeft: return "no space left";
57 case ErrorNoCCompilerInstalled: return "no C compiler installed";57 case ErrorNoCCompilerInstalled: return "no C compiler installed";
58 case ErrorNotLazy: return "not lazy";
59 case ErrorIsAsync: return "is async";
58 }60 }
59 return "(invalid error)";61 return "(invalid error)";
60}62}
src/ir.cpp+247-86
...@@ -3268,7 +3268,7 @@ static IrInstruction *ir_build_await_src(IrBuilder *irb, Scope *scope, AstNode *...@@ -3268,7 +3268,7 @@ static IrInstruction *ir_build_await_src(IrBuilder *irb, Scope *scope, AstNode *
3268 return &instruction->base;3268 return &instruction->base;
3269}3269}
32703270
3271static IrInstruction *ir_build_await_gen(IrAnalyze *ira, IrInstruction *source_instruction,3271static IrInstructionAwaitGen *ir_build_await_gen(IrAnalyze *ira, IrInstruction *source_instruction,
3272 IrInstruction *frame, ZigType *result_type, IrInstruction *result_loc)3272 IrInstruction *frame, ZigType *result_type, IrInstruction *result_loc)
3273{3273{
3274 IrInstructionAwaitGen *instruction = ir_build_instruction<IrInstructionAwaitGen>(&ira->new_irb,3274 IrInstructionAwaitGen *instruction = ir_build_instruction<IrInstructionAwaitGen>(&ira->new_irb,
...@@ -3280,7 +3280,7 @@ static IrInstruction *ir_build_await_gen(IrAnalyze *ira, IrInstruction *source_i...@@ -3280,7 +3280,7 @@ static IrInstruction *ir_build_await_gen(IrAnalyze *ira, IrInstruction *source_i
3280 ir_ref_instruction(frame, ira->new_irb.current_basic_block);3280 ir_ref_instruction(frame, ira->new_irb.current_basic_block);
3281 if (result_loc != nullptr) ir_ref_instruction(result_loc, ira->new_irb.current_basic_block);3281 if (result_loc != nullptr) ir_ref_instruction(result_loc, ira->new_irb.current_basic_block);
32823282
3283 return &instruction->base;3283 return instruction;
3284}3284}
32853285
3286static IrInstruction *ir_build_resume(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *frame) {3286static IrInstruction *ir_build_resume(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *frame) {
...@@ -10640,7 +10640,9 @@ static void ir_finish_bb(IrAnalyze *ira) {...@@ -10640,7 +10640,9 @@ static void ir_finish_bb(IrAnalyze *ira) {
1064010640
10641static IrInstruction *ir_unreach_error(IrAnalyze *ira) {10641static IrInstruction *ir_unreach_error(IrAnalyze *ira) {
10642 ira->old_bb_index = SIZE_MAX;10642 ira->old_bb_index = SIZE_MAX;
10643 assert(ira->new_irb.exec->first_err_trace_msg != nullptr);10643 if (ira->new_irb.exec->first_err_trace_msg == nullptr) {
10644 ira->new_irb.exec->first_err_trace_msg = ira->codegen->trace_err;
10645 }
10644 return ira->codegen->unreach_instruction;10646 return ira->codegen->unreach_instruction;
10645}10647}
1064610648
...@@ -12932,7 +12934,52 @@ static bool optional_value_is_null(ConstExprValue *val) {...@@ -12932,7 +12934,52 @@ static bool optional_value_is_null(ConstExprValue *val) {
12932 }12934 }
12933}12935}
1293412936
12937// Returns ErrorNotLazy when the value cannot be determined
12938static Error lazy_cmp_zero(AstNode *source_node, ConstExprValue *val, Cmp *result) {
12939 Error err;
12940
12941 switch (val->special) {
12942 case ConstValSpecialRuntime:
12943 case ConstValSpecialUndef:
12944 return ErrorNotLazy;
12945 case ConstValSpecialStatic:
12946 switch (val->type->id) {
12947 case ZigTypeIdComptimeInt:
12948 case ZigTypeIdInt:
12949 *result = bigint_cmp_zero(&val->data.x_bigint);
12950 return ErrorNone;
12951 default:
12952 return ErrorNotLazy;
12953 }
12954 case ConstValSpecialLazy:
12955 switch (val->data.x_lazy->id) {
12956 case LazyValueIdInvalid:
12957 zig_unreachable();
12958 case LazyValueIdAlignOf:
12959 *result = CmpGT;
12960 return ErrorNone;
12961 case LazyValueIdSizeOf: {
12962 LazyValueSizeOf *lazy_size_of = reinterpret_cast<LazyValueSizeOf *>(val->data.x_lazy);
12963 IrAnalyze *ira = lazy_size_of->ira;
12964 bool is_zero_bits;
12965 if ((err = type_val_resolve_zero_bits(ira->codegen, &lazy_size_of->target_type->value,
12966 nullptr, nullptr, &is_zero_bits)))
12967 {
12968 return err;
12969 }
12970 *result = is_zero_bits ? CmpEQ : CmpGT;
12971 return ErrorNone;
12972 }
12973 default:
12974 return ErrorNotLazy;
12975 }
12976 }
12977 zig_unreachable();
12978}
12979
12935static IrInstruction *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp *bin_op_instruction) {12980static IrInstruction *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp *bin_op_instruction) {
12981 Error err;
12982
12936 IrInstruction *op1 = bin_op_instruction->op1->child;12983 IrInstruction *op1 = bin_op_instruction->op1->child;
12937 if (type_is_invalid(op1->value.type))12984 if (type_is_invalid(op1->value.type))
12938 return ira->codegen->invalid_instruction;12985 return ira->codegen->invalid_instruction;
...@@ -13182,6 +13229,50 @@ static IrInstruction *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp *...@@ -13182,6 +13229,50 @@ static IrInstruction *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp *
13182 }13229 }
1318313230
13184 if (one_possible_value || (instr_is_comptime(casted_op1) && instr_is_comptime(casted_op2))) {13231 if (one_possible_value || (instr_is_comptime(casted_op1) && instr_is_comptime(casted_op2))) {
13232 {
13233 // Before resolving the values, we special case comparisons against zero. These can often be done
13234 // without resolving lazy values, preventing potential dependency loops.
13235 Cmp op1_cmp_zero;
13236 if ((err = lazy_cmp_zero(bin_op_instruction->base.source_node, &casted_op1->value, &op1_cmp_zero))) {
13237 if (err == ErrorNotLazy) goto never_mind_just_calculate_it_normally;
13238 return ira->codegen->invalid_instruction;
13239 }
13240 Cmp op2_cmp_zero;
13241 if ((err = lazy_cmp_zero(bin_op_instruction->base.source_node, &casted_op2->value, &op2_cmp_zero))) {
13242 if (err == ErrorNotLazy) goto never_mind_just_calculate_it_normally;
13243 return ira->codegen->invalid_instruction;
13244 }
13245 bool can_cmp_zero = false;
13246 Cmp cmp_result;
13247 if (op1_cmp_zero == CmpEQ && op2_cmp_zero == CmpEQ) {
13248 can_cmp_zero = true;
13249 cmp_result = CmpEQ;
13250 } else if (op1_cmp_zero == CmpGT && op2_cmp_zero == CmpEQ) {
13251 can_cmp_zero = true;
13252 cmp_result = CmpGT;
13253 } else if (op1_cmp_zero == CmpEQ && op2_cmp_zero == CmpGT) {
13254 can_cmp_zero = true;
13255 cmp_result = CmpLT;
13256 } else if (op1_cmp_zero == CmpLT && op2_cmp_zero == CmpEQ) {
13257 can_cmp_zero = true;
13258 cmp_result = CmpLT;
13259 } else if (op1_cmp_zero == CmpEQ && op2_cmp_zero == CmpLT) {
13260 can_cmp_zero = true;
13261 cmp_result = CmpGT;
13262 } else if (op1_cmp_zero == CmpLT && op2_cmp_zero == CmpGT) {
13263 can_cmp_zero = true;
13264 cmp_result = CmpLT;
13265 } else if (op1_cmp_zero == CmpGT && op2_cmp_zero == CmpLT) {
13266 can_cmp_zero = true;
13267 cmp_result = CmpGT;
13268 }
13269 if (can_cmp_zero) {
13270 bool answer = resolve_cmp_op_id(op_id, cmp_result);
13271 return ir_const_bool(ira, &bin_op_instruction->base, answer);
13272 }
13273 }
13274never_mind_just_calculate_it_normally:
13275
13185 ConstExprValue *op1_val = one_possible_value ? &casted_op1->value : ir_resolve_const(ira, casted_op1, UndefBad);13276 ConstExprValue *op1_val = one_possible_value ? &casted_op1->value : ir_resolve_const(ira, casted_op1, UndefBad);
13186 if (op1_val == nullptr)13277 if (op1_val == nullptr)
13187 return ira->codegen->invalid_instruction;13278 return ira->codegen->invalid_instruction;
...@@ -14626,28 +14717,23 @@ static IrInstruction *ir_analyze_instruction_error_return_trace(IrAnalyze *ira,...@@ -14626,28 +14717,23 @@ static IrInstruction *ir_analyze_instruction_error_return_trace(IrAnalyze *ira,
14626static IrInstruction *ir_analyze_instruction_error_union(IrAnalyze *ira,14717static IrInstruction *ir_analyze_instruction_error_union(IrAnalyze *ira,
14627 IrInstructionErrorUnion *instruction)14718 IrInstructionErrorUnion *instruction)
14628{14719{
14629 Error err;14720 IrInstruction *result = ir_const(ira, &instruction->base, ira->codegen->builtin_types.entry_type);
1463014721 result->value.special = ConstValSpecialLazy;
14631 ZigType *err_set_type = ir_resolve_type(ira, instruction->err_set->child);
14632 if (type_is_invalid(err_set_type))
14633 return ira->codegen->invalid_instruction;
1463414722
14635 ZigType *payload_type = ir_resolve_type(ira, instruction->payload->child);14723 LazyValueErrUnionType *lazy_err_union_type = allocate<LazyValueErrUnionType>(1);
14636 if (type_is_invalid(payload_type))14724 lazy_err_union_type->ira = ira;
14637 return ira->codegen->invalid_instruction;14725 result->value.data.x_lazy = &lazy_err_union_type->base;
14726 lazy_err_union_type->base.id = LazyValueIdErrUnionType;
1463814727
14639 if (err_set_type->id != ZigTypeIdErrorSet) {14728 lazy_err_union_type->err_set_type = instruction->err_set->child;
14640 ir_add_error(ira, instruction->err_set->child,14729 if (ir_resolve_type_lazy(ira, lazy_err_union_type->err_set_type) == nullptr)
14641 buf_sprintf("expected error set type, found type '%s'",
14642 buf_ptr(&err_set_type->name)));
14643 return ira->codegen->invalid_instruction;14730 return ira->codegen->invalid_instruction;
14644 }
1464514731
14646 if ((err = type_resolve(ira->codegen, payload_type, ResolveStatusSizeKnown)))14732 lazy_err_union_type->payload_type = instruction->payload->child;
14733 if (ir_resolve_type_lazy(ira, lazy_err_union_type->payload_type) == nullptr)
14647 return ira->codegen->invalid_instruction;14734 return ira->codegen->invalid_instruction;
14648 ZigType *result_type = get_error_union_type(ira->codegen, err_set_type, payload_type);
1464914735
14650 return ir_const_type(ira, &instruction->base, result_type);14736 return result;
14651}14737}
1465214738
14653static IrInstruction *ir_analyze_alloca(IrAnalyze *ira, IrInstruction *source_inst, ZigType *var_type,14739static IrInstruction *ir_analyze_alloca(IrAnalyze *ira, IrInstruction *source_inst, ZigType *var_type,
...@@ -16815,12 +16901,6 @@ static IrInstruction *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruct...@@ -16815,12 +16901,6 @@ static IrInstruction *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruct
16815 return ira->codegen->invalid_instruction;16901 return ira->codegen->invalid_instruction;
1681616902
16817 bool safety_check_on = elem_ptr_instruction->safety_check_on;16903 bool safety_check_on = elem_ptr_instruction->safety_check_on;
16818 if ((err = type_resolve(ira->codegen, return_type->data.pointer.child_type, ResolveStatusSizeKnown)))
16819 return ira->codegen->invalid_instruction;
16820
16821 uint64_t elem_size = type_size(ira->codegen, return_type->data.pointer.child_type);
16822 uint64_t abi_align = get_abi_alignment(ira->codegen, return_type->data.pointer.child_type);
16823 uint64_t ptr_align = get_ptr_align(ira->codegen, return_type);
16824 if (instr_is_comptime(casted_elem_index)) {16904 if (instr_is_comptime(casted_elem_index)) {
16825 uint64_t index = bigint_as_u64(&casted_elem_index->value.data.x_bigint);16905 uint64_t index = bigint_as_u64(&casted_elem_index->value.data.x_bigint);
16826 if (array_type->id == ZigTypeIdArray) {16906 if (array_type->id == ZigTypeIdArray) {
...@@ -16834,8 +16914,16 @@ static IrInstruction *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruct...@@ -16834,8 +16914,16 @@ static IrInstruction *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruct
16834 safety_check_on = false;16914 safety_check_on = false;
16835 }16915 }
1683616916
16837 {16917 if (return_type->data.pointer.explicit_alignment != 0) {
16838 // figure out the largest alignment possible16918 // figure out the largest alignment possible
16919
16920 if ((err = type_resolve(ira->codegen, return_type->data.pointer.child_type, ResolveStatusSizeKnown)))
16921 return ira->codegen->invalid_instruction;
16922
16923 uint64_t elem_size = type_size(ira->codegen, return_type->data.pointer.child_type);
16924 uint64_t abi_align = get_abi_alignment(ira->codegen, return_type->data.pointer.child_type);
16925 uint64_t ptr_align = get_ptr_align(ira->codegen, return_type);
16926
16839 uint64_t chosen_align = abi_align;16927 uint64_t chosen_align = abi_align;
16840 if (ptr_align >= abi_align) {16928 if (ptr_align >= abi_align) {
16841 while (ptr_align > abi_align) {16929 while (ptr_align > abi_align) {
...@@ -17064,15 +17152,24 @@ static IrInstruction *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruct...@@ -17064,15 +17152,24 @@ static IrInstruction *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruct
17064 case ReqCompTimeNo:17152 case ReqCompTimeNo:
17065 break;17153 break;
17066 }17154 }
17067 if (ptr_align < abi_align) {17155
17068 if (elem_size >= ptr_align && elem_size % ptr_align == 0) {17156 if (return_type->data.pointer.explicit_alignment != 0) {
17069 return_type = adjust_ptr_align(ira->codegen, return_type, ptr_align);17157 if ((err = type_resolve(ira->codegen, return_type->data.pointer.child_type, ResolveStatusSizeKnown)))
17158 return ira->codegen->invalid_instruction;
17159
17160 uint64_t elem_size = type_size(ira->codegen, return_type->data.pointer.child_type);
17161 uint64_t abi_align = get_abi_alignment(ira->codegen, return_type->data.pointer.child_type);
17162 uint64_t ptr_align = get_ptr_align(ira->codegen, return_type);
17163 if (ptr_align < abi_align) {
17164 if (elem_size >= ptr_align && elem_size % ptr_align == 0) {
17165 return_type = adjust_ptr_align(ira->codegen, return_type, ptr_align);
17166 } else {
17167 // can't get here because guaranteed elem_size >= abi_align
17168 zig_unreachable();
17169 }
17070 } else {17170 } else {
17071 // can't get here because guaranteed elem_size >= abi_align17171 return_type = adjust_ptr_align(ira->codegen, return_type, abi_align);
17072 zig_unreachable();
17073 }17172 }
17074 } else {
17075 return_type = adjust_ptr_align(ira->codegen, return_type, abi_align);
17076 }17173 }
17077 }17174 }
1707817175
...@@ -18071,54 +18168,20 @@ static IrInstruction *ir_analyze_instruction_array_type(IrAnalyze *ira,...@@ -18071,54 +18168,20 @@ static IrInstruction *ir_analyze_instruction_array_type(IrAnalyze *ira,
18071 zig_unreachable();18168 zig_unreachable();
18072}18169}
1807318170
18074static IrInstruction *ir_analyze_instruction_size_of(IrAnalyze *ira,18171static IrInstruction *ir_analyze_instruction_size_of(IrAnalyze *ira, IrInstructionSizeOf *instruction) {
18075 IrInstructionSizeOf *size_of_instruction)18172 IrInstruction *result = ir_const(ira, &instruction->base, ira->codegen->builtin_types.entry_num_lit_int);
18076{18173 result->value.special = ConstValSpecialLazy;
18077 Error err;
18078 IrInstruction *type_value = size_of_instruction->type_value->child;
18079 ZigType *type_entry = ir_resolve_type(ira, type_value);
1808018174
18081 if ((err = type_resolve(ira->codegen, type_entry, ResolveStatusSizeKnown)))18175 LazyValueSizeOf *lazy_size_of = allocate<LazyValueSizeOf>(1);
18176 lazy_size_of->ira = ira;
18177 result->value.data.x_lazy = &lazy_size_of->base;
18178 lazy_size_of->base.id = LazyValueIdSizeOf;
18179
18180 lazy_size_of->target_type = instruction->type_value->child;
18181 if (ir_resolve_type_lazy(ira, lazy_size_of->target_type) == nullptr)
18082 return ira->codegen->invalid_instruction;18182 return ira->codegen->invalid_instruction;
1808318183
18084 switch (type_entry->id) {18184 return result;
18085 case ZigTypeIdInvalid: // handled above
18086 zig_unreachable();
18087 case ZigTypeIdUnreachable:
18088 case ZigTypeIdUndefined:
18089 case ZigTypeIdNull:
18090 case ZigTypeIdBoundFn:
18091 case ZigTypeIdArgTuple:
18092 case ZigTypeIdOpaque:
18093 ir_add_error_node(ira, type_value->source_node,
18094 buf_sprintf("no size available for type '%s'", buf_ptr(&type_entry->name)));
18095 return ira->codegen->invalid_instruction;
18096 case ZigTypeIdMetaType:
18097 case ZigTypeIdEnumLiteral:
18098 case ZigTypeIdComptimeFloat:
18099 case ZigTypeIdComptimeInt:
18100 case ZigTypeIdVoid:
18101 case ZigTypeIdBool:
18102 case ZigTypeIdInt:
18103 case ZigTypeIdFloat:
18104 case ZigTypeIdPointer:
18105 case ZigTypeIdArray:
18106 case ZigTypeIdStruct:
18107 case ZigTypeIdOptional:
18108 case ZigTypeIdErrorUnion:
18109 case ZigTypeIdErrorSet:
18110 case ZigTypeIdEnum:
18111 case ZigTypeIdUnion:
18112 case ZigTypeIdFn:
18113 case ZigTypeIdVector:
18114 case ZigTypeIdFnFrame:
18115 case ZigTypeIdAnyFrame:
18116 {
18117 uint64_t size_in_bytes = type_size(ira->codegen, type_entry);
18118 return ir_const_unsigned(ira, &size_of_instruction->base, size_in_bytes);
18119 }
18120 }
18121 zig_unreachable();
18122}18185}
1812318186
18124static IrInstruction *ir_analyze_test_non_null(IrAnalyze *ira, IrInstruction *source_inst, IrInstruction *value) {18187static IrInstruction *ir_analyze_test_non_null(IrAnalyze *ira, IrInstruction *source_inst, IrInstruction *value) {
...@@ -24702,18 +24765,22 @@ static IrInstruction *ir_analyze_instruction_suspend_finish(IrAnalyze *ira,...@@ -24702,18 +24765,22 @@ static IrInstruction *ir_analyze_instruction_suspend_finish(IrAnalyze *ira,
24702}24765}
2470324766
24704static IrInstruction *analyze_frame_ptr_to_anyframe_T(IrAnalyze *ira, IrInstruction *source_instr,24767static IrInstruction *analyze_frame_ptr_to_anyframe_T(IrAnalyze *ira, IrInstruction *source_instr,
24705 IrInstruction *frame_ptr)24768 IrInstruction *frame_ptr, ZigFn **target_fn)
24706{24769{
24707 if (type_is_invalid(frame_ptr->value.type))24770 if (type_is_invalid(frame_ptr->value.type))
24708 return ira->codegen->invalid_instruction;24771 return ira->codegen->invalid_instruction;
2470924772
24773 *target_fn = nullptr;
24774
24710 ZigType *result_type;24775 ZigType *result_type;
24711 IrInstruction *frame;24776 IrInstruction *frame;
24712 if (frame_ptr->value.type->id == ZigTypeIdPointer &&24777 if (frame_ptr->value.type->id == ZigTypeIdPointer &&
24713 frame_ptr->value.type->data.pointer.ptr_len == PtrLenSingle &&24778 frame_ptr->value.type->data.pointer.ptr_len == PtrLenSingle &&
24714 frame_ptr->value.type->data.pointer.child_type->id == ZigTypeIdFnFrame)24779 frame_ptr->value.type->data.pointer.child_type->id == ZigTypeIdFnFrame)
24715 {24780 {
24716 result_type = frame_ptr->value.type->data.pointer.child_type->data.frame.fn->type_entry->data.fn.fn_type_id.return_type;24781 ZigFn *func = frame_ptr->value.type->data.pointer.child_type->data.frame.fn;
24782 result_type = func->type_entry->data.fn.fn_type_id.return_type;
24783 *target_fn = func;
24717 frame = frame_ptr;24784 frame = frame_ptr;
24718 } else {24785 } else {
24719 frame = ir_get_deref(ira, source_instr, frame_ptr, nullptr);24786 frame = ir_get_deref(ira, source_instr, frame_ptr, nullptr);
...@@ -24721,7 +24788,9 @@ static IrInstruction *analyze_frame_ptr_to_anyframe_T(IrAnalyze *ira, IrInstruct...@@ -24721,7 +24788,9 @@ static IrInstruction *analyze_frame_ptr_to_anyframe_T(IrAnalyze *ira, IrInstruct
24721 frame->value.type->data.pointer.ptr_len == PtrLenSingle &&24788 frame->value.type->data.pointer.ptr_len == PtrLenSingle &&
24722 frame->value.type->data.pointer.child_type->id == ZigTypeIdFnFrame)24789 frame->value.type->data.pointer.child_type->id == ZigTypeIdFnFrame)
24723 {24790 {
24724 result_type = frame->value.type->data.pointer.child_type->data.frame.fn->type_entry->data.fn.fn_type_id.return_type;24791 ZigFn *func = frame->value.type->data.pointer.child_type->data.frame.fn;
24792 result_type = func->type_entry->data.fn.fn_type_id.return_type;
24793 *target_fn = func;
24725 } else if (frame->value.type->id != ZigTypeIdAnyFrame ||24794 } else if (frame->value.type->id != ZigTypeIdAnyFrame ||
24726 frame->value.type->data.any_frame.result_type == nullptr)24795 frame->value.type->data.any_frame.result_type == nullptr)
24727 {24796 {
...@@ -24742,7 +24811,11 @@ static IrInstruction *analyze_frame_ptr_to_anyframe_T(IrAnalyze *ira, IrInstruct...@@ -24742,7 +24811,11 @@ static IrInstruction *analyze_frame_ptr_to_anyframe_T(IrAnalyze *ira, IrInstruct
24742}24811}
2474324812
24744static IrInstruction *ir_analyze_instruction_await(IrAnalyze *ira, IrInstructionAwaitSrc *instruction) {24813static IrInstruction *ir_analyze_instruction_await(IrAnalyze *ira, IrInstructionAwaitSrc *instruction) {
24745 IrInstruction *frame = analyze_frame_ptr_to_anyframe_T(ira, &instruction->base, instruction->frame->child);24814 IrInstruction *operand = instruction->frame->child;
24815 if (type_is_invalid(operand->value.type))
24816 return ira->codegen->invalid_instruction;
24817 ZigFn *target_fn;
24818 IrInstruction *frame = analyze_frame_ptr_to_anyframe_T(ira, &instruction->base, operand, &target_fn);
24746 if (type_is_invalid(frame->value.type))24819 if (type_is_invalid(frame->value.type))
24747 return ira->codegen->invalid_instruction;24820 return ira->codegen->invalid_instruction;
2474824821
...@@ -24751,8 +24824,11 @@ static IrInstruction *ir_analyze_instruction_await(IrAnalyze *ira, IrInstruction...@@ -24751,8 +24824,11 @@ static IrInstruction *ir_analyze_instruction_await(IrAnalyze *ira, IrInstruction
24751 ZigFn *fn_entry = exec_fn_entry(ira->new_irb.exec);24824 ZigFn *fn_entry = exec_fn_entry(ira->new_irb.exec);
24752 ir_assert(fn_entry != nullptr, &instruction->base);24825 ir_assert(fn_entry != nullptr, &instruction->base);
2475324826
24754 if (fn_entry->inferred_async_node == nullptr) {24827 // If it's not @Frame(func) then it's definitely a suspend point
24755 fn_entry->inferred_async_node = instruction->base.source_node;24828 if (target_fn == nullptr) {
24829 if (fn_entry->inferred_async_node == nullptr) {
24830 fn_entry->inferred_async_node = instruction->base.source_node;
24831 }
24756 }24832 }
2475724833
24758 if (type_can_fail(result_type)) {24834 if (type_can_fail(result_type)) {
...@@ -24769,8 +24845,10 @@ static IrInstruction *ir_analyze_instruction_await(IrAnalyze *ira, IrInstruction...@@ -24769,8 +24845,10 @@ static IrInstruction *ir_analyze_instruction_await(IrAnalyze *ira, IrInstruction
24769 result_loc = nullptr;24845 result_loc = nullptr;
24770 }24846 }
2477124847
24772 IrInstruction *result = ir_build_await_gen(ira, &instruction->base, frame, result_type, result_loc);24848 IrInstructionAwaitGen *result = ir_build_await_gen(ira, &instruction->base, frame, result_type, result_loc);
24773 return ir_finish_anal(ira, result);24849 result->target_fn = target_fn;
24850 fn_entry->await_list.append(result);
24851 return ir_finish_anal(ira, &result->base);
24774}24852}
2477524853
24776static IrInstruction *ir_analyze_instruction_resume(IrAnalyze *ira, IrInstructionResume *instruction) {24854static IrInstruction *ir_analyze_instruction_resume(IrAnalyze *ira, IrInstructionResume *instruction) {
...@@ -25553,6 +25631,61 @@ static Error ir_resolve_lazy_raw(AstNode *source_node, ConstExprValue *val) {...@@ -25553,6 +25631,61 @@ static Error ir_resolve_lazy_raw(AstNode *source_node, ConstExprValue *val) {
25553 bigint_init_unsigned(&val->data.x_bigint, align_in_bytes);25631 bigint_init_unsigned(&val->data.x_bigint, align_in_bytes);
25554 return ErrorNone;25632 return ErrorNone;
25555 }25633 }
25634 case LazyValueIdSizeOf: {
25635 LazyValueSizeOf *lazy_size_of = reinterpret_cast<LazyValueSizeOf *>(val->data.x_lazy);
25636 IrAnalyze *ira = lazy_size_of->ira;
25637
25638 if (lazy_size_of->target_type->value.special == ConstValSpecialStatic) {
25639 switch (lazy_size_of->target_type->value.data.x_type->id) {
25640 case ZigTypeIdInvalid: // handled above
25641 zig_unreachable();
25642 case ZigTypeIdUnreachable:
25643 case ZigTypeIdUndefined:
25644 case ZigTypeIdNull:
25645 case ZigTypeIdBoundFn:
25646 case ZigTypeIdArgTuple:
25647 case ZigTypeIdOpaque:
25648 ir_add_error(ira, lazy_size_of->target_type,
25649 buf_sprintf("no size available for type '%s'",
25650 buf_ptr(&lazy_size_of->target_type->value.data.x_type->name)));
25651 return ErrorSemanticAnalyzeFail;
25652 case ZigTypeIdMetaType:
25653 case ZigTypeIdEnumLiteral:
25654 case ZigTypeIdComptimeFloat:
25655 case ZigTypeIdComptimeInt:
25656 case ZigTypeIdVoid:
25657 case ZigTypeIdBool:
25658 case ZigTypeIdInt:
25659 case ZigTypeIdFloat:
25660 case ZigTypeIdPointer:
25661 case ZigTypeIdArray:
25662 case ZigTypeIdStruct:
25663 case ZigTypeIdOptional:
25664 case ZigTypeIdErrorUnion:
25665 case ZigTypeIdErrorSet:
25666 case ZigTypeIdEnum:
25667 case ZigTypeIdUnion:
25668 case ZigTypeIdFn:
25669 case ZigTypeIdVector:
25670 case ZigTypeIdFnFrame:
25671 case ZigTypeIdAnyFrame:
25672 break;
25673 }
25674 }
25675
25676 uint64_t abi_size;
25677 uint64_t size_in_bits;
25678 if ((err = type_val_resolve_abi_size(ira->codegen, source_node, &lazy_size_of->target_type->value,
25679 &abi_size, &size_in_bits)))
25680 {
25681 return err;
25682 }
25683
25684 val->special = ConstValSpecialStatic;
25685 assert(val->type->id == ZigTypeIdComptimeInt);
25686 bigint_init_unsigned(&val->data.x_bigint, abi_size);
25687 return ErrorNone;
25688 }
25556 case LazyValueIdSliceType: {25689 case LazyValueIdSliceType: {
25557 LazyValueSliceType *lazy_slice_type = reinterpret_cast<LazyValueSliceType *>(val->data.x_lazy);25690 LazyValueSliceType *lazy_slice_type = reinterpret_cast<LazyValueSliceType *>(val->data.x_lazy);
25558 IrAnalyze *ira = lazy_slice_type->ira;25691 IrAnalyze *ira = lazy_slice_type->ira;
...@@ -25698,6 +25831,34 @@ static Error ir_resolve_lazy_raw(AstNode *source_node, ConstExprValue *val) {...@@ -25698,6 +25831,34 @@ static Error ir_resolve_lazy_raw(AstNode *source_node, ConstExprValue *val) {
25698 val->data.x_type = fn_type;25831 val->data.x_type = fn_type;
25699 return ErrorNone;25832 return ErrorNone;
25700 }25833 }
25834 case LazyValueIdErrUnionType: {
25835 LazyValueErrUnionType *lazy_err_union_type =
25836 reinterpret_cast<LazyValueErrUnionType *>(val->data.x_lazy);
25837 IrAnalyze *ira = lazy_err_union_type->ira;
25838
25839 ZigType *err_set_type = ir_resolve_type(ira, lazy_err_union_type->err_set_type);
25840 if (type_is_invalid(err_set_type))
25841 return ErrorSemanticAnalyzeFail;
25842
25843 ZigType *payload_type = ir_resolve_type(ira, lazy_err_union_type->payload_type);
25844 if (type_is_invalid(payload_type))
25845 return ErrorSemanticAnalyzeFail;
25846
25847 if (err_set_type->id != ZigTypeIdErrorSet) {
25848 ir_add_error(ira, lazy_err_union_type->err_set_type,
25849 buf_sprintf("expected error set type, found type '%s'",
25850 buf_ptr(&err_set_type->name)));
25851 return ErrorSemanticAnalyzeFail;
25852 }
25853
25854 if ((err = type_resolve(ira->codegen, payload_type, ResolveStatusSizeKnown)))
25855 return ErrorSemanticAnalyzeFail;
25856
25857 assert(val->type->id == ZigTypeIdMetaType);
25858 val->data.x_type = get_error_union_type(ira->codegen, err_set_type, payload_type);
25859 val->special = ConstValSpecialStatic;
25860 return ErrorNone;
25861 }
25701 }25862 }
25702 zig_unreachable();25863 zig_unreachable();
25703}25864}
src/list.hpp+11
...@@ -74,6 +74,17 @@ struct ZigList {...@@ -74,6 +74,17 @@ struct ZigList {
74 capacity = better_capacity;74 capacity = better_capacity;
75 }75 }
7676
77 T swap_remove(size_t index) {
78 if (length - 1 == index) return pop();
79
80 assert(index != SIZE_MAX);
81 assert(index < length);
82
83 T old_item = items[index];
84 items[index] = pop();
85 return old_item;
86 }
87
77 T *items;88 T *items;
78 size_t length;89 size_t length;
79 size_t capacity;90 size_t capacity;
src/userland.h+2
...@@ -75,6 +75,8 @@ enum Error {...@@ -75,6 +75,8 @@ enum Error {
75 ErrorOperationAborted,75 ErrorOperationAborted,
76 ErrorBrokenPipe,76 ErrorBrokenPipe,
77 ErrorNoSpaceLeft,77 ErrorNoSpaceLeft,
78 ErrorNotLazy,
79 ErrorIsAsync,
78};80};
7981
80// ABI warning82// ABI warning
std/hash/auto_hash.zig+12-2
...@@ -1,5 +1,6 @@...@@ -1,5 +1,6 @@
1const std = @import("std");1const std = @import("std");
2const builtin = @import("builtin");2const builtin = @import("builtin");
3const assert = std.debug.assert;
3const mem = std.mem;4const mem = std.mem;
4const meta = std.meta;5const meta = std.meta;
56
...@@ -165,8 +166,17 @@ pub fn hash(hasher: var, key: var, comptime strat: HashStrategy) void {...@@ -165,8 +166,17 @@ pub fn hash(hasher: var, key: var, comptime strat: HashStrategy) void {
165/// Slices are rejected to avoid ambiguity on the user's intention.166/// Slices are rejected to avoid ambiguity on the user's intention.
166pub fn autoHash(hasher: var, key: var) void {167pub fn autoHash(hasher: var, key: var) void {
167 const Key = @typeOf(key);168 const Key = @typeOf(key);
168 if (comptime meta.trait.isSlice(Key))169 if (comptime meta.trait.isSlice(Key)) {
169 @compileError("std.auto_hash.autoHash does not allow slices (here " ++ @typeName(Key) ++ " because the intent is unclear. Consider using std.auto_hash.hash or providing your own hash function instead.");170 comptime assert(@hasDecl(std, "StringHashMap")); // detect when the following message needs updated
171 const extra_help = if (Key == []const u8)
172 " Consider std.StringHashMap for hashing the contents of []const u8."
173 else
174 "";
175
176 @compileError("std.auto_hash.autoHash does not allow slices (here " ++ @typeName(Key) ++
177 ") because the intent is unclear. Consider using std.auto_hash.hash or providing your own hash function instead." ++
178 extra_help);
179 }
170180
171 hash(hasher, key, .Shallow);181 hash(hasher, key, .Shallow);
172}182}
std/mem.zig+6-5
...@@ -75,15 +75,16 @@ pub const Allocator = struct {...@@ -75,15 +75,16 @@ pub const Allocator = struct {
75 new_alignment: u29,75 new_alignment: u29,
76 ) []u8,76 ) []u8,
7777
78 /// Call `destroy` with the result.78 /// Returns a pointer to undefined memory.
79 /// Returns undefined memory.79 /// Call `destroy` with the result to free the memory.
80 pub fn create(self: *Allocator, comptime T: type) Error!*T {80 pub fn create(self: *Allocator, comptime T: type) Error!*T {
81 if (@sizeOf(T) == 0) return &(T{});81 if (@sizeOf(T) == 0) return &(T{});
82 const slice = try self.alloc(T, 1);82 const slice = try self.alloc(T, 1);
83 return &slice[0];83 return &slice[0];
84 }84 }
8585
86 /// `ptr` should be the return value of `create`86 /// `ptr` should be the return value of `create`, or otherwise
87 /// have the same address and alignment property.
87 pub fn destroy(self: *Allocator, ptr: var) void {88 pub fn destroy(self: *Allocator, ptr: var) void {
88 const T = @typeOf(ptr).Child;89 const T = @typeOf(ptr).Child;
89 if (@sizeOf(T) == 0) return;90 if (@sizeOf(T) == 0) return;
...@@ -92,7 +93,7 @@ pub const Allocator = struct {...@@ -92,7 +93,7 @@ pub const Allocator = struct {
92 assert(shrink_result.len == 0);93 assert(shrink_result.len == 0);
93 }94 }
9495
95 pub fn alloc(self: *Allocator, comptime T: type, n: usize) ![]T {96 pub fn alloc(self: *Allocator, comptime T: type, n: usize) Error![]T {
96 return self.alignedAlloc(T, @alignOf(T), n);97 return self.alignedAlloc(T, @alignOf(T), n);
97 }98 }
9899
...@@ -101,7 +102,7 @@ pub const Allocator = struct {...@@ -101,7 +102,7 @@ pub const Allocator = struct {
101 comptime T: type,102 comptime T: type,
102 comptime alignment: u29,103 comptime alignment: u29,
103 n: usize,104 n: usize,
104 ) ![]align(alignment) T {105 ) Error![]align(alignment) T {
105 if (n == 0) {106 if (n == 0) {
106 return ([*]align(alignment) T)(undefined)[0..0];107 return ([*]align(alignment) T)(undefined)[0..0];
107 }108 }
std/zig/parser_test.zig+111-1
...@@ -210,6 +210,103 @@ test "zig fmt: comment to disable/enable zig fmt" {...@@ -210,6 +210,103 @@ test "zig fmt: comment to disable/enable zig fmt" {
210 );210 );
211}211}
212212
213test "zig fmt: line comment following 'zig fmt: off'" {
214 try testCanonical(
215 \\// zig fmt: off
216 \\// Test
217 \\const e = f;
218 );
219}
220
221test "zig fmt: doc comment following 'zig fmt: off'" {
222 try testCanonical(
223 \\// zig fmt: off
224 \\/// test
225 \\const e = f;
226 );
227}
228
229test "zig fmt: line and doc comment following 'zig fmt: off'" {
230 try testCanonical(
231 \\// zig fmt: off
232 \\// test 1
233 \\/// test 2
234 \\const e = f;
235 );
236}
237
238test "zig fmt: doc and line comment following 'zig fmt: off'" {
239 try testCanonical(
240 \\// zig fmt: off
241 \\/// test 1
242 \\// test 2
243 \\const e = f;
244 );
245}
246
247test "zig fmt: alternating 'zig fmt: off' and 'zig fmt: on'" {
248 try testCanonical(
249 \\// zig fmt: off
250 \\// zig fmt: on
251 \\// zig fmt: off
252 \\const e = f;
253 \\// zig fmt: off
254 \\// zig fmt: on
255 \\// zig fmt: off
256 \\const a = b;
257 \\// zig fmt: on
258 \\const c = d;
259 \\// zig fmt: on
260 \\
261 );
262}
263
264test "zig fmt: line comment following 'zig fmt: on'" {
265 try testCanonical(
266 \\// zig fmt: off
267 \\const e = f;
268 \\// zig fmt: on
269 \\// test
270 \\const e = f;
271 \\
272 );
273}
274
275test "zig fmt: doc comment following 'zig fmt: on'" {
276 try testCanonical(
277 \\// zig fmt: off
278 \\const e = f;
279 \\// zig fmt: on
280 \\/// test
281 \\const e = f;
282 \\
283 );
284}
285
286test "zig fmt: line and doc comment following 'zig fmt: on'" {
287 try testCanonical(
288 \\// zig fmt: off
289 \\const e = f;
290 \\// zig fmt: on
291 \\// test1
292 \\/// test2
293 \\const e = f;
294 \\
295 );
296}
297
298test "zig fmt: doc and line comment following 'zig fmt: on'" {
299 try testCanonical(
300 \\// zig fmt: off
301 \\const e = f;
302 \\// zig fmt: on
303 \\/// test1
304 \\// test2
305 \\const e = f;
306 \\
307 );
308}
309
213test "zig fmt: pointer of unknown length" {310test "zig fmt: pointer of unknown length" {
214 try testCanonical(311 try testCanonical(
215 \\fn foo(ptr: [*]u8) void {}312 \\fn foo(ptr: [*]u8) void {}
...@@ -2278,7 +2375,6 @@ test "zig fmt: if type expr" {...@@ -2278,7 +2375,6 @@ test "zig fmt: if type expr" {
2278 \\2375 \\
2279 );2376 );
2280}2377}
2281
2282test "zig fmt: file ends with struct field" {2378test "zig fmt: file ends with struct field" {
2283 try testTransform(2379 try testTransform(
2284 \\a: bool2380 \\a: bool
...@@ -2288,6 +2384,20 @@ test "zig fmt: file ends with struct field" {...@@ -2288,6 +2384,20 @@ test "zig fmt: file ends with struct field" {
2288 );2384 );
2289}2385}
22902386
2387test "zig fmt: comment after empty comment" {
2388 try testTransform(
2389 \\const x = true; //
2390 \\//
2391 \\//
2392 \\//a
2393 \\
2394 ,
2395 \\const x = true;
2396 \\//a
2397 \\
2398 );
2399}
2400
2291test "zig fmt: comments at several places in struct init" {2401test "zig fmt: comments at several places in struct init" {
2292 try testTransform(2402 try testTransform(
2293 \\var bar = Bar{2403 \\var bar = Bar{
std/zig/render.zig+101-35
...@@ -89,41 +89,98 @@ fn renderRoot(...@@ -89,41 +89,98 @@ fn renderRoot(
89 var it = tree.root_node.decls.iterator(0);89 var it = tree.root_node.decls.iterator(0);
90 while (true) {90 while (true) {
91 var decl = (it.next() orelse return).*;91 var decl = (it.next() orelse return).*;
92 // look for zig fmt: off comment92
93 var start_token_index = decl.firstToken();93 // This loop does the following:
94 zig_fmt_loop: while (start_token_index != 0) {94 //
95 start_token_index -= 1;95 // - Iterates through line/doc comment tokens that precedes the current
96 const start_token = tree.tokens.at(start_token_index);96 // decl.
97 switch (start_token.id) {97 // - Figures out the first token index (`copy_start_token_index`) which
98 // hasn't been copied to the output stream yet.
99 // - Detects `zig fmt: (off|on)` in the line comment tokens, and
100 // determines whether the current decl should be reformatted or not.
101 //
102 var token_index = decl.firstToken();
103 var fmt_active = true;
104 var found_fmt_directive = false;
105
106 var copy_start_token_index = token_index;
107
108 while (token_index != 0) {
109 token_index -= 1;
110 const token = tree.tokens.at(token_index);
111 switch (token.id) {
98 Token.Id.LineComment => {},112 Token.Id.LineComment => {},
99 Token.Id.DocComment => continue,113 Token.Id.DocComment => {
114 copy_start_token_index = token_index;
115 continue;
116 },
100 else => break,117 else => break,
101 }118 }
102 if (mem.eql(u8, mem.trim(u8, tree.tokenSlicePtr(start_token)[2..], " "), "zig fmt: off")) {119
103 var end_token_index = start_token_index;120 if (mem.eql(u8, mem.trim(u8, tree.tokenSlicePtr(token)[2..], " "), "zig fmt: off")) {
104 while (true) {121 if (!found_fmt_directive) {
105 end_token_index += 1;122 fmt_active = false;
106 const end_token = tree.tokens.at(end_token_index);123 found_fmt_directive = true;
107 switch (end_token.id) {124 }
125 } else if (mem.eql(u8, mem.trim(u8, tree.tokenSlicePtr(token)[2..], " "), "zig fmt: on")) {
126 if (!found_fmt_directive) {
127 fmt_active = true;
128 found_fmt_directive = true;
129 }
130 }
131 }
132
133 if (!fmt_active) {
134 // Reformatting is disabled for the current decl and possibly some
135 // more decls that follow.
136 // Find the next `decl` for which reformatting is re-enabled.
137 token_index = decl.firstToken();
138
139 while (!fmt_active) {
140 decl = (it.next() orelse {
141 // If there's no next reformatted `decl`, just copy the
142 // remaining input tokens and bail out.
143 const start = tree.tokens.at(copy_start_token_index).start;
144 try copyFixingWhitespace(stream, tree.source[start..]);
145 return;
146 }).*;
147 var decl_first_token_index = decl.firstToken();
148
149 while (token_index < decl_first_token_index) : (token_index += 1) {
150 const token = tree.tokens.at(token_index);
151 switch (token.id) {
108 Token.Id.LineComment => {},152 Token.Id.LineComment => {},
109 Token.Id.Eof => {153 Token.Id.Eof => unreachable,
110 const start = tree.tokens.at(start_token_index + 1).start;
111 try copyFixingWhitespace(stream, tree.source[start..]);
112 return;
113 },
114 else => continue,154 else => continue,
115 }155 }
116 if (mem.eql(u8, mem.trim(u8, tree.tokenSlicePtr(end_token)[2..], " "), "zig fmt: on")) {156 if (mem.eql(u8, mem.trim(u8, tree.tokenSlicePtr(token)[2..], " "), "zig fmt: on")) {
117 const start = tree.tokens.at(start_token_index + 1).start;157 fmt_active = true;
118 try copyFixingWhitespace(stream, tree.source[start..end_token.end]);158 } else if (mem.eql(u8, mem.trim(u8, tree.tokenSlicePtr(token)[2..], " "), "zig fmt: off")) {
119 try stream.writeByte('\n');159 fmt_active = false;
120 while (tree.tokens.at(decl.firstToken()).start < end_token.end) {
121 decl = (it.next() orelse return).*;
122 }
123 break :zig_fmt_loop;
124 }160 }
125 }161 }
126 }162 }
163
164 // Found the next `decl` for which reformatting is enabled. Copy
165 // the input tokens before the `decl` that haven't been copied yet.
166 var copy_end_token_index = decl.firstToken();
167 token_index = copy_end_token_index;
168 while (token_index != 0) {
169 token_index -= 1;
170 const token = tree.tokens.at(token_index);
171 switch (token.id) {
172 Token.Id.LineComment => {},
173 Token.Id.DocComment => {
174 copy_end_token_index = token_index;
175 continue;
176 },
177 else => break,
178 }
179 }
180
181 const start = tree.tokens.at(copy_start_token_index).start;
182 const end = tree.tokens.at(copy_end_token_index).start;
183 try copyFixingWhitespace(stream, tree.source[start..end]);
127 }184 }
128185
129 try renderTopLevelDecl(allocator, stream, tree, 0, &start_col, decl);186 try renderTopLevelDecl(allocator, stream, tree, 0, &start_col, decl);
...@@ -1937,15 +1994,24 @@ fn renderTokenOffset(...@@ -1937,15 +1994,24 @@ fn renderTokenOffset(
1937 }1994 }
1938 }1995 }
19391996
1940 const comment_is_empty = mem.trimRight(u8, tree.tokenSlicePtr(next_token), " ").len == 2;1997 while (true) {
1941 if (comment_is_empty) {1998 const comment_is_empty = mem.trimRight(u8, tree.tokenSlicePtr(next_token), " ").len == 2;
1942 switch (space) {1999 if (comment_is_empty) {
1943 Space.Newline => {2000 switch (space) {
1944 try stream.writeByte('\n');2001 Space.Newline => {
1945 start_col.* = 0;2002 offset += 1;
1946 return;2003 token = next_token;
1947 },2004 next_token = tree.tokens.at(token_index + offset);
1948 else => {},2005 if (next_token.id != .LineComment) {
2006 try stream.writeByte('\n');
2007 start_col.* = 0;
2008 return;
2009 }
2010 },
2011 else => break,
2012 }
2013 } else {
2014 break;
1949 }2015 }
1950 }2016 }
19512017
test/compile_errors.zig+4-4
...@@ -273,7 +273,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -273,7 +273,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
273 \\}273 \\}
274 ,274 ,
275 "tmp.zig:1:1: error: function with calling convention 'ccc' cannot be async",275 "tmp.zig:1:1: error: function with calling convention 'ccc' cannot be async",
276 "tmp.zig:3:18: note: await is a suspend point",276 "tmp.zig:3:18: note: await here is a suspend point",
277 );277 );
278278
279 cases.add(279 cases.add(
...@@ -507,11 +507,11 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -507,11 +507,11 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
507507
508 cases.add(508 cases.add(
509 "@sizeOf bad type",509 "@sizeOf bad type",
510 \\export fn entry() void {510 \\export fn entry() usize {
511 \\ _ = @sizeOf(@typeOf(null));511 \\ return @sizeOf(@typeOf(null));
512 \\}512 \\}
513 ,513 ,
514 "tmp.zig:2:17: error: no size available for type '(null)'",514 "tmp.zig:2:20: error: no size available for type '(null)'",
515 );515 );
516516
517 cases.add(517 cases.add(
test/stage1/behavior/array.zig+6
...@@ -292,3 +292,9 @@ test "read/write through global variable array of struct fields initialized via...@@ -292,3 +292,9 @@ test "read/write through global variable array of struct fields initialized via
292 };292 };
293 S.doTheTest();293 S.doTheTest();
294}294}
295
296test "implicit cast zero sized array ptr to slice" {
297 var b = "";
298 const c: []const u8 = &b;
299 expect(c.len == 0);
300}
test/stage1/behavior/async_fn.zig+10
...@@ -844,3 +844,13 @@ test "cast fn to async fn when it is inferred to be async" {...@@ -844,3 +844,13 @@ test "cast fn to async fn when it is inferred to be async" {
844 resume S.frame;844 resume S.frame;
845 expect(S.ok);845 expect(S.ok);
846}846}
847
848test "await does not force async if callee is blocking" {
849 const S = struct {
850 fn simple() i32 {
851 return 1234;
852 }
853 };
854 var x = async S.simple();
855 expect(await x == 1234);
856}
test/stage1/behavior/error.zig+20
...@@ -375,3 +375,23 @@ test "implicit cast to optional to error union to return result loc" {...@@ -375,3 +375,23 @@ test "implicit cast to optional to error union to return result loc" {
375 S.entry();375 S.entry();
376 //comptime S.entry(); TODO376 //comptime S.entry(); TODO
377}377}
378
379test "function pointer with return type that is error union with payload which is pointer of parent struct" {
380 const S = struct {
381 const Foo = struct {
382 fun: fn (a: i32) (anyerror!*Foo),
383 };
384
385 const Err = error{UnspecifiedErr};
386
387 fn bar(a: i32) anyerror!*Foo {
388 return Err.UnspecifiedErr;
389 }
390
391 fn doTheTest() void {
392 var x = Foo{ .fun = bar };
393 expectError(error.UnspecifiedErr, x.fun(1));
394 }
395 };
396 S.doTheTest();
397}
test/stage1/behavior/sizeof_and_typeof.zig+15
...@@ -74,3 +74,18 @@ test "@sizeOf on compile-time types" {...@@ -74,3 +74,18 @@ test "@sizeOf on compile-time types" {
74 expect(@sizeOf(@typeOf(.hi)) == 0);74 expect(@sizeOf(@typeOf(.hi)) == 0);
75 expect(@sizeOf(@typeOf(type)) == 0);75 expect(@sizeOf(@typeOf(type)) == 0);
76}76}
77
78test "@sizeOf(T) == 0 doesn't force resolving struct size" {
79 const S = struct {
80 const Foo = struct {
81 y: if (@sizeOf(Foo) == 0) u64 else u32,
82 };
83 const Bar = struct {
84 x: i32,
85 y: if (0 == @sizeOf(Bar)) u64 else u32,
86 };
87 };
88
89 expect(@sizeOf(S.Foo) == 4);
90 expect(@sizeOf(S.Bar) == 8);
91}