| 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,8 +303,6 @@ struct TldVar { |
| 303 | Tld base; | 303 | Tld base; |
| 304 | 304 | ||
| 305 | VariableTableEntry *var; | 305 | VariableTableEntry *var; |
| 306 | AstNode *set_global_align_node; | ||
| 307 | uint32_t alignment; | ||
| 308 | AstNode *set_global_section_node; | 306 | AstNode *set_global_section_node; |
| 309 | Buf *section_name; | 307 | Buf *section_name; |
| 310 | AstNode *set_global_linkage_node; | 308 | AstNode *set_global_linkage_node; |
| ... | @@ -358,6 +356,7 @@ enum NodeType { | ... | @@ -358,6 +356,7 @@ enum NodeType { |
| 358 | NodeTypeCharLiteral, | 356 | NodeTypeCharLiteral, |
| 359 | NodeTypeSymbol, | 357 | NodeTypeSymbol, |
| 360 | NodeTypePrefixOpExpr, | 358 | NodeTypePrefixOpExpr, |
| 359 | NodeTypeAddrOfExpr, | ||
| 361 | NodeTypeFnCallExpr, | 360 | NodeTypeFnCallExpr, |
| 362 | NodeTypeArrayAccessExpr, | 361 | NodeTypeArrayAccessExpr, |
| 363 | NodeTypeSliceExpr, | 362 | NodeTypeSliceExpr, |
| ... | @@ -415,6 +414,8 @@ struct AstNodeFnProto { | ... | @@ -415,6 +414,8 @@ struct AstNodeFnProto { |
| 415 | AstNode *fn_def_node; | 414 | AstNode *fn_def_node; |
| 416 | // populated if this is an extern declaration | 415 | // populated if this is an extern declaration |
| 417 | Buf *lib_name; | 416 | Buf *lib_name; |
| 417 | // populated if the "align A" is present | ||
| 418 | AstNode *align_expr; | ||
| 418 | }; | 419 | }; |
| 419 | 420 | ||
| 420 | struct AstNodeFnDef { | 421 | struct AstNodeFnDef { |
| ... | @@ -470,6 +471,8 @@ struct AstNodeVariableDeclaration { | ... | @@ -470,6 +471,8 @@ struct AstNodeVariableDeclaration { |
| 470 | AstNode *expr; | 471 | AstNode *expr; |
| 471 | // populated if this is an extern declaration | 472 | // populated if this is an extern declaration |
| 472 | Buf *lib_name; | 473 | Buf *lib_name; |
| 474 | // populated if the "align A" is present | ||
| 475 | AstNode *align_expr; | ||
| 473 | }; | 476 | }; |
| 474 | 477 | ||
| 475 | struct AstNodeErrorValueDecl { | 478 | struct AstNodeErrorValueDecl { |
| ... | @@ -579,10 +582,6 @@ enum PrefixOp { | ... | @@ -579,10 +582,6 @@ enum PrefixOp { |
| 579 | PrefixOpBinNot, | 582 | PrefixOpBinNot, |
| 580 | PrefixOpNegation, | 583 | PrefixOpNegation, |
| 581 | PrefixOpNegationWrap, | 584 | PrefixOpNegationWrap, |
| 582 | PrefixOpAddressOf, | ||
| 583 | PrefixOpConstAddressOf, | ||
| 584 | PrefixOpVolatileAddressOf, | ||
| 585 | PrefixOpConstVolatileAddressOf, | ||
| 586 | PrefixOpDereference, | 585 | PrefixOpDereference, |
| 587 | PrefixOpMaybe, | 586 | PrefixOpMaybe, |
| 588 | PrefixOpError, | 587 | PrefixOpError, |
| ... | @@ -595,6 +594,23 @@ struct AstNodePrefixOpExpr { | ... | @@ -595,6 +594,23 @@ struct AstNodePrefixOpExpr { |
| 595 | AstNode *primary_expr; | 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 | struct AstNodeUse { | 614 | struct AstNodeUse { |
| 599 | VisibMod visib_mod; | 615 | VisibMod visib_mod; |
| 600 | AstNode *expr; | 616 | AstNode *expr; |
| ... | @@ -807,12 +823,6 @@ struct AstNodeUnreachableExpr { | ... | @@ -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 | struct AstNodeErrorType { | 826 | struct AstNodeErrorType { |
| 817 | }; | 827 | }; |
| 818 | 828 | ||
| ... | @@ -841,6 +851,7 @@ struct AstNode { | ... | @@ -841,6 +851,7 @@ struct AstNode { |
| 841 | AstNodeBinOpExpr bin_op_expr; | 851 | AstNodeBinOpExpr bin_op_expr; |
| 842 | AstNodeUnwrapErrorExpr unwrap_err_expr; | 852 | AstNodeUnwrapErrorExpr unwrap_err_expr; |
| 843 | AstNodePrefixOpExpr prefix_op_expr; | 853 | AstNodePrefixOpExpr prefix_op_expr; |
| 854 | AstNodeAddrOfExpr addr_of_expr; | ||
| 844 | AstNodeFnCallExpr fn_call_expr; | 855 | AstNodeFnCallExpr fn_call_expr; |
| 845 | AstNodeArrayAccessExpr array_access_expr; | 856 | AstNodeArrayAccessExpr array_access_expr; |
| 846 | AstNodeSliceExpr slice_expr; | 857 | AstNodeSliceExpr slice_expr; |
| ... | @@ -911,8 +922,10 @@ struct TypeTableEntryPointer { | ... | @@ -911,8 +922,10 @@ struct TypeTableEntryPointer { |
| 911 | TypeTableEntry *child_type; | 922 | TypeTableEntry *child_type; |
| 912 | bool is_const; | 923 | bool is_const; |
| 913 | bool is_volatile; | 924 | bool is_volatile; |
| 925 | uint32_t alignment; | ||
| 914 | uint32_t bit_offset; | 926 | uint32_t bit_offset; |
| 915 | uint32_t unaligned_bit_count; | 927 | uint32_t unaligned_bit_count; |
| 928 | TypeTableEntry *slice_parent; | ||
| 916 | }; | 929 | }; |
| 917 | 930 | ||
| 918 | struct TypeTableEntryInt { | 931 | struct TypeTableEntryInt { |
| ... | @@ -958,6 +971,7 @@ struct TypeTableEntryStruct { | ... | @@ -958,6 +971,7 @@ struct TypeTableEntryStruct { |
| 958 | 971 | ||
| 959 | bool zero_bits_loop_flag; | 972 | bool zero_bits_loop_flag; |
| 960 | bool zero_bits_known; | 973 | bool zero_bits_known; |
| 974 | uint32_t abi_alignment; // also figured out with zero_bits pass | ||
| 961 | }; | 975 | }; |
| 962 | 976 | ||
| 963 | struct TypeTableEntryMaybe { | 977 | struct TypeTableEntryMaybe { |
| ... | @@ -989,6 +1003,7 @@ struct TypeTableEntryEnum { | ... | @@ -989,6 +1003,7 @@ struct TypeTableEntryEnum { |
| 989 | 1003 | ||
| 990 | bool zero_bits_loop_flag; | 1004 | bool zero_bits_loop_flag; |
| 991 | bool zero_bits_known; | 1005 | bool zero_bits_known; |
| 1006 | uint32_t abi_alignment; // also figured out with zero_bits pass | ||
| 992 | 1007 | ||
| 993 | size_t gen_union_index; | 1008 | size_t gen_union_index; |
| 994 | size_t gen_tag_index; | 1009 | size_t gen_tag_index; |
| ... | @@ -1101,7 +1116,6 @@ struct TypeTableEntry { | ... | @@ -1101,7 +1116,6 @@ struct TypeTableEntry { |
| 1101 | 1116 | ||
| 1102 | // use these fields to make sure we don't duplicate type table entries for the same type | 1117 | // use these fields to make sure we don't duplicate type table entries for the same type |
| 1103 | TypeTableEntry *pointer_parent[2]; // [0 - mut, 1 - const] | 1118 | TypeTableEntry *pointer_parent[2]; // [0 - mut, 1 - const] |
| 1104 | TypeTableEntry *slice_parent[2]; // [0 - mut, 1 - const] | ||
| 1105 | TypeTableEntry *maybe_parent; | 1119 | TypeTableEntry *maybe_parent; |
| 1106 | TypeTableEntry *error_parent; | 1120 | TypeTableEntry *error_parent; |
| 1107 | // If we generate a constant name value for this type, we memoize it here. | 1121 | // If we generate a constant name value for this type, we memoize it here. |
| ... | @@ -1164,6 +1178,7 @@ struct FnTableEntry { | ... | @@ -1164,6 +1178,7 @@ struct FnTableEntry { |
| 1164 | size_t prealloc_bbc; | 1178 | size_t prealloc_bbc; |
| 1165 | AstNode **param_source_nodes; | 1179 | AstNode **param_source_nodes; |
| 1166 | Buf **param_names; | 1180 | Buf **param_names; |
| 1181 | uint32_t align_bytes; | ||
| 1167 | 1182 | ||
| 1168 | AstNode *fn_no_inline_set_node; | 1183 | AstNode *fn_no_inline_set_node; |
| 1169 | AstNode *fn_static_eval_set_node; | 1184 | AstNode *fn_static_eval_set_node; |
| ... | @@ -1171,8 +1186,6 @@ struct FnTableEntry { | ... | @@ -1171,8 +1186,6 @@ struct FnTableEntry { |
| 1171 | ZigList<IrInstruction *> alloca_list; | 1186 | ZigList<IrInstruction *> alloca_list; |
| 1172 | ZigList<VariableTableEntry *> variable_list; | 1187 | ZigList<VariableTableEntry *> variable_list; |
| 1173 | 1188 | ||
| 1174 | AstNode *set_global_align_node; | ||
| 1175 | uint32_t alignment; | ||
| 1176 | AstNode *set_global_section_node; | 1189 | AstNode *set_global_section_node; |
| 1177 | Buf *section_name; | 1190 | Buf *section_name; |
| 1178 | AstNode *set_global_linkage_node; | 1191 | AstNode *set_global_linkage_node; |
| ... | @@ -1187,8 +1200,7 @@ enum BuiltinFnId { | ... | @@ -1187,8 +1200,7 @@ enum BuiltinFnId { |
| 1187 | BuiltinFnIdMemcpy, | 1200 | BuiltinFnIdMemcpy, |
| 1188 | BuiltinFnIdMemset, | 1201 | BuiltinFnIdMemset, |
| 1189 | BuiltinFnIdSizeof, | 1202 | BuiltinFnIdSizeof, |
| 1190 | BuiltinFnIdPreferredAlignOf, | 1203 | BuiltinFnIdAlignOf, |
| 1191 | BuiltinFnIdAbiAlignOf, | ||
| 1192 | BuiltinFnIdMaxValue, | 1204 | BuiltinFnIdMaxValue, |
| 1193 | BuiltinFnIdMinValue, | 1205 | BuiltinFnIdMinValue, |
| 1194 | BuiltinFnIdMemberCount, | 1206 | BuiltinFnIdMemberCount, |
| ... | @@ -1224,7 +1236,6 @@ enum BuiltinFnId { | ... | @@ -1224,7 +1236,6 @@ enum BuiltinFnId { |
| 1224 | BuiltinFnIdSetFloatMode, | 1236 | BuiltinFnIdSetFloatMode, |
| 1225 | BuiltinFnIdTypeName, | 1237 | BuiltinFnIdTypeName, |
| 1226 | BuiltinFnIdCanImplicitCast, | 1238 | BuiltinFnIdCanImplicitCast, |
| 1227 | BuiltinFnIdSetGlobalAlign, | ||
| 1228 | BuiltinFnIdSetGlobalSection, | 1239 | BuiltinFnIdSetGlobalSection, |
| 1229 | BuiltinFnIdSetGlobalLinkage, | 1240 | BuiltinFnIdSetGlobalLinkage, |
| 1230 | BuiltinFnIdPanic, | 1241 | BuiltinFnIdPanic, |
| ... | @@ -1277,6 +1288,7 @@ struct TypeId { | ... | @@ -1277,6 +1288,7 @@ struct TypeId { |
| 1277 | TypeTableEntry *child_type; | 1288 | TypeTableEntry *child_type; |
| 1278 | bool is_const; | 1289 | bool is_const; |
| 1279 | bool is_volatile; | 1290 | bool is_volatile; |
| 1291 | uint32_t alignment; | ||
| 1280 | uint32_t bit_offset; | 1292 | uint32_t bit_offset; |
| 1281 | uint32_t unaligned_bit_count; | 1293 | uint32_t unaligned_bit_count; |
| 1282 | } pointer; | 1294 | } pointer; |
| ... | @@ -1392,7 +1404,7 @@ struct CodeGen { | ... | @@ -1392,7 +1404,7 @@ struct CodeGen { |
| 1392 | 1404 | ||
| 1393 | struct { | 1405 | struct { |
| 1394 | TypeTableEntry *entry_bool; | 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 | TypeTableEntry *entry_c_int[CIntTypeCount]; | 1408 | TypeTableEntry *entry_c_int[CIntTypeCount]; |
| 1397 | TypeTableEntry *entry_c_longdouble; | 1409 | TypeTableEntry *entry_c_longdouble; |
| 1398 | TypeTableEntry *entry_c_void; | 1410 | TypeTableEntry *entry_c_void; |
| ... | @@ -1547,6 +1559,8 @@ struct CodeGen { | ... | @@ -1547,6 +1559,8 @@ struct CodeGen { |
| 1547 | 1559 | ||
| 1548 | ZigList<FnTableEntry *> inline_fns; | 1560 | ZigList<FnTableEntry *> inline_fns; |
| 1549 | ZigList<AstNode *> tld_ref_source_node_stack; | 1561 | ZigList<AstNode *> tld_ref_source_node_stack; |
| 1562 | |||
| 1563 | TypeTableEntry *align_amt_type; | ||
| 1550 | }; | 1564 | }; |
| 1551 | 1565 | ||
| 1552 | enum VarLinkage { | 1566 | enum VarLinkage { |
| ... | @@ -1575,6 +1589,7 @@ struct VariableTableEntry { | ... | @@ -1575,6 +1589,7 @@ struct VariableTableEntry { |
| 1575 | size_t ref_count; | 1589 | size_t ref_count; |
| 1576 | VarLinkage linkage; | 1590 | VarLinkage linkage; |
| 1577 | IrInstruction *decl_instruction; | 1591 | IrInstruction *decl_instruction; |
| 1592 | uint32_t align_bytes; | ||
| 1578 | }; | 1593 | }; |
| 1579 | 1594 | ||
| 1580 | struct ErrorTableEntry { | 1595 | struct ErrorTableEntry { |
| ... | @@ -1808,8 +1823,7 @@ enum IrInstructionId { | ... | @@ -1808,8 +1823,7 @@ enum IrInstructionId { |
| 1808 | IrInstructionIdBreakpoint, | 1823 | IrInstructionIdBreakpoint, |
| 1809 | IrInstructionIdReturnAddress, | 1824 | IrInstructionIdReturnAddress, |
| 1810 | IrInstructionIdFrameAddress, | 1825 | IrInstructionIdFrameAddress, |
| 1811 | IrInstructionIdPreferredAlignOf, | 1826 | IrInstructionIdAlignOf, |
| 1812 | IrInstructionIdAbiAlignOf, | ||
| 1813 | IrInstructionIdOverflowOp, | 1827 | IrInstructionIdOverflowOp, |
| 1814 | IrInstructionIdTestErr, | 1828 | IrInstructionIdTestErr, |
| 1815 | IrInstructionIdUnwrapErrCode, | 1829 | IrInstructionIdUnwrapErrCode, |
| ... | @@ -1831,7 +1845,6 @@ enum IrInstructionId { | ... | @@ -1831,7 +1845,6 @@ enum IrInstructionId { |
| 1831 | IrInstructionIdCheckStatementIsVoid, | 1845 | IrInstructionIdCheckStatementIsVoid, |
| 1832 | IrInstructionIdTypeName, | 1846 | IrInstructionIdTypeName, |
| 1833 | IrInstructionIdCanImplicitCast, | 1847 | IrInstructionIdCanImplicitCast, |
| 1834 | IrInstructionIdSetGlobalAlign, | ||
| 1835 | IrInstructionIdSetGlobalSection, | 1848 | IrInstructionIdSetGlobalSection, |
| 1836 | IrInstructionIdSetGlobalLinkage, | 1849 | IrInstructionIdSetGlobalLinkage, |
| 1837 | IrInstructionIdDeclRef, | 1850 | IrInstructionIdDeclRef, |
| ... | @@ -1841,6 +1854,7 @@ enum IrInstructionId { | ... | @@ -1841,6 +1854,7 @@ enum IrInstructionId { |
| 1841 | IrInstructionIdOffsetOf, | 1854 | IrInstructionIdOffsetOf, |
| 1842 | IrInstructionIdTypeId, | 1855 | IrInstructionIdTypeId, |
| 1843 | IrInstructionIdSetEvalBranchQuota, | 1856 | IrInstructionIdSetEvalBranchQuota, |
| 1857 | IrInstructionIdPtrTypeOf, | ||
| 1844 | }; | 1858 | }; |
| 1845 | 1859 | ||
| 1846 | struct IrInstruction { | 1860 | struct IrInstruction { |
| ... | @@ -1976,6 +1990,7 @@ struct IrInstructionDeclVar { | ... | @@ -1976,6 +1990,7 @@ struct IrInstructionDeclVar { |
| 1976 | 1990 | ||
| 1977 | VariableTableEntry *var; | 1991 | VariableTableEntry *var; |
| 1978 | IrInstruction *var_type; | 1992 | IrInstruction *var_type; |
| 1993 | IrInstruction *align_value; | ||
| 1979 | IrInstruction *init_value; | 1994 | IrInstruction *init_value; |
| 1980 | }; | 1995 | }; |
| 1981 | 1996 | ||
| ... | @@ -2152,7 +2167,9 @@ struct IrInstructionArrayType { | ... | @@ -2152,7 +2167,9 @@ struct IrInstructionArrayType { |
| 2152 | struct IrInstructionSliceType { | 2167 | struct IrInstructionSliceType { |
| 2153 | IrInstruction base; | 2168 | IrInstruction base; |
| 2154 | 2169 | ||
| 2170 | IrInstruction *align_value; | ||
| 2155 | bool is_const; | 2171 | bool is_const; |
| 2172 | bool is_volatile; | ||
| 2156 | IrInstruction *child_type; | 2173 | IrInstruction *child_type; |
| 2157 | }; | 2174 | }; |
| 2158 | 2175 | ||
| ... | @@ -2393,13 +2410,7 @@ struct IrInstructionOverflowOp { | ... | @@ -2393,13 +2410,7 @@ struct IrInstructionOverflowOp { |
| 2393 | TypeTableEntry *result_ptr_type; | 2410 | TypeTableEntry *result_ptr_type; |
| 2394 | }; | 2411 | }; |
| 2395 | 2412 | ||
| 2396 | struct IrInstructionPreferredAlignOf { | 2413 | struct IrInstructionAlignOf { |
| 2397 | IrInstruction base; | ||
| 2398 | |||
| 2399 | IrInstruction *type_value; | ||
| 2400 | }; | ||
| 2401 | |||
| 2402 | struct IrInstructionAbiAlignOf { | ||
| 2403 | IrInstruction base; | 2414 | IrInstruction base; |
| 2404 | 2415 | ||
| 2405 | IrInstruction *type_value; | 2416 | IrInstruction *type_value; |
| ... | @@ -2554,13 +2565,6 @@ struct IrInstructionCanImplicitCast { | ... | @@ -2554,13 +2565,6 @@ struct IrInstructionCanImplicitCast { |
| 2554 | IrInstruction *target_value; | 2565 | IrInstruction *target_value; |
| 2555 | }; | 2566 | }; |
| 2556 | 2567 | ||
| 2557 | struct IrInstructionSetGlobalAlign { | ||
| 2558 | IrInstruction base; | ||
| 2559 | |||
| 2560 | Tld *tld; | ||
| 2561 | IrInstruction *value; | ||
| 2562 | }; | ||
| 2563 | |||
| 2564 | struct IrInstructionSetGlobalSection { | 2568 | struct IrInstructionSetGlobalSection { |
| 2565 | IrInstruction base; | 2569 | IrInstruction base; |
| 2566 | 2570 | ||
| ... | @@ -2622,6 +2626,17 @@ struct IrInstructionSetEvalBranchQuota { | ... | @@ -2622,6 +2626,17 @@ struct IrInstructionSetEvalBranchQuota { |
| 2622 | IrInstruction *new_quota; | 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 | static const size_t slice_ptr_index = 0; | 2640 | static const size_t slice_ptr_index = 0; |
| 2626 | static const size_t slice_len_index = 1; | 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,17 +320,21 @@ TypeTableEntry *get_smallest_unsigned_int_type(CodeGen *g, uint64_t x) { |
| 320 | } | 320 | } |
| 321 | 321 | ||
| 322 | TypeTableEntry *get_pointer_to_type_extra(CodeGen *g, TypeTableEntry *child_type, bool is_const, | 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 | assert(child_type->id != TypeTableEntryIdInvalid); | 325 | assert(child_type->id != TypeTableEntryIdInvalid); |
| 326 | 326 | ||
| 327 | TypeId type_id = {}; | 327 | TypeId type_id = {}; |
| 328 | TypeTableEntry **parent_pointer = nullptr; | 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 | type_id.id = TypeTableEntryIdPointer; | 333 | type_id.id = TypeTableEntryIdPointer; |
| 331 | type_id.data.pointer.child_type = child_type; | 334 | type_id.data.pointer.child_type = child_type; |
| 332 | type_id.data.pointer.is_const = is_const; | 335 | type_id.data.pointer.is_const = is_const; |
| 333 | type_id.data.pointer.is_volatile = is_volatile; | 336 | type_id.data.pointer.is_volatile = is_volatile; |
| 337 | type_id.data.pointer.alignment = byte_alignment; | ||
| 334 | type_id.data.pointer.bit_offset = bit_offset; | 338 | type_id.data.pointer.bit_offset = bit_offset; |
| 335 | type_id.data.pointer.unaligned_bit_count = unaligned_bit_count; | 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,11 +356,14 @@ TypeTableEntry *get_pointer_to_type_extra(CodeGen *g, TypeTableEntry *child_type |
| 352 | const char *const_str = is_const ? "const " : ""; | 356 | const char *const_str = is_const ? "const " : ""; |
| 353 | const char *volatile_str = is_volatile ? "volatile " : ""; | 357 | const char *volatile_str = is_volatile ? "volatile " : ""; |
| 354 | buf_resize(&entry->name, 0); | 358 | buf_resize(&entry->name, 0); |
| 355 | if (unaligned_bit_count == 0) { | 359 | if (unaligned_bit_count == 0 && byte_alignment == abi_alignment) { |
| 356 | buf_appendf(&entry->name, "&%s%s%s", const_str, volatile_str, buf_ptr(&child_type->name)); | 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 | } else { | 364 | } else { |
| 358 | buf_appendf(&entry->name, "&:%" PRIu32 ":%" PRIu32 " %s%s%s", bit_offset, | 365 | buf_appendf(&entry->name, "&align %" PRIu32 ":%" PRIu32 ":%" PRIu32 " %s%s%s", byte_alignment, |
| 359 | bit_offset + unaligned_bit_count, const_str, volatile_str, buf_ptr(&child_type->name)); | 366 | bit_offset, bit_offset + unaligned_bit_count, const_str, volatile_str, buf_ptr(&child_type->name)); |
| 360 | } | 367 | } |
| 361 | 368 | ||
| 362 | assert(child_type->id != TypeTableEntryIdInvalid); | 369 | assert(child_type->id != TypeTableEntryIdInvalid); |
| ... | @@ -364,20 +371,29 @@ TypeTableEntry *get_pointer_to_type_extra(CodeGen *g, TypeTableEntry *child_type | ... | @@ -364,20 +371,29 @@ TypeTableEntry *get_pointer_to_type_extra(CodeGen *g, TypeTableEntry *child_type |
| 364 | entry->zero_bits = !type_has_bits(child_type); | 371 | entry->zero_bits = !type_has_bits(child_type); |
| 365 | 372 | ||
| 366 | if (!entry->zero_bits) { | 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); | 382 | 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); | 383 | uint64_t debug_align_in_bits = 8*LLVMABIAlignmentOfType(g->target_data_ref, entry->type_ref); |
| 371 | assert(child_type->di_type); | 384 | assert(child_type->di_type); |
| 372 | entry->di_type = ZigLLVMCreateDebugPointerType(g->dbuilder, child_type->di_type, | 385 | entry->di_type = ZigLLVMCreateDebugPointerType(g->dbuilder, child_type->di_type, |
| 373 | debug_size_in_bits, debug_align_in_bits, buf_ptr(&entry->name)); | 386 | debug_size_in_bits, debug_align_in_bits, buf_ptr(&entry->name)); |
| 387 | } | ||
| 374 | } else { | 388 | } else { |
| 389 | assert(byte_alignment == 0); | ||
| 375 | entry->di_type = g->builtin_types.entry_void->di_type; | 390 | entry->di_type = g->builtin_types.entry_void->di_type; |
| 376 | } | 391 | } |
| 377 | 392 | ||
| 378 | entry->data.pointer.child_type = child_type; | 393 | entry->data.pointer.child_type = child_type; |
| 379 | entry->data.pointer.is_const = is_const; | 394 | entry->data.pointer.is_const = is_const; |
| 380 | entry->data.pointer.is_volatile = is_volatile; | 395 | entry->data.pointer.is_volatile = is_volatile; |
| 396 | entry->data.pointer.alignment = byte_alignment; | ||
| 381 | entry->data.pointer.bit_offset = bit_offset; | 397 | entry->data.pointer.bit_offset = bit_offset; |
| 382 | entry->data.pointer.unaligned_bit_count = unaligned_bit_count; | 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,7 +406,7 @@ TypeTableEntry *get_pointer_to_type_extra(CodeGen *g, TypeTableEntry *child_type |
| 390 | } | 406 | } |
| 391 | 407 | ||
| 392 | TypeTableEntry *get_pointer_to_type(CodeGen *g, TypeTableEntry *child_type, bool is_const) { | 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 | TypeTableEntry *get_maybe_type(CodeGen *g, TypeTableEntry *child_type) { | 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,11 +608,7 @@ TypeTableEntry *get_array_type(CodeGen *g, TypeTableEntry *child_type, uint64_t |
| 592 | return entry; | 608 | return entry; |
| 593 | } | 609 | } |
| 594 | 610 | ||
| 595 | static void slice_type_common_init(CodeGen *g, TypeTableEntry *child_type, | 611 | static void slice_type_common_init(CodeGen *g, TypeTableEntry *pointer_type, TypeTableEntry *entry) { |
| 596 | bool is_const, TypeTableEntry *entry) | ||
| 597 | { | ||
| 598 | TypeTableEntry *pointer_type = get_pointer_to_type(g, child_type, is_const); | ||
| 599 | |||
| 600 | unsigned element_count = 2; | 612 | unsigned element_count = 2; |
| 601 | entry->data.structure.layout = ContainerLayoutAuto; | 613 | entry->data.structure.layout = ContainerLayoutAuto; |
| 602 | entry->data.structure.is_slice = true; | 614 | entry->data.structure.is_slice = true; |
| ... | @@ -612,156 +624,167 @@ static void slice_type_common_init(CodeGen *g, TypeTableEntry *child_type, | ... | @@ -612,156 +624,167 @@ static void slice_type_common_init(CodeGen *g, TypeTableEntry *child_type, |
| 612 | entry->data.structure.fields[slice_len_index].src_index = slice_len_index; | 624 | entry->data.structure.fields[slice_len_index].src_index = slice_len_index; |
| 613 | entry->data.structure.fields[slice_len_index].gen_index = 1; | 625 | entry->data.structure.fields[slice_len_index].gen_index = 1; |
| 614 | 626 | ||
| 615 | assert(type_has_zero_bits_known(child_type)); | 627 | assert(type_has_zero_bits_known(pointer_type->data.pointer.child_type)); |
| 616 | if (child_type->zero_bits) { | 628 | if (pointer_type->data.pointer.child_type->zero_bits) { |
| 617 | entry->data.structure.gen_field_count = 1; | 629 | entry->data.structure.gen_field_count = 1; |
| 618 | entry->data.structure.fields[slice_ptr_index].gen_index = SIZE_MAX; | 630 | entry->data.structure.fields[slice_ptr_index].gen_index = SIZE_MAX; |
| 619 | entry->data.structure.fields[slice_len_index].gen_index = 0; | 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) { | 635 | TypeTableEntry *get_slice_type(CodeGen *g, TypeTableEntry *ptr_type) { |
| 624 | assert(child_type->id != TypeTableEntryIdInvalid); | 636 | assert(ptr_type->id == TypeTableEntryIdPointer); |
| 625 | TypeTableEntry **parent_pointer = &child_type->slice_parent[(is_const ? 1 : 0)]; | ||
| 626 | 637 | ||
| 638 | TypeTableEntry **parent_pointer = &ptr_type->data.pointer.slice_parent; | ||
| 627 | if (*parent_pointer) { | 639 | if (*parent_pointer) { |
| 628 | return *parent_pointer; | 640 | return *parent_pointer; |
| 629 | } else if (is_const) { | 641 | } |
| 630 | TypeTableEntry *var_peer = get_slice_type(g, child_type, false); | ||
| 631 | TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdStruct); | ||
| 632 | entry->is_copyable = true; | ||
| 633 | 642 | ||
| 634 | buf_resize(&entry->name, 0); | 643 | TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdStruct); |
| 635 | buf_appendf(&entry->name, "[]const %s", buf_ptr(&child_type->name)); | 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; | 650 | TypeTableEntry *child_type = ptr_type->data.pointer.child_type; |
| 640 | entry->di_type = var_peer->di_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 | entry->data.structure.complete = true; | 662 | entry->data.structure.complete = true; |
| 642 | entry->data.structure.zero_bits_known = true; | 663 | entry->data.structure.zero_bits_known = true; |
| 664 | entry->data.structure.abi_alignment = peer_slice_type->data.structure.abi_alignment; | ||
| 643 | 665 | ||
| 644 | *parent_pointer = entry; | 666 | *parent_pointer = entry; |
| 645 | return entry; | 667 | return entry; |
| 646 | } else { | 668 | } |
| 647 | TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdStruct); | 669 | |
| 648 | entry->is_copyable = true; | 670 | // If the child type is []const T then we need to make sure the type ref |
| 649 | 671 | // and debug info is the same as if the child type were []T. | |
| 650 | // If the child type is []const T then we need to make sure the type ref | 672 | if (is_slice(child_type)) { |
| 651 | // and debug info is the same as if the child type were []T. | 673 | TypeTableEntry *child_ptr_type = child_type->data.structure.fields[slice_ptr_index].type_entry; |
| 652 | if (is_slice(child_type)) { | 674 | assert(child_ptr_type->id == TypeTableEntryIdPointer); |
| 653 | TypeTableEntry *ptr_type = child_type->data.structure.fields[slice_ptr_index].type_entry; | 675 | TypeTableEntry *grand_child_type = child_ptr_type->data.pointer.child_type; |
| 654 | assert(ptr_type->id == TypeTableEntryIdPointer); | 676 | if (child_ptr_type->data.pointer.is_const || child_ptr_type->data.pointer.is_volatile || |
| 655 | if (ptr_type->data.pointer.is_const) { | 677 | child_ptr_type->data.pointer.alignment != get_abi_alignment(g, grand_child_type)) |
| 656 | TypeTableEntry *non_const_child_type = get_slice_type(g, | 678 | { |
| 657 | ptr_type->data.pointer.child_type, false); | 679 | TypeTableEntry *bland_child_ptr_type = get_pointer_to_type(g, grand_child_type, false); |
| 658 | TypeTableEntry *var_peer = get_slice_type(g, non_const_child_type, false); | 680 | TypeTableEntry *bland_child_slice = get_slice_type(g, bland_child_ptr_type); |
| 659 | 681 | TypeTableEntry *peer_ptr_type = get_pointer_to_type(g, bland_child_slice, false); | |
| 660 | entry->type_ref = var_peer->type_ref; | 682 | TypeTableEntry *peer_slice_type = get_slice_type(g, peer_ptr_type); |
| 661 | entry->di_type = var_peer->di_type; | 683 | |
| 662 | } | 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); | 690 | slice_type_common_init(g, ptr_type, entry); |
| 666 | buf_appendf(&entry->name, "[]%s", buf_ptr(&child_type->name)); | ||
| 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) { | 695 | ZigLLVMDIScope *compile_unit_scope = ZigLLVMCompileUnitToScope(g->compile_unit); |
| 671 | entry->type_ref = LLVMStructCreateNamed(LLVMGetGlobalContext(), buf_ptr(&entry->name)); | 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); | 702 | if (child_type->zero_bits) { |
| 674 | ZigLLVMDIFile *di_file = nullptr; | 703 | LLVMTypeRef element_types[] = { |
| 675 | unsigned line = 0; | 704 | g->builtin_types.entry_usize->type_ref, |
| 676 | entry->di_type = ZigLLVMCreateReplaceableCompositeType(g->dbuilder, | 705 | }; |
| 677 | ZigLLVMTag_DW_structure_type(), buf_ptr(&entry->name), | 706 | LLVMStructSetBody(entry->type_ref, element_types, 1, false); |
| 678 | compile_unit_scope, di_file, line); | ||
| 679 | 707 | ||
| 680 | if (child_type->zero_bits) { | 708 | TypeTableEntry *usize_type = g->builtin_types.entry_usize; |
| 681 | LLVMTypeRef element_types[] = { | 709 | uint64_t len_debug_size_in_bits = 8*LLVMStoreSizeOfType(g->target_data_ref, usize_type->type_ref); |
| 682 | g->builtin_types.entry_usize->type_ref, | 710 | uint64_t len_debug_align_in_bits = 8*LLVMABIAlignmentOfType(g->target_data_ref, usize_type->type_ref); |
| 683 | }; | 711 | uint64_t len_offset_in_bits = 8*LLVMOffsetOfElement(g->target_data_ref, entry->type_ref, 0); |
| 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); | ||
| 712 | 712 | ||
| 713 | unsigned element_count = 2; | 713 | uint64_t debug_size_in_bits = 8*LLVMStoreSizeOfType(g->target_data_ref, entry->type_ref); |
| 714 | LLVMTypeRef element_types[] = { | 714 | uint64_t debug_align_in_bits = 8*LLVMABIAlignmentOfType(g->target_data_ref, entry->type_ref); |
| 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 | } | ||
| 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; | 730 | ZigLLVMReplaceTemporary(g->dbuilder, entry->di_type, replacement_di_type); |
| 760 | entry->data.structure.zero_bits_known = true; | 731 | entry->di_type = replacement_di_type; |
| 761 | 732 | ||
| 762 | *parent_pointer = entry; | 733 | entry->data.structure.abi_alignment = LLVMABIAlignmentOfType(g->target_data_ref, usize_type->type_ref); |
| 763 | return entry; | 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 | TypeTableEntry *get_opaque_type(CodeGen *g, Scope *scope, AstNode *source_node, const char *name) { | 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,26 +1296,24 @@ static void resolve_enum_type(CodeGen *g, TypeTableEntry *enum_type) { |
| 1273 | continue; | 1296 | continue; |
| 1274 | 1297 | ||
| 1275 | uint64_t store_size_in_bits = 8*LLVMStoreSizeOfType(g->target_data_ref, field_type->type_ref); | 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 | assert(store_size_in_bits > 0); | 1301 | assert(store_size_in_bits > 0); |
| 1279 | assert(preferred_align_in_bits > 0); | 1302 | assert(abi_align_in_bits > 0); |
| 1280 | 1303 | ||
| 1281 | union_inner_di_types[type_enum_field->gen_index] = ZigLLVMCreateDebugMemberType(g->dbuilder, | 1304 | union_inner_di_types[type_enum_field->gen_index] = ZigLLVMCreateDebugMemberType(g->dbuilder, |
| 1282 | ZigLLVMTypeToScope(enum_type->di_type), buf_ptr(type_enum_field->name), | 1305 | ZigLLVMTypeToScope(enum_type->di_type), buf_ptr(type_enum_field->name), |
| 1283 | import->di_file, (unsigned)(field_node->line + 1), | 1306 | import->di_file, (unsigned)(field_node->line + 1), |
| 1284 | store_size_in_bits, | 1307 | store_size_in_bits, |
| 1285 | preferred_align_in_bits, | 1308 | abi_align_in_bits, |
| 1286 | 0, | 1309 | 0, |
| 1287 | 0, field_type->di_type); | 1310 | 0, field_type->di_type); |
| 1288 | 1311 | ||
| 1289 | biggest_size_in_bits = max(biggest_size_in_bits, store_size_in_bits); | 1312 | biggest_size_in_bits = max(biggest_size_in_bits, store_size_in_bits); |
| 1290 | 1313 | ||
| 1291 | if (!most_aligned_union_member || | 1314 | if (!most_aligned_union_member || abi_align_in_bits > biggest_align_in_bits) { |
| 1292 | preferred_align_in_bits > biggest_align_in_bits) | ||
| 1293 | { | ||
| 1294 | most_aligned_union_member = field_type; | 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 | size_of_most_aligned_member_in_bits = store_size_in_bits; | 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,7 +1327,7 @@ static void resolve_enum_type(CodeGen *g, TypeTableEntry *enum_type) { |
| 1306 | TypeTableEntry *tag_type_entry = create_enum_tag_type(g, enum_type, tag_int_type); | 1327 | TypeTableEntry *tag_type_entry = create_enum_tag_type(g, enum_type, tag_int_type); |
| 1307 | enum_type->data.enumeration.tag_type = tag_type_entry; | 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 | if (most_aligned_union_member) { | 1332 | if (most_aligned_union_member) { |
| 1312 | // create llvm type for union | 1333 | // create llvm type for union |
| ... | @@ -1328,7 +1349,7 @@ static void resolve_enum_type(CodeGen *g, TypeTableEntry *enum_type) { | ... | @@ -1328,7 +1349,7 @@ static void resolve_enum_type(CodeGen *g, TypeTableEntry *enum_type) { |
| 1328 | } | 1349 | } |
| 1329 | enum_type->data.enumeration.union_type_ref = union_type_ref; | 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 | assert(8*LLVMStoreSizeOfType(g->target_data_ref, union_type_ref) >= biggest_size_in_bits); | 1353 | assert(8*LLVMStoreSizeOfType(g->target_data_ref, union_type_ref) >= biggest_size_in_bits); |
| 1333 | 1354 | ||
| 1334 | if (align_of_tag_in_bits >= biggest_align_in_bits) { | 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,7 +1368,7 @@ static void resolve_enum_type(CodeGen *g, TypeTableEntry *enum_type) { |
| 1347 | 1368 | ||
| 1348 | // create debug type for tag | 1369 | // create debug type for tag |
| 1349 | uint64_t tag_debug_size_in_bits = 8*LLVMStoreSizeOfType(g->target_data_ref, tag_type_entry->type_ref); | 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 | ZigLLVMDIType *tag_di_type = ZigLLVMCreateDebugEnumerationType(g->dbuilder, | 1372 | ZigLLVMDIType *tag_di_type = ZigLLVMCreateDebugEnumerationType(g->dbuilder, |
| 1352 | ZigLLVMTypeToScope(enum_type->di_type), "AnonEnum", | 1373 | ZigLLVMTypeToScope(enum_type->di_type), "AnonEnum", |
| 1353 | import->di_file, (unsigned)(decl_node->line + 1), | 1374 | import->di_file, (unsigned)(decl_node->line + 1), |
| ... | @@ -1405,7 +1426,7 @@ static void resolve_enum_type(CodeGen *g, TypeTableEntry *enum_type) { | ... | @@ -1405,7 +1426,7 @@ static void resolve_enum_type(CodeGen *g, TypeTableEntry *enum_type) { |
| 1405 | 1426 | ||
| 1406 | // create debug type for tag | 1427 | // create debug type for tag |
| 1407 | uint64_t tag_debug_size_in_bits = 8*LLVMStoreSizeOfType(g->target_data_ref, tag_type_entry->type_ref); | 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 | ZigLLVMDIType *tag_di_type = ZigLLVMCreateDebugEnumerationType(g->dbuilder, | 1430 | ZigLLVMDIType *tag_di_type = ZigLLVMCreateDebugEnumerationType(g->dbuilder, |
| 1410 | ZigLLVMFileToScope(import->di_file), buf_ptr(&enum_type->name), | 1431 | ZigLLVMFileToScope(import->di_file), buf_ptr(&enum_type->name), |
| 1411 | import->di_file, (unsigned)(decl_node->line + 1), | 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,7 +1518,7 @@ TypeTableEntry *get_struct_type(CodeGen *g, const char *type_name, const char *f |
| 1497 | TypeStructField *type_struct_field = &struct_type->data.structure.fields[i]; | 1518 | TypeStructField *type_struct_field = &struct_type->data.structure.fields[i]; |
| 1498 | TypeTableEntry *field_type = type_struct_field->type_entry; | 1519 | TypeTableEntry *field_type = type_struct_field->type_entry; |
| 1499 | uint64_t debug_size_in_bits = 8*LLVMStoreSizeOfType(g->target_data_ref, field_type->type_ref); | 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 | uint64_t debug_offset_in_bits = 8*LLVMOffsetOfElement(g->target_data_ref, struct_type->type_ref, i); | 1522 | uint64_t debug_offset_in_bits = 8*LLVMOffsetOfElement(g->target_data_ref, struct_type->type_ref, i); |
| 1502 | di_element_types[i] = ZigLLVMCreateDebugMemberType(g->dbuilder, | 1523 | di_element_types[i] = ZigLLVMCreateDebugMemberType(g->dbuilder, |
| 1503 | ZigLLVMTypeToScope(struct_type->di_type), buf_ptr(type_struct_field->name), | 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,6 +1543,7 @@ TypeTableEntry *get_struct_type(CodeGen *g, const char *type_name, const char *f |
| 1522 | 1543 | ||
| 1523 | ZigLLVMReplaceTemporary(g->dbuilder, struct_type->di_type, replacement_di_type); | 1544 | ZigLLVMReplaceTemporary(g->dbuilder, struct_type->di_type, replacement_di_type); |
| 1524 | struct_type->di_type = replacement_di_type; | 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 | return struct_type; | 1548 | return struct_type; |
| 1527 | } | 1549 | } |
| ... | @@ -1663,6 +1685,10 @@ static void resolve_struct_type(CodeGen *g, TypeTableEntry *struct_type) { | ... | @@ -1663,6 +1685,10 @@ static void resolve_struct_type(CodeGen *g, TypeTableEntry *struct_type) { |
| 1663 | struct_type->data.structure.gen_field_count = (uint32_t)gen_field_count; | 1685 | struct_type->data.structure.gen_field_count = (uint32_t)gen_field_count; |
| 1664 | 1686 | ||
| 1665 | LLVMStructSetBody(struct_type->type_ref, element_types, (unsigned)gen_field_count, packed); | 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 | assert(LLVMStoreSizeOfType(g->target_data_ref, struct_type->type_ref) > 0); | 1692 | assert(LLVMStoreSizeOfType(g->target_data_ref, struct_type->type_ref) > 0); |
| 1667 | 1693 | ||
| 1668 | ZigLLVMDIType **di_element_types = allocate<ZigLLVMDIType*>(debug_field_count); | 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,6 +1786,8 @@ static void resolve_enum_zero_bits(CodeGen *g, TypeTableEntry *enum_type) { |
| 1760 | enum_type->data.enumeration.src_field_count = field_count; | 1786 | enum_type->data.enumeration.src_field_count = field_count; |
| 1761 | enum_type->data.enumeration.fields = allocate<TypeEnumField>(field_count); | 1787 | enum_type->data.enumeration.fields = allocate<TypeEnumField>(field_count); |
| 1762 | 1788 | ||
| 1789 | uint32_t biggest_align_bytes = 0; | ||
| 1790 | |||
| 1763 | Scope *scope = &enum_type->data.enumeration.decls_scope->base; | 1791 | Scope *scope = &enum_type->data.enumeration.decls_scope->base; |
| 1764 | 1792 | ||
| 1765 | uint32_t gen_field_index = 0; | 1793 | uint32_t gen_field_index = 0; |
| ... | @@ -1782,12 +1810,22 @@ static void resolve_enum_zero_bits(CodeGen *g, TypeTableEntry *enum_type) { | ... | @@ -1782,12 +1810,22 @@ static void resolve_enum_zero_bits(CodeGen *g, TypeTableEntry *enum_type) { |
| 1782 | 1810 | ||
| 1783 | type_enum_field->gen_index = gen_field_index; | 1811 | type_enum_field->gen_index = gen_field_index; |
| 1784 | gen_field_index += 1; | 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 | enum_type->data.enumeration.zero_bits_loop_flag = false; | 1820 | enum_type->data.enumeration.zero_bits_loop_flag = false; |
| 1788 | enum_type->data.enumeration.gen_field_count = gen_field_index; | 1821 | enum_type->data.enumeration.gen_field_count = gen_field_index; |
| 1789 | enum_type->zero_bits = (gen_field_index == 0 && field_count < 2); | 1822 | enum_type->zero_bits = (gen_field_index == 0 && field_count < 2); |
| 1790 | enum_type->data.enumeration.zero_bits_known = true; | 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 | static void resolve_struct_zero_bits(CodeGen *g, TypeTableEntry *struct_type) { | 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,7 +1835,19 @@ static void resolve_struct_zero_bits(CodeGen *g, TypeTableEntry *struct_type) { |
| 1797 | return; | 1835 | return; |
| 1798 | 1836 | ||
| 1799 | if (struct_type->data.structure.zero_bits_loop_flag) { | 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 | struct_type->data.structure.zero_bits_known = true; | 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 | return; | 1851 | return; |
| 1802 | } | 1852 | } |
| 1803 | 1853 | ||
| ... | @@ -1833,6 +1883,17 @@ static void resolve_struct_zero_bits(CodeGen *g, TypeTableEntry *struct_type) { | ... | @@ -1833,6 +1883,17 @@ static void resolve_struct_zero_bits(CodeGen *g, TypeTableEntry *struct_type) { |
| 1833 | if (!type_has_bits(field_type)) | 1883 | if (!type_has_bits(field_type)) |
| 1834 | continue; | 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 | type_struct_field->gen_index = gen_field_index; | 1897 | type_struct_field->gen_index = gen_field_index; |
| 1837 | gen_field_index += 1; | 1898 | gen_field_index += 1; |
| 1838 | } | 1899 | } |
| ... | @@ -1925,7 +1986,8 @@ static void typecheck_panic_fn(CodeGen *g, FnTableEntry *panic_fn) { | ... | @@ -1925,7 +1986,8 @@ static void typecheck_panic_fn(CodeGen *g, FnTableEntry *panic_fn) { |
| 1925 | if (fn_type_id->param_count != 1) { | 1986 | if (fn_type_id->param_count != 1) { |
| 1926 | return wrong_panic_prototype(g, proto_node, fn_type); | 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 | if (fn_type_id->param_info[0].type != const_u8_slice) { | 1991 | if (fn_type_id->param_info[0].type != const_u8_slice) { |
| 1930 | return wrong_panic_prototype(g, proto_node, fn_type); | 1992 | return wrong_panic_prototype(g, proto_node, fn_type); |
| 1931 | } | 1993 | } |
| ... | @@ -1946,6 +2008,25 @@ TypeTableEntry *get_test_fn_type(CodeGen *g) { | ... | @@ -1946,6 +2008,25 @@ TypeTableEntry *get_test_fn_type(CodeGen *g) { |
| 1946 | return g->test_fn_type; | 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 | static void resolve_decl_fn(CodeGen *g, TldFn *tld_fn) { | 2030 | static void resolve_decl_fn(CodeGen *g, TldFn *tld_fn) { |
| 1950 | ImportTableEntry *import = tld_fn->base.import; | 2031 | ImportTableEntry *import = tld_fn->base.import; |
| 1951 | AstNode *source_node = tld_fn->base.source_node; | 2032 | AstNode *source_node = tld_fn->base.source_node; |
| ... | @@ -1982,6 +2063,16 @@ static void resolve_decl_fn(CodeGen *g, TldFn *tld_fn) { | ... | @@ -1982,6 +2063,16 @@ static void resolve_decl_fn(CodeGen *g, TldFn *tld_fn) { |
| 1982 | return; | 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 | if (!fn_table_entry->type_entry->data.fn.is_generic) { | 2076 | if (!fn_table_entry->type_entry->data.fn.is_generic) { |
| 1986 | g->fn_protos.append(fn_table_entry); | 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,6 +2240,7 @@ void update_compile_var(CodeGen *g, Buf *name, ConstExprValue *value) { |
| 2149 | assert(tld->id == TldIdVar); | 2240 | assert(tld->id == TldIdVar); |
| 2150 | TldVar *tld_var = (TldVar *)tld; | 2241 | TldVar *tld_var = (TldVar *)tld; |
| 2151 | tld_var->var->value = value; | 2242 | tld_var->var->value = value; |
| 2243 | tld_var->var->align_bytes = get_abi_alignment(g, value->type); | ||
| 2152 | } | 2244 | } |
| 2153 | 2245 | ||
| 2154 | void scan_decls(CodeGen *g, ScopeDecls *decls_scope, AstNode *node) { | 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,6 +2328,7 @@ void scan_decls(CodeGen *g, ScopeDecls *decls_scope, AstNode *node) { |
| 2236 | case NodeTypeThisLiteral: | 2328 | case NodeTypeThisLiteral: |
| 2237 | case NodeTypeSymbol: | 2329 | case NodeTypeSymbol: |
| 2238 | case NodeTypePrefixOpExpr: | 2330 | case NodeTypePrefixOpExpr: |
| 2331 | case NodeTypeAddrOfExpr: | ||
| 2239 | case NodeTypeIfBoolExpr: | 2332 | case NodeTypeIfBoolExpr: |
| 2240 | case NodeTypeWhileExpr: | 2333 | case NodeTypeWhileExpr: |
| 2241 | case NodeTypeForExpr: | 2334 | case NodeTypeForExpr: |
| ... | @@ -2331,6 +2424,7 @@ VariableTableEntry *add_variable(CodeGen *g, AstNode *source_node, Scope *parent | ... | @@ -2331,6 +2424,7 @@ VariableTableEntry *add_variable(CodeGen *g, AstNode *source_node, Scope *parent |
| 2331 | variable_entry->shadowable = false; | 2424 | variable_entry->shadowable = false; |
| 2332 | variable_entry->mem_slot_index = SIZE_MAX; | 2425 | variable_entry->mem_slot_index = SIZE_MAX; |
| 2333 | variable_entry->src_arg_index = SIZE_MAX; | 2426 | variable_entry->src_arg_index = SIZE_MAX; |
| 2427 | variable_entry->align_bytes = get_abi_alignment(g, value->type); | ||
| 2334 | 2428 | ||
| 2335 | assert(name); | 2429 | assert(name); |
| 2336 | 2430 | ||
| ... | @@ -2389,7 +2483,8 @@ VariableTableEntry *add_variable(CodeGen *g, AstNode *source_node, Scope *parent | ... | @@ -2389,7 +2483,8 @@ VariableTableEntry *add_variable(CodeGen *g, AstNode *source_node, Scope *parent |
| 2389 | } | 2483 | } |
| 2390 | 2484 | ||
| 2391 | static void resolve_decl_var(CodeGen *g, TldVar *tld_var) { | 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 | bool is_const = var_decl->is_const; | 2489 | bool is_const = var_decl->is_const; |
| 2395 | bool is_export = (tld_var->base.visib_mod == VisibModExport); | 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,8 +2496,6 @@ static void resolve_decl_var(CodeGen *g, TldVar *tld_var) { |
| 2401 | explicit_type = validate_var_type(g, var_decl->type, proposed_type); | 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 | if (is_export && is_extern) { | 2499 | if (is_export && is_extern) { |
| 2407 | add_node_error(g, source_node, buf_sprintf("variable is both export and extern")); | 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,6 +2551,12 @@ static void resolve_decl_var(CodeGen *g, TldVar *tld_var) { |
| 2458 | is_const, init_val, &tld_var->base); | 2551 | is_const, init_val, &tld_var->base); |
| 2459 | tld_var->var->linkage = linkage; | 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 | g->global_vars.append(tld_var); | 2560 | g->global_vars.append(tld_var); |
| 2462 | } | 2561 | } |
| 2463 | 2562 | ||
| ... | @@ -3129,26 +3228,28 @@ void semantic_analyze(CodeGen *g) { | ... | @@ -3129,26 +3228,28 @@ void semantic_analyze(CodeGen *g) { |
| 3129 | 3228 | ||
| 3130 | TypeTableEntry **get_int_type_ptr(CodeGen *g, bool is_signed, uint32_t size_in_bits) { | 3229 | TypeTableEntry **get_int_type_ptr(CodeGen *g, bool is_signed, uint32_t size_in_bits) { |
| 3131 | size_t index; | 3230 | size_t index; |
| 3132 | if (size_in_bits == 3) { | 3231 | if (size_in_bits == 2) { |
| 3133 | index = 0; | 3232 | index = 0; |
| 3134 | } else if (size_in_bits == 4) { | 3233 | } else if (size_in_bits == 3) { |
| 3135 | index = 1; | 3234 | index = 1; |
| 3136 | } else if (size_in_bits == 5) { | 3235 | } else if (size_in_bits == 4) { |
| 3137 | index = 2; | 3236 | index = 2; |
| 3138 | } else if (size_in_bits == 6) { | 3237 | } else if (size_in_bits == 5) { |
| 3139 | index = 3; | 3238 | index = 3; |
| 3140 | } else if (size_in_bits == 7) { | 3239 | } else if (size_in_bits == 6) { |
| 3141 | index = 4; | 3240 | index = 4; |
| 3142 | } else if (size_in_bits == 8) { | 3241 | } else if (size_in_bits == 7) { |
| 3143 | index = 5; | 3242 | index = 5; |
| 3144 | } else if (size_in_bits == 16) { | 3243 | } else if (size_in_bits == 8) { |
| 3145 | index = 6; | 3244 | index = 6; |
| 3146 | } else if (size_in_bits == 32) { | 3245 | } else if (size_in_bits == 16) { |
| 3147 | index = 7; | 3246 | index = 7; |
| 3148 | } else if (size_in_bits == 64) { | 3247 | } else if (size_in_bits == 32) { |
| 3149 | index = 8; | 3248 | index = 8; |
| 3150 | } else if (size_in_bits == 128) { | 3249 | } else if (size_in_bits == 64) { |
| 3151 | index = 9; | 3250 | index = 9; |
| 3251 | } else if (size_in_bits == 128) { | ||
| 3252 | index = 10; | ||
| 3152 | } else { | 3253 | } else { |
| 3153 | return nullptr; | 3254 | return nullptr; |
| 3154 | } | 3255 | } |
| ... | @@ -3723,8 +3824,10 @@ void init_const_slice(CodeGen *g, ConstExprValue *const_val, ConstExprValue *arr | ... | @@ -3723,8 +3824,10 @@ void init_const_slice(CodeGen *g, ConstExprValue *const_val, ConstExprValue *arr |
| 3723 | { | 3824 | { |
| 3724 | assert(array_val->type->id == TypeTableEntryIdArray); | 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 | const_val->special = ConstValSpecialStatic; | 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 | const_val->data.x_struct.fields = create_const_vals(2); | 3831 | const_val->data.x_struct.fields = create_const_vals(2); |
| 3729 | 3832 | ||
| 3730 | init_const_ptr_array(g, &const_val->data.x_struct.fields[slice_ptr_index], array_val, start, is_const); | 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,14 +4445,15 @@ uint32_t type_id_hash(TypeId x) { |
| 4342 | return hash_ptr(x.data.pointer.child_type) + | 4445 | return hash_ptr(x.data.pointer.child_type) + |
| 4343 | (x.data.pointer.is_const ? (uint32_t)2749109194 : (uint32_t)4047371087) + | 4446 | (x.data.pointer.is_const ? (uint32_t)2749109194 : (uint32_t)4047371087) + |
| 4344 | (x.data.pointer.is_volatile ? (uint32_t)536730450 : (uint32_t)1685612214) + | 4447 | (x.data.pointer.is_volatile ? (uint32_t)536730450 : (uint32_t)1685612214) + |
| 4345 | (((uint32_t)x.data.pointer.bit_offset) * (uint32_t)2639019452) + | 4448 | (((uint32_t)x.data.pointer.alignment) ^ (uint32_t)0x777fbe0e) + |
| 4346 | (((uint32_t)x.data.pointer.unaligned_bit_count) * (uint32_t)529908881); | 4449 | (((uint32_t)x.data.pointer.bit_offset) ^ (uint32_t)2639019452) + |
| 4450 | (((uint32_t)x.data.pointer.unaligned_bit_count) ^ (uint32_t)529908881); | ||
| 4347 | case TypeTableEntryIdArray: | 4451 | case TypeTableEntryIdArray: |
| 4348 | return hash_ptr(x.data.array.child_type) + | 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 | case TypeTableEntryIdInt: | 4454 | case TypeTableEntryIdInt: |
| 4351 | return (x.data.integer.is_signed ? (uint32_t)2652528194 : (uint32_t)163929201) + | 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 | zig_unreachable(); | 4458 | zig_unreachable(); |
| 4355 | } | 4459 | } |
| ... | @@ -4387,6 +4491,7 @@ bool type_id_eql(TypeId a, TypeId b) { | ... | @@ -4387,6 +4491,7 @@ bool type_id_eql(TypeId a, TypeId b) { |
| 4387 | return a.data.pointer.child_type == b.data.pointer.child_type && | 4491 | return a.data.pointer.child_type == b.data.pointer.child_type && |
| 4388 | a.data.pointer.is_const == b.data.pointer.is_const && | 4492 | a.data.pointer.is_const == b.data.pointer.is_const && |
| 4389 | a.data.pointer.is_volatile == b.data.pointer.is_volatile && | 4493 | a.data.pointer.is_volatile == b.data.pointer.is_volatile && |
| 4494 | a.data.pointer.alignment == b.data.pointer.alignment && | ||
| 4390 | a.data.pointer.bit_offset == b.data.pointer.bit_offset && | 4495 | a.data.pointer.bit_offset == b.data.pointer.bit_offset && |
| 4391 | a.data.pointer.unaligned_bit_count == b.data.pointer.unaligned_bit_count; | 4496 | a.data.pointer.unaligned_bit_count == b.data.pointer.unaligned_bit_count; |
| 4392 | case TypeTableEntryIdArray: | 4497 | case TypeTableEntryIdArray: |
| ... | @@ -4692,3 +4797,30 @@ void add_link_lib_symbol(CodeGen *g, Buf *lib_name, Buf *symbol_name) { | ... | @@ -4692,3 +4797,30 @@ void add_link_lib_symbol(CodeGen *g, Buf *lib_name, Buf *symbol_name) { |
| 4692 | } | 4797 | } |
| 4693 | link_lib->symbols.append(symbol_name); | 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,7 +16,7 @@ ErrorMsg *add_error_note(CodeGen *g, ErrorMsg *parent_msg, AstNode *node, Buf *m |
| 16 | TypeTableEntry *new_type_table_entry(TypeTableEntryId id); | 16 | TypeTableEntry *new_type_table_entry(TypeTableEntryId id); |
| 17 | TypeTableEntry *get_pointer_to_type(CodeGen *g, TypeTableEntry *child_type, bool is_const); | 17 | TypeTableEntry *get_pointer_to_type(CodeGen *g, TypeTableEntry *child_type, bool is_const); |
| 18 | TypeTableEntry *get_pointer_to_type_extra(CodeGen *g, TypeTableEntry *child_type, bool is_const, | 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 | uint64_t type_size(CodeGen *g, TypeTableEntry *type_entry); | 20 | uint64_t type_size(CodeGen *g, TypeTableEntry *type_entry); |
| 21 | uint64_t type_size_bits(CodeGen *g, TypeTableEntry *type_entry); | 21 | uint64_t type_size_bits(CodeGen *g, TypeTableEntry *type_entry); |
| 22 | TypeTableEntry **get_int_type_ptr(CodeGen *g, bool is_signed, uint32_t size_in_bits); | 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,7 +26,7 @@ TypeTableEntry *get_c_int_type(CodeGen *g, CIntType c_int_type); |
| 26 | TypeTableEntry *get_fn_type(CodeGen *g, FnTypeId *fn_type_id); | 26 | TypeTableEntry *get_fn_type(CodeGen *g, FnTypeId *fn_type_id); |
| 27 | TypeTableEntry *get_maybe_type(CodeGen *g, TypeTableEntry *child_type); | 27 | TypeTableEntry *get_maybe_type(CodeGen *g, TypeTableEntry *child_type); |
| 28 | TypeTableEntry *get_array_type(CodeGen *g, TypeTableEntry *child_type, uint64_t array_size); | 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 | TypeTableEntry *get_partial_container_type(CodeGen *g, Scope *scope, ContainerKind kind, | 30 | TypeTableEntry *get_partial_container_type(CodeGen *g, Scope *scope, ContainerKind kind, |
| 31 | AstNode *decl_node, const char *name, ContainerLayout layout); | 31 | AstNode *decl_node, const char *name, ContainerLayout layout); |
| 32 | TypeTableEntry *get_smallest_unsigned_int_type(CodeGen *g, uint64_t x); | 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,4 +171,7 @@ bool calling_convention_does_first_arg_return(CallingConvention cc); |
| 171 | LinkLib *add_link_lib(CodeGen *codegen, Buf *lib); | 171 | LinkLib *add_link_lib(CodeGen *codegen, Buf *lib); |
| 172 | void add_link_lib_symbol(CodeGen *g, Buf *lib_name, Buf *symbol_name); | 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 | #endif | 177 | #endif |
src/ast_render.cpp+34-4| ... | @@ -65,10 +65,6 @@ static const char *prefix_op_str(PrefixOp prefix_op) { | ... | @@ -65,10 +65,6 @@ static const char *prefix_op_str(PrefixOp prefix_op) { |
| 65 | case PrefixOpNegationWrap: return "-%"; | 65 | case PrefixOpNegationWrap: return "-%"; |
| 66 | case PrefixOpBoolNot: return "!"; | 66 | case PrefixOpBoolNot: return "!"; |
| 67 | case PrefixOpBinNot: return "~"; | 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 | case PrefixOpDereference: return "*"; | 68 | case PrefixOpDereference: return "*"; |
| 73 | case PrefixOpMaybe: return "?"; | 69 | case PrefixOpMaybe: return "?"; |
| 74 | case PrefixOpError: return "%"; | 70 | case PrefixOpError: return "%"; |
| ... | @@ -192,6 +188,8 @@ static const char *node_type_str(NodeType node_type) { | ... | @@ -192,6 +188,8 @@ static const char *node_type_str(NodeType node_type) { |
| 192 | return "Symbol"; | 188 | return "Symbol"; |
| 193 | case NodeTypePrefixOpExpr: | 189 | case NodeTypePrefixOpExpr: |
| 194 | return "PrefixOpExpr"; | 190 | return "PrefixOpExpr"; |
| 191 | case NodeTypeAddrOfExpr: | ||
| 192 | return "AddrOfExpr"; | ||
| 195 | case NodeTypeUse: | 193 | case NodeTypeUse: |
| 196 | return "Use"; | 194 | return "Use"; |
| 197 | case NodeTypeBoolLiteral: | 195 | case NodeTypeBoolLiteral: |
| ... | @@ -583,6 +581,38 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) { | ... | @@ -583,6 +581,38 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) { |
| 583 | render_node_ungrouped(ar, node->data.prefix_op_expr.primary_expr); | 581 | render_node_ungrouped(ar, node->data.prefix_op_expr.primary_expr); |
| 584 | break; | 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 | case NodeTypeFnCallExpr: | 616 | case NodeTypeFnCallExpr: |
| 587 | { | 617 | { |
| 588 | if (node->data.fn_call_expr.is_builtin) { | 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,6 +350,12 @@ static LLVMCallConv get_llvm_cc(CodeGen *g, CallingConvention cc) { |
| 350 | zig_unreachable(); | 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 | static LLVMValueRef fn_llvm_value(CodeGen *g, FnTableEntry *fn_table_entry) { | 359 | static LLVMValueRef fn_llvm_value(CodeGen *g, FnTableEntry *fn_table_entry) { |
| 354 | if (fn_table_entry->llvm_value) | 360 | if (fn_table_entry->llvm_value) |
| 355 | return fn_table_entry->llvm_value; | 361 | return fn_table_entry->llvm_value; |
| ... | @@ -442,14 +448,14 @@ static LLVMValueRef fn_llvm_value(CodeGen *g, FnTableEntry *fn_table_entry) { | ... | @@ -442,14 +448,14 @@ static LLVMValueRef fn_llvm_value(CodeGen *g, FnTableEntry *fn_table_entry) { |
| 442 | if (fn_table_entry->section_name) { | 448 | if (fn_table_entry->section_name) { |
| 443 | LLVMSetSection(fn_table_entry->llvm_value, buf_ptr(fn_table_entry->section_name)); | 449 | LLVMSetSection(fn_table_entry->llvm_value, buf_ptr(fn_table_entry->section_name)); |
| 444 | } | 450 | } |
| 445 | if (fn_table_entry->alignment) { | 451 | if (fn_table_entry->align_bytes > 0) { |
| 446 | LLVMSetAlignment(fn_table_entry->llvm_value, (unsigned)fn_table_entry->alignment); | 452 | LLVMSetAlignment(fn_table_entry->llvm_value, (unsigned)fn_table_entry->align_bytes); |
| 447 | } else if (external_linkage) { | 453 | } else if (fn_table_entry->type_entry->data.fn.fn_type_id.cc == CallingConventionUnspecified) { |
| 448 | LLVMSetAlignment(fn_table_entry->llvm_value, | 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 | } else { | 456 | } else { |
| 451 | LLVMSetAlignment(fn_table_entry->llvm_value, | 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 | return fn_table_entry->llvm_value; | 461 | return fn_table_entry->llvm_value; |
| ... | @@ -604,13 +610,15 @@ static LLVMValueRef get_floor_ceil_fn(CodeGen *g, TypeTableEntry *type_entry, Zi | ... | @@ -604,13 +610,15 @@ static LLVMValueRef get_floor_ceil_fn(CodeGen *g, TypeTableEntry *type_entry, Zi |
| 604 | return fn_val; | 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 | if (type_has_bits(type)) { | 614 | if (type_has_bits(type)) { |
| 609 | if (handle_is_ptr(type)) { | 615 | if (handle_is_ptr(type)) { |
| 610 | return ptr; | 616 | return ptr; |
| 611 | } else { | 617 | } else { |
| 618 | assert(ptr_type->id == TypeTableEntryIdPointer); | ||
| 612 | LLVMValueRef result = LLVMBuildLoad(g->builder, ptr, ""); | 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 | return result; | 622 | return result; |
| 615 | } | 623 | } |
| 616 | } else { | 624 | } else { |
| ... | @@ -657,34 +665,6 @@ static bool ir_want_debug_safety(CodeGen *g, IrInstruction *instruction) { | ... | @@ -657,34 +665,6 @@ static bool ir_want_debug_safety(CodeGen *g, IrInstruction *instruction) { |
| 657 | return true; | 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 | static Buf *panic_msg_buf(PanicMsgId msg_id) { | 668 | static Buf *panic_msg_buf(PanicMsgId msg_id) { |
| 689 | switch (msg_id) { | 669 | switch (msg_id) { |
| 690 | case PanicMsgIdCount: | 670 | case PanicMsgIdCount: |
| ... | @@ -745,7 +725,8 @@ static void gen_panic_raw(CodeGen *g, LLVMValueRef msg_ptr, LLVMValueRef msg_len | ... | @@ -745,7 +725,8 @@ static void gen_panic_raw(CodeGen *g, LLVMValueRef msg_ptr, LLVMValueRef msg_len |
| 745 | } | 725 | } |
| 746 | 726 | ||
| 747 | static void gen_panic(CodeGen *g, LLVMValueRef msg_arg) { | 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 | size_t ptr_index = str_type->data.structure.fields[slice_ptr_index].gen_index; | 730 | size_t ptr_index = str_type->data.structure.fields[slice_ptr_index].gen_index; |
| 750 | size_t len_index = str_type->data.structure.fields[slice_len_index].gen_index; | 731 | size_t len_index = str_type->data.structure.fields[slice_len_index].gen_index; |
| 751 | LLVMValueRef ptr_ptr = LLVMBuildStructGEP(g->builder, msg_arg, (unsigned)ptr_index, ""); | 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,7 +787,7 @@ static LLVMValueRef get_safety_crash_err_fn(CodeGen *g) { |
| 806 | LLVMSetLinkage(global_value, LLVMInternalLinkage); | 787 | LLVMSetLinkage(global_value, LLVMInternalLinkage); |
| 807 | LLVMSetGlobalConstant(global_value, false); | 788 | LLVMSetGlobalConstant(global_value, false); |
| 808 | LLVMSetUnnamedAddr(global_value, true); | 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 | TypeTableEntry *usize = g->builtin_types.entry_usize; | 792 | TypeTableEntry *usize = g->builtin_types.entry_usize; |
| 812 | LLVMValueRef full_buf_ptr_indices[] = { | 793 | LLVMValueRef full_buf_ptr_indices[] = { |
| ... | @@ -833,7 +814,7 @@ static LLVMValueRef get_safety_crash_err_fn(CodeGen *g) { | ... | @@ -833,7 +814,7 @@ static LLVMValueRef get_safety_crash_err_fn(CodeGen *g) { |
| 833 | ZigLLVMAddFunctionAttr(fn_val, "no-frame-pointer-elim", "true"); | 814 | ZigLLVMAddFunctionAttr(fn_val, "no-frame-pointer-elim", "true"); |
| 834 | ZigLLVMAddFunctionAttr(fn_val, "no-frame-pointer-elim-non-leaf", nullptr); | 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 | LLVMBasicBlockRef entry_block = LLVMAppendBasicBlock(fn_val, "Entry"); | 819 | LLVMBasicBlockRef entry_block = LLVMAppendBasicBlock(fn_val, "Entry"); |
| 839 | LLVMBasicBlockRef prev_block = LLVMGetInsertBlock(g->builder); | 820 | LLVMBasicBlockRef prev_block = LLVMGetInsertBlock(g->builder); |
| ... | @@ -1056,50 +1037,49 @@ static LLVMRealPredicate cmp_op_to_real_predicate(IrBinOp cmp_op) { | ... | @@ -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 | static LLVMValueRef gen_assign_raw(CodeGen *g, LLVMValueRef ptr, TypeTableEntry *ptr_type, | 1040 | static LLVMValueRef gen_assign_raw(CodeGen *g, LLVMValueRef ptr, TypeTableEntry *ptr_type, |
| 1090 | LLVMValueRef value) | 1041 | LLVMValueRef value) |
| 1091 | { | 1042 | { |
| 1043 | assert(ptr_type->id == TypeTableEntryIdPointer); | ||
| 1092 | TypeTableEntry *child_type = ptr_type->data.pointer.child_type; | 1044 | TypeTableEntry *child_type = ptr_type->data.pointer.child_type; |
| 1093 | 1045 | ||
| 1094 | if (!type_has_bits(child_type)) | 1046 | if (!type_has_bits(child_type)) |
| 1095 | return nullptr; | 1047 | return nullptr; |
| 1096 | 1048 | ||
| 1097 | if (handle_is_ptr(child_type)) | 1049 | if (handle_is_ptr(child_type)) { |
| 1098 | return gen_struct_memcpy(g, value, 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 | uint32_t unaligned_bit_count = ptr_type->data.pointer.unaligned_bit_count; | 1079 | uint32_t unaligned_bit_count = ptr_type->data.pointer.unaligned_bit_count; |
| 1101 | if (unaligned_bit_count == 0) { | 1080 | if (unaligned_bit_count == 0) { |
| 1102 | LLVMValueRef llvm_instruction = LLVMBuildStore(g->builder, value, ptr); | 1081 | LLVMValueRef llvm_instruction = LLVMBuildStore(g->builder, value, ptr); |
| 1082 | LLVMSetAlignment(llvm_instruction, ptr_type->data.pointer.alignment); | ||
| 1103 | LLVMSetVolatile(llvm_instruction, ptr_type->data.pointer.is_volatile); | 1083 | LLVMSetVolatile(llvm_instruction, ptr_type->data.pointer.is_volatile); |
| 1104 | return nullptr; | 1084 | return nullptr; |
| 1105 | } | 1085 | } |
| ... | @@ -1122,6 +1102,7 @@ static LLVMValueRef gen_assign_raw(CodeGen *g, LLVMValueRef ptr, TypeTableEntry | ... | @@ -1122,6 +1102,7 @@ static LLVMValueRef gen_assign_raw(CodeGen *g, LLVMValueRef ptr, TypeTableEntry |
| 1122 | LLVMValueRef ored_value = LLVMBuildOr(g->builder, shifted_value, anded_containing_int, ""); | 1102 | LLVMValueRef ored_value = LLVMBuildOr(g->builder, shifted_value, anded_containing_int, ""); |
| 1123 | 1103 | ||
| 1124 | LLVMValueRef llvm_instruction = LLVMBuildStore(g->builder, ored_value, ptr); | 1104 | LLVMValueRef llvm_instruction = LLVMBuildStore(g->builder, ored_value, ptr); |
| 1105 | LLVMSetAlignment(llvm_instruction, ptr_type->data.pointer.alignment); | ||
| 1125 | LLVMSetVolatile(llvm_instruction, ptr_type->data.pointer.is_volatile); | 1106 | LLVMSetVolatile(llvm_instruction, ptr_type->data.pointer.is_volatile); |
| 1126 | return nullptr; | 1107 | return nullptr; |
| 1127 | } | 1108 | } |
| ... | @@ -2010,23 +1991,24 @@ static LLVMValueRef ir_render_decl_var(CodeGen *g, IrExecutable *executable, | ... | @@ -2010,23 +1991,24 @@ static LLVMValueRef ir_render_decl_var(CodeGen *g, IrExecutable *executable, |
| 2010 | 1991 | ||
| 2011 | if (have_init_expr) { | 1992 | if (have_init_expr) { |
| 2012 | assert(var->value->type == init_value->value.type); | 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), | 1994 | TypeTableEntry *var_ptr_type = get_pointer_to_type_extra(g, var->value->type, false, false, |
| 2014 | ir_llvm_value(g, init_value)); | 1995 | var->align_bytes, 0, 0); |
| 1996 | gen_assign_raw(g, var->value_ref, var_ptr_type, ir_llvm_value(g, init_value)); | ||
| 2015 | } else { | 1997 | } else { |
| 2016 | bool ignore_uninit = false; | ||
| 2017 | // handle runtime stack allocation | ||
| 2018 | bool want_safe = ir_want_debug_safety(g, &decl_var_instruction->base); | 1998 | bool want_safe = ir_want_debug_safety(g, &decl_var_instruction->base); |
| 2019 | if (!ignore_uninit && want_safe) { | 1999 | if (want_safe) { |
| 2020 | TypeTableEntry *usize = g->builtin_types.entry_usize; | 2000 | TypeTableEntry *usize = g->builtin_types.entry_usize; |
| 2021 | uint64_t size_bytes = LLVMStoreSizeOfType(g->target_data_ref, var->value->type->type_ref); | 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 | // memset uninitialized memory to 0xa | 2006 | // memset uninitialized memory to 0xa |
| 2025 | LLVMTypeRef ptr_u8 = LLVMPointerType(LLVMInt8Type(), 0); | 2007 | LLVMTypeRef ptr_u8 = LLVMPointerType(LLVMInt8Type(), 0); |
| 2026 | LLVMValueRef fill_char = LLVMConstInt(LLVMInt8Type(), 0xaa, false); | 2008 | LLVMValueRef fill_char = LLVMConstInt(LLVMInt8Type(), 0xaa, false); |
| 2027 | LLVMValueRef dest_ptr = LLVMBuildBitCast(g->builder, var->value_ref, ptr_u8, ""); | 2009 | LLVMValueRef dest_ptr = LLVMBuildBitCast(g->builder, var->value_ref, ptr_u8, ""); |
| 2028 | LLVMValueRef byte_count = LLVMConstInt(usize->type_ref, size_bytes, false); | 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 | LLVMValueRef params[] = { | 2012 | LLVMValueRef params[] = { |
| 2031 | dest_ptr, | 2013 | dest_ptr, |
| 2032 | fill_char, | 2014 | fill_char, |
| ... | @@ -2051,15 +2033,14 @@ static LLVMValueRef ir_render_load_ptr(CodeGen *g, IrExecutable *executable, IrI | ... | @@ -2051,15 +2033,14 @@ static LLVMValueRef ir_render_load_ptr(CodeGen *g, IrExecutable *executable, IrI |
| 2051 | LLVMValueRef ptr = ir_llvm_value(g, instruction->ptr); | 2033 | LLVMValueRef ptr = ir_llvm_value(g, instruction->ptr); |
| 2052 | TypeTableEntry *ptr_type = instruction->ptr->value.type; | 2034 | TypeTableEntry *ptr_type = instruction->ptr->value.type; |
| 2053 | assert(ptr_type->id == TypeTableEntryIdPointer); | 2035 | assert(ptr_type->id == TypeTableEntryIdPointer); |
| 2054 | bool is_volatile = ptr_type->data.pointer.is_volatile; | ||
| 2055 | 2036 | ||
| 2056 | uint32_t unaligned_bit_count = ptr_type->data.pointer.unaligned_bit_count; | 2037 | uint32_t unaligned_bit_count = ptr_type->data.pointer.unaligned_bit_count; |
| 2057 | if (unaligned_bit_count == 0) | 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 | assert(!handle_is_ptr(child_type)); | 2041 | assert(!handle_is_ptr(child_type)); |
| 2061 | LLVMValueRef containing_int = LLVMBuildLoad(g->builder, ptr, ""); | 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 | uint32_t bit_offset = ptr_type->data.pointer.bit_offset; | 2045 | uint32_t bit_offset = ptr_type->data.pointer.bit_offset; |
| 2065 | uint32_t host_bit_count = LLVMGetIntTypeWidth(LLVMTypeOf(containing_int)); | 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,9 +2078,8 @@ static LLVMValueRef ir_render_elem_ptr(CodeGen *g, IrExecutable *executable, IrI |
| 2097 | LLVMValueRef array_ptr_ptr = ir_llvm_value(g, instruction->array_ptr); | 2078 | LLVMValueRef array_ptr_ptr = ir_llvm_value(g, instruction->array_ptr); |
| 2098 | TypeTableEntry *array_ptr_type = instruction->array_ptr->value.type; | 2079 | TypeTableEntry *array_ptr_type = instruction->array_ptr->value.type; |
| 2099 | assert(array_ptr_type->id == TypeTableEntryIdPointer); | 2080 | assert(array_ptr_type->id == TypeTableEntryIdPointer); |
| 2100 | bool is_volatile = array_ptr_type->data.pointer.is_volatile; | ||
| 2101 | TypeTableEntry *array_type = array_ptr_type->data.pointer.child_type; | 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 | LLVMValueRef subscript_value = ir_llvm_value(g, instruction->elem_index); | 2083 | LLVMValueRef subscript_value = ir_llvm_value(g, instruction->elem_index); |
| 2104 | assert(subscript_value); | 2084 | assert(subscript_value); |
| 2105 | 2085 | ||
| ... | @@ -2427,12 +2407,11 @@ static LLVMValueRef ir_render_unwrap_maybe(CodeGen *g, IrExecutable *executable, | ... | @@ -2427,12 +2407,11 @@ static LLVMValueRef ir_render_unwrap_maybe(CodeGen *g, IrExecutable *executable, |
| 2427 | { | 2407 | { |
| 2428 | TypeTableEntry *ptr_type = instruction->value->value.type; | 2408 | TypeTableEntry *ptr_type = instruction->value->value.type; |
| 2429 | assert(ptr_type->id == TypeTableEntryIdPointer); | 2409 | assert(ptr_type->id == TypeTableEntryIdPointer); |
| 2430 | bool is_volatile = ptr_type->data.pointer.is_volatile; | ||
| 2431 | TypeTableEntry *maybe_type = ptr_type->data.pointer.child_type; | 2410 | TypeTableEntry *maybe_type = ptr_type->data.pointer.child_type; |
| 2432 | assert(maybe_type->id == TypeTableEntryIdMaybe); | 2411 | assert(maybe_type->id == TypeTableEntryIdMaybe); |
| 2433 | TypeTableEntry *child_type = maybe_type->data.maybe.child_type; | 2412 | TypeTableEntry *child_type = maybe_type->data.maybe.child_type; |
| 2434 | LLVMValueRef maybe_ptr = ir_llvm_value(g, instruction->value); | 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 | if (ir_want_debug_safety(g, &instruction->base) && instruction->safety_check_on) { | 2415 | if (ir_want_debug_safety(g, &instruction->base) && instruction->safety_check_on) { |
| 2437 | LLVMValueRef non_null_bit = gen_non_null_bit(g, maybe_type, maybe_handle); | 2416 | LLVMValueRef non_null_bit = gen_non_null_bit(g, maybe_type, maybe_handle); |
| 2438 | LLVMBasicBlockRef ok_block = LLVMAppendBasicBlock(g->cur_fn_val, "UnwrapMaybeOk"); | 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,7 +2430,7 @@ static LLVMValueRef ir_render_unwrap_maybe(CodeGen *g, IrExecutable *executable, |
| 2451 | if (maybe_is_ptr) { | 2430 | if (maybe_is_ptr) { |
| 2452 | return maybe_ptr; | 2431 | return maybe_ptr; |
| 2453 | } else { | 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 | return LLVMBuildStructGEP(g->builder, maybe_struct_ref, maybe_child_index, ""); | 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,11 +2673,13 @@ static LLVMValueRef ir_render_memset(CodeGen *g, IrExecutable *executable, IrIns |
| 2694 | LLVMValueRef is_volatile = ptr_type->data.pointer.is_volatile ? | 2673 | LLVMValueRef is_volatile = ptr_type->data.pointer.is_volatile ? |
| 2695 | LLVMConstAllOnes(LLVMInt1Type()) : LLVMConstNull(LLVMInt1Type()); | 2674 | LLVMConstAllOnes(LLVMInt1Type()) : LLVMConstNull(LLVMInt1Type()); |
| 2696 | 2675 | ||
| 2676 | LLVMValueRef align_val = LLVMConstInt(LLVMInt32Type(), ptr_type->data.pointer.alignment, false); | ||
| 2677 | |||
| 2697 | LLVMValueRef params[] = { | 2678 | LLVMValueRef params[] = { |
| 2698 | dest_ptr_casted, // dest pointer | 2679 | dest_ptr_casted, |
| 2699 | char_val, // source pointer | 2680 | char_val, |
| 2700 | len_val, // byte count | 2681 | len_val, |
| 2701 | LLVMConstInt(LLVMInt32Type(), 1, false), // align in bytes | 2682 | align_val, |
| 2702 | is_volatile, | 2683 | is_volatile, |
| 2703 | }; | 2684 | }; |
| 2704 | 2685 | ||
| ... | @@ -2725,11 +2706,14 @@ static LLVMValueRef ir_render_memcpy(CodeGen *g, IrExecutable *executable, IrIns | ... | @@ -2725,11 +2706,14 @@ static LLVMValueRef ir_render_memcpy(CodeGen *g, IrExecutable *executable, IrIns |
| 2725 | LLVMValueRef is_volatile = (dest_ptr_type->data.pointer.is_volatile || src_ptr_type->data.pointer.is_volatile) ? | 2706 | LLVMValueRef is_volatile = (dest_ptr_type->data.pointer.is_volatile || src_ptr_type->data.pointer.is_volatile) ? |
| 2726 | LLVMConstAllOnes(LLVMInt1Type()) : LLVMConstNull(LLVMInt1Type()); | 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 | LLVMValueRef params[] = { | 2712 | LLVMValueRef params[] = { |
| 2729 | dest_ptr_casted, // dest pointer | 2713 | dest_ptr_casted, |
| 2730 | src_ptr_casted, // source pointer | 2714 | src_ptr_casted, |
| 2731 | len_val, // byte count | 2715 | len_val, |
| 2732 | LLVMConstInt(LLVMInt32Type(), 1, false), // align in bytes | 2716 | align_val, |
| 2733 | is_volatile, | 2717 | is_volatile, |
| 2734 | }; | 2718 | }; |
| 2735 | 2719 | ||
| ... | @@ -2743,9 +2727,8 @@ static LLVMValueRef ir_render_slice(CodeGen *g, IrExecutable *executable, IrInst | ... | @@ -2743,9 +2727,8 @@ static LLVMValueRef ir_render_slice(CodeGen *g, IrExecutable *executable, IrInst |
| 2743 | LLVMValueRef array_ptr_ptr = ir_llvm_value(g, instruction->ptr); | 2727 | LLVMValueRef array_ptr_ptr = ir_llvm_value(g, instruction->ptr); |
| 2744 | TypeTableEntry *array_ptr_type = instruction->ptr->value.type; | 2728 | TypeTableEntry *array_ptr_type = instruction->ptr->value.type; |
| 2745 | assert(array_ptr_type->id == TypeTableEntryIdPointer); | 2729 | assert(array_ptr_type->id == TypeTableEntryIdPointer); |
| 2746 | bool is_volatile = array_ptr_type->data.pointer.is_volatile; | ||
| 2747 | TypeTableEntry *array_type = array_ptr_type->data.pointer.child_type; | 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 | LLVMValueRef tmp_struct_ptr = instruction->tmp_ptr; | 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,11 +2972,10 @@ static LLVMValueRef ir_render_test_err(CodeGen *g, IrExecutable *executable, IrI |
| 2989 | static LLVMValueRef ir_render_unwrap_err_code(CodeGen *g, IrExecutable *executable, IrInstructionUnwrapErrCode *instruction) { | 2972 | static LLVMValueRef ir_render_unwrap_err_code(CodeGen *g, IrExecutable *executable, IrInstructionUnwrapErrCode *instruction) { |
| 2990 | TypeTableEntry *ptr_type = instruction->value->value.type; | 2973 | TypeTableEntry *ptr_type = instruction->value->value.type; |
| 2991 | assert(ptr_type->id == TypeTableEntryIdPointer); | 2974 | assert(ptr_type->id == TypeTableEntryIdPointer); |
| 2992 | bool is_volatile = ptr_type->data.pointer.is_volatile; | ||
| 2993 | TypeTableEntry *err_union_type = ptr_type->data.pointer.child_type; | 2975 | TypeTableEntry *err_union_type = ptr_type->data.pointer.child_type; |
| 2994 | TypeTableEntry *child_type = err_union_type->data.error.child_type; | 2976 | TypeTableEntry *child_type = err_union_type->data.error.child_type; |
| 2995 | LLVMValueRef err_union_ptr = ir_llvm_value(g, instruction->value); | 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 | if (type_has_bits(child_type)) { | 2980 | if (type_has_bits(child_type)) { |
| 2999 | LLVMValueRef err_val_ptr = LLVMBuildStructGEP(g->builder, err_union_handle, err_union_err_index, ""); | 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,11 +2988,10 @@ static LLVMValueRef ir_render_unwrap_err_code(CodeGen *g, IrExecutable *executab |
| 3006 | static LLVMValueRef ir_render_unwrap_err_payload(CodeGen *g, IrExecutable *executable, IrInstructionUnwrapErrPayload *instruction) { | 2988 | static LLVMValueRef ir_render_unwrap_err_payload(CodeGen *g, IrExecutable *executable, IrInstructionUnwrapErrPayload *instruction) { |
| 3007 | TypeTableEntry *ptr_type = instruction->value->value.type; | 2989 | TypeTableEntry *ptr_type = instruction->value->value.type; |
| 3008 | assert(ptr_type->id == TypeTableEntryIdPointer); | 2990 | assert(ptr_type->id == TypeTableEntryIdPointer); |
| 3009 | bool is_volatile = ptr_type->data.pointer.is_volatile; | ||
| 3010 | TypeTableEntry *err_union_type = ptr_type->data.pointer.child_type; | 2991 | TypeTableEntry *err_union_type = ptr_type->data.pointer.child_type; |
| 3011 | TypeTableEntry *child_type = err_union_type->data.error.child_type; | 2992 | TypeTableEntry *child_type = err_union_type->data.error.child_type; |
| 3012 | LLVMValueRef err_union_ptr = ir_llvm_value(g, instruction->value); | 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 | if (ir_want_debug_safety(g, &instruction->base) && instruction->safety_check_on && g->error_decls.length > 1) { | 2996 | if (ir_want_debug_safety(g, &instruction->base) && instruction->safety_check_on && g->error_decls.length > 1) { |
| 3016 | LLVMValueRef err_val; | 2997 | LLVMValueRef err_val; |
| ... | @@ -3123,7 +3104,8 @@ static LLVMValueRef ir_render_enum_tag(CodeGen *g, IrExecutable *executable, IrI | ... | @@ -3123,7 +3104,8 @@ static LLVMValueRef ir_render_enum_tag(CodeGen *g, IrExecutable *executable, IrI |
| 3123 | return enum_val; | 3104 | return enum_val; |
| 3124 | 3105 | ||
| 3125 | LLVMValueRef tag_field_ptr = LLVMBuildStructGEP(g->builder, enum_val, enum_type->data.enumeration.gen_tag_index, ""); | 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 | static LLVMValueRef ir_render_init_enum(CodeGen *g, IrExecutable *executable, IrInstructionInitEnum *instruction) { | 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,8 +3146,10 @@ static LLVMValueRef ir_render_struct_init(CodeGen *g, IrExecutable *executable, |
| 3164 | (unsigned)type_struct_field->gen_index, ""); | 3146 | (unsigned)type_struct_field->gen_index, ""); |
| 3165 | LLVMValueRef value = ir_llvm_value(g, field->value); | 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 | TypeTableEntry *ptr_type = get_pointer_to_type_extra(g, type_struct_field->type_entry, | 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 | (uint32_t)type_struct_field->packed_bits_offset, (uint32_t)type_struct_field->unaligned_bit_count); | 3153 | (uint32_t)type_struct_field->packed_bits_offset, (uint32_t)type_struct_field->unaligned_bit_count); |
| 3170 | 3154 | ||
| 3171 | gen_assign_raw(g, field_ptr, ptr_type, value); | 3155 | gen_assign_raw(g, field_ptr, ptr_type, value); |
| ... | @@ -3243,15 +3227,13 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable, | ... | @@ -3243,15 +3227,13 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable, |
| 3243 | case IrInstructionIdEmbedFile: | 3227 | case IrInstructionIdEmbedFile: |
| 3244 | case IrInstructionIdIntType: | 3228 | case IrInstructionIdIntType: |
| 3245 | case IrInstructionIdMemberCount: | 3229 | case IrInstructionIdMemberCount: |
| 3246 | case IrInstructionIdPreferredAlignOf: | 3230 | case IrInstructionIdAlignOf: |
| 3247 | case IrInstructionIdAbiAlignOf: | ||
| 3248 | case IrInstructionIdFnProto: | 3231 | case IrInstructionIdFnProto: |
| 3249 | case IrInstructionIdTestComptime: | 3232 | case IrInstructionIdTestComptime: |
| 3250 | case IrInstructionIdCheckSwitchProngs: | 3233 | case IrInstructionIdCheckSwitchProngs: |
| 3251 | case IrInstructionIdCheckStatementIsVoid: | 3234 | case IrInstructionIdCheckStatementIsVoid: |
| 3252 | case IrInstructionIdTypeName: | 3235 | case IrInstructionIdTypeName: |
| 3253 | case IrInstructionIdCanImplicitCast: | 3236 | case IrInstructionIdCanImplicitCast: |
| 3254 | case IrInstructionIdSetGlobalAlign: | ||
| 3255 | case IrInstructionIdSetGlobalSection: | 3237 | case IrInstructionIdSetGlobalSection: |
| 3256 | case IrInstructionIdSetGlobalLinkage: | 3238 | case IrInstructionIdSetGlobalLinkage: |
| 3257 | case IrInstructionIdDeclRef: | 3239 | case IrInstructionIdDeclRef: |
| ... | @@ -3259,6 +3241,7 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable, | ... | @@ -3259,6 +3241,7 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable, |
| 3259 | case IrInstructionIdOffsetOf: | 3241 | case IrInstructionIdOffsetOf: |
| 3260 | case IrInstructionIdTypeId: | 3242 | case IrInstructionIdTypeId: |
| 3261 | case IrInstructionIdSetEvalBranchQuota: | 3243 | case IrInstructionIdSetEvalBranchQuota: |
| 3244 | case IrInstructionIdPtrTypeOf: | ||
| 3262 | zig_unreachable(); | 3245 | zig_unreachable(); |
| 3263 | case IrInstructionIdReturn: | 3246 | case IrInstructionIdReturn: |
| 3264 | return ir_render_return(g, executable, (IrInstructionReturn *)instruction); | 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,7 +3823,7 @@ static void render_const_val_global(CodeGen *g, ConstExprValue *const_val, const |
| 3840 | LLVMSetLinkage(global_value, LLVMInternalLinkage); | 3823 | LLVMSetLinkage(global_value, LLVMInternalLinkage); |
| 3841 | LLVMSetGlobalConstant(global_value, true); | 3824 | LLVMSetGlobalConstant(global_value, true); |
| 3842 | LLVMSetUnnamedAddr(global_value, true); | 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 | const_val->global_refs->llvm_global = global_value; | 3828 | const_val->global_refs->llvm_global = global_value; |
| 3846 | } | 3829 | } |
| ... | @@ -3856,8 +3839,8 @@ static void generate_error_name_table(CodeGen *g) { | ... | @@ -3856,8 +3839,8 @@ static void generate_error_name_table(CodeGen *g) { |
| 3856 | 3839 | ||
| 3857 | assert(g->error_decls.length > 0); | 3840 | assert(g->error_decls.length > 0); |
| 3858 | 3841 | ||
| 3859 | TypeTableEntry *str_type = get_slice_type(g, g->builtin_types.entry_u8, true); | 3842 | TypeTableEntry *u8_ptr_type = get_pointer_to_type(g, g->builtin_types.entry_u8, true); |
| 3860 | TypeTableEntry *u8_ptr_type = str_type->data.structure.fields[0].type_entry; | 3843 | TypeTableEntry *str_type = get_slice_type(g, u8_ptr_type); |
| 3861 | 3844 | ||
| 3862 | LLVMValueRef *values = allocate<LLVMValueRef>(g->error_decls.length); | 3845 | LLVMValueRef *values = allocate<LLVMValueRef>(g->error_decls.length); |
| 3863 | values[0] = LLVMGetUndef(str_type->type_ref); | 3846 | values[0] = LLVMGetUndef(str_type->type_ref); |
| ... | @@ -3893,8 +3876,8 @@ static void generate_error_name_table(CodeGen *g) { | ... | @@ -3893,8 +3876,8 @@ static void generate_error_name_table(CodeGen *g) { |
| 3893 | } | 3876 | } |
| 3894 | 3877 | ||
| 3895 | static void generate_enum_name_tables(CodeGen *g) { | 3878 | static void generate_enum_name_tables(CodeGen *g) { |
| 3896 | TypeTableEntry *str_type = get_slice_type(g, g->builtin_types.entry_u8, true); | 3879 | TypeTableEntry *u8_ptr_type = get_pointer_to_type(g, g->builtin_types.entry_u8, true); |
| 3897 | TypeTableEntry *u8_ptr_type = str_type->data.structure.fields[0].type_entry; | 3880 | TypeTableEntry *str_type = get_slice_type(g, u8_ptr_type); |
| 3898 | 3881 | ||
| 3899 | for (size_t enum_i = 0; enum_i < g->name_table_enums.length; enum_i += 1) { | 3882 | for (size_t enum_i = 0; enum_i < g->name_table_enums.length; enum_i += 1) { |
| 3900 | TypeTableEntry *enum_tag_type = g->name_table_enums.at(enum_i); | 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,9 +3948,10 @@ static void gen_global_var(CodeGen *g, VariableTableEntry *var, LLVMValueRef ini |
| 3965 | // TODO ^^ make an actual global variable | 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 | LLVMValueRef result = LLVMBuildAlloca(g->builder, type_entry->type_ref, name); | 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 | return result; | 3955 | return result; |
| 3972 | } | 3956 | } |
| 3973 | 3957 | ||
| ... | @@ -4056,6 +4040,7 @@ static void do_code_gen(CodeGen *g) { | ... | @@ -4056,6 +4040,7 @@ static void do_code_gen(CodeGen *g) { |
| 4056 | // TODO debug info for the extern variable | 4040 | // TODO debug info for the extern variable |
| 4057 | 4041 | ||
| 4058 | LLVMSetLinkage(global_value, LLVMExternalLinkage); | 4042 | LLVMSetLinkage(global_value, LLVMExternalLinkage); |
| 4043 | LLVMSetAlignment(global_value, var->align_bytes); | ||
| 4059 | } else { | 4044 | } else { |
| 4060 | bool exported = (var->linkage == VarLinkageExport); | 4045 | bool exported = (var->linkage == VarLinkageExport); |
| 4061 | render_const_val(g, var->value); | 4046 | render_const_val(g, var->value); |
| ... | @@ -4068,8 +4053,7 @@ static void do_code_gen(CodeGen *g) { | ... | @@ -4068,8 +4053,7 @@ static void do_code_gen(CodeGen *g) { |
| 4068 | if (tld_var->section_name) { | 4053 | if (tld_var->section_name) { |
| 4069 | LLVMSetSection(global_value, buf_ptr(tld_var->section_name)); | 4054 | LLVMSetSection(global_value, buf_ptr(tld_var->section_name)); |
| 4070 | } | 4055 | } |
| 4071 | LLVMSetAlignment(global_value, tld_var->alignment ? | 4056 | LLVMSetAlignment(global_value, var->align_bytes); |
| 4072 | tld_var->alignment : get_type_alignment(g, var->value->type)); | ||
| 4073 | 4057 | ||
| 4074 | // TODO debug info for function pointers | 4058 | // TODO debug info for function pointers |
| 4075 | if (var->gen_is_const && var->value->type->id != TypeTableEntryIdFn) { | 4059 | if (var->gen_is_const && var->value->type->id != TypeTableEntryIdFn) { |
| ... | @@ -4189,7 +4173,7 @@ static void do_code_gen(CodeGen *g) { | ... | @@ -4189,7 +4173,7 @@ static void do_code_gen(CodeGen *g) { |
| 4189 | } else { | 4173 | } else { |
| 4190 | zig_unreachable(); | 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 | ImportTableEntry *import = get_scope_import(&fn_table_entry->fndef_scope->base); | 4179 | ImportTableEntry *import = get_scope_import(&fn_table_entry->fndef_scope->base); |
| ... | @@ -4207,7 +4191,7 @@ static void do_code_gen(CodeGen *g) { | ... | @@ -4207,7 +4191,7 @@ static void do_code_gen(CodeGen *g) { |
| 4207 | continue; | 4191 | continue; |
| 4208 | 4192 | ||
| 4209 | if (var->src_arg_index == SIZE_MAX) { | 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 | var->di_loc_var = ZigLLVMCreateAutoVariable(g->dbuilder, get_di_scope(g, var->parent_scope), | 4196 | var->di_loc_var = ZigLLVMCreateAutoVariable(g->dbuilder, get_di_scope(g, var->parent_scope), |
| 4213 | buf_ptr(&var->name), import->di_file, (unsigned)(var->decl_node->line + 1), | 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,7 +4211,7 @@ static void do_code_gen(CodeGen *g) { |
| 4227 | var->value_ref = LLVMGetParam(fn, (unsigned)var->gen_arg_index); | 4211 | var->value_ref = LLVMGetParam(fn, (unsigned)var->gen_arg_index); |
| 4228 | } else { | 4212 | } else { |
| 4229 | gen_type = var->value->type; | 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 | if (var->decl_node) { | 4216 | if (var->decl_node) { |
| 4233 | var->di_loc_var = ZigLLVMCreateParameterVariable(g->dbuilder, get_di_scope(g, var->parent_scope), | 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,6 +4293,7 @@ static void do_code_gen(CodeGen *g) { |
| 4309 | } | 4293 | } |
| 4310 | 4294 | ||
| 4311 | static const uint8_t int_sizes_in_bits[] = { | 4295 | static const uint8_t int_sizes_in_bits[] = { |
| 4296 | 2, | ||
| 4312 | 3, | 4297 | 3, |
| 4313 | 4, | 4298 | 4, |
| 4314 | 5, | 4299 | 5, |
| ... | @@ -4605,8 +4590,7 @@ static void define_builtin_fns(CodeGen *g) { | ... | @@ -4605,8 +4590,7 @@ static void define_builtin_fns(CodeGen *g) { |
| 4605 | create_builtin_fn(g, BuiltinFnIdMemcpy, "memcpy", 3); | 4590 | create_builtin_fn(g, BuiltinFnIdMemcpy, "memcpy", 3); |
| 4606 | create_builtin_fn(g, BuiltinFnIdMemset, "memset", 3); | 4591 | create_builtin_fn(g, BuiltinFnIdMemset, "memset", 3); |
| 4607 | create_builtin_fn(g, BuiltinFnIdSizeof, "sizeOf", 1); | 4592 | create_builtin_fn(g, BuiltinFnIdSizeof, "sizeOf", 1); |
| 4608 | create_builtin_fn(g, BuiltinFnIdPreferredAlignOf, "preferredAlignOf", 1); | 4593 | create_builtin_fn(g, BuiltinFnIdAlignOf, "alignOf", 1); |
| 4609 | create_builtin_fn(g, BuiltinFnIdAbiAlignOf, "cAbiAlignOf", 1); | ||
| 4610 | create_builtin_fn(g, BuiltinFnIdMaxValue, "maxValue", 1); | 4594 | create_builtin_fn(g, BuiltinFnIdMaxValue, "maxValue", 1); |
| 4611 | create_builtin_fn(g, BuiltinFnIdMinValue, "minValue", 1); | 4595 | create_builtin_fn(g, BuiltinFnIdMinValue, "minValue", 1); |
| 4612 | create_builtin_fn(g, BuiltinFnIdMemberCount, "memberCount", 1); | 4596 | create_builtin_fn(g, BuiltinFnIdMemberCount, "memberCount", 1); |
| ... | @@ -4634,7 +4618,6 @@ static void define_builtin_fns(CodeGen *g) { | ... | @@ -4634,7 +4618,6 @@ static void define_builtin_fns(CodeGen *g) { |
| 4634 | create_builtin_fn(g, BuiltinFnIdIntType, "IntType", 2); | 4618 | create_builtin_fn(g, BuiltinFnIdIntType, "IntType", 2); |
| 4635 | create_builtin_fn(g, BuiltinFnIdSetDebugSafety, "setDebugSafety", 2); | 4619 | create_builtin_fn(g, BuiltinFnIdSetDebugSafety, "setDebugSafety", 2); |
| 4636 | create_builtin_fn(g, BuiltinFnIdSetFloatMode, "setFloatMode", 2); | 4620 | create_builtin_fn(g, BuiltinFnIdSetFloatMode, "setFloatMode", 2); |
| 4637 | create_builtin_fn(g, BuiltinFnIdSetGlobalAlign, "setGlobalAlign", 2); | ||
| 4638 | create_builtin_fn(g, BuiltinFnIdSetGlobalSection, "setGlobalSection", 2); | 4621 | create_builtin_fn(g, BuiltinFnIdSetGlobalSection, "setGlobalSection", 2); |
| 4639 | create_builtin_fn(g, BuiltinFnIdSetGlobalLinkage, "setGlobalLinkage", 2); | 4622 | create_builtin_fn(g, BuiltinFnIdSetGlobalLinkage, "setGlobalLinkage", 2); |
| 4640 | create_builtin_fn(g, BuiltinFnIdPanic, "panic", 1); | 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,7 +4972,8 @@ static void create_test_compile_var_and_add_test_runner(CodeGen *g) { |
| 4989 | exit(0); | 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 | TypeTableEntry *fn_type = get_test_fn_type(g); | 4977 | TypeTableEntry *fn_type = get_test_fn_type(g); |
| 4994 | 4978 | ||
| 4995 | const char *field_names[] = { "name", "func", }; | 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,6 +51,7 @@ static IrInstruction *ir_gen_node_extra(IrBuilder *irb, AstNode *node, Scope *sc |
| 51 | static TypeTableEntry *ir_analyze_instruction(IrAnalyze *ira, IrInstruction *instruction); | 51 | static TypeTableEntry *ir_analyze_instruction(IrAnalyze *ira, IrInstruction *instruction); |
| 52 | static IrInstruction *ir_implicit_cast(IrAnalyze *ira, IrInstruction *value, TypeTableEntry *expected_type); | 52 | static IrInstruction *ir_implicit_cast(IrAnalyze *ira, IrInstruction *value, TypeTableEntry *expected_type); |
| 53 | static IrInstruction *ir_get_deref(IrAnalyze *ira, IrInstruction *source_instruction, IrInstruction *ptr); | 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 | ConstExprValue *const_ptr_pointee(CodeGen *g, ConstExprValue *const_val) { | 56 | ConstExprValue *const_ptr_pointee(CodeGen *g, ConstExprValue *const_val) { |
| 56 | assert(const_val->type->id == TypeTableEntryIdPointer); | 57 | assert(const_val->type->id == TypeTableEntryIdPointer); |
| ... | @@ -422,12 +423,8 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionFrameAddress *) | ... | @@ -422,12 +423,8 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionFrameAddress *) |
| 422 | return IrInstructionIdFrameAddress; | 423 | return IrInstructionIdFrameAddress; |
| 423 | } | 424 | } |
| 424 | 425 | ||
| 425 | static constexpr IrInstructionId ir_instruction_id(IrInstructionPreferredAlignOf *) { | 426 | static constexpr IrInstructionId ir_instruction_id(IrInstructionAlignOf *) { |
| 426 | return IrInstructionIdPreferredAlignOf; | 427 | return IrInstructionIdAlignOf; |
| 427 | } | ||
| 428 | |||
| 429 | static constexpr IrInstructionId ir_instruction_id(IrInstructionAbiAlignOf *) { | ||
| 430 | return IrInstructionIdAbiAlignOf; | ||
| 431 | } | 428 | } |
| 432 | 429 | ||
| 433 | static constexpr IrInstructionId ir_instruction_id(IrInstructionOverflowOp *) { | 430 | static constexpr IrInstructionId ir_instruction_id(IrInstructionOverflowOp *) { |
| ... | @@ -518,10 +515,6 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionCanImplicitCast | ... | @@ -518,10 +515,6 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionCanImplicitCast |
| 518 | return IrInstructionIdCanImplicitCast; | 515 | return IrInstructionIdCanImplicitCast; |
| 519 | } | 516 | } |
| 520 | 517 | ||
| 521 | static constexpr IrInstructionId ir_instruction_id(IrInstructionSetGlobalAlign *) { | ||
| 522 | return IrInstructionIdSetGlobalAlign; | ||
| 523 | } | ||
| 524 | |||
| 525 | static constexpr IrInstructionId ir_instruction_id(IrInstructionSetGlobalSection *) { | 518 | static constexpr IrInstructionId ir_instruction_id(IrInstructionSetGlobalSection *) { |
| 526 | return IrInstructionIdSetGlobalSection; | 519 | return IrInstructionIdSetGlobalSection; |
| 527 | } | 520 | } |
| ... | @@ -558,6 +551,10 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionSetEvalBranchQuo | ... | @@ -558,6 +551,10 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionSetEvalBranchQuo |
| 558 | return IrInstructionIdSetEvalBranchQuota; | 551 | return IrInstructionIdSetEvalBranchQuota; |
| 559 | } | 552 | } |
| 560 | 553 | ||
| 554 | static constexpr IrInstructionId ir_instruction_id(IrInstructionPtrTypeOf *) { | ||
| 555 | return IrInstructionIdPtrTypeOf; | ||
| 556 | } | ||
| 557 | |||
| 561 | template<typename T> | 558 | template<typename T> |
| 562 | static T *ir_create_instruction(IrBuilder *irb, Scope *scope, AstNode *source_node) { | 559 | static T *ir_create_instruction(IrBuilder *irb, Scope *scope, AstNode *source_node) { |
| 563 | T *special_instruction = allocate<T>(1); | 560 | T *special_instruction = allocate<T>(1); |
| ... | @@ -988,6 +985,24 @@ static IrInstruction *ir_build_br_from(IrBuilder *irb, IrInstruction *old_instru | ... | @@ -988,6 +985,24 @@ static IrInstruction *ir_build_br_from(IrBuilder *irb, IrInstruction *old_instru |
| 988 | return new_instruction; | 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 | static IrInstruction *ir_build_un_op(IrBuilder *irb, Scope *scope, AstNode *source_node, IrUnOp op_id, IrInstruction *value) { | 1006 | static IrInstruction *ir_build_un_op(IrBuilder *irb, Scope *scope, AstNode *source_node, IrUnOp op_id, IrInstruction *value) { |
| 992 | IrInstructionUnOp *br_instruction = ir_build_instruction<IrInstructionUnOp>(irb, scope, source_node); | 1007 | IrInstructionUnOp *br_instruction = ir_build_instruction<IrInstructionUnOp>(irb, scope, source_node); |
| 993 | br_instruction->op_id = op_id; | 1008 | br_instruction->op_id = op_id; |
| ... | @@ -1112,26 +1127,28 @@ static IrInstruction *ir_build_store_ptr_from(IrBuilder *irb, IrInstruction *old | ... | @@ -1112,26 +1127,28 @@ static IrInstruction *ir_build_store_ptr_from(IrBuilder *irb, IrInstruction *old |
| 1112 | } | 1127 | } |
| 1113 | 1128 | ||
| 1114 | static IrInstruction *ir_build_var_decl(IrBuilder *irb, Scope *scope, AstNode *source_node, | 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 | IrInstructionDeclVar *decl_var_instruction = ir_build_instruction<IrInstructionDeclVar>(irb, scope, source_node); | 1132 | IrInstructionDeclVar *decl_var_instruction = ir_build_instruction<IrInstructionDeclVar>(irb, scope, source_node); |
| 1118 | decl_var_instruction->base.value.special = ConstValSpecialStatic; | 1133 | decl_var_instruction->base.value.special = ConstValSpecialStatic; |
| 1119 | decl_var_instruction->base.value.type = irb->codegen->builtin_types.entry_void; | 1134 | decl_var_instruction->base.value.type = irb->codegen->builtin_types.entry_void; |
| 1120 | decl_var_instruction->var = var; | 1135 | decl_var_instruction->var = var; |
| 1121 | decl_var_instruction->var_type = var_type; | 1136 | decl_var_instruction->var_type = var_type; |
| 1137 | decl_var_instruction->align_value = align_value; | ||
| 1122 | decl_var_instruction->init_value = init_value; | 1138 | decl_var_instruction->init_value = init_value; |
| 1123 | 1139 | ||
| 1124 | if (var_type) ir_ref_instruction(var_type, irb->current_basic_block); | 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 | ir_ref_instruction(init_value, irb->current_basic_block); | 1142 | ir_ref_instruction(init_value, irb->current_basic_block); |
| 1126 | 1143 | ||
| 1127 | return &decl_var_instruction->base; | 1144 | return &decl_var_instruction->base; |
| 1128 | } | 1145 | } |
| 1129 | 1146 | ||
| 1130 | static IrInstruction *ir_build_var_decl_from(IrBuilder *irb, IrInstruction *old_instruction, | 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 | IrInstruction *new_instruction = ir_build_var_decl(irb, old_instruction->scope, | 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 | ir_link_new_instruction(new_instruction, old_instruction); | 1152 | ir_link_new_instruction(new_instruction, old_instruction); |
| 1136 | return new_instruction; | 1153 | return new_instruction; |
| 1137 | } | 1154 | } |
| ... | @@ -1221,14 +1238,17 @@ static IrInstruction *ir_build_array_type(IrBuilder *irb, Scope *scope, AstNode | ... | @@ -1221,14 +1238,17 @@ static IrInstruction *ir_build_array_type(IrBuilder *irb, Scope *scope, AstNode |
| 1221 | return &instruction->base; | 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, | 1241 | static IrInstruction *ir_build_slice_type(IrBuilder *irb, Scope *scope, AstNode *source_node, |
| 1225 | IrInstruction *child_type) | 1242 | IrInstruction *child_type, bool is_const, bool is_volatile, IrInstruction *align_value) |
| 1226 | { | 1243 | { |
| 1227 | IrInstructionSliceType *instruction = ir_build_instruction<IrInstructionSliceType>(irb, scope, source_node); | 1244 | IrInstructionSliceType *instruction = ir_build_instruction<IrInstructionSliceType>(irb, scope, source_node); |
| 1228 | instruction->is_const = is_const; | 1245 | instruction->is_const = is_const; |
| 1246 | instruction->is_volatile = is_volatile; | ||
| 1229 | instruction->child_type = child_type; | 1247 | instruction->child_type = child_type; |
| 1248 | instruction->align_value = align_value; | ||
| 1230 | 1249 | ||
| 1231 | ir_ref_instruction(child_type, irb->current_basic_block); | 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 | return &instruction->base; | 1253 | return &instruction->base; |
| 1234 | } | 1254 | } |
| ... | @@ -1810,17 +1830,8 @@ static IrInstruction *ir_build_overflow_op_from(IrBuilder *irb, IrInstruction *o | ... | @@ -1810,17 +1830,8 @@ static IrInstruction *ir_build_overflow_op_from(IrBuilder *irb, IrInstruction *o |
| 1810 | return new_instruction; | 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) { | 1833 | static IrInstruction *ir_build_align_of(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *type_value) { |
| 1814 | IrInstructionPreferredAlignOf *instruction = ir_build_instruction<IrInstructionPreferredAlignOf>(irb, scope, source_node); | 1834 | IrInstructionAlignOf *instruction = ir_build_instruction<IrInstructionAlignOf>(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); | ||
| 1824 | instruction->type_value = type_value; | 1835 | instruction->type_value = type_value; |
| 1825 | 1836 | ||
| 1826 | ir_ref_instruction(type_value, irb->current_basic_block); | 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,19 +2108,6 @@ static IrInstruction *ir_build_can_implicit_cast(IrBuilder *irb, Scope *scope, A |
| 2097 | return &instruction->base; | 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 | static IrInstruction *ir_build_set_global_section(IrBuilder *irb, Scope *scope, AstNode *source_node, | 2111 | static IrInstruction *ir_build_set_global_section(IrBuilder *irb, Scope *scope, AstNode *source_node, |
| 2114 | Tld *tld, IrInstruction *value) | 2112 | Tld *tld, IrInstruction *value) |
| 2115 | { | 2113 | { |
| ... | @@ -2277,11 +2275,20 @@ static IrInstruction *ir_instruction_binop_get_dep(IrInstructionBinOp *instructi | ... | @@ -2277,11 +2275,20 @@ static IrInstruction *ir_instruction_binop_get_dep(IrInstructionBinOp *instructi |
| 2277 | } | 2275 | } |
| 2278 | 2276 | ||
| 2279 | static IrInstruction *ir_instruction_declvar_get_dep(IrInstructionDeclVar *instruction, size_t index) { | 2277 | static IrInstruction *ir_instruction_declvar_get_dep(IrInstructionDeclVar *instruction, size_t index) { |
| 2280 | switch (index) { | 2278 | if (index == 0) return instruction->init_value; |
| 2281 | case 0: return instruction->init_value; | 2279 | index -= 1; |
| 2282 | case 1: return instruction->var_type; | 2280 | |
| 2283 | default: return nullptr; | 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 | static IrInstruction *ir_instruction_loadptr_get_dep(IrInstructionLoadPtr *instruction, size_t index) { | 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,14 +2678,7 @@ static IrInstruction *ir_instruction_frameaddress_get_dep(IrInstructionFrameAddr |
| 2671 | return nullptr; | 2678 | return nullptr; |
| 2672 | } | 2679 | } |
| 2673 | 2680 | ||
| 2674 | static IrInstruction *ir_instruction_preferredalignof_get_dep(IrInstructionPreferredAlignOf *instruction, size_t index) { | 2681 | static IrInstruction *ir_instruction_alignof_get_dep(IrInstructionAlignOf *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) { | ||
| 2682 | switch (index) { | 2682 | switch (index) { |
| 2683 | case 0: return instruction->type_value; | 2683 | case 0: return instruction->type_value; |
| 2684 | default: return nullptr; | 2684 | default: return nullptr; |
| ... | @@ -2854,13 +2854,6 @@ static IrInstruction *ir_instruction_canimplicitcast_get_dep(IrInstructionCanImp | ... | @@ -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 | static IrInstruction *ir_instruction_setglobalsection_get_dep(IrInstructionSetGlobalSection *instruction, size_t index) { | 2857 | static IrInstruction *ir_instruction_setglobalsection_get_dep(IrInstructionSetGlobalSection *instruction, size_t index) { |
| 2865 | switch (index) { | 2858 | switch (index) { |
| 2866 | case 0: return instruction->value; | 2859 | case 0: return instruction->value; |
| ... | @@ -2924,6 +2917,14 @@ static IrInstruction *ir_instruction_setevalbranchquota_get_dep(IrInstructionSet | ... | @@ -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 | static IrInstruction *ir_instruction_get_dep(IrInstruction *instruction, size_t index) { | 2928 | static IrInstruction *ir_instruction_get_dep(IrInstruction *instruction, size_t index) { |
| 2928 | switch (instruction->id) { | 2929 | switch (instruction->id) { |
| 2929 | case IrInstructionIdInvalid: | 2930 | case IrInstructionIdInvalid: |
| ... | @@ -3056,10 +3057,8 @@ static IrInstruction *ir_instruction_get_dep(IrInstruction *instruction, size_t | ... | @@ -3056,10 +3057,8 @@ static IrInstruction *ir_instruction_get_dep(IrInstruction *instruction, size_t |
| 3056 | return ir_instruction_returnaddress_get_dep((IrInstructionReturnAddress *) instruction, index); | 3057 | return ir_instruction_returnaddress_get_dep((IrInstructionReturnAddress *) instruction, index); |
| 3057 | case IrInstructionIdFrameAddress: | 3058 | case IrInstructionIdFrameAddress: |
| 3058 | return ir_instruction_frameaddress_get_dep((IrInstructionFrameAddress *) instruction, index); | 3059 | return ir_instruction_frameaddress_get_dep((IrInstructionFrameAddress *) instruction, index); |
| 3059 | case IrInstructionIdPreferredAlignOf: | 3060 | case IrInstructionIdAlignOf: |
| 3060 | return ir_instruction_preferredalignof_get_dep((IrInstructionPreferredAlignOf *) instruction, index); | 3061 | return ir_instruction_alignof_get_dep((IrInstructionAlignOf *) instruction, index); |
| 3061 | case IrInstructionIdAbiAlignOf: | ||
| 3062 | return ir_instruction_abialignof_get_dep((IrInstructionAbiAlignOf *) instruction, index); | ||
| 3063 | case IrInstructionIdOverflowOp: | 3062 | case IrInstructionIdOverflowOp: |
| 3064 | return ir_instruction_overflowop_get_dep((IrInstructionOverflowOp *) instruction, index); | 3063 | return ir_instruction_overflowop_get_dep((IrInstructionOverflowOp *) instruction, index); |
| 3065 | case IrInstructionIdTestErr: | 3064 | case IrInstructionIdTestErr: |
| ... | @@ -3102,8 +3101,6 @@ static IrInstruction *ir_instruction_get_dep(IrInstruction *instruction, size_t | ... | @@ -3102,8 +3101,6 @@ static IrInstruction *ir_instruction_get_dep(IrInstruction *instruction, size_t |
| 3102 | return ir_instruction_typename_get_dep((IrInstructionTypeName *) instruction, index); | 3101 | return ir_instruction_typename_get_dep((IrInstructionTypeName *) instruction, index); |
| 3103 | case IrInstructionIdCanImplicitCast: | 3102 | case IrInstructionIdCanImplicitCast: |
| 3104 | return ir_instruction_canimplicitcast_get_dep((IrInstructionCanImplicitCast *) instruction, index); | 3103 | return ir_instruction_canimplicitcast_get_dep((IrInstructionCanImplicitCast *) instruction, index); |
| 3105 | case IrInstructionIdSetGlobalAlign: | ||
| 3106 | return ir_instruction_setglobalalign_get_dep((IrInstructionSetGlobalAlign *) instruction, index); | ||
| 3107 | case IrInstructionIdSetGlobalSection: | 3104 | case IrInstructionIdSetGlobalSection: |
| 3108 | return ir_instruction_setglobalsection_get_dep((IrInstructionSetGlobalSection *) instruction, index); | 3105 | return ir_instruction_setglobalsection_get_dep((IrInstructionSetGlobalSection *) instruction, index); |
| 3109 | case IrInstructionIdSetGlobalLinkage: | 3106 | case IrInstructionIdSetGlobalLinkage: |
| ... | @@ -3122,6 +3119,8 @@ static IrInstruction *ir_instruction_get_dep(IrInstruction *instruction, size_t | ... | @@ -3122,6 +3119,8 @@ static IrInstruction *ir_instruction_get_dep(IrInstruction *instruction, size_t |
| 3122 | return ir_instruction_typeid_get_dep((IrInstructionTypeId *) instruction, index); | 3119 | return ir_instruction_typeid_get_dep((IrInstructionTypeId *) instruction, index); |
| 3123 | case IrInstructionIdSetEvalBranchQuota: | 3120 | case IrInstructionIdSetEvalBranchQuota: |
| 3124 | return ir_instruction_setevalbranchquota_get_dep((IrInstructionSetEvalBranchQuota *) instruction, index); | 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 | zig_unreachable(); | 3125 | zig_unreachable(); |
| 3127 | } | 3126 | } |
| ... | @@ -4286,23 +4285,14 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo | ... | @@ -4286,23 +4285,14 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo |
| 4286 | return ir_build_return_address(irb, scope, node); | 4285 | return ir_build_return_address(irb, scope, node); |
| 4287 | case BuiltinFnIdFrameAddress: | 4286 | case BuiltinFnIdFrameAddress: |
| 4288 | return ir_build_frame_address(irb, scope, node); | 4287 | return ir_build_frame_address(irb, scope, node); |
| 4289 | case BuiltinFnIdPreferredAlignOf: | 4288 | case BuiltinFnIdAlignOf: |
| 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: | ||
| 4299 | { | 4289 | { |
| 4300 | AstNode *arg0_node = node->data.fn_call_expr.params.at(0); | 4290 | AstNode *arg0_node = node->data.fn_call_expr.params.at(0); |
| 4301 | IrInstruction *arg0_value = ir_gen_node(irb, arg0_node, scope); | 4291 | IrInstruction *arg0_value = ir_gen_node(irb, arg0_node, scope); |
| 4302 | if (arg0_value == irb->codegen->invalid_instruction) | 4292 | if (arg0_value == irb->codegen->invalid_instruction) |
| 4303 | return arg0_value; | 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 | case BuiltinFnIdAddWithOverflow: | 4297 | case BuiltinFnIdAddWithOverflow: |
| 4308 | return ir_gen_overflow_op(irb, scope, node, IrOverflowOpAdd); | 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,7 +4325,6 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo |
| 4335 | 4325 | ||
| 4336 | return ir_build_can_implicit_cast(irb, scope, node, arg0_value, arg1_value); | 4326 | return ir_build_can_implicit_cast(irb, scope, node, arg0_value, arg1_value); |
| 4337 | } | 4327 | } |
| 4338 | case BuiltinFnIdSetGlobalAlign: | ||
| 4339 | case BuiltinFnIdSetGlobalSection: | 4328 | case BuiltinFnIdSetGlobalSection: |
| 4340 | case BuiltinFnIdSetGlobalLinkage: | 4329 | case BuiltinFnIdSetGlobalLinkage: |
| 4341 | { | 4330 | { |
| ... | @@ -4361,9 +4350,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo | ... | @@ -4361,9 +4350,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo |
| 4361 | if (arg1_value == irb->codegen->invalid_instruction) | 4350 | if (arg1_value == irb->codegen->invalid_instruction) |
| 4362 | return arg1_value; | 4351 | return arg1_value; |
| 4363 | 4352 | ||
| 4364 | if (builtin_fn->id == BuiltinFnIdSetGlobalAlign) { | 4353 | if (builtin_fn->id == BuiltinFnIdSetGlobalSection) { |
| 4365 | return ir_build_set_global_align(irb, scope, node, tld, arg1_value); | ||
| 4366 | } else if (builtin_fn->id == BuiltinFnIdSetGlobalSection) { | ||
| 4367 | return ir_build_set_global_section(irb, scope, node, tld, arg1_value); | 4354 | return ir_build_set_global_section(irb, scope, node, tld, arg1_value); |
| 4368 | } else if (builtin_fn->id == BuiltinFnIdSetGlobalLinkage) { | 4355 | } else if (builtin_fn->id == BuiltinFnIdSetGlobalLinkage) { |
| 4369 | return ir_build_set_global_linkage(irb, scope, node, tld, arg1_value); | 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,17 +4639,51 @@ static IrInstruction *ir_lval_wrap(IrBuilder *irb, Scope *scope, IrInstruction * |
| 4652 | return ir_build_ref(irb, scope, value->source_node, value, lval.is_const, lval.is_volatile); | 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, | 4642 | static IrInstruction *ir_gen_address_of(IrBuilder *irb, Scope *scope, AstNode *node) { |
| 4656 | bool is_const, bool is_volatile, LVal lval) | 4643 | assert(node->type == NodeTypeAddrOfExpr); |
| 4657 | { | 4644 | bool is_const = node->data.addr_of_expr.is_const; |
| 4658 | assert(node->type == NodeTypePrefixOpExpr); | 4645 | bool is_volatile = node->data.addr_of_expr.is_volatile; |
| 4659 | AstNode *expr_node = node->data.prefix_op_expr.primary_expr; | 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)); | 4649 | if (align_expr == nullptr) { |
| 4662 | if (value == irb->codegen->invalid_instruction) | 4650 | return ir_gen_node_extra(irb, expr_node, scope, make_lval_addr(is_const, is_volatile)); |
| 4663 | return value; | 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 | static IrInstruction *ir_gen_err_assert_ok(IrBuilder *irb, Scope *scope, AstNode *node, LVal lval) { | 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,14 +4746,6 @@ static IrInstruction *ir_gen_prefix_op_expr(IrBuilder *irb, Scope *scope, AstNod |
| 4725 | return ir_lval_wrap(irb, scope, ir_gen_prefix_op_id(irb, scope, node, IrUnOpNegation), lval); | 4746 | return ir_lval_wrap(irb, scope, ir_gen_prefix_op_id(irb, scope, node, IrUnOpNegation), lval); |
| 4726 | case PrefixOpNegationWrap: | 4747 | case PrefixOpNegationWrap: |
| 4727 | return ir_lval_wrap(irb, scope, ir_gen_prefix_op_id(irb, scope, node, IrUnOpNegationWrap), lval); | 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 | case PrefixOpDereference: | 4749 | case PrefixOpDereference: |
| 4737 | return ir_gen_prefix_op_id_lval(irb, scope, node, IrUnOpDereference, lval); | 4750 | return ir_gen_prefix_op_id_lval(irb, scope, node, IrUnOpDereference, lval); |
| 4738 | case PrefixOpMaybe: | 4751 | case PrefixOpMaybe: |
| ... | @@ -4822,11 +4835,18 @@ static IrInstruction *ir_gen_var_decl(IrBuilder *irb, Scope *scope, AstNode *nod | ... | @@ -4822,11 +4835,18 @@ static IrInstruction *ir_gen_var_decl(IrBuilder *irb, Scope *scope, AstNode *nod |
| 4822 | return irb->codegen->invalid_instruction; | 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 | IrInstruction *init_value = ir_gen_node(irb, variable_declaration->expr, scope); | 4845 | IrInstruction *init_value = ir_gen_node(irb, variable_declaration->expr, scope); |
| 4826 | if (init_value == irb->codegen->invalid_instruction) | 4846 | if (init_value == irb->codegen->invalid_instruction) |
| 4827 | return init_value; | 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 | var->decl_instruction = result; | 4850 | var->decl_instruction = result; |
| 4831 | return result; | 4851 | return result; |
| 4832 | } | 4852 | } |
| ... | @@ -4883,7 +4903,7 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *n | ... | @@ -4883,7 +4903,7 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *n |
| 4883 | err_val_ptr, false); | 4903 | err_val_ptr, false); |
| 4884 | IrInstruction *var_value = node->data.while_expr.var_is_ptr ? | 4904 | IrInstruction *var_value = node->data.while_expr.var_is_ptr ? |
| 4885 | var_ptr_value : ir_build_load_ptr(irb, payload_scope, symbol_node, var_ptr_value); | 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 | ZigList<IrInstruction *> incoming_values = {0}; | 4909 | ZigList<IrInstruction *> incoming_values = {0}; |
| ... | @@ -4922,7 +4942,7 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *n | ... | @@ -4922,7 +4942,7 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *n |
| 4922 | true, false, false, is_comptime); | 4942 | true, false, false, is_comptime); |
| 4923 | Scope *err_scope = err_var->child_scope; | 4943 | Scope *err_scope = err_var->child_scope; |
| 4924 | IrInstruction *err_var_value = ir_build_unwrap_err_code(irb, err_scope, err_symbol_node, err_val_ptr); | 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 | else_result = ir_gen_node(irb, else_node, err_scope); | 4947 | else_result = ir_gen_node(irb, else_node, err_scope); |
| 4928 | if (else_result == irb->codegen->invalid_instruction) | 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,7 +4984,7 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *n |
| 4964 | IrInstruction *var_ptr_value = ir_build_unwrap_maybe(irb, child_scope, symbol_node, maybe_val_ptr, false); | 4984 | IrInstruction *var_ptr_value = ir_build_unwrap_maybe(irb, child_scope, symbol_node, maybe_val_ptr, false); |
| 4965 | IrInstruction *var_value = node->data.while_expr.var_is_ptr ? | 4985 | IrInstruction *var_value = node->data.while_expr.var_is_ptr ? |
| 4966 | var_ptr_value : ir_build_load_ptr(irb, child_scope, symbol_node, var_ptr_value); | 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 | ZigList<IrInstruction *> incoming_values = {0}; | 4989 | ZigList<IrInstruction *> incoming_values = {0}; |
| 4970 | ZigList<IrBasicBlock *> incoming_blocks = {0}; | 4990 | ZigList<IrBasicBlock *> incoming_blocks = {0}; |
| ... | @@ -5115,7 +5135,7 @@ static IrInstruction *ir_gen_for_expr(IrBuilder *irb, Scope *parent_scope, AstNo | ... | @@ -5115,7 +5135,7 @@ static IrInstruction *ir_gen_for_expr(IrBuilder *irb, Scope *parent_scope, AstNo |
| 5115 | Scope *child_scope = elem_var->child_scope; | 5135 | Scope *child_scope = elem_var->child_scope; |
| 5116 | 5136 | ||
| 5117 | IrInstruction *undefined_value = ir_build_const_undefined(irb, child_scope, elem_node); | 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 | IrInstruction *elem_var_ptr = ir_build_var_ptr(irb, child_scope, node, elem_var, false, false); | 5139 | IrInstruction *elem_var_ptr = ir_build_var_ptr(irb, child_scope, node, elem_var, false, false); |
| 5120 | 5140 | ||
| 5121 | AstNode *index_var_source_node; | 5141 | AstNode *index_var_source_node; |
| ... | @@ -5133,7 +5153,7 @@ static IrInstruction *ir_gen_for_expr(IrBuilder *irb, Scope *parent_scope, AstNo | ... | @@ -5133,7 +5153,7 @@ static IrInstruction *ir_gen_for_expr(IrBuilder *irb, Scope *parent_scope, AstNo |
| 5133 | IrInstruction *usize = ir_build_const_type(irb, child_scope, node, irb->codegen->builtin_types.entry_usize); | 5153 | IrInstruction *usize = ir_build_const_type(irb, child_scope, node, irb->codegen->builtin_types.entry_usize); |
| 5134 | IrInstruction *zero = ir_build_const_usize(irb, child_scope, node, 0); | 5154 | IrInstruction *zero = ir_build_const_usize(irb, child_scope, node, 0); |
| 5135 | IrInstruction *one = ir_build_const_usize(irb, child_scope, node, 1); | 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 | IrInstruction *index_ptr = ir_build_var_ptr(irb, child_scope, node, index_var, false, false); | 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,12 +5274,22 @@ static IrInstruction *ir_gen_array_type(IrBuilder *irb, Scope *scope, AstNode *n |
| 5254 | AstNode *size_node = node->data.array_type.size; | 5274 | AstNode *size_node = node->data.array_type.size; |
| 5255 | AstNode *child_type_node = node->data.array_type.child_type; | 5275 | AstNode *child_type_node = node->data.array_type.child_type; |
| 5256 | bool is_const = node->data.array_type.is_const; | 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 | if (size_node) { | 5280 | if (size_node) { |
| 5259 | if (is_const) { | 5281 | if (is_const) { |
| 5260 | add_node_error(irb->codegen, node, buf_create_from_str("const qualifier invalid on array type")); | 5282 | add_node_error(irb->codegen, node, buf_create_from_str("const qualifier invalid on array type")); |
| 5261 | return irb->codegen->invalid_instruction; | 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 | IrInstruction *size_value = ir_gen_node(irb, size_node, scope); | 5294 | IrInstruction *size_value = ir_gen_node(irb, size_node, scope); |
| 5265 | if (size_value == irb->codegen->invalid_instruction) | 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,11 +5301,20 @@ static IrInstruction *ir_gen_array_type(IrBuilder *irb, Scope *scope, AstNode *n |
| 5271 | 5301 | ||
| 5272 | return ir_build_array_type(irb, scope, node, size_value, child_type); | 5302 | return ir_build_array_type(irb, scope, node, size_value, child_type); |
| 5273 | } else { | 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 | IrInstruction *child_type = ir_gen_node(irb, child_type_node, scope); | 5313 | IrInstruction *child_type = ir_gen_node(irb, child_type_node, scope); |
| 5275 | if (child_type == irb->codegen->invalid_instruction) | 5314 | if (child_type == irb->codegen->invalid_instruction) |
| 5276 | return child_type; | 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,7 +5414,7 @@ static IrInstruction *ir_gen_test_expr(IrBuilder *irb, Scope *scope, AstNode *no |
| 5375 | 5414 | ||
| 5376 | IrInstruction *var_ptr_value = ir_build_unwrap_maybe(irb, scope, node, maybe_val_ptr, false); | 5415 | IrInstruction *var_ptr_value = ir_build_unwrap_maybe(irb, scope, node, maybe_val_ptr, false); |
| 5377 | IrInstruction *var_value = var_is_ptr ? var_ptr_value : ir_build_load_ptr(irb, scope, node, var_ptr_value); | 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 | var_scope = var->child_scope; | 5418 | var_scope = var->child_scope; |
| 5380 | } else { | 5419 | } else { |
| 5381 | var_scope = scope; | 5420 | var_scope = scope; |
| ... | @@ -5452,7 +5491,7 @@ static IrInstruction *ir_gen_try_expr(IrBuilder *irb, Scope *scope, AstNode *nod | ... | @@ -5452,7 +5491,7 @@ static IrInstruction *ir_gen_try_expr(IrBuilder *irb, Scope *scope, AstNode *nod |
| 5452 | 5491 | ||
| 5453 | IrInstruction *var_ptr_value = ir_build_unwrap_err_payload(irb, scope, node, err_val_ptr, false); | 5492 | IrInstruction *var_ptr_value = ir_build_unwrap_err_payload(irb, scope, node, err_val_ptr, false); |
| 5454 | IrInstruction *var_value = var_is_ptr ? var_ptr_value : ir_build_load_ptr(irb, scope, node, var_ptr_value); | 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 | var_scope = var->child_scope; | 5495 | var_scope = var->child_scope; |
| 5457 | } else { | 5496 | } else { |
| 5458 | var_scope = scope; | 5497 | var_scope = scope; |
| ... | @@ -5477,7 +5516,7 @@ static IrInstruction *ir_gen_try_expr(IrBuilder *irb, Scope *scope, AstNode *nod | ... | @@ -5477,7 +5516,7 @@ static IrInstruction *ir_gen_try_expr(IrBuilder *irb, Scope *scope, AstNode *nod |
| 5477 | err_symbol, is_const, is_const, is_shadowable, is_comptime); | 5516 | err_symbol, is_const, is_const, is_shadowable, is_comptime); |
| 5478 | 5517 | ||
| 5479 | IrInstruction *var_value = ir_build_unwrap_err_code(irb, scope, node, err_val_ptr); | 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 | err_var_scope = var->child_scope; | 5520 | err_var_scope = var->child_scope; |
| 5482 | } else { | 5521 | } else { |
| 5483 | err_var_scope = scope; | 5522 | err_var_scope = scope; |
| ... | @@ -5531,7 +5570,7 @@ static bool ir_gen_switch_prong_expr(IrBuilder *irb, Scope *scope, AstNode *swit | ... | @@ -5531,7 +5570,7 @@ static bool ir_gen_switch_prong_expr(IrBuilder *irb, Scope *scope, AstNode *swit |
| 5531 | var_value = var_is_ptr ? target_value_ptr : ir_build_load_ptr(irb, scope, var_symbol_node, target_value_ptr); | 5570 | var_value = var_is_ptr ? target_value_ptr : ir_build_load_ptr(irb, scope, var_symbol_node, target_value_ptr); |
| 5532 | } | 5571 | } |
| 5533 | IrInstruction *var_type = nullptr; // infer the type | 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 | } else { | 5574 | } else { |
| 5536 | child_scope = scope; | 5575 | child_scope = scope; |
| 5537 | } | 5576 | } |
| ... | @@ -5912,7 +5951,7 @@ static IrInstruction *ir_gen_err_ok_or(IrBuilder *irb, Scope *parent_scope, AstN | ... | @@ -5912,7 +5951,7 @@ static IrInstruction *ir_gen_err_ok_or(IrBuilder *irb, Scope *parent_scope, AstN |
| 5912 | is_const, is_const, is_shadowable, is_comptime); | 5951 | is_const, is_const, is_shadowable, is_comptime); |
| 5913 | err_scope = var->child_scope; | 5952 | err_scope = var->child_scope; |
| 5914 | IrInstruction *err_val = ir_build_unwrap_err_code(irb, err_scope, node, err_union_ptr); | 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 | } else { | 5955 | } else { |
| 5917 | err_scope = parent_scope; | 5956 | err_scope = parent_scope; |
| 5918 | } | 5957 | } |
| ... | @@ -6056,6 +6095,8 @@ static IrInstruction *ir_gen_node_raw(IrBuilder *irb, AstNode *node, Scope *scop | ... | @@ -6056,6 +6095,8 @@ static IrInstruction *ir_gen_node_raw(IrBuilder *irb, AstNode *node, Scope *scop |
| 6056 | return ir_lval_wrap(irb, scope, ir_gen_if_bool_expr(irb, scope, node), lval); | 6095 | return ir_lval_wrap(irb, scope, ir_gen_if_bool_expr(irb, scope, node), lval); |
| 6057 | case NodeTypePrefixOpExpr: | 6096 | case NodeTypePrefixOpExpr: |
| 6058 | return ir_gen_prefix_op_expr(irb, scope, node, lval); | 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 | case NodeTypeContainerInitExpr: | 6100 | case NodeTypeContainerInitExpr: |
| 6060 | return ir_lval_wrap(irb, scope, ir_gen_container_init_expr(irb, scope, node), lval); | 6101 | return ir_lval_wrap(irb, scope, ir_gen_container_init_expr(irb, scope, node), lval); |
| 6061 | case NodeTypeVariableDeclaration: | 6102 | case NodeTypeVariableDeclaration: |
| ... | @@ -7264,7 +7305,8 @@ static TypeTableEntry *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_nod | ... | @@ -7264,7 +7305,8 @@ static TypeTableEntry *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_nod |
| 7264 | } | 7305 | } |
| 7265 | if (convert_to_const_slice) { | 7306 | if (convert_to_const_slice) { |
| 7266 | assert(prev_inst->value.type->id == TypeTableEntryIdArray); | 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 | if (any_are_pure_error) { | 7310 | if (any_are_pure_error) { |
| 7269 | return get_error_type(ira->codegen, slice_type); | 7311 | return get_error_type(ira->codegen, slice_type); |
| 7270 | } else { | 7312 | } else { |
| ... | @@ -7569,7 +7611,7 @@ static TypeTableEntry *ir_analyze_void(IrAnalyze *ira, IrInstruction *instructio | ... | @@ -7569,7 +7611,7 @@ static TypeTableEntry *ir_analyze_void(IrAnalyze *ira, IrInstruction *instructio |
| 7569 | 7611 | ||
| 7570 | static IrInstruction *ir_get_const_ptr(IrAnalyze *ira, IrInstruction *instruction, | 7612 | static IrInstruction *ir_get_const_ptr(IrAnalyze *ira, IrInstruction *instruction, |
| 7571 | ConstExprValue *pointee, TypeTableEntry *pointee_type, | 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 | if (pointee_type->id == TypeTableEntryIdMetaType) { | 7616 | if (pointee_type->id == TypeTableEntryIdMetaType) { |
| 7575 | TypeTableEntry *type_entry = pointee->data.x_type; | 7617 | TypeTableEntry *type_entry = pointee->data.x_type; |
| ... | @@ -7583,11 +7625,11 @@ static IrInstruction *ir_get_const_ptr(IrAnalyze *ira, IrInstruction *instructio | ... | @@ -7583,11 +7625,11 @@ static IrInstruction *ir_get_const_ptr(IrAnalyze *ira, IrInstruction *instructio |
| 7583 | const_val->type = pointee_type; | 7625 | const_val->type = pointee_type; |
| 7584 | type_ensure_zero_bits_known(ira->codegen, type_entry); | 7626 | type_ensure_zero_bits_known(ira->codegen, type_entry); |
| 7585 | const_val->data.x_type = get_pointer_to_type_extra(ira->codegen, type_entry, | 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 | return const_instr; | 7629 | return const_instr; |
| 7588 | } else { | 7630 | } else { |
| 7589 | TypeTableEntry *ptr_type = get_pointer_to_type_extra(ira->codegen, pointee_type, | 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 | IrInstruction *const_instr = ir_get_const(ira, instruction); | 7633 | IrInstruction *const_instr = ir_get_const(ira, instruction); |
| 7592 | ConstExprValue *const_val = &const_instr->value; | 7634 | ConstExprValue *const_val = &const_instr->value; |
| 7593 | const_val->type = ptr_type; | 7635 | const_val->type = ptr_type; |
| ... | @@ -7603,7 +7645,8 @@ static TypeTableEntry *ir_analyze_const_ptr(IrAnalyze *ira, IrInstruction *instr | ... | @@ -7603,7 +7645,8 @@ static TypeTableEntry *ir_analyze_const_ptr(IrAnalyze *ira, IrInstruction *instr |
| 7603 | ConstPtrMut ptr_mut, bool ptr_is_const, bool ptr_is_volatile) | 7645 | ConstPtrMut ptr_mut, bool ptr_is_const, bool ptr_is_volatile) |
| 7604 | { | 7646 | { |
| 7605 | IrInstruction *const_instr = ir_get_const_ptr(ira, instruction, pointee, | 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 | ir_link_new_instruction(const_instr, instruction); | 7650 | ir_link_new_instruction(const_instr, instruction); |
| 7608 | return const_instr->value.type; | 7651 | return const_instr->value.type; |
| 7609 | } | 7652 | } |
| ... | @@ -7876,10 +7919,12 @@ static IrInstruction *ir_get_ref(IrAnalyze *ira, IrInstruction *source_instructi | ... | @@ -7876,10 +7919,12 @@ static IrInstruction *ir_get_ref(IrAnalyze *ira, IrInstruction *source_instructi |
| 7876 | return ira->codegen->invalid_instruction; | 7919 | return ira->codegen->invalid_instruction; |
| 7877 | bool final_is_const = (value->value.type->id == TypeTableEntryIdMetaType) ? is_const : true; | 7920 | bool final_is_const = (value->value.type->id == TypeTableEntryIdMetaType) ? is_const : true; |
| 7878 | return ir_get_const_ptr(ira, source_instruction, val, value->value.type, | 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 | FnTableEntry *fn_entry = exec_fn_entry(ira->new_irb.exec); | 7928 | FnTableEntry *fn_entry = exec_fn_entry(ira->new_irb.exec); |
| 7884 | assert(fn_entry); | 7929 | assert(fn_entry); |
| 7885 | IrInstruction *new_instruction = ir_build_ref(&ira->new_irb, source_instruction->scope, | 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,6 +8624,33 @@ static TypeTableEntry *ir_analyze_ref(IrAnalyze *ira, IrInstruction *source_inst |
| 8579 | return result->value.type; | 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 | static bool ir_resolve_usize(IrAnalyze *ira, IrInstruction *value, uint64_t *out) { | 8654 | static bool ir_resolve_usize(IrAnalyze *ira, IrInstruction *value, uint64_t *out) { |
| 8583 | if (type_is_invalid(value->value.type)) | 8655 | if (type_is_invalid(value->value.type)) |
| 8584 | return false; | 8656 | return false; |
| ... | @@ -8656,7 +8728,8 @@ static Buf *ir_resolve_str(IrAnalyze *ira, IrInstruction *value) { | ... | @@ -8656,7 +8728,8 @@ static Buf *ir_resolve_str(IrAnalyze *ira, IrInstruction *value) { |
| 8656 | if (type_is_invalid(value->value.type)) | 8728 | if (type_is_invalid(value->value.type)) |
| 8657 | return nullptr; | 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 | IrInstruction *casted_value = ir_implicit_cast(ira, value, str_type); | 8733 | IrInstruction *casted_value = ir_implicit_cast(ira, value, str_type); |
| 8661 | if (type_is_invalid(casted_value->value.type)) | 8734 | if (type_is_invalid(casted_value->value.type)) |
| 8662 | return nullptr; | 8735 | return nullptr; |
| ... | @@ -9715,6 +9788,14 @@ static TypeTableEntry *ir_analyze_instruction_decl_var(IrAnalyze *ira, IrInstruc | ... | @@ -9715,6 +9788,14 @@ static TypeTableEntry *ir_analyze_instruction_decl_var(IrAnalyze *ira, IrInstruc |
| 9715 | 9788 | ||
| 9716 | bool is_comptime = ir_get_var_is_comptime(var); | 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 | if (casted_init_value->value.special != ConstValSpecialRuntime) { | 9799 | if (casted_init_value->value.special != ConstValSpecialRuntime) { |
| 9719 | if (var->mem_slot_index != SIZE_MAX) { | 9800 | if (var->mem_slot_index != SIZE_MAX) { |
| 9720 | assert(var->mem_slot_index < ira->exec_context.mem_slot_count); | 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,7 +9814,7 @@ static TypeTableEntry *ir_analyze_instruction_decl_var(IrAnalyze *ira, IrInstruc |
| 9733 | return ira->codegen->builtin_types.entry_invalid; | 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 | FnTableEntry *fn_entry = exec_fn_entry(ira->new_irb.exec); | 9819 | FnTableEntry *fn_entry = exec_fn_entry(ira->new_irb.exec); |
| 9739 | if (fn_entry) | 9820 | if (fn_entry) |
| ... | @@ -9892,11 +9973,12 @@ static IrInstruction *ir_get_var_ptr(IrAnalyze *ira, IrInstruction *instruction, | ... | @@ -9892,11 +9973,12 @@ static IrInstruction *ir_get_var_ptr(IrAnalyze *ira, IrInstruction *instruction, |
| 9892 | ptr_mut = ConstPtrMutRuntimeVar; | 9973 | ptr_mut = ConstPtrMutRuntimeVar; |
| 9893 | } | 9974 | } |
| 9894 | return ir_get_const_ptr(ira, instruction, mem_slot, var->value->type, | 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 | } else { | 9977 | } else { |
| 9897 | IrInstruction *var_ptr_instruction = ir_build_var_ptr(&ira->new_irb, | 9978 | IrInstruction *var_ptr_instruction = ir_build_var_ptr(&ira->new_irb, |
| 9898 | instruction->scope, instruction->source_node, var, is_const, is_volatile); | 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 | type_ensure_zero_bits_known(ira->codegen, var->value->type); | 9982 | type_ensure_zero_bits_known(ira->codegen, var->value->type); |
| 9901 | 9983 | ||
| 9902 | bool in_fn_scope = (scope_fn_entry(var->parent_scope) != nullptr); | 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,6 +10213,16 @@ static TypeTableEntry *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *cal |
| 10131 | impl_fn->child_scope, param_name, true, var_args_val, nullptr); | 10213 | impl_fn->child_scope, param_name, true, var_args_val, nullptr); |
| 10132 | impl_fn->child_scope = var->child_scope; | 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 | AstNode *return_type_node = fn_proto_node->data.fn_proto.return_type; | 10227 | AstNode *return_type_node = fn_proto_node->data.fn_proto.return_type; |
| 10136 | TypeTableEntry *return_type = analyze_type_expr(ira->codegen, impl_fn->child_scope, return_type_node); | 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,7 +10823,8 @@ static TypeTableEntry *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruc |
| 10731 | TypeTableEntry *child_type = array_type->data.array.child_type; | 10823 | TypeTableEntry *child_type = array_type->data.array.child_type; |
| 10732 | if (ptr_type->data.pointer.unaligned_bit_count == 0) { | 10824 | if (ptr_type->data.pointer.unaligned_bit_count == 0) { |
| 10733 | return_type = get_pointer_to_type_extra(ira->codegen, child_type, | 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 | } else { | 10828 | } else { |
| 10736 | uint64_t elem_val_scalar; | 10829 | uint64_t elem_val_scalar; |
| 10737 | if (!ir_resolve_usize(ira, elem_index, &elem_val_scalar)) | 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,6 +10835,7 @@ static TypeTableEntry *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruc |
| 10742 | 10835 | ||
| 10743 | return_type = get_pointer_to_type_extra(ira->codegen, child_type, | 10836 | return_type = get_pointer_to_type_extra(ira->codegen, child_type, |
| 10744 | ptr_type->data.pointer.is_const, ptr_type->data.pointer.is_volatile, | 10837 | ptr_type->data.pointer.is_const, ptr_type->data.pointer.is_volatile, |
| 10838 | get_abi_alignment(ira->codegen, child_type), | ||
| 10745 | (uint32_t)bit_offset, (uint32_t)bit_width); | 10839 | (uint32_t)bit_offset, (uint32_t)bit_width); |
| 10746 | } | 10840 | } |
| 10747 | } else if (array_type->id == TypeTableEntryIdPointer) { | 10841 | } else if (array_type->id == TypeTableEntryIdPointer) { |
| ... | @@ -10964,6 +11058,8 @@ static TypeTableEntry *ir_analyze_container_field_ptr(IrAnalyze *ira, Buf *field | ... | @@ -10964,6 +11058,8 @@ static TypeTableEntry *ir_analyze_container_field_ptr(IrAnalyze *ira, Buf *field |
| 10964 | 11058 | ||
| 10965 | TypeStructField *field = find_struct_type_field(bare_type, field_name); | 11059 | TypeStructField *field = find_struct_type_field(bare_type, field_name); |
| 10966 | if (field) { | 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 | if (instr_is_comptime(container_ptr)) { | 11063 | if (instr_is_comptime(container_ptr)) { |
| 10968 | ConstExprValue *ptr_val = ir_resolve_const(ira, container_ptr, UndefBad); | 11064 | ConstExprValue *ptr_val = ir_resolve_const(ira, container_ptr, UndefBad); |
| 10969 | if (!ptr_val) | 11065 | if (!ptr_val) |
| ... | @@ -10973,7 +11069,7 @@ static TypeTableEntry *ir_analyze_container_field_ptr(IrAnalyze *ira, Buf *field | ... | @@ -10973,7 +11069,7 @@ static TypeTableEntry *ir_analyze_container_field_ptr(IrAnalyze *ira, Buf *field |
| 10973 | ConstExprValue *struct_val = const_ptr_pointee(ira->codegen, ptr_val); | 11069 | ConstExprValue *struct_val = const_ptr_pointee(ira->codegen, ptr_val); |
| 10974 | ConstExprValue *field_val = &struct_val->data.x_struct.fields[field->src_index]; | 11070 | ConstExprValue *field_val = &struct_val->data.x_struct.fields[field->src_index]; |
| 10975 | TypeTableEntry *ptr_type = get_pointer_to_type_extra(ira->codegen, field_val->type, | 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 | ConstExprValue *const_val = ir_build_const_from(ira, &field_ptr_instruction->base); | 11073 | ConstExprValue *const_val = ir_build_const_from(ira, &field_ptr_instruction->base); |
| 10978 | const_val->data.x_ptr.special = ConstPtrSpecialBaseStruct; | 11074 | const_val->data.x_ptr.special = ConstPtrSpecialBaseStruct; |
| 10979 | const_val->data.x_ptr.mut = container_ptr->value.data.x_ptr.mut; | 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,6 +11084,7 @@ static TypeTableEntry *ir_analyze_container_field_ptr(IrAnalyze *ira, Buf *field |
| 10988 | field->unaligned_bit_count : type_size_bits(ira->codegen, field->type_entry); | 11084 | field->unaligned_bit_count : type_size_bits(ira->codegen, field->type_entry); |
| 10989 | ir_build_struct_field_ptr_from(&ira->new_irb, &field_ptr_instruction->base, container_ptr, field); | 11085 | ir_build_struct_field_ptr_from(&ira->new_irb, &field_ptr_instruction->base, container_ptr, field); |
| 10990 | return get_pointer_to_type_extra(ira->codegen, field->type_entry, is_const, is_volatile, | 11086 | return get_pointer_to_type_extra(ira->codegen, field->type_entry, is_const, is_volatile, |
| 11087 | align_bytes, | ||
| 10991 | (uint32_t)(ptr_bit_offset + field->packed_bits_offset), | 11088 | (uint32_t)(ptr_bit_offset + field->packed_bits_offset), |
| 10992 | (uint32_t)unaligned_bit_count_for_result_type); | 11089 | (uint32_t)unaligned_bit_count_for_result_type); |
| 10993 | } else { | 11090 | } else { |
| ... | @@ -11001,7 +11098,8 @@ static TypeTableEntry *ir_analyze_container_field_ptr(IrAnalyze *ira, Buf *field | ... | @@ -11001,7 +11098,8 @@ static TypeTableEntry *ir_analyze_container_field_ptr(IrAnalyze *ira, Buf *field |
| 11001 | TypeEnumField *field = find_enum_type_field(bare_type, field_name); | 11098 | TypeEnumField *field = find_enum_type_field(bare_type, field_name); |
| 11002 | if (field) { | 11099 | if (field) { |
| 11003 | ir_build_enum_field_ptr_from(&ira->new_irb, &field_ptr_instruction->base, container_ptr, field); | 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 | } else { | 11103 | } else { |
| 11006 | return ir_analyze_container_member_access_inner(ira, bare_type, field_name, | 11104 | return ir_analyze_container_member_access_inner(ira, bare_type, field_name, |
| 11007 | field_ptr_instruction, container_ptr, container_type); | 11105 | field_ptr_instruction, container_ptr, container_type); |
| ... | @@ -11427,7 +11525,6 @@ static TypeTableEntry *ir_analyze_instruction_ptr_type_child(IrAnalyze *ira, | ... | @@ -11427,7 +11525,6 @@ static TypeTableEntry *ir_analyze_instruction_ptr_type_child(IrAnalyze *ira, |
| 11427 | if (type_is_invalid(type_entry)) | 11525 | if (type_is_invalid(type_entry)) |
| 11428 | return type_entry; | 11526 | return type_entry; |
| 11429 | 11527 | ||
| 11430 | // TODO handle typedefs | ||
| 11431 | if (type_entry->id != TypeTableEntryIdPointer) { | 11528 | if (type_entry->id != TypeTableEntryIdPointer) { |
| 11432 | ir_add_error_node(ira, ptr_type_child_instruction->base.source_node, | 11529 | ir_add_error_node(ira, ptr_type_child_instruction->base.source_node, |
| 11433 | buf_sprintf("expected pointer type, found '%s'", buf_ptr(&type_entry->name))); | 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,69 +11536,6 @@ static TypeTableEntry *ir_analyze_instruction_ptr_type_child(IrAnalyze *ira, |
| 11439 | return ira->codegen->builtin_types.entry_type; | 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 | static TypeTableEntry *ir_analyze_instruction_set_global_section(IrAnalyze *ira, | 11539 | static TypeTableEntry *ir_analyze_instruction_set_global_section(IrAnalyze *ira, |
| 11506 | IrInstructionSetGlobalSection *instruction) | 11540 | IrInstructionSetGlobalSection *instruction) |
| 11507 | { | 11541 | { |
| ... | @@ -11750,16 +11784,24 @@ static TypeTableEntry *ir_analyze_instruction_set_float_mode(IrAnalyze *ira, | ... | @@ -11750,16 +11784,24 @@ static TypeTableEntry *ir_analyze_instruction_set_float_mode(IrAnalyze *ira, |
| 11750 | static TypeTableEntry *ir_analyze_instruction_slice_type(IrAnalyze *ira, | 11784 | static TypeTableEntry *ir_analyze_instruction_slice_type(IrAnalyze *ira, |
| 11751 | IrInstructionSliceType *slice_type_instruction) | 11785 | IrInstructionSliceType *slice_type_instruction) |
| 11752 | { | 11786 | { |
| 11753 | IrInstruction *child_type = slice_type_instruction->child_type->other; | 11787 | uint32_t align_bytes; |
| 11754 | if (type_is_invalid(child_type->value.type)) | 11788 | if (slice_type_instruction->align_value != nullptr) { |
| 11755 | return ira->codegen->builtin_types.entry_invalid; | 11789 | if (!ir_resolve_align(ira, slice_type_instruction->align_value->other, &align_bytes)) |
| 11756 | bool is_const = slice_type_instruction->is_const; | 11790 | return ira->codegen->builtin_types.entry_invalid; |
| 11791 | } | ||
| 11757 | 11792 | ||
| 11758 | TypeTableEntry *resolved_child_type = ir_resolve_type(ira, child_type); | 11793 | TypeTableEntry *child_type = ir_resolve_type(ira, slice_type_instruction->child_type->other); |
| 11759 | if (type_is_invalid(resolved_child_type)) | 11794 | if (type_is_invalid(child_type)) |
| 11760 | return ira->codegen->builtin_types.entry_invalid; | 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 | case TypeTableEntryIdInvalid: // handled above | 11805 | case TypeTableEntryIdInvalid: // handled above |
| 11764 | zig_unreachable(); | 11806 | zig_unreachable(); |
| 11765 | case TypeTableEntryIdVar: | 11807 | case TypeTableEntryIdVar: |
| ... | @@ -11770,7 +11812,7 @@ static TypeTableEntry *ir_analyze_instruction_slice_type(IrAnalyze *ira, | ... | @@ -11770,7 +11812,7 @@ static TypeTableEntry *ir_analyze_instruction_slice_type(IrAnalyze *ira, |
| 11770 | case TypeTableEntryIdArgTuple: | 11812 | case TypeTableEntryIdArgTuple: |
| 11771 | case TypeTableEntryIdOpaque: | 11813 | case TypeTableEntryIdOpaque: |
| 11772 | ir_add_error_node(ira, slice_type_instruction->base.source_node, | 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 | return ira->codegen->builtin_types.entry_invalid; | 11816 | return ira->codegen->builtin_types.entry_invalid; |
| 11775 | case TypeTableEntryIdMetaType: | 11817 | case TypeTableEntryIdMetaType: |
| 11776 | case TypeTableEntryIdVoid: | 11818 | case TypeTableEntryIdVoid: |
| ... | @@ -11792,8 +11834,10 @@ static TypeTableEntry *ir_analyze_instruction_slice_type(IrAnalyze *ira, | ... | @@ -11792,8 +11834,10 @@ static TypeTableEntry *ir_analyze_instruction_slice_type(IrAnalyze *ira, |
| 11792 | case TypeTableEntryIdBoundFn: | 11834 | case TypeTableEntryIdBoundFn: |
| 11793 | case TypeTableEntryIdEnumTag: | 11835 | case TypeTableEntryIdEnumTag: |
| 11794 | { | 11836 | { |
| 11795 | type_ensure_zero_bits_known(ira->codegen, resolved_child_type); | 11837 | type_ensure_zero_bits_known(ira->codegen, child_type); |
| 11796 | TypeTableEntry *result_type = get_slice_type(ira->codegen, resolved_child_type, is_const); | 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 | ConstExprValue *out_val = ir_build_const_from(ira, &slice_type_instruction->base); | 11841 | ConstExprValue *out_val = ir_build_const_from(ira, &slice_type_instruction->base); |
| 11798 | out_val->data.x_type = result_type; | 11842 | out_val->data.x_type = result_type; |
| 11799 | return ira->codegen->builtin_types.entry_type; | 11843 | return ira->codegen->builtin_types.entry_type; |
| ... | @@ -12018,7 +12062,6 @@ static TypeTableEntry *ir_analyze_instruction_unwrap_maybe(IrAnalyze *ira, | ... | @@ -12018,7 +12062,6 @@ static TypeTableEntry *ir_analyze_instruction_unwrap_maybe(IrAnalyze *ira, |
| 12018 | assert(ptr_type->id == TypeTableEntryIdPointer); | 12062 | assert(ptr_type->id == TypeTableEntryIdPointer); |
| 12019 | 12063 | ||
| 12020 | TypeTableEntry *type_entry = ptr_type->data.pointer.child_type; | 12064 | TypeTableEntry *type_entry = ptr_type->data.pointer.child_type; |
| 12021 | // TODO handle typedef | ||
| 12022 | if (type_is_invalid(type_entry)) { | 12065 | if (type_is_invalid(type_entry)) { |
| 12023 | return ira->codegen->builtin_types.entry_invalid; | 12066 | return ira->codegen->builtin_types.entry_invalid; |
| 12024 | } else if (type_entry->id != TypeTableEntryIdMaybe) { | 12067 | } else if (type_entry->id != TypeTableEntryIdMaybe) { |
| ... | @@ -12028,7 +12071,8 @@ static TypeTableEntry *ir_analyze_instruction_unwrap_maybe(IrAnalyze *ira, | ... | @@ -12028,7 +12071,8 @@ static TypeTableEntry *ir_analyze_instruction_unwrap_maybe(IrAnalyze *ira, |
| 12028 | } | 12071 | } |
| 12029 | TypeTableEntry *child_type = type_entry->data.maybe.child_type; | 12072 | TypeTableEntry *child_type = type_entry->data.maybe.child_type; |
| 12030 | TypeTableEntry *result_type = get_pointer_to_type_extra(ira->codegen, child_type, | 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 | if (instr_is_comptime(value)) { | 12077 | if (instr_is_comptime(value)) { |
| 12034 | ConstExprValue *val = ir_resolve_const(ira, value, UndefBad); | 12078 | ConstExprValue *val = ir_resolve_const(ira, value, UndefBad); |
| ... | @@ -12887,7 +12931,8 @@ static TypeTableEntry *ir_analyze_instruction_err_name(IrAnalyze *ira, IrInstruc | ... | @@ -12887,7 +12931,8 @@ static TypeTableEntry *ir_analyze_instruction_err_name(IrAnalyze *ira, IrInstruc |
| 12887 | if (type_is_invalid(casted_value->value.type)) | 12931 | if (type_is_invalid(casted_value->value.type)) |
| 12888 | return ira->codegen->builtin_types.entry_invalid; | 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 | if (casted_value->value.special == ConstValSpecialStatic) { | 12936 | if (casted_value->value.special == ConstValSpecialStatic) { |
| 12892 | ErrorTableEntry *err = casted_value->value.data.x_pure_err; | 12937 | ErrorTableEntry *err = casted_value->value.data.x_pure_err; |
| 12893 | if (!err->cached_error_name_val) { | 12938 | if (!err->cached_error_name_val) { |
| ... | @@ -12929,7 +12974,8 @@ static TypeTableEntry *ir_analyze_instruction_enum_tag_name(IrAnalyze *ira, IrIn | ... | @@ -12929,7 +12974,8 @@ static TypeTableEntry *ir_analyze_instruction_enum_tag_name(IrAnalyze *ira, IrIn |
| 12929 | IrInstruction *result = ir_build_enum_tag_name(&ira->new_irb, instruction->base.scope, | 12974 | IrInstruction *result = ir_build_enum_tag_name(&ira->new_irb, instruction->base.scope, |
| 12930 | instruction->base.source_node, target); | 12975 | instruction->base.source_node, target); |
| 12931 | ir_link_new_instruction(result, &instruction->base); | 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 | return result->value.type; | 12979 | return result->value.type; |
| 12934 | } | 12980 | } |
| 12935 | 12981 | ||
| ... | @@ -12972,16 +13018,22 @@ static TypeTableEntry *ir_analyze_instruction_field_parent_ptr(IrAnalyze *ira, | ... | @@ -12972,16 +13018,22 @@ static TypeTableEntry *ir_analyze_instruction_field_parent_ptr(IrAnalyze *ira, |
| 12972 | return ira->codegen->builtin_types.entry_invalid; | 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 | TypeTableEntry *field_ptr_type = get_pointer_to_type_extra(ira->codegen, field->type_entry, | 13025 | TypeTableEntry *field_ptr_type = get_pointer_to_type_extra(ira->codegen, field->type_entry, |
| 12976 | field_ptr->value.type->data.pointer.is_const, | 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 | IrInstruction *casted_field_ptr = ir_implicit_cast(ira, field_ptr, field_ptr_type); | 13029 | IrInstruction *casted_field_ptr = ir_implicit_cast(ira, field_ptr, field_ptr_type); |
| 12979 | if (type_is_invalid(casted_field_ptr->value.type)) | 13030 | if (type_is_invalid(casted_field_ptr->value.type)) |
| 12980 | return ira->codegen->builtin_types.entry_invalid; | 13031 | return ira->codegen->builtin_types.entry_invalid; |
| 12981 | 13032 | ||
| 12982 | TypeTableEntry *result_type = get_pointer_to_type_extra(ira->codegen, container_type, | 13033 | TypeTableEntry *result_type = get_pointer_to_type_extra(ira->codegen, container_type, |
| 12983 | casted_field_ptr->value.type->data.pointer.is_const, | 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 | if (instr_is_comptime(casted_field_ptr)) { | 13038 | if (instr_is_comptime(casted_field_ptr)) { |
| 12987 | ConstExprValue *field_ptr_val = ir_resolve_const(ira, casted_field_ptr, UndefBad); | 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,7 +13488,9 @@ static TypeTableEntry *ir_analyze_instruction_memset(IrAnalyze *ira, IrInstructi |
| 13436 | 13488 | ||
| 13437 | TypeTableEntry *usize = ira->codegen->builtin_types.entry_usize; | 13489 | TypeTableEntry *usize = ira->codegen->builtin_types.entry_usize; |
| 13438 | TypeTableEntry *u8 = ira->codegen->builtin_types.entry_u8; | 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 | IrInstruction *casted_dest_ptr = ir_implicit_cast(ira, dest_ptr, u8_ptr); | 13495 | IrInstruction *casted_dest_ptr = ir_implicit_cast(ira, dest_ptr, u8_ptr); |
| 13442 | if (type_is_invalid(casted_dest_ptr->value.type)) | 13496 | if (type_is_invalid(casted_dest_ptr->value.type)) |
| ... | @@ -13517,17 +13571,21 @@ static TypeTableEntry *ir_analyze_instruction_memcpy(IrAnalyze *ira, IrInstructi | ... | @@ -13517,17 +13571,21 @@ static TypeTableEntry *ir_analyze_instruction_memcpy(IrAnalyze *ira, IrInstructi |
| 13517 | if (type_is_invalid(count_value->value.type)) | 13571 | if (type_is_invalid(count_value->value.type)) |
| 13518 | return ira->codegen->builtin_types.entry_invalid; | 13572 | return ira->codegen->builtin_types.entry_invalid; |
| 13519 | 13573 | ||
| 13574 | TypeTableEntry *u8 = ira->codegen->builtin_types.entry_u8; | ||
| 13520 | TypeTableEntry *dest_uncasted_type = dest_ptr->value.type; | 13575 | TypeTableEntry *dest_uncasted_type = dest_ptr->value.type; |
| 13521 | TypeTableEntry *src_uncasted_type = src_ptr->value.type; | 13576 | TypeTableEntry *src_uncasted_type = src_ptr->value.type; |
| 13522 | bool dest_is_volatile = (dest_uncasted_type->id == TypeTableEntryIdPointer) && | 13577 | bool dest_is_volatile = (dest_uncasted_type->id == TypeTableEntryIdPointer) && |
| 13523 | dest_uncasted_type->data.pointer.is_volatile; | 13578 | dest_uncasted_type->data.pointer.is_volatile; |
| 13524 | bool src_is_volatile = (src_uncasted_type->id == TypeTableEntryIdPointer) && | 13579 | bool src_is_volatile = (src_uncasted_type->id == TypeTableEntryIdPointer) && |
| 13525 | src_uncasted_type->data.pointer.is_volatile; | 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 | TypeTableEntry *usize = ira->codegen->builtin_types.entry_usize; | 13586 | TypeTableEntry *usize = ira->codegen->builtin_types.entry_usize; |
| 13528 | TypeTableEntry *u8 = ira->codegen->builtin_types.entry_u8; | 13587 | TypeTableEntry *u8_ptr_mut = get_pointer_to_type_extra(ira->codegen, u8, false, dest_is_volatile, dest_align, 0, 0); |
| 13529 | TypeTableEntry *u8_ptr_mut = get_pointer_to_type_extra(ira->codegen, u8, false, dest_is_volatile, 0, 0); | 13588 | TypeTableEntry *u8_ptr_const = get_pointer_to_type_extra(ira->codegen, u8, true, src_is_volatile, src_align, 0, 0); |
| 13530 | TypeTableEntry *u8_ptr_const = get_pointer_to_type_extra(ira->codegen, u8, true, src_is_volatile, 0, 0); | ||
| 13531 | 13589 | ||
| 13532 | IrInstruction *casted_dest_ptr = ir_implicit_cast(ira, dest_ptr, u8_ptr_mut); | 13590 | IrInstruction *casted_dest_ptr = ir_implicit_cast(ira, dest_ptr, u8_ptr_mut); |
| 13533 | if (type_is_invalid(casted_dest_ptr->value.type)) | 13591 | if (type_is_invalid(casted_dest_ptr->value.type)) |
| ... | @@ -13662,17 +13720,24 @@ static TypeTableEntry *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstructio | ... | @@ -13662,17 +13720,24 @@ static TypeTableEntry *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstructio |
| 13662 | TypeTableEntry *return_type; | 13720 | TypeTableEntry *return_type; |
| 13663 | 13721 | ||
| 13664 | if (array_type->id == TypeTableEntryIdArray) { | 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 | } else if (array_type->id == TypeTableEntryIdPointer) { | 13729 | } else if (array_type->id == TypeTableEntryIdPointer) { |
| 13667 | return_type = get_slice_type(ira->codegen, array_type->data.pointer.child_type, | 13730 | TypeTableEntry *slice_ptr_type = get_pointer_to_type_extra(ira->codegen, array_type->data.pointer.child_type, |
| 13668 | array_type->data.pointer.is_const); | 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 | if (!end) { | 13734 | if (!end) { |
| 13670 | ir_add_error(ira, &instruction->base, buf_sprintf("slice of pointer must include end value")); | 13735 | ir_add_error(ira, &instruction->base, buf_sprintf("slice of pointer must include end value")); |
| 13671 | return ira->codegen->builtin_types.entry_invalid; | 13736 | return ira->codegen->builtin_types.entry_invalid; |
| 13672 | } | 13737 | } |
| 13673 | } else if (is_slice(array_type)) { | 13738 | } else if (is_slice(array_type)) { |
| 13674 | TypeTableEntry *ptr_type = array_type->data.structure.fields[slice_ptr_index].type_entry; | 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 | } else { | 13741 | } else { |
| 13677 | ir_add_error(ira, &instruction->base, | 13742 | ir_add_error(ira, &instruction->base, |
| 13678 | buf_sprintf("slice of non-array type '%s'", buf_ptr(&array_type->name))); | 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,7 +13925,7 @@ static TypeTableEntry *ir_analyze_instruction_frame_address(IrAnalyze *ira, IrIn |
| 13860 | return u8_ptr_const; | 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 | IrInstruction *type_value = instruction->type_value->other; | 13929 | IrInstruction *type_value = instruction->type_value->other; |
| 13865 | if (type_is_invalid(type_value->value.type)) | 13930 | if (type_is_invalid(type_value->value.type)) |
| 13866 | return ira->codegen->builtin_types.entry_invalid; | 13931 | return ira->codegen->builtin_types.entry_invalid; |
| ... | @@ -13884,62 +13949,11 @@ static TypeTableEntry *ir_analyze_instruction_preferred_align_of(IrAnalyze *ira, | ... | @@ -13884,62 +13949,11 @@ static TypeTableEntry *ir_analyze_instruction_preferred_align_of(IrAnalyze *ira, |
| 13884 | case TypeTableEntryIdBlock: | 13949 | case TypeTableEntryIdBlock: |
| 13885 | case TypeTableEntryIdBoundFn: | 13950 | case TypeTableEntryIdBoundFn: |
| 13886 | case TypeTableEntryIdArgTuple: | 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 | case TypeTableEntryIdVoid: | 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 | case TypeTableEntryIdOpaque: | 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 | ir_add_error(ira, instruction->type_value, | 13954 | ir_add_error(ira, instruction->type_value, |
| 13940 | buf_sprintf("no align available for type '%s'", buf_ptr(&type_entry->name))); | 13955 | buf_sprintf("no align available for type '%s'", buf_ptr(&type_entry->name))); |
| 13941 | return ira->codegen->builtin_types.entry_invalid; | 13956 | return ira->codegen->builtin_types.entry_invalid; |
| 13942 | case TypeTableEntryIdVoid: | ||
| 13943 | case TypeTableEntryIdBool: | 13957 | case TypeTableEntryIdBool: |
| 13944 | case TypeTableEntryIdInt: | 13958 | case TypeTableEntryIdInt: |
| 13945 | case TypeTableEntryIdFloat: | 13959 | case TypeTableEntryIdFloat: |
| ... | @@ -13953,9 +13967,8 @@ static TypeTableEntry *ir_analyze_instruction_abi_align_of(IrAnalyze *ira, IrIns | ... | @@ -13953,9 +13967,8 @@ static TypeTableEntry *ir_analyze_instruction_abi_align_of(IrAnalyze *ira, IrIns |
| 13953 | case TypeTableEntryIdEnumTag: | 13967 | case TypeTableEntryIdEnumTag: |
| 13954 | case TypeTableEntryIdUnion: | 13968 | case TypeTableEntryIdUnion: |
| 13955 | case TypeTableEntryIdFn: | 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 | ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base); | 13972 | ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base); |
| 13960 | bigint_init_unsigned(&out_val->data.x_bigint, align_in_bytes); | 13973 | bigint_init_unsigned(&out_val->data.x_bigint, align_in_bytes); |
| 13961 | return ira->codegen->builtin_types.entry_num_lit_int; | 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,7 +14156,8 @@ static TypeTableEntry *ir_analyze_instruction_unwrap_err_payload(IrAnalyze *ira, |
| 14143 | } else if (type_entry->id == TypeTableEntryIdErrorUnion) { | 14156 | } else if (type_entry->id == TypeTableEntryIdErrorUnion) { |
| 14144 | TypeTableEntry *child_type = type_entry->data.error.child_type; | 14157 | TypeTableEntry *child_type = type_entry->data.error.child_type; |
| 14145 | TypeTableEntry *result_type = get_pointer_to_type_extra(ira->codegen, child_type, | 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 | if (instr_is_comptime(value)) { | 14161 | if (instr_is_comptime(value)) { |
| 14148 | ConstExprValue *ptr_val = ir_resolve_const(ira, value, UndefBad); | 14162 | ConstExprValue *ptr_val = ir_resolve_const(ira, value, UndefBad); |
| 14149 | if (!ptr_val) | 14163 | if (!ptr_val) |
| ... | @@ -14390,7 +14404,8 @@ static TypeTableEntry *ir_analyze_instruction_panic(IrAnalyze *ira, IrInstructio | ... | @@ -14390,7 +14404,8 @@ static TypeTableEntry *ir_analyze_instruction_panic(IrAnalyze *ira, IrInstructio |
| 14390 | if (type_is_invalid(msg->value.type)) | 14404 | if (type_is_invalid(msg->value.type)) |
| 14391 | return ira->codegen->builtin_types.entry_invalid; | 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 | IrInstruction *casted_msg = ir_implicit_cast(ira, msg, str_type); | 14409 | IrInstruction *casted_msg = ir_implicit_cast(ira, msg, str_type); |
| 14395 | if (type_is_invalid(casted_msg->value.type)) | 14410 | if (type_is_invalid(casted_msg->value.type)) |
| 14396 | return ira->codegen->builtin_types.entry_invalid; | 14411 | return ira->codegen->builtin_types.entry_invalid; |
| ... | @@ -14814,6 +14829,23 @@ static TypeTableEntry *ir_analyze_instruction_ptr_to_int(IrAnalyze *ira, IrInstr | ... | @@ -14814,6 +14829,23 @@ static TypeTableEntry *ir_analyze_instruction_ptr_to_int(IrAnalyze *ira, IrInstr |
| 14814 | return usize; | 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 | static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstruction *instruction) { | 14849 | static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstruction *instruction) { |
| 14818 | switch (instruction->id) { | 14850 | switch (instruction->id) { |
| 14819 | case IrInstructionIdInvalid: | 14851 | case IrInstructionIdInvalid: |
| ... | @@ -14862,8 +14894,6 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi | ... | @@ -14862,8 +14894,6 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi |
| 14862 | return ir_analyze_instruction_to_ptr_type(ira, (IrInstructionToPtrType *)instruction); | 14894 | return ir_analyze_instruction_to_ptr_type(ira, (IrInstructionToPtrType *)instruction); |
| 14863 | case IrInstructionIdPtrTypeChild: | 14895 | case IrInstructionIdPtrTypeChild: |
| 14864 | return ir_analyze_instruction_ptr_type_child(ira, (IrInstructionPtrTypeChild *)instruction); | 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 | case IrInstructionIdSetGlobalSection: | 14897 | case IrInstructionIdSetGlobalSection: |
| 14868 | return ir_analyze_instruction_set_global_section(ira, (IrInstructionSetGlobalSection *)instruction); | 14898 | return ir_analyze_instruction_set_global_section(ira, (IrInstructionSetGlobalSection *)instruction); |
| 14869 | case IrInstructionIdSetGlobalLinkage: | 14899 | case IrInstructionIdSetGlobalLinkage: |
| ... | @@ -14952,10 +14982,8 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi | ... | @@ -14952,10 +14982,8 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi |
| 14952 | return ir_analyze_instruction_return_address(ira, (IrInstructionReturnAddress *)instruction); | 14982 | return ir_analyze_instruction_return_address(ira, (IrInstructionReturnAddress *)instruction); |
| 14953 | case IrInstructionIdFrameAddress: | 14983 | case IrInstructionIdFrameAddress: |
| 14954 | return ir_analyze_instruction_frame_address(ira, (IrInstructionFrameAddress *)instruction); | 14984 | return ir_analyze_instruction_frame_address(ira, (IrInstructionFrameAddress *)instruction); |
| 14955 | case IrInstructionIdPreferredAlignOf: | 14985 | case IrInstructionIdAlignOf: |
| 14956 | return ir_analyze_instruction_preferred_align_of(ira, (IrInstructionPreferredAlignOf *)instruction); | 14986 | return ir_analyze_instruction_align_of(ira, (IrInstructionAlignOf *)instruction); |
| 14957 | case IrInstructionIdAbiAlignOf: | ||
| 14958 | return ir_analyze_instruction_abi_align_of(ira, (IrInstructionAbiAlignOf *)instruction); | ||
| 14959 | case IrInstructionIdOverflowOp: | 14987 | case IrInstructionIdOverflowOp: |
| 14960 | return ir_analyze_instruction_overflow_op(ira, (IrInstructionOverflowOp *)instruction); | 14988 | return ir_analyze_instruction_overflow_op(ira, (IrInstructionOverflowOp *)instruction); |
| 14961 | case IrInstructionIdTestErr: | 14989 | case IrInstructionIdTestErr: |
| ... | @@ -14996,6 +15024,8 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi | ... | @@ -14996,6 +15024,8 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi |
| 14996 | return ir_analyze_instruction_type_id(ira, (IrInstructionTypeId *)instruction); | 15024 | return ir_analyze_instruction_type_id(ira, (IrInstructionTypeId *)instruction); |
| 14997 | case IrInstructionIdSetEvalBranchQuota: | 15025 | case IrInstructionIdSetEvalBranchQuota: |
| 14998 | return ir_analyze_instruction_set_eval_branch_quota(ira, (IrInstructionSetEvalBranchQuota *)instruction); | 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 | case IrInstructionIdMaybeWrap: | 15029 | case IrInstructionIdMaybeWrap: |
| 15000 | case IrInstructionIdErrWrapCode: | 15030 | case IrInstructionIdErrWrapCode: |
| 15001 | case IrInstructionIdErrWrapPayload: | 15031 | case IrInstructionIdErrWrapPayload: |
| ... | @@ -15108,11 +15138,11 @@ bool ir_has_side_effects(IrInstruction *instruction) { | ... | @@ -15108,11 +15138,11 @@ bool ir_has_side_effects(IrInstruction *instruction) { |
| 15108 | case IrInstructionIdOverflowOp: // TODO when we support multiple returns this can be side effect free | 15138 | case IrInstructionIdOverflowOp: // TODO when we support multiple returns this can be side effect free |
| 15109 | case IrInstructionIdCheckSwitchProngs: | 15139 | case IrInstructionIdCheckSwitchProngs: |
| 15110 | case IrInstructionIdCheckStatementIsVoid: | 15140 | case IrInstructionIdCheckStatementIsVoid: |
| 15111 | case IrInstructionIdSetGlobalAlign: | ||
| 15112 | case IrInstructionIdSetGlobalSection: | 15141 | case IrInstructionIdSetGlobalSection: |
| 15113 | case IrInstructionIdSetGlobalLinkage: | 15142 | case IrInstructionIdSetGlobalLinkage: |
| 15114 | case IrInstructionIdPanic: | 15143 | case IrInstructionIdPanic: |
| 15115 | case IrInstructionIdSetEvalBranchQuota: | 15144 | case IrInstructionIdSetEvalBranchQuota: |
| 15145 | case IrInstructionIdPtrTypeOf: | ||
| 15116 | return true; | 15146 | return true; |
| 15117 | case IrInstructionIdPhi: | 15147 | case IrInstructionIdPhi: |
| 15118 | case IrInstructionIdUnOp: | 15148 | case IrInstructionIdUnOp: |
| ... | @@ -15151,8 +15181,7 @@ bool ir_has_side_effects(IrInstruction *instruction) { | ... | @@ -15151,8 +15181,7 @@ bool ir_has_side_effects(IrInstruction *instruction) { |
| 15151 | case IrInstructionIdBoolNot: | 15181 | case IrInstructionIdBoolNot: |
| 15152 | case IrInstructionIdSlice: | 15182 | case IrInstructionIdSlice: |
| 15153 | case IrInstructionIdMemberCount: | 15183 | case IrInstructionIdMemberCount: |
| 15154 | case IrInstructionIdPreferredAlignOf: | 15184 | case IrInstructionIdAlignOf: |
| 15155 | case IrInstructionIdAbiAlignOf: | ||
| 15156 | case IrInstructionIdReturnAddress: | 15185 | case IrInstructionIdReturnAddress: |
| 15157 | case IrInstructionIdFrameAddress: | 15186 | case IrInstructionIdFrameAddress: |
| 15158 | case IrInstructionIdTestErr: | 15187 | case IrInstructionIdTestErr: |
src/ir_print.cpp+14-19| ... | @@ -664,14 +664,8 @@ static void ir_print_return_address(IrPrint *irp, IrInstructionReturnAddress *in | ... | @@ -664,14 +664,8 @@ static void ir_print_return_address(IrPrint *irp, IrInstructionReturnAddress *in |
| 664 | fprintf(irp->f, "@returnAddress()"); | 664 | fprintf(irp->f, "@returnAddress()"); |
| 665 | } | 665 | } |
| 666 | 666 | ||
| 667 | static void ir_print_preferred_align_of(IrPrint *irp, IrInstructionPreferredAlignOf *instruction) { | 667 | static void ir_print_align_of(IrPrint *irp, IrInstructionAlignOf *instruction) { |
| 668 | fprintf(irp->f, "@preferredAlignOf("); | 668 | fprintf(irp->f, "@alignOf("); |
| 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("); | ||
| 675 | ir_print_other_instruction(irp, instruction->type_value); | 669 | ir_print_other_instruction(irp, instruction->type_value); |
| 676 | fprintf(irp->f, ")"); | 670 | fprintf(irp->f, ")"); |
| 677 | } | 671 | } |
| ... | @@ -860,10 +854,14 @@ static void ir_print_can_implicit_cast(IrPrint *irp, IrInstructionCanImplicitCas | ... | @@ -860,10 +854,14 @@ static void ir_print_can_implicit_cast(IrPrint *irp, IrInstructionCanImplicitCas |
| 860 | fprintf(irp->f, ")"); | 854 | fprintf(irp->f, ")"); |
| 861 | } | 855 | } |
| 862 | 856 | ||
| 863 | static void ir_print_set_global_align(IrPrint *irp, IrInstructionSetGlobalAlign *instruction) { | 857 | static void ir_print_ptr_type_of(IrPrint *irp, IrInstructionPtrTypeOf *instruction) { |
| 864 | fprintf(irp->f, "@setGlobalAlign(%s,", buf_ptr(instruction->tld->name)); | 858 | fprintf(irp->f, "&align "); |
| 865 | ir_print_other_instruction(irp, instruction->value); | 859 | ir_print_other_instruction(irp, instruction->align_value); |
| 866 | fprintf(irp->f, ")"); | 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 | static void ir_print_set_global_section(IrPrint *irp, IrInstructionSetGlobalSection *instruction) { | 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,11 +1114,8 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) { |
| 1116 | case IrInstructionIdFrameAddress: | 1114 | case IrInstructionIdFrameAddress: |
| 1117 | ir_print_frame_address(irp, (IrInstructionFrameAddress *)instruction); | 1115 | ir_print_frame_address(irp, (IrInstructionFrameAddress *)instruction); |
| 1118 | break; | 1116 | break; |
| 1119 | case IrInstructionIdPreferredAlignOf: | 1117 | case IrInstructionIdAlignOf: |
| 1120 | ir_print_preferred_align_of(irp, (IrInstructionPreferredAlignOf *)instruction); | 1118 | ir_print_align_of(irp, (IrInstructionAlignOf *)instruction); |
| 1121 | break; | ||
| 1122 | case IrInstructionIdAbiAlignOf: | ||
| 1123 | ir_print_abi_align_of(irp, (IrInstructionAbiAlignOf *)instruction); | ||
| 1124 | break; | 1119 | break; |
| 1125 | case IrInstructionIdOverflowOp: | 1120 | case IrInstructionIdOverflowOp: |
| 1126 | ir_print_overflow_op(irp, (IrInstructionOverflowOp *)instruction); | 1121 | ir_print_overflow_op(irp, (IrInstructionOverflowOp *)instruction); |
| ... | @@ -1191,8 +1186,8 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) { | ... | @@ -1191,8 +1186,8 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) { |
| 1191 | case IrInstructionIdCanImplicitCast: | 1186 | case IrInstructionIdCanImplicitCast: |
| 1192 | ir_print_can_implicit_cast(irp, (IrInstructionCanImplicitCast *)instruction); | 1187 | ir_print_can_implicit_cast(irp, (IrInstructionCanImplicitCast *)instruction); |
| 1193 | break; | 1188 | break; |
| 1194 | case IrInstructionIdSetGlobalAlign: | 1189 | case IrInstructionIdPtrTypeOf: |
| 1195 | ir_print_set_global_align(irp, (IrInstructionSetGlobalAlign *)instruction); | 1190 | ir_print_ptr_type_of(irp, (IrInstructionPtrTypeOf *)instruction); |
| 1196 | break; | 1191 | break; |
| 1197 | case IrInstructionIdSetGlobalSection: | 1192 | case IrInstructionIdSetGlobalSection: |
| 1198 | ir_print_set_global_section(irp, (IrInstructionSetGlobalSection *)instruction); | 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,6 +710,7 @@ static TypeTableEntry *resolve_enum_decl(Context *c, const EnumDecl *enum_decl) |
| 710 | TypeTableEntry *enum_type = get_partial_container_type(c->codegen, &c->import->decls_scope->base, | 710 | TypeTableEntry *enum_type = get_partial_container_type(c->codegen, &c->import->decls_scope->base, |
| 711 | ContainerKindEnum, c->source_node, buf_ptr(full_type_name), ContainerLayoutExtern); | 711 | ContainerKindEnum, c->source_node, buf_ptr(full_type_name), ContainerLayoutExtern); |
| 712 | enum_type->data.enumeration.zero_bits_known = true; | 712 | enum_type->data.enumeration.zero_bits_known = true; |
| 713 | enum_type->data.enumeration.abi_alignment = 1; | ||
| 713 | c->enum_type_table.put(bare_name, enum_type); | 714 | c->enum_type_table.put(bare_name, enum_type); |
| 714 | c->decl_table.put(enum_decl, enum_type); | 715 | c->decl_table.put(enum_decl, enum_type); |
| 715 | replace_with_fwd_decl(c, enum_type, full_type_name); | 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,6 +742,7 @@ static TypeTableEntry *resolve_enum_decl(Context *c, const EnumDecl *enum_decl) |
| 741 | enum_type->data.enumeration.gen_field_count = 0; | 742 | enum_type->data.enumeration.gen_field_count = 0; |
| 742 | enum_type->data.enumeration.complete = true; | 743 | enum_type->data.enumeration.complete = true; |
| 743 | enum_type->data.enumeration.zero_bits_known = true; | 744 | enum_type->data.enumeration.zero_bits_known = true; |
| 745 | enum_type->data.enumeration.abi_alignment = 1; | ||
| 744 | enum_type->data.enumeration.tag_type = tag_type_entry; | 746 | enum_type->data.enumeration.tag_type = tag_type_entry; |
| 745 | 747 | ||
| 746 | enum_type->data.enumeration.src_field_count = field_count; | 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,6 +780,9 @@ static TypeTableEntry *resolve_enum_decl(Context *c, const EnumDecl *enum_decl) |
| 778 | // create llvm type for root struct | 780 | // create llvm type for root struct |
| 779 | enum_type->type_ref = tag_type_entry->type_ref; | 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 | // create debug type for tag | 786 | // create debug type for tag |
| 782 | unsigned line = c->source_node ? (c->source_node->line + 1) : 0; | 787 | unsigned line = c->source_node ? (c->source_node->line + 1) : 0; |
| 783 | uint64_t debug_size_in_bits = 8*LLVMStoreSizeOfType(c->codegen->target_data_ref, enum_type->type_ref); | 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,6 +869,7 @@ static TypeTableEntry *resolve_record_decl(Context *c, const RecordDecl *record_ |
| 864 | TypeTableEntry *struct_type = get_partial_container_type(c->codegen, &c->import->decls_scope->base, | 869 | TypeTableEntry *struct_type = get_partial_container_type(c->codegen, &c->import->decls_scope->base, |
| 865 | ContainerKindStruct, c->source_node, buf_ptr(full_type_name), ContainerLayoutExtern); | 870 | ContainerKindStruct, c->source_node, buf_ptr(full_type_name), ContainerLayoutExtern); |
| 866 | struct_type->data.structure.zero_bits_known = true; | 871 | struct_type->data.structure.zero_bits_known = true; |
| 872 | struct_type->data.structure.abi_alignment = 1; | ||
| 867 | 873 | ||
| 868 | c->struct_type_table.put(bare_name, struct_type); | 874 | c->struct_type_table.put(bare_name, struct_type); |
| 869 | c->decl_table.put(record_decl, struct_type); | 875 | c->decl_table.put(record_decl, struct_type); |
| ... | @@ -950,6 +956,8 @@ static TypeTableEntry *resolve_record_decl(Context *c, const RecordDecl *record_ | ... | @@ -950,6 +956,8 @@ static TypeTableEntry *resolve_record_decl(Context *c, const RecordDecl *record_ |
| 950 | 956 | ||
| 951 | struct_type->data.structure.gen_field_count = field_count; | 957 | struct_type->data.structure.gen_field_count = field_count; |
| 952 | struct_type->data.structure.complete = true; | 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 | uint64_t debug_size_in_bits = 8*LLVMStoreSizeOfType(c->codegen->target_data_ref, struct_type->type_ref); | 962 | uint64_t debug_size_in_bits = 8*LLVMStoreSizeOfType(c->codegen->target_data_ref, struct_type->type_ref); |
| 955 | uint64_t debug_align_in_bits = 8*LLVMABISizeOfType(c->codegen->target_data_ref, struct_type->type_ref); | 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,6 +228,7 @@ static AstNode *ast_parse_fn_proto(ParseContext *pc, size_t *token_index, bool m |
| 228 | static AstNode *ast_parse_return_expr(ParseContext *pc, size_t *token_index); | 228 | static AstNode *ast_parse_return_expr(ParseContext *pc, size_t *token_index); |
| 229 | static AstNode *ast_parse_grouped_expr(ParseContext *pc, size_t *token_index, bool mandatory); | 229 | static AstNode *ast_parse_grouped_expr(ParseContext *pc, size_t *token_index, bool mandatory); |
| 230 | static AstNode *ast_parse_container_decl(ParseContext *pc, size_t *token_index, bool mandatory); | 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 | static void ast_expect_token(ParseContext *pc, Token *token, TokenId token_id) { | 233 | static void ast_expect_token(ParseContext *pc, Token *token, TokenId token_id) { |
| 233 | if (token->id == token_id) { | 234 | if (token->id == token_id) { |
| ... | @@ -384,7 +385,7 @@ static AstNode *ast_parse_grouped_expr(ParseContext *pc, size_t *token_index, bo | ... | @@ -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 | static AstNode *ast_parse_array_type_expr(ParseContext *pc, size_t *token_index, bool mandatory) { | 390 | static AstNode *ast_parse_array_type_expr(ParseContext *pc, size_t *token_index, bool mandatory) { |
| 390 | Token *l_bracket = &pc->tokens->at(*token_index); | 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,10 +404,22 @@ static AstNode *ast_parse_array_type_expr(ParseContext *pc, size_t *token_index, |
| 403 | 404 | ||
| 404 | ast_eat_token(pc, token_index, TokenIdRBracket); | 405 | ast_eat_token(pc, token_index, TokenIdRBracket); |
| 405 | 406 | ||
| 406 | Token *const_tok = &pc->tokens->at(*token_index); | 407 | Token *token = &pc->tokens->at(*token_index); |
| 407 | if (const_tok->id == TokenIdKeywordConst) { | 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 | *token_index += 1; | 415 | *token_index += 1; |
| 409 | node->data.array_type.is_const = true; | 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 | node->data.array_type.child_type = ast_parse_type_expr(pc, token_index, true); | 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,7 +966,6 @@ static PrefixOp tok_to_prefix_op(Token *token) { |
| 953 | case TokenIdDash: return PrefixOpNegation; | 966 | case TokenIdDash: return PrefixOpNegation; |
| 954 | case TokenIdMinusPercent: return PrefixOpNegationWrap; | 967 | case TokenIdMinusPercent: return PrefixOpNegationWrap; |
| 955 | case TokenIdTilde: return PrefixOpBinNot; | 968 | case TokenIdTilde: return PrefixOpBinNot; |
| 956 | case TokenIdAmpersand: return PrefixOpAddressOf; | ||
| 957 | case TokenIdStar: return PrefixOpDereference; | 969 | case TokenIdStar: return PrefixOpDereference; |
| 958 | case TokenIdMaybe: return PrefixOpMaybe; | 970 | case TokenIdMaybe: return PrefixOpMaybe; |
| 959 | case TokenIdPercent: return PrefixOpError; | 971 | case TokenIdPercent: return PrefixOpError; |
| ... | @@ -964,12 +976,52 @@ static PrefixOp tok_to_prefix_op(Token *token) { | ... | @@ -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 | PrefixOpExpression : PrefixOp PrefixOpExpression | SuffixOpExpression | 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 | static AstNode *ast_parse_prefix_op_expr(ParseContext *pc, size_t *token_index, bool mandatory) { | 1020 | static AstNode *ast_parse_prefix_op_expr(ParseContext *pc, size_t *token_index, bool mandatory) { |
| 972 | Token *token = &pc->tokens->at(*token_index); | 1021 | Token *token = &pc->tokens->at(*token_index); |
| 1022 | if (token->id == TokenIdAmpersand) { | ||
| 1023 | return ast_parse_addr_of(pc, token_index); | ||
| 1024 | } | ||
| 973 | PrefixOp prefix_op = tok_to_prefix_op(token); | 1025 | PrefixOp prefix_op = tok_to_prefix_op(token); |
| 974 | if (prefix_op == PrefixOpInvalid) { | 1026 | if (prefix_op == PrefixOpInvalid) { |
| 975 | return ast_parse_suffix_op_expr(pc, token_index, mandatory); | 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,23 +1049,6 @@ static AstNode *ast_parse_prefix_op_expr(ParseContext *pc, size_t *token_index, |
| 997 | node->column += 1; | 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 | AstNode *prefix_op_expr = ast_parse_prefix_op_expr(pc, token_index, true); | 1052 | AstNode *prefix_op_expr = ast_parse_prefix_op_expr(pc, token_index, true); |
| 1018 | node->data.prefix_op_expr.primary_expr = prefix_op_expr; | 1053 | node->data.prefix_op_expr.primary_expr = prefix_op_expr; |
| 1019 | node->data.prefix_op_expr.prefix_op = prefix_op; | 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,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 | static AstNode *ast_parse_variable_declaration_expr(ParseContext *pc, size_t *token_index, bool mandatory, | 1539 | static AstNode *ast_parse_variable_declaration_expr(ParseContext *pc, size_t *token_index, bool mandatory, |
| 1505 | VisibMod visib_mod) | 1540 | VisibMod visib_mod) |
| ... | @@ -1549,25 +1584,28 @@ static AstNode *ast_parse_variable_declaration_expr(ParseContext *pc, size_t *to | ... | @@ -1549,25 +1584,28 @@ static AstNode *ast_parse_variable_declaration_expr(ParseContext *pc, size_t *to |
| 1549 | Token *name_token = ast_eat_token(pc, token_index, TokenIdSymbol); | 1584 | Token *name_token = ast_eat_token(pc, token_index, TokenIdSymbol); |
| 1550 | node->data.variable_declaration.symbol = token_buf(name_token); | 1585 | node->data.variable_declaration.symbol = token_buf(name_token); |
| 1551 | 1586 | ||
| 1552 | Token *eq_or_colon = &pc->tokens->at(*token_index); | 1587 | Token *next_token = &pc->tokens->at(*token_index); |
| 1553 | *token_index += 1; | 1588 | |
| 1554 | if (eq_or_colon->id == TokenIdEq) { | 1589 | if (next_token->id == TokenIdColon) { |
| 1555 | node->data.variable_declaration.expr = ast_parse_expression(pc, token_index, true); | 1590 | *token_index += 1; |
| 1556 | } else if (eq_or_colon->id == TokenIdColon) { | ||
| 1557 | node->data.variable_declaration.type = ast_parse_type_expr(pc, token_index, true); | 1591 | node->data.variable_declaration.type = ast_parse_type_expr(pc, token_index, true); |
| 1558 | Token *eq_token = &pc->tokens->at(*token_index); | 1592 | next_token = &pc->tokens->at(*token_index); |
| 1559 | if (eq_token->id == TokenIdEq) { | 1593 | } |
| 1560 | *token_index += 1; | ||
| 1561 | 1594 | ||
| 1562 | node->data.variable_declaration.expr = ast_parse_expression(pc, token_index, true); | 1595 | if (next_token->id == TokenIdKeywordAlign) { |
| 1563 | } | 1596 | *token_index += 1; |
| 1564 | } else { | 1597 | node->data.variable_declaration.align_expr = ast_parse_primary_expr(pc, token_index, true); |
| 1565 | ast_invalid_token_error(pc, eq_or_colon); | 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 | // peek ahead and ensure that all variable declarations are followed by a semicolon | 1607 | // peek ahead and ensure that all variable declarations are followed by a semicolon |
| 1569 | Token *semicolon_token = &pc->tokens->at(*token_index); | 1608 | ast_expect_token(pc, next_token, TokenIdSemicolon); |
| 1570 | ast_expect_token(pc, semicolon_token, TokenIdSemicolon); | ||
| 1571 | 1609 | ||
| 1572 | return node; | 1610 | return node; |
| 1573 | } | 1611 | } |
| ... | @@ -2165,7 +2203,7 @@ static AstNode *ast_parse_block(ParseContext *pc, size_t *token_index, bool mand | ... | @@ -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 | static AstNode *ast_parse_fn_proto(ParseContext *pc, size_t *token_index, bool mandatory, VisibMod visib_mod) { | 2208 | static AstNode *ast_parse_fn_proto(ParseContext *pc, size_t *token_index, bool mandatory, VisibMod visib_mod) { |
| 2171 | Token *first_token = &pc->tokens->at(*token_index); | 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,6 +2238,7 @@ static AstNode *ast_parse_fn_proto(ParseContext *pc, size_t *token_index, bool m |
| 2200 | node->data.fn_proto.cc = cc; | 2238 | node->data.fn_proto.cc = cc; |
| 2201 | 2239 | ||
| 2202 | Token *fn_name = &pc->tokens->at(*token_index); | 2240 | Token *fn_name = &pc->tokens->at(*token_index); |
| 2241 | |||
| 2203 | if (fn_name->id == TokenIdSymbol) { | 2242 | if (fn_name->id == TokenIdSymbol) { |
| 2204 | *token_index += 1; | 2243 | *token_index += 1; |
| 2205 | node->data.fn_proto.name = token_buf(fn_name); | 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,6 +2249,12 @@ static AstNode *ast_parse_fn_proto(ParseContext *pc, size_t *token_index, bool m |
| 2210 | ast_parse_param_decl_list(pc, token_index, &node->data.fn_proto.params, &node->data.fn_proto.is_var_args); | 2249 | ast_parse_param_decl_list(pc, token_index, &node->data.fn_proto.params, &node->data.fn_proto.is_var_args); |
| 2211 | 2250 | ||
| 2212 | Token *next_token = &pc->tokens->at(*token_index); | 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 | if (next_token->id == TokenIdArrow) { | 2258 | if (next_token->id == TokenIdArrow) { |
| 2214 | *token_index += 1; | 2259 | *token_index += 1; |
| 2215 | node->data.fn_proto.return_type = ast_parse_type_expr(pc, token_index, false); | 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,6 +2640,7 @@ void ast_visit_node_children(AstNode *node, void (*visit)(AstNode **, void *cont |
| 2595 | case NodeTypeFnProto: | 2640 | case NodeTypeFnProto: |
| 2596 | visit_field(&node->data.fn_proto.return_type, visit, context); | 2641 | visit_field(&node->data.fn_proto.return_type, visit, context); |
| 2597 | visit_node_list(&node->data.fn_proto.params, visit, context); | 2642 | visit_node_list(&node->data.fn_proto.params, visit, context); |
| 2643 | visit_field(&node->data.fn_proto.align_expr, visit, context); | ||
| 2598 | break; | 2644 | break; |
| 2599 | case NodeTypeFnDef: | 2645 | case NodeTypeFnDef: |
| 2600 | visit_field(&node->data.fn_def.fn_proto, visit, context); | 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,6 +2667,7 @@ void ast_visit_node_children(AstNode *node, void (*visit)(AstNode **, void *cont |
| 2621 | case NodeTypeVariableDeclaration: | 2667 | case NodeTypeVariableDeclaration: |
| 2622 | visit_field(&node->data.variable_declaration.type, visit, context); | 2668 | visit_field(&node->data.variable_declaration.type, visit, context); |
| 2623 | visit_field(&node->data.variable_declaration.expr, visit, context); | 2669 | visit_field(&node->data.variable_declaration.expr, visit, context); |
| 2670 | visit_field(&node->data.variable_declaration.align_expr, visit, context); | ||
| 2624 | break; | 2671 | break; |
| 2625 | case NodeTypeErrorValueDecl: | 2672 | case NodeTypeErrorValueDecl: |
| 2626 | // none | 2673 | // none |
| ... | @@ -2769,6 +2816,7 @@ void ast_visit_node_children(AstNode *node, void (*visit)(AstNode **, void *cont | ... | @@ -2769,6 +2816,7 @@ void ast_visit_node_children(AstNode *node, void (*visit)(AstNode **, void *cont |
| 2769 | case NodeTypeArrayType: | 2816 | case NodeTypeArrayType: |
| 2770 | visit_field(&node->data.array_type.size, visit, context); | 2817 | visit_field(&node->data.array_type.size, visit, context); |
| 2771 | visit_field(&node->data.array_type.child_type, visit, context); | 2818 | visit_field(&node->data.array_type.child_type, visit, context); |
| 2819 | visit_field(&node->data.array_type.align_expr, visit, context); | ||
| 2772 | break; | 2820 | break; |
| 2773 | case NodeTypeErrorType: | 2821 | case NodeTypeErrorType: |
| 2774 | // none | 2822 | // none |
| ... | @@ -2776,5 +2824,9 @@ void ast_visit_node_children(AstNode *node, void (*visit)(AstNode **, void *cont | ... | @@ -2776,5 +2824,9 @@ void ast_visit_node_children(AstNode *node, void (*visit)(AstNode **, void *cont |
| 2776 | case NodeTypeVarLiteral: | 2824 | case NodeTypeVarLiteral: |
| 2777 | // none | 2825 | // none |
| 2778 | break; | 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,6 +107,7 @@ struct ZigKeyword { |
| 107 | }; | 107 | }; |
| 108 | 108 | ||
| 109 | static const struct ZigKeyword zig_keywords[] = { | 109 | static const struct ZigKeyword zig_keywords[] = { |
| 110 | {"align", TokenIdKeywordAlign}, | ||
| 110 | {"and", TokenIdKeywordAnd}, | 111 | {"and", TokenIdKeywordAnd}, |
| 111 | {"asm", TokenIdKeywordAsm}, | 112 | {"asm", TokenIdKeywordAsm}, |
| 112 | {"break", TokenIdKeywordBreak}, | 113 | {"break", TokenIdKeywordBreak}, |
| ... | @@ -1454,6 +1455,7 @@ const char * token_name(TokenId id) { | ... | @@ -1454,6 +1455,7 @@ const char * token_name(TokenId id) { |
| 1454 | case TokenIdFatArrow: return "=>"; | 1455 | case TokenIdFatArrow: return "=>"; |
| 1455 | case TokenIdFloatLiteral: return "FloatLiteral"; | 1456 | case TokenIdFloatLiteral: return "FloatLiteral"; |
| 1456 | case TokenIdIntLiteral: return "IntLiteral"; | 1457 | case TokenIdIntLiteral: return "IntLiteral"; |
| 1458 | case TokenIdKeywordAlign: return "align"; | ||
| 1457 | case TokenIdKeywordAnd: return "and"; | 1459 | case TokenIdKeywordAnd: return "and"; |
| 1458 | case TokenIdKeywordAsm: return "asm"; | 1460 | case TokenIdKeywordAsm: return "asm"; |
| 1459 | case TokenIdKeywordBreak: return "break"; | 1461 | case TokenIdKeywordBreak: return "break"; |
src/tokenizer.hpp+1| ... | @@ -46,6 +46,7 @@ enum TokenId { | ... | @@ -46,6 +46,7 @@ enum TokenId { |
| 46 | TokenIdFatArrow, | 46 | TokenIdFatArrow, |
| 47 | TokenIdFloatLiteral, | 47 | TokenIdFloatLiteral, |
| 48 | TokenIdIntLiteral, | 48 | TokenIdIntLiteral, |
| 49 | TokenIdKeywordAlign, | ||
| 49 | TokenIdKeywordAnd, | 50 | TokenIdKeywordAnd, |
| 50 | TokenIdKeywordAsm, | 51 | TokenIdKeywordAsm, |
| 51 | TokenIdKeywordBreak, | 52 | TokenIdKeywordBreak, |
src/zig_llvm.cpp-5| ... | @@ -713,11 +713,6 @@ void ZigLLVMAddModuleDebugInfoFlag(LLVMModuleRef module) { | ... | @@ -713,11 +713,6 @@ void ZigLLVMAddModuleDebugInfoFlag(LLVMModuleRef module) { |
| 713 | unwrap(module)->addModuleFlag(Module::Warning, "Debug Info Version", DEBUG_METADATA_VERSION); | 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 | static AtomicOrdering mapFromLLVMOrdering(LLVMAtomicOrdering Ordering) { | 716 | static AtomicOrdering mapFromLLVMOrdering(LLVMAtomicOrdering Ordering) { |
| 722 | switch (Ordering) { | 717 | switch (Ordering) { |
| 723 | case LLVMAtomicOrderingNotAtomic: return AtomicOrdering::NotAtomic; | 718 | case LLVMAtomicOrderingNotAtomic: return AtomicOrdering::NotAtomic; |
src/zig_llvm.hpp-2| ... | @@ -167,8 +167,6 @@ void ZigLLVMSetFastMath(LLVMBuilderRef builder_wrapped, bool on_state); | ... | @@ -167,8 +167,6 @@ void ZigLLVMSetFastMath(LLVMBuilderRef builder_wrapped, bool on_state); |
| 167 | void ZigLLVMAddFunctionAttr(LLVMValueRef fn, const char *attr_name, const char *attr_value); | 167 | void ZigLLVMAddFunctionAttr(LLVMValueRef fn, const char *attr_name, const char *attr_value); |
| 168 | void ZigLLVMAddFunctionAttrCold(LLVMValueRef fn); | 168 | void ZigLLVMAddFunctionAttrCold(LLVMValueRef fn); |
| 169 | 169 | ||
| 170 | unsigned ZigLLVMGetPrefTypeAlignment(LLVMTargetDataRef TD, LLVMTypeRef Ty); | ||
| 171 | |||
| 172 | 170 | ||
| 173 | // copied from include/llvm/ADT/Triple.h | 171 | // copied from include/llvm/ADT/Triple.h |
| 174 | 172 |
std/hash_map.zig+1-1| ... | @@ -251,7 +251,7 @@ test "basicHashMapTest" { | ... | @@ -251,7 +251,7 @@ test "basicHashMapTest" { |
| 251 | } | 251 | } |
| 252 | 252 | ||
| 253 | fn hash_i32(x: i32) -> u32 { | 253 | fn hash_i32(x: i32) -> u32 { |
| 254 | *@ptrCast(&u32, &x) | 254 | @bitCast(u32, x) |
| 255 | } | 255 | } |
| 256 | 256 | ||
| 257 | fn eql_i32(a: i32, b: i32) -> bool { | 257 | fn eql_i32(a: i32, b: i32) -> bool { |
std/mem.zig+1-4| ... | @@ -21,10 +21,7 @@ pub const Allocator = struct { | ... | @@ -21,10 +21,7 @@ pub const Allocator = struct { |
| 21 | 21 | ||
| 22 | /// Aborts the program if an allocation fails. | 22 | /// Aborts the program if an allocation fails. |
| 23 | fn checkedAlloc(self: &Allocator, comptime T: type, n: usize) -> []T { | 23 | fn checkedAlloc(self: &Allocator, comptime T: type, n: usize) -> []T { |
| 24 | alloc(self, T, n) %% |err| { | 24 | alloc(self, T, n) %% |err| debug.panic("allocation failure: {}", @errorName(err)) |
| 25 | %%io.stderr.printf("allocation failure: {}\n", @errorName(err)); | ||
| 26 | os.abort() | ||
| 27 | } | ||
| 28 | } | 25 | } |
| 29 | 26 | ||
| 30 | fn create(self: &Allocator, comptime T: type) -> %&T { | 27 | fn create(self: &Allocator, comptime T: type) -> %&T { |
test/cases/alignof.zig+3-6| ... | @@ -3,12 +3,9 @@ const builtin = @import("builtin"); | ... | @@ -3,12 +3,9 @@ const builtin = @import("builtin"); |
| 3 | 3 | ||
| 4 | const Foo = struct { x: u32, y: u32, z: u32, }; | 4 | const Foo = struct { x: u32, y: u32, z: u32, }; |
| 5 | 5 | ||
| 6 | test "@abiAlignOf(T) before referencing T" { | 6 | test "@alignOf(T) before referencing T" { |
| 7 | comptime assert(@cAbiAlignOf(Foo) != @maxValue(usize)); | 7 | comptime assert(@alignOf(Foo) != @maxValue(usize)); |
| 8 | if (builtin.arch == builtin.Arch.x86_64) { | 8 | if (builtin.arch == builtin.Arch.x86_64) { |
| 9 | comptime { | 9 | comptime assert(@alignOf(Foo) == 4); |
| 10 | assert(@cAbiAlignOf(Foo) == 4); | ||
| 11 | assert(@preferredAlignOf(Foo) == 8); | ||
| 12 | } | ||
| 13 | } | 10 | } |
| 14 | } | 11 | } |
test/cases/enum.zig+2-2| ... | @@ -124,8 +124,8 @@ const BareNumber = enum { | ... | @@ -124,8 +124,8 @@ const BareNumber = enum { |
| 124 | 124 | ||
| 125 | test "enum alignment" { | 125 | test "enum alignment" { |
| 126 | comptime { | 126 | comptime { |
| 127 | assert(@cAbiAlignOf(AlignTestEnum) >= @cAbiAlignOf([9]u8)); | 127 | assert(@alignOf(AlignTestEnum) >= @alignOf([9]u8)); |
| 128 | assert(@cAbiAlignOf(AlignTestEnum) >= @cAbiAlignOf(u64)); | 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,8 +201,6 @@ test "packed struct" { |
| 201 | } | 201 | } |
| 202 | 202 | ||
| 203 | 203 | ||
| 204 | const u2 = @IntType(false, 2); | ||
| 205 | |||
| 206 | const BitField1 = packed struct { | 204 | const BitField1 = packed struct { |
| 207 | a: u3, | 205 | a: u3, |
| 208 | b: u3, | 206 | b: u3, |
test/cases/switch.zig-1| ... | @@ -172,7 +172,6 @@ test "switch handles all cases of number" { | ... | @@ -172,7 +172,6 @@ test "switch handles all cases of number" { |
| 172 | comptime testSwitchHandleAllCases(); | 172 | comptime testSwitchHandleAllCases(); |
| 173 | } | 173 | } |
| 174 | 174 | ||
| 175 | const u2 = @IntType(false, 2); | ||
| 176 | fn testSwitchHandleAllCases() { | 175 | fn testSwitchHandleAllCases() { |
| 177 | assert(testSwitchHandleAllCasesExhaustive(0) == 3); | 176 | assert(testSwitchHandleAllCasesExhaustive(0) == 3); |
| 178 | assert(testSwitchHandleAllCasesExhaustive(1) == 2); | 177 | assert(testSwitchHandleAllCasesExhaustive(1) == 2); |
test/compile_errors.zig+9-28| ... | @@ -1316,13 +1316,15 @@ pub fn addCases(cases: &tests.CompileErrorContext) { | ... | @@ -1316,13 +1316,15 @@ pub fn addCases(cases: &tests.CompileErrorContext) { |
| 1316 | \\} | 1316 | \\} |
| 1317 | , ".tmp_source.zig:2:24: error: integer value 753664 cannot be implicitly casted to type 'u16'"); | 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", | 1319 | cases.add("global variable alignment non power of 2", |
| 1320 | \\const some_data: [100]u8 = undefined; | 1320 | \\const some_data: [100]u8 align 3 = undefined; |
| 1321 | \\comptime { | ||
| 1322 | \\ @setGlobalAlign(some_data, 3); | ||
| 1323 | \\} | ||
| 1324 | \\export fn entry() -> usize { @sizeOf(@typeOf(some_data)) } | 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 | cases.add("compile log", | 1329 | cases.add("compile log", |
| 1328 | \\export fn foo() { | 1330 | \\export fn foo() { |
| ... | @@ -1342,9 +1344,6 @@ pub fn addCases(cases: &tests.CompileErrorContext) { | ... | @@ -1342,9 +1344,6 @@ pub fn addCases(cases: &tests.CompileErrorContext) { |
| 1342 | ".tmp_source.zig:2:17: note: called from here"); | 1344 | ".tmp_source.zig:2:17: note: called from here"); |
| 1343 | 1345 | ||
| 1344 | cases.add("casting bit offset pointer to regular pointer", | 1346 | cases.add("casting bit offset pointer to regular pointer", |
| 1345 | \\const u2 = @IntType(false, 2); | ||
| 1346 | \\const u3 = @IntType(false, 3); | ||
| 1347 | \\ | ||
| 1348 | \\const BitField = packed struct { | 1347 | \\const BitField = packed struct { |
| 1349 | \\ a: u3, | 1348 | \\ a: u3, |
| 1350 | \\ b: u3, | 1349 | \\ b: u3, |
| ... | @@ -1360,7 +1359,7 @@ pub fn addCases(cases: &tests.CompileErrorContext) { | ... | @@ -1360,7 +1359,7 @@ pub fn addCases(cases: &tests.CompileErrorContext) { |
| 1360 | \\} | 1359 | \\} |
| 1361 | \\ | 1360 | \\ |
| 1362 | \\export fn entry() -> usize { @sizeOf(@typeOf(foo)) } | 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 | cases.add("referring to a struct that is invalid", | 1364 | cases.add("referring to a struct that is invalid", |
| 1366 | \\const UsbDeviceRequest = struct { | 1365 | \\const UsbDeviceRequest = struct { |
| ... | @@ -1626,24 +1625,6 @@ pub fn addCases(cases: &tests.CompileErrorContext) { | ... | @@ -1626,24 +1625,6 @@ pub fn addCases(cases: &tests.CompileErrorContext) { |
| 1626 | "error: 'main' is private", | 1625 | "error: 'main' is private", |
| 1627 | ".tmp_source.zig:1:1: note: declared here"); | 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 | cases.add("@setGlobalSection extern variable", | 1628 | cases.add("@setGlobalSection extern variable", |
| 1648 | \\extern var foo: i32; | 1629 | \\extern var foo: i32; |
| 1649 | \\comptime { | 1630 | \\comptime { |