| author | |
| committer | |
| log | 7efc2a06264170632e56256a5fad97e945768056 |
| tree | f96446fade460810afbdf4ccc003be2069e378de |
| parent | 51a40f9a666085b53353f65f017bcf9bf18daaa3 |
* `@as` and `@bitCast` no longer unconditionally return `true` from
this function; they forward the question to their sub-expression.
* fix `@splat` incorrectly being marked as needing a memory location
(this function returns a SIMD vector; it definitely does not want a
memory location).
Makes AstGen generate slightly nicer ZIR, which in turn generates
slightly nicer AIR, generating slightly nicer machine code in debug
builds.
It also means I can procrastinate implementing the bitcast_result_ptr
ZIR instruction semantic analysis :^)2 files changed, 37 insertions(+), 15 deletions(-)
src/AstGen.zig+20-6| ... | ... | @@ -8271,17 +8271,31 @@ fn nodeMayNeedMemoryLocation(tree: *const Ast, start_node: Ast.Node.Index) bool |
| 8271 | 8271 | } |
| 8272 | 8272 | }, |
| 8273 | 8273 | |
| 8274 | .builtin_call, | |
| 8275 | .builtin_call_comma, | |
| 8276 | .builtin_call_two, | |
| 8277 | .builtin_call_two_comma, | |
| 8278 | => { | |
| 8274 | .builtin_call_two, .builtin_call_two_comma => { | |
| 8275 | const builtin_token = main_tokens[node]; | |
| 8276 | const builtin_name = tree.tokenSlice(builtin_token); | |
| 8277 | // If the builtin is an invalid name, we don't cause an error here; instead | |
| 8278 | // let it pass, and the error will be "invalid builtin function" later. | |
| 8279 | const builtin_info = BuiltinFn.list.get(builtin_name) orelse return false; | |
| 8280 | switch (builtin_info.needs_mem_loc) { | |
| 8281 | .never => return false, | |
| 8282 | .always => return true, | |
| 8283 | .forward1 => node = node_datas[node].rhs, | |
| 8284 | } | |
| 8285 | }, | |
| 8286 | ||
| 8287 | .builtin_call, .builtin_call_comma => { | |
| 8288 | const params = tree.extra_data[node_datas[node].lhs..node_datas[node].rhs]; | |
| 8279 | 8289 | const builtin_token = main_tokens[node]; |
| 8280 | 8290 | const builtin_name = tree.tokenSlice(builtin_token); |
| 8281 | 8291 | // If the builtin is an invalid name, we don't cause an error here; instead |
| 8282 | 8292 | // let it pass, and the error will be "invalid builtin function" later. |
| 8283 | 8293 | const builtin_info = BuiltinFn.list.get(builtin_name) orelse return false; |
| 8284 | return builtin_info.needs_mem_loc; | |
| 8294 | switch (builtin_info.needs_mem_loc) { | |
| 8295 | .never => return false, | |
| 8296 | .always => return true, | |
| 8297 | .forward1 => node = params[1], | |
| 8298 | } | |
| 8285 | 8299 | }, |
| 8286 | 8300 | } |
| 8287 | 8301 | } |
src/BuiltinFn.zig+17-9| ... | ... | @@ -110,10 +110,19 @@ pub const Tag = enum { |
| 110 | 110 | Vector, |
| 111 | 111 | }; |
| 112 | 112 | |
| 113 | pub const MemLocRequirement = enum { | |
| 114 | /// The builtin never needs a memory location. | |
| 115 | never, | |
| 116 | /// The builtin always needs a memory location. | |
| 117 | always, | |
| 118 | /// The builtin forwards the question to argument at index 1. | |
| 119 | forward1, | |
| 120 | }; | |
| 121 | ||
| 113 | 122 | tag: Tag, |
| 114 | 123 | |
| 115 | /// `true` if the builtin call can take advantage of a result location pointer. | |
| 116 | needs_mem_loc: bool = false, | |
| 124 | /// Info about the builtin call's ability to take advantage of a result location pointer. | |
| 125 | needs_mem_loc: MemLocRequirement = .never, | |
| 117 | 126 | /// `true` if the builtin call can be the left-hand side of an expression (assigned to). |
| 118 | 127 | allows_lvalue: bool = false, |
| 119 | 128 | /// The number of parameters to this builtin function. `null` means variable number |
| ... | ... | @@ -148,7 +157,7 @@ pub const list = list: { |
| 148 | 157 | "@as", |
| 149 | 158 | .{ |
| 150 | 159 | .tag = .as, |
| 151 | .needs_mem_loc = true, | |
| 160 | .needs_mem_loc = .forward1, | |
| 152 | 161 | .param_count = 2, |
| 153 | 162 | }, |
| 154 | 163 | }, |
| ... | ... | @@ -184,7 +193,7 @@ pub const list = list: { |
| 184 | 193 | "@bitCast", |
| 185 | 194 | .{ |
| 186 | 195 | .tag = .bit_cast, |
| 187 | .needs_mem_loc = true, | |
| 196 | .needs_mem_loc = .forward1, | |
| 188 | 197 | .param_count = 2, |
| 189 | 198 | }, |
| 190 | 199 | }, |
| ... | ... | @@ -248,7 +257,7 @@ pub const list = list: { |
| 248 | 257 | "@call", |
| 249 | 258 | .{ |
| 250 | 259 | .tag = .call, |
| 251 | .needs_mem_loc = true, | |
| 260 | .needs_mem_loc = .always, | |
| 252 | 261 | .param_count = 3, |
| 253 | 262 | }, |
| 254 | 263 | }, |
| ... | ... | @@ -410,7 +419,7 @@ pub const list = list: { |
| 410 | 419 | "@field", |
| 411 | 420 | .{ |
| 412 | 421 | .tag = .field, |
| 413 | .needs_mem_loc = true, | |
| 422 | .needs_mem_loc = .always, | |
| 414 | 423 | .param_count = 2, |
| 415 | 424 | .allows_lvalue = true, |
| 416 | 425 | }, |
| ... | ... | @@ -699,7 +708,6 @@ pub const list = list: { |
| 699 | 708 | "@splat", |
| 700 | 709 | .{ |
| 701 | 710 | .tag = .splat, |
| 702 | .needs_mem_loc = true, | |
| 703 | 711 | .param_count = 2, |
| 704 | 712 | }, |
| 705 | 713 | }, |
| ... | ... | @@ -714,7 +722,7 @@ pub const list = list: { |
| 714 | 722 | "@src", |
| 715 | 723 | .{ |
| 716 | 724 | .tag = .src, |
| 717 | .needs_mem_loc = true, | |
| 725 | .needs_mem_loc = .always, | |
| 718 | 726 | .param_count = 0, |
| 719 | 727 | }, |
| 720 | 728 | }, |
| ... | ... | @@ -869,7 +877,7 @@ pub const list = list: { |
| 869 | 877 | "@unionInit", |
| 870 | 878 | .{ |
| 871 | 879 | .tag = .union_init, |
| 872 | .needs_mem_loc = true, | |
| 880 | .needs_mem_loc = .always, | |
| 873 | 881 | .param_count = 3, |
| 874 | 882 | }, |
| 875 | 883 | }, |