| ... | ... | @@ -534,7 +534,7 @@ fn varDecl( |
| 534 | 534 | // Depending on the type of AST the initialization expression is, we may need an lvalue |
| 535 | 535 | // or an rvalue as a result location. If it is an rvalue, we can use the instruction as |
| 536 | 536 | // the variable, no memory location needed. |
| 537 | | const result_loc = if (nodeMayNeedMemoryLocation(init_node)) r: { |
| 537 | const result_loc = if (nodeMayNeedMemoryLocation(init_node, scope)) r: { |
| 538 | 538 | if (node.getTypeNode()) |type_node| { |
| 539 | 539 | const type_inst = try typeExpr(mod, scope, type_node); |
| 540 | 540 | const alloc = try addZIRUnOp(mod, scope, name_src, .alloc, type_inst); |
| ... | ... | @@ -1831,7 +1831,7 @@ fn ret(mod: *Module, scope: *Scope, cfe: *ast.Node.ControlFlowExpression) InnerE |
| 1831 | 1831 | const tree = scope.tree(); |
| 1832 | 1832 | const src = tree.token_locs[cfe.ltoken].start; |
| 1833 | 1833 | if (cfe.getRHS()) |rhs_node| { |
| 1834 | | if (nodeMayNeedMemoryLocation(rhs_node)) { |
| 1834 | if (nodeMayNeedMemoryLocation(rhs_node, scope)) { |
| 1835 | 1835 | const ret_ptr = try addZIRNoOp(mod, scope, src, .ret_ptr); |
| 1836 | 1836 | const operand = try expr(mod, scope, .{ .ptr = ret_ptr }, rhs_node); |
| 1837 | 1837 | return addZIRUnOp(mod, scope, src, .@"return", operand); |
| ... | ... | @@ -2248,6 +2248,23 @@ fn import(mod: *Module, scope: *Scope, call: *ast.Node.BuiltinCall) InnerError!* |
| 2248 | 2248 | return addZIRUnOp(mod, scope, src, .import, target); |
| 2249 | 2249 | } |
| 2250 | 2250 | |
| 2251 | fn typeOf(mod: *Module, scope: *Scope, rl: ResultLoc, call: *ast.Node.BuiltinCall) InnerError!*zir.Inst { |
| 2252 | const tree = scope.tree(); |
| 2253 | const arena = scope.arena(); |
| 2254 | const src = tree.token_locs[call.builtin_token].start; |
| 2255 | const params = call.params(); |
| 2256 | if (params.len < 1) { |
| 2257 | return mod.failTok(scope, call.builtin_token, "expected at least 1 argument, found 0", .{}); |
| 2258 | } |
| 2259 | if (params.len == 1) { |
| 2260 | return rlWrap(mod, scope, rl, try addZIRUnOp(mod, scope, src, .typeof, try expr(mod, scope, .none, params[0]))); |
| 2261 | } |
| 2262 | var items = try arena.alloc(*zir.Inst, params.len); |
| 2263 | for (params) |param, param_i| |
| 2264 | items[param_i] = try expr(mod, scope, .none, param); |
| 2265 | return rlWrap(mod, scope, rl, try addZIRInst(mod, scope, src, zir.Inst.TypeOfPeer, .{ .items = items }, .{})); |
| 2266 | } |
| 2267 | |
| 2251 | 2268 | fn builtinCall(mod: *Module, scope: *Scope, rl: ResultLoc, call: *ast.Node.BuiltinCall) InnerError!*zir.Inst { |
| 2252 | 2269 | const tree = scope.tree(); |
| 2253 | 2270 | const builtin_name = tree.tokenSlice(call.builtin_token); |
| ... | ... | @@ -2267,6 +2284,8 @@ fn builtinCall(mod: *Module, scope: *Scope, rl: ResultLoc, call: *ast.Node.Built |
| 2267 | 2284 | return simpleCast(mod, scope, rl, call, .intcast); |
| 2268 | 2285 | } else if (mem.eql(u8, builtin_name, "@bitCast")) { |
| 2269 | 2286 | return bitCast(mod, scope, rl, call); |
| 2287 | } else if (mem.eql(u8, builtin_name, "@TypeOf")) { |
| 2288 | return typeOf(mod, scope, rl, call); |
| 2270 | 2289 | } else if (mem.eql(u8, builtin_name, "@breakpoint")) { |
| 2271 | 2290 | const src = tree.token_locs[call.builtin_token].start; |
| 2272 | 2291 | return rlWrap(mod, scope, rl, try addZIRNoOp(mod, scope, src, .breakpoint)); |
| ... | ... | @@ -2344,7 +2363,7 @@ fn getSimplePrimitiveValue(name: []const u8) ?TypedValue { |
| 2344 | 2363 | return null; |
| 2345 | 2364 | } |
| 2346 | 2365 | |
| 2347 | | fn nodeMayNeedMemoryLocation(start_node: *ast.Node) bool { |
| 2366 | fn nodeMayNeedMemoryLocation(start_node: *ast.Node, scope: *Scope) bool { |
| 2348 | 2367 | var node = start_node; |
| 2349 | 2368 | while (true) { |
| 2350 | 2369 | switch (node.tag) { |
| ... | ... | @@ -2468,10 +2487,120 @@ fn nodeMayNeedMemoryLocation(start_node: *ast.Node) bool { |
| 2468 | 2487 | .For, |
| 2469 | 2488 | .Switch, |
| 2470 | 2489 | .Call, |
| 2471 | | .BuiltinCall, // TODO some of these can return false |
| 2472 | 2490 | .LabeledBlock, |
| 2473 | 2491 | => return true, |
| 2474 | 2492 | |
| 2493 | .BuiltinCall => { |
| 2494 | @setEvalBranchQuota(5000); |
| 2495 | const builtin_needs_mem_loc = std.ComptimeStringMap(bool, .{ |
| 2496 | .{ "@addWithOverflow", false }, |
| 2497 | .{ "@alignCast", false }, |
| 2498 | .{ "@alignOf", false }, |
| 2499 | .{ "@as", true }, |
| 2500 | .{ "@asyncCall", false }, |
| 2501 | .{ "@atomicLoad", false }, |
| 2502 | .{ "@atomicRmw", false }, |
| 2503 | .{ "@atomicStore", false }, |
| 2504 | .{ "@bitCast", true }, |
| 2505 | .{ "@bitOffsetOf", false }, |
| 2506 | .{ "@boolToInt", false }, |
| 2507 | .{ "@bitSizeOf", false }, |
| 2508 | .{ "@breakpoint", false }, |
| 2509 | .{ "@mulAdd", false }, |
| 2510 | .{ "@byteSwap", false }, |
| 2511 | .{ "@bitReverse", false }, |
| 2512 | .{ "@byteOffsetOf", false }, |
| 2513 | .{ "@call", true }, |
| 2514 | .{ "@cDefine", false }, |
| 2515 | .{ "@cImport", false }, |
| 2516 | .{ "@cInclude", false }, |
| 2517 | .{ "@clz", false }, |
| 2518 | .{ "@cmpxchgStrong", false }, |
| 2519 | .{ "@cmpxchgWeak", false }, |
| 2520 | .{ "@compileError", false }, |
| 2521 | .{ "@compileLog", false }, |
| 2522 | .{ "@ctz", false }, |
| 2523 | .{ "@cUndef", false }, |
| 2524 | .{ "@divExact", false }, |
| 2525 | .{ "@divFloor", false }, |
| 2526 | .{ "@divTrunc", false }, |
| 2527 | .{ "@embedFile", false }, |
| 2528 | .{ "@enumToInt", false }, |
| 2529 | .{ "@errorName", false }, |
| 2530 | .{ "@errorReturnTrace", false }, |
| 2531 | .{ "@errorToInt", false }, |
| 2532 | .{ "@errSetCast", false }, |
| 2533 | .{ "@export", false }, |
| 2534 | .{ "@fence", false }, |
| 2535 | .{ "@field", true }, |
| 2536 | .{ "@fieldParentPtr", false }, |
| 2537 | .{ "@floatCast", false }, |
| 2538 | .{ "@floatToInt", false }, |
| 2539 | .{ "@frame", false }, |
| 2540 | .{ "@Frame", false }, |
| 2541 | .{ "@frameAddress", false }, |
| 2542 | .{ "@frameSize", false }, |
| 2543 | .{ "@hasDecl", false }, |
| 2544 | .{ "@hasField", false }, |
| 2545 | .{ "@import", false }, |
| 2546 | .{ "@intCast", false }, |
| 2547 | .{ "@intToEnum", false }, |
| 2548 | .{ "@intToError", false }, |
| 2549 | .{ "@intToFloat", false }, |
| 2550 | .{ "@intToPtr", false }, |
| 2551 | .{ "@memcpy", false }, |
| 2552 | .{ "@memset", false }, |
| 2553 | .{ "@wasmMemorySize", false }, |
| 2554 | .{ "@wasmMemoryGrow", false }, |
| 2555 | .{ "@mod", false }, |
| 2556 | .{ "@mulWithOverflow", false }, |
| 2557 | .{ "@panic", false }, |
| 2558 | .{ "@popCount", false }, |
| 2559 | .{ "@ptrCast", false }, |
| 2560 | .{ "@ptrToInt", false }, |
| 2561 | .{ "@rem", false }, |
| 2562 | .{ "@returnAddress", false }, |
| 2563 | .{ "@setAlignStack", false }, |
| 2564 | .{ "@setCold", false }, |
| 2565 | .{ "@setEvalBranchQuota", false }, |
| 2566 | .{ "@setFloatMode", false }, |
| 2567 | .{ "@setRuntimeSafety", false }, |
| 2568 | .{ "@shlExact", false }, |
| 2569 | .{ "@shlWithOverflow", false }, |
| 2570 | .{ "@shrExact", false }, |
| 2571 | .{ "@shuffle", false }, |
| 2572 | .{ "@sizeOf", false }, |
| 2573 | .{ "@splat", true }, |
| 2574 | .{ "@reduce", false }, |
| 2575 | .{ "@src", true }, |
| 2576 | .{ "@sqrt", false }, |
| 2577 | .{ "@sin", false }, |
| 2578 | .{ "@cos", false }, |
| 2579 | .{ "@exp", false }, |
| 2580 | .{ "@exp2", false }, |
| 2581 | .{ "@log", false }, |
| 2582 | .{ "@log2", false }, |
| 2583 | .{ "@log10", false }, |
| 2584 | .{ "@fabs", false }, |
| 2585 | .{ "@floor", false }, |
| 2586 | .{ "@ceil", false }, |
| 2587 | .{ "@trunc", false }, |
| 2588 | .{ "@round", false }, |
| 2589 | .{ "@subWithOverflow", false }, |
| 2590 | .{ "@tagName", false }, |
| 2591 | .{ "@TagType", false }, |
| 2592 | .{ "@This", false }, |
| 2593 | .{ "@truncate", false }, |
| 2594 | .{ "@Type", false }, |
| 2595 | .{ "@typeInfo", false }, |
| 2596 | .{ "@typeName", false }, |
| 2597 | .{ "@TypeOf", false }, |
| 2598 | .{ "@unionInit", true }, |
| 2599 | }); |
| 2600 | const name = scope.tree().tokenSlice(node.castTag(.BuiltinCall).?.builtin_token); |
| 2601 | return builtin_needs_mem_loc.get(name).?; |
| 2602 | }, |
| 2603 | |
| 2475 | 2604 | // Depending on AST properties, they may need memory locations. |
| 2476 | 2605 | .If => return node.castTag(.If).?.@"else" != null, |
| 2477 | 2606 | } |