authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2017-08-29 07:30:22-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2017-08-29 07:51:34-04:00
logc5c9d98065890eaeb9070cba20e5a1ed48b392af
tree46ad520853066174a22ad5eb6e3ac81e51f11d16
parentb8ed0cb3741533e036ee05faa165d2f0c49064f4

introduce align keyword

* 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 #37

20 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;
304304
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 declaration415 // 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};
419420
420struct AstNodeFnDef {421struct 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 declaration472 // 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};
474477
475struct AstNodeErrorValueDecl {478struct 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};
597596
597struct 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
606struct AstNodeArrayType {
607 AstNode *size;
608 AstNode *child_type;
609 AstNode *align_expr;
610 bool is_const;
611 bool is_volatile;
612};
613
598struct AstNodeUse {614struct 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};
808824
809825
810struct AstNodeArrayType {
811 AstNode *size;
812 AstNode *child_type;
813 bool is_const;
814};
815
816struct AstNodeErrorType {826struct AstNodeErrorType {
817};827};
818828
...@@ -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};
917930
918struct TypeTableEntryInt {931struct TypeTableEntryInt {
...@@ -958,6 +971,7 @@ struct TypeTableEntryStruct {...@@ -958,6 +971,7 @@ struct TypeTableEntryStruct {
958971
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};
962976
963struct TypeTableEntryMaybe {977struct TypeTableEntryMaybe {
...@@ -989,6 +1003,7 @@ struct TypeTableEntryEnum {...@@ -989,6 +1003,7 @@ struct TypeTableEntryEnum {
9891003
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
9921007
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 {
11011116
1102 // use these fields to make sure we don't duplicate type table entries for the same type1117 // 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;
11671182
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;
11731188
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 {
13921404
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 {
15471559
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};
15511565
1552enum VarLinkage {1566enum 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};
15791594
1580struct ErrorTableEntry {1595struct 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};
18451859
1846struct IrInstruction {1860struct IrInstruction {
...@@ -1976,6 +1990,7 @@ struct IrInstructionDeclVar {...@@ -1976,6 +1990,7 @@ struct IrInstructionDeclVar {
19761990
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};
19811996
...@@ -2152,7 +2167,9 @@ struct IrInstructionArrayType {...@@ -2152,7 +2167,9 @@ struct IrInstructionArrayType {
2152struct IrInstructionSliceType {2167struct IrInstructionSliceType {
2153 IrInstruction base;2168 IrInstruction base;
21542169
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};
21582175
...@@ -2393,13 +2410,7 @@ struct IrInstructionOverflowOp {...@@ -2393,13 +2410,7 @@ struct IrInstructionOverflowOp {
2393 TypeTableEntry *result_ptr_type;2410 TypeTableEntry *result_ptr_type;
2394};2411};
23952412
2396struct IrInstructionPreferredAlignOf {2413struct IrInstructionAlignOf {
2397 IrInstruction base;
2398
2399 IrInstruction *type_value;
2400};
2401
2402struct IrInstructionAbiAlignOf {
2403 IrInstruction base;2414 IrInstruction base;
24042415
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};
25562567
2557struct IrInstructionSetGlobalAlign {
2558 IrInstruction base;
2559
2560 Tld *tld;
2561 IrInstruction *value;
2562};
2563
2564struct IrInstructionSetGlobalSection {2568struct IrInstructionSetGlobalSection {
2565 IrInstruction base;2569 IrInstruction base;
25662570
...@@ -2622,6 +2626,17 @@ struct IrInstructionSetEvalBranchQuota {...@@ -2622,6 +2626,17 @@ struct IrInstructionSetEvalBranchQuota {
2622 IrInstruction *new_quota;2626 IrInstruction *new_quota;
2623};2627};
26242628
2629struct 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
2625static const size_t slice_ptr_index = 0;2640static const size_t slice_ptr_index = 0;
2626static const size_t slice_len_index = 1;2641static const size_t slice_len_index = 1;
26272642
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}
321321
322TypeTableEntry *get_pointer_to_type_extra(CodeGen *g, TypeTableEntry *child_type, bool is_const,322TypeTableEntry *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);
326326
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;
336340
...@@ -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 }
361368
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);
365372
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);
368381
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 }
377392
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;
383399
...@@ -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}
391407
392TypeTableEntry *get_pointer_to_type(CodeGen *g, TypeTableEntry *child_type, bool is_const) {408TypeTableEntry *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}
395411
396TypeTableEntry *get_maybe_type(CodeGen *g, TypeTableEntry *child_type) {412TypeTableEntry *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}
594610
595static void slice_type_common_init(CodeGen *g, TypeTableEntry *child_type,611static 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;
614626
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}
622634
623TypeTableEntry *get_slice_type(CodeGen *g, TypeTableEntry *child_type, bool is_const) {635TypeTableEntry *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)];
626637
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;
633642
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;
636645
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);
638649
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;
643665
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
649671 // 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 ref672 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);
659681 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 }
664689
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));
667691
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));
669694
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);
672701
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);
679707
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);
712712
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 }
757715
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, "");
758729
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;
761732
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}
766789
767TypeTableEntry *get_opaque_type(CodeGen *g, Scope *scope, AstNode *source_node, const char *name) {790TypeTableEntry *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;
12741297
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);
12771300
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);
12801303
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);
12881311
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);
12901313
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;
13081329
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);
13101331
1311 if (most_aligned_union_member) {1332 if (most_aligned_union_member) {
1312 // create llvm type for union1333 // 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;
13301351
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);
13331354
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) {
13471368
1348 // create debug type for tag1369 // 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) {
14051426
1406 // create debug type for tag1427 // 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
15221543
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);
15251547
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;
16641686
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);
16671693
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);
17621788
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;
17641792
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) {
17821810
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 }
17861819
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}
17921830
1793static void resolve_struct_zero_bits(CodeGen *g, TypeTableEntry *struct_type) {1831static 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;
17981836
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 }
18031853
...@@ -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;
18351885
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}
19482010
2011static 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
1949static void resolve_decl_fn(CodeGen *g, TldFn *tld_fn) {2030static 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 }
19842065
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);
19872078
...@@ -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}
21532245
2154void scan_decls(CodeGen *g, ScopeDecls *decls_scope, AstNode *node) {2246void 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);
23342428
2335 assert(name);2429 assert(name);
23362430
...@@ -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}
23902484
2391static void resolve_decl_var(CodeGen *g, TldVar *tld_var) {2485static 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;
23932488
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 }
24032498
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;
24602553
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}
24632562
...@@ -3129,26 +3228,28 @@ void semantic_analyze(CodeGen *g) {...@@ -3129,26 +3228,28 @@ void semantic_analyze(CodeGen *g) {
31293228
3130TypeTableEntry **get_int_type_ptr(CodeGen *g, bool is_signed, uint32_t size_in_bits) {3229TypeTableEntry **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);
37253826
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);
37293832
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
4801uint32_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
4820TypeTableEntry *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
16TypeTableEntry *new_type_table_entry(TypeTableEntryId id);16TypeTableEntry *new_type_table_entry(TypeTableEntryId id);
17TypeTableEntry *get_pointer_to_type(CodeGen *g, TypeTableEntry *child_type, bool is_const);17TypeTableEntry *get_pointer_to_type(CodeGen *g, TypeTableEntry *child_type, bool is_const);
18TypeTableEntry *get_pointer_to_type_extra(CodeGen *g, TypeTableEntry *child_type, bool is_const,18TypeTableEntry *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);
20uint64_t type_size(CodeGen *g, TypeTableEntry *type_entry);20uint64_t type_size(CodeGen *g, TypeTableEntry *type_entry);
21uint64_t type_size_bits(CodeGen *g, TypeTableEntry *type_entry);21uint64_t type_size_bits(CodeGen *g, TypeTableEntry *type_entry);
22TypeTableEntry **get_int_type_ptr(CodeGen *g, bool is_signed, uint32_t size_in_bits);22TypeTableEntry **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);
26TypeTableEntry *get_fn_type(CodeGen *g, FnTypeId *fn_type_id);26TypeTableEntry *get_fn_type(CodeGen *g, FnTypeId *fn_type_id);
27TypeTableEntry *get_maybe_type(CodeGen *g, TypeTableEntry *child_type);27TypeTableEntry *get_maybe_type(CodeGen *g, TypeTableEntry *child_type);
28TypeTableEntry *get_array_type(CodeGen *g, TypeTableEntry *child_type, uint64_t array_size);28TypeTableEntry *get_array_type(CodeGen *g, TypeTableEntry *child_type, uint64_t array_size);
29TypeTableEntry *get_slice_type(CodeGen *g, TypeTableEntry *child_type, bool is_const);29TypeTableEntry *get_slice_type(CodeGen *g, TypeTableEntry *ptr_type);
30TypeTableEntry *get_partial_container_type(CodeGen *g, Scope *scope, ContainerKind kind,30TypeTableEntry *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);
32TypeTableEntry *get_smallest_unsigned_int_type(CodeGen *g, uint64_t x);32TypeTableEntry *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);
171LinkLib *add_link_lib(CodeGen *codegen, Buf *lib);171LinkLib *add_link_lib(CodeGen *codegen, Buf *lib);
172void add_link_lib_symbol(CodeGen *g, Buf *lib_name, Buf *symbol_name);172void add_link_lib_symbol(CodeGen *g, Buf *lib_name, Buf *symbol_name);
173173
174uint32_t get_abi_alignment(CodeGen *g, TypeTableEntry *type_entry);
175TypeTableEntry *get_align_amt_type(CodeGen *g);
176
174#endif177#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}
352352
353static 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
353static LLVMValueRef fn_llvm_value(CodeGen *g, FnTableEntry *fn_table_entry) {359static 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 }
454460
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}
606612
607static LLVMValueRef get_handle_value(CodeGen *g, LLVMValueRef ptr, TypeTableEntry *type, bool is_volatile) {613static 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}
659667
660static 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
677static 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
688static Buf *panic_msg_buf(PanicMsgId msg_id) {668static 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}
746726
747static void gen_panic(CodeGen *g, LLVMValueRef msg_arg) {727static 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));
810791
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));
837818
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}
10581039
1059static 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
1089static LLVMValueRef gen_assign_raw(CodeGen *g, LLVMValueRef ptr, TypeTableEntry *ptr_type,1040static 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;
10931045
1094 if (!type_has_bits(child_type))1046 if (!type_has_bits(child_type))
1095 return nullptr;1047 return nullptr;
10961048
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 }
10991078
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, "");
11231103
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,
20101991
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);
20232005
2024 // memset uninitialized memory to 0xa2006 // 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;
20552036
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);
20592040
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);
20632044
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);
21052085
...@@ -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());
26962675
2676 LLVMValueRef align_val = LLVMConstInt(LLVMInt32Type(), ptr_type->data.pointer.alignment, false);
2677
2697 LLVMValueRef params[] = {2678 LLVMValueRef params[] = {
2698 dest_ptr_casted, // dest pointer2679 dest_ptr_casted,
2699 char_val, // source pointer2680 char_val,
2700 len_val, // byte count2681 len_val,
2701 LLVMConstInt(LLVMInt32Type(), 1, false), // align in bytes2682 align_val,
2702 is_volatile,2683 is_volatile,
2703 };2684 };
27042685
...@@ -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());
27272708
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 pointer2713 dest_ptr_casted,
2730 src_ptr_casted, // source pointer2714 src_ptr_casted,
2731 len_val, // byte count2715 len_val,
2732 LLVMConstInt(LLVMInt32Type(), 1, false), // align in bytes2716 align_val,
2733 is_volatile,2717 is_volatile,
2734 };2718 };
27352719
...@@ -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);
27492732
2750 LLVMValueRef tmp_struct_ptr = instruction->tmp_ptr;2733 LLVMValueRef tmp_struct_ptr = instruction->tmp_ptr;
27512734
...@@ -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
2989static LLVMValueRef ir_render_unwrap_err_code(CodeGen *g, IrExecutable *executable, IrInstructionUnwrapErrCode *instruction) {2972static 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);
29972979
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
3006static LLVMValueRef ir_render_unwrap_err_payload(CodeGen *g, IrExecutable *executable, IrInstructionUnwrapErrPayload *instruction) {2988static 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);
30142995
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;
31243105
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}
31283110
3129static LLVMValueRef ir_render_init_enum(CodeGen *g, IrExecutable *executable, IrInstructionInitEnum *instruction) {3111static 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);
31663148
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);
31703154
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));
38443827
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) {
38563839
3857 assert(g->error_decls.length > 0);3840 assert(g->error_decls.length > 0);
38583841
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);
38613844
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}
38943877
3895static void generate_enum_name_tables(CodeGen *g) {3878static 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);
38983881
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 variable3948 // TODO ^^ make an actual global variable
3966}3949}
39673950
3968static LLVMValueRef build_alloca(CodeGen *g, TypeTableEntry *type_entry, const char *name) {3951static 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}
39733957
...@@ -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 variable4040 // TODO debug info for the extern variable
40574041
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));
40734057
4074 // TODO debug info for function pointers4058 // 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 }
41944178
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;
42084192
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);
42114195
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}
43104294
4311static const uint8_t int_sizes_in_bits[] = {4295static 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 }
49914974
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);
49944978
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
51static TypeTableEntry *ir_analyze_instruction(IrAnalyze *ira, IrInstruction *instruction);51static TypeTableEntry *ir_analyze_instruction(IrAnalyze *ira, IrInstruction *instruction);
52static IrInstruction *ir_implicit_cast(IrAnalyze *ira, IrInstruction *value, TypeTableEntry *expected_type);52static IrInstruction *ir_implicit_cast(IrAnalyze *ira, IrInstruction *value, TypeTableEntry *expected_type);
53static IrInstruction *ir_get_deref(IrAnalyze *ira, IrInstruction *source_instruction, IrInstruction *ptr);53static IrInstruction *ir_get_deref(IrAnalyze *ira, IrInstruction *source_instruction, IrInstruction *ptr);
54static ErrorMsg *exec_add_error_node(CodeGen *codegen, IrExecutable *exec, AstNode *source_node, Buf *msg);
5455
55ConstExprValue *const_ptr_pointee(CodeGen *g, ConstExprValue *const_val) {56ConstExprValue *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}
424425
425static constexpr IrInstructionId ir_instruction_id(IrInstructionPreferredAlignOf *) {426static constexpr IrInstructionId ir_instruction_id(IrInstructionAlignOf *) {
426 return IrInstructionIdPreferredAlignOf;427 return IrInstructionIdAlignOf;
427}
428
429static constexpr IrInstructionId ir_instruction_id(IrInstructionAbiAlignOf *) {
430 return IrInstructionIdAbiAlignOf;
431}428}
432429
433static constexpr IrInstructionId ir_instruction_id(IrInstructionOverflowOp *) {430static 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}
520517
521static constexpr IrInstructionId ir_instruction_id(IrInstructionSetGlobalAlign *) {
522 return IrInstructionIdSetGlobalAlign;
523}
524
525static constexpr IrInstructionId ir_instruction_id(IrInstructionSetGlobalSection *) {518static 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}
560553
554static constexpr IrInstructionId ir_instruction_id(IrInstructionPtrTypeOf *) {
555 return IrInstructionIdPtrTypeOf;
556}
557
561template<typename T>558template<typename T>
562static T *ir_create_instruction(IrBuilder *irb, Scope *scope, AstNode *source_node) {559static 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}
990987
988static 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
991static IrInstruction *ir_build_un_op(IrBuilder *irb, Scope *scope, AstNode *source_node, IrUnOp op_id, IrInstruction *value) {1006static 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}
11131128
1114static IrInstruction *ir_build_var_decl(IrBuilder *irb, Scope *scope, AstNode *source_node,1129static 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;
11231139
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);
11261143
1127 return &decl_var_instruction->base;1144 return &decl_var_instruction->base;
1128}1145}
11291146
1130static IrInstruction *ir_build_var_decl_from(IrBuilder *irb, IrInstruction *old_instruction,1147static 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}
12231240
1224static IrInstruction *ir_build_slice_type(IrBuilder *irb, Scope *scope, AstNode *source_node, bool is_const,1241static 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;
12301249
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);
12321252
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}
18121832
1813static IrInstruction *ir_build_preferred_align_of(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *type_value) {1833static 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
1822static 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;
18251836
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}
20992110
2100static 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
2113static IrInstruction *ir_build_set_global_section(IrBuilder *irb, Scope *scope, AstNode *source_node,2111static 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}
22782276
2279static IrInstruction *ir_instruction_declvar_get_dep(IrInstructionDeclVar *instruction, size_t index) {2277static 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}
22862293
2287static IrInstruction *ir_instruction_loadptr_get_dep(IrInstructionLoadPtr *instruction, size_t index) {2294static 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}
26732680
2674static IrInstruction *ir_instruction_preferredalignof_get_dep(IrInstructionPreferredAlignOf *instruction, size_t index) {2681static 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
2681static 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}
28562856
2857static 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
2864static IrInstruction *ir_instruction_setglobalsection_get_dep(IrInstructionSetGlobalSection *instruction, size_t index) {2857static 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}
29262919
2920static 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
2927static IrInstruction *ir_instruction_get_dep(IrInstruction *instruction, size_t index) {2928static 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;
43044294
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
43354325
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;
43634352
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}
46544641
4655static IrInstruction *ir_gen_address_of(IrBuilder *irb, Scope *scope, AstNode *node,4642static 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;
46604648
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 }
46644684
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}
46674688
4668static IrInstruction *ir_gen_err_assert_ok(IrBuilder *irb, Scope *scope, AstNode *node, LVal lval) {4689static 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 }
48244837
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;
48284848
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 }
48884908
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);
49264946
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);
49684988
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;
51165136
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);
51205140
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);
51385158
51395159
...@@ -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;
52575279
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 }
52635293
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
52715301
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;
52775316
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}
52815320
...@@ -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
53755414
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
54525491
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);
54785517
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 type5572 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
75697611
7570static IrInstruction *ir_get_const_ptr(IrAnalyze *ira, IrInstruction *instruction,7612static 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 }
78817925
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}
85818626
8627static 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
8582static bool ir_resolve_usize(IrAnalyze *ira, IrInstruction *value, uint64_t *out) {8654static 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;
86588730
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
97159788
9716 bool is_comptime = ir_get_var_is_comptime(var);9789 bool is_comptime = ir_get_var_is_comptime(var);
97179790
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 }
97359816
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);
97379818
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);
99019983
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
1074210835
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
1096411058
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;
1142911527
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}
1144111538
11442static 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
11505static TypeTableEntry *ir_analyze_instruction_set_global_section(IrAnalyze *ira,11539static 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,
11750static TypeTableEntry *ir_analyze_instruction_slice_type(IrAnalyze *ira,11784static 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 }
1175711792
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;
1176111796
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 above11805 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);
1201912063
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);
1203212076
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;
1288912933
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}
1293512981
...@@ -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 }
1297413020
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;
1298113032
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);
1298513037
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
1343613488
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);
1344013494
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;
1351913573
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);
1352613585
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);
1353113589
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;
1366313721
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}
1386213927
13863static TypeTableEntry *ir_analyze_instruction_preferred_align_of(IrAnalyze *ira, IrInstructionPreferredAlignOf *instruction) {13928static 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
13915static 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;
1439214406
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}
1481614831
14832static 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
14817static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstruction *instruction) {14849static 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 free15138 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}
666666
667static void ir_print_preferred_align_of(IrPrint *irp, IrInstructionPreferredAlignOf *instruction) {667static 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
673static 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}
862856
863static void ir_print_set_global_align(IrPrint *irp, IrInstructionSetGlobalAlign *instruction) {857static 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}
868866
869static void ir_print_set_global_section(IrPrint *irp, IrInstructionSetGlobalSection *instruction) {867static 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;
745747
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 struct780 // 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;
780782
783 enum_type->data.enumeration.abi_alignment = LLVMABIAlignmentOfType(c->codegen->target_data_ref,
784 enum_type->type_ref);
785
781 // create debug type for tag786 // 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;
867873
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_
950956
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);
953961
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
228static AstNode *ast_parse_return_expr(ParseContext *pc, size_t *token_index);228static AstNode *ast_parse_return_expr(ParseContext *pc, size_t *token_index);
229static AstNode *ast_parse_grouped_expr(ParseContext *pc, size_t *token_index, bool mandatory);229static AstNode *ast_parse_grouped_expr(ParseContext *pc, size_t *token_index, bool mandatory);
230static AstNode *ast_parse_container_decl(ParseContext *pc, size_t *token_index, bool mandatory);230static AstNode *ast_parse_container_decl(ParseContext *pc, size_t *token_index, bool mandatory);
231static AstNode *ast_parse_primary_expr(ParseContext *pc, size_t *token_index, bool mandatory);
231232
232static void ast_expect_token(ParseContext *pc, Token *token, TokenId token_id) {233static 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}
385386
386/*387/*
387ArrayType : "[" option(Expression) "]" option("const") PrefixOpExpression388ArrayType : "[" option(Expression) "]" option("align" PrimaryExpression)) option("const") option("volatile") PrefixOpExpression
388*/389*/
389static AstNode *ast_parse_array_type_expr(ParseContext *pc, size_t *token_index, bool mandatory) {390static 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,
403404
404 ast_eat_token(pc, token_index, TokenIdRBracket);405 ast_eat_token(pc, token_index, TokenIdRBracket);
405406
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 }
411424
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}
966978
979static 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/*
968PrefixOpExpression : PrefixOp PrefixOpExpression | SuffixOpExpression1017PrefixOpExpression : PrefixOp PrefixOpExpression | SuffixOpExpression
969PrefixOp = "!" | "-" | "~" | "*" | ("&" option("const") option("volatile")) | "?" | "%" | "%%" | "??" | "-%"1018PrefixOp = "!" | "-" | "~" | "*" | ("&" option("align" PrimaryExpression option(":" Integer ":" Integer)) option("const") option("volatile")) | "?" | "%" | "%%" | "??" | "-%"
970*/1019*/
971static AstNode *ast_parse_prefix_op_expr(ParseContext *pc, size_t *token_index, bool mandatory) {1020static 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 }
9991051
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}
15001535
1501/*1536/*
1502VariableDeclaration = option("comptime") ("var" | "const") Symbol option(":" TypeExpr) "=" Expression1537VariableDeclaration = option("comptime") ("var" | "const") Symbol option(":" TypeExpr) option("align" PrimaryExpression) "=" Expression
1503*/1538*/
1504static AstNode *ast_parse_variable_declaration_expr(ParseContext *pc, size_t *token_index, bool mandatory,1539static 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);
15511586
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;
15611594
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 }
15671606
1568 // peek ahead and ensure that all variable declarations are followed by a semicolon1607 // 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);
15711609
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}
21662204
2167/*2205/*
2168FnProto = option("coldcc" | "nakedcc" | "stdcallcc") "fn" option(Symbol) ParamDeclList option("->" TypeExpr)2206FnProto = option("coldcc" | "nakedcc" | "stdcallcc") "fn" option(Symbol) ParamDeclList option("align" PrimaryExpression) option("->" TypeExpr)
2169*/2207*/
2170static AstNode *ast_parse_fn_proto(ParseContext *pc, size_t *token_index, bool mandatory, VisibMod visib_mod) {2208static 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;
22012239
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);
22112250
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 // none2673 // 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 // none2822 // 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 // none2825 // 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};
108108
109static const struct ZigKeyword zig_keywords[] = {109static 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}
715715
716unsigned ZigLLVMGetPrefTypeAlignment(LLVMTargetDataRef TD, LLVMTypeRef Ty) {
717 return unwrap(TD)->getPrefTypeAlignment(unwrap(Ty));
718}
719
720
721static AtomicOrdering mapFromLLVMOrdering(LLVMAtomicOrdering Ordering) {716static 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);
167void ZigLLVMAddFunctionAttr(LLVMValueRef fn, const char *attr_name, const char *attr_value);167void ZigLLVMAddFunctionAttr(LLVMValueRef fn, const char *attr_name, const char *attr_value);
168void ZigLLVMAddFunctionAttrCold(LLVMValueRef fn);168void ZigLLVMAddFunctionAttrCold(LLVMValueRef fn);
169169
170unsigned ZigLLVMGetPrefTypeAlignment(LLVMTargetDataRef TD, LLVMTypeRef Ty);
171
172170
173// copied from include/llvm/ADT/Triple.h171// copied from include/llvm/ADT/Triple.h
174172
std/hash_map.zig+1-1
...@@ -251,7 +251,7 @@ test "basicHashMapTest" {...@@ -251,7 +251,7 @@ test "basicHashMapTest" {
251}251}
252252
253fn hash_i32(x: i32) -> u32 {253fn hash_i32(x: i32) -> u32 {
254 *@ptrCast(&u32, &x)254 @bitCast(u32, x)
255}255}
256256
257fn eql_i32(a: i32, b: i32) -> bool {257fn 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 {
2121
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 }
2926
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");
33
4const Foo = struct { x: u32, y: u32, z: u32, };4const Foo = struct { x: u32, y: u32, z: u32, };
55
6test "@abiAlignOf(T) before referencing T" {6test "@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 {
124124
125test "enum alignment" {125test "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}
131131
test/cases/struct.zig-2
...@@ -201,8 +201,6 @@ test "packed struct" {...@@ -201,8 +201,6 @@ test "packed struct" {
201}201}
202202
203203
204const u2 = @IntType(false, 2);
205
206const BitField1 = packed struct {204const 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}
174174
175const u2 = @IntType(false, 2);
176fn testSwitchHandleAllCases() {175fn 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'");
13181318
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");
13261328
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");
13431345
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'");
13641363
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");
16281627
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 {