| ... | @@ -1902,9 +1902,6 @@ fn varDecl( | ... | @@ -1902,9 +1902,6 @@ fn varDecl( |
| 1902 | ) InnerError!*Scope { | 1902 | ) InnerError!*Scope { |
| 1903 | try emitDbgNode(gz, node); | 1903 | try emitDbgNode(gz, node); |
| 1904 | const astgen = gz.astgen; | 1904 | const astgen = gz.astgen; |
| 1905 | if (var_decl.ast.align_node != 0) { | | |
| 1906 | return astgen.failNode(var_decl.ast.align_node, "TODO implement alignment on locals", .{}); | | |
| 1907 | } | | |
| 1908 | const gpa = astgen.gpa; | 1905 | const gpa = astgen.gpa; |
| 1909 | const tree = &astgen.file.tree; | 1906 | const tree = &astgen.file.tree; |
| 1910 | const token_tags = tree.tokens.items(.tag); | 1907 | const token_tags = tree.tokens.items(.tag); |
| ... | @@ -1919,12 +1916,12 @@ fn varDecl( | ... | @@ -1919,12 +1916,12 @@ fn varDecl( |
| 1919 | .local_val => { | 1916 | .local_val => { |
| 1920 | const local_val = s.cast(Scope.LocalVal).?; | 1917 | const local_val = s.cast(Scope.LocalVal).?; |
| 1921 | if (mem.eql(u8, local_val.name, ident_name)) { | 1918 | if (mem.eql(u8, local_val.name, ident_name)) { |
| 1922 | return astgen.failTokNotes(name_token, "redefinition of '{s}'", .{ | 1919 | return astgen.failTokNotes(name_token, "redeclaration of '{s}'", .{ |
| 1923 | ident_name, | 1920 | ident_name, |
| 1924 | }, &[_]u32{ | 1921 | }, &[_]u32{ |
| 1925 | try astgen.errNoteTok( | 1922 | try astgen.errNoteTok( |
| 1926 | local_val.token_src, | 1923 | local_val.token_src, |
| 1927 | "previous definition is here", | 1924 | "previous declaration is here", |
| 1928 | .{}, | 1925 | .{}, |
| 1929 | ), | 1926 | ), |
| 1930 | }); | 1927 | }); |
| ... | @@ -1934,12 +1931,12 @@ fn varDecl( | ... | @@ -1934,12 +1931,12 @@ fn varDecl( |
| 1934 | .local_ptr => { | 1931 | .local_ptr => { |
| 1935 | const local_ptr = s.cast(Scope.LocalPtr).?; | 1932 | const local_ptr = s.cast(Scope.LocalPtr).?; |
| 1936 | if (mem.eql(u8, local_ptr.name, ident_name)) { | 1933 | if (mem.eql(u8, local_ptr.name, ident_name)) { |
| 1937 | return astgen.failTokNotes(name_token, "redefinition of '{s}'", .{ | 1934 | return astgen.failTokNotes(name_token, "redeclaration of '{s}'", .{ |
| 1938 | ident_name, | 1935 | ident_name, |
| 1939 | }, &[_]u32{ | 1936 | }, &[_]u32{ |
| 1940 | try astgen.errNoteTok( | 1937 | try astgen.errNoteTok( |
| 1941 | local_ptr.token_src, | 1938 | local_ptr.token_src, |
| 1942 | "previous definition is here", | 1939 | "previous declaration is here", |
| 1943 | .{}, | 1940 | .{}, |
| 1944 | ), | 1941 | ), |
| 1945 | }); | 1942 | }); |
| ... | @@ -1957,15 +1954,21 @@ fn varDecl( | ... | @@ -1957,15 +1954,21 @@ fn varDecl( |
| 1957 | return astgen.failNode(node, "variables must be initialized", .{}); | 1954 | return astgen.failNode(node, "variables must be initialized", .{}); |
| 1958 | } | 1955 | } |
| 1959 | | 1956 | |
| | 1957 | const align_inst: Zir.Inst.Ref = if (var_decl.ast.align_node != 0) |
| | 1958 | try expr(gz, scope, align_rl, var_decl.ast.align_node) |
| | 1959 | else |
| | 1960 | .none; |
| | 1961 | |
| 1960 | switch (token_tags[var_decl.ast.mut_token]) { | 1962 | switch (token_tags[var_decl.ast.mut_token]) { |
| 1961 | .keyword_const => { | 1963 | .keyword_const => { |
| 1962 | if (var_decl.comptime_token) |comptime_token| { | 1964 | if (var_decl.comptime_token) |comptime_token| { |
| 1963 | return astgen.failTok(comptime_token, "'comptime const' is redundant; instead wrap the initialization expression with 'comptime'", .{}); | 1965 | return astgen.failTok(comptime_token, "'comptime const' is redundant; instead wrap the initialization expression with 'comptime'", .{}); |
| 1964 | } | 1966 | } |
| | 1967 | |
| 1965 | // Depending on the type of AST the initialization expression is, we may need an lvalue | 1968 | // Depending on the type of AST the initialization expression is, we may need an lvalue |
| 1966 | // or an rvalue as a result location. If it is an rvalue, we can use the instruction as | 1969 | // or an rvalue as a result location. If it is an rvalue, we can use the instruction as |
| 1967 | // the variable, no memory location needed. | 1970 | // the variable, no memory location needed. |
| 1968 | if (!nodeMayNeedMemoryLocation(tree, var_decl.ast.init_node)) { | 1971 | if (align_inst == .none and !nodeMayNeedMemoryLocation(tree, var_decl.ast.init_node)) { |
| 1969 | const result_loc: ResultLoc = if (var_decl.ast.type_node != 0) .{ | 1972 | const result_loc: ResultLoc = if (var_decl.ast.type_node != 0) .{ |
| 1970 | .ty = try typeExpr(gz, scope, var_decl.ast.type_node), | 1973 | .ty = try typeExpr(gz, scope, var_decl.ast.type_node), |
| 1971 | } else .none; | 1974 | } else .none; |
| ... | @@ -1997,10 +2000,29 @@ fn varDecl( | ... | @@ -1997,10 +2000,29 @@ fn varDecl( |
| 1997 | if (var_decl.ast.type_node != 0) { | 2000 | if (var_decl.ast.type_node != 0) { |
| 1998 | const type_inst = try typeExpr(gz, &init_scope.base, var_decl.ast.type_node); | 2001 | const type_inst = try typeExpr(gz, &init_scope.base, var_decl.ast.type_node); |
| 1999 | opt_type_inst = type_inst; | 2002 | opt_type_inst = type_inst; |
| 2000 | init_scope.rl_ptr = try init_scope.addUnNode(.alloc, type_inst, node); | 2003 | if (align_inst == .none) { |
| | 2004 | init_scope.rl_ptr = try init_scope.addUnNode(.alloc, type_inst, node); |
| | 2005 | } else { |
| | 2006 | init_scope.rl_ptr = try gz.addAllocExtended(.{ |
| | 2007 | .node = node, |
| | 2008 | .type_inst = type_inst, |
| | 2009 | .align_inst = align_inst, |
| | 2010 | .is_const = true, |
| | 2011 | .is_comptime = false, |
| | 2012 | }); |
| | 2013 | } |
| 2001 | init_scope.rl_ty_inst = type_inst; | 2014 | init_scope.rl_ty_inst = type_inst; |
| 2002 | } else { | 2015 | } else { |
| 2003 | const alloc = try init_scope.addNode(.alloc_inferred, node); | 2016 | const alloc = if (align_inst == .none) |
| | 2017 | try init_scope.addNode(.alloc_inferred, node) |
| | 2018 | else |
| | 2019 | try gz.addAllocExtended(.{ |
| | 2020 | .node = node, |
| | 2021 | .type_inst = .none, |
| | 2022 | .align_inst = align_inst, |
| | 2023 | .is_const = true, |
| | 2024 | .is_comptime = false, |
| | 2025 | }); |
| 2004 | resolve_inferred_alloc = alloc; | 2026 | resolve_inferred_alloc = alloc; |
| 2005 | init_scope.rl_ptr = alloc; | 2027 | init_scope.rl_ptr = alloc; |
| 2006 | } | 2028 | } |
| ... | @@ -2010,7 +2032,7 @@ fn varDecl( | ... | @@ -2010,7 +2032,7 @@ fn varDecl( |
| 2010 | const zir_datas = astgen.instructions.items(.data); | 2032 | const zir_datas = astgen.instructions.items(.data); |
| 2011 | | 2033 | |
| 2012 | const parent_zir = &gz.instructions; | 2034 | const parent_zir = &gz.instructions; |
| 2013 | if (init_scope.rvalue_rl_count == 1) { | 2035 | if (align_inst == .none and init_scope.rvalue_rl_count == 1) { |
| 2014 | // Result location pointer not used. We don't need an alloc for this | 2036 | // Result location pointer not used. We don't need an alloc for this |
| 2015 | // const local, and type inference becomes trivial. | 2037 | // const local, and type inference becomes trivial. |
| 2016 | // Move the init_scope instructions into the parent scope, eliding | 2038 | // Move the init_scope instructions into the parent scope, eliding |
| ... | @@ -2070,12 +2092,36 @@ fn varDecl( | ... | @@ -2070,12 +2092,36 @@ fn varDecl( |
| 2070 | alloc: Zir.Inst.Ref, | 2092 | alloc: Zir.Inst.Ref, |
| 2071 | } = if (var_decl.ast.type_node != 0) a: { | 2093 | } = if (var_decl.ast.type_node != 0) a: { |
| 2072 | const type_inst = try typeExpr(gz, scope, var_decl.ast.type_node); | 2094 | const type_inst = try typeExpr(gz, scope, var_decl.ast.type_node); |
| 2073 | const tag: Zir.Inst.Tag = if (is_comptime) .alloc_comptime else .alloc_mut; | 2095 | const alloc = alloc: { |
| 2074 | const alloc = try gz.addUnNode(tag, type_inst, node); | 2096 | if (align_inst == .none) { |
| | 2097 | const tag: Zir.Inst.Tag = if (is_comptime) .alloc_comptime else .alloc_mut; |
| | 2098 | break :alloc try gz.addUnNode(tag, type_inst, node); |
| | 2099 | } else { |
| | 2100 | break :alloc try gz.addAllocExtended(.{ |
| | 2101 | .node = node, |
| | 2102 | .type_inst = type_inst, |
| | 2103 | .align_inst = align_inst, |
| | 2104 | .is_const = false, |
| | 2105 | .is_comptime = is_comptime, |
| | 2106 | }); |
| | 2107 | } |
| | 2108 | }; |
| 2075 | break :a .{ .alloc = alloc, .result_loc = .{ .ptr = alloc } }; | 2109 | break :a .{ .alloc = alloc, .result_loc = .{ .ptr = alloc } }; |
| 2076 | } else a: { | 2110 | } else a: { |
| 2077 | const tag: Zir.Inst.Tag = if (is_comptime) .alloc_inferred_comptime else .alloc_inferred_mut; | 2111 | const alloc = alloc: { |
| 2078 | const alloc = try gz.addNode(tag, node); | 2112 | if (align_inst == .none) { |
| | 2113 | const tag: Zir.Inst.Tag = if (is_comptime) .alloc_inferred_comptime else .alloc_inferred_mut; |
| | 2114 | break :alloc try gz.addNode(tag, node); |
| | 2115 | } else { |
| | 2116 | break :alloc try gz.addAllocExtended(.{ |
| | 2117 | .node = node, |
| | 2118 | .type_inst = .none, |
| | 2119 | .align_inst = align_inst, |
| | 2120 | .is_const = false, |
| | 2121 | .is_comptime = is_comptime, |
| | 2122 | }); |
| | 2123 | } |
| | 2124 | }; |
| 2079 | resolve_inferred_alloc = alloc; | 2125 | resolve_inferred_alloc = alloc; |
| 2080 | break :a .{ .alloc = alloc, .result_loc = .{ .inferred_ptr = alloc } }; | 2126 | break :a .{ .alloc = alloc, .result_loc = .{ .inferred_ptr = alloc } }; |
| 2081 | }; | 2127 | }; |