authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-09-20 17:32:52-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-09-20 17:32:52-07:00
logf8b914fcf328b30f98d31bb6461c953e4b7a33a7
tree06b74c36e25e94c1a8a5e384d289ffd556fdd4a9
parentabc30f79489b68f6dc0ee4b408c63a8e783215d1
parent619260d94d68bdecdac649fa7b156dc8962a9889

Merge branch 'address-space' of Snektron/zig into Snektron-address-space

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,
903903
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};
168168
169/// This data structure is used by the Zig language code generation and
170/// therefore must be kept in sync with the compiler implementation.
171pub 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 and178/// 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.
171pub const SourceLocation = struct {180pub 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,
231241
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 we1027 // 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 rparen1037 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 we1069 // 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 rparen1079 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 };
28972933
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 };
29212958
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 };
29272969
...@@ -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 }
631631
632 /// FnProto <- KEYWORD_fn IDENTIFIER? LPAREN ParamDeclList RPAREN ByteAlign? LinkSection? CallConv? EXCLAMATIONMARK? TypeExpr632 /// 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;
635635
...@@ -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 }
652653
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 }
710713
711 /// VarDecl <- (KEYWORD_const / KEYWORD_var) IDENTIFIER (COLON TypeExpr)? ByteAlign? LinkSection? (EQUAL Expr)? SEMICOLON714 /// 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) orelse716 const mut_token = p.eatToken(.keyword_const) orelse
714 p.eatToken(.keyword_var) orelse717 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 /// PrefixTypeOp1445 /// PrefixTypeOp
1441 /// <- QUESTIONMARK1446 /// <- QUESTIONMARK
1442 /// / KEYWORD_anyframe MINUSRARROW1447 /// / 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 /// / ArrayTypeStart1450 /// / ArrayTypeStart
1446 /// SliceTypeStart <- LBRACKET (COLON Expr)? RBRACKET1451 /// SliceTypeStart <- LBRACKET (COLON Expr)? RBRACKET
1447 /// PtrTypeStart1452 /// 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 }
28812918
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 /// ParamDecl2928 /// ParamDecl
2883 /// <- (KEYWORD_noalias / KEYWORD_comptime)? (IDENTIFIER COLON)? ParamType2929 /// <- (KEYWORD_noalias / KEYWORD_comptime)? (IDENTIFIER COLON)? ParamType
2884 /// / DOT32930 /// / DOT3
...@@ -3011,6 +3057,7 @@ const Parser = struct {...@@ -3011,6 +3057,7 @@ const Parser = struct {
30113057
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" {
553test "zig fmt: pointer-to-one with modifiers" {557test "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" {
562test "zig fmt: pointer-to-many with modifiers" {566test "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" {
571test "zig fmt: sentinel pointer with modifiers" {575test "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" {
580test "zig fmt: c pointer with modifiers" {584test "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" {
589test "zig fmt: slice with modifiers" {593test "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" {
597test "zig fmt: sentinel slice with modifiers" {601test "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}
11311135
1136test "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
1132test "zig fmt: correctly space struct fields with doc comments" {1146test "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 }
799799
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
921929
922 const name_space = if (var_decl.ast.type_node == 0 and930 const name_space = if (var_decl.ast.type_node == 0 and
923 (var_decl.ast.align_node != 0 or931 (var_decl.ast.align_node != 0 or
932 var_decl.ast.addrspace_node != 0 or
924 var_decl.ast.section_node != 0 or933 var_decl.ast.section_node != 0 or
925 var_decl.ast.init_node != 0))934 var_decl.ast.init_node != 0))
926 Space.space935 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
930939
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 or942 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); // align957 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 }
14091443
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 };
1212
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);
23742380
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 }
23872393
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 else2404 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);
27152729
2716 const simple = ptr_info.ast.align_node == 0 and2730 const simple = ptr_info.ast.align_node == 0 and
2731 ptr_info.ast.addrspace_node == 0 and
2717 ptr_info.ast.sentinel == 0 and2732 ptr_info.ast.sentinel == 0 and
2718 ptr_info.ast.bit_range_start == 0;2733 ptr_info.ast.bit_range_start == 0;
27192734
...@@ -2732,6 +2747,7 @@ fn ptrType(...@@ -2732,6 +2747,7 @@ fn ptrType(
27322747
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 }
28632887
...@@ -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);
29262951
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);
31143142
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}
31343164
...@@ -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);
31823216
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);
32583292
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}
32783313
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 associated358 /// 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 additionally359 /// 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 it375 /// 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 }
494496
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 }
502512
...@@ -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 Decl3233 // 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(
35263556
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
35313561
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;
35543584
3555 // zig fmt: off3585 // 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: on3590 // zig fmt: on
35613591
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
4384pub 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 bug4420 // TODO stage1 type inference bug
4338 const T = Type.Tag;4421 const T = Type.Tag;
43394422
...@@ -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}
43544437
4355pub 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
4383pub fn optionalType(arena: *Allocator, child_type: Type) Allocator.Error!Type {4438pub 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();
47144769
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 }
13751375
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}
13791385
...@@ -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);
15991617
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;
16041628
...@@ -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 }
36593703
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 );
36623712
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()});
37743824
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 );
37773833
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;
69136970
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 situation8681 // 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 former8683 // 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);
87908883
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;
87938887
8794 const field_index = struct_obj.fields.getIndex(field_name) orelse8888 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 );
87988898
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);
88878987
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;
88908991
...@@ -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);
88938994
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 );
88969003
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 error9005 // 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 else9180 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 );
90759185
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;
91659276
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 }
92999410
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 or9415 const ok_sent = dest_info.sentinel == null or src_info.size == .C or
9301 (src_info.sentinel != null and9416 (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 }
96189733
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);
96249740
...@@ -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 alignment9897 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 );
1096411090
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
11107pub 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
11124pub 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 };
23622368
2363 /// Stored in extra. Depending on the flags in Data, there will be up to 42369 /// 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 set2371 /// 0. sentinel: Ref // if `has_sentinel` flag is set
2366 /// 1. align: Ref // if `has_align` flag is set2372 /// 1. align: Ref // if `has_align` flag is set
2367 /// 2. bit_start: Ref // if `has_bit_range` flag is set2373 /// 2. address_space: Ref // if `has_addrspace` flag is set
2368 /// 3. bit_end: Ref // if `has_bit_range` flag is set2374 /// 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 pub2490 /// 0b000X: whether corresponding decl is pub
2484 /// 0b00X0: whether corresponding decl is exported2491 /// 0b00X0: whether corresponding decl is exported
2485 /// 0b0X00: whether corresponding decl has an align expression2492 /// 0b0X00: whether corresponding decl has an align expression
2486 /// 0bX000: whether corresponding decl has a linksection expression2493 /// 0bX000: whether corresponding decl has a linksection or an address space expression
2487 /// 5. decl: { // for every decls_len2494 /// 5. decl: { // for every decls_len
2488 /// src_hash: [4]u32, // hash of source bytes2495 /// src_hash: [4]u32, // hash of source bytes
2489 /// line: u32, // line number of decl, relative to parent2496 /// 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 set2504 /// align: Ref, // if corresponding bit is set
2498 /// link_section: Ref, // if corresponding bit is set2505 /// 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_len2510 /// 6. inst: Index // for every body_len
2501 /// 7. flags: u32 // for every 8 fields2511 /// 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 pub2557 /// 0b000X: whether corresponding decl is pub
2548 /// 0b00X0: whether corresponding decl is exported2558 /// 0b00X0: whether corresponding decl is exported
2549 /// 0b0X00: whether corresponding decl has an align expression2559 /// 0b0X00: whether corresponding decl has an align expression
2550 /// 0bX000: whether corresponding decl has a linksection expression2560 /// 0bX000: whether corresponding decl has a linksection or an address space expression
2551 /// 6. decl: { // for every decls_len2561 /// 6. decl: { // for every decls_len
2552 /// src_hash: [4]u32, // hash of source bytes2562 /// src_hash: [4]u32, // hash of source bytes
2553 /// line: u32, // line number of decl, relative to parent2563 /// 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 set2571 /// align: Ref, // if corresponding bit is set
2562 /// link_section: Ref, // if corresponding bit is set2572 /// 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_len2577 /// 7. inst: Index // for every body_len
2565 /// 8. has_bits: u32 // for every 32 fields2578 /// 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 pub2605 /// 0b000X: whether corresponding decl is pub
2593 /// 0b00X0: whether corresponding decl is exported2606 /// 0b00X0: whether corresponding decl is exported
2594 /// 0b0X00: whether corresponding decl has an align expression2607 /// 0b0X00: whether corresponding decl has an align expression
2595 /// 0bX000: whether corresponding decl has a linksection expression2608 /// 0bX000: whether corresponding decl has a linksection or an address space expression
2596 /// 6. decl: { // for every decls_len2609 /// 6. decl: { // for every decls_len
2597 /// src_hash: [4]u32, // hash of source bytes2610 /// src_hash: [4]u32, // hash of source bytes
2598 /// line: u32, // line number of decl, relative to parent2611 /// 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 set2619 /// align: Ref, // if corresponding bit is set
2607 /// link_section: Ref, // if corresponding bit is set2620 /// 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_len2625 /// 7. inst: Index // for every body_len
2610 /// 8. has_bits: u32 // for every 8 fields2626 /// 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 pub2657 /// 0b000X: whether corresponding decl is pub
2642 /// 0b00X0: whether corresponding decl is exported2658 /// 0b00X0: whether corresponding decl is exported
2643 /// 0b0X00: whether corresponding decl has an align expression2659 /// 0b0X00: whether corresponding decl has an align expression
2644 /// 0bX000: whether corresponding decl has a linksection expression2660 /// 0bX000: whether corresponding decl has a linksection or an address space expression
2645 /// 1. decl: { // for every decls_len2661 /// 1. decl: { // for every decls_len
2646 /// src_hash: [4]u32, // hash of source bytes2662 /// src_hash: [4]u32, // hash of source bytes
2647 /// line: u32, // line number of decl, relative to parent2663 /// 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 set2671 /// align: Ref, // if corresponding bit is set
2656 /// link_section: Ref, // if corresponding bit is set2672 /// 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);
562563
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 }
585603
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);
614632
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;
199199
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;
202205
...@@ -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;
211214
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;
214220
...@@ -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
1015pub 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;
11521152
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 CallingConventionSysV86 CallingConventionSysV
87};87};
8888
89// Stage 1 supports only the generic address space
90enum 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.
90enum BuiltinPtrSize {98enum 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}
10211021
1022const 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
1022ZigType *get_stack_trace_type(CodeGen *g) {1032ZigType *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);
242bool calling_convention_allows_zig_types(CallingConvention cc);242bool calling_convention_allows_zig_types(CallingConvention cc);
243const char *calling_convention_name(CallingConvention cc);243const char *calling_convention_name(CallingConvention cc);
244244
245const char *address_space_name(AddressSpace as);
246
245Error ATTRIBUTE_MUST_USE file_fetch(CodeGen *g, Buf *resolved_path, Buf *contents);247Error ATTRIBUTE_MUST_USE file_fetch(CodeGen *g, Buf *resolved_path, Buf *contents);
246248
247void walk_function_params(CodeGen *g, ZigType *fn_type, FnWalk *fn_walk);249void 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,
1612416124
16125static Stage1AirInst *ir_analyze_instruction_ctz(IrAnalyze *ira, Stage1ZirInstCtz *instruction) {16125static 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
1620016200
16201static Stage1AirInst *ir_analyze_instruction_clz(IrAnalyze *ira, Stage1ZirInstClz *instruction) {16201static 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
1627616276
16277static Stage1AirInst *ir_analyze_instruction_pop_count(IrAnalyze *ira, Stage1ZirInstPopCount *instruction) {16277static 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;
1790617906
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;
1790917909
17910 // size: Size17910 // 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: type17942 // 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: bool17947 // 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: anytype17952 // 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 }
1796117966
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);
1846718472
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;
1847018475
18471 // calling_convention: TypeInfo.CallingConvention18476 // 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;
1884718852
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 }
1885818876
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 }
1886518883
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
548pub 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;
464479
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 }
14981522
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 }
21072158
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),
21112167
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 },
21282188
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 },
21452236
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}
418418
419LLVMValueRef 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
419LLVMValueRef ZigLLVMBuildCall(LLVMBuilderRef B, LLVMValueRef Fn, LLVMValueRef *Args,424LLVMValueRef 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
6565
66ZIG_EXTERN_C LLVMTypeRef ZigLLVMTokenTypeInContext(LLVMContextRef context_ref);66ZIG_EXTERN_C LLVMTypeRef ZigLLVMTokenTypeInContext(LLVMContextRef context_ref);
6767
68ZIG_EXTERN_C LLVMValueRef ZigLLVMAddFunctionInAddressSpace(LLVMModuleRef M, const char *Name,
69 LLVMTypeRef FunctionTy, unsigned AddressSpace);
70
68enum ZigLLVM_CallingConv {71enum 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 });
722723
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}