| author | |
| committer | |
| log | c5c9d98065890eaeb9070cba20e5a1ed48b392af |
| tree | 46ad520853066174a22ad5eb6e3ac81e51f11d16 |
| parent | b8ed0cb3741533e036ee05faa165d2f0c49064f4 |
* remove `@setGlobalAlign`
* add align keyword for setting alignment on functions and
variables.
* loads and stores use alignment from pointer
* memcpy, memset use alignment from pointer
* add syntax for pointer alignment
* slices can have volatile
* add u2, i2 primitives
* ignore preferred align and use abi align everywhere
* back to only having alignOf builtin.
preferredAlignOf is too tricky to be useful.
See #432. Partial revert of
e726925e802eddab53cbfd9aacbc5eefe95c356f.
See #3720 files changed, 931 insertions(+), 715 deletions(-)
src/all_types.hpp+51-36| ... | ... | @@ -303,8 +303,6 @@ struct TldVar { |
| 303 | 303 | Tld base; |
| 304 | 304 | |
| 305 | 305 | VariableTableEntry *var; |
| 306 | AstNode *set_global_align_node; | |
| 307 | uint32_t alignment; | |
| 308 | 306 | AstNode *set_global_section_node; |
| 309 | 307 | Buf *section_name; |
| 310 | 308 | AstNode *set_global_linkage_node; |
| ... | ... | @@ -358,6 +356,7 @@ enum NodeType { |
| 358 | 356 | NodeTypeCharLiteral, |
| 359 | 357 | NodeTypeSymbol, |
| 360 | 358 | NodeTypePrefixOpExpr, |
| 359 | NodeTypeAddrOfExpr, | |
| 361 | 360 | NodeTypeFnCallExpr, |
| 362 | 361 | NodeTypeArrayAccessExpr, |
| 363 | 362 | NodeTypeSliceExpr, |
| ... | ... | @@ -415,6 +414,8 @@ struct AstNodeFnProto { |
| 415 | 414 | AstNode *fn_def_node; |
| 416 | 415 | // populated if this is an extern declaration |
| 417 | 416 | Buf *lib_name; |
| 417 | // populated if the "align A" is present | |
| 418 | AstNode *align_expr; | |
| 418 | 419 | }; |
| 419 | 420 | |
| 420 | 421 | struct AstNodeFnDef { |
| ... | ... | @@ -470,6 +471,8 @@ struct AstNodeVariableDeclaration { |
| 470 | 471 | AstNode *expr; |
| 471 | 472 | // populated if this is an extern declaration |
| 472 | 473 | Buf *lib_name; |
| 474 | // populated if the "align A" is present | |
| 475 | AstNode *align_expr; | |
| 473 | 476 | }; |
| 474 | 477 | |
| 475 | 478 | struct AstNodeErrorValueDecl { |
| ... | ... | @@ -579,10 +582,6 @@ enum PrefixOp { |
| 579 | 582 | PrefixOpBinNot, |
| 580 | 583 | PrefixOpNegation, |
| 581 | 584 | PrefixOpNegationWrap, |
| 582 | PrefixOpAddressOf, | |
| 583 | PrefixOpConstAddressOf, | |
| 584 | PrefixOpVolatileAddressOf, | |
| 585 | PrefixOpConstVolatileAddressOf, | |
| 586 | 585 | PrefixOpDereference, |
| 587 | 586 | PrefixOpMaybe, |
| 588 | 587 | PrefixOpError, |
| ... | ... | @@ -595,6 +594,23 @@ struct AstNodePrefixOpExpr { |
| 595 | 594 | AstNode *primary_expr; |
| 596 | 595 | }; |
| 597 | 596 | |
| 597 | struct AstNodeAddrOfExpr { | |
| 598 | AstNode *align_expr; | |
| 599 | BigInt *bit_offset_start; | |
| 600 | BigInt *bit_offset_end; | |
| 601 | bool is_const; | |
| 602 | bool is_volatile; | |
| 603 | AstNode *op_expr; | |
| 604 | }; | |
| 605 | ||
| 606 | struct AstNodeArrayType { | |
| 607 | AstNode *size; | |
| 608 | AstNode *child_type; | |
| 609 | AstNode *align_expr; | |
| 610 | bool is_const; | |
| 611 | bool is_volatile; | |
| 612 | }; | |
| 613 | ||
| 598 | 614 | struct AstNodeUse { |
| 599 | 615 | VisibMod visib_mod; |
| 600 | 616 | AstNode *expr; |
| ... | ... | @@ -807,12 +823,6 @@ struct AstNodeUnreachableExpr { |
| 807 | 823 | }; |
| 808 | 824 | |
| 809 | 825 | |
| 810 | struct AstNodeArrayType { | |
| 811 | AstNode *size; | |
| 812 | AstNode *child_type; | |
| 813 | bool is_const; | |
| 814 | }; | |
| 815 | ||
| 816 | 826 | struct AstNodeErrorType { |
| 817 | 827 | }; |
| 818 | 828 | |
| ... | ... | @@ -841,6 +851,7 @@ struct AstNode { |
| 841 | 851 | AstNodeBinOpExpr bin_op_expr; |
| 842 | 852 | AstNodeUnwrapErrorExpr unwrap_err_expr; |
| 843 | 853 | AstNodePrefixOpExpr prefix_op_expr; |
| 854 | AstNodeAddrOfExpr addr_of_expr; | |
| 844 | 855 | AstNodeFnCallExpr fn_call_expr; |
| 845 | 856 | AstNodeArrayAccessExpr array_access_expr; |
| 846 | 857 | AstNodeSliceExpr slice_expr; |
| ... | ... | @@ -911,8 +922,10 @@ struct TypeTableEntryPointer { |
| 911 | 922 | TypeTableEntry *child_type; |
| 912 | 923 | bool is_const; |
| 913 | 924 | bool is_volatile; |
| 925 | uint32_t alignment; | |
| 914 | 926 | uint32_t bit_offset; |
| 915 | 927 | uint32_t unaligned_bit_count; |
| 928 | TypeTableEntry *slice_parent; | |
| 916 | 929 | }; |
| 917 | 930 | |
| 918 | 931 | struct TypeTableEntryInt { |
| ... | ... | @@ -958,6 +971,7 @@ struct TypeTableEntryStruct { |
| 958 | 971 | |
| 959 | 972 | bool zero_bits_loop_flag; |
| 960 | 973 | bool zero_bits_known; |
| 974 | uint32_t abi_alignment; // also figured out with zero_bits pass | |
| 961 | 975 | }; |
| 962 | 976 | |
| 963 | 977 | struct TypeTableEntryMaybe { |
| ... | ... | @@ -989,6 +1003,7 @@ struct TypeTableEntryEnum { |
| 989 | 1003 | |
| 990 | 1004 | bool zero_bits_loop_flag; |
| 991 | 1005 | bool zero_bits_known; |
| 1006 | uint32_t abi_alignment; // also figured out with zero_bits pass | |
| 992 | 1007 | |
| 993 | 1008 | size_t gen_union_index; |
| 994 | 1009 | size_t gen_tag_index; |
| ... | ... | @@ -1101,7 +1116,6 @@ struct TypeTableEntry { |
| 1101 | 1116 | |
| 1102 | 1117 | // use these fields to make sure we don't duplicate type table entries for the same type |
| 1103 | 1118 | TypeTableEntry *pointer_parent[2]; // [0 - mut, 1 - const] |
| 1104 | TypeTableEntry *slice_parent[2]; // [0 - mut, 1 - const] | |
| 1105 | 1119 | TypeTableEntry *maybe_parent; |
| 1106 | 1120 | TypeTableEntry *error_parent; |
| 1107 | 1121 | // If we generate a constant name value for this type, we memoize it here. |
| ... | ... | @@ -1164,6 +1178,7 @@ struct FnTableEntry { |
| 1164 | 1178 | size_t prealloc_bbc; |
| 1165 | 1179 | AstNode **param_source_nodes; |
| 1166 | 1180 | Buf **param_names; |
| 1181 | uint32_t align_bytes; | |
| 1167 | 1182 | |
| 1168 | 1183 | AstNode *fn_no_inline_set_node; |
| 1169 | 1184 | AstNode *fn_static_eval_set_node; |
| ... | ... | @@ -1171,8 +1186,6 @@ struct FnTableEntry { |
| 1171 | 1186 | ZigList<IrInstruction *> alloca_list; |
| 1172 | 1187 | ZigList<VariableTableEntry *> variable_list; |
| 1173 | 1188 | |
| 1174 | AstNode *set_global_align_node; | |
| 1175 | uint32_t alignment; | |
| 1176 | 1189 | AstNode *set_global_section_node; |
| 1177 | 1190 | Buf *section_name; |
| 1178 | 1191 | AstNode *set_global_linkage_node; |
| ... | ... | @@ -1187,8 +1200,7 @@ enum BuiltinFnId { |
| 1187 | 1200 | BuiltinFnIdMemcpy, |
| 1188 | 1201 | BuiltinFnIdMemset, |
| 1189 | 1202 | BuiltinFnIdSizeof, |
| 1190 | BuiltinFnIdPreferredAlignOf, | |
| 1191 | BuiltinFnIdAbiAlignOf, | |
| 1203 | BuiltinFnIdAlignOf, | |
| 1192 | 1204 | BuiltinFnIdMaxValue, |
| 1193 | 1205 | BuiltinFnIdMinValue, |
| 1194 | 1206 | BuiltinFnIdMemberCount, |
| ... | ... | @@ -1224,7 +1236,6 @@ enum BuiltinFnId { |
| 1224 | 1236 | BuiltinFnIdSetFloatMode, |
| 1225 | 1237 | BuiltinFnIdTypeName, |
| 1226 | 1238 | BuiltinFnIdCanImplicitCast, |
| 1227 | BuiltinFnIdSetGlobalAlign, | |
| 1228 | 1239 | BuiltinFnIdSetGlobalSection, |
| 1229 | 1240 | BuiltinFnIdSetGlobalLinkage, |
| 1230 | 1241 | BuiltinFnIdPanic, |
| ... | ... | @@ -1277,6 +1288,7 @@ struct TypeId { |
| 1277 | 1288 | TypeTableEntry *child_type; |
| 1278 | 1289 | bool is_const; |
| 1279 | 1290 | bool is_volatile; |
| 1291 | uint32_t alignment; | |
| 1280 | 1292 | uint32_t bit_offset; |
| 1281 | 1293 | uint32_t unaligned_bit_count; |
| 1282 | 1294 | } pointer; |
| ... | ... | @@ -1392,7 +1404,7 @@ struct CodeGen { |
| 1392 | 1404 | |
| 1393 | 1405 | struct { |
| 1394 | 1406 | TypeTableEntry *entry_bool; |
| 1395 | TypeTableEntry *entry_int[2][10]; // [signed,unsigned][3,4,5,6,7,8,16,32,64,128] | |
| 1407 | TypeTableEntry *entry_int[2][11]; // [signed,unsigned][2,3,4,5,6,7,8,16,32,64,128] | |
| 1396 | 1408 | TypeTableEntry *entry_c_int[CIntTypeCount]; |
| 1397 | 1409 | TypeTableEntry *entry_c_longdouble; |
| 1398 | 1410 | TypeTableEntry *entry_c_void; |
| ... | ... | @@ -1547,6 +1559,8 @@ struct CodeGen { |
| 1547 | 1559 | |
| 1548 | 1560 | ZigList<FnTableEntry *> inline_fns; |
| 1549 | 1561 | ZigList<AstNode *> tld_ref_source_node_stack; |
| 1562 | ||
| 1563 | TypeTableEntry *align_amt_type; | |
| 1550 | 1564 | }; |
| 1551 | 1565 | |
| 1552 | 1566 | enum VarLinkage { |
| ... | ... | @@ -1575,6 +1589,7 @@ struct VariableTableEntry { |
| 1575 | 1589 | size_t ref_count; |
| 1576 | 1590 | VarLinkage linkage; |
| 1577 | 1591 | IrInstruction *decl_instruction; |
| 1592 | uint32_t align_bytes; | |
| 1578 | 1593 | }; |
| 1579 | 1594 | |
| 1580 | 1595 | struct ErrorTableEntry { |
| ... | ... | @@ -1808,8 +1823,7 @@ enum IrInstructionId { |
| 1808 | 1823 | IrInstructionIdBreakpoint, |
| 1809 | 1824 | IrInstructionIdReturnAddress, |
| 1810 | 1825 | IrInstructionIdFrameAddress, |
| 1811 | IrInstructionIdPreferredAlignOf, | |
| 1812 | IrInstructionIdAbiAlignOf, | |
| 1826 | IrInstructionIdAlignOf, | |
| 1813 | 1827 | IrInstructionIdOverflowOp, |
| 1814 | 1828 | IrInstructionIdTestErr, |
| 1815 | 1829 | IrInstructionIdUnwrapErrCode, |
| ... | ... | @@ -1831,7 +1845,6 @@ enum IrInstructionId { |
| 1831 | 1845 | IrInstructionIdCheckStatementIsVoid, |
| 1832 | 1846 | IrInstructionIdTypeName, |
| 1833 | 1847 | IrInstructionIdCanImplicitCast, |
| 1834 | IrInstructionIdSetGlobalAlign, | |
| 1835 | 1848 | IrInstructionIdSetGlobalSection, |
| 1836 | 1849 | IrInstructionIdSetGlobalLinkage, |
| 1837 | 1850 | IrInstructionIdDeclRef, |
| ... | ... | @@ -1841,6 +1854,7 @@ enum IrInstructionId { |
| 1841 | 1854 | IrInstructionIdOffsetOf, |
| 1842 | 1855 | IrInstructionIdTypeId, |
| 1843 | 1856 | IrInstructionIdSetEvalBranchQuota, |
| 1857 | IrInstructionIdPtrTypeOf, | |
| 1844 | 1858 | }; |
| 1845 | 1859 | |
| 1846 | 1860 | struct IrInstruction { |
| ... | ... | @@ -1976,6 +1990,7 @@ struct IrInstructionDeclVar { |
| 1976 | 1990 | |
| 1977 | 1991 | VariableTableEntry *var; |
| 1978 | 1992 | IrInstruction *var_type; |
| 1993 | IrInstruction *align_value; | |
| 1979 | 1994 | IrInstruction *init_value; |
| 1980 | 1995 | }; |
| 1981 | 1996 | |
| ... | ... | @@ -2152,7 +2167,9 @@ struct IrInstructionArrayType { |
| 2152 | 2167 | struct IrInstructionSliceType { |
| 2153 | 2168 | IrInstruction base; |
| 2154 | 2169 | |
| 2170 | IrInstruction *align_value; | |
| 2155 | 2171 | bool is_const; |
| 2172 | bool is_volatile; | |
| 2156 | 2173 | IrInstruction *child_type; |
| 2157 | 2174 | }; |
| 2158 | 2175 | |
| ... | ... | @@ -2393,13 +2410,7 @@ struct IrInstructionOverflowOp { |
| 2393 | 2410 | TypeTableEntry *result_ptr_type; |
| 2394 | 2411 | }; |
| 2395 | 2412 | |
| 2396 | struct IrInstructionPreferredAlignOf { | |
| 2397 | IrInstruction base; | |
| 2398 | ||
| 2399 | IrInstruction *type_value; | |
| 2400 | }; | |
| 2401 | ||
| 2402 | struct IrInstructionAbiAlignOf { | |
| 2413 | struct IrInstructionAlignOf { | |
| 2403 | 2414 | IrInstruction base; |
| 2404 | 2415 | |
| 2405 | 2416 | IrInstruction *type_value; |
| ... | ... | @@ -2554,13 +2565,6 @@ struct IrInstructionCanImplicitCast { |
| 2554 | 2565 | IrInstruction *target_value; |
| 2555 | 2566 | }; |
| 2556 | 2567 | |
| 2557 | struct IrInstructionSetGlobalAlign { | |
| 2558 | IrInstruction base; | |
| 2559 | ||
| 2560 | Tld *tld; | |
| 2561 | IrInstruction *value; | |
| 2562 | }; | |
| 2563 | ||
| 2564 | 2568 | struct IrInstructionSetGlobalSection { |
| 2565 | 2569 | IrInstruction base; |
| 2566 | 2570 | |
| ... | ... | @@ -2622,6 +2626,17 @@ struct IrInstructionSetEvalBranchQuota { |
| 2622 | 2626 | IrInstruction *new_quota; |
| 2623 | 2627 | }; |
| 2624 | 2628 | |
| 2629 | struct IrInstructionPtrTypeOf { | |
| 2630 | IrInstruction base; | |
| 2631 | ||
| 2632 | IrInstruction *align_value; | |
| 2633 | IrInstruction *child_type; | |
| 2634 | uint32_t bit_offset_start; | |
| 2635 | uint32_t bit_offset_end; | |
| 2636 | bool is_const; | |
| 2637 | bool is_volatile; | |
| 2638 | }; | |
| 2639 | ||
| 2625 | 2640 | static const size_t slice_ptr_index = 0; |
| 2626 | 2641 | static const size_t slice_len_index = 1; |
| 2627 | 2642 |
src/analyze.cpp+302-170| ... | ... | @@ -320,17 +320,21 @@ TypeTableEntry *get_smallest_unsigned_int_type(CodeGen *g, uint64_t x) { |
| 320 | 320 | } |
| 321 | 321 | |
| 322 | 322 | TypeTableEntry *get_pointer_to_type_extra(CodeGen *g, TypeTableEntry *child_type, bool is_const, |
| 323 | bool is_volatile, uint32_t bit_offset, uint32_t unaligned_bit_count) | |
| 323 | bool is_volatile, uint32_t byte_alignment, uint32_t bit_offset, uint32_t unaligned_bit_count) | |
| 324 | 324 | { |
| 325 | 325 | assert(child_type->id != TypeTableEntryIdInvalid); |
| 326 | 326 | |
| 327 | 327 | TypeId type_id = {}; |
| 328 | 328 | TypeTableEntry **parent_pointer = nullptr; |
| 329 | if (unaligned_bit_count != 0 || is_volatile) { | |
| 329 | uint32_t abi_alignment; | |
| 330 | if (unaligned_bit_count != 0 || is_volatile || | |
| 331 | byte_alignment != (abi_alignment = get_abi_alignment(g, child_type))) | |
| 332 | { | |
| 330 | 333 | type_id.id = TypeTableEntryIdPointer; |
| 331 | 334 | type_id.data.pointer.child_type = child_type; |
| 332 | 335 | type_id.data.pointer.is_const = is_const; |
| 333 | 336 | type_id.data.pointer.is_volatile = is_volatile; |
| 337 | type_id.data.pointer.alignment = byte_alignment; | |
| 334 | 338 | type_id.data.pointer.bit_offset = bit_offset; |
| 335 | 339 | type_id.data.pointer.unaligned_bit_count = unaligned_bit_count; |
| 336 | 340 | |
| ... | ... | @@ -352,11 +356,14 @@ TypeTableEntry *get_pointer_to_type_extra(CodeGen *g, TypeTableEntry *child_type |
| 352 | 356 | const char *const_str = is_const ? "const " : ""; |
| 353 | 357 | const char *volatile_str = is_volatile ? "volatile " : ""; |
| 354 | 358 | buf_resize(&entry->name, 0); |
| 355 | if (unaligned_bit_count == 0) { | |
| 359 | if (unaligned_bit_count == 0 && byte_alignment == abi_alignment) { | |
| 356 | 360 | buf_appendf(&entry->name, "&%s%s%s", const_str, volatile_str, buf_ptr(&child_type->name)); |
| 361 | } else if (unaligned_bit_count == 0) { | |
| 362 | buf_appendf(&entry->name, "&align %" PRIu32 " %s%s%s", byte_alignment, | |
| 363 | const_str, volatile_str, buf_ptr(&child_type->name)); | |
| 357 | 364 | } else { |
| 358 | buf_appendf(&entry->name, "&:%" PRIu32 ":%" PRIu32 " %s%s%s", bit_offset, | |
| 359 | bit_offset + unaligned_bit_count, const_str, volatile_str, buf_ptr(&child_type->name)); | |
| 365 | buf_appendf(&entry->name, "&align %" PRIu32 ":%" PRIu32 ":%" PRIu32 " %s%s%s", byte_alignment, | |
| 366 | bit_offset, bit_offset + unaligned_bit_count, const_str, volatile_str, buf_ptr(&child_type->name)); | |
| 360 | 367 | } |
| 361 | 368 | |
| 362 | 369 | assert(child_type->id != TypeTableEntryIdInvalid); |
| ... | ... | @@ -364,20 +371,29 @@ TypeTableEntry *get_pointer_to_type_extra(CodeGen *g, TypeTableEntry *child_type |
| 364 | 371 | entry->zero_bits = !type_has_bits(child_type); |
| 365 | 372 | |
| 366 | 373 | if (!entry->zero_bits) { |
| 367 | entry->type_ref = LLVMPointerType(child_type->type_ref, 0); | |
| 374 | assert(byte_alignment > 0); | |
| 375 | if (is_const || is_volatile || unaligned_bit_count != 0 || byte_alignment != abi_alignment) { | |
| 376 | TypeTableEntry *peer_type = get_pointer_to_type(g, child_type, false); | |
| 377 | entry->type_ref = peer_type->type_ref; | |
| 378 | entry->di_type = peer_type->di_type; | |
| 379 | } else { | |
| 380 | entry->type_ref = LLVMPointerType(child_type->type_ref, 0); | |
| 368 | 381 | |
| 369 | uint64_t debug_size_in_bits = 8*LLVMStoreSizeOfType(g->target_data_ref, entry->type_ref); | |
| 370 | uint64_t debug_align_in_bits = 8*LLVMABISizeOfType(g->target_data_ref, entry->type_ref); | |
| 371 | assert(child_type->di_type); | |
| 372 | entry->di_type = ZigLLVMCreateDebugPointerType(g->dbuilder, child_type->di_type, | |
| 373 | debug_size_in_bits, debug_align_in_bits, buf_ptr(&entry->name)); | |
| 382 | uint64_t debug_size_in_bits = 8*LLVMStoreSizeOfType(g->target_data_ref, entry->type_ref); | |
| 383 | uint64_t debug_align_in_bits = 8*LLVMABIAlignmentOfType(g->target_data_ref, entry->type_ref); | |
| 384 | assert(child_type->di_type); | |
| 385 | entry->di_type = ZigLLVMCreateDebugPointerType(g->dbuilder, child_type->di_type, | |
| 386 | debug_size_in_bits, debug_align_in_bits, buf_ptr(&entry->name)); | |
| 387 | } | |
| 374 | 388 | } else { |
| 389 | assert(byte_alignment == 0); | |
| 375 | 390 | entry->di_type = g->builtin_types.entry_void->di_type; |
| 376 | 391 | } |
| 377 | 392 | |
| 378 | 393 | entry->data.pointer.child_type = child_type; |
| 379 | 394 | entry->data.pointer.is_const = is_const; |
| 380 | 395 | entry->data.pointer.is_volatile = is_volatile; |
| 396 | entry->data.pointer.alignment = byte_alignment; | |
| 381 | 397 | entry->data.pointer.bit_offset = bit_offset; |
| 382 | 398 | entry->data.pointer.unaligned_bit_count = unaligned_bit_count; |
| 383 | 399 | |
| ... | ... | @@ -390,7 +406,7 @@ TypeTableEntry *get_pointer_to_type_extra(CodeGen *g, TypeTableEntry *child_type |
| 390 | 406 | } |
| 391 | 407 | |
| 392 | 408 | TypeTableEntry *get_pointer_to_type(CodeGen *g, TypeTableEntry *child_type, bool is_const) { |
| 393 | return get_pointer_to_type_extra(g, child_type, is_const, false, 0, 0); | |
| 409 | return get_pointer_to_type_extra(g, child_type, is_const, false, get_abi_alignment(g, child_type), 0, 0); | |
| 394 | 410 | } |
| 395 | 411 | |
| 396 | 412 | TypeTableEntry *get_maybe_type(CodeGen *g, TypeTableEntry *child_type) { |
| ... | ... | @@ -592,11 +608,7 @@ TypeTableEntry *get_array_type(CodeGen *g, TypeTableEntry *child_type, uint64_t |
| 592 | 608 | return entry; |
| 593 | 609 | } |
| 594 | 610 | |
| 595 | static void slice_type_common_init(CodeGen *g, TypeTableEntry *child_type, | |
| 596 | bool is_const, TypeTableEntry *entry) | |
| 597 | { | |
| 598 | TypeTableEntry *pointer_type = get_pointer_to_type(g, child_type, is_const); | |
| 599 | ||
| 611 | static void slice_type_common_init(CodeGen *g, TypeTableEntry *pointer_type, TypeTableEntry *entry) { | |
| 600 | 612 | unsigned element_count = 2; |
| 601 | 613 | entry->data.structure.layout = ContainerLayoutAuto; |
| 602 | 614 | entry->data.structure.is_slice = true; |
| ... | ... | @@ -612,156 +624,167 @@ static void slice_type_common_init(CodeGen *g, TypeTableEntry *child_type, |
| 612 | 624 | entry->data.structure.fields[slice_len_index].src_index = slice_len_index; |
| 613 | 625 | entry->data.structure.fields[slice_len_index].gen_index = 1; |
| 614 | 626 | |
| 615 | assert(type_has_zero_bits_known(child_type)); | |
| 616 | if (child_type->zero_bits) { | |
| 627 | assert(type_has_zero_bits_known(pointer_type->data.pointer.child_type)); | |
| 628 | if (pointer_type->data.pointer.child_type->zero_bits) { | |
| 617 | 629 | entry->data.structure.gen_field_count = 1; |
| 618 | 630 | entry->data.structure.fields[slice_ptr_index].gen_index = SIZE_MAX; |
| 619 | 631 | entry->data.structure.fields[slice_len_index].gen_index = 0; |
| 620 | 632 | } |
| 621 | 633 | } |
| 622 | 634 | |
| 623 | TypeTableEntry *get_slice_type(CodeGen *g, TypeTableEntry *child_type, bool is_const) { | |
| 624 | assert(child_type->id != TypeTableEntryIdInvalid); | |
| 625 | TypeTableEntry **parent_pointer = &child_type->slice_parent[(is_const ? 1 : 0)]; | |
| 635 | TypeTableEntry *get_slice_type(CodeGen *g, TypeTableEntry *ptr_type) { | |
| 636 | assert(ptr_type->id == TypeTableEntryIdPointer); | |
| 626 | 637 | |
| 638 | TypeTableEntry **parent_pointer = &ptr_type->data.pointer.slice_parent; | |
| 627 | 639 | if (*parent_pointer) { |
| 628 | 640 | return *parent_pointer; |
| 629 | } else if (is_const) { | |
| 630 | TypeTableEntry *var_peer = get_slice_type(g, child_type, false); | |
| 631 | TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdStruct); | |
| 632 | entry->is_copyable = true; | |
| 641 | } | |
| 633 | 642 | |
| 634 | buf_resize(&entry->name, 0); | |
| 635 | buf_appendf(&entry->name, "[]const %s", buf_ptr(&child_type->name)); | |
| 643 | TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdStruct); | |
| 644 | entry->is_copyable = true; | |
| 636 | 645 | |
| 637 | slice_type_common_init(g, child_type, is_const, entry); | |
| 646 | // replace the & with [] to go from a ptr type name to a slice type name | |
| 647 | buf_resize(&entry->name, 0); | |
| 648 | buf_appendf(&entry->name, "[]%s", buf_ptr(&ptr_type->name) + 1); | |
| 638 | 649 | |
| 639 | entry->type_ref = var_peer->type_ref; | |
| 640 | entry->di_type = var_peer->di_type; | |
| 650 | TypeTableEntry *child_type = ptr_type->data.pointer.child_type; | |
| 651 | uint32_t abi_alignment; | |
| 652 | if (ptr_type->data.pointer.is_const || ptr_type->data.pointer.is_volatile || | |
| 653 | ptr_type->data.pointer.alignment != (abi_alignment = get_abi_alignment(g, child_type))) | |
| 654 | { | |
| 655 | TypeTableEntry *peer_ptr_type = get_pointer_to_type(g, child_type, false); | |
| 656 | TypeTableEntry *peer_slice_type = get_slice_type(g, peer_ptr_type); | |
| 657 | ||
| 658 | slice_type_common_init(g, ptr_type, entry); | |
| 659 | ||
| 660 | entry->type_ref = peer_slice_type->type_ref; | |
| 661 | entry->di_type = peer_slice_type->di_type; | |
| 641 | 662 | entry->data.structure.complete = true; |
| 642 | 663 | entry->data.structure.zero_bits_known = true; |
| 664 | entry->data.structure.abi_alignment = peer_slice_type->data.structure.abi_alignment; | |
| 643 | 665 | |
| 644 | 666 | *parent_pointer = entry; |
| 645 | 667 | return entry; |
| 646 | } else { | |
| 647 | TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdStruct); | |
| 648 | entry->is_copyable = true; | |
| 649 | ||
| 650 | // If the child type is []const T then we need to make sure the type ref | |
| 651 | // and debug info is the same as if the child type were []T. | |
| 652 | if (is_slice(child_type)) { | |
| 653 | TypeTableEntry *ptr_type = child_type->data.structure.fields[slice_ptr_index].type_entry; | |
| 654 | assert(ptr_type->id == TypeTableEntryIdPointer); | |
| 655 | if (ptr_type->data.pointer.is_const) { | |
| 656 | TypeTableEntry *non_const_child_type = get_slice_type(g, | |
| 657 | ptr_type->data.pointer.child_type, false); | |
| 658 | TypeTableEntry *var_peer = get_slice_type(g, non_const_child_type, false); | |
| 659 | ||
| 660 | entry->type_ref = var_peer->type_ref; | |
| 661 | entry->di_type = var_peer->di_type; | |
| 662 | } | |
| 668 | } | |
| 669 | ||
| 670 | // If the child type is []const T then we need to make sure the type ref | |
| 671 | // and debug info is the same as if the child type were []T. | |
| 672 | if (is_slice(child_type)) { | |
| 673 | TypeTableEntry *child_ptr_type = child_type->data.structure.fields[slice_ptr_index].type_entry; | |
| 674 | assert(child_ptr_type->id == TypeTableEntryIdPointer); | |
| 675 | TypeTableEntry *grand_child_type = child_ptr_type->data.pointer.child_type; | |
| 676 | if (child_ptr_type->data.pointer.is_const || child_ptr_type->data.pointer.is_volatile || | |
| 677 | child_ptr_type->data.pointer.alignment != get_abi_alignment(g, grand_child_type)) | |
| 678 | { | |
| 679 | TypeTableEntry *bland_child_ptr_type = get_pointer_to_type(g, grand_child_type, false); | |
| 680 | TypeTableEntry *bland_child_slice = get_slice_type(g, bland_child_ptr_type); | |
| 681 | TypeTableEntry *peer_ptr_type = get_pointer_to_type(g, bland_child_slice, false); | |
| 682 | TypeTableEntry *peer_slice_type = get_slice_type(g, peer_ptr_type); | |
| 683 | ||
| 684 | entry->type_ref = peer_slice_type->type_ref; | |
| 685 | entry->di_type = peer_slice_type->di_type; | |
| 686 | entry->data.structure.abi_alignment = peer_slice_type->data.structure.abi_alignment; | |
| 663 | 687 | } |
| 688 | } | |
| 664 | 689 | |
| 665 | buf_resize(&entry->name, 0); | |
| 666 | buf_appendf(&entry->name, "[]%s", buf_ptr(&child_type->name)); | |
| 690 | slice_type_common_init(g, ptr_type, entry); | |
| 667 | 691 | |
| 668 | slice_type_common_init(g, child_type, is_const, entry); | |
| 692 | if (!entry->type_ref) { | |
| 693 | entry->type_ref = LLVMStructCreateNamed(LLVMGetGlobalContext(), buf_ptr(&entry->name)); | |
| 669 | 694 | |
| 670 | if (!entry->type_ref) { | |
| 671 | entry->type_ref = LLVMStructCreateNamed(LLVMGetGlobalContext(), buf_ptr(&entry->name)); | |
| 695 | ZigLLVMDIScope *compile_unit_scope = ZigLLVMCompileUnitToScope(g->compile_unit); | |
| 696 | ZigLLVMDIFile *di_file = nullptr; | |
| 697 | unsigned line = 0; | |
| 698 | entry->di_type = ZigLLVMCreateReplaceableCompositeType(g->dbuilder, | |
| 699 | ZigLLVMTag_DW_structure_type(), buf_ptr(&entry->name), | |
| 700 | compile_unit_scope, di_file, line); | |
| 672 | 701 | |
| 673 | ZigLLVMDIScope *compile_unit_scope = ZigLLVMCompileUnitToScope(g->compile_unit); | |
| 674 | ZigLLVMDIFile *di_file = nullptr; | |
| 675 | unsigned line = 0; | |
| 676 | entry->di_type = ZigLLVMCreateReplaceableCompositeType(g->dbuilder, | |
| 677 | ZigLLVMTag_DW_structure_type(), buf_ptr(&entry->name), | |
| 678 | compile_unit_scope, di_file, line); | |
| 702 | if (child_type->zero_bits) { | |
| 703 | LLVMTypeRef element_types[] = { | |
| 704 | g->builtin_types.entry_usize->type_ref, | |
| 705 | }; | |
| 706 | LLVMStructSetBody(entry->type_ref, element_types, 1, false); | |
| 679 | 707 | |
| 680 | if (child_type->zero_bits) { | |
| 681 | LLVMTypeRef element_types[] = { | |
| 682 | g->builtin_types.entry_usize->type_ref, | |
| 683 | }; | |
| 684 | LLVMStructSetBody(entry->type_ref, element_types, 1, false); | |
| 685 | ||
| 686 | TypeTableEntry *usize_type = g->builtin_types.entry_usize; | |
| 687 | uint64_t len_debug_size_in_bits = 8*LLVMStoreSizeOfType(g->target_data_ref, usize_type->type_ref); | |
| 688 | uint64_t len_debug_align_in_bits = 8*LLVMABISizeOfType(g->target_data_ref, usize_type->type_ref); | |
| 689 | uint64_t len_offset_in_bits = 8*LLVMOffsetOfElement(g->target_data_ref, entry->type_ref, 0); | |
| 690 | ||
| 691 | uint64_t debug_size_in_bits = 8*LLVMStoreSizeOfType(g->target_data_ref, entry->type_ref); | |
| 692 | uint64_t debug_align_in_bits = 8*LLVMABISizeOfType(g->target_data_ref, entry->type_ref); | |
| 693 | ||
| 694 | ZigLLVMDIType *di_element_types[] = { | |
| 695 | ZigLLVMCreateDebugMemberType(g->dbuilder, ZigLLVMTypeToScope(entry->di_type), | |
| 696 | "len", di_file, line, | |
| 697 | len_debug_size_in_bits, | |
| 698 | len_debug_align_in_bits, | |
| 699 | len_offset_in_bits, | |
| 700 | 0, usize_type->di_type), | |
| 701 | }; | |
| 702 | ZigLLVMDIType *replacement_di_type = ZigLLVMCreateDebugStructType(g->dbuilder, | |
| 703 | compile_unit_scope, | |
| 704 | buf_ptr(&entry->name), | |
| 705 | di_file, line, debug_size_in_bits, debug_align_in_bits, 0, | |
| 706 | nullptr, di_element_types, 1, 0, nullptr, ""); | |
| 707 | ||
| 708 | ZigLLVMReplaceTemporary(g->dbuilder, entry->di_type, replacement_di_type); | |
| 709 | entry->di_type = replacement_di_type; | |
| 710 | } else { | |
| 711 | TypeTableEntry *pointer_type = get_pointer_to_type(g, child_type, is_const); | |
| 708 | TypeTableEntry *usize_type = g->builtin_types.entry_usize; | |
| 709 | uint64_t len_debug_size_in_bits = 8*LLVMStoreSizeOfType(g->target_data_ref, usize_type->type_ref); | |
| 710 | uint64_t len_debug_align_in_bits = 8*LLVMABIAlignmentOfType(g->target_data_ref, usize_type->type_ref); | |
| 711 | uint64_t len_offset_in_bits = 8*LLVMOffsetOfElement(g->target_data_ref, entry->type_ref, 0); | |
| 712 | 712 | |
| 713 | unsigned element_count = 2; | |
| 714 | LLVMTypeRef element_types[] = { | |
| 715 | pointer_type->type_ref, | |
| 716 | g->builtin_types.entry_usize->type_ref, | |
| 717 | }; | |
| 718 | LLVMStructSetBody(entry->type_ref, element_types, element_count, false); | |
| 719 | ||
| 720 | ||
| 721 | uint64_t ptr_debug_size_in_bits = 8*LLVMStoreSizeOfType(g->target_data_ref, pointer_type->type_ref); | |
| 722 | uint64_t ptr_debug_align_in_bits = 8*LLVMABISizeOfType(g->target_data_ref, pointer_type->type_ref); | |
| 723 | uint64_t ptr_offset_in_bits = 8*LLVMOffsetOfElement(g->target_data_ref, entry->type_ref, 0); | |
| 724 | ||
| 725 | TypeTableEntry *usize_type = g->builtin_types.entry_usize; | |
| 726 | uint64_t len_debug_size_in_bits = 8*LLVMStoreSizeOfType(g->target_data_ref, usize_type->type_ref); | |
| 727 | uint64_t len_debug_align_in_bits = 8*LLVMABISizeOfType(g->target_data_ref, usize_type->type_ref); | |
| 728 | uint64_t len_offset_in_bits = 8*LLVMOffsetOfElement(g->target_data_ref, entry->type_ref, 1); | |
| 729 | ||
| 730 | uint64_t debug_size_in_bits = 8*LLVMStoreSizeOfType(g->target_data_ref, entry->type_ref); | |
| 731 | uint64_t debug_align_in_bits = 8*LLVMABISizeOfType(g->target_data_ref, entry->type_ref); | |
| 732 | ||
| 733 | ZigLLVMDIType *di_element_types[] = { | |
| 734 | ZigLLVMCreateDebugMemberType(g->dbuilder, ZigLLVMTypeToScope(entry->di_type), | |
| 735 | "ptr", di_file, line, | |
| 736 | ptr_debug_size_in_bits, | |
| 737 | ptr_debug_align_in_bits, | |
| 738 | ptr_offset_in_bits, | |
| 739 | 0, pointer_type->di_type), | |
| 740 | ZigLLVMCreateDebugMemberType(g->dbuilder, ZigLLVMTypeToScope(entry->di_type), | |
| 741 | "len", di_file, line, | |
| 742 | len_debug_size_in_bits, | |
| 743 | len_debug_align_in_bits, | |
| 744 | len_offset_in_bits, | |
| 745 | 0, usize_type->di_type), | |
| 746 | }; | |
| 747 | ZigLLVMDIType *replacement_di_type = ZigLLVMCreateDebugStructType(g->dbuilder, | |
| 748 | compile_unit_scope, | |
| 749 | buf_ptr(&entry->name), | |
| 750 | di_file, line, debug_size_in_bits, debug_align_in_bits, 0, | |
| 751 | nullptr, di_element_types, 2, 0, nullptr, ""); | |
| 752 | ||
| 753 | ZigLLVMReplaceTemporary(g->dbuilder, entry->di_type, replacement_di_type); | |
| 754 | entry->di_type = replacement_di_type; | |
| 755 | } | |
| 756 | } | |
| 713 | uint64_t debug_size_in_bits = 8*LLVMStoreSizeOfType(g->target_data_ref, entry->type_ref); | |
| 714 | uint64_t debug_align_in_bits = 8*LLVMABIAlignmentOfType(g->target_data_ref, entry->type_ref); | |
| 757 | 715 | |
| 716 | ZigLLVMDIType *di_element_types[] = { | |
| 717 | ZigLLVMCreateDebugMemberType(g->dbuilder, ZigLLVMTypeToScope(entry->di_type), | |
| 718 | "len", di_file, line, | |
| 719 | len_debug_size_in_bits, | |
| 720 | len_debug_align_in_bits, | |
| 721 | len_offset_in_bits, | |
| 722 | 0, usize_type->di_type), | |
| 723 | }; | |
| 724 | ZigLLVMDIType *replacement_di_type = ZigLLVMCreateDebugStructType(g->dbuilder, | |
| 725 | compile_unit_scope, | |
| 726 | buf_ptr(&entry->name), | |
| 727 | di_file, line, debug_size_in_bits, debug_align_in_bits, 0, | |
| 728 | nullptr, di_element_types, 1, 0, nullptr, ""); | |
| 758 | 729 | |
| 759 | entry->data.structure.complete = true; | |
| 760 | entry->data.structure.zero_bits_known = true; | |
| 730 | ZigLLVMReplaceTemporary(g->dbuilder, entry->di_type, replacement_di_type); | |
| 731 | entry->di_type = replacement_di_type; | |
| 761 | 732 | |
| 762 | *parent_pointer = entry; | |
| 763 | return entry; | |
| 733 | entry->data.structure.abi_alignment = LLVMABIAlignmentOfType(g->target_data_ref, usize_type->type_ref); | |
| 734 | } else { | |
| 735 | unsigned element_count = 2; | |
| 736 | LLVMTypeRef element_types[] = { | |
| 737 | ptr_type->type_ref, | |
| 738 | g->builtin_types.entry_usize->type_ref, | |
| 739 | }; | |
| 740 | LLVMStructSetBody(entry->type_ref, element_types, element_count, false); | |
| 741 | ||
| 742 | ||
| 743 | uint64_t ptr_debug_size_in_bits = 8*LLVMStoreSizeOfType(g->target_data_ref, ptr_type->type_ref); | |
| 744 | uint64_t ptr_debug_align_in_bits = 8*LLVMABIAlignmentOfType(g->target_data_ref, ptr_type->type_ref); | |
| 745 | uint64_t ptr_offset_in_bits = 8*LLVMOffsetOfElement(g->target_data_ref, entry->type_ref, 0); | |
| 746 | ||
| 747 | TypeTableEntry *usize_type = g->builtin_types.entry_usize; | |
| 748 | uint64_t len_debug_size_in_bits = 8*LLVMStoreSizeOfType(g->target_data_ref, usize_type->type_ref); | |
| 749 | uint64_t len_debug_align_in_bits = 8*LLVMABIAlignmentOfType(g->target_data_ref, usize_type->type_ref); | |
| 750 | uint64_t len_offset_in_bits = 8*LLVMOffsetOfElement(g->target_data_ref, entry->type_ref, 1); | |
| 751 | ||
| 752 | uint64_t debug_size_in_bits = 8*LLVMStoreSizeOfType(g->target_data_ref, entry->type_ref); | |
| 753 | uint64_t debug_align_in_bits = 8*LLVMABIAlignmentOfType(g->target_data_ref, entry->type_ref); | |
| 754 | ||
| 755 | ZigLLVMDIType *di_element_types[] = { | |
| 756 | ZigLLVMCreateDebugMemberType(g->dbuilder, ZigLLVMTypeToScope(entry->di_type), | |
| 757 | "ptr", di_file, line, | |
| 758 | ptr_debug_size_in_bits, | |
| 759 | ptr_debug_align_in_bits, | |
| 760 | ptr_offset_in_bits, | |
| 761 | 0, ptr_type->di_type), | |
| 762 | ZigLLVMCreateDebugMemberType(g->dbuilder, ZigLLVMTypeToScope(entry->di_type), | |
| 763 | "len", di_file, line, | |
| 764 | len_debug_size_in_bits, | |
| 765 | len_debug_align_in_bits, | |
| 766 | len_offset_in_bits, | |
| 767 | 0, usize_type->di_type), | |
| 768 | }; | |
| 769 | ZigLLVMDIType *replacement_di_type = ZigLLVMCreateDebugStructType(g->dbuilder, | |
| 770 | compile_unit_scope, | |
| 771 | buf_ptr(&entry->name), | |
| 772 | di_file, line, debug_size_in_bits, debug_align_in_bits, 0, | |
| 773 | nullptr, di_element_types, 2, 0, nullptr, ""); | |
| 774 | ||
| 775 | ZigLLVMReplaceTemporary(g->dbuilder, entry->di_type, replacement_di_type); | |
| 776 | entry->di_type = replacement_di_type; | |
| 777 | ||
| 778 | entry->data.structure.abi_alignment = LLVMABIAlignmentOfType(g->target_data_ref, entry->type_ref); | |
| 779 | } | |
| 764 | 780 | } |
| 781 | ||
| 782 | ||
| 783 | entry->data.structure.complete = true; | |
| 784 | entry->data.structure.zero_bits_known = true; | |
| 785 | ||
| 786 | *parent_pointer = entry; | |
| 787 | return entry; | |
| 765 | 788 | } |
| 766 | 789 | |
| 767 | 790 | TypeTableEntry *get_opaque_type(CodeGen *g, Scope *scope, AstNode *source_node, const char *name) { |
| ... | ... | @@ -1273,26 +1296,24 @@ static void resolve_enum_type(CodeGen *g, TypeTableEntry *enum_type) { |
| 1273 | 1296 | continue; |
| 1274 | 1297 | |
| 1275 | 1298 | uint64_t store_size_in_bits = 8*LLVMStoreSizeOfType(g->target_data_ref, field_type->type_ref); |
| 1276 | uint64_t preferred_align_in_bits = 8*LLVMPreferredAlignmentOfType(g->target_data_ref, field_type->type_ref); | |
| 1299 | uint64_t abi_align_in_bits = 8*LLVMABIAlignmentOfType(g->target_data_ref, field_type->type_ref); | |
| 1277 | 1300 | |
| 1278 | 1301 | assert(store_size_in_bits > 0); |
| 1279 | assert(preferred_align_in_bits > 0); | |
| 1302 | assert(abi_align_in_bits > 0); | |
| 1280 | 1303 | |
| 1281 | 1304 | union_inner_di_types[type_enum_field->gen_index] = ZigLLVMCreateDebugMemberType(g->dbuilder, |
| 1282 | 1305 | ZigLLVMTypeToScope(enum_type->di_type), buf_ptr(type_enum_field->name), |
| 1283 | 1306 | import->di_file, (unsigned)(field_node->line + 1), |
| 1284 | 1307 | store_size_in_bits, |
| 1285 | preferred_align_in_bits, | |
| 1308 | abi_align_in_bits, | |
| 1286 | 1309 | 0, |
| 1287 | 1310 | 0, field_type->di_type); |
| 1288 | 1311 | |
| 1289 | 1312 | biggest_size_in_bits = max(biggest_size_in_bits, store_size_in_bits); |
| 1290 | 1313 | |
| 1291 | if (!most_aligned_union_member || | |
| 1292 | preferred_align_in_bits > biggest_align_in_bits) | |
| 1293 | { | |
| 1314 | if (!most_aligned_union_member || abi_align_in_bits > biggest_align_in_bits) { | |
| 1294 | 1315 | most_aligned_union_member = field_type; |
| 1295 | biggest_align_in_bits = preferred_align_in_bits; | |
| 1316 | biggest_align_in_bits = abi_align_in_bits; | |
| 1296 | 1317 | size_of_most_aligned_member_in_bits = store_size_in_bits; |
| 1297 | 1318 | } |
| 1298 | 1319 | } |
| ... | ... | @@ -1306,7 +1327,7 @@ static void resolve_enum_type(CodeGen *g, TypeTableEntry *enum_type) { |
| 1306 | 1327 | TypeTableEntry *tag_type_entry = create_enum_tag_type(g, enum_type, tag_int_type); |
| 1307 | 1328 | enum_type->data.enumeration.tag_type = tag_type_entry; |
| 1308 | 1329 | |
| 1309 | uint64_t align_of_tag_in_bits = 8*LLVMPreferredAlignmentOfType(g->target_data_ref, tag_int_type->type_ref); | |
| 1330 | uint64_t align_of_tag_in_bits = 8*LLVMABIAlignmentOfType(g->target_data_ref, tag_int_type->type_ref); | |
| 1310 | 1331 | |
| 1311 | 1332 | if (most_aligned_union_member) { |
| 1312 | 1333 | // create llvm type for union |
| ... | ... | @@ -1328,7 +1349,7 @@ static void resolve_enum_type(CodeGen *g, TypeTableEntry *enum_type) { |
| 1328 | 1349 | } |
| 1329 | 1350 | enum_type->data.enumeration.union_type_ref = union_type_ref; |
| 1330 | 1351 | |
| 1331 | assert(8*LLVMPreferredAlignmentOfType(g->target_data_ref, union_type_ref) >= biggest_align_in_bits); | |
| 1352 | assert(8*LLVMABIAlignmentOfType(g->target_data_ref, union_type_ref) >= biggest_align_in_bits); | |
| 1332 | 1353 | assert(8*LLVMStoreSizeOfType(g->target_data_ref, union_type_ref) >= biggest_size_in_bits); |
| 1333 | 1354 | |
| 1334 | 1355 | if (align_of_tag_in_bits >= biggest_align_in_bits) { |
| ... | ... | @@ -1347,7 +1368,7 @@ static void resolve_enum_type(CodeGen *g, TypeTableEntry *enum_type) { |
| 1347 | 1368 | |
| 1348 | 1369 | // create debug type for tag |
| 1349 | 1370 | uint64_t tag_debug_size_in_bits = 8*LLVMStoreSizeOfType(g->target_data_ref, tag_type_entry->type_ref); |
| 1350 | uint64_t tag_debug_align_in_bits = 8*LLVMPreferredAlignmentOfType(g->target_data_ref, tag_type_entry->type_ref); | |
| 1371 | uint64_t tag_debug_align_in_bits = 8*LLVMABIAlignmentOfType(g->target_data_ref, tag_type_entry->type_ref); | |
| 1351 | 1372 | ZigLLVMDIType *tag_di_type = ZigLLVMCreateDebugEnumerationType(g->dbuilder, |
| 1352 | 1373 | ZigLLVMTypeToScope(enum_type->di_type), "AnonEnum", |
| 1353 | 1374 | import->di_file, (unsigned)(decl_node->line + 1), |
| ... | ... | @@ -1405,7 +1426,7 @@ static void resolve_enum_type(CodeGen *g, TypeTableEntry *enum_type) { |
| 1405 | 1426 | |
| 1406 | 1427 | // create debug type for tag |
| 1407 | 1428 | uint64_t tag_debug_size_in_bits = 8*LLVMStoreSizeOfType(g->target_data_ref, tag_type_entry->type_ref); |
| 1408 | uint64_t tag_debug_align_in_bits = 8*LLVMPreferredAlignmentOfType(g->target_data_ref, tag_type_entry->type_ref); | |
| 1429 | uint64_t tag_debug_align_in_bits = 8*LLVMABIAlignmentOfType(g->target_data_ref, tag_type_entry->type_ref); | |
| 1409 | 1430 | ZigLLVMDIType *tag_di_type = ZigLLVMCreateDebugEnumerationType(g->dbuilder, |
| 1410 | 1431 | ZigLLVMFileToScope(import->di_file), buf_ptr(&enum_type->name), |
| 1411 | 1432 | import->di_file, (unsigned)(decl_node->line + 1), |
| ... | ... | @@ -1497,7 +1518,7 @@ TypeTableEntry *get_struct_type(CodeGen *g, const char *type_name, const char *f |
| 1497 | 1518 | TypeStructField *type_struct_field = &struct_type->data.structure.fields[i]; |
| 1498 | 1519 | TypeTableEntry *field_type = type_struct_field->type_entry; |
| 1499 | 1520 | uint64_t debug_size_in_bits = 8*LLVMStoreSizeOfType(g->target_data_ref, field_type->type_ref); |
| 1500 | uint64_t debug_align_in_bits = 8*LLVMABISizeOfType(g->target_data_ref, field_type->type_ref); | |
| 1521 | uint64_t debug_align_in_bits = 8*LLVMABIAlignmentOfType(g->target_data_ref, field_type->type_ref); | |
| 1501 | 1522 | uint64_t debug_offset_in_bits = 8*LLVMOffsetOfElement(g->target_data_ref, struct_type->type_ref, i); |
| 1502 | 1523 | di_element_types[i] = ZigLLVMCreateDebugMemberType(g->dbuilder, |
| 1503 | 1524 | ZigLLVMTypeToScope(struct_type->di_type), buf_ptr(type_struct_field->name), |
| ... | ... | @@ -1522,6 +1543,7 @@ TypeTableEntry *get_struct_type(CodeGen *g, const char *type_name, const char *f |
| 1522 | 1543 | |
| 1523 | 1544 | ZigLLVMReplaceTemporary(g->dbuilder, struct_type->di_type, replacement_di_type); |
| 1524 | 1545 | struct_type->di_type = replacement_di_type; |
| 1546 | struct_type->data.structure.abi_alignment = LLVMABIAlignmentOfType(g->target_data_ref, struct_type->type_ref); | |
| 1525 | 1547 | |
| 1526 | 1548 | return struct_type; |
| 1527 | 1549 | } |
| ... | ... | @@ -1663,6 +1685,10 @@ static void resolve_struct_type(CodeGen *g, TypeTableEntry *struct_type) { |
| 1663 | 1685 | struct_type->data.structure.gen_field_count = (uint32_t)gen_field_count; |
| 1664 | 1686 | |
| 1665 | 1687 | LLVMStructSetBody(struct_type->type_ref, element_types, (unsigned)gen_field_count, packed); |
| 1688 | ||
| 1689 | // if you hit this assert then probably this type or a related type didn't | |
| 1690 | // get ensure_complete_type called on it before using it with something that | |
| 1691 | // requires a complete type | |
| 1666 | 1692 | assert(LLVMStoreSizeOfType(g->target_data_ref, struct_type->type_ref) > 0); |
| 1667 | 1693 | |
| 1668 | 1694 | ZigLLVMDIType **di_element_types = allocate<ZigLLVMDIType*>(debug_field_count); |
| ... | ... | @@ -1760,6 +1786,8 @@ static void resolve_enum_zero_bits(CodeGen *g, TypeTableEntry *enum_type) { |
| 1760 | 1786 | enum_type->data.enumeration.src_field_count = field_count; |
| 1761 | 1787 | enum_type->data.enumeration.fields = allocate<TypeEnumField>(field_count); |
| 1762 | 1788 | |
| 1789 | uint32_t biggest_align_bytes = 0; | |
| 1790 | ||
| 1763 | 1791 | Scope *scope = &enum_type->data.enumeration.decls_scope->base; |
| 1764 | 1792 | |
| 1765 | 1793 | uint32_t gen_field_index = 0; |
| ... | ... | @@ -1782,12 +1810,22 @@ static void resolve_enum_zero_bits(CodeGen *g, TypeTableEntry *enum_type) { |
| 1782 | 1810 | |
| 1783 | 1811 | type_enum_field->gen_index = gen_field_index; |
| 1784 | 1812 | gen_field_index += 1; |
| 1813 | ||
| 1814 | uint32_t field_align_bytes = get_abi_alignment(g, field_type); | |
| 1815 | if (field_align_bytes > biggest_align_bytes) { | |
| 1816 | biggest_align_bytes = field_align_bytes; | |
| 1817 | } | |
| 1785 | 1818 | } |
| 1786 | 1819 | |
| 1787 | 1820 | enum_type->data.enumeration.zero_bits_loop_flag = false; |
| 1788 | 1821 | enum_type->data.enumeration.gen_field_count = gen_field_index; |
| 1789 | 1822 | enum_type->zero_bits = (gen_field_index == 0 && field_count < 2); |
| 1790 | 1823 | enum_type->data.enumeration.zero_bits_known = true; |
| 1824 | ||
| 1825 | // also compute abi_alignment | |
| 1826 | TypeTableEntry *tag_int_type = get_smallest_unsigned_int_type(g, field_count); | |
| 1827 | uint32_t align_of_tag_in_bytes = LLVMABIAlignmentOfType(g->target_data_ref, tag_int_type->type_ref); | |
| 1828 | enum_type->data.enumeration.abi_alignment = max(align_of_tag_in_bytes, biggest_align_bytes); | |
| 1791 | 1829 | } |
| 1792 | 1830 | |
| 1793 | 1831 | static void resolve_struct_zero_bits(CodeGen *g, TypeTableEntry *struct_type) { |
| ... | ... | @@ -1797,7 +1835,19 @@ static void resolve_struct_zero_bits(CodeGen *g, TypeTableEntry *struct_type) { |
| 1797 | 1835 | return; |
| 1798 | 1836 | |
| 1799 | 1837 | if (struct_type->data.structure.zero_bits_loop_flag) { |
| 1838 | // If we get here it's due to recursion. From this we conclude that the struct is | |
| 1839 | // not zero bits, and if abi_alignment == 0 we further conclude that the first field | |
| 1840 | // is a pointer to this very struct, or a function pointer with parameters that | |
| 1841 | // reference such a type. | |
| 1800 | 1842 | struct_type->data.structure.zero_bits_known = true; |
| 1843 | if (struct_type->data.structure.abi_alignment == 0) { | |
| 1844 | if (struct_type->data.structure.layout == ContainerLayoutPacked) { | |
| 1845 | struct_type->data.structure.abi_alignment = 1; | |
| 1846 | } else { | |
| 1847 | struct_type->data.structure.abi_alignment = LLVMABIAlignmentOfType(g->target_data_ref, | |
| 1848 | LLVMPointerType(LLVMInt8Type(), 0)); | |
| 1849 | } | |
| 1850 | } | |
| 1801 | 1851 | return; |
| 1802 | 1852 | } |
| 1803 | 1853 | |
| ... | ... | @@ -1833,6 +1883,17 @@ static void resolve_struct_zero_bits(CodeGen *g, TypeTableEntry *struct_type) { |
| 1833 | 1883 | if (!type_has_bits(field_type)) |
| 1834 | 1884 | continue; |
| 1835 | 1885 | |
| 1886 | if (gen_field_index == 0) { | |
| 1887 | if (struct_type->data.structure.layout == ContainerLayoutPacked) { | |
| 1888 | struct_type->data.structure.abi_alignment = 1; | |
| 1889 | } else { | |
| 1890 | // Alignment of structs is the alignment of the first field, for now. | |
| 1891 | // TODO change this when we re-order struct fields (issue #168) | |
| 1892 | struct_type->data.structure.abi_alignment = get_abi_alignment(g, field_type); | |
| 1893 | assert(struct_type->data.structure.abi_alignment != 0); | |
| 1894 | } | |
| 1895 | } | |
| 1896 | ||
| 1836 | 1897 | type_struct_field->gen_index = gen_field_index; |
| 1837 | 1898 | gen_field_index += 1; |
| 1838 | 1899 | } |
| ... | ... | @@ -1925,7 +1986,8 @@ static void typecheck_panic_fn(CodeGen *g, FnTableEntry *panic_fn) { |
| 1925 | 1986 | if (fn_type_id->param_count != 1) { |
| 1926 | 1987 | return wrong_panic_prototype(g, proto_node, fn_type); |
| 1927 | 1988 | } |
| 1928 | TypeTableEntry *const_u8_slice = get_slice_type(g, g->builtin_types.entry_u8, true); | |
| 1989 | TypeTableEntry *const_u8_ptr = get_pointer_to_type(g, g->builtin_types.entry_u8, true); | |
| 1990 | TypeTableEntry *const_u8_slice = get_slice_type(g, const_u8_ptr); | |
| 1929 | 1991 | if (fn_type_id->param_info[0].type != const_u8_slice) { |
| 1930 | 1992 | return wrong_panic_prototype(g, proto_node, fn_type); |
| 1931 | 1993 | } |
| ... | ... | @@ -1946,6 +2008,25 @@ TypeTableEntry *get_test_fn_type(CodeGen *g) { |
| 1946 | 2008 | return g->test_fn_type; |
| 1947 | 2009 | } |
| 1948 | 2010 | |
| 2011 | static bool analyze_const_align(CodeGen *g, Scope *scope, AstNode *node, uint32_t *result) { | |
| 2012 | IrInstruction *align_result = analyze_const_value(g, scope, node, get_align_amt_type(g), nullptr); | |
| 2013 | if (type_is_invalid(align_result->value.type)) | |
| 2014 | return false; | |
| 2015 | ||
| 2016 | uint32_t align_bytes = bigint_as_unsigned(&align_result->value.data.x_bigint); | |
| 2017 | if (align_bytes == 0) { | |
| 2018 | add_node_error(g, node, buf_sprintf("alignment must be >= 1")); | |
| 2019 | return false; | |
| 2020 | } | |
| 2021 | if (!is_power_of_2(align_bytes)) { | |
| 2022 | add_node_error(g, node, buf_sprintf("alignment value %" PRIu32 " is not a power of 2", align_bytes)); | |
| 2023 | return false; | |
| 2024 | } | |
| 2025 | ||
| 2026 | *result = align_bytes; | |
| 2027 | return true; | |
| 2028 | } | |
| 2029 | ||
| 1949 | 2030 | static void resolve_decl_fn(CodeGen *g, TldFn *tld_fn) { |
| 1950 | 2031 | ImportTableEntry *import = tld_fn->base.import; |
| 1951 | 2032 | AstNode *source_node = tld_fn->base.source_node; |
| ... | ... | @@ -1982,6 +2063,16 @@ static void resolve_decl_fn(CodeGen *g, TldFn *tld_fn) { |
| 1982 | 2063 | return; |
| 1983 | 2064 | } |
| 1984 | 2065 | |
| 2066 | if (fn_proto->align_expr != nullptr) { | |
| 2067 | if (!analyze_const_align(g, tld_fn->base.parent_scope, fn_proto->align_expr, | |
| 2068 | &fn_table_entry->align_bytes)) | |
| 2069 | { | |
| 2070 | fn_table_entry->type_entry = g->builtin_types.entry_invalid; | |
| 2071 | tld_fn->base.resolution = TldResolutionInvalid; | |
| 2072 | return; | |
| 2073 | } | |
| 2074 | } | |
| 2075 | ||
| 1985 | 2076 | if (!fn_table_entry->type_entry->data.fn.is_generic) { |
| 1986 | 2077 | g->fn_protos.append(fn_table_entry); |
| 1987 | 2078 | |
| ... | ... | @@ -2149,6 +2240,7 @@ void update_compile_var(CodeGen *g, Buf *name, ConstExprValue *value) { |
| 2149 | 2240 | assert(tld->id == TldIdVar); |
| 2150 | 2241 | TldVar *tld_var = (TldVar *)tld; |
| 2151 | 2242 | tld_var->var->value = value; |
| 2243 | tld_var->var->align_bytes = get_abi_alignment(g, value->type); | |
| 2152 | 2244 | } |
| 2153 | 2245 | |
| 2154 | 2246 | void scan_decls(CodeGen *g, ScopeDecls *decls_scope, AstNode *node) { |
| ... | ... | @@ -2236,6 +2328,7 @@ void scan_decls(CodeGen *g, ScopeDecls *decls_scope, AstNode *node) { |
| 2236 | 2328 | case NodeTypeThisLiteral: |
| 2237 | 2329 | case NodeTypeSymbol: |
| 2238 | 2330 | case NodeTypePrefixOpExpr: |
| 2331 | case NodeTypeAddrOfExpr: | |
| 2239 | 2332 | case NodeTypeIfBoolExpr: |
| 2240 | 2333 | case NodeTypeWhileExpr: |
| 2241 | 2334 | case NodeTypeForExpr: |
| ... | ... | @@ -2331,6 +2424,7 @@ VariableTableEntry *add_variable(CodeGen *g, AstNode *source_node, Scope *parent |
| 2331 | 2424 | variable_entry->shadowable = false; |
| 2332 | 2425 | variable_entry->mem_slot_index = SIZE_MAX; |
| 2333 | 2426 | variable_entry->src_arg_index = SIZE_MAX; |
| 2427 | variable_entry->align_bytes = get_abi_alignment(g, value->type); | |
| 2334 | 2428 | |
| 2335 | 2429 | assert(name); |
| 2336 | 2430 | |
| ... | ... | @@ -2389,7 +2483,8 @@ VariableTableEntry *add_variable(CodeGen *g, AstNode *source_node, Scope *parent |
| 2389 | 2483 | } |
| 2390 | 2484 | |
| 2391 | 2485 | static void resolve_decl_var(CodeGen *g, TldVar *tld_var) { |
| 2392 | AstNodeVariableDeclaration *var_decl = &tld_var->base.source_node->data.variable_declaration; | |
| 2486 | AstNode *source_node = tld_var->base.source_node; | |
| 2487 | AstNodeVariableDeclaration *var_decl = &source_node->data.variable_declaration; | |
| 2393 | 2488 | |
| 2394 | 2489 | bool is_const = var_decl->is_const; |
| 2395 | 2490 | bool is_export = (tld_var->base.visib_mod == VisibModExport); |
| ... | ... | @@ -2401,8 +2496,6 @@ static void resolve_decl_var(CodeGen *g, TldVar *tld_var) { |
| 2401 | 2496 | explicit_type = validate_var_type(g, var_decl->type, proposed_type); |
| 2402 | 2497 | } |
| 2403 | 2498 | |
| 2404 | AstNode *source_node = tld_var->base.source_node; | |
| 2405 | ||
| 2406 | 2499 | if (is_export && is_extern) { |
| 2407 | 2500 | add_node_error(g, source_node, buf_sprintf("variable is both export and extern")); |
| 2408 | 2501 | } |
| ... | ... | @@ -2458,6 +2551,12 @@ static void resolve_decl_var(CodeGen *g, TldVar *tld_var) { |
| 2458 | 2551 | is_const, init_val, &tld_var->base); |
| 2459 | 2552 | tld_var->var->linkage = linkage; |
| 2460 | 2553 | |
| 2554 | if (var_decl->align_expr != nullptr) { | |
| 2555 | if (!analyze_const_align(g, tld_var->base.parent_scope, var_decl->align_expr, &tld_var->var->align_bytes)) { | |
| 2556 | tld_var->var->value->type = g->builtin_types.entry_invalid; | |
| 2557 | } | |
| 2558 | } | |
| 2559 | ||
| 2461 | 2560 | g->global_vars.append(tld_var); |
| 2462 | 2561 | } |
| 2463 | 2562 | |
| ... | ... | @@ -3129,26 +3228,28 @@ void semantic_analyze(CodeGen *g) { |
| 3129 | 3228 | |
| 3130 | 3229 | TypeTableEntry **get_int_type_ptr(CodeGen *g, bool is_signed, uint32_t size_in_bits) { |
| 3131 | 3230 | size_t index; |
| 3132 | if (size_in_bits == 3) { | |
| 3231 | if (size_in_bits == 2) { | |
| 3133 | 3232 | index = 0; |
| 3134 | } else if (size_in_bits == 4) { | |
| 3233 | } else if (size_in_bits == 3) { | |
| 3135 | 3234 | index = 1; |
| 3136 | } else if (size_in_bits == 5) { | |
| 3235 | } else if (size_in_bits == 4) { | |
| 3137 | 3236 | index = 2; |
| 3138 | } else if (size_in_bits == 6) { | |
| 3237 | } else if (size_in_bits == 5) { | |
| 3139 | 3238 | index = 3; |
| 3140 | } else if (size_in_bits == 7) { | |
| 3239 | } else if (size_in_bits == 6) { | |
| 3141 | 3240 | index = 4; |
| 3142 | } else if (size_in_bits == 8) { | |
| 3241 | } else if (size_in_bits == 7) { | |
| 3143 | 3242 | index = 5; |
| 3144 | } else if (size_in_bits == 16) { | |
| 3243 | } else if (size_in_bits == 8) { | |
| 3145 | 3244 | index = 6; |
| 3146 | } else if (size_in_bits == 32) { | |
| 3245 | } else if (size_in_bits == 16) { | |
| 3147 | 3246 | index = 7; |
| 3148 | } else if (size_in_bits == 64) { | |
| 3247 | } else if (size_in_bits == 32) { | |
| 3149 | 3248 | index = 8; |
| 3150 | } else if (size_in_bits == 128) { | |
| 3249 | } else if (size_in_bits == 64) { | |
| 3151 | 3250 | index = 9; |
| 3251 | } else if (size_in_bits == 128) { | |
| 3252 | index = 10; | |
| 3152 | 3253 | } else { |
| 3153 | 3254 | return nullptr; |
| 3154 | 3255 | } |
| ... | ... | @@ -3723,8 +3824,10 @@ void init_const_slice(CodeGen *g, ConstExprValue *const_val, ConstExprValue *arr |
| 3723 | 3824 | { |
| 3724 | 3825 | assert(array_val->type->id == TypeTableEntryIdArray); |
| 3725 | 3826 | |
| 3827 | TypeTableEntry *ptr_type = get_pointer_to_type(g, array_val->type->data.array.child_type, is_const); | |
| 3828 | ||
| 3726 | 3829 | const_val->special = ConstValSpecialStatic; |
| 3727 | const_val->type = get_slice_type(g, array_val->type->data.array.child_type, is_const); | |
| 3830 | const_val->type = get_slice_type(g, ptr_type); | |
| 3728 | 3831 | const_val->data.x_struct.fields = create_const_vals(2); |
| 3729 | 3832 | |
| 3730 | 3833 | init_const_ptr_array(g, &const_val->data.x_struct.fields[slice_ptr_index], array_val, start, is_const); |
| ... | ... | @@ -4342,14 +4445,15 @@ uint32_t type_id_hash(TypeId x) { |
| 4342 | 4445 | return hash_ptr(x.data.pointer.child_type) + |
| 4343 | 4446 | (x.data.pointer.is_const ? (uint32_t)2749109194 : (uint32_t)4047371087) + |
| 4344 | 4447 | (x.data.pointer.is_volatile ? (uint32_t)536730450 : (uint32_t)1685612214) + |
| 4345 | (((uint32_t)x.data.pointer.bit_offset) * (uint32_t)2639019452) + | |
| 4346 | (((uint32_t)x.data.pointer.unaligned_bit_count) * (uint32_t)529908881); | |
| 4448 | (((uint32_t)x.data.pointer.alignment) ^ (uint32_t)0x777fbe0e) + | |
| 4449 | (((uint32_t)x.data.pointer.bit_offset) ^ (uint32_t)2639019452) + | |
| 4450 | (((uint32_t)x.data.pointer.unaligned_bit_count) ^ (uint32_t)529908881); | |
| 4347 | 4451 | case TypeTableEntryIdArray: |
| 4348 | 4452 | return hash_ptr(x.data.array.child_type) + |
| 4349 | ((uint32_t)x.data.array.size * (uint32_t)2122979968); | |
| 4453 | ((uint32_t)x.data.array.size ^ (uint32_t)2122979968); | |
| 4350 | 4454 | case TypeTableEntryIdInt: |
| 4351 | 4455 | return (x.data.integer.is_signed ? (uint32_t)2652528194 : (uint32_t)163929201) + |
| 4352 | (((uint32_t)x.data.integer.bit_count) * (uint32_t)2998081557); | |
| 4456 | (((uint32_t)x.data.integer.bit_count) ^ (uint32_t)2998081557); | |
| 4353 | 4457 | } |
| 4354 | 4458 | zig_unreachable(); |
| 4355 | 4459 | } |
| ... | ... | @@ -4387,6 +4491,7 @@ bool type_id_eql(TypeId a, TypeId b) { |
| 4387 | 4491 | return a.data.pointer.child_type == b.data.pointer.child_type && |
| 4388 | 4492 | a.data.pointer.is_const == b.data.pointer.is_const && |
| 4389 | 4493 | a.data.pointer.is_volatile == b.data.pointer.is_volatile && |
| 4494 | a.data.pointer.alignment == b.data.pointer.alignment && | |
| 4390 | 4495 | a.data.pointer.bit_offset == b.data.pointer.bit_offset && |
| 4391 | 4496 | a.data.pointer.unaligned_bit_count == b.data.pointer.unaligned_bit_count; |
| 4392 | 4497 | case TypeTableEntryIdArray: |
| ... | ... | @@ -4692,3 +4797,30 @@ void add_link_lib_symbol(CodeGen *g, Buf *lib_name, Buf *symbol_name) { |
| 4692 | 4797 | } |
| 4693 | 4798 | link_lib->symbols.append(symbol_name); |
| 4694 | 4799 | } |
| 4800 | ||
| 4801 | uint32_t get_abi_alignment(CodeGen *g, TypeTableEntry *type_entry) { | |
| 4802 | type_ensure_zero_bits_known(g, type_entry); | |
| 4803 | if (type_entry->zero_bits) return 0; | |
| 4804 | ||
| 4805 | // We need to make this function work without requiring ensure_complete_type | |
| 4806 | // so that we can have structs with fields that are pointers to their own type. | |
| 4807 | if (type_entry->id == TypeTableEntryIdStruct) { | |
| 4808 | assert(type_entry->data.structure.abi_alignment != 0); | |
| 4809 | return type_entry->data.structure.abi_alignment; | |
| 4810 | } else if (type_entry->id == TypeTableEntryIdEnum) { | |
| 4811 | assert(type_entry->data.enumeration.abi_alignment != 0); | |
| 4812 | return type_entry->data.enumeration.abi_alignment; | |
| 4813 | } else if (type_entry->id == TypeTableEntryIdUnion) { | |
| 4814 | zig_panic("TODO"); | |
| 4815 | } else { | |
| 4816 | return LLVMABIAlignmentOfType(g->target_data_ref, type_entry->type_ref); | |
| 4817 | } | |
| 4818 | } | |
| 4819 | ||
| 4820 | TypeTableEntry *get_align_amt_type(CodeGen *g) { | |
| 4821 | if (g->align_amt_type == nullptr) { | |
| 4822 | // according to LLVM the maximum alignment is 1 << 29. | |
| 4823 | g->align_amt_type = get_int_type(g, false, 29); | |
| 4824 | } | |
| 4825 | return g->align_amt_type; | |
| 4826 | } |
src/analyze.hpp+5-2| ... | ... | @@ -16,7 +16,7 @@ ErrorMsg *add_error_note(CodeGen *g, ErrorMsg *parent_msg, AstNode *node, Buf *m |
| 16 | 16 | TypeTableEntry *new_type_table_entry(TypeTableEntryId id); |
| 17 | 17 | TypeTableEntry *get_pointer_to_type(CodeGen *g, TypeTableEntry *child_type, bool is_const); |
| 18 | 18 | TypeTableEntry *get_pointer_to_type_extra(CodeGen *g, TypeTableEntry *child_type, bool is_const, |
| 19 | bool is_volatile, uint32_t bit_offset, uint32_t unaligned_bit_count); | |
| 19 | bool is_volatile, uint32_t byte_alignment, uint32_t bit_offset, uint32_t unaligned_bit_count); | |
| 20 | 20 | uint64_t type_size(CodeGen *g, TypeTableEntry *type_entry); |
| 21 | 21 | uint64_t type_size_bits(CodeGen *g, TypeTableEntry *type_entry); |
| 22 | 22 | TypeTableEntry **get_int_type_ptr(CodeGen *g, bool is_signed, uint32_t size_in_bits); |
| ... | ... | @@ -26,7 +26,7 @@ TypeTableEntry *get_c_int_type(CodeGen *g, CIntType c_int_type); |
| 26 | 26 | TypeTableEntry *get_fn_type(CodeGen *g, FnTypeId *fn_type_id); |
| 27 | 27 | TypeTableEntry *get_maybe_type(CodeGen *g, TypeTableEntry *child_type); |
| 28 | 28 | TypeTableEntry *get_array_type(CodeGen *g, TypeTableEntry *child_type, uint64_t array_size); |
| 29 | TypeTableEntry *get_slice_type(CodeGen *g, TypeTableEntry *child_type, bool is_const); | |
| 29 | TypeTableEntry *get_slice_type(CodeGen *g, TypeTableEntry *ptr_type); | |
| 30 | 30 | TypeTableEntry *get_partial_container_type(CodeGen *g, Scope *scope, ContainerKind kind, |
| 31 | 31 | AstNode *decl_node, const char *name, ContainerLayout layout); |
| 32 | 32 | TypeTableEntry *get_smallest_unsigned_int_type(CodeGen *g, uint64_t x); |
| ... | ... | @@ -171,4 +171,7 @@ bool calling_convention_does_first_arg_return(CallingConvention cc); |
| 171 | 171 | LinkLib *add_link_lib(CodeGen *codegen, Buf *lib); |
| 172 | 172 | void add_link_lib_symbol(CodeGen *g, Buf *lib_name, Buf *symbol_name); |
| 173 | 173 | |
| 174 | uint32_t get_abi_alignment(CodeGen *g, TypeTableEntry *type_entry); | |
| 175 | TypeTableEntry *get_align_amt_type(CodeGen *g); | |
| 176 | ||
| 174 | 177 | #endif |
src/ast_render.cpp+34-4| ... | ... | @@ -65,10 +65,6 @@ static const char *prefix_op_str(PrefixOp prefix_op) { |
| 65 | 65 | case PrefixOpNegationWrap: return "-%"; |
| 66 | 66 | case PrefixOpBoolNot: return "!"; |
| 67 | 67 | case PrefixOpBinNot: return "~"; |
| 68 | case PrefixOpAddressOf: return "&"; | |
| 69 | case PrefixOpConstAddressOf: return "&const "; | |
| 70 | case PrefixOpVolatileAddressOf: return "&volatile "; | |
| 71 | case PrefixOpConstVolatileAddressOf: return "&const volatile "; | |
| 72 | 68 | case PrefixOpDereference: return "*"; |
| 73 | 69 | case PrefixOpMaybe: return "?"; |
| 74 | 70 | case PrefixOpError: return "%"; |
| ... | ... | @@ -192,6 +188,8 @@ static const char *node_type_str(NodeType node_type) { |
| 192 | 188 | return "Symbol"; |
| 193 | 189 | case NodeTypePrefixOpExpr: |
| 194 | 190 | return "PrefixOpExpr"; |
| 191 | case NodeTypeAddrOfExpr: | |
| 192 | return "AddrOfExpr"; | |
| 195 | 193 | case NodeTypeUse: |
| 196 | 194 | return "Use"; |
| 197 | 195 | case NodeTypeBoolLiteral: |
| ... | ... | @@ -583,6 +581,38 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) { |
| 583 | 581 | render_node_ungrouped(ar, node->data.prefix_op_expr.primary_expr); |
| 584 | 582 | break; |
| 585 | 583 | } |
| 584 | case NodeTypeAddrOfExpr: | |
| 585 | { | |
| 586 | fprintf(ar->f, "&"); | |
| 587 | if (node->data.addr_of_expr.align_expr != nullptr) { | |
| 588 | fprintf(ar->f, "align "); | |
| 589 | render_node_grouped(ar, node->data.addr_of_expr.align_expr); | |
| 590 | if (node->data.addr_of_expr.bit_offset_start != nullptr) { | |
| 591 | assert(node->data.addr_of_expr.bit_offset_end != nullptr); | |
| 592 | ||
| 593 | Buf offset_start_buf = BUF_INIT; | |
| 594 | buf_resize(&offset_start_buf, 0); | |
| 595 | bigint_append_buf(&offset_start_buf, node->data.addr_of_expr.bit_offset_start, 10); | |
| 596 | ||
| 597 | Buf offset_end_buf = BUF_INIT; | |
| 598 | buf_resize(&offset_end_buf, 0); | |
| 599 | bigint_append_buf(&offset_end_buf, node->data.addr_of_expr.bit_offset_end, 10); | |
| 600 | ||
| 601 | fprintf(ar->f, ":%s:%s ", buf_ptr(&offset_start_buf), buf_ptr(&offset_end_buf)); | |
| 602 | } else { | |
| 603 | fprintf(ar->f, " "); | |
| 604 | } | |
| 605 | } | |
| 606 | if (node->data.addr_of_expr.is_const) { | |
| 607 | fprintf(ar->f, "const "); | |
| 608 | } | |
| 609 | if (node->data.addr_of_expr.is_volatile) { | |
| 610 | fprintf(ar->f, "volatile "); | |
| 611 | } | |
| 612 | ||
| 613 | render_node_ungrouped(ar, node->data.addr_of_expr.op_expr); | |
| 614 | break; | |
| 615 | } | |
| 586 | 616 | case NodeTypeFnCallExpr: |
| 587 | 617 | { |
| 588 | 618 | if (node->data.fn_call_expr.is_builtin) { |
src/codegen.cpp+104-120| ... | ... | @@ -350,6 +350,12 @@ static LLVMCallConv get_llvm_cc(CodeGen *g, CallingConvention cc) { |
| 350 | 350 | zig_unreachable(); |
| 351 | 351 | } |
| 352 | 352 | |
| 353 | static uint32_t get_pref_fn_align(CodeGen *g, LLVMTypeRef fn_type_ref) { | |
| 354 | uint32_t pref_align = LLVMPreferredAlignmentOfType(g->target_data_ref, fn_type_ref); | |
| 355 | uint32_t abi_align = LLVMABIAlignmentOfType(g->target_data_ref, fn_type_ref); | |
| 356 | return (pref_align > abi_align) ? pref_align : abi_align; | |
| 357 | } | |
| 358 | ||
| 353 | 359 | static LLVMValueRef fn_llvm_value(CodeGen *g, FnTableEntry *fn_table_entry) { |
| 354 | 360 | if (fn_table_entry->llvm_value) |
| 355 | 361 | return fn_table_entry->llvm_value; |
| ... | ... | @@ -442,14 +448,14 @@ static LLVMValueRef fn_llvm_value(CodeGen *g, FnTableEntry *fn_table_entry) { |
| 442 | 448 | if (fn_table_entry->section_name) { |
| 443 | 449 | LLVMSetSection(fn_table_entry->llvm_value, buf_ptr(fn_table_entry->section_name)); |
| 444 | 450 | } |
| 445 | if (fn_table_entry->alignment) { | |
| 446 | LLVMSetAlignment(fn_table_entry->llvm_value, (unsigned)fn_table_entry->alignment); | |
| 447 | } else if (external_linkage) { | |
| 451 | if (fn_table_entry->align_bytes > 0) { | |
| 452 | LLVMSetAlignment(fn_table_entry->llvm_value, (unsigned)fn_table_entry->align_bytes); | |
| 453 | } else if (fn_table_entry->type_entry->data.fn.fn_type_id.cc == CallingConventionUnspecified) { | |
| 448 | 454 | LLVMSetAlignment(fn_table_entry->llvm_value, |
| 449 | LLVMABIAlignmentOfType(g->target_data_ref, fn_table_entry->type_entry->data.fn.raw_type_ref)); | |
| 455 | get_pref_fn_align(g, fn_table_entry->type_entry->data.fn.raw_type_ref)); | |
| 450 | 456 | } else { |
| 451 | 457 | LLVMSetAlignment(fn_table_entry->llvm_value, |
| 452 | LLVMPreferredAlignmentOfType(g->target_data_ref, fn_table_entry->type_entry->data.fn.raw_type_ref)); | |
| 458 | LLVMABIAlignmentOfType(g->target_data_ref, fn_table_entry->type_entry->data.fn.raw_type_ref)); | |
| 453 | 459 | } |
| 454 | 460 | |
| 455 | 461 | return fn_table_entry->llvm_value; |
| ... | ... | @@ -604,13 +610,15 @@ static LLVMValueRef get_floor_ceil_fn(CodeGen *g, TypeTableEntry *type_entry, Zi |
| 604 | 610 | return fn_val; |
| 605 | 611 | } |
| 606 | 612 | |
| 607 | static LLVMValueRef get_handle_value(CodeGen *g, LLVMValueRef ptr, TypeTableEntry *type, bool is_volatile) { | |
| 613 | static LLVMValueRef get_handle_value(CodeGen *g, LLVMValueRef ptr, TypeTableEntry *type, TypeTableEntry *ptr_type) { | |
| 608 | 614 | if (type_has_bits(type)) { |
| 609 | 615 | if (handle_is_ptr(type)) { |
| 610 | 616 | return ptr; |
| 611 | 617 | } else { |
| 618 | assert(ptr_type->id == TypeTableEntryIdPointer); | |
| 612 | 619 | LLVMValueRef result = LLVMBuildLoad(g->builder, ptr, ""); |
| 613 | LLVMSetVolatile(result, is_volatile); | |
| 620 | LLVMSetVolatile(result, ptr_type->data.pointer.is_volatile); | |
| 621 | LLVMSetAlignment(result, ptr_type->data.pointer.alignment); | |
| 614 | 622 | return result; |
| 615 | 623 | } |
| 616 | 624 | } else { |
| ... | ... | @@ -657,34 +665,6 @@ static bool ir_want_debug_safety(CodeGen *g, IrInstruction *instruction) { |
| 657 | 665 | return true; |
| 658 | 666 | } |
| 659 | 667 | |
| 660 | static bool is_array_of_at_least_n_bytes(CodeGen *g, TypeTableEntry *type_entry, uint32_t n) { | |
| 661 | if (type_entry->id != TypeTableEntryIdArray) | |
| 662 | return false; | |
| 663 | ||
| 664 | TypeTableEntry *child_type = type_entry->data.array.child_type; | |
| 665 | if (child_type->id != TypeTableEntryIdInt) | |
| 666 | return false; | |
| 667 | ||
| 668 | if (child_type != g->builtin_types.entry_u8) | |
| 669 | return false; | |
| 670 | ||
| 671 | if (type_entry->data.array.len < n) | |
| 672 | return false; | |
| 673 | ||
| 674 | return true; | |
| 675 | } | |
| 676 | ||
| 677 | static uint32_t get_type_alignment(CodeGen *g, TypeTableEntry *type_entry) { | |
| 678 | uint32_t alignment = ZigLLVMGetPrefTypeAlignment(g->target_data_ref, type_entry->type_ref); | |
| 679 | uint32_t dbl_ptr_bytes = g->pointer_size_bytes * 2; | |
| 680 | if (is_array_of_at_least_n_bytes(g, type_entry, dbl_ptr_bytes)) { | |
| 681 | return (alignment < dbl_ptr_bytes) ? dbl_ptr_bytes : alignment; | |
| 682 | } else { | |
| 683 | return alignment; | |
| 684 | } | |
| 685 | } | |
| 686 | ||
| 687 | ||
| 688 | 668 | static Buf *panic_msg_buf(PanicMsgId msg_id) { |
| 689 | 669 | switch (msg_id) { |
| 690 | 670 | case PanicMsgIdCount: |
| ... | ... | @@ -745,7 +725,8 @@ static void gen_panic_raw(CodeGen *g, LLVMValueRef msg_ptr, LLVMValueRef msg_len |
| 745 | 725 | } |
| 746 | 726 | |
| 747 | 727 | static void gen_panic(CodeGen *g, LLVMValueRef msg_arg) { |
| 748 | TypeTableEntry *str_type = get_slice_type(g, g->builtin_types.entry_u8, true); | |
| 728 | TypeTableEntry *ptr_type = get_pointer_to_type(g, g->builtin_types.entry_u8, true); | |
| 729 | TypeTableEntry *str_type = get_slice_type(g, ptr_type); | |
| 749 | 730 | size_t ptr_index = str_type->data.structure.fields[slice_ptr_index].gen_index; |
| 750 | 731 | size_t len_index = str_type->data.structure.fields[slice_len_index].gen_index; |
| 751 | 732 | LLVMValueRef ptr_ptr = LLVMBuildStructGEP(g->builder, msg_arg, (unsigned)ptr_index, ""); |
| ... | ... | @@ -806,7 +787,7 @@ static LLVMValueRef get_safety_crash_err_fn(CodeGen *g) { |
| 806 | 787 | LLVMSetLinkage(global_value, LLVMInternalLinkage); |
| 807 | 788 | LLVMSetGlobalConstant(global_value, false); |
| 808 | 789 | LLVMSetUnnamedAddr(global_value, true); |
| 809 | LLVMSetAlignment(global_value, get_type_alignment(g, g->builtin_types.entry_u8)); | |
| 790 | LLVMSetAlignment(global_value, get_abi_alignment(g, g->builtin_types.entry_u8)); | |
| 810 | 791 | |
| 811 | 792 | TypeTableEntry *usize = g->builtin_types.entry_usize; |
| 812 | 793 | LLVMValueRef full_buf_ptr_indices[] = { |
| ... | ... | @@ -833,7 +814,7 @@ static LLVMValueRef get_safety_crash_err_fn(CodeGen *g) { |
| 833 | 814 | ZigLLVMAddFunctionAttr(fn_val, "no-frame-pointer-elim", "true"); |
| 834 | 815 | ZigLLVMAddFunctionAttr(fn_val, "no-frame-pointer-elim-non-leaf", nullptr); |
| 835 | 816 | } |
| 836 | LLVMSetAlignment(fn_val, LLVMPreferredAlignmentOfType(g->target_data_ref, fn_type_ref)); | |
| 817 | LLVMSetAlignment(fn_val, get_pref_fn_align(g, fn_type_ref)); | |
| 837 | 818 | |
| 838 | 819 | LLVMBasicBlockRef entry_block = LLVMAppendBasicBlock(fn_val, "Entry"); |
| 839 | 820 | LLVMBasicBlockRef prev_block = LLVMGetInsertBlock(g->builder); |
| ... | ... | @@ -1056,50 +1037,49 @@ static LLVMRealPredicate cmp_op_to_real_predicate(IrBinOp cmp_op) { |
| 1056 | 1037 | } |
| 1057 | 1038 | } |
| 1058 | 1039 | |
| 1059 | static LLVMValueRef gen_struct_memcpy(CodeGen *g, LLVMValueRef src, LLVMValueRef dest, | |
| 1060 | TypeTableEntry *type_entry) | |
| 1061 | { | |
| 1062 | assert(handle_is_ptr(type_entry)); | |
| 1063 | ||
| 1064 | assert(LLVMGetTypeKind(LLVMTypeOf(src)) == LLVMPointerTypeKind); | |
| 1065 | assert(LLVMGetTypeKind(LLVMTypeOf(dest)) == LLVMPointerTypeKind); | |
| 1066 | ||
| 1067 | LLVMTypeRef ptr_u8 = LLVMPointerType(LLVMInt8Type(), 0); | |
| 1068 | ||
| 1069 | LLVMValueRef src_ptr = LLVMBuildBitCast(g->builder, src, ptr_u8, ""); | |
| 1070 | LLVMValueRef dest_ptr = LLVMBuildBitCast(g->builder, dest, ptr_u8, ""); | |
| 1071 | ||
| 1072 | TypeTableEntry *usize = g->builtin_types.entry_usize; | |
| 1073 | uint64_t size_bytes = LLVMStoreSizeOfType(g->target_data_ref, type_entry->type_ref); | |
| 1074 | uint64_t align_bytes = get_type_alignment(g, type_entry); | |
| 1075 | assert(size_bytes > 0); | |
| 1076 | assert(align_bytes > 0); | |
| 1077 | ||
| 1078 | LLVMValueRef params[] = { | |
| 1079 | dest_ptr, // dest pointer | |
| 1080 | src_ptr, // source pointer | |
| 1081 | LLVMConstInt(usize->type_ref, size_bytes, false), | |
| 1082 | LLVMConstInt(LLVMInt32Type(), align_bytes, false), | |
| 1083 | LLVMConstNull(LLVMInt1Type()), // is volatile | |
| 1084 | }; | |
| 1085 | ||
| 1086 | return LLVMBuildCall(g->builder, get_memcpy_fn_val(g), params, 5, ""); | |
| 1087 | } | |
| 1088 | ||
| 1089 | 1040 | static LLVMValueRef gen_assign_raw(CodeGen *g, LLVMValueRef ptr, TypeTableEntry *ptr_type, |
| 1090 | 1041 | LLVMValueRef value) |
| 1091 | 1042 | { |
| 1043 | assert(ptr_type->id == TypeTableEntryIdPointer); | |
| 1092 | 1044 | TypeTableEntry *child_type = ptr_type->data.pointer.child_type; |
| 1093 | 1045 | |
| 1094 | 1046 | if (!type_has_bits(child_type)) |
| 1095 | 1047 | return nullptr; |
| 1096 | 1048 | |
| 1097 | if (handle_is_ptr(child_type)) | |
| 1098 | return gen_struct_memcpy(g, value, ptr, child_type); | |
| 1049 | if (handle_is_ptr(child_type)) { | |
| 1050 | assert(LLVMGetTypeKind(LLVMTypeOf(value)) == LLVMPointerTypeKind); | |
| 1051 | assert(LLVMGetTypeKind(LLVMTypeOf(ptr)) == LLVMPointerTypeKind); | |
| 1052 | ||
| 1053 | LLVMTypeRef ptr_u8 = LLVMPointerType(LLVMInt8Type(), 0); | |
| 1054 | ||
| 1055 | LLVMValueRef src_ptr = LLVMBuildBitCast(g->builder, value, ptr_u8, ""); | |
| 1056 | LLVMValueRef dest_ptr = LLVMBuildBitCast(g->builder, ptr, ptr_u8, ""); | |
| 1057 | ||
| 1058 | TypeTableEntry *usize = g->builtin_types.entry_usize; | |
| 1059 | uint64_t size_bytes = LLVMStoreSizeOfType(g->target_data_ref, child_type->type_ref); | |
| 1060 | uint64_t align_bytes = ptr_type->data.pointer.alignment; | |
| 1061 | assert(size_bytes > 0); | |
| 1062 | assert(align_bytes > 0); | |
| 1063 | ||
| 1064 | LLVMValueRef volatile_bit = ptr_type->data.pointer.is_volatile ? | |
| 1065 | LLVMConstAllOnes(LLVMInt1Type()) : LLVMConstNull(LLVMInt1Type()); | |
| 1066 | ||
| 1067 | LLVMValueRef params[] = { | |
| 1068 | dest_ptr, // dest pointer | |
| 1069 | src_ptr, // source pointer | |
| 1070 | LLVMConstInt(usize->type_ref, size_bytes, false), | |
| 1071 | LLVMConstInt(LLVMInt32Type(), align_bytes, false), | |
| 1072 | volatile_bit, | |
| 1073 | }; | |
| 1074 | ||
| 1075 | LLVMBuildCall(g->builder, get_memcpy_fn_val(g), params, 5, ""); | |
| 1076 | return nullptr; | |
| 1077 | } | |
| 1099 | 1078 | |
| 1100 | 1079 | uint32_t unaligned_bit_count = ptr_type->data.pointer.unaligned_bit_count; |
| 1101 | 1080 | if (unaligned_bit_count == 0) { |
| 1102 | 1081 | LLVMValueRef llvm_instruction = LLVMBuildStore(g->builder, value, ptr); |
| 1082 | LLVMSetAlignment(llvm_instruction, ptr_type->data.pointer.alignment); | |
| 1103 | 1083 | LLVMSetVolatile(llvm_instruction, ptr_type->data.pointer.is_volatile); |
| 1104 | 1084 | return nullptr; |
| 1105 | 1085 | } |
| ... | ... | @@ -1122,6 +1102,7 @@ static LLVMValueRef gen_assign_raw(CodeGen *g, LLVMValueRef ptr, TypeTableEntry |
| 1122 | 1102 | LLVMValueRef ored_value = LLVMBuildOr(g->builder, shifted_value, anded_containing_int, ""); |
| 1123 | 1103 | |
| 1124 | 1104 | LLVMValueRef llvm_instruction = LLVMBuildStore(g->builder, ored_value, ptr); |
| 1105 | LLVMSetAlignment(llvm_instruction, ptr_type->data.pointer.alignment); | |
| 1125 | 1106 | LLVMSetVolatile(llvm_instruction, ptr_type->data.pointer.is_volatile); |
| 1126 | 1107 | return nullptr; |
| 1127 | 1108 | } |
| ... | ... | @@ -2010,23 +1991,24 @@ static LLVMValueRef ir_render_decl_var(CodeGen *g, IrExecutable *executable, |
| 2010 | 1991 | |
| 2011 | 1992 | if (have_init_expr) { |
| 2012 | 1993 | assert(var->value->type == init_value->value.type); |
| 2013 | gen_assign_raw(g, var->value_ref, get_pointer_to_type(g, var->value->type, false), | |
| 2014 | ir_llvm_value(g, init_value)); | |
| 1994 | TypeTableEntry *var_ptr_type = get_pointer_to_type_extra(g, var->value->type, false, false, | |
| 1995 | var->align_bytes, 0, 0); | |
| 1996 | gen_assign_raw(g, var->value_ref, var_ptr_type, ir_llvm_value(g, init_value)); | |
| 2015 | 1997 | } else { |
| 2016 | bool ignore_uninit = false; | |
| 2017 | // handle runtime stack allocation | |
| 2018 | 1998 | bool want_safe = ir_want_debug_safety(g, &decl_var_instruction->base); |
| 2019 | if (!ignore_uninit && want_safe) { | |
| 1999 | if (want_safe) { | |
| 2020 | 2000 | TypeTableEntry *usize = g->builtin_types.entry_usize; |
| 2021 | 2001 | uint64_t size_bytes = LLVMStoreSizeOfType(g->target_data_ref, var->value->type->type_ref); |
| 2022 | uint64_t align_bytes = get_type_alignment(g, var->value->type); | |
| 2002 | assert(size_bytes > 0); | |
| 2003 | ||
| 2004 | assert(var->align_bytes > 0); | |
| 2023 | 2005 | |
| 2024 | 2006 | // memset uninitialized memory to 0xa |
| 2025 | 2007 | LLVMTypeRef ptr_u8 = LLVMPointerType(LLVMInt8Type(), 0); |
| 2026 | 2008 | LLVMValueRef fill_char = LLVMConstInt(LLVMInt8Type(), 0xaa, false); |
| 2027 | 2009 | LLVMValueRef dest_ptr = LLVMBuildBitCast(g->builder, var->value_ref, ptr_u8, ""); |
| 2028 | 2010 | LLVMValueRef byte_count = LLVMConstInt(usize->type_ref, size_bytes, false); |
| 2029 | LLVMValueRef align_in_bytes = LLVMConstInt(LLVMInt32Type(), align_bytes, false); | |
| 2011 | LLVMValueRef align_in_bytes = LLVMConstInt(LLVMInt32Type(), var->align_bytes, false); | |
| 2030 | 2012 | LLVMValueRef params[] = { |
| 2031 | 2013 | dest_ptr, |
| 2032 | 2014 | fill_char, |
| ... | ... | @@ -2051,15 +2033,14 @@ static LLVMValueRef ir_render_load_ptr(CodeGen *g, IrExecutable *executable, IrI |
| 2051 | 2033 | LLVMValueRef ptr = ir_llvm_value(g, instruction->ptr); |
| 2052 | 2034 | TypeTableEntry *ptr_type = instruction->ptr->value.type; |
| 2053 | 2035 | assert(ptr_type->id == TypeTableEntryIdPointer); |
| 2054 | bool is_volatile = ptr_type->data.pointer.is_volatile; | |
| 2055 | 2036 | |
| 2056 | 2037 | uint32_t unaligned_bit_count = ptr_type->data.pointer.unaligned_bit_count; |
| 2057 | 2038 | if (unaligned_bit_count == 0) |
| 2058 | return get_handle_value(g, ptr, child_type, is_volatile); | |
| 2039 | return get_handle_value(g, ptr, child_type, ptr_type); | |
| 2059 | 2040 | |
| 2060 | 2041 | assert(!handle_is_ptr(child_type)); |
| 2061 | 2042 | LLVMValueRef containing_int = LLVMBuildLoad(g->builder, ptr, ""); |
| 2062 | LLVMSetVolatile(containing_int, is_volatile); | |
| 2043 | LLVMSetVolatile(containing_int, ptr_type->data.pointer.is_volatile); | |
| 2063 | 2044 | |
| 2064 | 2045 | uint32_t bit_offset = ptr_type->data.pointer.bit_offset; |
| 2065 | 2046 | uint32_t host_bit_count = LLVMGetIntTypeWidth(LLVMTypeOf(containing_int)); |
| ... | ... | @@ -2097,9 +2078,8 @@ static LLVMValueRef ir_render_elem_ptr(CodeGen *g, IrExecutable *executable, IrI |
| 2097 | 2078 | LLVMValueRef array_ptr_ptr = ir_llvm_value(g, instruction->array_ptr); |
| 2098 | 2079 | TypeTableEntry *array_ptr_type = instruction->array_ptr->value.type; |
| 2099 | 2080 | assert(array_ptr_type->id == TypeTableEntryIdPointer); |
| 2100 | bool is_volatile = array_ptr_type->data.pointer.is_volatile; | |
| 2101 | 2081 | TypeTableEntry *array_type = array_ptr_type->data.pointer.child_type; |
| 2102 | LLVMValueRef array_ptr = get_handle_value(g, array_ptr_ptr, array_type, is_volatile); | |
| 2082 | LLVMValueRef array_ptr = get_handle_value(g, array_ptr_ptr, array_type, array_ptr_type); | |
| 2103 | 2083 | LLVMValueRef subscript_value = ir_llvm_value(g, instruction->elem_index); |
| 2104 | 2084 | assert(subscript_value); |
| 2105 | 2085 | |
| ... | ... | @@ -2427,12 +2407,11 @@ static LLVMValueRef ir_render_unwrap_maybe(CodeGen *g, IrExecutable *executable, |
| 2427 | 2407 | { |
| 2428 | 2408 | TypeTableEntry *ptr_type = instruction->value->value.type; |
| 2429 | 2409 | assert(ptr_type->id == TypeTableEntryIdPointer); |
| 2430 | bool is_volatile = ptr_type->data.pointer.is_volatile; | |
| 2431 | 2410 | TypeTableEntry *maybe_type = ptr_type->data.pointer.child_type; |
| 2432 | 2411 | assert(maybe_type->id == TypeTableEntryIdMaybe); |
| 2433 | 2412 | TypeTableEntry *child_type = maybe_type->data.maybe.child_type; |
| 2434 | 2413 | LLVMValueRef maybe_ptr = ir_llvm_value(g, instruction->value); |
| 2435 | LLVMValueRef maybe_handle = get_handle_value(g, maybe_ptr, maybe_type, is_volatile); | |
| 2414 | LLVMValueRef maybe_handle = get_handle_value(g, maybe_ptr, maybe_type, ptr_type); | |
| 2436 | 2415 | if (ir_want_debug_safety(g, &instruction->base) && instruction->safety_check_on) { |
| 2437 | 2416 | LLVMValueRef non_null_bit = gen_non_null_bit(g, maybe_type, maybe_handle); |
| 2438 | 2417 | LLVMBasicBlockRef ok_block = LLVMAppendBasicBlock(g->cur_fn_val, "UnwrapMaybeOk"); |
| ... | ... | @@ -2451,7 +2430,7 @@ static LLVMValueRef ir_render_unwrap_maybe(CodeGen *g, IrExecutable *executable, |
| 2451 | 2430 | if (maybe_is_ptr) { |
| 2452 | 2431 | return maybe_ptr; |
| 2453 | 2432 | } else { |
| 2454 | LLVMValueRef maybe_struct_ref = get_handle_value(g, maybe_ptr, maybe_type, is_volatile); | |
| 2433 | LLVMValueRef maybe_struct_ref = get_handle_value(g, maybe_ptr, maybe_type, ptr_type); | |
| 2455 | 2434 | return LLVMBuildStructGEP(g->builder, maybe_struct_ref, maybe_child_index, ""); |
| 2456 | 2435 | } |
| 2457 | 2436 | } |
| ... | ... | @@ -2694,11 +2673,13 @@ static LLVMValueRef ir_render_memset(CodeGen *g, IrExecutable *executable, IrIns |
| 2694 | 2673 | LLVMValueRef is_volatile = ptr_type->data.pointer.is_volatile ? |
| 2695 | 2674 | LLVMConstAllOnes(LLVMInt1Type()) : LLVMConstNull(LLVMInt1Type()); |
| 2696 | 2675 | |
| 2676 | LLVMValueRef align_val = LLVMConstInt(LLVMInt32Type(), ptr_type->data.pointer.alignment, false); | |
| 2677 | ||
| 2697 | 2678 | LLVMValueRef params[] = { |
| 2698 | dest_ptr_casted, // dest pointer | |
| 2699 | char_val, // source pointer | |
| 2700 | len_val, // byte count | |
| 2701 | LLVMConstInt(LLVMInt32Type(), 1, false), // align in bytes | |
| 2679 | dest_ptr_casted, | |
| 2680 | char_val, | |
| 2681 | len_val, | |
| 2682 | align_val, | |
| 2702 | 2683 | is_volatile, |
| 2703 | 2684 | }; |
| 2704 | 2685 | |
| ... | ... | @@ -2725,11 +2706,14 @@ static LLVMValueRef ir_render_memcpy(CodeGen *g, IrExecutable *executable, IrIns |
| 2725 | 2706 | LLVMValueRef is_volatile = (dest_ptr_type->data.pointer.is_volatile || src_ptr_type->data.pointer.is_volatile) ? |
| 2726 | 2707 | LLVMConstAllOnes(LLVMInt1Type()) : LLVMConstNull(LLVMInt1Type()); |
| 2727 | 2708 | |
| 2709 | uint32_t min_align_bytes = min(src_ptr_type->data.pointer.alignment, dest_ptr_type->data.pointer.alignment); | |
| 2710 | LLVMValueRef align_val = LLVMConstInt(LLVMInt32Type(), min_align_bytes, false); | |
| 2711 | ||
| 2728 | 2712 | LLVMValueRef params[] = { |
| 2729 | dest_ptr_casted, // dest pointer | |
| 2730 | src_ptr_casted, // source pointer | |
| 2731 | len_val, // byte count | |
| 2732 | LLVMConstInt(LLVMInt32Type(), 1, false), // align in bytes | |
| 2713 | dest_ptr_casted, | |
| 2714 | src_ptr_casted, | |
| 2715 | len_val, | |
| 2716 | align_val, | |
| 2733 | 2717 | is_volatile, |
| 2734 | 2718 | }; |
| 2735 | 2719 | |
| ... | ... | @@ -2743,9 +2727,8 @@ static LLVMValueRef ir_render_slice(CodeGen *g, IrExecutable *executable, IrInst |
| 2743 | 2727 | LLVMValueRef array_ptr_ptr = ir_llvm_value(g, instruction->ptr); |
| 2744 | 2728 | TypeTableEntry *array_ptr_type = instruction->ptr->value.type; |
| 2745 | 2729 | assert(array_ptr_type->id == TypeTableEntryIdPointer); |
| 2746 | bool is_volatile = array_ptr_type->data.pointer.is_volatile; | |
| 2747 | 2730 | TypeTableEntry *array_type = array_ptr_type->data.pointer.child_type; |
| 2748 | LLVMValueRef array_ptr = get_handle_value(g, array_ptr_ptr, array_type, is_volatile); | |
| 2731 | LLVMValueRef array_ptr = get_handle_value(g, array_ptr_ptr, array_type, array_ptr_type); | |
| 2749 | 2732 | |
| 2750 | 2733 | LLVMValueRef tmp_struct_ptr = instruction->tmp_ptr; |
| 2751 | 2734 | |
| ... | ... | @@ -2989,11 +2972,10 @@ static LLVMValueRef ir_render_test_err(CodeGen *g, IrExecutable *executable, IrI |
| 2989 | 2972 | static LLVMValueRef ir_render_unwrap_err_code(CodeGen *g, IrExecutable *executable, IrInstructionUnwrapErrCode *instruction) { |
| 2990 | 2973 | TypeTableEntry *ptr_type = instruction->value->value.type; |
| 2991 | 2974 | assert(ptr_type->id == TypeTableEntryIdPointer); |
| 2992 | bool is_volatile = ptr_type->data.pointer.is_volatile; | |
| 2993 | 2975 | TypeTableEntry *err_union_type = ptr_type->data.pointer.child_type; |
| 2994 | 2976 | TypeTableEntry *child_type = err_union_type->data.error.child_type; |
| 2995 | 2977 | LLVMValueRef err_union_ptr = ir_llvm_value(g, instruction->value); |
| 2996 | LLVMValueRef err_union_handle = get_handle_value(g, err_union_ptr, err_union_type, is_volatile); | |
| 2978 | LLVMValueRef err_union_handle = get_handle_value(g, err_union_ptr, err_union_type, ptr_type); | |
| 2997 | 2979 | |
| 2998 | 2980 | if (type_has_bits(child_type)) { |
| 2999 | 2981 | LLVMValueRef err_val_ptr = LLVMBuildStructGEP(g->builder, err_union_handle, err_union_err_index, ""); |
| ... | ... | @@ -3006,11 +2988,10 @@ static LLVMValueRef ir_render_unwrap_err_code(CodeGen *g, IrExecutable *executab |
| 3006 | 2988 | static LLVMValueRef ir_render_unwrap_err_payload(CodeGen *g, IrExecutable *executable, IrInstructionUnwrapErrPayload *instruction) { |
| 3007 | 2989 | TypeTableEntry *ptr_type = instruction->value->value.type; |
| 3008 | 2990 | assert(ptr_type->id == TypeTableEntryIdPointer); |
| 3009 | bool is_volatile = ptr_type->data.pointer.is_volatile; | |
| 3010 | 2991 | TypeTableEntry *err_union_type = ptr_type->data.pointer.child_type; |
| 3011 | 2992 | TypeTableEntry *child_type = err_union_type->data.error.child_type; |
| 3012 | 2993 | LLVMValueRef err_union_ptr = ir_llvm_value(g, instruction->value); |
| 3013 | LLVMValueRef err_union_handle = get_handle_value(g, err_union_ptr, err_union_type, is_volatile); | |
| 2994 | LLVMValueRef err_union_handle = get_handle_value(g, err_union_ptr, err_union_type, ptr_type); | |
| 3014 | 2995 | |
| 3015 | 2996 | if (ir_want_debug_safety(g, &instruction->base) && instruction->safety_check_on && g->error_decls.length > 1) { |
| 3016 | 2997 | LLVMValueRef err_val; |
| ... | ... | @@ -3123,7 +3104,8 @@ static LLVMValueRef ir_render_enum_tag(CodeGen *g, IrExecutable *executable, IrI |
| 3123 | 3104 | return enum_val; |
| 3124 | 3105 | |
| 3125 | 3106 | LLVMValueRef tag_field_ptr = LLVMBuildStructGEP(g->builder, enum_val, enum_type->data.enumeration.gen_tag_index, ""); |
| 3126 | return get_handle_value(g, tag_field_ptr, tag_type, false); | |
| 3107 | TypeTableEntry *ptr_type = get_pointer_to_type(g, tag_type, false); | |
| 3108 | return get_handle_value(g, tag_field_ptr, tag_type, ptr_type); | |
| 3127 | 3109 | } |
| 3128 | 3110 | |
| 3129 | 3111 | static LLVMValueRef ir_render_init_enum(CodeGen *g, IrExecutable *executable, IrInstructionInitEnum *instruction) { |
| ... | ... | @@ -3164,8 +3146,10 @@ static LLVMValueRef ir_render_struct_init(CodeGen *g, IrExecutable *executable, |
| 3164 | 3146 | (unsigned)type_struct_field->gen_index, ""); |
| 3165 | 3147 | LLVMValueRef value = ir_llvm_value(g, field->value); |
| 3166 | 3148 | |
| 3149 | uint32_t field_align_bytes = get_abi_alignment(g, type_struct_field->type_entry); | |
| 3150 | ||
| 3167 | 3151 | TypeTableEntry *ptr_type = get_pointer_to_type_extra(g, type_struct_field->type_entry, |
| 3168 | false, false, | |
| 3152 | false, false, field_align_bytes, | |
| 3169 | 3153 | (uint32_t)type_struct_field->packed_bits_offset, (uint32_t)type_struct_field->unaligned_bit_count); |
| 3170 | 3154 | |
| 3171 | 3155 | gen_assign_raw(g, field_ptr, ptr_type, value); |
| ... | ... | @@ -3243,15 +3227,13 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable, |
| 3243 | 3227 | case IrInstructionIdEmbedFile: |
| 3244 | 3228 | case IrInstructionIdIntType: |
| 3245 | 3229 | case IrInstructionIdMemberCount: |
| 3246 | case IrInstructionIdPreferredAlignOf: | |
| 3247 | case IrInstructionIdAbiAlignOf: | |
| 3230 | case IrInstructionIdAlignOf: | |
| 3248 | 3231 | case IrInstructionIdFnProto: |
| 3249 | 3232 | case IrInstructionIdTestComptime: |
| 3250 | 3233 | case IrInstructionIdCheckSwitchProngs: |
| 3251 | 3234 | case IrInstructionIdCheckStatementIsVoid: |
| 3252 | 3235 | case IrInstructionIdTypeName: |
| 3253 | 3236 | case IrInstructionIdCanImplicitCast: |
| 3254 | case IrInstructionIdSetGlobalAlign: | |
| 3255 | 3237 | case IrInstructionIdSetGlobalSection: |
| 3256 | 3238 | case IrInstructionIdSetGlobalLinkage: |
| 3257 | 3239 | case IrInstructionIdDeclRef: |
| ... | ... | @@ -3259,6 +3241,7 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable, |
| 3259 | 3241 | case IrInstructionIdOffsetOf: |
| 3260 | 3242 | case IrInstructionIdTypeId: |
| 3261 | 3243 | case IrInstructionIdSetEvalBranchQuota: |
| 3244 | case IrInstructionIdPtrTypeOf: | |
| 3262 | 3245 | zig_unreachable(); |
| 3263 | 3246 | case IrInstructionIdReturn: |
| 3264 | 3247 | return ir_render_return(g, executable, (IrInstructionReturn *)instruction); |
| ... | ... | @@ -3840,7 +3823,7 @@ static void render_const_val_global(CodeGen *g, ConstExprValue *const_val, const |
| 3840 | 3823 | LLVMSetLinkage(global_value, LLVMInternalLinkage); |
| 3841 | 3824 | LLVMSetGlobalConstant(global_value, true); |
| 3842 | 3825 | LLVMSetUnnamedAddr(global_value, true); |
| 3843 | LLVMSetAlignment(global_value, get_type_alignment(g, const_val->type)); | |
| 3826 | LLVMSetAlignment(global_value, get_abi_alignment(g, const_val->type)); | |
| 3844 | 3827 | |
| 3845 | 3828 | const_val->global_refs->llvm_global = global_value; |
| 3846 | 3829 | } |
| ... | ... | @@ -3856,8 +3839,8 @@ static void generate_error_name_table(CodeGen *g) { |
| 3856 | 3839 | |
| 3857 | 3840 | assert(g->error_decls.length > 0); |
| 3858 | 3841 | |
| 3859 | TypeTableEntry *str_type = get_slice_type(g, g->builtin_types.entry_u8, true); | |
| 3860 | TypeTableEntry *u8_ptr_type = str_type->data.structure.fields[0].type_entry; | |
| 3842 | TypeTableEntry *u8_ptr_type = get_pointer_to_type(g, g->builtin_types.entry_u8, true); | |
| 3843 | TypeTableEntry *str_type = get_slice_type(g, u8_ptr_type); | |
| 3861 | 3844 | |
| 3862 | 3845 | LLVMValueRef *values = allocate<LLVMValueRef>(g->error_decls.length); |
| 3863 | 3846 | values[0] = LLVMGetUndef(str_type->type_ref); |
| ... | ... | @@ -3893,8 +3876,8 @@ static void generate_error_name_table(CodeGen *g) { |
| 3893 | 3876 | } |
| 3894 | 3877 | |
| 3895 | 3878 | static void generate_enum_name_tables(CodeGen *g) { |
| 3896 | TypeTableEntry *str_type = get_slice_type(g, g->builtin_types.entry_u8, true); | |
| 3897 | TypeTableEntry *u8_ptr_type = str_type->data.structure.fields[0].type_entry; | |
| 3879 | TypeTableEntry *u8_ptr_type = get_pointer_to_type(g, g->builtin_types.entry_u8, true); | |
| 3880 | TypeTableEntry *str_type = get_slice_type(g, u8_ptr_type); | |
| 3898 | 3881 | |
| 3899 | 3882 | for (size_t enum_i = 0; enum_i < g->name_table_enums.length; enum_i += 1) { |
| 3900 | 3883 | TypeTableEntry *enum_tag_type = g->name_table_enums.at(enum_i); |
| ... | ... | @@ -3965,9 +3948,10 @@ static void gen_global_var(CodeGen *g, VariableTableEntry *var, LLVMValueRef ini |
| 3965 | 3948 | // TODO ^^ make an actual global variable |
| 3966 | 3949 | } |
| 3967 | 3950 | |
| 3968 | static LLVMValueRef build_alloca(CodeGen *g, TypeTableEntry *type_entry, const char *name) { | |
| 3951 | static LLVMValueRef build_alloca(CodeGen *g, TypeTableEntry *type_entry, const char *name, uint32_t alignment) { | |
| 3952 | assert(alignment > 0); | |
| 3969 | 3953 | LLVMValueRef result = LLVMBuildAlloca(g->builder, type_entry->type_ref, name); |
| 3970 | LLVMSetAlignment(result, get_type_alignment(g, type_entry)); | |
| 3954 | LLVMSetAlignment(result, alignment); | |
| 3971 | 3955 | return result; |
| 3972 | 3956 | } |
| 3973 | 3957 | |
| ... | ... | @@ -4056,6 +4040,7 @@ static void do_code_gen(CodeGen *g) { |
| 4056 | 4040 | // TODO debug info for the extern variable |
| 4057 | 4041 | |
| 4058 | 4042 | LLVMSetLinkage(global_value, LLVMExternalLinkage); |
| 4043 | LLVMSetAlignment(global_value, var->align_bytes); | |
| 4059 | 4044 | } else { |
| 4060 | 4045 | bool exported = (var->linkage == VarLinkageExport); |
| 4061 | 4046 | render_const_val(g, var->value); |
| ... | ... | @@ -4068,8 +4053,7 @@ static void do_code_gen(CodeGen *g) { |
| 4068 | 4053 | if (tld_var->section_name) { |
| 4069 | 4054 | LLVMSetSection(global_value, buf_ptr(tld_var->section_name)); |
| 4070 | 4055 | } |
| 4071 | LLVMSetAlignment(global_value, tld_var->alignment ? | |
| 4072 | tld_var->alignment : get_type_alignment(g, var->value->type)); | |
| 4056 | LLVMSetAlignment(global_value, var->align_bytes); | |
| 4073 | 4057 | |
| 4074 | 4058 | // TODO debug info for function pointers |
| 4075 | 4059 | if (var->gen_is_const && var->value->type->id != TypeTableEntryIdFn) { |
| ... | ... | @@ -4189,7 +4173,7 @@ static void do_code_gen(CodeGen *g) { |
| 4189 | 4173 | } else { |
| 4190 | 4174 | zig_unreachable(); |
| 4191 | 4175 | } |
| 4192 | *slot = build_alloca(g, slot_type, ""); | |
| 4176 | *slot = build_alloca(g, slot_type, "", get_abi_alignment(g, slot_type)); | |
| 4193 | 4177 | } |
| 4194 | 4178 | |
| 4195 | 4179 | ImportTableEntry *import = get_scope_import(&fn_table_entry->fndef_scope->base); |
| ... | ... | @@ -4207,7 +4191,7 @@ static void do_code_gen(CodeGen *g) { |
| 4207 | 4191 | continue; |
| 4208 | 4192 | |
| 4209 | 4193 | if (var->src_arg_index == SIZE_MAX) { |
| 4210 | var->value_ref = build_alloca(g, var->value->type, buf_ptr(&var->name)); | |
| 4194 | var->value_ref = build_alloca(g, var->value->type, buf_ptr(&var->name), var->align_bytes); | |
| 4211 | 4195 | |
| 4212 | 4196 | var->di_loc_var = ZigLLVMCreateAutoVariable(g->dbuilder, get_di_scope(g, var->parent_scope), |
| 4213 | 4197 | buf_ptr(&var->name), import->di_file, (unsigned)(var->decl_node->line + 1), |
| ... | ... | @@ -4227,7 +4211,7 @@ static void do_code_gen(CodeGen *g) { |
| 4227 | 4211 | var->value_ref = LLVMGetParam(fn, (unsigned)var->gen_arg_index); |
| 4228 | 4212 | } else { |
| 4229 | 4213 | gen_type = var->value->type; |
| 4230 | var->value_ref = build_alloca(g, var->value->type, buf_ptr(&var->name)); | |
| 4214 | var->value_ref = build_alloca(g, var->value->type, buf_ptr(&var->name), var->align_bytes); | |
| 4231 | 4215 | } |
| 4232 | 4216 | if (var->decl_node) { |
| 4233 | 4217 | var->di_loc_var = ZigLLVMCreateParameterVariable(g->dbuilder, get_di_scope(g, var->parent_scope), |
| ... | ... | @@ -4309,6 +4293,7 @@ static void do_code_gen(CodeGen *g) { |
| 4309 | 4293 | } |
| 4310 | 4294 | |
| 4311 | 4295 | static const uint8_t int_sizes_in_bits[] = { |
| 4296 | 2, | |
| 4312 | 4297 | 3, |
| 4313 | 4298 | 4, |
| 4314 | 4299 | 5, |
| ... | ... | @@ -4605,8 +4590,7 @@ static void define_builtin_fns(CodeGen *g) { |
| 4605 | 4590 | create_builtin_fn(g, BuiltinFnIdMemcpy, "memcpy", 3); |
| 4606 | 4591 | create_builtin_fn(g, BuiltinFnIdMemset, "memset", 3); |
| 4607 | 4592 | create_builtin_fn(g, BuiltinFnIdSizeof, "sizeOf", 1); |
| 4608 | create_builtin_fn(g, BuiltinFnIdPreferredAlignOf, "preferredAlignOf", 1); | |
| 4609 | create_builtin_fn(g, BuiltinFnIdAbiAlignOf, "cAbiAlignOf", 1); | |
| 4593 | create_builtin_fn(g, BuiltinFnIdAlignOf, "alignOf", 1); | |
| 4610 | 4594 | create_builtin_fn(g, BuiltinFnIdMaxValue, "maxValue", 1); |
| 4611 | 4595 | create_builtin_fn(g, BuiltinFnIdMinValue, "minValue", 1); |
| 4612 | 4596 | create_builtin_fn(g, BuiltinFnIdMemberCount, "memberCount", 1); |
| ... | ... | @@ -4634,7 +4618,6 @@ static void define_builtin_fns(CodeGen *g) { |
| 4634 | 4618 | create_builtin_fn(g, BuiltinFnIdIntType, "IntType", 2); |
| 4635 | 4619 | create_builtin_fn(g, BuiltinFnIdSetDebugSafety, "setDebugSafety", 2); |
| 4636 | 4620 | create_builtin_fn(g, BuiltinFnIdSetFloatMode, "setFloatMode", 2); |
| 4637 | create_builtin_fn(g, BuiltinFnIdSetGlobalAlign, "setGlobalAlign", 2); | |
| 4638 | 4621 | create_builtin_fn(g, BuiltinFnIdSetGlobalSection, "setGlobalSection", 2); |
| 4639 | 4622 | create_builtin_fn(g, BuiltinFnIdSetGlobalLinkage, "setGlobalLinkage", 2); |
| 4640 | 4623 | create_builtin_fn(g, BuiltinFnIdPanic, "panic", 1); |
| ... | ... | @@ -4989,7 +4972,8 @@ static void create_test_compile_var_and_add_test_runner(CodeGen *g) { |
| 4989 | 4972 | exit(0); |
| 4990 | 4973 | } |
| 4991 | 4974 | |
| 4992 | TypeTableEntry *str_type = get_slice_type(g, g->builtin_types.entry_u8, true); | |
| 4975 | TypeTableEntry *u8_ptr_type = get_pointer_to_type(g, g->builtin_types.entry_u8, true); | |
| 4976 | TypeTableEntry *str_type = get_slice_type(g, u8_ptr_type); | |
| 4993 | 4977 | TypeTableEntry *fn_type = get_test_fn_type(g); |
| 4994 | 4978 | |
| 4995 | 4979 | const char *field_names[] = { "name", "func", }; |
src/ir.cpp+304-275| ... | ... | @@ -51,6 +51,7 @@ static IrInstruction *ir_gen_node_extra(IrBuilder *irb, AstNode *node, Scope *sc |
| 51 | 51 | static TypeTableEntry *ir_analyze_instruction(IrAnalyze *ira, IrInstruction *instruction); |
| 52 | 52 | static IrInstruction *ir_implicit_cast(IrAnalyze *ira, IrInstruction *value, TypeTableEntry *expected_type); |
| 53 | 53 | static IrInstruction *ir_get_deref(IrAnalyze *ira, IrInstruction *source_instruction, IrInstruction *ptr); |
| 54 | static ErrorMsg *exec_add_error_node(CodeGen *codegen, IrExecutable *exec, AstNode *source_node, Buf *msg); | |
| 54 | 55 | |
| 55 | 56 | ConstExprValue *const_ptr_pointee(CodeGen *g, ConstExprValue *const_val) { |
| 56 | 57 | assert(const_val->type->id == TypeTableEntryIdPointer); |
| ... | ... | @@ -422,12 +423,8 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionFrameAddress *) |
| 422 | 423 | return IrInstructionIdFrameAddress; |
| 423 | 424 | } |
| 424 | 425 | |
| 425 | static constexpr IrInstructionId ir_instruction_id(IrInstructionPreferredAlignOf *) { | |
| 426 | return IrInstructionIdPreferredAlignOf; | |
| 427 | } | |
| 428 | ||
| 429 | static constexpr IrInstructionId ir_instruction_id(IrInstructionAbiAlignOf *) { | |
| 430 | return IrInstructionIdAbiAlignOf; | |
| 426 | static constexpr IrInstructionId ir_instruction_id(IrInstructionAlignOf *) { | |
| 427 | return IrInstructionIdAlignOf; | |
| 431 | 428 | } |
| 432 | 429 | |
| 433 | 430 | static constexpr IrInstructionId ir_instruction_id(IrInstructionOverflowOp *) { |
| ... | ... | @@ -518,10 +515,6 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionCanImplicitCast |
| 518 | 515 | return IrInstructionIdCanImplicitCast; |
| 519 | 516 | } |
| 520 | 517 | |
| 521 | static constexpr IrInstructionId ir_instruction_id(IrInstructionSetGlobalAlign *) { | |
| 522 | return IrInstructionIdSetGlobalAlign; | |
| 523 | } | |
| 524 | ||
| 525 | 518 | static constexpr IrInstructionId ir_instruction_id(IrInstructionSetGlobalSection *) { |
| 526 | 519 | return IrInstructionIdSetGlobalSection; |
| 527 | 520 | } |
| ... | ... | @@ -558,6 +551,10 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionSetEvalBranchQuo |
| 558 | 551 | return IrInstructionIdSetEvalBranchQuota; |
| 559 | 552 | } |
| 560 | 553 | |
| 554 | static constexpr IrInstructionId ir_instruction_id(IrInstructionPtrTypeOf *) { | |
| 555 | return IrInstructionIdPtrTypeOf; | |
| 556 | } | |
| 557 | ||
| 561 | 558 | template<typename T> |
| 562 | 559 | static T *ir_create_instruction(IrBuilder *irb, Scope *scope, AstNode *source_node) { |
| 563 | 560 | T *special_instruction = allocate<T>(1); |
| ... | ... | @@ -988,6 +985,24 @@ static IrInstruction *ir_build_br_from(IrBuilder *irb, IrInstruction *old_instru |
| 988 | 985 | return new_instruction; |
| 989 | 986 | } |
| 990 | 987 | |
| 988 | static IrInstruction *ir_build_ptr_type_of(IrBuilder *irb, Scope *scope, AstNode *source_node, | |
| 989 | IrInstruction *child_type, bool is_const, bool is_volatile, IrInstruction *align_value, | |
| 990 | uint32_t bit_offset_start, uint32_t bit_offset_end) | |
| 991 | { | |
| 992 | IrInstructionPtrTypeOf *ptr_type_of_instruction = ir_build_instruction<IrInstructionPtrTypeOf>(irb, scope, source_node); | |
| 993 | ptr_type_of_instruction->align_value = align_value; | |
| 994 | ptr_type_of_instruction->child_type = child_type; | |
| 995 | ptr_type_of_instruction->is_const = is_const; | |
| 996 | ptr_type_of_instruction->is_volatile = is_volatile; | |
| 997 | ptr_type_of_instruction->bit_offset_start = bit_offset_start; | |
| 998 | ptr_type_of_instruction->bit_offset_end = bit_offset_end; | |
| 999 | ||
| 1000 | ir_ref_instruction(align_value, irb->current_basic_block); | |
| 1001 | ir_ref_instruction(child_type, irb->current_basic_block); | |
| 1002 | ||
| 1003 | return &ptr_type_of_instruction->base; | |
| 1004 | } | |
| 1005 | ||
| 991 | 1006 | static IrInstruction *ir_build_un_op(IrBuilder *irb, Scope *scope, AstNode *source_node, IrUnOp op_id, IrInstruction *value) { |
| 992 | 1007 | IrInstructionUnOp *br_instruction = ir_build_instruction<IrInstructionUnOp>(irb, scope, source_node); |
| 993 | 1008 | br_instruction->op_id = op_id; |
| ... | ... | @@ -1112,26 +1127,28 @@ static IrInstruction *ir_build_store_ptr_from(IrBuilder *irb, IrInstruction *old |
| 1112 | 1127 | } |
| 1113 | 1128 | |
| 1114 | 1129 | static IrInstruction *ir_build_var_decl(IrBuilder *irb, Scope *scope, AstNode *source_node, |
| 1115 | VariableTableEntry *var, IrInstruction *var_type, IrInstruction *init_value) | |
| 1130 | VariableTableEntry *var, IrInstruction *var_type, IrInstruction *align_value, IrInstruction *init_value) | |
| 1116 | 1131 | { |
| 1117 | 1132 | IrInstructionDeclVar *decl_var_instruction = ir_build_instruction<IrInstructionDeclVar>(irb, scope, source_node); |
| 1118 | 1133 | decl_var_instruction->base.value.special = ConstValSpecialStatic; |
| 1119 | 1134 | decl_var_instruction->base.value.type = irb->codegen->builtin_types.entry_void; |
| 1120 | 1135 | decl_var_instruction->var = var; |
| 1121 | 1136 | decl_var_instruction->var_type = var_type; |
| 1137 | decl_var_instruction->align_value = align_value; | |
| 1122 | 1138 | decl_var_instruction->init_value = init_value; |
| 1123 | 1139 | |
| 1124 | 1140 | if (var_type) ir_ref_instruction(var_type, irb->current_basic_block); |
| 1141 | if (align_value) ir_ref_instruction(align_value, irb->current_basic_block); | |
| 1125 | 1142 | ir_ref_instruction(init_value, irb->current_basic_block); |
| 1126 | 1143 | |
| 1127 | 1144 | return &decl_var_instruction->base; |
| 1128 | 1145 | } |
| 1129 | 1146 | |
| 1130 | 1147 | static IrInstruction *ir_build_var_decl_from(IrBuilder *irb, IrInstruction *old_instruction, |
| 1131 | VariableTableEntry *var, IrInstruction *var_type, IrInstruction *init_value) | |
| 1148 | VariableTableEntry *var, IrInstruction *var_type, IrInstruction *align_value, IrInstruction *init_value) | |
| 1132 | 1149 | { |
| 1133 | 1150 | IrInstruction *new_instruction = ir_build_var_decl(irb, old_instruction->scope, |
| 1134 | old_instruction->source_node, var, var_type, init_value); | |
| 1151 | old_instruction->source_node, var, var_type, align_value, init_value); | |
| 1135 | 1152 | ir_link_new_instruction(new_instruction, old_instruction); |
| 1136 | 1153 | return new_instruction; |
| 1137 | 1154 | } |
| ... | ... | @@ -1221,14 +1238,17 @@ static IrInstruction *ir_build_array_type(IrBuilder *irb, Scope *scope, AstNode |
| 1221 | 1238 | return &instruction->base; |
| 1222 | 1239 | } |
| 1223 | 1240 | |
| 1224 | static IrInstruction *ir_build_slice_type(IrBuilder *irb, Scope *scope, AstNode *source_node, bool is_const, | |
| 1225 | IrInstruction *child_type) | |
| 1241 | static IrInstruction *ir_build_slice_type(IrBuilder *irb, Scope *scope, AstNode *source_node, | |
| 1242 | IrInstruction *child_type, bool is_const, bool is_volatile, IrInstruction *align_value) | |
| 1226 | 1243 | { |
| 1227 | 1244 | IrInstructionSliceType *instruction = ir_build_instruction<IrInstructionSliceType>(irb, scope, source_node); |
| 1228 | 1245 | instruction->is_const = is_const; |
| 1246 | instruction->is_volatile = is_volatile; | |
| 1229 | 1247 | instruction->child_type = child_type; |
| 1248 | instruction->align_value = align_value; | |
| 1230 | 1249 | |
| 1231 | 1250 | ir_ref_instruction(child_type, irb->current_basic_block); |
| 1251 | if (align_value) ir_ref_instruction(align_value, irb->current_basic_block); | |
| 1232 | 1252 | |
| 1233 | 1253 | return &instruction->base; |
| 1234 | 1254 | } |
| ... | ... | @@ -1810,17 +1830,8 @@ static IrInstruction *ir_build_overflow_op_from(IrBuilder *irb, IrInstruction *o |
| 1810 | 1830 | return new_instruction; |
| 1811 | 1831 | } |
| 1812 | 1832 | |
| 1813 | static IrInstruction *ir_build_preferred_align_of(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *type_value) { | |
| 1814 | IrInstructionPreferredAlignOf *instruction = ir_build_instruction<IrInstructionPreferredAlignOf>(irb, scope, source_node); | |
| 1815 | instruction->type_value = type_value; | |
| 1816 | ||
| 1817 | ir_ref_instruction(type_value, irb->current_basic_block); | |
| 1818 | ||
| 1819 | return &instruction->base; | |
| 1820 | } | |
| 1821 | ||
| 1822 | static IrInstruction *ir_build_abi_align_of(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *type_value) { | |
| 1823 | IrInstructionAbiAlignOf *instruction = ir_build_instruction<IrInstructionAbiAlignOf>(irb, scope, source_node); | |
| 1833 | static IrInstruction *ir_build_align_of(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *type_value) { | |
| 1834 | IrInstructionAlignOf *instruction = ir_build_instruction<IrInstructionAlignOf>(irb, scope, source_node); | |
| 1824 | 1835 | instruction->type_value = type_value; |
| 1825 | 1836 | |
| 1826 | 1837 | ir_ref_instruction(type_value, irb->current_basic_block); |
| ... | ... | @@ -2097,19 +2108,6 @@ static IrInstruction *ir_build_can_implicit_cast(IrBuilder *irb, Scope *scope, A |
| 2097 | 2108 | return &instruction->base; |
| 2098 | 2109 | } |
| 2099 | 2110 | |
| 2100 | static IrInstruction *ir_build_set_global_align(IrBuilder *irb, Scope *scope, AstNode *source_node, | |
| 2101 | Tld *tld, IrInstruction *value) | |
| 2102 | { | |
| 2103 | IrInstructionSetGlobalAlign *instruction = ir_build_instruction<IrInstructionSetGlobalAlign>( | |
| 2104 | irb, scope, source_node); | |
| 2105 | instruction->tld = tld; | |
| 2106 | instruction->value = value; | |
| 2107 | ||
| 2108 | ir_ref_instruction(value, irb->current_basic_block); | |
| 2109 | ||
| 2110 | return &instruction->base; | |
| 2111 | } | |
| 2112 | ||
| 2113 | 2111 | static IrInstruction *ir_build_set_global_section(IrBuilder *irb, Scope *scope, AstNode *source_node, |
| 2114 | 2112 | Tld *tld, IrInstruction *value) |
| 2115 | 2113 | { |
| ... | ... | @@ -2277,11 +2275,20 @@ static IrInstruction *ir_instruction_binop_get_dep(IrInstructionBinOp *instructi |
| 2277 | 2275 | } |
| 2278 | 2276 | |
| 2279 | 2277 | static IrInstruction *ir_instruction_declvar_get_dep(IrInstructionDeclVar *instruction, size_t index) { |
| 2280 | switch (index) { | |
| 2281 | case 0: return instruction->init_value; | |
| 2282 | case 1: return instruction->var_type; | |
| 2283 | default: return nullptr; | |
| 2278 | if (index == 0) return instruction->init_value; | |
| 2279 | index -= 1; | |
| 2280 | ||
| 2281 | if (instruction->align_value != nullptr) { | |
| 2282 | if (index == 0) return instruction->align_value; | |
| 2283 | index -= 1; | |
| 2284 | } | |
| 2285 | ||
| 2286 | if (instruction->var_type != nullptr) { | |
| 2287 | if (index == 0) return instruction->var_type; | |
| 2288 | index -= 1; | |
| 2284 | 2289 | } |
| 2290 | ||
| 2291 | return nullptr; | |
| 2285 | 2292 | } |
| 2286 | 2293 | |
| 2287 | 2294 | static IrInstruction *ir_instruction_loadptr_get_dep(IrInstructionLoadPtr *instruction, size_t index) { |
| ... | ... | @@ -2671,14 +2678,7 @@ static IrInstruction *ir_instruction_frameaddress_get_dep(IrInstructionFrameAddr |
| 2671 | 2678 | return nullptr; |
| 2672 | 2679 | } |
| 2673 | 2680 | |
| 2674 | static IrInstruction *ir_instruction_preferredalignof_get_dep(IrInstructionPreferredAlignOf *instruction, size_t index) { | |
| 2675 | switch (index) { | |
| 2676 | case 0: return instruction->type_value; | |
| 2677 | default: return nullptr; | |
| 2678 | } | |
| 2679 | } | |
| 2680 | ||
| 2681 | static IrInstruction *ir_instruction_abialignof_get_dep(IrInstructionAbiAlignOf *instruction, size_t index) { | |
| 2681 | static IrInstruction *ir_instruction_alignof_get_dep(IrInstructionAlignOf *instruction, size_t index) { | |
| 2682 | 2682 | switch (index) { |
| 2683 | 2683 | case 0: return instruction->type_value; |
| 2684 | 2684 | default: return nullptr; |
| ... | ... | @@ -2854,13 +2854,6 @@ static IrInstruction *ir_instruction_canimplicitcast_get_dep(IrInstructionCanImp |
| 2854 | 2854 | } |
| 2855 | 2855 | } |
| 2856 | 2856 | |
| 2857 | static IrInstruction *ir_instruction_setglobalalign_get_dep(IrInstructionSetGlobalAlign *instruction, size_t index) { | |
| 2858 | switch (index) { | |
| 2859 | case 0: return instruction->value; | |
| 2860 | default: return nullptr; | |
| 2861 | } | |
| 2862 | } | |
| 2863 | ||
| 2864 | 2857 | static IrInstruction *ir_instruction_setglobalsection_get_dep(IrInstructionSetGlobalSection *instruction, size_t index) { |
| 2865 | 2858 | switch (index) { |
| 2866 | 2859 | case 0: return instruction->value; |
| ... | ... | @@ -2924,6 +2917,14 @@ static IrInstruction *ir_instruction_setevalbranchquota_get_dep(IrInstructionSet |
| 2924 | 2917 | } |
| 2925 | 2918 | } |
| 2926 | 2919 | |
| 2920 | static IrInstruction *ir_instruction_ptrtypeof_get_dep(IrInstructionPtrTypeOf *instruction, size_t index) { | |
| 2921 | switch (index) { | |
| 2922 | case 0: return instruction->align_value; | |
| 2923 | case 1: return instruction->child_type; | |
| 2924 | default: return nullptr; | |
| 2925 | } | |
| 2926 | } | |
| 2927 | ||
| 2927 | 2928 | static IrInstruction *ir_instruction_get_dep(IrInstruction *instruction, size_t index) { |
| 2928 | 2929 | switch (instruction->id) { |
| 2929 | 2930 | case IrInstructionIdInvalid: |
| ... | ... | @@ -3056,10 +3057,8 @@ static IrInstruction *ir_instruction_get_dep(IrInstruction *instruction, size_t |
| 3056 | 3057 | return ir_instruction_returnaddress_get_dep((IrInstructionReturnAddress *) instruction, index); |
| 3057 | 3058 | case IrInstructionIdFrameAddress: |
| 3058 | 3059 | return ir_instruction_frameaddress_get_dep((IrInstructionFrameAddress *) instruction, index); |
| 3059 | case IrInstructionIdPreferredAlignOf: | |
| 3060 | return ir_instruction_preferredalignof_get_dep((IrInstructionPreferredAlignOf *) instruction, index); | |
| 3061 | case IrInstructionIdAbiAlignOf: | |
| 3062 | return ir_instruction_abialignof_get_dep((IrInstructionAbiAlignOf *) instruction, index); | |
| 3060 | case IrInstructionIdAlignOf: | |
| 3061 | return ir_instruction_alignof_get_dep((IrInstructionAlignOf *) instruction, index); | |
| 3063 | 3062 | case IrInstructionIdOverflowOp: |
| 3064 | 3063 | return ir_instruction_overflowop_get_dep((IrInstructionOverflowOp *) instruction, index); |
| 3065 | 3064 | case IrInstructionIdTestErr: |
| ... | ... | @@ -3102,8 +3101,6 @@ static IrInstruction *ir_instruction_get_dep(IrInstruction *instruction, size_t |
| 3102 | 3101 | return ir_instruction_typename_get_dep((IrInstructionTypeName *) instruction, index); |
| 3103 | 3102 | case IrInstructionIdCanImplicitCast: |
| 3104 | 3103 | return ir_instruction_canimplicitcast_get_dep((IrInstructionCanImplicitCast *) instruction, index); |
| 3105 | case IrInstructionIdSetGlobalAlign: | |
| 3106 | return ir_instruction_setglobalalign_get_dep((IrInstructionSetGlobalAlign *) instruction, index); | |
| 3107 | 3104 | case IrInstructionIdSetGlobalSection: |
| 3108 | 3105 | return ir_instruction_setglobalsection_get_dep((IrInstructionSetGlobalSection *) instruction, index); |
| 3109 | 3106 | case IrInstructionIdSetGlobalLinkage: |
| ... | ... | @@ -3122,6 +3119,8 @@ static IrInstruction *ir_instruction_get_dep(IrInstruction *instruction, size_t |
| 3122 | 3119 | return ir_instruction_typeid_get_dep((IrInstructionTypeId *) instruction, index); |
| 3123 | 3120 | case IrInstructionIdSetEvalBranchQuota: |
| 3124 | 3121 | return ir_instruction_setevalbranchquota_get_dep((IrInstructionSetEvalBranchQuota *) instruction, index); |
| 3122 | case IrInstructionIdPtrTypeOf: | |
| 3123 | return ir_instruction_ptrtypeof_get_dep((IrInstructionPtrTypeOf *) instruction, index); | |
| 3125 | 3124 | } |
| 3126 | 3125 | zig_unreachable(); |
| 3127 | 3126 | } |
| ... | ... | @@ -4286,23 +4285,14 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo |
| 4286 | 4285 | return ir_build_return_address(irb, scope, node); |
| 4287 | 4286 | case BuiltinFnIdFrameAddress: |
| 4288 | 4287 | return ir_build_frame_address(irb, scope, node); |
| 4289 | case BuiltinFnIdPreferredAlignOf: | |
| 4290 | { | |
| 4291 | AstNode *arg0_node = node->data.fn_call_expr.params.at(0); | |
| 4292 | IrInstruction *arg0_value = ir_gen_node(irb, arg0_node, scope); | |
| 4293 | if (arg0_value == irb->codegen->invalid_instruction) | |
| 4294 | return arg0_value; | |
| 4295 | ||
| 4296 | return ir_build_preferred_align_of(irb, scope, node, arg0_value); | |
| 4297 | } | |
| 4298 | case BuiltinFnIdAbiAlignOf: | |
| 4288 | case BuiltinFnIdAlignOf: | |
| 4299 | 4289 | { |
| 4300 | 4290 | AstNode *arg0_node = node->data.fn_call_expr.params.at(0); |
| 4301 | 4291 | IrInstruction *arg0_value = ir_gen_node(irb, arg0_node, scope); |
| 4302 | 4292 | if (arg0_value == irb->codegen->invalid_instruction) |
| 4303 | 4293 | return arg0_value; |
| 4304 | 4294 | |
| 4305 | return ir_build_abi_align_of(irb, scope, node, arg0_value); | |
| 4295 | return ir_build_align_of(irb, scope, node, arg0_value); | |
| 4306 | 4296 | } |
| 4307 | 4297 | case BuiltinFnIdAddWithOverflow: |
| 4308 | 4298 | return ir_gen_overflow_op(irb, scope, node, IrOverflowOpAdd); |
| ... | ... | @@ -4335,7 +4325,6 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo |
| 4335 | 4325 | |
| 4336 | 4326 | return ir_build_can_implicit_cast(irb, scope, node, arg0_value, arg1_value); |
| 4337 | 4327 | } |
| 4338 | case BuiltinFnIdSetGlobalAlign: | |
| 4339 | 4328 | case BuiltinFnIdSetGlobalSection: |
| 4340 | 4329 | case BuiltinFnIdSetGlobalLinkage: |
| 4341 | 4330 | { |
| ... | ... | @@ -4361,9 +4350,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo |
| 4361 | 4350 | if (arg1_value == irb->codegen->invalid_instruction) |
| 4362 | 4351 | return arg1_value; |
| 4363 | 4352 | |
| 4364 | if (builtin_fn->id == BuiltinFnIdSetGlobalAlign) { | |
| 4365 | return ir_build_set_global_align(irb, scope, node, tld, arg1_value); | |
| 4366 | } else if (builtin_fn->id == BuiltinFnIdSetGlobalSection) { | |
| 4353 | if (builtin_fn->id == BuiltinFnIdSetGlobalSection) { | |
| 4367 | 4354 | return ir_build_set_global_section(irb, scope, node, tld, arg1_value); |
| 4368 | 4355 | } else if (builtin_fn->id == BuiltinFnIdSetGlobalLinkage) { |
| 4369 | 4356 | return ir_build_set_global_linkage(irb, scope, node, tld, arg1_value); |
| ... | ... | @@ -4652,17 +4639,51 @@ static IrInstruction *ir_lval_wrap(IrBuilder *irb, Scope *scope, IrInstruction * |
| 4652 | 4639 | return ir_build_ref(irb, scope, value->source_node, value, lval.is_const, lval.is_volatile); |
| 4653 | 4640 | } |
| 4654 | 4641 | |
| 4655 | static IrInstruction *ir_gen_address_of(IrBuilder *irb, Scope *scope, AstNode *node, | |
| 4656 | bool is_const, bool is_volatile, LVal lval) | |
| 4657 | { | |
| 4658 | assert(node->type == NodeTypePrefixOpExpr); | |
| 4659 | AstNode *expr_node = node->data.prefix_op_expr.primary_expr; | |
| 4642 | static IrInstruction *ir_gen_address_of(IrBuilder *irb, Scope *scope, AstNode *node) { | |
| 4643 | assert(node->type == NodeTypeAddrOfExpr); | |
| 4644 | bool is_const = node->data.addr_of_expr.is_const; | |
| 4645 | bool is_volatile = node->data.addr_of_expr.is_volatile; | |
| 4646 | AstNode *expr_node = node->data.addr_of_expr.op_expr; | |
| 4647 | AstNode *align_expr = node->data.addr_of_expr.align_expr; | |
| 4660 | 4648 | |
| 4661 | IrInstruction *value = ir_gen_node_extra(irb, expr_node, scope, make_lval_addr(is_const, is_volatile)); | |
| 4662 | if (value == irb->codegen->invalid_instruction) | |
| 4663 | return value; | |
| 4649 | if (align_expr == nullptr) { | |
| 4650 | return ir_gen_node_extra(irb, expr_node, scope, make_lval_addr(is_const, is_volatile)); | |
| 4651 | } | |
| 4652 | ||
| 4653 | IrInstruction *align_value = ir_gen_node(irb, align_expr, scope); | |
| 4654 | if (align_value == irb->codegen->invalid_instruction) | |
| 4655 | return align_value; | |
| 4656 | ||
| 4657 | IrInstruction *child_type = ir_gen_node(irb, expr_node, scope); | |
| 4658 | if (child_type == irb->codegen->invalid_instruction) | |
| 4659 | return child_type; | |
| 4660 | ||
| 4661 | uint32_t bit_offset_start = 0; | |
| 4662 | if (node->data.addr_of_expr.bit_offset_start != nullptr) { | |
| 4663 | if (!bigint_fits_in_bits(node->data.addr_of_expr.bit_offset_start, 32, false)) { | |
| 4664 | Buf *val_buf = buf_alloc(); | |
| 4665 | bigint_append_buf(val_buf, node->data.addr_of_expr.bit_offset_start, 10); | |
| 4666 | exec_add_error_node(irb->codegen, irb->exec, node, | |
| 4667 | buf_sprintf("value %s too large for u32 bit offset", buf_ptr(val_buf))); | |
| 4668 | return irb->codegen->invalid_instruction; | |
| 4669 | } | |
| 4670 | bit_offset_start = bigint_as_unsigned(node->data.addr_of_expr.bit_offset_start); | |
| 4671 | } | |
| 4672 | ||
| 4673 | uint32_t bit_offset_end = 0; | |
| 4674 | if (node->data.addr_of_expr.bit_offset_end != nullptr) { | |
| 4675 | if (!bigint_fits_in_bits(node->data.addr_of_expr.bit_offset_end, 32, false)) { | |
| 4676 | Buf *val_buf = buf_alloc(); | |
| 4677 | bigint_append_buf(val_buf, node->data.addr_of_expr.bit_offset_end, 10); | |
| 4678 | exec_add_error_node(irb->codegen, irb->exec, node, | |
| 4679 | buf_sprintf("value %s too large for u32 bit offset", buf_ptr(val_buf))); | |
| 4680 | return irb->codegen->invalid_instruction; | |
| 4681 | } | |
| 4682 | bit_offset_end = bigint_as_unsigned(node->data.addr_of_expr.bit_offset_end); | |
| 4683 | } | |
| 4664 | 4684 | |
| 4665 | return ir_lval_wrap(irb, scope, value, lval); | |
| 4685 | return ir_build_ptr_type_of(irb, scope, node, child_type, is_const, is_volatile, | |
| 4686 | align_value, bit_offset_start, bit_offset_end); | |
| 4666 | 4687 | } |
| 4667 | 4688 | |
| 4668 | 4689 | static IrInstruction *ir_gen_err_assert_ok(IrBuilder *irb, Scope *scope, AstNode *node, LVal lval) { |
| ... | ... | @@ -4725,14 +4746,6 @@ static IrInstruction *ir_gen_prefix_op_expr(IrBuilder *irb, Scope *scope, AstNod |
| 4725 | 4746 | return ir_lval_wrap(irb, scope, ir_gen_prefix_op_id(irb, scope, node, IrUnOpNegation), lval); |
| 4726 | 4747 | case PrefixOpNegationWrap: |
| 4727 | 4748 | return ir_lval_wrap(irb, scope, ir_gen_prefix_op_id(irb, scope, node, IrUnOpNegationWrap), lval); |
| 4728 | case PrefixOpAddressOf: | |
| 4729 | return ir_gen_address_of(irb, scope, node, false, false, lval); | |
| 4730 | case PrefixOpConstAddressOf: | |
| 4731 | return ir_gen_address_of(irb, scope, node, true, false, lval); | |
| 4732 | case PrefixOpVolatileAddressOf: | |
| 4733 | return ir_gen_address_of(irb, scope, node, false, true, lval); | |
| 4734 | case PrefixOpConstVolatileAddressOf: | |
| 4735 | return ir_gen_address_of(irb, scope, node, true, true, lval); | |
| 4736 | 4749 | case PrefixOpDereference: |
| 4737 | 4750 | return ir_gen_prefix_op_id_lval(irb, scope, node, IrUnOpDereference, lval); |
| 4738 | 4751 | case PrefixOpMaybe: |
| ... | ... | @@ -4822,11 +4835,18 @@ static IrInstruction *ir_gen_var_decl(IrBuilder *irb, Scope *scope, AstNode *nod |
| 4822 | 4835 | return irb->codegen->invalid_instruction; |
| 4823 | 4836 | } |
| 4824 | 4837 | |
| 4838 | IrInstruction *align_value = nullptr; | |
| 4839 | if (variable_declaration->align_expr != nullptr) { | |
| 4840 | align_value = ir_gen_node(irb, variable_declaration->align_expr, scope); | |
| 4841 | if (align_value == irb->codegen->invalid_instruction) | |
| 4842 | return align_value; | |
| 4843 | } | |
| 4844 | ||
| 4825 | 4845 | IrInstruction *init_value = ir_gen_node(irb, variable_declaration->expr, scope); |
| 4826 | 4846 | if (init_value == irb->codegen->invalid_instruction) |
| 4827 | 4847 | return init_value; |
| 4828 | 4848 | |
| 4829 | IrInstruction *result = ir_build_var_decl(irb, scope, node, var, type_instruction, init_value); | |
| 4849 | IrInstruction *result = ir_build_var_decl(irb, scope, node, var, type_instruction, align_value, init_value); | |
| 4830 | 4850 | var->decl_instruction = result; |
| 4831 | 4851 | return result; |
| 4832 | 4852 | } |
| ... | ... | @@ -4883,7 +4903,7 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *n |
| 4883 | 4903 | err_val_ptr, false); |
| 4884 | 4904 | IrInstruction *var_value = node->data.while_expr.var_is_ptr ? |
| 4885 | 4905 | var_ptr_value : ir_build_load_ptr(irb, payload_scope, symbol_node, var_ptr_value); |
| 4886 | ir_build_var_decl(irb, payload_scope, symbol_node, payload_var, nullptr, var_value); | |
| 4906 | ir_build_var_decl(irb, payload_scope, symbol_node, payload_var, nullptr, nullptr, var_value); | |
| 4887 | 4907 | } |
| 4888 | 4908 | |
| 4889 | 4909 | ZigList<IrInstruction *> incoming_values = {0}; |
| ... | ... | @@ -4922,7 +4942,7 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *n |
| 4922 | 4942 | true, false, false, is_comptime); |
| 4923 | 4943 | Scope *err_scope = err_var->child_scope; |
| 4924 | 4944 | IrInstruction *err_var_value = ir_build_unwrap_err_code(irb, err_scope, err_symbol_node, err_val_ptr); |
| 4925 | ir_build_var_decl(irb, err_scope, symbol_node, err_var, nullptr, err_var_value); | |
| 4945 | ir_build_var_decl(irb, err_scope, symbol_node, err_var, nullptr, nullptr, err_var_value); | |
| 4926 | 4946 | |
| 4927 | 4947 | else_result = ir_gen_node(irb, else_node, err_scope); |
| 4928 | 4948 | if (else_result == irb->codegen->invalid_instruction) |
| ... | ... | @@ -4964,7 +4984,7 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *n |
| 4964 | 4984 | IrInstruction *var_ptr_value = ir_build_unwrap_maybe(irb, child_scope, symbol_node, maybe_val_ptr, false); |
| 4965 | 4985 | IrInstruction *var_value = node->data.while_expr.var_is_ptr ? |
| 4966 | 4986 | var_ptr_value : ir_build_load_ptr(irb, child_scope, symbol_node, var_ptr_value); |
| 4967 | ir_build_var_decl(irb, child_scope, symbol_node, payload_var, nullptr, var_value); | |
| 4987 | ir_build_var_decl(irb, child_scope, symbol_node, payload_var, nullptr, nullptr, var_value); | |
| 4968 | 4988 | |
| 4969 | 4989 | ZigList<IrInstruction *> incoming_values = {0}; |
| 4970 | 4990 | ZigList<IrBasicBlock *> incoming_blocks = {0}; |
| ... | ... | @@ -5115,7 +5135,7 @@ static IrInstruction *ir_gen_for_expr(IrBuilder *irb, Scope *parent_scope, AstNo |
| 5115 | 5135 | Scope *child_scope = elem_var->child_scope; |
| 5116 | 5136 | |
| 5117 | 5137 | IrInstruction *undefined_value = ir_build_const_undefined(irb, child_scope, elem_node); |
| 5118 | ir_build_var_decl(irb, child_scope, elem_node, elem_var, elem_var_type, undefined_value); | |
| 5138 | ir_build_var_decl(irb, child_scope, elem_node, elem_var, elem_var_type, nullptr, undefined_value); | |
| 5119 | 5139 | IrInstruction *elem_var_ptr = ir_build_var_ptr(irb, child_scope, node, elem_var, false, false); |
| 5120 | 5140 | |
| 5121 | 5141 | AstNode *index_var_source_node; |
| ... | ... | @@ -5133,7 +5153,7 @@ static IrInstruction *ir_gen_for_expr(IrBuilder *irb, Scope *parent_scope, AstNo |
| 5133 | 5153 | IrInstruction *usize = ir_build_const_type(irb, child_scope, node, irb->codegen->builtin_types.entry_usize); |
| 5134 | 5154 | IrInstruction *zero = ir_build_const_usize(irb, child_scope, node, 0); |
| 5135 | 5155 | IrInstruction *one = ir_build_const_usize(irb, child_scope, node, 1); |
| 5136 | ir_build_var_decl(irb, child_scope, index_var_source_node, index_var, usize, zero); | |
| 5156 | ir_build_var_decl(irb, child_scope, index_var_source_node, index_var, usize, nullptr, zero); | |
| 5137 | 5157 | IrInstruction *index_ptr = ir_build_var_ptr(irb, child_scope, node, index_var, false, false); |
| 5138 | 5158 | |
| 5139 | 5159 | |
| ... | ... | @@ -5254,12 +5274,22 @@ static IrInstruction *ir_gen_array_type(IrBuilder *irb, Scope *scope, AstNode *n |
| 5254 | 5274 | AstNode *size_node = node->data.array_type.size; |
| 5255 | 5275 | AstNode *child_type_node = node->data.array_type.child_type; |
| 5256 | 5276 | bool is_const = node->data.array_type.is_const; |
| 5277 | bool is_volatile = node->data.array_type.is_volatile; | |
| 5278 | AstNode *align_expr = node->data.array_type.align_expr; | |
| 5257 | 5279 | |
| 5258 | 5280 | if (size_node) { |
| 5259 | 5281 | if (is_const) { |
| 5260 | 5282 | add_node_error(irb->codegen, node, buf_create_from_str("const qualifier invalid on array type")); |
| 5261 | 5283 | return irb->codegen->invalid_instruction; |
| 5262 | 5284 | } |
| 5285 | if (is_volatile) { | |
| 5286 | add_node_error(irb->codegen, node, buf_create_from_str("volatile qualifier invalid on array type")); | |
| 5287 | return irb->codegen->invalid_instruction; | |
| 5288 | } | |
| 5289 | if (align_expr != nullptr) { | |
| 5290 | add_node_error(irb->codegen, node, buf_create_from_str("align qualifier invalid on array type")); | |
| 5291 | return irb->codegen->invalid_instruction; | |
| 5292 | } | |
| 5263 | 5293 | |
| 5264 | 5294 | IrInstruction *size_value = ir_gen_node(irb, size_node, scope); |
| 5265 | 5295 | if (size_value == irb->codegen->invalid_instruction) |
| ... | ... | @@ -5271,11 +5301,20 @@ static IrInstruction *ir_gen_array_type(IrBuilder *irb, Scope *scope, AstNode *n |
| 5271 | 5301 | |
| 5272 | 5302 | return ir_build_array_type(irb, scope, node, size_value, child_type); |
| 5273 | 5303 | } else { |
| 5304 | IrInstruction *align_value; | |
| 5305 | if (align_expr != nullptr) { | |
| 5306 | align_value = ir_gen_node(irb, align_expr, scope); | |
| 5307 | if (align_value == irb->codegen->invalid_instruction) | |
| 5308 | return align_value; | |
| 5309 | } else { | |
| 5310 | align_value = nullptr; | |
| 5311 | } | |
| 5312 | ||
| 5274 | 5313 | IrInstruction *child_type = ir_gen_node(irb, child_type_node, scope); |
| 5275 | 5314 | if (child_type == irb->codegen->invalid_instruction) |
| 5276 | 5315 | return child_type; |
| 5277 | 5316 | |
| 5278 | return ir_build_slice_type(irb, scope, node, is_const, child_type); | |
| 5317 | return ir_build_slice_type(irb, scope, node, child_type, is_const, is_volatile, align_value); | |
| 5279 | 5318 | } |
| 5280 | 5319 | } |
| 5281 | 5320 | |
| ... | ... | @@ -5375,7 +5414,7 @@ static IrInstruction *ir_gen_test_expr(IrBuilder *irb, Scope *scope, AstNode *no |
| 5375 | 5414 | |
| 5376 | 5415 | IrInstruction *var_ptr_value = ir_build_unwrap_maybe(irb, scope, node, maybe_val_ptr, false); |
| 5377 | 5416 | IrInstruction *var_value = var_is_ptr ? var_ptr_value : ir_build_load_ptr(irb, scope, node, var_ptr_value); |
| 5378 | ir_build_var_decl(irb, scope, node, var, var_type, var_value); | |
| 5417 | ir_build_var_decl(irb, scope, node, var, var_type, nullptr, var_value); | |
| 5379 | 5418 | var_scope = var->child_scope; |
| 5380 | 5419 | } else { |
| 5381 | 5420 | var_scope = scope; |
| ... | ... | @@ -5452,7 +5491,7 @@ static IrInstruction *ir_gen_try_expr(IrBuilder *irb, Scope *scope, AstNode *nod |
| 5452 | 5491 | |
| 5453 | 5492 | IrInstruction *var_ptr_value = ir_build_unwrap_err_payload(irb, scope, node, err_val_ptr, false); |
| 5454 | 5493 | IrInstruction *var_value = var_is_ptr ? var_ptr_value : ir_build_load_ptr(irb, scope, node, var_ptr_value); |
| 5455 | ir_build_var_decl(irb, scope, node, var, var_type, var_value); | |
| 5494 | ir_build_var_decl(irb, scope, node, var, var_type, nullptr, var_value); | |
| 5456 | 5495 | var_scope = var->child_scope; |
| 5457 | 5496 | } else { |
| 5458 | 5497 | var_scope = scope; |
| ... | ... | @@ -5477,7 +5516,7 @@ static IrInstruction *ir_gen_try_expr(IrBuilder *irb, Scope *scope, AstNode *nod |
| 5477 | 5516 | err_symbol, is_const, is_const, is_shadowable, is_comptime); |
| 5478 | 5517 | |
| 5479 | 5518 | IrInstruction *var_value = ir_build_unwrap_err_code(irb, scope, node, err_val_ptr); |
| 5480 | ir_build_var_decl(irb, scope, node, var, var_type, var_value); | |
| 5519 | ir_build_var_decl(irb, scope, node, var, var_type, nullptr, var_value); | |
| 5481 | 5520 | err_var_scope = var->child_scope; |
| 5482 | 5521 | } else { |
| 5483 | 5522 | err_var_scope = scope; |
| ... | ... | @@ -5531,7 +5570,7 @@ static bool ir_gen_switch_prong_expr(IrBuilder *irb, Scope *scope, AstNode *swit |
| 5531 | 5570 | var_value = var_is_ptr ? target_value_ptr : ir_build_load_ptr(irb, scope, var_symbol_node, target_value_ptr); |
| 5532 | 5571 | } |
| 5533 | 5572 | IrInstruction *var_type = nullptr; // infer the type |
| 5534 | ir_build_var_decl(irb, scope, var_symbol_node, var, var_type, var_value); | |
| 5573 | ir_build_var_decl(irb, scope, var_symbol_node, var, var_type, nullptr, var_value); | |
| 5535 | 5574 | } else { |
| 5536 | 5575 | child_scope = scope; |
| 5537 | 5576 | } |
| ... | ... | @@ -5912,7 +5951,7 @@ static IrInstruction *ir_gen_err_ok_or(IrBuilder *irb, Scope *parent_scope, AstN |
| 5912 | 5951 | is_const, is_const, is_shadowable, is_comptime); |
| 5913 | 5952 | err_scope = var->child_scope; |
| 5914 | 5953 | IrInstruction *err_val = ir_build_unwrap_err_code(irb, err_scope, node, err_union_ptr); |
| 5915 | ir_build_var_decl(irb, err_scope, var_node, var, var_type, err_val); | |
| 5954 | ir_build_var_decl(irb, err_scope, var_node, var, var_type, nullptr, err_val); | |
| 5916 | 5955 | } else { |
| 5917 | 5956 | err_scope = parent_scope; |
| 5918 | 5957 | } |
| ... | ... | @@ -6056,6 +6095,8 @@ static IrInstruction *ir_gen_node_raw(IrBuilder *irb, AstNode *node, Scope *scop |
| 6056 | 6095 | return ir_lval_wrap(irb, scope, ir_gen_if_bool_expr(irb, scope, node), lval); |
| 6057 | 6096 | case NodeTypePrefixOpExpr: |
| 6058 | 6097 | return ir_gen_prefix_op_expr(irb, scope, node, lval); |
| 6098 | case NodeTypeAddrOfExpr: | |
| 6099 | return ir_lval_wrap(irb, scope, ir_gen_address_of(irb, scope, node), lval); | |
| 6059 | 6100 | case NodeTypeContainerInitExpr: |
| 6060 | 6101 | return ir_lval_wrap(irb, scope, ir_gen_container_init_expr(irb, scope, node), lval); |
| 6061 | 6102 | case NodeTypeVariableDeclaration: |
| ... | ... | @@ -7264,7 +7305,8 @@ static TypeTableEntry *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_nod |
| 7264 | 7305 | } |
| 7265 | 7306 | if (convert_to_const_slice) { |
| 7266 | 7307 | assert(prev_inst->value.type->id == TypeTableEntryIdArray); |
| 7267 | TypeTableEntry *slice_type = get_slice_type(ira->codegen, prev_inst->value.type->data.array.child_type, true); | |
| 7308 | TypeTableEntry *ptr_type = get_pointer_to_type(ira->codegen, prev_inst->value.type->data.array.child_type, true); | |
| 7309 | TypeTableEntry *slice_type = get_slice_type(ira->codegen, ptr_type); | |
| 7268 | 7310 | if (any_are_pure_error) { |
| 7269 | 7311 | return get_error_type(ira->codegen, slice_type); |
| 7270 | 7312 | } else { |
| ... | ... | @@ -7569,7 +7611,7 @@ static TypeTableEntry *ir_analyze_void(IrAnalyze *ira, IrInstruction *instructio |
| 7569 | 7611 | |
| 7570 | 7612 | static IrInstruction *ir_get_const_ptr(IrAnalyze *ira, IrInstruction *instruction, |
| 7571 | 7613 | ConstExprValue *pointee, TypeTableEntry *pointee_type, |
| 7572 | ConstPtrMut ptr_mut, bool ptr_is_const, bool ptr_is_volatile) | |
| 7614 | ConstPtrMut ptr_mut, bool ptr_is_const, bool ptr_is_volatile, uint32_t ptr_align) | |
| 7573 | 7615 | { |
| 7574 | 7616 | if (pointee_type->id == TypeTableEntryIdMetaType) { |
| 7575 | 7617 | TypeTableEntry *type_entry = pointee->data.x_type; |
| ... | ... | @@ -7583,11 +7625,11 @@ static IrInstruction *ir_get_const_ptr(IrAnalyze *ira, IrInstruction *instructio |
| 7583 | 7625 | const_val->type = pointee_type; |
| 7584 | 7626 | type_ensure_zero_bits_known(ira->codegen, type_entry); |
| 7585 | 7627 | const_val->data.x_type = get_pointer_to_type_extra(ira->codegen, type_entry, |
| 7586 | ptr_is_const, ptr_is_volatile, 0, 0); | |
| 7628 | ptr_is_const, ptr_is_volatile, get_abi_alignment(ira->codegen, type_entry), 0, 0); | |
| 7587 | 7629 | return const_instr; |
| 7588 | 7630 | } else { |
| 7589 | 7631 | TypeTableEntry *ptr_type = get_pointer_to_type_extra(ira->codegen, pointee_type, |
| 7590 | ptr_is_const, ptr_is_volatile, 0, 0); | |
| 7632 | ptr_is_const, ptr_is_volatile, ptr_align, 0, 0); | |
| 7591 | 7633 | IrInstruction *const_instr = ir_get_const(ira, instruction); |
| 7592 | 7634 | ConstExprValue *const_val = &const_instr->value; |
| 7593 | 7635 | const_val->type = ptr_type; |
| ... | ... | @@ -7603,7 +7645,8 @@ static TypeTableEntry *ir_analyze_const_ptr(IrAnalyze *ira, IrInstruction *instr |
| 7603 | 7645 | ConstPtrMut ptr_mut, bool ptr_is_const, bool ptr_is_volatile) |
| 7604 | 7646 | { |
| 7605 | 7647 | IrInstruction *const_instr = ir_get_const_ptr(ira, instruction, pointee, |
| 7606 | pointee_type, ptr_mut, ptr_is_const, ptr_is_volatile); | |
| 7648 | pointee_type, ptr_mut, ptr_is_const, ptr_is_volatile, | |
| 7649 | get_abi_alignment(ira->codegen, pointee_type)); | |
| 7607 | 7650 | ir_link_new_instruction(const_instr, instruction); |
| 7608 | 7651 | return const_instr->value.type; |
| 7609 | 7652 | } |
| ... | ... | @@ -7876,10 +7919,12 @@ static IrInstruction *ir_get_ref(IrAnalyze *ira, IrInstruction *source_instructi |
| 7876 | 7919 | return ira->codegen->invalid_instruction; |
| 7877 | 7920 | bool final_is_const = (value->value.type->id == TypeTableEntryIdMetaType) ? is_const : true; |
| 7878 | 7921 | return ir_get_const_ptr(ira, source_instruction, val, value->value.type, |
| 7879 | ConstPtrMutComptimeConst, final_is_const, is_volatile); | |
| 7922 | ConstPtrMutComptimeConst, final_is_const, is_volatile, | |
| 7923 | get_abi_alignment(ira->codegen, value->value.type)); | |
| 7880 | 7924 | } |
| 7881 | 7925 | |
| 7882 | TypeTableEntry *ptr_type = get_pointer_to_type_extra(ira->codegen, value->value.type, is_const, is_volatile, 0, 0); | |
| 7926 | TypeTableEntry *ptr_type = get_pointer_to_type_extra(ira->codegen, value->value.type, | |
| 7927 | is_const, is_volatile, get_abi_alignment(ira->codegen, value->value.type), 0, 0); | |
| 7883 | 7928 | FnTableEntry *fn_entry = exec_fn_entry(ira->new_irb.exec); |
| 7884 | 7929 | assert(fn_entry); |
| 7885 | 7930 | IrInstruction *new_instruction = ir_build_ref(&ira->new_irb, source_instruction->scope, |
| ... | ... | @@ -8579,6 +8624,33 @@ static TypeTableEntry *ir_analyze_ref(IrAnalyze *ira, IrInstruction *source_inst |
| 8579 | 8624 | return result->value.type; |
| 8580 | 8625 | } |
| 8581 | 8626 | |
| 8627 | static bool ir_resolve_align(IrAnalyze *ira, IrInstruction *value, uint32_t *out) { | |
| 8628 | if (type_is_invalid(value->value.type)) | |
| 8629 | return false; | |
| 8630 | ||
| 8631 | IrInstruction *casted_value = ir_implicit_cast(ira, value, get_align_amt_type(ira->codegen)); | |
| 8632 | if (type_is_invalid(casted_value->value.type)) | |
| 8633 | return false; | |
| 8634 | ||
| 8635 | ConstExprValue *const_val = ir_resolve_const(ira, casted_value, UndefBad); | |
| 8636 | if (!const_val) | |
| 8637 | return false; | |
| 8638 | ||
| 8639 | uint32_t align_bytes = bigint_as_unsigned(&const_val->data.x_bigint); | |
| 8640 | if (align_bytes == 0) { | |
| 8641 | ir_add_error(ira, value, buf_sprintf("alignment must be >= 1")); | |
| 8642 | return false; | |
| 8643 | } | |
| 8644 | ||
| 8645 | if (!is_power_of_2(align_bytes)) { | |
| 8646 | ir_add_error(ira, value, buf_sprintf("alignment value %" PRIu32 " is not a power of 2", align_bytes)); | |
| 8647 | return false; | |
| 8648 | } | |
| 8649 | ||
| 8650 | *out = align_bytes; | |
| 8651 | return true; | |
| 8652 | } | |
| 8653 | ||
| 8582 | 8654 | static bool ir_resolve_usize(IrAnalyze *ira, IrInstruction *value, uint64_t *out) { |
| 8583 | 8655 | if (type_is_invalid(value->value.type)) |
| 8584 | 8656 | return false; |
| ... | ... | @@ -8656,7 +8728,8 @@ static Buf *ir_resolve_str(IrAnalyze *ira, IrInstruction *value) { |
| 8656 | 8728 | if (type_is_invalid(value->value.type)) |
| 8657 | 8729 | return nullptr; |
| 8658 | 8730 | |
| 8659 | TypeTableEntry *str_type = get_slice_type(ira->codegen, ira->codegen->builtin_types.entry_u8, true); | |
| 8731 | TypeTableEntry *ptr_type = get_pointer_to_type(ira->codegen, ira->codegen->builtin_types.entry_u8, true); | |
| 8732 | TypeTableEntry *str_type = get_slice_type(ira->codegen, ptr_type); | |
| 8660 | 8733 | IrInstruction *casted_value = ir_implicit_cast(ira, value, str_type); |
| 8661 | 8734 | if (type_is_invalid(casted_value->value.type)) |
| 8662 | 8735 | return nullptr; |
| ... | ... | @@ -9715,6 +9788,14 @@ static TypeTableEntry *ir_analyze_instruction_decl_var(IrAnalyze *ira, IrInstruc |
| 9715 | 9788 | |
| 9716 | 9789 | bool is_comptime = ir_get_var_is_comptime(var); |
| 9717 | 9790 | |
| 9791 | if (decl_var_instruction->align_value == nullptr) { | |
| 9792 | var->align_bytes = get_abi_alignment(ira->codegen, result_type); | |
| 9793 | } else { | |
| 9794 | if (!ir_resolve_align(ira, decl_var_instruction->align_value->other, &var->align_bytes)) { | |
| 9795 | var->value->type = ira->codegen->builtin_types.entry_invalid; | |
| 9796 | } | |
| 9797 | } | |
| 9798 | ||
| 9718 | 9799 | if (casted_init_value->value.special != ConstValSpecialRuntime) { |
| 9719 | 9800 | if (var->mem_slot_index != SIZE_MAX) { |
| 9720 | 9801 | assert(var->mem_slot_index < ira->exec_context.mem_slot_count); |
| ... | ... | @@ -9733,7 +9814,7 @@ static TypeTableEntry *ir_analyze_instruction_decl_var(IrAnalyze *ira, IrInstruc |
| 9733 | 9814 | return ira->codegen->builtin_types.entry_invalid; |
| 9734 | 9815 | } |
| 9735 | 9816 | |
| 9736 | ir_build_var_decl_from(&ira->new_irb, &decl_var_instruction->base, var, var_type, casted_init_value); | |
| 9817 | ir_build_var_decl_from(&ira->new_irb, &decl_var_instruction->base, var, var_type, nullptr, casted_init_value); | |
| 9737 | 9818 | |
| 9738 | 9819 | FnTableEntry *fn_entry = exec_fn_entry(ira->new_irb.exec); |
| 9739 | 9820 | if (fn_entry) |
| ... | ... | @@ -9892,11 +9973,12 @@ static IrInstruction *ir_get_var_ptr(IrAnalyze *ira, IrInstruction *instruction, |
| 9892 | 9973 | ptr_mut = ConstPtrMutRuntimeVar; |
| 9893 | 9974 | } |
| 9894 | 9975 | return ir_get_const_ptr(ira, instruction, mem_slot, var->value->type, |
| 9895 | ptr_mut, is_const, is_volatile); | |
| 9976 | ptr_mut, is_const, is_volatile, var->align_bytes); | |
| 9896 | 9977 | } else { |
| 9897 | 9978 | IrInstruction *var_ptr_instruction = ir_build_var_ptr(&ira->new_irb, |
| 9898 | 9979 | instruction->scope, instruction->source_node, var, is_const, is_volatile); |
| 9899 | var_ptr_instruction->value.type = get_pointer_to_type(ira->codegen, var->value->type, var->src_is_const); | |
| 9980 | var_ptr_instruction->value.type = get_pointer_to_type_extra(ira->codegen, var->value->type, | |
| 9981 | var->src_is_const, is_volatile, var->align_bytes, 0, 0); | |
| 9900 | 9982 | type_ensure_zero_bits_known(ira->codegen, var->value->type); |
| 9901 | 9983 | |
| 9902 | 9984 | bool in_fn_scope = (scope_fn_entry(var->parent_scope) != nullptr); |
| ... | ... | @@ -10131,6 +10213,16 @@ static TypeTableEntry *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *cal |
| 10131 | 10213 | impl_fn->child_scope, param_name, true, var_args_val, nullptr); |
| 10132 | 10214 | impl_fn->child_scope = var->child_scope; |
| 10133 | 10215 | } |
| 10216 | ||
| 10217 | if (fn_proto_node->data.fn_proto.align_expr != nullptr) { | |
| 10218 | IrInstruction *align_result = ir_eval_const_value(ira->codegen, impl_fn->child_scope, | |
| 10219 | fn_proto_node->data.fn_proto.align_expr, get_align_amt_type(ira->codegen), | |
| 10220 | ira->new_irb.exec->backward_branch_count, ira->new_irb.exec->backward_branch_quota, | |
| 10221 | nullptr, nullptr, fn_proto_node->data.fn_proto.align_expr, nullptr, ira->new_irb.exec); | |
| 10222 | ||
| 10223 | ir_resolve_align(ira, align_result, &impl_fn->align_bytes); | |
| 10224 | } | |
| 10225 | ||
| 10134 | 10226 | { |
| 10135 | 10227 | AstNode *return_type_node = fn_proto_node->data.fn_proto.return_type; |
| 10136 | 10228 | TypeTableEntry *return_type = analyze_type_expr(ira->codegen, impl_fn->child_scope, return_type_node); |
| ... | ... | @@ -10731,7 +10823,8 @@ static TypeTableEntry *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruc |
| 10731 | 10823 | TypeTableEntry *child_type = array_type->data.array.child_type; |
| 10732 | 10824 | if (ptr_type->data.pointer.unaligned_bit_count == 0) { |
| 10733 | 10825 | return_type = get_pointer_to_type_extra(ira->codegen, child_type, |
| 10734 | ptr_type->data.pointer.is_const, ptr_type->data.pointer.is_volatile, 0, 0); | |
| 10826 | ptr_type->data.pointer.is_const, ptr_type->data.pointer.is_volatile, | |
| 10827 | get_abi_alignment(ira->codegen, child_type), 0, 0); | |
| 10735 | 10828 | } else { |
| 10736 | 10829 | uint64_t elem_val_scalar; |
| 10737 | 10830 | if (!ir_resolve_usize(ira, elem_index, &elem_val_scalar)) |
| ... | ... | @@ -10742,6 +10835,7 @@ static TypeTableEntry *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruc |
| 10742 | 10835 | |
| 10743 | 10836 | return_type = get_pointer_to_type_extra(ira->codegen, child_type, |
| 10744 | 10837 | ptr_type->data.pointer.is_const, ptr_type->data.pointer.is_volatile, |
| 10838 | get_abi_alignment(ira->codegen, child_type), | |
| 10745 | 10839 | (uint32_t)bit_offset, (uint32_t)bit_width); |
| 10746 | 10840 | } |
| 10747 | 10841 | } else if (array_type->id == TypeTableEntryIdPointer) { |
| ... | ... | @@ -10964,6 +11058,8 @@ static TypeTableEntry *ir_analyze_container_field_ptr(IrAnalyze *ira, Buf *field |
| 10964 | 11058 | |
| 10965 | 11059 | TypeStructField *field = find_struct_type_field(bare_type, field_name); |
| 10966 | 11060 | if (field) { |
| 11061 | bool is_packed = (bare_type->data.structure.layout == ContainerLayoutPacked); | |
| 11062 | uint32_t align_bytes = is_packed ? 1 : get_abi_alignment(ira->codegen, field->type_entry); | |
| 10967 | 11063 | if (instr_is_comptime(container_ptr)) { |
| 10968 | 11064 | ConstExprValue *ptr_val = ir_resolve_const(ira, container_ptr, UndefBad); |
| 10969 | 11065 | if (!ptr_val) |
| ... | ... | @@ -10973,7 +11069,7 @@ static TypeTableEntry *ir_analyze_container_field_ptr(IrAnalyze *ira, Buf *field |
| 10973 | 11069 | ConstExprValue *struct_val = const_ptr_pointee(ira->codegen, ptr_val); |
| 10974 | 11070 | ConstExprValue *field_val = &struct_val->data.x_struct.fields[field->src_index]; |
| 10975 | 11071 | TypeTableEntry *ptr_type = get_pointer_to_type_extra(ira->codegen, field_val->type, |
| 10976 | is_const, is_volatile, 0, 0); | |
| 11072 | is_const, is_volatile, align_bytes, 0, 0); | |
| 10977 | 11073 | ConstExprValue *const_val = ir_build_const_from(ira, &field_ptr_instruction->base); |
| 10978 | 11074 | const_val->data.x_ptr.special = ConstPtrSpecialBaseStruct; |
| 10979 | 11075 | const_val->data.x_ptr.mut = container_ptr->value.data.x_ptr.mut; |
| ... | ... | @@ -10988,6 +11084,7 @@ static TypeTableEntry *ir_analyze_container_field_ptr(IrAnalyze *ira, Buf *field |
| 10988 | 11084 | field->unaligned_bit_count : type_size_bits(ira->codegen, field->type_entry); |
| 10989 | 11085 | ir_build_struct_field_ptr_from(&ira->new_irb, &field_ptr_instruction->base, container_ptr, field); |
| 10990 | 11086 | return get_pointer_to_type_extra(ira->codegen, field->type_entry, is_const, is_volatile, |
| 11087 | align_bytes, | |
| 10991 | 11088 | (uint32_t)(ptr_bit_offset + field->packed_bits_offset), |
| 10992 | 11089 | (uint32_t)unaligned_bit_count_for_result_type); |
| 10993 | 11090 | } else { |
| ... | ... | @@ -11001,7 +11098,8 @@ static TypeTableEntry *ir_analyze_container_field_ptr(IrAnalyze *ira, Buf *field |
| 11001 | 11098 | TypeEnumField *field = find_enum_type_field(bare_type, field_name); |
| 11002 | 11099 | if (field) { |
| 11003 | 11100 | ir_build_enum_field_ptr_from(&ira->new_irb, &field_ptr_instruction->base, container_ptr, field); |
| 11004 | return get_pointer_to_type_extra(ira->codegen, field->type_entry, is_const, is_volatile, 0, 0); | |
| 11101 | return get_pointer_to_type_extra(ira->codegen, field->type_entry, is_const, is_volatile, | |
| 11102 | get_abi_alignment(ira->codegen, field->type_entry), 0, 0); | |
| 11005 | 11103 | } else { |
| 11006 | 11104 | return ir_analyze_container_member_access_inner(ira, bare_type, field_name, |
| 11007 | 11105 | field_ptr_instruction, container_ptr, container_type); |
| ... | ... | @@ -11427,7 +11525,6 @@ static TypeTableEntry *ir_analyze_instruction_ptr_type_child(IrAnalyze *ira, |
| 11427 | 11525 | if (type_is_invalid(type_entry)) |
| 11428 | 11526 | return type_entry; |
| 11429 | 11527 | |
| 11430 | // TODO handle typedefs | |
| 11431 | 11528 | if (type_entry->id != TypeTableEntryIdPointer) { |
| 11432 | 11529 | ir_add_error_node(ira, ptr_type_child_instruction->base.source_node, |
| 11433 | 11530 | buf_sprintf("expected pointer type, found '%s'", buf_ptr(&type_entry->name))); |
| ... | ... | @@ -11439,69 +11536,6 @@ static TypeTableEntry *ir_analyze_instruction_ptr_type_child(IrAnalyze *ira, |
| 11439 | 11536 | return ira->codegen->builtin_types.entry_type; |
| 11440 | 11537 | } |
| 11441 | 11538 | |
| 11442 | static TypeTableEntry *ir_analyze_instruction_set_global_align(IrAnalyze *ira, | |
| 11443 | IrInstructionSetGlobalAlign *instruction) | |
| 11444 | { | |
| 11445 | Tld *tld = instruction->tld; | |
| 11446 | IrInstruction *align_value = instruction->value->other; | |
| 11447 | ||
| 11448 | resolve_top_level_decl(ira->codegen, tld, true, instruction->base.source_node); | |
| 11449 | if (tld->resolution == TldResolutionInvalid) | |
| 11450 | return ira->codegen->builtin_types.entry_invalid; | |
| 11451 | ||
| 11452 | uint64_t scalar_align; | |
| 11453 | if (!ir_resolve_usize(ira, align_value, &scalar_align)) | |
| 11454 | return ira->codegen->builtin_types.entry_invalid; | |
| 11455 | ||
| 11456 | if (!is_power_of_2(scalar_align)) { | |
| 11457 | ir_add_error(ira, instruction->value, buf_sprintf("alignment value must be power of 2")); | |
| 11458 | return ira->codegen->builtin_types.entry_invalid; | |
| 11459 | } | |
| 11460 | ||
| 11461 | AstNode **set_global_align_node; | |
| 11462 | uint32_t *alignment_ptr; | |
| 11463 | if (tld->id == TldIdVar) { | |
| 11464 | TldVar *tld_var = (TldVar *)tld; | |
| 11465 | set_global_align_node = &tld_var->set_global_align_node; | |
| 11466 | alignment_ptr = &tld_var->alignment; | |
| 11467 | ||
| 11468 | if (tld_var->var->linkage == VarLinkageExternal) { | |
| 11469 | ErrorMsg *msg = ir_add_error(ira, &instruction->base, | |
| 11470 | buf_sprintf("cannot set alignment of external variable '%s'", buf_ptr(&tld_var->var->name))); | |
| 11471 | add_error_note(ira->codegen, msg, tld->source_node, buf_sprintf("declared here")); | |
| 11472 | return ira->codegen->builtin_types.entry_invalid; | |
| 11473 | } | |
| 11474 | } else if (tld->id == TldIdFn) { | |
| 11475 | TldFn *tld_fn = (TldFn *)tld; | |
| 11476 | FnTableEntry *fn_entry = tld_fn->fn_entry; | |
| 11477 | set_global_align_node = &fn_entry->set_global_align_node; | |
| 11478 | alignment_ptr = &fn_entry->alignment; | |
| 11479 | ||
| 11480 | if (fn_entry->def_scope == nullptr) { | |
| 11481 | ErrorMsg *msg = ir_add_error(ira, &instruction->base, | |
| 11482 | buf_sprintf("cannot set alignment of external function '%s'", buf_ptr(&fn_entry->symbol_name))); | |
| 11483 | add_error_note(ira->codegen, msg, tld->source_node, buf_sprintf("declared here")); | |
| 11484 | return ira->codegen->builtin_types.entry_invalid; | |
| 11485 | } | |
| 11486 | } else { | |
| 11487 | // error is caught in pass1 IR gen | |
| 11488 | zig_unreachable(); | |
| 11489 | } | |
| 11490 | ||
| 11491 | AstNode *source_node = instruction->base.source_node; | |
| 11492 | if (*set_global_align_node) { | |
| 11493 | ErrorMsg *msg = ir_add_error_node(ira, source_node, | |
| 11494 | buf_sprintf("alignment set twice")); | |
| 11495 | add_error_note(ira->codegen, msg, *set_global_align_node, buf_sprintf("first set here")); | |
| 11496 | return ira->codegen->builtin_types.entry_invalid; | |
| 11497 | } | |
| 11498 | *set_global_align_node = source_node; | |
| 11499 | *alignment_ptr = (uint32_t)scalar_align; | |
| 11500 | ||
| 11501 | ir_build_const_from(ira, &instruction->base); | |
| 11502 | return ira->codegen->builtin_types.entry_void; | |
| 11503 | } | |
| 11504 | ||
| 11505 | 11539 | static TypeTableEntry *ir_analyze_instruction_set_global_section(IrAnalyze *ira, |
| 11506 | 11540 | IrInstructionSetGlobalSection *instruction) |
| 11507 | 11541 | { |
| ... | ... | @@ -11750,16 +11784,24 @@ static TypeTableEntry *ir_analyze_instruction_set_float_mode(IrAnalyze *ira, |
| 11750 | 11784 | static TypeTableEntry *ir_analyze_instruction_slice_type(IrAnalyze *ira, |
| 11751 | 11785 | IrInstructionSliceType *slice_type_instruction) |
| 11752 | 11786 | { |
| 11753 | IrInstruction *child_type = slice_type_instruction->child_type->other; | |
| 11754 | if (type_is_invalid(child_type->value.type)) | |
| 11755 | return ira->codegen->builtin_types.entry_invalid; | |
| 11756 | bool is_const = slice_type_instruction->is_const; | |
| 11787 | uint32_t align_bytes; | |
| 11788 | if (slice_type_instruction->align_value != nullptr) { | |
| 11789 | if (!ir_resolve_align(ira, slice_type_instruction->align_value->other, &align_bytes)) | |
| 11790 | return ira->codegen->builtin_types.entry_invalid; | |
| 11791 | } | |
| 11757 | 11792 | |
| 11758 | TypeTableEntry *resolved_child_type = ir_resolve_type(ira, child_type); | |
| 11759 | if (type_is_invalid(resolved_child_type)) | |
| 11793 | TypeTableEntry *child_type = ir_resolve_type(ira, slice_type_instruction->child_type->other); | |
| 11794 | if (type_is_invalid(child_type)) | |
| 11760 | 11795 | return ira->codegen->builtin_types.entry_invalid; |
| 11761 | 11796 | |
| 11762 | switch (resolved_child_type->id) { | |
| 11797 | if (slice_type_instruction->align_value == nullptr) { | |
| 11798 | align_bytes = get_abi_alignment(ira->codegen, child_type); | |
| 11799 | } | |
| 11800 | ||
| 11801 | bool is_const = slice_type_instruction->is_const; | |
| 11802 | bool is_volatile = slice_type_instruction->is_volatile; | |
| 11803 | ||
| 11804 | switch (child_type->id) { | |
| 11763 | 11805 | case TypeTableEntryIdInvalid: // handled above |
| 11764 | 11806 | zig_unreachable(); |
| 11765 | 11807 | case TypeTableEntryIdVar: |
| ... | ... | @@ -11770,7 +11812,7 @@ static TypeTableEntry *ir_analyze_instruction_slice_type(IrAnalyze *ira, |
| 11770 | 11812 | case TypeTableEntryIdArgTuple: |
| 11771 | 11813 | case TypeTableEntryIdOpaque: |
| 11772 | 11814 | ir_add_error_node(ira, slice_type_instruction->base.source_node, |
| 11773 | buf_sprintf("slice of type '%s' not allowed", buf_ptr(&resolved_child_type->name))); | |
| 11815 | buf_sprintf("slice of type '%s' not allowed", buf_ptr(&child_type->name))); | |
| 11774 | 11816 | return ira->codegen->builtin_types.entry_invalid; |
| 11775 | 11817 | case TypeTableEntryIdMetaType: |
| 11776 | 11818 | case TypeTableEntryIdVoid: |
| ... | ... | @@ -11792,8 +11834,10 @@ static TypeTableEntry *ir_analyze_instruction_slice_type(IrAnalyze *ira, |
| 11792 | 11834 | case TypeTableEntryIdBoundFn: |
| 11793 | 11835 | case TypeTableEntryIdEnumTag: |
| 11794 | 11836 | { |
| 11795 | type_ensure_zero_bits_known(ira->codegen, resolved_child_type); | |
| 11796 | TypeTableEntry *result_type = get_slice_type(ira->codegen, resolved_child_type, is_const); | |
| 11837 | type_ensure_zero_bits_known(ira->codegen, child_type); | |
| 11838 | TypeTableEntry *slice_ptr_type = get_pointer_to_type_extra(ira->codegen, child_type, | |
| 11839 | is_const, is_volatile, align_bytes, 0, 0); | |
| 11840 | TypeTableEntry *result_type = get_slice_type(ira->codegen, slice_ptr_type); | |
| 11797 | 11841 | ConstExprValue *out_val = ir_build_const_from(ira, &slice_type_instruction->base); |
| 11798 | 11842 | out_val->data.x_type = result_type; |
| 11799 | 11843 | return ira->codegen->builtin_types.entry_type; |
| ... | ... | @@ -12018,7 +12062,6 @@ static TypeTableEntry *ir_analyze_instruction_unwrap_maybe(IrAnalyze *ira, |
| 12018 | 12062 | assert(ptr_type->id == TypeTableEntryIdPointer); |
| 12019 | 12063 | |
| 12020 | 12064 | TypeTableEntry *type_entry = ptr_type->data.pointer.child_type; |
| 12021 | // TODO handle typedef | |
| 12022 | 12065 | if (type_is_invalid(type_entry)) { |
| 12023 | 12066 | return ira->codegen->builtin_types.entry_invalid; |
| 12024 | 12067 | } else if (type_entry->id != TypeTableEntryIdMaybe) { |
| ... | ... | @@ -12028,7 +12071,8 @@ static TypeTableEntry *ir_analyze_instruction_unwrap_maybe(IrAnalyze *ira, |
| 12028 | 12071 | } |
| 12029 | 12072 | TypeTableEntry *child_type = type_entry->data.maybe.child_type; |
| 12030 | 12073 | TypeTableEntry *result_type = get_pointer_to_type_extra(ira->codegen, child_type, |
| 12031 | ptr_type->data.pointer.is_const, ptr_type->data.pointer.is_volatile, 0, 0); | |
| 12074 | ptr_type->data.pointer.is_const, ptr_type->data.pointer.is_volatile, | |
| 12075 | get_abi_alignment(ira->codegen, child_type), 0, 0); | |
| 12032 | 12076 | |
| 12033 | 12077 | if (instr_is_comptime(value)) { |
| 12034 | 12078 | ConstExprValue *val = ir_resolve_const(ira, value, UndefBad); |
| ... | ... | @@ -12887,7 +12931,8 @@ static TypeTableEntry *ir_analyze_instruction_err_name(IrAnalyze *ira, IrInstruc |
| 12887 | 12931 | if (type_is_invalid(casted_value->value.type)) |
| 12888 | 12932 | return ira->codegen->builtin_types.entry_invalid; |
| 12889 | 12933 | |
| 12890 | TypeTableEntry *str_type = get_slice_type(ira->codegen, ira->codegen->builtin_types.entry_u8, true); | |
| 12934 | TypeTableEntry *u8_ptr_type = get_pointer_to_type(ira->codegen, ira->codegen->builtin_types.entry_u8, true); | |
| 12935 | TypeTableEntry *str_type = get_slice_type(ira->codegen, u8_ptr_type); | |
| 12891 | 12936 | if (casted_value->value.special == ConstValSpecialStatic) { |
| 12892 | 12937 | ErrorTableEntry *err = casted_value->value.data.x_pure_err; |
| 12893 | 12938 | if (!err->cached_error_name_val) { |
| ... | ... | @@ -12929,7 +12974,8 @@ static TypeTableEntry *ir_analyze_instruction_enum_tag_name(IrAnalyze *ira, IrIn |
| 12929 | 12974 | IrInstruction *result = ir_build_enum_tag_name(&ira->new_irb, instruction->base.scope, |
| 12930 | 12975 | instruction->base.source_node, target); |
| 12931 | 12976 | ir_link_new_instruction(result, &instruction->base); |
| 12932 | result->value.type = get_slice_type(ira->codegen, ira->codegen->builtin_types.entry_u8, true); | |
| 12977 | TypeTableEntry *u8_ptr_type = get_pointer_to_type(ira->codegen, ira->codegen->builtin_types.entry_u8, true); | |
| 12978 | result->value.type = get_slice_type(ira->codegen, u8_ptr_type); | |
| 12933 | 12979 | return result->value.type; |
| 12934 | 12980 | } |
| 12935 | 12981 | |
| ... | ... | @@ -12972,16 +13018,22 @@ static TypeTableEntry *ir_analyze_instruction_field_parent_ptr(IrAnalyze *ira, |
| 12972 | 13018 | return ira->codegen->builtin_types.entry_invalid; |
| 12973 | 13019 | } |
| 12974 | 13020 | |
| 13021 | bool is_packed = (container_type->data.structure.layout == ContainerLayoutPacked); | |
| 13022 | uint32_t field_ptr_align = is_packed ? 1 : get_abi_alignment(ira->codegen, field->type_entry); | |
| 13023 | uint32_t parent_ptr_align = is_packed ? 1 : get_abi_alignment(ira->codegen, container_type); | |
| 13024 | ||
| 12975 | 13025 | TypeTableEntry *field_ptr_type = get_pointer_to_type_extra(ira->codegen, field->type_entry, |
| 12976 | 13026 | field_ptr->value.type->data.pointer.is_const, |
| 12977 | field_ptr->value.type->data.pointer.is_volatile, 0, 0); | |
| 13027 | field_ptr->value.type->data.pointer.is_volatile, | |
| 13028 | field_ptr_align, 0, 0); | |
| 12978 | 13029 | IrInstruction *casted_field_ptr = ir_implicit_cast(ira, field_ptr, field_ptr_type); |
| 12979 | 13030 | if (type_is_invalid(casted_field_ptr->value.type)) |
| 12980 | 13031 | return ira->codegen->builtin_types.entry_invalid; |
| 12981 | 13032 | |
| 12982 | 13033 | TypeTableEntry *result_type = get_pointer_to_type_extra(ira->codegen, container_type, |
| 12983 | 13034 | casted_field_ptr->value.type->data.pointer.is_const, |
| 12984 | casted_field_ptr->value.type->data.pointer.is_volatile, 0, 0); | |
| 13035 | casted_field_ptr->value.type->data.pointer.is_volatile, | |
| 13036 | parent_ptr_align, 0, 0); | |
| 12985 | 13037 | |
| 12986 | 13038 | if (instr_is_comptime(casted_field_ptr)) { |
| 12987 | 13039 | ConstExprValue *field_ptr_val = ir_resolve_const(ira, casted_field_ptr, UndefBad); |
| ... | ... | @@ -13436,7 +13488,9 @@ static TypeTableEntry *ir_analyze_instruction_memset(IrAnalyze *ira, IrInstructi |
| 13436 | 13488 | |
| 13437 | 13489 | TypeTableEntry *usize = ira->codegen->builtin_types.entry_usize; |
| 13438 | 13490 | TypeTableEntry *u8 = ira->codegen->builtin_types.entry_u8; |
| 13439 | TypeTableEntry *u8_ptr = get_pointer_to_type_extra(ira->codegen, u8, false, dest_is_volatile, 0, 0); | |
| 13491 | uint32_t dest_align = (dest_uncasted_type->id == TypeTableEntryIdPointer) ? | |
| 13492 | dest_uncasted_type->data.pointer.alignment : get_abi_alignment(ira->codegen, u8); | |
| 13493 | TypeTableEntry *u8_ptr = get_pointer_to_type_extra(ira->codegen, u8, false, dest_is_volatile, dest_align, 0, 0); | |
| 13440 | 13494 | |
| 13441 | 13495 | IrInstruction *casted_dest_ptr = ir_implicit_cast(ira, dest_ptr, u8_ptr); |
| 13442 | 13496 | if (type_is_invalid(casted_dest_ptr->value.type)) |
| ... | ... | @@ -13517,17 +13571,21 @@ static TypeTableEntry *ir_analyze_instruction_memcpy(IrAnalyze *ira, IrInstructi |
| 13517 | 13571 | if (type_is_invalid(count_value->value.type)) |
| 13518 | 13572 | return ira->codegen->builtin_types.entry_invalid; |
| 13519 | 13573 | |
| 13574 | TypeTableEntry *u8 = ira->codegen->builtin_types.entry_u8; | |
| 13520 | 13575 | TypeTableEntry *dest_uncasted_type = dest_ptr->value.type; |
| 13521 | 13576 | TypeTableEntry *src_uncasted_type = src_ptr->value.type; |
| 13522 | 13577 | bool dest_is_volatile = (dest_uncasted_type->id == TypeTableEntryIdPointer) && |
| 13523 | 13578 | dest_uncasted_type->data.pointer.is_volatile; |
| 13524 | 13579 | bool src_is_volatile = (src_uncasted_type->id == TypeTableEntryIdPointer) && |
| 13525 | 13580 | src_uncasted_type->data.pointer.is_volatile; |
| 13581 | uint32_t dest_align = (dest_uncasted_type->id == TypeTableEntryIdPointer) ? | |
| 13582 | dest_uncasted_type->data.pointer.alignment : get_abi_alignment(ira->codegen, u8); | |
| 13583 | uint32_t src_align = (src_uncasted_type->id == TypeTableEntryIdPointer) ? | |
| 13584 | src_uncasted_type->data.pointer.alignment : get_abi_alignment(ira->codegen, u8); | |
| 13526 | 13585 | |
| 13527 | 13586 | TypeTableEntry *usize = ira->codegen->builtin_types.entry_usize; |
| 13528 | TypeTableEntry *u8 = ira->codegen->builtin_types.entry_u8; | |
| 13529 | TypeTableEntry *u8_ptr_mut = get_pointer_to_type_extra(ira->codegen, u8, false, dest_is_volatile, 0, 0); | |
| 13530 | TypeTableEntry *u8_ptr_const = get_pointer_to_type_extra(ira->codegen, u8, true, src_is_volatile, 0, 0); | |
| 13587 | TypeTableEntry *u8_ptr_mut = get_pointer_to_type_extra(ira->codegen, u8, false, dest_is_volatile, dest_align, 0, 0); | |
| 13588 | TypeTableEntry *u8_ptr_const = get_pointer_to_type_extra(ira->codegen, u8, true, src_is_volatile, src_align, 0, 0); | |
| 13531 | 13589 | |
| 13532 | 13590 | IrInstruction *casted_dest_ptr = ir_implicit_cast(ira, dest_ptr, u8_ptr_mut); |
| 13533 | 13591 | if (type_is_invalid(casted_dest_ptr->value.type)) |
| ... | ... | @@ -13662,17 +13720,24 @@ static TypeTableEntry *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstructio |
| 13662 | 13720 | TypeTableEntry *return_type; |
| 13663 | 13721 | |
| 13664 | 13722 | if (array_type->id == TypeTableEntryIdArray) { |
| 13665 | return_type = get_slice_type(ira->codegen, array_type->data.array.child_type, ptr_type->data.pointer.is_const); | |
| 13723 | uint32_t normal_array_alignment = get_abi_alignment(ira->codegen, array_type); | |
| 13724 | uint32_t align_bytes = (ptr_type->data.pointer.alignment >= normal_array_alignment) ? | |
| 13725 | normal_array_alignment : 1; | |
| 13726 | TypeTableEntry *slice_ptr_type = get_pointer_to_type_extra(ira->codegen, array_type->data.array.child_type, | |
| 13727 | ptr_type->data.pointer.is_const, ptr_type->data.pointer.is_volatile, align_bytes, 0, 0); | |
| 13728 | return_type = get_slice_type(ira->codegen, slice_ptr_type); | |
| 13666 | 13729 | } else if (array_type->id == TypeTableEntryIdPointer) { |
| 13667 | return_type = get_slice_type(ira->codegen, array_type->data.pointer.child_type, | |
| 13668 | array_type->data.pointer.is_const); | |
| 13730 | TypeTableEntry *slice_ptr_type = get_pointer_to_type_extra(ira->codegen, array_type->data.pointer.child_type, | |
| 13731 | array_type->data.pointer.is_const, array_type->data.pointer.is_volatile, | |
| 13732 | array_type->data.pointer.alignment, 0, 0); | |
| 13733 | return_type = get_slice_type(ira->codegen, slice_ptr_type); | |
| 13669 | 13734 | if (!end) { |
| 13670 | 13735 | ir_add_error(ira, &instruction->base, buf_sprintf("slice of pointer must include end value")); |
| 13671 | 13736 | return ira->codegen->builtin_types.entry_invalid; |
| 13672 | 13737 | } |
| 13673 | 13738 | } else if (is_slice(array_type)) { |
| 13674 | 13739 | TypeTableEntry *ptr_type = array_type->data.structure.fields[slice_ptr_index].type_entry; |
| 13675 | return_type = get_slice_type(ira->codegen, ptr_type->data.pointer.child_type, ptr_type->data.pointer.is_const); | |
| 13740 | return_type = get_slice_type(ira->codegen, ptr_type); | |
| 13676 | 13741 | } else { |
| 13677 | 13742 | ir_add_error(ira, &instruction->base, |
| 13678 | 13743 | buf_sprintf("slice of non-array type '%s'", buf_ptr(&array_type->name))); |
| ... | ... | @@ -13860,7 +13925,7 @@ static TypeTableEntry *ir_analyze_instruction_frame_address(IrAnalyze *ira, IrIn |
| 13860 | 13925 | return u8_ptr_const; |
| 13861 | 13926 | } |
| 13862 | 13927 | |
| 13863 | static TypeTableEntry *ir_analyze_instruction_preferred_align_of(IrAnalyze *ira, IrInstructionPreferredAlignOf *instruction) { | |
| 13928 | static TypeTableEntry *ir_analyze_instruction_align_of(IrAnalyze *ira, IrInstructionAlignOf *instruction) { | |
| 13864 | 13929 | IrInstruction *type_value = instruction->type_value->other; |
| 13865 | 13930 | if (type_is_invalid(type_value->value.type)) |
| 13866 | 13931 | return ira->codegen->builtin_types.entry_invalid; |
| ... | ... | @@ -13884,62 +13949,11 @@ static TypeTableEntry *ir_analyze_instruction_preferred_align_of(IrAnalyze *ira, |
| 13884 | 13949 | case TypeTableEntryIdBlock: |
| 13885 | 13950 | case TypeTableEntryIdBoundFn: |
| 13886 | 13951 | case TypeTableEntryIdArgTuple: |
| 13887 | ir_add_error(ira, instruction->type_value, | |
| 13888 | buf_sprintf("no align available for type '%s'", buf_ptr(&type_entry->name))); | |
| 13889 | return ira->codegen->builtin_types.entry_invalid; | |
| 13890 | 13952 | case TypeTableEntryIdVoid: |
| 13891 | case TypeTableEntryIdBool: | |
| 13892 | case TypeTableEntryIdInt: | |
| 13893 | case TypeTableEntryIdFloat: | |
| 13894 | case TypeTableEntryIdPointer: | |
| 13895 | case TypeTableEntryIdArray: | |
| 13896 | case TypeTableEntryIdStruct: | |
| 13897 | case TypeTableEntryIdMaybe: | |
| 13898 | case TypeTableEntryIdErrorUnion: | |
| 13899 | case TypeTableEntryIdPureError: | |
| 13900 | case TypeTableEntryIdEnum: | |
| 13901 | case TypeTableEntryIdEnumTag: | |
| 13902 | case TypeTableEntryIdUnion: | |
| 13903 | case TypeTableEntryIdFn: | |
| 13904 | 13953 | case TypeTableEntryIdOpaque: |
| 13905 | { | |
| 13906 | uint64_t align_in_bytes = LLVMPreferredAlignmentOfType(ira->codegen->target_data_ref, type_entry->type_ref); | |
| 13907 | ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base); | |
| 13908 | bigint_init_unsigned(&out_val->data.x_bigint, align_in_bytes); | |
| 13909 | return ira->codegen->builtin_types.entry_num_lit_int; | |
| 13910 | } | |
| 13911 | } | |
| 13912 | zig_unreachable(); | |
| 13913 | } | |
| 13914 | ||
| 13915 | static TypeTableEntry *ir_analyze_instruction_abi_align_of(IrAnalyze *ira, IrInstructionAbiAlignOf *instruction) { | |
| 13916 | IrInstruction *type_value = instruction->type_value->other; | |
| 13917 | if (type_is_invalid(type_value->value.type)) | |
| 13918 | return ira->codegen->builtin_types.entry_invalid; | |
| 13919 | TypeTableEntry *type_entry = ir_resolve_type(ira, type_value); | |
| 13920 | ||
| 13921 | ensure_complete_type(ira->codegen, type_entry); | |
| 13922 | if (type_is_invalid(type_entry)) | |
| 13923 | return ira->codegen->builtin_types.entry_invalid; | |
| 13924 | ||
| 13925 | switch (type_entry->id) { | |
| 13926 | case TypeTableEntryIdInvalid: | |
| 13927 | case TypeTableEntryIdVar: | |
| 13928 | zig_unreachable(); | |
| 13929 | case TypeTableEntryIdMetaType: | |
| 13930 | case TypeTableEntryIdUnreachable: | |
| 13931 | case TypeTableEntryIdNumLitFloat: | |
| 13932 | case TypeTableEntryIdNumLitInt: | |
| 13933 | case TypeTableEntryIdUndefLit: | |
| 13934 | case TypeTableEntryIdNullLit: | |
| 13935 | case TypeTableEntryIdNamespace: | |
| 13936 | case TypeTableEntryIdBlock: | |
| 13937 | case TypeTableEntryIdBoundFn: | |
| 13938 | case TypeTableEntryIdArgTuple: | |
| 13939 | 13954 | ir_add_error(ira, instruction->type_value, |
| 13940 | 13955 | buf_sprintf("no align available for type '%s'", buf_ptr(&type_entry->name))); |
| 13941 | 13956 | return ira->codegen->builtin_types.entry_invalid; |
| 13942 | case TypeTableEntryIdVoid: | |
| 13943 | 13957 | case TypeTableEntryIdBool: |
| 13944 | 13958 | case TypeTableEntryIdInt: |
| 13945 | 13959 | case TypeTableEntryIdFloat: |
| ... | ... | @@ -13953,9 +13967,8 @@ static TypeTableEntry *ir_analyze_instruction_abi_align_of(IrAnalyze *ira, IrIns |
| 13953 | 13967 | case TypeTableEntryIdEnumTag: |
| 13954 | 13968 | case TypeTableEntryIdUnion: |
| 13955 | 13969 | case TypeTableEntryIdFn: |
| 13956 | case TypeTableEntryIdOpaque: | |
| 13957 | 13970 | { |
| 13958 | uint64_t align_in_bytes = LLVMABIAlignmentOfType(ira->codegen->target_data_ref, type_entry->type_ref); | |
| 13971 | uint64_t align_in_bytes = get_abi_alignment(ira->codegen, type_entry); | |
| 13959 | 13972 | ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base); |
| 13960 | 13973 | bigint_init_unsigned(&out_val->data.x_bigint, align_in_bytes); |
| 13961 | 13974 | return ira->codegen->builtin_types.entry_num_lit_int; |
| ... | ... | @@ -14143,7 +14156,8 @@ static TypeTableEntry *ir_analyze_instruction_unwrap_err_payload(IrAnalyze *ira, |
| 14143 | 14156 | } else if (type_entry->id == TypeTableEntryIdErrorUnion) { |
| 14144 | 14157 | TypeTableEntry *child_type = type_entry->data.error.child_type; |
| 14145 | 14158 | TypeTableEntry *result_type = get_pointer_to_type_extra(ira->codegen, child_type, |
| 14146 | ptr_type->data.pointer.is_const, ptr_type->data.pointer.is_volatile, 0, 0); | |
| 14159 | ptr_type->data.pointer.is_const, ptr_type->data.pointer.is_volatile, | |
| 14160 | get_abi_alignment(ira->codegen, child_type), 0, 0); | |
| 14147 | 14161 | if (instr_is_comptime(value)) { |
| 14148 | 14162 | ConstExprValue *ptr_val = ir_resolve_const(ira, value, UndefBad); |
| 14149 | 14163 | if (!ptr_val) |
| ... | ... | @@ -14390,7 +14404,8 @@ static TypeTableEntry *ir_analyze_instruction_panic(IrAnalyze *ira, IrInstructio |
| 14390 | 14404 | if (type_is_invalid(msg->value.type)) |
| 14391 | 14405 | return ira->codegen->builtin_types.entry_invalid; |
| 14392 | 14406 | |
| 14393 | TypeTableEntry *str_type = get_slice_type(ira->codegen, ira->codegen->builtin_types.entry_u8, true); | |
| 14407 | TypeTableEntry *u8_ptr_type = get_pointer_to_type(ira->codegen, ira->codegen->builtin_types.entry_u8, true); | |
| 14408 | TypeTableEntry *str_type = get_slice_type(ira->codegen, u8_ptr_type); | |
| 14394 | 14409 | IrInstruction *casted_msg = ir_implicit_cast(ira, msg, str_type); |
| 14395 | 14410 | if (type_is_invalid(casted_msg->value.type)) |
| 14396 | 14411 | return ira->codegen->builtin_types.entry_invalid; |
| ... | ... | @@ -14814,6 +14829,23 @@ static TypeTableEntry *ir_analyze_instruction_ptr_to_int(IrAnalyze *ira, IrInstr |
| 14814 | 14829 | return usize; |
| 14815 | 14830 | } |
| 14816 | 14831 | |
| 14832 | static TypeTableEntry *ir_analyze_instruction_ptr_type_of(IrAnalyze *ira, IrInstructionPtrTypeOf *instruction) { | |
| 14833 | TypeTableEntry *child_type = ir_resolve_type(ira, instruction->child_type->other); | |
| 14834 | if (type_is_invalid(child_type)) | |
| 14835 | return ira->codegen->builtin_types.entry_invalid; | |
| 14836 | ||
| 14837 | uint32_t align_bytes; | |
| 14838 | if (!ir_resolve_align(ira, instruction->align_value->other, &align_bytes)) | |
| 14839 | return ira->codegen->builtin_types.entry_invalid; | |
| 14840 | ||
| 14841 | ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base); | |
| 14842 | out_val->data.x_type = get_pointer_to_type_extra(ira->codegen, child_type, | |
| 14843 | instruction->is_const, instruction->is_volatile, align_bytes, | |
| 14844 | instruction->bit_offset_start, instruction->bit_offset_end); | |
| 14845 | ||
| 14846 | return ira->codegen->builtin_types.entry_type; | |
| 14847 | } | |
| 14848 | ||
| 14817 | 14849 | static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstruction *instruction) { |
| 14818 | 14850 | switch (instruction->id) { |
| 14819 | 14851 | case IrInstructionIdInvalid: |
| ... | ... | @@ -14862,8 +14894,6 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi |
| 14862 | 14894 | return ir_analyze_instruction_to_ptr_type(ira, (IrInstructionToPtrType *)instruction); |
| 14863 | 14895 | case IrInstructionIdPtrTypeChild: |
| 14864 | 14896 | return ir_analyze_instruction_ptr_type_child(ira, (IrInstructionPtrTypeChild *)instruction); |
| 14865 | case IrInstructionIdSetGlobalAlign: | |
| 14866 | return ir_analyze_instruction_set_global_align(ira, (IrInstructionSetGlobalAlign *)instruction); | |
| 14867 | 14897 | case IrInstructionIdSetGlobalSection: |
| 14868 | 14898 | return ir_analyze_instruction_set_global_section(ira, (IrInstructionSetGlobalSection *)instruction); |
| 14869 | 14899 | case IrInstructionIdSetGlobalLinkage: |
| ... | ... | @@ -14952,10 +14982,8 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi |
| 14952 | 14982 | return ir_analyze_instruction_return_address(ira, (IrInstructionReturnAddress *)instruction); |
| 14953 | 14983 | case IrInstructionIdFrameAddress: |
| 14954 | 14984 | return ir_analyze_instruction_frame_address(ira, (IrInstructionFrameAddress *)instruction); |
| 14955 | case IrInstructionIdPreferredAlignOf: | |
| 14956 | return ir_analyze_instruction_preferred_align_of(ira, (IrInstructionPreferredAlignOf *)instruction); | |
| 14957 | case IrInstructionIdAbiAlignOf: | |
| 14958 | return ir_analyze_instruction_abi_align_of(ira, (IrInstructionAbiAlignOf *)instruction); | |
| 14985 | case IrInstructionIdAlignOf: | |
| 14986 | return ir_analyze_instruction_align_of(ira, (IrInstructionAlignOf *)instruction); | |
| 14959 | 14987 | case IrInstructionIdOverflowOp: |
| 14960 | 14988 | return ir_analyze_instruction_overflow_op(ira, (IrInstructionOverflowOp *)instruction); |
| 14961 | 14989 | case IrInstructionIdTestErr: |
| ... | ... | @@ -14996,6 +15024,8 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi |
| 14996 | 15024 | return ir_analyze_instruction_type_id(ira, (IrInstructionTypeId *)instruction); |
| 14997 | 15025 | case IrInstructionIdSetEvalBranchQuota: |
| 14998 | 15026 | return ir_analyze_instruction_set_eval_branch_quota(ira, (IrInstructionSetEvalBranchQuota *)instruction); |
| 15027 | case IrInstructionIdPtrTypeOf: | |
| 15028 | return ir_analyze_instruction_ptr_type_of(ira, (IrInstructionPtrTypeOf *)instruction); | |
| 14999 | 15029 | case IrInstructionIdMaybeWrap: |
| 15000 | 15030 | case IrInstructionIdErrWrapCode: |
| 15001 | 15031 | case IrInstructionIdErrWrapPayload: |
| ... | ... | @@ -15108,11 +15138,11 @@ bool ir_has_side_effects(IrInstruction *instruction) { |
| 15108 | 15138 | case IrInstructionIdOverflowOp: // TODO when we support multiple returns this can be side effect free |
| 15109 | 15139 | case IrInstructionIdCheckSwitchProngs: |
| 15110 | 15140 | case IrInstructionIdCheckStatementIsVoid: |
| 15111 | case IrInstructionIdSetGlobalAlign: | |
| 15112 | 15141 | case IrInstructionIdSetGlobalSection: |
| 15113 | 15142 | case IrInstructionIdSetGlobalLinkage: |
| 15114 | 15143 | case IrInstructionIdPanic: |
| 15115 | 15144 | case IrInstructionIdSetEvalBranchQuota: |
| 15145 | case IrInstructionIdPtrTypeOf: | |
| 15116 | 15146 | return true; |
| 15117 | 15147 | case IrInstructionIdPhi: |
| 15118 | 15148 | case IrInstructionIdUnOp: |
| ... | ... | @@ -15151,8 +15181,7 @@ bool ir_has_side_effects(IrInstruction *instruction) { |
| 15151 | 15181 | case IrInstructionIdBoolNot: |
| 15152 | 15182 | case IrInstructionIdSlice: |
| 15153 | 15183 | case IrInstructionIdMemberCount: |
| 15154 | case IrInstructionIdPreferredAlignOf: | |
| 15155 | case IrInstructionIdAbiAlignOf: | |
| 15184 | case IrInstructionIdAlignOf: | |
| 15156 | 15185 | case IrInstructionIdReturnAddress: |
| 15157 | 15186 | case IrInstructionIdFrameAddress: |
| 15158 | 15187 | case IrInstructionIdTestErr: |
src/ir_print.cpp+14-19| ... | ... | @@ -664,14 +664,8 @@ static void ir_print_return_address(IrPrint *irp, IrInstructionReturnAddress *in |
| 664 | 664 | fprintf(irp->f, "@returnAddress()"); |
| 665 | 665 | } |
| 666 | 666 | |
| 667 | static void ir_print_preferred_align_of(IrPrint *irp, IrInstructionPreferredAlignOf *instruction) { | |
| 668 | fprintf(irp->f, "@preferredAlignOf("); | |
| 669 | ir_print_other_instruction(irp, instruction->type_value); | |
| 670 | fprintf(irp->f, ")"); | |
| 671 | } | |
| 672 | ||
| 673 | static void ir_print_abi_align_of(IrPrint *irp, IrInstructionAbiAlignOf *instruction) { | |
| 674 | fprintf(irp->f, "@abiAlignOf("); | |
| 667 | static void ir_print_align_of(IrPrint *irp, IrInstructionAlignOf *instruction) { | |
| 668 | fprintf(irp->f, "@alignOf("); | |
| 675 | 669 | ir_print_other_instruction(irp, instruction->type_value); |
| 676 | 670 | fprintf(irp->f, ")"); |
| 677 | 671 | } |
| ... | ... | @@ -860,10 +854,14 @@ static void ir_print_can_implicit_cast(IrPrint *irp, IrInstructionCanImplicitCas |
| 860 | 854 | fprintf(irp->f, ")"); |
| 861 | 855 | } |
| 862 | 856 | |
| 863 | static void ir_print_set_global_align(IrPrint *irp, IrInstructionSetGlobalAlign *instruction) { | |
| 864 | fprintf(irp->f, "@setGlobalAlign(%s,", buf_ptr(instruction->tld->name)); | |
| 865 | ir_print_other_instruction(irp, instruction->value); | |
| 866 | fprintf(irp->f, ")"); | |
| 857 | static void ir_print_ptr_type_of(IrPrint *irp, IrInstructionPtrTypeOf *instruction) { | |
| 858 | fprintf(irp->f, "&align "); | |
| 859 | ir_print_other_instruction(irp, instruction->align_value); | |
| 860 | const char *const_str = instruction->is_const ? "const " : ""; | |
| 861 | const char *volatile_str = instruction->is_volatile ? "volatile " : ""; | |
| 862 | fprintf(irp->f, ":%" PRIu32 ":%" PRIu32 " %s%s", instruction->bit_offset_start, instruction->bit_offset_end, | |
| 863 | const_str, volatile_str); | |
| 864 | ir_print_other_instruction(irp, instruction->child_type); | |
| 867 | 865 | } |
| 868 | 866 | |
| 869 | 867 | static void ir_print_set_global_section(IrPrint *irp, IrInstructionSetGlobalSection *instruction) { |
| ... | ... | @@ -1116,11 +1114,8 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) { |
| 1116 | 1114 | case IrInstructionIdFrameAddress: |
| 1117 | 1115 | ir_print_frame_address(irp, (IrInstructionFrameAddress *)instruction); |
| 1118 | 1116 | break; |
| 1119 | case IrInstructionIdPreferredAlignOf: | |
| 1120 | ir_print_preferred_align_of(irp, (IrInstructionPreferredAlignOf *)instruction); | |
| 1121 | break; | |
| 1122 | case IrInstructionIdAbiAlignOf: | |
| 1123 | ir_print_abi_align_of(irp, (IrInstructionAbiAlignOf *)instruction); | |
| 1117 | case IrInstructionIdAlignOf: | |
| 1118 | ir_print_align_of(irp, (IrInstructionAlignOf *)instruction); | |
| 1124 | 1119 | break; |
| 1125 | 1120 | case IrInstructionIdOverflowOp: |
| 1126 | 1121 | ir_print_overflow_op(irp, (IrInstructionOverflowOp *)instruction); |
| ... | ... | @@ -1191,8 +1186,8 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) { |
| 1191 | 1186 | case IrInstructionIdCanImplicitCast: |
| 1192 | 1187 | ir_print_can_implicit_cast(irp, (IrInstructionCanImplicitCast *)instruction); |
| 1193 | 1188 | break; |
| 1194 | case IrInstructionIdSetGlobalAlign: | |
| 1195 | ir_print_set_global_align(irp, (IrInstructionSetGlobalAlign *)instruction); | |
| 1189 | case IrInstructionIdPtrTypeOf: | |
| 1190 | ir_print_ptr_type_of(irp, (IrInstructionPtrTypeOf *)instruction); | |
| 1196 | 1191 | break; |
| 1197 | 1192 | case IrInstructionIdSetGlobalSection: |
| 1198 | 1193 | ir_print_set_global_section(irp, (IrInstructionSetGlobalSection *)instruction); |
src/parseh.cpp+8| ... | ... | @@ -710,6 +710,7 @@ static TypeTableEntry *resolve_enum_decl(Context *c, const EnumDecl *enum_decl) |
| 710 | 710 | TypeTableEntry *enum_type = get_partial_container_type(c->codegen, &c->import->decls_scope->base, |
| 711 | 711 | ContainerKindEnum, c->source_node, buf_ptr(full_type_name), ContainerLayoutExtern); |
| 712 | 712 | enum_type->data.enumeration.zero_bits_known = true; |
| 713 | enum_type->data.enumeration.abi_alignment = 1; | |
| 713 | 714 | c->enum_type_table.put(bare_name, enum_type); |
| 714 | 715 | c->decl_table.put(enum_decl, enum_type); |
| 715 | 716 | replace_with_fwd_decl(c, enum_type, full_type_name); |
| ... | ... | @@ -741,6 +742,7 @@ static TypeTableEntry *resolve_enum_decl(Context *c, const EnumDecl *enum_decl) |
| 741 | 742 | enum_type->data.enumeration.gen_field_count = 0; |
| 742 | 743 | enum_type->data.enumeration.complete = true; |
| 743 | 744 | enum_type->data.enumeration.zero_bits_known = true; |
| 745 | enum_type->data.enumeration.abi_alignment = 1; | |
| 744 | 746 | enum_type->data.enumeration.tag_type = tag_type_entry; |
| 745 | 747 | |
| 746 | 748 | enum_type->data.enumeration.src_field_count = field_count; |
| ... | ... | @@ -778,6 +780,9 @@ static TypeTableEntry *resolve_enum_decl(Context *c, const EnumDecl *enum_decl) |
| 778 | 780 | // create llvm type for root struct |
| 779 | 781 | enum_type->type_ref = tag_type_entry->type_ref; |
| 780 | 782 | |
| 783 | enum_type->data.enumeration.abi_alignment = LLVMABIAlignmentOfType(c->codegen->target_data_ref, | |
| 784 | enum_type->type_ref); | |
| 785 | ||
| 781 | 786 | // create debug type for tag |
| 782 | 787 | unsigned line = c->source_node ? (c->source_node->line + 1) : 0; |
| 783 | 788 | uint64_t debug_size_in_bits = 8*LLVMStoreSizeOfType(c->codegen->target_data_ref, enum_type->type_ref); |
| ... | ... | @@ -864,6 +869,7 @@ static TypeTableEntry *resolve_record_decl(Context *c, const RecordDecl *record_ |
| 864 | 869 | TypeTableEntry *struct_type = get_partial_container_type(c->codegen, &c->import->decls_scope->base, |
| 865 | 870 | ContainerKindStruct, c->source_node, buf_ptr(full_type_name), ContainerLayoutExtern); |
| 866 | 871 | struct_type->data.structure.zero_bits_known = true; |
| 872 | struct_type->data.structure.abi_alignment = 1; | |
| 867 | 873 | |
| 868 | 874 | c->struct_type_table.put(bare_name, struct_type); |
| 869 | 875 | c->decl_table.put(record_decl, struct_type); |
| ... | ... | @@ -950,6 +956,8 @@ static TypeTableEntry *resolve_record_decl(Context *c, const RecordDecl *record_ |
| 950 | 956 | |
| 951 | 957 | struct_type->data.structure.gen_field_count = field_count; |
| 952 | 958 | struct_type->data.structure.complete = true; |
| 959 | struct_type->data.structure.abi_alignment = LLVMABIAlignmentOfType(c->codegen->target_data_ref, | |
| 960 | struct_type->type_ref); | |
| 953 | 961 | |
| 954 | 962 | uint64_t debug_size_in_bits = 8*LLVMStoreSizeOfType(c->codegen->target_data_ref, struct_type->type_ref); |
| 955 | 963 | uint64_t debug_align_in_bits = 8*LLVMABISizeOfType(c->codegen->target_data_ref, struct_type->type_ref); |
src/parser.cpp+90-38| ... | ... | @@ -228,6 +228,7 @@ static AstNode *ast_parse_fn_proto(ParseContext *pc, size_t *token_index, bool m |
| 228 | 228 | static AstNode *ast_parse_return_expr(ParseContext *pc, size_t *token_index); |
| 229 | 229 | static AstNode *ast_parse_grouped_expr(ParseContext *pc, size_t *token_index, bool mandatory); |
| 230 | 230 | static AstNode *ast_parse_container_decl(ParseContext *pc, size_t *token_index, bool mandatory); |
| 231 | static AstNode *ast_parse_primary_expr(ParseContext *pc, size_t *token_index, bool mandatory); | |
| 231 | 232 | |
| 232 | 233 | static void ast_expect_token(ParseContext *pc, Token *token, TokenId token_id) { |
| 233 | 234 | if (token->id == token_id) { |
| ... | ... | @@ -384,7 +385,7 @@ static AstNode *ast_parse_grouped_expr(ParseContext *pc, size_t *token_index, bo |
| 384 | 385 | } |
| 385 | 386 | |
| 386 | 387 | /* |
| 387 | ArrayType : "[" option(Expression) "]" option("const") PrefixOpExpression | |
| 388 | ArrayType : "[" option(Expression) "]" option("align" PrimaryExpression)) option("const") option("volatile") PrefixOpExpression | |
| 388 | 389 | */ |
| 389 | 390 | static AstNode *ast_parse_array_type_expr(ParseContext *pc, size_t *token_index, bool mandatory) { |
| 390 | 391 | Token *l_bracket = &pc->tokens->at(*token_index); |
| ... | ... | @@ -403,10 +404,22 @@ static AstNode *ast_parse_array_type_expr(ParseContext *pc, size_t *token_index, |
| 403 | 404 | |
| 404 | 405 | ast_eat_token(pc, token_index, TokenIdRBracket); |
| 405 | 406 | |
| 406 | Token *const_tok = &pc->tokens->at(*token_index); | |
| 407 | if (const_tok->id == TokenIdKeywordConst) { | |
| 407 | Token *token = &pc->tokens->at(*token_index); | |
| 408 | if (token->id == TokenIdKeywordAlign) { | |
| 409 | *token_index += 1; | |
| 410 | node->data.array_type.align_expr = ast_parse_primary_expr(pc, token_index, true); | |
| 411 | ||
| 412 | token = &pc->tokens->at(*token_index); | |
| 413 | } | |
| 414 | if (token->id == TokenIdKeywordConst) { | |
| 408 | 415 | *token_index += 1; |
| 409 | 416 | node->data.array_type.is_const = true; |
| 417 | ||
| 418 | token = &pc->tokens->at(*token_index); | |
| 419 | } | |
| 420 | if (token->id == TokenIdKeywordVolatile) { | |
| 421 | *token_index += 1; | |
| 422 | node->data.array_type.is_volatile = true; | |
| 410 | 423 | } |
| 411 | 424 | |
| 412 | 425 | node->data.array_type.child_type = ast_parse_type_expr(pc, token_index, true); |
| ... | ... | @@ -953,7 +966,6 @@ static PrefixOp tok_to_prefix_op(Token *token) { |
| 953 | 966 | case TokenIdDash: return PrefixOpNegation; |
| 954 | 967 | case TokenIdMinusPercent: return PrefixOpNegationWrap; |
| 955 | 968 | case TokenIdTilde: return PrefixOpBinNot; |
| 956 | case TokenIdAmpersand: return PrefixOpAddressOf; | |
| 957 | 969 | case TokenIdStar: return PrefixOpDereference; |
| 958 | 970 | case TokenIdMaybe: return PrefixOpMaybe; |
| 959 | 971 | case TokenIdPercent: return PrefixOpError; |
| ... | ... | @@ -964,12 +976,52 @@ static PrefixOp tok_to_prefix_op(Token *token) { |
| 964 | 976 | } |
| 965 | 977 | } |
| 966 | 978 | |
| 979 | static AstNode *ast_parse_addr_of(ParseContext *pc, size_t *token_index) { | |
| 980 | Token *ampersand_tok = ast_eat_token(pc, token_index, TokenIdAmpersand); | |
| 981 | ||
| 982 | AstNode *node = ast_create_node(pc, NodeTypeAddrOfExpr, ampersand_tok); | |
| 983 | ||
| 984 | Token *token = &pc->tokens->at(*token_index); | |
| 985 | if (token->id == TokenIdKeywordAlign) { | |
| 986 | *token_index += 1; | |
| 987 | node->data.addr_of_expr.align_expr = ast_parse_primary_expr(pc, token_index, true); | |
| 988 | ||
| 989 | token = &pc->tokens->at(*token_index); | |
| 990 | if (token->id == TokenIdColon) { | |
| 991 | *token_index += 1; | |
| 992 | Token *bit_offset_start_tok = ast_eat_token(pc, token_index, TokenIdIntLiteral); | |
| 993 | ast_eat_token(pc, token_index, TokenIdColon); | |
| 994 | Token *bit_offset_end_tok = ast_eat_token(pc, token_index, TokenIdIntLiteral); | |
| 995 | token = &pc->tokens->at(*token_index); | |
| 996 | ||
| 997 | node->data.addr_of_expr.bit_offset_start = token_bigint(bit_offset_start_tok); | |
| 998 | node->data.addr_of_expr.bit_offset_end = token_bigint(bit_offset_end_tok); | |
| 999 | } | |
| 1000 | } | |
| 1001 | if (token->id == TokenIdKeywordConst) { | |
| 1002 | *token_index += 1; | |
| 1003 | node->data.addr_of_expr.is_const = true; | |
| 1004 | ||
| 1005 | token = &pc->tokens->at(*token_index); | |
| 1006 | } | |
| 1007 | if (token->id == TokenIdKeywordVolatile) { | |
| 1008 | *token_index += 1; | |
| 1009 | node->data.addr_of_expr.is_volatile = true; | |
| 1010 | } | |
| 1011 | ||
| 1012 | node->data.addr_of_expr.op_expr = ast_parse_prefix_op_expr(pc, token_index, true); | |
| 1013 | return node; | |
| 1014 | } | |
| 1015 | ||
| 967 | 1016 | /* |
| 968 | 1017 | PrefixOpExpression : PrefixOp PrefixOpExpression | SuffixOpExpression |
| 969 | PrefixOp = "!" | "-" | "~" | "*" | ("&" option("const") option("volatile")) | "?" | "%" | "%%" | "??" | "-%" | |
| 1018 | PrefixOp = "!" | "-" | "~" | "*" | ("&" option("align" PrimaryExpression option(":" Integer ":" Integer)) option("const") option("volatile")) | "?" | "%" | "%%" | "??" | "-%" | |
| 970 | 1019 | */ |
| 971 | 1020 | static AstNode *ast_parse_prefix_op_expr(ParseContext *pc, size_t *token_index, bool mandatory) { |
| 972 | 1021 | Token *token = &pc->tokens->at(*token_index); |
| 1022 | if (token->id == TokenIdAmpersand) { | |
| 1023 | return ast_parse_addr_of(pc, token_index); | |
| 1024 | } | |
| 973 | 1025 | PrefixOp prefix_op = tok_to_prefix_op(token); |
| 974 | 1026 | if (prefix_op == PrefixOpInvalid) { |
| 975 | 1027 | return ast_parse_suffix_op_expr(pc, token_index, mandatory); |
| ... | ... | @@ -997,23 +1049,6 @@ static AstNode *ast_parse_prefix_op_expr(ParseContext *pc, size_t *token_index, |
| 997 | 1049 | node->column += 1; |
| 998 | 1050 | } |
| 999 | 1051 | |
| 1000 | if (prefix_op == PrefixOpAddressOf) { | |
| 1001 | Token *const_or_volatile_tok = &pc->tokens->at(*token_index); | |
| 1002 | if (const_or_volatile_tok->id == TokenIdKeywordConst) { | |
| 1003 | *token_index += 1; | |
| 1004 | Token *volatile_token = &pc->tokens->at(*token_index); | |
| 1005 | if (volatile_token->id == TokenIdKeywordVolatile) { | |
| 1006 | *token_index += 1; | |
| 1007 | prefix_op = PrefixOpConstVolatileAddressOf; | |
| 1008 | } else { | |
| 1009 | prefix_op = PrefixOpConstAddressOf; | |
| 1010 | } | |
| 1011 | } else if (const_or_volatile_tok->id == TokenIdKeywordVolatile) { | |
| 1012 | prefix_op = PrefixOpVolatileAddressOf; | |
| 1013 | *token_index += 1; | |
| 1014 | } | |
| 1015 | } | |
| 1016 | ||
| 1017 | 1052 | AstNode *prefix_op_expr = ast_parse_prefix_op_expr(pc, token_index, true); |
| 1018 | 1053 | node->data.prefix_op_expr.primary_expr = prefix_op_expr; |
| 1019 | 1054 | node->data.prefix_op_expr.prefix_op = prefix_op; |
| ... | ... | @@ -1499,7 +1534,7 @@ static AstNode *ast_parse_defer_expr(ParseContext *pc, size_t *token_index) { |
| 1499 | 1534 | } |
| 1500 | 1535 | |
| 1501 | 1536 | /* |
| 1502 | VariableDeclaration = option("comptime") ("var" | "const") Symbol option(":" TypeExpr) "=" Expression | |
| 1537 | VariableDeclaration = option("comptime") ("var" | "const") Symbol option(":" TypeExpr) option("align" PrimaryExpression) "=" Expression | |
| 1503 | 1538 | */ |
| 1504 | 1539 | static AstNode *ast_parse_variable_declaration_expr(ParseContext *pc, size_t *token_index, bool mandatory, |
| 1505 | 1540 | VisibMod visib_mod) |
| ... | ... | @@ -1549,25 +1584,28 @@ static AstNode *ast_parse_variable_declaration_expr(ParseContext *pc, size_t *to |
| 1549 | 1584 | Token *name_token = ast_eat_token(pc, token_index, TokenIdSymbol); |
| 1550 | 1585 | node->data.variable_declaration.symbol = token_buf(name_token); |
| 1551 | 1586 | |
| 1552 | Token *eq_or_colon = &pc->tokens->at(*token_index); | |
| 1553 | *token_index += 1; | |
| 1554 | if (eq_or_colon->id == TokenIdEq) { | |
| 1555 | node->data.variable_declaration.expr = ast_parse_expression(pc, token_index, true); | |
| 1556 | } else if (eq_or_colon->id == TokenIdColon) { | |
| 1587 | Token *next_token = &pc->tokens->at(*token_index); | |
| 1588 | ||
| 1589 | if (next_token->id == TokenIdColon) { | |
| 1590 | *token_index += 1; | |
| 1557 | 1591 | node->data.variable_declaration.type = ast_parse_type_expr(pc, token_index, true); |
| 1558 | Token *eq_token = &pc->tokens->at(*token_index); | |
| 1559 | if (eq_token->id == TokenIdEq) { | |
| 1560 | *token_index += 1; | |
| 1592 | next_token = &pc->tokens->at(*token_index); | |
| 1593 | } | |
| 1561 | 1594 | |
| 1562 | node->data.variable_declaration.expr = ast_parse_expression(pc, token_index, true); | |
| 1563 | } | |
| 1564 | } else { | |
| 1565 | ast_invalid_token_error(pc, eq_or_colon); | |
| 1595 | if (next_token->id == TokenIdKeywordAlign) { | |
| 1596 | *token_index += 1; | |
| 1597 | node->data.variable_declaration.align_expr = ast_parse_primary_expr(pc, token_index, true); | |
| 1598 | next_token = &pc->tokens->at(*token_index); | |
| 1599 | } | |
| 1600 | ||
| 1601 | if (next_token->id == TokenIdEq) { | |
| 1602 | *token_index += 1; | |
| 1603 | node->data.variable_declaration.expr = ast_parse_expression(pc, token_index, true); | |
| 1604 | next_token = &pc->tokens->at(*token_index); | |
| 1566 | 1605 | } |
| 1567 | 1606 | |
| 1568 | 1607 | // peek ahead and ensure that all variable declarations are followed by a semicolon |
| 1569 | Token *semicolon_token = &pc->tokens->at(*token_index); | |
| 1570 | ast_expect_token(pc, semicolon_token, TokenIdSemicolon); | |
| 1608 | ast_expect_token(pc, next_token, TokenIdSemicolon); | |
| 1571 | 1609 | |
| 1572 | 1610 | return node; |
| 1573 | 1611 | } |
| ... | ... | @@ -2165,7 +2203,7 @@ static AstNode *ast_parse_block(ParseContext *pc, size_t *token_index, bool mand |
| 2165 | 2203 | } |
| 2166 | 2204 | |
| 2167 | 2205 | /* |
| 2168 | FnProto = option("coldcc" | "nakedcc" | "stdcallcc") "fn" option(Symbol) ParamDeclList option("->" TypeExpr) | |
| 2206 | FnProto = option("coldcc" | "nakedcc" | "stdcallcc") "fn" option(Symbol) ParamDeclList option("align" PrimaryExpression) option("->" TypeExpr) | |
| 2169 | 2207 | */ |
| 2170 | 2208 | static AstNode *ast_parse_fn_proto(ParseContext *pc, size_t *token_index, bool mandatory, VisibMod visib_mod) { |
| 2171 | 2209 | Token *first_token = &pc->tokens->at(*token_index); |
| ... | ... | @@ -2200,6 +2238,7 @@ static AstNode *ast_parse_fn_proto(ParseContext *pc, size_t *token_index, bool m |
| 2200 | 2238 | node->data.fn_proto.cc = cc; |
| 2201 | 2239 | |
| 2202 | 2240 | Token *fn_name = &pc->tokens->at(*token_index); |
| 2241 | ||
| 2203 | 2242 | if (fn_name->id == TokenIdSymbol) { |
| 2204 | 2243 | *token_index += 1; |
| 2205 | 2244 | node->data.fn_proto.name = token_buf(fn_name); |
| ... | ... | @@ -2210,6 +2249,12 @@ static AstNode *ast_parse_fn_proto(ParseContext *pc, size_t *token_index, bool m |
| 2210 | 2249 | ast_parse_param_decl_list(pc, token_index, &node->data.fn_proto.params, &node->data.fn_proto.is_var_args); |
| 2211 | 2250 | |
| 2212 | 2251 | Token *next_token = &pc->tokens->at(*token_index); |
| 2252 | if (next_token->id == TokenIdKeywordAlign) { | |
| 2253 | *token_index += 1; | |
| 2254 | ||
| 2255 | node->data.fn_proto.align_expr = ast_parse_primary_expr(pc, token_index, true); | |
| 2256 | next_token = &pc->tokens->at(*token_index); | |
| 2257 | } | |
| 2213 | 2258 | if (next_token->id == TokenIdArrow) { |
| 2214 | 2259 | *token_index += 1; |
| 2215 | 2260 | node->data.fn_proto.return_type = ast_parse_type_expr(pc, token_index, false); |
| ... | ... | @@ -2595,6 +2640,7 @@ void ast_visit_node_children(AstNode *node, void (*visit)(AstNode **, void *cont |
| 2595 | 2640 | case NodeTypeFnProto: |
| 2596 | 2641 | visit_field(&node->data.fn_proto.return_type, visit, context); |
| 2597 | 2642 | visit_node_list(&node->data.fn_proto.params, visit, context); |
| 2643 | visit_field(&node->data.fn_proto.align_expr, visit, context); | |
| 2598 | 2644 | break; |
| 2599 | 2645 | case NodeTypeFnDef: |
| 2600 | 2646 | visit_field(&node->data.fn_def.fn_proto, visit, context); |
| ... | ... | @@ -2621,6 +2667,7 @@ void ast_visit_node_children(AstNode *node, void (*visit)(AstNode **, void *cont |
| 2621 | 2667 | case NodeTypeVariableDeclaration: |
| 2622 | 2668 | visit_field(&node->data.variable_declaration.type, visit, context); |
| 2623 | 2669 | visit_field(&node->data.variable_declaration.expr, visit, context); |
| 2670 | visit_field(&node->data.variable_declaration.align_expr, visit, context); | |
| 2624 | 2671 | break; |
| 2625 | 2672 | case NodeTypeErrorValueDecl: |
| 2626 | 2673 | // none |
| ... | ... | @@ -2769,6 +2816,7 @@ void ast_visit_node_children(AstNode *node, void (*visit)(AstNode **, void *cont |
| 2769 | 2816 | case NodeTypeArrayType: |
| 2770 | 2817 | visit_field(&node->data.array_type.size, visit, context); |
| 2771 | 2818 | visit_field(&node->data.array_type.child_type, visit, context); |
| 2819 | visit_field(&node->data.array_type.align_expr, visit, context); | |
| 2772 | 2820 | break; |
| 2773 | 2821 | case NodeTypeErrorType: |
| 2774 | 2822 | // none |
| ... | ... | @@ -2776,5 +2824,9 @@ void ast_visit_node_children(AstNode *node, void (*visit)(AstNode **, void *cont |
| 2776 | 2824 | case NodeTypeVarLiteral: |
| 2777 | 2825 | // none |
| 2778 | 2826 | break; |
| 2827 | case NodeTypeAddrOfExpr: | |
| 2828 | visit_field(&node->data.addr_of_expr.align_expr, visit, context); | |
| 2829 | visit_field(&node->data.addr_of_expr.op_expr, visit, context); | |
| 2830 | break; | |
| 2779 | 2831 | } |
| 2780 | 2832 | } |
src/tokenizer.cpp+2| ... | ... | @@ -107,6 +107,7 @@ struct ZigKeyword { |
| 107 | 107 | }; |
| 108 | 108 | |
| 109 | 109 | static const struct ZigKeyword zig_keywords[] = { |
| 110 | {"align", TokenIdKeywordAlign}, | |
| 110 | 111 | {"and", TokenIdKeywordAnd}, |
| 111 | 112 | {"asm", TokenIdKeywordAsm}, |
| 112 | 113 | {"break", TokenIdKeywordBreak}, |
| ... | ... | @@ -1454,6 +1455,7 @@ const char * token_name(TokenId id) { |
| 1454 | 1455 | case TokenIdFatArrow: return "=>"; |
| 1455 | 1456 | case TokenIdFloatLiteral: return "FloatLiteral"; |
| 1456 | 1457 | case TokenIdIntLiteral: return "IntLiteral"; |
| 1458 | case TokenIdKeywordAlign: return "align"; | |
| 1457 | 1459 | case TokenIdKeywordAnd: return "and"; |
| 1458 | 1460 | case TokenIdKeywordAsm: return "asm"; |
| 1459 | 1461 | case TokenIdKeywordBreak: return "break"; |
src/tokenizer.hpp+1| ... | ... | @@ -46,6 +46,7 @@ enum TokenId { |
| 46 | 46 | TokenIdFatArrow, |
| 47 | 47 | TokenIdFloatLiteral, |
| 48 | 48 | TokenIdIntLiteral, |
| 49 | TokenIdKeywordAlign, | |
| 49 | 50 | TokenIdKeywordAnd, |
| 50 | 51 | TokenIdKeywordAsm, |
| 51 | 52 | TokenIdKeywordBreak, |
src/zig_llvm.cpp-5| ... | ... | @@ -713,11 +713,6 @@ void ZigLLVMAddModuleDebugInfoFlag(LLVMModuleRef module) { |
| 713 | 713 | unwrap(module)->addModuleFlag(Module::Warning, "Debug Info Version", DEBUG_METADATA_VERSION); |
| 714 | 714 | } |
| 715 | 715 | |
| 716 | unsigned ZigLLVMGetPrefTypeAlignment(LLVMTargetDataRef TD, LLVMTypeRef Ty) { | |
| 717 | return unwrap(TD)->getPrefTypeAlignment(unwrap(Ty)); | |
| 718 | } | |
| 719 | ||
| 720 | ||
| 721 | 716 | static AtomicOrdering mapFromLLVMOrdering(LLVMAtomicOrdering Ordering) { |
| 722 | 717 | switch (Ordering) { |
| 723 | 718 | case LLVMAtomicOrderingNotAtomic: return AtomicOrdering::NotAtomic; |
src/zig_llvm.hpp-2| ... | ... | @@ -167,8 +167,6 @@ void ZigLLVMSetFastMath(LLVMBuilderRef builder_wrapped, bool on_state); |
| 167 | 167 | void ZigLLVMAddFunctionAttr(LLVMValueRef fn, const char *attr_name, const char *attr_value); |
| 168 | 168 | void ZigLLVMAddFunctionAttrCold(LLVMValueRef fn); |
| 169 | 169 | |
| 170 | unsigned ZigLLVMGetPrefTypeAlignment(LLVMTargetDataRef TD, LLVMTypeRef Ty); | |
| 171 | ||
| 172 | 170 | |
| 173 | 171 | // copied from include/llvm/ADT/Triple.h |
| 174 | 172 |
std/hash_map.zig+1-1| ... | ... | @@ -251,7 +251,7 @@ test "basicHashMapTest" { |
| 251 | 251 | } |
| 252 | 252 | |
| 253 | 253 | fn hash_i32(x: i32) -> u32 { |
| 254 | *@ptrCast(&u32, &x) | |
| 254 | @bitCast(u32, x) | |
| 255 | 255 | } |
| 256 | 256 | |
| 257 | 257 | fn eql_i32(a: i32, b: i32) -> bool { |
std/mem.zig+1-4| ... | ... | @@ -21,10 +21,7 @@ pub const Allocator = struct { |
| 21 | 21 | |
| 22 | 22 | /// Aborts the program if an allocation fails. |
| 23 | 23 | fn checkedAlloc(self: &Allocator, comptime T: type, n: usize) -> []T { |
| 24 | alloc(self, T, n) %% |err| { | |
| 25 | %%io.stderr.printf("allocation failure: {}\n", @errorName(err)); | |
| 26 | os.abort() | |
| 27 | } | |
| 24 | alloc(self, T, n) %% |err| debug.panic("allocation failure: {}", @errorName(err)) | |
| 28 | 25 | } |
| 29 | 26 | |
| 30 | 27 | fn create(self: &Allocator, comptime T: type) -> %&T { |
test/cases/alignof.zig+3-6| ... | ... | @@ -3,12 +3,9 @@ const builtin = @import("builtin"); |
| 3 | 3 | |
| 4 | 4 | const Foo = struct { x: u32, y: u32, z: u32, }; |
| 5 | 5 | |
| 6 | test "@abiAlignOf(T) before referencing T" { | |
| 7 | comptime assert(@cAbiAlignOf(Foo) != @maxValue(usize)); | |
| 6 | test "@alignOf(T) before referencing T" { | |
| 7 | comptime assert(@alignOf(Foo) != @maxValue(usize)); | |
| 8 | 8 | if (builtin.arch == builtin.Arch.x86_64) { |
| 9 | comptime { | |
| 10 | assert(@cAbiAlignOf(Foo) == 4); | |
| 11 | assert(@preferredAlignOf(Foo) == 8); | |
| 12 | } | |
| 9 | comptime assert(@alignOf(Foo) == 4); | |
| 13 | 10 | } |
| 14 | 11 | } |
test/cases/enum.zig+2-2| ... | ... | @@ -124,8 +124,8 @@ const BareNumber = enum { |
| 124 | 124 | |
| 125 | 125 | test "enum alignment" { |
| 126 | 126 | comptime { |
| 127 | assert(@cAbiAlignOf(AlignTestEnum) >= @cAbiAlignOf([9]u8)); | |
| 128 | assert(@cAbiAlignOf(AlignTestEnum) >= @cAbiAlignOf(u64)); | |
| 127 | assert(@alignOf(AlignTestEnum) >= @alignOf([9]u8)); | |
| 128 | assert(@alignOf(AlignTestEnum) >= @alignOf(u64)); | |
| 129 | 129 | } |
| 130 | 130 | } |
| 131 | 131 |
test/cases/struct.zig-2| ... | ... | @@ -201,8 +201,6 @@ test "packed struct" { |
| 201 | 201 | } |
| 202 | 202 | |
| 203 | 203 | |
| 204 | const u2 = @IntType(false, 2); | |
| 205 | ||
| 206 | 204 | const BitField1 = packed struct { |
| 207 | 205 | a: u3, |
| 208 | 206 | b: u3, |
test/cases/switch.zig-1| ... | ... | @@ -172,7 +172,6 @@ test "switch handles all cases of number" { |
| 172 | 172 | comptime testSwitchHandleAllCases(); |
| 173 | 173 | } |
| 174 | 174 | |
| 175 | const u2 = @IntType(false, 2); | |
| 176 | 175 | fn testSwitchHandleAllCases() { |
| 177 | 176 | assert(testSwitchHandleAllCasesExhaustive(0) == 3); |
| 178 | 177 | assert(testSwitchHandleAllCasesExhaustive(1) == 2); |
test/compile_errors.zig+9-28| ... | ... | @@ -1316,13 +1316,15 @@ pub fn addCases(cases: &tests.CompileErrorContext) { |
| 1316 | 1316 | \\} |
| 1317 | 1317 | , ".tmp_source.zig:2:24: error: integer value 753664 cannot be implicitly casted to type 'u16'"); |
| 1318 | 1318 | |
| 1319 | cases.add("set global variable alignment to non power of 2", | |
| 1320 | \\const some_data: [100]u8 = undefined; | |
| 1321 | \\comptime { | |
| 1322 | \\ @setGlobalAlign(some_data, 3); | |
| 1323 | \\} | |
| 1319 | cases.add("global variable alignment non power of 2", | |
| 1320 | \\const some_data: [100]u8 align 3 = undefined; | |
| 1324 | 1321 | \\export fn entry() -> usize { @sizeOf(@typeOf(some_data)) } |
| 1325 | , ".tmp_source.zig:3:32: error: alignment value must be power of 2"); | |
| 1322 | , ".tmp_source.zig:1:32: error: alignment value 3 is not a power of 2"); | |
| 1323 | ||
| 1324 | cases.add("function alignment non power of 2", | |
| 1325 | \\extern fn foo() align 3; | |
| 1326 | \\export fn entry() { foo() } | |
| 1327 | , ".tmp_source.zig:1:23: error: alignment value 3 is not a power of 2"); | |
| 1326 | 1328 | |
| 1327 | 1329 | cases.add("compile log", |
| 1328 | 1330 | \\export fn foo() { |
| ... | ... | @@ -1342,9 +1344,6 @@ pub fn addCases(cases: &tests.CompileErrorContext) { |
| 1342 | 1344 | ".tmp_source.zig:2:17: note: called from here"); |
| 1343 | 1345 | |
| 1344 | 1346 | cases.add("casting bit offset pointer to regular pointer", |
| 1345 | \\const u2 = @IntType(false, 2); | |
| 1346 | \\const u3 = @IntType(false, 3); | |
| 1347 | \\ | |
| 1348 | 1347 | \\const BitField = packed struct { |
| 1349 | 1348 | \\ a: u3, |
| 1350 | 1349 | \\ b: u3, |
| ... | ... | @@ -1360,7 +1359,7 @@ pub fn addCases(cases: &tests.CompileErrorContext) { |
| 1360 | 1359 | \\} |
| 1361 | 1360 | \\ |
| 1362 | 1361 | \\export fn entry() -> usize { @sizeOf(@typeOf(foo)) } |
| 1363 | , ".tmp_source.zig:11:26: error: expected type '&const u3', found '&:3:6 const u3'"); | |
| 1362 | , ".tmp_source.zig:8:26: error: expected type '&const u3', found '&align 1:3:6 const u3'"); | |
| 1364 | 1363 | |
| 1365 | 1364 | cases.add("referring to a struct that is invalid", |
| 1366 | 1365 | \\const UsbDeviceRequest = struct { |
| ... | ... | @@ -1626,24 +1625,6 @@ pub fn addCases(cases: &tests.CompileErrorContext) { |
| 1626 | 1625 | "error: 'main' is private", |
| 1627 | 1626 | ".tmp_source.zig:1:1: note: declared here"); |
| 1628 | 1627 | |
| 1629 | cases.add("@setGlobalAlign extern variable", | |
| 1630 | \\extern var foo: i32; | |
| 1631 | \\comptime { | |
| 1632 | \\ @setGlobalAlign(foo, 4); | |
| 1633 | \\} | |
| 1634 | , | |
| 1635 | ".tmp_source.zig:3:5: error: cannot set alignment of external variable 'foo'", | |
| 1636 | ".tmp_source.zig:1:8: note: declared here"); | |
| 1637 | ||
| 1638 | cases.add("@setGlobalAlign extern fn", | |
| 1639 | \\extern fn foo(); | |
| 1640 | \\comptime { | |
| 1641 | \\ @setGlobalAlign(foo, 4); | |
| 1642 | \\} | |
| 1643 | , | |
| 1644 | ".tmp_source.zig:3:5: error: cannot set alignment of external function 'foo'", | |
| 1645 | ".tmp_source.zig:1:8: note: declared here"); | |
| 1646 | ||
| 1647 | 1628 | cases.add("@setGlobalSection extern variable", |
| 1648 | 1629 | \\extern var foo: i32; |
| 1649 | 1630 | \\comptime { |