| author | |
| committer | |
| log | f8b914fcf328b30f98d31bb6461c953e4b7a33a7 |
| tree | 06b74c36e25e94c1a8a5e384d289ffd556fdd4a9 |
| parent | abc30f79489b68f6dc0ee4b408c63a8e783215d1 |
| parent | 619260d94d68bdecdac649fa7b156dc8962a9889 |
There were two things to resolve here:
* Snektron's branch edited Zir printing, but in master branch
I moved the printing code from Zir.zig to print_zir.zig. So that
just had to be moved over.
* In master branch I fleshed out coerceInMemory a bit more, which
caused one of Snektron's test cases to fail, so I had to add
addrspace awareness to that. Once I did that the tests passed again.33 files changed, 1173 insertions(+), 220 deletions(-)
doc/docgen.zig+1| ... | ... | @@ -901,6 +901,7 @@ fn tokenizeAndPrintRaw( |
| 901 | 901 | switch (token.tag) { |
| 902 | 902 | .eof => break, |
| 903 | 903 | |
| 904 | .keyword_addrspace, | |
| 904 | 905 | .keyword_align, |
| 905 | 906 | .keyword_and, |
| 906 | 907 | .keyword_asm, |
lib/std/builtin.zig+10| ... | ... | @@ -166,6 +166,15 @@ pub const CallingConvention = enum { |
| 166 | 166 | SysV, |
| 167 | 167 | }; |
| 168 | 168 | |
| 169 | /// This data structure is used by the Zig language code generation and | |
| 170 | /// therefore must be kept in sync with the compiler implementation. | |
| 171 | pub const AddressSpace = enum { | |
| 172 | generic, | |
| 173 | gs, | |
| 174 | fs, | |
| 175 | ss, | |
| 176 | }; | |
| 177 | ||
| 169 | 178 | /// This data structure is used by the Zig language code generation and |
| 170 | 179 | /// therefore must be kept in sync with the compiler implementation. |
| 171 | 180 | pub const SourceLocation = struct { |
| ... | ... | @@ -226,6 +235,7 @@ pub const TypeInfo = union(enum) { |
| 226 | 235 | is_const: bool, |
| 227 | 236 | is_volatile: bool, |
| 228 | 237 | alignment: comptime_int, |
| 238 | address_space: AddressSpace, | |
| 229 | 239 | child: type, |
| 230 | 240 | is_allowzero: bool, |
| 231 | 241 |
lib/std/mem.zig+2| ... | ... | @@ -2472,6 +2472,7 @@ fn CopyPtrAttrs(comptime source: type, comptime size: std.builtin.TypeInfo.Point |
| 2472 | 2472 | .is_volatile = info.is_volatile, |
| 2473 | 2473 | .is_allowzero = info.is_allowzero, |
| 2474 | 2474 | .alignment = info.alignment, |
| 2475 | .address_space = info.address_space, | |
| 2475 | 2476 | .child = child, |
| 2476 | 2477 | .sentinel = null, |
| 2477 | 2478 | }, |
| ... | ... | @@ -2960,6 +2961,7 @@ fn AlignedSlice(comptime AttributeSource: type, comptime new_alignment: u29) typ |
| 2960 | 2961 | .is_volatile = info.is_volatile, |
| 2961 | 2962 | .is_allowzero = info.is_allowzero, |
| 2962 | 2963 | .alignment = new_alignment, |
| 2964 | .address_space = info.address_space, | |
| 2963 | 2965 | .child = info.child, |
| 2964 | 2966 | .sentinel = null, |
| 2965 | 2967 | }, |
lib/std/meta.zig+3| ... | ... | @@ -235,6 +235,7 @@ pub fn Sentinel(comptime T: type, comptime sentinel_val: Elem(T)) type { |
| 235 | 235 | .is_const = info.is_const, |
| 236 | 236 | .is_volatile = info.is_volatile, |
| 237 | 237 | .alignment = info.alignment, |
| 238 | .address_space = info.address_space, | |
| 238 | 239 | .child = @Type(.{ |
| 239 | 240 | .Array = .{ |
| 240 | 241 | .len = array_info.len, |
| ... | ... | @@ -254,6 +255,7 @@ pub fn Sentinel(comptime T: type, comptime sentinel_val: Elem(T)) type { |
| 254 | 255 | .is_const = info.is_const, |
| 255 | 256 | .is_volatile = info.is_volatile, |
| 256 | 257 | .alignment = info.alignment, |
| 258 | .address_space = info.address_space, | |
| 257 | 259 | .child = info.child, |
| 258 | 260 | .is_allowzero = info.is_allowzero, |
| 259 | 261 | .sentinel = sentinel_val, |
| ... | ... | @@ -271,6 +273,7 @@ pub fn Sentinel(comptime T: type, comptime sentinel_val: Elem(T)) type { |
| 271 | 273 | .is_const = ptr_info.is_const, |
| 272 | 274 | .is_volatile = ptr_info.is_volatile, |
| 273 | 275 | .alignment = ptr_info.alignment, |
| 276 | .address_space = ptr_info.address_space, | |
| 274 | 277 | .child = ptr_info.child, |
| 275 | 278 | .is_allowzero = ptr_info.is_allowzero, |
| 276 | 279 | .sentinel = sentinel_val, |
lib/std/zig/Ast.zig+50-4| ... | ... | @@ -262,6 +262,9 @@ pub fn renderError(tree: Tree, parse_error: Error, stream: anytype) !void { |
| 262 | 262 | token_tags[parse_error.token].symbol(), |
| 263 | 263 | }); |
| 264 | 264 | }, |
| 265 | .extra_addrspace_qualifier => { | |
| 266 | return stream.writeAll("extra addrspace qualifier"); | |
| 267 | }, | |
| 265 | 268 | .extra_align_qualifier => { |
| 266 | 269 | return stream.writeAll("extra align qualifier"); |
| 267 | 270 | }, |
| ... | ... | @@ -1021,7 +1024,7 @@ pub fn lastToken(tree: Tree, node: Node.Index) TokenIndex { |
| 1021 | 1024 | }, |
| 1022 | 1025 | .fn_proto_one => { |
| 1023 | 1026 | const extra = tree.extraData(datas[n].lhs, Node.FnProtoOne); |
| 1024 | // linksection, callconv, align can appear in any order, so we | |
| 1027 | // addrspace, linksection, callconv, align can appear in any order, so we | |
| 1025 | 1028 | // find the last one here. |
| 1026 | 1029 | var max_node: Node.Index = datas[n].rhs; |
| 1027 | 1030 | var max_start = token_starts[main_tokens[max_node]]; |
| ... | ... | @@ -1034,6 +1037,14 @@ pub fn lastToken(tree: Tree, node: Node.Index) TokenIndex { |
| 1034 | 1037 | max_offset = 1; // for the rparen |
| 1035 | 1038 | } |
| 1036 | 1039 | } |
| 1040 | if (extra.addrspace_expr != 0) { | |
| 1041 | const start = token_starts[main_tokens[extra.addrspace_expr]]; | |
| 1042 | if (start > max_start) { | |
| 1043 | max_node = extra.addrspace_expr; | |
| 1044 | max_start = start; | |
| 1045 | max_offset = 1; // for the rparen | |
| 1046 | } | |
| 1047 | } | |
| 1037 | 1048 | if (extra.section_expr != 0) { |
| 1038 | 1049 | const start = token_starts[main_tokens[extra.section_expr]]; |
| 1039 | 1050 | if (start > max_start) { |
| ... | ... | @@ -1055,7 +1066,7 @@ pub fn lastToken(tree: Tree, node: Node.Index) TokenIndex { |
| 1055 | 1066 | }, |
| 1056 | 1067 | .fn_proto => { |
| 1057 | 1068 | const extra = tree.extraData(datas[n].lhs, Node.FnProto); |
| 1058 | // linksection, callconv, align can appear in any order, so we | |
| 1069 | // addrspace, linksection, callconv, align can appear in any order, so we | |
| 1059 | 1070 | // find the last one here. |
| 1060 | 1071 | var max_node: Node.Index = datas[n].rhs; |
| 1061 | 1072 | var max_start = token_starts[main_tokens[max_node]]; |
| ... | ... | @@ -1068,6 +1079,14 @@ pub fn lastToken(tree: Tree, node: Node.Index) TokenIndex { |
| 1068 | 1079 | max_offset = 1; // for the rparen |
| 1069 | 1080 | } |
| 1070 | 1081 | } |
| 1082 | if (extra.addrspace_expr != 0) { | |
| 1083 | const start = token_starts[main_tokens[extra.addrspace_expr]]; | |
| 1084 | if (start > max_start) { | |
| 1085 | max_node = extra.addrspace_expr; | |
| 1086 | max_start = start; | |
| 1087 | max_offset = 1; // for the rparen | |
| 1088 | } | |
| 1089 | } | |
| 1071 | 1090 | if (extra.section_expr != 0) { |
| 1072 | 1091 | const start = token_starts[main_tokens[extra.section_expr]]; |
| 1073 | 1092 | if (start > max_start) { |
| ... | ... | @@ -1138,6 +1157,7 @@ pub fn globalVarDecl(tree: Tree, node: Node.Index) full.VarDecl { |
| 1138 | 1157 | return tree.fullVarDecl(.{ |
| 1139 | 1158 | .type_node = extra.type_node, |
| 1140 | 1159 | .align_node = extra.align_node, |
| 1160 | .addrspace_node = extra.addrspace_node, | |
| 1141 | 1161 | .section_node = extra.section_node, |
| 1142 | 1162 | .init_node = data.rhs, |
| 1143 | 1163 | .mut_token = tree.nodes.items(.main_token)[node], |
| ... | ... | @@ -1151,6 +1171,7 @@ pub fn localVarDecl(tree: Tree, node: Node.Index) full.VarDecl { |
| 1151 | 1171 | return tree.fullVarDecl(.{ |
| 1152 | 1172 | .type_node = extra.type_node, |
| 1153 | 1173 | .align_node = extra.align_node, |
| 1174 | .addrspace_node = 0, | |
| 1154 | 1175 | .section_node = 0, |
| 1155 | 1176 | .init_node = data.rhs, |
| 1156 | 1177 | .mut_token = tree.nodes.items(.main_token)[node], |
| ... | ... | @@ -1163,6 +1184,7 @@ pub fn simpleVarDecl(tree: Tree, node: Node.Index) full.VarDecl { |
| 1163 | 1184 | return tree.fullVarDecl(.{ |
| 1164 | 1185 | .type_node = data.lhs, |
| 1165 | 1186 | .align_node = 0, |
| 1187 | .addrspace_node = 0, | |
| 1166 | 1188 | .section_node = 0, |
| 1167 | 1189 | .init_node = data.rhs, |
| 1168 | 1190 | .mut_token = tree.nodes.items(.main_token)[node], |
| ... | ... | @@ -1175,6 +1197,7 @@ pub fn alignedVarDecl(tree: Tree, node: Node.Index) full.VarDecl { |
| 1175 | 1197 | return tree.fullVarDecl(.{ |
| 1176 | 1198 | .type_node = 0, |
| 1177 | 1199 | .align_node = data.lhs, |
| 1200 | .addrspace_node = 0, | |
| 1178 | 1201 | .section_node = 0, |
| 1179 | 1202 | .init_node = data.rhs, |
| 1180 | 1203 | .mut_token = tree.nodes.items(.main_token)[node], |
| ... | ... | @@ -1249,6 +1272,7 @@ pub fn fnProtoSimple(tree: Tree, buffer: *[1]Node.Index, node: Node.Index) full. |
| 1249 | 1272 | .return_type = data.rhs, |
| 1250 | 1273 | .params = params, |
| 1251 | 1274 | .align_expr = 0, |
| 1275 | .addrspace_expr = 0, | |
| 1252 | 1276 | .section_expr = 0, |
| 1253 | 1277 | .callconv_expr = 0, |
| 1254 | 1278 | }); |
| ... | ... | @@ -1265,6 +1289,7 @@ pub fn fnProtoMulti(tree: Tree, node: Node.Index) full.FnProto { |
| 1265 | 1289 | .return_type = data.rhs, |
| 1266 | 1290 | .params = params, |
| 1267 | 1291 | .align_expr = 0, |
| 1292 | .addrspace_expr = 0, | |
| 1268 | 1293 | .section_expr = 0, |
| 1269 | 1294 | .callconv_expr = 0, |
| 1270 | 1295 | }); |
| ... | ... | @@ -1282,6 +1307,7 @@ pub fn fnProtoOne(tree: Tree, buffer: *[1]Node.Index, node: Node.Index) full.FnP |
| 1282 | 1307 | .return_type = data.rhs, |
| 1283 | 1308 | .params = params, |
| 1284 | 1309 | .align_expr = extra.align_expr, |
| 1310 | .addrspace_expr = extra.addrspace_expr, | |
| 1285 | 1311 | .section_expr = extra.section_expr, |
| 1286 | 1312 | .callconv_expr = extra.callconv_expr, |
| 1287 | 1313 | }); |
| ... | ... | @@ -1298,6 +1324,7 @@ pub fn fnProto(tree: Tree, node: Node.Index) full.FnProto { |
| 1298 | 1324 | .return_type = data.rhs, |
| 1299 | 1325 | .params = params, |
| 1300 | 1326 | .align_expr = extra.align_expr, |
| 1327 | .addrspace_expr = extra.addrspace_expr, | |
| 1301 | 1328 | .section_expr = extra.section_expr, |
| 1302 | 1329 | .callconv_expr = extra.callconv_expr, |
| 1303 | 1330 | }); |
| ... | ... | @@ -1453,6 +1480,7 @@ pub fn ptrTypeAligned(tree: Tree, node: Node.Index) full.PtrType { |
| 1453 | 1480 | return tree.fullPtrType(.{ |
| 1454 | 1481 | .main_token = tree.nodes.items(.main_token)[node], |
| 1455 | 1482 | .align_node = data.lhs, |
| 1483 | .addrspace_node = 0, | |
| 1456 | 1484 | .sentinel = 0, |
| 1457 | 1485 | .bit_range_start = 0, |
| 1458 | 1486 | .bit_range_end = 0, |
| ... | ... | @@ -1466,6 +1494,7 @@ pub fn ptrTypeSentinel(tree: Tree, node: Node.Index) full.PtrType { |
| 1466 | 1494 | return tree.fullPtrType(.{ |
| 1467 | 1495 | .main_token = tree.nodes.items(.main_token)[node], |
| 1468 | 1496 | .align_node = 0, |
| 1497 | .addrspace_node = 0, | |
| 1469 | 1498 | .sentinel = data.lhs, |
| 1470 | 1499 | .bit_range_start = 0, |
| 1471 | 1500 | .bit_range_end = 0, |
| ... | ... | @@ -1480,6 +1509,7 @@ pub fn ptrType(tree: Tree, node: Node.Index) full.PtrType { |
| 1480 | 1509 | return tree.fullPtrType(.{ |
| 1481 | 1510 | .main_token = tree.nodes.items(.main_token)[node], |
| 1482 | 1511 | .align_node = extra.align_node, |
| 1512 | .addrspace_node = extra.addrspace_node, | |
| 1483 | 1513 | .sentinel = extra.sentinel, |
| 1484 | 1514 | .bit_range_start = 0, |
| 1485 | 1515 | .bit_range_end = 0, |
| ... | ... | @@ -1494,6 +1524,7 @@ pub fn ptrTypeBitRange(tree: Tree, node: Node.Index) full.PtrType { |
| 1494 | 1524 | return tree.fullPtrType(.{ |
| 1495 | 1525 | .main_token = tree.nodes.items(.main_token)[node], |
| 1496 | 1526 | .align_node = extra.align_node, |
| 1527 | .addrspace_node = extra.addrspace_node, | |
| 1497 | 1528 | .sentinel = extra.sentinel, |
| 1498 | 1529 | .bit_range_start = extra.bit_range_start, |
| 1499 | 1530 | .bit_range_end = extra.bit_range_end, |
| ... | ... | @@ -2063,6 +2094,7 @@ pub const full = struct { |
| 2063 | 2094 | mut_token: TokenIndex, |
| 2064 | 2095 | type_node: Node.Index, |
| 2065 | 2096 | align_node: Node.Index, |
| 2097 | addrspace_node: Node.Index, | |
| 2066 | 2098 | section_node: Node.Index, |
| 2067 | 2099 | init_node: Node.Index, |
| 2068 | 2100 | }; |
| ... | ... | @@ -2130,6 +2162,7 @@ pub const full = struct { |
| 2130 | 2162 | return_type: Node.Index, |
| 2131 | 2163 | params: []const Node.Index, |
| 2132 | 2164 | align_expr: Node.Index, |
| 2165 | addrspace_expr: Node.Index, | |
| 2133 | 2166 | section_expr: Node.Index, |
| 2134 | 2167 | callconv_expr: Node.Index, |
| 2135 | 2168 | }; |
| ... | ... | @@ -2288,6 +2321,7 @@ pub const full = struct { |
| 2288 | 2321 | pub const Components = struct { |
| 2289 | 2322 | main_token: TokenIndex, |
| 2290 | 2323 | align_node: Node.Index, |
| 2324 | addrspace_node: Node.Index, | |
| 2291 | 2325 | sentinel: Node.Index, |
| 2292 | 2326 | bit_range_start: Node.Index, |
| 2293 | 2327 | bit_range_end: Node.Index, |
| ... | ... | @@ -2397,6 +2431,7 @@ pub const Error = struct { |
| 2397 | 2431 | expected_var_decl_or_fn, |
| 2398 | 2432 | expected_loop_payload, |
| 2399 | 2433 | expected_container, |
| 2434 | extra_addrspace_qualifier, | |
| 2400 | 2435 | extra_align_qualifier, |
| 2401 | 2436 | extra_allowzero_qualifier, |
| 2402 | 2437 | extra_const_qualifier, |
| ... | ... | @@ -2723,13 +2758,13 @@ pub const Node = struct { |
| 2723 | 2758 | /// main_token is the `fn` keyword. |
| 2724 | 2759 | /// extern function declarations use this tag. |
| 2725 | 2760 | fn_proto_multi, |
| 2726 | /// `fn(a: b) rhs linksection(e) callconv(f)`. `FnProtoOne[lhs]`. | |
| 2761 | /// `fn(a: b) rhs addrspace(e) linksection(f) callconv(g)`. `FnProtoOne[lhs]`. | |
| 2727 | 2762 | /// zero or one parameters. |
| 2728 | 2763 | /// anytype and ... parameters are omitted from the AST tree. |
| 2729 | 2764 | /// main_token is the `fn` keyword. |
| 2730 | 2765 | /// extern function declarations use this tag. |
| 2731 | 2766 | fn_proto_one, |
| 2732 | /// `fn(a: b, c: d) rhs linksection(e) callconv(f)`. `FnProto[lhs]`. | |
| 2767 | /// `fn(a: b, c: d) rhs addrspace(e) linksection(f) callconv(g)`. `FnProto[lhs]`. | |
| 2733 | 2768 | /// anytype and ... parameters are omitted from the AST tree. |
| 2734 | 2769 | /// main_token is the `fn` keyword. |
| 2735 | 2770 | /// extern function declarations use this tag. |
| ... | ... | @@ -2893,11 +2928,13 @@ pub const Node = struct { |
| 2893 | 2928 | pub const PtrType = struct { |
| 2894 | 2929 | sentinel: Index, |
| 2895 | 2930 | align_node: Index, |
| 2931 | addrspace_node: Index, | |
| 2896 | 2932 | }; |
| 2897 | 2933 | |
| 2898 | 2934 | pub const PtrTypeBitRange = struct { |
| 2899 | 2935 | sentinel: Index, |
| 2900 | 2936 | align_node: Index, |
| 2937 | addrspace_node: Index, | |
| 2901 | 2938 | bit_range_start: Index, |
| 2902 | 2939 | bit_range_end: Index, |
| 2903 | 2940 | }; |
| ... | ... | @@ -2920,8 +2957,13 @@ pub const Node = struct { |
| 2920 | 2957 | }; |
| 2921 | 2958 | |
| 2922 | 2959 | pub const GlobalVarDecl = struct { |
| 2960 | /// Populated if there is an explicit type ascription. | |
| 2923 | 2961 | type_node: Index, |
| 2962 | /// Populated if align(A) is present. | |
| 2924 | 2963 | align_node: Index, |
| 2964 | /// Populated if addrspace(A) is present. | |
| 2965 | addrspace_node: Index, | |
| 2966 | /// Populated if linksection(A) is present. | |
| 2925 | 2967 | section_node: Index, |
| 2926 | 2968 | }; |
| 2927 | 2969 | |
| ... | ... | @@ -2953,6 +2995,8 @@ pub const Node = struct { |
| 2953 | 2995 | param: Index, |
| 2954 | 2996 | /// Populated if align(A) is present. |
| 2955 | 2997 | align_expr: Index, |
| 2998 | /// Populated if addrspace(A) is present. | |
| 2999 | addrspace_expr: Index, | |
| 2956 | 3000 | /// Populated if linksection(A) is present. |
| 2957 | 3001 | section_expr: Index, |
| 2958 | 3002 | /// Populated if callconv(A) is present. |
| ... | ... | @@ -2964,6 +3008,8 @@ pub const Node = struct { |
| 2964 | 3008 | params_end: Index, |
| 2965 | 3009 | /// Populated if align(A) is present. |
| 2966 | 3010 | align_expr: Index, |
| 3011 | /// Populated if addrspace(A) is present. | |
| 3012 | addrspace_expr: Index, | |
| 2967 | 3013 | /// Populated if linksection(A) is present. |
| 2968 | 3014 | section_expr: Index, |
| 2969 | 3015 | /// Populated if callconv(A) is present. |
lib/std/zig/c_translation.zig+1| ... | ... | @@ -325,6 +325,7 @@ pub fn FlexibleArrayType(comptime SelfType: type, ElementType: type) type { |
| 325 | 325 | .is_const = ptr.is_const, |
| 326 | 326 | .is_volatile = ptr.is_volatile, |
| 327 | 327 | .alignment = @alignOf(ElementType), |
| 328 | .address_space = .generic, | |
| 328 | 329 | .child = ElementType, |
| 329 | 330 | .is_allowzero = true, |
| 330 | 331 | .sentinel = null, |
lib/std/zig/parse.zig+81-26| ... | ... | @@ -629,7 +629,7 @@ const Parser = struct { |
| 629 | 629 | }; |
| 630 | 630 | } |
| 631 | 631 | |
| 632 | /// FnProto <- KEYWORD_fn IDENTIFIER? LPAREN ParamDeclList RPAREN ByteAlign? LinkSection? CallConv? EXCLAMATIONMARK? TypeExpr | |
| 632 | /// FnProto <- KEYWORD_fn IDENTIFIER? LPAREN ParamDeclList RPAREN ByteAlign? AddrSpace? LinkSection? CallConv? EXCLAMATIONMARK? TypeExpr | |
| 633 | 633 | fn parseFnProto(p: *Parser) !Node.Index { |
| 634 | 634 | const fn_token = p.eatToken(.keyword_fn) orelse return null_node; |
| 635 | 635 | |
| ... | ... | @@ -639,6 +639,7 @@ const Parser = struct { |
| 639 | 639 | _ = p.eatToken(.identifier); |
| 640 | 640 | const params = try p.parseParamDeclList(); |
| 641 | 641 | const align_expr = try p.parseByteAlign(); |
| 642 | const addrspace_expr = try p.parseAddrSpace(); | |
| 642 | 643 | const section_expr = try p.parseLinkSection(); |
| 643 | 644 | const callconv_expr = try p.parseCallconv(); |
| 644 | 645 | _ = p.eatToken(.bang); |
| ... | ... | @@ -650,7 +651,7 @@ const Parser = struct { |
| 650 | 651 | try p.warn(.expected_return_type); |
| 651 | 652 | } |
| 652 | 653 | |
| 653 | if (align_expr == 0 and section_expr == 0 and callconv_expr == 0) { | |
| 654 | if (align_expr == 0 and section_expr == 0 and callconv_expr == 0 and addrspace_expr == 0) { | |
| 654 | 655 | switch (params) { |
| 655 | 656 | .zero_or_one => |param| return p.setNode(fn_proto_index, .{ |
| 656 | 657 | .tag = .fn_proto_simple, |
| ... | ... | @@ -683,6 +684,7 @@ const Parser = struct { |
| 683 | 684 | .lhs = try p.addExtra(Node.FnProtoOne{ |
| 684 | 685 | .param = param, |
| 685 | 686 | .align_expr = align_expr, |
| 687 | .addrspace_expr = addrspace_expr, | |
| 686 | 688 | .section_expr = section_expr, |
| 687 | 689 | .callconv_expr = callconv_expr, |
| 688 | 690 | }), |
| ... | ... | @@ -698,6 +700,7 @@ const Parser = struct { |
| 698 | 700 | .params_start = span.start, |
| 699 | 701 | .params_end = span.end, |
| 700 | 702 | .align_expr = align_expr, |
| 703 | .addrspace_expr = addrspace_expr, | |
| 701 | 704 | .section_expr = section_expr, |
| 702 | 705 | .callconv_expr = callconv_expr, |
| 703 | 706 | }), |
| ... | ... | @@ -708,7 +711,7 @@ const Parser = struct { |
| 708 | 711 | } |
| 709 | 712 | } |
| 710 | 713 | |
| 711 | /// VarDecl <- (KEYWORD_const / KEYWORD_var) IDENTIFIER (COLON TypeExpr)? ByteAlign? LinkSection? (EQUAL Expr)? SEMICOLON | |
| 714 | /// VarDecl <- (KEYWORD_const / KEYWORD_var) IDENTIFIER (COLON TypeExpr)? ByteAlign? AddrSpace? LinkSection? (EQUAL Expr)? SEMICOLON | |
| 712 | 715 | fn parseVarDecl(p: *Parser) !Node.Index { |
| 713 | 716 | const mut_token = p.eatToken(.keyword_const) orelse |
| 714 | 717 | p.eatToken(.keyword_var) orelse |
| ... | ... | @@ -717,9 +720,10 @@ const Parser = struct { |
| 717 | 720 | _ = try p.expectToken(.identifier); |
| 718 | 721 | const type_node: Node.Index = if (p.eatToken(.colon) == null) 0 else try p.expectTypeExpr(); |
| 719 | 722 | const align_node = try p.parseByteAlign(); |
| 723 | const addrspace_node = try p.parseAddrSpace(); | |
| 720 | 724 | const section_node = try p.parseLinkSection(); |
| 721 | 725 | const init_node: Node.Index = if (p.eatToken(.equal) == null) 0 else try p.expectExpr(); |
| 722 | if (section_node == 0) { | |
| 726 | if (section_node == 0 and addrspace_node == 0) { | |
| 723 | 727 | if (align_node == 0) { |
| 724 | 728 | return p.addNode(.{ |
| 725 | 729 | .tag = .simple_var_decl, |
| ... | ... | @@ -759,6 +763,7 @@ const Parser = struct { |
| 759 | 763 | .lhs = try p.addExtra(Node.GlobalVarDecl{ |
| 760 | 764 | .type_node = type_node, |
| 761 | 765 | .align_node = align_node, |
| 766 | .addrspace_node = addrspace_node, | |
| 762 | 767 | .section_node = section_node, |
| 763 | 768 | }), |
| 764 | 769 | .rhs = init_node, |
| ... | ... | @@ -1440,8 +1445,8 @@ const Parser = struct { |
| 1440 | 1445 | /// PrefixTypeOp |
| 1441 | 1446 | /// <- QUESTIONMARK |
| 1442 | 1447 | /// / KEYWORD_anyframe MINUSRARROW |
| 1443 | /// / SliceTypeStart (ByteAlign / KEYWORD_const / KEYWORD_volatile / KEYWORD_allowzero)* | |
| 1444 | /// / PtrTypeStart (KEYWORD_align LPAREN Expr (COLON INTEGER COLON INTEGER)? RPAREN / KEYWORD_const / KEYWORD_volatile / KEYWORD_allowzero)* | |
| 1448 | /// / SliceTypeStart (ByteAlign / AddrSpace / KEYWORD_const / KEYWORD_volatile / KEYWORD_allowzero)* | |
| 1449 | /// / PtrTypeStart (AddrSpace / KEYWORD_align LPAREN Expr (COLON INTEGER COLON INTEGER)? RPAREN / KEYWORD_const / KEYWORD_volatile / KEYWORD_allowzero)* | |
| 1445 | 1450 | /// / ArrayTypeStart |
| 1446 | 1451 | /// SliceTypeStart <- LBRACKET (COLON Expr)? RBRACKET |
| 1447 | 1452 | /// PtrTypeStart |
| ... | ... | @@ -1474,29 +1479,43 @@ const Parser = struct { |
| 1474 | 1479 | const asterisk = p.nextToken(); |
| 1475 | 1480 | const mods = try p.parsePtrModifiers(); |
| 1476 | 1481 | const elem_type = try p.expectTypeExpr(); |
| 1477 | if (mods.bit_range_start == 0) { | |
| 1482 | if (mods.bit_range_start != 0) { | |
| 1478 | 1483 | return p.addNode(.{ |
| 1479 | .tag = .ptr_type_aligned, | |
| 1484 | .tag = .ptr_type_bit_range, | |
| 1480 | 1485 | .main_token = asterisk, |
| 1481 | 1486 | .data = .{ |
| 1482 | .lhs = mods.align_node, | |
| 1487 | .lhs = try p.addExtra(Node.PtrTypeBitRange{ | |
| 1488 | .sentinel = 0, | |
| 1489 | .align_node = mods.align_node, | |
| 1490 | .addrspace_node = mods.addrspace_node, | |
| 1491 | .bit_range_start = mods.bit_range_start, | |
| 1492 | .bit_range_end = mods.bit_range_end, | |
| 1493 | }), | |
| 1483 | 1494 | .rhs = elem_type, |
| 1484 | 1495 | }, |
| 1485 | 1496 | }); |
| 1486 | } else { | |
| 1497 | } else if (mods.addrspace_node != 0) { | |
| 1487 | 1498 | return p.addNode(.{ |
| 1488 | .tag = .ptr_type_bit_range, | |
| 1499 | .tag = .ptr_type, | |
| 1489 | 1500 | .main_token = asterisk, |
| 1490 | 1501 | .data = .{ |
| 1491 | .lhs = try p.addExtra(Node.PtrTypeBitRange{ | |
| 1502 | .lhs = try p.addExtra(Node.PtrType{ | |
| 1492 | 1503 | .sentinel = 0, |
| 1493 | 1504 | .align_node = mods.align_node, |
| 1494 | .bit_range_start = mods.bit_range_start, | |
| 1495 | .bit_range_end = mods.bit_range_end, | |
| 1505 | .addrspace_node = mods.addrspace_node, | |
| 1496 | 1506 | }), |
| 1497 | 1507 | .rhs = elem_type, |
| 1498 | 1508 | }, |
| 1499 | 1509 | }); |
| 1510 | } else { | |
| 1511 | return p.addNode(.{ | |
| 1512 | .tag = .ptr_type_aligned, | |
| 1513 | .main_token = asterisk, | |
| 1514 | .data = .{ | |
| 1515 | .lhs = mods.align_node, | |
| 1516 | .rhs = elem_type, | |
| 1517 | }, | |
| 1518 | }); | |
| 1500 | 1519 | } |
| 1501 | 1520 | }, |
| 1502 | 1521 | .asterisk_asterisk => { |
| ... | ... | @@ -1504,29 +1523,43 @@ const Parser = struct { |
| 1504 | 1523 | const mods = try p.parsePtrModifiers(); |
| 1505 | 1524 | const elem_type = try p.expectTypeExpr(); |
| 1506 | 1525 | const inner: Node.Index = inner: { |
| 1507 | if (mods.bit_range_start == 0) { | |
| 1526 | if (mods.bit_range_start != 0) { | |
| 1508 | 1527 | break :inner try p.addNode(.{ |
| 1509 | .tag = .ptr_type_aligned, | |
| 1528 | .tag = .ptr_type_bit_range, | |
| 1510 | 1529 | .main_token = asterisk, |
| 1511 | 1530 | .data = .{ |
| 1512 | .lhs = mods.align_node, | |
| 1531 | .lhs = try p.addExtra(Node.PtrTypeBitRange{ | |
| 1532 | .sentinel = 0, | |
| 1533 | .align_node = mods.align_node, | |
| 1534 | .addrspace_node = mods.addrspace_node, | |
| 1535 | .bit_range_start = mods.bit_range_start, | |
| 1536 | .bit_range_end = mods.bit_range_end, | |
| 1537 | }), | |
| 1513 | 1538 | .rhs = elem_type, |
| 1514 | 1539 | }, |
| 1515 | 1540 | }); |
| 1516 | } else { | |
| 1541 | } else if (mods.addrspace_node != 0) { | |
| 1517 | 1542 | break :inner try p.addNode(.{ |
| 1518 | .tag = .ptr_type_bit_range, | |
| 1543 | .tag = .ptr_type, | |
| 1519 | 1544 | .main_token = asterisk, |
| 1520 | 1545 | .data = .{ |
| 1521 | .lhs = try p.addExtra(Node.PtrTypeBitRange{ | |
| 1546 | .lhs = try p.addExtra(Node.PtrType{ | |
| 1522 | 1547 | .sentinel = 0, |
| 1523 | 1548 | .align_node = mods.align_node, |
| 1524 | .bit_range_start = mods.bit_range_start, | |
| 1525 | .bit_range_end = mods.bit_range_end, | |
| 1549 | .addrspace_node = mods.addrspace_node, | |
| 1526 | 1550 | }), |
| 1527 | 1551 | .rhs = elem_type, |
| 1528 | 1552 | }, |
| 1529 | 1553 | }); |
| 1554 | } else { | |
| 1555 | break :inner try p.addNode(.{ | |
| 1556 | .tag = .ptr_type_aligned, | |
| 1557 | .main_token = asterisk, | |
| 1558 | .data = .{ | |
| 1559 | .lhs = mods.align_node, | |
| 1560 | .rhs = elem_type, | |
| 1561 | }, | |
| 1562 | }); | |
| 1530 | 1563 | } |
| 1531 | 1564 | }; |
| 1532 | 1565 | return p.addNode(.{ |
| ... | ... | @@ -1560,7 +1593,7 @@ const Parser = struct { |
| 1560 | 1593 | const mods = try p.parsePtrModifiers(); |
| 1561 | 1594 | const elem_type = try p.expectTypeExpr(); |
| 1562 | 1595 | if (mods.bit_range_start == 0) { |
| 1563 | if (sentinel == 0) { | |
| 1596 | if (sentinel == 0 and mods.addrspace_node == 0) { | |
| 1564 | 1597 | return p.addNode(.{ |
| 1565 | 1598 | .tag = .ptr_type_aligned, |
| 1566 | 1599 | .main_token = asterisk, |
| ... | ... | @@ -1569,7 +1602,7 @@ const Parser = struct { |
| 1569 | 1602 | .rhs = elem_type, |
| 1570 | 1603 | }, |
| 1571 | 1604 | }); |
| 1572 | } else if (mods.align_node == 0) { | |
| 1605 | } else if (mods.align_node == 0 and mods.addrspace_node == 0) { | |
| 1573 | 1606 | return p.addNode(.{ |
| 1574 | 1607 | .tag = .ptr_type_sentinel, |
| 1575 | 1608 | .main_token = asterisk, |
| ... | ... | @@ -1586,6 +1619,7 @@ const Parser = struct { |
| 1586 | 1619 | .lhs = try p.addExtra(Node.PtrType{ |
| 1587 | 1620 | .sentinel = sentinel, |
| 1588 | 1621 | .align_node = mods.align_node, |
| 1622 | .addrspace_node = mods.addrspace_node, | |
| 1589 | 1623 | }), |
| 1590 | 1624 | .rhs = elem_type, |
| 1591 | 1625 | }, |
| ... | ... | @@ -1599,6 +1633,7 @@ const Parser = struct { |
| 1599 | 1633 | .lhs = try p.addExtra(Node.PtrTypeBitRange{ |
| 1600 | 1634 | .sentinel = sentinel, |
| 1601 | 1635 | .align_node = mods.align_node, |
| 1636 | .addrspace_node = mods.addrspace_node, | |
| 1602 | 1637 | .bit_range_start = mods.bit_range_start, |
| 1603 | 1638 | .bit_range_end = mods.bit_range_end, |
| 1604 | 1639 | }), |
| ... | ... | @@ -1624,7 +1659,7 @@ const Parser = struct { |
| 1624 | 1659 | .token = p.nodes.items(.main_token)[mods.bit_range_start], |
| 1625 | 1660 | }); |
| 1626 | 1661 | } |
| 1627 | if (sentinel == 0) { | |
| 1662 | if (sentinel == 0 and mods.addrspace_node == 0) { | |
| 1628 | 1663 | return p.addNode(.{ |
| 1629 | 1664 | .tag = .ptr_type_aligned, |
| 1630 | 1665 | .main_token = lbracket, |
| ... | ... | @@ -1633,7 +1668,7 @@ const Parser = struct { |
| 1633 | 1668 | .rhs = elem_type, |
| 1634 | 1669 | }, |
| 1635 | 1670 | }); |
| 1636 | } else if (mods.align_node == 0) { | |
| 1671 | } else if (mods.align_node == 0 and mods.addrspace_node == 0) { | |
| 1637 | 1672 | return p.addNode(.{ |
| 1638 | 1673 | .tag = .ptr_type_sentinel, |
| 1639 | 1674 | .main_token = lbracket, |
| ... | ... | @@ -1650,6 +1685,7 @@ const Parser = struct { |
| 1650 | 1685 | .lhs = try p.addExtra(Node.PtrType{ |
| 1651 | 1686 | .sentinel = sentinel, |
| 1652 | 1687 | .align_node = mods.align_node, |
| 1688 | .addrspace_node = mods.addrspace_node, | |
| 1653 | 1689 | }), |
| 1654 | 1690 | .rhs = elem_type, |
| 1655 | 1691 | }, |
| ... | ... | @@ -1661,6 +1697,7 @@ const Parser = struct { |
| 1661 | 1697 | .keyword_const, |
| 1662 | 1698 | .keyword_volatile, |
| 1663 | 1699 | .keyword_allowzero, |
| 1700 | .keyword_addrspace, | |
| 1664 | 1701 | => return p.fail(.ptr_mod_on_array_child_type), |
| 1665 | 1702 | else => {}, |
| 1666 | 1703 | } |
| ... | ... | @@ -2879,6 +2916,15 @@ const Parser = struct { |
| 2879 | 2916 | return expr_node; |
| 2880 | 2917 | } |
| 2881 | 2918 | |
| 2919 | /// AddrSpace <- KEYWORD_addrspace LPAREN Expr RPAREN | |
| 2920 | fn parseAddrSpace(p: *Parser) !Node.Index { | |
| 2921 | _ = p.eatToken(.keyword_addrspace) orelse return null_node; | |
| 2922 | _ = try p.expectToken(.l_paren); | |
| 2923 | const expr_node = try p.expectExpr(); | |
| 2924 | _ = try p.expectToken(.r_paren); | |
| 2925 | return expr_node; | |
| 2926 | } | |
| 2927 | ||
| 2882 | 2928 | /// ParamDecl |
| 2883 | 2929 | /// <- (KEYWORD_noalias / KEYWORD_comptime)? (IDENTIFIER COLON)? ParamType |
| 2884 | 2930 | /// / DOT3 |
| ... | ... | @@ -3011,6 +3057,7 @@ const Parser = struct { |
| 3011 | 3057 | |
| 3012 | 3058 | const PtrModifiers = struct { |
| 3013 | 3059 | align_node: Node.Index, |
| 3060 | addrspace_node: Node.Index, | |
| 3014 | 3061 | bit_range_start: Node.Index, |
| 3015 | 3062 | bit_range_end: Node.Index, |
| 3016 | 3063 | }; |
| ... | ... | @@ -3018,12 +3065,14 @@ const Parser = struct { |
| 3018 | 3065 | fn parsePtrModifiers(p: *Parser) !PtrModifiers { |
| 3019 | 3066 | var result: PtrModifiers = .{ |
| 3020 | 3067 | .align_node = 0, |
| 3068 | .addrspace_node = 0, | |
| 3021 | 3069 | .bit_range_start = 0, |
| 3022 | 3070 | .bit_range_end = 0, |
| 3023 | 3071 | }; |
| 3024 | 3072 | var saw_const = false; |
| 3025 | 3073 | var saw_volatile = false; |
| 3026 | 3074 | var saw_allowzero = false; |
| 3075 | var saw_addrspace = false; | |
| 3027 | 3076 | while (true) { |
| 3028 | 3077 | switch (p.token_tags[p.tok_i]) { |
| 3029 | 3078 | .keyword_align => { |
| ... | ... | @@ -3063,6 +3112,12 @@ const Parser = struct { |
| 3063 | 3112 | p.tok_i += 1; |
| 3064 | 3113 | saw_allowzero = true; |
| 3065 | 3114 | }, |
| 3115 | .keyword_addrspace => { | |
| 3116 | if (saw_addrspace) { | |
| 3117 | try p.warn(.extra_addrspace_qualifier); | |
| 3118 | } | |
| 3119 | result.addrspace_node = try p.parseAddrSpace(); | |
| 3120 | }, | |
| 3066 | 3121 | else => return result, |
| 3067 | 3122 | } |
| 3068 | 3123 | } |
lib/std/zig/parser_test.zig+24-10| ... | ... | @@ -404,6 +404,10 @@ test "zig fmt: trailing comma in fn parameter list" { |
| 404 | 404 | \\pub fn f( |
| 405 | 405 | \\ a: i32, |
| 406 | 406 | \\ b: i32, |
| 407 | \\) addrspace(.generic) i32 {} | |
| 408 | \\pub fn f( | |
| 409 | \\ a: i32, | |
| 410 | \\ b: i32, | |
| 407 | 411 | \\) linksection(".text") i32 {} |
| 408 | 412 | \\pub fn f( |
| 409 | 413 | \\ a: i32, |
| ... | ... | @@ -553,8 +557,8 @@ test "zig fmt: sentinel-terminated slice type" { |
| 553 | 557 | test "zig fmt: pointer-to-one with modifiers" { |
| 554 | 558 | try testCanonical( |
| 555 | 559 | \\const x: *u32 = undefined; |
| 556 | \\const y: *allowzero align(8) const volatile u32 = undefined; | |
| 557 | \\const z: *allowzero align(8:4:2) const volatile u32 = undefined; | |
| 560 | \\const y: *allowzero align(8) addrspace(.generic) const volatile u32 = undefined; | |
| 561 | \\const z: *allowzero align(8:4:2) addrspace(.generic) const volatile u32 = undefined; | |
| 558 | 562 | \\ |
| 559 | 563 | ); |
| 560 | 564 | } |
| ... | ... | @@ -562,8 +566,8 @@ test "zig fmt: pointer-to-one with modifiers" { |
| 562 | 566 | test "zig fmt: pointer-to-many with modifiers" { |
| 563 | 567 | try testCanonical( |
| 564 | 568 | \\const x: [*]u32 = undefined; |
| 565 | \\const y: [*]allowzero align(8) const volatile u32 = undefined; | |
| 566 | \\const z: [*]allowzero align(8:4:2) const volatile u32 = undefined; | |
| 569 | \\const y: [*]allowzero align(8) addrspace(.generic) const volatile u32 = undefined; | |
| 570 | \\const z: [*]allowzero align(8:4:2) addrspace(.generic) const volatile u32 = undefined; | |
| 567 | 571 | \\ |
| 568 | 572 | ); |
| 569 | 573 | } |
| ... | ... | @@ -571,8 +575,8 @@ test "zig fmt: pointer-to-many with modifiers" { |
| 571 | 575 | test "zig fmt: sentinel pointer with modifiers" { |
| 572 | 576 | try testCanonical( |
| 573 | 577 | \\const x: [*:42]u32 = undefined; |
| 574 | \\const y: [*:42]allowzero align(8) const volatile u32 = undefined; | |
| 575 | \\const y: [*:42]allowzero align(8:4:2) const volatile u32 = undefined; | |
| 578 | \\const y: [*:42]allowzero align(8) addrspace(.generic) const volatile u32 = undefined; | |
| 579 | \\const y: [*:42]allowzero align(8:4:2) addrspace(.generic) const volatile u32 = undefined; | |
| 576 | 580 | \\ |
| 577 | 581 | ); |
| 578 | 582 | } |
| ... | ... | @@ -580,8 +584,8 @@ test "zig fmt: sentinel pointer with modifiers" { |
| 580 | 584 | test "zig fmt: c pointer with modifiers" { |
| 581 | 585 | try testCanonical( |
| 582 | 586 | \\const x: [*c]u32 = undefined; |
| 583 | \\const y: [*c]allowzero align(8) const volatile u32 = undefined; | |
| 584 | \\const z: [*c]allowzero align(8:4:2) const volatile u32 = undefined; | |
| 587 | \\const y: [*c]allowzero align(8) addrspace(.generic) const volatile u32 = undefined; | |
| 588 | \\const z: [*c]allowzero align(8:4:2) addrspace(.generic) const volatile u32 = undefined; | |
| 585 | 589 | \\ |
| 586 | 590 | ); |
| 587 | 591 | } |
| ... | ... | @@ -589,7 +593,7 @@ test "zig fmt: c pointer with modifiers" { |
| 589 | 593 | test "zig fmt: slice with modifiers" { |
| 590 | 594 | try testCanonical( |
| 591 | 595 | \\const x: []u32 = undefined; |
| 592 | \\const y: []allowzero align(8) const volatile u32 = undefined; | |
| 596 | \\const y: []allowzero align(8) addrspace(.generic) const volatile u32 = undefined; | |
| 593 | 597 | \\ |
| 594 | 598 | ); |
| 595 | 599 | } |
| ... | ... | @@ -597,7 +601,7 @@ test "zig fmt: slice with modifiers" { |
| 597 | 601 | test "zig fmt: sentinel slice with modifiers" { |
| 598 | 602 | try testCanonical( |
| 599 | 603 | \\const x: [:42]u32 = undefined; |
| 600 | \\const y: [:42]allowzero align(8) const volatile u32 = undefined; | |
| 604 | \\const y: [:42]allowzero align(8) addrspace(.generic) const volatile u32 = undefined; | |
| 601 | 605 | \\ |
| 602 | 606 | ); |
| 603 | 607 | } |
| ... | ... | @@ -1129,6 +1133,16 @@ test "zig fmt: linksection" { |
| 1129 | 1133 | ); |
| 1130 | 1134 | } |
| 1131 | 1135 | |
| 1136 | test "zig fmt: addrspace" { | |
| 1137 | try testCanonical( | |
| 1138 | \\export var python_length: u64 align(1) addrspace(.generic); | |
| 1139 | \\export var python_color: Color addrspace(.generic) = .green; | |
| 1140 | \\export var python_legs: u0 align(8) addrspace(.generic) linksection(".python") = 0; | |
| 1141 | \\export fn python_hiss() align(8) addrspace(.generic) linksection(".python") void; | |
| 1142 | \\ | |
| 1143 | ); | |
| 1144 | } | |
| 1145 | ||
| 1132 | 1146 | test "zig fmt: correctly space struct fields with doc comments" { |
| 1133 | 1147 | try testTransform( |
| 1134 | 1148 | \\pub const S = struct { |
lib/std/zig/render.zig+46-2| ... | ... | @@ -797,6 +797,14 @@ fn renderPtrType( |
| 797 | 797 | } |
| 798 | 798 | } |
| 799 | 799 | |
| 800 | if (ptr_type.ast.addrspace_node != 0) { | |
| 801 | const addrspace_first = tree.firstToken(ptr_type.ast.addrspace_node); | |
| 802 | try renderToken(ais, tree, addrspace_first - 2, .none); // addrspace | |
| 803 | try renderToken(ais, tree, addrspace_first - 1, .none); // lparen | |
| 804 | try renderExpression(gpa, ais, tree, ptr_type.ast.addrspace_node, .none); | |
| 805 | try renderToken(ais, tree, tree.lastToken(ptr_type.ast.addrspace_node) + 1, .space); // rparen | |
| 806 | } | |
| 807 | ||
| 800 | 808 | if (ptr_type.const_token) |const_token| { |
| 801 | 809 | try renderToken(ais, tree, const_token, .space); |
| 802 | 810 | } |
| ... | ... | @@ -921,6 +929,7 @@ fn renderVarDecl(gpa: *Allocator, ais: *Ais, tree: Ast, var_decl: Ast.full.VarDe |
| 921 | 929 | |
| 922 | 930 | const name_space = if (var_decl.ast.type_node == 0 and |
| 923 | 931 | (var_decl.ast.align_node != 0 or |
| 932 | var_decl.ast.addrspace_node != 0 or | |
| 924 | 933 | var_decl.ast.section_node != 0 or |
| 925 | 934 | var_decl.ast.init_node != 0)) |
| 926 | 935 | Space.space |
| ... | ... | @@ -930,8 +939,8 @@ fn renderVarDecl(gpa: *Allocator, ais: *Ais, tree: Ast, var_decl: Ast.full.VarDe |
| 930 | 939 | |
| 931 | 940 | if (var_decl.ast.type_node != 0) { |
| 932 | 941 | try renderToken(ais, tree, var_decl.ast.mut_token + 2, Space.space); // : |
| 933 | if (var_decl.ast.align_node != 0 or var_decl.ast.section_node != 0 or | |
| 934 | var_decl.ast.init_node != 0) | |
| 942 | if (var_decl.ast.align_node != 0 or var_decl.ast.addrspace_node != 0 or | |
| 943 | var_decl.ast.section_node != 0 or var_decl.ast.init_node != 0) | |
| 935 | 944 | { |
| 936 | 945 | try renderExpression(gpa, ais, tree, var_decl.ast.type_node, .space); |
| 937 | 946 | } else { |
| ... | ... | @@ -948,6 +957,23 @@ fn renderVarDecl(gpa: *Allocator, ais: *Ais, tree: Ast, var_decl: Ast.full.VarDe |
| 948 | 957 | try renderToken(ais, tree, align_kw, Space.none); // align |
| 949 | 958 | try renderToken(ais, tree, lparen, Space.none); // ( |
| 950 | 959 | try renderExpression(gpa, ais, tree, var_decl.ast.align_node, Space.none); |
| 960 | if (var_decl.ast.addrspace_node != 0 or var_decl.ast.section_node != 0 or | |
| 961 | var_decl.ast.init_node != 0) | |
| 962 | { | |
| 963 | try renderToken(ais, tree, rparen, .space); // ) | |
| 964 | } else { | |
| 965 | try renderToken(ais, tree, rparen, .none); // ) | |
| 966 | return renderToken(ais, tree, rparen + 1, Space.newline); // ; | |
| 967 | } | |
| 968 | } | |
| 969 | ||
| 970 | if (var_decl.ast.addrspace_node != 0) { | |
| 971 | const lparen = tree.firstToken(var_decl.ast.addrspace_node) - 1; | |
| 972 | const addrspace_kw = lparen - 1; | |
| 973 | const rparen = tree.lastToken(var_decl.ast.addrspace_node) + 1; | |
| 974 | try renderToken(ais, tree, addrspace_kw, Space.none); // addrspace | |
| 975 | try renderToken(ais, tree, lparen, Space.none); // ( | |
| 976 | try renderExpression(gpa, ais, tree, var_decl.ast.addrspace_node, Space.none); | |
| 951 | 977 | if (var_decl.ast.section_node != 0 or var_decl.ast.init_node != 0) { |
| 952 | 978 | try renderToken(ais, tree, rparen, .space); // ) |
| 953 | 979 | } else { |
| ... | ... | @@ -1267,6 +1293,14 @@ fn renderFnProto(gpa: *Allocator, ais: *Ais, tree: Ast, fn_proto: Ast.full.FnPro |
| 1267 | 1293 | smallest_start = start; |
| 1268 | 1294 | } |
| 1269 | 1295 | } |
| 1296 | if (fn_proto.ast.addrspace_expr != 0) { | |
| 1297 | const tok = tree.firstToken(fn_proto.ast.addrspace_expr) - 3; | |
| 1298 | const start = token_starts[tok]; | |
| 1299 | if (start < smallest_start) { | |
| 1300 | rparen = tok; | |
| 1301 | smallest_start = start; | |
| 1302 | } | |
| 1303 | } | |
| 1270 | 1304 | if (fn_proto.ast.section_expr != 0) { |
| 1271 | 1305 | const tok = tree.firstToken(fn_proto.ast.section_expr) - 3; |
| 1272 | 1306 | const start = token_starts[tok]; |
| ... | ... | @@ -1407,6 +1441,16 @@ fn renderFnProto(gpa: *Allocator, ais: *Ais, tree: Ast, fn_proto: Ast.full.FnPro |
| 1407 | 1441 | try renderToken(ais, tree, align_rparen, .space); // ) |
| 1408 | 1442 | } |
| 1409 | 1443 | |
| 1444 | if (fn_proto.ast.addrspace_expr != 0) { | |
| 1445 | const align_lparen = tree.firstToken(fn_proto.ast.addrspace_expr) - 1; | |
| 1446 | const align_rparen = tree.lastToken(fn_proto.ast.addrspace_expr) + 1; | |
| 1447 | ||
| 1448 | try renderToken(ais, tree, align_lparen - 1, .none); // addrspace | |
| 1449 | try renderToken(ais, tree, align_lparen, .none); // ( | |
| 1450 | try renderExpression(gpa, ais, tree, fn_proto.ast.addrspace_expr, .none); | |
| 1451 | try renderToken(ais, tree, align_rparen, .space); // ) | |
| 1452 | } | |
| 1453 | ||
| 1410 | 1454 | if (fn_proto.ast.section_expr != 0) { |
| 1411 | 1455 | const section_lparen = tree.firstToken(fn_proto.ast.section_expr) - 1; |
| 1412 | 1456 | const section_rparen = tree.lastToken(fn_proto.ast.section_expr) + 1; |
lib/std/zig/tokenizer.zig+3| ... | ... | @@ -11,6 +11,7 @@ pub const Token = struct { |
| 11 | 11 | }; |
| 12 | 12 | |
| 13 | 13 | pub const keywords = std.ComptimeStringMap(Tag, .{ |
| 14 | .{ "addrspace", .keyword_addrspace }, | |
| 14 | 15 | .{ "align", .keyword_align }, |
| 15 | 16 | .{ "allowzero", .keyword_allowzero }, |
| 16 | 17 | .{ "and", .keyword_and }, |
| ... | ... | @@ -132,6 +133,7 @@ pub const Token = struct { |
| 132 | 133 | float_literal, |
| 133 | 134 | doc_comment, |
| 134 | 135 | container_doc_comment, |
| 136 | keyword_addrspace, | |
| 135 | 137 | keyword_align, |
| 136 | 138 | keyword_allowzero, |
| 137 | 139 | keyword_and, |
| ... | ... | @@ -251,6 +253,7 @@ pub const Token = struct { |
| 251 | 253 | .angle_bracket_angle_bracket_right => ">>", |
| 252 | 254 | .angle_bracket_angle_bracket_right_equal => ">>=", |
| 253 | 255 | .tilde => "~", |
| 256 | .keyword_addrspace => "addrspace", | |
| 254 | 257 | .keyword_align => "align", |
| 255 | 258 | .keyword_allowzero => "allowzero", |
| 256 | 259 | .keyword_and => "and", |
src/AstGen.zig+43-8| ... | ... | @@ -1116,6 +1116,11 @@ fn fnProtoExpr( |
| 1116 | 1116 | const align_inst: Zir.Inst.Ref = if (fn_proto.ast.align_expr == 0) .none else inst: { |
| 1117 | 1117 | break :inst try expr(gz, scope, align_rl, fn_proto.ast.align_expr); |
| 1118 | 1118 | }; |
| 1119 | ||
| 1120 | if (fn_proto.ast.addrspace_expr != 0) { | |
| 1121 | return astgen.failNode(fn_proto.ast.addrspace_expr, "addrspace not allowed on function prototypes", .{}); | |
| 1122 | } | |
| 1123 | ||
| 1119 | 1124 | if (fn_proto.ast.section_expr != 0) { |
| 1120 | 1125 | return astgen.failNode(fn_proto.ast.section_expr, "linksection not allowed on function prototypes", .{}); |
| 1121 | 1126 | } |
| ... | ... | @@ -2371,6 +2376,7 @@ fn varDecl( |
| 2371 | 2376 | const gpa = astgen.gpa; |
| 2372 | 2377 | const tree = astgen.tree; |
| 2373 | 2378 | const token_tags = tree.tokens.items(.tag); |
| 2379 | const main_tokens = tree.nodes.items(.main_token); | |
| 2374 | 2380 | |
| 2375 | 2381 | const name_token = var_decl.ast.mut_token + 1; |
| 2376 | 2382 | const ident_name_raw = tree.tokenSlice(name_token); |
| ... | ... | @@ -2385,6 +2391,14 @@ fn varDecl( |
| 2385 | 2391 | return astgen.failNode(node, "variables must be initialized", .{}); |
| 2386 | 2392 | } |
| 2387 | 2393 | |
| 2394 | if (var_decl.ast.addrspace_node != 0) { | |
| 2395 | return astgen.failTok(main_tokens[var_decl.ast.addrspace_node], "cannot set address space of local variable '{s}'", .{ident_name_raw}); | |
| 2396 | } | |
| 2397 | ||
| 2398 | if (var_decl.ast.section_node != 0) { | |
| 2399 | return astgen.failTok(main_tokens[var_decl.ast.section_node], "cannot set section of local variable '{s}'", .{ident_name_raw}); | |
| 2400 | } | |
| 2401 | ||
| 2388 | 2402 | const align_inst: Zir.Inst.Ref = if (var_decl.ast.align_node != 0) |
| 2389 | 2403 | try expr(gz, scope, align_rl, var_decl.ast.align_node) |
| 2390 | 2404 | else |
| ... | ... | @@ -2714,6 +2728,7 @@ fn ptrType( |
| 2714 | 2728 | const elem_type = try typeExpr(gz, scope, ptr_info.ast.child_type); |
| 2715 | 2729 | |
| 2716 | 2730 | const simple = ptr_info.ast.align_node == 0 and |
| 2731 | ptr_info.ast.addrspace_node == 0 and | |
| 2717 | 2732 | ptr_info.ast.sentinel == 0 and |
| 2718 | 2733 | ptr_info.ast.bit_range_start == 0; |
| 2719 | 2734 | |
| ... | ... | @@ -2732,6 +2747,7 @@ fn ptrType( |
| 2732 | 2747 | |
| 2733 | 2748 | var sentinel_ref: Zir.Inst.Ref = .none; |
| 2734 | 2749 | var align_ref: Zir.Inst.Ref = .none; |
| 2750 | var addrspace_ref: Zir.Inst.Ref = .none; | |
| 2735 | 2751 | var bit_start_ref: Zir.Inst.Ref = .none; |
| 2736 | 2752 | var bit_end_ref: Zir.Inst.Ref = .none; |
| 2737 | 2753 | var trailing_count: u32 = 0; |
| ... | ... | @@ -2744,6 +2760,10 @@ fn ptrType( |
| 2744 | 2760 | align_ref = try expr(gz, scope, align_rl, ptr_info.ast.align_node); |
| 2745 | 2761 | trailing_count += 1; |
| 2746 | 2762 | } |
| 2763 | if (ptr_info.ast.addrspace_node != 0) { | |
| 2764 | addrspace_ref = try expr(gz, scope, .{ .ty = .address_space_type }, ptr_info.ast.addrspace_node); | |
| 2765 | trailing_count += 1; | |
| 2766 | } | |
| 2747 | 2767 | if (ptr_info.ast.bit_range_start != 0) { |
| 2748 | 2768 | assert(ptr_info.ast.bit_range_end != 0); |
| 2749 | 2769 | bit_start_ref = try expr(gz, scope, .none, ptr_info.ast.bit_range_start); |
| ... | ... | @@ -2764,6 +2784,9 @@ fn ptrType( |
| 2764 | 2784 | if (align_ref != .none) { |
| 2765 | 2785 | gz.astgen.extra.appendAssumeCapacity(@enumToInt(align_ref)); |
| 2766 | 2786 | } |
| 2787 | if (addrspace_ref != .none) { | |
| 2788 | gz.astgen.extra.appendAssumeCapacity(@enumToInt(addrspace_ref)); | |
| 2789 | } | |
| 2767 | 2790 | if (bit_start_ref != .none) { |
| 2768 | 2791 | gz.astgen.extra.appendAssumeCapacity(@enumToInt(bit_start_ref)); |
| 2769 | 2792 | gz.astgen.extra.appendAssumeCapacity(@enumToInt(bit_end_ref)); |
| ... | ... | @@ -2779,6 +2802,7 @@ fn ptrType( |
| 2779 | 2802 | .is_volatile = ptr_info.volatile_token != null, |
| 2780 | 2803 | .has_sentinel = sentinel_ref != .none, |
| 2781 | 2804 | .has_align = align_ref != .none, |
| 2805 | .has_addrspace = addrspace_ref != .none, | |
| 2782 | 2806 | .has_bit_range = bit_start_ref != .none, |
| 2783 | 2807 | }, |
| 2784 | 2808 | .size = ptr_info.size, |
| ... | ... | @@ -2847,7 +2871,7 @@ const WipDecls = struct { |
| 2847 | 2871 | is_pub: bool, |
| 2848 | 2872 | is_export: bool, |
| 2849 | 2873 | has_align: bool, |
| 2850 | has_section: bool, | |
| 2874 | has_section_or_addrspace: bool, | |
| 2851 | 2875 | ) Allocator.Error!void { |
| 2852 | 2876 | if (wip_decls.decl_index % fields_per_u32 == 0 and wip_decls.decl_index != 0) { |
| 2853 | 2877 | try wip_decls.bit_bag.append(gpa, wip_decls.cur_bit_bag); |
| ... | ... | @@ -2857,7 +2881,7 @@ const WipDecls = struct { |
| 2857 | 2881 | (@as(u32, @boolToInt(is_pub)) << 28) | |
| 2858 | 2882 | (@as(u32, @boolToInt(is_export)) << 29) | |
| 2859 | 2883 | (@as(u32, @boolToInt(has_align)) << 30) | |
| 2860 | (@as(u32, @boolToInt(has_section)) << 31); | |
| 2884 | (@as(u32, @boolToInt(has_section_or_addrspace)) << 31); | |
| 2861 | 2885 | wip_decls.decl_index += 1; |
| 2862 | 2886 | } |
| 2863 | 2887 | |
| ... | ... | @@ -2922,7 +2946,8 @@ fn fnDecl( |
| 2922 | 2946 | const maybe_inline_token = fn_proto.extern_export_inline_token orelse break :blk false; |
| 2923 | 2947 | break :blk token_tags[maybe_inline_token] == .keyword_inline; |
| 2924 | 2948 | }; |
| 2925 | try wip_decls.next(gpa, is_pub, is_export, fn_proto.ast.align_expr != 0, fn_proto.ast.section_expr != 0); | |
| 2949 | const has_section_or_addrspace = fn_proto.ast.section_expr != 0 or fn_proto.ast.addrspace_expr != 0; | |
| 2950 | try wip_decls.next(gpa, is_pub, is_export, fn_proto.ast.align_expr != 0, has_section_or_addrspace); | |
| 2926 | 2951 | |
| 2927 | 2952 | var params_scope = &fn_gz.base; |
| 2928 | 2953 | const is_var_args = is_var_args: { |
| ... | ... | @@ -3011,6 +3036,9 @@ fn fnDecl( |
| 3011 | 3036 | const align_inst: Zir.Inst.Ref = if (fn_proto.ast.align_expr == 0) .none else inst: { |
| 3012 | 3037 | break :inst try expr(&decl_gz, params_scope, align_rl, fn_proto.ast.align_expr); |
| 3013 | 3038 | }; |
| 3039 | const addrspace_inst: Zir.Inst.Ref = if (fn_proto.ast.addrspace_expr == 0) .none else inst: { | |
| 3040 | break :inst try expr(&decl_gz, params_scope, .{ .ty = .address_space_type }, fn_proto.ast.addrspace_expr); | |
| 3041 | }; | |
| 3014 | 3042 | const section_inst: Zir.Inst.Ref = if (fn_proto.ast.section_expr == 0) .none else inst: { |
| 3015 | 3043 | break :inst try comptimeExpr(&decl_gz, params_scope, .{ .ty = .const_slice_u8_type }, fn_proto.ast.section_expr); |
| 3016 | 3044 | }; |
| ... | ... | @@ -3112,7 +3140,7 @@ fn fnDecl( |
| 3112 | 3140 | _ = try decl_gz.addBreak(.break_inline, block_inst, func_inst); |
| 3113 | 3141 | try decl_gz.setBlockBody(block_inst); |
| 3114 | 3142 | |
| 3115 | try wip_decls.payload.ensureUnusedCapacity(gpa, 9); | |
| 3143 | try wip_decls.payload.ensureUnusedCapacity(gpa, 10); | |
| 3116 | 3144 | { |
| 3117 | 3145 | const contents_hash = std.zig.hashSrc(tree.getNodeSource(decl_node)); |
| 3118 | 3146 | const casted = @bitCast([4]u32, contents_hash); |
| ... | ... | @@ -3127,8 +3155,10 @@ fn fnDecl( |
| 3127 | 3155 | if (align_inst != .none) { |
| 3128 | 3156 | wip_decls.payload.appendAssumeCapacity(@enumToInt(align_inst)); |
| 3129 | 3157 | } |
| 3130 | if (section_inst != .none) { | |
| 3158 | ||
| 3159 | if (has_section_or_addrspace) { | |
| 3131 | 3160 | wip_decls.payload.appendAssumeCapacity(@enumToInt(section_inst)); |
| 3161 | wip_decls.payload.appendAssumeCapacity(@enumToInt(addrspace_inst)); | |
| 3132 | 3162 | } |
| 3133 | 3163 | } |
| 3134 | 3164 | |
| ... | ... | @@ -3175,10 +3205,14 @@ fn globalVarDecl( |
| 3175 | 3205 | const align_inst: Zir.Inst.Ref = if (var_decl.ast.align_node == 0) .none else inst: { |
| 3176 | 3206 | break :inst try expr(&block_scope, &block_scope.base, align_rl, var_decl.ast.align_node); |
| 3177 | 3207 | }; |
| 3208 | const addrspace_inst: Zir.Inst.Ref = if (var_decl.ast.addrspace_node == 0) .none else inst: { | |
| 3209 | break :inst try expr(&block_scope, &block_scope.base, .{ .ty = .address_space_type }, var_decl.ast.addrspace_node); | |
| 3210 | }; | |
| 3178 | 3211 | const section_inst: Zir.Inst.Ref = if (var_decl.ast.section_node == 0) .none else inst: { |
| 3179 | 3212 | break :inst try comptimeExpr(&block_scope, &block_scope.base, .{ .ty = .const_slice_u8_type }, var_decl.ast.section_node); |
| 3180 | 3213 | }; |
| 3181 | try wip_decls.next(gpa, is_pub, is_export, align_inst != .none, section_inst != .none); | |
| 3214 | const has_section_or_addrspace = section_inst != .none or addrspace_inst != .none; | |
| 3215 | try wip_decls.next(gpa, is_pub, is_export, align_inst != .none, has_section_or_addrspace); | |
| 3182 | 3216 | |
| 3183 | 3217 | const is_threadlocal = if (var_decl.threadlocal_token) |tok| blk: { |
| 3184 | 3218 | if (!is_mutable) { |
| ... | ... | @@ -3256,7 +3290,7 @@ fn globalVarDecl( |
| 3256 | 3290 | _ = try block_scope.addBreak(.break_inline, block_inst, var_inst); |
| 3257 | 3291 | try block_scope.setBlockBody(block_inst); |
| 3258 | 3292 | |
| 3259 | try wip_decls.payload.ensureUnusedCapacity(gpa, 9); | |
| 3293 | try wip_decls.payload.ensureUnusedCapacity(gpa, 10); | |
| 3260 | 3294 | { |
| 3261 | 3295 | const contents_hash = std.zig.hashSrc(tree.getNodeSource(node)); |
| 3262 | 3296 | const casted = @bitCast([4]u32, contents_hash); |
| ... | ... | @@ -3271,8 +3305,9 @@ fn globalVarDecl( |
| 3271 | 3305 | if (align_inst != .none) { |
| 3272 | 3306 | wip_decls.payload.appendAssumeCapacity(@enumToInt(align_inst)); |
| 3273 | 3307 | } |
| 3274 | if (section_inst != .none) { | |
| 3308 | if (has_section_or_addrspace) { | |
| 3275 | 3309 | wip_decls.payload.appendAssumeCapacity(@enumToInt(section_inst)); |
| 3310 | wip_decls.payload.appendAssumeCapacity(@enumToInt(addrspace_inst)); | |
| 3276 | 3311 | } |
| 3277 | 3312 | } |
| 3278 | 3313 |
src/Module.zig+100-45| ... | ... | @@ -288,6 +288,8 @@ pub const Decl = struct { |
| 288 | 288 | align_val: Value, |
| 289 | 289 | /// Populated when `has_tv`. |
| 290 | 290 | linksection_val: Value, |
| 291 | /// Populated when `has_tv`. | |
| 292 | @"addrspace": std.builtin.AddressSpace, | |
| 291 | 293 | /// The memory for ty, val, align_val, linksection_val. |
| 292 | 294 | /// If this is `null` then there is no memory management needed. |
| 293 | 295 | value_arena: ?*std.heap.ArenaAllocator.State = null, |
| ... | ... | @@ -351,7 +353,7 @@ pub const Decl = struct { |
| 351 | 353 | /// to require re-analysis. |
| 352 | 354 | outdated, |
| 353 | 355 | }, |
| 354 | /// Whether `typed_value`, `align_val`, and `linksection_val` are populated. | |
| 356 | /// Whether `typed_value`, `align_val`, `linksection_val` and `addrspace` are populated. | |
| 355 | 357 | has_tv: bool, |
| 356 | 358 | /// If `true` it means the `Decl` is the resource owner of the type/value associated |
| 357 | 359 | /// with it. That means when `Decl` is destroyed, the cleanup code should additionally |
| ... | ... | @@ -366,8 +368,8 @@ pub const Decl = struct { |
| 366 | 368 | is_exported: bool, |
| 367 | 369 | /// Whether the ZIR code provides an align instruction. |
| 368 | 370 | has_align: bool, |
| 369 | /// Whether the ZIR code provides a linksection instruction. | |
| 370 | has_linksection: bool, | |
| 371 | /// Whether the ZIR code provides a linksection and address space instruction. | |
| 372 | has_linksection_or_addrspace: bool, | |
| 371 | 373 | /// Flag used by garbage collection to mark and sweep. |
| 372 | 374 | /// Decls which correspond to an AST node always have this field set to `true`. |
| 373 | 375 | /// Anonymous Decls are initialized with this field set to `false` and then it |
| ... | ... | @@ -489,14 +491,22 @@ pub const Decl = struct { |
| 489 | 491 | if (!decl.has_align) return .none; |
| 490 | 492 | assert(decl.zir_decl_index != 0); |
| 491 | 493 | const zir = decl.namespace.file_scope.zir; |
| 492 | return @intToEnum(Zir.Inst.Ref, zir.extra[decl.zir_decl_index + 6]); | |
| 494 | return @intToEnum(Zir.Inst.Ref, zir.extra[decl.zir_decl_index + 7]); | |
| 493 | 495 | } |
| 494 | 496 | |
| 495 | 497 | pub fn zirLinksectionRef(decl: Decl) Zir.Inst.Ref { |
| 496 | if (!decl.has_linksection) return .none; | |
| 498 | if (!decl.has_linksection_or_addrspace) return .none; | |
| 497 | 499 | assert(decl.zir_decl_index != 0); |
| 498 | 500 | const zir = decl.namespace.file_scope.zir; |
| 499 | const extra_index = decl.zir_decl_index + 6 + @boolToInt(decl.has_align); | |
| 501 | const extra_index = decl.zir_decl_index + 7 + @boolToInt(decl.has_align); | |
| 502 | return @intToEnum(Zir.Inst.Ref, zir.extra[extra_index]); | |
| 503 | } | |
| 504 | ||
| 505 | pub fn zirAddrspaceRef(decl: Decl) Zir.Inst.Ref { | |
| 506 | if (!decl.has_linksection_or_addrspace) return .none; | |
| 507 | assert(decl.zir_decl_index != 0); | |
| 508 | const zir = decl.namespace.file_scope.zir; | |
| 509 | const extra_index = decl.zir_decl_index + 7 + @boolToInt(decl.has_align) + 1; | |
| 500 | 510 | return @intToEnum(Zir.Inst.Ref, zir.extra[extra_index]); |
| 501 | 511 | } |
| 502 | 512 | |
| ... | ... | @@ -3072,7 +3082,7 @@ pub fn semaFile(mod: *Module, file: *Scope.File) SemaError!void { |
| 3072 | 3082 | new_decl.is_pub = true; |
| 3073 | 3083 | new_decl.is_exported = false; |
| 3074 | 3084 | new_decl.has_align = false; |
| 3075 | new_decl.has_linksection = false; | |
| 3085 | new_decl.has_linksection_or_addrspace = false; | |
| 3076 | 3086 | new_decl.ty = struct_ty; |
| 3077 | 3087 | new_decl.val = struct_val; |
| 3078 | 3088 | new_decl.has_tv = true; |
| ... | ... | @@ -3202,6 +3212,24 @@ fn semaDecl(mod: *Module, decl: *Decl) !bool { |
| 3202 | 3212 | if (linksection_ref == .none) break :blk Value.initTag(.null_value); |
| 3203 | 3213 | break :blk (try sema.resolveInstConst(&block_scope, src, linksection_ref)).val; |
| 3204 | 3214 | }; |
| 3215 | const address_space = blk: { | |
| 3216 | const addrspace_ctx: Sema.AddressSpaceContext = switch (decl_tv.val.tag()) { | |
| 3217 | .function, .extern_fn => .function, | |
| 3218 | .variable => .variable, | |
| 3219 | else => .constant, | |
| 3220 | }; | |
| 3221 | ||
| 3222 | break :blk switch (decl.zirAddrspaceRef()) { | |
| 3223 | .none => switch (addrspace_ctx) { | |
| 3224 | .function => target_util.defaultAddressSpace(sema.mod.getTarget(), .function), | |
| 3225 | .variable => target_util.defaultAddressSpace(sema.mod.getTarget(), .global_mutable), | |
| 3226 | .constant => target_util.defaultAddressSpace(sema.mod.getTarget(), .global_constant), | |
| 3227 | else => unreachable, | |
| 3228 | }, | |
| 3229 | else => |addrspace_ref| try sema.analyzeAddrspace(&block_scope, src, addrspace_ref, addrspace_ctx), | |
| 3230 | }; | |
| 3231 | }; | |
| 3232 | ||
| 3205 | 3233 | // Note this resolves the type of the Decl, not the value; if this Decl |
| 3206 | 3234 | // is a struct, for example, this resolves `type` (which needs no resolution), |
| 3207 | 3235 | // not the struct itself. |
| ... | ... | @@ -3258,6 +3286,7 @@ fn semaDecl(mod: *Module, decl: *Decl) !bool { |
| 3258 | 3286 | decl.val = try decl_tv.val.copy(&decl_arena.allocator); |
| 3259 | 3287 | decl.align_val = try align_val.copy(&decl_arena.allocator); |
| 3260 | 3288 | decl.linksection_val = try linksection_val.copy(&decl_arena.allocator); |
| 3289 | decl.@"addrspace" = address_space; | |
| 3261 | 3290 | decl.has_tv = true; |
| 3262 | 3291 | decl.owns_tv = owns_tv; |
| 3263 | 3292 | decl_arena_state.* = decl_arena.state; |
| ... | ... | @@ -3319,6 +3348,7 @@ fn semaDecl(mod: *Module, decl: *Decl) !bool { |
| 3319 | 3348 | decl.val = try decl_tv.val.copy(&decl_arena.allocator); |
| 3320 | 3349 | decl.align_val = try align_val.copy(&decl_arena.allocator); |
| 3321 | 3350 | decl.linksection_val = try linksection_val.copy(&decl_arena.allocator); |
| 3351 | decl.@"addrspace" = address_space; | |
| 3322 | 3352 | decl.has_tv = true; |
| 3323 | 3353 | decl_arena_state.* = decl_arena.state; |
| 3324 | 3354 | decl.value_arena = decl_arena_state; |
| ... | ... | @@ -3526,8 +3556,8 @@ pub fn scanNamespace( |
| 3526 | 3556 | |
| 3527 | 3557 | const decl_sub_index = extra_index; |
| 3528 | 3558 | extra_index += 7; // src_hash(4) + line(1) + name(1) + value(1) |
| 3529 | extra_index += @truncate(u1, flags >> 2); | |
| 3530 | extra_index += @truncate(u1, flags >> 3); | |
| 3559 | extra_index += @truncate(u1, flags >> 2); // Align | |
| 3560 | extra_index += @as(u2, @truncate(u1, flags >> 3)) * 2; // Link section or address space, consists of 2 Refs | |
| 3531 | 3561 | |
| 3532 | 3562 | try scanDecl(&scan_decl_iter, decl_sub_index, flags); |
| 3533 | 3563 | } |
| ... | ... | @@ -3553,10 +3583,10 @@ fn scanDecl(iter: *ScanDeclIter, decl_sub_index: usize, flags: u4) SemaError!voi |
| 3553 | 3583 | const zir = namespace.file_scope.zir; |
| 3554 | 3584 | |
| 3555 | 3585 | // zig fmt: off |
| 3556 | const is_pub = (flags & 0b0001) != 0; | |
| 3557 | const export_bit = (flags & 0b0010) != 0; | |
| 3558 | const has_align = (flags & 0b0100) != 0; | |
| 3559 | const has_linksection = (flags & 0b1000) != 0; | |
| 3586 | const is_pub = (flags & 0b0001) != 0; | |
| 3587 | const export_bit = (flags & 0b0010) != 0; | |
| 3588 | const has_align = (flags & 0b0100) != 0; | |
| 3589 | const has_linksection_or_addrspace = (flags & 0b1000) != 0; | |
| 3560 | 3590 | // zig fmt: on |
| 3561 | 3591 | |
| 3562 | 3592 | const line = iter.parent_decl.relativeToLine(zir.extra[decl_sub_index + 4]); |
| ... | ... | @@ -3639,7 +3669,7 @@ fn scanDecl(iter: *ScanDeclIter, decl_sub_index: usize, flags: u4) SemaError!voi |
| 3639 | 3669 | new_decl.is_exported = is_exported; |
| 3640 | 3670 | new_decl.is_usingnamespace = is_usingnamespace; |
| 3641 | 3671 | new_decl.has_align = has_align; |
| 3642 | new_decl.has_linksection = has_linksection; | |
| 3672 | new_decl.has_linksection_or_addrspace = has_linksection_or_addrspace; | |
| 3643 | 3673 | new_decl.zir_decl_index = @intCast(u32, decl_sub_index); |
| 3644 | 3674 | new_decl.alive = true; // This Decl corresponds to an AST node and therefore always alive. |
| 3645 | 3675 | return; |
| ... | ... | @@ -3656,7 +3686,7 @@ fn scanDecl(iter: *ScanDeclIter, decl_sub_index: usize, flags: u4) SemaError!voi |
| 3656 | 3686 | decl.is_exported = is_exported; |
| 3657 | 3687 | decl.is_usingnamespace = is_usingnamespace; |
| 3658 | 3688 | decl.has_align = has_align; |
| 3659 | decl.has_linksection = has_linksection; | |
| 3689 | decl.has_linksection_or_addrspace = has_linksection_or_addrspace; | |
| 3660 | 3690 | decl.zir_decl_index = @intCast(u32, decl_sub_index); |
| 3661 | 3691 | if (decl.getFunction()) |_| { |
| 3662 | 3692 | switch (mod.comp.bin_file.tag) { |
| ... | ... | @@ -4028,6 +4058,7 @@ pub fn allocateNewDecl(mod: *Module, namespace: *Scope.Namespace, src_node: Ast. |
| 4028 | 4058 | .val = undefined, |
| 4029 | 4059 | .align_val = undefined, |
| 4030 | 4060 | .linksection_val = undefined, |
| 4061 | .@"addrspace" = undefined, | |
| 4031 | 4062 | .analysis = .unreferenced, |
| 4032 | 4063 | .deletion_flag = false, |
| 4033 | 4064 | .zir_decl_index = 0, |
| ... | ... | @@ -4052,7 +4083,7 @@ pub fn allocateNewDecl(mod: *Module, namespace: *Scope.Namespace, src_node: Ast. |
| 4052 | 4083 | .generation = 0, |
| 4053 | 4084 | .is_pub = false, |
| 4054 | 4085 | .is_exported = false, |
| 4055 | .has_linksection = false, | |
| 4086 | .has_linksection_or_addrspace = false, | |
| 4056 | 4087 | .has_align = false, |
| 4057 | 4088 | .alive = false, |
| 4058 | 4089 | .is_usingnamespace = false, |
| ... | ... | @@ -4185,6 +4216,9 @@ pub fn createAnonymousDeclFromDeclNamed( |
| 4185 | 4216 | new_decl.src_line = owner_decl.src_line; |
| 4186 | 4217 | new_decl.ty = typed_value.ty; |
| 4187 | 4218 | new_decl.val = typed_value.val; |
| 4219 | new_decl.align_val = Value.initTag(.null_value); | |
| 4220 | new_decl.linksection_val = Value.initTag(.null_value); | |
| 4221 | new_decl.@"addrspace" = .generic; // default global addrspace | |
| 4188 | 4222 | new_decl.has_tv = true; |
| 4189 | 4223 | new_decl.analysis = .complete; |
| 4190 | 4224 | new_decl.generation = mod.generation; |
| ... | ... | @@ -4330,10 +4364,59 @@ pub fn simplePtrType( |
| 4330 | 4364 | elem_ty: Type, |
| 4331 | 4365 | mutable: bool, |
| 4332 | 4366 | size: std.builtin.TypeInfo.Pointer.Size, |
| 4367 | @"addrspace": std.builtin.AddressSpace, | |
| 4333 | 4368 | ) Allocator.Error!Type { |
| 4369 | return ptrType( | |
| 4370 | arena, | |
| 4371 | elem_ty, | |
| 4372 | null, | |
| 4373 | 0, | |
| 4374 | @"addrspace", | |
| 4375 | 0, | |
| 4376 | 0, | |
| 4377 | mutable, | |
| 4378 | false, | |
| 4379 | false, | |
| 4380 | size, | |
| 4381 | ); | |
| 4382 | } | |
| 4383 | ||
| 4384 | pub fn ptrType( | |
| 4385 | arena: *Allocator, | |
| 4386 | elem_ty: Type, | |
| 4387 | sentinel: ?Value, | |
| 4388 | @"align": u32, | |
| 4389 | @"addrspace": std.builtin.AddressSpace, | |
| 4390 | bit_offset: u16, | |
| 4391 | host_size: u16, | |
| 4392 | mutable: bool, | |
| 4393 | @"allowzero": bool, | |
| 4394 | @"volatile": bool, | |
| 4395 | size: std.builtin.TypeInfo.Pointer.Size, | |
| 4396 | ) Allocator.Error!Type { | |
| 4397 | assert(host_size == 0 or bit_offset < host_size * 8); | |
| 4398 | ||
| 4399 | if (sentinel != null or @"align" != 0 or @"addrspace" != .generic or | |
| 4400 | bit_offset != 0 or host_size != 0 or @"allowzero" or @"volatile") | |
| 4401 | { | |
| 4402 | return Type.Tag.pointer.create(arena, .{ | |
| 4403 | .pointee_type = elem_ty, | |
| 4404 | .sentinel = sentinel, | |
| 4405 | .@"align" = @"align", | |
| 4406 | .@"addrspace" = @"addrspace", | |
| 4407 | .bit_offset = bit_offset, | |
| 4408 | .host_size = host_size, | |
| 4409 | .@"allowzero" = @"allowzero", | |
| 4410 | .mutable = mutable, | |
| 4411 | .@"volatile" = @"volatile", | |
| 4412 | .size = size, | |
| 4413 | }); | |
| 4414 | } | |
| 4415 | ||
| 4334 | 4416 | if (!mutable and size == .Slice and elem_ty.eql(Type.initTag(.u8))) { |
| 4335 | 4417 | return Type.initTag(.const_slice_u8); |
| 4336 | 4418 | } |
| 4419 | ||
| 4337 | 4420 | // TODO stage1 type inference bug |
| 4338 | 4421 | const T = Type.Tag; |
| 4339 | 4422 | |
| ... | ... | @@ -4352,34 +4435,6 @@ pub fn simplePtrType( |
| 4352 | 4435 | return Type.initPayload(&type_payload.base); |
| 4353 | 4436 | } |
| 4354 | 4437 | |
| 4355 | pub fn ptrType( | |
| 4356 | arena: *Allocator, | |
| 4357 | elem_ty: Type, | |
| 4358 | sentinel: ?Value, | |
| 4359 | @"align": u32, | |
| 4360 | bit_offset: u16, | |
| 4361 | host_size: u16, | |
| 4362 | mutable: bool, | |
| 4363 | @"allowzero": bool, | |
| 4364 | @"volatile": bool, | |
| 4365 | size: std.builtin.TypeInfo.Pointer.Size, | |
| 4366 | ) Allocator.Error!Type { | |
| 4367 | assert(host_size == 0 or bit_offset < host_size * 8); | |
| 4368 | ||
| 4369 | // TODO check if type can be represented by simplePtrType | |
| 4370 | return Type.Tag.pointer.create(arena, .{ | |
| 4371 | .pointee_type = elem_ty, | |
| 4372 | .sentinel = sentinel, | |
| 4373 | .@"align" = @"align", | |
| 4374 | .bit_offset = bit_offset, | |
| 4375 | .host_size = host_size, | |
| 4376 | .@"allowzero" = @"allowzero", | |
| 4377 | .mutable = mutable, | |
| 4378 | .@"volatile" = @"volatile", | |
| 4379 | .size = size, | |
| 4380 | }); | |
| 4381 | } | |
| 4382 | ||
| 4383 | 4438 | pub fn optionalType(arena: *Allocator, child_type: Type) Allocator.Error!Type { |
| 4384 | 4439 | switch (child_type.tag()) { |
| 4385 | 4440 | .single_const_pointer => return Type.Tag.optional_single_const_pointer.create( |
| ... | ... | @@ -4709,7 +4764,7 @@ pub fn populateTestFunctions(mod: *Module) !void { |
| 4709 | 4764 | const builtin_file = (mod.importPkg(builtin_pkg) catch unreachable).file; |
| 4710 | 4765 | const builtin_namespace = builtin_file.root_decl.?.namespace; |
| 4711 | 4766 | const decl = builtin_namespace.decls.get("test_functions").?; |
| 4712 | var buf: Type.Payload.ElemType = undefined; | |
| 4767 | var buf: Type.SlicePtrFieldTypeBuffer = undefined; | |
| 4713 | 4768 | const tmp_test_fn_ty = decl.ty.slicePtrFieldType(&buf).elemType(); |
| 4714 | 4769 | |
| 4715 | 4770 | const array_decl = d: { |
src/Sema.zig+242-61| ... | ... | @@ -1373,7 +1373,13 @@ fn zirRetPtr( |
| 1373 | 1373 | return sema.analyzeComptimeAlloc(block, sema.fn_ret_ty); |
| 1374 | 1374 | } |
| 1375 | 1375 | |
| 1376 | const ptr_type = try Module.simplePtrType(sema.arena, sema.fn_ret_ty, true, .One); | |
| 1376 | const ptr_type = try Module.simplePtrType( | |
| 1377 | sema.arena, | |
| 1378 | sema.fn_ret_ty, | |
| 1379 | true, | |
| 1380 | .One, | |
| 1381 | target_util.defaultAddressSpace(sema.mod.getTarget(), .local), | |
| 1382 | ); | |
| 1377 | 1383 | return block.addTy(.alloc, ptr_type); |
| 1378 | 1384 | } |
| 1379 | 1385 | |
| ... | ... | @@ -1521,7 +1527,13 @@ fn zirAlloc(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileError |
| 1521 | 1527 | const ty_src: LazySrcLoc = .{ .node_offset_var_decl_ty = inst_data.src_node }; |
| 1522 | 1528 | const var_decl_src = inst_data.src(); |
| 1523 | 1529 | const var_type = try sema.resolveType(block, ty_src, inst_data.operand); |
| 1524 | const ptr_type = try Module.simplePtrType(sema.arena, var_type, true, .One); | |
| 1530 | const ptr_type = try Module.simplePtrType( | |
| 1531 | sema.arena, | |
| 1532 | var_type, | |
| 1533 | true, | |
| 1534 | .One, | |
| 1535 | target_util.defaultAddressSpace(sema.mod.getTarget(), .local), | |
| 1536 | ); | |
| 1525 | 1537 | try sema.requireRuntimeBlock(block, var_decl_src); |
| 1526 | 1538 | return block.addTy(.alloc, ptr_type); |
| 1527 | 1539 | } |
| ... | ... | @@ -1538,7 +1550,13 @@ fn zirAllocMut(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileEr |
| 1538 | 1550 | return sema.analyzeComptimeAlloc(block, var_type); |
| 1539 | 1551 | } |
| 1540 | 1552 | try sema.validateVarType(block, ty_src, var_type); |
| 1541 | const ptr_type = try Module.simplePtrType(sema.arena, var_type, true, .One); | |
| 1553 | const ptr_type = try Module.simplePtrType( | |
| 1554 | sema.arena, | |
| 1555 | var_type, | |
| 1556 | true, | |
| 1557 | .One, | |
| 1558 | target_util.defaultAddressSpace(sema.mod.getTarget(), .local), | |
| 1559 | ); | |
| 1542 | 1560 | try sema.requireRuntimeBlock(block, var_decl_src); |
| 1543 | 1561 | return block.addTy(.alloc, ptr_type); |
| 1544 | 1562 | } |
| ... | ... | @@ -1598,7 +1616,13 @@ fn zirResolveInferredAlloc(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Inde |
| 1598 | 1616 | try sema.mod.declareDeclDependency(sema.owner_decl, decl); |
| 1599 | 1617 | |
| 1600 | 1618 | const final_elem_ty = try decl.ty.copy(sema.arena); |
| 1601 | const final_ptr_ty = try Module.simplePtrType(sema.arena, final_elem_ty, true, .One); | |
| 1619 | const final_ptr_ty = try Module.simplePtrType( | |
| 1620 | sema.arena, | |
| 1621 | final_elem_ty, | |
| 1622 | true, | |
| 1623 | .One, | |
| 1624 | target_util.defaultAddressSpace(sema.mod.getTarget(), .local), | |
| 1625 | ); | |
| 1602 | 1626 | const final_ptr_ty_inst = try sema.addType(final_ptr_ty); |
| 1603 | 1627 | sema.air_instructions.items(.data)[ptr_inst].ty_pl.ty = final_ptr_ty_inst; |
| 1604 | 1628 | |
| ... | ... | @@ -1620,7 +1644,13 @@ fn zirResolveInferredAlloc(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Inde |
| 1620 | 1644 | try sema.validateVarType(block, ty_src, final_elem_ty); |
| 1621 | 1645 | } |
| 1622 | 1646 | // Change it to a normal alloc. |
| 1623 | const final_ptr_ty = try Module.simplePtrType(sema.arena, final_elem_ty, true, .One); | |
| 1647 | const final_ptr_ty = try Module.simplePtrType( | |
| 1648 | sema.arena, | |
| 1649 | final_elem_ty, | |
| 1650 | true, | |
| 1651 | .One, | |
| 1652 | target_util.defaultAddressSpace(sema.mod.getTarget(), .local), | |
| 1653 | ); | |
| 1624 | 1654 | sema.air_instructions.set(ptr_inst, .{ |
| 1625 | 1655 | .tag = .alloc, |
| 1626 | 1656 | .data = .{ .ty = final_ptr_ty }, |
| ... | ... | @@ -1774,7 +1804,14 @@ fn zirStoreToBlockPtr(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) Co |
| 1774 | 1804 | } |
| 1775 | 1805 | const ptr = sema.resolveInst(bin_inst.lhs); |
| 1776 | 1806 | const value = sema.resolveInst(bin_inst.rhs); |
| 1777 | const ptr_ty = try Module.simplePtrType(sema.arena, sema.typeOf(value), true, .One); | |
| 1807 | const ptr_ty = try Module.simplePtrType( | |
| 1808 | sema.arena, | |
| 1809 | sema.typeOf(value), | |
| 1810 | true, | |
| 1811 | .One, | |
| 1812 | // TODO figure out which address space is appropriate here | |
| 1813 | target_util.defaultAddressSpace(sema.mod.getTarget(), .local), | |
| 1814 | ); | |
| 1778 | 1815 | // TODO detect when this store should be done at compile-time. For example, |
| 1779 | 1816 | // if expressions should force it when the condition is compile-time known. |
| 1780 | 1817 | const src: LazySrcLoc = .unneeded; |
| ... | ... | @@ -1821,7 +1858,14 @@ fn zirStoreToInferredPtr(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) |
| 1821 | 1858 | // for the inferred allocation. |
| 1822 | 1859 | try inferred_alloc.data.stored_inst_list.append(sema.arena, operand); |
| 1823 | 1860 | // Create a runtime bitcast instruction with exactly the type the pointer wants. |
| 1824 | const ptr_ty = try Module.simplePtrType(sema.arena, operand_ty, true, .One); | |
| 1861 | const ptr_ty = try Module.simplePtrType( | |
| 1862 | sema.arena, | |
| 1863 | operand_ty, | |
| 1864 | true, | |
| 1865 | .One, | |
| 1866 | // TODO figure out which address space is appropriate here | |
| 1867 | target_util.defaultAddressSpace(sema.mod.getTarget(), .local), | |
| 1868 | ); | |
| 1825 | 1869 | const bitcasted_ptr = try block.addTyOp(.bitcast, ptr_ty, ptr); |
| 1826 | 1870 | return sema.storePtr(block, src, bitcasted_ptr, operand); |
| 1827 | 1871 | } |
| ... | ... | @@ -3004,7 +3048,7 @@ fn analyzeCall( |
| 3004 | 3048 | new_decl.is_pub = module_fn.owner_decl.is_pub; |
| 3005 | 3049 | new_decl.is_exported = module_fn.owner_decl.is_exported; |
| 3006 | 3050 | new_decl.has_align = module_fn.owner_decl.has_align; |
| 3007 | new_decl.has_linksection = module_fn.owner_decl.has_linksection; | |
| 3051 | new_decl.has_linksection_or_addrspace = module_fn.owner_decl.has_linksection_or_addrspace; | |
| 3008 | 3052 | new_decl.zir_decl_index = module_fn.owner_decl.zir_decl_index; |
| 3009 | 3053 | new_decl.alive = true; // This Decl is called at runtime. |
| 3010 | 3054 | new_decl.has_tv = true; |
| ... | ... | @@ -3658,7 +3702,13 @@ fn zirOptionalPayloadPtr( |
| 3658 | 3702 | } |
| 3659 | 3703 | |
| 3660 | 3704 | const child_type = try opt_type.optionalChildAlloc(sema.arena); |
| 3661 | const child_pointer = try Module.simplePtrType(sema.arena, child_type, !optional_ptr_ty.isConstPtr(), .One); | |
| 3705 | const child_pointer = try Module.simplePtrType( | |
| 3706 | sema.arena, | |
| 3707 | child_type, | |
| 3708 | !optional_ptr_ty.isConstPtr(), | |
| 3709 | .One, | |
| 3710 | optional_ptr_ty.ptrAddressSpace(), | |
| 3711 | ); | |
| 3662 | 3712 | |
| 3663 | 3713 | if (try sema.resolveDefinedValue(block, src, optional_ptr)) |pointer_val| { |
| 3664 | 3714 | if (try pointer_val.pointerDeref(sema.arena)) |val| { |
| ... | ... | @@ -3773,7 +3823,13 @@ fn zirErrUnionPayloadPtr( |
| 3773 | 3823 | return sema.mod.fail(&block.base, src, "expected error union type, found {}", .{operand_ty.elemType()}); |
| 3774 | 3824 | |
| 3775 | 3825 | const payload_ty = operand_ty.elemType().errorUnionPayload(); |
| 3776 | const operand_pointer_ty = try Module.simplePtrType(sema.arena, payload_ty, !operand_ty.isConstPtr(), .One); | |
| 3826 | const operand_pointer_ty = try Module.simplePtrType( | |
| 3827 | sema.arena, | |
| 3828 | payload_ty, | |
| 3829 | !operand_ty.isConstPtr(), | |
| 3830 | .One, | |
| 3831 | operand_ty.ptrAddressSpace(), | |
| 3832 | ); | |
| 3777 | 3833 | |
| 3778 | 3834 | if (try sema.resolveDefinedValue(block, src, operand)) |pointer_val| { |
| 3779 | 3835 | if (try pointer_val.pointerDeref(sema.arena)) |val| { |
| ... | ... | @@ -6879,6 +6935,7 @@ fn zirPtrTypeSimple(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) Comp |
| 6879 | 6935 | elem_type, |
| 6880 | 6936 | null, |
| 6881 | 6937 | 0, |
| 6938 | .generic, | |
| 6882 | 6939 | 0, |
| 6883 | 6940 | 0, |
| 6884 | 6941 | inst_data.is_mutable, |
| ... | ... | @@ -6911,6 +6968,12 @@ fn zirPtrType(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileErr |
| 6911 | 6968 | break :blk try sema.resolveAlreadyCoercedInt(block, .unneeded, ref, u32); |
| 6912 | 6969 | } else 0; |
| 6913 | 6970 | |
| 6971 | const address_space = if (inst_data.flags.has_addrspace) blk: { | |
| 6972 | const ref = @intToEnum(Zir.Inst.Ref, sema.code.extra[extra_i]); | |
| 6973 | extra_i += 1; | |
| 6974 | break :blk try sema.analyzeAddrspace(block, .unneeded, ref, .pointer); | |
| 6975 | } else .generic; | |
| 6976 | ||
| 6914 | 6977 | const bit_start = if (inst_data.flags.has_bit_range) blk: { |
| 6915 | 6978 | const ref = @intToEnum(Zir.Inst.Ref, sema.code.extra[extra_i]); |
| 6916 | 6979 | extra_i += 1; |
| ... | ... | @@ -6933,6 +6996,7 @@ fn zirPtrType(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileErr |
| 6933 | 6996 | elem_type, |
| 6934 | 6997 | sentinel, |
| 6935 | 6998 | abi_align, |
| 6999 | address_space, | |
| 6936 | 7000 | bit_start, |
| 6937 | 7001 | bit_end, |
| 6938 | 7002 | inst_data.flags.is_mutable, |
| ... | ... | @@ -8339,7 +8403,13 @@ fn panicWithMsg( |
| 8339 | 8403 | const panic_fn = try sema.getBuiltin(block, src, "panic"); |
| 8340 | 8404 | const unresolved_stack_trace_ty = try sema.getBuiltinType(block, src, "StackTrace"); |
| 8341 | 8405 | const stack_trace_ty = try sema.resolveTypeFields(block, src, unresolved_stack_trace_ty); |
| 8342 | const ptr_stack_trace_ty = try Module.simplePtrType(arena, stack_trace_ty, true, .One); | |
| 8406 | const ptr_stack_trace_ty = try Module.simplePtrType( | |
| 8407 | arena, | |
| 8408 | stack_trace_ty, | |
| 8409 | true, | |
| 8410 | .One, | |
| 8411 | target_util.defaultAddressSpace(sema.mod.getTarget(), .global_constant), // TODO might need a place that is more dynamic | |
| 8412 | ); | |
| 8343 | 8413 | const null_stack_trace = try sema.addConstant( |
| 8344 | 8414 | try Module.optionalType(arena, ptr_stack_trace_ty), |
| 8345 | 8415 | Value.initTag(.null_value), |
| ... | ... | @@ -8423,7 +8493,7 @@ fn fieldVal( |
| 8423 | 8493 | .Pointer => switch (object_ty.ptrSize()) { |
| 8424 | 8494 | .Slice => { |
| 8425 | 8495 | if (mem.eql(u8, field_name, "ptr")) { |
| 8426 | const buf = try arena.create(Type.Payload.ElemType); | |
| 8496 | const buf = try arena.create(Type.SlicePtrFieldTypeBuffer); | |
| 8427 | 8497 | const result_ty = object_ty.slicePtrFieldType(buf); |
| 8428 | 8498 | if (try sema.resolveMaybeUndefVal(block, object_src, object)) |val| { |
| 8429 | 8499 | if (val.isUndef()) return sema.addConstUndef(result_ty); |
| ... | ... | @@ -8457,21 +8527,32 @@ fn fieldVal( |
| 8457 | 8527 | } |
| 8458 | 8528 | }, |
| 8459 | 8529 | .One => { |
| 8460 | const elem_ty = object_ty.elemType(); | |
| 8461 | if (elem_ty.zigTypeTag() == .Array) { | |
| 8462 | if (mem.eql(u8, field_name, "len")) { | |
| 8463 | return sema.addConstant( | |
| 8464 | Type.initTag(.comptime_int), | |
| 8465 | try Value.Tag.int_u64.create(arena, elem_ty.arrayLen()), | |
| 8466 | ); | |
| 8467 | } else { | |
| 8468 | return mod.fail( | |
| 8469 | &block.base, | |
| 8470 | field_name_src, | |
| 8471 | "no member named '{s}' in '{}'", | |
| 8472 | .{ field_name, object_ty }, | |
| 8473 | ); | |
| 8474 | } | |
| 8530 | const ptr_child = object_ty.elemType(); | |
| 8531 | switch (ptr_child.zigTypeTag()) { | |
| 8532 | .Array => { | |
| 8533 | if (mem.eql(u8, field_name, "len")) { | |
| 8534 | return sema.addConstant( | |
| 8535 | Type.initTag(.comptime_int), | |
| 8536 | try Value.Tag.int_u64.create(arena, ptr_child.arrayLen()), | |
| 8537 | ); | |
| 8538 | } else { | |
| 8539 | return mod.fail( | |
| 8540 | &block.base, | |
| 8541 | field_name_src, | |
| 8542 | "no member named '{s}' in '{}'", | |
| 8543 | .{ field_name, object_ty }, | |
| 8544 | ); | |
| 8545 | } | |
| 8546 | }, | |
| 8547 | .Struct => { | |
| 8548 | const struct_ptr_deref = try sema.analyzeLoad(block, src, object, object_src); | |
| 8549 | return sema.unionFieldVal(block, src, struct_ptr_deref, field_name, field_name_src, ptr_child); | |
| 8550 | }, | |
| 8551 | .Union => { | |
| 8552 | const union_ptr_deref = try sema.analyzeLoad(block, src, object, object_src); | |
| 8553 | return sema.unionFieldVal(block, src, union_ptr_deref, field_name, field_name_src, ptr_child); | |
| 8554 | }, | |
| 8555 | else => {}, | |
| 8475 | 8556 | } |
| 8476 | 8557 | }, |
| 8477 | 8558 | .Many, .C => {}, |
| ... | ... | @@ -8595,9 +8676,8 @@ fn fieldPtr( |
| 8595 | 8676 | ); |
| 8596 | 8677 | } |
| 8597 | 8678 | }, |
| 8598 | .Pointer => { | |
| 8599 | const ptr_child = object_ty.elemType(); | |
| 8600 | if (ptr_child.isSlice()) { | |
| 8679 | .Pointer => switch (object_ty.ptrSize()) { | |
| 8680 | .Slice => { | |
| 8601 | 8681 | // Here for the ptr and len fields what we need to do is the situation |
| 8602 | 8682 | // when a temporary has its address taken, e.g. `&a[c..d].len`. |
| 8603 | 8683 | // This value may be known at compile-time or runtime. In the former |
| ... | ... | @@ -8627,26 +8707,39 @@ fn fieldPtr( |
| 8627 | 8707 | .{ field_name, object_ty }, |
| 8628 | 8708 | ); |
| 8629 | 8709 | } |
| 8630 | } else switch (ptr_child.zigTypeTag()) { | |
| 8631 | .Array => { | |
| 8632 | if (mem.eql(u8, field_name, "len")) { | |
| 8633 | var anon_decl = try block.startAnonDecl(); | |
| 8634 | defer anon_decl.deinit(); | |
| 8635 | return sema.analyzeDeclRef(try anon_decl.finish( | |
| 8636 | Type.initTag(.comptime_int), | |
| 8637 | try Value.Tag.int_u64.create(anon_decl.arena(), ptr_child.arrayLen()), | |
| 8638 | )); | |
| 8639 | } else { | |
| 8640 | return mod.fail( | |
| 8641 | &block.base, | |
| 8642 | field_name_src, | |
| 8643 | "no member named '{s}' in '{}'", | |
| 8644 | .{ field_name, object_ty }, | |
| 8645 | ); | |
| 8646 | } | |
| 8647 | }, | |
| 8648 | else => {}, | |
| 8649 | } | |
| 8710 | }, | |
| 8711 | .One => { | |
| 8712 | const ptr_child = object_ty.elemType(); | |
| 8713 | switch (ptr_child.zigTypeTag()) { | |
| 8714 | .Array => { | |
| 8715 | if (mem.eql(u8, field_name, "len")) { | |
| 8716 | var anon_decl = try block.startAnonDecl(); | |
| 8717 | defer anon_decl.deinit(); | |
| 8718 | return sema.analyzeDeclRef(try anon_decl.finish( | |
| 8719 | Type.initTag(.comptime_int), | |
| 8720 | try Value.Tag.int_u64.create(anon_decl.arena(), ptr_child.arrayLen()), | |
| 8721 | )); | |
| 8722 | } else { | |
| 8723 | return mod.fail( | |
| 8724 | &block.base, | |
| 8725 | field_name_src, | |
| 8726 | "no member named '{s}' in '{}'", | |
| 8727 | .{ field_name, object_ty }, | |
| 8728 | ); | |
| 8729 | } | |
| 8730 | }, | |
| 8731 | .Struct => { | |
| 8732 | const struct_ptr_deref = try sema.analyzeLoad(block, src, object_ptr, object_ptr_src); | |
| 8733 | return sema.structFieldPtr(block, src, struct_ptr_deref, field_name, field_name_src, ptr_child); | |
| 8734 | }, | |
| 8735 | .Union => { | |
| 8736 | const union_ptr_deref = try sema.analyzeLoad(block, src, object_ptr, object_ptr_src); | |
| 8737 | return sema.unionFieldPtr(block, src, union_ptr_deref, field_name, field_name_src, ptr_child); | |
| 8738 | }, | |
| 8739 | else => {}, | |
| 8740 | } | |
| 8741 | }, | |
| 8742 | .Many, .C => {}, | |
| 8650 | 8743 | }, |
| 8651 | 8744 | .Type => { |
| 8652 | 8745 | _ = try sema.resolveConstValue(block, object_ptr_src, object_ptr); |
| ... | ... | @@ -8788,13 +8881,20 @@ fn structFieldPtr( |
| 8788 | 8881 | const arena = sema.arena; |
| 8789 | 8882 | assert(unresolved_struct_ty.zigTypeTag() == .Struct); |
| 8790 | 8883 | |
| 8884 | const struct_ptr_ty = sema.typeOf(struct_ptr); | |
| 8791 | 8885 | const struct_ty = try sema.resolveTypeFields(block, src, unresolved_struct_ty); |
| 8792 | 8886 | const struct_obj = struct_ty.castTag(.@"struct").?.data; |
| 8793 | 8887 | |
| 8794 | 8888 | const field_index = struct_obj.fields.getIndex(field_name) orelse |
| 8795 | 8889 | return sema.failWithBadFieldAccess(block, struct_obj, field_name_src, field_name); |
| 8796 | 8890 | const field = struct_obj.fields.values()[field_index]; |
| 8797 | const ptr_field_ty = try Module.simplePtrType(arena, field.ty, true, .One); | |
| 8891 | const ptr_field_ty = try Module.simplePtrType( | |
| 8892 | arena, | |
| 8893 | field.ty, | |
| 8894 | struct_ptr_ty.ptrIsMutable(), | |
| 8895 | .One, | |
| 8896 | struct_ptr_ty.ptrAddressSpace(), | |
| 8897 | ); | |
| 8798 | 8898 | |
| 8799 | 8899 | if (try sema.resolveDefinedValue(block, src, struct_ptr)) |struct_ptr_val| { |
| 8800 | 8900 | return sema.addConstant( |
| ... | ... | @@ -8885,6 +8985,7 @@ fn unionFieldPtr( |
| 8885 | 8985 | const arena = sema.arena; |
| 8886 | 8986 | assert(unresolved_union_ty.zigTypeTag() == .Union); |
| 8887 | 8987 | |
| 8988 | const union_ptr_ty = sema.typeOf(union_ptr); | |
| 8888 | 8989 | const union_ty = try sema.resolveTypeFields(block, src, unresolved_union_ty); |
| 8889 | 8990 | const union_obj = union_ty.cast(Type.Payload.Union).?.data; |
| 8890 | 8991 | |
| ... | ... | @@ -8892,7 +8993,13 @@ fn unionFieldPtr( |
| 8892 | 8993 | return sema.failWithBadUnionFieldAccess(block, union_obj, field_name_src, field_name); |
| 8893 | 8994 | |
| 8894 | 8995 | const field = union_obj.fields.values()[field_index]; |
| 8895 | const ptr_field_ty = try Module.simplePtrType(arena, field.ty, true, .One); | |
| 8996 | const ptr_field_ty = try Module.simplePtrType( | |
| 8997 | arena, | |
| 8998 | field.ty, | |
| 8999 | union_ptr_ty.ptrIsMutable(), | |
| 9000 | .One, | |
| 9001 | union_ptr_ty.ptrAddressSpace(), | |
| 9002 | ); | |
| 8896 | 9003 | |
| 8897 | 9004 | if (try sema.resolveDefinedValue(block, src, union_ptr)) |union_ptr_val| { |
| 8898 | 9005 | // TODO detect inactive union field and emit compile error |
| ... | ... | @@ -9068,10 +9175,13 @@ fn elemPtrArray( |
| 9068 | 9175 | ) CompileError!Air.Inst.Ref { |
| 9069 | 9176 | const array_ptr_ty = sema.typeOf(array_ptr); |
| 9070 | 9177 | const pointee_type = array_ptr_ty.elemType().elemType(); |
| 9071 | const result_ty = if (array_ptr_ty.ptrIsMutable()) | |
| 9072 | try Type.Tag.single_mut_pointer.create(sema.arena, pointee_type) | |
| 9073 | else | |
| 9074 | try Type.Tag.single_const_pointer.create(sema.arena, pointee_type); | |
| 9178 | const result_ty = try Module.simplePtrType( | |
| 9179 | sema.arena, | |
| 9180 | pointee_type, | |
| 9181 | array_ptr_ty.ptrIsMutable(), | |
| 9182 | .One, | |
| 9183 | array_ptr_ty.ptrAddressSpace(), | |
| 9184 | ); | |
| 9075 | 9185 | |
| 9076 | 9186 | if (try sema.resolveDefinedValue(block, src, array_ptr)) |array_ptr_val| { |
| 9077 | 9187 | if (try sema.resolveDefinedValue(block, elem_index_src, elem_index)) |index_val| { |
| ... | ... | @@ -9162,6 +9272,7 @@ fn coerce( |
| 9162 | 9272 | const dest_is_mut = !dest_type.isConstPtr(); |
| 9163 | 9273 | if (inst_ty.isConstPtr() and dest_is_mut) break :src_array_ptr; |
| 9164 | 9274 | if (inst_ty.isVolatilePtr() and !dest_type.isVolatilePtr()) break :src_array_ptr; |
| 9275 | if (inst_ty.ptrAddressSpace() != dest_type.ptrAddressSpace()) break :src_array_ptr; | |
| 9165 | 9276 | |
| 9166 | 9277 | const dst_elem_type = dest_type.elemType(); |
| 9167 | 9278 | switch (coerceInMemoryAllowed(dst_elem_type, array_elem_type, dest_is_mut)) { |
| ... | ... | @@ -9297,6 +9408,10 @@ fn coerceInMemoryAllowed(dest_type: Type, src_type: Type, dest_is_mut: bool) InM |
| 9297 | 9408 | return child; |
| 9298 | 9409 | } |
| 9299 | 9410 | |
| 9411 | if (dest_info.@"addrspace" != src_info.@"addrspace") { | |
| 9412 | return .no_match; | |
| 9413 | } | |
| 9414 | ||
| 9300 | 9415 | const ok_sent = dest_info.sentinel == null or src_info.size == .C or |
| 9301 | 9416 | (src_info.sentinel != null and |
| 9302 | 9417 | dest_info.sentinel.?.eql(src_info.sentinel.?, dest_info.pointee_type)); |
| ... | ... | @@ -9590,11 +9705,11 @@ fn analyzeDeclRef(sema: *Sema, decl: *Decl) CompileError!Air.Inst.Ref { |
| 9590 | 9705 | const decl_tv = try decl.typedValue(); |
| 9591 | 9706 | if (decl_tv.val.castTag(.variable)) |payload| { |
| 9592 | 9707 | const variable = payload.data; |
| 9593 | const ty = try Module.simplePtrType(sema.arena, decl_tv.ty, variable.is_mutable, .One); | |
| 9708 | const ty = try Module.simplePtrType(sema.arena, decl_tv.ty, variable.is_mutable, .One, decl.@"addrspace"); | |
| 9594 | 9709 | return sema.addConstant(ty, try Value.Tag.decl_ref.create(sema.arena, decl)); |
| 9595 | 9710 | } |
| 9596 | 9711 | return sema.addConstant( |
| 9597 | try Module.simplePtrType(sema.arena, decl_tv.ty, false, .One), | |
| 9712 | try Module.simplePtrType(sema.arena, decl_tv.ty, false, .One, decl.@"addrspace"), | |
| 9598 | 9713 | try Value.Tag.decl_ref.create(sema.arena, decl), |
| 9599 | 9714 | ); |
| 9600 | 9715 | } |
| ... | ... | @@ -9617,8 +9732,9 @@ fn analyzeRef( |
| 9617 | 9732 | } |
| 9618 | 9733 | |
| 9619 | 9734 | try sema.requireRuntimeBlock(block, src); |
| 9620 | const ptr_type = try Module.simplePtrType(sema.arena, operand_ty, false, .One); | |
| 9621 | const mut_ptr_type = try Module.simplePtrType(sema.arena, operand_ty, true, .One); | |
| 9735 | const address_space = target_util.defaultAddressSpace(sema.mod.getTarget(), .local); | |
| 9736 | const ptr_type = try Module.simplePtrType(sema.arena, operand_ty, false, .One, address_space); | |
| 9737 | const mut_ptr_type = try Module.simplePtrType(sema.arena, operand_ty, true, .One, address_space); | |
| 9622 | 9738 | const alloc = try block.addTy(.alloc, mut_ptr_type); |
| 9623 | 9739 | try sema.storePtr(block, src, alloc, operand); |
| 9624 | 9740 | |
| ... | ... | @@ -9779,6 +9895,7 @@ fn analyzeSlice( |
| 9779 | 9895 | return_elem_type, |
| 9780 | 9896 | if (end_opt == .none) slice_sentinel else null, |
| 9781 | 9897 | 0, // TODO alignment |
| 9898 | if (ptr_child.zigTypeTag() == .Pointer) ptr_child.ptrAddressSpace() else .generic, | |
| 9782 | 9899 | 0, |
| 9783 | 9900 | 0, |
| 9784 | 9901 | !ptr_child.isConstPtr(), |
| ... | ... | @@ -10286,6 +10403,7 @@ fn resolveTypeFields(sema: *Sema, block: *Scope.Block, src: LazySrcLoc, ty: Type |
| 10286 | 10403 | .atomic_order => return sema.resolveBuiltinTypeFields(block, src, "AtomicOrder"), |
| 10287 | 10404 | .atomic_rmw_op => return sema.resolveBuiltinTypeFields(block, src, "AtomicRmwOp"), |
| 10288 | 10405 | .calling_convention => return sema.resolveBuiltinTypeFields(block, src, "CallingConvention"), |
| 10406 | .address_space => return sema.resolveBuiltinTypeFields(block, src, "AddressSpace"), | |
| 10289 | 10407 | .float_mode => return sema.resolveBuiltinTypeFields(block, src, "FloatMode"), |
| 10290 | 10408 | .reduce_op => return sema.resolveBuiltinTypeFields(block, src, "ReduceOp"), |
| 10291 | 10409 | .call_options => return sema.resolveBuiltinTypeFields(block, src, "CallOptions"), |
| ... | ... | @@ -10680,6 +10798,7 @@ fn typeHasOnePossibleValue( |
| 10680 | 10798 | .atomic_order, |
| 10681 | 10799 | .atomic_rmw_op, |
| 10682 | 10800 | .calling_convention, |
| 10801 | .address_space, | |
| 10683 | 10802 | .float_mode, |
| 10684 | 10803 | .reduce_op, |
| 10685 | 10804 | .call_options, |
| ... | ... | @@ -10865,6 +10984,7 @@ pub fn addType(sema: *Sema, ty: Type) !Air.Inst.Ref { |
| 10865 | 10984 | .atomic_order => return .atomic_order_type, |
| 10866 | 10985 | .atomic_rmw_op => return .atomic_rmw_op_type, |
| 10867 | 10986 | .calling_convention => return .calling_convention_type, |
| 10987 | .address_space => return .address_space_type, | |
| 10868 | 10988 | .float_mode => return .float_mode_type, |
| 10869 | 10989 | .reduce_op => return .reduce_op_type, |
| 10870 | 10990 | .call_options => return .call_options_type, |
| ... | ... | @@ -10960,7 +11080,13 @@ fn analyzeComptimeAlloc( |
| 10960 | 11080 | block: *Scope.Block, |
| 10961 | 11081 | var_type: Type, |
| 10962 | 11082 | ) CompileError!Air.Inst.Ref { |
| 10963 | const ptr_type = try Module.simplePtrType(sema.arena, var_type, true, .One); | |
| 11083 | const ptr_type = try Module.simplePtrType( | |
| 11084 | sema.arena, | |
| 11085 | var_type, | |
| 11086 | true, | |
| 11087 | .One, | |
| 11088 | target_util.defaultAddressSpace(sema.mod.getTarget(), .global_constant), | |
| 11089 | ); | |
| 10964 | 11090 | |
| 10965 | 11091 | var anon_decl = try block.startAnonDecl(); |
| 10966 | 11092 | defer anon_decl.deinit(); |
| ... | ... | @@ -10976,3 +11102,58 @@ fn analyzeComptimeAlloc( |
| 10976 | 11102 | .decl = decl, |
| 10977 | 11103 | })); |
| 10978 | 11104 | } |
| 11105 | ||
| 11106 | /// The places where a user can specify an address space attribute | |
| 11107 | pub const AddressSpaceContext = enum { | |
| 11108 | /// A function is specificed to be placed in a certain address space. | |
| 11109 | function, | |
| 11110 | ||
| 11111 | /// A (global) variable is specified to be placed in a certain address space. | |
| 11112 | /// In contrast to .constant, these values (and thus the address space they will be | |
| 11113 | /// placed in) are required to be mutable. | |
| 11114 | variable, | |
| 11115 | ||
| 11116 | /// A (global) constant value is specified to be placed in a certain address space. | |
| 11117 | /// In contrast to .variable, values placed in this address space are not required to be mutable. | |
| 11118 | constant, | |
| 11119 | ||
| 11120 | /// A pointer is ascripted to point into a certian address space. | |
| 11121 | pointer, | |
| 11122 | }; | |
| 11123 | ||
| 11124 | pub fn analyzeAddrspace( | |
| 11125 | sema: *Sema, | |
| 11126 | block: *Scope.Block, | |
| 11127 | src: LazySrcLoc, | |
| 11128 | zir_ref: Zir.Inst.Ref, | |
| 11129 | ctx: AddressSpaceContext, | |
| 11130 | ) !std.builtin.AddressSpace { | |
| 11131 | const addrspace_tv = try sema.resolveInstConst(block, src, zir_ref); | |
| 11132 | const address_space = addrspace_tv.val.toEnum(std.builtin.AddressSpace); | |
| 11133 | const target = sema.mod.getTarget(); | |
| 11134 | const arch = target.cpu.arch; | |
| 11135 | ||
| 11136 | const supported = switch (address_space) { | |
| 11137 | .generic => true, | |
| 11138 | .gs, .fs, .ss => (arch == .i386 or arch == .x86_64) and ctx == .pointer, | |
| 11139 | }; | |
| 11140 | ||
| 11141 | if (!supported) { | |
| 11142 | // TODO error messages could be made more elaborate here | |
| 11143 | const entity = switch (ctx) { | |
| 11144 | .function => "functions", | |
| 11145 | .variable => "mutable values", | |
| 11146 | .constant => "constant values", | |
| 11147 | .pointer => "pointers", | |
| 11148 | }; | |
| 11149 | ||
| 11150 | return sema.mod.fail( | |
| 11151 | &block.base, | |
| 11152 | src, | |
| 11153 | "{s} with address space '{s}' are not supported on {s}", | |
| 11154 | .{ entity, @tagName(address_space), arch.genericName() }, | |
| 11155 | ); | |
| 11156 | } | |
| 11157 | ||
| 11158 | return address_space; | |
| 11159 | } |
src/Zir.zig+33-14| ... | ... | @@ -443,10 +443,10 @@ pub const Inst = struct { |
| 443 | 443 | /// this instruction; a following 'ret' instruction will do the diversion. |
| 444 | 444 | /// Uses the `str_tok` union field. |
| 445 | 445 | ret_err_value_code, |
| 446 | /// Create a pointer type that does not have a sentinel, alignment, or bit range specified. | |
| 446 | /// Create a pointer type that does not have a sentinel, alignment, address space, or bit range specified. | |
| 447 | 447 | /// Uses the `ptr_type_simple` union field. |
| 448 | 448 | ptr_type_simple, |
| 449 | /// Create a pointer type which can have a sentinel, alignment, and/or bit range. | |
| 449 | /// Create a pointer type which can have a sentinel, alignment, address space, and/or bit range. | |
| 450 | 450 | /// Uses the `ptr_type` union field. |
| 451 | 451 | ptr_type, |
| 452 | 452 | /// Slice operation `lhs[rhs..]`. No sentinel and no end offset. |
| ... | ... | @@ -1672,6 +1672,7 @@ pub const Inst = struct { |
| 1672 | 1672 | atomic_order_type, |
| 1673 | 1673 | atomic_rmw_op_type, |
| 1674 | 1674 | calling_convention_type, |
| 1675 | address_space_type, | |
| 1675 | 1676 | float_mode_type, |
| 1676 | 1677 | reduce_op_type, |
| 1677 | 1678 | call_options_type, |
| ... | ... | @@ -1928,6 +1929,10 @@ pub const Inst = struct { |
| 1928 | 1929 | .ty = Type.initTag(.type), |
| 1929 | 1930 | .val = Value.initTag(.calling_convention_type), |
| 1930 | 1931 | }, |
| 1932 | .address_space_type = .{ | |
| 1933 | .ty = Type.initTag(.type), | |
| 1934 | .val = Value.initTag(.address_space_type), | |
| 1935 | }, | |
| 1931 | 1936 | .float_mode_type = .{ |
| 1932 | 1937 | .ty = Type.initTag(.type), |
| 1933 | 1938 | .val = Value.initTag(.float_mode_type), |
| ... | ... | @@ -2129,8 +2134,9 @@ pub const Inst = struct { |
| 2129 | 2134 | is_volatile: bool, |
| 2130 | 2135 | has_sentinel: bool, |
| 2131 | 2136 | has_align: bool, |
| 2137 | has_addrspace: bool, | |
| 2132 | 2138 | has_bit_range: bool, |
| 2133 | _: u2 = undefined, | |
| 2139 | _: u1 = undefined, | |
| 2134 | 2140 | }, |
| 2135 | 2141 | size: std.builtin.TypeInfo.Pointer.Size, |
| 2136 | 2142 | /// Index into extra. See `PtrType`. |
| ... | ... | @@ -2360,12 +2366,13 @@ pub const Inst = struct { |
| 2360 | 2366 | else_body_len: u32, |
| 2361 | 2367 | }; |
| 2362 | 2368 | |
| 2363 | /// Stored in extra. Depending on the flags in Data, there will be up to 4 | |
| 2369 | /// Stored in extra. Depending on the flags in Data, there will be up to 5 | |
| 2364 | 2370 | /// trailing Ref fields: |
| 2365 | 2371 | /// 0. sentinel: Ref // if `has_sentinel` flag is set |
| 2366 | 2372 | /// 1. align: Ref // if `has_align` flag is set |
| 2367 | /// 2. bit_start: Ref // if `has_bit_range` flag is set | |
| 2368 | /// 3. bit_end: Ref // if `has_bit_range` flag is set | |
| 2373 | /// 2. address_space: Ref // if `has_addrspace` flag is set | |
| 2374 | /// 3. bit_start: Ref // if `has_bit_range` flag is set | |
| 2375 | /// 4. bit_end: Ref // if `has_bit_range` flag is set | |
| 2369 | 2376 | pub const PtrType = struct { |
| 2370 | 2377 | elem_type: Ref, |
| 2371 | 2378 | }; |
| ... | ... | @@ -2483,7 +2490,7 @@ pub const Inst = struct { |
| 2483 | 2490 | /// 0b000X: whether corresponding decl is pub |
| 2484 | 2491 | /// 0b00X0: whether corresponding decl is exported |
| 2485 | 2492 | /// 0b0X00: whether corresponding decl has an align expression |
| 2486 | /// 0bX000: whether corresponding decl has a linksection expression | |
| 2493 | /// 0bX000: whether corresponding decl has a linksection or an address space expression | |
| 2487 | 2494 | /// 5. decl: { // for every decls_len |
| 2488 | 2495 | /// src_hash: [4]u32, // hash of source bytes |
| 2489 | 2496 | /// line: u32, // line number of decl, relative to parent |
| ... | ... | @@ -2495,7 +2502,10 @@ pub const Inst = struct { |
| 2495 | 2502 | /// this is a test decl, and the name starts at `name+1`. |
| 2496 | 2503 | /// value: Index, |
| 2497 | 2504 | /// align: Ref, // if corresponding bit is set |
| 2498 | /// link_section: Ref, // if corresponding bit is set | |
| 2505 | /// link_section_or_address_space: { // if corresponding bit is set. | |
| 2506 | /// link_section: Ref, | |
| 2507 | /// address_space: Ref, | |
| 2508 | /// } | |
| 2499 | 2509 | /// } |
| 2500 | 2510 | /// 6. inst: Index // for every body_len |
| 2501 | 2511 | /// 7. flags: u32 // for every 8 fields |
| ... | ... | @@ -2547,7 +2557,7 @@ pub const Inst = struct { |
| 2547 | 2557 | /// 0b000X: whether corresponding decl is pub |
| 2548 | 2558 | /// 0b00X0: whether corresponding decl is exported |
| 2549 | 2559 | /// 0b0X00: whether corresponding decl has an align expression |
| 2550 | /// 0bX000: whether corresponding decl has a linksection expression | |
| 2560 | /// 0bX000: whether corresponding decl has a linksection or an address space expression | |
| 2551 | 2561 | /// 6. decl: { // for every decls_len |
| 2552 | 2562 | /// src_hash: [4]u32, // hash of source bytes |
| 2553 | 2563 | /// line: u32, // line number of decl, relative to parent |
| ... | ... | @@ -2559,7 +2569,10 @@ pub const Inst = struct { |
| 2559 | 2569 | /// this is a test decl, and the name starts at `name+1`. |
| 2560 | 2570 | /// value: Index, |
| 2561 | 2571 | /// align: Ref, // if corresponding bit is set |
| 2562 | /// link_section: Ref, // if corresponding bit is set | |
| 2572 | /// link_section_or_address_space: { // if corresponding bit is set. | |
| 2573 | /// link_section: Ref, | |
| 2574 | /// address_space: Ref, | |
| 2575 | /// } | |
| 2563 | 2576 | /// } |
| 2564 | 2577 | /// 7. inst: Index // for every body_len |
| 2565 | 2578 | /// 8. has_bits: u32 // for every 32 fields |
| ... | ... | @@ -2592,7 +2605,7 @@ pub const Inst = struct { |
| 2592 | 2605 | /// 0b000X: whether corresponding decl is pub |
| 2593 | 2606 | /// 0b00X0: whether corresponding decl is exported |
| 2594 | 2607 | /// 0b0X00: whether corresponding decl has an align expression |
| 2595 | /// 0bX000: whether corresponding decl has a linksection expression | |
| 2608 | /// 0bX000: whether corresponding decl has a linksection or an address space expression | |
| 2596 | 2609 | /// 6. decl: { // for every decls_len |
| 2597 | 2610 | /// src_hash: [4]u32, // hash of source bytes |
| 2598 | 2611 | /// line: u32, // line number of decl, relative to parent |
| ... | ... | @@ -2604,7 +2617,10 @@ pub const Inst = struct { |
| 2604 | 2617 | /// this is a test decl, and the name starts at `name+1`. |
| 2605 | 2618 | /// value: Index, |
| 2606 | 2619 | /// align: Ref, // if corresponding bit is set |
| 2607 | /// link_section: Ref, // if corresponding bit is set | |
| 2620 | /// link_section_or_address_space: { // if corresponding bit is set. | |
| 2621 | /// link_section: Ref, | |
| 2622 | /// address_space: Ref, | |
| 2623 | /// } | |
| 2608 | 2624 | /// } |
| 2609 | 2625 | /// 7. inst: Index // for every body_len |
| 2610 | 2626 | /// 8. has_bits: u32 // for every 8 fields |
| ... | ... | @@ -2641,7 +2657,7 @@ pub const Inst = struct { |
| 2641 | 2657 | /// 0b000X: whether corresponding decl is pub |
| 2642 | 2658 | /// 0b00X0: whether corresponding decl is exported |
| 2643 | 2659 | /// 0b0X00: whether corresponding decl has an align expression |
| 2644 | /// 0bX000: whether corresponding decl has a linksection expression | |
| 2660 | /// 0bX000: whether corresponding decl has a linksection or an address space expression | |
| 2645 | 2661 | /// 1. decl: { // for every decls_len |
| 2646 | 2662 | /// src_hash: [4]u32, // hash of source bytes |
| 2647 | 2663 | /// line: u32, // line number of decl, relative to parent |
| ... | ... | @@ -2653,7 +2669,10 @@ pub const Inst = struct { |
| 2653 | 2669 | /// this is a test decl, and the name starts at `name+1`. |
| 2654 | 2670 | /// value: Index, |
| 2655 | 2671 | /// align: Ref, // if corresponding bit is set |
| 2656 | /// link_section: Ref, // if corresponding bit is set | |
| 2672 | /// link_section_or_address_space: { // if corresponding bit is set. | |
| 2673 | /// link_section: Ref, | |
| 2674 | /// address_space: Ref, | |
| 2675 | /// } | |
| 2657 | 2676 | /// } |
| 2658 | 2677 | pub const OpaqueDecl = struct { |
| 2659 | 2678 | decls_len: u32, |
src/codegen.zig+1-1| ... | ... | @@ -4895,7 +4895,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { |
| 4895 | 4895 | switch (typed_value.ty.zigTypeTag()) { |
| 4896 | 4896 | .Pointer => switch (typed_value.ty.ptrSize()) { |
| 4897 | 4897 | .Slice => { |
| 4898 | var buf: Type.Payload.ElemType = undefined; | |
| 4898 | var buf: Type.SlicePtrFieldTypeBuffer = undefined; | |
| 4899 | 4899 | const ptr_type = typed_value.ty.slicePtrFieldType(&buf); |
| 4900 | 4900 | const ptr_mcv = try self.genTypedValue(.{ .ty = ptr_type, .val = typed_value.val }); |
| 4901 | 4901 | const slice_len = typed_value.val.sliceLen(); |
src/codegen/c.zig+1-1| ... | ... | @@ -251,7 +251,7 @@ pub const DeclGen = struct { |
| 251 | 251 | try writer.writeByte('('); |
| 252 | 252 | try dg.renderType(writer, t); |
| 253 | 253 | try writer.writeAll("){"); |
| 254 | var buf: Type.Payload.ElemType = undefined; | |
| 254 | var buf: Type.SlicePtrFieldTypeBuffer = undefined; | |
| 255 | 255 | try dg.renderValue(writer, t.slicePtrFieldType(&buf), val); |
| 256 | 256 | try writer.writeAll(", "); |
| 257 | 257 | try writer.print("{d}", .{val.sliceLen()}); |
src/codegen/llvm.zig+30-8| ... | ... | @@ -558,7 +558,8 @@ pub const DeclGen = struct { |
| 558 | 558 | llvm_params_len, |
| 559 | 559 | .False, |
| 560 | 560 | ); |
| 561 | const llvm_fn = self.llvmModule().addFunction(decl.name, fn_type); | |
| 561 | const llvm_addrspace = self.llvmAddressSpace(decl.@"addrspace"); | |
| 562 | const llvm_fn = self.llvmModule().addFunctionInAddressSpace(decl.name, fn_type, llvm_addrspace); | |
| 562 | 563 | |
| 563 | 564 | const is_extern = decl.val.tag() == .extern_fn; |
| 564 | 565 | if (!is_extern) { |
| ... | ... | @@ -580,7 +581,24 @@ pub const DeclGen = struct { |
| 580 | 581 | if (llvm_module.getNamedGlobal(decl.name)) |val| return val; |
| 581 | 582 | // TODO: remove this redundant `llvmType`, it is also called in `genTypedValue`. |
| 582 | 583 | const llvm_type = try self.llvmType(decl.ty); |
| 583 | return llvm_module.addGlobal(llvm_type, decl.name); | |
| 584 | const llvm_addrspace = self.llvmAddressSpace(decl.@"addrspace"); | |
| 585 | return llvm_module.addGlobalInAddressSpace(llvm_type, decl.name, llvm_addrspace); | |
| 586 | } | |
| 587 | ||
| 588 | fn llvmAddressSpace(self: DeclGen, address_space: std.builtin.AddressSpace) c_uint { | |
| 589 | const target = self.module.getTarget(); | |
| 590 | return switch (target.cpu.arch) { | |
| 591 | .i386, .x86_64 => switch (address_space) { | |
| 592 | .generic => llvm.address_space.default, | |
| 593 | .gs => llvm.address_space.x86.gs, | |
| 594 | .fs => llvm.address_space.x86.fs, | |
| 595 | .ss => llvm.address_space.x86.ss, | |
| 596 | }, | |
| 597 | else => switch (address_space) { | |
| 598 | .generic => llvm.address_space.default, | |
| 599 | else => unreachable, | |
| 600 | }, | |
| 601 | }; | |
| 584 | 602 | } |
| 585 | 603 | |
| 586 | 604 | fn llvmType(self: *DeclGen, t: Type) error{ OutOfMemory, CodegenFail }!*const llvm.Type { |
| ... | ... | @@ -609,7 +627,7 @@ pub const DeclGen = struct { |
| 609 | 627 | .Bool => return self.context.intType(1), |
| 610 | 628 | .Pointer => { |
| 611 | 629 | if (t.isSlice()) { |
| 612 | var buf: Type.Payload.ElemType = undefined; | |
| 630 | var buf: Type.SlicePtrFieldTypeBuffer = undefined; | |
| 613 | 631 | const ptr_type = t.slicePtrFieldType(&buf); |
| 614 | 632 | |
| 615 | 633 | const fields: [2]*const llvm.Type = .{ |
| ... | ... | @@ -619,7 +637,8 @@ pub const DeclGen = struct { |
| 619 | 637 | return self.context.structType(&fields, fields.len, .False); |
| 620 | 638 | } else { |
| 621 | 639 | const elem_type = try self.llvmType(t.elemType()); |
| 622 | return elem_type.pointerType(0); | |
| 640 | const llvm_addrspace = self.llvmAddressSpace(t.ptrAddressSpace()); | |
| 641 | return elem_type.pointerType(llvm_addrspace); | |
| 623 | 642 | } |
| 624 | 643 | }, |
| 625 | 644 | .Array => { |
| ... | ... | @@ -685,7 +704,9 @@ pub const DeclGen = struct { |
| 685 | 704 | @intCast(c_uint, llvm_params.len), |
| 686 | 705 | llvm.Bool.fromBool(is_var_args), |
| 687 | 706 | ); |
| 688 | return llvm_fn_ty.pointerType(0); | |
| 707 | // TODO make .Fn not both a pointer type and a prototype | |
| 708 | const llvm_addrspace = self.llvmAddressSpace(.generic); | |
| 709 | return llvm_fn_ty.pointerType(llvm_addrspace); | |
| 689 | 710 | }, |
| 690 | 711 | .ComptimeInt => unreachable, |
| 691 | 712 | .ComptimeFloat => unreachable, |
| ... | ... | @@ -753,7 +774,7 @@ pub const DeclGen = struct { |
| 753 | 774 | .Pointer => switch (tv.val.tag()) { |
| 754 | 775 | .decl_ref => { |
| 755 | 776 | if (tv.ty.isSlice()) { |
| 756 | var buf: Type.Payload.ElemType = undefined; | |
| 777 | var buf: Type.SlicePtrFieldTypeBuffer = undefined; | |
| 757 | 778 | const ptr_ty = tv.ty.slicePtrFieldType(&buf); |
| 758 | 779 | var slice_len: Value.Payload.U64 = .{ |
| 759 | 780 | .base = .{ .tag = .int_u64 }, |
| ... | ... | @@ -783,12 +804,13 @@ pub const DeclGen = struct { |
| 783 | 804 | decl.alive = true; |
| 784 | 805 | const val = try self.resolveGlobalDecl(decl); |
| 785 | 806 | const llvm_var_type = try self.llvmType(tv.ty); |
| 786 | const llvm_type = llvm_var_type.pointerType(0); | |
| 807 | const llvm_addrspace = self.llvmAddressSpace(decl.@"addrspace"); | |
| 808 | const llvm_type = llvm_var_type.pointerType(llvm_addrspace); | |
| 787 | 809 | return val.constBitCast(llvm_type); |
| 788 | 810 | }, |
| 789 | 811 | .slice => { |
| 790 | 812 | const slice = tv.val.castTag(.slice).?.data; |
| 791 | var buf: Type.Payload.ElemType = undefined; | |
| 813 | var buf: Type.SlicePtrFieldTypeBuffer = undefined; | |
| 792 | 814 | const fields: [2]*const llvm.Value = .{ |
| 793 | 815 | try self.genTypedValue(.{ |
| 794 | 816 | .ty = tv.ty.slicePtrFieldType(&buf), |
src/codegen/llvm/bindings.zig+68| ... | ... | @@ -197,6 +197,9 @@ pub const Module = opaque { |
| 197 | 197 | pub const addFunction = LLVMAddFunction; |
| 198 | 198 | extern fn LLVMAddFunction(*const Module, Name: [*:0]const u8, FunctionTy: *const Type) *const Value; |
| 199 | 199 | |
| 200 | pub const addFunctionInAddressSpace = ZigLLVMAddFunctionInAddressSpace; | |
| 201 | extern fn ZigLLVMAddFunctionInAddressSpace(*const Module, Name: [*:0]const u8, FunctionTy: *const Type, AddressSpace: c_uint) *const Value; | |
| 202 | ||
| 200 | 203 | pub const getNamedFunction = LLVMGetNamedFunction; |
| 201 | 204 | extern fn LLVMGetNamedFunction(*const Module, Name: [*:0]const u8) ?*const Value; |
| 202 | 205 | |
| ... | ... | @@ -209,6 +212,9 @@ pub const Module = opaque { |
| 209 | 212 | pub const addGlobal = LLVMAddGlobal; |
| 210 | 213 | extern fn LLVMAddGlobal(M: *const Module, Ty: *const Type, Name: [*:0]const u8) *const Value; |
| 211 | 214 | |
| 215 | pub const addGlobalInAddressSpace = LLVMAddGlobalInAddressSpace; | |
| 216 | extern fn LLVMAddGlobalInAddressSpace(M: *const Module, Ty: *const Type, Name: [*:0]const u8, AddressSpace: c_uint) *const Value; | |
| 217 | ||
| 212 | 218 | pub const getNamedGlobal = LLVMGetNamedGlobal; |
| 213 | 219 | extern fn LLVMGetNamedGlobal(M: *const Module, Name: [*:0]const u8) ?*const Value; |
| 214 | 220 | |
| ... | ... | @@ -1005,3 +1011,65 @@ pub const TypeKind = enum(c_int) { |
| 1005 | 1011 | BFloat, |
| 1006 | 1012 | X86_AMX, |
| 1007 | 1013 | }; |
| 1014 | ||
| 1015 | pub const address_space = struct { | |
| 1016 | pub const default: c_uint = 0; | |
| 1017 | ||
| 1018 | // See llvm/lib/Target/X86/X86.h | |
| 1019 | pub const x86_64 = x86; | |
| 1020 | pub const x86 = struct { | |
| 1021 | pub const gs: c_uint = 256; | |
| 1022 | pub const fs: c_uint = 257; | |
| 1023 | pub const ss: c_uint = 258; | |
| 1024 | ||
| 1025 | pub const ptr32_sptr: c_uint = 270; | |
| 1026 | pub const ptr32_uptr: c_uint = 271; | |
| 1027 | pub const ptr64: c_uint = 272; | |
| 1028 | }; | |
| 1029 | ||
| 1030 | // See llvm/lib/Target/AVR/AVR.h | |
| 1031 | pub const avr = struct { | |
| 1032 | pub const data_memory: c_uint = 0; | |
| 1033 | pub const program_memory: c_uint = 1; | |
| 1034 | }; | |
| 1035 | ||
| 1036 | // See llvm/lib/Target/NVPTX/NVPTX.h | |
| 1037 | pub const nvptx = struct { | |
| 1038 | pub const generic: c_uint = 0; | |
| 1039 | pub const global: c_uint = 1; | |
| 1040 | pub const constant: c_uint = 2; | |
| 1041 | pub const shared: c_uint = 3; | |
| 1042 | pub const param: c_uint = 4; | |
| 1043 | pub const local: c_uint = 5; | |
| 1044 | }; | |
| 1045 | ||
| 1046 | // See llvm/lib/Target/AMDGPU/AMDGPU.h | |
| 1047 | pub const amdgpu = struct { | |
| 1048 | pub const flat: c_uint = 0; | |
| 1049 | pub const global: c_uint = 1; | |
| 1050 | pub const region: c_uint = 2; | |
| 1051 | pub const local: c_uint = 3; | |
| 1052 | pub const constant: c_uint = 4; | |
| 1053 | pub const private: c_uint = 5; | |
| 1054 | pub const constant_32bit: c_uint = 6; | |
| 1055 | pub const buffer_fat_pointer: c_uint = 7; | |
| 1056 | pub const param_d: c_uint = 6; | |
| 1057 | pub const param_i: c_uint = 7; | |
| 1058 | pub const constant_buffer_0: c_uint = 8; | |
| 1059 | pub const constant_buffer_1: c_uint = 9; | |
| 1060 | pub const constant_buffer_2: c_uint = 10; | |
| 1061 | pub const constant_buffer_3: c_uint = 11; | |
| 1062 | pub const constant_buffer_4: c_uint = 12; | |
| 1063 | pub const constant_buffer_5: c_uint = 13; | |
| 1064 | pub const constant_buffer_6: c_uint = 14; | |
| 1065 | pub const constant_buffer_7: c_uint = 15; | |
| 1066 | pub const constant_buffer_8: c_uint = 16; | |
| 1067 | pub const constant_buffer_9: c_uint = 17; | |
| 1068 | pub const constant_buffer_10: c_uint = 18; | |
| 1069 | pub const constant_buffer_11: c_uint = 19; | |
| 1070 | pub const constant_buffer_12: c_uint = 20; | |
| 1071 | pub const constant_buffer_13: c_uint = 21; | |
| 1072 | pub const constant_buffer_14: c_uint = 22; | |
| 1073 | pub const constant_buffer_15: c_uint = 23; | |
| 1074 | }; | |
| 1075 | }; |
src/print_zir.zig+12-2| ... | ... | @@ -1147,7 +1147,7 @@ const Writer = struct { |
| 1147 | 1147 | cur_bit_bag >>= 1; |
| 1148 | 1148 | const has_align = @truncate(u1, cur_bit_bag) != 0; |
| 1149 | 1149 | cur_bit_bag >>= 1; |
| 1150 | const has_section = @truncate(u1, cur_bit_bag) != 0; | |
| 1150 | const has_section_or_addrspace = @truncate(u1, cur_bit_bag) != 0; | |
| 1151 | 1151 | cur_bit_bag >>= 1; |
| 1152 | 1152 | |
| 1153 | 1153 | const sub_index = extra_index; |
| ... | ... | @@ -1165,7 +1165,12 @@ const Writer = struct { |
| 1165 | 1165 | extra_index += 1; |
| 1166 | 1166 | break :inst inst; |
| 1167 | 1167 | }; |
| 1168 | const section_inst: Zir.Inst.Ref = if (!has_section) .none else inst: { | |
| 1168 | const section_inst: Zir.Inst.Ref = if (!has_section_or_addrspace) .none else inst: { | |
| 1169 | const inst = @intToEnum(Zir.Inst.Ref, self.code.extra[extra_index]); | |
| 1170 | extra_index += 1; | |
| 1171 | break :inst inst; | |
| 1172 | }; | |
| 1173 | const addrspace_inst: Zir.Inst.Ref = if (!has_section_or_addrspace) .none else inst: { | |
| 1169 | 1174 | const inst = @intToEnum(Zir.Inst.Ref, self.code.extra[extra_index]); |
| 1170 | 1175 | extra_index += 1; |
| 1171 | 1176 | break :inst inst; |
| ... | ... | @@ -1196,6 +1201,11 @@ const Writer = struct { |
| 1196 | 1201 | try self.writeInstRef(stream, align_inst); |
| 1197 | 1202 | try stream.writeAll(")"); |
| 1198 | 1203 | } |
| 1204 | if (addrspace_inst != .none) { | |
| 1205 | try stream.writeAll(" addrspace("); | |
| 1206 | try self.writeInstRef(stream, addrspace_inst); | |
| 1207 | try stream.writeAll(")"); | |
| 1208 | } | |
| 1199 | 1209 | if (section_inst != .none) { |
| 1200 | 1210 | try stream.writeAll(" linksection("); |
| 1201 | 1211 | try self.writeInstRef(stream, section_inst); |
src/stage1/all_types.hpp+8| ... | ... | @@ -86,6 +86,14 @@ enum CallingConvention { |
| 86 | 86 | CallingConventionSysV |
| 87 | 87 | }; |
| 88 | 88 | |
| 89 | // Stage 1 supports only the generic address space | |
| 90 | enum AddressSpace { | |
| 91 | AddressSpaceGeneric, | |
| 92 | AddressSpaceGS, | |
| 93 | AddressSpaceFS, | |
| 94 | AddressSpaceSS, | |
| 95 | }; | |
| 96 | ||
| 89 | 97 | // This one corresponds to the builtin.zig enum. |
| 90 | 98 | enum BuiltinPtrSize { |
| 91 | 99 | BuiltinPtrSizeOne, |
src/stage1/analyze.cpp+10| ... | ... | @@ -1019,6 +1019,16 @@ bool calling_convention_allows_zig_types(CallingConvention cc) { |
| 1019 | 1019 | zig_unreachable(); |
| 1020 | 1020 | } |
| 1021 | 1021 | |
| 1022 | const char *address_space_name(AddressSpace as) { | |
| 1023 | switch (as) { | |
| 1024 | case AddressSpaceGeneric: return "generic"; | |
| 1025 | case AddressSpaceGS: return "gs"; | |
| 1026 | case AddressSpaceFS: return "fs"; | |
| 1027 | case AddressSpaceSS: return "ss"; | |
| 1028 | } | |
| 1029 | zig_unreachable(); | |
| 1030 | } | |
| 1031 | ||
| 1022 | 1032 | ZigType *get_stack_trace_type(CodeGen *g) { |
| 1023 | 1033 | if (g->stack_trace_type == nullptr) { |
| 1024 | 1034 | g->stack_trace_type = get_builtin_type(g, "StackTrace"); |
src/stage1/analyze.hpp+2| ... | ... | @@ -242,6 +242,8 @@ Error get_primitive_type(CodeGen *g, Buf *name, ZigType **result); |
| 242 | 242 | bool calling_convention_allows_zig_types(CallingConvention cc); |
| 243 | 243 | const char *calling_convention_name(CallingConvention cc); |
| 244 | 244 | |
| 245 | const char *address_space_name(AddressSpace as); | |
| 246 | ||
| 245 | 247 | Error ATTRIBUTE_MUST_USE file_fetch(CodeGen *g, Buf *resolved_path, Buf *contents); |
| 246 | 248 | |
| 247 | 249 | void walk_function_params(CodeGen *g, ZigType *fn_type, FnWalk *fn_walk); |
src/stage1/ir.cpp+42-25| ... | ... | @@ -16124,7 +16124,7 @@ static Stage1AirInst *ir_analyze_instruction_optional_unwrap_ptr(IrAnalyze *ira, |
| 16124 | 16124 | |
| 16125 | 16125 | static Stage1AirInst *ir_analyze_instruction_ctz(IrAnalyze *ira, Stage1ZirInstCtz *instruction) { |
| 16126 | 16126 | Error err; |
| 16127 | ||
| 16127 | ||
| 16128 | 16128 | ZigType *int_type = ir_resolve_int_type(ira, instruction->type->child); |
| 16129 | 16129 | if (type_is_invalid(int_type)) |
| 16130 | 16130 | return ira->codegen->invalid_inst_gen; |
| ... | ... | @@ -16166,7 +16166,7 @@ static Stage1AirInst *ir_analyze_instruction_ctz(IrAnalyze *ira, Stage1ZirInstCt |
| 16166 | 16166 | return ira->codegen->invalid_inst_gen; |
| 16167 | 16167 | if (val->special == ConstValSpecialUndef) |
| 16168 | 16168 | return ir_const_undef(ira, instruction->base.scope, instruction->base.source_node, ira->codegen->builtin_types.entry_num_lit_int); |
| 16169 | ||
| 16169 | ||
| 16170 | 16170 | if (is_vector) { |
| 16171 | 16171 | ZigType *smallest_vec_type = get_vector_type(ira->codegen, vector_len, smallest_type); |
| 16172 | 16172 | Stage1AirInst *result = ir_const(ira, instruction->base.scope, instruction->base.source_node, smallest_vec_type); |
| ... | ... | @@ -16200,7 +16200,7 @@ static Stage1AirInst *ir_analyze_instruction_ctz(IrAnalyze *ira, Stage1ZirInstCt |
| 16200 | 16200 | |
| 16201 | 16201 | static Stage1AirInst *ir_analyze_instruction_clz(IrAnalyze *ira, Stage1ZirInstClz *instruction) { |
| 16202 | 16202 | Error err; |
| 16203 | ||
| 16203 | ||
| 16204 | 16204 | ZigType *int_type = ir_resolve_int_type(ira, instruction->type->child); |
| 16205 | 16205 | if (type_is_invalid(int_type)) |
| 16206 | 16206 | return ira->codegen->invalid_inst_gen; |
| ... | ... | @@ -16242,7 +16242,7 @@ static Stage1AirInst *ir_analyze_instruction_clz(IrAnalyze *ira, Stage1ZirInstCl |
| 16242 | 16242 | return ira->codegen->invalid_inst_gen; |
| 16243 | 16243 | if (val->special == ConstValSpecialUndef) |
| 16244 | 16244 | return ir_const_undef(ira, instruction->base.scope, instruction->base.source_node, ira->codegen->builtin_types.entry_num_lit_int); |
| 16245 | ||
| 16245 | ||
| 16246 | 16246 | if (is_vector) { |
| 16247 | 16247 | ZigType *smallest_vec_type = get_vector_type(ira->codegen, vector_len, smallest_type); |
| 16248 | 16248 | Stage1AirInst *result = ir_const(ira, instruction->base.scope, instruction->base.source_node, smallest_vec_type); |
| ... | ... | @@ -16276,7 +16276,7 @@ static Stage1AirInst *ir_analyze_instruction_clz(IrAnalyze *ira, Stage1ZirInstCl |
| 16276 | 16276 | |
| 16277 | 16277 | static Stage1AirInst *ir_analyze_instruction_pop_count(IrAnalyze *ira, Stage1ZirInstPopCount *instruction) { |
| 16278 | 16278 | Error err; |
| 16279 | ||
| 16279 | ||
| 16280 | 16280 | ZigType *int_type = ir_resolve_int_type(ira, instruction->type->child); |
| 16281 | 16281 | if (type_is_invalid(int_type)) |
| 16282 | 16282 | return ira->codegen->invalid_inst_gen; |
| ... | ... | @@ -16318,7 +16318,7 @@ static Stage1AirInst *ir_analyze_instruction_pop_count(IrAnalyze *ira, Stage1Zir |
| 16318 | 16318 | return ira->codegen->invalid_inst_gen; |
| 16319 | 16319 | if (val->special == ConstValSpecialUndef) |
| 16320 | 16320 | return ir_const_undef(ira, instruction->base.scope, instruction->base.source_node, ira->codegen->builtin_types.entry_num_lit_int); |
| 16321 | ||
| 16321 | ||
| 16322 | 16322 | if (is_vector) { |
| 16323 | 16323 | ZigType *smallest_vec_type = get_vector_type(ira->codegen, vector_len, smallest_type); |
| 16324 | 16324 | Stage1AirInst *result = ir_const(ira, instruction->base.scope, instruction->base.source_node, smallest_vec_type); |
| ... | ... | @@ -17904,7 +17904,7 @@ static ZigValue *create_ptr_like_type_info(IrAnalyze *ira, Scope *scope, AstNode |
| 17904 | 17904 | result->special = ConstValSpecialStatic; |
| 17905 | 17905 | result->type = type_info_pointer_type; |
| 17906 | 17906 | |
| 17907 | ZigValue **fields = alloc_const_vals_ptrs(ira->codegen, 7); | |
| 17907 | ZigValue **fields = alloc_const_vals_ptrs(ira->codegen, 8); | |
| 17908 | 17908 | result->data.x_struct.fields = fields; |
| 17909 | 17909 | |
| 17910 | 17910 | // size: Size |
| ... | ... | @@ -17939,24 +17939,29 @@ static ZigValue *create_ptr_like_type_info(IrAnalyze *ira, Scope *scope, AstNode |
| 17939 | 17939 | lazy_align_of->base.id = LazyValueIdAlignOf; |
| 17940 | 17940 | lazy_align_of->target_type = ir_const_type(ira, scope, source_node, attrs_type->data.pointer.child_type); |
| 17941 | 17941 | } |
| 17942 | // child: type | |
| 17943 | ensure_field_index(result->type, "child", 4); | |
| 17942 | // address_space: AddressSpace, | |
| 17943 | ensure_field_index(result->type, "address_space", 4); | |
| 17944 | 17944 | fields[4]->special = ConstValSpecialStatic; |
| 17945 | fields[4]->type = ira->codegen->builtin_types.entry_type; | |
| 17946 | fields[4]->data.x_type = attrs_type->data.pointer.child_type; | |
| 17947 | // is_allowzero: bool | |
| 17948 | ensure_field_index(result->type, "is_allowzero", 5); | |
| 17945 | fields[4]->type = get_builtin_type(ira->codegen, "AddressSpace"); | |
| 17946 | bigint_init_unsigned(&fields[4]->data.x_enum_tag, AddressSpaceGeneric); | |
| 17947 | // child: type | |
| 17948 | ensure_field_index(result->type, "child", 5); | |
| 17949 | 17949 | fields[5]->special = ConstValSpecialStatic; |
| 17950 | fields[5]->type = ira->codegen->builtin_types.entry_bool; | |
| 17951 | fields[5]->data.x_bool = attrs_type->data.pointer.allow_zero; | |
| 17952 | // sentinel: anytype | |
| 17953 | ensure_field_index(result->type, "sentinel", 6); | |
| 17950 | fields[5]->type = ira->codegen->builtin_types.entry_type; | |
| 17951 | fields[5]->data.x_type = attrs_type->data.pointer.child_type; | |
| 17952 | // is_allowzero: bool | |
| 17953 | ensure_field_index(result->type, "is_allowzero", 6); | |
| 17954 | 17954 | fields[6]->special = ConstValSpecialStatic; |
| 17955 | fields[6]->type = ira->codegen->builtin_types.entry_bool; | |
| 17956 | fields[6]->data.x_bool = attrs_type->data.pointer.allow_zero; | |
| 17957 | // sentinel: anytype | |
| 17958 | ensure_field_index(result->type, "sentinel", 7); | |
| 17959 | fields[7]->special = ConstValSpecialStatic; | |
| 17955 | 17960 | if (attrs_type->data.pointer.sentinel != nullptr) { |
| 17956 | fields[6]->type = get_optional_type(ira->codegen, attrs_type->data.pointer.child_type); | |
| 17957 | set_optional_payload(fields[6], attrs_type->data.pointer.sentinel); | |
| 17961 | fields[7]->type = get_optional_type(ira->codegen, attrs_type->data.pointer.child_type); | |
| 17962 | set_optional_payload(fields[7], attrs_type->data.pointer.sentinel); | |
| 17958 | 17963 | } else { |
| 17959 | fields[6]->type = ira->codegen->builtin_types.entry_null; | |
| 17964 | fields[7]->type = ira->codegen->builtin_types.entry_null; | |
| 17960 | 17965 | } |
| 17961 | 17966 | |
| 17962 | 17967 | return result; |
| ... | ... | @@ -18465,7 +18470,7 @@ static Error ir_make_type_info_value(IrAnalyze *ira, Scope *scope, AstNode *sour |
| 18465 | 18470 | result->special = ConstValSpecialStatic; |
| 18466 | 18471 | result->type = ir_type_info_get_type(ira, "Fn", nullptr); |
| 18467 | 18472 | |
| 18468 | ZigValue **fields = alloc_const_vals_ptrs(ira->codegen, 6); | |
| 18473 | ZigValue **fields = alloc_const_vals_ptrs(ira->codegen, 7); | |
| 18469 | 18474 | result->data.x_struct.fields = fields; |
| 18470 | 18475 | |
| 18471 | 18476 | // calling_convention: TypeInfo.CallingConvention |
| ... | ... | @@ -18826,11 +18831,11 @@ static ZigType *type_info_to_type(IrAnalyze *ira, Scope *scope, AstNode *source_ |
| 18826 | 18831 | assert(size_value->type == ir_type_info_get_type(ira, "Size", type_info_pointer_type)); |
| 18827 | 18832 | BuiltinPtrSize size_enum_index = (BuiltinPtrSize)bigint_as_u32(&size_value->data.x_enum_tag); |
| 18828 | 18833 | PtrLen ptr_len = size_enum_index_to_ptr_len(size_enum_index); |
| 18829 | ZigType *elem_type = get_const_field_meta_type(ira, source_node, payload, "child", 4); | |
| 18834 | ZigType *elem_type = get_const_field_meta_type(ira, source_node, payload, "child", 5); | |
| 18830 | 18835 | if (type_is_invalid(elem_type)) |
| 18831 | 18836 | return ira->codegen->invalid_inst_gen->value->type; |
| 18832 | 18837 | ZigValue *sentinel; |
| 18833 | if ((err = get_const_field_sentinel(ira, scope, source_node, payload, "sentinel", 6, | |
| 18838 | if ((err = get_const_field_sentinel(ira, scope, source_node, payload, "sentinel", 7, | |
| 18834 | 18839 | elem_type, &sentinel))) |
| 18835 | 18840 | { |
| 18836 | 18841 | return ira->codegen->invalid_inst_gen->value->type; |
| ... | ... | @@ -18845,6 +18850,19 @@ static ZigType *type_info_to_type(IrAnalyze *ira, Scope *scope, AstNode *source_ |
| 18845 | 18850 | if (alignment == nullptr) |
| 18846 | 18851 | return ira->codegen->invalid_inst_gen->value->type; |
| 18847 | 18852 | |
| 18853 | ZigValue *as_value = get_const_field(ira, source_node, payload, "address_space", 4); | |
| 18854 | if (as_value == nullptr) | |
| 18855 | return ira->codegen->invalid_inst_gen->value->type; | |
| 18856 | assert(as_value->special == ConstValSpecialStatic); | |
| 18857 | assert(as_value->type == get_builtin_type(ira->codegen, "AddressSpace")); | |
| 18858 | AddressSpace as = (AddressSpace)bigint_as_u32(&as_value->data.x_enum_tag); | |
| 18859 | if (as != AddressSpaceGeneric) { | |
| 18860 | ir_add_error_node(ira, source_node, buf_sprintf( | |
| 18861 | "address space '%s' not available in stage 1 compiler, must be .generic", | |
| 18862 | address_space_name(as))); | |
| 18863 | return ira->codegen->invalid_inst_gen->value->type; | |
| 18864 | } | |
| 18865 | ||
| 18848 | 18866 | bool is_const; |
| 18849 | 18867 | if ((err = get_const_field_bool(ira, source_node, payload, "is_const", 1, &is_const))) |
| 18850 | 18868 | return ira->codegen->invalid_inst_gen->value->type; |
| ... | ... | @@ -18857,13 +18875,12 @@ static ZigType *type_info_to_type(IrAnalyze *ira, Scope *scope, AstNode *source_ |
| 18857 | 18875 | } |
| 18858 | 18876 | |
| 18859 | 18877 | bool is_allowzero; |
| 18860 | if ((err = get_const_field_bool(ira, source_node, payload, "is_allowzero", 5, | |
| 18878 | if ((err = get_const_field_bool(ira, source_node, payload, "is_allowzero", 6, | |
| 18861 | 18879 | &is_allowzero))) |
| 18862 | 18880 | { |
| 18863 | 18881 | return ira->codegen->invalid_inst_gen->value->type; |
| 18864 | 18882 | } |
| 18865 | 18883 | |
| 18866 | ||
| 18867 | 18884 | ZigType *ptr_type = get_pointer_to_type_extra2(ira->codegen, |
| 18868 | 18885 | elem_type, |
| 18869 | 18886 | is_const, |
src/target.zig+18| ... | ... | @@ -544,3 +544,21 @@ pub fn largestAtomicBits(target: std.Target) u32 { |
| 544 | 544 | .x86_64 => 128, |
| 545 | 545 | }; |
| 546 | 546 | } |
| 547 | ||
| 548 | pub fn defaultAddressSpace( | |
| 549 | target: std.Target, | |
| 550 | context: enum { | |
| 551 | /// Query the default address space for global constant values. | |
| 552 | global_constant, | |
| 553 | /// Query the default address space for global mutable values. | |
| 554 | global_mutable, | |
| 555 | /// Query the default address space for function-local values. | |
| 556 | local, | |
| 557 | /// Query the default address space for functions themselves. | |
| 558 | function, | |
| 559 | }, | |
| 560 | ) std.builtin.AddressSpace { | |
| 561 | _ = target; | |
| 562 | _ = context; | |
| 563 | return .generic; | |
| 564 | } |
src/translate_c/ast.zig+3| ... | ... | @@ -2614,6 +2614,7 @@ fn renderVar(c: *Context, node: Node) !NodeIndex { |
| 2614 | 2614 | .type_node = type_node, |
| 2615 | 2615 | .align_node = align_node, |
| 2616 | 2616 | .section_node = section_node, |
| 2617 | .addrspace_node = 0, | |
| 2617 | 2618 | }), |
| 2618 | 2619 | .rhs = init_node, |
| 2619 | 2620 | }, |
| ... | ... | @@ -2705,6 +2706,7 @@ fn renderFunc(c: *Context, node: Node) !NodeIndex { |
| 2705 | 2706 | .lhs = try c.addExtra(std.zig.Ast.Node.FnProtoOne{ |
| 2706 | 2707 | .param = params.items[0], |
| 2707 | 2708 | .align_expr = align_expr, |
| 2709 | .addrspace_expr = 0, // TODO | |
| 2708 | 2710 | .section_expr = section_expr, |
| 2709 | 2711 | .callconv_expr = callconv_expr, |
| 2710 | 2712 | }), |
| ... | ... | @@ -2720,6 +2722,7 @@ fn renderFunc(c: *Context, node: Node) !NodeIndex { |
| 2720 | 2722 | .params_start = span.start, |
| 2721 | 2723 | .params_end = span.end, |
| 2722 | 2724 | .align_expr = align_expr, |
| 2725 | .addrspace_expr = 0, // TODO | |
| 2723 | 2726 | .section_expr = section_expr, |
| 2724 | 2727 | .callconv_expr = callconv_expr, |
| 2725 | 2728 | }), |
src/type.zig+115-13| ... | ... | @@ -127,6 +127,7 @@ pub const Type = extern union { |
| 127 | 127 | .atomic_order, |
| 128 | 128 | .atomic_rmw_op, |
| 129 | 129 | .calling_convention, |
| 130 | .address_space, | |
| 130 | 131 | .float_mode, |
| 131 | 132 | .reduce_op, |
| 132 | 133 | => return .Enum, |
| ... | ... | @@ -288,6 +289,7 @@ pub const Type = extern union { |
| 288 | 289 | .pointee_type = Type.initTag(.comptime_int), |
| 289 | 290 | .sentinel = null, |
| 290 | 291 | .@"align" = 0, |
| 292 | .@"addrspace" = .generic, | |
| 291 | 293 | .bit_offset = 0, |
| 292 | 294 | .host_size = 0, |
| 293 | 295 | .@"allowzero" = false, |
| ... | ... | @@ -299,6 +301,7 @@ pub const Type = extern union { |
| 299 | 301 | .pointee_type = Type.initTag(.u8), |
| 300 | 302 | .sentinel = null, |
| 301 | 303 | .@"align" = 0, |
| 304 | .@"addrspace" = .generic, | |
| 302 | 305 | .bit_offset = 0, |
| 303 | 306 | .host_size = 0, |
| 304 | 307 | .@"allowzero" = false, |
| ... | ... | @@ -310,6 +313,7 @@ pub const Type = extern union { |
| 310 | 313 | .pointee_type = self.castPointer().?.data, |
| 311 | 314 | .sentinel = null, |
| 312 | 315 | .@"align" = 0, |
| 316 | .@"addrspace" = .generic, | |
| 313 | 317 | .bit_offset = 0, |
| 314 | 318 | .host_size = 0, |
| 315 | 319 | .@"allowzero" = false, |
| ... | ... | @@ -321,6 +325,7 @@ pub const Type = extern union { |
| 321 | 325 | .pointee_type = self.castPointer().?.data, |
| 322 | 326 | .sentinel = null, |
| 323 | 327 | .@"align" = 0, |
| 328 | .@"addrspace" = .generic, | |
| 324 | 329 | .bit_offset = 0, |
| 325 | 330 | .host_size = 0, |
| 326 | 331 | .@"allowzero" = false, |
| ... | ... | @@ -332,6 +337,7 @@ pub const Type = extern union { |
| 332 | 337 | .pointee_type = self.castPointer().?.data, |
| 333 | 338 | .sentinel = null, |
| 334 | 339 | .@"align" = 0, |
| 340 | .@"addrspace" = .generic, | |
| 335 | 341 | .bit_offset = 0, |
| 336 | 342 | .host_size = 0, |
| 337 | 343 | .@"allowzero" = false, |
| ... | ... | @@ -343,6 +349,7 @@ pub const Type = extern union { |
| 343 | 349 | .pointee_type = Type.initTag(.u8), |
| 344 | 350 | .sentinel = null, |
| 345 | 351 | .@"align" = 0, |
| 352 | .@"addrspace" = .generic, | |
| 346 | 353 | .bit_offset = 0, |
| 347 | 354 | .host_size = 0, |
| 348 | 355 | .@"allowzero" = false, |
| ... | ... | @@ -354,6 +361,7 @@ pub const Type = extern union { |
| 354 | 361 | .pointee_type = self.castPointer().?.data, |
| 355 | 362 | .sentinel = null, |
| 356 | 363 | .@"align" = 0, |
| 364 | .@"addrspace" = .generic, | |
| 357 | 365 | .bit_offset = 0, |
| 358 | 366 | .host_size = 0, |
| 359 | 367 | .@"allowzero" = false, |
| ... | ... | @@ -365,6 +373,7 @@ pub const Type = extern union { |
| 365 | 373 | .pointee_type = Type.initTag(.u8), |
| 366 | 374 | .sentinel = null, |
| 367 | 375 | .@"align" = 0, |
| 376 | .@"addrspace" = .generic, | |
| 368 | 377 | .bit_offset = 0, |
| 369 | 378 | .host_size = 0, |
| 370 | 379 | .@"allowzero" = false, |
| ... | ... | @@ -376,6 +385,7 @@ pub const Type = extern union { |
| 376 | 385 | .pointee_type = self.castPointer().?.data, |
| 377 | 386 | .sentinel = null, |
| 378 | 387 | .@"align" = 0, |
| 388 | .@"addrspace" = .generic, | |
| 379 | 389 | .bit_offset = 0, |
| 380 | 390 | .host_size = 0, |
| 381 | 391 | .@"allowzero" = false, |
| ... | ... | @@ -387,6 +397,7 @@ pub const Type = extern union { |
| 387 | 397 | .pointee_type = self.castPointer().?.data, |
| 388 | 398 | .sentinel = null, |
| 389 | 399 | .@"align" = 0, |
| 400 | .@"addrspace" = .generic, | |
| 390 | 401 | .bit_offset = 0, |
| 391 | 402 | .host_size = 0, |
| 392 | 403 | .@"allowzero" = false, |
| ... | ... | @@ -398,6 +409,7 @@ pub const Type = extern union { |
| 398 | 409 | .pointee_type = self.castPointer().?.data, |
| 399 | 410 | .sentinel = null, |
| 400 | 411 | .@"align" = 0, |
| 412 | .@"addrspace" = .generic, | |
| 401 | 413 | .bit_offset = 0, |
| 402 | 414 | .host_size = 0, |
| 403 | 415 | .@"allowzero" = false, |
| ... | ... | @@ -409,6 +421,7 @@ pub const Type = extern union { |
| 409 | 421 | .pointee_type = self.castPointer().?.data, |
| 410 | 422 | .sentinel = null, |
| 411 | 423 | .@"align" = 0, |
| 424 | .@"addrspace" = .generic, | |
| 412 | 425 | .bit_offset = 0, |
| 413 | 426 | .host_size = 0, |
| 414 | 427 | .@"allowzero" = false, |
| ... | ... | @@ -461,6 +474,8 @@ pub const Type = extern union { |
| 461 | 474 | return false; |
| 462 | 475 | if (info_a.host_size != info_b.host_size) |
| 463 | 476 | return false; |
| 477 | if (info_a.@"addrspace" != info_b.@"addrspace") | |
| 478 | return false; | |
| 464 | 479 | |
| 465 | 480 | const sentinel_a = info_a.sentinel; |
| 466 | 481 | const sentinel_b = info_b.sentinel; |
| ... | ... | @@ -746,6 +761,7 @@ pub const Type = extern union { |
| 746 | 761 | .atomic_order, |
| 747 | 762 | .atomic_rmw_op, |
| 748 | 763 | .calling_convention, |
| 764 | .address_space, | |
| 749 | 765 | .float_mode, |
| 750 | 766 | .reduce_op, |
| 751 | 767 | .call_options, |
| ... | ... | @@ -835,6 +851,7 @@ pub const Type = extern union { |
| 835 | 851 | .pointee_type = try payload.pointee_type.copy(allocator), |
| 836 | 852 | .sentinel = sent, |
| 837 | 853 | .@"align" = payload.@"align", |
| 854 | .@"addrspace" = payload.@"addrspace", | |
| 838 | 855 | .bit_offset = payload.bit_offset, |
| 839 | 856 | .host_size = payload.host_size, |
| 840 | 857 | .@"allowzero" = payload.@"allowzero", |
| ... | ... | @@ -958,6 +975,7 @@ pub const Type = extern union { |
| 958 | 975 | .atomic_order => return writer.writeAll("std.builtin.AtomicOrder"), |
| 959 | 976 | .atomic_rmw_op => return writer.writeAll("std.builtin.AtomicRmwOp"), |
| 960 | 977 | .calling_convention => return writer.writeAll("std.builtin.CallingConvention"), |
| 978 | .address_space => return writer.writeAll("std.builtin.AddressSpace"), | |
| 961 | 979 | .float_mode => return writer.writeAll("std.builtin.FloatMode"), |
| 962 | 980 | .reduce_op => return writer.writeAll("std.builtin.ReduceOp"), |
| 963 | 981 | .call_options => return writer.writeAll("std.builtin.CallOptions"), |
| ... | ... | @@ -1111,6 +1129,9 @@ pub const Type = extern union { |
| 1111 | 1129 | } |
| 1112 | 1130 | try writer.writeAll(") "); |
| 1113 | 1131 | } |
| 1132 | if (payload.@"addrspace" != .generic) { | |
| 1133 | try writer.print("addrspace(.{s}) ", .{@tagName(payload.@"addrspace")}); | |
| 1134 | } | |
| 1114 | 1135 | if (!payload.mutable) try writer.writeAll("const "); |
| 1115 | 1136 | if (payload.@"volatile") try writer.writeAll("volatile "); |
| 1116 | 1137 | if (payload.@"allowzero") try writer.writeAll("allowzero "); |
| ... | ... | @@ -1186,6 +1207,7 @@ pub const Type = extern union { |
| 1186 | 1207 | .atomic_order, |
| 1187 | 1208 | .atomic_rmw_op, |
| 1188 | 1209 | .calling_convention, |
| 1210 | .address_space, | |
| 1189 | 1211 | .float_mode, |
| 1190 | 1212 | .reduce_op, |
| 1191 | 1213 | .call_options, |
| ... | ... | @@ -1301,6 +1323,7 @@ pub const Type = extern union { |
| 1301 | 1323 | .atomic_order => return Value.initTag(.atomic_order_type), |
| 1302 | 1324 | .atomic_rmw_op => return Value.initTag(.atomic_rmw_op_type), |
| 1303 | 1325 | .calling_convention => return Value.initTag(.calling_convention_type), |
| 1326 | .address_space => return Value.initTag(.address_space_type), | |
| 1304 | 1327 | .float_mode => return Value.initTag(.float_mode_type), |
| 1305 | 1328 | .reduce_op => return Value.initTag(.reduce_op_type), |
| 1306 | 1329 | .call_options => return Value.initTag(.call_options_type), |
| ... | ... | @@ -1362,6 +1385,7 @@ pub const Type = extern union { |
| 1362 | 1385 | .atomic_order, |
| 1363 | 1386 | .atomic_rmw_op, |
| 1364 | 1387 | .calling_convention, |
| 1388 | .address_space, | |
| 1365 | 1389 | .float_mode, |
| 1366 | 1390 | .reduce_op, |
| 1367 | 1391 | .call_options, |
| ... | ... | @@ -1496,6 +1520,30 @@ pub const Type = extern union { |
| 1496 | 1520 | } |
| 1497 | 1521 | } |
| 1498 | 1522 | |
| 1523 | pub fn ptrAddressSpace(self: Type) std.builtin.AddressSpace { | |
| 1524 | return switch (self.tag()) { | |
| 1525 | .single_const_pointer_to_comptime_int, | |
| 1526 | .const_slice_u8, | |
| 1527 | .single_const_pointer, | |
| 1528 | .single_mut_pointer, | |
| 1529 | .many_const_pointer, | |
| 1530 | .many_mut_pointer, | |
| 1531 | .c_const_pointer, | |
| 1532 | .c_mut_pointer, | |
| 1533 | .const_slice, | |
| 1534 | .mut_slice, | |
| 1535 | .inferred_alloc_const, | |
| 1536 | .inferred_alloc_mut, | |
| 1537 | .manyptr_u8, | |
| 1538 | .manyptr_const_u8, | |
| 1539 | => .generic, | |
| 1540 | ||
| 1541 | .pointer => self.castTag(.pointer).?.data.@"addrspace", | |
| 1542 | ||
| 1543 | else => unreachable, | |
| 1544 | }; | |
| 1545 | } | |
| 1546 | ||
| 1499 | 1547 | /// Asserts that hasCodeGenBits() is true. |
| 1500 | 1548 | pub fn abiAlignment(self: Type, target: Target) u32 { |
| 1501 | 1549 | return switch (self.tag()) { |
| ... | ... | @@ -1508,6 +1556,7 @@ pub const Type = extern union { |
| 1508 | 1556 | .atomic_order, |
| 1509 | 1557 | .atomic_rmw_op, |
| 1510 | 1558 | .calling_convention, |
| 1559 | .address_space, | |
| 1511 | 1560 | .float_mode, |
| 1512 | 1561 | .reduce_op, |
| 1513 | 1562 | .call_options, |
| ... | ... | @@ -1734,6 +1783,7 @@ pub const Type = extern union { |
| 1734 | 1783 | .atomic_order, |
| 1735 | 1784 | .atomic_rmw_op, |
| 1736 | 1785 | .calling_convention, |
| 1786 | .address_space, | |
| 1737 | 1787 | .float_mode, |
| 1738 | 1788 | .reduce_op, |
| 1739 | 1789 | .call_options, |
| ... | ... | @@ -2019,6 +2069,7 @@ pub const Type = extern union { |
| 2019 | 2069 | .atomic_order, |
| 2020 | 2070 | .atomic_rmw_op, |
| 2021 | 2071 | .calling_convention, |
| 2072 | .address_space, | |
| 2022 | 2073 | .float_mode, |
| 2023 | 2074 | .reduce_op, |
| 2024 | 2075 | .call_options, |
| ... | ... | @@ -2105,42 +2156,82 @@ pub const Type = extern union { |
| 2105 | 2156 | }; |
| 2106 | 2157 | } |
| 2107 | 2158 | |
| 2108 | pub fn slicePtrFieldType(self: Type, buffer: *Payload.ElemType) Type { | |
| 2159 | pub const SlicePtrFieldTypeBuffer = union { | |
| 2160 | elem_type: Payload.ElemType, | |
| 2161 | pointer: Payload.Pointer, | |
| 2162 | }; | |
| 2163 | ||
| 2164 | pub fn slicePtrFieldType(self: Type, buffer: *SlicePtrFieldTypeBuffer) Type { | |
| 2109 | 2165 | switch (self.tag()) { |
| 2110 | 2166 | .const_slice_u8 => return Type.initTag(.manyptr_const_u8), |
| 2111 | 2167 | |
| 2112 | 2168 | .const_slice => { |
| 2113 | 2169 | const elem_type = self.castTag(.const_slice).?.data; |
| 2114 | 2170 | buffer.* = .{ |
| 2115 | .base = .{ .tag = .many_const_pointer }, | |
| 2116 | .data = elem_type, | |
| 2171 | .elem_type = .{ | |
| 2172 | .base = .{ .tag = .many_const_pointer }, | |
| 2173 | .data = elem_type, | |
| 2174 | }, | |
| 2117 | 2175 | }; |
| 2118 | return Type.initPayload(&buffer.base); | |
| 2176 | return Type.initPayload(&buffer.elem_type.base); | |
| 2119 | 2177 | }, |
| 2120 | 2178 | .mut_slice => { |
| 2121 | 2179 | const elem_type = self.castTag(.mut_slice).?.data; |
| 2122 | 2180 | buffer.* = .{ |
| 2123 | .base = .{ .tag = .many_mut_pointer }, | |
| 2124 | .data = elem_type, | |
| 2181 | .elem_type = .{ | |
| 2182 | .base = .{ .tag = .many_mut_pointer }, | |
| 2183 | .data = elem_type, | |
| 2184 | }, | |
| 2125 | 2185 | }; |
| 2126 | return Type.initPayload(&buffer.base); | |
| 2186 | return Type.initPayload(&buffer.elem_type.base); | |
| 2127 | 2187 | }, |
| 2128 | 2188 | |
| 2129 | 2189 | .pointer => { |
| 2130 | 2190 | const payload = self.castTag(.pointer).?.data; |
| 2131 | 2191 | assert(payload.size == .Slice); |
| 2132 | if (payload.mutable) { | |
| 2192 | ||
| 2193 | if (payload.sentinel != null or | |
| 2194 | payload.@"align" != 0 or | |
| 2195 | payload.@"addrspace" != .generic or | |
| 2196 | payload.bit_offset != 0 or | |
| 2197 | payload.host_size != 0 or | |
| 2198 | payload.@"allowzero" or | |
| 2199 | payload.@"volatile") | |
| 2200 | { | |
| 2133 | 2201 | buffer.* = .{ |
| 2134 | .base = .{ .tag = .many_mut_pointer }, | |
| 2135 | .data = payload.pointee_type, | |
| 2202 | .pointer = .{ | |
| 2203 | .data = .{ | |
| 2204 | .pointee_type = payload.pointee_type, | |
| 2205 | .sentinel = payload.sentinel, | |
| 2206 | .@"align" = payload.@"align", | |
| 2207 | .@"addrspace" = payload.@"addrspace", | |
| 2208 | .bit_offset = payload.bit_offset, | |
| 2209 | .host_size = payload.host_size, | |
| 2210 | .@"allowzero" = payload.@"allowzero", | |
| 2211 | .mutable = payload.mutable, | |
| 2212 | .@"volatile" = payload.@"volatile", | |
| 2213 | .size = .Many, | |
| 2214 | }, | |
| 2215 | }, | |
| 2136 | 2216 | }; |
| 2217 | return Type.initPayload(&buffer.pointer.base); | |
| 2218 | } else if (payload.mutable) { | |
| 2219 | buffer.* = .{ | |
| 2220 | .elem_type = .{ | |
| 2221 | .base = .{ .tag = .many_mut_pointer }, | |
| 2222 | .data = payload.pointee_type, | |
| 2223 | }, | |
| 2224 | }; | |
| 2225 | return Type.initPayload(&buffer.elem_type.base); | |
| 2137 | 2226 | } else { |
| 2138 | 2227 | buffer.* = .{ |
| 2139 | .base = .{ .tag = .many_const_pointer }, | |
| 2140 | .data = payload.pointee_type, | |
| 2228 | .elem_type = .{ | |
| 2229 | .base = .{ .tag = .many_const_pointer }, | |
| 2230 | .data = payload.pointee_type, | |
| 2231 | }, | |
| 2141 | 2232 | }; |
| 2233 | return Type.initPayload(&buffer.elem_type.base); | |
| 2142 | 2234 | } |
| 2143 | return Type.initPayload(&buffer.base); | |
| 2144 | 2235 | }, |
| 2145 | 2236 | |
| 2146 | 2237 | else => unreachable, |
| ... | ... | @@ -2793,6 +2884,7 @@ pub const Type = extern union { |
| 2793 | 2884 | .atomic_order, |
| 2794 | 2885 | .atomic_rmw_op, |
| 2795 | 2886 | .calling_convention, |
| 2887 | .address_space, | |
| 2796 | 2888 | .float_mode, |
| 2797 | 2889 | .reduce_op, |
| 2798 | 2890 | .call_options, |
| ... | ... | @@ -3000,6 +3092,7 @@ pub const Type = extern union { |
| 3000 | 3092 | .atomic_order, |
| 3001 | 3093 | .atomic_rmw_op, |
| 3002 | 3094 | .calling_convention, |
| 3095 | .address_space, | |
| 3003 | 3096 | .float_mode, |
| 3004 | 3097 | .reduce_op, |
| 3005 | 3098 | .call_options, |
| ... | ... | @@ -3024,6 +3117,7 @@ pub const Type = extern union { |
| 3024 | 3117 | .atomic_order, |
| 3025 | 3118 | .atomic_rmw_op, |
| 3026 | 3119 | .calling_convention, |
| 3120 | .address_space, | |
| 3027 | 3121 | .float_mode, |
| 3028 | 3122 | .reduce_op, |
| 3029 | 3123 | .call_options, |
| ... | ... | @@ -3047,6 +3141,7 @@ pub const Type = extern union { |
| 3047 | 3141 | .atomic_order, |
| 3048 | 3142 | .atomic_rmw_op, |
| 3049 | 3143 | .calling_convention, |
| 3144 | .address_space, | |
| 3050 | 3145 | .float_mode, |
| 3051 | 3146 | .reduce_op, |
| 3052 | 3147 | .call_options, |
| ... | ... | @@ -3100,6 +3195,7 @@ pub const Type = extern union { |
| 3100 | 3195 | .atomic_order, |
| 3101 | 3196 | .atomic_rmw_op, |
| 3102 | 3197 | .calling_convention, |
| 3198 | .address_space, | |
| 3103 | 3199 | .float_mode, |
| 3104 | 3200 | .reduce_op, |
| 3105 | 3201 | .call_options, |
| ... | ... | @@ -3155,6 +3251,7 @@ pub const Type = extern union { |
| 3155 | 3251 | .atomic_order, |
| 3156 | 3252 | .atomic_rmw_op, |
| 3157 | 3253 | .calling_convention, |
| 3254 | .address_space, | |
| 3158 | 3255 | .float_mode, |
| 3159 | 3256 | .reduce_op, |
| 3160 | 3257 | .call_options, |
| ... | ... | @@ -3192,6 +3289,7 @@ pub const Type = extern union { |
| 3192 | 3289 | .atomic_order, |
| 3193 | 3290 | .atomic_rmw_op, |
| 3194 | 3291 | .calling_convention, |
| 3292 | .address_space, | |
| 3195 | 3293 | .float_mode, |
| 3196 | 3294 | .reduce_op, |
| 3197 | 3295 | .call_options, |
| ... | ... | @@ -3242,6 +3340,7 @@ pub const Type = extern union { |
| 3242 | 3340 | .atomic_order, |
| 3243 | 3341 | .atomic_rmw_op, |
| 3244 | 3342 | .calling_convention, |
| 3343 | .address_space, | |
| 3245 | 3344 | .float_mode, |
| 3246 | 3345 | .reduce_op, |
| 3247 | 3346 | .call_options, |
| ... | ... | @@ -3302,6 +3401,7 @@ pub const Type = extern union { |
| 3302 | 3401 | atomic_order, |
| 3303 | 3402 | atomic_rmw_op, |
| 3304 | 3403 | calling_convention, |
| 3404 | address_space, | |
| 3305 | 3405 | float_mode, |
| 3306 | 3406 | reduce_op, |
| 3307 | 3407 | call_options, |
| ... | ... | @@ -3425,6 +3525,7 @@ pub const Type = extern union { |
| 3425 | 3525 | .atomic_order, |
| 3426 | 3526 | .atomic_rmw_op, |
| 3427 | 3527 | .calling_convention, |
| 3528 | .address_space, | |
| 3428 | 3529 | .float_mode, |
| 3429 | 3530 | .reduce_op, |
| 3430 | 3531 | .call_options, |
| ... | ... | @@ -3580,6 +3681,7 @@ pub const Type = extern union { |
| 3580 | 3681 | sentinel: ?Value, |
| 3581 | 3682 | /// If zero use pointee_type.AbiAlign() |
| 3582 | 3683 | @"align": u32, |
| 3684 | @"addrspace": std.builtin.AddressSpace, | |
| 3583 | 3685 | bit_offset: u16, |
| 3584 | 3686 | host_size: u16, |
| 3585 | 3687 | @"allowzero": bool, |
src/value.zig+5| ... | ... | @@ -63,6 +63,7 @@ pub const Value = extern union { |
| 63 | 63 | atomic_order_type, |
| 64 | 64 | atomic_rmw_op_type, |
| 65 | 65 | calling_convention_type, |
| 66 | address_space_type, | |
| 66 | 67 | float_mode_type, |
| 67 | 68 | reduce_op_type, |
| 68 | 69 | call_options_type, |
| ... | ... | @@ -226,6 +227,7 @@ pub const Value = extern union { |
| 226 | 227 | .atomic_order_type, |
| 227 | 228 | .atomic_rmw_op_type, |
| 228 | 229 | .calling_convention_type, |
| 230 | .address_space_type, | |
| 229 | 231 | .float_mode_type, |
| 230 | 232 | .reduce_op_type, |
| 231 | 233 | .call_options_type, |
| ... | ... | @@ -412,6 +414,7 @@ pub const Value = extern union { |
| 412 | 414 | .atomic_order_type, |
| 413 | 415 | .atomic_rmw_op_type, |
| 414 | 416 | .calling_convention_type, |
| 417 | .address_space_type, | |
| 415 | 418 | .float_mode_type, |
| 416 | 419 | .reduce_op_type, |
| 417 | 420 | .call_options_type, |
| ... | ... | @@ -625,6 +628,7 @@ pub const Value = extern union { |
| 625 | 628 | .atomic_order_type => return out_stream.writeAll("std.builtin.AtomicOrder"), |
| 626 | 629 | .atomic_rmw_op_type => return out_stream.writeAll("std.builtin.AtomicRmwOp"), |
| 627 | 630 | .calling_convention_type => return out_stream.writeAll("std.builtin.CallingConvention"), |
| 631 | .address_space_type => return out_stream.writeAll("std.builtin.AddressSpace"), | |
| 628 | 632 | .float_mode_type => return out_stream.writeAll("std.builtin.FloatMode"), |
| 629 | 633 | .reduce_op_type => return out_stream.writeAll("std.builtin.ReduceOp"), |
| 630 | 634 | .call_options_type => return out_stream.writeAll("std.builtin.CallOptions"), |
| ... | ... | @@ -792,6 +796,7 @@ pub const Value = extern union { |
| 792 | 796 | .atomic_order_type => Type.initTag(.atomic_order), |
| 793 | 797 | .atomic_rmw_op_type => Type.initTag(.atomic_rmw_op), |
| 794 | 798 | .calling_convention_type => Type.initTag(.calling_convention), |
| 799 | .address_space_type => Type.initTag(.address_space), | |
| 795 | 800 | .float_mode_type => Type.initTag(.float_mode), |
| 796 | 801 | .reduce_op_type => Type.initTag(.reduce_op), |
| 797 | 802 | .call_options_type => Type.initTag(.call_options), |
src/zig_llvm.cpp+5| ... | ... | @@ -416,6 +416,11 @@ ZIG_EXTERN_C LLVMTypeRef ZigLLVMTokenTypeInContext(LLVMContextRef context_ref) { |
| 416 | 416 | return wrap(Type::getTokenTy(*unwrap(context_ref))); |
| 417 | 417 | } |
| 418 | 418 | |
| 419 | LLVMValueRef ZigLLVMAddFunctionInAddressSpace(LLVMModuleRef M, const char *Name, LLVMTypeRef FunctionTy, unsigned AddressSpace) { | |
| 420 | Function* func = Function::Create(unwrap<FunctionType>(FunctionTy), GlobalValue::ExternalLinkage, AddressSpace, Name, unwrap(M)); | |
| 421 | return wrap(func); | |
| 422 | } | |
| 423 | ||
| 419 | 424 | LLVMValueRef ZigLLVMBuildCall(LLVMBuilderRef B, LLVMValueRef Fn, LLVMValueRef *Args, |
| 420 | 425 | unsigned NumArgs, ZigLLVM_CallingConv CC, ZigLLVM_CallAttr attr, const char *Name) |
| 421 | 426 | { |
src/zig_llvm.h+3| ... | ... | @@ -65,6 +65,9 @@ ZIG_EXTERN_C LLVMTargetMachineRef ZigLLVMCreateTargetMachine(LLVMTargetRef T, co |
| 65 | 65 | |
| 66 | 66 | ZIG_EXTERN_C LLVMTypeRef ZigLLVMTokenTypeInContext(LLVMContextRef context_ref); |
| 67 | 67 | |
| 68 | ZIG_EXTERN_C LLVMValueRef ZigLLVMAddFunctionInAddressSpace(LLVMModuleRef M, const char *Name, | |
| 69 | LLVMTypeRef FunctionTy, unsigned AddressSpace); | |
| 70 | ||
| 68 | 71 | enum ZigLLVM_CallingConv { |
| 69 | 72 | ZigLLVM_C = 0, |
| 70 | 73 | ZigLLVM_Fast = 8, |
test/behavior/type.zig+1| ... | ... | @@ -137,6 +137,7 @@ test "@Type create slice with null sentinel" { |
| 137 | 137 | .is_volatile = false, |
| 138 | 138 | .is_allowzero = false, |
| 139 | 139 | .alignment = 8, |
| 140 | .address_space = .generic, | |
| 140 | 141 | .child = *i32, |
| 141 | 142 | .sentinel = null, |
| 142 | 143 | }, |
test/cases.zig+12| ... | ... | @@ -1807,4 +1807,16 @@ pub fn addCases(ctx: *TestContext) !void { |
| 1807 | 1807 | \\} |
| 1808 | 1808 | , ""); |
| 1809 | 1809 | } |
| 1810 | ||
| 1811 | { | |
| 1812 | var case = ctx.exe("setting an address space on a local variable", linux_x64); | |
| 1813 | case.addError( | |
| 1814 | \\export fn entry() i32 { | |
| 1815 | \\ var foo: i32 addrspace(".general") = 1234; | |
| 1816 | \\ return foo; | |
| 1817 | \\} | |
| 1818 | , &[_][]const u8{ | |
| 1819 | ":2:28: error: cannot set address space of local variable 'foo'", | |
| 1820 | }); | |
| 1821 | } | |
| 1810 | 1822 | } |
test/compile_errors.zig+18| ... | ... | @@ -711,6 +711,7 @@ pub fn addCases(ctx: *TestContext) !void { |
| 711 | 711 | \\ .is_const = false, |
| 712 | 712 | \\ .is_volatile = false, |
| 713 | 713 | \\ .alignment = 1, |
| 714 | \\ .address_space = .generic, | |
| 714 | 715 | \\ .child = u8, |
| 715 | 716 | \\ .is_allowzero = false, |
| 716 | 717 | \\ .sentinel = 0, |
| ... | ... | @@ -720,6 +721,23 @@ pub fn addCases(ctx: *TestContext) !void { |
| 720 | 721 | "tmp.zig:2:16: error: sentinels are only allowed on slices and unknown-length pointers", |
| 721 | 722 | }); |
| 722 | 723 | |
| 724 | ctx.objErrStage1("@Type(.Pointer) with invalid address space ", | |
| 725 | \\export fn entry() void { | |
| 726 | \\ _ = @Type(.{ .Pointer = .{ | |
| 727 | \\ .size = .One, | |
| 728 | \\ .is_const = false, | |
| 729 | \\ .is_volatile = false, | |
| 730 | \\ .alignment = 1, | |
| 731 | \\ .address_space = .gs, | |
| 732 | \\ .child = u8, | |
| 733 | \\ .is_allowzero = false, | |
| 734 | \\ .sentinel = null, | |
| 735 | \\ }}); | |
| 736 | \\} | |
| 737 | , &[_][]const u8{ | |
| 738 | "tmp.zig:2:16: error: address space 'gs' not available in stage 1 compiler, must be .generic", | |
| 739 | }); | |
| 740 | ||
| 723 | 741 | ctx.testErrStage1("helpful return type error message", |
| 724 | 742 | \\export fn foo() u32 { |
| 725 | 743 | \\ return error.Ohno; |
test/stage2/llvm.zig+180| ... | ... | @@ -242,4 +242,184 @@ pub fn addCases(ctx: *TestContext) !void { |
| 242 | 242 | \\} |
| 243 | 243 | , ""); |
| 244 | 244 | } |
| 245 | ||
| 246 | { | |
| 247 | var case = ctx.exeUsingLlvmBackend("invalid address space coercion", linux_x64); | |
| 248 | case.addError( | |
| 249 | \\fn entry(a: *addrspace(.gs) i32) *i32 { | |
| 250 | \\ return a; | |
| 251 | \\} | |
| 252 | \\pub export fn main() void { _ = entry; } | |
| 253 | , &[_][]const u8{ | |
| 254 | ":2:12: error: expected *i32, found *addrspace(.gs) i32", | |
| 255 | }); | |
| 256 | } | |
| 257 | ||
| 258 | { | |
| 259 | var case = ctx.exeUsingLlvmBackend("pointer keeps address space", linux_x64); | |
| 260 | case.compiles( | |
| 261 | \\fn entry(a: *addrspace(.gs) i32) *addrspace(.gs) i32 { | |
| 262 | \\ return a; | |
| 263 | \\} | |
| 264 | \\pub export fn main() void { _ = entry; } | |
| 265 | ); | |
| 266 | } | |
| 267 | ||
| 268 | { | |
| 269 | var case = ctx.exeUsingLlvmBackend("pointer to explicit generic address space coerces to implicit pointer", linux_x64); | |
| 270 | case.compiles( | |
| 271 | \\fn entry(a: *addrspace(.generic) i32) *i32 { | |
| 272 | \\ return a; | |
| 273 | \\} | |
| 274 | \\pub export fn main() void { _ = entry; } | |
| 275 | ); | |
| 276 | } | |
| 277 | ||
| 278 | { | |
| 279 | var case = ctx.exeUsingLlvmBackend("pointers with different address spaces", linux_x64); | |
| 280 | case.addError( | |
| 281 | \\fn entry(a: *addrspace(.gs) i32) *addrspace(.fs) i32 { | |
| 282 | \\ return a; | |
| 283 | \\} | |
| 284 | \\pub export fn main() void { _ = entry; } | |
| 285 | , &[_][]const u8{ | |
| 286 | ":2:12: error: expected *addrspace(.fs) i32, found *addrspace(.gs) i32", | |
| 287 | }); | |
| 288 | } | |
| 289 | ||
| 290 | { | |
| 291 | var case = ctx.exeUsingLlvmBackend("pointers with different address spaces", linux_x64); | |
| 292 | case.addError( | |
| 293 | \\fn entry(a: ?*addrspace(.gs) i32) *i32 { | |
| 294 | \\ return a.?; | |
| 295 | \\} | |
| 296 | \\pub export fn main() void { _ = entry; } | |
| 297 | , &[_][]const u8{ | |
| 298 | ":2:13: error: expected *i32, found *addrspace(.gs) i32", | |
| 299 | }); | |
| 300 | } | |
| 301 | ||
| 302 | { | |
| 303 | var case = ctx.exeUsingLlvmBackend("invalid pointer keeps address space when taking address of dereference", linux_x64); | |
| 304 | case.addError( | |
| 305 | \\fn entry(a: *addrspace(.gs) i32) *i32 { | |
| 306 | \\ return &a.*; | |
| 307 | \\} | |
| 308 | \\pub export fn main() void { _ = entry; } | |
| 309 | , &[_][]const u8{ | |
| 310 | ":2:12: error: expected *i32, found *addrspace(.gs) i32", | |
| 311 | }); | |
| 312 | } | |
| 313 | ||
| 314 | { | |
| 315 | var case = ctx.exeUsingLlvmBackend("pointer keeps address space when taking address of dereference", linux_x64); | |
| 316 | case.compiles( | |
| 317 | \\fn entry(a: *addrspace(.gs) i32) *addrspace(.gs) i32 { | |
| 318 | \\ return &a.*; | |
| 319 | \\} | |
| 320 | \\pub export fn main() void { _ = entry; } | |
| 321 | ); | |
| 322 | } | |
| 323 | ||
| 324 | { | |
| 325 | var case = ctx.exeUsingLlvmBackend("address spaces pointer access chaining: array pointer", linux_x64); | |
| 326 | case.compiles( | |
| 327 | \\fn entry(a: *addrspace(.gs) [1]i32) *addrspace(.gs) i32 { | |
| 328 | \\ return &a[0]; | |
| 329 | \\} | |
| 330 | \\pub export fn main() void { _ = entry; } | |
| 331 | ); | |
| 332 | } | |
| 333 | ||
| 334 | { | |
| 335 | var case = ctx.exeUsingLlvmBackend("address spaces pointer access chaining: pointer to optional array", linux_x64); | |
| 336 | case.compiles( | |
| 337 | \\fn entry(a: *addrspace(.gs) ?[1]i32) *addrspace(.gs) i32 { | |
| 338 | \\ return &a.*.?[0]; | |
| 339 | \\} | |
| 340 | \\pub export fn main() void { _ = entry; } | |
| 341 | ); | |
| 342 | } | |
| 343 | ||
| 344 | { | |
| 345 | var case = ctx.exeUsingLlvmBackend("address spaces pointer access chaining: struct pointer", linux_x64); | |
| 346 | case.compiles( | |
| 347 | \\const A = struct{ a: i32 }; | |
| 348 | \\fn entry(a: *addrspace(.gs) A) *addrspace(.gs) i32 { | |
| 349 | \\ return &a.a; | |
| 350 | \\} | |
| 351 | \\pub export fn main() void { _ = entry; } | |
| 352 | ); | |
| 353 | } | |
| 354 | ||
| 355 | { | |
| 356 | var case = ctx.exeUsingLlvmBackend("address spaces pointer access chaining: complex", linux_x64); | |
| 357 | case.compiles( | |
| 358 | \\const A = struct{ a: ?[1]i32 }; | |
| 359 | \\fn entry(a: *addrspace(.gs) [1]A) *addrspace(.gs) i32 { | |
| 360 | \\ return &a[0].a.?[0]; | |
| 361 | \\} | |
| 362 | \\pub export fn main() void { _ = entry; } | |
| 363 | ); | |
| 364 | } | |
| 365 | ||
| 366 | { | |
| 367 | var case = ctx.exeUsingLlvmBackend("dereferencing through multiple pointers with address spaces", linux_x64); | |
| 368 | case.compiles( | |
| 369 | \\fn entry(a: *addrspace(.fs) *addrspace(.gs) *i32) *i32 { | |
| 370 | \\ return a.*.*; | |
| 371 | \\} | |
| 372 | \\pub export fn main() void { _ = entry; } | |
| 373 | ); | |
| 374 | } | |
| 375 | ||
| 376 | { | |
| 377 | var case = ctx.exeUsingLlvmBackend("f segment address space reading and writing", linux_x64); | |
| 378 | case.addCompareOutput( | |
| 379 | \\fn assert(ok: bool) void { | |
| 380 | \\ if (!ok) unreachable; | |
| 381 | \\} | |
| 382 | \\ | |
| 383 | \\fn setFs(value: c_ulong) void { | |
| 384 | \\ asm volatile ( | |
| 385 | \\ \\syscall | |
| 386 | \\ : | |
| 387 | \\ : [number] "{rax}" (158), | |
| 388 | \\ [code] "{rdi}" (0x1002), | |
| 389 | \\ [val] "{rsi}" (value), | |
| 390 | \\ : "rcx", "r11", "memory" | |
| 391 | \\ ); | |
| 392 | \\} | |
| 393 | \\ | |
| 394 | \\fn getFs() c_ulong { | |
| 395 | \\ var result: c_ulong = undefined; | |
| 396 | \\ asm volatile ( | |
| 397 | \\ \\syscall | |
| 398 | \\ : | |
| 399 | \\ : [number] "{rax}" (158), | |
| 400 | \\ [code] "{rdi}" (0x1003), | |
| 401 | \\ [ptr] "{rsi}" (@ptrToInt(&result)), | |
| 402 | \\ : "rcx", "r11", "memory" | |
| 403 | \\ ); | |
| 404 | \\ return result; | |
| 405 | \\} | |
| 406 | \\ | |
| 407 | \\var test_value: u64 = 12345; | |
| 408 | \\ | |
| 409 | \\pub export fn main() c_int { | |
| 410 | \\ const orig_fs = getFs(); | |
| 411 | \\ | |
| 412 | \\ setFs(@ptrToInt(&test_value)); | |
| 413 | \\ assert(getFs() == @ptrToInt(&test_value)); | |
| 414 | \\ | |
| 415 | \\ var test_ptr = @intToPtr(*allowzero addrspace(.fs) u64, 0); | |
| 416 | \\ assert(test_ptr.* == 12345); | |
| 417 | \\ test_ptr.* = 98765; | |
| 418 | \\ assert(test_value == 98765); | |
| 419 | \\ | |
| 420 | \\ setFs(orig_fs); | |
| 421 | \\ return 0; | |
| 422 | \\} | |
| 423 | , ""); | |
| 424 | } | |
| 245 | 425 | } |