| author | |
| committer | |
| log | 72e983670e65eac0b89da5564432988862828b30 |
| tree | 0fe5e7c91bbeee208e5b2036207c41f9eae20b99 |
| parent | 54e716afdcb0609cfc42229ad925e6dc9b07a66f |
| signature | Commit is signed but in an unrecognized format. |
7 files changed, 448 insertions(+), 66 deletions(-)
CMakeLists.txt+1-1| ... | ... | @@ -426,7 +426,6 @@ set(ZIG_MAIN_SRC "${CMAKE_SOURCE_DIR}/src/main.cpp") |
| 426 | 426 | set(ZIG0_SHIM_SRC "${CMAKE_SOURCE_DIR}/src/userland.cpp") |
| 427 | 427 | |
| 428 | 428 | set(ZIG_SOURCES |
| 429 | "${CMAKE_SOURCE_DIR}/src/glibc.cpp" | |
| 430 | 429 | "${CMAKE_SOURCE_DIR}/src/analyze.cpp" |
| 431 | 430 | "${CMAKE_SOURCE_DIR}/src/ast_render.cpp" |
| 432 | 431 | "${CMAKE_SOURCE_DIR}/src/bigfloat.cpp" |
| ... | ... | @@ -438,6 +437,7 @@ set(ZIG_SOURCES |
| 438 | 437 | "${CMAKE_SOURCE_DIR}/src/compiler.cpp" |
| 439 | 438 | "${CMAKE_SOURCE_DIR}/src/errmsg.cpp" |
| 440 | 439 | "${CMAKE_SOURCE_DIR}/src/error.cpp" |
| 440 | "${CMAKE_SOURCE_DIR}/src/glibc.cpp" | |
| 441 | 441 | "${CMAKE_SOURCE_DIR}/src/ir.cpp" |
| 442 | 442 | "${CMAKE_SOURCE_DIR}/src/ir_print.cpp" |
| 443 | 443 | "${CMAKE_SOURCE_DIR}/src/libc_installation.cpp" |
src/all_types.hpp+30| ... | ... | @@ -1251,6 +1251,7 @@ enum ZigTypeId { |
| 1251 | 1251 | ZigTypeIdBoundFn, |
| 1252 | 1252 | ZigTypeIdArgTuple, |
| 1253 | 1253 | ZigTypeIdOpaque, |
| 1254 | ZigTypeIdCoroFrame, | |
| 1254 | 1255 | ZigTypeIdVector, |
| 1255 | 1256 | ZigTypeIdEnumLiteral, |
| 1256 | 1257 | }; |
| ... | ... | @@ -1265,6 +1266,11 @@ struct ZigTypeOpaque { |
| 1265 | 1266 | Buf *bare_name; |
| 1266 | 1267 | }; |
| 1267 | 1268 | |
| 1269 | struct ZigTypeCoroFrame { | |
| 1270 | ZigFn *fn; | |
| 1271 | ZigType *locals_struct; | |
| 1272 | }; | |
| 1273 | ||
| 1268 | 1274 | struct ZigType { |
| 1269 | 1275 | ZigTypeId id; |
| 1270 | 1276 | Buf name; |
| ... | ... | @@ -1290,6 +1296,7 @@ struct ZigType { |
| 1290 | 1296 | ZigTypeBoundFn bound_fn; |
| 1291 | 1297 | ZigTypeVector vector; |
| 1292 | 1298 | ZigTypeOpaque opaque; |
| 1299 | ZigTypeCoroFrame frame; | |
| 1293 | 1300 | } data; |
| 1294 | 1301 | |
| 1295 | 1302 | // use these fields to make sure we don't duplicate type table entries for the same type |
| ... | ... | @@ -1340,6 +1347,7 @@ struct ZigFn { |
| 1340 | 1347 | ScopeBlock *def_scope; // parent is child_scope |
| 1341 | 1348 | Buf symbol_name; |
| 1342 | 1349 | ZigType *type_entry; // function type |
| 1350 | ZigType *frame_type; // coro frame type | |
| 1343 | 1351 | // in the case of normal functions this is the implicit return type |
| 1344 | 1352 | // in the case of async functions this is the implicit return type according to the |
| 1345 | 1353 | // zig source code, not according to zig ir |
| ... | ... | @@ -1356,6 +1364,7 @@ struct ZigFn { |
| 1356 | 1364 | |
| 1357 | 1365 | ZigList<IrInstructionAllocaGen *> alloca_gen_list; |
| 1358 | 1366 | ZigList<ZigVar *> variable_list; |
| 1367 | ZigList<IrBasicBlock *> resume_blocks; | |
| 1359 | 1368 | |
| 1360 | 1369 | Buf *section_name; |
| 1361 | 1370 | AstNode *set_alignstack_node; |
| ... | ... | @@ -1365,6 +1374,7 @@ struct ZigFn { |
| 1365 | 1374 | ZigList<GlobalExport> export_list; |
| 1366 | 1375 | |
| 1367 | 1376 | LLVMValueRef valgrind_client_request_array; |
| 1377 | LLVMBasicBlockRef preamble_llvm_block; | |
| 1368 | 1378 | |
| 1369 | 1379 | FnInline fn_inline; |
| 1370 | 1380 | FnAnalState anal_state; |
| ... | ... | @@ -1512,6 +1522,7 @@ enum PanicMsgId { |
| 1512 | 1522 | PanicMsgIdBadEnumValue, |
| 1513 | 1523 | PanicMsgIdFloatToInt, |
| 1514 | 1524 | PanicMsgIdPtrCastNull, |
| 1525 | PanicMsgIdBadResume, | |
| 1515 | 1526 | |
| 1516 | 1527 | PanicMsgIdCount, |
| 1517 | 1528 | }; |
| ... | ... | @@ -1755,6 +1766,7 @@ struct CodeGen { |
| 1755 | 1766 | ZigType *entry_global_error_set; |
| 1756 | 1767 | ZigType *entry_arg_tuple; |
| 1757 | 1768 | ZigType *entry_enum_literal; |
| 1769 | ZigType *entry_frame_header; | |
| 1758 | 1770 | } builtin_types; |
| 1759 | 1771 | ZigType *align_amt_type; |
| 1760 | 1772 | ZigType *stack_trace_type; |
| ... | ... | @@ -2119,6 +2131,8 @@ struct IrBasicBlock { |
| 2119 | 2131 | size_t ref_count; |
| 2120 | 2132 | // index into the basic block list |
| 2121 | 2133 | size_t index; |
| 2134 | // for coroutines, the resume_index which corresponds to this block | |
| 2135 | size_t resume_index; | |
| 2122 | 2136 | LLVMBasicBlockRef llvm_block; |
| 2123 | 2137 | LLVMBasicBlockRef llvm_exit_block; |
| 2124 | 2138 | // The instruction that referenced this basic block and caused us to |
| ... | ... | @@ -2297,6 +2311,8 @@ enum IrInstructionId { |
| 2297 | 2311 | IrInstructionIdEndExpr, |
| 2298 | 2312 | IrInstructionIdPtrOfArrayToSlice, |
| 2299 | 2313 | IrInstructionIdUnionInitNamedField, |
| 2314 | IrInstructionIdSuspendBegin, | |
| 2315 | IrInstructionIdSuspendBr, | |
| 2300 | 2316 | }; |
| 2301 | 2317 | |
| 2302 | 2318 | struct IrInstruction { |
| ... | ... | @@ -3511,6 +3527,18 @@ struct IrInstructionPtrOfArrayToSlice { |
| 3511 | 3527 | IrInstruction *result_loc; |
| 3512 | 3528 | }; |
| 3513 | 3529 | |
| 3530 | struct IrInstructionSuspendBegin { | |
| 3531 | IrInstruction base; | |
| 3532 | ||
| 3533 | IrBasicBlock *resume_block; | |
| 3534 | }; | |
| 3535 | ||
| 3536 | struct IrInstructionSuspendBr { | |
| 3537 | IrInstruction base; | |
| 3538 | ||
| 3539 | IrBasicBlock *resume_block; | |
| 3540 | }; | |
| 3541 | ||
| 3514 | 3542 | enum ResultLocId { |
| 3515 | 3543 | ResultLocIdInvalid, |
| 3516 | 3544 | ResultLocIdNone, |
| ... | ... | @@ -3593,6 +3621,8 @@ static const size_t maybe_null_index = 1; |
| 3593 | 3621 | static const size_t err_union_err_index = 0; |
| 3594 | 3622 | static const size_t err_union_payload_index = 1; |
| 3595 | 3623 | |
| 3624 | static const size_t coro_resume_index_index = 0; | |
| 3625 | ||
| 3596 | 3626 | // TODO call graph analysis to find out what this number needs to be for every function |
| 3597 | 3627 | // MUST BE A POWER OF TWO. |
| 3598 | 3628 | static const size_t stack_trace_ptr_count = 32; |
src/analyze.cpp+123-14| ... | ... | @@ -228,6 +228,8 @@ AstNode *type_decl_node(ZigType *type_entry) { |
| 228 | 228 | return type_entry->data.enumeration.decl_node; |
| 229 | 229 | case ZigTypeIdUnion: |
| 230 | 230 | return type_entry->data.unionation.decl_node; |
| 231 | case ZigTypeIdCoroFrame: | |
| 232 | return type_entry->data.frame.fn->proto_node; | |
| 231 | 233 | case ZigTypeIdOpaque: |
| 232 | 234 | case ZigTypeIdMetaType: |
| 233 | 235 | case ZigTypeIdVoid: |
| ... | ... | @@ -262,6 +264,20 @@ bool type_is_resolved(ZigType *type_entry, ResolveStatus status) { |
| 262 | 264 | return type_entry->data.structure.resolve_status >= status; |
| 263 | 265 | case ZigTypeIdUnion: |
| 264 | 266 | return type_entry->data.unionation.resolve_status >= status; |
| 267 | case ZigTypeIdCoroFrame: | |
| 268 | switch (status) { | |
| 269 | case ResolveStatusInvalid: | |
| 270 | zig_unreachable(); | |
| 271 | case ResolveStatusUnstarted: | |
| 272 | case ResolveStatusZeroBitsKnown: | |
| 273 | return true; | |
| 274 | case ResolveStatusAlignmentKnown: | |
| 275 | case ResolveStatusSizeKnown: | |
| 276 | return type_entry->data.frame.locals_struct != nullptr; | |
| 277 | case ResolveStatusLLVMFwdDecl: | |
| 278 | case ResolveStatusLLVMFull: | |
| 279 | return type_entry->llvm_type != nullptr; | |
| 280 | } | |
| 265 | 281 | case ZigTypeIdEnum: |
| 266 | 282 | switch (status) { |
| 267 | 283 | case ResolveStatusUnstarted: |
| ... | ... | @@ -345,6 +361,25 @@ static const char *ptr_len_to_star_str(PtrLen ptr_len) { |
| 345 | 361 | zig_unreachable(); |
| 346 | 362 | } |
| 347 | 363 | |
| 364 | ZigType *get_coro_frame_type(CodeGen *g, ZigFn *fn) { | |
| 365 | if (fn->frame_type != nullptr) { | |
| 366 | return fn->frame_type; | |
| 367 | } | |
| 368 | ||
| 369 | ZigType *entry = new_type_table_entry(ZigTypeIdCoroFrame); | |
| 370 | buf_resize(&entry->name, 0); | |
| 371 | buf_appendf(&entry->name, "@Frame(%s)", buf_ptr(&fn->symbol_name)); | |
| 372 | ||
| 373 | entry->data.frame.fn = fn; | |
| 374 | ||
| 375 | // Coroutine frames are always non-zero bits because they always have a resume index. | |
| 376 | entry->abi_size = SIZE_MAX; | |
| 377 | entry->size_in_bits = SIZE_MAX; | |
| 378 | ||
| 379 | fn->frame_type = entry; | |
| 380 | return entry; | |
| 381 | } | |
| 382 | ||
| 348 | 383 | ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, bool is_const, |
| 349 | 384 | bool is_volatile, PtrLen ptr_len, uint32_t byte_alignment, |
| 350 | 385 | uint32_t bit_offset_in_host, uint32_t host_int_bytes, bool allow_zero) |
| ... | ... | @@ -1039,6 +1074,7 @@ static Error emit_error_unless_type_allowed_in_packed_struct(CodeGen *g, ZigType |
| 1039 | 1074 | case ZigTypeIdBoundFn: |
| 1040 | 1075 | case ZigTypeIdArgTuple: |
| 1041 | 1076 | case ZigTypeIdOpaque: |
| 1077 | case ZigTypeIdCoroFrame: | |
| 1042 | 1078 | add_node_error(g, source_node, |
| 1043 | 1079 | buf_sprintf("type '%s' not allowed in packed struct; no guaranteed in-memory representation", |
| 1044 | 1080 | buf_ptr(&type_entry->name))); |
| ... | ... | @@ -1127,6 +1163,7 @@ bool type_allowed_in_extern(CodeGen *g, ZigType *type_entry) { |
| 1127 | 1163 | case ZigTypeIdBoundFn: |
| 1128 | 1164 | case ZigTypeIdArgTuple: |
| 1129 | 1165 | case ZigTypeIdVoid: |
| 1166 | case ZigTypeIdCoroFrame: | |
| 1130 | 1167 | return false; |
| 1131 | 1168 | case ZigTypeIdOpaque: |
| 1132 | 1169 | case ZigTypeIdUnreachable: |
| ... | ... | @@ -1297,6 +1334,7 @@ static ZigType *analyze_fn_type(CodeGen *g, AstNode *proto_node, Scope *child_sc |
| 1297 | 1334 | case ZigTypeIdUnion: |
| 1298 | 1335 | case ZigTypeIdFn: |
| 1299 | 1336 | case ZigTypeIdVector: |
| 1337 | case ZigTypeIdCoroFrame: | |
| 1300 | 1338 | switch (type_requires_comptime(g, type_entry)) { |
| 1301 | 1339 | case ReqCompTimeNo: |
| 1302 | 1340 | break; |
| ... | ... | @@ -1392,6 +1430,7 @@ static ZigType *analyze_fn_type(CodeGen *g, AstNode *proto_node, Scope *child_sc |
| 1392 | 1430 | case ZigTypeIdUnion: |
| 1393 | 1431 | case ZigTypeIdFn: |
| 1394 | 1432 | case ZigTypeIdVector: |
| 1433 | case ZigTypeIdCoroFrame: | |
| 1395 | 1434 | switch (type_requires_comptime(g, fn_type_id.return_type)) { |
| 1396 | 1435 | case ReqCompTimeInvalid: |
| 1397 | 1436 | return g->builtin_types.entry_invalid; |
| ... | ... | @@ -1825,6 +1864,39 @@ static Error resolve_union_type(CodeGen *g, ZigType *union_type) { |
| 1825 | 1864 | return ErrorNone; |
| 1826 | 1865 | } |
| 1827 | 1866 | |
| 1867 | static Error resolve_coro_frame(CodeGen *g, ZigType *frame_type) { | |
| 1868 | assert(frame_type->data.frame.locals_struct == nullptr); | |
| 1869 | ||
| 1870 | ZigFn *fn = frame_type->data.frame.fn; | |
| 1871 | switch (fn->anal_state) { | |
| 1872 | case FnAnalStateInvalid: | |
| 1873 | return ErrorSemanticAnalyzeFail; | |
| 1874 | case FnAnalStateComplete: | |
| 1875 | break; | |
| 1876 | case FnAnalStateReady: | |
| 1877 | analyze_fn_body(g, fn); | |
| 1878 | if (fn->anal_state == FnAnalStateInvalid) | |
| 1879 | return ErrorSemanticAnalyzeFail; | |
| 1880 | break; | |
| 1881 | case FnAnalStateProbing: | |
| 1882 | add_node_error(g, fn->proto_node, | |
| 1883 | buf_sprintf("cannot resolve '%s': function not fully analyzed yet", | |
| 1884 | buf_ptr(&frame_type->name))); | |
| 1885 | return ErrorSemanticAnalyzeFail; | |
| 1886 | } | |
| 1887 | // TODO iterate over fn->alloca_gen_list | |
| 1888 | ZigList<ZigType *> field_types = {}; | |
| 1889 | ZigList<const char *> field_names = {}; | |
| 1890 | ||
| 1891 | field_names.append("resume_index"); | |
| 1892 | field_types.append(g->builtin_types.entry_usize); | |
| 1893 | ||
| 1894 | assert(field_names.length == field_types.length); | |
| 1895 | frame_type->data.frame.locals_struct = get_struct_type(g, buf_ptr(&frame_type->name), | |
| 1896 | field_names.items, field_types.items, field_names.length); | |
| 1897 | return ErrorNone; | |
| 1898 | } | |
| 1899 | ||
| 1828 | 1900 | static bool type_is_valid_extern_enum_tag(CodeGen *g, ZigType *ty) { |
| 1829 | 1901 | // Only integer types are allowed by the C ABI |
| 1830 | 1902 | if(ty->id != ZigTypeIdInt) |
| ... | ... | @@ -2997,6 +3069,7 @@ ZigType *validate_var_type(CodeGen *g, AstNode *source_node, ZigType *type_entry |
| 2997 | 3069 | case ZigTypeIdFn: |
| 2998 | 3070 | case ZigTypeIdBoundFn: |
| 2999 | 3071 | case ZigTypeIdVector: |
| 3072 | case ZigTypeIdCoroFrame: | |
| 3000 | 3073 | return type_entry; |
| 3001 | 3074 | } |
| 3002 | 3075 | zig_unreachable(); |
| ... | ... | @@ -3496,6 +3569,7 @@ bool is_container(ZigType *type_entry) { |
| 3496 | 3569 | case ZigTypeIdArgTuple: |
| 3497 | 3570 | case ZigTypeIdOpaque: |
| 3498 | 3571 | case ZigTypeIdVector: |
| 3572 | case ZigTypeIdCoroFrame: | |
| 3499 | 3573 | return false; |
| 3500 | 3574 | } |
| 3501 | 3575 | zig_unreachable(); |
| ... | ... | @@ -3552,6 +3626,7 @@ Error resolve_container_type(CodeGen *g, ZigType *type_entry) { |
| 3552 | 3626 | case ZigTypeIdArgTuple: |
| 3553 | 3627 | case ZigTypeIdOpaque: |
| 3554 | 3628 | case ZigTypeIdVector: |
| 3629 | case ZigTypeIdCoroFrame: | |
| 3555 | 3630 | zig_unreachable(); |
| 3556 | 3631 | } |
| 3557 | 3632 | zig_unreachable(); |
| ... | ... | @@ -4002,6 +4077,7 @@ bool handle_is_ptr(ZigType *type_entry) { |
| 4002 | 4077 | return false; |
| 4003 | 4078 | case ZigTypeIdArray: |
| 4004 | 4079 | case ZigTypeIdStruct: |
| 4080 | case ZigTypeIdCoroFrame: | |
| 4005 | 4081 | return type_has_bits(type_entry); |
| 4006 | 4082 | case ZigTypeIdErrorUnion: |
| 4007 | 4083 | return type_has_bits(type_entry->data.error_union.payload_type); |
| ... | ... | @@ -4246,6 +4322,9 @@ static uint32_t hash_const_val(ConstExprValue *const_val) { |
| 4246 | 4322 | case ZigTypeIdVector: |
| 4247 | 4323 | // TODO better hashing algorithm |
| 4248 | 4324 | return 3647867726; |
| 4325 | case ZigTypeIdCoroFrame: | |
| 4326 | // TODO better hashing algorithm | |
| 4327 | return 675741936; | |
| 4249 | 4328 | case ZigTypeIdBoundFn: |
| 4250 | 4329 | case ZigTypeIdInvalid: |
| 4251 | 4330 | case ZigTypeIdUnreachable: |
| ... | ... | @@ -4310,6 +4389,7 @@ static bool can_mutate_comptime_var_state(ConstExprValue *value) { |
| 4310 | 4389 | case ZigTypeIdOpaque: |
| 4311 | 4390 | case ZigTypeIdErrorSet: |
| 4312 | 4391 | case ZigTypeIdEnum: |
| 4392 | case ZigTypeIdCoroFrame: | |
| 4313 | 4393 | return false; |
| 4314 | 4394 | |
| 4315 | 4395 | case ZigTypeIdPointer: |
| ... | ... | @@ -4381,6 +4461,7 @@ static bool return_type_is_cacheable(ZigType *return_type) { |
| 4381 | 4461 | case ZigTypeIdEnum: |
| 4382 | 4462 | case ZigTypeIdPointer: |
| 4383 | 4463 | case ZigTypeIdVector: |
| 4464 | case ZigTypeIdCoroFrame: | |
| 4384 | 4465 | return true; |
| 4385 | 4466 | |
| 4386 | 4467 | case ZigTypeIdArray: |
| ... | ... | @@ -4512,6 +4593,7 @@ OnePossibleValue type_has_one_possible_value(CodeGen *g, ZigType *type_entry) { |
| 4512 | 4593 | case ZigTypeIdBool: |
| 4513 | 4594 | case ZigTypeIdFloat: |
| 4514 | 4595 | case ZigTypeIdErrorUnion: |
| 4596 | case ZigTypeIdCoroFrame: | |
| 4515 | 4597 | return OnePossibleValueNo; |
| 4516 | 4598 | case ZigTypeIdUndefined: |
| 4517 | 4599 | case ZigTypeIdNull: |
| ... | ... | @@ -4599,6 +4681,7 @@ ReqCompTime type_requires_comptime(CodeGen *g, ZigType *type_entry) { |
| 4599 | 4681 | case ZigTypeIdFloat: |
| 4600 | 4682 | case ZigTypeIdVoid: |
| 4601 | 4683 | case ZigTypeIdUnreachable: |
| 4684 | case ZigTypeIdCoroFrame: | |
| 4602 | 4685 | return ReqCompTimeNo; |
| 4603 | 4686 | } |
| 4604 | 4687 | zig_unreachable(); |
| ... | ... | @@ -4941,6 +5024,8 @@ Error type_resolve(CodeGen *g, ZigType *ty, ResolveStatus status) { |
| 4941 | 5024 | return resolve_enum_zero_bits(g, ty); |
| 4942 | 5025 | } else if (ty->id == ZigTypeIdUnion) { |
| 4943 | 5026 | return resolve_union_alignment(g, ty); |
| 5027 | } else if (ty->id == ZigTypeIdCoroFrame) { | |
| 5028 | return resolve_coro_frame(g, ty); | |
| 4944 | 5029 | } |
| 4945 | 5030 | return ErrorNone; |
| 4946 | 5031 | case ResolveStatusSizeKnown: |
| ... | ... | @@ -4950,6 +5035,8 @@ Error type_resolve(CodeGen *g, ZigType *ty, ResolveStatus status) { |
| 4950 | 5035 | return resolve_enum_zero_bits(g, ty); |
| 4951 | 5036 | } else if (ty->id == ZigTypeIdUnion) { |
| 4952 | 5037 | return resolve_union_type(g, ty); |
| 5038 | } else if (ty->id == ZigTypeIdCoroFrame) { | |
| 5039 | return resolve_coro_frame(g, ty); | |
| 4953 | 5040 | } |
| 4954 | 5041 | return ErrorNone; |
| 4955 | 5042 | case ResolveStatusLLVMFwdDecl: |
| ... | ... | @@ -5144,6 +5231,8 @@ bool const_values_equal(CodeGen *g, ConstExprValue *a, ConstExprValue *b) { |
| 5144 | 5231 | return false; |
| 5145 | 5232 | } |
| 5146 | 5233 | return true; |
| 5234 | case ZigTypeIdCoroFrame: | |
| 5235 | zig_panic("TODO"); | |
| 5147 | 5236 | case ZigTypeIdUndefined: |
| 5148 | 5237 | zig_panic("TODO"); |
| 5149 | 5238 | case ZigTypeIdNull: |
| ... | ... | @@ -5496,6 +5585,10 @@ void render_const_value(CodeGen *g, Buf *buf, ConstExprValue *const_val) { |
| 5496 | 5585 | buf_appendf(buf, "(args value)"); |
| 5497 | 5586 | return; |
| 5498 | 5587 | } |
| 5588 | case ZigTypeIdCoroFrame: | |
| 5589 | buf_appendf(buf, "(TODO: coroutine frame value)"); | |
| 5590 | return; | |
| 5591 | ||
| 5499 | 5592 | } |
| 5500 | 5593 | zig_unreachable(); |
| 5501 | 5594 | } |
| ... | ... | @@ -5542,6 +5635,7 @@ uint32_t type_id_hash(TypeId x) { |
| 5542 | 5635 | case ZigTypeIdFn: |
| 5543 | 5636 | case ZigTypeIdBoundFn: |
| 5544 | 5637 | case ZigTypeIdArgTuple: |
| 5638 | case ZigTypeIdCoroFrame: | |
| 5545 | 5639 | zig_unreachable(); |
| 5546 | 5640 | case ZigTypeIdErrorUnion: |
| 5547 | 5641 | return hash_ptr(x.data.error_union.err_set_type) ^ hash_ptr(x.data.error_union.payload_type); |
| ... | ... | @@ -5590,6 +5684,7 @@ bool type_id_eql(TypeId a, TypeId b) { |
| 5590 | 5684 | case ZigTypeIdBoundFn: |
| 5591 | 5685 | case ZigTypeIdArgTuple: |
| 5592 | 5686 | case ZigTypeIdOpaque: |
| 5687 | case ZigTypeIdCoroFrame: | |
| 5593 | 5688 | zig_unreachable(); |
| 5594 | 5689 | case ZigTypeIdErrorUnion: |
| 5595 | 5690 | return a.data.error_union.err_set_type == b.data.error_union.err_set_type && |
| ... | ... | @@ -5818,10 +5913,12 @@ size_t type_id_index(ZigType *entry) { |
| 5818 | 5913 | return 20; |
| 5819 | 5914 | case ZigTypeIdOpaque: |
| 5820 | 5915 | return 21; |
| 5821 | case ZigTypeIdVector: | |
| 5916 | case ZigTypeIdCoroFrame: | |
| 5822 | 5917 | return 22; |
| 5823 | case ZigTypeIdEnumLiteral: | |
| 5918 | case ZigTypeIdVector: | |
| 5824 | 5919 | return 23; |
| 5920 | case ZigTypeIdEnumLiteral: | |
| 5921 | return 24; | |
| 5825 | 5922 | } |
| 5826 | 5923 | zig_unreachable(); |
| 5827 | 5924 | } |
| ... | ... | @@ -5878,6 +5975,8 @@ const char *type_id_name(ZigTypeId id) { |
| 5878 | 5975 | return "Opaque"; |
| 5879 | 5976 | case ZigTypeIdVector: |
| 5880 | 5977 | return "Vector"; |
| 5978 | case ZigTypeIdCoroFrame: | |
| 5979 | return "Frame"; | |
| 5881 | 5980 | } |
| 5882 | 5981 | zig_unreachable(); |
| 5883 | 5982 | } |
| ... | ... | @@ -5947,7 +6046,7 @@ bool type_can_fail(ZigType *type_entry) { |
| 5947 | 6046 | } |
| 5948 | 6047 | |
| 5949 | 6048 | bool fn_type_can_fail(FnTypeId *fn_type_id) { |
| 5950 | return type_can_fail(fn_type_id->return_type) || fn_type_id->cc == CallingConventionAsync; | |
| 6049 | return type_can_fail(fn_type_id->return_type); | |
| 5951 | 6050 | } |
| 5952 | 6051 | |
| 5953 | 6052 | // ErrorNone - result pointer has the type |
| ... | ... | @@ -6935,12 +7034,12 @@ static void resolve_llvm_types_array(CodeGen *g, ZigType *type) { |
| 6935 | 7034 | debug_align_in_bits, get_llvm_di_type(g, elem_type), (int)type->data.array.len); |
| 6936 | 7035 | } |
| 6937 | 7036 | |
| 6938 | static void resolve_llvm_types_fn(CodeGen *g, ZigType *fn_type) { | |
| 7037 | void resolve_llvm_types_fn(CodeGen *g, ZigType *fn_type, ZigFn *fn) { | |
| 6939 | 7038 | if (fn_type->llvm_di_type != nullptr) return; |
| 6940 | 7039 | |
| 6941 | 7040 | FnTypeId *fn_type_id = &fn_type->data.fn.fn_type_id; |
| 6942 | 7041 | bool first_arg_return = want_first_arg_sret(g, fn_type_id); |
| 6943 | bool is_async = fn_type_id->cc == CallingConventionAsync; | |
| 7042 | bool is_async = fn_type_id->cc == CallingConventionAsync || (fn != nullptr && fn->resume_blocks.length != 0); | |
| 6944 | 7043 | bool is_c_abi = fn_type_id->cc == CallingConventionC; |
| 6945 | 7044 | bool prefix_arg_error_return_trace = g->have_err_ret_tracing && fn_type_can_fail(fn_type_id); |
| 6946 | 7045 | // +1 for maybe making the first argument the return value |
| ... | ... | @@ -6955,7 +7054,7 @@ static void resolve_llvm_types_fn(CodeGen *g, ZigType *fn_type) { |
| 6955 | 7054 | param_di_types.append(get_llvm_di_type(g, fn_type_id->return_type)); |
| 6956 | 7055 | ZigType *gen_return_type; |
| 6957 | 7056 | if (is_async) { |
| 6958 | gen_return_type = get_pointer_to_type(g, g->builtin_types.entry_u8, false); | |
| 7057 | gen_return_type = g->builtin_types.entry_usize; | |
| 6959 | 7058 | } else if (!type_has_bits(fn_type_id->return_type)) { |
| 6960 | 7059 | gen_return_type = g->builtin_types.entry_void; |
| 6961 | 7060 | } else if (first_arg_return) { |
| ... | ... | @@ -6974,13 +7073,10 @@ static void resolve_llvm_types_fn(CodeGen *g, ZigType *fn_type) { |
| 6974 | 7073 | param_di_types.append(get_llvm_di_type(g, gen_type)); |
| 6975 | 7074 | } |
| 6976 | 7075 | if (is_async) { |
| 6977 | // coroutine frame pointer | |
| 6978 | // TODO if we can make this typed a little more it will be better for | |
| 6979 | // debug symbols. | |
| 6980 | // TODO do we need to make this aligned more? | |
| 6981 | ZigType *void_star = get_pointer_to_type(g, g->builtin_types.entry_c_void, false); | |
| 6982 | gen_param_types.append(get_llvm_type(g, void_star)); | |
| 6983 | param_di_types.append(get_llvm_di_type(g, void_star)); | |
| 7076 | ZigType *frame_type = (fn == nullptr) ? g->builtin_types.entry_frame_header : get_coro_frame_type(g, fn); | |
| 7077 | ZigType *ptr_type = get_pointer_to_type(g, frame_type, false); | |
| 7078 | gen_param_types.append(get_llvm_type(g, ptr_type)); | |
| 7079 | param_di_types.append(get_llvm_di_type(g, ptr_type)); | |
| 6984 | 7080 | } |
| 6985 | 7081 | |
| 6986 | 7082 | fn_type->data.fn.gen_param_info = allocate<FnGenParamInfo>(fn_type_id->param_count); |
| ... | ... | @@ -7055,6 +7151,17 @@ static void resolve_llvm_types_anyerror(CodeGen *g) { |
| 7055 | 7151 | get_llvm_di_type(g, g->err_tag_type), ""); |
| 7056 | 7152 | } |
| 7057 | 7153 | |
| 7154 | static void resolve_llvm_types_coro_frame(CodeGen *g, ZigType *frame_type, ResolveStatus wanted_resolve_status) { | |
| 7155 | if (frame_type->llvm_di_type != nullptr) return; | |
| 7156 | ||
| 7157 | resolve_llvm_types_struct(g, frame_type->data.frame.locals_struct, wanted_resolve_status); | |
| 7158 | frame_type->llvm_type = frame_type->data.frame.locals_struct->llvm_type; | |
| 7159 | frame_type->llvm_di_type = frame_type->data.frame.locals_struct->llvm_di_type; | |
| 7160 | frame_type->abi_size = frame_type->data.frame.locals_struct->abi_size; | |
| 7161 | frame_type->abi_align = frame_type->data.frame.locals_struct->abi_align; | |
| 7162 | frame_type->size_in_bits = frame_type->data.frame.locals_struct->size_in_bits; | |
| 7163 | } | |
| 7164 | ||
| 7058 | 7165 | static void resolve_llvm_types(CodeGen *g, ZigType *type, ResolveStatus wanted_resolve_status) { |
| 7059 | 7166 | assert(type->id == ZigTypeIdOpaque || type_is_resolved(type, ResolveStatusSizeKnown)); |
| 7060 | 7167 | assert(wanted_resolve_status > ResolveStatusSizeKnown); |
| ... | ... | @@ -7096,7 +7203,7 @@ static void resolve_llvm_types(CodeGen *g, ZigType *type, ResolveStatus wanted_r |
| 7096 | 7203 | case ZigTypeIdArray: |
| 7097 | 7204 | return resolve_llvm_types_array(g, type); |
| 7098 | 7205 | case ZigTypeIdFn: |
| 7099 | return resolve_llvm_types_fn(g, type); | |
| 7206 | return resolve_llvm_types_fn(g, type, nullptr); | |
| 7100 | 7207 | case ZigTypeIdErrorSet: { |
| 7101 | 7208 | if (type->llvm_di_type != nullptr) return; |
| 7102 | 7209 | |
| ... | ... | @@ -7115,6 +7222,8 @@ static void resolve_llvm_types(CodeGen *g, ZigType *type, ResolveStatus wanted_r |
| 7115 | 7222 | type->abi_align, get_llvm_di_type(g, type->data.vector.elem_type), type->data.vector.len); |
| 7116 | 7223 | return; |
| 7117 | 7224 | } |
| 7225 | case ZigTypeIdCoroFrame: | |
| 7226 | return resolve_llvm_types_coro_frame(g, type, wanted_resolve_status); | |
| 7118 | 7227 | } |
| 7119 | 7228 | zig_unreachable(); |
| 7120 | 7229 | } |
src/analyze.hpp+3| ... | ... | @@ -16,6 +16,7 @@ ErrorMsg *add_token_error(CodeGen *g, ZigType *owner, Token *token, Buf *msg); |
| 16 | 16 | ErrorMsg *add_error_note(CodeGen *g, ErrorMsg *parent_msg, AstNode *node, Buf *msg); |
| 17 | 17 | void emit_error_notes_for_ref_stack(CodeGen *g, ErrorMsg *msg); |
| 18 | 18 | ZigType *new_type_table_entry(ZigTypeId id); |
| 19 | ZigType *get_coro_frame_type(CodeGen *g, ZigFn *fn); | |
| 19 | 20 | ZigType *get_pointer_to_type(CodeGen *g, ZigType *child_type, bool is_const); |
| 20 | 21 | ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, bool is_const, |
| 21 | 22 | bool is_volatile, PtrLen ptr_len, |
| ... | ... | @@ -247,4 +248,6 @@ void src_assert(bool ok, AstNode *source_node); |
| 247 | 248 | bool is_container(ZigType *type_entry); |
| 248 | 249 | ConstExprValue *analyze_const_value(CodeGen *g, Scope *scope, AstNode *node, ZigType *type_entry, Buf *type_name); |
| 249 | 250 | |
| 251 | void resolve_llvm_types_fn(CodeGen *g, ZigType *fn_type, ZigFn *fn); | |
| 252 | ||
| 250 | 253 | #endif |
src/codegen.cpp+116-23| ... | ... | @@ -498,7 +498,7 @@ static LLVMValueRef fn_llvm_value(CodeGen *g, ZigFn *fn_table_entry) { |
| 498 | 498 | |
| 499 | 499 | ZigType *fn_type = fn_table_entry->type_entry; |
| 500 | 500 | // Make the raw_type_ref populated |
| 501 | (void)get_llvm_type(g, fn_type); | |
| 501 | resolve_llvm_types_fn(g, fn_type, fn_table_entry); | |
| 502 | 502 | LLVMTypeRef fn_llvm_type = fn_type->data.fn.raw_type_ref; |
| 503 | 503 | if (fn_table_entry->body_node == nullptr) { |
| 504 | 504 | LLVMValueRef existing_llvm_fn = LLVMGetNamedFunction(g->module, buf_ptr(symbol_name)); |
| ... | ... | @@ -921,9 +921,8 @@ static bool ir_want_fast_math(CodeGen *g, IrInstruction *instruction) { |
| 921 | 921 | return false; |
| 922 | 922 | } |
| 923 | 923 | |
| 924 | static bool ir_want_runtime_safety(CodeGen *g, IrInstruction *instruction) { | |
| 924 | static bool ir_want_runtime_safety_scope(CodeGen *g, Scope *scope) { | |
| 925 | 925 | // TODO memoize |
| 926 | Scope *scope = instruction->scope; | |
| 927 | 926 | while (scope) { |
| 928 | 927 | if (scope->id == ScopeIdBlock) { |
| 929 | 928 | ScopeBlock *block_scope = (ScopeBlock *)scope; |
| ... | ... | @@ -941,6 +940,10 @@ static bool ir_want_runtime_safety(CodeGen *g, IrInstruction *instruction) { |
| 941 | 940 | g->build_mode != BuildModeSmallRelease); |
| 942 | 941 | } |
| 943 | 942 | |
| 943 | static bool ir_want_runtime_safety(CodeGen *g, IrInstruction *instruction) { | |
| 944 | return ir_want_runtime_safety_scope(g, instruction->scope); | |
| 945 | } | |
| 946 | ||
| 944 | 947 | static Buf *panic_msg_buf(PanicMsgId msg_id) { |
| 945 | 948 | switch (msg_id) { |
| 946 | 949 | case PanicMsgIdCount: |
| ... | ... | @@ -981,6 +984,8 @@ static Buf *panic_msg_buf(PanicMsgId msg_id) { |
| 981 | 984 | return buf_create_from_str("integer part of floating point value out of bounds"); |
| 982 | 985 | case PanicMsgIdPtrCastNull: |
| 983 | 986 | return buf_create_from_str("cast causes pointer to be null"); |
| 987 | case PanicMsgIdBadResume: | |
| 988 | return buf_create_from_str("invalid resume of async function"); | |
| 984 | 989 | } |
| 985 | 990 | zig_unreachable(); |
| 986 | 991 | } |
| ... | ... | @@ -1027,14 +1032,18 @@ static void gen_safety_crash(CodeGen *g, PanicMsgId msg_id) { |
| 1027 | 1032 | gen_panic(g, get_panic_msg_ptr_val(g, msg_id), nullptr); |
| 1028 | 1033 | } |
| 1029 | 1034 | |
| 1030 | static void gen_assertion(CodeGen *g, PanicMsgId msg_id, IrInstruction *source_instruction) { | |
| 1031 | if (ir_want_runtime_safety(g, source_instruction)) { | |
| 1035 | static void gen_assertion_scope(CodeGen *g, PanicMsgId msg_id, Scope *source_scope) { | |
| 1036 | if (ir_want_runtime_safety_scope(g, source_scope)) { | |
| 1032 | 1037 | gen_safety_crash(g, msg_id); |
| 1033 | 1038 | } else { |
| 1034 | 1039 | LLVMBuildUnreachable(g->builder); |
| 1035 | 1040 | } |
| 1036 | 1041 | } |
| 1037 | 1042 | |
| 1043 | static void gen_assertion(CodeGen *g, PanicMsgId msg_id, IrInstruction *source_instruction) { | |
| 1044 | return gen_assertion_scope(g, msg_id, source_instruction->scope); | |
| 1045 | } | |
| 1046 | ||
| 1038 | 1047 | static LLVMValueRef get_stacksave_fn_val(CodeGen *g) { |
| 1039 | 1048 | if (g->stacksave_fn_val) |
| 1040 | 1049 | return g->stacksave_fn_val; |
| ... | ... | @@ -2092,6 +2101,10 @@ static LLVMValueRef ir_render_save_err_ret_addr(CodeGen *g, IrExecutable *execut |
| 2092 | 2101 | } |
| 2093 | 2102 | |
| 2094 | 2103 | static LLVMValueRef ir_render_return(CodeGen *g, IrExecutable *executable, IrInstructionReturn *return_instruction) { |
| 2104 | if (g->cur_fn->resume_blocks.length != 0) { | |
| 2105 | LLVMBuildRet(g->builder, LLVMGetUndef(g->builtin_types.entry_usize->llvm_type)); | |
| 2106 | return nullptr; | |
| 2107 | } | |
| 2095 | 2108 | if (want_first_arg_sret(g, &g->cur_fn->type_entry->data.fn.fn_type_id)) { |
| 2096 | 2109 | if (return_instruction->value == nullptr) { |
| 2097 | 2110 | LLVMBuildRetVoid(g->builder); |
| ... | ... | @@ -3375,8 +3388,7 @@ static LLVMValueRef ir_render_elem_ptr(CodeGen *g, IrExecutable *executable, IrI |
| 3375 | 3388 | static bool get_prefix_arg_err_ret_stack(CodeGen *g, FnTypeId *fn_type_id) { |
| 3376 | 3389 | return g->have_err_ret_tracing && |
| 3377 | 3390 | (fn_type_id->return_type->id == ZigTypeIdErrorUnion || |
| 3378 | fn_type_id->return_type->id == ZigTypeIdErrorSet || | |
| 3379 | fn_type_id->cc == CallingConventionAsync); | |
| 3391 | fn_type_id->return_type->id == ZigTypeIdErrorSet); | |
| 3380 | 3392 | } |
| 3381 | 3393 | |
| 3382 | 3394 | static LLVMValueRef get_new_stack_addr(CodeGen *g, LLVMValueRef new_stack) { |
| ... | ... | @@ -3440,15 +3452,23 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr |
| 3440 | 3452 | bool is_var_args = fn_type_id->is_var_args; |
| 3441 | 3453 | ZigList<LLVMValueRef> gen_param_values = {}; |
| 3442 | 3454 | LLVMValueRef result_loc = instruction->result_loc ? ir_llvm_value(g, instruction->result_loc) : nullptr; |
| 3443 | if (first_arg_ret) { | |
| 3455 | if (instruction->is_async) { | |
| 3456 | assert(result_loc != nullptr); | |
| 3457 | assert(instruction->fn_entry != nullptr); | |
| 3458 | LLVMValueRef resume_index_ptr = LLVMBuildStructGEP(g->builder, result_loc, coro_resume_index_index, ""); | |
| 3459 | LLVMValueRef zero = LLVMConstNull(g->builtin_types.entry_usize->llvm_type); | |
| 3460 | LLVMBuildStore(g->builder, zero, resume_index_ptr); | |
| 3461 | ||
| 3462 | if (prefix_arg_err_ret_stack) { | |
| 3463 | zig_panic("TODO"); | |
| 3464 | } | |
| 3465 | ||
| 3444 | 3466 | gen_param_values.append(result_loc); |
| 3445 | } | |
| 3446 | if (prefix_arg_err_ret_stack) { | |
| 3467 | } else if (first_arg_ret) { | |
| 3468 | gen_param_values.append(result_loc); | |
| 3469 | } else if (prefix_arg_err_ret_stack) { | |
| 3447 | 3470 | gen_param_values.append(get_cur_err_ret_trace_val(g, instruction->base.scope)); |
| 3448 | 3471 | } |
| 3449 | if (instruction->is_async) { | |
| 3450 | zig_panic("TODO codegen async call"); | |
| 3451 | } | |
| 3452 | 3472 | FnWalk fn_walk = {}; |
| 3453 | 3473 | fn_walk.id = FnWalkIdCall; |
| 3454 | 3474 | fn_walk.data.call.inst = instruction; |
| ... | ... | @@ -3489,9 +3509,7 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr |
| 3489 | 3509 | |
| 3490 | 3510 | |
| 3491 | 3511 | if (instruction->is_async) { |
| 3492 | LLVMValueRef payload_ptr = LLVMBuildStructGEP(g->builder, result_loc, err_union_payload_index, ""); | |
| 3493 | LLVMBuildStore(g->builder, result, payload_ptr); | |
| 3494 | return result_loc; | |
| 3512 | return nullptr; | |
| 3495 | 3513 | } |
| 3496 | 3514 | |
| 3497 | 3515 | if (src_return_type->id == ZigTypeIdUnreachable) { |
| ... | ... | @@ -4921,6 +4939,24 @@ static LLVMValueRef ir_render_assert_non_null(CodeGen *g, IrExecutable *executab |
| 4921 | 4939 | return nullptr; |
| 4922 | 4940 | } |
| 4923 | 4941 | |
| 4942 | static LLVMValueRef ir_render_suspend_begin(CodeGen *g, IrExecutable *executable, | |
| 4943 | IrInstructionSuspendBegin *instruction) | |
| 4944 | { | |
| 4945 | LLVMValueRef locals_ptr = g->cur_ret_ptr; | |
| 4946 | LLVMValueRef resume_index_ptr = LLVMBuildStructGEP(g->builder, locals_ptr, coro_resume_index_index, ""); | |
| 4947 | LLVMValueRef new_resume_index = LLVMConstInt(g->builtin_types.entry_usize->llvm_type, | |
| 4948 | instruction->resume_block->resume_index, false); | |
| 4949 | LLVMBuildStore(g->builder, new_resume_index, resume_index_ptr); | |
| 4950 | return nullptr; | |
| 4951 | } | |
| 4952 | ||
| 4953 | static LLVMValueRef ir_render_suspend_br(CodeGen *g, IrExecutable *executable, | |
| 4954 | IrInstructionSuspendBr *instruction) | |
| 4955 | { | |
| 4956 | LLVMBuildRet(g->builder, LLVMGetUndef(g->builtin_types.entry_usize->llvm_type)); | |
| 4957 | return nullptr; | |
| 4958 | } | |
| 4959 | ||
| 4924 | 4960 | static void set_debug_location(CodeGen *g, IrInstruction *instruction) { |
| 4925 | 4961 | AstNode *source_node = instruction->source_node; |
| 4926 | 4962 | Scope *scope = instruction->scope; |
| ... | ... | @@ -5161,6 +5197,10 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable, |
| 5161 | 5197 | return ir_render_resize_slice(g, executable, (IrInstructionResizeSlice *)instruction); |
| 5162 | 5198 | case IrInstructionIdPtrOfArrayToSlice: |
| 5163 | 5199 | return ir_render_ptr_of_array_to_slice(g, executable, (IrInstructionPtrOfArrayToSlice *)instruction); |
| 5200 | case IrInstructionIdSuspendBegin: | |
| 5201 | return ir_render_suspend_begin(g, executable, (IrInstructionSuspendBegin *)instruction); | |
| 5202 | case IrInstructionIdSuspendBr: | |
| 5203 | return ir_render_suspend_br(g, executable, (IrInstructionSuspendBr *)instruction); | |
| 5164 | 5204 | } |
| 5165 | 5205 | zig_unreachable(); |
| 5166 | 5206 | } |
| ... | ... | @@ -5422,7 +5462,8 @@ static LLVMValueRef pack_const_int(CodeGen *g, LLVMTypeRef big_int_type_ref, Con |
| 5422 | 5462 | } |
| 5423 | 5463 | return val; |
| 5424 | 5464 | } |
| 5425 | ||
| 5465 | case ZigTypeIdCoroFrame: | |
| 5466 | zig_panic("TODO bit pack a coroutine frame"); | |
| 5426 | 5467 | } |
| 5427 | 5468 | zig_unreachable(); |
| 5428 | 5469 | } |
| ... | ... | @@ -5943,7 +5984,8 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val, const c |
| 5943 | 5984 | case ZigTypeIdArgTuple: |
| 5944 | 5985 | case ZigTypeIdOpaque: |
| 5945 | 5986 | zig_unreachable(); |
| 5946 | ||
| 5987 | case ZigTypeIdCoroFrame: | |
| 5988 | zig_panic("TODO"); | |
| 5947 | 5989 | } |
| 5948 | 5990 | zig_unreachable(); |
| 5949 | 5991 | } |
| ... | ... | @@ -6027,12 +6069,20 @@ static void generate_error_name_table(CodeGen *g) { |
| 6027 | 6069 | static void build_all_basic_blocks(CodeGen *g, ZigFn *fn) { |
| 6028 | 6070 | IrExecutable *executable = &fn->analyzed_executable; |
| 6029 | 6071 | assert(executable->basic_block_list.length > 0); |
| 6072 | LLVMValueRef fn_val = fn_llvm_value(g, fn); | |
| 6073 | LLVMBasicBlockRef first_bb = nullptr; | |
| 6074 | if (fn->resume_blocks.length != 0) { | |
| 6075 | first_bb = LLVMAppendBasicBlock(fn_val, "AsyncSwitch"); | |
| 6076 | fn->preamble_llvm_block = first_bb; | |
| 6077 | } | |
| 6030 | 6078 | for (size_t block_i = 0; block_i < executable->basic_block_list.length; block_i += 1) { |
| 6031 | 6079 | IrBasicBlock *bb = executable->basic_block_list.at(block_i); |
| 6032 | bb->llvm_block = LLVMAppendBasicBlock(fn_llvm_value(g, fn), bb->name_hint); | |
| 6080 | bb->llvm_block = LLVMAppendBasicBlock(fn_val, bb->name_hint); | |
| 6081 | } | |
| 6082 | if (first_bb == nullptr) { | |
| 6083 | first_bb = executable->basic_block_list.at(0)->llvm_block; | |
| 6033 | 6084 | } |
| 6034 | IrBasicBlock *entry_bb = executable->basic_block_list.at(0); | |
| 6035 | LLVMPositionBuilderAtEnd(g->builder, entry_bb->llvm_block); | |
| 6085 | LLVMPositionBuilderAtEnd(g->builder, first_bb); | |
| 6036 | 6086 | } |
| 6037 | 6087 | |
| 6038 | 6088 | static void gen_global_var(CodeGen *g, ZigVar *var, LLVMValueRef init_val, |
| ... | ... | @@ -6209,7 +6259,7 @@ static void do_code_gen(CodeGen *g) { |
| 6209 | 6259 | build_all_basic_blocks(g, fn_table_entry); |
| 6210 | 6260 | clear_debug_source_node(g); |
| 6211 | 6261 | |
| 6212 | if (want_sret) { | |
| 6262 | if (want_sret || fn_table_entry->resume_blocks.length != 0) { | |
| 6213 | 6263 | g->cur_ret_ptr = LLVMGetParam(fn, 0); |
| 6214 | 6264 | } else if (handle_is_ptr(fn_type_id->return_type)) { |
| 6215 | 6265 | g->cur_ret_ptr = build_alloca(g, fn_type_id->return_type, "result", 0); |
| ... | ... | @@ -6357,6 +6407,41 @@ static void do_code_gen(CodeGen *g) { |
| 6357 | 6407 | fn_walk_init.data.inits.gen_i = gen_i_init; |
| 6358 | 6408 | walk_function_params(g, fn_table_entry->type_entry, &fn_walk_init); |
| 6359 | 6409 | |
| 6410 | if (fn_table_entry->resume_blocks.length != 0) { | |
| 6411 | if (!g->strip_debug_symbols) { | |
| 6412 | AstNode *source_node = fn_table_entry->proto_node; | |
| 6413 | ZigLLVMSetCurrentDebugLocation(g->builder, (int)source_node->line + 1, | |
| 6414 | (int)source_node->column + 1, get_di_scope(g, fn_table_entry->child_scope)); | |
| 6415 | } | |
| 6416 | LLVMTypeRef usize_type_ref = g->builtin_types.entry_usize->llvm_type; | |
| 6417 | LLVMBasicBlockRef bad_resume_block = LLVMAppendBasicBlock(g->cur_fn_val, "BadResume"); | |
| 6418 | LLVMPositionBuilderAtEnd(g->builder, bad_resume_block); | |
| 6419 | gen_assertion_scope(g, PanicMsgIdBadResume, fn_table_entry->child_scope); | |
| 6420 | ||
| 6421 | LLVMBasicBlockRef get_size_block = LLVMAppendBasicBlock(g->cur_fn_val, "GetSize"); | |
| 6422 | LLVMPositionBuilderAtEnd(g->builder, get_size_block); | |
| 6423 | assert(fn_table_entry->frame_type->abi_size != 0); | |
| 6424 | assert(fn_table_entry->frame_type->abi_size != SIZE_MAX); | |
| 6425 | LLVMValueRef size_val = LLVMConstInt(usize_type_ref, fn_table_entry->frame_type->abi_size, false); | |
| 6426 | LLVMBuildRet(g->builder, size_val); | |
| 6427 | ||
| 6428 | LLVMPositionBuilderAtEnd(g->builder, fn_table_entry->preamble_llvm_block); | |
| 6429 | LLVMValueRef resume_index_ptr = LLVMBuildStructGEP(g->builder, g->cur_ret_ptr, | |
| 6430 | coro_resume_index_index, ""); | |
| 6431 | LLVMValueRef resume_index = LLVMBuildLoad(g->builder, resume_index_ptr, ""); | |
| 6432 | // The +1 is because index 0 is reserved for getting the size. | |
| 6433 | LLVMValueRef switch_instr = LLVMBuildSwitch(g->builder, resume_index, bad_resume_block, | |
| 6434 | fn_table_entry->resume_blocks.length + 1); | |
| 6435 | ||
| 6436 | LLVMValueRef zero = LLVMConstNull(usize_type_ref); | |
| 6437 | LLVMAddCase(switch_instr, zero, get_size_block); | |
| 6438 | ||
| 6439 | for (size_t resume_i = 0; resume_i < fn_table_entry->resume_blocks.length; resume_i += 1) { | |
| 6440 | LLVMValueRef case_value = LLVMConstInt(usize_type_ref, resume_i + 1, false); | |
| 6441 | LLVMAddCase(switch_instr, case_value, fn_table_entry->resume_blocks.at(resume_i)->llvm_block); | |
| 6442 | } | |
| 6443 | } | |
| 6444 | ||
| 6360 | 6445 | ir_render(g, fn_table_entry); |
| 6361 | 6446 | |
| 6362 | 6447 | } |
| ... | ... | @@ -6644,9 +6729,13 @@ static void define_builtin_types(CodeGen *g) { |
| 6644 | 6729 | |
| 6645 | 6730 | g->primitive_type_table.put(&entry->name, entry); |
| 6646 | 6731 | } |
| 6732 | { | |
| 6733 | const char *field_names[] = {"resume_index"}; | |
| 6734 | ZigType *field_types[] = {g->builtin_types.entry_usize}; | |
| 6735 | g->builtin_types.entry_frame_header = get_struct_type(g, "(frame header)", field_names, field_types, 1); | |
| 6736 | } | |
| 6647 | 6737 | } |
| 6648 | 6738 | |
| 6649 | ||
| 6650 | 6739 | static BuiltinFnEntry *create_builtin_fn(CodeGen *g, BuiltinFnId id, const char *name, size_t count) { |
| 6651 | 6740 | BuiltinFnEntry *builtin_fn = allocate<BuiltinFnEntry>(1); |
| 6652 | 6741 | buf_init_from_str(&builtin_fn->name, name); |
| ... | ... | @@ -7072,6 +7161,7 @@ Buf *codegen_generate_builtin_source(CodeGen *g) { |
| 7072 | 7161 | " BoundFn: Fn,\n" |
| 7073 | 7162 | " ArgTuple: void,\n" |
| 7074 | 7163 | " Opaque: void,\n" |
| 7164 | " Frame: void,\n" | |
| 7075 | 7165 | " Vector: Vector,\n" |
| 7076 | 7166 | " EnumLiteral: void,\n" |
| 7077 | 7167 | "\n\n" |
| ... | ... | @@ -8335,6 +8425,7 @@ static void prepend_c_type_to_decl_list(CodeGen *g, GenH *gen_h, ZigType *type_e |
| 8335 | 8425 | case ZigTypeIdArgTuple: |
| 8336 | 8426 | case ZigTypeIdErrorUnion: |
| 8337 | 8427 | case ZigTypeIdErrorSet: |
| 8428 | case ZigTypeIdCoroFrame: | |
| 8338 | 8429 | zig_unreachable(); |
| 8339 | 8430 | case ZigTypeIdVoid: |
| 8340 | 8431 | case ZigTypeIdUnreachable: |
| ... | ... | @@ -8518,6 +8609,7 @@ static void get_c_type(CodeGen *g, GenH *gen_h, ZigType *type_entry, Buf *out_bu |
| 8518 | 8609 | case ZigTypeIdUndefined: |
| 8519 | 8610 | case ZigTypeIdNull: |
| 8520 | 8611 | case ZigTypeIdArgTuple: |
| 8612 | case ZigTypeIdCoroFrame: | |
| 8521 | 8613 | zig_unreachable(); |
| 8522 | 8614 | } |
| 8523 | 8615 | } |
| ... | ... | @@ -8685,6 +8777,7 @@ static void gen_h_file(CodeGen *g) { |
| 8685 | 8777 | case ZigTypeIdOptional: |
| 8686 | 8778 | case ZigTypeIdFn: |
| 8687 | 8779 | case ZigTypeIdVector: |
| 8780 | case ZigTypeIdCoroFrame: | |
| 8688 | 8781 | zig_unreachable(); |
| 8689 | 8782 | case ZigTypeIdEnum: |
| 8690 | 8783 | if (type_entry->data.enumeration.layout == ContainerLayoutExtern) { |
src/ir.cpp+159-28| ... | ... | @@ -318,6 +318,7 @@ static bool types_have_same_zig_comptime_repr(ZigType *a, ZigType *b) { |
| 318 | 318 | case ZigTypeIdFn: |
| 319 | 319 | case ZigTypeIdArgTuple: |
| 320 | 320 | case ZigTypeIdVector: |
| 321 | case ZigTypeIdCoroFrame: | |
| 321 | 322 | return false; |
| 322 | 323 | } |
| 323 | 324 | zig_unreachable(); |
| ... | ... | @@ -1026,6 +1027,14 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionUnionInitNamedFi |
| 1026 | 1027 | return IrInstructionIdUnionInitNamedField; |
| 1027 | 1028 | } |
| 1028 | 1029 | |
| 1030 | static constexpr IrInstructionId ir_instruction_id(IrInstructionSuspendBegin *) { | |
| 1031 | return IrInstructionIdSuspendBegin; | |
| 1032 | } | |
| 1033 | ||
| 1034 | static constexpr IrInstructionId ir_instruction_id(IrInstructionSuspendBr *) { | |
| 1035 | return IrInstructionIdSuspendBr; | |
| 1036 | } | |
| 1037 | ||
| 1029 | 1038 | template<typename T> |
| 1030 | 1039 | static T *ir_create_instruction(IrBuilder *irb, Scope *scope, AstNode *source_node) { |
| 1031 | 1040 | T *special_instruction = allocate<T>(1); |
| ... | ... | @@ -3183,6 +3192,30 @@ static IrInstruction *ir_build_end_expr(IrBuilder *irb, Scope *scope, AstNode *s |
| 3183 | 3192 | return &instruction->base; |
| 3184 | 3193 | } |
| 3185 | 3194 | |
| 3195 | static IrInstruction *ir_build_suspend_begin(IrBuilder *irb, Scope *scope, AstNode *source_node, | |
| 3196 | IrBasicBlock *resume_block) | |
| 3197 | { | |
| 3198 | IrInstructionSuspendBegin *instruction = ir_build_instruction<IrInstructionSuspendBegin>(irb, scope, source_node); | |
| 3199 | instruction->base.value.type = irb->codegen->builtin_types.entry_void; | |
| 3200 | instruction->resume_block = resume_block; | |
| 3201 | ||
| 3202 | ir_ref_bb(resume_block); | |
| 3203 | ||
| 3204 | return &instruction->base; | |
| 3205 | } | |
| 3206 | ||
| 3207 | static IrInstruction *ir_build_suspend_br(IrBuilder *irb, Scope *scope, AstNode *source_node, | |
| 3208 | IrBasicBlock *resume_block) | |
| 3209 | { | |
| 3210 | IrInstructionSuspendBr *instruction = ir_build_instruction<IrInstructionSuspendBr>(irb, scope, source_node); | |
| 3211 | instruction->base.value.type = irb->codegen->builtin_types.entry_unreachable; | |
| 3212 | instruction->resume_block = resume_block; | |
| 3213 | ||
| 3214 | ir_ref_bb(resume_block); | |
| 3215 | ||
| 3216 | return &instruction->base; | |
| 3217 | } | |
| 3218 | ||
| 3186 | 3219 | static void ir_count_defers(IrBuilder *irb, Scope *inner_scope, Scope *outer_scope, size_t *results) { |
| 3187 | 3220 | results[ReturnKindUnconditional] = 0; |
| 3188 | 3221 | results[ReturnKindError] = 0; |
| ... | ... | @@ -3286,6 +3319,18 @@ static void ir_set_cursor_at_end_and_append_block(IrBuilder *irb, IrBasicBlock * |
| 3286 | 3319 | ir_set_cursor_at_end(irb, basic_block); |
| 3287 | 3320 | } |
| 3288 | 3321 | |
| 3322 | static ScopeSuspend *get_scope_suspend(Scope *scope) { | |
| 3323 | while (scope) { | |
| 3324 | if (scope->id == ScopeIdSuspend) | |
| 3325 | return (ScopeSuspend *)scope; | |
| 3326 | if (scope->id == ScopeIdFnDef) | |
| 3327 | return nullptr; | |
| 3328 | ||
| 3329 | scope = scope->parent; | |
| 3330 | } | |
| 3331 | return nullptr; | |
| 3332 | } | |
| 3333 | ||
| 3289 | 3334 | static ScopeDeferExpr *get_scope_defer_expr(Scope *scope) { |
| 3290 | 3335 | while (scope) { |
| 3291 | 3336 | if (scope->id == ScopeIdDeferExpr) |
| ... | ... | @@ -3308,14 +3353,9 @@ static IrInstruction *ir_gen_async_return(IrBuilder *irb, Scope *scope, AstNode |
| 3308 | 3353 | { |
| 3309 | 3354 | ir_mark_gen(ir_build_add_implicit_return_type(irb, scope, node, return_value)); |
| 3310 | 3355 | |
| 3311 | bool is_async = exec_is_async(irb->exec); | |
| 3312 | if (!is_async) { | |
| 3313 | IrInstruction *return_inst = ir_build_return(irb, scope, node, return_value); | |
| 3314 | return_inst->is_gen = is_generated_code; | |
| 3315 | return return_inst; | |
| 3316 | } | |
| 3317 | ||
| 3318 | zig_panic("TODO async return"); | |
| 3356 | IrInstruction *return_inst = ir_build_return(irb, scope, node, return_value); | |
| 3357 | return_inst->is_gen = is_generated_code; | |
| 3358 | return return_inst; | |
| 3319 | 3359 | } |
| 3320 | 3360 | |
| 3321 | 3361 | static IrInstruction *ir_gen_return(IrBuilder *irb, Scope *scope, AstNode *node, LVal lval, ResultLoc *result_loc) { |
| ... | ... | @@ -5393,12 +5433,8 @@ static IrInstruction *ir_gen_fn_call(IrBuilder *irb, Scope *scope, AstNode *node |
| 5393 | 5433 | } |
| 5394 | 5434 | |
| 5395 | 5435 | bool is_async = node->data.fn_call_expr.is_async; |
| 5396 | if (is_async) { | |
| 5397 | zig_panic("TODO async fn call"); | |
| 5398 | } | |
| 5399 | ||
| 5400 | IrInstruction *fn_call = ir_build_call_src(irb, scope, node, nullptr, fn_ref, arg_count, args, false, FnInlineAuto, | |
| 5401 | is_async, nullptr, result_loc); | |
| 5436 | IrInstruction *fn_call = ir_build_call_src(irb, scope, node, nullptr, fn_ref, arg_count, args, false, | |
| 5437 | FnInlineAuto, is_async, nullptr, result_loc); | |
| 5402 | 5438 | return ir_lval_wrap(irb, scope, fn_call, lval, result_loc); |
| 5403 | 5439 | } |
| 5404 | 5440 | |
| ... | ... | @@ -7655,7 +7691,45 @@ static IrInstruction *ir_gen_await_expr(IrBuilder *irb, Scope *scope, AstNode *n |
| 7655 | 7691 | static IrInstruction *ir_gen_suspend(IrBuilder *irb, Scope *parent_scope, AstNode *node) { |
| 7656 | 7692 | assert(node->type == NodeTypeSuspend); |
| 7657 | 7693 | |
| 7658 | zig_panic("TODO ir_gen_suspend"); | |
| 7694 | ZigFn *fn_entry = exec_fn_entry(irb->exec); | |
| 7695 | if (!fn_entry) { | |
| 7696 | add_node_error(irb->codegen, node, buf_sprintf("suspend outside function definition")); | |
| 7697 | return irb->codegen->invalid_instruction; | |
| 7698 | } | |
| 7699 | ScopeDeferExpr *scope_defer_expr = get_scope_defer_expr(parent_scope); | |
| 7700 | if (scope_defer_expr) { | |
| 7701 | if (!scope_defer_expr->reported_err) { | |
| 7702 | ErrorMsg *msg = add_node_error(irb->codegen, node, buf_sprintf("cannot suspend inside defer expression")); | |
| 7703 | add_error_note(irb->codegen, msg, scope_defer_expr->base.source_node, buf_sprintf("defer here")); | |
| 7704 | scope_defer_expr->reported_err = true; | |
| 7705 | } | |
| 7706 | return irb->codegen->invalid_instruction; | |
| 7707 | } | |
| 7708 | ScopeSuspend *existing_suspend_scope = get_scope_suspend(parent_scope); | |
| 7709 | if (existing_suspend_scope) { | |
| 7710 | if (!existing_suspend_scope->reported_err) { | |
| 7711 | ErrorMsg *msg = add_node_error(irb->codegen, node, buf_sprintf("cannot suspend inside suspend block")); | |
| 7712 | add_error_note(irb->codegen, msg, existing_suspend_scope->base.source_node, buf_sprintf("other suspend block here")); | |
| 7713 | existing_suspend_scope->reported_err = true; | |
| 7714 | } | |
| 7715 | return irb->codegen->invalid_instruction; | |
| 7716 | } | |
| 7717 | ||
| 7718 | IrBasicBlock *resume_block = ir_create_basic_block(irb, parent_scope, "Resume"); | |
| 7719 | ||
| 7720 | ir_build_suspend_begin(irb, parent_scope, node, resume_block); | |
| 7721 | if (node->data.suspend.block != nullptr) { | |
| 7722 | Scope *child_scope; | |
| 7723 | ScopeSuspend *suspend_scope = create_suspend_scope(irb->codegen, node, parent_scope); | |
| 7724 | suspend_scope->resume_block = resume_block; | |
| 7725 | child_scope = &suspend_scope->base; | |
| 7726 | IrInstruction *susp_res = ir_gen_node(irb, node->data.suspend.block, child_scope); | |
| 7727 | ir_mark_gen(ir_build_check_statement_is_void(irb, child_scope, node->data.suspend.block, susp_res)); | |
| 7728 | } | |
| 7729 | ||
| 7730 | IrInstruction *result = ir_build_suspend_br(irb, parent_scope, node, resume_block); | |
| 7731 | ir_set_cursor_at_end_and_append_block(irb, resume_block); | |
| 7732 | return result; | |
| 7659 | 7733 | } |
| 7660 | 7734 | |
| 7661 | 7735 | static IrInstruction *ir_gen_node_raw(IrBuilder *irb, AstNode *node, Scope *scope, |
| ... | ... | @@ -7854,13 +7928,6 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec |
| 7854 | 7928 | // Entry block gets a reference because we enter it to begin. |
| 7855 | 7929 | ir_ref_bb(irb->current_basic_block); |
| 7856 | 7930 | |
| 7857 | ZigFn *fn_entry = exec_fn_entry(irb->exec); | |
| 7858 | ||
| 7859 | bool is_async = fn_entry != nullptr && fn_entry->type_entry->data.fn.fn_type_id.cc == CallingConventionAsync; | |
| 7860 | if (is_async) { | |
| 7861 | zig_panic("ir_gen async fn"); | |
| 7862 | } | |
| 7863 | ||
| 7864 | 7931 | IrInstruction *result = ir_gen_node_extra(irb, node, scope, LValNone, nullptr); |
| 7865 | 7932 | assert(result); |
| 7866 | 7933 | if (irb->exec->invalid) |
| ... | ... | @@ -12659,6 +12726,7 @@ static IrInstruction *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp * |
| 12659 | 12726 | case ZigTypeIdNull: |
| 12660 | 12727 | case ZigTypeIdErrorUnion: |
| 12661 | 12728 | case ZigTypeIdUnion: |
| 12729 | case ZigTypeIdCoroFrame: | |
| 12662 | 12730 | operator_allowed = false; |
| 12663 | 12731 | break; |
| 12664 | 12732 | case ZigTypeIdOptional: |
| ... | ... | @@ -14023,6 +14091,7 @@ static IrInstruction *ir_analyze_instruction_export(IrAnalyze *ira, IrInstructio |
| 14023 | 14091 | case ZigTypeIdBoundFn: |
| 14024 | 14092 | case ZigTypeIdArgTuple: |
| 14025 | 14093 | case ZigTypeIdOpaque: |
| 14094 | case ZigTypeIdCoroFrame: | |
| 14026 | 14095 | ir_add_error(ira, target, |
| 14027 | 14096 | buf_sprintf("invalid export target '%s'", buf_ptr(&type_value->name))); |
| 14028 | 14097 | break; |
| ... | ... | @@ -14047,6 +14116,7 @@ static IrInstruction *ir_analyze_instruction_export(IrAnalyze *ira, IrInstructio |
| 14047 | 14116 | case ZigTypeIdArgTuple: |
| 14048 | 14117 | case ZigTypeIdOpaque: |
| 14049 | 14118 | case ZigTypeIdEnumLiteral: |
| 14119 | case ZigTypeIdCoroFrame: | |
| 14050 | 14120 | ir_add_error(ira, target, |
| 14051 | 14121 | buf_sprintf("invalid export target type '%s'", buf_ptr(&target->value.type->name))); |
| 14052 | 14122 | break; |
| ... | ... | @@ -14553,6 +14623,20 @@ static IrInstruction *ir_analyze_instruction_reset_result(IrAnalyze *ira, IrInst |
| 14553 | 14623 | return ir_const_void(ira, &instruction->base); |
| 14554 | 14624 | } |
| 14555 | 14625 | |
| 14626 | static IrInstruction *ir_analyze_async_call(IrAnalyze *ira, IrInstructionCallSrc *call_instruction, ZigFn *fn_entry, | |
| 14627 | ZigType *fn_type, IrInstruction *fn_ref, IrInstruction **casted_args, size_t arg_count) | |
| 14628 | { | |
| 14629 | ir_assert(fn_entry != nullptr, &call_instruction->base); | |
| 14630 | ||
| 14631 | ZigType *frame_type = get_coro_frame_type(ira->codegen, fn_entry); | |
| 14632 | IrInstruction *result_loc = ir_resolve_result(ira, &call_instruction->base, call_instruction->result_loc, | |
| 14633 | frame_type, nullptr, true, true); | |
| 14634 | if (result_loc != nullptr && (type_is_invalid(result_loc->value.type) || instr_is_unreachable(result_loc))) { | |
| 14635 | return result_loc; | |
| 14636 | } | |
| 14637 | return ir_build_call_gen(ira, &call_instruction->base, fn_entry, fn_ref, arg_count, | |
| 14638 | casted_args, FnInlineAuto, true, nullptr, result_loc, frame_type); | |
| 14639 | } | |
| 14556 | 14640 | static bool ir_analyze_fn_call_inline_arg(IrAnalyze *ira, AstNode *fn_proto_node, |
| 14557 | 14641 | IrInstruction *arg, Scope **exec_scope, size_t *next_proto_i) |
| 14558 | 14642 | { |
| ... | ... | @@ -15366,16 +15450,18 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCallSrc *c |
| 15366 | 15450 | if (type_is_invalid(return_type)) |
| 15367 | 15451 | return ira->codegen->invalid_instruction; |
| 15368 | 15452 | |
| 15369 | if (call_instruction->is_async) { | |
| 15370 | zig_panic("TODO async call"); | |
| 15371 | } | |
| 15372 | ||
| 15373 | 15453 | if (fn_entry != nullptr && fn_entry->fn_inline == FnInlineAlways && fn_inline == FnInlineNever) { |
| 15374 | 15454 | ir_add_error(ira, &call_instruction->base, |
| 15375 | 15455 | buf_sprintf("no-inline call of inline function")); |
| 15376 | 15456 | return ira->codegen->invalid_instruction; |
| 15377 | 15457 | } |
| 15378 | 15458 | |
| 15459 | if (call_instruction->is_async) { | |
| 15460 | IrInstruction *result = ir_analyze_async_call(ira, call_instruction, fn_entry, fn_type, fn_ref, | |
| 15461 | casted_args, call_param_count); | |
| 15462 | return ir_finish_anal(ira, result); | |
| 15463 | } | |
| 15464 | ||
| 15379 | 15465 | IrInstruction *result_loc; |
| 15380 | 15466 | if (handle_is_ptr(return_type)) { |
| 15381 | 15467 | result_loc = ir_resolve_result(ira, &call_instruction->base, call_instruction->result_loc, |
| ... | ... | @@ -15535,7 +15621,7 @@ static Error ir_read_const_ptr(IrAnalyze *ira, CodeGen *codegen, AstNode *source |
| 15535 | 15621 | zig_unreachable(); |
| 15536 | 15622 | } |
| 15537 | 15623 | |
| 15538 | static IrInstruction *ir_analyze_maybe(IrAnalyze *ira, IrInstructionUnOp *un_op_instruction) { | |
| 15624 | static IrInstruction *ir_analyze_optional_type(IrAnalyze *ira, IrInstructionUnOp *un_op_instruction) { | |
| 15539 | 15625 | Error err; |
| 15540 | 15626 | IrInstruction *value = un_op_instruction->value->child; |
| 15541 | 15627 | ZigType *type_entry = ir_resolve_type(ira, value); |
| ... | ... | @@ -15569,6 +15655,7 @@ static IrInstruction *ir_analyze_maybe(IrAnalyze *ira, IrInstructionUnOp *un_op_ |
| 15569 | 15655 | case ZigTypeIdFn: |
| 15570 | 15656 | case ZigTypeIdBoundFn: |
| 15571 | 15657 | case ZigTypeIdArgTuple: |
| 15658 | case ZigTypeIdCoroFrame: | |
| 15572 | 15659 | return ir_const_type(ira, &un_op_instruction->base, get_optional_type(ira->codegen, type_entry)); |
| 15573 | 15660 | case ZigTypeIdUnreachable: |
| 15574 | 15661 | case ZigTypeIdOpaque: |
| ... | ... | @@ -15733,7 +15820,7 @@ static IrInstruction *ir_analyze_instruction_un_op(IrAnalyze *ira, IrInstruction |
| 15733 | 15820 | return result; |
| 15734 | 15821 | } |
| 15735 | 15822 | case IrUnOpOptional: |
| 15736 | return ir_analyze_maybe(ira, instruction); | |
| 15823 | return ir_analyze_optional_type(ira, instruction); | |
| 15737 | 15824 | } |
| 15738 | 15825 | zig_unreachable(); |
| 15739 | 15826 | } |
| ... | ... | @@ -17340,6 +17427,7 @@ static IrInstruction *ir_analyze_instruction_slice_type(IrAnalyze *ira, |
| 17340 | 17427 | case ZigTypeIdFn: |
| 17341 | 17428 | case ZigTypeIdBoundFn: |
| 17342 | 17429 | case ZigTypeIdVector: |
| 17430 | case ZigTypeIdCoroFrame: | |
| 17343 | 17431 | { |
| 17344 | 17432 | ResolveStatus needed_status = (align_bytes == 0) ? |
| 17345 | 17433 | ResolveStatusZeroBitsKnown : ResolveStatusAlignmentKnown; |
| ... | ... | @@ -17454,6 +17542,7 @@ static IrInstruction *ir_analyze_instruction_array_type(IrAnalyze *ira, |
| 17454 | 17542 | case ZigTypeIdFn: |
| 17455 | 17543 | case ZigTypeIdBoundFn: |
| 17456 | 17544 | case ZigTypeIdVector: |
| 17545 | case ZigTypeIdCoroFrame: | |
| 17457 | 17546 | { |
| 17458 | 17547 | if ((err = ensure_complete_type(ira->codegen, child_type))) |
| 17459 | 17548 | return ira->codegen->invalid_instruction; |
| ... | ... | @@ -17504,6 +17593,7 @@ static IrInstruction *ir_analyze_instruction_size_of(IrAnalyze *ira, |
| 17504 | 17593 | case ZigTypeIdUnion: |
| 17505 | 17594 | case ZigTypeIdFn: |
| 17506 | 17595 | case ZigTypeIdVector: |
| 17596 | case ZigTypeIdCoroFrame: | |
| 17507 | 17597 | { |
| 17508 | 17598 | uint64_t size_in_bytes = type_size(ira->codegen, type_entry); |
| 17509 | 17599 | return ir_const_unsigned(ira, &size_of_instruction->base, size_in_bytes); |
| ... | ... | @@ -18067,6 +18157,7 @@ static IrInstruction *ir_analyze_instruction_switch_target(IrAnalyze *ira, |
| 18067 | 18157 | case ZigTypeIdArgTuple: |
| 18068 | 18158 | case ZigTypeIdOpaque: |
| 18069 | 18159 | case ZigTypeIdVector: |
| 18160 | case ZigTypeIdCoroFrame: | |
| 18070 | 18161 | ir_add_error(ira, &switch_target_instruction->base, |
| 18071 | 18162 | buf_sprintf("invalid switch target type '%s'", buf_ptr(&target_type->name))); |
| 18072 | 18163 | return ira->codegen->invalid_instruction; |
| ... | ... | @@ -19906,6 +19997,8 @@ static Error ir_make_type_info_value(IrAnalyze *ira, IrInstruction *source_instr |
| 19906 | 19997 | |
| 19907 | 19998 | break; |
| 19908 | 19999 | } |
| 20000 | case ZigTypeIdCoroFrame: | |
| 20001 | zig_panic("TODO @typeInfo for coro frames"); | |
| 19909 | 20002 | } |
| 19910 | 20003 | |
| 19911 | 20004 | assert(result != nullptr); |
| ... | ... | @@ -21660,6 +21753,7 @@ static IrInstruction *ir_analyze_instruction_align_of(IrAnalyze *ira, IrInstruct |
| 21660 | 21753 | case ZigTypeIdUnion: |
| 21661 | 21754 | case ZigTypeIdFn: |
| 21662 | 21755 | case ZigTypeIdVector: |
| 21756 | case ZigTypeIdCoroFrame: | |
| 21663 | 21757 | { |
| 21664 | 21758 | uint64_t align_in_bytes = get_abi_alignment(ira->codegen, type_entry); |
| 21665 | 21759 | return ir_const_unsigned(ira, &instruction->base, align_in_bytes); |
| ... | ... | @@ -22815,6 +22909,8 @@ static void buf_write_value_bytes(CodeGen *codegen, uint8_t *buf, ConstExprValue |
| 22815 | 22909 | zig_panic("TODO buf_write_value_bytes fn type"); |
| 22816 | 22910 | case ZigTypeIdUnion: |
| 22817 | 22911 | zig_panic("TODO buf_write_value_bytes union type"); |
| 22912 | case ZigTypeIdCoroFrame: | |
| 22913 | zig_panic("TODO buf_write_value_bytes coro frame type"); | |
| 22818 | 22914 | } |
| 22819 | 22915 | zig_unreachable(); |
| 22820 | 22916 | } |
| ... | ... | @@ -22994,6 +23090,8 @@ static Error buf_read_value_bytes(IrAnalyze *ira, CodeGen *codegen, AstNode *sou |
| 22994 | 23090 | zig_panic("TODO buf_read_value_bytes fn type"); |
| 22995 | 23091 | case ZigTypeIdUnion: |
| 22996 | 23092 | zig_panic("TODO buf_read_value_bytes union type"); |
| 23093 | case ZigTypeIdCoroFrame: | |
| 23094 | zig_panic("TODO buf_read_value_bytes coro frame type"); | |
| 22997 | 23095 | } |
| 22998 | 23096 | zig_unreachable(); |
| 22999 | 23097 | } |
| ... | ... | @@ -24021,6 +24119,33 @@ static IrInstruction *ir_analyze_instruction_union_init_named_field(IrAnalyze *i |
| 24021 | 24119 | union_type, field_name, field_result_loc, result_loc); |
| 24022 | 24120 | } |
| 24023 | 24121 | |
| 24122 | static IrInstruction *ir_analyze_instruction_suspend_begin(IrAnalyze *ira, IrInstructionSuspendBegin *instruction) { | |
| 24123 | IrBasicBlock *new_bb = ir_get_new_bb_runtime(ira, instruction->resume_block, &instruction->base); | |
| 24124 | if (new_bb == nullptr) | |
| 24125 | return ir_unreach_error(ira); | |
| 24126 | return ir_build_suspend_begin(&ira->new_irb, instruction->base.scope, instruction->base.source_node, new_bb); | |
| 24127 | } | |
| 24128 | ||
| 24129 | static IrInstruction *ir_analyze_instruction_suspend_br(IrAnalyze *ira, IrInstructionSuspendBr *instruction) { | |
| 24130 | IrBasicBlock *old_dest_block = instruction->resume_block; | |
| 24131 | ||
| 24132 | IrBasicBlock *new_bb = ir_get_new_bb_runtime(ira, old_dest_block, &instruction->base); | |
| 24133 | if (new_bb == nullptr) | |
| 24134 | return ir_unreach_error(ira); | |
| 24135 | ||
| 24136 | ZigFn *fn_entry = exec_fn_entry(ira->new_irb.exec); | |
| 24137 | ir_assert(fn_entry != nullptr, &instruction->base); | |
| 24138 | fn_entry->resume_blocks.append(new_bb); | |
| 24139 | // This is done after appending the block because resume_index 0 is reserved for querying the size. | |
| 24140 | new_bb->resume_index = fn_entry->resume_blocks.length; | |
| 24141 | ||
| 24142 | ir_push_resume_block(ira, old_dest_block); | |
| 24143 | ||
| 24144 | IrInstruction *result = ir_build_suspend_br(&ira->new_irb, | |
| 24145 | instruction->base.scope, instruction->base.source_node, new_bb); | |
| 24146 | return ir_finish_anal(ira, result); | |
| 24147 | } | |
| 24148 | ||
| 24024 | 24149 | static IrInstruction *ir_analyze_instruction_base(IrAnalyze *ira, IrInstruction *instruction) { |
| 24025 | 24150 | switch (instruction->id) { |
| 24026 | 24151 | case IrInstructionIdInvalid: |
| ... | ... | @@ -24304,6 +24429,10 @@ static IrInstruction *ir_analyze_instruction_base(IrAnalyze *ira, IrInstruction |
| 24304 | 24429 | return ir_analyze_instruction_bit_cast_src(ira, (IrInstructionBitCastSrc *)instruction); |
| 24305 | 24430 | case IrInstructionIdUnionInitNamedField: |
| 24306 | 24431 | return ir_analyze_instruction_union_init_named_field(ira, (IrInstructionUnionInitNamedField *)instruction); |
| 24432 | case IrInstructionIdSuspendBegin: | |
| 24433 | return ir_analyze_instruction_suspend_begin(ira, (IrInstructionSuspendBegin *)instruction); | |
| 24434 | case IrInstructionIdSuspendBr: | |
| 24435 | return ir_analyze_instruction_suspend_br(ira, (IrInstructionSuspendBr *)instruction); | |
| 24307 | 24436 | } |
| 24308 | 24437 | zig_unreachable(); |
| 24309 | 24438 | } |
| ... | ... | @@ -24436,6 +24565,8 @@ bool ir_has_side_effects(IrInstruction *instruction) { |
| 24436 | 24565 | case IrInstructionIdOptionalWrap: |
| 24437 | 24566 | case IrInstructionIdVectorToArray: |
| 24438 | 24567 | case IrInstructionIdResetResult: |
| 24568 | case IrInstructionIdSuspendBegin: | |
| 24569 | case IrInstructionIdSuspendBr: | |
| 24439 | 24570 | return true; |
| 24440 | 24571 | |
| 24441 | 24572 | case IrInstructionIdPhi: |
src/ir_print.cpp+16| ... | ... | @@ -1503,6 +1503,16 @@ static void ir_print_union_init_named_field(IrPrint *irp, IrInstructionUnionInit |
| 1503 | 1503 | fprintf(irp->f, ")"); |
| 1504 | 1504 | } |
| 1505 | 1505 | |
| 1506 | static void ir_print_suspend_begin(IrPrint *irp, IrInstructionSuspendBegin *instruction) { | |
| 1507 | fprintf(irp->f, "@suspendBegin()"); | |
| 1508 | } | |
| 1509 | ||
| 1510 | static void ir_print_suspend_br(IrPrint *irp, IrInstructionSuspendBr *instruction) { | |
| 1511 | fprintf(irp->f, "@suspendBr("); | |
| 1512 | ir_print_other_block(irp, instruction->resume_block); | |
| 1513 | fprintf(irp->f, ")"); | |
| 1514 | } | |
| 1515 | ||
| 1506 | 1516 | static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) { |
| 1507 | 1517 | ir_print_prefix(irp, instruction); |
| 1508 | 1518 | switch (instruction->id) { |
| ... | ... | @@ -1961,6 +1971,12 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) { |
| 1961 | 1971 | case IrInstructionIdUnionInitNamedField: |
| 1962 | 1972 | ir_print_union_init_named_field(irp, (IrInstructionUnionInitNamedField *)instruction); |
| 1963 | 1973 | break; |
| 1974 | case IrInstructionIdSuspendBegin: | |
| 1975 | ir_print_suspend_begin(irp, (IrInstructionSuspendBegin *)instruction); | |
| 1976 | break; | |
| 1977 | case IrInstructionIdSuspendBr: | |
| 1978 | ir_print_suspend_br(irp, (IrInstructionSuspendBr *)instruction); | |
| 1979 | break; | |
| 1964 | 1980 | } |
| 1965 | 1981 | fprintf(irp->f, "\n"); |
| 1966 | 1982 | } |