| 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,6 +901,7 @@ fn tokenizeAndPrintRaw( |
| 901 | switch (token.tag) { | 901 | switch (token.tag) { |
| 902 | .eof => break, | 902 | .eof => break, |
| 903 | 903 | ||
| 904 | .keyword_addrspace, | ||
| 904 | .keyword_align, | 905 | .keyword_align, |
| 905 | .keyword_and, | 906 | .keyword_and, |
| 906 | .keyword_asm, | 907 | .keyword_asm, |
lib/std/builtin.zig+10| ... | @@ -166,6 +166,15 @@ pub const CallingConvention = enum { | ... | @@ -166,6 +166,15 @@ pub const CallingConvention = enum { |
| 166 | SysV, | 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 | /// This data structure is used by the Zig language code generation and | 178 | /// This data structure is used by the Zig language code generation and |
| 170 | /// therefore must be kept in sync with the compiler implementation. | 179 | /// therefore must be kept in sync with the compiler implementation. |
| 171 | pub const SourceLocation = struct { | 180 | pub const SourceLocation = struct { |
| ... | @@ -226,6 +235,7 @@ pub const TypeInfo = union(enum) { | ... | @@ -226,6 +235,7 @@ pub const TypeInfo = union(enum) { |
| 226 | is_const: bool, | 235 | is_const: bool, |
| 227 | is_volatile: bool, | 236 | is_volatile: bool, |
| 228 | alignment: comptime_int, | 237 | alignment: comptime_int, |
| 238 | address_space: AddressSpace, | ||
| 229 | child: type, | 239 | child: type, |
| 230 | is_allowzero: bool, | 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,6 +2472,7 @@ fn CopyPtrAttrs(comptime source: type, comptime size: std.builtin.TypeInfo.Point |
| 2472 | .is_volatile = info.is_volatile, | 2472 | .is_volatile = info.is_volatile, |
| 2473 | .is_allowzero = info.is_allowzero, | 2473 | .is_allowzero = info.is_allowzero, |
| 2474 | .alignment = info.alignment, | 2474 | .alignment = info.alignment, |
| 2475 | .address_space = info.address_space, | ||
| 2475 | .child = child, | 2476 | .child = child, |
| 2476 | .sentinel = null, | 2477 | .sentinel = null, |
| 2477 | }, | 2478 | }, |
| ... | @@ -2960,6 +2961,7 @@ fn AlignedSlice(comptime AttributeSource: type, comptime new_alignment: u29) typ | ... | @@ -2960,6 +2961,7 @@ fn AlignedSlice(comptime AttributeSource: type, comptime new_alignment: u29) typ |
| 2960 | .is_volatile = info.is_volatile, | 2961 | .is_volatile = info.is_volatile, |
| 2961 | .is_allowzero = info.is_allowzero, | 2962 | .is_allowzero = info.is_allowzero, |
| 2962 | .alignment = new_alignment, | 2963 | .alignment = new_alignment, |
| 2964 | .address_space = info.address_space, | ||
| 2963 | .child = info.child, | 2965 | .child = info.child, |
| 2964 | .sentinel = null, | 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,6 +235,7 @@ pub fn Sentinel(comptime T: type, comptime sentinel_val: Elem(T)) type { |
| 235 | .is_const = info.is_const, | 235 | .is_const = info.is_const, |
| 236 | .is_volatile = info.is_volatile, | 236 | .is_volatile = info.is_volatile, |
| 237 | .alignment = info.alignment, | 237 | .alignment = info.alignment, |
| 238 | .address_space = info.address_space, | ||
| 238 | .child = @Type(.{ | 239 | .child = @Type(.{ |
| 239 | .Array = .{ | 240 | .Array = .{ |
| 240 | .len = array_info.len, | 241 | .len = array_info.len, |
| ... | @@ -254,6 +255,7 @@ pub fn Sentinel(comptime T: type, comptime sentinel_val: Elem(T)) type { | ... | @@ -254,6 +255,7 @@ pub fn Sentinel(comptime T: type, comptime sentinel_val: Elem(T)) type { |
| 254 | .is_const = info.is_const, | 255 | .is_const = info.is_const, |
| 255 | .is_volatile = info.is_volatile, | 256 | .is_volatile = info.is_volatile, |
| 256 | .alignment = info.alignment, | 257 | .alignment = info.alignment, |
| 258 | .address_space = info.address_space, | ||
| 257 | .child = info.child, | 259 | .child = info.child, |
| 258 | .is_allowzero = info.is_allowzero, | 260 | .is_allowzero = info.is_allowzero, |
| 259 | .sentinel = sentinel_val, | 261 | .sentinel = sentinel_val, |
| ... | @@ -271,6 +273,7 @@ pub fn Sentinel(comptime T: type, comptime sentinel_val: Elem(T)) type { | ... | @@ -271,6 +273,7 @@ pub fn Sentinel(comptime T: type, comptime sentinel_val: Elem(T)) type { |
| 271 | .is_const = ptr_info.is_const, | 273 | .is_const = ptr_info.is_const, |
| 272 | .is_volatile = ptr_info.is_volatile, | 274 | .is_volatile = ptr_info.is_volatile, |
| 273 | .alignment = ptr_info.alignment, | 275 | .alignment = ptr_info.alignment, |
| 276 | .address_space = ptr_info.address_space, | ||
| 274 | .child = ptr_info.child, | 277 | .child = ptr_info.child, |
| 275 | .is_allowzero = ptr_info.is_allowzero, | 278 | .is_allowzero = ptr_info.is_allowzero, |
| 276 | .sentinel = sentinel_val, | 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,6 +262,9 @@ pub fn renderError(tree: Tree, parse_error: Error, stream: anytype) !void { |
| 262 | token_tags[parse_error.token].symbol(), | 262 | token_tags[parse_error.token].symbol(), |
| 263 | }); | 263 | }); |
| 264 | }, | 264 | }, |
| 265 | .extra_addrspace_qualifier => { | ||
| 266 | return stream.writeAll("extra addrspace qualifier"); | ||
| 267 | }, | ||
| 265 | .extra_align_qualifier => { | 268 | .extra_align_qualifier => { |
| 266 | return stream.writeAll("extra align qualifier"); | 269 | return stream.writeAll("extra align qualifier"); |
| 267 | }, | 270 | }, |
| ... | @@ -1021,7 +1024,7 @@ pub fn lastToken(tree: Tree, node: Node.Index) TokenIndex { | ... | @@ -1021,7 +1024,7 @@ pub fn lastToken(tree: Tree, node: Node.Index) TokenIndex { |
| 1021 | }, | 1024 | }, |
| 1022 | .fn_proto_one => { | 1025 | .fn_proto_one => { |
| 1023 | const extra = tree.extraData(datas[n].lhs, Node.FnProtoOne); | 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 | // find the last one here. | 1028 | // find the last one here. |
| 1026 | var max_node: Node.Index = datas[n].rhs; | 1029 | var max_node: Node.Index = datas[n].rhs; |
| 1027 | var max_start = token_starts[main_tokens[max_node]]; | 1030 | var max_start = token_starts[main_tokens[max_node]]; |
| ... | @@ -1034,6 +1037,14 @@ pub fn lastToken(tree: Tree, node: Node.Index) TokenIndex { | ... | @@ -1034,6 +1037,14 @@ pub fn lastToken(tree: Tree, node: Node.Index) TokenIndex { |
| 1034 | max_offset = 1; // for the rparen | 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 | if (extra.section_expr != 0) { | 1048 | if (extra.section_expr != 0) { |
| 1038 | const start = token_starts[main_tokens[extra.section_expr]]; | 1049 | const start = token_starts[main_tokens[extra.section_expr]]; |
| 1039 | if (start > max_start) { | 1050 | if (start > max_start) { |
| ... | @@ -1055,7 +1066,7 @@ pub fn lastToken(tree: Tree, node: Node.Index) TokenIndex { | ... | @@ -1055,7 +1066,7 @@ pub fn lastToken(tree: Tree, node: Node.Index) TokenIndex { |
| 1055 | }, | 1066 | }, |
| 1056 | .fn_proto => { | 1067 | .fn_proto => { |
| 1057 | const extra = tree.extraData(datas[n].lhs, Node.FnProto); | 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 | // find the last one here. | 1070 | // find the last one here. |
| 1060 | var max_node: Node.Index = datas[n].rhs; | 1071 | var max_node: Node.Index = datas[n].rhs; |
| 1061 | var max_start = token_starts[main_tokens[max_node]]; | 1072 | var max_start = token_starts[main_tokens[max_node]]; |
| ... | @@ -1068,6 +1079,14 @@ pub fn lastToken(tree: Tree, node: Node.Index) TokenIndex { | ... | @@ -1068,6 +1079,14 @@ pub fn lastToken(tree: Tree, node: Node.Index) TokenIndex { |
| 1068 | max_offset = 1; // for the rparen | 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 | if (extra.section_expr != 0) { | 1090 | if (extra.section_expr != 0) { |
| 1072 | const start = token_starts[main_tokens[extra.section_expr]]; | 1091 | const start = token_starts[main_tokens[extra.section_expr]]; |
| 1073 | if (start > max_start) { | 1092 | if (start > max_start) { |
| ... | @@ -1138,6 +1157,7 @@ pub fn globalVarDecl(tree: Tree, node: Node.Index) full.VarDecl { | ... | @@ -1138,6 +1157,7 @@ pub fn globalVarDecl(tree: Tree, node: Node.Index) full.VarDecl { |
| 1138 | return tree.fullVarDecl(.{ | 1157 | return tree.fullVarDecl(.{ |
| 1139 | .type_node = extra.type_node, | 1158 | .type_node = extra.type_node, |
| 1140 | .align_node = extra.align_node, | 1159 | .align_node = extra.align_node, |
| 1160 | .addrspace_node = extra.addrspace_node, | ||
| 1141 | .section_node = extra.section_node, | 1161 | .section_node = extra.section_node, |
| 1142 | .init_node = data.rhs, | 1162 | .init_node = data.rhs, |
| 1143 | .mut_token = tree.nodes.items(.main_token)[node], | 1163 | .mut_token = tree.nodes.items(.main_token)[node], |
| ... | @@ -1151,6 +1171,7 @@ pub fn localVarDecl(tree: Tree, node: Node.Index) full.VarDecl { | ... | @@ -1151,6 +1171,7 @@ pub fn localVarDecl(tree: Tree, node: Node.Index) full.VarDecl { |
| 1151 | return tree.fullVarDecl(.{ | 1171 | return tree.fullVarDecl(.{ |
| 1152 | .type_node = extra.type_node, | 1172 | .type_node = extra.type_node, |
| 1153 | .align_node = extra.align_node, | 1173 | .align_node = extra.align_node, |
| 1174 | .addrspace_node = 0, | ||
| 1154 | .section_node = 0, | 1175 | .section_node = 0, |
| 1155 | .init_node = data.rhs, | 1176 | .init_node = data.rhs, |
| 1156 | .mut_token = tree.nodes.items(.main_token)[node], | 1177 | .mut_token = tree.nodes.items(.main_token)[node], |
| ... | @@ -1163,6 +1184,7 @@ pub fn simpleVarDecl(tree: Tree, node: Node.Index) full.VarDecl { | ... | @@ -1163,6 +1184,7 @@ pub fn simpleVarDecl(tree: Tree, node: Node.Index) full.VarDecl { |
| 1163 | return tree.fullVarDecl(.{ | 1184 | return tree.fullVarDecl(.{ |
| 1164 | .type_node = data.lhs, | 1185 | .type_node = data.lhs, |
| 1165 | .align_node = 0, | 1186 | .align_node = 0, |
| 1187 | .addrspace_node = 0, | ||
| 1166 | .section_node = 0, | 1188 | .section_node = 0, |
| 1167 | .init_node = data.rhs, | 1189 | .init_node = data.rhs, |
| 1168 | .mut_token = tree.nodes.items(.main_token)[node], | 1190 | .mut_token = tree.nodes.items(.main_token)[node], |
| ... | @@ -1175,6 +1197,7 @@ pub fn alignedVarDecl(tree: Tree, node: Node.Index) full.VarDecl { | ... | @@ -1175,6 +1197,7 @@ pub fn alignedVarDecl(tree: Tree, node: Node.Index) full.VarDecl { |
| 1175 | return tree.fullVarDecl(.{ | 1197 | return tree.fullVarDecl(.{ |
| 1176 | .type_node = 0, | 1198 | .type_node = 0, |
| 1177 | .align_node = data.lhs, | 1199 | .align_node = data.lhs, |
| 1200 | .addrspace_node = 0, | ||
| 1178 | .section_node = 0, | 1201 | .section_node = 0, |
| 1179 | .init_node = data.rhs, | 1202 | .init_node = data.rhs, |
| 1180 | .mut_token = tree.nodes.items(.main_token)[node], | 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,6 +1272,7 @@ pub fn fnProtoSimple(tree: Tree, buffer: *[1]Node.Index, node: Node.Index) full. |
| 1249 | .return_type = data.rhs, | 1272 | .return_type = data.rhs, |
| 1250 | .params = params, | 1273 | .params = params, |
| 1251 | .align_expr = 0, | 1274 | .align_expr = 0, |
| 1275 | .addrspace_expr = 0, | ||
| 1252 | .section_expr = 0, | 1276 | .section_expr = 0, |
| 1253 | .callconv_expr = 0, | 1277 | .callconv_expr = 0, |
| 1254 | }); | 1278 | }); |
| ... | @@ -1265,6 +1289,7 @@ pub fn fnProtoMulti(tree: Tree, node: Node.Index) full.FnProto { | ... | @@ -1265,6 +1289,7 @@ pub fn fnProtoMulti(tree: Tree, node: Node.Index) full.FnProto { |
| 1265 | .return_type = data.rhs, | 1289 | .return_type = data.rhs, |
| 1266 | .params = params, | 1290 | .params = params, |
| 1267 | .align_expr = 0, | 1291 | .align_expr = 0, |
| 1292 | .addrspace_expr = 0, | ||
| 1268 | .section_expr = 0, | 1293 | .section_expr = 0, |
| 1269 | .callconv_expr = 0, | 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,6 +1307,7 @@ pub fn fnProtoOne(tree: Tree, buffer: *[1]Node.Index, node: Node.Index) full.FnP |
| 1282 | .return_type = data.rhs, | 1307 | .return_type = data.rhs, |
| 1283 | .params = params, | 1308 | .params = params, |
| 1284 | .align_expr = extra.align_expr, | 1309 | .align_expr = extra.align_expr, |
| 1310 | .addrspace_expr = extra.addrspace_expr, | ||
| 1285 | .section_expr = extra.section_expr, | 1311 | .section_expr = extra.section_expr, |
| 1286 | .callconv_expr = extra.callconv_expr, | 1312 | .callconv_expr = extra.callconv_expr, |
| 1287 | }); | 1313 | }); |
| ... | @@ -1298,6 +1324,7 @@ pub fn fnProto(tree: Tree, node: Node.Index) full.FnProto { | ... | @@ -1298,6 +1324,7 @@ pub fn fnProto(tree: Tree, node: Node.Index) full.FnProto { |
| 1298 | .return_type = data.rhs, | 1324 | .return_type = data.rhs, |
| 1299 | .params = params, | 1325 | .params = params, |
| 1300 | .align_expr = extra.align_expr, | 1326 | .align_expr = extra.align_expr, |
| 1327 | .addrspace_expr = extra.addrspace_expr, | ||
| 1301 | .section_expr = extra.section_expr, | 1328 | .section_expr = extra.section_expr, |
| 1302 | .callconv_expr = extra.callconv_expr, | 1329 | .callconv_expr = extra.callconv_expr, |
| 1303 | }); | 1330 | }); |
| ... | @@ -1453,6 +1480,7 @@ pub fn ptrTypeAligned(tree: Tree, node: Node.Index) full.PtrType { | ... | @@ -1453,6 +1480,7 @@ pub fn ptrTypeAligned(tree: Tree, node: Node.Index) full.PtrType { |
| 1453 | return tree.fullPtrType(.{ | 1480 | return tree.fullPtrType(.{ |
| 1454 | .main_token = tree.nodes.items(.main_token)[node], | 1481 | .main_token = tree.nodes.items(.main_token)[node], |
| 1455 | .align_node = data.lhs, | 1482 | .align_node = data.lhs, |
| 1483 | .addrspace_node = 0, | ||
| 1456 | .sentinel = 0, | 1484 | .sentinel = 0, |
| 1457 | .bit_range_start = 0, | 1485 | .bit_range_start = 0, |
| 1458 | .bit_range_end = 0, | 1486 | .bit_range_end = 0, |
| ... | @@ -1466,6 +1494,7 @@ pub fn ptrTypeSentinel(tree: Tree, node: Node.Index) full.PtrType { | ... | @@ -1466,6 +1494,7 @@ pub fn ptrTypeSentinel(tree: Tree, node: Node.Index) full.PtrType { |
| 1466 | return tree.fullPtrType(.{ | 1494 | return tree.fullPtrType(.{ |
| 1467 | .main_token = tree.nodes.items(.main_token)[node], | 1495 | .main_token = tree.nodes.items(.main_token)[node], |
| 1468 | .align_node = 0, | 1496 | .align_node = 0, |
| 1497 | .addrspace_node = 0, | ||
| 1469 | .sentinel = data.lhs, | 1498 | .sentinel = data.lhs, |
| 1470 | .bit_range_start = 0, | 1499 | .bit_range_start = 0, |
| 1471 | .bit_range_end = 0, | 1500 | .bit_range_end = 0, |
| ... | @@ -1480,6 +1509,7 @@ pub fn ptrType(tree: Tree, node: Node.Index) full.PtrType { | ... | @@ -1480,6 +1509,7 @@ pub fn ptrType(tree: Tree, node: Node.Index) full.PtrType { |
| 1480 | return tree.fullPtrType(.{ | 1509 | return tree.fullPtrType(.{ |
| 1481 | .main_token = tree.nodes.items(.main_token)[node], | 1510 | .main_token = tree.nodes.items(.main_token)[node], |
| 1482 | .align_node = extra.align_node, | 1511 | .align_node = extra.align_node, |
| 1512 | .addrspace_node = extra.addrspace_node, | ||
| 1483 | .sentinel = extra.sentinel, | 1513 | .sentinel = extra.sentinel, |
| 1484 | .bit_range_start = 0, | 1514 | .bit_range_start = 0, |
| 1485 | .bit_range_end = 0, | 1515 | .bit_range_end = 0, |
| ... | @@ -1494,6 +1524,7 @@ pub fn ptrTypeBitRange(tree: Tree, node: Node.Index) full.PtrType { | ... | @@ -1494,6 +1524,7 @@ pub fn ptrTypeBitRange(tree: Tree, node: Node.Index) full.PtrType { |
| 1494 | return tree.fullPtrType(.{ | 1524 | return tree.fullPtrType(.{ |
| 1495 | .main_token = tree.nodes.items(.main_token)[node], | 1525 | .main_token = tree.nodes.items(.main_token)[node], |
| 1496 | .align_node = extra.align_node, | 1526 | .align_node = extra.align_node, |
| 1527 | .addrspace_node = extra.addrspace_node, | ||
| 1497 | .sentinel = extra.sentinel, | 1528 | .sentinel = extra.sentinel, |
| 1498 | .bit_range_start = extra.bit_range_start, | 1529 | .bit_range_start = extra.bit_range_start, |
| 1499 | .bit_range_end = extra.bit_range_end, | 1530 | .bit_range_end = extra.bit_range_end, |
| ... | @@ -2063,6 +2094,7 @@ pub const full = struct { | ... | @@ -2063,6 +2094,7 @@ pub const full = struct { |
| 2063 | mut_token: TokenIndex, | 2094 | mut_token: TokenIndex, |
| 2064 | type_node: Node.Index, | 2095 | type_node: Node.Index, |
| 2065 | align_node: Node.Index, | 2096 | align_node: Node.Index, |
| 2097 | addrspace_node: Node.Index, | ||
| 2066 | section_node: Node.Index, | 2098 | section_node: Node.Index, |
| 2067 | init_node: Node.Index, | 2099 | init_node: Node.Index, |
| 2068 | }; | 2100 | }; |
| ... | @@ -2130,6 +2162,7 @@ pub const full = struct { | ... | @@ -2130,6 +2162,7 @@ pub const full = struct { |
| 2130 | return_type: Node.Index, | 2162 | return_type: Node.Index, |
| 2131 | params: []const Node.Index, | 2163 | params: []const Node.Index, |
| 2132 | align_expr: Node.Index, | 2164 | align_expr: Node.Index, |
| 2165 | addrspace_expr: Node.Index, | ||
| 2133 | section_expr: Node.Index, | 2166 | section_expr: Node.Index, |
| 2134 | callconv_expr: Node.Index, | 2167 | callconv_expr: Node.Index, |
| 2135 | }; | 2168 | }; |
| ... | @@ -2288,6 +2321,7 @@ pub const full = struct { | ... | @@ -2288,6 +2321,7 @@ pub const full = struct { |
| 2288 | pub const Components = struct { | 2321 | pub const Components = struct { |
| 2289 | main_token: TokenIndex, | 2322 | main_token: TokenIndex, |
| 2290 | align_node: Node.Index, | 2323 | align_node: Node.Index, |
| 2324 | addrspace_node: Node.Index, | ||
| 2291 | sentinel: Node.Index, | 2325 | sentinel: Node.Index, |
| 2292 | bit_range_start: Node.Index, | 2326 | bit_range_start: Node.Index, |
| 2293 | bit_range_end: Node.Index, | 2327 | bit_range_end: Node.Index, |
| ... | @@ -2397,6 +2431,7 @@ pub const Error = struct { | ... | @@ -2397,6 +2431,7 @@ pub const Error = struct { |
| 2397 | expected_var_decl_or_fn, | 2431 | expected_var_decl_or_fn, |
| 2398 | expected_loop_payload, | 2432 | expected_loop_payload, |
| 2399 | expected_container, | 2433 | expected_container, |
| 2434 | extra_addrspace_qualifier, | ||
| 2400 | extra_align_qualifier, | 2435 | extra_align_qualifier, |
| 2401 | extra_allowzero_qualifier, | 2436 | extra_allowzero_qualifier, |
| 2402 | extra_const_qualifier, | 2437 | extra_const_qualifier, |
| ... | @@ -2723,13 +2758,13 @@ pub const Node = struct { | ... | @@ -2723,13 +2758,13 @@ pub const Node = struct { |
| 2723 | /// main_token is the `fn` keyword. | 2758 | /// main_token is the `fn` keyword. |
| 2724 | /// extern function declarations use this tag. | 2759 | /// extern function declarations use this tag. |
| 2725 | fn_proto_multi, | 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 | /// zero or one parameters. | 2762 | /// zero or one parameters. |
| 2728 | /// anytype and ... parameters are omitted from the AST tree. | 2763 | /// anytype and ... parameters are omitted from the AST tree. |
| 2729 | /// main_token is the `fn` keyword. | 2764 | /// main_token is the `fn` keyword. |
| 2730 | /// extern function declarations use this tag. | 2765 | /// extern function declarations use this tag. |
| 2731 | fn_proto_one, | 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 | /// anytype and ... parameters are omitted from the AST tree. | 2768 | /// anytype and ... parameters are omitted from the AST tree. |
| 2734 | /// main_token is the `fn` keyword. | 2769 | /// main_token is the `fn` keyword. |
| 2735 | /// extern function declarations use this tag. | 2770 | /// extern function declarations use this tag. |
| ... | @@ -2893,11 +2928,13 @@ pub const Node = struct { | ... | @@ -2893,11 +2928,13 @@ pub const Node = struct { |
| 2893 | pub const PtrType = struct { | 2928 | pub const PtrType = struct { |
| 2894 | sentinel: Index, | 2929 | sentinel: Index, |
| 2895 | align_node: Index, | 2930 | align_node: Index, |
| 2931 | addrspace_node: Index, | ||
| 2896 | }; | 2932 | }; |
| 2897 | 2933 | ||
| 2898 | pub const PtrTypeBitRange = struct { | 2934 | pub const PtrTypeBitRange = struct { |
| 2899 | sentinel: Index, | 2935 | sentinel: Index, |
| 2900 | align_node: Index, | 2936 | align_node: Index, |
| 2937 | addrspace_node: Index, | ||
| 2901 | bit_range_start: Index, | 2938 | bit_range_start: Index, |
| 2902 | bit_range_end: Index, | 2939 | bit_range_end: Index, |
| 2903 | }; | 2940 | }; |
| ... | @@ -2920,8 +2957,13 @@ pub const Node = struct { | ... | @@ -2920,8 +2957,13 @@ pub const Node = struct { |
| 2920 | }; | 2957 | }; |
| 2921 | 2958 | ||
| 2922 | pub const GlobalVarDecl = struct { | 2959 | pub const GlobalVarDecl = struct { |
| 2960 | /// Populated if there is an explicit type ascription. | ||
| 2923 | type_node: Index, | 2961 | type_node: Index, |
| 2962 | /// Populated if align(A) is present. | ||
| 2924 | align_node: Index, | 2963 | align_node: Index, |
| 2964 | /// Populated if addrspace(A) is present. | ||
| 2965 | addrspace_node: Index, | ||
| 2966 | /// Populated if linksection(A) is present. | ||
| 2925 | section_node: Index, | 2967 | section_node: Index, |
| 2926 | }; | 2968 | }; |
| 2927 | 2969 | ||
| ... | @@ -2953,6 +2995,8 @@ pub const Node = struct { | ... | @@ -2953,6 +2995,8 @@ pub const Node = struct { |
| 2953 | param: Index, | 2995 | param: Index, |
| 2954 | /// Populated if align(A) is present. | 2996 | /// Populated if align(A) is present. |
| 2955 | align_expr: Index, | 2997 | align_expr: Index, |
| 2998 | /// Populated if addrspace(A) is present. | ||
| 2999 | addrspace_expr: Index, | ||
| 2956 | /// Populated if linksection(A) is present. | 3000 | /// Populated if linksection(A) is present. |
| 2957 | section_expr: Index, | 3001 | section_expr: Index, |
| 2958 | /// Populated if callconv(A) is present. | 3002 | /// Populated if callconv(A) is present. |
| ... | @@ -2964,6 +3008,8 @@ pub const Node = struct { | ... | @@ -2964,6 +3008,8 @@ pub const Node = struct { |
| 2964 | params_end: Index, | 3008 | params_end: Index, |
| 2965 | /// Populated if align(A) is present. | 3009 | /// Populated if align(A) is present. |
| 2966 | align_expr: Index, | 3010 | align_expr: Index, |
| 3011 | /// Populated if addrspace(A) is present. | ||
| 3012 | addrspace_expr: Index, | ||
| 2967 | /// Populated if linksection(A) is present. | 3013 | /// Populated if linksection(A) is present. |
| 2968 | section_expr: Index, | 3014 | section_expr: Index, |
| 2969 | /// Populated if callconv(A) is present. | 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,6 +325,7 @@ pub fn FlexibleArrayType(comptime SelfType: type, ElementType: type) type { |
| 325 | .is_const = ptr.is_const, | 325 | .is_const = ptr.is_const, |
| 326 | .is_volatile = ptr.is_volatile, | 326 | .is_volatile = ptr.is_volatile, |
| 327 | .alignment = @alignOf(ElementType), | 327 | .alignment = @alignOf(ElementType), |
| 328 | .address_space = .generic, | ||
| 328 | .child = ElementType, | 329 | .child = ElementType, |
| 329 | .is_allowzero = true, | 330 | .is_allowzero = true, |
| 330 | .sentinel = null, | 331 | .sentinel = null, |
lib/std/zig/parse.zig+81-26| ... | @@ -629,7 +629,7 @@ const Parser = struct { | ... | @@ -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 | fn parseFnProto(p: *Parser) !Node.Index { | 633 | fn parseFnProto(p: *Parser) !Node.Index { |
| 634 | const fn_token = p.eatToken(.keyword_fn) orelse return null_node; | 634 | const fn_token = p.eatToken(.keyword_fn) orelse return null_node; |
| 635 | 635 | ||
| ... | @@ -639,6 +639,7 @@ const Parser = struct { | ... | @@ -639,6 +639,7 @@ const Parser = struct { |
| 639 | _ = p.eatToken(.identifier); | 639 | _ = p.eatToken(.identifier); |
| 640 | const params = try p.parseParamDeclList(); | 640 | const params = try p.parseParamDeclList(); |
| 641 | const align_expr = try p.parseByteAlign(); | 641 | const align_expr = try p.parseByteAlign(); |
| 642 | const addrspace_expr = try p.parseAddrSpace(); | ||
| 642 | const section_expr = try p.parseLinkSection(); | 643 | const section_expr = try p.parseLinkSection(); |
| 643 | const callconv_expr = try p.parseCallconv(); | 644 | const callconv_expr = try p.parseCallconv(); |
| 644 | _ = p.eatToken(.bang); | 645 | _ = p.eatToken(.bang); |
| ... | @@ -650,7 +651,7 @@ const Parser = struct { | ... | @@ -650,7 +651,7 @@ const Parser = struct { |
| 650 | try p.warn(.expected_return_type); | 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 | switch (params) { | 655 | switch (params) { |
| 655 | .zero_or_one => |param| return p.setNode(fn_proto_index, .{ | 656 | .zero_or_one => |param| return p.setNode(fn_proto_index, .{ |
| 656 | .tag = .fn_proto_simple, | 657 | .tag = .fn_proto_simple, |
| ... | @@ -683,6 +684,7 @@ const Parser = struct { | ... | @@ -683,6 +684,7 @@ const Parser = struct { |
| 683 | .lhs = try p.addExtra(Node.FnProtoOne{ | 684 | .lhs = try p.addExtra(Node.FnProtoOne{ |
| 684 | .param = param, | 685 | .param = param, |
| 685 | .align_expr = align_expr, | 686 | .align_expr = align_expr, |
| 687 | .addrspace_expr = addrspace_expr, | ||
| 686 | .section_expr = section_expr, | 688 | .section_expr = section_expr, |
| 687 | .callconv_expr = callconv_expr, | 689 | .callconv_expr = callconv_expr, |
| 688 | }), | 690 | }), |
| ... | @@ -698,6 +700,7 @@ const Parser = struct { | ... | @@ -698,6 +700,7 @@ const Parser = struct { |
| 698 | .params_start = span.start, | 700 | .params_start = span.start, |
| 699 | .params_end = span.end, | 701 | .params_end = span.end, |
| 700 | .align_expr = align_expr, | 702 | .align_expr = align_expr, |
| 703 | .addrspace_expr = addrspace_expr, | ||
| 701 | .section_expr = section_expr, | 704 | .section_expr = section_expr, |
| 702 | .callconv_expr = callconv_expr, | 705 | .callconv_expr = callconv_expr, |
| 703 | }), | 706 | }), |
| ... | @@ -708,7 +711,7 @@ const Parser = struct { | ... | @@ -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 | fn parseVarDecl(p: *Parser) !Node.Index { | 715 | fn parseVarDecl(p: *Parser) !Node.Index { |
| 713 | const mut_token = p.eatToken(.keyword_const) orelse | 716 | const mut_token = p.eatToken(.keyword_const) orelse |
| 714 | p.eatToken(.keyword_var) orelse | 717 | p.eatToken(.keyword_var) orelse |
| ... | @@ -717,9 +720,10 @@ const Parser = struct { | ... | @@ -717,9 +720,10 @@ const Parser = struct { |
| 717 | _ = try p.expectToken(.identifier); | 720 | _ = try p.expectToken(.identifier); |
| 718 | const type_node: Node.Index = if (p.eatToken(.colon) == null) 0 else try p.expectTypeExpr(); | 721 | const type_node: Node.Index = if (p.eatToken(.colon) == null) 0 else try p.expectTypeExpr(); |
| 719 | const align_node = try p.parseByteAlign(); | 722 | const align_node = try p.parseByteAlign(); |
| 723 | const addrspace_node = try p.parseAddrSpace(); | ||
| 720 | const section_node = try p.parseLinkSection(); | 724 | const section_node = try p.parseLinkSection(); |
| 721 | const init_node: Node.Index = if (p.eatToken(.equal) == null) 0 else try p.expectExpr(); | 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 | if (align_node == 0) { | 727 | if (align_node == 0) { |
| 724 | return p.addNode(.{ | 728 | return p.addNode(.{ |
| 725 | .tag = .simple_var_decl, | 729 | .tag = .simple_var_decl, |
| ... | @@ -759,6 +763,7 @@ const Parser = struct { | ... | @@ -759,6 +763,7 @@ const Parser = struct { |
| 759 | .lhs = try p.addExtra(Node.GlobalVarDecl{ | 763 | .lhs = try p.addExtra(Node.GlobalVarDecl{ |
| 760 | .type_node = type_node, | 764 | .type_node = type_node, |
| 761 | .align_node = align_node, | 765 | .align_node = align_node, |
| 766 | .addrspace_node = addrspace_node, | ||
| 762 | .section_node = section_node, | 767 | .section_node = section_node, |
| 763 | }), | 768 | }), |
| 764 | .rhs = init_node, | 769 | .rhs = init_node, |
| ... | @@ -1440,8 +1445,8 @@ const Parser = struct { | ... | @@ -1440,8 +1445,8 @@ const Parser = struct { |
| 1440 | /// PrefixTypeOp | 1445 | /// PrefixTypeOp |
| 1441 | /// <- QUESTIONMARK | 1446 | /// <- QUESTIONMARK |
| 1442 | /// / KEYWORD_anyframe MINUSRARROW | 1447 | /// / KEYWORD_anyframe MINUSRARROW |
| 1443 | /// / SliceTypeStart (ByteAlign / KEYWORD_const / KEYWORD_volatile / KEYWORD_allowzero)* | 1448 | /// / SliceTypeStart (ByteAlign / AddrSpace / KEYWORD_const / KEYWORD_volatile / KEYWORD_allowzero)* |
| 1444 | /// / PtrTypeStart (KEYWORD_align LPAREN Expr (COLON INTEGER COLON INTEGER)? RPAREN / 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 | /// / ArrayTypeStart | 1450 | /// / ArrayTypeStart |
| 1446 | /// SliceTypeStart <- LBRACKET (COLON Expr)? RBRACKET | 1451 | /// SliceTypeStart <- LBRACKET (COLON Expr)? RBRACKET |
| 1447 | /// PtrTypeStart | 1452 | /// PtrTypeStart |
| ... | @@ -1474,29 +1479,43 @@ const Parser = struct { | ... | @@ -1474,29 +1479,43 @@ const Parser = struct { |
| 1474 | const asterisk = p.nextToken(); | 1479 | const asterisk = p.nextToken(); |
| 1475 | const mods = try p.parsePtrModifiers(); | 1480 | const mods = try p.parsePtrModifiers(); |
| 1476 | const elem_type = try p.expectTypeExpr(); | 1481 | const elem_type = try p.expectTypeExpr(); |
| 1477 | if (mods.bit_range_start == 0) { | 1482 | if (mods.bit_range_start != 0) { |
| 1478 | return p.addNode(.{ | 1483 | return p.addNode(.{ |
| 1479 | .tag = .ptr_type_aligned, | 1484 | .tag = .ptr_type_bit_range, |
| 1480 | .main_token = asterisk, | 1485 | .main_token = asterisk, |
| 1481 | .data = .{ | 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 | .rhs = elem_type, | 1494 | .rhs = elem_type, |
| 1484 | }, | 1495 | }, |
| 1485 | }); | 1496 | }); |
| 1486 | } else { | 1497 | } else if (mods.addrspace_node != 0) { |
| 1487 | return p.addNode(.{ | 1498 | return p.addNode(.{ |
| 1488 | .tag = .ptr_type_bit_range, | 1499 | .tag = .ptr_type, |
| 1489 | .main_token = asterisk, | 1500 | .main_token = asterisk, |
| 1490 | .data = .{ | 1501 | .data = .{ |
| 1491 | .lhs = try p.addExtra(Node.PtrTypeBitRange{ | 1502 | .lhs = try p.addExtra(Node.PtrType{ |
| 1492 | .sentinel = 0, | 1503 | .sentinel = 0, |
| 1493 | .align_node = mods.align_node, | 1504 | .align_node = mods.align_node, |
| 1494 | .bit_range_start = mods.bit_range_start, | 1505 | .addrspace_node = mods.addrspace_node, |
| 1495 | .bit_range_end = mods.bit_range_end, | ||
| 1496 | }), | 1506 | }), |
| 1497 | .rhs = elem_type, | 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 | .asterisk_asterisk => { | 1521 | .asterisk_asterisk => { |
| ... | @@ -1504,29 +1523,43 @@ const Parser = struct { | ... | @@ -1504,29 +1523,43 @@ const Parser = struct { |
| 1504 | const mods = try p.parsePtrModifiers(); | 1523 | const mods = try p.parsePtrModifiers(); |
| 1505 | const elem_type = try p.expectTypeExpr(); | 1524 | const elem_type = try p.expectTypeExpr(); |
| 1506 | const inner: Node.Index = inner: { | 1525 | const inner: Node.Index = inner: { |
| 1507 | if (mods.bit_range_start == 0) { | 1526 | if (mods.bit_range_start != 0) { |
| 1508 | break :inner try p.addNode(.{ | 1527 | break :inner try p.addNode(.{ |
| 1509 | .tag = .ptr_type_aligned, | 1528 | .tag = .ptr_type_bit_range, |
| 1510 | .main_token = asterisk, | 1529 | .main_token = asterisk, |
| 1511 | .data = .{ | 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 | .rhs = elem_type, | 1538 | .rhs = elem_type, |
| 1514 | }, | 1539 | }, |
| 1515 | }); | 1540 | }); |
| 1516 | } else { | 1541 | } else if (mods.addrspace_node != 0) { |
| 1517 | break :inner try p.addNode(.{ | 1542 | break :inner try p.addNode(.{ |
| 1518 | .tag = .ptr_type_bit_range, | 1543 | .tag = .ptr_type, |
| 1519 | .main_token = asterisk, | 1544 | .main_token = asterisk, |
| 1520 | .data = .{ | 1545 | .data = .{ |
| 1521 | .lhs = try p.addExtra(Node.PtrTypeBitRange{ | 1546 | .lhs = try p.addExtra(Node.PtrType{ |
| 1522 | .sentinel = 0, | 1547 | .sentinel = 0, |
| 1523 | .align_node = mods.align_node, | 1548 | .align_node = mods.align_node, |
| 1524 | .bit_range_start = mods.bit_range_start, | 1549 | .addrspace_node = mods.addrspace_node, |
| 1525 | .bit_range_end = mods.bit_range_end, | ||
| 1526 | }), | 1550 | }), |
| 1527 | .rhs = elem_type, | 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 | return p.addNode(.{ | 1565 | return p.addNode(.{ |
| ... | @@ -1560,7 +1593,7 @@ const Parser = struct { | ... | @@ -1560,7 +1593,7 @@ const Parser = struct { |
| 1560 | const mods = try p.parsePtrModifiers(); | 1593 | const mods = try p.parsePtrModifiers(); |
| 1561 | const elem_type = try p.expectTypeExpr(); | 1594 | const elem_type = try p.expectTypeExpr(); |
| 1562 | if (mods.bit_range_start == 0) { | 1595 | if (mods.bit_range_start == 0) { |
| 1563 | if (sentinel == 0) { | 1596 | if (sentinel == 0 and mods.addrspace_node == 0) { |
| 1564 | return p.addNode(.{ | 1597 | return p.addNode(.{ |
| 1565 | .tag = .ptr_type_aligned, | 1598 | .tag = .ptr_type_aligned, |
| 1566 | .main_token = asterisk, | 1599 | .main_token = asterisk, |
| ... | @@ -1569,7 +1602,7 @@ const Parser = struct { | ... | @@ -1569,7 +1602,7 @@ const Parser = struct { |
| 1569 | .rhs = elem_type, | 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 | return p.addNode(.{ | 1606 | return p.addNode(.{ |
| 1574 | .tag = .ptr_type_sentinel, | 1607 | .tag = .ptr_type_sentinel, |
| 1575 | .main_token = asterisk, | 1608 | .main_token = asterisk, |
| ... | @@ -1586,6 +1619,7 @@ const Parser = struct { | ... | @@ -1586,6 +1619,7 @@ const Parser = struct { |
| 1586 | .lhs = try p.addExtra(Node.PtrType{ | 1619 | .lhs = try p.addExtra(Node.PtrType{ |
| 1587 | .sentinel = sentinel, | 1620 | .sentinel = sentinel, |
| 1588 | .align_node = mods.align_node, | 1621 | .align_node = mods.align_node, |
| 1622 | .addrspace_node = mods.addrspace_node, | ||
| 1589 | }), | 1623 | }), |
| 1590 | .rhs = elem_type, | 1624 | .rhs = elem_type, |
| 1591 | }, | 1625 | }, |
| ... | @@ -1599,6 +1633,7 @@ const Parser = struct { | ... | @@ -1599,6 +1633,7 @@ const Parser = struct { |
| 1599 | .lhs = try p.addExtra(Node.PtrTypeBitRange{ | 1633 | .lhs = try p.addExtra(Node.PtrTypeBitRange{ |
| 1600 | .sentinel = sentinel, | 1634 | .sentinel = sentinel, |
| 1601 | .align_node = mods.align_node, | 1635 | .align_node = mods.align_node, |
| 1636 | .addrspace_node = mods.addrspace_node, | ||
| 1602 | .bit_range_start = mods.bit_range_start, | 1637 | .bit_range_start = mods.bit_range_start, |
| 1603 | .bit_range_end = mods.bit_range_end, | 1638 | .bit_range_end = mods.bit_range_end, |
| 1604 | }), | 1639 | }), |
| ... | @@ -1624,7 +1659,7 @@ const Parser = struct { | ... | @@ -1624,7 +1659,7 @@ const Parser = struct { |
| 1624 | .token = p.nodes.items(.main_token)[mods.bit_range_start], | 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 | return p.addNode(.{ | 1663 | return p.addNode(.{ |
| 1629 | .tag = .ptr_type_aligned, | 1664 | .tag = .ptr_type_aligned, |
| 1630 | .main_token = lbracket, | 1665 | .main_token = lbracket, |
| ... | @@ -1633,7 +1668,7 @@ const Parser = struct { | ... | @@ -1633,7 +1668,7 @@ const Parser = struct { |
| 1633 | .rhs = elem_type, | 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 | return p.addNode(.{ | 1672 | return p.addNode(.{ |
| 1638 | .tag = .ptr_type_sentinel, | 1673 | .tag = .ptr_type_sentinel, |
| 1639 | .main_token = lbracket, | 1674 | .main_token = lbracket, |
| ... | @@ -1650,6 +1685,7 @@ const Parser = struct { | ... | @@ -1650,6 +1685,7 @@ const Parser = struct { |
| 1650 | .lhs = try p.addExtra(Node.PtrType{ | 1685 | .lhs = try p.addExtra(Node.PtrType{ |
| 1651 | .sentinel = sentinel, | 1686 | .sentinel = sentinel, |
| 1652 | .align_node = mods.align_node, | 1687 | .align_node = mods.align_node, |
| 1688 | .addrspace_node = mods.addrspace_node, | ||
| 1653 | }), | 1689 | }), |
| 1654 | .rhs = elem_type, | 1690 | .rhs = elem_type, |
| 1655 | }, | 1691 | }, |
| ... | @@ -1661,6 +1697,7 @@ const Parser = struct { | ... | @@ -1661,6 +1697,7 @@ const Parser = struct { |
| 1661 | .keyword_const, | 1697 | .keyword_const, |
| 1662 | .keyword_volatile, | 1698 | .keyword_volatile, |
| 1663 | .keyword_allowzero, | 1699 | .keyword_allowzero, |
| 1700 | .keyword_addrspace, | ||
| 1664 | => return p.fail(.ptr_mod_on_array_child_type), | 1701 | => return p.fail(.ptr_mod_on_array_child_type), |
| 1665 | else => {}, | 1702 | else => {}, |
| 1666 | } | 1703 | } |
| ... | @@ -2879,6 +2916,15 @@ const Parser = struct { | ... | @@ -2879,6 +2916,15 @@ const Parser = struct { |
| 2879 | return expr_node; | 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 | /// ParamDecl | 2928 | /// ParamDecl |
| 2883 | /// <- (KEYWORD_noalias / KEYWORD_comptime)? (IDENTIFIER COLON)? ParamType | 2929 | /// <- (KEYWORD_noalias / KEYWORD_comptime)? (IDENTIFIER COLON)? ParamType |
| 2884 | /// / DOT3 | 2930 | /// / DOT3 |
| ... | @@ -3011,6 +3057,7 @@ const Parser = struct { | ... | @@ -3011,6 +3057,7 @@ const Parser = struct { |
| 3011 | 3057 | ||
| 3012 | const PtrModifiers = struct { | 3058 | const PtrModifiers = struct { |
| 3013 | align_node: Node.Index, | 3059 | align_node: Node.Index, |
| 3060 | addrspace_node: Node.Index, | ||
| 3014 | bit_range_start: Node.Index, | 3061 | bit_range_start: Node.Index, |
| 3015 | bit_range_end: Node.Index, | 3062 | bit_range_end: Node.Index, |
| 3016 | }; | 3063 | }; |
| ... | @@ -3018,12 +3065,14 @@ const Parser = struct { | ... | @@ -3018,12 +3065,14 @@ const Parser = struct { |
| 3018 | fn parsePtrModifiers(p: *Parser) !PtrModifiers { | 3065 | fn parsePtrModifiers(p: *Parser) !PtrModifiers { |
| 3019 | var result: PtrModifiers = .{ | 3066 | var result: PtrModifiers = .{ |
| 3020 | .align_node = 0, | 3067 | .align_node = 0, |
| 3068 | .addrspace_node = 0, | ||
| 3021 | .bit_range_start = 0, | 3069 | .bit_range_start = 0, |
| 3022 | .bit_range_end = 0, | 3070 | .bit_range_end = 0, |
| 3023 | }; | 3071 | }; |
| 3024 | var saw_const = false; | 3072 | var saw_const = false; |
| 3025 | var saw_volatile = false; | 3073 | var saw_volatile = false; |
| 3026 | var saw_allowzero = false; | 3074 | var saw_allowzero = false; |
| 3075 | var saw_addrspace = false; | ||
| 3027 | while (true) { | 3076 | while (true) { |
| 3028 | switch (p.token_tags[p.tok_i]) { | 3077 | switch (p.token_tags[p.tok_i]) { |
| 3029 | .keyword_align => { | 3078 | .keyword_align => { |
| ... | @@ -3063,6 +3112,12 @@ const Parser = struct { | ... | @@ -3063,6 +3112,12 @@ const Parser = struct { |
| 3063 | p.tok_i += 1; | 3112 | p.tok_i += 1; |
| 3064 | saw_allowzero = true; | 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 | else => return result, | 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,6 +404,10 @@ test "zig fmt: trailing comma in fn parameter list" { |
| 404 | \\pub fn f( | 404 | \\pub fn f( |
| 405 | \\ a: i32, | 405 | \\ a: i32, |
| 406 | \\ b: i32, | 406 | \\ b: i32, |
| 407 | \\) addrspace(.generic) i32 {} | ||
| 408 | \\pub fn f( | ||
| 409 | \\ a: i32, | ||
| 410 | \\ b: i32, | ||
| 407 | \\) linksection(".text") i32 {} | 411 | \\) linksection(".text") i32 {} |
| 408 | \\pub fn f( | 412 | \\pub fn f( |
| 409 | \\ a: i32, | 413 | \\ a: i32, |
| ... | @@ -553,8 +557,8 @@ test "zig fmt: sentinel-terminated slice type" { | ... | @@ -553,8 +557,8 @@ test "zig fmt: sentinel-terminated slice type" { |
| 553 | test "zig fmt: pointer-to-one with modifiers" { | 557 | test "zig fmt: pointer-to-one with modifiers" { |
| 554 | try testCanonical( | 558 | try testCanonical( |
| 555 | \\const x: *u32 = undefined; | 559 | \\const x: *u32 = undefined; |
| 556 | \\const y: *allowzero align(8) const volatile u32 = undefined; | 560 | \\const y: *allowzero align(8) addrspace(.generic) const volatile u32 = undefined; |
| 557 | \\const z: *allowzero align(8:4:2) 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,8 +566,8 @@ test "zig fmt: pointer-to-one with modifiers" { |
| 562 | test "zig fmt: pointer-to-many with modifiers" { | 566 | test "zig fmt: pointer-to-many with modifiers" { |
| 563 | try testCanonical( | 567 | try testCanonical( |
| 564 | \\const x: [*]u32 = undefined; | 568 | \\const x: [*]u32 = undefined; |
| 565 | \\const y: [*]allowzero align(8) const volatile u32 = undefined; | 569 | \\const y: [*]allowzero align(8) addrspace(.generic) const volatile u32 = undefined; |
| 566 | \\const z: [*]allowzero align(8:4:2) 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,8 +575,8 @@ test "zig fmt: pointer-to-many with modifiers" { |
| 571 | test "zig fmt: sentinel pointer with modifiers" { | 575 | test "zig fmt: sentinel pointer with modifiers" { |
| 572 | try testCanonical( | 576 | try testCanonical( |
| 573 | \\const x: [*:42]u32 = undefined; | 577 | \\const x: [*:42]u32 = undefined; |
| 574 | \\const y: [*:42]allowzero align(8) const volatile u32 = undefined; | 578 | \\const y: [*:42]allowzero align(8) addrspace(.generic) const volatile u32 = undefined; |
| 575 | \\const y: [*:42]allowzero align(8:4:2) 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,8 +584,8 @@ test "zig fmt: sentinel pointer with modifiers" { |
| 580 | test "zig fmt: c pointer with modifiers" { | 584 | test "zig fmt: c pointer with modifiers" { |
| 581 | try testCanonical( | 585 | try testCanonical( |
| 582 | \\const x: [*c]u32 = undefined; | 586 | \\const x: [*c]u32 = undefined; |
| 583 | \\const y: [*c]allowzero align(8) const volatile u32 = undefined; | 587 | \\const y: [*c]allowzero align(8) addrspace(.generic) const volatile u32 = undefined; |
| 584 | \\const z: [*c]allowzero align(8:4:2) 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,7 +593,7 @@ test "zig fmt: c pointer with modifiers" { |
| 589 | test "zig fmt: slice with modifiers" { | 593 | test "zig fmt: slice with modifiers" { |
| 590 | try testCanonical( | 594 | try testCanonical( |
| 591 | \\const x: []u32 = undefined; | 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,7 +601,7 @@ test "zig fmt: slice with modifiers" { |
| 597 | test "zig fmt: sentinel slice with modifiers" { | 601 | test "zig fmt: sentinel slice with modifiers" { |
| 598 | try testCanonical( | 602 | try testCanonical( |
| 599 | \\const x: [:42]u32 = undefined; | 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,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 | test "zig fmt: correctly space struct fields with doc comments" { | 1146 | test "zig fmt: correctly space struct fields with doc comments" { |
| 1133 | try testTransform( | 1147 | try testTransform( |
| 1134 | \\pub const S = struct { | 1148 | \\pub const S = struct { |
lib/std/zig/render.zig+46-2| ... | @@ -797,6 +797,14 @@ fn renderPtrType( | ... | @@ -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 | if (ptr_type.const_token) |const_token| { | 808 | if (ptr_type.const_token) |const_token| { |
| 801 | try renderToken(ais, tree, const_token, .space); | 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,6 +929,7 @@ fn renderVarDecl(gpa: *Allocator, ais: *Ais, tree: Ast, var_decl: Ast.full.VarDe |
| 921 | 929 | ||
| 922 | const name_space = if (var_decl.ast.type_node == 0 and | 930 | const name_space = if (var_decl.ast.type_node == 0 and |
| 923 | (var_decl.ast.align_node != 0 or | 931 | (var_decl.ast.align_node != 0 or |
| 932 | var_decl.ast.addrspace_node != 0 or | ||
| 924 | var_decl.ast.section_node != 0 or | 933 | var_decl.ast.section_node != 0 or |
| 925 | var_decl.ast.init_node != 0)) | 934 | var_decl.ast.init_node != 0)) |
| 926 | Space.space | 935 | Space.space |
| ... | @@ -930,8 +939,8 @@ fn renderVarDecl(gpa: *Allocator, ais: *Ais, tree: Ast, var_decl: Ast.full.VarDe | ... | @@ -930,8 +939,8 @@ fn renderVarDecl(gpa: *Allocator, ais: *Ais, tree: Ast, var_decl: Ast.full.VarDe |
| 930 | 939 | ||
| 931 | if (var_decl.ast.type_node != 0) { | 940 | if (var_decl.ast.type_node != 0) { |
| 932 | try renderToken(ais, tree, var_decl.ast.mut_token + 2, Space.space); // : | 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 | 942 | if (var_decl.ast.align_node != 0 or var_decl.ast.addrspace_node != 0 or |
| 934 | var_decl.ast.init_node != 0) | 943 | var_decl.ast.section_node != 0 or var_decl.ast.init_node != 0) |
| 935 | { | 944 | { |
| 936 | try renderExpression(gpa, ais, tree, var_decl.ast.type_node, .space); | 945 | try renderExpression(gpa, ais, tree, var_decl.ast.type_node, .space); |
| 937 | } else { | 946 | } else { |
| ... | @@ -948,6 +957,23 @@ fn renderVarDecl(gpa: *Allocator, ais: *Ais, tree: Ast, var_decl: Ast.full.VarDe | ... | @@ -948,6 +957,23 @@ fn renderVarDecl(gpa: *Allocator, ais: *Ais, tree: Ast, var_decl: Ast.full.VarDe |
| 948 | try renderToken(ais, tree, align_kw, Space.none); // align | 957 | try renderToken(ais, tree, align_kw, Space.none); // align |
| 949 | try renderToken(ais, tree, lparen, Space.none); // ( | 958 | try renderToken(ais, tree, lparen, Space.none); // ( |
| 950 | try renderExpression(gpa, ais, tree, var_decl.ast.align_node, Space.none); | 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 | if (var_decl.ast.section_node != 0 or var_decl.ast.init_node != 0) { | 977 | if (var_decl.ast.section_node != 0 or var_decl.ast.init_node != 0) { |
| 952 | try renderToken(ais, tree, rparen, .space); // ) | 978 | try renderToken(ais, tree, rparen, .space); // ) |
| 953 | } else { | 979 | } else { |
| ... | @@ -1267,6 +1293,14 @@ fn renderFnProto(gpa: *Allocator, ais: *Ais, tree: Ast, fn_proto: Ast.full.FnPro | ... | @@ -1267,6 +1293,14 @@ fn renderFnProto(gpa: *Allocator, ais: *Ais, tree: Ast, fn_proto: Ast.full.FnPro |
| 1267 | smallest_start = start; | 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 | if (fn_proto.ast.section_expr != 0) { | 1304 | if (fn_proto.ast.section_expr != 0) { |
| 1271 | const tok = tree.firstToken(fn_proto.ast.section_expr) - 3; | 1305 | const tok = tree.firstToken(fn_proto.ast.section_expr) - 3; |
| 1272 | const start = token_starts[tok]; | 1306 | const start = token_starts[tok]; |
| ... | @@ -1407,6 +1441,16 @@ fn renderFnProto(gpa: *Allocator, ais: *Ais, tree: Ast, fn_proto: Ast.full.FnPro | ... | @@ -1407,6 +1441,16 @@ fn renderFnProto(gpa: *Allocator, ais: *Ais, tree: Ast, fn_proto: Ast.full.FnPro |
| 1407 | try renderToken(ais, tree, align_rparen, .space); // ) | 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 | if (fn_proto.ast.section_expr != 0) { | 1454 | if (fn_proto.ast.section_expr != 0) { |
| 1411 | const section_lparen = tree.firstToken(fn_proto.ast.section_expr) - 1; | 1455 | const section_lparen = tree.firstToken(fn_proto.ast.section_expr) - 1; |
| 1412 | const section_rparen = tree.lastToken(fn_proto.ast.section_expr) + 1; | 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,6 +11,7 @@ pub const Token = struct { |
| 11 | }; | 11 | }; |
| 12 | 12 | ||
| 13 | pub const keywords = std.ComptimeStringMap(Tag, .{ | 13 | pub const keywords = std.ComptimeStringMap(Tag, .{ |
| 14 | .{ "addrspace", .keyword_addrspace }, | ||
| 14 | .{ "align", .keyword_align }, | 15 | .{ "align", .keyword_align }, |
| 15 | .{ "allowzero", .keyword_allowzero }, | 16 | .{ "allowzero", .keyword_allowzero }, |
| 16 | .{ "and", .keyword_and }, | 17 | .{ "and", .keyword_and }, |
| ... | @@ -132,6 +133,7 @@ pub const Token = struct { | ... | @@ -132,6 +133,7 @@ pub const Token = struct { |
| 132 | float_literal, | 133 | float_literal, |
| 133 | doc_comment, | 134 | doc_comment, |
| 134 | container_doc_comment, | 135 | container_doc_comment, |
| 136 | keyword_addrspace, | ||
| 135 | keyword_align, | 137 | keyword_align, |
| 136 | keyword_allowzero, | 138 | keyword_allowzero, |
| 137 | keyword_and, | 139 | keyword_and, |
| ... | @@ -251,6 +253,7 @@ pub const Token = struct { | ... | @@ -251,6 +253,7 @@ pub const Token = struct { |
| 251 | .angle_bracket_angle_bracket_right => ">>", | 253 | .angle_bracket_angle_bracket_right => ">>", |
| 252 | .angle_bracket_angle_bracket_right_equal => ">>=", | 254 | .angle_bracket_angle_bracket_right_equal => ">>=", |
| 253 | .tilde => "~", | 255 | .tilde => "~", |
| 256 | .keyword_addrspace => "addrspace", | ||
| 254 | .keyword_align => "align", | 257 | .keyword_align => "align", |
| 255 | .keyword_allowzero => "allowzero", | 258 | .keyword_allowzero => "allowzero", |
| 256 | .keyword_and => "and", | 259 | .keyword_and => "and", |
src/AstGen.zig+43-8| ... | @@ -1116,6 +1116,11 @@ fn fnProtoExpr( | ... | @@ -1116,6 +1116,11 @@ fn fnProtoExpr( |
| 1116 | const align_inst: Zir.Inst.Ref = if (fn_proto.ast.align_expr == 0) .none else inst: { | 1116 | const align_inst: Zir.Inst.Ref = if (fn_proto.ast.align_expr == 0) .none else inst: { |
| 1117 | break :inst try expr(gz, scope, align_rl, fn_proto.ast.align_expr); | 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 | if (fn_proto.ast.section_expr != 0) { | 1124 | if (fn_proto.ast.section_expr != 0) { |
| 1120 | return astgen.failNode(fn_proto.ast.section_expr, "linksection not allowed on function prototypes", .{}); | 1125 | return astgen.failNode(fn_proto.ast.section_expr, "linksection not allowed on function prototypes", .{}); |
| 1121 | } | 1126 | } |
| ... | @@ -2371,6 +2376,7 @@ fn varDecl( | ... | @@ -2371,6 +2376,7 @@ fn varDecl( |
| 2371 | const gpa = astgen.gpa; | 2376 | const gpa = astgen.gpa; |
| 2372 | const tree = astgen.tree; | 2377 | const tree = astgen.tree; |
| 2373 | const token_tags = tree.tokens.items(.tag); | 2378 | const token_tags = tree.tokens.items(.tag); |
| 2379 | const main_tokens = tree.nodes.items(.main_token); | ||
| 2374 | 2380 | ||
| 2375 | const name_token = var_decl.ast.mut_token + 1; | 2381 | const name_token = var_decl.ast.mut_token + 1; |
| 2376 | const ident_name_raw = tree.tokenSlice(name_token); | 2382 | const ident_name_raw = tree.tokenSlice(name_token); |
| ... | @@ -2385,6 +2391,14 @@ fn varDecl( | ... | @@ -2385,6 +2391,14 @@ fn varDecl( |
| 2385 | return astgen.failNode(node, "variables must be initialized", .{}); | 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 | const align_inst: Zir.Inst.Ref = if (var_decl.ast.align_node != 0) | 2402 | const align_inst: Zir.Inst.Ref = if (var_decl.ast.align_node != 0) |
| 2389 | try expr(gz, scope, align_rl, var_decl.ast.align_node) | 2403 | try expr(gz, scope, align_rl, var_decl.ast.align_node) |
| 2390 | else | 2404 | else |
| ... | @@ -2714,6 +2728,7 @@ fn ptrType( | ... | @@ -2714,6 +2728,7 @@ fn ptrType( |
| 2714 | const elem_type = try typeExpr(gz, scope, ptr_info.ast.child_type); | 2728 | const elem_type = try typeExpr(gz, scope, ptr_info.ast.child_type); |
| 2715 | 2729 | ||
| 2716 | const simple = ptr_info.ast.align_node == 0 and | 2730 | const simple = ptr_info.ast.align_node == 0 and |
| 2731 | ptr_info.ast.addrspace_node == 0 and | ||
| 2717 | ptr_info.ast.sentinel == 0 and | 2732 | ptr_info.ast.sentinel == 0 and |
| 2718 | ptr_info.ast.bit_range_start == 0; | 2733 | ptr_info.ast.bit_range_start == 0; |
| 2719 | 2734 | ||
| ... | @@ -2732,6 +2747,7 @@ fn ptrType( | ... | @@ -2732,6 +2747,7 @@ fn ptrType( |
| 2732 | 2747 | ||
| 2733 | var sentinel_ref: Zir.Inst.Ref = .none; | 2748 | var sentinel_ref: Zir.Inst.Ref = .none; |
| 2734 | var align_ref: Zir.Inst.Ref = .none; | 2749 | var align_ref: Zir.Inst.Ref = .none; |
| 2750 | var addrspace_ref: Zir.Inst.Ref = .none; | ||
| 2735 | var bit_start_ref: Zir.Inst.Ref = .none; | 2751 | var bit_start_ref: Zir.Inst.Ref = .none; |
| 2736 | var bit_end_ref: Zir.Inst.Ref = .none; | 2752 | var bit_end_ref: Zir.Inst.Ref = .none; |
| 2737 | var trailing_count: u32 = 0; | 2753 | var trailing_count: u32 = 0; |
| ... | @@ -2744,6 +2760,10 @@ fn ptrType( | ... | @@ -2744,6 +2760,10 @@ fn ptrType( |
| 2744 | align_ref = try expr(gz, scope, align_rl, ptr_info.ast.align_node); | 2760 | align_ref = try expr(gz, scope, align_rl, ptr_info.ast.align_node); |
| 2745 | trailing_count += 1; | 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 | if (ptr_info.ast.bit_range_start != 0) { | 2767 | if (ptr_info.ast.bit_range_start != 0) { |
| 2748 | assert(ptr_info.ast.bit_range_end != 0); | 2768 | assert(ptr_info.ast.bit_range_end != 0); |
| 2749 | bit_start_ref = try expr(gz, scope, .none, ptr_info.ast.bit_range_start); | 2769 | bit_start_ref = try expr(gz, scope, .none, ptr_info.ast.bit_range_start); |
| ... | @@ -2764,6 +2784,9 @@ fn ptrType( | ... | @@ -2764,6 +2784,9 @@ fn ptrType( |
| 2764 | if (align_ref != .none) { | 2784 | if (align_ref != .none) { |
| 2765 | gz.astgen.extra.appendAssumeCapacity(@enumToInt(align_ref)); | 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 | if (bit_start_ref != .none) { | 2790 | if (bit_start_ref != .none) { |
| 2768 | gz.astgen.extra.appendAssumeCapacity(@enumToInt(bit_start_ref)); | 2791 | gz.astgen.extra.appendAssumeCapacity(@enumToInt(bit_start_ref)); |
| 2769 | gz.astgen.extra.appendAssumeCapacity(@enumToInt(bit_end_ref)); | 2792 | gz.astgen.extra.appendAssumeCapacity(@enumToInt(bit_end_ref)); |
| ... | @@ -2779,6 +2802,7 @@ fn ptrType( | ... | @@ -2779,6 +2802,7 @@ fn ptrType( |
| 2779 | .is_volatile = ptr_info.volatile_token != null, | 2802 | .is_volatile = ptr_info.volatile_token != null, |
| 2780 | .has_sentinel = sentinel_ref != .none, | 2803 | .has_sentinel = sentinel_ref != .none, |
| 2781 | .has_align = align_ref != .none, | 2804 | .has_align = align_ref != .none, |
| 2805 | .has_addrspace = addrspace_ref != .none, | ||
| 2782 | .has_bit_range = bit_start_ref != .none, | 2806 | .has_bit_range = bit_start_ref != .none, |
| 2783 | }, | 2807 | }, |
| 2784 | .size = ptr_info.size, | 2808 | .size = ptr_info.size, |
| ... | @@ -2847,7 +2871,7 @@ const WipDecls = struct { | ... | @@ -2847,7 +2871,7 @@ const WipDecls = struct { |
| 2847 | is_pub: bool, | 2871 | is_pub: bool, |
| 2848 | is_export: bool, | 2872 | is_export: bool, |
| 2849 | has_align: bool, | 2873 | has_align: bool, |
| 2850 | has_section: bool, | 2874 | has_section_or_addrspace: bool, |
| 2851 | ) Allocator.Error!void { | 2875 | ) Allocator.Error!void { |
| 2852 | if (wip_decls.decl_index % fields_per_u32 == 0 and wip_decls.decl_index != 0) { | 2876 | if (wip_decls.decl_index % fields_per_u32 == 0 and wip_decls.decl_index != 0) { |
| 2853 | try wip_decls.bit_bag.append(gpa, wip_decls.cur_bit_bag); | 2877 | try wip_decls.bit_bag.append(gpa, wip_decls.cur_bit_bag); |
| ... | @@ -2857,7 +2881,7 @@ const WipDecls = struct { | ... | @@ -2857,7 +2881,7 @@ const WipDecls = struct { |
| 2857 | (@as(u32, @boolToInt(is_pub)) << 28) | | 2881 | (@as(u32, @boolToInt(is_pub)) << 28) | |
| 2858 | (@as(u32, @boolToInt(is_export)) << 29) | | 2882 | (@as(u32, @boolToInt(is_export)) << 29) | |
| 2859 | (@as(u32, @boolToInt(has_align)) << 30) | | 2883 | (@as(u32, @boolToInt(has_align)) << 30) | |
| 2860 | (@as(u32, @boolToInt(has_section)) << 31); | 2884 | (@as(u32, @boolToInt(has_section_or_addrspace)) << 31); |
| 2861 | wip_decls.decl_index += 1; | 2885 | wip_decls.decl_index += 1; |
| 2862 | } | 2886 | } |
| 2863 | 2887 | ||
| ... | @@ -2922,7 +2946,8 @@ fn fnDecl( | ... | @@ -2922,7 +2946,8 @@ fn fnDecl( |
| 2922 | const maybe_inline_token = fn_proto.extern_export_inline_token orelse break :blk false; | 2946 | const maybe_inline_token = fn_proto.extern_export_inline_token orelse break :blk false; |
| 2923 | break :blk token_tags[maybe_inline_token] == .keyword_inline; | 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 | var params_scope = &fn_gz.base; | 2952 | var params_scope = &fn_gz.base; |
| 2928 | const is_var_args = is_var_args: { | 2953 | const is_var_args = is_var_args: { |
| ... | @@ -3011,6 +3036,9 @@ fn fnDecl( | ... | @@ -3011,6 +3036,9 @@ fn fnDecl( |
| 3011 | const align_inst: Zir.Inst.Ref = if (fn_proto.ast.align_expr == 0) .none else inst: { | 3036 | const align_inst: Zir.Inst.Ref = if (fn_proto.ast.align_expr == 0) .none else inst: { |
| 3012 | break :inst try expr(&decl_gz, params_scope, align_rl, fn_proto.ast.align_expr); | 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 | const section_inst: Zir.Inst.Ref = if (fn_proto.ast.section_expr == 0) .none else inst: { | 3042 | const section_inst: Zir.Inst.Ref = if (fn_proto.ast.section_expr == 0) .none else inst: { |
| 3015 | break :inst try comptimeExpr(&decl_gz, params_scope, .{ .ty = .const_slice_u8_type }, fn_proto.ast.section_expr); | 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,7 +3140,7 @@ fn fnDecl( |
| 3112 | _ = try decl_gz.addBreak(.break_inline, block_inst, func_inst); | 3140 | _ = try decl_gz.addBreak(.break_inline, block_inst, func_inst); |
| 3113 | try decl_gz.setBlockBody(block_inst); | 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 | const contents_hash = std.zig.hashSrc(tree.getNodeSource(decl_node)); | 3145 | const contents_hash = std.zig.hashSrc(tree.getNodeSource(decl_node)); |
| 3118 | const casted = @bitCast([4]u32, contents_hash); | 3146 | const casted = @bitCast([4]u32, contents_hash); |
| ... | @@ -3127,8 +3155,10 @@ fn fnDecl( | ... | @@ -3127,8 +3155,10 @@ fn fnDecl( |
| 3127 | if (align_inst != .none) { | 3155 | if (align_inst != .none) { |
| 3128 | wip_decls.payload.appendAssumeCapacity(@enumToInt(align_inst)); | 3156 | wip_decls.payload.appendAssumeCapacity(@enumToInt(align_inst)); |
| 3129 | } | 3157 | } |
| 3130 | if (section_inst != .none) { | 3158 | |
| 3159 | if (has_section_or_addrspace) { | ||
| 3131 | wip_decls.payload.appendAssumeCapacity(@enumToInt(section_inst)); | 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,10 +3205,14 @@ fn globalVarDecl( |
| 3175 | const align_inst: Zir.Inst.Ref = if (var_decl.ast.align_node == 0) .none else inst: { | 3205 | const align_inst: Zir.Inst.Ref = if (var_decl.ast.align_node == 0) .none else inst: { |
| 3176 | break :inst try expr(&block_scope, &block_scope.base, align_rl, var_decl.ast.align_node); | 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 | const section_inst: Zir.Inst.Ref = if (var_decl.ast.section_node == 0) .none else inst: { | 3211 | const section_inst: Zir.Inst.Ref = if (var_decl.ast.section_node == 0) .none else inst: { |
| 3179 | break :inst try comptimeExpr(&block_scope, &block_scope.base, .{ .ty = .const_slice_u8_type }, var_decl.ast.section_node); | 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 | const is_threadlocal = if (var_decl.threadlocal_token) |tok| blk: { | 3217 | const is_threadlocal = if (var_decl.threadlocal_token) |tok| blk: { |
| 3184 | if (!is_mutable) { | 3218 | if (!is_mutable) { |
| ... | @@ -3256,7 +3290,7 @@ fn globalVarDecl( | ... | @@ -3256,7 +3290,7 @@ fn globalVarDecl( |
| 3256 | _ = try block_scope.addBreak(.break_inline, block_inst, var_inst); | 3290 | _ = try block_scope.addBreak(.break_inline, block_inst, var_inst); |
| 3257 | try block_scope.setBlockBody(block_inst); | 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 | const contents_hash = std.zig.hashSrc(tree.getNodeSource(node)); | 3295 | const contents_hash = std.zig.hashSrc(tree.getNodeSource(node)); |
| 3262 | const casted = @bitCast([4]u32, contents_hash); | 3296 | const casted = @bitCast([4]u32, contents_hash); |
| ... | @@ -3271,8 +3305,9 @@ fn globalVarDecl( | ... | @@ -3271,8 +3305,9 @@ fn globalVarDecl( |
| 3271 | if (align_inst != .none) { | 3305 | if (align_inst != .none) { |
| 3272 | wip_decls.payload.appendAssumeCapacity(@enumToInt(align_inst)); | 3306 | wip_decls.payload.appendAssumeCapacity(@enumToInt(align_inst)); |
| 3273 | } | 3307 | } |
| 3274 | if (section_inst != .none) { | 3308 | if (has_section_or_addrspace) { |
| 3275 | wip_decls.payload.appendAssumeCapacity(@enumToInt(section_inst)); | 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,6 +288,8 @@ pub const Decl = struct { |
| 288 | align_val: Value, | 288 | align_val: Value, |
| 289 | /// Populated when `has_tv`. | 289 | /// Populated when `has_tv`. |
| 290 | linksection_val: Value, | 290 | linksection_val: Value, |
| 291 | /// Populated when `has_tv`. | ||
| 292 | @"addrspace": std.builtin.AddressSpace, | ||
| 291 | /// The memory for ty, val, align_val, linksection_val. | 293 | /// The memory for ty, val, align_val, linksection_val. |
| 292 | /// If this is `null` then there is no memory management needed. | 294 | /// If this is `null` then there is no memory management needed. |
| 293 | value_arena: ?*std.heap.ArenaAllocator.State = null, | 295 | value_arena: ?*std.heap.ArenaAllocator.State = null, |
| ... | @@ -351,7 +353,7 @@ pub const Decl = struct { | ... | @@ -351,7 +353,7 @@ pub const Decl = struct { |
| 351 | /// to require re-analysis. | 353 | /// to require re-analysis. |
| 352 | outdated, | 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 | has_tv: bool, | 357 | has_tv: bool, |
| 356 | /// If `true` it means the `Decl` is the resource owner of the type/value associated | 358 | /// If `true` it means the `Decl` is the resource owner of the type/value associated |
| 357 | /// with it. That means when `Decl` is destroyed, the cleanup code should additionally | 359 | /// with it. That means when `Decl` is destroyed, the cleanup code should additionally |
| ... | @@ -366,8 +368,8 @@ pub const Decl = struct { | ... | @@ -366,8 +368,8 @@ pub const Decl = struct { |
| 366 | is_exported: bool, | 368 | is_exported: bool, |
| 367 | /// Whether the ZIR code provides an align instruction. | 369 | /// Whether the ZIR code provides an align instruction. |
| 368 | has_align: bool, | 370 | has_align: bool, |
| 369 | /// Whether the ZIR code provides a linksection instruction. | 371 | /// Whether the ZIR code provides a linksection and address space instruction. |
| 370 | has_linksection: bool, | 372 | has_linksection_or_addrspace: bool, |
| 371 | /// Flag used by garbage collection to mark and sweep. | 373 | /// Flag used by garbage collection to mark and sweep. |
| 372 | /// Decls which correspond to an AST node always have this field set to `true`. | 374 | /// Decls which correspond to an AST node always have this field set to `true`. |
| 373 | /// Anonymous Decls are initialized with this field set to `false` and then it | 375 | /// Anonymous Decls are initialized with this field set to `false` and then it |
| ... | @@ -489,14 +491,22 @@ pub const Decl = struct { | ... | @@ -489,14 +491,22 @@ pub const Decl = struct { |
| 489 | if (!decl.has_align) return .none; | 491 | if (!decl.has_align) return .none; |
| 490 | assert(decl.zir_decl_index != 0); | 492 | assert(decl.zir_decl_index != 0); |
| 491 | const zir = decl.namespace.file_scope.zir; | 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 | pub fn zirLinksectionRef(decl: Decl) Zir.Inst.Ref { | 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 | assert(decl.zir_decl_index != 0); | 499 | assert(decl.zir_decl_index != 0); |
| 498 | const zir = decl.namespace.file_scope.zir; | 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 | return @intToEnum(Zir.Inst.Ref, zir.extra[extra_index]); | 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,7 +3082,7 @@ pub fn semaFile(mod: *Module, file: *Scope.File) SemaError!void { |
| 3072 | new_decl.is_pub = true; | 3082 | new_decl.is_pub = true; |
| 3073 | new_decl.is_exported = false; | 3083 | new_decl.is_exported = false; |
| 3074 | new_decl.has_align = false; | 3084 | new_decl.has_align = false; |
| 3075 | new_decl.has_linksection = false; | 3085 | new_decl.has_linksection_or_addrspace = false; |
| 3076 | new_decl.ty = struct_ty; | 3086 | new_decl.ty = struct_ty; |
| 3077 | new_decl.val = struct_val; | 3087 | new_decl.val = struct_val; |
| 3078 | new_decl.has_tv = true; | 3088 | new_decl.has_tv = true; |
| ... | @@ -3202,6 +3212,24 @@ fn semaDecl(mod: *Module, decl: *Decl) !bool { | ... | @@ -3202,6 +3212,24 @@ fn semaDecl(mod: *Module, decl: *Decl) !bool { |
| 3202 | if (linksection_ref == .none) break :blk Value.initTag(.null_value); | 3212 | if (linksection_ref == .none) break :blk Value.initTag(.null_value); |
| 3203 | break :blk (try sema.resolveInstConst(&block_scope, src, linksection_ref)).val; | 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 | // Note this resolves the type of the Decl, not the value; if this Decl | 3233 | // Note this resolves the type of the Decl, not the value; if this Decl |
| 3206 | // is a struct, for example, this resolves `type` (which needs no resolution), | 3234 | // is a struct, for example, this resolves `type` (which needs no resolution), |
| 3207 | // not the struct itself. | 3235 | // not the struct itself. |
| ... | @@ -3258,6 +3286,7 @@ fn semaDecl(mod: *Module, decl: *Decl) !bool { | ... | @@ -3258,6 +3286,7 @@ fn semaDecl(mod: *Module, decl: *Decl) !bool { |
| 3258 | decl.val = try decl_tv.val.copy(&decl_arena.allocator); | 3286 | decl.val = try decl_tv.val.copy(&decl_arena.allocator); |
| 3259 | decl.align_val = try align_val.copy(&decl_arena.allocator); | 3287 | decl.align_val = try align_val.copy(&decl_arena.allocator); |
| 3260 | decl.linksection_val = try linksection_val.copy(&decl_arena.allocator); | 3288 | decl.linksection_val = try linksection_val.copy(&decl_arena.allocator); |
| 3289 | decl.@"addrspace" = address_space; | ||
| 3261 | decl.has_tv = true; | 3290 | decl.has_tv = true; |
| 3262 | decl.owns_tv = owns_tv; | 3291 | decl.owns_tv = owns_tv; |
| 3263 | decl_arena_state.* = decl_arena.state; | 3292 | decl_arena_state.* = decl_arena.state; |
| ... | @@ -3319,6 +3348,7 @@ fn semaDecl(mod: *Module, decl: *Decl) !bool { | ... | @@ -3319,6 +3348,7 @@ fn semaDecl(mod: *Module, decl: *Decl) !bool { |
| 3319 | decl.val = try decl_tv.val.copy(&decl_arena.allocator); | 3348 | decl.val = try decl_tv.val.copy(&decl_arena.allocator); |
| 3320 | decl.align_val = try align_val.copy(&decl_arena.allocator); | 3349 | decl.align_val = try align_val.copy(&decl_arena.allocator); |
| 3321 | decl.linksection_val = try linksection_val.copy(&decl_arena.allocator); | 3350 | decl.linksection_val = try linksection_val.copy(&decl_arena.allocator); |
| 3351 | decl.@"addrspace" = address_space; | ||
| 3322 | decl.has_tv = true; | 3352 | decl.has_tv = true; |
| 3323 | decl_arena_state.* = decl_arena.state; | 3353 | decl_arena_state.* = decl_arena.state; |
| 3324 | decl.value_arena = decl_arena_state; | 3354 | decl.value_arena = decl_arena_state; |
| ... | @@ -3526,8 +3556,8 @@ pub fn scanNamespace( | ... | @@ -3526,8 +3556,8 @@ pub fn scanNamespace( |
| 3526 | 3556 | ||
| 3527 | const decl_sub_index = extra_index; | 3557 | const decl_sub_index = extra_index; |
| 3528 | extra_index += 7; // src_hash(4) + line(1) + name(1) + value(1) | 3558 | extra_index += 7; // src_hash(4) + line(1) + name(1) + value(1) |
| 3529 | extra_index += @truncate(u1, flags >> 2); | 3559 | extra_index += @truncate(u1, flags >> 2); // Align |
| 3530 | extra_index += @truncate(u1, flags >> 3); | 3560 | extra_index += @as(u2, @truncate(u1, flags >> 3)) * 2; // Link section or address space, consists of 2 Refs |
| 3531 | 3561 | ||
| 3532 | try scanDecl(&scan_decl_iter, decl_sub_index, flags); | 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,10 +3583,10 @@ fn scanDecl(iter: *ScanDeclIter, decl_sub_index: usize, flags: u4) SemaError!voi |
| 3553 | const zir = namespace.file_scope.zir; | 3583 | const zir = namespace.file_scope.zir; |
| 3554 | 3584 | ||
| 3555 | // zig fmt: off | 3585 | // zig fmt: off |
| 3556 | const is_pub = (flags & 0b0001) != 0; | 3586 | const is_pub = (flags & 0b0001) != 0; |
| 3557 | const export_bit = (flags & 0b0010) != 0; | 3587 | const export_bit = (flags & 0b0010) != 0; |
| 3558 | const has_align = (flags & 0b0100) != 0; | 3588 | const has_align = (flags & 0b0100) != 0; |
| 3559 | const has_linksection = (flags & 0b1000) != 0; | 3589 | const has_linksection_or_addrspace = (flags & 0b1000) != 0; |
| 3560 | // zig fmt: on | 3590 | // zig fmt: on |
| 3561 | 3591 | ||
| 3562 | const line = iter.parent_decl.relativeToLine(zir.extra[decl_sub_index + 4]); | 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,7 +3669,7 @@ fn scanDecl(iter: *ScanDeclIter, decl_sub_index: usize, flags: u4) SemaError!voi |
| 3639 | new_decl.is_exported = is_exported; | 3669 | new_decl.is_exported = is_exported; |
| 3640 | new_decl.is_usingnamespace = is_usingnamespace; | 3670 | new_decl.is_usingnamespace = is_usingnamespace; |
| 3641 | new_decl.has_align = has_align; | 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 | new_decl.zir_decl_index = @intCast(u32, decl_sub_index); | 3673 | new_decl.zir_decl_index = @intCast(u32, decl_sub_index); |
| 3644 | new_decl.alive = true; // This Decl corresponds to an AST node and therefore always alive. | 3674 | new_decl.alive = true; // This Decl corresponds to an AST node and therefore always alive. |
| 3645 | return; | 3675 | return; |
| ... | @@ -3656,7 +3686,7 @@ fn scanDecl(iter: *ScanDeclIter, decl_sub_index: usize, flags: u4) SemaError!voi | ... | @@ -3656,7 +3686,7 @@ fn scanDecl(iter: *ScanDeclIter, decl_sub_index: usize, flags: u4) SemaError!voi |
| 3656 | decl.is_exported = is_exported; | 3686 | decl.is_exported = is_exported; |
| 3657 | decl.is_usingnamespace = is_usingnamespace; | 3687 | decl.is_usingnamespace = is_usingnamespace; |
| 3658 | decl.has_align = has_align; | 3688 | decl.has_align = has_align; |
| 3659 | decl.has_linksection = has_linksection; | 3689 | decl.has_linksection_or_addrspace = has_linksection_or_addrspace; |
| 3660 | decl.zir_decl_index = @intCast(u32, decl_sub_index); | 3690 | decl.zir_decl_index = @intCast(u32, decl_sub_index); |
| 3661 | if (decl.getFunction()) |_| { | 3691 | if (decl.getFunction()) |_| { |
| 3662 | switch (mod.comp.bin_file.tag) { | 3692 | switch (mod.comp.bin_file.tag) { |
| ... | @@ -4028,6 +4058,7 @@ pub fn allocateNewDecl(mod: *Module, namespace: *Scope.Namespace, src_node: Ast. | ... | @@ -4028,6 +4058,7 @@ pub fn allocateNewDecl(mod: *Module, namespace: *Scope.Namespace, src_node: Ast. |
| 4028 | .val = undefined, | 4058 | .val = undefined, |
| 4029 | .align_val = undefined, | 4059 | .align_val = undefined, |
| 4030 | .linksection_val = undefined, | 4060 | .linksection_val = undefined, |
| 4061 | .@"addrspace" = undefined, | ||
| 4031 | .analysis = .unreferenced, | 4062 | .analysis = .unreferenced, |
| 4032 | .deletion_flag = false, | 4063 | .deletion_flag = false, |
| 4033 | .zir_decl_index = 0, | 4064 | .zir_decl_index = 0, |
| ... | @@ -4052,7 +4083,7 @@ pub fn allocateNewDecl(mod: *Module, namespace: *Scope.Namespace, src_node: Ast. | ... | @@ -4052,7 +4083,7 @@ pub fn allocateNewDecl(mod: *Module, namespace: *Scope.Namespace, src_node: Ast. |
| 4052 | .generation = 0, | 4083 | .generation = 0, |
| 4053 | .is_pub = false, | 4084 | .is_pub = false, |
| 4054 | .is_exported = false, | 4085 | .is_exported = false, |
| 4055 | .has_linksection = false, | 4086 | .has_linksection_or_addrspace = false, |
| 4056 | .has_align = false, | 4087 | .has_align = false, |
| 4057 | .alive = false, | 4088 | .alive = false, |
| 4058 | .is_usingnamespace = false, | 4089 | .is_usingnamespace = false, |
| ... | @@ -4185,6 +4216,9 @@ pub fn createAnonymousDeclFromDeclNamed( | ... | @@ -4185,6 +4216,9 @@ pub fn createAnonymousDeclFromDeclNamed( |
| 4185 | new_decl.src_line = owner_decl.src_line; | 4216 | new_decl.src_line = owner_decl.src_line; |
| 4186 | new_decl.ty = typed_value.ty; | 4217 | new_decl.ty = typed_value.ty; |
| 4187 | new_decl.val = typed_value.val; | 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 | new_decl.has_tv = true; | 4222 | new_decl.has_tv = true; |
| 4189 | new_decl.analysis = .complete; | 4223 | new_decl.analysis = .complete; |
| 4190 | new_decl.generation = mod.generation; | 4224 | new_decl.generation = mod.generation; |
| ... | @@ -4330,10 +4364,59 @@ pub fn simplePtrType( | ... | @@ -4330,10 +4364,59 @@ pub fn simplePtrType( |
| 4330 | elem_ty: Type, | 4364 | elem_ty: Type, |
| 4331 | mutable: bool, | 4365 | mutable: bool, |
| 4332 | size: std.builtin.TypeInfo.Pointer.Size, | 4366 | size: std.builtin.TypeInfo.Pointer.Size, |
| 4367 | @"addrspace": std.builtin.AddressSpace, | ||
| 4333 | ) Allocator.Error!Type { | 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 | if (!mutable and size == .Slice and elem_ty.eql(Type.initTag(.u8))) { | 4416 | if (!mutable and size == .Slice and elem_ty.eql(Type.initTag(.u8))) { |
| 4335 | return Type.initTag(.const_slice_u8); | 4417 | return Type.initTag(.const_slice_u8); |
| 4336 | } | 4418 | } |
| 4419 | |||
| 4337 | // TODO stage1 type inference bug | 4420 | // TODO stage1 type inference bug |
| 4338 | const T = Type.Tag; | 4421 | const T = Type.Tag; |
| 4339 | 4422 | ||
| ... | @@ -4352,34 +4435,6 @@ pub fn simplePtrType( | ... | @@ -4352,34 +4435,6 @@ pub fn simplePtrType( |
| 4352 | return Type.initPayload(&type_payload.base); | 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 | pub fn optionalType(arena: *Allocator, child_type: Type) Allocator.Error!Type { | 4438 | pub fn optionalType(arena: *Allocator, child_type: Type) Allocator.Error!Type { |
| 4384 | switch (child_type.tag()) { | 4439 | switch (child_type.tag()) { |
| 4385 | .single_const_pointer => return Type.Tag.optional_single_const_pointer.create( | 4440 | .single_const_pointer => return Type.Tag.optional_single_const_pointer.create( |
| ... | @@ -4709,7 +4764,7 @@ pub fn populateTestFunctions(mod: *Module) !void { | ... | @@ -4709,7 +4764,7 @@ pub fn populateTestFunctions(mod: *Module) !void { |
| 4709 | const builtin_file = (mod.importPkg(builtin_pkg) catch unreachable).file; | 4764 | const builtin_file = (mod.importPkg(builtin_pkg) catch unreachable).file; |
| 4710 | const builtin_namespace = builtin_file.root_decl.?.namespace; | 4765 | const builtin_namespace = builtin_file.root_decl.?.namespace; |
| 4711 | const decl = builtin_namespace.decls.get("test_functions").?; | 4766 | const decl = builtin_namespace.decls.get("test_functions").?; |
| 4712 | var buf: Type.Payload.ElemType = undefined; | 4767 | var buf: Type.SlicePtrFieldTypeBuffer = undefined; |
| 4713 | const tmp_test_fn_ty = decl.ty.slicePtrFieldType(&buf).elemType(); | 4768 | const tmp_test_fn_ty = decl.ty.slicePtrFieldType(&buf).elemType(); |
| 4714 | 4769 | ||
| 4715 | const array_decl = d: { | 4770 | const array_decl = d: { |
src/Sema.zig+242-61| ... | @@ -1373,7 +1373,13 @@ fn zirRetPtr( | ... | @@ -1373,7 +1373,13 @@ fn zirRetPtr( |
| 1373 | return sema.analyzeComptimeAlloc(block, sema.fn_ret_ty); | 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 | return block.addTy(.alloc, ptr_type); | 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,7 +1527,13 @@ fn zirAlloc(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileError |
| 1521 | const ty_src: LazySrcLoc = .{ .node_offset_var_decl_ty = inst_data.src_node }; | 1527 | const ty_src: LazySrcLoc = .{ .node_offset_var_decl_ty = inst_data.src_node }; |
| 1522 | const var_decl_src = inst_data.src(); | 1528 | const var_decl_src = inst_data.src(); |
| 1523 | const var_type = try sema.resolveType(block, ty_src, inst_data.operand); | 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 | try sema.requireRuntimeBlock(block, var_decl_src); | 1537 | try sema.requireRuntimeBlock(block, var_decl_src); |
| 1526 | return block.addTy(.alloc, ptr_type); | 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,7 +1550,13 @@ fn zirAllocMut(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileEr |
| 1538 | return sema.analyzeComptimeAlloc(block, var_type); | 1550 | return sema.analyzeComptimeAlloc(block, var_type); |
| 1539 | } | 1551 | } |
| 1540 | try sema.validateVarType(block, ty_src, var_type); | 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 | try sema.requireRuntimeBlock(block, var_decl_src); | 1560 | try sema.requireRuntimeBlock(block, var_decl_src); |
| 1543 | return block.addTy(.alloc, ptr_type); | 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,7 +1616,13 @@ fn zirResolveInferredAlloc(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Inde |
| 1598 | try sema.mod.declareDeclDependency(sema.owner_decl, decl); | 1616 | try sema.mod.declareDeclDependency(sema.owner_decl, decl); |
| 1599 | 1617 | ||
| 1600 | const final_elem_ty = try decl.ty.copy(sema.arena); | 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 | const final_ptr_ty_inst = try sema.addType(final_ptr_ty); | 1626 | const final_ptr_ty_inst = try sema.addType(final_ptr_ty); |
| 1603 | sema.air_instructions.items(.data)[ptr_inst].ty_pl.ty = final_ptr_ty_inst; | 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,7 +1644,13 @@ fn zirResolveInferredAlloc(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Inde |
| 1620 | try sema.validateVarType(block, ty_src, final_elem_ty); | 1644 | try sema.validateVarType(block, ty_src, final_elem_ty); |
| 1621 | } | 1645 | } |
| 1622 | // Change it to a normal alloc. | 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 | sema.air_instructions.set(ptr_inst, .{ | 1654 | sema.air_instructions.set(ptr_inst, .{ |
| 1625 | .tag = .alloc, | 1655 | .tag = .alloc, |
| 1626 | .data = .{ .ty = final_ptr_ty }, | 1656 | .data = .{ .ty = final_ptr_ty }, |
| ... | @@ -1774,7 +1804,14 @@ fn zirStoreToBlockPtr(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) Co | ... | @@ -1774,7 +1804,14 @@ fn zirStoreToBlockPtr(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) Co |
| 1774 | } | 1804 | } |
| 1775 | const ptr = sema.resolveInst(bin_inst.lhs); | 1805 | const ptr = sema.resolveInst(bin_inst.lhs); |
| 1776 | const value = sema.resolveInst(bin_inst.rhs); | 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 | // TODO detect when this store should be done at compile-time. For example, | 1815 | // TODO detect when this store should be done at compile-time. For example, |
| 1779 | // if expressions should force it when the condition is compile-time known. | 1816 | // if expressions should force it when the condition is compile-time known. |
| 1780 | const src: LazySrcLoc = .unneeded; | 1817 | const src: LazySrcLoc = .unneeded; |
| ... | @@ -1821,7 +1858,14 @@ fn zirStoreToInferredPtr(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) | ... | @@ -1821,7 +1858,14 @@ fn zirStoreToInferredPtr(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) |
| 1821 | // for the inferred allocation. | 1858 | // for the inferred allocation. |
| 1822 | try inferred_alloc.data.stored_inst_list.append(sema.arena, operand); | 1859 | try inferred_alloc.data.stored_inst_list.append(sema.arena, operand); |
| 1823 | // Create a runtime bitcast instruction with exactly the type the pointer wants. | 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 | const bitcasted_ptr = try block.addTyOp(.bitcast, ptr_ty, ptr); | 1869 | const bitcasted_ptr = try block.addTyOp(.bitcast, ptr_ty, ptr); |
| 1826 | return sema.storePtr(block, src, bitcasted_ptr, operand); | 1870 | return sema.storePtr(block, src, bitcasted_ptr, operand); |
| 1827 | } | 1871 | } |
| ... | @@ -3004,7 +3048,7 @@ fn analyzeCall( | ... | @@ -3004,7 +3048,7 @@ fn analyzeCall( |
| 3004 | new_decl.is_pub = module_fn.owner_decl.is_pub; | 3048 | new_decl.is_pub = module_fn.owner_decl.is_pub; |
| 3005 | new_decl.is_exported = module_fn.owner_decl.is_exported; | 3049 | new_decl.is_exported = module_fn.owner_decl.is_exported; |
| 3006 | new_decl.has_align = module_fn.owner_decl.has_align; | 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 | new_decl.zir_decl_index = module_fn.owner_decl.zir_decl_index; | 3052 | new_decl.zir_decl_index = module_fn.owner_decl.zir_decl_index; |
| 3009 | new_decl.alive = true; // This Decl is called at runtime. | 3053 | new_decl.alive = true; // This Decl is called at runtime. |
| 3010 | new_decl.has_tv = true; | 3054 | new_decl.has_tv = true; |
| ... | @@ -3658,7 +3702,13 @@ fn zirOptionalPayloadPtr( | ... | @@ -3658,7 +3702,13 @@ fn zirOptionalPayloadPtr( |
| 3658 | } | 3702 | } |
| 3659 | 3703 | ||
| 3660 | const child_type = try opt_type.optionalChildAlloc(sema.arena); | 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 | if (try sema.resolveDefinedValue(block, src, optional_ptr)) |pointer_val| { | 3713 | if (try sema.resolveDefinedValue(block, src, optional_ptr)) |pointer_val| { |
| 3664 | if (try pointer_val.pointerDeref(sema.arena)) |val| { | 3714 | if (try pointer_val.pointerDeref(sema.arena)) |val| { |
| ... | @@ -3773,7 +3823,13 @@ fn zirErrUnionPayloadPtr( | ... | @@ -3773,7 +3823,13 @@ fn zirErrUnionPayloadPtr( |
| 3773 | return sema.mod.fail(&block.base, src, "expected error union type, found {}", .{operand_ty.elemType()}); | 3823 | return sema.mod.fail(&block.base, src, "expected error union type, found {}", .{operand_ty.elemType()}); |
| 3774 | 3824 | ||
| 3775 | const payload_ty = operand_ty.elemType().errorUnionPayload(); | 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 | if (try sema.resolveDefinedValue(block, src, operand)) |pointer_val| { | 3834 | if (try sema.resolveDefinedValue(block, src, operand)) |pointer_val| { |
| 3779 | if (try pointer_val.pointerDeref(sema.arena)) |val| { | 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,6 +6935,7 @@ fn zirPtrTypeSimple(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) Comp |
| 6879 | elem_type, | 6935 | elem_type, |
| 6880 | null, | 6936 | null, |
| 6881 | 0, | 6937 | 0, |
| 6938 | .generic, | ||
| 6882 | 0, | 6939 | 0, |
| 6883 | 0, | 6940 | 0, |
| 6884 | inst_data.is_mutable, | 6941 | inst_data.is_mutable, |
| ... | @@ -6911,6 +6968,12 @@ fn zirPtrType(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileErr | ... | @@ -6911,6 +6968,12 @@ fn zirPtrType(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileErr |
| 6911 | break :blk try sema.resolveAlreadyCoercedInt(block, .unneeded, ref, u32); | 6968 | break :blk try sema.resolveAlreadyCoercedInt(block, .unneeded, ref, u32); |
| 6912 | } else 0; | 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 | const bit_start = if (inst_data.flags.has_bit_range) blk: { | 6977 | const bit_start = if (inst_data.flags.has_bit_range) blk: { |
| 6915 | const ref = @intToEnum(Zir.Inst.Ref, sema.code.extra[extra_i]); | 6978 | const ref = @intToEnum(Zir.Inst.Ref, sema.code.extra[extra_i]); |
| 6916 | extra_i += 1; | 6979 | extra_i += 1; |
| ... | @@ -6933,6 +6996,7 @@ fn zirPtrType(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileErr | ... | @@ -6933,6 +6996,7 @@ fn zirPtrType(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileErr |
| 6933 | elem_type, | 6996 | elem_type, |
| 6934 | sentinel, | 6997 | sentinel, |
| 6935 | abi_align, | 6998 | abi_align, |
| 6999 | address_space, | ||
| 6936 | bit_start, | 7000 | bit_start, |
| 6937 | bit_end, | 7001 | bit_end, |
| 6938 | inst_data.flags.is_mutable, | 7002 | inst_data.flags.is_mutable, |
| ... | @@ -8339,7 +8403,13 @@ fn panicWithMsg( | ... | @@ -8339,7 +8403,13 @@ fn panicWithMsg( |
| 8339 | const panic_fn = try sema.getBuiltin(block, src, "panic"); | 8403 | const panic_fn = try sema.getBuiltin(block, src, "panic"); |
| 8340 | const unresolved_stack_trace_ty = try sema.getBuiltinType(block, src, "StackTrace"); | 8404 | const unresolved_stack_trace_ty = try sema.getBuiltinType(block, src, "StackTrace"); |
| 8341 | const stack_trace_ty = try sema.resolveTypeFields(block, src, unresolved_stack_trace_ty); | 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 | const null_stack_trace = try sema.addConstant( | 8413 | const null_stack_trace = try sema.addConstant( |
| 8344 | try Module.optionalType(arena, ptr_stack_trace_ty), | 8414 | try Module.optionalType(arena, ptr_stack_trace_ty), |
| 8345 | Value.initTag(.null_value), | 8415 | Value.initTag(.null_value), |
| ... | @@ -8423,7 +8493,7 @@ fn fieldVal( | ... | @@ -8423,7 +8493,7 @@ fn fieldVal( |
| 8423 | .Pointer => switch (object_ty.ptrSize()) { | 8493 | .Pointer => switch (object_ty.ptrSize()) { |
| 8424 | .Slice => { | 8494 | .Slice => { |
| 8425 | if (mem.eql(u8, field_name, "ptr")) { | 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 | const result_ty = object_ty.slicePtrFieldType(buf); | 8497 | const result_ty = object_ty.slicePtrFieldType(buf); |
| 8428 | if (try sema.resolveMaybeUndefVal(block, object_src, object)) |val| { | 8498 | if (try sema.resolveMaybeUndefVal(block, object_src, object)) |val| { |
| 8429 | if (val.isUndef()) return sema.addConstUndef(result_ty); | 8499 | if (val.isUndef()) return sema.addConstUndef(result_ty); |
| ... | @@ -8457,21 +8527,32 @@ fn fieldVal( | ... | @@ -8457,21 +8527,32 @@ fn fieldVal( |
| 8457 | } | 8527 | } |
| 8458 | }, | 8528 | }, |
| 8459 | .One => { | 8529 | .One => { |
| 8460 | const elem_ty = object_ty.elemType(); | 8530 | const ptr_child = object_ty.elemType(); |
| 8461 | if (elem_ty.zigTypeTag() == .Array) { | 8531 | switch (ptr_child.zigTypeTag()) { |
| 8462 | if (mem.eql(u8, field_name, "len")) { | 8532 | .Array => { |
| 8463 | return sema.addConstant( | 8533 | if (mem.eql(u8, field_name, "len")) { |
| 8464 | Type.initTag(.comptime_int), | 8534 | return sema.addConstant( |
| 8465 | try Value.Tag.int_u64.create(arena, elem_ty.arrayLen()), | 8535 | Type.initTag(.comptime_int), |
| 8466 | ); | 8536 | try Value.Tag.int_u64.create(arena, ptr_child.arrayLen()), |
| 8467 | } else { | 8537 | ); |
| 8468 | return mod.fail( | 8538 | } else { |
| 8469 | &block.base, | 8539 | return mod.fail( |
| 8470 | field_name_src, | 8540 | &block.base, |
| 8471 | "no member named '{s}' in '{}'", | 8541 | field_name_src, |
| 8472 | .{ field_name, object_ty }, | 8542 | "no member named '{s}' in '{}'", |
| 8473 | ); | 8543 | .{ field_name, object_ty }, |
| 8474 | } | 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 | .Many, .C => {}, | 8558 | .Many, .C => {}, |
| ... | @@ -8595,9 +8676,8 @@ fn fieldPtr( | ... | @@ -8595,9 +8676,8 @@ fn fieldPtr( |
| 8595 | ); | 8676 | ); |
| 8596 | } | 8677 | } |
| 8597 | }, | 8678 | }, |
| 8598 | .Pointer => { | 8679 | .Pointer => switch (object_ty.ptrSize()) { |
| 8599 | const ptr_child = object_ty.elemType(); | 8680 | .Slice => { |
| 8600 | if (ptr_child.isSlice()) { | ||
| 8601 | // Here for the ptr and len fields what we need to do is the situation | 8681 | // Here for the ptr and len fields what we need to do is the situation |
| 8602 | // when a temporary has its address taken, e.g. `&a[c..d].len`. | 8682 | // when a temporary has its address taken, e.g. `&a[c..d].len`. |
| 8603 | // This value may be known at compile-time or runtime. In the former | 8683 | // This value may be known at compile-time or runtime. In the former |
| ... | @@ -8627,26 +8707,39 @@ fn fieldPtr( | ... | @@ -8627,26 +8707,39 @@ fn fieldPtr( |
| 8627 | .{ field_name, object_ty }, | 8707 | .{ field_name, object_ty }, |
| 8628 | ); | 8708 | ); |
| 8629 | } | 8709 | } |
| 8630 | } else switch (ptr_child.zigTypeTag()) { | 8710 | }, |
| 8631 | .Array => { | 8711 | .One => { |
| 8632 | if (mem.eql(u8, field_name, "len")) { | 8712 | const ptr_child = object_ty.elemType(); |
| 8633 | var anon_decl = try block.startAnonDecl(); | 8713 | switch (ptr_child.zigTypeTag()) { |
| 8634 | defer anon_decl.deinit(); | 8714 | .Array => { |
| 8635 | return sema.analyzeDeclRef(try anon_decl.finish( | 8715 | if (mem.eql(u8, field_name, "len")) { |
| 8636 | Type.initTag(.comptime_int), | 8716 | var anon_decl = try block.startAnonDecl(); |
| 8637 | try Value.Tag.int_u64.create(anon_decl.arena(), ptr_child.arrayLen()), | 8717 | defer anon_decl.deinit(); |
| 8638 | )); | 8718 | return sema.analyzeDeclRef(try anon_decl.finish( |
| 8639 | } else { | 8719 | Type.initTag(.comptime_int), |
| 8640 | return mod.fail( | 8720 | try Value.Tag.int_u64.create(anon_decl.arena(), ptr_child.arrayLen()), |
| 8641 | &block.base, | 8721 | )); |
| 8642 | field_name_src, | 8722 | } else { |
| 8643 | "no member named '{s}' in '{}'", | 8723 | return mod.fail( |
| 8644 | .{ field_name, object_ty }, | 8724 | &block.base, |
| 8645 | ); | 8725 | field_name_src, |
| 8646 | } | 8726 | "no member named '{s}' in '{}'", |
| 8647 | }, | 8727 | .{ field_name, object_ty }, |
| 8648 | else => {}, | 8728 | ); |
| 8649 | } | 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 | .Type => { | 8744 | .Type => { |
| 8652 | _ = try sema.resolveConstValue(block, object_ptr_src, object_ptr); | 8745 | _ = try sema.resolveConstValue(block, object_ptr_src, object_ptr); |
| ... | @@ -8788,13 +8881,20 @@ fn structFieldPtr( | ... | @@ -8788,13 +8881,20 @@ fn structFieldPtr( |
| 8788 | const arena = sema.arena; | 8881 | const arena = sema.arena; |
| 8789 | assert(unresolved_struct_ty.zigTypeTag() == .Struct); | 8882 | assert(unresolved_struct_ty.zigTypeTag() == .Struct); |
| 8790 | 8883 | ||
| 8884 | const struct_ptr_ty = sema.typeOf(struct_ptr); | ||
| 8791 | const struct_ty = try sema.resolveTypeFields(block, src, unresolved_struct_ty); | 8885 | const struct_ty = try sema.resolveTypeFields(block, src, unresolved_struct_ty); |
| 8792 | const struct_obj = struct_ty.castTag(.@"struct").?.data; | 8886 | const struct_obj = struct_ty.castTag(.@"struct").?.data; |
| 8793 | 8887 | ||
| 8794 | const field_index = struct_obj.fields.getIndex(field_name) orelse | 8888 | const field_index = struct_obj.fields.getIndex(field_name) orelse |
| 8795 | return sema.failWithBadFieldAccess(block, struct_obj, field_name_src, field_name); | 8889 | return sema.failWithBadFieldAccess(block, struct_obj, field_name_src, field_name); |
| 8796 | const field = struct_obj.fields.values()[field_index]; | 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 | if (try sema.resolveDefinedValue(block, src, struct_ptr)) |struct_ptr_val| { | 8899 | if (try sema.resolveDefinedValue(block, src, struct_ptr)) |struct_ptr_val| { |
| 8800 | return sema.addConstant( | 8900 | return sema.addConstant( |
| ... | @@ -8885,6 +8985,7 @@ fn unionFieldPtr( | ... | @@ -8885,6 +8985,7 @@ fn unionFieldPtr( |
| 8885 | const arena = sema.arena; | 8985 | const arena = sema.arena; |
| 8886 | assert(unresolved_union_ty.zigTypeTag() == .Union); | 8986 | assert(unresolved_union_ty.zigTypeTag() == .Union); |
| 8887 | 8987 | ||
| 8988 | const union_ptr_ty = sema.typeOf(union_ptr); | ||
| 8888 | const union_ty = try sema.resolveTypeFields(block, src, unresolved_union_ty); | 8989 | const union_ty = try sema.resolveTypeFields(block, src, unresolved_union_ty); |
| 8889 | const union_obj = union_ty.cast(Type.Payload.Union).?.data; | 8990 | const union_obj = union_ty.cast(Type.Payload.Union).?.data; |
| 8890 | 8991 | ||
| ... | @@ -8892,7 +8993,13 @@ fn unionFieldPtr( | ... | @@ -8892,7 +8993,13 @@ fn unionFieldPtr( |
| 8892 | return sema.failWithBadUnionFieldAccess(block, union_obj, field_name_src, field_name); | 8993 | return sema.failWithBadUnionFieldAccess(block, union_obj, field_name_src, field_name); |
| 8893 | 8994 | ||
| 8894 | const field = union_obj.fields.values()[field_index]; | 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 | if (try sema.resolveDefinedValue(block, src, union_ptr)) |union_ptr_val| { | 9004 | if (try sema.resolveDefinedValue(block, src, union_ptr)) |union_ptr_val| { |
| 8898 | // TODO detect inactive union field and emit compile error | 9005 | // TODO detect inactive union field and emit compile error |
| ... | @@ -9068,10 +9175,13 @@ fn elemPtrArray( | ... | @@ -9068,10 +9175,13 @@ fn elemPtrArray( |
| 9068 | ) CompileError!Air.Inst.Ref { | 9175 | ) CompileError!Air.Inst.Ref { |
| 9069 | const array_ptr_ty = sema.typeOf(array_ptr); | 9176 | const array_ptr_ty = sema.typeOf(array_ptr); |
| 9070 | const pointee_type = array_ptr_ty.elemType().elemType(); | 9177 | const pointee_type = array_ptr_ty.elemType().elemType(); |
| 9071 | const result_ty = if (array_ptr_ty.ptrIsMutable()) | 9178 | const result_ty = try Module.simplePtrType( |
| 9072 | try Type.Tag.single_mut_pointer.create(sema.arena, pointee_type) | 9179 | sema.arena, |
| 9073 | else | 9180 | pointee_type, |
| 9074 | try Type.Tag.single_const_pointer.create(sema.arena, pointee_type); | 9181 | array_ptr_ty.ptrIsMutable(), |
| 9182 | .One, | ||
| 9183 | array_ptr_ty.ptrAddressSpace(), | ||
| 9184 | ); | ||
| 9075 | 9185 | ||
| 9076 | if (try sema.resolveDefinedValue(block, src, array_ptr)) |array_ptr_val| { | 9186 | if (try sema.resolveDefinedValue(block, src, array_ptr)) |array_ptr_val| { |
| 9077 | if (try sema.resolveDefinedValue(block, elem_index_src, elem_index)) |index_val| { | 9187 | if (try sema.resolveDefinedValue(block, elem_index_src, elem_index)) |index_val| { |
| ... | @@ -9162,6 +9272,7 @@ fn coerce( | ... | @@ -9162,6 +9272,7 @@ fn coerce( |
| 9162 | const dest_is_mut = !dest_type.isConstPtr(); | 9272 | const dest_is_mut = !dest_type.isConstPtr(); |
| 9163 | if (inst_ty.isConstPtr() and dest_is_mut) break :src_array_ptr; | 9273 | if (inst_ty.isConstPtr() and dest_is_mut) break :src_array_ptr; |
| 9164 | if (inst_ty.isVolatilePtr() and !dest_type.isVolatilePtr()) break :src_array_ptr; | 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 | const dst_elem_type = dest_type.elemType(); | 9277 | const dst_elem_type = dest_type.elemType(); |
| 9167 | switch (coerceInMemoryAllowed(dst_elem_type, array_elem_type, dest_is_mut)) { | 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,6 +9408,10 @@ fn coerceInMemoryAllowed(dest_type: Type, src_type: Type, dest_is_mut: bool) InM |
| 9297 | return child; | 9408 | return child; |
| 9298 | } | 9409 | } |
| 9299 | 9410 | ||
| 9411 | if (dest_info.@"addrspace" != src_info.@"addrspace") { | ||
| 9412 | return .no_match; | ||
| 9413 | } | ||
| 9414 | |||
| 9300 | const ok_sent = dest_info.sentinel == null or src_info.size == .C or | 9415 | const ok_sent = dest_info.sentinel == null or src_info.size == .C or |
| 9301 | (src_info.sentinel != null and | 9416 | (src_info.sentinel != null and |
| 9302 | dest_info.sentinel.?.eql(src_info.sentinel.?, dest_info.pointee_type)); | 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,11 +9705,11 @@ fn analyzeDeclRef(sema: *Sema, decl: *Decl) CompileError!Air.Inst.Ref { |
| 9590 | const decl_tv = try decl.typedValue(); | 9705 | const decl_tv = try decl.typedValue(); |
| 9591 | if (decl_tv.val.castTag(.variable)) |payload| { | 9706 | if (decl_tv.val.castTag(.variable)) |payload| { |
| 9592 | const variable = payload.data; | 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 | return sema.addConstant(ty, try Value.Tag.decl_ref.create(sema.arena, decl)); | 9709 | return sema.addConstant(ty, try Value.Tag.decl_ref.create(sema.arena, decl)); |
| 9595 | } | 9710 | } |
| 9596 | return sema.addConstant( | 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 | try Value.Tag.decl_ref.create(sema.arena, decl), | 9713 | try Value.Tag.decl_ref.create(sema.arena, decl), |
| 9599 | ); | 9714 | ); |
| 9600 | } | 9715 | } |
| ... | @@ -9617,8 +9732,9 @@ fn analyzeRef( | ... | @@ -9617,8 +9732,9 @@ fn analyzeRef( |
| 9617 | } | 9732 | } |
| 9618 | 9733 | ||
| 9619 | try sema.requireRuntimeBlock(block, src); | 9734 | try sema.requireRuntimeBlock(block, src); |
| 9620 | const ptr_type = try Module.simplePtrType(sema.arena, operand_ty, false, .One); | 9735 | const address_space = target_util.defaultAddressSpace(sema.mod.getTarget(), .local); |
| 9621 | const mut_ptr_type = try Module.simplePtrType(sema.arena, operand_ty, true, .One); | 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 | const alloc = try block.addTy(.alloc, mut_ptr_type); | 9738 | const alloc = try block.addTy(.alloc, mut_ptr_type); |
| 9623 | try sema.storePtr(block, src, alloc, operand); | 9739 | try sema.storePtr(block, src, alloc, operand); |
| 9624 | 9740 | ||
| ... | @@ -9779,6 +9895,7 @@ fn analyzeSlice( | ... | @@ -9779,6 +9895,7 @@ fn analyzeSlice( |
| 9779 | return_elem_type, | 9895 | return_elem_type, |
| 9780 | if (end_opt == .none) slice_sentinel else null, | 9896 | if (end_opt == .none) slice_sentinel else null, |
| 9781 | 0, // TODO alignment | 9897 | 0, // TODO alignment |
| 9898 | if (ptr_child.zigTypeTag() == .Pointer) ptr_child.ptrAddressSpace() else .generic, | ||
| 9782 | 0, | 9899 | 0, |
| 9783 | 0, | 9900 | 0, |
| 9784 | !ptr_child.isConstPtr(), | 9901 | !ptr_child.isConstPtr(), |
| ... | @@ -10286,6 +10403,7 @@ fn resolveTypeFields(sema: *Sema, block: *Scope.Block, src: LazySrcLoc, ty: Type | ... | @@ -10286,6 +10403,7 @@ fn resolveTypeFields(sema: *Sema, block: *Scope.Block, src: LazySrcLoc, ty: Type |
| 10286 | .atomic_order => return sema.resolveBuiltinTypeFields(block, src, "AtomicOrder"), | 10403 | .atomic_order => return sema.resolveBuiltinTypeFields(block, src, "AtomicOrder"), |
| 10287 | .atomic_rmw_op => return sema.resolveBuiltinTypeFields(block, src, "AtomicRmwOp"), | 10404 | .atomic_rmw_op => return sema.resolveBuiltinTypeFields(block, src, "AtomicRmwOp"), |
| 10288 | .calling_convention => return sema.resolveBuiltinTypeFields(block, src, "CallingConvention"), | 10405 | .calling_convention => return sema.resolveBuiltinTypeFields(block, src, "CallingConvention"), |
| 10406 | .address_space => return sema.resolveBuiltinTypeFields(block, src, "AddressSpace"), | ||
| 10289 | .float_mode => return sema.resolveBuiltinTypeFields(block, src, "FloatMode"), | 10407 | .float_mode => return sema.resolveBuiltinTypeFields(block, src, "FloatMode"), |
| 10290 | .reduce_op => return sema.resolveBuiltinTypeFields(block, src, "ReduceOp"), | 10408 | .reduce_op => return sema.resolveBuiltinTypeFields(block, src, "ReduceOp"), |
| 10291 | .call_options => return sema.resolveBuiltinTypeFields(block, src, "CallOptions"), | 10409 | .call_options => return sema.resolveBuiltinTypeFields(block, src, "CallOptions"), |
| ... | @@ -10680,6 +10798,7 @@ fn typeHasOnePossibleValue( | ... | @@ -10680,6 +10798,7 @@ fn typeHasOnePossibleValue( |
| 10680 | .atomic_order, | 10798 | .atomic_order, |
| 10681 | .atomic_rmw_op, | 10799 | .atomic_rmw_op, |
| 10682 | .calling_convention, | 10800 | .calling_convention, |
| 10801 | .address_space, | ||
| 10683 | .float_mode, | 10802 | .float_mode, |
| 10684 | .reduce_op, | 10803 | .reduce_op, |
| 10685 | .call_options, | 10804 | .call_options, |
| ... | @@ -10865,6 +10984,7 @@ pub fn addType(sema: *Sema, ty: Type) !Air.Inst.Ref { | ... | @@ -10865,6 +10984,7 @@ pub fn addType(sema: *Sema, ty: Type) !Air.Inst.Ref { |
| 10865 | .atomic_order => return .atomic_order_type, | 10984 | .atomic_order => return .atomic_order_type, |
| 10866 | .atomic_rmw_op => return .atomic_rmw_op_type, | 10985 | .atomic_rmw_op => return .atomic_rmw_op_type, |
| 10867 | .calling_convention => return .calling_convention_type, | 10986 | .calling_convention => return .calling_convention_type, |
| 10987 | .address_space => return .address_space_type, | ||
| 10868 | .float_mode => return .float_mode_type, | 10988 | .float_mode => return .float_mode_type, |
| 10869 | .reduce_op => return .reduce_op_type, | 10989 | .reduce_op => return .reduce_op_type, |
| 10870 | .call_options => return .call_options_type, | 10990 | .call_options => return .call_options_type, |
| ... | @@ -10960,7 +11080,13 @@ fn analyzeComptimeAlloc( | ... | @@ -10960,7 +11080,13 @@ fn analyzeComptimeAlloc( |
| 10960 | block: *Scope.Block, | 11080 | block: *Scope.Block, |
| 10961 | var_type: Type, | 11081 | var_type: Type, |
| 10962 | ) CompileError!Air.Inst.Ref { | 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 | var anon_decl = try block.startAnonDecl(); | 11091 | var anon_decl = try block.startAnonDecl(); |
| 10966 | defer anon_decl.deinit(); | 11092 | defer anon_decl.deinit(); |
| ... | @@ -10976,3 +11102,58 @@ fn analyzeComptimeAlloc( | ... | @@ -10976,3 +11102,58 @@ fn analyzeComptimeAlloc( |
| 10976 | .decl = decl, | 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,10 +443,10 @@ pub const Inst = struct { |
| 443 | /// this instruction; a following 'ret' instruction will do the diversion. | 443 | /// this instruction; a following 'ret' instruction will do the diversion. |
| 444 | /// Uses the `str_tok` union field. | 444 | /// Uses the `str_tok` union field. |
| 445 | ret_err_value_code, | 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 | /// Uses the `ptr_type_simple` union field. | 447 | /// Uses the `ptr_type_simple` union field. |
| 448 | ptr_type_simple, | 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 | /// Uses the `ptr_type` union field. | 450 | /// Uses the `ptr_type` union field. |
| 451 | ptr_type, | 451 | ptr_type, |
| 452 | /// Slice operation `lhs[rhs..]`. No sentinel and no end offset. | 452 | /// Slice operation `lhs[rhs..]`. No sentinel and no end offset. |
| ... | @@ -1672,6 +1672,7 @@ pub const Inst = struct { | ... | @@ -1672,6 +1672,7 @@ pub const Inst = struct { |
| 1672 | atomic_order_type, | 1672 | atomic_order_type, |
| 1673 | atomic_rmw_op_type, | 1673 | atomic_rmw_op_type, |
| 1674 | calling_convention_type, | 1674 | calling_convention_type, |
| 1675 | address_space_type, | ||
| 1675 | float_mode_type, | 1676 | float_mode_type, |
| 1676 | reduce_op_type, | 1677 | reduce_op_type, |
| 1677 | call_options_type, | 1678 | call_options_type, |
| ... | @@ -1928,6 +1929,10 @@ pub const Inst = struct { | ... | @@ -1928,6 +1929,10 @@ pub const Inst = struct { |
| 1928 | .ty = Type.initTag(.type), | 1929 | .ty = Type.initTag(.type), |
| 1929 | .val = Value.initTag(.calling_convention_type), | 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 | .float_mode_type = .{ | 1936 | .float_mode_type = .{ |
| 1932 | .ty = Type.initTag(.type), | 1937 | .ty = Type.initTag(.type), |
| 1933 | .val = Value.initTag(.float_mode_type), | 1938 | .val = Value.initTag(.float_mode_type), |
| ... | @@ -2129,8 +2134,9 @@ pub const Inst = struct { | ... | @@ -2129,8 +2134,9 @@ pub const Inst = struct { |
| 2129 | is_volatile: bool, | 2134 | is_volatile: bool, |
| 2130 | has_sentinel: bool, | 2135 | has_sentinel: bool, |
| 2131 | has_align: bool, | 2136 | has_align: bool, |
| 2137 | has_addrspace: bool, | ||
| 2132 | has_bit_range: bool, | 2138 | has_bit_range: bool, |
| 2133 | _: u2 = undefined, | 2139 | _: u1 = undefined, |
| 2134 | }, | 2140 | }, |
| 2135 | size: std.builtin.TypeInfo.Pointer.Size, | 2141 | size: std.builtin.TypeInfo.Pointer.Size, |
| 2136 | /// Index into extra. See `PtrType`. | 2142 | /// Index into extra. See `PtrType`. |
| ... | @@ -2360,12 +2366,13 @@ pub const Inst = struct { | ... | @@ -2360,12 +2366,13 @@ pub const Inst = struct { |
| 2360 | else_body_len: u32, | 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 | /// trailing Ref fields: | 2370 | /// trailing Ref fields: |
| 2365 | /// 0. sentinel: Ref // if `has_sentinel` flag is set | 2371 | /// 0. sentinel: Ref // if `has_sentinel` flag is set |
| 2366 | /// 1. align: Ref // if `has_align` flag is set | 2372 | /// 1. align: Ref // if `has_align` flag is set |
| 2367 | /// 2. bit_start: Ref // if `has_bit_range` flag is set | 2373 | /// 2. address_space: Ref // if `has_addrspace` flag is set |
| 2368 | /// 3. bit_end: Ref // if `has_bit_range` 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 | pub const PtrType = struct { | 2376 | pub const PtrType = struct { |
| 2370 | elem_type: Ref, | 2377 | elem_type: Ref, |
| 2371 | }; | 2378 | }; |
| ... | @@ -2483,7 +2490,7 @@ pub const Inst = struct { | ... | @@ -2483,7 +2490,7 @@ pub const Inst = struct { |
| 2483 | /// 0b000X: whether corresponding decl is pub | 2490 | /// 0b000X: whether corresponding decl is pub |
| 2484 | /// 0b00X0: whether corresponding decl is exported | 2491 | /// 0b00X0: whether corresponding decl is exported |
| 2485 | /// 0b0X00: whether corresponding decl has an align expression | 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 | /// 5. decl: { // for every decls_len | 2494 | /// 5. decl: { // for every decls_len |
| 2488 | /// src_hash: [4]u32, // hash of source bytes | 2495 | /// src_hash: [4]u32, // hash of source bytes |
| 2489 | /// line: u32, // line number of decl, relative to parent | 2496 | /// line: u32, // line number of decl, relative to parent |
| ... | @@ -2495,7 +2502,10 @@ pub const Inst = struct { | ... | @@ -2495,7 +2502,10 @@ pub const Inst = struct { |
| 2495 | /// this is a test decl, and the name starts at `name+1`. | 2502 | /// this is a test decl, and the name starts at `name+1`. |
| 2496 | /// value: Index, | 2503 | /// value: Index, |
| 2497 | /// align: Ref, // if corresponding bit is set | 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 | /// 6. inst: Index // for every body_len | 2510 | /// 6. inst: Index // for every body_len |
| 2501 | /// 7. flags: u32 // for every 8 fields | 2511 | /// 7. flags: u32 // for every 8 fields |
| ... | @@ -2547,7 +2557,7 @@ pub const Inst = struct { | ... | @@ -2547,7 +2557,7 @@ pub const Inst = struct { |
| 2547 | /// 0b000X: whether corresponding decl is pub | 2557 | /// 0b000X: whether corresponding decl is pub |
| 2548 | /// 0b00X0: whether corresponding decl is exported | 2558 | /// 0b00X0: whether corresponding decl is exported |
| 2549 | /// 0b0X00: whether corresponding decl has an align expression | 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 | /// 6. decl: { // for every decls_len | 2561 | /// 6. decl: { // for every decls_len |
| 2552 | /// src_hash: [4]u32, // hash of source bytes | 2562 | /// src_hash: [4]u32, // hash of source bytes |
| 2553 | /// line: u32, // line number of decl, relative to parent | 2563 | /// line: u32, // line number of decl, relative to parent |
| ... | @@ -2559,7 +2569,10 @@ pub const Inst = struct { | ... | @@ -2559,7 +2569,10 @@ pub const Inst = struct { |
| 2559 | /// this is a test decl, and the name starts at `name+1`. | 2569 | /// this is a test decl, and the name starts at `name+1`. |
| 2560 | /// value: Index, | 2570 | /// value: Index, |
| 2561 | /// align: Ref, // if corresponding bit is set | 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 | /// 7. inst: Index // for every body_len | 2577 | /// 7. inst: Index // for every body_len |
| 2565 | /// 8. has_bits: u32 // for every 32 fields | 2578 | /// 8. has_bits: u32 // for every 32 fields |
| ... | @@ -2592,7 +2605,7 @@ pub const Inst = struct { | ... | @@ -2592,7 +2605,7 @@ pub const Inst = struct { |
| 2592 | /// 0b000X: whether corresponding decl is pub | 2605 | /// 0b000X: whether corresponding decl is pub |
| 2593 | /// 0b00X0: whether corresponding decl is exported | 2606 | /// 0b00X0: whether corresponding decl is exported |
| 2594 | /// 0b0X00: whether corresponding decl has an align expression | 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 | /// 6. decl: { // for every decls_len | 2609 | /// 6. decl: { // for every decls_len |
| 2597 | /// src_hash: [4]u32, // hash of source bytes | 2610 | /// src_hash: [4]u32, // hash of source bytes |
| 2598 | /// line: u32, // line number of decl, relative to parent | 2611 | /// line: u32, // line number of decl, relative to parent |
| ... | @@ -2604,7 +2617,10 @@ pub const Inst = struct { | ... | @@ -2604,7 +2617,10 @@ pub const Inst = struct { |
| 2604 | /// this is a test decl, and the name starts at `name+1`. | 2617 | /// this is a test decl, and the name starts at `name+1`. |
| 2605 | /// value: Index, | 2618 | /// value: Index, |
| 2606 | /// align: Ref, // if corresponding bit is set | 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 | /// 7. inst: Index // for every body_len | 2625 | /// 7. inst: Index // for every body_len |
| 2610 | /// 8. has_bits: u32 // for every 8 fields | 2626 | /// 8. has_bits: u32 // for every 8 fields |
| ... | @@ -2641,7 +2657,7 @@ pub const Inst = struct { | ... | @@ -2641,7 +2657,7 @@ pub const Inst = struct { |
| 2641 | /// 0b000X: whether corresponding decl is pub | 2657 | /// 0b000X: whether corresponding decl is pub |
| 2642 | /// 0b00X0: whether corresponding decl is exported | 2658 | /// 0b00X0: whether corresponding decl is exported |
| 2643 | /// 0b0X00: whether corresponding decl has an align expression | 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 | /// 1. decl: { // for every decls_len | 2661 | /// 1. decl: { // for every decls_len |
| 2646 | /// src_hash: [4]u32, // hash of source bytes | 2662 | /// src_hash: [4]u32, // hash of source bytes |
| 2647 | /// line: u32, // line number of decl, relative to parent | 2663 | /// line: u32, // line number of decl, relative to parent |
| ... | @@ -2653,7 +2669,10 @@ pub const Inst = struct { | ... | @@ -2653,7 +2669,10 @@ pub const Inst = struct { |
| 2653 | /// this is a test decl, and the name starts at `name+1`. | 2669 | /// this is a test decl, and the name starts at `name+1`. |
| 2654 | /// value: Index, | 2670 | /// value: Index, |
| 2655 | /// align: Ref, // if corresponding bit is set | 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 | pub const OpaqueDecl = struct { | 2677 | pub const OpaqueDecl = struct { |
| 2659 | decls_len: u32, | 2678 | decls_len: u32, |
src/codegen.zig+1-1| ... | @@ -4895,7 +4895,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { | ... | @@ -4895,7 +4895,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { |
| 4895 | switch (typed_value.ty.zigTypeTag()) { | 4895 | switch (typed_value.ty.zigTypeTag()) { |
| 4896 | .Pointer => switch (typed_value.ty.ptrSize()) { | 4896 | .Pointer => switch (typed_value.ty.ptrSize()) { |
| 4897 | .Slice => { | 4897 | .Slice => { |
| 4898 | var buf: Type.Payload.ElemType = undefined; | 4898 | var buf: Type.SlicePtrFieldTypeBuffer = undefined; |
| 4899 | const ptr_type = typed_value.ty.slicePtrFieldType(&buf); | 4899 | const ptr_type = typed_value.ty.slicePtrFieldType(&buf); |
| 4900 | const ptr_mcv = try self.genTypedValue(.{ .ty = ptr_type, .val = typed_value.val }); | 4900 | const ptr_mcv = try self.genTypedValue(.{ .ty = ptr_type, .val = typed_value.val }); |
| 4901 | const slice_len = typed_value.val.sliceLen(); | 4901 | const slice_len = typed_value.val.sliceLen(); |
src/codegen/c.zig+1-1| ... | @@ -251,7 +251,7 @@ pub const DeclGen = struct { | ... | @@ -251,7 +251,7 @@ pub const DeclGen = struct { |
| 251 | try writer.writeByte('('); | 251 | try writer.writeByte('('); |
| 252 | try dg.renderType(writer, t); | 252 | try dg.renderType(writer, t); |
| 253 | try writer.writeAll("){"); | 253 | try writer.writeAll("){"); |
| 254 | var buf: Type.Payload.ElemType = undefined; | 254 | var buf: Type.SlicePtrFieldTypeBuffer = undefined; |
| 255 | try dg.renderValue(writer, t.slicePtrFieldType(&buf), val); | 255 | try dg.renderValue(writer, t.slicePtrFieldType(&buf), val); |
| 256 | try writer.writeAll(", "); | 256 | try writer.writeAll(", "); |
| 257 | try writer.print("{d}", .{val.sliceLen()}); | 257 | try writer.print("{d}", .{val.sliceLen()}); |
src/codegen/llvm.zig+30-8| ... | @@ -558,7 +558,8 @@ pub const DeclGen = struct { | ... | @@ -558,7 +558,8 @@ pub const DeclGen = struct { |
| 558 | llvm_params_len, | 558 | llvm_params_len, |
| 559 | .False, | 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 | const is_extern = decl.val.tag() == .extern_fn; | 564 | const is_extern = decl.val.tag() == .extern_fn; |
| 564 | if (!is_extern) { | 565 | if (!is_extern) { |
| ... | @@ -580,7 +581,24 @@ pub const DeclGen = struct { | ... | @@ -580,7 +581,24 @@ pub const DeclGen = struct { |
| 580 | if (llvm_module.getNamedGlobal(decl.name)) |val| return val; | 581 | if (llvm_module.getNamedGlobal(decl.name)) |val| return val; |
| 581 | // TODO: remove this redundant `llvmType`, it is also called in `genTypedValue`. | 582 | // TODO: remove this redundant `llvmType`, it is also called in `genTypedValue`. |
| 582 | const llvm_type = try self.llvmType(decl.ty); | 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 | fn llvmType(self: *DeclGen, t: Type) error{ OutOfMemory, CodegenFail }!*const llvm.Type { | 604 | fn llvmType(self: *DeclGen, t: Type) error{ OutOfMemory, CodegenFail }!*const llvm.Type { |
| ... | @@ -609,7 +627,7 @@ pub const DeclGen = struct { | ... | @@ -609,7 +627,7 @@ pub const DeclGen = struct { |
| 609 | .Bool => return self.context.intType(1), | 627 | .Bool => return self.context.intType(1), |
| 610 | .Pointer => { | 628 | .Pointer => { |
| 611 | if (t.isSlice()) { | 629 | if (t.isSlice()) { |
| 612 | var buf: Type.Payload.ElemType = undefined; | 630 | var buf: Type.SlicePtrFieldTypeBuffer = undefined; |
| 613 | const ptr_type = t.slicePtrFieldType(&buf); | 631 | const ptr_type = t.slicePtrFieldType(&buf); |
| 614 | 632 | ||
| 615 | const fields: [2]*const llvm.Type = .{ | 633 | const fields: [2]*const llvm.Type = .{ |
| ... | @@ -619,7 +637,8 @@ pub const DeclGen = struct { | ... | @@ -619,7 +637,8 @@ pub const DeclGen = struct { |
| 619 | return self.context.structType(&fields, fields.len, .False); | 637 | return self.context.structType(&fields, fields.len, .False); |
| 620 | } else { | 638 | } else { |
| 621 | const elem_type = try self.llvmType(t.elemType()); | 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 | .Array => { | 644 | .Array => { |
| ... | @@ -685,7 +704,9 @@ pub const DeclGen = struct { | ... | @@ -685,7 +704,9 @@ pub const DeclGen = struct { |
| 685 | @intCast(c_uint, llvm_params.len), | 704 | @intCast(c_uint, llvm_params.len), |
| 686 | llvm.Bool.fromBool(is_var_args), | 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 | .ComptimeInt => unreachable, | 711 | .ComptimeInt => unreachable, |
| 691 | .ComptimeFloat => unreachable, | 712 | .ComptimeFloat => unreachable, |
| ... | @@ -753,7 +774,7 @@ pub const DeclGen = struct { | ... | @@ -753,7 +774,7 @@ pub const DeclGen = struct { |
| 753 | .Pointer => switch (tv.val.tag()) { | 774 | .Pointer => switch (tv.val.tag()) { |
| 754 | .decl_ref => { | 775 | .decl_ref => { |
| 755 | if (tv.ty.isSlice()) { | 776 | if (tv.ty.isSlice()) { |
| 756 | var buf: Type.Payload.ElemType = undefined; | 777 | var buf: Type.SlicePtrFieldTypeBuffer = undefined; |
| 757 | const ptr_ty = tv.ty.slicePtrFieldType(&buf); | 778 | const ptr_ty = tv.ty.slicePtrFieldType(&buf); |
| 758 | var slice_len: Value.Payload.U64 = .{ | 779 | var slice_len: Value.Payload.U64 = .{ |
| 759 | .base = .{ .tag = .int_u64 }, | 780 | .base = .{ .tag = .int_u64 }, |
| ... | @@ -783,12 +804,13 @@ pub const DeclGen = struct { | ... | @@ -783,12 +804,13 @@ pub const DeclGen = struct { |
| 783 | decl.alive = true; | 804 | decl.alive = true; |
| 784 | const val = try self.resolveGlobalDecl(decl); | 805 | const val = try self.resolveGlobalDecl(decl); |
| 785 | const llvm_var_type = try self.llvmType(tv.ty); | 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 | return val.constBitCast(llvm_type); | 809 | return val.constBitCast(llvm_type); |
| 788 | }, | 810 | }, |
| 789 | .slice => { | 811 | .slice => { |
| 790 | const slice = tv.val.castTag(.slice).?.data; | 812 | const slice = tv.val.castTag(.slice).?.data; |
| 791 | var buf: Type.Payload.ElemType = undefined; | 813 | var buf: Type.SlicePtrFieldTypeBuffer = undefined; |
| 792 | const fields: [2]*const llvm.Value = .{ | 814 | const fields: [2]*const llvm.Value = .{ |
| 793 | try self.genTypedValue(.{ | 815 | try self.genTypedValue(.{ |
| 794 | .ty = tv.ty.slicePtrFieldType(&buf), | 816 | .ty = tv.ty.slicePtrFieldType(&buf), |
src/codegen/llvm/bindings.zig+68| ... | @@ -197,6 +197,9 @@ pub const Module = opaque { | ... | @@ -197,6 +197,9 @@ pub const Module = opaque { |
| 197 | pub const addFunction = LLVMAddFunction; | 197 | pub const addFunction = LLVMAddFunction; |
| 198 | extern fn LLVMAddFunction(*const Module, Name: [*:0]const u8, FunctionTy: *const Type) *const Value; | 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 | pub const getNamedFunction = LLVMGetNamedFunction; | 203 | pub const getNamedFunction = LLVMGetNamedFunction; |
| 201 | extern fn LLVMGetNamedFunction(*const Module, Name: [*:0]const u8) ?*const Value; | 204 | extern fn LLVMGetNamedFunction(*const Module, Name: [*:0]const u8) ?*const Value; |
| 202 | 205 | ||
| ... | @@ -209,6 +212,9 @@ pub const Module = opaque { | ... | @@ -209,6 +212,9 @@ pub const Module = opaque { |
| 209 | pub const addGlobal = LLVMAddGlobal; | 212 | pub const addGlobal = LLVMAddGlobal; |
| 210 | extern fn LLVMAddGlobal(M: *const Module, Ty: *const Type, Name: [*:0]const u8) *const Value; | 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 | pub const getNamedGlobal = LLVMGetNamedGlobal; | 218 | pub const getNamedGlobal = LLVMGetNamedGlobal; |
| 213 | extern fn LLVMGetNamedGlobal(M: *const Module, Name: [*:0]const u8) ?*const Value; | 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,3 +1011,65 @@ pub const TypeKind = enum(c_int) { |
| 1005 | BFloat, | 1011 | BFloat, |
| 1006 | X86_AMX, | 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,7 +1147,7 @@ const Writer = struct { |
| 1147 | cur_bit_bag >>= 1; | 1147 | cur_bit_bag >>= 1; |
| 1148 | const has_align = @truncate(u1, cur_bit_bag) != 0; | 1148 | const has_align = @truncate(u1, cur_bit_bag) != 0; |
| 1149 | cur_bit_bag >>= 1; | 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 | cur_bit_bag >>= 1; | 1151 | cur_bit_bag >>= 1; |
| 1152 | 1152 | ||
| 1153 | const sub_index = extra_index; | 1153 | const sub_index = extra_index; |
| ... | @@ -1165,7 +1165,12 @@ const Writer = struct { | ... | @@ -1165,7 +1165,12 @@ const Writer = struct { |
| 1165 | extra_index += 1; | 1165 | extra_index += 1; |
| 1166 | break :inst inst; | 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 | const inst = @intToEnum(Zir.Inst.Ref, self.code.extra[extra_index]); | 1174 | const inst = @intToEnum(Zir.Inst.Ref, self.code.extra[extra_index]); |
| 1170 | extra_index += 1; | 1175 | extra_index += 1; |
| 1171 | break :inst inst; | 1176 | break :inst inst; |
| ... | @@ -1196,6 +1201,11 @@ const Writer = struct { | ... | @@ -1196,6 +1201,11 @@ const Writer = struct { |
| 1196 | try self.writeInstRef(stream, align_inst); | 1201 | try self.writeInstRef(stream, align_inst); |
| 1197 | try stream.writeAll(")"); | 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 | if (section_inst != .none) { | 1209 | if (section_inst != .none) { |
| 1200 | try stream.writeAll(" linksection("); | 1210 | try stream.writeAll(" linksection("); |
| 1201 | try self.writeInstRef(stream, section_inst); | 1211 | try self.writeInstRef(stream, section_inst); |
src/stage1/all_types.hpp+8| ... | @@ -86,6 +86,14 @@ enum CallingConvention { | ... | @@ -86,6 +86,14 @@ enum CallingConvention { |
| 86 | CallingConventionSysV | 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 | // This one corresponds to the builtin.zig enum. | 97 | // This one corresponds to the builtin.zig enum. |
| 90 | enum BuiltinPtrSize { | 98 | enum BuiltinPtrSize { |
| 91 | BuiltinPtrSizeOne, | 99 | BuiltinPtrSizeOne, |
src/stage1/analyze.cpp+10| ... | @@ -1019,6 +1019,16 @@ bool calling_convention_allows_zig_types(CallingConvention cc) { | ... | @@ -1019,6 +1019,16 @@ bool calling_convention_allows_zig_types(CallingConvention cc) { |
| 1019 | zig_unreachable(); | 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 | ZigType *get_stack_trace_type(CodeGen *g) { | 1032 | ZigType *get_stack_trace_type(CodeGen *g) { |
| 1023 | if (g->stack_trace_type == nullptr) { | 1033 | if (g->stack_trace_type == nullptr) { |
| 1024 | g->stack_trace_type = get_builtin_type(g, "StackTrace"); | 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,6 +242,8 @@ Error get_primitive_type(CodeGen *g, Buf *name, ZigType **result); |
| 242 | bool calling_convention_allows_zig_types(CallingConvention cc); | 242 | bool calling_convention_allows_zig_types(CallingConvention cc); |
| 243 | const char *calling_convention_name(CallingConvention cc); | 243 | const char *calling_convention_name(CallingConvention cc); |
| 244 | 244 | ||
| 245 | const char *address_space_name(AddressSpace as); | ||
| 246 | |||
| 245 | Error ATTRIBUTE_MUST_USE file_fetch(CodeGen *g, Buf *resolved_path, Buf *contents); | 247 | Error ATTRIBUTE_MUST_USE file_fetch(CodeGen *g, Buf *resolved_path, Buf *contents); |
| 246 | 248 | ||
| 247 | void walk_function_params(CodeGen *g, ZigType *fn_type, FnWalk *fn_walk); | 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,7 +16124,7 @@ static Stage1AirInst *ir_analyze_instruction_optional_unwrap_ptr(IrAnalyze *ira, |
| 16124 | 16124 | ||
| 16125 | static Stage1AirInst *ir_analyze_instruction_ctz(IrAnalyze *ira, Stage1ZirInstCtz *instruction) { | 16125 | static Stage1AirInst *ir_analyze_instruction_ctz(IrAnalyze *ira, Stage1ZirInstCtz *instruction) { |
| 16126 | Error err; | 16126 | Error err; |
| 16127 | 16127 | ||
| 16128 | ZigType *int_type = ir_resolve_int_type(ira, instruction->type->child); | 16128 | ZigType *int_type = ir_resolve_int_type(ira, instruction->type->child); |
| 16129 | if (type_is_invalid(int_type)) | 16129 | if (type_is_invalid(int_type)) |
| 16130 | return ira->codegen->invalid_inst_gen; | 16130 | return ira->codegen->invalid_inst_gen; |
| ... | @@ -16166,7 +16166,7 @@ static Stage1AirInst *ir_analyze_instruction_ctz(IrAnalyze *ira, Stage1ZirInstCt | ... | @@ -16166,7 +16166,7 @@ static Stage1AirInst *ir_analyze_instruction_ctz(IrAnalyze *ira, Stage1ZirInstCt |
| 16166 | return ira->codegen->invalid_inst_gen; | 16166 | return ira->codegen->invalid_inst_gen; |
| 16167 | if (val->special == ConstValSpecialUndef) | 16167 | if (val->special == ConstValSpecialUndef) |
| 16168 | return ir_const_undef(ira, instruction->base.scope, instruction->base.source_node, ira->codegen->builtin_types.entry_num_lit_int); | 16168 | return ir_const_undef(ira, instruction->base.scope, instruction->base.source_node, ira->codegen->builtin_types.entry_num_lit_int); |
| 16169 | 16169 | ||
| 16170 | if (is_vector) { | 16170 | if (is_vector) { |
| 16171 | ZigType *smallest_vec_type = get_vector_type(ira->codegen, vector_len, smallest_type); | 16171 | ZigType *smallest_vec_type = get_vector_type(ira->codegen, vector_len, smallest_type); |
| 16172 | Stage1AirInst *result = ir_const(ira, instruction->base.scope, instruction->base.source_node, smallest_vec_type); | 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,7 +16200,7 @@ static Stage1AirInst *ir_analyze_instruction_ctz(IrAnalyze *ira, Stage1ZirInstCt |
| 16200 | 16200 | ||
| 16201 | static Stage1AirInst *ir_analyze_instruction_clz(IrAnalyze *ira, Stage1ZirInstClz *instruction) { | 16201 | static Stage1AirInst *ir_analyze_instruction_clz(IrAnalyze *ira, Stage1ZirInstClz *instruction) { |
| 16202 | Error err; | 16202 | Error err; |
| 16203 | 16203 | ||
| 16204 | ZigType *int_type = ir_resolve_int_type(ira, instruction->type->child); | 16204 | ZigType *int_type = ir_resolve_int_type(ira, instruction->type->child); |
| 16205 | if (type_is_invalid(int_type)) | 16205 | if (type_is_invalid(int_type)) |
| 16206 | return ira->codegen->invalid_inst_gen; | 16206 | return ira->codegen->invalid_inst_gen; |
| ... | @@ -16242,7 +16242,7 @@ static Stage1AirInst *ir_analyze_instruction_clz(IrAnalyze *ira, Stage1ZirInstCl | ... | @@ -16242,7 +16242,7 @@ static Stage1AirInst *ir_analyze_instruction_clz(IrAnalyze *ira, Stage1ZirInstCl |
| 16242 | return ira->codegen->invalid_inst_gen; | 16242 | return ira->codegen->invalid_inst_gen; |
| 16243 | if (val->special == ConstValSpecialUndef) | 16243 | if (val->special == ConstValSpecialUndef) |
| 16244 | return ir_const_undef(ira, instruction->base.scope, instruction->base.source_node, ira->codegen->builtin_types.entry_num_lit_int); | 16244 | return ir_const_undef(ira, instruction->base.scope, instruction->base.source_node, ira->codegen->builtin_types.entry_num_lit_int); |
| 16245 | 16245 | ||
| 16246 | if (is_vector) { | 16246 | if (is_vector) { |
| 16247 | ZigType *smallest_vec_type = get_vector_type(ira->codegen, vector_len, smallest_type); | 16247 | ZigType *smallest_vec_type = get_vector_type(ira->codegen, vector_len, smallest_type); |
| 16248 | Stage1AirInst *result = ir_const(ira, instruction->base.scope, instruction->base.source_node, smallest_vec_type); | 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,7 +16276,7 @@ static Stage1AirInst *ir_analyze_instruction_clz(IrAnalyze *ira, Stage1ZirInstCl |
| 16276 | 16276 | ||
| 16277 | static Stage1AirInst *ir_analyze_instruction_pop_count(IrAnalyze *ira, Stage1ZirInstPopCount *instruction) { | 16277 | static Stage1AirInst *ir_analyze_instruction_pop_count(IrAnalyze *ira, Stage1ZirInstPopCount *instruction) { |
| 16278 | Error err; | 16278 | Error err; |
| 16279 | 16279 | ||
| 16280 | ZigType *int_type = ir_resolve_int_type(ira, instruction->type->child); | 16280 | ZigType *int_type = ir_resolve_int_type(ira, instruction->type->child); |
| 16281 | if (type_is_invalid(int_type)) | 16281 | if (type_is_invalid(int_type)) |
| 16282 | return ira->codegen->invalid_inst_gen; | 16282 | return ira->codegen->invalid_inst_gen; |
| ... | @@ -16318,7 +16318,7 @@ static Stage1AirInst *ir_analyze_instruction_pop_count(IrAnalyze *ira, Stage1Zir | ... | @@ -16318,7 +16318,7 @@ static Stage1AirInst *ir_analyze_instruction_pop_count(IrAnalyze *ira, Stage1Zir |
| 16318 | return ira->codegen->invalid_inst_gen; | 16318 | return ira->codegen->invalid_inst_gen; |
| 16319 | if (val->special == ConstValSpecialUndef) | 16319 | if (val->special == ConstValSpecialUndef) |
| 16320 | return ir_const_undef(ira, instruction->base.scope, instruction->base.source_node, ira->codegen->builtin_types.entry_num_lit_int); | 16320 | return ir_const_undef(ira, instruction->base.scope, instruction->base.source_node, ira->codegen->builtin_types.entry_num_lit_int); |
| 16321 | 16321 | ||
| 16322 | if (is_vector) { | 16322 | if (is_vector) { |
| 16323 | ZigType *smallest_vec_type = get_vector_type(ira->codegen, vector_len, smallest_type); | 16323 | ZigType *smallest_vec_type = get_vector_type(ira->codegen, vector_len, smallest_type); |
| 16324 | Stage1AirInst *result = ir_const(ira, instruction->base.scope, instruction->base.source_node, smallest_vec_type); | 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,7 +17904,7 @@ static ZigValue *create_ptr_like_type_info(IrAnalyze *ira, Scope *scope, AstNode |
| 17904 | result->special = ConstValSpecialStatic; | 17904 | result->special = ConstValSpecialStatic; |
| 17905 | result->type = type_info_pointer_type; | 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 | result->data.x_struct.fields = fields; | 17908 | result->data.x_struct.fields = fields; |
| 17909 | 17909 | ||
| 17910 | // size: Size | 17910 | // size: Size |
| ... | @@ -17939,24 +17939,29 @@ static ZigValue *create_ptr_like_type_info(IrAnalyze *ira, Scope *scope, AstNode | ... | @@ -17939,24 +17939,29 @@ static ZigValue *create_ptr_like_type_info(IrAnalyze *ira, Scope *scope, AstNode |
| 17939 | lazy_align_of->base.id = LazyValueIdAlignOf; | 17939 | lazy_align_of->base.id = LazyValueIdAlignOf; |
| 17940 | lazy_align_of->target_type = ir_const_type(ira, scope, source_node, attrs_type->data.pointer.child_type); | 17940 | lazy_align_of->target_type = ir_const_type(ira, scope, source_node, attrs_type->data.pointer.child_type); |
| 17941 | } | 17941 | } |
| 17942 | // child: type | 17942 | // address_space: AddressSpace, |
| 17943 | ensure_field_index(result->type, "child", 4); | 17943 | ensure_field_index(result->type, "address_space", 4); |
| 17944 | fields[4]->special = ConstValSpecialStatic; | 17944 | fields[4]->special = ConstValSpecialStatic; |
| 17945 | fields[4]->type = ira->codegen->builtin_types.entry_type; | 17945 | fields[4]->type = get_builtin_type(ira->codegen, "AddressSpace"); |
| 17946 | fields[4]->data.x_type = attrs_type->data.pointer.child_type; | 17946 | bigint_init_unsigned(&fields[4]->data.x_enum_tag, AddressSpaceGeneric); |
| 17947 | // is_allowzero: bool | 17947 | // child: type |
| 17948 | ensure_field_index(result->type, "is_allowzero", 5); | 17948 | ensure_field_index(result->type, "child", 5); |
| 17949 | fields[5]->special = ConstValSpecialStatic; | 17949 | fields[5]->special = ConstValSpecialStatic; |
| 17950 | fields[5]->type = ira->codegen->builtin_types.entry_bool; | 17950 | fields[5]->type = ira->codegen->builtin_types.entry_type; |
| 17951 | fields[5]->data.x_bool = attrs_type->data.pointer.allow_zero; | 17951 | fields[5]->data.x_type = attrs_type->data.pointer.child_type; |
| 17952 | // sentinel: anytype | 17952 | // is_allowzero: bool |
| 17953 | ensure_field_index(result->type, "sentinel", 6); | 17953 | ensure_field_index(result->type, "is_allowzero", 6); |
| 17954 | fields[6]->special = ConstValSpecialStatic; | 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 | if (attrs_type->data.pointer.sentinel != nullptr) { | 17960 | if (attrs_type->data.pointer.sentinel != nullptr) { |
| 17956 | fields[6]->type = get_optional_type(ira->codegen, attrs_type->data.pointer.child_type); | 17961 | fields[7]->type = get_optional_type(ira->codegen, attrs_type->data.pointer.child_type); |
| 17957 | set_optional_payload(fields[6], attrs_type->data.pointer.sentinel); | 17962 | set_optional_payload(fields[7], attrs_type->data.pointer.sentinel); |
| 17958 | } else { | 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 | return result; | 17967 | return result; |
| ... | @@ -18465,7 +18470,7 @@ static Error ir_make_type_info_value(IrAnalyze *ira, Scope *scope, AstNode *sour | ... | @@ -18465,7 +18470,7 @@ static Error ir_make_type_info_value(IrAnalyze *ira, Scope *scope, AstNode *sour |
| 18465 | result->special = ConstValSpecialStatic; | 18470 | result->special = ConstValSpecialStatic; |
| 18466 | result->type = ir_type_info_get_type(ira, "Fn", nullptr); | 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 | result->data.x_struct.fields = fields; | 18474 | result->data.x_struct.fields = fields; |
| 18470 | 18475 | ||
| 18471 | // calling_convention: TypeInfo.CallingConvention | 18476 | // calling_convention: TypeInfo.CallingConvention |
| ... | @@ -18826,11 +18831,11 @@ static ZigType *type_info_to_type(IrAnalyze *ira, Scope *scope, AstNode *source_ | ... | @@ -18826,11 +18831,11 @@ static ZigType *type_info_to_type(IrAnalyze *ira, Scope *scope, AstNode *source_ |
| 18826 | assert(size_value->type == ir_type_info_get_type(ira, "Size", type_info_pointer_type)); | 18831 | assert(size_value->type == ir_type_info_get_type(ira, "Size", type_info_pointer_type)); |
| 18827 | BuiltinPtrSize size_enum_index = (BuiltinPtrSize)bigint_as_u32(&size_value->data.x_enum_tag); | 18832 | BuiltinPtrSize size_enum_index = (BuiltinPtrSize)bigint_as_u32(&size_value->data.x_enum_tag); |
| 18828 | PtrLen ptr_len = size_enum_index_to_ptr_len(size_enum_index); | 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 | if (type_is_invalid(elem_type)) | 18835 | if (type_is_invalid(elem_type)) |
| 18831 | return ira->codegen->invalid_inst_gen->value->type; | 18836 | return ira->codegen->invalid_inst_gen->value->type; |
| 18832 | ZigValue *sentinel; | 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 | elem_type, &sentinel))) | 18839 | elem_type, &sentinel))) |
| 18835 | { | 18840 | { |
| 18836 | return ira->codegen->invalid_inst_gen->value->type; | 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,6 +18850,19 @@ static ZigType *type_info_to_type(IrAnalyze *ira, Scope *scope, AstNode *source_ |
| 18845 | if (alignment == nullptr) | 18850 | if (alignment == nullptr) |
| 18846 | return ira->codegen->invalid_inst_gen->value->type; | 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 | bool is_const; | 18866 | bool is_const; |
| 18849 | if ((err = get_const_field_bool(ira, source_node, payload, "is_const", 1, &is_const))) | 18867 | if ((err = get_const_field_bool(ira, source_node, payload, "is_const", 1, &is_const))) |
| 18850 | return ira->codegen->invalid_inst_gen->value->type; | 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,13 +18875,12 @@ static ZigType *type_info_to_type(IrAnalyze *ira, Scope *scope, AstNode *source_ |
| 18857 | } | 18875 | } |
| 18858 | 18876 | ||
| 18859 | bool is_allowzero; | 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 | &is_allowzero))) | 18879 | &is_allowzero))) |
| 18862 | { | 18880 | { |
| 18863 | return ira->codegen->invalid_inst_gen->value->type; | 18881 | return ira->codegen->invalid_inst_gen->value->type; |
| 18864 | } | 18882 | } |
| 18865 | 18883 | ||
| 18866 | |||
| 18867 | ZigType *ptr_type = get_pointer_to_type_extra2(ira->codegen, | 18884 | ZigType *ptr_type = get_pointer_to_type_extra2(ira->codegen, |
| 18868 | elem_type, | 18885 | elem_type, |
| 18869 | is_const, | 18886 | is_const, |
src/target.zig+18| ... | @@ -544,3 +544,21 @@ pub fn largestAtomicBits(target: std.Target) u32 { | ... | @@ -544,3 +544,21 @@ pub fn largestAtomicBits(target: std.Target) u32 { |
| 544 | .x86_64 => 128, | 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,6 +2614,7 @@ fn renderVar(c: *Context, node: Node) !NodeIndex { |
| 2614 | .type_node = type_node, | 2614 | .type_node = type_node, |
| 2615 | .align_node = align_node, | 2615 | .align_node = align_node, |
| 2616 | .section_node = section_node, | 2616 | .section_node = section_node, |
| 2617 | .addrspace_node = 0, | ||
| 2617 | }), | 2618 | }), |
| 2618 | .rhs = init_node, | 2619 | .rhs = init_node, |
| 2619 | }, | 2620 | }, |
| ... | @@ -2705,6 +2706,7 @@ fn renderFunc(c: *Context, node: Node) !NodeIndex { | ... | @@ -2705,6 +2706,7 @@ fn renderFunc(c: *Context, node: Node) !NodeIndex { |
| 2705 | .lhs = try c.addExtra(std.zig.Ast.Node.FnProtoOne{ | 2706 | .lhs = try c.addExtra(std.zig.Ast.Node.FnProtoOne{ |
| 2706 | .param = params.items[0], | 2707 | .param = params.items[0], |
| 2707 | .align_expr = align_expr, | 2708 | .align_expr = align_expr, |
| 2709 | .addrspace_expr = 0, // TODO | ||
| 2708 | .section_expr = section_expr, | 2710 | .section_expr = section_expr, |
| 2709 | .callconv_expr = callconv_expr, | 2711 | .callconv_expr = callconv_expr, |
| 2710 | }), | 2712 | }), |
| ... | @@ -2720,6 +2722,7 @@ fn renderFunc(c: *Context, node: Node) !NodeIndex { | ... | @@ -2720,6 +2722,7 @@ fn renderFunc(c: *Context, node: Node) !NodeIndex { |
| 2720 | .params_start = span.start, | 2722 | .params_start = span.start, |
| 2721 | .params_end = span.end, | 2723 | .params_end = span.end, |
| 2722 | .align_expr = align_expr, | 2724 | .align_expr = align_expr, |
| 2725 | .addrspace_expr = 0, // TODO | ||
| 2723 | .section_expr = section_expr, | 2726 | .section_expr = section_expr, |
| 2724 | .callconv_expr = callconv_expr, | 2727 | .callconv_expr = callconv_expr, |
| 2725 | }), | 2728 | }), |
src/type.zig+115-13| ... | @@ -127,6 +127,7 @@ pub const Type = extern union { | ... | @@ -127,6 +127,7 @@ pub const Type = extern union { |
| 127 | .atomic_order, | 127 | .atomic_order, |
| 128 | .atomic_rmw_op, | 128 | .atomic_rmw_op, |
| 129 | .calling_convention, | 129 | .calling_convention, |
| 130 | .address_space, | ||
| 130 | .float_mode, | 131 | .float_mode, |
| 131 | .reduce_op, | 132 | .reduce_op, |
| 132 | => return .Enum, | 133 | => return .Enum, |
| ... | @@ -288,6 +289,7 @@ pub const Type = extern union { | ... | @@ -288,6 +289,7 @@ pub const Type = extern union { |
| 288 | .pointee_type = Type.initTag(.comptime_int), | 289 | .pointee_type = Type.initTag(.comptime_int), |
| 289 | .sentinel = null, | 290 | .sentinel = null, |
| 290 | .@"align" = 0, | 291 | .@"align" = 0, |
| 292 | .@"addrspace" = .generic, | ||
| 291 | .bit_offset = 0, | 293 | .bit_offset = 0, |
| 292 | .host_size = 0, | 294 | .host_size = 0, |
| 293 | .@"allowzero" = false, | 295 | .@"allowzero" = false, |
| ... | @@ -299,6 +301,7 @@ pub const Type = extern union { | ... | @@ -299,6 +301,7 @@ pub const Type = extern union { |
| 299 | .pointee_type = Type.initTag(.u8), | 301 | .pointee_type = Type.initTag(.u8), |
| 300 | .sentinel = null, | 302 | .sentinel = null, |
| 301 | .@"align" = 0, | 303 | .@"align" = 0, |
| 304 | .@"addrspace" = .generic, | ||
| 302 | .bit_offset = 0, | 305 | .bit_offset = 0, |
| 303 | .host_size = 0, | 306 | .host_size = 0, |
| 304 | .@"allowzero" = false, | 307 | .@"allowzero" = false, |
| ... | @@ -310,6 +313,7 @@ pub const Type = extern union { | ... | @@ -310,6 +313,7 @@ pub const Type = extern union { |
| 310 | .pointee_type = self.castPointer().?.data, | 313 | .pointee_type = self.castPointer().?.data, |
| 311 | .sentinel = null, | 314 | .sentinel = null, |
| 312 | .@"align" = 0, | 315 | .@"align" = 0, |
| 316 | .@"addrspace" = .generic, | ||
| 313 | .bit_offset = 0, | 317 | .bit_offset = 0, |
| 314 | .host_size = 0, | 318 | .host_size = 0, |
| 315 | .@"allowzero" = false, | 319 | .@"allowzero" = false, |
| ... | @@ -321,6 +325,7 @@ pub const Type = extern union { | ... | @@ -321,6 +325,7 @@ pub const Type = extern union { |
| 321 | .pointee_type = self.castPointer().?.data, | 325 | .pointee_type = self.castPointer().?.data, |
| 322 | .sentinel = null, | 326 | .sentinel = null, |
| 323 | .@"align" = 0, | 327 | .@"align" = 0, |
| 328 | .@"addrspace" = .generic, | ||
| 324 | .bit_offset = 0, | 329 | .bit_offset = 0, |
| 325 | .host_size = 0, | 330 | .host_size = 0, |
| 326 | .@"allowzero" = false, | 331 | .@"allowzero" = false, |
| ... | @@ -332,6 +337,7 @@ pub const Type = extern union { | ... | @@ -332,6 +337,7 @@ pub const Type = extern union { |
| 332 | .pointee_type = self.castPointer().?.data, | 337 | .pointee_type = self.castPointer().?.data, |
| 333 | .sentinel = null, | 338 | .sentinel = null, |
| 334 | .@"align" = 0, | 339 | .@"align" = 0, |
| 340 | .@"addrspace" = .generic, | ||
| 335 | .bit_offset = 0, | 341 | .bit_offset = 0, |
| 336 | .host_size = 0, | 342 | .host_size = 0, |
| 337 | .@"allowzero" = false, | 343 | .@"allowzero" = false, |
| ... | @@ -343,6 +349,7 @@ pub const Type = extern union { | ... | @@ -343,6 +349,7 @@ pub const Type = extern union { |
| 343 | .pointee_type = Type.initTag(.u8), | 349 | .pointee_type = Type.initTag(.u8), |
| 344 | .sentinel = null, | 350 | .sentinel = null, |
| 345 | .@"align" = 0, | 351 | .@"align" = 0, |
| 352 | .@"addrspace" = .generic, | ||
| 346 | .bit_offset = 0, | 353 | .bit_offset = 0, |
| 347 | .host_size = 0, | 354 | .host_size = 0, |
| 348 | .@"allowzero" = false, | 355 | .@"allowzero" = false, |
| ... | @@ -354,6 +361,7 @@ pub const Type = extern union { | ... | @@ -354,6 +361,7 @@ pub const Type = extern union { |
| 354 | .pointee_type = self.castPointer().?.data, | 361 | .pointee_type = self.castPointer().?.data, |
| 355 | .sentinel = null, | 362 | .sentinel = null, |
| 356 | .@"align" = 0, | 363 | .@"align" = 0, |
| 364 | .@"addrspace" = .generic, | ||
| 357 | .bit_offset = 0, | 365 | .bit_offset = 0, |
| 358 | .host_size = 0, | 366 | .host_size = 0, |
| 359 | .@"allowzero" = false, | 367 | .@"allowzero" = false, |
| ... | @@ -365,6 +373,7 @@ pub const Type = extern union { | ... | @@ -365,6 +373,7 @@ pub const Type = extern union { |
| 365 | .pointee_type = Type.initTag(.u8), | 373 | .pointee_type = Type.initTag(.u8), |
| 366 | .sentinel = null, | 374 | .sentinel = null, |
| 367 | .@"align" = 0, | 375 | .@"align" = 0, |
| 376 | .@"addrspace" = .generic, | ||
| 368 | .bit_offset = 0, | 377 | .bit_offset = 0, |
| 369 | .host_size = 0, | 378 | .host_size = 0, |
| 370 | .@"allowzero" = false, | 379 | .@"allowzero" = false, |
| ... | @@ -376,6 +385,7 @@ pub const Type = extern union { | ... | @@ -376,6 +385,7 @@ pub const Type = extern union { |
| 376 | .pointee_type = self.castPointer().?.data, | 385 | .pointee_type = self.castPointer().?.data, |
| 377 | .sentinel = null, | 386 | .sentinel = null, |
| 378 | .@"align" = 0, | 387 | .@"align" = 0, |
| 388 | .@"addrspace" = .generic, | ||
| 379 | .bit_offset = 0, | 389 | .bit_offset = 0, |
| 380 | .host_size = 0, | 390 | .host_size = 0, |
| 381 | .@"allowzero" = false, | 391 | .@"allowzero" = false, |
| ... | @@ -387,6 +397,7 @@ pub const Type = extern union { | ... | @@ -387,6 +397,7 @@ pub const Type = extern union { |
| 387 | .pointee_type = self.castPointer().?.data, | 397 | .pointee_type = self.castPointer().?.data, |
| 388 | .sentinel = null, | 398 | .sentinel = null, |
| 389 | .@"align" = 0, | 399 | .@"align" = 0, |
| 400 | .@"addrspace" = .generic, | ||
| 390 | .bit_offset = 0, | 401 | .bit_offset = 0, |
| 391 | .host_size = 0, | 402 | .host_size = 0, |
| 392 | .@"allowzero" = false, | 403 | .@"allowzero" = false, |
| ... | @@ -398,6 +409,7 @@ pub const Type = extern union { | ... | @@ -398,6 +409,7 @@ pub const Type = extern union { |
| 398 | .pointee_type = self.castPointer().?.data, | 409 | .pointee_type = self.castPointer().?.data, |
| 399 | .sentinel = null, | 410 | .sentinel = null, |
| 400 | .@"align" = 0, | 411 | .@"align" = 0, |
| 412 | .@"addrspace" = .generic, | ||
| 401 | .bit_offset = 0, | 413 | .bit_offset = 0, |
| 402 | .host_size = 0, | 414 | .host_size = 0, |
| 403 | .@"allowzero" = false, | 415 | .@"allowzero" = false, |
| ... | @@ -409,6 +421,7 @@ pub const Type = extern union { | ... | @@ -409,6 +421,7 @@ pub const Type = extern union { |
| 409 | .pointee_type = self.castPointer().?.data, | 421 | .pointee_type = self.castPointer().?.data, |
| 410 | .sentinel = null, | 422 | .sentinel = null, |
| 411 | .@"align" = 0, | 423 | .@"align" = 0, |
| 424 | .@"addrspace" = .generic, | ||
| 412 | .bit_offset = 0, | 425 | .bit_offset = 0, |
| 413 | .host_size = 0, | 426 | .host_size = 0, |
| 414 | .@"allowzero" = false, | 427 | .@"allowzero" = false, |
| ... | @@ -461,6 +474,8 @@ pub const Type = extern union { | ... | @@ -461,6 +474,8 @@ pub const Type = extern union { |
| 461 | return false; | 474 | return false; |
| 462 | if (info_a.host_size != info_b.host_size) | 475 | if (info_a.host_size != info_b.host_size) |
| 463 | return false; | 476 | return false; |
| 477 | if (info_a.@"addrspace" != info_b.@"addrspace") | ||
| 478 | return false; | ||
| 464 | 479 | ||
| 465 | const sentinel_a = info_a.sentinel; | 480 | const sentinel_a = info_a.sentinel; |
| 466 | const sentinel_b = info_b.sentinel; | 481 | const sentinel_b = info_b.sentinel; |
| ... | @@ -746,6 +761,7 @@ pub const Type = extern union { | ... | @@ -746,6 +761,7 @@ pub const Type = extern union { |
| 746 | .atomic_order, | 761 | .atomic_order, |
| 747 | .atomic_rmw_op, | 762 | .atomic_rmw_op, |
| 748 | .calling_convention, | 763 | .calling_convention, |
| 764 | .address_space, | ||
| 749 | .float_mode, | 765 | .float_mode, |
| 750 | .reduce_op, | 766 | .reduce_op, |
| 751 | .call_options, | 767 | .call_options, |
| ... | @@ -835,6 +851,7 @@ pub const Type = extern union { | ... | @@ -835,6 +851,7 @@ pub const Type = extern union { |
| 835 | .pointee_type = try payload.pointee_type.copy(allocator), | 851 | .pointee_type = try payload.pointee_type.copy(allocator), |
| 836 | .sentinel = sent, | 852 | .sentinel = sent, |
| 837 | .@"align" = payload.@"align", | 853 | .@"align" = payload.@"align", |
| 854 | .@"addrspace" = payload.@"addrspace", | ||
| 838 | .bit_offset = payload.bit_offset, | 855 | .bit_offset = payload.bit_offset, |
| 839 | .host_size = payload.host_size, | 856 | .host_size = payload.host_size, |
| 840 | .@"allowzero" = payload.@"allowzero", | 857 | .@"allowzero" = payload.@"allowzero", |
| ... | @@ -958,6 +975,7 @@ pub const Type = extern union { | ... | @@ -958,6 +975,7 @@ pub const Type = extern union { |
| 958 | .atomic_order => return writer.writeAll("std.builtin.AtomicOrder"), | 975 | .atomic_order => return writer.writeAll("std.builtin.AtomicOrder"), |
| 959 | .atomic_rmw_op => return writer.writeAll("std.builtin.AtomicRmwOp"), | 976 | .atomic_rmw_op => return writer.writeAll("std.builtin.AtomicRmwOp"), |
| 960 | .calling_convention => return writer.writeAll("std.builtin.CallingConvention"), | 977 | .calling_convention => return writer.writeAll("std.builtin.CallingConvention"), |
| 978 | .address_space => return writer.writeAll("std.builtin.AddressSpace"), | ||
| 961 | .float_mode => return writer.writeAll("std.builtin.FloatMode"), | 979 | .float_mode => return writer.writeAll("std.builtin.FloatMode"), |
| 962 | .reduce_op => return writer.writeAll("std.builtin.ReduceOp"), | 980 | .reduce_op => return writer.writeAll("std.builtin.ReduceOp"), |
| 963 | .call_options => return writer.writeAll("std.builtin.CallOptions"), | 981 | .call_options => return writer.writeAll("std.builtin.CallOptions"), |
| ... | @@ -1111,6 +1129,9 @@ pub const Type = extern union { | ... | @@ -1111,6 +1129,9 @@ pub const Type = extern union { |
| 1111 | } | 1129 | } |
| 1112 | try writer.writeAll(") "); | 1130 | try writer.writeAll(") "); |
| 1113 | } | 1131 | } |
| 1132 | if (payload.@"addrspace" != .generic) { | ||
| 1133 | try writer.print("addrspace(.{s}) ", .{@tagName(payload.@"addrspace")}); | ||
| 1134 | } | ||
| 1114 | if (!payload.mutable) try writer.writeAll("const "); | 1135 | if (!payload.mutable) try writer.writeAll("const "); |
| 1115 | if (payload.@"volatile") try writer.writeAll("volatile "); | 1136 | if (payload.@"volatile") try writer.writeAll("volatile "); |
| 1116 | if (payload.@"allowzero") try writer.writeAll("allowzero "); | 1137 | if (payload.@"allowzero") try writer.writeAll("allowzero "); |
| ... | @@ -1186,6 +1207,7 @@ pub const Type = extern union { | ... | @@ -1186,6 +1207,7 @@ pub const Type = extern union { |
| 1186 | .atomic_order, | 1207 | .atomic_order, |
| 1187 | .atomic_rmw_op, | 1208 | .atomic_rmw_op, |
| 1188 | .calling_convention, | 1209 | .calling_convention, |
| 1210 | .address_space, | ||
| 1189 | .float_mode, | 1211 | .float_mode, |
| 1190 | .reduce_op, | 1212 | .reduce_op, |
| 1191 | .call_options, | 1213 | .call_options, |
| ... | @@ -1301,6 +1323,7 @@ pub const Type = extern union { | ... | @@ -1301,6 +1323,7 @@ pub const Type = extern union { |
| 1301 | .atomic_order => return Value.initTag(.atomic_order_type), | 1323 | .atomic_order => return Value.initTag(.atomic_order_type), |
| 1302 | .atomic_rmw_op => return Value.initTag(.atomic_rmw_op_type), | 1324 | .atomic_rmw_op => return Value.initTag(.atomic_rmw_op_type), |
| 1303 | .calling_convention => return Value.initTag(.calling_convention_type), | 1325 | .calling_convention => return Value.initTag(.calling_convention_type), |
| 1326 | .address_space => return Value.initTag(.address_space_type), | ||
| 1304 | .float_mode => return Value.initTag(.float_mode_type), | 1327 | .float_mode => return Value.initTag(.float_mode_type), |
| 1305 | .reduce_op => return Value.initTag(.reduce_op_type), | 1328 | .reduce_op => return Value.initTag(.reduce_op_type), |
| 1306 | .call_options => return Value.initTag(.call_options_type), | 1329 | .call_options => return Value.initTag(.call_options_type), |
| ... | @@ -1362,6 +1385,7 @@ pub const Type = extern union { | ... | @@ -1362,6 +1385,7 @@ pub const Type = extern union { |
| 1362 | .atomic_order, | 1385 | .atomic_order, |
| 1363 | .atomic_rmw_op, | 1386 | .atomic_rmw_op, |
| 1364 | .calling_convention, | 1387 | .calling_convention, |
| 1388 | .address_space, | ||
| 1365 | .float_mode, | 1389 | .float_mode, |
| 1366 | .reduce_op, | 1390 | .reduce_op, |
| 1367 | .call_options, | 1391 | .call_options, |
| ... | @@ -1496,6 +1520,30 @@ pub const Type = extern union { | ... | @@ -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 | /// Asserts that hasCodeGenBits() is true. | 1547 | /// Asserts that hasCodeGenBits() is true. |
| 1500 | pub fn abiAlignment(self: Type, target: Target) u32 { | 1548 | pub fn abiAlignment(self: Type, target: Target) u32 { |
| 1501 | return switch (self.tag()) { | 1549 | return switch (self.tag()) { |
| ... | @@ -1508,6 +1556,7 @@ pub const Type = extern union { | ... | @@ -1508,6 +1556,7 @@ pub const Type = extern union { |
| 1508 | .atomic_order, | 1556 | .atomic_order, |
| 1509 | .atomic_rmw_op, | 1557 | .atomic_rmw_op, |
| 1510 | .calling_convention, | 1558 | .calling_convention, |
| 1559 | .address_space, | ||
| 1511 | .float_mode, | 1560 | .float_mode, |
| 1512 | .reduce_op, | 1561 | .reduce_op, |
| 1513 | .call_options, | 1562 | .call_options, |
| ... | @@ -1734,6 +1783,7 @@ pub const Type = extern union { | ... | @@ -1734,6 +1783,7 @@ pub const Type = extern union { |
| 1734 | .atomic_order, | 1783 | .atomic_order, |
| 1735 | .atomic_rmw_op, | 1784 | .atomic_rmw_op, |
| 1736 | .calling_convention, | 1785 | .calling_convention, |
| 1786 | .address_space, | ||
| 1737 | .float_mode, | 1787 | .float_mode, |
| 1738 | .reduce_op, | 1788 | .reduce_op, |
| 1739 | .call_options, | 1789 | .call_options, |
| ... | @@ -2019,6 +2069,7 @@ pub const Type = extern union { | ... | @@ -2019,6 +2069,7 @@ pub const Type = extern union { |
| 2019 | .atomic_order, | 2069 | .atomic_order, |
| 2020 | .atomic_rmw_op, | 2070 | .atomic_rmw_op, |
| 2021 | .calling_convention, | 2071 | .calling_convention, |
| 2072 | .address_space, | ||
| 2022 | .float_mode, | 2073 | .float_mode, |
| 2023 | .reduce_op, | 2074 | .reduce_op, |
| 2024 | .call_options, | 2075 | .call_options, |
| ... | @@ -2105,42 +2156,82 @@ pub const Type = extern union { | ... | @@ -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 | switch (self.tag()) { | 2165 | switch (self.tag()) { |
| 2110 | .const_slice_u8 => return Type.initTag(.manyptr_const_u8), | 2166 | .const_slice_u8 => return Type.initTag(.manyptr_const_u8), |
| 2111 | 2167 | ||
| 2112 | .const_slice => { | 2168 | .const_slice => { |
| 2113 | const elem_type = self.castTag(.const_slice).?.data; | 2169 | const elem_type = self.castTag(.const_slice).?.data; |
| 2114 | buffer.* = .{ | 2170 | buffer.* = .{ |
| 2115 | .base = .{ .tag = .many_const_pointer }, | 2171 | .elem_type = .{ |
| 2116 | .data = 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 | .mut_slice => { | 2178 | .mut_slice => { |
| 2121 | const elem_type = self.castTag(.mut_slice).?.data; | 2179 | const elem_type = self.castTag(.mut_slice).?.data; |
| 2122 | buffer.* = .{ | 2180 | buffer.* = .{ |
| 2123 | .base = .{ .tag = .many_mut_pointer }, | 2181 | .elem_type = .{ |
| 2124 | .data = 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 | .pointer => { | 2189 | .pointer => { |
| 2130 | const payload = self.castTag(.pointer).?.data; | 2190 | const payload = self.castTag(.pointer).?.data; |
| 2131 | assert(payload.size == .Slice); | 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 | buffer.* = .{ | 2201 | buffer.* = .{ |
| 2134 | .base = .{ .tag = .many_mut_pointer }, | 2202 | .pointer = .{ |
| 2135 | .data = payload.pointee_type, | 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 | } else { | 2226 | } else { |
| 2138 | buffer.* = .{ | 2227 | buffer.* = .{ |
| 2139 | .base = .{ .tag = .many_const_pointer }, | 2228 | .elem_type = .{ |
| 2140 | .data = payload.pointee_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 | else => unreachable, | 2237 | else => unreachable, |
| ... | @@ -2793,6 +2884,7 @@ pub const Type = extern union { | ... | @@ -2793,6 +2884,7 @@ pub const Type = extern union { |
| 2793 | .atomic_order, | 2884 | .atomic_order, |
| 2794 | .atomic_rmw_op, | 2885 | .atomic_rmw_op, |
| 2795 | .calling_convention, | 2886 | .calling_convention, |
| 2887 | .address_space, | ||
| 2796 | .float_mode, | 2888 | .float_mode, |
| 2797 | .reduce_op, | 2889 | .reduce_op, |
| 2798 | .call_options, | 2890 | .call_options, |
| ... | @@ -3000,6 +3092,7 @@ pub const Type = extern union { | ... | @@ -3000,6 +3092,7 @@ pub const Type = extern union { |
| 3000 | .atomic_order, | 3092 | .atomic_order, |
| 3001 | .atomic_rmw_op, | 3093 | .atomic_rmw_op, |
| 3002 | .calling_convention, | 3094 | .calling_convention, |
| 3095 | .address_space, | ||
| 3003 | .float_mode, | 3096 | .float_mode, |
| 3004 | .reduce_op, | 3097 | .reduce_op, |
| 3005 | .call_options, | 3098 | .call_options, |
| ... | @@ -3024,6 +3117,7 @@ pub const Type = extern union { | ... | @@ -3024,6 +3117,7 @@ pub const Type = extern union { |
| 3024 | .atomic_order, | 3117 | .atomic_order, |
| 3025 | .atomic_rmw_op, | 3118 | .atomic_rmw_op, |
| 3026 | .calling_convention, | 3119 | .calling_convention, |
| 3120 | .address_space, | ||
| 3027 | .float_mode, | 3121 | .float_mode, |
| 3028 | .reduce_op, | 3122 | .reduce_op, |
| 3029 | .call_options, | 3123 | .call_options, |
| ... | @@ -3047,6 +3141,7 @@ pub const Type = extern union { | ... | @@ -3047,6 +3141,7 @@ pub const Type = extern union { |
| 3047 | .atomic_order, | 3141 | .atomic_order, |
| 3048 | .atomic_rmw_op, | 3142 | .atomic_rmw_op, |
| 3049 | .calling_convention, | 3143 | .calling_convention, |
| 3144 | .address_space, | ||
| 3050 | .float_mode, | 3145 | .float_mode, |
| 3051 | .reduce_op, | 3146 | .reduce_op, |
| 3052 | .call_options, | 3147 | .call_options, |
| ... | @@ -3100,6 +3195,7 @@ pub const Type = extern union { | ... | @@ -3100,6 +3195,7 @@ pub const Type = extern union { |
| 3100 | .atomic_order, | 3195 | .atomic_order, |
| 3101 | .atomic_rmw_op, | 3196 | .atomic_rmw_op, |
| 3102 | .calling_convention, | 3197 | .calling_convention, |
| 3198 | .address_space, | ||
| 3103 | .float_mode, | 3199 | .float_mode, |
| 3104 | .reduce_op, | 3200 | .reduce_op, |
| 3105 | .call_options, | 3201 | .call_options, |
| ... | @@ -3155,6 +3251,7 @@ pub const Type = extern union { | ... | @@ -3155,6 +3251,7 @@ pub const Type = extern union { |
| 3155 | .atomic_order, | 3251 | .atomic_order, |
| 3156 | .atomic_rmw_op, | 3252 | .atomic_rmw_op, |
| 3157 | .calling_convention, | 3253 | .calling_convention, |
| 3254 | .address_space, | ||
| 3158 | .float_mode, | 3255 | .float_mode, |
| 3159 | .reduce_op, | 3256 | .reduce_op, |
| 3160 | .call_options, | 3257 | .call_options, |
| ... | @@ -3192,6 +3289,7 @@ pub const Type = extern union { | ... | @@ -3192,6 +3289,7 @@ pub const Type = extern union { |
| 3192 | .atomic_order, | 3289 | .atomic_order, |
| 3193 | .atomic_rmw_op, | 3290 | .atomic_rmw_op, |
| 3194 | .calling_convention, | 3291 | .calling_convention, |
| 3292 | .address_space, | ||
| 3195 | .float_mode, | 3293 | .float_mode, |
| 3196 | .reduce_op, | 3294 | .reduce_op, |
| 3197 | .call_options, | 3295 | .call_options, |
| ... | @@ -3242,6 +3340,7 @@ pub const Type = extern union { | ... | @@ -3242,6 +3340,7 @@ pub const Type = extern union { |
| 3242 | .atomic_order, | 3340 | .atomic_order, |
| 3243 | .atomic_rmw_op, | 3341 | .atomic_rmw_op, |
| 3244 | .calling_convention, | 3342 | .calling_convention, |
| 3343 | .address_space, | ||
| 3245 | .float_mode, | 3344 | .float_mode, |
| 3246 | .reduce_op, | 3345 | .reduce_op, |
| 3247 | .call_options, | 3346 | .call_options, |
| ... | @@ -3302,6 +3401,7 @@ pub const Type = extern union { | ... | @@ -3302,6 +3401,7 @@ pub const Type = extern union { |
| 3302 | atomic_order, | 3401 | atomic_order, |
| 3303 | atomic_rmw_op, | 3402 | atomic_rmw_op, |
| 3304 | calling_convention, | 3403 | calling_convention, |
| 3404 | address_space, | ||
| 3305 | float_mode, | 3405 | float_mode, |
| 3306 | reduce_op, | 3406 | reduce_op, |
| 3307 | call_options, | 3407 | call_options, |
| ... | @@ -3425,6 +3525,7 @@ pub const Type = extern union { | ... | @@ -3425,6 +3525,7 @@ pub const Type = extern union { |
| 3425 | .atomic_order, | 3525 | .atomic_order, |
| 3426 | .atomic_rmw_op, | 3526 | .atomic_rmw_op, |
| 3427 | .calling_convention, | 3527 | .calling_convention, |
| 3528 | .address_space, | ||
| 3428 | .float_mode, | 3529 | .float_mode, |
| 3429 | .reduce_op, | 3530 | .reduce_op, |
| 3430 | .call_options, | 3531 | .call_options, |
| ... | @@ -3580,6 +3681,7 @@ pub const Type = extern union { | ... | @@ -3580,6 +3681,7 @@ pub const Type = extern union { |
| 3580 | sentinel: ?Value, | 3681 | sentinel: ?Value, |
| 3581 | /// If zero use pointee_type.AbiAlign() | 3682 | /// If zero use pointee_type.AbiAlign() |
| 3582 | @"align": u32, | 3683 | @"align": u32, |
| 3684 | @"addrspace": std.builtin.AddressSpace, | ||
| 3583 | bit_offset: u16, | 3685 | bit_offset: u16, |
| 3584 | host_size: u16, | 3686 | host_size: u16, |
| 3585 | @"allowzero": bool, | 3687 | @"allowzero": bool, |
src/value.zig+5| ... | @@ -63,6 +63,7 @@ pub const Value = extern union { | ... | @@ -63,6 +63,7 @@ pub const Value = extern union { |
| 63 | atomic_order_type, | 63 | atomic_order_type, |
| 64 | atomic_rmw_op_type, | 64 | atomic_rmw_op_type, |
| 65 | calling_convention_type, | 65 | calling_convention_type, |
| 66 | address_space_type, | ||
| 66 | float_mode_type, | 67 | float_mode_type, |
| 67 | reduce_op_type, | 68 | reduce_op_type, |
| 68 | call_options_type, | 69 | call_options_type, |
| ... | @@ -226,6 +227,7 @@ pub const Value = extern union { | ... | @@ -226,6 +227,7 @@ pub const Value = extern union { |
| 226 | .atomic_order_type, | 227 | .atomic_order_type, |
| 227 | .atomic_rmw_op_type, | 228 | .atomic_rmw_op_type, |
| 228 | .calling_convention_type, | 229 | .calling_convention_type, |
| 230 | .address_space_type, | ||
| 229 | .float_mode_type, | 231 | .float_mode_type, |
| 230 | .reduce_op_type, | 232 | .reduce_op_type, |
| 231 | .call_options_type, | 233 | .call_options_type, |
| ... | @@ -412,6 +414,7 @@ pub const Value = extern union { | ... | @@ -412,6 +414,7 @@ pub const Value = extern union { |
| 412 | .atomic_order_type, | 414 | .atomic_order_type, |
| 413 | .atomic_rmw_op_type, | 415 | .atomic_rmw_op_type, |
| 414 | .calling_convention_type, | 416 | .calling_convention_type, |
| 417 | .address_space_type, | ||
| 415 | .float_mode_type, | 418 | .float_mode_type, |
| 416 | .reduce_op_type, | 419 | .reduce_op_type, |
| 417 | .call_options_type, | 420 | .call_options_type, |
| ... | @@ -625,6 +628,7 @@ pub const Value = extern union { | ... | @@ -625,6 +628,7 @@ pub const Value = extern union { |
| 625 | .atomic_order_type => return out_stream.writeAll("std.builtin.AtomicOrder"), | 628 | .atomic_order_type => return out_stream.writeAll("std.builtin.AtomicOrder"), |
| 626 | .atomic_rmw_op_type => return out_stream.writeAll("std.builtin.AtomicRmwOp"), | 629 | .atomic_rmw_op_type => return out_stream.writeAll("std.builtin.AtomicRmwOp"), |
| 627 | .calling_convention_type => return out_stream.writeAll("std.builtin.CallingConvention"), | 630 | .calling_convention_type => return out_stream.writeAll("std.builtin.CallingConvention"), |
| 631 | .address_space_type => return out_stream.writeAll("std.builtin.AddressSpace"), | ||
| 628 | .float_mode_type => return out_stream.writeAll("std.builtin.FloatMode"), | 632 | .float_mode_type => return out_stream.writeAll("std.builtin.FloatMode"), |
| 629 | .reduce_op_type => return out_stream.writeAll("std.builtin.ReduceOp"), | 633 | .reduce_op_type => return out_stream.writeAll("std.builtin.ReduceOp"), |
| 630 | .call_options_type => return out_stream.writeAll("std.builtin.CallOptions"), | 634 | .call_options_type => return out_stream.writeAll("std.builtin.CallOptions"), |
| ... | @@ -792,6 +796,7 @@ pub const Value = extern union { | ... | @@ -792,6 +796,7 @@ pub const Value = extern union { |
| 792 | .atomic_order_type => Type.initTag(.atomic_order), | 796 | .atomic_order_type => Type.initTag(.atomic_order), |
| 793 | .atomic_rmw_op_type => Type.initTag(.atomic_rmw_op), | 797 | .atomic_rmw_op_type => Type.initTag(.atomic_rmw_op), |
| 794 | .calling_convention_type => Type.initTag(.calling_convention), | 798 | .calling_convention_type => Type.initTag(.calling_convention), |
| 799 | .address_space_type => Type.initTag(.address_space), | ||
| 795 | .float_mode_type => Type.initTag(.float_mode), | 800 | .float_mode_type => Type.initTag(.float_mode), |
| 796 | .reduce_op_type => Type.initTag(.reduce_op), | 801 | .reduce_op_type => Type.initTag(.reduce_op), |
| 797 | .call_options_type => Type.initTag(.call_options), | 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,6 +416,11 @@ ZIG_EXTERN_C LLVMTypeRef ZigLLVMTokenTypeInContext(LLVMContextRef context_ref) { |
| 416 | return wrap(Type::getTokenTy(*unwrap(context_ref))); | 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 | LLVMValueRef ZigLLVMBuildCall(LLVMBuilderRef B, LLVMValueRef Fn, LLVMValueRef *Args, | 424 | LLVMValueRef ZigLLVMBuildCall(LLVMBuilderRef B, LLVMValueRef Fn, LLVMValueRef *Args, |
| 420 | unsigned NumArgs, ZigLLVM_CallingConv CC, ZigLLVM_CallAttr attr, const char *Name) | 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,6 +65,9 @@ ZIG_EXTERN_C LLVMTargetMachineRef ZigLLVMCreateTargetMachine(LLVMTargetRef T, co |
| 65 | 65 | ||
| 66 | ZIG_EXTERN_C LLVMTypeRef ZigLLVMTokenTypeInContext(LLVMContextRef context_ref); | 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 | enum ZigLLVM_CallingConv { | 71 | enum ZigLLVM_CallingConv { |
| 69 | ZigLLVM_C = 0, | 72 | ZigLLVM_C = 0, |
| 70 | ZigLLVM_Fast = 8, | 73 | ZigLLVM_Fast = 8, |
test/behavior/type.zig+1| ... | @@ -137,6 +137,7 @@ test "@Type create slice with null sentinel" { | ... | @@ -137,6 +137,7 @@ test "@Type create slice with null sentinel" { |
| 137 | .is_volatile = false, | 137 | .is_volatile = false, |
| 138 | .is_allowzero = false, | 138 | .is_allowzero = false, |
| 139 | .alignment = 8, | 139 | .alignment = 8, |
| 140 | .address_space = .generic, | ||
| 140 | .child = *i32, | 141 | .child = *i32, |
| 141 | .sentinel = null, | 142 | .sentinel = null, |
| 142 | }, | 143 | }, |
test/cases.zig+12| ... | @@ -1807,4 +1807,16 @@ pub fn addCases(ctx: *TestContext) !void { | ... | @@ -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,6 +711,7 @@ pub fn addCases(ctx: *TestContext) !void { |
| 711 | \\ .is_const = false, | 711 | \\ .is_const = false, |
| 712 | \\ .is_volatile = false, | 712 | \\ .is_volatile = false, |
| 713 | \\ .alignment = 1, | 713 | \\ .alignment = 1, |
| 714 | \\ .address_space = .generic, | ||
| 714 | \\ .child = u8, | 715 | \\ .child = u8, |
| 715 | \\ .is_allowzero = false, | 716 | \\ .is_allowzero = false, |
| 716 | \\ .sentinel = 0, | 717 | \\ .sentinel = 0, |
| ... | @@ -720,6 +721,23 @@ pub fn addCases(ctx: *TestContext) !void { | ... | @@ -720,6 +721,23 @@ pub fn addCases(ctx: *TestContext) !void { |
| 720 | "tmp.zig:2:16: error: sentinels are only allowed on slices and unknown-length pointers", | 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 | ctx.testErrStage1("helpful return type error message", | 741 | ctx.testErrStage1("helpful return type error message", |
| 724 | \\export fn foo() u32 { | 742 | \\export fn foo() u32 { |
| 725 | \\ return error.Ohno; | 743 | \\ return error.Ohno; |
test/stage2/llvm.zig+180| ... | @@ -242,4 +242,184 @@ pub fn addCases(ctx: *TestContext) !void { | ... | @@ -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 | } |