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(
901901 switch (token.tag) {
902902 .eof => break,
903903
904 .keyword_addrspace,
904905 .keyword_align,
905906 .keyword_and,
906907 .keyword_asm,
lib/std/builtin.zig+10
......@@ -166,6 +166,15 @@ pub const CallingConvention = enum {
166166 SysV,
167167};
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
169178/// This data structure is used by the Zig language code generation and
170179/// therefore must be kept in sync with the compiler implementation.
171180pub const SourceLocation = struct {
......@@ -226,6 +235,7 @@ pub const TypeInfo = union(enum) {
226235 is_const: bool,
227236 is_volatile: bool,
228237 alignment: comptime_int,
238 address_space: AddressSpace,
229239 child: type,
230240 is_allowzero: bool,
231241
lib/std/mem.zig+2
......@@ -2472,6 +2472,7 @@ fn CopyPtrAttrs(comptime source: type, comptime size: std.builtin.TypeInfo.Point
24722472 .is_volatile = info.is_volatile,
24732473 .is_allowzero = info.is_allowzero,
24742474 .alignment = info.alignment,
2475 .address_space = info.address_space,
24752476 .child = child,
24762477 .sentinel = null,
24772478 },
......@@ -2960,6 +2961,7 @@ fn AlignedSlice(comptime AttributeSource: type, comptime new_alignment: u29) typ
29602961 .is_volatile = info.is_volatile,
29612962 .is_allowzero = info.is_allowzero,
29622963 .alignment = new_alignment,
2964 .address_space = info.address_space,
29632965 .child = info.child,
29642966 .sentinel = null,
29652967 },
lib/std/meta.zig+3
......@@ -235,6 +235,7 @@ pub fn Sentinel(comptime T: type, comptime sentinel_val: Elem(T)) type {
235235 .is_const = info.is_const,
236236 .is_volatile = info.is_volatile,
237237 .alignment = info.alignment,
238 .address_space = info.address_space,
238239 .child = @Type(.{
239240 .Array = .{
240241 .len = array_info.len,
......@@ -254,6 +255,7 @@ pub fn Sentinel(comptime T: type, comptime sentinel_val: Elem(T)) type {
254255 .is_const = info.is_const,
255256 .is_volatile = info.is_volatile,
256257 .alignment = info.alignment,
258 .address_space = info.address_space,
257259 .child = info.child,
258260 .is_allowzero = info.is_allowzero,
259261 .sentinel = sentinel_val,
......@@ -271,6 +273,7 @@ pub fn Sentinel(comptime T: type, comptime sentinel_val: Elem(T)) type {
271273 .is_const = ptr_info.is_const,
272274 .is_volatile = ptr_info.is_volatile,
273275 .alignment = ptr_info.alignment,
276 .address_space = ptr_info.address_space,
274277 .child = ptr_info.child,
275278 .is_allowzero = ptr_info.is_allowzero,
276279 .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 {
262262 token_tags[parse_error.token].symbol(),
263263 });
264264 },
265 .extra_addrspace_qualifier => {
266 return stream.writeAll("extra addrspace qualifier");
267 },
265268 .extra_align_qualifier => {
266269 return stream.writeAll("extra align qualifier");
267270 },
......@@ -1021,7 +1024,7 @@ pub fn lastToken(tree: Tree, node: Node.Index) TokenIndex {
10211024 },
10221025 .fn_proto_one => {
10231026 const extra = tree.extraData(datas[n].lhs, Node.FnProtoOne);
1024 // linksection, callconv, align can appear in any order, so we
1027 // addrspace, linksection, callconv, align can appear in any order, so we
10251028 // find the last one here.
10261029 var max_node: Node.Index = datas[n].rhs;
10271030 var max_start = token_starts[main_tokens[max_node]];
......@@ -1034,6 +1037,14 @@ pub fn lastToken(tree: Tree, node: Node.Index) TokenIndex {
10341037 max_offset = 1; // for the rparen
10351038 }
10361039 }
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 }
10371048 if (extra.section_expr != 0) {
10381049 const start = token_starts[main_tokens[extra.section_expr]];
10391050 if (start > max_start) {
......@@ -1055,7 +1066,7 @@ pub fn lastToken(tree: Tree, node: Node.Index) TokenIndex {
10551066 },
10561067 .fn_proto => {
10571068 const extra = tree.extraData(datas[n].lhs, Node.FnProto);
1058 // linksection, callconv, align can appear in any order, so we
1069 // addrspace, linksection, callconv, align can appear in any order, so we
10591070 // find the last one here.
10601071 var max_node: Node.Index = datas[n].rhs;
10611072 var max_start = token_starts[main_tokens[max_node]];
......@@ -1068,6 +1079,14 @@ pub fn lastToken(tree: Tree, node: Node.Index) TokenIndex {
10681079 max_offset = 1; // for the rparen
10691080 }
10701081 }
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 }
10711090 if (extra.section_expr != 0) {
10721091 const start = token_starts[main_tokens[extra.section_expr]];
10731092 if (start > max_start) {
......@@ -1138,6 +1157,7 @@ pub fn globalVarDecl(tree: Tree, node: Node.Index) full.VarDecl {
11381157 return tree.fullVarDecl(.{
11391158 .type_node = extra.type_node,
11401159 .align_node = extra.align_node,
1160 .addrspace_node = extra.addrspace_node,
11411161 .section_node = extra.section_node,
11421162 .init_node = data.rhs,
11431163 .mut_token = tree.nodes.items(.main_token)[node],
......@@ -1151,6 +1171,7 @@ pub fn localVarDecl(tree: Tree, node: Node.Index) full.VarDecl {
11511171 return tree.fullVarDecl(.{
11521172 .type_node = extra.type_node,
11531173 .align_node = extra.align_node,
1174 .addrspace_node = 0,
11541175 .section_node = 0,
11551176 .init_node = data.rhs,
11561177 .mut_token = tree.nodes.items(.main_token)[node],
......@@ -1163,6 +1184,7 @@ pub fn simpleVarDecl(tree: Tree, node: Node.Index) full.VarDecl {
11631184 return tree.fullVarDecl(.{
11641185 .type_node = data.lhs,
11651186 .align_node = 0,
1187 .addrspace_node = 0,
11661188 .section_node = 0,
11671189 .init_node = data.rhs,
11681190 .mut_token = tree.nodes.items(.main_token)[node],
......@@ -1175,6 +1197,7 @@ pub fn alignedVarDecl(tree: Tree, node: Node.Index) full.VarDecl {
11751197 return tree.fullVarDecl(.{
11761198 .type_node = 0,
11771199 .align_node = data.lhs,
1200 .addrspace_node = 0,
11781201 .section_node = 0,
11791202 .init_node = data.rhs,
11801203 .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.
12491272 .return_type = data.rhs,
12501273 .params = params,
12511274 .align_expr = 0,
1275 .addrspace_expr = 0,
12521276 .section_expr = 0,
12531277 .callconv_expr = 0,
12541278 });
......@@ -1265,6 +1289,7 @@ pub fn fnProtoMulti(tree: Tree, node: Node.Index) full.FnProto {
12651289 .return_type = data.rhs,
12661290 .params = params,
12671291 .align_expr = 0,
1292 .addrspace_expr = 0,
12681293 .section_expr = 0,
12691294 .callconv_expr = 0,
12701295 });
......@@ -1282,6 +1307,7 @@ pub fn fnProtoOne(tree: Tree, buffer: *[1]Node.Index, node: Node.Index) full.FnP
12821307 .return_type = data.rhs,
12831308 .params = params,
12841309 .align_expr = extra.align_expr,
1310 .addrspace_expr = extra.addrspace_expr,
12851311 .section_expr = extra.section_expr,
12861312 .callconv_expr = extra.callconv_expr,
12871313 });
......@@ -1298,6 +1324,7 @@ pub fn fnProto(tree: Tree, node: Node.Index) full.FnProto {
12981324 .return_type = data.rhs,
12991325 .params = params,
13001326 .align_expr = extra.align_expr,
1327 .addrspace_expr = extra.addrspace_expr,
13011328 .section_expr = extra.section_expr,
13021329 .callconv_expr = extra.callconv_expr,
13031330 });
......@@ -1453,6 +1480,7 @@ pub fn ptrTypeAligned(tree: Tree, node: Node.Index) full.PtrType {
14531480 return tree.fullPtrType(.{
14541481 .main_token = tree.nodes.items(.main_token)[node],
14551482 .align_node = data.lhs,
1483 .addrspace_node = 0,
14561484 .sentinel = 0,
14571485 .bit_range_start = 0,
14581486 .bit_range_end = 0,
......@@ -1466,6 +1494,7 @@ pub fn ptrTypeSentinel(tree: Tree, node: Node.Index) full.PtrType {
14661494 return tree.fullPtrType(.{
14671495 .main_token = tree.nodes.items(.main_token)[node],
14681496 .align_node = 0,
1497 .addrspace_node = 0,
14691498 .sentinel = data.lhs,
14701499 .bit_range_start = 0,
14711500 .bit_range_end = 0,
......@@ -1480,6 +1509,7 @@ pub fn ptrType(tree: Tree, node: Node.Index) full.PtrType {
14801509 return tree.fullPtrType(.{
14811510 .main_token = tree.nodes.items(.main_token)[node],
14821511 .align_node = extra.align_node,
1512 .addrspace_node = extra.addrspace_node,
14831513 .sentinel = extra.sentinel,
14841514 .bit_range_start = 0,
14851515 .bit_range_end = 0,
......@@ -1494,6 +1524,7 @@ pub fn ptrTypeBitRange(tree: Tree, node: Node.Index) full.PtrType {
14941524 return tree.fullPtrType(.{
14951525 .main_token = tree.nodes.items(.main_token)[node],
14961526 .align_node = extra.align_node,
1527 .addrspace_node = extra.addrspace_node,
14971528 .sentinel = extra.sentinel,
14981529 .bit_range_start = extra.bit_range_start,
14991530 .bit_range_end = extra.bit_range_end,
......@@ -2063,6 +2094,7 @@ pub const full = struct {
20632094 mut_token: TokenIndex,
20642095 type_node: Node.Index,
20652096 align_node: Node.Index,
2097 addrspace_node: Node.Index,
20662098 section_node: Node.Index,
20672099 init_node: Node.Index,
20682100 };
......@@ -2130,6 +2162,7 @@ pub const full = struct {
21302162 return_type: Node.Index,
21312163 params: []const Node.Index,
21322164 align_expr: Node.Index,
2165 addrspace_expr: Node.Index,
21332166 section_expr: Node.Index,
21342167 callconv_expr: Node.Index,
21352168 };
......@@ -2288,6 +2321,7 @@ pub const full = struct {
22882321 pub const Components = struct {
22892322 main_token: TokenIndex,
22902323 align_node: Node.Index,
2324 addrspace_node: Node.Index,
22912325 sentinel: Node.Index,
22922326 bit_range_start: Node.Index,
22932327 bit_range_end: Node.Index,
......@@ -2397,6 +2431,7 @@ pub const Error = struct {
23972431 expected_var_decl_or_fn,
23982432 expected_loop_payload,
23992433 expected_container,
2434 extra_addrspace_qualifier,
24002435 extra_align_qualifier,
24012436 extra_allowzero_qualifier,
24022437 extra_const_qualifier,
......@@ -2723,13 +2758,13 @@ pub const Node = struct {
27232758 /// main_token is the `fn` keyword.
27242759 /// extern function declarations use this tag.
27252760 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]`.
27272762 /// zero or one parameters.
27282763 /// anytype and ... parameters are omitted from the AST tree.
27292764 /// main_token is the `fn` keyword.
27302765 /// extern function declarations use this tag.
27312766 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]`.
27332768 /// anytype and ... parameters are omitted from the AST tree.
27342769 /// main_token is the `fn` keyword.
27352770 /// extern function declarations use this tag.
......@@ -2893,11 +2928,13 @@ pub const Node = struct {
28932928 pub const PtrType = struct {
28942929 sentinel: Index,
28952930 align_node: Index,
2931 addrspace_node: Index,
28962932 };
28972933
28982934 pub const PtrTypeBitRange = struct {
28992935 sentinel: Index,
29002936 align_node: Index,
2937 addrspace_node: Index,
29012938 bit_range_start: Index,
29022939 bit_range_end: Index,
29032940 };
......@@ -2920,8 +2957,13 @@ pub const Node = struct {
29202957 };
29212958
29222959 pub const GlobalVarDecl = struct {
2960 /// Populated if there is an explicit type ascription.
29232961 type_node: Index,
2962 /// Populated if align(A) is present.
29242963 align_node: Index,
2964 /// Populated if addrspace(A) is present.
2965 addrspace_node: Index,
2966 /// Populated if linksection(A) is present.
29252967 section_node: Index,
29262968 };
29272969
......@@ -2953,6 +2995,8 @@ pub const Node = struct {
29532995 param: Index,
29542996 /// Populated if align(A) is present.
29552997 align_expr: Index,
2998 /// Populated if addrspace(A) is present.
2999 addrspace_expr: Index,
29563000 /// Populated if linksection(A) is present.
29573001 section_expr: Index,
29583002 /// Populated if callconv(A) is present.
......@@ -2964,6 +3008,8 @@ pub const Node = struct {
29643008 params_end: Index,
29653009 /// Populated if align(A) is present.
29663010 align_expr: Index,
3011 /// Populated if addrspace(A) is present.
3012 addrspace_expr: Index,
29673013 /// Populated if linksection(A) is present.
29683014 section_expr: Index,
29693015 /// 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 {
325325 .is_const = ptr.is_const,
326326 .is_volatile = ptr.is_volatile,
327327 .alignment = @alignOf(ElementType),
328 .address_space = .generic,
328329 .child = ElementType,
329330 .is_allowzero = true,
330331 .sentinel = null,
lib/std/zig/parse.zig+81-26
......@@ -629,7 +629,7 @@ const Parser = struct {
629629 };
630630 }
631631
632 /// FnProto <- KEYWORD_fn IDENTIFIER? LPAREN ParamDeclList RPAREN ByteAlign? LinkSection? CallConv? EXCLAMATIONMARK? TypeExpr
632 /// FnProto <- KEYWORD_fn IDENTIFIER? LPAREN ParamDeclList RPAREN ByteAlign? AddrSpace? LinkSection? CallConv? EXCLAMATIONMARK? TypeExpr
633633 fn parseFnProto(p: *Parser) !Node.Index {
634634 const fn_token = p.eatToken(.keyword_fn) orelse return null_node;
635635
......@@ -639,6 +639,7 @@ const Parser = struct {
639639 _ = p.eatToken(.identifier);
640640 const params = try p.parseParamDeclList();
641641 const align_expr = try p.parseByteAlign();
642 const addrspace_expr = try p.parseAddrSpace();
642643 const section_expr = try p.parseLinkSection();
643644 const callconv_expr = try p.parseCallconv();
644645 _ = p.eatToken(.bang);
......@@ -650,7 +651,7 @@ const Parser = struct {
650651 try p.warn(.expected_return_type);
651652 }
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) {
654655 switch (params) {
655656 .zero_or_one => |param| return p.setNode(fn_proto_index, .{
656657 .tag = .fn_proto_simple,
......@@ -683,6 +684,7 @@ const Parser = struct {
683684 .lhs = try p.addExtra(Node.FnProtoOne{
684685 .param = param,
685686 .align_expr = align_expr,
687 .addrspace_expr = addrspace_expr,
686688 .section_expr = section_expr,
687689 .callconv_expr = callconv_expr,
688690 }),
......@@ -698,6 +700,7 @@ const Parser = struct {
698700 .params_start = span.start,
699701 .params_end = span.end,
700702 .align_expr = align_expr,
703 .addrspace_expr = addrspace_expr,
701704 .section_expr = section_expr,
702705 .callconv_expr = callconv_expr,
703706 }),
......@@ -708,7 +711,7 @@ const Parser = struct {
708711 }
709712 }
710713
711 /// VarDecl <- (KEYWORD_const / KEYWORD_var) IDENTIFIER (COLON TypeExpr)? ByteAlign? LinkSection? (EQUAL Expr)? SEMICOLON
714 /// VarDecl <- (KEYWORD_const / KEYWORD_var) IDENTIFIER (COLON TypeExpr)? ByteAlign? AddrSpace? LinkSection? (EQUAL Expr)? SEMICOLON
712715 fn parseVarDecl(p: *Parser) !Node.Index {
713716 const mut_token = p.eatToken(.keyword_const) orelse
714717 p.eatToken(.keyword_var) orelse
......@@ -717,9 +720,10 @@ const Parser = struct {
717720 _ = try p.expectToken(.identifier);
718721 const type_node: Node.Index = if (p.eatToken(.colon) == null) 0 else try p.expectTypeExpr();
719722 const align_node = try p.parseByteAlign();
723 const addrspace_node = try p.parseAddrSpace();
720724 const section_node = try p.parseLinkSection();
721725 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) {
723727 if (align_node == 0) {
724728 return p.addNode(.{
725729 .tag = .simple_var_decl,
......@@ -759,6 +763,7 @@ const Parser = struct {
759763 .lhs = try p.addExtra(Node.GlobalVarDecl{
760764 .type_node = type_node,
761765 .align_node = align_node,
766 .addrspace_node = addrspace_node,
762767 .section_node = section_node,
763768 }),
764769 .rhs = init_node,
......@@ -1440,8 +1445,8 @@ const Parser = struct {
14401445 /// PrefixTypeOp
14411446 /// <- QUESTIONMARK
14421447 /// / KEYWORD_anyframe MINUSRARROW
1443 /// / SliceTypeStart (ByteAlign / KEYWORD_const / KEYWORD_volatile / KEYWORD_allowzero)*
1444 /// / PtrTypeStart (KEYWORD_align LPAREN Expr (COLON INTEGER COLON INTEGER)? RPAREN / KEYWORD_const / KEYWORD_volatile / KEYWORD_allowzero)*
1448 /// / SliceTypeStart (ByteAlign / AddrSpace / KEYWORD_const / KEYWORD_volatile / KEYWORD_allowzero)*
1449 /// / PtrTypeStart (AddrSpace / KEYWORD_align LPAREN Expr (COLON INTEGER COLON INTEGER)? RPAREN / KEYWORD_const / KEYWORD_volatile / KEYWORD_allowzero)*
14451450 /// / ArrayTypeStart
14461451 /// SliceTypeStart <- LBRACKET (COLON Expr)? RBRACKET
14471452 /// PtrTypeStart
......@@ -1474,29 +1479,43 @@ const Parser = struct {
14741479 const asterisk = p.nextToken();
14751480 const mods = try p.parsePtrModifiers();
14761481 const elem_type = try p.expectTypeExpr();
1477 if (mods.bit_range_start == 0) {
1482 if (mods.bit_range_start != 0) {
14781483 return p.addNode(.{
1479 .tag = .ptr_type_aligned,
1484 .tag = .ptr_type_bit_range,
14801485 .main_token = asterisk,
14811486 .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 }),
14831494 .rhs = elem_type,
14841495 },
14851496 });
1486 } else {
1497 } else if (mods.addrspace_node != 0) {
14871498 return p.addNode(.{
1488 .tag = .ptr_type_bit_range,
1499 .tag = .ptr_type,
14891500 .main_token = asterisk,
14901501 .data = .{
1491 .lhs = try p.addExtra(Node.PtrTypeBitRange{
1502 .lhs = try p.addExtra(Node.PtrType{
14921503 .sentinel = 0,
14931504 .align_node = mods.align_node,
1494 .bit_range_start = mods.bit_range_start,
1495 .bit_range_end = mods.bit_range_end,
1505 .addrspace_node = mods.addrspace_node,
14961506 }),
14971507 .rhs = elem_type,
14981508 },
14991509 });
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 });
15001519 }
15011520 },
15021521 .asterisk_asterisk => {
......@@ -1504,29 +1523,43 @@ const Parser = struct {
15041523 const mods = try p.parsePtrModifiers();
15051524 const elem_type = try p.expectTypeExpr();
15061525 const inner: Node.Index = inner: {
1507 if (mods.bit_range_start == 0) {
1526 if (mods.bit_range_start != 0) {
15081527 break :inner try p.addNode(.{
1509 .tag = .ptr_type_aligned,
1528 .tag = .ptr_type_bit_range,
15101529 .main_token = asterisk,
15111530 .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 }),
15131538 .rhs = elem_type,
15141539 },
15151540 });
1516 } else {
1541 } else if (mods.addrspace_node != 0) {
15171542 break :inner try p.addNode(.{
1518 .tag = .ptr_type_bit_range,
1543 .tag = .ptr_type,
15191544 .main_token = asterisk,
15201545 .data = .{
1521 .lhs = try p.addExtra(Node.PtrTypeBitRange{
1546 .lhs = try p.addExtra(Node.PtrType{
15221547 .sentinel = 0,
15231548 .align_node = mods.align_node,
1524 .bit_range_start = mods.bit_range_start,
1525 .bit_range_end = mods.bit_range_end,
1549 .addrspace_node = mods.addrspace_node,
15261550 }),
15271551 .rhs = elem_type,
15281552 },
15291553 });
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 });
15301563 }
15311564 };
15321565 return p.addNode(.{
......@@ -1560,7 +1593,7 @@ const Parser = struct {
15601593 const mods = try p.parsePtrModifiers();
15611594 const elem_type = try p.expectTypeExpr();
15621595 if (mods.bit_range_start == 0) {
1563 if (sentinel == 0) {
1596 if (sentinel == 0 and mods.addrspace_node == 0) {
15641597 return p.addNode(.{
15651598 .tag = .ptr_type_aligned,
15661599 .main_token = asterisk,
......@@ -1569,7 +1602,7 @@ const Parser = struct {
15691602 .rhs = elem_type,
15701603 },
15711604 });
1572 } else if (mods.align_node == 0) {
1605 } else if (mods.align_node == 0 and mods.addrspace_node == 0) {
15731606 return p.addNode(.{
15741607 .tag = .ptr_type_sentinel,
15751608 .main_token = asterisk,
......@@ -1586,6 +1619,7 @@ const Parser = struct {
15861619 .lhs = try p.addExtra(Node.PtrType{
15871620 .sentinel = sentinel,
15881621 .align_node = mods.align_node,
1622 .addrspace_node = mods.addrspace_node,
15891623 }),
15901624 .rhs = elem_type,
15911625 },
......@@ -1599,6 +1633,7 @@ const Parser = struct {
15991633 .lhs = try p.addExtra(Node.PtrTypeBitRange{
16001634 .sentinel = sentinel,
16011635 .align_node = mods.align_node,
1636 .addrspace_node = mods.addrspace_node,
16021637 .bit_range_start = mods.bit_range_start,
16031638 .bit_range_end = mods.bit_range_end,
16041639 }),
......@@ -1624,7 +1659,7 @@ const Parser = struct {
16241659 .token = p.nodes.items(.main_token)[mods.bit_range_start],
16251660 });
16261661 }
1627 if (sentinel == 0) {
1662 if (sentinel == 0 and mods.addrspace_node == 0) {
16281663 return p.addNode(.{
16291664 .tag = .ptr_type_aligned,
16301665 .main_token = lbracket,
......@@ -1633,7 +1668,7 @@ const Parser = struct {
16331668 .rhs = elem_type,
16341669 },
16351670 });
1636 } else if (mods.align_node == 0) {
1671 } else if (mods.align_node == 0 and mods.addrspace_node == 0) {
16371672 return p.addNode(.{
16381673 .tag = .ptr_type_sentinel,
16391674 .main_token = lbracket,
......@@ -1650,6 +1685,7 @@ const Parser = struct {
16501685 .lhs = try p.addExtra(Node.PtrType{
16511686 .sentinel = sentinel,
16521687 .align_node = mods.align_node,
1688 .addrspace_node = mods.addrspace_node,
16531689 }),
16541690 .rhs = elem_type,
16551691 },
......@@ -1661,6 +1697,7 @@ const Parser = struct {
16611697 .keyword_const,
16621698 .keyword_volatile,
16631699 .keyword_allowzero,
1700 .keyword_addrspace,
16641701 => return p.fail(.ptr_mod_on_array_child_type),
16651702 else => {},
16661703 }
......@@ -2879,6 +2916,15 @@ const Parser = struct {
28792916 return expr_node;
28802917 }
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
28822928 /// ParamDecl
28832929 /// <- (KEYWORD_noalias / KEYWORD_comptime)? (IDENTIFIER COLON)? ParamType
28842930 /// / DOT3
......@@ -3011,6 +3057,7 @@ const Parser = struct {
30113057
30123058 const PtrModifiers = struct {
30133059 align_node: Node.Index,
3060 addrspace_node: Node.Index,
30143061 bit_range_start: Node.Index,
30153062 bit_range_end: Node.Index,
30163063 };
......@@ -3018,12 +3065,14 @@ const Parser = struct {
30183065 fn parsePtrModifiers(p: *Parser) !PtrModifiers {
30193066 var result: PtrModifiers = .{
30203067 .align_node = 0,
3068 .addrspace_node = 0,
30213069 .bit_range_start = 0,
30223070 .bit_range_end = 0,
30233071 };
30243072 var saw_const = false;
30253073 var saw_volatile = false;
30263074 var saw_allowzero = false;
3075 var saw_addrspace = false;
30273076 while (true) {
30283077 switch (p.token_tags[p.tok_i]) {
30293078 .keyword_align => {
......@@ -3063,6 +3112,12 @@ const Parser = struct {
30633112 p.tok_i += 1;
30643113 saw_allowzero = true;
30653114 },
3115 .keyword_addrspace => {
3116 if (saw_addrspace) {
3117 try p.warn(.extra_addrspace_qualifier);
3118 }
3119 result.addrspace_node = try p.parseAddrSpace();
3120 },
30663121 else => return result,
30673122 }
30683123 }
lib/std/zig/parser_test.zig+24-10
......@@ -404,6 +404,10 @@ test "zig fmt: trailing comma in fn parameter list" {
404404 \\pub fn f(
405405 \\ a: i32,
406406 \\ b: i32,
407 \\) addrspace(.generic) i32 {}
408 \\pub fn f(
409 \\ a: i32,
410 \\ b: i32,
407411 \\) linksection(".text") i32 {}
408412 \\pub fn f(
409413 \\ a: i32,
......@@ -553,8 +557,8 @@ test "zig fmt: sentinel-terminated slice type" {
553557test "zig fmt: pointer-to-one with modifiers" {
554558 try testCanonical(
555559 \\const x: *u32 = undefined;
556 \\const y: *allowzero align(8) const volatile u32 = undefined;
557 \\const z: *allowzero align(8:4:2) const volatile u32 = undefined;
560 \\const y: *allowzero align(8) addrspace(.generic) const volatile u32 = undefined;
561 \\const z: *allowzero align(8:4:2) addrspace(.generic) const volatile u32 = undefined;
558562 \\
559563 );
560564}
......@@ -562,8 +566,8 @@ test "zig fmt: pointer-to-one with modifiers" {
562566test "zig fmt: pointer-to-many with modifiers" {
563567 try testCanonical(
564568 \\const x: [*]u32 = undefined;
565 \\const y: [*]allowzero align(8) const volatile u32 = undefined;
566 \\const z: [*]allowzero align(8:4:2) const volatile u32 = undefined;
569 \\const y: [*]allowzero align(8) addrspace(.generic) const volatile u32 = undefined;
570 \\const z: [*]allowzero align(8:4:2) addrspace(.generic) const volatile u32 = undefined;
567571 \\
568572 );
569573}
......@@ -571,8 +575,8 @@ test "zig fmt: pointer-to-many with modifiers" {
571575test "zig fmt: sentinel pointer with modifiers" {
572576 try testCanonical(
573577 \\const x: [*:42]u32 = undefined;
574 \\const y: [*:42]allowzero align(8) const volatile u32 = undefined;
575 \\const y: [*:42]allowzero align(8:4:2) const volatile u32 = undefined;
578 \\const y: [*:42]allowzero align(8) addrspace(.generic) const volatile u32 = undefined;
579 \\const y: [*:42]allowzero align(8:4:2) addrspace(.generic) const volatile u32 = undefined;
576580 \\
577581 );
578582}
......@@ -580,8 +584,8 @@ test "zig fmt: sentinel pointer with modifiers" {
580584test "zig fmt: c pointer with modifiers" {
581585 try testCanonical(
582586 \\const x: [*c]u32 = undefined;
583 \\const y: [*c]allowzero align(8) const volatile u32 = undefined;
584 \\const z: [*c]allowzero align(8:4:2) const volatile u32 = undefined;
587 \\const y: [*c]allowzero align(8) addrspace(.generic) const volatile u32 = undefined;
588 \\const z: [*c]allowzero align(8:4:2) addrspace(.generic) const volatile u32 = undefined;
585589 \\
586590 );
587591}
......@@ -589,7 +593,7 @@ test "zig fmt: c pointer with modifiers" {
589593test "zig fmt: slice with modifiers" {
590594 try testCanonical(
591595 \\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;
593597 \\
594598 );
595599}
......@@ -597,7 +601,7 @@ test "zig fmt: slice with modifiers" {
597601test "zig fmt: sentinel slice with modifiers" {
598602 try testCanonical(
599603 \\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;
601605 \\
602606 );
603607}
......@@ -1129,6 +1133,16 @@ test "zig fmt: linksection" {
11291133 );
11301134}
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
11321146test "zig fmt: correctly space struct fields with doc comments" {
11331147 try testTransform(
11341148 \\pub const S = struct {
lib/std/zig/render.zig+46-2
......@@ -797,6 +797,14 @@ fn renderPtrType(
797797 }
798798 }
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
800808 if (ptr_type.const_token) |const_token| {
801809 try renderToken(ais, tree, const_token, .space);
802810 }
......@@ -921,6 +929,7 @@ fn renderVarDecl(gpa: *Allocator, ais: *Ais, tree: Ast, var_decl: Ast.full.VarDe
921929
922930 const name_space = if (var_decl.ast.type_node == 0 and
923931 (var_decl.ast.align_node != 0 or
932 var_decl.ast.addrspace_node != 0 or
924933 var_decl.ast.section_node != 0 or
925934 var_decl.ast.init_node != 0))
926935 Space.space
......@@ -930,8 +939,8 @@ fn renderVarDecl(gpa: *Allocator, ais: *Ais, tree: Ast, var_decl: Ast.full.VarDe
930939
931940 if (var_decl.ast.type_node != 0) {
932941 try renderToken(ais, tree, var_decl.ast.mut_token + 2, Space.space); // :
933 if (var_decl.ast.align_node != 0 or var_decl.ast.section_node != 0 or
934 var_decl.ast.init_node != 0)
942 if (var_decl.ast.align_node != 0 or var_decl.ast.addrspace_node != 0 or
943 var_decl.ast.section_node != 0 or var_decl.ast.init_node != 0)
935944 {
936945 try renderExpression(gpa, ais, tree, var_decl.ast.type_node, .space);
937946 } else {
......@@ -948,6 +957,23 @@ fn renderVarDecl(gpa: *Allocator, ais: *Ais, tree: Ast, var_decl: Ast.full.VarDe
948957 try renderToken(ais, tree, align_kw, Space.none); // align
949958 try renderToken(ais, tree, lparen, Space.none); // (
950959 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);
951977 if (var_decl.ast.section_node != 0 or var_decl.ast.init_node != 0) {
952978 try renderToken(ais, tree, rparen, .space); // )
953979 } else {
......@@ -1267,6 +1293,14 @@ fn renderFnProto(gpa: *Allocator, ais: *Ais, tree: Ast, fn_proto: Ast.full.FnPro
12671293 smallest_start = start;
12681294 }
12691295 }
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 }
12701304 if (fn_proto.ast.section_expr != 0) {
12711305 const tok = tree.firstToken(fn_proto.ast.section_expr) - 3;
12721306 const start = token_starts[tok];
......@@ -1407,6 +1441,16 @@ fn renderFnProto(gpa: *Allocator, ais: *Ais, tree: Ast, fn_proto: Ast.full.FnPro
14071441 try renderToken(ais, tree, align_rparen, .space); // )
14081442 }
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
14101454 if (fn_proto.ast.section_expr != 0) {
14111455 const section_lparen = tree.firstToken(fn_proto.ast.section_expr) - 1;
14121456 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 {
1111 };
1212
1313 pub const keywords = std.ComptimeStringMap(Tag, .{
14 .{ "addrspace", .keyword_addrspace },
1415 .{ "align", .keyword_align },
1516 .{ "allowzero", .keyword_allowzero },
1617 .{ "and", .keyword_and },
......@@ -132,6 +133,7 @@ pub const Token = struct {
132133 float_literal,
133134 doc_comment,
134135 container_doc_comment,
136 keyword_addrspace,
135137 keyword_align,
136138 keyword_allowzero,
137139 keyword_and,
......@@ -251,6 +253,7 @@ pub const Token = struct {
251253 .angle_bracket_angle_bracket_right => ">>",
252254 .angle_bracket_angle_bracket_right_equal => ">>=",
253255 .tilde => "~",
256 .keyword_addrspace => "addrspace",
254257 .keyword_align => "align",
255258 .keyword_allowzero => "allowzero",
256259 .keyword_and => "and",
src/AstGen.zig+43-8
......@@ -1116,6 +1116,11 @@ fn fnProtoExpr(
11161116 const align_inst: Zir.Inst.Ref = if (fn_proto.ast.align_expr == 0) .none else inst: {
11171117 break :inst try expr(gz, scope, align_rl, fn_proto.ast.align_expr);
11181118 };
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
11191124 if (fn_proto.ast.section_expr != 0) {
11201125 return astgen.failNode(fn_proto.ast.section_expr, "linksection not allowed on function prototypes", .{});
11211126 }
......@@ -2371,6 +2376,7 @@ fn varDecl(
23712376 const gpa = astgen.gpa;
23722377 const tree = astgen.tree;
23732378 const token_tags = tree.tokens.items(.tag);
2379 const main_tokens = tree.nodes.items(.main_token);
23742380
23752381 const name_token = var_decl.ast.mut_token + 1;
23762382 const ident_name_raw = tree.tokenSlice(name_token);
......@@ -2385,6 +2391,14 @@ fn varDecl(
23852391 return astgen.failNode(node, "variables must be initialized", .{});
23862392 }
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
23882402 const align_inst: Zir.Inst.Ref = if (var_decl.ast.align_node != 0)
23892403 try expr(gz, scope, align_rl, var_decl.ast.align_node)
23902404 else
......@@ -2714,6 +2728,7 @@ fn ptrType(
27142728 const elem_type = try typeExpr(gz, scope, ptr_info.ast.child_type);
27152729
27162730 const simple = ptr_info.ast.align_node == 0 and
2731 ptr_info.ast.addrspace_node == 0 and
27172732 ptr_info.ast.sentinel == 0 and
27182733 ptr_info.ast.bit_range_start == 0;
27192734
......@@ -2732,6 +2747,7 @@ fn ptrType(
27322747
27332748 var sentinel_ref: Zir.Inst.Ref = .none;
27342749 var align_ref: Zir.Inst.Ref = .none;
2750 var addrspace_ref: Zir.Inst.Ref = .none;
27352751 var bit_start_ref: Zir.Inst.Ref = .none;
27362752 var bit_end_ref: Zir.Inst.Ref = .none;
27372753 var trailing_count: u32 = 0;
......@@ -2744,6 +2760,10 @@ fn ptrType(
27442760 align_ref = try expr(gz, scope, align_rl, ptr_info.ast.align_node);
27452761 trailing_count += 1;
27462762 }
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 }
27472767 if (ptr_info.ast.bit_range_start != 0) {
27482768 assert(ptr_info.ast.bit_range_end != 0);
27492769 bit_start_ref = try expr(gz, scope, .none, ptr_info.ast.bit_range_start);
......@@ -2764,6 +2784,9 @@ fn ptrType(
27642784 if (align_ref != .none) {
27652785 gz.astgen.extra.appendAssumeCapacity(@enumToInt(align_ref));
27662786 }
2787 if (addrspace_ref != .none) {
2788 gz.astgen.extra.appendAssumeCapacity(@enumToInt(addrspace_ref));
2789 }
27672790 if (bit_start_ref != .none) {
27682791 gz.astgen.extra.appendAssumeCapacity(@enumToInt(bit_start_ref));
27692792 gz.astgen.extra.appendAssumeCapacity(@enumToInt(bit_end_ref));
......@@ -2779,6 +2802,7 @@ fn ptrType(
27792802 .is_volatile = ptr_info.volatile_token != null,
27802803 .has_sentinel = sentinel_ref != .none,
27812804 .has_align = align_ref != .none,
2805 .has_addrspace = addrspace_ref != .none,
27822806 .has_bit_range = bit_start_ref != .none,
27832807 },
27842808 .size = ptr_info.size,
......@@ -2847,7 +2871,7 @@ const WipDecls = struct {
28472871 is_pub: bool,
28482872 is_export: bool,
28492873 has_align: bool,
2850 has_section: bool,
2874 has_section_or_addrspace: bool,
28512875 ) Allocator.Error!void {
28522876 if (wip_decls.decl_index % fields_per_u32 == 0 and wip_decls.decl_index != 0) {
28532877 try wip_decls.bit_bag.append(gpa, wip_decls.cur_bit_bag);
......@@ -2857,7 +2881,7 @@ const WipDecls = struct {
28572881 (@as(u32, @boolToInt(is_pub)) << 28) |
28582882 (@as(u32, @boolToInt(is_export)) << 29) |
28592883 (@as(u32, @boolToInt(has_align)) << 30) |
2860 (@as(u32, @boolToInt(has_section)) << 31);
2884 (@as(u32, @boolToInt(has_section_or_addrspace)) << 31);
28612885 wip_decls.decl_index += 1;
28622886 }
28632887
......@@ -2922,7 +2946,8 @@ fn fnDecl(
29222946 const maybe_inline_token = fn_proto.extern_export_inline_token orelse break :blk false;
29232947 break :blk token_tags[maybe_inline_token] == .keyword_inline;
29242948 };
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
29272952 var params_scope = &fn_gz.base;
29282953 const is_var_args = is_var_args: {
......@@ -3011,6 +3036,9 @@ fn fnDecl(
30113036 const align_inst: Zir.Inst.Ref = if (fn_proto.ast.align_expr == 0) .none else inst: {
30123037 break :inst try expr(&decl_gz, params_scope, align_rl, fn_proto.ast.align_expr);
30133038 };
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 };
30143042 const section_inst: Zir.Inst.Ref = if (fn_proto.ast.section_expr == 0) .none else inst: {
30153043 break :inst try comptimeExpr(&decl_gz, params_scope, .{ .ty = .const_slice_u8_type }, fn_proto.ast.section_expr);
30163044 };
......@@ -3112,7 +3140,7 @@ fn fnDecl(
31123140 _ = try decl_gz.addBreak(.break_inline, block_inst, func_inst);
31133141 try decl_gz.setBlockBody(block_inst);
31143142
3115 try wip_decls.payload.ensureUnusedCapacity(gpa, 9);
3143 try wip_decls.payload.ensureUnusedCapacity(gpa, 10);
31163144 {
31173145 const contents_hash = std.zig.hashSrc(tree.getNodeSource(decl_node));
31183146 const casted = @bitCast([4]u32, contents_hash);
......@@ -3127,8 +3155,10 @@ fn fnDecl(
31273155 if (align_inst != .none) {
31283156 wip_decls.payload.appendAssumeCapacity(@enumToInt(align_inst));
31293157 }
3130 if (section_inst != .none) {
3158
3159 if (has_section_or_addrspace) {
31313160 wip_decls.payload.appendAssumeCapacity(@enumToInt(section_inst));
3161 wip_decls.payload.appendAssumeCapacity(@enumToInt(addrspace_inst));
31323162 }
31333163}
31343164
......@@ -3175,10 +3205,14 @@ fn globalVarDecl(
31753205 const align_inst: Zir.Inst.Ref = if (var_decl.ast.align_node == 0) .none else inst: {
31763206 break :inst try expr(&block_scope, &block_scope.base, align_rl, var_decl.ast.align_node);
31773207 };
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 };
31783211 const section_inst: Zir.Inst.Ref = if (var_decl.ast.section_node == 0) .none else inst: {
31793212 break :inst try comptimeExpr(&block_scope, &block_scope.base, .{ .ty = .const_slice_u8_type }, var_decl.ast.section_node);
31803213 };
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
31833217 const is_threadlocal = if (var_decl.threadlocal_token) |tok| blk: {
31843218 if (!is_mutable) {
......@@ -3256,7 +3290,7 @@ fn globalVarDecl(
32563290 _ = try block_scope.addBreak(.break_inline, block_inst, var_inst);
32573291 try block_scope.setBlockBody(block_inst);
32583292
3259 try wip_decls.payload.ensureUnusedCapacity(gpa, 9);
3293 try wip_decls.payload.ensureUnusedCapacity(gpa, 10);
32603294 {
32613295 const contents_hash = std.zig.hashSrc(tree.getNodeSource(node));
32623296 const casted = @bitCast([4]u32, contents_hash);
......@@ -3271,8 +3305,9 @@ fn globalVarDecl(
32713305 if (align_inst != .none) {
32723306 wip_decls.payload.appendAssumeCapacity(@enumToInt(align_inst));
32733307 }
3274 if (section_inst != .none) {
3308 if (has_section_or_addrspace) {
32753309 wip_decls.payload.appendAssumeCapacity(@enumToInt(section_inst));
3310 wip_decls.payload.appendAssumeCapacity(@enumToInt(addrspace_inst));
32763311 }
32773312}
32783313
src/Module.zig+100-45
......@@ -288,6 +288,8 @@ pub const Decl = struct {
288288 align_val: Value,
289289 /// Populated when `has_tv`.
290290 linksection_val: Value,
291 /// Populated when `has_tv`.
292 @"addrspace": std.builtin.AddressSpace,
291293 /// The memory for ty, val, align_val, linksection_val.
292294 /// If this is `null` then there is no memory management needed.
293295 value_arena: ?*std.heap.ArenaAllocator.State = null,
......@@ -351,7 +353,7 @@ pub const Decl = struct {
351353 /// to require re-analysis.
352354 outdated,
353355 },
354 /// Whether `typed_value`, `align_val`, and `linksection_val` are populated.
356 /// Whether `typed_value`, `align_val`, `linksection_val` and `addrspace` are populated.
355357 has_tv: bool,
356358 /// If `true` it means the `Decl` is the resource owner of the type/value associated
357359 /// with it. That means when `Decl` is destroyed, the cleanup code should additionally
......@@ -366,8 +368,8 @@ pub const Decl = struct {
366368 is_exported: bool,
367369 /// Whether the ZIR code provides an align instruction.
368370 has_align: bool,
369 /// Whether the ZIR code provides a linksection instruction.
370 has_linksection: bool,
371 /// Whether the ZIR code provides a linksection and address space instruction.
372 has_linksection_or_addrspace: bool,
371373 /// Flag used by garbage collection to mark and sweep.
372374 /// Decls which correspond to an AST node always have this field set to `true`.
373375 /// Anonymous Decls are initialized with this field set to `false` and then it
......@@ -489,14 +491,22 @@ pub const Decl = struct {
489491 if (!decl.has_align) return .none;
490492 assert(decl.zir_decl_index != 0);
491493 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]);
493495 }
494496
495497 pub fn zirLinksectionRef(decl: Decl) Zir.Inst.Ref {
496 if (!decl.has_linksection) return .none;
498 if (!decl.has_linksection_or_addrspace) return .none;
497499 assert(decl.zir_decl_index != 0);
498500 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;
500510 return @intToEnum(Zir.Inst.Ref, zir.extra[extra_index]);
501511 }
502512
......@@ -3072,7 +3082,7 @@ pub fn semaFile(mod: *Module, file: *Scope.File) SemaError!void {
30723082 new_decl.is_pub = true;
30733083 new_decl.is_exported = false;
30743084 new_decl.has_align = false;
3075 new_decl.has_linksection = false;
3085 new_decl.has_linksection_or_addrspace = false;
30763086 new_decl.ty = struct_ty;
30773087 new_decl.val = struct_val;
30783088 new_decl.has_tv = true;
......@@ -3202,6 +3212,24 @@ fn semaDecl(mod: *Module, decl: *Decl) !bool {
32023212 if (linksection_ref == .none) break :blk Value.initTag(.null_value);
32033213 break :blk (try sema.resolveInstConst(&block_scope, src, linksection_ref)).val;
32043214 };
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
32053233 // Note this resolves the type of the Decl, not the value; if this Decl
32063234 // is a struct, for example, this resolves `type` (which needs no resolution),
32073235 // not the struct itself.
......@@ -3258,6 +3286,7 @@ fn semaDecl(mod: *Module, decl: *Decl) !bool {
32583286 decl.val = try decl_tv.val.copy(&decl_arena.allocator);
32593287 decl.align_val = try align_val.copy(&decl_arena.allocator);
32603288 decl.linksection_val = try linksection_val.copy(&decl_arena.allocator);
3289 decl.@"addrspace" = address_space;
32613290 decl.has_tv = true;
32623291 decl.owns_tv = owns_tv;
32633292 decl_arena_state.* = decl_arena.state;
......@@ -3319,6 +3348,7 @@ fn semaDecl(mod: *Module, decl: *Decl) !bool {
33193348 decl.val = try decl_tv.val.copy(&decl_arena.allocator);
33203349 decl.align_val = try align_val.copy(&decl_arena.allocator);
33213350 decl.linksection_val = try linksection_val.copy(&decl_arena.allocator);
3351 decl.@"addrspace" = address_space;
33223352 decl.has_tv = true;
33233353 decl_arena_state.* = decl_arena.state;
33243354 decl.value_arena = decl_arena_state;
......@@ -3526,8 +3556,8 @@ pub fn scanNamespace(
35263556
35273557 const decl_sub_index = extra_index;
35283558 extra_index += 7; // src_hash(4) + line(1) + name(1) + value(1)
3529 extra_index += @truncate(u1, flags >> 2);
3530 extra_index += @truncate(u1, flags >> 3);
3559 extra_index += @truncate(u1, flags >> 2); // Align
3560 extra_index += @as(u2, @truncate(u1, flags >> 3)) * 2; // Link section or address space, consists of 2 Refs
35313561
35323562 try scanDecl(&scan_decl_iter, decl_sub_index, flags);
35333563 }
......@@ -3553,10 +3583,10 @@ fn scanDecl(iter: *ScanDeclIter, decl_sub_index: usize, flags: u4) SemaError!voi
35533583 const zir = namespace.file_scope.zir;
35543584
35553585 // zig fmt: off
3556 const is_pub = (flags & 0b0001) != 0;
3557 const export_bit = (flags & 0b0010) != 0;
3558 const has_align = (flags & 0b0100) != 0;
3559 const has_linksection = (flags & 0b1000) != 0;
3586 const is_pub = (flags & 0b0001) != 0;
3587 const export_bit = (flags & 0b0010) != 0;
3588 const has_align = (flags & 0b0100) != 0;
3589 const has_linksection_or_addrspace = (flags & 0b1000) != 0;
35603590 // zig fmt: on
35613591
35623592 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
36393669 new_decl.is_exported = is_exported;
36403670 new_decl.is_usingnamespace = is_usingnamespace;
36413671 new_decl.has_align = has_align;
3642 new_decl.has_linksection = has_linksection;
3672 new_decl.has_linksection_or_addrspace = has_linksection_or_addrspace;
36433673 new_decl.zir_decl_index = @intCast(u32, decl_sub_index);
36443674 new_decl.alive = true; // This Decl corresponds to an AST node and therefore always alive.
36453675 return;
......@@ -3656,7 +3686,7 @@ fn scanDecl(iter: *ScanDeclIter, decl_sub_index: usize, flags: u4) SemaError!voi
36563686 decl.is_exported = is_exported;
36573687 decl.is_usingnamespace = is_usingnamespace;
36583688 decl.has_align = has_align;
3659 decl.has_linksection = has_linksection;
3689 decl.has_linksection_or_addrspace = has_linksection_or_addrspace;
36603690 decl.zir_decl_index = @intCast(u32, decl_sub_index);
36613691 if (decl.getFunction()) |_| {
36623692 switch (mod.comp.bin_file.tag) {
......@@ -4028,6 +4058,7 @@ pub fn allocateNewDecl(mod: *Module, namespace: *Scope.Namespace, src_node: Ast.
40284058 .val = undefined,
40294059 .align_val = undefined,
40304060 .linksection_val = undefined,
4061 .@"addrspace" = undefined,
40314062 .analysis = .unreferenced,
40324063 .deletion_flag = false,
40334064 .zir_decl_index = 0,
......@@ -4052,7 +4083,7 @@ pub fn allocateNewDecl(mod: *Module, namespace: *Scope.Namespace, src_node: Ast.
40524083 .generation = 0,
40534084 .is_pub = false,
40544085 .is_exported = false,
4055 .has_linksection = false,
4086 .has_linksection_or_addrspace = false,
40564087 .has_align = false,
40574088 .alive = false,
40584089 .is_usingnamespace = false,
......@@ -4185,6 +4216,9 @@ pub fn createAnonymousDeclFromDeclNamed(
41854216 new_decl.src_line = owner_decl.src_line;
41864217 new_decl.ty = typed_value.ty;
41874218 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
41884222 new_decl.has_tv = true;
41894223 new_decl.analysis = .complete;
41904224 new_decl.generation = mod.generation;
......@@ -4330,10 +4364,59 @@ pub fn simplePtrType(
43304364 elem_ty: Type,
43314365 mutable: bool,
43324366 size: std.builtin.TypeInfo.Pointer.Size,
4367 @"addrspace": std.builtin.AddressSpace,
43334368) 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
43344416 if (!mutable and size == .Slice and elem_ty.eql(Type.initTag(.u8))) {
43354417 return Type.initTag(.const_slice_u8);
43364418 }
4419
43374420 // TODO stage1 type inference bug
43384421 const T = Type.Tag;
43394422
......@@ -4352,34 +4435,6 @@ pub fn simplePtrType(
43524435 return Type.initPayload(&type_payload.base);
43534436}
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
43834438pub fn optionalType(arena: *Allocator, child_type: Type) Allocator.Error!Type {
43844439 switch (child_type.tag()) {
43854440 .single_const_pointer => return Type.Tag.optional_single_const_pointer.create(
......@@ -4709,7 +4764,7 @@ pub fn populateTestFunctions(mod: *Module) !void {
47094764 const builtin_file = (mod.importPkg(builtin_pkg) catch unreachable).file;
47104765 const builtin_namespace = builtin_file.root_decl.?.namespace;
47114766 const decl = builtin_namespace.decls.get("test_functions").?;
4712 var buf: Type.Payload.ElemType = undefined;
4767 var buf: Type.SlicePtrFieldTypeBuffer = undefined;
47134768 const tmp_test_fn_ty = decl.ty.slicePtrFieldType(&buf).elemType();
47144769
47154770 const array_decl = d: {
src/Sema.zig+242-61
......@@ -1373,7 +1373,13 @@ fn zirRetPtr(
13731373 return sema.analyzeComptimeAlloc(block, sema.fn_ret_ty);
13741374 }
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 );
13771383 return block.addTy(.alloc, ptr_type);
13781384}
13791385
......@@ -1521,7 +1527,13 @@ fn zirAlloc(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileError
15211527 const ty_src: LazySrcLoc = .{ .node_offset_var_decl_ty = inst_data.src_node };
15221528 const var_decl_src = inst_data.src();
15231529 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 );
15251537 try sema.requireRuntimeBlock(block, var_decl_src);
15261538 return block.addTy(.alloc, ptr_type);
15271539}
......@@ -1538,7 +1550,13 @@ fn zirAllocMut(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileEr
15381550 return sema.analyzeComptimeAlloc(block, var_type);
15391551 }
15401552 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 );
15421560 try sema.requireRuntimeBlock(block, var_decl_src);
15431561 return block.addTy(.alloc, ptr_type);
15441562}
......@@ -1598,7 +1616,13 @@ fn zirResolveInferredAlloc(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Inde
15981616 try sema.mod.declareDeclDependency(sema.owner_decl, decl);
15991617
16001618 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 );
16021626 const final_ptr_ty_inst = try sema.addType(final_ptr_ty);
16031627 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
16201644 try sema.validateVarType(block, ty_src, final_elem_ty);
16211645 }
16221646 // 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 );
16241654 sema.air_instructions.set(ptr_inst, .{
16251655 .tag = .alloc,
16261656 .data = .{ .ty = final_ptr_ty },
......@@ -1774,7 +1804,14 @@ fn zirStoreToBlockPtr(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) Co
17741804 }
17751805 const ptr = sema.resolveInst(bin_inst.lhs);
17761806 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 );
17781815 // TODO detect when this store should be done at compile-time. For example,
17791816 // if expressions should force it when the condition is compile-time known.
17801817 const src: LazySrcLoc = .unneeded;
......@@ -1821,7 +1858,14 @@ fn zirStoreToInferredPtr(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index)
18211858 // for the inferred allocation.
18221859 try inferred_alloc.data.stored_inst_list.append(sema.arena, operand);
18231860 // 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 );
18251869 const bitcasted_ptr = try block.addTyOp(.bitcast, ptr_ty, ptr);
18261870 return sema.storePtr(block, src, bitcasted_ptr, operand);
18271871 }
......@@ -3004,7 +3048,7 @@ fn analyzeCall(
30043048 new_decl.is_pub = module_fn.owner_decl.is_pub;
30053049 new_decl.is_exported = module_fn.owner_decl.is_exported;
30063050 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;
30083052 new_decl.zir_decl_index = module_fn.owner_decl.zir_decl_index;
30093053 new_decl.alive = true; // This Decl is called at runtime.
30103054 new_decl.has_tv = true;
......@@ -3658,7 +3702,13 @@ fn zirOptionalPayloadPtr(
36583702 }
36593703
36603704 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
36633713 if (try sema.resolveDefinedValue(block, src, optional_ptr)) |pointer_val| {
36643714 if (try pointer_val.pointerDeref(sema.arena)) |val| {
......@@ -3773,7 +3823,13 @@ fn zirErrUnionPayloadPtr(
37733823 return sema.mod.fail(&block.base, src, "expected error union type, found {}", .{operand_ty.elemType()});
37743824
37753825 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
37783834 if (try sema.resolveDefinedValue(block, src, operand)) |pointer_val| {
37793835 if (try pointer_val.pointerDeref(sema.arena)) |val| {
......@@ -6879,6 +6935,7 @@ fn zirPtrTypeSimple(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) Comp
68796935 elem_type,
68806936 null,
68816937 0,
6938 .generic,
68826939 0,
68836940 0,
68846941 inst_data.is_mutable,
......@@ -6911,6 +6968,12 @@ fn zirPtrType(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileErr
69116968 break :blk try sema.resolveAlreadyCoercedInt(block, .unneeded, ref, u32);
69126969 } 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
69146977 const bit_start = if (inst_data.flags.has_bit_range) blk: {
69156978 const ref = @intToEnum(Zir.Inst.Ref, sema.code.extra[extra_i]);
69166979 extra_i += 1;
......@@ -6933,6 +6996,7 @@ fn zirPtrType(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileErr
69336996 elem_type,
69346997 sentinel,
69356998 abi_align,
6999 address_space,
69367000 bit_start,
69377001 bit_end,
69387002 inst_data.flags.is_mutable,
......@@ -8339,7 +8403,13 @@ fn panicWithMsg(
83398403 const panic_fn = try sema.getBuiltin(block, src, "panic");
83408404 const unresolved_stack_trace_ty = try sema.getBuiltinType(block, src, "StackTrace");
83418405 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 );
83438413 const null_stack_trace = try sema.addConstant(
83448414 try Module.optionalType(arena, ptr_stack_trace_ty),
83458415 Value.initTag(.null_value),
......@@ -8423,7 +8493,7 @@ fn fieldVal(
84238493 .Pointer => switch (object_ty.ptrSize()) {
84248494 .Slice => {
84258495 if (mem.eql(u8, field_name, "ptr")) {
8426 const buf = try arena.create(Type.Payload.ElemType);
8496 const buf = try arena.create(Type.SlicePtrFieldTypeBuffer);
84278497 const result_ty = object_ty.slicePtrFieldType(buf);
84288498 if (try sema.resolveMaybeUndefVal(block, object_src, object)) |val| {
84298499 if (val.isUndef()) return sema.addConstUndef(result_ty);
......@@ -8457,21 +8527,32 @@ fn fieldVal(
84578527 }
84588528 },
84598529 .One => {
8460 const elem_ty = object_ty.elemType();
8461 if (elem_ty.zigTypeTag() == .Array) {
8462 if (mem.eql(u8, field_name, "len")) {
8463 return sema.addConstant(
8464 Type.initTag(.comptime_int),
8465 try Value.Tag.int_u64.create(arena, elem_ty.arrayLen()),
8466 );
8467 } else {
8468 return mod.fail(
8469 &block.base,
8470 field_name_src,
8471 "no member named '{s}' in '{}'",
8472 .{ field_name, object_ty },
8473 );
8474 }
8530 const ptr_child = object_ty.elemType();
8531 switch (ptr_child.zigTypeTag()) {
8532 .Array => {
8533 if (mem.eql(u8, field_name, "len")) {
8534 return sema.addConstant(
8535 Type.initTag(.comptime_int),
8536 try Value.Tag.int_u64.create(arena, ptr_child.arrayLen()),
8537 );
8538 } else {
8539 return mod.fail(
8540 &block.base,
8541 field_name_src,
8542 "no member named '{s}' in '{}'",
8543 .{ field_name, object_ty },
8544 );
8545 }
8546 },
8547 .Struct => {
8548 const struct_ptr_deref = try sema.analyzeLoad(block, src, object, object_src);
8549 return sema.unionFieldVal(block, src, struct_ptr_deref, field_name, field_name_src, ptr_child);
8550 },
8551 .Union => {
8552 const union_ptr_deref = try sema.analyzeLoad(block, src, object, object_src);
8553 return sema.unionFieldVal(block, src, union_ptr_deref, field_name, field_name_src, ptr_child);
8554 },
8555 else => {},
84758556 }
84768557 },
84778558 .Many, .C => {},
......@@ -8595,9 +8676,8 @@ fn fieldPtr(
85958676 );
85968677 }
85978678 },
8598 .Pointer => {
8599 const ptr_child = object_ty.elemType();
8600 if (ptr_child.isSlice()) {
8679 .Pointer => switch (object_ty.ptrSize()) {
8680 .Slice => {
86018681 // Here for the ptr and len fields what we need to do is the situation
86028682 // when a temporary has its address taken, e.g. `&a[c..d].len`.
86038683 // This value may be known at compile-time or runtime. In the former
......@@ -8627,26 +8707,39 @@ fn fieldPtr(
86278707 .{ field_name, object_ty },
86288708 );
86298709 }
8630 } else switch (ptr_child.zigTypeTag()) {
8631 .Array => {
8632 if (mem.eql(u8, field_name, "len")) {
8633 var anon_decl = try block.startAnonDecl();
8634 defer anon_decl.deinit();
8635 return sema.analyzeDeclRef(try anon_decl.finish(
8636 Type.initTag(.comptime_int),
8637 try Value.Tag.int_u64.create(anon_decl.arena(), ptr_child.arrayLen()),
8638 ));
8639 } else {
8640 return mod.fail(
8641 &block.base,
8642 field_name_src,
8643 "no member named '{s}' in '{}'",
8644 .{ field_name, object_ty },
8645 );
8646 }
8647 },
8648 else => {},
8649 }
8710 },
8711 .One => {
8712 const ptr_child = object_ty.elemType();
8713 switch (ptr_child.zigTypeTag()) {
8714 .Array => {
8715 if (mem.eql(u8, field_name, "len")) {
8716 var anon_decl = try block.startAnonDecl();
8717 defer anon_decl.deinit();
8718 return sema.analyzeDeclRef(try anon_decl.finish(
8719 Type.initTag(.comptime_int),
8720 try Value.Tag.int_u64.create(anon_decl.arena(), ptr_child.arrayLen()),
8721 ));
8722 } else {
8723 return mod.fail(
8724 &block.base,
8725 field_name_src,
8726 "no member named '{s}' in '{}'",
8727 .{ field_name, object_ty },
8728 );
8729 }
8730 },
8731 .Struct => {
8732 const struct_ptr_deref = try sema.analyzeLoad(block, src, object_ptr, object_ptr_src);
8733 return sema.structFieldPtr(block, src, struct_ptr_deref, field_name, field_name_src, ptr_child);
8734 },
8735 .Union => {
8736 const union_ptr_deref = try sema.analyzeLoad(block, src, object_ptr, object_ptr_src);
8737 return sema.unionFieldPtr(block, src, union_ptr_deref, field_name, field_name_src, ptr_child);
8738 },
8739 else => {},
8740 }
8741 },
8742 .Many, .C => {},
86508743 },
86518744 .Type => {
86528745 _ = try sema.resolveConstValue(block, object_ptr_src, object_ptr);
......@@ -8788,13 +8881,20 @@ fn structFieldPtr(
87888881 const arena = sema.arena;
87898882 assert(unresolved_struct_ty.zigTypeTag() == .Struct);
87908883
8884 const struct_ptr_ty = sema.typeOf(struct_ptr);
87918885 const struct_ty = try sema.resolveTypeFields(block, src, unresolved_struct_ty);
87928886 const struct_obj = struct_ty.castTag(.@"struct").?.data;
87938887
87948888 const field_index = struct_obj.fields.getIndex(field_name) orelse
87958889 return sema.failWithBadFieldAccess(block, struct_obj, field_name_src, field_name);
87968890 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
87998899 if (try sema.resolveDefinedValue(block, src, struct_ptr)) |struct_ptr_val| {
88008900 return sema.addConstant(
......@@ -8885,6 +8985,7 @@ fn unionFieldPtr(
88858985 const arena = sema.arena;
88868986 assert(unresolved_union_ty.zigTypeTag() == .Union);
88878987
8988 const union_ptr_ty = sema.typeOf(union_ptr);
88888989 const union_ty = try sema.resolveTypeFields(block, src, unresolved_union_ty);
88898990 const union_obj = union_ty.cast(Type.Payload.Union).?.data;
88908991
......@@ -8892,7 +8993,13 @@ fn unionFieldPtr(
88928993 return sema.failWithBadUnionFieldAccess(block, union_obj, field_name_src, field_name);
88938994
88948995 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
88979004 if (try sema.resolveDefinedValue(block, src, union_ptr)) |union_ptr_val| {
88989005 // TODO detect inactive union field and emit compile error
......@@ -9068,10 +9175,13 @@ fn elemPtrArray(
90689175) CompileError!Air.Inst.Ref {
90699176 const array_ptr_ty = sema.typeOf(array_ptr);
90709177 const pointee_type = array_ptr_ty.elemType().elemType();
9071 const result_ty = if (array_ptr_ty.ptrIsMutable())
9072 try Type.Tag.single_mut_pointer.create(sema.arena, pointee_type)
9073 else
9074 try Type.Tag.single_const_pointer.create(sema.arena, pointee_type);
9178 const result_ty = try Module.simplePtrType(
9179 sema.arena,
9180 pointee_type,
9181 array_ptr_ty.ptrIsMutable(),
9182 .One,
9183 array_ptr_ty.ptrAddressSpace(),
9184 );
90759185
90769186 if (try sema.resolveDefinedValue(block, src, array_ptr)) |array_ptr_val| {
90779187 if (try sema.resolveDefinedValue(block, elem_index_src, elem_index)) |index_val| {
......@@ -9162,6 +9272,7 @@ fn coerce(
91629272 const dest_is_mut = !dest_type.isConstPtr();
91639273 if (inst_ty.isConstPtr() and dest_is_mut) break :src_array_ptr;
91649274 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
91669277 const dst_elem_type = dest_type.elemType();
91679278 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
92979408 return child;
92989409 }
92999410
9411 if (dest_info.@"addrspace" != src_info.@"addrspace") {
9412 return .no_match;
9413 }
9414
93009415 const ok_sent = dest_info.sentinel == null or src_info.size == .C or
93019416 (src_info.sentinel != null and
93029417 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 {
95909705 const decl_tv = try decl.typedValue();
95919706 if (decl_tv.val.castTag(.variable)) |payload| {
95929707 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");
95949709 return sema.addConstant(ty, try Value.Tag.decl_ref.create(sema.arena, decl));
95959710 }
95969711 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"),
95989713 try Value.Tag.decl_ref.create(sema.arena, decl),
95999714 );
96009715}
......@@ -9617,8 +9732,9 @@ fn analyzeRef(
96179732 }
96189733
96199734 try sema.requireRuntimeBlock(block, src);
9620 const ptr_type = try Module.simplePtrType(sema.arena, operand_ty, false, .One);
9621 const mut_ptr_type = try Module.simplePtrType(sema.arena, operand_ty, true, .One);
9735 const address_space = target_util.defaultAddressSpace(sema.mod.getTarget(), .local);
9736 const ptr_type = try Module.simplePtrType(sema.arena, operand_ty, false, .One, address_space);
9737 const mut_ptr_type = try Module.simplePtrType(sema.arena, operand_ty, true, .One, address_space);
96229738 const alloc = try block.addTy(.alloc, mut_ptr_type);
96239739 try sema.storePtr(block, src, alloc, operand);
96249740
......@@ -9779,6 +9895,7 @@ fn analyzeSlice(
97799895 return_elem_type,
97809896 if (end_opt == .none) slice_sentinel else null,
97819897 0, // TODO alignment
9898 if (ptr_child.zigTypeTag() == .Pointer) ptr_child.ptrAddressSpace() else .generic,
97829899 0,
97839900 0,
97849901 !ptr_child.isConstPtr(),
......@@ -10286,6 +10403,7 @@ fn resolveTypeFields(sema: *Sema, block: *Scope.Block, src: LazySrcLoc, ty: Type
1028610403 .atomic_order => return sema.resolveBuiltinTypeFields(block, src, "AtomicOrder"),
1028710404 .atomic_rmw_op => return sema.resolveBuiltinTypeFields(block, src, "AtomicRmwOp"),
1028810405 .calling_convention => return sema.resolveBuiltinTypeFields(block, src, "CallingConvention"),
10406 .address_space => return sema.resolveBuiltinTypeFields(block, src, "AddressSpace"),
1028910407 .float_mode => return sema.resolveBuiltinTypeFields(block, src, "FloatMode"),
1029010408 .reduce_op => return sema.resolveBuiltinTypeFields(block, src, "ReduceOp"),
1029110409 .call_options => return sema.resolveBuiltinTypeFields(block, src, "CallOptions"),
......@@ -10680,6 +10798,7 @@ fn typeHasOnePossibleValue(
1068010798 .atomic_order,
1068110799 .atomic_rmw_op,
1068210800 .calling_convention,
10801 .address_space,
1068310802 .float_mode,
1068410803 .reduce_op,
1068510804 .call_options,
......@@ -10865,6 +10984,7 @@ pub fn addType(sema: *Sema, ty: Type) !Air.Inst.Ref {
1086510984 .atomic_order => return .atomic_order_type,
1086610985 .atomic_rmw_op => return .atomic_rmw_op_type,
1086710986 .calling_convention => return .calling_convention_type,
10987 .address_space => return .address_space_type,
1086810988 .float_mode => return .float_mode_type,
1086910989 .reduce_op => return .reduce_op_type,
1087010990 .call_options => return .call_options_type,
......@@ -10960,7 +11080,13 @@ fn analyzeComptimeAlloc(
1096011080 block: *Scope.Block,
1096111081 var_type: Type,
1096211082) 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
1096511091 var anon_decl = try block.startAnonDecl();
1096611092 defer anon_decl.deinit();
......@@ -10976,3 +11102,58 @@ fn analyzeComptimeAlloc(
1097611102 .decl = decl,
1097711103 }));
1097811104}
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 {
443443 /// this instruction; a following 'ret' instruction will do the diversion.
444444 /// Uses the `str_tok` union field.
445445 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.
447447 /// Uses the `ptr_type_simple` union field.
448448 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.
450450 /// Uses the `ptr_type` union field.
451451 ptr_type,
452452 /// Slice operation `lhs[rhs..]`. No sentinel and no end offset.
......@@ -1672,6 +1672,7 @@ pub const Inst = struct {
16721672 atomic_order_type,
16731673 atomic_rmw_op_type,
16741674 calling_convention_type,
1675 address_space_type,
16751676 float_mode_type,
16761677 reduce_op_type,
16771678 call_options_type,
......@@ -1928,6 +1929,10 @@ pub const Inst = struct {
19281929 .ty = Type.initTag(.type),
19291930 .val = Value.initTag(.calling_convention_type),
19301931 },
1932 .address_space_type = .{
1933 .ty = Type.initTag(.type),
1934 .val = Value.initTag(.address_space_type),
1935 },
19311936 .float_mode_type = .{
19321937 .ty = Type.initTag(.type),
19331938 .val = Value.initTag(.float_mode_type),
......@@ -2129,8 +2134,9 @@ pub const Inst = struct {
21292134 is_volatile: bool,
21302135 has_sentinel: bool,
21312136 has_align: bool,
2137 has_addrspace: bool,
21322138 has_bit_range: bool,
2133 _: u2 = undefined,
2139 _: u1 = undefined,
21342140 },
21352141 size: std.builtin.TypeInfo.Pointer.Size,
21362142 /// Index into extra. See `PtrType`.
......@@ -2360,12 +2366,13 @@ pub const Inst = struct {
23602366 else_body_len: u32,
23612367 };
23622368
2363 /// Stored in extra. Depending on the flags in Data, there will be up to 4
2369 /// Stored in extra. Depending on the flags in Data, there will be up to 5
23642370 /// trailing Ref fields:
23652371 /// 0. sentinel: Ref // if `has_sentinel` flag is set
23662372 /// 1. align: Ref // if `has_align` flag is set
2367 /// 2. bit_start: Ref // if `has_bit_range` flag is set
2368 /// 3. bit_end: Ref // if `has_bit_range` flag is set
2373 /// 2. address_space: Ref // if `has_addrspace` flag is set
2374 /// 3. bit_start: Ref // if `has_bit_range` flag is set
2375 /// 4. bit_end: Ref // if `has_bit_range` flag is set
23692376 pub const PtrType = struct {
23702377 elem_type: Ref,
23712378 };
......@@ -2483,7 +2490,7 @@ pub const Inst = struct {
24832490 /// 0b000X: whether corresponding decl is pub
24842491 /// 0b00X0: whether corresponding decl is exported
24852492 /// 0b0X00: whether corresponding decl has an align expression
2486 /// 0bX000: whether corresponding decl has a linksection expression
2493 /// 0bX000: whether corresponding decl has a linksection or an address space expression
24872494 /// 5. decl: { // for every decls_len
24882495 /// src_hash: [4]u32, // hash of source bytes
24892496 /// line: u32, // line number of decl, relative to parent
......@@ -2495,7 +2502,10 @@ pub const Inst = struct {
24952502 /// this is a test decl, and the name starts at `name+1`.
24962503 /// value: Index,
24972504 /// align: Ref, // if corresponding bit is set
2498 /// link_section: Ref, // if corresponding bit is set
2505 /// link_section_or_address_space: { // if corresponding bit is set.
2506 /// link_section: Ref,
2507 /// address_space: Ref,
2508 /// }
24992509 /// }
25002510 /// 6. inst: Index // for every body_len
25012511 /// 7. flags: u32 // for every 8 fields
......@@ -2547,7 +2557,7 @@ pub const Inst = struct {
25472557 /// 0b000X: whether corresponding decl is pub
25482558 /// 0b00X0: whether corresponding decl is exported
25492559 /// 0b0X00: whether corresponding decl has an align expression
2550 /// 0bX000: whether corresponding decl has a linksection expression
2560 /// 0bX000: whether corresponding decl has a linksection or an address space expression
25512561 /// 6. decl: { // for every decls_len
25522562 /// src_hash: [4]u32, // hash of source bytes
25532563 /// line: u32, // line number of decl, relative to parent
......@@ -2559,7 +2569,10 @@ pub const Inst = struct {
25592569 /// this is a test decl, and the name starts at `name+1`.
25602570 /// value: Index,
25612571 /// align: Ref, // if corresponding bit is set
2562 /// link_section: Ref, // if corresponding bit is set
2572 /// link_section_or_address_space: { // if corresponding bit is set.
2573 /// link_section: Ref,
2574 /// address_space: Ref,
2575 /// }
25632576 /// }
25642577 /// 7. inst: Index // for every body_len
25652578 /// 8. has_bits: u32 // for every 32 fields
......@@ -2592,7 +2605,7 @@ pub const Inst = struct {
25922605 /// 0b000X: whether corresponding decl is pub
25932606 /// 0b00X0: whether corresponding decl is exported
25942607 /// 0b0X00: whether corresponding decl has an align expression
2595 /// 0bX000: whether corresponding decl has a linksection expression
2608 /// 0bX000: whether corresponding decl has a linksection or an address space expression
25962609 /// 6. decl: { // for every decls_len
25972610 /// src_hash: [4]u32, // hash of source bytes
25982611 /// line: u32, // line number of decl, relative to parent
......@@ -2604,7 +2617,10 @@ pub const Inst = struct {
26042617 /// this is a test decl, and the name starts at `name+1`.
26052618 /// value: Index,
26062619 /// align: Ref, // if corresponding bit is set
2607 /// link_section: Ref, // if corresponding bit is set
2620 /// link_section_or_address_space: { // if corresponding bit is set.
2621 /// link_section: Ref,
2622 /// address_space: Ref,
2623 /// }
26082624 /// }
26092625 /// 7. inst: Index // for every body_len
26102626 /// 8. has_bits: u32 // for every 8 fields
......@@ -2641,7 +2657,7 @@ pub const Inst = struct {
26412657 /// 0b000X: whether corresponding decl is pub
26422658 /// 0b00X0: whether corresponding decl is exported
26432659 /// 0b0X00: whether corresponding decl has an align expression
2644 /// 0bX000: whether corresponding decl has a linksection expression
2660 /// 0bX000: whether corresponding decl has a linksection or an address space expression
26452661 /// 1. decl: { // for every decls_len
26462662 /// src_hash: [4]u32, // hash of source bytes
26472663 /// line: u32, // line number of decl, relative to parent
......@@ -2653,7 +2669,10 @@ pub const Inst = struct {
26532669 /// this is a test decl, and the name starts at `name+1`.
26542670 /// value: Index,
26552671 /// align: Ref, // if corresponding bit is set
2656 /// link_section: Ref, // if corresponding bit is set
2672 /// link_section_or_address_space: { // if corresponding bit is set.
2673 /// link_section: Ref,
2674 /// address_space: Ref,
2675 /// }
26572676 /// }
26582677 pub const OpaqueDecl = struct {
26592678 decls_len: u32,
src/codegen.zig+1-1
......@@ -4895,7 +4895,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
48954895 switch (typed_value.ty.zigTypeTag()) {
48964896 .Pointer => switch (typed_value.ty.ptrSize()) {
48974897 .Slice => {
4898 var buf: Type.Payload.ElemType = undefined;
4898 var buf: Type.SlicePtrFieldTypeBuffer = undefined;
48994899 const ptr_type = typed_value.ty.slicePtrFieldType(&buf);
49004900 const ptr_mcv = try self.genTypedValue(.{ .ty = ptr_type, .val = typed_value.val });
49014901 const slice_len = typed_value.val.sliceLen();
src/codegen/c.zig+1-1
......@@ -251,7 +251,7 @@ pub const DeclGen = struct {
251251 try writer.writeByte('(');
252252 try dg.renderType(writer, t);
253253 try writer.writeAll("){");
254 var buf: Type.Payload.ElemType = undefined;
254 var buf: Type.SlicePtrFieldTypeBuffer = undefined;
255255 try dg.renderValue(writer, t.slicePtrFieldType(&buf), val);
256256 try writer.writeAll(", ");
257257 try writer.print("{d}", .{val.sliceLen()});
src/codegen/llvm.zig+30-8
......@@ -558,7 +558,8 @@ pub const DeclGen = struct {
558558 llvm_params_len,
559559 .False,
560560 );
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
563564 const is_extern = decl.val.tag() == .extern_fn;
564565 if (!is_extern) {
......@@ -580,7 +581,24 @@ pub const DeclGen = struct {
580581 if (llvm_module.getNamedGlobal(decl.name)) |val| return val;
581582 // TODO: remove this redundant `llvmType`, it is also called in `genTypedValue`.
582583 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 };
584602 }
585603
586604 fn llvmType(self: *DeclGen, t: Type) error{ OutOfMemory, CodegenFail }!*const llvm.Type {
......@@ -609,7 +627,7 @@ pub const DeclGen = struct {
609627 .Bool => return self.context.intType(1),
610628 .Pointer => {
611629 if (t.isSlice()) {
612 var buf: Type.Payload.ElemType = undefined;
630 var buf: Type.SlicePtrFieldTypeBuffer = undefined;
613631 const ptr_type = t.slicePtrFieldType(&buf);
614632
615633 const fields: [2]*const llvm.Type = .{
......@@ -619,7 +637,8 @@ pub const DeclGen = struct {
619637 return self.context.structType(&fields, fields.len, .False);
620638 } else {
621639 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);
623642 }
624643 },
625644 .Array => {
......@@ -685,7 +704,9 @@ pub const DeclGen = struct {
685704 @intCast(c_uint, llvm_params.len),
686705 llvm.Bool.fromBool(is_var_args),
687706 );
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);
689710 },
690711 .ComptimeInt => unreachable,
691712 .ComptimeFloat => unreachable,
......@@ -753,7 +774,7 @@ pub const DeclGen = struct {
753774 .Pointer => switch (tv.val.tag()) {
754775 .decl_ref => {
755776 if (tv.ty.isSlice()) {
756 var buf: Type.Payload.ElemType = undefined;
777 var buf: Type.SlicePtrFieldTypeBuffer = undefined;
757778 const ptr_ty = tv.ty.slicePtrFieldType(&buf);
758779 var slice_len: Value.Payload.U64 = .{
759780 .base = .{ .tag = .int_u64 },
......@@ -783,12 +804,13 @@ pub const DeclGen = struct {
783804 decl.alive = true;
784805 const val = try self.resolveGlobalDecl(decl);
785806 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);
787809 return val.constBitCast(llvm_type);
788810 },
789811 .slice => {
790812 const slice = tv.val.castTag(.slice).?.data;
791 var buf: Type.Payload.ElemType = undefined;
813 var buf: Type.SlicePtrFieldTypeBuffer = undefined;
792814 const fields: [2]*const llvm.Value = .{
793815 try self.genTypedValue(.{
794816 .ty = tv.ty.slicePtrFieldType(&buf),
src/codegen/llvm/bindings.zig+68
......@@ -197,6 +197,9 @@ pub const Module = opaque {
197197 pub const addFunction = LLVMAddFunction;
198198 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
200203 pub const getNamedFunction = LLVMGetNamedFunction;
201204 extern fn LLVMGetNamedFunction(*const Module, Name: [*:0]const u8) ?*const Value;
202205
......@@ -209,6 +212,9 @@ pub const Module = opaque {
209212 pub const addGlobal = LLVMAddGlobal;
210213 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
212218 pub const getNamedGlobal = LLVMGetNamedGlobal;
213219 extern fn LLVMGetNamedGlobal(M: *const Module, Name: [*:0]const u8) ?*const Value;
214220
......@@ -1005,3 +1011,65 @@ pub const TypeKind = enum(c_int) {
10051011 BFloat,
10061012 X86_AMX,
10071013};
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 {
11471147 cur_bit_bag >>= 1;
11481148 const has_align = @truncate(u1, cur_bit_bag) != 0;
11491149 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;
11511151 cur_bit_bag >>= 1;
11521152
11531153 const sub_index = extra_index;
......@@ -1165,7 +1165,12 @@ const Writer = struct {
11651165 extra_index += 1;
11661166 break :inst inst;
11671167 };
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: {
11691174 const inst = @intToEnum(Zir.Inst.Ref, self.code.extra[extra_index]);
11701175 extra_index += 1;
11711176 break :inst inst;
......@@ -1196,6 +1201,11 @@ const Writer = struct {
11961201 try self.writeInstRef(stream, align_inst);
11971202 try stream.writeAll(")");
11981203 }
1204 if (addrspace_inst != .none) {
1205 try stream.writeAll(" addrspace(");
1206 try self.writeInstRef(stream, addrspace_inst);
1207 try stream.writeAll(")");
1208 }
11991209 if (section_inst != .none) {
12001210 try stream.writeAll(" linksection(");
12011211 try self.writeInstRef(stream, section_inst);
src/stage1/all_types.hpp+8
......@@ -86,6 +86,14 @@ enum CallingConvention {
8686 CallingConventionSysV
8787};
8888
89// Stage 1 supports only the generic address space
90enum AddressSpace {
91 AddressSpaceGeneric,
92 AddressSpaceGS,
93 AddressSpaceFS,
94 AddressSpaceSS,
95};
96
8997// This one corresponds to the builtin.zig enum.
9098enum BuiltinPtrSize {
9199 BuiltinPtrSizeOne,
src/stage1/analyze.cpp+10
......@@ -1019,6 +1019,16 @@ bool calling_convention_allows_zig_types(CallingConvention cc) {
10191019 zig_unreachable();
10201020}
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
10221032ZigType *get_stack_trace_type(CodeGen *g) {
10231033 if (g->stack_trace_type == nullptr) {
10241034 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);
242242bool calling_convention_allows_zig_types(CallingConvention cc);
243243const char *calling_convention_name(CallingConvention cc);
244244
245const char *address_space_name(AddressSpace as);
246
245247Error ATTRIBUTE_MUST_USE file_fetch(CodeGen *g, Buf *resolved_path, Buf *contents);
246248
247249void 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,
1612416124
1612516125static Stage1AirInst *ir_analyze_instruction_ctz(IrAnalyze *ira, Stage1ZirInstCtz *instruction) {
1612616126 Error err;
16127
16127
1612816128 ZigType *int_type = ir_resolve_int_type(ira, instruction->type->child);
1612916129 if (type_is_invalid(int_type))
1613016130 return ira->codegen->invalid_inst_gen;
......@@ -16166,7 +16166,7 @@ static Stage1AirInst *ir_analyze_instruction_ctz(IrAnalyze *ira, Stage1ZirInstCt
1616616166 return ira->codegen->invalid_inst_gen;
1616716167 if (val->special == ConstValSpecialUndef)
1616816168 return ir_const_undef(ira, instruction->base.scope, instruction->base.source_node, ira->codegen->builtin_types.entry_num_lit_int);
16169
16169
1617016170 if (is_vector) {
1617116171 ZigType *smallest_vec_type = get_vector_type(ira->codegen, vector_len, smallest_type);
1617216172 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
1620016200
1620116201static Stage1AirInst *ir_analyze_instruction_clz(IrAnalyze *ira, Stage1ZirInstClz *instruction) {
1620216202 Error err;
16203
16203
1620416204 ZigType *int_type = ir_resolve_int_type(ira, instruction->type->child);
1620516205 if (type_is_invalid(int_type))
1620616206 return ira->codegen->invalid_inst_gen;
......@@ -16242,7 +16242,7 @@ static Stage1AirInst *ir_analyze_instruction_clz(IrAnalyze *ira, Stage1ZirInstCl
1624216242 return ira->codegen->invalid_inst_gen;
1624316243 if (val->special == ConstValSpecialUndef)
1624416244 return ir_const_undef(ira, instruction->base.scope, instruction->base.source_node, ira->codegen->builtin_types.entry_num_lit_int);
16245
16245
1624616246 if (is_vector) {
1624716247 ZigType *smallest_vec_type = get_vector_type(ira->codegen, vector_len, smallest_type);
1624816248 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
1627616276
1627716277static Stage1AirInst *ir_analyze_instruction_pop_count(IrAnalyze *ira, Stage1ZirInstPopCount *instruction) {
1627816278 Error err;
16279
16279
1628016280 ZigType *int_type = ir_resolve_int_type(ira, instruction->type->child);
1628116281 if (type_is_invalid(int_type))
1628216282 return ira->codegen->invalid_inst_gen;
......@@ -16318,7 +16318,7 @@ static Stage1AirInst *ir_analyze_instruction_pop_count(IrAnalyze *ira, Stage1Zir
1631816318 return ira->codegen->invalid_inst_gen;
1631916319 if (val->special == ConstValSpecialUndef)
1632016320 return ir_const_undef(ira, instruction->base.scope, instruction->base.source_node, ira->codegen->builtin_types.entry_num_lit_int);
16321
16321
1632216322 if (is_vector) {
1632316323 ZigType *smallest_vec_type = get_vector_type(ira->codegen, vector_len, smallest_type);
1632416324 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
1790417904 result->special = ConstValSpecialStatic;
1790517905 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);
1790817908 result->data.x_struct.fields = fields;
1790917909
1791017910 // size: Size
......@@ -17939,24 +17939,29 @@ static ZigValue *create_ptr_like_type_info(IrAnalyze *ira, Scope *scope, AstNode
1793917939 lazy_align_of->base.id = LazyValueIdAlignOf;
1794017940 lazy_align_of->target_type = ir_const_type(ira, scope, source_node, attrs_type->data.pointer.child_type);
1794117941 }
17942 // child: type
17943 ensure_field_index(result->type, "child", 4);
17942 // address_space: AddressSpace,
17943 ensure_field_index(result->type, "address_space", 4);
1794417944 fields[4]->special = ConstValSpecialStatic;
17945 fields[4]->type = ira->codegen->builtin_types.entry_type;
17946 fields[4]->data.x_type = attrs_type->data.pointer.child_type;
17947 // is_allowzero: bool
17948 ensure_field_index(result->type, "is_allowzero", 5);
17945 fields[4]->type = get_builtin_type(ira->codegen, "AddressSpace");
17946 bigint_init_unsigned(&fields[4]->data.x_enum_tag, AddressSpaceGeneric);
17947 // child: type
17948 ensure_field_index(result->type, "child", 5);
1794917949 fields[5]->special = ConstValSpecialStatic;
17950 fields[5]->type = ira->codegen->builtin_types.entry_bool;
17951 fields[5]->data.x_bool = attrs_type->data.pointer.allow_zero;
17952 // sentinel: anytype
17953 ensure_field_index(result->type, "sentinel", 6);
17950 fields[5]->type = ira->codegen->builtin_types.entry_type;
17951 fields[5]->data.x_type = attrs_type->data.pointer.child_type;
17952 // is_allowzero: bool
17953 ensure_field_index(result->type, "is_allowzero", 6);
1795417954 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;
1795517960 if (attrs_type->data.pointer.sentinel != nullptr) {
17956 fields[6]->type = get_optional_type(ira->codegen, attrs_type->data.pointer.child_type);
17957 set_optional_payload(fields[6], attrs_type->data.pointer.sentinel);
17961 fields[7]->type = get_optional_type(ira->codegen, attrs_type->data.pointer.child_type);
17962 set_optional_payload(fields[7], attrs_type->data.pointer.sentinel);
1795817963 } else {
17959 fields[6]->type = ira->codegen->builtin_types.entry_null;
17964 fields[7]->type = ira->codegen->builtin_types.entry_null;
1796017965 }
1796117966
1796217967 return result;
......@@ -18465,7 +18470,7 @@ static Error ir_make_type_info_value(IrAnalyze *ira, Scope *scope, AstNode *sour
1846518470 result->special = ConstValSpecialStatic;
1846618471 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);
1846918474 result->data.x_struct.fields = fields;
1847018475
1847118476 // calling_convention: TypeInfo.CallingConvention
......@@ -18826,11 +18831,11 @@ static ZigType *type_info_to_type(IrAnalyze *ira, Scope *scope, AstNode *source_
1882618831 assert(size_value->type == ir_type_info_get_type(ira, "Size", type_info_pointer_type));
1882718832 BuiltinPtrSize size_enum_index = (BuiltinPtrSize)bigint_as_u32(&size_value->data.x_enum_tag);
1882818833 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);
1883018835 if (type_is_invalid(elem_type))
1883118836 return ira->codegen->invalid_inst_gen->value->type;
1883218837 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,
1883418839 elem_type, &sentinel)))
1883518840 {
1883618841 return ira->codegen->invalid_inst_gen->value->type;
......@@ -18845,6 +18850,19 @@ static ZigType *type_info_to_type(IrAnalyze *ira, Scope *scope, AstNode *source_
1884518850 if (alignment == nullptr)
1884618851 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
1884818866 bool is_const;
1884918867 if ((err = get_const_field_bool(ira, source_node, payload, "is_const", 1, &is_const)))
1885018868 return ira->codegen->invalid_inst_gen->value->type;
......@@ -18857,13 +18875,12 @@ static ZigType *type_info_to_type(IrAnalyze *ira, Scope *scope, AstNode *source_
1885718875 }
1885818876
1885918877 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,
1886118879 &is_allowzero)))
1886218880 {
1886318881 return ira->codegen->invalid_inst_gen->value->type;
1886418882 }
1886518883
18866
1886718884 ZigType *ptr_type = get_pointer_to_type_extra2(ira->codegen,
1886818885 elem_type,
1886918886 is_const,
src/target.zig+18
......@@ -544,3 +544,21 @@ pub fn largestAtomicBits(target: std.Target) u32 {
544544 .x86_64 => 128,
545545 };
546546}
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 {
26142614 .type_node = type_node,
26152615 .align_node = align_node,
26162616 .section_node = section_node,
2617 .addrspace_node = 0,
26172618 }),
26182619 .rhs = init_node,
26192620 },
......@@ -2705,6 +2706,7 @@ fn renderFunc(c: *Context, node: Node) !NodeIndex {
27052706 .lhs = try c.addExtra(std.zig.Ast.Node.FnProtoOne{
27062707 .param = params.items[0],
27072708 .align_expr = align_expr,
2709 .addrspace_expr = 0, // TODO
27082710 .section_expr = section_expr,
27092711 .callconv_expr = callconv_expr,
27102712 }),
......@@ -2720,6 +2722,7 @@ fn renderFunc(c: *Context, node: Node) !NodeIndex {
27202722 .params_start = span.start,
27212723 .params_end = span.end,
27222724 .align_expr = align_expr,
2725 .addrspace_expr = 0, // TODO
27232726 .section_expr = section_expr,
27242727 .callconv_expr = callconv_expr,
27252728 }),
src/type.zig+115-13
......@@ -127,6 +127,7 @@ pub const Type = extern union {
127127 .atomic_order,
128128 .atomic_rmw_op,
129129 .calling_convention,
130 .address_space,
130131 .float_mode,
131132 .reduce_op,
132133 => return .Enum,
......@@ -288,6 +289,7 @@ pub const Type = extern union {
288289 .pointee_type = Type.initTag(.comptime_int),
289290 .sentinel = null,
290291 .@"align" = 0,
292 .@"addrspace" = .generic,
291293 .bit_offset = 0,
292294 .host_size = 0,
293295 .@"allowzero" = false,
......@@ -299,6 +301,7 @@ pub const Type = extern union {
299301 .pointee_type = Type.initTag(.u8),
300302 .sentinel = null,
301303 .@"align" = 0,
304 .@"addrspace" = .generic,
302305 .bit_offset = 0,
303306 .host_size = 0,
304307 .@"allowzero" = false,
......@@ -310,6 +313,7 @@ pub const Type = extern union {
310313 .pointee_type = self.castPointer().?.data,
311314 .sentinel = null,
312315 .@"align" = 0,
316 .@"addrspace" = .generic,
313317 .bit_offset = 0,
314318 .host_size = 0,
315319 .@"allowzero" = false,
......@@ -321,6 +325,7 @@ pub const Type = extern union {
321325 .pointee_type = self.castPointer().?.data,
322326 .sentinel = null,
323327 .@"align" = 0,
328 .@"addrspace" = .generic,
324329 .bit_offset = 0,
325330 .host_size = 0,
326331 .@"allowzero" = false,
......@@ -332,6 +337,7 @@ pub const Type = extern union {
332337 .pointee_type = self.castPointer().?.data,
333338 .sentinel = null,
334339 .@"align" = 0,
340 .@"addrspace" = .generic,
335341 .bit_offset = 0,
336342 .host_size = 0,
337343 .@"allowzero" = false,
......@@ -343,6 +349,7 @@ pub const Type = extern union {
343349 .pointee_type = Type.initTag(.u8),
344350 .sentinel = null,
345351 .@"align" = 0,
352 .@"addrspace" = .generic,
346353 .bit_offset = 0,
347354 .host_size = 0,
348355 .@"allowzero" = false,
......@@ -354,6 +361,7 @@ pub const Type = extern union {
354361 .pointee_type = self.castPointer().?.data,
355362 .sentinel = null,
356363 .@"align" = 0,
364 .@"addrspace" = .generic,
357365 .bit_offset = 0,
358366 .host_size = 0,
359367 .@"allowzero" = false,
......@@ -365,6 +373,7 @@ pub const Type = extern union {
365373 .pointee_type = Type.initTag(.u8),
366374 .sentinel = null,
367375 .@"align" = 0,
376 .@"addrspace" = .generic,
368377 .bit_offset = 0,
369378 .host_size = 0,
370379 .@"allowzero" = false,
......@@ -376,6 +385,7 @@ pub const Type = extern union {
376385 .pointee_type = self.castPointer().?.data,
377386 .sentinel = null,
378387 .@"align" = 0,
388 .@"addrspace" = .generic,
379389 .bit_offset = 0,
380390 .host_size = 0,
381391 .@"allowzero" = false,
......@@ -387,6 +397,7 @@ pub const Type = extern union {
387397 .pointee_type = self.castPointer().?.data,
388398 .sentinel = null,
389399 .@"align" = 0,
400 .@"addrspace" = .generic,
390401 .bit_offset = 0,
391402 .host_size = 0,
392403 .@"allowzero" = false,
......@@ -398,6 +409,7 @@ pub const Type = extern union {
398409 .pointee_type = self.castPointer().?.data,
399410 .sentinel = null,
400411 .@"align" = 0,
412 .@"addrspace" = .generic,
401413 .bit_offset = 0,
402414 .host_size = 0,
403415 .@"allowzero" = false,
......@@ -409,6 +421,7 @@ pub const Type = extern union {
409421 .pointee_type = self.castPointer().?.data,
410422 .sentinel = null,
411423 .@"align" = 0,
424 .@"addrspace" = .generic,
412425 .bit_offset = 0,
413426 .host_size = 0,
414427 .@"allowzero" = false,
......@@ -461,6 +474,8 @@ pub const Type = extern union {
461474 return false;
462475 if (info_a.host_size != info_b.host_size)
463476 return false;
477 if (info_a.@"addrspace" != info_b.@"addrspace")
478 return false;
464479
465480 const sentinel_a = info_a.sentinel;
466481 const sentinel_b = info_b.sentinel;
......@@ -746,6 +761,7 @@ pub const Type = extern union {
746761 .atomic_order,
747762 .atomic_rmw_op,
748763 .calling_convention,
764 .address_space,
749765 .float_mode,
750766 .reduce_op,
751767 .call_options,
......@@ -835,6 +851,7 @@ pub const Type = extern union {
835851 .pointee_type = try payload.pointee_type.copy(allocator),
836852 .sentinel = sent,
837853 .@"align" = payload.@"align",
854 .@"addrspace" = payload.@"addrspace",
838855 .bit_offset = payload.bit_offset,
839856 .host_size = payload.host_size,
840857 .@"allowzero" = payload.@"allowzero",
......@@ -958,6 +975,7 @@ pub const Type = extern union {
958975 .atomic_order => return writer.writeAll("std.builtin.AtomicOrder"),
959976 .atomic_rmw_op => return writer.writeAll("std.builtin.AtomicRmwOp"),
960977 .calling_convention => return writer.writeAll("std.builtin.CallingConvention"),
978 .address_space => return writer.writeAll("std.builtin.AddressSpace"),
961979 .float_mode => return writer.writeAll("std.builtin.FloatMode"),
962980 .reduce_op => return writer.writeAll("std.builtin.ReduceOp"),
963981 .call_options => return writer.writeAll("std.builtin.CallOptions"),
......@@ -1111,6 +1129,9 @@ pub const Type = extern union {
11111129 }
11121130 try writer.writeAll(") ");
11131131 }
1132 if (payload.@"addrspace" != .generic) {
1133 try writer.print("addrspace(.{s}) ", .{@tagName(payload.@"addrspace")});
1134 }
11141135 if (!payload.mutable) try writer.writeAll("const ");
11151136 if (payload.@"volatile") try writer.writeAll("volatile ");
11161137 if (payload.@"allowzero") try writer.writeAll("allowzero ");
......@@ -1186,6 +1207,7 @@ pub const Type = extern union {
11861207 .atomic_order,
11871208 .atomic_rmw_op,
11881209 .calling_convention,
1210 .address_space,
11891211 .float_mode,
11901212 .reduce_op,
11911213 .call_options,
......@@ -1301,6 +1323,7 @@ pub const Type = extern union {
13011323 .atomic_order => return Value.initTag(.atomic_order_type),
13021324 .atomic_rmw_op => return Value.initTag(.atomic_rmw_op_type),
13031325 .calling_convention => return Value.initTag(.calling_convention_type),
1326 .address_space => return Value.initTag(.address_space_type),
13041327 .float_mode => return Value.initTag(.float_mode_type),
13051328 .reduce_op => return Value.initTag(.reduce_op_type),
13061329 .call_options => return Value.initTag(.call_options_type),
......@@ -1362,6 +1385,7 @@ pub const Type = extern union {
13621385 .atomic_order,
13631386 .atomic_rmw_op,
13641387 .calling_convention,
1388 .address_space,
13651389 .float_mode,
13661390 .reduce_op,
13671391 .call_options,
......@@ -1496,6 +1520,30 @@ pub const Type = extern union {
14961520 }
14971521 }
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
14991547 /// Asserts that hasCodeGenBits() is true.
15001548 pub fn abiAlignment(self: Type, target: Target) u32 {
15011549 return switch (self.tag()) {
......@@ -1508,6 +1556,7 @@ pub const Type = extern union {
15081556 .atomic_order,
15091557 .atomic_rmw_op,
15101558 .calling_convention,
1559 .address_space,
15111560 .float_mode,
15121561 .reduce_op,
15131562 .call_options,
......@@ -1734,6 +1783,7 @@ pub const Type = extern union {
17341783 .atomic_order,
17351784 .atomic_rmw_op,
17361785 .calling_convention,
1786 .address_space,
17371787 .float_mode,
17381788 .reduce_op,
17391789 .call_options,
......@@ -2019,6 +2069,7 @@ pub const Type = extern union {
20192069 .atomic_order,
20202070 .atomic_rmw_op,
20212071 .calling_convention,
2072 .address_space,
20222073 .float_mode,
20232074 .reduce_op,
20242075 .call_options,
......@@ -2105,42 +2156,82 @@ pub const Type = extern union {
21052156 };
21062157 }
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 {
21092165 switch (self.tag()) {
21102166 .const_slice_u8 => return Type.initTag(.manyptr_const_u8),
21112167
21122168 .const_slice => {
21132169 const elem_type = self.castTag(.const_slice).?.data;
21142170 buffer.* = .{
2115 .base = .{ .tag = .many_const_pointer },
2116 .data = elem_type,
2171 .elem_type = .{
2172 .base = .{ .tag = .many_const_pointer },
2173 .data = elem_type,
2174 },
21172175 };
2118 return Type.initPayload(&buffer.base);
2176 return Type.initPayload(&buffer.elem_type.base);
21192177 },
21202178 .mut_slice => {
21212179 const elem_type = self.castTag(.mut_slice).?.data;
21222180 buffer.* = .{
2123 .base = .{ .tag = .many_mut_pointer },
2124 .data = elem_type,
2181 .elem_type = .{
2182 .base = .{ .tag = .many_mut_pointer },
2183 .data = elem_type,
2184 },
21252185 };
2126 return Type.initPayload(&buffer.base);
2186 return Type.initPayload(&buffer.elem_type.base);
21272187 },
21282188
21292189 .pointer => {
21302190 const payload = self.castTag(.pointer).?.data;
21312191 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 {
21332201 buffer.* = .{
2134 .base = .{ .tag = .many_mut_pointer },
2135 .data = payload.pointee_type,
2202 .pointer = .{
2203 .data = .{
2204 .pointee_type = payload.pointee_type,
2205 .sentinel = payload.sentinel,
2206 .@"align" = payload.@"align",
2207 .@"addrspace" = payload.@"addrspace",
2208 .bit_offset = payload.bit_offset,
2209 .host_size = payload.host_size,
2210 .@"allowzero" = payload.@"allowzero",
2211 .mutable = payload.mutable,
2212 .@"volatile" = payload.@"volatile",
2213 .size = .Many,
2214 },
2215 },
21362216 };
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);
21372226 } else {
21382227 buffer.* = .{
2139 .base = .{ .tag = .many_const_pointer },
2140 .data = payload.pointee_type,
2228 .elem_type = .{
2229 .base = .{ .tag = .many_const_pointer },
2230 .data = payload.pointee_type,
2231 },
21412232 };
2233 return Type.initPayload(&buffer.elem_type.base);
21422234 }
2143 return Type.initPayload(&buffer.base);
21442235 },
21452236
21462237 else => unreachable,
......@@ -2793,6 +2884,7 @@ pub const Type = extern union {
27932884 .atomic_order,
27942885 .atomic_rmw_op,
27952886 .calling_convention,
2887 .address_space,
27962888 .float_mode,
27972889 .reduce_op,
27982890 .call_options,
......@@ -3000,6 +3092,7 @@ pub const Type = extern union {
30003092 .atomic_order,
30013093 .atomic_rmw_op,
30023094 .calling_convention,
3095 .address_space,
30033096 .float_mode,
30043097 .reduce_op,
30053098 .call_options,
......@@ -3024,6 +3117,7 @@ pub const Type = extern union {
30243117 .atomic_order,
30253118 .atomic_rmw_op,
30263119 .calling_convention,
3120 .address_space,
30273121 .float_mode,
30283122 .reduce_op,
30293123 .call_options,
......@@ -3047,6 +3141,7 @@ pub const Type = extern union {
30473141 .atomic_order,
30483142 .atomic_rmw_op,
30493143 .calling_convention,
3144 .address_space,
30503145 .float_mode,
30513146 .reduce_op,
30523147 .call_options,
......@@ -3100,6 +3195,7 @@ pub const Type = extern union {
31003195 .atomic_order,
31013196 .atomic_rmw_op,
31023197 .calling_convention,
3198 .address_space,
31033199 .float_mode,
31043200 .reduce_op,
31053201 .call_options,
......@@ -3155,6 +3251,7 @@ pub const Type = extern union {
31553251 .atomic_order,
31563252 .atomic_rmw_op,
31573253 .calling_convention,
3254 .address_space,
31583255 .float_mode,
31593256 .reduce_op,
31603257 .call_options,
......@@ -3192,6 +3289,7 @@ pub const Type = extern union {
31923289 .atomic_order,
31933290 .atomic_rmw_op,
31943291 .calling_convention,
3292 .address_space,
31953293 .float_mode,
31963294 .reduce_op,
31973295 .call_options,
......@@ -3242,6 +3340,7 @@ pub const Type = extern union {
32423340 .atomic_order,
32433341 .atomic_rmw_op,
32443342 .calling_convention,
3343 .address_space,
32453344 .float_mode,
32463345 .reduce_op,
32473346 .call_options,
......@@ -3302,6 +3401,7 @@ pub const Type = extern union {
33023401 atomic_order,
33033402 atomic_rmw_op,
33043403 calling_convention,
3404 address_space,
33053405 float_mode,
33063406 reduce_op,
33073407 call_options,
......@@ -3425,6 +3525,7 @@ pub const Type = extern union {
34253525 .atomic_order,
34263526 .atomic_rmw_op,
34273527 .calling_convention,
3528 .address_space,
34283529 .float_mode,
34293530 .reduce_op,
34303531 .call_options,
......@@ -3580,6 +3681,7 @@ pub const Type = extern union {
35803681 sentinel: ?Value,
35813682 /// If zero use pointee_type.AbiAlign()
35823683 @"align": u32,
3684 @"addrspace": std.builtin.AddressSpace,
35833685 bit_offset: u16,
35843686 host_size: u16,
35853687 @"allowzero": bool,
src/value.zig+5
......@@ -63,6 +63,7 @@ pub const Value = extern union {
6363 atomic_order_type,
6464 atomic_rmw_op_type,
6565 calling_convention_type,
66 address_space_type,
6667 float_mode_type,
6768 reduce_op_type,
6869 call_options_type,
......@@ -226,6 +227,7 @@ pub const Value = extern union {
226227 .atomic_order_type,
227228 .atomic_rmw_op_type,
228229 .calling_convention_type,
230 .address_space_type,
229231 .float_mode_type,
230232 .reduce_op_type,
231233 .call_options_type,
......@@ -412,6 +414,7 @@ pub const Value = extern union {
412414 .atomic_order_type,
413415 .atomic_rmw_op_type,
414416 .calling_convention_type,
417 .address_space_type,
415418 .float_mode_type,
416419 .reduce_op_type,
417420 .call_options_type,
......@@ -625,6 +628,7 @@ pub const Value = extern union {
625628 .atomic_order_type => return out_stream.writeAll("std.builtin.AtomicOrder"),
626629 .atomic_rmw_op_type => return out_stream.writeAll("std.builtin.AtomicRmwOp"),
627630 .calling_convention_type => return out_stream.writeAll("std.builtin.CallingConvention"),
631 .address_space_type => return out_stream.writeAll("std.builtin.AddressSpace"),
628632 .float_mode_type => return out_stream.writeAll("std.builtin.FloatMode"),
629633 .reduce_op_type => return out_stream.writeAll("std.builtin.ReduceOp"),
630634 .call_options_type => return out_stream.writeAll("std.builtin.CallOptions"),
......@@ -792,6 +796,7 @@ pub const Value = extern union {
792796 .atomic_order_type => Type.initTag(.atomic_order),
793797 .atomic_rmw_op_type => Type.initTag(.atomic_rmw_op),
794798 .calling_convention_type => Type.initTag(.calling_convention),
799 .address_space_type => Type.initTag(.address_space),
795800 .float_mode_type => Type.initTag(.float_mode),
796801 .reduce_op_type => Type.initTag(.reduce_op),
797802 .call_options_type => Type.initTag(.call_options),
src/zig_llvm.cpp+5
......@@ -416,6 +416,11 @@ ZIG_EXTERN_C LLVMTypeRef ZigLLVMTokenTypeInContext(LLVMContextRef context_ref) {
416416 return wrap(Type::getTokenTy(*unwrap(context_ref)));
417417}
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
419424LLVMValueRef ZigLLVMBuildCall(LLVMBuilderRef B, LLVMValueRef Fn, LLVMValueRef *Args,
420425 unsigned NumArgs, ZigLLVM_CallingConv CC, ZigLLVM_CallAttr attr, const char *Name)
421426{
src/zig_llvm.h+3
......@@ -65,6 +65,9 @@ ZIG_EXTERN_C LLVMTargetMachineRef ZigLLVMCreateTargetMachine(LLVMTargetRef T, co
6565
6666ZIG_EXTERN_C LLVMTypeRef ZigLLVMTokenTypeInContext(LLVMContextRef context_ref);
6767
68ZIG_EXTERN_C LLVMValueRef ZigLLVMAddFunctionInAddressSpace(LLVMModuleRef M, const char *Name,
69 LLVMTypeRef FunctionTy, unsigned AddressSpace);
70
6871enum ZigLLVM_CallingConv {
6972 ZigLLVM_C = 0,
7073 ZigLLVM_Fast = 8,
test/behavior/type.zig+1
......@@ -137,6 +137,7 @@ test "@Type create slice with null sentinel" {
137137 .is_volatile = false,
138138 .is_allowzero = false,
139139 .alignment = 8,
140 .address_space = .generic,
140141 .child = *i32,
141142 .sentinel = null,
142143 },
test/cases.zig+12
......@@ -1807,4 +1807,16 @@ pub fn addCases(ctx: *TestContext) !void {
18071807 \\}
18081808 , "");
18091809 }
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 }
18101822}
test/compile_errors.zig+18
......@@ -711,6 +711,7 @@ pub fn addCases(ctx: *TestContext) !void {
711711 \\ .is_const = false,
712712 \\ .is_volatile = false,
713713 \\ .alignment = 1,
714 \\ .address_space = .generic,
714715 \\ .child = u8,
715716 \\ .is_allowzero = false,
716717 \\ .sentinel = 0,
......@@ -720,6 +721,23 @@ pub fn addCases(ctx: *TestContext) !void {
720721 "tmp.zig:2:16: error: sentinels are only allowed on slices and unknown-length pointers",
721722 });
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
723741 ctx.testErrStage1("helpful return type error message",
724742 \\export fn foo() u32 {
725743 \\ return error.Ohno;
test/stage2/llvm.zig+180
......@@ -242,4 +242,184 @@ pub fn addCases(ctx: *TestContext) !void {
242242 \\}
243243 , "");
244244 }
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 }
245425}