| ... | @@ -534,7 +534,7 @@ fn varDecl( | ... | @@ -534,7 +534,7 @@ fn varDecl( |
| 534 | // Depending on the type of AST the initialization expression is, we may need an lvalue | 534 | // Depending on the type of AST the initialization expression is, we may need an lvalue |
| 535 | // or an rvalue as a result location. If it is an rvalue, we can use the instruction as | 535 | // or an rvalue as a result location. If it is an rvalue, we can use the instruction as |
| 536 | // the variable, no memory location needed. | 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 | if (node.getTypeNode()) |type_node| { | 538 | if (node.getTypeNode()) |type_node| { |
| 539 | const type_inst = try typeExpr(mod, scope, type_node); | 539 | const type_inst = try typeExpr(mod, scope, type_node); |
| 540 | const alloc = try addZIRUnOp(mod, scope, name_src, .alloc, type_inst); | 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,7 +1831,7 @@ fn ret(mod: *Module, scope: *Scope, cfe: *ast.Node.ControlFlowExpression) InnerE |
| 1831 | const tree = scope.tree(); | 1831 | const tree = scope.tree(); |
| 1832 | const src = tree.token_locs[cfe.ltoken].start; | 1832 | const src = tree.token_locs[cfe.ltoken].start; |
| 1833 | if (cfe.getRHS()) |rhs_node| { | 1833 | if (cfe.getRHS()) |rhs_node| { |
| 1834 | if (nodeMayNeedMemoryLocation(rhs_node)) { | 1834 | if (nodeMayNeedMemoryLocation(rhs_node, scope)) { |
| 1835 | const ret_ptr = try addZIRNoOp(mod, scope, src, .ret_ptr); | 1835 | const ret_ptr = try addZIRNoOp(mod, scope, src, .ret_ptr); |
| 1836 | const operand = try expr(mod, scope, .{ .ptr = ret_ptr }, rhs_node); | 1836 | const operand = try expr(mod, scope, .{ .ptr = ret_ptr }, rhs_node); |
| 1837 | return addZIRUnOp(mod, scope, src, .@"return", operand); | 1837 | return addZIRUnOp(mod, scope, src, .@"return", operand); |
| ... | @@ -2248,6 +2248,23 @@ fn import(mod: *Module, scope: *Scope, call: *ast.Node.BuiltinCall) InnerError!* | ... | @@ -2248,6 +2248,23 @@ fn import(mod: *Module, scope: *Scope, call: *ast.Node.BuiltinCall) InnerError!* |
| 2248 | return addZIRUnOp(mod, scope, src, .import, target); | 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 | fn builtinCall(mod: *Module, scope: *Scope, rl: ResultLoc, call: *ast.Node.BuiltinCall) InnerError!*zir.Inst { | 2268 | fn builtinCall(mod: *Module, scope: *Scope, rl: ResultLoc, call: *ast.Node.BuiltinCall) InnerError!*zir.Inst { |
| 2252 | const tree = scope.tree(); | 2269 | const tree = scope.tree(); |
| 2253 | const builtin_name = tree.tokenSlice(call.builtin_token); | 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,6 +2284,8 @@ fn builtinCall(mod: *Module, scope: *Scope, rl: ResultLoc, call: *ast.Node.Built |
| 2267 | return simpleCast(mod, scope, rl, call, .intcast); | 2284 | return simpleCast(mod, scope, rl, call, .intcast); |
| 2268 | } else if (mem.eql(u8, builtin_name, "@bitCast")) { | 2285 | } else if (mem.eql(u8, builtin_name, "@bitCast")) { |
| 2269 | return bitCast(mod, scope, rl, call); | 2286 | return bitCast(mod, scope, rl, call); |
| | 2287 | } else if (mem.eql(u8, builtin_name, "@TypeOf")) { |
| | 2288 | return typeOf(mod, scope, rl, call); |
| 2270 | } else if (mem.eql(u8, builtin_name, "@breakpoint")) { | 2289 | } else if (mem.eql(u8, builtin_name, "@breakpoint")) { |
| 2271 | const src = tree.token_locs[call.builtin_token].start; | 2290 | const src = tree.token_locs[call.builtin_token].start; |
| 2272 | return rlWrap(mod, scope, rl, try addZIRNoOp(mod, scope, src, .breakpoint)); | 2291 | return rlWrap(mod, scope, rl, try addZIRNoOp(mod, scope, src, .breakpoint)); |
| ... | @@ -2344,7 +2363,7 @@ fn getSimplePrimitiveValue(name: []const u8) ?TypedValue { | ... | @@ -2344,7 +2363,7 @@ fn getSimplePrimitiveValue(name: []const u8) ?TypedValue { |
| 2344 | return null; | 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 | var node = start_node; | 2367 | var node = start_node; |
| 2349 | while (true) { | 2368 | while (true) { |
| 2350 | switch (node.tag) { | 2369 | switch (node.tag) { |
| ... | @@ -2468,10 +2487,120 @@ fn nodeMayNeedMemoryLocation(start_node: *ast.Node) bool { | ... | @@ -2468,10 +2487,120 @@ fn nodeMayNeedMemoryLocation(start_node: *ast.Node) bool { |
| 2468 | .For, | 2487 | .For, |
| 2469 | .Switch, | 2488 | .Switch, |
| 2470 | .Call, | 2489 | .Call, |
| 2471 | .BuiltinCall, // TODO some of these can return false | | |
| 2472 | .LabeledBlock, | 2490 | .LabeledBlock, |
| 2473 | => return true, | 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 | // Depending on AST properties, they may need memory locations. | 2604 | // Depending on AST properties, they may need memory locations. |
| 2476 | .If => return node.castTag(.If).?.@"else" != null, | 2605 | .If => return node.castTag(.If).?.@"else" != null, |
| 2477 | } | 2606 | } |