| author | |
| committer | |
| log | b7900de1684021ff86c67105e14e34968821ea02 |
| tree | b881a288071705ffb8cd65ede5f8e7a1452b6dce |
| parent | 20145016ac0d098e8e63d5107a05eca376d1e7bb |
| parent | e2bb92b2e27dc54852a0227345e294ae383358fd |
72 files changed, 1691 insertions(+), 580 deletions(-)
.github/CODEOWNERS+2-1| ... | @@ -1,3 +1,4 @@ | ... | @@ -1,3 +1,4 @@ |
| 1 | # Autodoc | 1 | # Autodoc |
| 2 | /src/Autodoc.zig @kristoff-it | 2 | /src/Autodoc.zig @kristoff-it |
| 3 | /lib/docs/* @kristoff-it | ||
| \ No newline at end of file | |||
| 3 | /src/autodoc/* @kristoff-it | ||
| 4 | /lib/docs/* @kristoff-it | ||
ci/azure/macos_script+1| ... | @@ -52,6 +52,7 @@ stage3-release/bin/zig build test docs \ | ... | @@ -52,6 +52,7 @@ stage3-release/bin/zig build test docs \ |
| 52 | --zig-lib-dir "$(pwd)/../lib" \ | 52 | --zig-lib-dir "$(pwd)/../lib" \ |
| 53 | -Denable-macos-sdk \ | 53 | -Denable-macos-sdk \ |
| 54 | -Dstatic-llvm \ | 54 | -Dstatic-llvm \ |
| 55 | -Dskip-non-native \ | ||
| 55 | --search-prefix "$PREFIX" | 56 | --search-prefix "$PREFIX" |
| 56 | 57 | ||
| 57 | if [ "${BUILD_REASON}" != "PullRequest" ]; then | 58 | if [ "${BUILD_REASON}" != "PullRequest" ]; then |
ci/drone/test_linux_misc+1-1| ... | @@ -16,4 +16,4 @@ $ZIG build test-universal-libc -Dskip-non-native --zig-lib-dir lib | ... | @@ -16,4 +16,4 @@ $ZIG build test-universal-libc -Dskip-non-native --zig-lib-dir lib |
| 16 | $ZIG build test-stack-traces -Dskip-non-native --zig-lib-dir lib | 16 | $ZIG build test-stack-traces -Dskip-non-native --zig-lib-dir lib |
| 17 | $ZIG build test-cli -Dskip-non-native --zig-lib-dir lib | 17 | $ZIG build test-cli -Dskip-non-native --zig-lib-dir lib |
| 18 | $ZIG build test-asm-link -Dskip-non-native --zig-lib-dir lib | 18 | $ZIG build test-asm-link -Dskip-non-native --zig-lib-dir lib |
| 19 | $ZIG build test-translate-c -Dskip-non-native --zig-lib-dir lib | 19 | # $ZIG build test-translate-c -Dskip-non-native --zig-lib-dir lib |
ci/srht/update_download_page+37-21| ... | @@ -101,32 +101,48 @@ CIDIR="$(pwd)" | ... | @@ -101,32 +101,48 @@ CIDIR="$(pwd)" |
| 101 | 101 | ||
| 102 | cd "$HOME" | 102 | cd "$HOME" |
| 103 | 103 | ||
| 104 | # Upload new stdlib autodocs | 104 | # Update autodocs and langref directly to S3 in order to prevent the |
| 105 | mkdir -p docs_to_upload/documentation/master/std/ | 105 | # www.ziglang.org git repo from growing too big. |
| 106 | gzip -c -9 "$ZIGDIR/docs/std/index.html" > docs_to_upload/documentation/master/std/index.html | 106 | |
| 107 | gzip -c -9 "$ZIGDIR/docs/std/data.js" > docs_to_upload/documentation/master/std/data.js | 107 | # Please do not edit this script to pre-compress the artifacts before they hit |
| 108 | gzip -c -9 "$ZIGDIR/docs/std/main.js" > docs_to_upload/documentation/master/std/main.js | 108 | # S3. This prevents the website from working on browsers that do not support gzip |
| 109 | gzip -c -9 "$LANGREF" > docs_to_upload/documentation/master/index.html | 109 | # encoding. Cloudfront will automatically compress files if they are less than |
| 110 | $S3CMD put -P --no-mime-magic --recursive --add-header="Content-Encoding:gzip" --add-header="Cache-Control: max-age=0, must-revalidate" "docs_to_upload/" s3://ziglang.org/ | 110 | # 9.5 MiB, and the client advertises itself as capable of decompressing. |
| 111 | 111 | # The data.js file is currently 16 MiB. In order to fix this problem, we need to do | |
| 112 | mkdir -p docs_src_to_upload/documentation/master/std/ | 112 | # one of the following things: |
| 113 | cp -r "$ZIGDIR/docs/std/src" docs_src_to_upload/documentation/master/std/ | 113 | # * Reduce the size of data.js to less than 9.5 MiB. |
| 114 | $S3CMD put -P --no-mime-magic --recursive --add-header:"Content-Type:text/html" --add-header="Cache-Control: max-age=0, must-revalidate" "docs_src_to_upload/" s3://ziglang.org/ | 114 | # * Figure out how to adjust the Cloudfront settings to increase the max size for |
| 115 | 115 | # auto-compressed objects. | |
| 116 | ## Copy without compression: | 116 | # * Migrate to fastly. |
| 117 | # mkdir -p docs_to_upload/documentation/master/std/ | 117 | $S3CMD put -P --no-mime-magic \ |
| 118 | # cp "$ZIGDIR/docs/std/index.html" docs_to_upload/documentation/master/std/index.html | 118 | --add-header="Cache-Control: max-age=0, must-revalidate" \ |
| 119 | # cp "$ZIGDIR/docs/std/data.js" docs_to_upload/documentation/master/std/data.js | 119 | "$LANGREF" s3://ziglang.org/documentation/master/index.html |
| 120 | # cp "$ZIGDIR/docs/std/main.js" docs_to_upload/documentation/master/std/main.js | 120 | |
| 121 | # cp "$LANGREF" docs_to_upload/documentation/master/index.html | 121 | $S3CMD put -P --no-mime-magic \ |
| 122 | # $S3CMD put -P --no-mime-magic --recursive --add-header="Cache-Control: max-age=0, must-revalidate" "docs_to_upload/" s3://ziglang.org/ | 122 | --add-header="Cache-Control: max-age=0, must-revalidate" \ |
| 123 | "$ZIGDIR/docs/std/index.html" s3://ziglang.org/documentation/master/std/index.html | ||
| 124 | |||
| 125 | $S3CMD put -P --no-mime-magic \ | ||
| 126 | --add-header="Cache-Control: max-age=0, must-revalidate" \ | ||
| 127 | "$ZIGDIR/docs/std/main.js" s3://ziglang.org/documentation/master/std/main.js | ||
| 128 | |||
| 129 | $S3CMD put -P --no-mime-magic \ | ||
| 130 | --add-header="Cache-Control: max-age=0, must-revalidate" \ | ||
| 131 | "$ZIGDIR/docs/std/data.js" s3://ziglang.org/documentation/master/std/data.js | ||
| 132 | |||
| 133 | $S3CMD put -P --no-mime-magic --recursive \ | ||
| 134 | --add-header="Cache-Control: max-age=0, must-revalidate" \ | ||
| 135 | -m "text/html" \ | ||
| 136 | "$ZIGDIR/docs/std/src/" s3://ziglang.org/documentation/master/std/src/ | ||
| 137 | |||
| 138 | $S3CMD put -P --no-mime-magic \ | ||
| 139 | --add-header="cache-control: public, max-age=31536000, immutable" \ | ||
| 140 | "$HOME/$SRC_TARBALL" s3://ziglang.org/builds/ | ||
| 123 | 141 | ||
| 124 | git clone --depth 1 git@github.com:ziglang/www.ziglang.org.git | 142 | git clone --depth 1 git@github.com:ziglang/www.ziglang.org.git |
| 125 | cd www.ziglang.org | 143 | cd www.ziglang.org |
| 126 | WWWDIR="$(pwd)" | 144 | WWWDIR="$(pwd)" |
| 127 | 145 | ||
| 128 | $S3CMD put -P --no-mime-magic --add-header="cache-control: public, max-age=31536000, immutable" "$HOME/$SRC_TARBALL" s3://ziglang.org/builds/ | ||
| 129 | |||
| 130 | cd "$WWWDIR" | 146 | cd "$WWWDIR" |
| 131 | cp "$CIDIR/out/index.json" data/releases.json | 147 | cp "$CIDIR/out/index.json" data/releases.json |
| 132 | git add data/releases.json | 148 | git add data/releases.json |
ci/zinc/drone.yml+5| ... | @@ -75,6 +75,11 @@ steps: | ... | @@ -75,6 +75,11 @@ steps: |
| 75 | depends_on: | 75 | depends_on: |
| 76 | - macos_package | 76 | - macos_package |
| 77 | - linux_package | 77 | - linux_package |
| 78 | when: | ||
| 79 | branch: | ||
| 80 | - master | ||
| 81 | event: | ||
| 82 | - push | ||
| 78 | image: ci/debian-amd64:11.1-9 | 83 | image: ci/debian-amd64:11.1-9 |
| 79 | environment: | 84 | environment: |
| 80 | SRHT_OAUTH_TOKEN: | 85 | SRHT_OAUTH_TOKEN: |
ci/zinc/linux_package+1-1| ... | @@ -29,7 +29,7 @@ tar cfJ "$TARBALL" "$BASENAME" | ... | @@ -29,7 +29,7 @@ tar cfJ "$TARBALL" "$BASENAME" |
| 29 | SHASUM=$(sha256sum $TARBALL | cut '-d ' -f1) | 29 | SHASUM=$(sha256sum $TARBALL | cut '-d ' -f1) |
| 30 | BYTESIZE=$(wc -c < $TARBALL) | 30 | BYTESIZE=$(wc -c < $TARBALL) |
| 31 | 31 | ||
| 32 | MANIFEST="manifest.json" | 32 | MANIFEST="manifest-$TARGET.json" |
| 33 | touch $MANIFEST | 33 | touch $MANIFEST |
| 34 | echo "{\"tarball\": \"$TARBALL\"," >>$MANIFEST | 34 | echo "{\"tarball\": \"$TARBALL\"," >>$MANIFEST |
| 35 | echo "\"shasum\": \"$SHASUM\"," >>$MANIFEST | 35 | echo "\"shasum\": \"$SHASUM\"," >>$MANIFEST |
ci/zinc/macos_package+1-1| ... | @@ -33,7 +33,7 @@ tar cfJ "$TARBALL" "$BASENAME" | ... | @@ -33,7 +33,7 @@ tar cfJ "$TARBALL" "$BASENAME" |
| 33 | SHASUM=$(sha256sum $TARBALL | cut '-d ' -f1) | 33 | SHASUM=$(sha256sum $TARBALL | cut '-d ' -f1) |
| 34 | BYTESIZE=$(wc -c < $TARBALL) | 34 | BYTESIZE=$(wc -c < $TARBALL) |
| 35 | 35 | ||
| 36 | MANIFEST="manifest.json" | 36 | MANIFEST="manifest-$TARGET.json" |
| 37 | touch $MANIFEST | 37 | touch $MANIFEST |
| 38 | echo "{\"tarball\": \"$TARBALL\"," >>$MANIFEST | 38 | echo "{\"tarball\": \"$TARBALL\"," >>$MANIFEST |
| 39 | echo "\"shasum\": \"$SHASUM\"," >>$MANIFEST | 39 | echo "\"shasum\": \"$SHASUM\"," >>$MANIFEST |
doc/langref.html.in+1-1| ... | @@ -2631,7 +2631,7 @@ test "Conversion between vectors, arrays, and slices" { | ... | @@ -2631,7 +2631,7 @@ test "Conversion between vectors, arrays, and slices" { |
| 2631 | </li> | 2631 | </li> |
| 2632 | </ul> | 2632 | </ul> |
| 2633 | <ul> | 2633 | <ul> |
| 2634 | <li>{#syntax#}[]T{#endsyntax#} - pointer to runtime-known number of items. | 2634 | <li>{#syntax#}[]T{#endsyntax#} - is a slice (a fat pointer, which contains a pointer of type {#syntax#}[*]T{#endsyntax#} and a length). |
| 2635 | <ul> | 2635 | <ul> |
| 2636 | <li>Supports index syntax: {#syntax#}slice[i]{#endsyntax#}</li> | 2636 | <li>Supports index syntax: {#syntax#}slice[i]{#endsyntax#}</li> |
| 2637 | <li>Supports slice syntax: {#syntax#}slice[start..end]{#endsyntax#}</li> | 2637 | <li>Supports slice syntax: {#syntax#}slice[start..end]{#endsyntax#}</li> |
lib/docs/index.html+15-1| ... | @@ -359,7 +359,17 @@ | ... | @@ -359,7 +359,17 @@ |
| 359 | 359 | ||
| 360 | #listFns dt { | 360 | #listFns dt { |
| 361 | font-family: var(--mono); | 361 | font-family: var(--mono); |
| 362 | display: flex; | ||
| 363 | flex-direction: colunm; | ||
| 364 | justify-content: space-between; | ||
| 365 | } | ||
| 366 | |||
| 367 | #listFns dt .fnSignature { | ||
| 368 | overflow-x: hidden; | ||
| 369 | white-space: nowrap; | ||
| 370 | text-overflow: ellipsis; | ||
| 362 | } | 371 | } |
| 372 | |||
| 363 | .argBreaker { | 373 | .argBreaker { |
| 364 | display: none; | 374 | display: none; |
| 365 | } | 375 | } |
| ... | @@ -711,7 +721,11 @@ | ... | @@ -711,7 +721,11 @@ |
| 711 | <h2>Examples</h2> | 721 | <h2>Examples</h2> |
| 712 | <ul id="listFnExamples" class="examples"></ul> | 722 | <ul id="listFnExamples" class="examples"></ul> |
| 713 | </div> | 723 | </div> |
| 714 | <div id="sectTests" class="hidden"> | 724 | <div id="sectDocTests" class="hidden"> |
| 725 | <h2>DocTests</h2> | ||
| 726 | <pre id="docTestsCode"></pre> | ||
| 727 | </div> | ||
| 728 | <div id="sectTests" class="hidden"> | ||
| 715 | <h2>Tests</h2> | 729 | <h2>Tests</h2> |
| 716 | <div class="table-container"> | 730 | <div class="table-container"> |
| 717 | <table> | 731 | <table> |
lib/docs/main.js+53-8| ... | @@ -13,6 +13,8 @@ var zigAnalysis; | ... | @@ -13,6 +13,8 @@ var zigAnalysis; |
| 13 | const domListTypes = document.getElementById("listTypes"); | 13 | const domListTypes = document.getElementById("listTypes"); |
| 14 | const domSectTests = document.getElementById("sectTests"); | 14 | const domSectTests = document.getElementById("sectTests"); |
| 15 | const domListTests = document.getElementById("listTests"); | 15 | const domListTests = document.getElementById("listTests"); |
| 16 | const domSectDocTests = document.getElementById("sectDocTests"); | ||
| 17 | const domDocTestsCode = document.getElementById("docTestsCode"); | ||
| 16 | const domSectNamespaces = document.getElementById("sectNamespaces"); | 18 | const domSectNamespaces = document.getElementById("sectNamespaces"); |
| 17 | const domListNamespaces = document.getElementById("listNamespaces"); | 19 | const domListNamespaces = document.getElementById("listNamespaces"); |
| 18 | const domSectErrSets = document.getElementById("sectErrSets"); | 20 | const domSectErrSets = document.getElementById("sectErrSets"); |
| ... | @@ -241,7 +243,8 @@ var zigAnalysis; | ... | @@ -241,7 +243,8 @@ var zigAnalysis; |
| 241 | return ( | 243 | return ( |
| 242 | typeKind === typeKinds.Struct || | 244 | typeKind === typeKinds.Struct || |
| 243 | typeKind === typeKinds.Union || | 245 | typeKind === typeKinds.Union || |
| 244 | typeKind === typeKinds.Enum | 246 | typeKind === typeKinds.Enum || |
| 247 | typeKind === typeKinds.Opaque | ||
| 245 | ); | 248 | ); |
| 246 | } | 249 | } |
| 247 | 250 | ||
| ... | @@ -384,6 +387,7 @@ var zigAnalysis; | ... | @@ -384,6 +387,7 @@ var zigAnalysis; |
| 384 | domSectPkgs.classList.add("hidden"); | 387 | domSectPkgs.classList.add("hidden"); |
| 385 | domSectTypes.classList.add("hidden"); | 388 | domSectTypes.classList.add("hidden"); |
| 386 | domSectTests.classList.add("hidden"); | 389 | domSectTests.classList.add("hidden"); |
| 390 | domSectDocTests.classList.add("hidden"); | ||
| 387 | domSectNamespaces.classList.add("hidden"); | 391 | domSectNamespaces.classList.add("hidden"); |
| 388 | domSectErrSets.classList.add("hidden"); | 392 | domSectErrSets.classList.add("hidden"); |
| 389 | domSectFns.classList.add("hidden"); | 393 | domSectFns.classList.add("hidden"); |
| ... | @@ -452,6 +456,10 @@ var zigAnalysis; | ... | @@ -452,6 +456,10 @@ var zigAnalysis; |
| 452 | let lastIsDecl = isDecl(last); | 456 | let lastIsDecl = isDecl(last); |
| 453 | let lastIsType = isType(last); | 457 | let lastIsType = isType(last); |
| 454 | let lastIsContainerType = isContainerType(last); | 458 | let lastIsContainerType = isContainerType(last); |
| 459 | |||
| 460 | if (lastIsDecl){ | ||
| 461 | renderDocTest(last); | ||
| 462 | } | ||
| 455 | 463 | ||
| 456 | if (lastIsContainerType) { | 464 | if (lastIsContainerType) { |
| 457 | return renderContainer(last); | 465 | return renderContainer(last); |
| ... | @@ -477,6 +485,14 @@ var zigAnalysis; | ... | @@ -477,6 +485,14 @@ var zigAnalysis; |
| 477 | 485 | ||
| 478 | return renderValue(last); | 486 | return renderValue(last); |
| 479 | } | 487 | } |
| 488 | |||
| 489 | } | ||
| 490 | |||
| 491 | function renderDocTest(decl) { | ||
| 492 | if (!("decltest" in decl)) return; | ||
| 493 | const astNode = zigAnalysis.astNodes[decl.decltest]; | ||
| 494 | domSectDocTests.classList.remove("hidden"); | ||
| 495 | domDocTestsCode.innerHTML = astNode.code; | ||
| 480 | } | 496 | } |
| 481 | 497 | ||
| 482 | function renderUnknownDecl(decl) { | 498 | function renderUnknownDecl(decl) { |
| ... | @@ -1405,6 +1421,30 @@ var zigAnalysis; | ... | @@ -1405,6 +1421,30 @@ var zigAnalysis; |
| 1405 | operator += "**"; | 1421 | operator += "**"; |
| 1406 | break; | 1422 | break; |
| 1407 | } | 1423 | } |
| 1424 | case "cmp_eq": { | ||
| 1425 | operator += "=="; | ||
| 1426 | break; | ||
| 1427 | } | ||
| 1428 | case "cmp_neq": { | ||
| 1429 | operator += "!="; | ||
| 1430 | break; | ||
| 1431 | } | ||
| 1432 | case "cmp_gt": { | ||
| 1433 | operator += ">"; | ||
| 1434 | break; | ||
| 1435 | } | ||
| 1436 | case "cmp_gte": { | ||
| 1437 | operator += ">="; | ||
| 1438 | break; | ||
| 1439 | } | ||
| 1440 | case "cmp_lt": { | ||
| 1441 | operator += "<"; | ||
| 1442 | break; | ||
| 1443 | } | ||
| 1444 | case "cmp_lte": { | ||
| 1445 | operator += "<="; | ||
| 1446 | break; | ||
| 1447 | } | ||
| 1408 | default: | 1448 | default: |
| 1409 | console.log("operator not handled yet or doesn't exist!"); | 1449 | console.log("operator not handled yet or doesn't exist!"); |
| 1410 | } | 1450 | } |
| ... | @@ -1555,6 +1595,10 @@ var zigAnalysis; | ... | @@ -1555,6 +1595,10 @@ var zigAnalysis; |
| 1555 | return '"' + escapeHtml(expr.string) + '"'; | 1595 | return '"' + escapeHtml(expr.string) + '"'; |
| 1556 | } | 1596 | } |
| 1557 | 1597 | ||
| 1598 | case "int_big": { | ||
| 1599 | return (expr.int_big.negated ? "-" : "") + expr.int_big.value; | ||
| 1600 | } | ||
| 1601 | |||
| 1558 | case "anytype": { | 1602 | case "anytype": { |
| 1559 | return "anytype"; | 1603 | return "anytype"; |
| 1560 | } | 1604 | } |
| ... | @@ -1581,8 +1625,7 @@ var zigAnalysis; | ... | @@ -1581,8 +1625,7 @@ var zigAnalysis; |
| 1581 | } | 1625 | } |
| 1582 | case typeKinds.Opaque: { | 1626 | case typeKinds.Opaque: { |
| 1583 | let opaqueObj = typeObj; | 1627 | let opaqueObj = typeObj; |
| 1584 | 1628 | return opaqueObj; | |
| 1585 | return opaqueObj.name; | ||
| 1586 | } | 1629 | } |
| 1587 | case typeKinds.ComptimeExpr: { | 1630 | case typeKinds.ComptimeExpr: { |
| 1588 | return "anyopaque"; | 1631 | return "anyopaque"; |
| ... | @@ -2285,7 +2328,7 @@ var zigAnalysis; | ... | @@ -2285,7 +2328,7 @@ var zigAnalysis; |
| 2285 | 2328 | ||
| 2286 | return "<a style=\"float: right;\" href=\"" + | 2329 | return "<a style=\"float: right;\" href=\"" + |
| 2287 | sourceFileUrlTemplate.replace("{{file}}", | 2330 | sourceFileUrlTemplate.replace("{{file}}", |
| 2288 | zigAnalysis.files[srcNode.file]).replace("{{line}}", srcNode.line) + "\">[src]</a>"; | 2331 | zigAnalysis.files[srcNode.file]).replace("{{line}}", srcNode.line + 1) + "\">[src]</a>"; |
| 2289 | } | 2332 | } |
| 2290 | 2333 | ||
| 2291 | function renderContainer(container) { | 2334 | function renderContainer(container) { |
| ... | @@ -2393,24 +2436,26 @@ var zigAnalysis; | ... | @@ -2393,24 +2436,26 @@ var zigAnalysis; |
| 2393 | resizeDomList( | 2436 | resizeDomList( |
| 2394 | domListFns, | 2437 | domListFns, |
| 2395 | fnsList.length, | 2438 | fnsList.length, |
| 2396 | "<div><dt></dt><dd></dd></div>" | 2439 | "<div><dt><div class=\"fnSignature\"></div><div></div></dt><dd></dd></div>" |
| 2397 | ); | 2440 | ); |
| 2398 | 2441 | ||
| 2399 | for (let i = 0; i < fnsList.length; i += 1) { | 2442 | for (let i = 0; i < fnsList.length; i += 1) { |
| 2400 | let decl = fnsList[i]; | 2443 | let decl = fnsList[i]; |
| 2401 | let trDom = domListFns.children[i]; | 2444 | let trDom = domListFns.children[i]; |
| 2402 | 2445 | ||
| 2403 | let tdFnCode = trDom.children[0]; | 2446 | let tdFnSignature = trDom.children[0].children[0]; |
| 2447 | let tdFnSrc = trDom.children[0].children[1]; | ||
| 2404 | let tdDesc = trDom.children[1]; | 2448 | let tdDesc = trDom.children[1]; |
| 2405 | 2449 | ||
| 2406 | let declType = resolveValue(decl.value); | 2450 | let declType = resolveValue(decl.value); |
| 2407 | console.assert("type" in declType.expr); | 2451 | console.assert("type" in declType.expr); |
| 2408 | tdFnCode.innerHTML = exprName(declType.expr, { | 2452 | tdFnSignature.innerHTML = exprName(declType.expr, { |
| 2409 | wantHtml: true, | 2453 | wantHtml: true, |
| 2410 | wantLink: true, | 2454 | wantLink: true, |
| 2411 | fnDecl: decl, | 2455 | fnDecl: decl, |
| 2412 | linkFnNameDecl: navLinkDecl(decl.name), | 2456 | linkFnNameDecl: navLinkDecl(decl.name), |
| 2413 | }) + renderSourceFileLink(decl); | 2457 | }); |
| 2458 | tdFnSrc.innerHTML = renderSourceFileLink(decl); | ||
| 2414 | 2459 | ||
| 2415 | let docs = zigAnalysis.astNodes[decl.src].docs; | 2460 | let docs = zigAnalysis.astNodes[decl.src].docs; |
| 2416 | if (docs != null) { | 2461 | if (docs != null) { |
lib/std/Thread.zig+2-5| ... | @@ -769,16 +769,13 @@ const LinuxThreadImpl = struct { | ... | @@ -769,16 +769,13 @@ const LinuxThreadImpl = struct { |
| 769 | ), | 769 | ), |
| 770 | .x86_64 => asm volatile ( | 770 | .x86_64 => asm volatile ( |
| 771 | \\ movq $11, %%rax | 771 | \\ movq $11, %%rax |
| 772 | \\ movq %[ptr], %%rbx | ||
| 773 | \\ movq %[len], %%rcx | ||
| 774 | \\ syscall | 772 | \\ syscall |
| 775 | \\ movq $60, %%rax | 773 | \\ movq $60, %%rax |
| 776 | \\ movq $1, %%rdi | 774 | \\ movq $1, %%rdi |
| 777 | \\ syscall | 775 | \\ syscall |
| 778 | : | 776 | : |
| 779 | : [ptr] "r" (@ptrToInt(self.mapped.ptr)), | 777 | : [ptr] "{rdi}" (@ptrToInt(self.mapped.ptr)), |
| 780 | [len] "r" (self.mapped.len), | 778 | [len] "{rsi}" (self.mapped.len), |
| 781 | : "memory" | ||
| 782 | ), | 779 | ), |
| 783 | .arm, .armeb, .thumb, .thumbeb => asm volatile ( | 780 | .arm, .armeb, .thumb, .thumbeb => asm volatile ( |
| 784 | \\ mov r7, #91 | 781 | \\ mov r7, #91 |
lib/std/coff.zig+85| ... | @@ -419,6 +419,91 @@ pub const DebugType = enum(u32) { | ... | @@ -419,6 +419,91 @@ pub const DebugType = enum(u32) { |
| 419 | EX_DLLCHARACTERISTICS = 20, | 419 | EX_DLLCHARACTERISTICS = 20, |
| 420 | }; | 420 | }; |
| 421 | 421 | ||
| 422 | pub const ImportDirectoryEntry = extern struct { | ||
| 423 | /// The RVA of the import lookup table. | ||
| 424 | /// This table contains a name or ordinal for each import. | ||
| 425 | /// (The name "Characteristics" is used in Winnt.h, but no longer describes this field.) | ||
| 426 | import_lookup_table_rva: u32, | ||
| 427 | |||
| 428 | /// The stamp that is set to zero until the image is bound. | ||
| 429 | /// After the image is bound, this field is set to the time/data stamp of the DLL. | ||
| 430 | time_date_stamp: u32, | ||
| 431 | |||
| 432 | /// The index of the first forwarder reference. | ||
| 433 | forwarder_chain: u32, | ||
| 434 | |||
| 435 | /// The address of an ASCII string that contains the name of the DLL. | ||
| 436 | /// This address is relative to the image base. | ||
| 437 | name_rva: u32, | ||
| 438 | |||
| 439 | /// The RVA of the import address table. | ||
| 440 | /// The contents of this table are identical to the contents of the import lookup table until the image is bound. | ||
| 441 | import_address_table_rva: u32, | ||
| 442 | }; | ||
| 443 | |||
| 444 | pub const ImportLookupEntry32 = struct { | ||
| 445 | pub const ByName = packed struct { | ||
| 446 | name_table_rva: u31, | ||
| 447 | flag: u1 = 0, | ||
| 448 | }; | ||
| 449 | |||
| 450 | pub const ByOrdinal = packed struct { | ||
| 451 | ordinal_number: u16, | ||
| 452 | unused: u15 = 0, | ||
| 453 | flag: u1 = 1, | ||
| 454 | }; | ||
| 455 | |||
| 456 | const mask = 0x80000000; | ||
| 457 | |||
| 458 | pub fn getImportByName(raw: u32) ?ByName { | ||
| 459 | if (mask & raw != 0) return null; | ||
| 460 | return @bitCast(ByName, raw); | ||
| 461 | } | ||
| 462 | |||
| 463 | pub fn getImportByOrdinal(raw: u32) ?ByOrdinal { | ||
| 464 | if (mask & raw == 0) return null; | ||
| 465 | return @bitCast(ByOrdinal, raw); | ||
| 466 | } | ||
| 467 | }; | ||
| 468 | |||
| 469 | pub const ImportLookupEntry64 = struct { | ||
| 470 | pub const ByName = packed struct { | ||
| 471 | name_table_rva: u31, | ||
| 472 | unused: u32 = 0, | ||
| 473 | flag: u1 = 0, | ||
| 474 | }; | ||
| 475 | |||
| 476 | pub const ByOrdinal = packed struct { | ||
| 477 | ordinal_number: u16, | ||
| 478 | unused: u47 = 0, | ||
| 479 | flag: u1 = 1, | ||
| 480 | }; | ||
| 481 | |||
| 482 | const mask = 0x8000000000000000; | ||
| 483 | |||
| 484 | pub fn getImportByName(raw: u64) ?ByName { | ||
| 485 | if (mask & raw != 0) return null; | ||
| 486 | return @bitCast(ByName, raw); | ||
| 487 | } | ||
| 488 | |||
| 489 | pub fn getImportByOrdinal(raw: u64) ?ByOrdinal { | ||
| 490 | if (mask & raw == 0) return null; | ||
| 491 | return @bitCast(ByOrdinal, raw); | ||
| 492 | } | ||
| 493 | }; | ||
| 494 | |||
| 495 | /// Every name ends with a NULL byte. IF the NULL byte does not fall on | ||
| 496 | /// 2byte boundary, the entry structure is padded to ensure 2byte alignment. | ||
| 497 | pub const ImportHintNameEntry = extern struct { | ||
| 498 | /// An index into the export name pointer table. | ||
| 499 | /// A match is attempted first with this value. If it fails, a binary search is performed on the DLL's export name pointer table. | ||
| 500 | hint: u16, | ||
| 501 | |||
| 502 | /// Pointer to NULL terminated ASCII name. | ||
| 503 | /// Variable length... | ||
| 504 | name: [1]u8, | ||
| 505 | }; | ||
| 506 | |||
| 422 | pub const SectionHeader = extern struct { | 507 | pub const SectionHeader = extern struct { |
| 423 | name: [8]u8, | 508 | name: [8]u8, |
| 424 | virtual_size: u32, | 509 | virtual_size: u32, |
lib/std/log.zig+1-1| ... | @@ -38,7 +38,7 @@ | ... | @@ -38,7 +38,7 @@ |
| 38 | //! return, | 38 | //! return, |
| 39 | //! } ++ "): "; | 39 | //! } ++ "): "; |
| 40 | //! | 40 | //! |
| 41 | //! const prefix = "[" ++ level.asText() ++ "] " ++ scope_prefix; | 41 | //! const prefix = "[" ++ comptime level.asText() ++ "] " ++ scope_prefix; |
| 42 | //! | 42 | //! |
| 43 | //! // Print the message to stderr, silently ignoring any errors | 43 | //! // Print the message to stderr, silently ignoring any errors |
| 44 | //! std.debug.getStderrMutex().lock(); | 44 | //! std.debug.getStderrMutex().lock(); |
lib/std/math/big/rational.zig+14-2| ... | @@ -334,13 +334,13 @@ pub const Rational = struct { | ... | @@ -334,13 +334,13 @@ pub const Rational = struct { |
| 334 | /// Returns math.Order.lt, math.Order.eq, math.Order.gt if a < b, a == b or a | 334 | /// Returns math.Order.lt, math.Order.eq, math.Order.gt if a < b, a == b or a |
| 335 | /// > b respectively. | 335 | /// > b respectively. |
| 336 | pub fn order(a: Rational, b: Rational) !math.Order { | 336 | pub fn order(a: Rational, b: Rational) !math.Order { |
| 337 | return cmpInternal(a, b, true); | 337 | return cmpInternal(a, b, false); |
| 338 | } | 338 | } |
| 339 | 339 | ||
| 340 | /// Returns math.Order.lt, math.Order.eq, math.Order.gt if |a| < |b|, |a| == | 340 | /// Returns math.Order.lt, math.Order.eq, math.Order.gt if |a| < |b|, |a| == |
| 341 | /// |b| or |a| > |b| respectively. | 341 | /// |b| or |a| > |b| respectively. |
| 342 | pub fn orderAbs(a: Rational, b: Rational) !math.Order { | 342 | pub fn orderAbs(a: Rational, b: Rational) !math.Order { |
| 343 | return cmpInternal(a, b, false); | 343 | return cmpInternal(a, b, true); |
| 344 | } | 344 | } |
| 345 | 345 | ||
| 346 | // p/q > x/y iff p*y > x*q | 346 | // p/q > x/y iff p*y > x*q |
| ... | @@ -704,6 +704,18 @@ test "big.rational order" { | ... | @@ -704,6 +704,18 @@ test "big.rational order" { |
| 704 | try testing.expect((try a.order(b)) == .eq); | 704 | try testing.expect((try a.order(b)) == .eq); |
| 705 | } | 705 | } |
| 706 | 706 | ||
| 707 | test "big.rational order/orderAbs with negative" { | ||
| 708 | var a = try Rational.init(testing.allocator); | ||
| 709 | defer a.deinit(); | ||
| 710 | var b = try Rational.init(testing.allocator); | ||
| 711 | defer b.deinit(); | ||
| 712 | |||
| 713 | try a.setRatio(1, 1); | ||
| 714 | try b.setRatio(-2, 1); | ||
| 715 | try testing.expect((try a.order(b)) == .gt); | ||
| 716 | try testing.expect((try a.orderAbs(b)) == .lt); | ||
| 717 | } | ||
| 718 | |||
| 707 | test "big.rational add single-limb" { | 719 | test "big.rational add single-limb" { |
| 708 | var a = try Rational.init(testing.allocator); | 720 | var a = try Rational.init(testing.allocator); |
| 709 | defer a.deinit(); | 721 | defer a.deinit(); |
lib/std/os.zig+4| ... | @@ -3447,6 +3447,9 @@ pub const BindError = error{ | ... | @@ -3447,6 +3447,9 @@ pub const BindError = error{ |
| 3447 | /// A nonexistent interface was requested or the requested address was not local. | 3447 | /// A nonexistent interface was requested or the requested address was not local. |
| 3448 | AddressNotAvailable, | 3448 | AddressNotAvailable, |
| 3449 | 3449 | ||
| 3450 | /// The address is not valid for the address family of socket. | ||
| 3451 | AddressFamilyNotSupported, | ||
| 3452 | |||
| 3450 | /// Too many symbolic links were encountered in resolving addr. | 3453 | /// Too many symbolic links were encountered in resolving addr. |
| 3451 | SymLinkLoop, | 3454 | SymLinkLoop, |
| 3452 | 3455 | ||
| ... | @@ -3502,6 +3505,7 @@ pub fn bind(sock: socket_t, addr: *const sockaddr, len: socklen_t) BindError!voi | ... | @@ -3502,6 +3505,7 @@ pub fn bind(sock: socket_t, addr: *const sockaddr, len: socklen_t) BindError!voi |
| 3502 | .BADF => unreachable, // always a race condition if this error is returned | 3505 | .BADF => unreachable, // always a race condition if this error is returned |
| 3503 | .INVAL => unreachable, // invalid parameters | 3506 | .INVAL => unreachable, // invalid parameters |
| 3504 | .NOTSOCK => unreachable, // invalid `sockfd` | 3507 | .NOTSOCK => unreachable, // invalid `sockfd` |
| 3508 | .AFNOSUPPORT => return error.AddressFamilyNotSupported, | ||
| 3505 | .ADDRNOTAVAIL => return error.AddressNotAvailable, | 3509 | .ADDRNOTAVAIL => return error.AddressNotAvailable, |
| 3506 | .FAULT => unreachable, // invalid `addr` pointer | 3510 | .FAULT => unreachable, // invalid `addr` pointer |
| 3507 | .LOOP => return error.SymLinkLoop, | 3511 | .LOOP => return error.SymLinkLoop, |
lib/std/zig/c_translation.zig+1-1| ... | @@ -268,7 +268,7 @@ test "sizeof" { | ... | @@ -268,7 +268,7 @@ test "sizeof" { |
| 268 | pub const CIntLiteralRadix = enum { decimal, octal, hexadecimal }; | 268 | pub const CIntLiteralRadix = enum { decimal, octal, hexadecimal }; |
| 269 | 269 | ||
| 270 | fn PromoteIntLiteralReturnType(comptime SuffixType: type, comptime number: comptime_int, comptime radix: CIntLiteralRadix) type { | 270 | fn PromoteIntLiteralReturnType(comptime SuffixType: type, comptime number: comptime_int, comptime radix: CIntLiteralRadix) type { |
| 271 | const signed_decimal = [_]type{ c_int, c_long, c_longlong }; | 271 | const signed_decimal = [_]type{ c_int, c_long, c_longlong, c_ulonglong }; |
| 272 | const signed_oct_hex = [_]type{ c_int, c_uint, c_long, c_ulong, c_longlong, c_ulonglong }; | 272 | const signed_oct_hex = [_]type{ c_int, c_uint, c_long, c_ulong, c_longlong, c_ulonglong }; |
| 273 | const unsigned = [_]type{ c_uint, c_ulong, c_ulonglong }; | 273 | const unsigned = [_]type{ c_uint, c_ulong, c_ulonglong }; |
| 274 | 274 |
lib/std/zig/parser_test.zig+37| ... | @@ -16,6 +16,28 @@ test "zig fmt: preserves clobbers in inline asm with stray comma" { | ... | @@ -16,6 +16,28 @@ test "zig fmt: preserves clobbers in inline asm with stray comma" { |
| 16 | ); | 16 | ); |
| 17 | } | 17 | } |
| 18 | 18 | ||
| 19 | test "zig fmt: remove trailing comma at the end of assembly clobber" { | ||
| 20 | try testTransform( | ||
| 21 | \\fn foo() void { | ||
| 22 | \\ asm volatile ("" | ||
| 23 | \\ : [_] "" (-> type), | ||
| 24 | \\ : | ||
| 25 | \\ : "clobber1", "clobber2", | ||
| 26 | \\ ); | ||
| 27 | \\} | ||
| 28 | \\ | ||
| 29 | , | ||
| 30 | \\fn foo() void { | ||
| 31 | \\ asm volatile ("" | ||
| 32 | \\ : [_] "" (-> type), | ||
| 33 | \\ : | ||
| 34 | \\ : "clobber1", "clobber2" | ||
| 35 | \\ ); | ||
| 36 | \\} | ||
| 37 | \\ | ||
| 38 | ); | ||
| 39 | } | ||
| 40 | |||
| 19 | test "zig fmt: respect line breaks in struct field value declaration" { | 41 | test "zig fmt: respect line breaks in struct field value declaration" { |
| 20 | try testCanonical( | 42 | try testCanonical( |
| 21 | \\const Foo = struct { | 43 | \\const Foo = struct { |
| ... | @@ -5035,6 +5057,21 @@ test "zig fmt: make single-line if no trailing comma" { | ... | @@ -5035,6 +5057,21 @@ test "zig fmt: make single-line if no trailing comma" { |
| 5035 | ); | 5057 | ); |
| 5036 | } | 5058 | } |
| 5037 | 5059 | ||
| 5060 | test "zig fmt: preserve container doc comment in container without trailing comma" { | ||
| 5061 | try testTransform( | ||
| 5062 | \\const A = enum(u32) { | ||
| 5063 | \\//! comment | ||
| 5064 | \\_ }; | ||
| 5065 | \\ | ||
| 5066 | , | ||
| 5067 | \\const A = enum(u32) { | ||
| 5068 | \\ //! comment | ||
| 5069 | \\ _, | ||
| 5070 | \\}; | ||
| 5071 | \\ | ||
| 5072 | ); | ||
| 5073 | } | ||
| 5074 | |||
| 5038 | test "zig fmt: make single-line if no trailing comma" { | 5075 | test "zig fmt: make single-line if no trailing comma" { |
| 5039 | try testCanonical( | 5076 | try testCanonical( |
| 5040 | \\// Test trailing comma syntax | 5077 | \\// Test trailing comma syntax |
lib/std/zig/render.zig+19-6| ... | @@ -1933,12 +1933,15 @@ fn renderContainerDecl( | ... | @@ -1933,12 +1933,15 @@ fn renderContainerDecl( |
| 1933 | break :one_line; | 1933 | break :one_line; |
| 1934 | } | 1934 | } |
| 1935 | 1935 | ||
| 1936 | // 2. A member of the container has a doc comment. | 1936 | // 2. The container has a container comment. |
| 1937 | if (token_tags[lbrace + 1] == .container_doc_comment) break :one_line; | ||
| 1938 | |||
| 1939 | // 3. A member of the container has a doc comment. | ||
| 1937 | for (token_tags[lbrace + 1 .. rbrace - 1]) |tag| { | 1940 | for (token_tags[lbrace + 1 .. rbrace - 1]) |tag| { |
| 1938 | if (tag == .doc_comment) break :one_line; | 1941 | if (tag == .doc_comment) break :one_line; |
| 1939 | } | 1942 | } |
| 1940 | 1943 | ||
| 1941 | // 3. The container has non-field members. | 1944 | // 4. The container has non-field members. |
| 1942 | for (container_decl.ast.members) |member| { | 1945 | for (container_decl.ast.members) |member| { |
| 1943 | if (!node_tags[member].isContainerField()) break :one_line; | 1946 | if (!node_tags[member].isContainerField()) break :one_line; |
| 1944 | } | 1947 | } |
| ... | @@ -2114,9 +2117,19 @@ fn renderAsm( | ... | @@ -2114,9 +2117,19 @@ fn renderAsm( |
| 2114 | return renderToken(ais, tree, tok_i + 1, space); | 2117 | return renderToken(ais, tree, tok_i + 1, space); |
| 2115 | }, | 2118 | }, |
| 2116 | .comma => { | 2119 | .comma => { |
| 2117 | try renderToken(ais, tree, tok_i, .none); | 2120 | switch (token_tags[tok_i + 2]) { |
| 2118 | try renderToken(ais, tree, tok_i + 1, .space); | 2121 | .r_paren => { |
| 2119 | tok_i += 2; | 2122 | ais.setIndentDelta(indent_delta); |
| 2123 | ais.popIndent(); | ||
| 2124 | try renderToken(ais, tree, tok_i, .newline); | ||
| 2125 | return renderToken(ais, tree, tok_i + 2, space); | ||
| 2126 | }, | ||
| 2127 | else => { | ||
| 2128 | try renderToken(ais, tree, tok_i, .none); | ||
| 2129 | try renderToken(ais, tree, tok_i + 1, .space); | ||
| 2130 | tok_i += 2; | ||
| 2131 | }, | ||
| 2132 | } | ||
| 2120 | }, | 2133 | }, |
| 2121 | else => unreachable, | 2134 | else => unreachable, |
| 2122 | } | 2135 | } |
| ... | @@ -2348,7 +2361,7 @@ fn renderSpace(ais: *Ais, tree: Ast, token_index: Ast.TokenIndex, lexeme_len: us | ... | @@ -2348,7 +2361,7 @@ fn renderSpace(ais: *Ais, tree: Ast, token_index: Ast.TokenIndex, lexeme_len: us |
| 2348 | } | 2361 | } |
| 2349 | } | 2362 | } |
| 2350 | 2363 | ||
| 2351 | /// Returns true if there exists a comment between any of the tokens from | 2364 | /// Returns true if there exists a line comment between any of the tokens from |
| 2352 | /// `start_token` to `end_token`. This is used to determine if e.g. a | 2365 | /// `start_token` to `end_token`. This is used to determine if e.g. a |
| 2353 | /// fn_proto should be wrapped and have a trailing comma inserted even if | 2366 | /// fn_proto should be wrapped and have a trailing comma inserted even if |
| 2354 | /// there is none in the source. | 2367 | /// there is none in the source. |
src/AstGen.zig+1-1| ... | @@ -5127,7 +5127,7 @@ fn tryExpr( | ... | @@ -5127,7 +5127,7 @@ fn tryExpr( |
| 5127 | else => .none, | 5127 | else => .none, |
| 5128 | }; | 5128 | }; |
| 5129 | // This could be a pointer or value depending on the `rl` parameter. | 5129 | // This could be a pointer or value depending on the `rl` parameter. |
| 5130 | const operand = try expr(parent_gz, scope, operand_rl, operand_node); | 5130 | const operand = try reachableExpr(parent_gz, scope, operand_rl, operand_node, node); |
| 5131 | const is_inline = parent_gz.force_comptime; | 5131 | const is_inline = parent_gz.force_comptime; |
| 5132 | const is_inline_bit = @as(u2, @boolToInt(is_inline)); | 5132 | const is_inline_bit = @as(u2, @boolToInt(is_inline)); |
| 5133 | const is_ptr_bit = @as(u2, @boolToInt(operand_rl == .ref)) << 1; | 5133 | const is_ptr_bit = @as(u2, @boolToInt(operand_rl == .ref)) << 1; |
src/Autodoc.zig+384-230| ... | @@ -1,6 +1,7 @@ | ... | @@ -1,6 +1,7 @@ |
| 1 | const builtin = @import("builtin"); | 1 | const builtin = @import("builtin"); |
| 2 | const std = @import("std"); | 2 | const std = @import("std"); |
| 3 | const build_options = @import("build_options"); | 3 | const build_options = @import("build_options"); |
| 4 | const Ast = std.zig.Ast; | ||
| 4 | const Autodoc = @This(); | 5 | const Autodoc = @This(); |
| 5 | const Compilation = @import("Compilation.zig"); | 6 | const Compilation = @import("Compilation.zig"); |
| 6 | const Module = @import("Module.zig"); | 7 | const Module = @import("Module.zig"); |
| ... | @@ -47,6 +48,19 @@ const RefPathResumeInfo = struct { | ... | @@ -47,6 +48,19 @@ const RefPathResumeInfo = struct { |
| 47 | ref_path: []DocData.Expr, | 48 | ref_path: []DocData.Expr, |
| 48 | }; | 49 | }; |
| 49 | 50 | ||
| 51 | /// Used to accumulate src_node offsets. | ||
| 52 | /// In ZIR, all ast node indices are relative to the parent decl. | ||
| 53 | /// More concretely, `union_decl`, `struct_decl`, `enum_decl` and `opaque_decl` | ||
| 54 | /// and the value of each of their decls participate in the relative offset | ||
| 55 | /// counting, and nothing else. | ||
| 56 | /// We keep track of the line and byte values for these instructions in order | ||
| 57 | /// to avoid tokenizing every file (on new lines) from the start every time. | ||
| 58 | const SrcLocInfo = struct { | ||
| 59 | bytes: u32 = 0, | ||
| 60 | line: usize = 0, | ||
| 61 | src_node: u32 = 0, | ||
| 62 | }; | ||
| 63 | |||
| 50 | var arena_allocator: std.heap.ArenaAllocator = undefined; | 64 | var arena_allocator: std.heap.ArenaAllocator = undefined; |
| 51 | pub fn init(m: *Module, doc_location: Compilation.EmitLoc) Autodoc { | 65 | pub fn init(m: *Module, doc_location: Compilation.EmitLoc) Autodoc { |
| 52 | arena_allocator = std.heap.ArenaAllocator.init(m.gpa); | 66 | arena_allocator = std.heap.ArenaAllocator.init(m.gpa); |
| ... | @@ -202,7 +216,7 @@ pub fn generateZirData(self: *Autodoc) !void { | ... | @@ -202,7 +216,7 @@ pub fn generateZirData(self: *Autodoc) !void { |
| 202 | 216 | ||
| 203 | try self.ast_nodes.append(self.arena, .{ .name = "(root)" }); | 217 | try self.ast_nodes.append(self.arena, .{ .name = "(root)" }); |
| 204 | try self.files.put(self.arena, file, main_type_index); | 218 | try self.files.put(self.arena, file, main_type_index); |
| 205 | _ = try self.walkInstruction(file, &root_scope, 1, Zir.main_struct_inst, false); | 219 | _ = try self.walkInstruction(file, &root_scope, .{}, Zir.main_struct_inst, false); |
| 206 | 220 | ||
| 207 | if (self.ref_paths_pending_on_decls.count() > 0) { | 221 | if (self.ref_paths_pending_on_decls.count() > 0) { |
| 208 | @panic("some decl paths were never fully analized (pending on decls)"); | 222 | @panic("some decl paths were never fully analized (pending on decls)"); |
| ... | @@ -467,6 +481,7 @@ const DocData = struct { | ... | @@ -467,6 +481,7 @@ const DocData = struct { |
| 467 | line: usize = 0, | 481 | line: usize = 0, |
| 468 | col: usize = 0, | 482 | col: usize = 0, |
| 469 | name: ?[]const u8 = null, | 483 | name: ?[]const u8 = null, |
| 484 | code: ?[]const u8 = null, | ||
| 470 | docs: ?[]const u8 = null, | 485 | docs: ?[]const u8 = null, |
| 471 | fields: ?[]usize = null, // index into astNodes | 486 | fields: ?[]usize = null, // index into astNodes |
| 472 | @"comptime": bool = false, | 487 | @"comptime": bool = false, |
| ... | @@ -562,7 +577,13 @@ const DocData = struct { | ... | @@ -562,7 +577,13 @@ const DocData = struct { |
| 562 | is_extern: bool = false, | 577 | is_extern: bool = false, |
| 563 | }, | 578 | }, |
| 564 | BoundFn: struct { name: []const u8 }, | 579 | BoundFn: struct { name: []const u8 }, |
| 565 | Opaque: struct { name: []const u8 }, | 580 | Opaque: struct { |
| 581 | name: []const u8, | ||
| 582 | src: usize, // index into astNodes | ||
| 583 | privDecls: []usize = &.{}, // index into decls | ||
| 584 | pubDecls: []usize = &.{}, // index into decls | ||
| 585 | ast: usize, | ||
| 586 | }, | ||
| 566 | Frame: struct { name: []const u8 }, | 587 | Frame: struct { name: []const u8 }, |
| 567 | AnyFrame: struct { name: []const u8 }, | 588 | AnyFrame: struct { name: []const u8 }, |
| 568 | Vector: struct { name: []const u8 }, | 589 | Vector: struct { name: []const u8 }, |
| ... | @@ -625,7 +646,7 @@ const DocData = struct { | ... | @@ -625,7 +646,7 @@ const DocData = struct { |
| 625 | negated: bool = false, | 646 | negated: bool = false, |
| 626 | }, | 647 | }, |
| 627 | int_big: struct { | 648 | int_big: struct { |
| 628 | value: []const u8, // direct value | 649 | value: []const u8, // string representation |
| 629 | negated: bool = false, | 650 | negated: bool = false, |
| 630 | }, | 651 | }, |
| 631 | float: f64, // direct value | 652 | float: f64, // direct value |
| ... | @@ -712,12 +733,6 @@ const DocData = struct { | ... | @@ -712,12 +733,6 @@ const DocData = struct { |
| 712 | if (self.int.negated) try w.writeAll("-"); | 733 | if (self.int.negated) try w.writeAll("-"); |
| 713 | try jsw.emitNumber(self.int.value); | 734 | try jsw.emitNumber(self.int.value); |
| 714 | }, | 735 | }, |
| 715 | .int_big => { | ||
| 716 | |||
| 717 | //@panic("TODO: json serialization of big ints!"); | ||
| 718 | //if (v.negated) try w.writeAll("-"); | ||
| 719 | //try jsw.emitNumber(v.value); | ||
| 720 | }, | ||
| 721 | .builtinField => { | 736 | .builtinField => { |
| 722 | try jsw.emitString(@tagName(self.builtinField)); | 737 | try jsw.emitString(@tagName(self.builtinField)); |
| 723 | }, | 738 | }, |
| ... | @@ -758,8 +773,8 @@ const DocData = struct { | ... | @@ -758,8 +773,8 @@ const DocData = struct { |
| 758 | const AutodocErrors = error{ | 773 | const AutodocErrors = error{ |
| 759 | OutOfMemory, | 774 | OutOfMemory, |
| 760 | CurrentWorkingDirectoryUnlinked, | 775 | CurrentWorkingDirectoryUnlinked, |
| 761 | Unexpected, | 776 | UnexpectedEndOfFile, |
| 762 | }; | 777 | } || std.fs.File.OpenError || std.fs.File.ReadError; |
| 763 | 778 | ||
| 764 | /// Called when we need to analyze a Zir instruction. | 779 | /// Called when we need to analyze a Zir instruction. |
| 765 | /// For example it gets called by `generateZirData` on instruction 0, | 780 | /// For example it gets called by `generateZirData` on instruction 0, |
| ... | @@ -773,7 +788,7 @@ fn walkInstruction( | ... | @@ -773,7 +788,7 @@ fn walkInstruction( |
| 773 | self: *Autodoc, | 788 | self: *Autodoc, |
| 774 | file: *File, | 789 | file: *File, |
| 775 | parent_scope: *Scope, | 790 | parent_scope: *Scope, |
| 776 | parent_line: usize, | 791 | parent_src: SrcLocInfo, |
| 777 | inst_index: usize, | 792 | inst_index: usize, |
| 778 | need_type: bool, // true if the caller needs us to provide also a typeRef | 793 | need_type: bool, // true if the caller needs us to provide also a typeRef |
| 779 | ) AutodocErrors!DocData.WalkResult { | 794 | ) AutodocErrors!DocData.WalkResult { |
| ... | @@ -865,7 +880,7 @@ fn walkInstruction( | ... | @@ -865,7 +880,7 @@ fn walkInstruction( |
| 865 | return self.walkInstruction( | 880 | return self.walkInstruction( |
| 866 | new_file, | 881 | new_file, |
| 867 | &root_scope, | 882 | &root_scope, |
| 868 | 1, | 883 | .{}, |
| 869 | Zir.main_struct_inst, | 884 | Zir.main_struct_inst, |
| 870 | false, | 885 | false, |
| 871 | ); | 886 | ); |
| ... | @@ -890,14 +905,14 @@ fn walkInstruction( | ... | @@ -890,14 +905,14 @@ fn walkInstruction( |
| 890 | return self.walkInstruction( | 905 | return self.walkInstruction( |
| 891 | new_file.file, | 906 | new_file.file, |
| 892 | &new_scope, | 907 | &new_scope, |
| 893 | 1, | 908 | .{}, |
| 894 | Zir.main_struct_inst, | 909 | Zir.main_struct_inst, |
| 895 | need_type, | 910 | need_type, |
| 896 | ); | 911 | ); |
| 897 | }, | 912 | }, |
| 898 | .ret_node => { | 913 | .ret_node => { |
| 899 | const un_node = data[inst_index].un_node; | 914 | const un_node = data[inst_index].un_node; |
| 900 | return self.walkRef(file, parent_scope, parent_line, un_node.operand, false); | 915 | return self.walkRef(file, parent_scope, parent_src, un_node.operand, false); |
| 901 | }, | 916 | }, |
| 902 | .ret_load => { | 917 | .ret_load => { |
| 903 | const un_node = data[inst_index].un_node; | 918 | const un_node = data[inst_index].un_node; |
| ... | @@ -928,7 +943,7 @@ fn walkInstruction( | ... | @@ -928,7 +943,7 @@ fn walkInstruction( |
| 928 | } | 943 | } |
| 929 | 944 | ||
| 930 | if (result_ref) |rr| { | 945 | if (result_ref) |rr| { |
| 931 | return self.walkRef(file, parent_scope, parent_line, rr, need_type); | 946 | return self.walkRef(file, parent_scope, parent_src, rr, need_type); |
| 932 | } | 947 | } |
| 933 | 948 | ||
| 934 | return DocData.WalkResult{ | 949 | return DocData.WalkResult{ |
| ... | @@ -937,11 +952,11 @@ fn walkInstruction( | ... | @@ -937,11 +952,11 @@ fn walkInstruction( |
| 937 | }, | 952 | }, |
| 938 | .closure_get => { | 953 | .closure_get => { |
| 939 | const inst_node = data[inst_index].inst_node; | 954 | const inst_node = data[inst_index].inst_node; |
| 940 | return try self.walkInstruction(file, parent_scope, parent_line, inst_node.inst, need_type); | 955 | return try self.walkInstruction(file, parent_scope, parent_src, inst_node.inst, need_type); |
| 941 | }, | 956 | }, |
| 942 | .closure_capture => { | 957 | .closure_capture => { |
| 943 | const un_tok = data[inst_index].un_tok; | 958 | const un_tok = data[inst_index].un_tok; |
| 944 | return try self.walkRef(file, parent_scope, parent_line, un_tok.operand, need_type); | 959 | return try self.walkRef(file, parent_scope, parent_src, un_tok.operand, need_type); |
| 945 | }, | 960 | }, |
| 946 | .cmpxchg_strong, .cmpxchg_weak => { | 961 | .cmpxchg_strong, .cmpxchg_weak => { |
| 947 | const pl_node = data[inst_index].pl_node; | 962 | const pl_node = data[inst_index].pl_node; |
| ... | @@ -956,7 +971,7 @@ fn walkInstruction( | ... | @@ -956,7 +971,7 @@ fn walkInstruction( |
| 956 | var ptr: DocData.WalkResult = try self.walkRef( | 971 | var ptr: DocData.WalkResult = try self.walkRef( |
| 957 | file, | 972 | file, |
| 958 | parent_scope, | 973 | parent_scope, |
| 959 | parent_line, | 974 | parent_src, |
| 960 | extra.data.ptr, | 975 | extra.data.ptr, |
| 961 | false, | 976 | false, |
| 962 | ); | 977 | ); |
| ... | @@ -966,7 +981,7 @@ fn walkInstruction( | ... | @@ -966,7 +981,7 @@ fn walkInstruction( |
| 966 | var expected_value: DocData.WalkResult = try self.walkRef( | 981 | var expected_value: DocData.WalkResult = try self.walkRef( |
| 967 | file, | 982 | file, |
| 968 | parent_scope, | 983 | parent_scope, |
| 969 | parent_line, | 984 | parent_src, |
| 970 | extra.data.expected_value, | 985 | extra.data.expected_value, |
| 971 | false, | 986 | false, |
| 972 | ); | 987 | ); |
| ... | @@ -976,7 +991,7 @@ fn walkInstruction( | ... | @@ -976,7 +991,7 @@ fn walkInstruction( |
| 976 | var new_value: DocData.WalkResult = try self.walkRef( | 991 | var new_value: DocData.WalkResult = try self.walkRef( |
| 977 | file, | 992 | file, |
| 978 | parent_scope, | 993 | parent_scope, |
| 979 | parent_line, | 994 | parent_src, |
| 980 | extra.data.new_value, | 995 | extra.data.new_value, |
| 981 | false, | 996 | false, |
| 982 | ); | 997 | ); |
| ... | @@ -986,7 +1001,7 @@ fn walkInstruction( | ... | @@ -986,7 +1001,7 @@ fn walkInstruction( |
| 986 | var success_order: DocData.WalkResult = try self.walkRef( | 1001 | var success_order: DocData.WalkResult = try self.walkRef( |
| 987 | file, | 1002 | file, |
| 988 | parent_scope, | 1003 | parent_scope, |
| 989 | parent_line, | 1004 | parent_src, |
| 990 | extra.data.success_order, | 1005 | extra.data.success_order, |
| 991 | false, | 1006 | false, |
| 992 | ); | 1007 | ); |
| ... | @@ -996,7 +1011,7 @@ fn walkInstruction( | ... | @@ -996,7 +1011,7 @@ fn walkInstruction( |
| 996 | var failure_order: DocData.WalkResult = try self.walkRef( | 1011 | var failure_order: DocData.WalkResult = try self.walkRef( |
| 997 | file, | 1012 | file, |
| 998 | parent_scope, | 1013 | parent_scope, |
| 999 | parent_line, | 1014 | parent_src, |
| 1000 | extra.data.failure_order, | 1015 | extra.data.failure_order, |
| 1001 | false, | 1016 | false, |
| 1002 | ); | 1017 | ); |
| ... | @@ -1047,10 +1062,11 @@ fn walkInstruction( | ... | @@ -1047,10 +1062,11 @@ fn walkInstruction( |
| 1047 | }, | 1062 | }, |
| 1048 | .compile_error => { | 1063 | .compile_error => { |
| 1049 | const un_node = data[inst_index].un_node; | 1064 | const un_node = data[inst_index].un_node; |
| 1065 | |||
| 1050 | var operand: DocData.WalkResult = try self.walkRef( | 1066 | var operand: DocData.WalkResult = try self.walkRef( |
| 1051 | file, | 1067 | file, |
| 1052 | parent_scope, | 1068 | parent_scope, |
| 1053 | parent_line, | 1069 | parent_src, |
| 1054 | un_node.operand, | 1070 | un_node.operand, |
| 1055 | false, | 1071 | false, |
| 1056 | ); | 1072 | ); |
| ... | @@ -1084,15 +1100,24 @@ fn walkInstruction( | ... | @@ -1084,15 +1100,24 @@ fn walkInstruction( |
| 1084 | }, | 1100 | }, |
| 1085 | .int_big => { | 1101 | .int_big => { |
| 1086 | // @check | 1102 | // @check |
| 1087 | const str = data[inst_index].str.get(file.zir); | 1103 | const str = data[inst_index].str; //.get(file.zir); |
| 1088 | _ = str; | 1104 | const byte_count = str.len * @sizeOf(std.math.big.Limb); |
| 1089 | printWithContext( | 1105 | const limb_bytes = file.zir.string_bytes[str.start..][0..byte_count]; |
| 1090 | file, | 1106 | |
| 1091 | inst_index, | 1107 | var limbs = try self.arena.alloc(std.math.big.Limb, str.len); |
| 1092 | "TODO: implement `{s}` for walkInstruction\n\n", | 1108 | std.mem.copy(u8, std.mem.sliceAsBytes(limbs), limb_bytes); |
| 1093 | .{@tagName(tags[inst_index])}, | 1109 | |
| 1094 | ); | 1110 | const big_int = std.math.big.int.Const{ |
| 1095 | return self.cteTodo(@tagName(tags[inst_index])); | 1111 | .limbs = limbs, |
| 1112 | .positive = true, | ||
| 1113 | }; | ||
| 1114 | |||
| 1115 | const as_string = try big_int.toStringAlloc(self.arena, 10, .lower); | ||
| 1116 | |||
| 1117 | return DocData.WalkResult{ | ||
| 1118 | .typeRef = .{ .type = @enumToInt(Ref.comptime_int_type) }, | ||
| 1119 | .expr = .{ .int_big = .{ .value = as_string } }, | ||
| 1120 | }; | ||
| 1096 | }, | 1121 | }, |
| 1097 | 1122 | ||
| 1098 | .slice_start => { | 1123 | .slice_start => { |
| ... | @@ -1105,14 +1130,14 @@ fn walkInstruction( | ... | @@ -1105,14 +1130,14 @@ fn walkInstruction( |
| 1105 | var lhs: DocData.WalkResult = try self.walkRef( | 1130 | var lhs: DocData.WalkResult = try self.walkRef( |
| 1106 | file, | 1131 | file, |
| 1107 | parent_scope, | 1132 | parent_scope, |
| 1108 | parent_line, | 1133 | parent_src, |
| 1109 | extra.data.lhs, | 1134 | extra.data.lhs, |
| 1110 | false, | 1135 | false, |
| 1111 | ); | 1136 | ); |
| 1112 | var start: DocData.WalkResult = try self.walkRef( | 1137 | var start: DocData.WalkResult = try self.walkRef( |
| 1113 | file, | 1138 | file, |
| 1114 | parent_scope, | 1139 | parent_scope, |
| 1115 | parent_line, | 1140 | parent_src, |
| 1116 | extra.data.start, | 1141 | extra.data.start, |
| 1117 | false, | 1142 | false, |
| 1118 | ); | 1143 | ); |
| ... | @@ -1138,21 +1163,21 @@ fn walkInstruction( | ... | @@ -1138,21 +1163,21 @@ fn walkInstruction( |
| 1138 | var lhs: DocData.WalkResult = try self.walkRef( | 1163 | var lhs: DocData.WalkResult = try self.walkRef( |
| 1139 | file, | 1164 | file, |
| 1140 | parent_scope, | 1165 | parent_scope, |
| 1141 | parent_line, | 1166 | parent_src, |
| 1142 | extra.data.lhs, | 1167 | extra.data.lhs, |
| 1143 | false, | 1168 | false, |
| 1144 | ); | 1169 | ); |
| 1145 | var start: DocData.WalkResult = try self.walkRef( | 1170 | var start: DocData.WalkResult = try self.walkRef( |
| 1146 | file, | 1171 | file, |
| 1147 | parent_scope, | 1172 | parent_scope, |
| 1148 | parent_line, | 1173 | parent_src, |
| 1149 | extra.data.start, | 1174 | extra.data.start, |
| 1150 | false, | 1175 | false, |
| 1151 | ); | 1176 | ); |
| 1152 | var end: DocData.WalkResult = try self.walkRef( | 1177 | var end: DocData.WalkResult = try self.walkRef( |
| 1153 | file, | 1178 | file, |
| 1154 | parent_scope, | 1179 | parent_scope, |
| 1155 | parent_line, | 1180 | parent_src, |
| 1156 | extra.data.end, | 1181 | extra.data.end, |
| 1157 | false, | 1182 | false, |
| 1158 | ); | 1183 | ); |
| ... | @@ -1180,28 +1205,28 @@ fn walkInstruction( | ... | @@ -1180,28 +1205,28 @@ fn walkInstruction( |
| 1180 | var lhs: DocData.WalkResult = try self.walkRef( | 1205 | var lhs: DocData.WalkResult = try self.walkRef( |
| 1181 | file, | 1206 | file, |
| 1182 | parent_scope, | 1207 | parent_scope, |
| 1183 | parent_line, | 1208 | parent_src, |
| 1184 | extra.data.lhs, | 1209 | extra.data.lhs, |
| 1185 | false, | 1210 | false, |
| 1186 | ); | 1211 | ); |
| 1187 | var start: DocData.WalkResult = try self.walkRef( | 1212 | var start: DocData.WalkResult = try self.walkRef( |
| 1188 | file, | 1213 | file, |
| 1189 | parent_scope, | 1214 | parent_scope, |
| 1190 | parent_line, | 1215 | parent_src, |
| 1191 | extra.data.start, | 1216 | extra.data.start, |
| 1192 | false, | 1217 | false, |
| 1193 | ); | 1218 | ); |
| 1194 | var end: DocData.WalkResult = try self.walkRef( | 1219 | var end: DocData.WalkResult = try self.walkRef( |
| 1195 | file, | 1220 | file, |
| 1196 | parent_scope, | 1221 | parent_scope, |
| 1197 | parent_line, | 1222 | parent_src, |
| 1198 | extra.data.end, | 1223 | extra.data.end, |
| 1199 | false, | 1224 | false, |
| 1200 | ); | 1225 | ); |
| 1201 | var sentinel: DocData.WalkResult = try self.walkRef( | 1226 | var sentinel: DocData.WalkResult = try self.walkRef( |
| 1202 | file, | 1227 | file, |
| 1203 | parent_scope, | 1228 | parent_scope, |
| 1204 | parent_line, | 1229 | parent_src, |
| 1205 | extra.data.sentinel, | 1230 | extra.data.sentinel, |
| 1206 | false, | 1231 | false, |
| 1207 | ); | 1232 | ); |
| ... | @@ -1251,14 +1276,14 @@ fn walkInstruction( | ... | @@ -1251,14 +1276,14 @@ fn walkInstruction( |
| 1251 | var lhs: DocData.WalkResult = try self.walkRef( | 1276 | var lhs: DocData.WalkResult = try self.walkRef( |
| 1252 | file, | 1277 | file, |
| 1253 | parent_scope, | 1278 | parent_scope, |
| 1254 | parent_line, | 1279 | parent_src, |
| 1255 | extra.data.lhs, | 1280 | extra.data.lhs, |
| 1256 | false, | 1281 | false, |
| 1257 | ); | 1282 | ); |
| 1258 | var rhs: DocData.WalkResult = try self.walkRef( | 1283 | var rhs: DocData.WalkResult = try self.walkRef( |
| 1259 | file, | 1284 | file, |
| 1260 | parent_scope, | 1285 | parent_scope, |
| 1261 | parent_line, | 1286 | parent_src, |
| 1262 | extra.data.rhs, | 1287 | extra.data.rhs, |
| 1263 | false, | 1288 | false, |
| 1264 | ); | 1289 | ); |
| ... | @@ -1278,6 +1303,50 @@ fn walkInstruction( | ... | @@ -1278,6 +1303,50 @@ fn walkInstruction( |
| 1278 | .expr = .{ .binOpIndex = binop_index }, | 1303 | .expr = .{ .binOpIndex = binop_index }, |
| 1279 | }; | 1304 | }; |
| 1280 | }, | 1305 | }, |
| 1306 | // compare operators | ||
| 1307 | .cmp_eq, | ||
| 1308 | .cmp_neq, | ||
| 1309 | .cmp_gt, | ||
| 1310 | .cmp_gte, | ||
| 1311 | .cmp_lt, | ||
| 1312 | .cmp_lte, | ||
| 1313 | => { | ||
| 1314 | const pl_node = data[inst_index].pl_node; | ||
| 1315 | const extra = file.zir.extraData(Zir.Inst.Bin, pl_node.payload_index); | ||
| 1316 | |||
| 1317 | const binop_index = self.exprs.items.len; | ||
| 1318 | try self.exprs.append(self.arena, .{ .binOp = .{ .lhs = 0, .rhs = 0 } }); | ||
| 1319 | |||
| 1320 | var lhs: DocData.WalkResult = try self.walkRef( | ||
| 1321 | file, | ||
| 1322 | parent_scope, | ||
| 1323 | parent_src, | ||
| 1324 | extra.data.lhs, | ||
| 1325 | false, | ||
| 1326 | ); | ||
| 1327 | var rhs: DocData.WalkResult = try self.walkRef( | ||
| 1328 | file, | ||
| 1329 | parent_scope, | ||
| 1330 | parent_src, | ||
| 1331 | extra.data.rhs, | ||
| 1332 | false, | ||
| 1333 | ); | ||
| 1334 | |||
| 1335 | const lhs_index = self.exprs.items.len; | ||
| 1336 | try self.exprs.append(self.arena, lhs.expr); | ||
| 1337 | const rhs_index = self.exprs.items.len; | ||
| 1338 | try self.exprs.append(self.arena, rhs.expr); | ||
| 1339 | self.exprs.items[binop_index] = .{ .binOp = .{ | ||
| 1340 | .name = @tagName(tags[inst_index]), | ||
| 1341 | .lhs = lhs_index, | ||
| 1342 | .rhs = rhs_index, | ||
| 1343 | } }; | ||
| 1344 | |||
| 1345 | return DocData.WalkResult{ | ||
| 1346 | .typeRef = .{ .type = @enumToInt(Ref.bool_type) }, | ||
| 1347 | .expr = .{ .binOpIndex = binop_index }, | ||
| 1348 | }; | ||
| 1349 | }, | ||
| 1281 | 1350 | ||
| 1282 | // builtin functions | 1351 | // builtin functions |
| 1283 | .align_of, | 1352 | .align_of, |
| ... | @@ -1319,7 +1388,7 @@ fn walkInstruction( | ... | @@ -1319,7 +1388,7 @@ fn walkInstruction( |
| 1319 | const un_node = data[inst_index].un_node; | 1388 | const un_node = data[inst_index].un_node; |
| 1320 | const bin_index = self.exprs.items.len; | 1389 | const bin_index = self.exprs.items.len; |
| 1321 | try self.exprs.append(self.arena, .{ .builtin = .{ .param = 0 } }); | 1390 | try self.exprs.append(self.arena, .{ .builtin = .{ .param = 0 } }); |
| 1322 | const param = try self.walkRef(file, parent_scope, parent_line, un_node.operand, false); | 1391 | const param = try self.walkRef(file, parent_scope, parent_src, un_node.operand, false); |
| 1323 | 1392 | ||
| 1324 | const param_index = self.exprs.items.len; | 1393 | const param_index = self.exprs.items.len; |
| 1325 | try self.exprs.append(self.arena, param.expr); | 1394 | try self.exprs.append(self.arena, param.expr); |
| ... | @@ -1368,14 +1437,14 @@ fn walkInstruction( | ... | @@ -1368,14 +1437,14 @@ fn walkInstruction( |
| 1368 | var lhs: DocData.WalkResult = try self.walkRef( | 1437 | var lhs: DocData.WalkResult = try self.walkRef( |
| 1369 | file, | 1438 | file, |
| 1370 | parent_scope, | 1439 | parent_scope, |
| 1371 | parent_line, | 1440 | parent_src, |
| 1372 | extra.data.lhs, | 1441 | extra.data.lhs, |
| 1373 | false, | 1442 | false, |
| 1374 | ); | 1443 | ); |
| 1375 | var rhs: DocData.WalkResult = try self.walkRef( | 1444 | var rhs: DocData.WalkResult = try self.walkRef( |
| 1376 | file, | 1445 | file, |
| 1377 | parent_scope, | 1446 | parent_scope, |
| 1378 | parent_line, | 1447 | parent_src, |
| 1379 | extra.data.rhs, | 1448 | extra.data.rhs, |
| 1380 | false, | 1449 | false, |
| 1381 | ); | 1450 | ); |
| ... | @@ -1398,14 +1467,14 @@ fn walkInstruction( | ... | @@ -1398,14 +1467,14 @@ fn walkInstruction( |
| 1398 | var lhs: DocData.WalkResult = try self.walkRef( | 1467 | var lhs: DocData.WalkResult = try self.walkRef( |
| 1399 | file, | 1468 | file, |
| 1400 | parent_scope, | 1469 | parent_scope, |
| 1401 | parent_line, | 1470 | parent_src, |
| 1402 | extra.data.lhs, | 1471 | extra.data.lhs, |
| 1403 | false, | 1472 | false, |
| 1404 | ); | 1473 | ); |
| 1405 | var rhs: DocData.WalkResult = try self.walkRef( | 1474 | var rhs: DocData.WalkResult = try self.walkRef( |
| 1406 | file, | 1475 | file, |
| 1407 | parent_scope, | 1476 | parent_scope, |
| 1408 | parent_line, | 1477 | parent_src, |
| 1409 | extra.data.rhs, | 1478 | extra.data.rhs, |
| 1410 | false, | 1479 | false, |
| 1411 | ); | 1480 | ); |
| ... | @@ -1428,14 +1497,14 @@ fn walkInstruction( | ... | @@ -1428,14 +1497,14 @@ fn walkInstruction( |
| 1428 | var lhs: DocData.WalkResult = try self.walkRef( | 1497 | var lhs: DocData.WalkResult = try self.walkRef( |
| 1429 | file, | 1498 | file, |
| 1430 | parent_scope, | 1499 | parent_scope, |
| 1431 | parent_line, | 1500 | parent_src, |
| 1432 | extra.data.lhs, | 1501 | extra.data.lhs, |
| 1433 | false, | 1502 | false, |
| 1434 | ); | 1503 | ); |
| 1435 | var rhs: DocData.WalkResult = try self.walkRef( | 1504 | var rhs: DocData.WalkResult = try self.walkRef( |
| 1436 | file, | 1505 | file, |
| 1437 | parent_scope, | 1506 | parent_scope, |
| 1438 | parent_line, | 1507 | parent_src, |
| 1439 | extra.data.rhs, | 1508 | extra.data.rhs, |
| 1440 | false, | 1509 | false, |
| 1441 | ); | 1510 | ); |
| ... | @@ -1455,7 +1524,7 @@ fn walkInstruction( | ... | @@ -1455,7 +1524,7 @@ fn walkInstruction( |
| 1455 | 1524 | ||
| 1456 | // var operand: DocData.WalkResult = try self.walkRef( | 1525 | // var operand: DocData.WalkResult = try self.walkRef( |
| 1457 | // file, | 1526 | // file, |
| 1458 | // parent_scope, parent_line, | 1527 | // parent_scope, parent_src, |
| 1459 | // un_node.operand, | 1528 | // un_node.operand, |
| 1460 | // false, | 1529 | // false, |
| 1461 | // ); | 1530 | // ); |
| ... | @@ -1464,7 +1533,8 @@ fn walkInstruction( | ... | @@ -1464,7 +1533,8 @@ fn walkInstruction( |
| 1464 | // }, | 1533 | // }, |
| 1465 | .overflow_arithmetic_ptr => { | 1534 | .overflow_arithmetic_ptr => { |
| 1466 | const un_node = data[inst_index].un_node; | 1535 | const un_node = data[inst_index].un_node; |
| 1467 | const elem_type_ref = try self.walkRef(file, parent_scope, parent_line, un_node.operand, false); | 1536 | |
| 1537 | const elem_type_ref = try self.walkRef(file, parent_scope, parent_src, un_node.operand, false); | ||
| 1468 | const type_slot_index = self.types.items.len; | 1538 | const type_slot_index = self.types.items.len; |
| 1469 | try self.types.append(self.arena, .{ | 1539 | try self.types.append(self.arena, .{ |
| 1470 | .Pointer = .{ | 1540 | .Pointer = .{ |
| ... | @@ -1489,7 +1559,7 @@ fn walkInstruction( | ... | @@ -1489,7 +1559,7 @@ fn walkInstruction( |
| 1489 | const elem_type_ref = try self.walkRef( | 1559 | const elem_type_ref = try self.walkRef( |
| 1490 | file, | 1560 | file, |
| 1491 | parent_scope, | 1561 | parent_scope, |
| 1492 | parent_line, | 1562 | parent_src, |
| 1493 | extra.data.elem_type, | 1563 | extra.data.elem_type, |
| 1494 | false, | 1564 | false, |
| 1495 | ); | 1565 | ); |
| ... | @@ -1499,7 +1569,7 @@ fn walkInstruction( | ... | @@ -1499,7 +1569,7 @@ fn walkInstruction( |
| 1499 | var sentinel: ?DocData.Expr = null; | 1569 | var sentinel: ?DocData.Expr = null; |
| 1500 | if (ptr.flags.has_sentinel) { | 1570 | if (ptr.flags.has_sentinel) { |
| 1501 | const ref = @intToEnum(Zir.Inst.Ref, file.zir.extra[extra_index]); | 1571 | const ref = @intToEnum(Zir.Inst.Ref, file.zir.extra[extra_index]); |
| 1502 | const ref_result = try self.walkRef(file, parent_scope, parent_line, ref, false); | 1572 | const ref_result = try self.walkRef(file, parent_scope, parent_src, ref, false); |
| 1503 | sentinel = ref_result.expr; | 1573 | sentinel = ref_result.expr; |
| 1504 | extra_index += 1; | 1574 | extra_index += 1; |
| 1505 | } | 1575 | } |
| ... | @@ -1507,21 +1577,21 @@ fn walkInstruction( | ... | @@ -1507,21 +1577,21 @@ fn walkInstruction( |
| 1507 | var @"align": ?DocData.Expr = null; | 1577 | var @"align": ?DocData.Expr = null; |
| 1508 | if (ptr.flags.has_align) { | 1578 | if (ptr.flags.has_align) { |
| 1509 | const ref = @intToEnum(Zir.Inst.Ref, file.zir.extra[extra_index]); | 1579 | const ref = @intToEnum(Zir.Inst.Ref, file.zir.extra[extra_index]); |
| 1510 | const ref_result = try self.walkRef(file, parent_scope, parent_line, ref, false); | 1580 | const ref_result = try self.walkRef(file, parent_scope, parent_src, ref, false); |
| 1511 | @"align" = ref_result.expr; | 1581 | @"align" = ref_result.expr; |
| 1512 | extra_index += 1; | 1582 | extra_index += 1; |
| 1513 | } | 1583 | } |
| 1514 | var address_space: ?DocData.Expr = null; | 1584 | var address_space: ?DocData.Expr = null; |
| 1515 | if (ptr.flags.has_addrspace) { | 1585 | if (ptr.flags.has_addrspace) { |
| 1516 | const ref = @intToEnum(Zir.Inst.Ref, file.zir.extra[extra_index]); | 1586 | const ref = @intToEnum(Zir.Inst.Ref, file.zir.extra[extra_index]); |
| 1517 | const ref_result = try self.walkRef(file, parent_scope, parent_line, ref, false); | 1587 | const ref_result = try self.walkRef(file, parent_scope, parent_src, ref, false); |
| 1518 | address_space = ref_result.expr; | 1588 | address_space = ref_result.expr; |
| 1519 | extra_index += 1; | 1589 | extra_index += 1; |
| 1520 | } | 1590 | } |
| 1521 | var bit_start: ?DocData.Expr = null; | 1591 | var bit_start: ?DocData.Expr = null; |
| 1522 | if (ptr.flags.has_bit_range) { | 1592 | if (ptr.flags.has_bit_range) { |
| 1523 | const ref = @intToEnum(Zir.Inst.Ref, file.zir.extra[extra_index]); | 1593 | const ref = @intToEnum(Zir.Inst.Ref, file.zir.extra[extra_index]); |
| 1524 | const ref_result = try self.walkRef(file, parent_scope, parent_line, ref, false); | 1594 | const ref_result = try self.walkRef(file, parent_scope, parent_src, ref, false); |
| 1525 | address_space = ref_result.expr; | 1595 | address_space = ref_result.expr; |
| 1526 | extra_index += 1; | 1596 | extra_index += 1; |
| 1527 | } | 1597 | } |
| ... | @@ -1529,7 +1599,7 @@ fn walkInstruction( | ... | @@ -1529,7 +1599,7 @@ fn walkInstruction( |
| 1529 | var host_size: ?DocData.Expr = null; | 1599 | var host_size: ?DocData.Expr = null; |
| 1530 | if (ptr.flags.has_bit_range) { | 1600 | if (ptr.flags.has_bit_range) { |
| 1531 | const ref = @intToEnum(Zir.Inst.Ref, file.zir.extra[extra_index]); | 1601 | const ref = @intToEnum(Zir.Inst.Ref, file.zir.extra[extra_index]); |
| 1532 | const ref_result = try self.walkRef(file, parent_scope, parent_line, ref, false); | 1602 | const ref_result = try self.walkRef(file, parent_scope, parent_src, ref, false); |
| 1533 | host_size = ref_result.expr; | 1603 | host_size = ref_result.expr; |
| 1534 | } | 1604 | } |
| 1535 | 1605 | ||
| ... | @@ -1558,9 +1628,10 @@ fn walkInstruction( | ... | @@ -1558,9 +1628,10 @@ fn walkInstruction( |
| 1558 | }, | 1628 | }, |
| 1559 | .array_type => { | 1629 | .array_type => { |
| 1560 | const pl_node = data[inst_index].pl_node; | 1630 | const pl_node = data[inst_index].pl_node; |
| 1631 | |||
| 1561 | const bin = file.zir.extraData(Zir.Inst.Bin, pl_node.payload_index).data; | 1632 | const bin = file.zir.extraData(Zir.Inst.Bin, pl_node.payload_index).data; |
| 1562 | const len = try self.walkRef(file, parent_scope, parent_line, bin.lhs, false); | 1633 | const len = try self.walkRef(file, parent_scope, parent_src, bin.lhs, false); |
| 1563 | const child = try self.walkRef(file, parent_scope, parent_line, bin.rhs, false); | 1634 | const child = try self.walkRef(file, parent_scope, parent_src, bin.rhs, false); |
| 1564 | 1635 | ||
| 1565 | const type_slot_index = self.types.items.len; | 1636 | const type_slot_index = self.types.items.len; |
| 1566 | try self.types.append(self.arena, .{ | 1637 | try self.types.append(self.arena, .{ |
| ... | @@ -1578,9 +1649,9 @@ fn walkInstruction( | ... | @@ -1578,9 +1649,9 @@ fn walkInstruction( |
| 1578 | .array_type_sentinel => { | 1649 | .array_type_sentinel => { |
| 1579 | const pl_node = data[inst_index].pl_node; | 1650 | const pl_node = data[inst_index].pl_node; |
| 1580 | const extra = file.zir.extraData(Zir.Inst.ArrayTypeSentinel, pl_node.payload_index); | 1651 | const extra = file.zir.extraData(Zir.Inst.ArrayTypeSentinel, pl_node.payload_index); |
| 1581 | const len = try self.walkRef(file, parent_scope, parent_line, extra.data.len, false); | 1652 | const len = try self.walkRef(file, parent_scope, parent_src, extra.data.len, false); |
| 1582 | const sentinel = try self.walkRef(file, parent_scope, parent_line, extra.data.sentinel, false); | 1653 | const sentinel = try self.walkRef(file, parent_scope, parent_src, extra.data.sentinel, false); |
| 1583 | const elem_type = try self.walkRef(file, parent_scope, parent_line, extra.data.elem_type, false); | 1654 | const elem_type = try self.walkRef(file, parent_scope, parent_src, extra.data.elem_type, false); |
| 1584 | 1655 | ||
| 1585 | const type_slot_index = self.types.items.len; | 1656 | const type_slot_index = self.types.items.len; |
| 1586 | try self.types.append(self.arena, .{ | 1657 | try self.types.append(self.arena, .{ |
| ... | @@ -1602,10 +1673,10 @@ fn walkInstruction( | ... | @@ -1602,10 +1673,10 @@ fn walkInstruction( |
| 1602 | const array_data = try self.arena.alloc(usize, operands.len - 1); | 1673 | const array_data = try self.arena.alloc(usize, operands.len - 1); |
| 1603 | 1674 | ||
| 1604 | std.debug.assert(operands.len > 0); | 1675 | std.debug.assert(operands.len > 0); |
| 1605 | var array_type = try self.walkRef(file, parent_scope, parent_line, operands[0], false); | 1676 | var array_type = try self.walkRef(file, parent_scope, parent_src, operands[0], false); |
| 1606 | 1677 | ||
| 1607 | for (operands[1..]) |op, idx| { | 1678 | for (operands[1..]) |op, idx| { |
| 1608 | const wr = try self.walkRef(file, parent_scope, parent_line, op, false); | 1679 | const wr = try self.walkRef(file, parent_scope, parent_src, op, false); |
| 1609 | const expr_index = self.exprs.items.len; | 1680 | const expr_index = self.exprs.items.len; |
| 1610 | try self.exprs.append(self.arena, wr.expr); | 1681 | try self.exprs.append(self.arena, wr.expr); |
| 1611 | array_data[idx] = expr_index; | 1682 | array_data[idx] = expr_index; |
| ... | @@ -1623,7 +1694,7 @@ fn walkInstruction( | ... | @@ -1623,7 +1694,7 @@ fn walkInstruction( |
| 1623 | const array_data = try self.arena.alloc(usize, operands.len); | 1694 | const array_data = try self.arena.alloc(usize, operands.len); |
| 1624 | 1695 | ||
| 1625 | for (operands) |op, idx| { | 1696 | for (operands) |op, idx| { |
| 1626 | const wr = try self.walkRef(file, parent_scope, parent_line, op, false); | 1697 | const wr = try self.walkRef(file, parent_scope, parent_src, op, false); |
| 1627 | const expr_index = self.exprs.items.len; | 1698 | const expr_index = self.exprs.items.len; |
| 1628 | try self.exprs.append(self.arena, wr.expr); | 1699 | try self.exprs.append(self.arena, wr.expr); |
| 1629 | array_data[idx] = expr_index; | 1700 | array_data[idx] = expr_index; |
| ... | @@ -1641,10 +1712,10 @@ fn walkInstruction( | ... | @@ -1641,10 +1712,10 @@ fn walkInstruction( |
| 1641 | const array_data = try self.arena.alloc(usize, operands.len - 1); | 1712 | const array_data = try self.arena.alloc(usize, operands.len - 1); |
| 1642 | 1713 | ||
| 1643 | std.debug.assert(operands.len > 0); | 1714 | std.debug.assert(operands.len > 0); |
| 1644 | var array_type = try self.walkRef(file, parent_scope, parent_line, operands[0], false); | 1715 | var array_type = try self.walkRef(file, parent_scope, parent_src, operands[0], false); |
| 1645 | 1716 | ||
| 1646 | for (operands[1..]) |op, idx| { | 1717 | for (operands[1..]) |op, idx| { |
| 1647 | const wr = try self.walkRef(file, parent_scope, parent_line, op, false); | 1718 | const wr = try self.walkRef(file, parent_scope, parent_src, op, false); |
| 1648 | const expr_index = self.exprs.items.len; | 1719 | const expr_index = self.exprs.items.len; |
| 1649 | try self.exprs.append(self.arena, wr.expr); | 1720 | try self.exprs.append(self.arena, wr.expr); |
| 1650 | array_data[idx] = expr_index; | 1721 | array_data[idx] = expr_index; |
| ... | @@ -1673,7 +1744,7 @@ fn walkInstruction( | ... | @@ -1673,7 +1744,7 @@ fn walkInstruction( |
| 1673 | const array_data = try self.arena.alloc(usize, operands.len); | 1744 | const array_data = try self.arena.alloc(usize, operands.len); |
| 1674 | 1745 | ||
| 1675 | for (operands) |op, idx| { | 1746 | for (operands) |op, idx| { |
| 1676 | const wr = try self.walkRef(file, parent_scope, parent_line, op, false); | 1747 | const wr = try self.walkRef(file, parent_scope, parent_src, op, false); |
| 1677 | const expr_index = self.exprs.items.len; | 1748 | const expr_index = self.exprs.items.len; |
| 1678 | try self.exprs.append(self.arena, wr.expr); | 1749 | try self.exprs.append(self.arena, wr.expr); |
| 1679 | array_data[idx] = expr_index; | 1750 | array_data[idx] = expr_index; |
| ... | @@ -1705,15 +1776,17 @@ fn walkInstruction( | ... | @@ -1705,15 +1776,17 @@ fn walkInstruction( |
| 1705 | }, | 1776 | }, |
| 1706 | .negate => { | 1777 | .negate => { |
| 1707 | const un_node = data[inst_index].un_node; | 1778 | const un_node = data[inst_index].un_node; |
| 1779 | |||
| 1708 | var operand: DocData.WalkResult = try self.walkRef( | 1780 | var operand: DocData.WalkResult = try self.walkRef( |
| 1709 | file, | 1781 | file, |
| 1710 | parent_scope, | 1782 | parent_scope, |
| 1711 | parent_line, | 1783 | parent_src, |
| 1712 | un_node.operand, | 1784 | un_node.operand, |
| 1713 | need_type, | 1785 | need_type, |
| 1714 | ); | 1786 | ); |
| 1715 | switch (operand.expr) { | 1787 | switch (operand.expr) { |
| 1716 | .int => |*int| int.negated = true, | 1788 | .int => |*int| int.negated = true, |
| 1789 | .int_big => |*int_big| int_big.negated = true, | ||
| 1717 | else => { | 1790 | else => { |
| 1718 | printWithContext( | 1791 | printWithContext( |
| 1719 | file, | 1792 | file, |
| ... | @@ -1727,10 +1800,11 @@ fn walkInstruction( | ... | @@ -1727,10 +1800,11 @@ fn walkInstruction( |
| 1727 | }, | 1800 | }, |
| 1728 | .size_of => { | 1801 | .size_of => { |
| 1729 | const un_node = data[inst_index].un_node; | 1802 | const un_node = data[inst_index].un_node; |
| 1803 | |||
| 1730 | const operand = try self.walkRef( | 1804 | const operand = try self.walkRef( |
| 1731 | file, | 1805 | file, |
| 1732 | parent_scope, | 1806 | parent_scope, |
| 1733 | parent_line, | 1807 | parent_src, |
| 1734 | un_node.operand, | 1808 | un_node.operand, |
| 1735 | false, | 1809 | false, |
| 1736 | ); | 1810 | ); |
| ... | @@ -1744,10 +1818,11 @@ fn walkInstruction( | ... | @@ -1744,10 +1818,11 @@ fn walkInstruction( |
| 1744 | .bit_size_of => { | 1818 | .bit_size_of => { |
| 1745 | // not working correctly with `align()` | 1819 | // not working correctly with `align()` |
| 1746 | const un_node = data[inst_index].un_node; | 1820 | const un_node = data[inst_index].un_node; |
| 1821 | |||
| 1747 | const operand = try self.walkRef( | 1822 | const operand = try self.walkRef( |
| 1748 | file, | 1823 | file, |
| 1749 | parent_scope, | 1824 | parent_scope, |
| 1750 | parent_line, | 1825 | parent_src, |
| 1751 | un_node.operand, | 1826 | un_node.operand, |
| 1752 | need_type, | 1827 | need_type, |
| 1753 | ); | 1828 | ); |
| ... | @@ -1765,7 +1840,7 @@ fn walkInstruction( | ... | @@ -1765,7 +1840,7 @@ fn walkInstruction( |
| 1765 | const operand = try self.walkRef( | 1840 | const operand = try self.walkRef( |
| 1766 | file, | 1841 | file, |
| 1767 | parent_scope, | 1842 | parent_scope, |
| 1768 | parent_line, | 1843 | parent_src, |
| 1769 | un_node.operand, | 1844 | un_node.operand, |
| 1770 | false, | 1845 | false, |
| 1771 | ); | 1846 | ); |
| ... | @@ -1782,7 +1857,8 @@ fn walkInstruction( | ... | @@ -1782,7 +1857,8 @@ fn walkInstruction( |
| 1782 | const pl_node = data[inst_index].pl_node; | 1857 | const pl_node = data[inst_index].pl_node; |
| 1783 | const extra = file.zir.extraData(Zir.Inst.SwitchBlock, pl_node.payload_index); | 1858 | const extra = file.zir.extraData(Zir.Inst.SwitchBlock, pl_node.payload_index); |
| 1784 | const cond_index = self.exprs.items.len; | 1859 | const cond_index = self.exprs.items.len; |
| 1785 | _ = try self.walkRef(file, parent_scope, parent_line, extra.data.operand, false); | 1860 | |
| 1861 | _ = try self.walkRef(file, parent_scope, parent_src, extra.data.operand, false); | ||
| 1786 | 1862 | ||
| 1787 | const ast_index = self.ast_nodes.items.len; | 1863 | const ast_index = self.ast_nodes.items.len; |
| 1788 | const type_index = self.types.items.len - 1; | 1864 | const type_index = self.types.items.len - 1; |
| ... | @@ -1810,7 +1886,7 @@ fn walkInstruction( | ... | @@ -1810,7 +1886,7 @@ fn walkInstruction( |
| 1810 | const operand = try self.walkRef( | 1886 | const operand = try self.walkRef( |
| 1811 | file, | 1887 | file, |
| 1812 | parent_scope, | 1888 | parent_scope, |
| 1813 | parent_line, | 1889 | parent_src, |
| 1814 | un_node.operand, | 1890 | un_node.operand, |
| 1815 | need_type, | 1891 | need_type, |
| 1816 | ); | 1892 | ); |
| ... | @@ -1833,10 +1909,11 @@ fn walkInstruction( | ... | @@ -1833,10 +1909,11 @@ fn walkInstruction( |
| 1833 | 1909 | ||
| 1834 | .typeof => { | 1910 | .typeof => { |
| 1835 | const un_node = data[inst_index].un_node; | 1911 | const un_node = data[inst_index].un_node; |
| 1912 | |||
| 1836 | const operand = try self.walkRef( | 1913 | const operand = try self.walkRef( |
| 1837 | file, | 1914 | file, |
| 1838 | parent_scope, | 1915 | parent_scope, |
| 1839 | parent_line, | 1916 | parent_src, |
| 1840 | un_node.operand, | 1917 | un_node.operand, |
| 1841 | need_type, | 1918 | need_type, |
| 1842 | ); | 1919 | ); |
| ... | @@ -1852,11 +1929,10 @@ fn walkInstruction( | ... | @@ -1852,11 +1929,10 @@ fn walkInstruction( |
| 1852 | const pl_node = data[inst_index].pl_node; | 1929 | const pl_node = data[inst_index].pl_node; |
| 1853 | const extra = file.zir.extraData(Zir.Inst.Block, pl_node.payload_index); | 1930 | const extra = file.zir.extraData(Zir.Inst.Block, pl_node.payload_index); |
| 1854 | const body = file.zir.extra[extra.end..][extra.data.body_len - 1]; | 1931 | const body = file.zir.extra[extra.end..][extra.data.body_len - 1]; |
| 1855 | |||
| 1856 | var operand: DocData.WalkResult = try self.walkRef( | 1932 | var operand: DocData.WalkResult = try self.walkRef( |
| 1857 | file, | 1933 | file, |
| 1858 | parent_scope, | 1934 | parent_scope, |
| 1859 | parent_line, | 1935 | parent_src, |
| 1860 | data[body].@"break".operand, | 1936 | data[body].@"break".operand, |
| 1861 | false, | 1937 | false, |
| 1862 | ); | 1938 | ); |
| ... | @@ -1872,10 +1948,11 @@ fn walkInstruction( | ... | @@ -1872,10 +1948,11 @@ fn walkInstruction( |
| 1872 | .type_info => { | 1948 | .type_info => { |
| 1873 | // @check | 1949 | // @check |
| 1874 | const un_node = data[inst_index].un_node; | 1950 | const un_node = data[inst_index].un_node; |
| 1951 | |||
| 1875 | const operand = try self.walkRef( | 1952 | const operand = try self.walkRef( |
| 1876 | file, | 1953 | file, |
| 1877 | parent_scope, | 1954 | parent_scope, |
| 1878 | parent_line, | 1955 | parent_src, |
| 1879 | un_node.operand, | 1956 | un_node.operand, |
| 1880 | need_type, | 1957 | need_type, |
| 1881 | ); | 1958 | ); |
| ... | @@ -1894,7 +1971,7 @@ fn walkInstruction( | ... | @@ -1894,7 +1971,7 @@ fn walkInstruction( |
| 1894 | const dest_type_walk = try self.walkRef( | 1971 | const dest_type_walk = try self.walkRef( |
| 1895 | file, | 1972 | file, |
| 1896 | parent_scope, | 1973 | parent_scope, |
| 1897 | parent_line, | 1974 | parent_src, |
| 1898 | extra.data.dest_type, | 1975 | extra.data.dest_type, |
| 1899 | false, | 1976 | false, |
| 1900 | ); | 1977 | ); |
| ... | @@ -1902,7 +1979,7 @@ fn walkInstruction( | ... | @@ -1902,7 +1979,7 @@ fn walkInstruction( |
| 1902 | const operand = try self.walkRef( | 1979 | const operand = try self.walkRef( |
| 1903 | file, | 1980 | file, |
| 1904 | parent_scope, | 1981 | parent_scope, |
| 1905 | parent_line, | 1982 | parent_src, |
| 1906 | extra.data.operand, | 1983 | extra.data.operand, |
| 1907 | false, | 1984 | false, |
| 1908 | ); | 1985 | ); |
| ... | @@ -1927,10 +2004,11 @@ fn walkInstruction( | ... | @@ -1927,10 +2004,11 @@ fn walkInstruction( |
| 1927 | }, | 2004 | }, |
| 1928 | .optional_type => { | 2005 | .optional_type => { |
| 1929 | const un_node = data[inst_index].un_node; | 2006 | const un_node = data[inst_index].un_node; |
| 2007 | |||
| 1930 | const operand: DocData.WalkResult = try self.walkRef( | 2008 | const operand: DocData.WalkResult = try self.walkRef( |
| 1931 | file, | 2009 | file, |
| 1932 | parent_scope, | 2010 | parent_scope, |
| 1933 | parent_line, | 2011 | parent_src, |
| 1934 | un_node.operand, | 2012 | un_node.operand, |
| 1935 | false, | 2013 | false, |
| 1936 | ); | 2014 | ); |
| ... | @@ -2014,7 +2092,7 @@ fn walkInstruction( | ... | @@ -2014,7 +2092,7 @@ fn walkInstruction( |
| 2014 | } | 2092 | } |
| 2015 | } | 2093 | } |
| 2016 | 2094 | ||
| 2017 | break :blk try self.walkRef(file, parent_scope, parent_line, lhs_ref, false); | 2095 | break :blk try self.walkRef(file, parent_scope, parent_src, lhs_ref, false); |
| 2018 | }; | 2096 | }; |
| 2019 | try path.append(self.arena, wr.expr); | 2097 | try path.append(self.arena, wr.expr); |
| 2020 | 2098 | ||
| ... | @@ -2065,7 +2143,7 @@ fn walkInstruction( | ... | @@ -2065,7 +2143,7 @@ fn walkInstruction( |
| 2065 | return self.walkRef( | 2143 | return self.walkRef( |
| 2066 | file, | 2144 | file, |
| 2067 | parent_scope, | 2145 | parent_scope, |
| 2068 | parent_line, | 2146 | parent_src, |
| 2069 | getBlockInlineBreak(file.zir, inst_index), | 2147 | getBlockInlineBreak(file.zir, inst_index), |
| 2070 | need_type, | 2148 | need_type, |
| 2071 | ); | 2149 | ); |
| ... | @@ -2092,13 +2170,18 @@ fn walkInstruction( | ... | @@ -2092,13 +2170,18 @@ fn walkInstruction( |
| 2092 | Zir.Inst.FieldType, | 2170 | Zir.Inst.FieldType, |
| 2093 | field_pl_node.payload_index, | 2171 | field_pl_node.payload_index, |
| 2094 | ); | 2172 | ); |
| 2173 | const field_src = try self.srcLocInfo( | ||
| 2174 | file, | ||
| 2175 | field_pl_node.src_node, | ||
| 2176 | parent_src, | ||
| 2177 | ); | ||
| 2095 | 2178 | ||
| 2096 | // On first iteration use field info to find out the struct type | 2179 | // On first iteration use field info to find out the struct type |
| 2097 | if (idx == extra.end) { | 2180 | if (idx == extra.end) { |
| 2098 | const wr = try self.walkRef( | 2181 | const wr = try self.walkRef( |
| 2099 | file, | 2182 | file, |
| 2100 | parent_scope, | 2183 | parent_scope, |
| 2101 | parent_line, | 2184 | field_src, |
| 2102 | field_extra.data.container_type, | 2185 | field_extra.data.container_type, |
| 2103 | false, | 2186 | false, |
| 2104 | ); | 2187 | ); |
| ... | @@ -2109,7 +2192,7 @@ fn walkInstruction( | ... | @@ -2109,7 +2192,7 @@ fn walkInstruction( |
| 2109 | const value = try self.walkRef( | 2192 | const value = try self.walkRef( |
| 2110 | file, | 2193 | file, |
| 2111 | parent_scope, | 2194 | parent_scope, |
| 2112 | parent_line, | 2195 | parent_src, |
| 2113 | init_extra.data.init, | 2196 | init_extra.data.init, |
| 2114 | need_type, | 2197 | need_type, |
| 2115 | ); | 2198 | ); |
| ... | @@ -2123,10 +2206,11 @@ fn walkInstruction( | ... | @@ -2123,10 +2206,11 @@ fn walkInstruction( |
| 2123 | }, | 2206 | }, |
| 2124 | .struct_init_empty => { | 2207 | .struct_init_empty => { |
| 2125 | const un_node = data[inst_index].un_node; | 2208 | const un_node = data[inst_index].un_node; |
| 2209 | |||
| 2126 | var operand: DocData.WalkResult = try self.walkRef( | 2210 | var operand: DocData.WalkResult = try self.walkRef( |
| 2127 | file, | 2211 | file, |
| 2128 | parent_scope, | 2212 | parent_scope, |
| 2129 | parent_line, | 2213 | parent_src, |
| 2130 | un_node.operand, | 2214 | un_node.operand, |
| 2131 | false, | 2215 | false, |
| 2132 | ); | 2216 | ); |
| ... | @@ -2159,7 +2243,7 @@ fn walkInstruction( | ... | @@ -2159,7 +2243,7 @@ fn walkInstruction( |
| 2159 | const value = try self.walkRef( | 2243 | const value = try self.walkRef( |
| 2160 | file, | 2244 | file, |
| 2161 | parent_scope, | 2245 | parent_scope, |
| 2162 | parent_line, | 2246 | parent_src, |
| 2163 | init_extra.data.init, | 2247 | init_extra.data.init, |
| 2164 | need_type, | 2248 | need_type, |
| 2165 | ); | 2249 | ); |
| ... | @@ -2235,7 +2319,7 @@ fn walkInstruction( | ... | @@ -2235,7 +2319,7 @@ fn walkInstruction( |
| 2235 | const pl_node = data[inst_index].pl_node; | 2319 | const pl_node = data[inst_index].pl_node; |
| 2236 | const extra = file.zir.extraData(Zir.Inst.Call, pl_node.payload_index); | 2320 | const extra = file.zir.extraData(Zir.Inst.Call, pl_node.payload_index); |
| 2237 | 2321 | ||
| 2238 | const callee = try self.walkRef(file, parent_scope, parent_line, extra.data.callee, need_type); | 2322 | const callee = try self.walkRef(file, parent_scope, parent_src, extra.data.callee, need_type); |
| 2239 | 2323 | ||
| 2240 | const args_len = extra.data.flags.args_len; | 2324 | const args_len = extra.data.flags.args_len; |
| 2241 | var args = try self.arena.alloc(DocData.Expr, args_len); | 2325 | var args = try self.arena.alloc(DocData.Expr, args_len); |
| ... | @@ -2250,7 +2334,7 @@ fn walkInstruction( | ... | @@ -2250,7 +2334,7 @@ fn walkInstruction( |
| 2250 | // to show discrepancies between the types of provided | 2334 | // to show discrepancies between the types of provided |
| 2251 | // arguments and the types declared in the function | 2335 | // arguments and the types declared in the function |
| 2252 | // signature for its parameters. | 2336 | // signature for its parameters. |
| 2253 | const wr = try self.walkRef(file, parent_scope, parent_line, ref, false); | 2337 | const wr = try self.walkRef(file, parent_scope, parent_src, ref, false); |
| 2254 | args[i] = wr.expr; | 2338 | args[i] = wr.expr; |
| 2255 | } | 2339 | } |
| 2256 | 2340 | ||
| ... | @@ -2281,7 +2365,7 @@ fn walkInstruction( | ... | @@ -2281,7 +2365,7 @@ fn walkInstruction( |
| 2281 | const result = self.analyzeFunction( | 2365 | const result = self.analyzeFunction( |
| 2282 | file, | 2366 | file, |
| 2283 | parent_scope, | 2367 | parent_scope, |
| 2284 | parent_line, | 2368 | parent_src, |
| 2285 | inst_index, | 2369 | inst_index, |
| 2286 | self_ast_node_index, | 2370 | self_ast_node_index, |
| 2287 | type_slot_index, | 2371 | type_slot_index, |
| ... | @@ -2297,7 +2381,7 @@ fn walkInstruction( | ... | @@ -2297,7 +2381,7 @@ fn walkInstruction( |
| 2297 | const result = self.analyzeFancyFunction( | 2381 | const result = self.analyzeFancyFunction( |
| 2298 | file, | 2382 | file, |
| 2299 | parent_scope, | 2383 | parent_scope, |
| 2300 | parent_line, | 2384 | parent_src, |
| 2301 | inst_index, | 2385 | inst_index, |
| 2302 | self_ast_node_index, | 2386 | self_ast_node_index, |
| 2303 | type_slot_index, | 2387 | type_slot_index, |
| ... | @@ -2325,7 +2409,7 @@ fn walkInstruction( | ... | @@ -2325,7 +2409,7 @@ fn walkInstruction( |
| 2325 | 2409 | ||
| 2326 | var array_type: ?DocData.Expr = null; | 2410 | var array_type: ?DocData.Expr = null; |
| 2327 | for (args) |arg, idx| { | 2411 | for (args) |arg, idx| { |
| 2328 | const wr = try self.walkRef(file, parent_scope, parent_line, arg, idx == 0); | 2412 | const wr = try self.walkRef(file, parent_scope, parent_src, arg, idx == 0); |
| 2329 | if (idx == 0) { | 2413 | if (idx == 0) { |
| 2330 | array_type = wr.typeRef; | 2414 | array_type = wr.typeRef; |
| 2331 | } | 2415 | } |
| ... | @@ -2355,36 +2439,91 @@ fn walkInstruction( | ... | @@ -2355,36 +2439,91 @@ fn walkInstruction( |
| 2355 | return result; | 2439 | return result; |
| 2356 | }, | 2440 | }, |
| 2357 | .opaque_decl => { | 2441 | .opaque_decl => { |
| 2442 | const type_slot_index = self.types.items.len; | ||
| 2443 | try self.types.append(self.arena, .{ .Unanalyzed = .{} }); | ||
| 2444 | |||
| 2445 | var scope: Scope = .{ | ||
| 2446 | .parent = parent_scope, | ||
| 2447 | .enclosing_type = type_slot_index, | ||
| 2448 | }; | ||
| 2449 | |||
| 2358 | const small = @bitCast(Zir.Inst.OpaqueDecl.Small, extended.small); | 2450 | const small = @bitCast(Zir.Inst.OpaqueDecl.Small, extended.small); |
| 2359 | var extra_index: usize = extended.operand; | 2451 | var extra_index: usize = extended.operand; |
| 2452 | |||
| 2360 | const src_node: ?i32 = if (small.has_src_node) blk: { | 2453 | const src_node: ?i32 = if (small.has_src_node) blk: { |
| 2361 | const src_node = @bitCast(i32, file.zir.extra[extra_index]); | 2454 | const src_node = @bitCast(i32, file.zir.extra[extra_index]); |
| 2362 | extra_index += 1; | 2455 | extra_index += 1; |
| 2363 | break :blk src_node; | 2456 | break :blk src_node; |
| 2364 | } else null; | 2457 | } else null; |
| 2365 | _ = src_node; | 2458 | |
| 2459 | const src_info = if (src_node) |sn| | ||
| 2460 | try self.srcLocInfo(file, sn, parent_src) | ||
| 2461 | else | ||
| 2462 | parent_src; | ||
| 2463 | _ = src_info; | ||
| 2366 | 2464 | ||
| 2367 | const decls_len = if (small.has_decls_len) blk: { | 2465 | const decls_len = if (small.has_decls_len) blk: { |
| 2368 | const decls_len = file.zir.extra[extra_index]; | 2466 | const decls_len = file.zir.extra[extra_index]; |
| 2369 | extra_index += 1; | 2467 | extra_index += 1; |
| 2370 | break :blk decls_len; | 2468 | break :blk decls_len; |
| 2371 | } else 0; | 2469 | } else 0; |
| 2372 | _ = decls_len; | 2470 | |
| 2373 | 2471 | var decl_indexes: std.ArrayListUnmanaged(usize) = .{}; | |
| 2374 | const decls_bits = file.zir.extra[extra_index]; | 2472 | var priv_decl_indexes: std.ArrayListUnmanaged(usize) = .{}; |
| 2375 | _ = decls_bits; | 2473 | |
| 2376 | 2474 | const decls_first_index = self.decls.items.len; | |
| 2377 | // const sep = "=" ** 200; | 2475 | // Decl name lookahead for reserving slots in `scope` (and `decls`). |
| 2378 | // log.debug("{s}", .{sep}); | 2476 | // Done to make sure that all decl refs can be resolved correctly, |
| 2379 | // log.debug("small = {any}", .{small}); | 2477 | // even if we haven't fully analyzed the decl yet. |
| 2380 | // log.debug("src_node = {}", .{src_node}); | 2478 | { |
| 2381 | // log.debug("decls_len = {}", .{decls_len}); | 2479 | var it = file.zir.declIterator(@intCast(u32, inst_index)); |
| 2382 | // log.debug("decls_bit = {}", .{decls_bits}); | 2480 | try self.decls.resize(self.arena, decls_first_index + it.decls_len); |
| 2383 | // log.debug("{s}", .{sep}); | 2481 | for (self.decls.items[decls_first_index..]) |*slot| { |
| 2384 | const type_slot_index = self.types.items.len - 1; | 2482 | slot._analyzed = false; |
| 2385 | try self.types.append(self.arena, .{ .Opaque = .{ .name = "TODO" } }); | 2483 | } |
| 2484 | var decls_slot_index = decls_first_index; | ||
| 2485 | while (it.next()) |d| : (decls_slot_index += 1) { | ||
| 2486 | const decl_name_index = file.zir.extra[d.sub_index + 5]; | ||
| 2487 | try scope.insertDeclRef(self.arena, decl_name_index, decls_slot_index); | ||
| 2488 | } | ||
| 2489 | } | ||
| 2490 | |||
| 2491 | extra_index = try self.walkDecls( | ||
| 2492 | file, | ||
| 2493 | &scope, | ||
| 2494 | src_info, | ||
| 2495 | decls_first_index, | ||
| 2496 | decls_len, | ||
| 2497 | &decl_indexes, | ||
| 2498 | &priv_decl_indexes, | ||
| 2499 | extra_index, | ||
| 2500 | ); | ||
| 2501 | |||
| 2502 | self.types.items[type_slot_index] = .{ | ||
| 2503 | .Opaque = .{ | ||
| 2504 | .name = "todo_name", | ||
| 2505 | .src = self_ast_node_index, | ||
| 2506 | .privDecls = priv_decl_indexes.items, | ||
| 2507 | .pubDecls = decl_indexes.items, | ||
| 2508 | .ast = self_ast_node_index, | ||
| 2509 | }, | ||
| 2510 | }; | ||
| 2511 | if (self.ref_paths_pending_on_types.get(type_slot_index)) |paths| { | ||
| 2512 | for (paths.items) |resume_info| { | ||
| 2513 | try self.tryResolveRefPath( | ||
| 2514 | resume_info.file, | ||
| 2515 | inst_index, | ||
| 2516 | resume_info.ref_path, | ||
| 2517 | ); | ||
| 2518 | } | ||
| 2519 | |||
| 2520 | _ = self.ref_paths_pending_on_types.remove(type_slot_index); | ||
| 2521 | // TODO: we should deallocate the arraylist that holds all the | ||
| 2522 | // decl paths. not doing it now since it's arena-allocated | ||
| 2523 | // anyway, but maybe we should put it elsewhere. | ||
| 2524 | } | ||
| 2386 | return DocData.WalkResult{ | 2525 | return DocData.WalkResult{ |
| 2387 | .typeRef = .{ .type = @enumToInt(Ref.anyopaque_type) }, | 2526 | .typeRef = .{ .type = @enumToInt(Ref.type_type) }, |
| 2388 | .expr = .{ .type = type_slot_index }, | 2527 | .expr = .{ .type = type_slot_index }, |
| 2389 | }; | 2528 | }; |
| 2390 | }, | 2529 | }, |
| ... | @@ -2419,7 +2558,11 @@ fn walkInstruction( | ... | @@ -2419,7 +2558,11 @@ fn walkInstruction( |
| 2419 | extra_index += 1; | 2558 | extra_index += 1; |
| 2420 | break :blk src_node; | 2559 | break :blk src_node; |
| 2421 | } else null; | 2560 | } else null; |
| 2422 | _ = src_node; | 2561 | |
| 2562 | const src_info = if (src_node) |sn| | ||
| 2563 | try self.srcLocInfo(file, sn, parent_src) | ||
| 2564 | else | ||
| 2565 | parent_src; | ||
| 2423 | 2566 | ||
| 2424 | const tag_type: ?Ref = if (small.has_tag_type) blk: { | 2567 | const tag_type: ?Ref = if (small.has_tag_type) blk: { |
| 2425 | const tag_type = file.zir.extra[extra_index]; | 2568 | const tag_type = file.zir.extra[extra_index]; |
| ... | @@ -2470,7 +2613,7 @@ fn walkInstruction( | ... | @@ -2470,7 +2613,7 @@ fn walkInstruction( |
| 2470 | extra_index = try self.walkDecls( | 2613 | extra_index = try self.walkDecls( |
| 2471 | file, | 2614 | file, |
| 2472 | &scope, | 2615 | &scope, |
| 2473 | parent_line, | 2616 | src_info, |
| 2474 | decls_first_index, | 2617 | decls_first_index, |
| 2475 | decls_len, | 2618 | decls_len, |
| 2476 | &decl_indexes, | 2619 | &decl_indexes, |
| ... | @@ -2491,7 +2634,7 @@ fn walkInstruction( | ... | @@ -2491,7 +2634,7 @@ fn walkInstruction( |
| 2491 | try self.collectUnionFieldInfo( | 2634 | try self.collectUnionFieldInfo( |
| 2492 | file, | 2635 | file, |
| 2493 | &scope, | 2636 | &scope, |
| 2494 | parent_line, | 2637 | src_info, |
| 2495 | fields_len, | 2638 | fields_len, |
| 2496 | &field_type_refs, | 2639 | &field_type_refs, |
| 2497 | &field_name_indexes, | 2640 | &field_name_indexes, |
| ... | @@ -2541,7 +2684,11 @@ fn walkInstruction( | ... | @@ -2541,7 +2684,11 @@ fn walkInstruction( |
| 2541 | extra_index += 1; | 2684 | extra_index += 1; |
| 2542 | break :blk src_node; | 2685 | break :blk src_node; |
| 2543 | } else null; | 2686 | } else null; |
| 2544 | _ = src_node; | 2687 | |
| 2688 | const src_info = if (src_node) |sn| | ||
| 2689 | try self.srcLocInfo(file, sn, parent_src) | ||
| 2690 | else | ||
| 2691 | parent_src; | ||
| 2545 | 2692 | ||
| 2546 | const tag_type: ?Ref = if (small.has_tag_type) blk: { | 2693 | const tag_type: ?Ref = if (small.has_tag_type) blk: { |
| 2547 | const tag_type = file.zir.extra[extra_index]; | 2694 | const tag_type = file.zir.extra[extra_index]; |
| ... | @@ -2592,7 +2739,7 @@ fn walkInstruction( | ... | @@ -2592,7 +2739,7 @@ fn walkInstruction( |
| 2592 | extra_index = try self.walkDecls( | 2739 | extra_index = try self.walkDecls( |
| 2593 | file, | 2740 | file, |
| 2594 | &scope, | 2741 | &scope, |
| 2595 | parent_line, | 2742 | src_info, |
| 2596 | decls_first_index, | 2743 | decls_first_index, |
| 2597 | decls_len, | 2744 | decls_len, |
| 2598 | &decl_indexes, | 2745 | &decl_indexes, |
| ... | @@ -2687,7 +2834,11 @@ fn walkInstruction( | ... | @@ -2687,7 +2834,11 @@ fn walkInstruction( |
| 2687 | extra_index += 1; | 2834 | extra_index += 1; |
| 2688 | break :blk src_node; | 2835 | break :blk src_node; |
| 2689 | } else null; | 2836 | } else null; |
| 2690 | _ = src_node; | 2837 | |
| 2838 | const src_info = if (src_node) |sn| | ||
| 2839 | try self.srcLocInfo(file, sn, parent_src) | ||
| 2840 | else | ||
| 2841 | parent_src; | ||
| 2691 | 2842 | ||
| 2692 | const fields_len = if (small.has_fields_len) blk: { | 2843 | const fields_len = if (small.has_fields_len) blk: { |
| 2693 | const fields_len = file.zir.extra[extra_index]; | 2844 | const fields_len = file.zir.extra[extra_index]; |
| ... | @@ -2736,7 +2887,7 @@ fn walkInstruction( | ... | @@ -2736,7 +2887,7 @@ fn walkInstruction( |
| 2736 | extra_index = try self.walkDecls( | 2887 | extra_index = try self.walkDecls( |
| 2737 | file, | 2888 | file, |
| 2738 | &scope, | 2889 | &scope, |
| 2739 | parent_line, | 2890 | src_info, |
| 2740 | decls_first_index, | 2891 | decls_first_index, |
| 2741 | decls_len, | 2892 | decls_len, |
| 2742 | &decl_indexes, | 2893 | &decl_indexes, |
| ... | @@ -2749,7 +2900,7 @@ fn walkInstruction( | ... | @@ -2749,7 +2900,7 @@ fn walkInstruction( |
| 2749 | try self.collectStructFieldInfo( | 2900 | try self.collectStructFieldInfo( |
| 2750 | file, | 2901 | file, |
| 2751 | &scope, | 2902 | &scope, |
| 2752 | parent_line, | 2903 | src_info, |
| 2753 | fields_len, | 2904 | fields_len, |
| 2754 | &field_type_refs, | 2905 | &field_type_refs, |
| 2755 | &field_name_indexes, | 2906 | &field_name_indexes, |
| ... | @@ -2793,7 +2944,7 @@ fn walkInstruction( | ... | @@ -2793,7 +2944,7 @@ fn walkInstruction( |
| 2793 | const extra = file.zir.extraData(Zir.Inst.UnNode, extended.operand).data; | 2944 | const extra = file.zir.extraData(Zir.Inst.UnNode, extended.operand).data; |
| 2794 | const bin_index = self.exprs.items.len; | 2945 | const bin_index = self.exprs.items.len; |
| 2795 | try self.exprs.append(self.arena, .{ .builtin = .{ .param = 0 } }); | 2946 | try self.exprs.append(self.arena, .{ .builtin = .{ .param = 0 } }); |
| 2796 | const param = try self.walkRef(file, parent_scope, parent_line, extra.operand, false); | 2947 | const param = try self.walkRef(file, parent_scope, parent_src, extra.operand, false); |
| 2797 | 2948 | ||
| 2798 | const param_index = self.exprs.items.len; | 2949 | const param_index = self.exprs.items.len; |
| 2799 | try self.exprs.append(self.arena, param.expr); | 2950 | try self.exprs.append(self.arena, param.expr); |
| ... | @@ -2821,13 +2972,14 @@ fn walkDecls( | ... | @@ -2821,13 +2972,14 @@ fn walkDecls( |
| 2821 | self: *Autodoc, | 2972 | self: *Autodoc, |
| 2822 | file: *File, | 2973 | file: *File, |
| 2823 | scope: *Scope, | 2974 | scope: *Scope, |
| 2824 | parent_line: usize, | 2975 | parent_src: SrcLocInfo, |
| 2825 | decls_first_index: usize, | 2976 | decls_first_index: usize, |
| 2826 | decls_len: u32, | 2977 | decls_len: u32, |
| 2827 | decl_indexes: *std.ArrayListUnmanaged(usize), | 2978 | decl_indexes: *std.ArrayListUnmanaged(usize), |
| 2828 | priv_decl_indexes: *std.ArrayListUnmanaged(usize), | 2979 | priv_decl_indexes: *std.ArrayListUnmanaged(usize), |
| 2829 | extra_start: usize, | 2980 | extra_start: usize, |
| 2830 | ) AutodocErrors!usize { | 2981 | ) AutodocErrors!usize { |
| 2982 | const data = file.zir.instructions.items(.data); | ||
| 2831 | const bit_bags_count = std.math.divCeil(usize, decls_len, 8) catch unreachable; | 2983 | const bit_bags_count = std.math.divCeil(usize, decls_len, 8) catch unreachable; |
| 2832 | var extra_index = extra_start + bit_bags_count; | 2984 | var extra_index = extra_start + bit_bags_count; |
| 2833 | var bit_bag_index: usize = extra_start; | 2985 | var bit_bag_index: usize = extra_start; |
| ... | @@ -2854,7 +3006,8 @@ fn walkDecls( | ... | @@ -2854,7 +3006,8 @@ fn walkDecls( |
| 2854 | 3006 | ||
| 2855 | // const hash_u32s = file.zir.extra[extra_index..][0..4]; | 3007 | // const hash_u32s = file.zir.extra[extra_index..][0..4]; |
| 2856 | extra_index += 4; | 3008 | extra_index += 4; |
| 2857 | const line = parent_line + file.zir.extra[extra_index]; | 3009 | |
| 3010 | // const line = file.zir.extra[extra_index]; | ||
| 2858 | extra_index += 1; | 3011 | extra_index += 1; |
| 2859 | const decl_name_index = file.zir.extra[extra_index]; | 3012 | const decl_name_index = file.zir.extra[extra_index]; |
| 2860 | extra_index += 1; | 3013 | extra_index += 1; |
| ... | @@ -2884,10 +3037,11 @@ fn walkDecls( | ... | @@ -2884,10 +3037,11 @@ fn walkDecls( |
| 2884 | }; | 3037 | }; |
| 2885 | _ = addrspace_inst; | 3038 | _ = addrspace_inst; |
| 2886 | 3039 | ||
| 2887 | // const pub_str = if (is_pub) "pub " else ""; | 3040 | // This is known to work because decl values are always block_inlines |
| 2888 | // const hash_bytes = @bitCast([16]u8, hash_u32s.*); | 3041 | const value_pl_node = data[value_index].pl_node; |
| 3042 | const decl_src = try self.srcLocInfo(file, value_pl_node.src_node, parent_src); | ||
| 2889 | 3043 | ||
| 2890 | var is_test = false; // we discover if it's a test by lookin at its name | 3044 | var is_test = false; // we discover if it's a test by looking at its name |
| 2891 | const name: []const u8 = blk: { | 3045 | const name: []const u8 = blk: { |
| 2892 | if (decl_name_index == 0) { | 3046 | if (decl_name_index == 0) { |
| 2893 | break :blk if (is_exported) "usingnamespace" else "comptime"; | 3047 | break :blk if (is_exported) "usingnamespace" else "comptime"; |
| ... | @@ -2895,84 +3049,32 @@ fn walkDecls( | ... | @@ -2895,84 +3049,32 @@ fn walkDecls( |
| 2895 | is_test = true; | 3049 | is_test = true; |
| 2896 | break :blk "test"; | 3050 | break :blk "test"; |
| 2897 | } else if (decl_name_index == 2) { | 3051 | } else if (decl_name_index == 2) { |
| 2898 | is_test = true; | 3052 | // it is a decltest |
| 2899 | // TODO: remove temporary hack | 3053 | const decl_being_tested = scope.resolveDeclName(doc_comment_index); |
| 2900 | break :blk "test"; | 3054 | const func_index = getBlockInlineBreak(file.zir, value_index); |
| 2901 | // // it is a decltest | 3055 | |
| 2902 | // const decl_being_tested = scope.resolveDeclName(doc_comment_index); | 3056 | const pl_node = data[Zir.refToIndex(func_index).?].pl_node; |
| 2903 | // const ast_node_index = idx: { | 3057 | const fn_src = try self.srcLocInfo(file, pl_node.src_node, decl_src); |
| 2904 | // const idx = self.ast_nodes.items.len; | 3058 | const tree = try file.getTree(self.module.gpa); |
| 2905 | // const file_source = file.getSource(self.module.gpa) catch unreachable; // TODO fix this | 3059 | const test_source_code = tree.getNodeSource(fn_src.src_node); |
| 2906 | // const source_of_decltest_function = srcloc: { | 3060 | |
| 2907 | // const func_index = getBlockInlineBreak(file.zir, value_index); | 3061 | const ast_node_index = self.ast_nodes.items.len; |
| 2908 | // // a decltest is always a function | 3062 | try self.ast_nodes.append(self.arena, .{ |
| 2909 | // const tag = file.zir.instructions.items(.tag)[Zir.refToIndex(func_index).?]; | 3063 | .file = 0, |
| 2910 | // std.debug.assert(tag == .func_extended); | 3064 | .line = 0, |
| 2911 | 3065 | .col = 0, | |
| 2912 | // const pl_node = file.zir.instructions.items(.data)[Zir.refToIndex(func_index).?].pl_node; | 3066 | .code = test_source_code, |
| 2913 | // const extra = file.zir.extraData(Zir.Inst.ExtendedFunc, pl_node.payload_index); | 3067 | }); |
| 2914 | // const bits = @bitCast(Zir.Inst.ExtendedFunc.Bits, extra.data.bits); | 3068 | self.decls.items[decl_being_tested].decltest = ast_node_index; |
| 2915 | 3069 | self.decls.items[decls_slot_index] = .{ | |
| 2916 | // var extra_index_for_this_func: usize = extra.end; | 3070 | ._analyzed = true, |
| 2917 | // if (bits.has_lib_name) extra_index_for_this_func += 1; | 3071 | .name = "test", |
| 2918 | // if (bits.has_cc) extra_index_for_this_func += 1; | 3072 | .isTest = true, |
| 2919 | // if (bits.has_align) extra_index_for_this_func += 1; | 3073 | .src = ast_node_index, |
| 2920 | 3074 | .value = .{ .expr = .{ .type = 0 } }, | |
| 2921 | // const ret_ty_body = file.zir.extra[extra_index_for_this_func..][0..extra.data.ret_body_len]; | 3075 | .kind = "const", |
| 2922 | // extra_index_for_this_func += ret_ty_body.len; | 3076 | }; |
| 2923 | 3077 | continue; | |
| 2924 | // const body = file.zir.extra[extra_index_for_this_func..][0..extra.data.body_len]; | ||
| 2925 | // extra_index_for_this_func += body.len; | ||
| 2926 | |||
| 2927 | // var src_locs: Zir.Inst.Func.SrcLocs = undefined; | ||
| 2928 | // if (body.len != 0) { | ||
| 2929 | // src_locs = file.zir.extraData(Zir.Inst.Func.SrcLocs, extra_index_for_this_func).data; | ||
| 2930 | // } else { | ||
| 2931 | // src_locs = .{ | ||
| 2932 | // .lbrace_line = line, | ||
| 2933 | // .rbrace_line = line, | ||
| 2934 | // .columns = 0, // TODO get columns when body.len == 0 | ||
| 2935 | // }; | ||
| 2936 | // } | ||
| 2937 | // break :srcloc src_locs; | ||
| 2938 | // }; | ||
| 2939 | // const source_slice = slice: { | ||
| 2940 | // var start_byte_offset: u32 = 0; | ||
| 2941 | // var end_byte_offset: u32 = 0; | ||
| 2942 | // const rbrace_col = @truncate(u16, source_of_decltest_function.columns >> 16); | ||
| 2943 | // var lines: u32 = 0; | ||
| 2944 | // for (file_source.bytes) |b, i| { | ||
| 2945 | // if (b == '\n') { | ||
| 2946 | // lines += 1; | ||
| 2947 | // } | ||
| 2948 | // if (lines == source_of_decltest_function.lbrace_line) { | ||
| 2949 | // start_byte_offset = @intCast(u32, i); | ||
| 2950 | // } | ||
| 2951 | // if (lines == source_of_decltest_function.rbrace_line) { | ||
| 2952 | // end_byte_offset = @intCast(u32, i) + rbrace_col; | ||
| 2953 | // break; | ||
| 2954 | // } | ||
| 2955 | // } | ||
| 2956 | // break :slice file_source.bytes[start_byte_offset..end_byte_offset]; | ||
| 2957 | // }; | ||
| 2958 | // try self.ast_nodes.append(self.arena, .{ | ||
| 2959 | // .file = 0, | ||
| 2960 | // .line = line, | ||
| 2961 | // .col = 0, | ||
| 2962 | // .name = try self.arena.dupe(u8, source_slice), | ||
| 2963 | // }); | ||
| 2964 | // break :idx idx; | ||
| 2965 | // }; | ||
| 2966 | // self.decls.items[decl_being_tested].decltest = ast_node_index; | ||
| 2967 | // self.decls.items[decls_slot_index] = .{ | ||
| 2968 | // ._analyzed = true, | ||
| 2969 | // .name = "test", | ||
| 2970 | // .isTest = true, | ||
| 2971 | // .src = ast_node_index, | ||
| 2972 | // .value = .{ .expr = .{ .type = 0 } }, | ||
| 2973 | // .kind = "const", | ||
| 2974 | // }; | ||
| 2975 | // continue; | ||
| 2976 | } else { | 3078 | } else { |
| 2977 | const raw_decl_name = file.zir.nullTerminatedString(decl_name_index); | 3079 | const raw_decl_name = file.zir.nullTerminatedString(decl_name_index); |
| 2978 | if (raw_decl_name.len == 0) { | 3080 | if (raw_decl_name.len == 0) { |
| ... | @@ -2993,8 +3095,8 @@ fn walkDecls( | ... | @@ -2993,8 +3095,8 @@ fn walkDecls( |
| 2993 | const ast_node_index = idx: { | 3095 | const ast_node_index = idx: { |
| 2994 | const idx = self.ast_nodes.items.len; | 3096 | const idx = self.ast_nodes.items.len; |
| 2995 | try self.ast_nodes.append(self.arena, .{ | 3097 | try self.ast_nodes.append(self.arena, .{ |
| 2996 | .file = self.files.getIndex(file) orelse unreachable, | 3098 | .file = self.files.getIndex(file).?, |
| 2997 | .line = line, | 3099 | .line = decl_src.line, |
| 2998 | .col = 0, | 3100 | .col = 0, |
| 2999 | .docs = doc_comment, | 3101 | .docs = doc_comment, |
| 3000 | .fields = null, // walkInstruction will fill `fields` if necessary | 3102 | .fields = null, // walkInstruction will fill `fields` if necessary |
| ... | @@ -3005,7 +3107,7 @@ fn walkDecls( | ... | @@ -3005,7 +3107,7 @@ fn walkDecls( |
| 3005 | const walk_result = if (is_test) // TODO: decide if tests should show up at all | 3107 | const walk_result = if (is_test) // TODO: decide if tests should show up at all |
| 3006 | DocData.WalkResult{ .expr = .{ .void = .{} } } | 3108 | DocData.WalkResult{ .expr = .{ .void = .{} } } |
| 3007 | else | 3109 | else |
| 3008 | try self.walkInstruction(file, scope, line, value_index, true); | 3110 | try self.walkInstruction(file, scope, decl_src, value_index, true); |
| 3009 | 3111 | ||
| 3010 | if (is_pub) { | 3112 | if (is_pub) { |
| 3011 | try decl_indexes.append(self.arena, decls_slot_index); | 3113 | try decl_indexes.append(self.arena, decls_slot_index); |
| ... | @@ -3381,6 +3483,37 @@ fn tryResolveRefPath( | ... | @@ -3381,6 +3483,37 @@ fn tryResolveRefPath( |
| 3381 | path[i + 1] = (try self.cteTodo(child_string)).expr; | 3483 | path[i + 1] = (try self.cteTodo(child_string)).expr; |
| 3382 | continue :outer; | 3484 | continue :outer; |
| 3383 | }, | 3485 | }, |
| 3486 | .Opaque => |t_opaque| { | ||
| 3487 | for (t_opaque.pubDecls) |d| { | ||
| 3488 | // TODO: this could be improved a lot | ||
| 3489 | // by having our own string table! | ||
| 3490 | const decl = self.decls.items[d]; | ||
| 3491 | if (std.mem.eql(u8, decl.name, child_string)) { | ||
| 3492 | path[i + 1] = .{ .declRef = d }; | ||
| 3493 | continue :outer; | ||
| 3494 | } | ||
| 3495 | } | ||
| 3496 | for (t_opaque.privDecls) |d| { | ||
| 3497 | // TODO: this could be improved a lot | ||
| 3498 | // by having our own string table! | ||
| 3499 | const decl = self.decls.items[d]; | ||
| 3500 | if (std.mem.eql(u8, decl.name, child_string)) { | ||
| 3501 | path[i + 1] = .{ .declRef = d }; | ||
| 3502 | continue :outer; | ||
| 3503 | } | ||
| 3504 | } | ||
| 3505 | |||
| 3506 | // if we got here, our search failed | ||
| 3507 | printWithContext( | ||
| 3508 | file, | ||
| 3509 | inst_index, | ||
| 3510 | "failed to match `{s}` in opaque", | ||
| 3511 | .{child_string}, | ||
| 3512 | ); | ||
| 3513 | |||
| 3514 | path[i + 1] = (try self.cteTodo("match failure")).expr; | ||
| 3515 | continue :outer; | ||
| 3516 | }, | ||
| 3384 | }, | 3517 | }, |
| 3385 | } | 3518 | } |
| 3386 | } | 3519 | } |
| ... | @@ -3401,7 +3534,7 @@ fn analyzeFancyFunction( | ... | @@ -3401,7 +3534,7 @@ fn analyzeFancyFunction( |
| 3401 | self: *Autodoc, | 3534 | self: *Autodoc, |
| 3402 | file: *File, | 3535 | file: *File, |
| 3403 | scope: *Scope, | 3536 | scope: *Scope, |
| 3404 | parent_line: usize, | 3537 | parent_src: SrcLocInfo, |
| 3405 | inst_index: usize, | 3538 | inst_index: usize, |
| 3406 | self_ast_node_index: usize, | 3539 | self_ast_node_index: usize, |
| 3407 | type_slot_index: usize, | 3540 | type_slot_index: usize, |
| ... | @@ -3466,7 +3599,7 @@ fn analyzeFancyFunction( | ... | @@ -3466,7 +3599,7 @@ fn analyzeFancyFunction( |
| 3466 | 3599 | ||
| 3467 | const break_index = file.zir.extra[extra.end..][extra.data.body_len - 1]; | 3600 | const break_index = file.zir.extra[extra.end..][extra.data.body_len - 1]; |
| 3468 | const break_operand = data[break_index].@"break".operand; | 3601 | const break_operand = data[break_index].@"break".operand; |
| 3469 | const param_type_ref = try self.walkRef(file, scope, parent_line, break_operand, false); | 3602 | const param_type_ref = try self.walkRef(file, scope, parent_src, break_operand, false); |
| 3470 | 3603 | ||
| 3471 | param_type_refs.appendAssumeCapacity(param_type_ref.expr); | 3604 | param_type_refs.appendAssumeCapacity(param_type_ref.expr); |
| 3472 | }, | 3605 | }, |
| ... | @@ -3475,8 +3608,8 @@ fn analyzeFancyFunction( | ... | @@ -3475,8 +3608,8 @@ fn analyzeFancyFunction( |
| 3475 | 3608 | ||
| 3476 | self.ast_nodes.items[self_ast_node_index].fields = param_ast_indexes.items; | 3609 | self.ast_nodes.items[self_ast_node_index].fields = param_ast_indexes.items; |
| 3477 | 3610 | ||
| 3478 | const inst_data = data[inst_index].pl_node; | 3611 | const pl_node = data[inst_index].pl_node; |
| 3479 | const extra = file.zir.extraData(Zir.Inst.FuncFancy, inst_data.payload_index); | 3612 | const extra = file.zir.extraData(Zir.Inst.FuncFancy, pl_node.payload_index); |
| 3480 | 3613 | ||
| 3481 | var extra_index: usize = extra.end; | 3614 | var extra_index: usize = extra.end; |
| 3482 | 3615 | ||
| ... | @@ -3490,7 +3623,7 @@ fn analyzeFancyFunction( | ... | @@ -3490,7 +3623,7 @@ fn analyzeFancyFunction( |
| 3490 | if (extra.data.bits.has_align_ref) { | 3623 | if (extra.data.bits.has_align_ref) { |
| 3491 | const align_ref = @intToEnum(Zir.Inst.Ref, file.zir.extra[extra_index]); | 3624 | const align_ref = @intToEnum(Zir.Inst.Ref, file.zir.extra[extra_index]); |
| 3492 | align_index = self.exprs.items.len; | 3625 | align_index = self.exprs.items.len; |
| 3493 | _ = try self.walkRef(file, scope, parent_line, align_ref, false); | 3626 | _ = try self.walkRef(file, scope, parent_src, align_ref, false); |
| 3494 | extra_index += 1; | 3627 | extra_index += 1; |
| 3495 | } else if (extra.data.bits.has_align_body) { | 3628 | } else if (extra.data.bits.has_align_body) { |
| 3496 | const align_body_len = file.zir.extra[extra_index]; | 3629 | const align_body_len = file.zir.extra[extra_index]; |
| ... | @@ -3507,7 +3640,7 @@ fn analyzeFancyFunction( | ... | @@ -3507,7 +3640,7 @@ fn analyzeFancyFunction( |
| 3507 | if (extra.data.bits.has_addrspace_ref) { | 3640 | if (extra.data.bits.has_addrspace_ref) { |
| 3508 | const addrspace_ref = @intToEnum(Zir.Inst.Ref, file.zir.extra[extra_index]); | 3641 | const addrspace_ref = @intToEnum(Zir.Inst.Ref, file.zir.extra[extra_index]); |
| 3509 | addrspace_index = self.exprs.items.len; | 3642 | addrspace_index = self.exprs.items.len; |
| 3510 | _ = try self.walkRef(file, scope, parent_line, addrspace_ref, false); | 3643 | _ = try self.walkRef(file, scope, parent_src, addrspace_ref, false); |
| 3511 | extra_index += 1; | 3644 | extra_index += 1; |
| 3512 | } else if (extra.data.bits.has_addrspace_body) { | 3645 | } else if (extra.data.bits.has_addrspace_body) { |
| 3513 | const addrspace_body_len = file.zir.extra[extra_index]; | 3646 | const addrspace_body_len = file.zir.extra[extra_index]; |
| ... | @@ -3524,7 +3657,7 @@ fn analyzeFancyFunction( | ... | @@ -3524,7 +3657,7 @@ fn analyzeFancyFunction( |
| 3524 | if (extra.data.bits.has_section_ref) { | 3657 | if (extra.data.bits.has_section_ref) { |
| 3525 | const section_ref = @intToEnum(Zir.Inst.Ref, file.zir.extra[extra_index]); | 3658 | const section_ref = @intToEnum(Zir.Inst.Ref, file.zir.extra[extra_index]); |
| 3526 | section_index = self.exprs.items.len; | 3659 | section_index = self.exprs.items.len; |
| 3527 | _ = try self.walkRef(file, scope, parent_line, section_ref, false); | 3660 | _ = try self.walkRef(file, scope, parent_src, section_ref, false); |
| 3528 | extra_index += 1; | 3661 | extra_index += 1; |
| 3529 | } else if (extra.data.bits.has_section_body) { | 3662 | } else if (extra.data.bits.has_section_body) { |
| 3530 | const section_body_len = file.zir.extra[extra_index]; | 3663 | const section_body_len = file.zir.extra[extra_index]; |
| ... | @@ -3541,7 +3674,7 @@ fn analyzeFancyFunction( | ... | @@ -3541,7 +3674,7 @@ fn analyzeFancyFunction( |
| 3541 | if (extra.data.bits.has_cc_ref) { | 3674 | if (extra.data.bits.has_cc_ref) { |
| 3542 | const cc_ref = @intToEnum(Zir.Inst.Ref, file.zir.extra[extra_index]); | 3675 | const cc_ref = @intToEnum(Zir.Inst.Ref, file.zir.extra[extra_index]); |
| 3543 | cc_index = self.exprs.items.len; | 3676 | cc_index = self.exprs.items.len; |
| 3544 | _ = try self.walkRef(file, scope, parent_line, cc_ref, false); | 3677 | _ = try self.walkRef(file, scope, parent_src, cc_ref, false); |
| 3545 | extra_index += 1; | 3678 | extra_index += 1; |
| 3546 | } else if (extra.data.bits.has_cc_body) { | 3679 | } else if (extra.data.bits.has_cc_body) { |
| 3547 | const cc_body_len = file.zir.extra[extra_index]; | 3680 | const cc_body_len = file.zir.extra[extra_index]; |
| ... | @@ -3560,14 +3693,14 @@ fn analyzeFancyFunction( | ... | @@ -3560,14 +3693,14 @@ fn analyzeFancyFunction( |
| 3560 | .none => DocData.Expr{ .void = .{} }, | 3693 | .none => DocData.Expr{ .void = .{} }, |
| 3561 | else => blk: { | 3694 | else => blk: { |
| 3562 | const ref = fn_info.ret_ty_ref; | 3695 | const ref = fn_info.ret_ty_ref; |
| 3563 | const wr = try self.walkRef(file, scope, parent_line, ref, false); | 3696 | const wr = try self.walkRef(file, scope, parent_src, ref, false); |
| 3564 | break :blk wr.expr; | 3697 | break :blk wr.expr; |
| 3565 | }, | 3698 | }, |
| 3566 | }, | 3699 | }, |
| 3567 | else => blk: { | 3700 | else => blk: { |
| 3568 | const last_instr_index = fn_info.ret_ty_body[fn_info.ret_ty_body.len - 1]; | 3701 | const last_instr_index = fn_info.ret_ty_body[fn_info.ret_ty_body.len - 1]; |
| 3569 | const break_operand = data[last_instr_index].@"break".operand; | 3702 | const break_operand = data[last_instr_index].@"break".operand; |
| 3570 | const wr = try self.walkRef(file, scope, parent_line, break_operand, false); | 3703 | const wr = try self.walkRef(file, scope, parent_src, break_operand, false); |
| 3571 | break :blk wr.expr; | 3704 | break :blk wr.expr; |
| 3572 | }, | 3705 | }, |
| 3573 | }; | 3706 | }; |
| ... | @@ -3582,7 +3715,7 @@ fn analyzeFancyFunction( | ... | @@ -3582,7 +3715,7 @@ fn analyzeFancyFunction( |
| 3582 | break :blk try self.getGenericReturnType( | 3715 | break :blk try self.getGenericReturnType( |
| 3583 | file, | 3716 | file, |
| 3584 | scope, | 3717 | scope, |
| 3585 | parent_line, | 3718 | parent_src, |
| 3586 | fn_info.body[fn_info.body.len - 1], | 3719 | fn_info.body[fn_info.body.len - 1], |
| 3587 | ); | 3720 | ); |
| 3588 | } else { | 3721 | } else { |
| ... | @@ -3619,7 +3752,7 @@ fn analyzeFunction( | ... | @@ -3619,7 +3752,7 @@ fn analyzeFunction( |
| 3619 | self: *Autodoc, | 3752 | self: *Autodoc, |
| 3620 | file: *File, | 3753 | file: *File, |
| 3621 | scope: *Scope, | 3754 | scope: *Scope, |
| 3622 | parent_line: usize, | 3755 | parent_src: SrcLocInfo, |
| 3623 | inst_index: usize, | 3756 | inst_index: usize, |
| 3624 | self_ast_node_index: usize, | 3757 | self_ast_node_index: usize, |
| 3625 | type_slot_index: usize, | 3758 | type_slot_index: usize, |
| ... | @@ -3685,7 +3818,7 @@ fn analyzeFunction( | ... | @@ -3685,7 +3818,7 @@ fn analyzeFunction( |
| 3685 | 3818 | ||
| 3686 | const break_index = file.zir.extra[extra.end..][extra.data.body_len - 1]; | 3819 | const break_index = file.zir.extra[extra.end..][extra.data.body_len - 1]; |
| 3687 | const break_operand = data[break_index].@"break".operand; | 3820 | const break_operand = data[break_index].@"break".operand; |
| 3688 | const param_type_ref = try self.walkRef(file, scope, parent_line, break_operand, false); | 3821 | const param_type_ref = try self.walkRef(file, scope, parent_src, break_operand, false); |
| 3689 | 3822 | ||
| 3690 | param_type_refs.appendAssumeCapacity(param_type_ref.expr); | 3823 | param_type_refs.appendAssumeCapacity(param_type_ref.expr); |
| 3691 | }, | 3824 | }, |
| ... | @@ -3698,14 +3831,14 @@ fn analyzeFunction( | ... | @@ -3698,14 +3831,14 @@ fn analyzeFunction( |
| 3698 | .none => DocData.Expr{ .void = .{} }, | 3831 | .none => DocData.Expr{ .void = .{} }, |
| 3699 | else => blk: { | 3832 | else => blk: { |
| 3700 | const ref = fn_info.ret_ty_ref; | 3833 | const ref = fn_info.ret_ty_ref; |
| 3701 | const wr = try self.walkRef(file, scope, parent_line, ref, false); | 3834 | const wr = try self.walkRef(file, scope, parent_src, ref, false); |
| 3702 | break :blk wr.expr; | 3835 | break :blk wr.expr; |
| 3703 | }, | 3836 | }, |
| 3704 | }, | 3837 | }, |
| 3705 | else => blk: { | 3838 | else => blk: { |
| 3706 | const last_instr_index = fn_info.ret_ty_body[fn_info.ret_ty_body.len - 1]; | 3839 | const last_instr_index = fn_info.ret_ty_body[fn_info.ret_ty_body.len - 1]; |
| 3707 | const break_operand = data[last_instr_index].@"break".operand; | 3840 | const break_operand = data[last_instr_index].@"break".operand; |
| 3708 | const wr = try self.walkRef(file, scope, parent_line, break_operand, false); | 3841 | const wr = try self.walkRef(file, scope, parent_src, break_operand, false); |
| 3709 | break :blk wr.expr; | 3842 | break :blk wr.expr; |
| 3710 | }, | 3843 | }, |
| 3711 | }; | 3844 | }; |
| ... | @@ -3720,7 +3853,7 @@ fn analyzeFunction( | ... | @@ -3720,7 +3853,7 @@ fn analyzeFunction( |
| 3720 | break :blk try self.getGenericReturnType( | 3853 | break :blk try self.getGenericReturnType( |
| 3721 | file, | 3854 | file, |
| 3722 | scope, | 3855 | scope, |
| 3723 | parent_line, | 3856 | parent_src, |
| 3724 | fn_info.body[fn_info.body.len - 1], | 3857 | fn_info.body[fn_info.body.len - 1], |
| 3725 | ); | 3858 | ); |
| 3726 | } else { | 3859 | } else { |
| ... | @@ -3761,11 +3894,11 @@ fn getGenericReturnType( | ... | @@ -3761,11 +3894,11 @@ fn getGenericReturnType( |
| 3761 | self: *Autodoc, | 3894 | self: *Autodoc, |
| 3762 | file: *File, | 3895 | file: *File, |
| 3763 | scope: *Scope, | 3896 | scope: *Scope, |
| 3764 | parent_line: usize, // function decl line | 3897 | parent_src: SrcLocInfo, // function decl line |
| 3765 | body_end: usize, | 3898 | body_end: usize, |
| 3766 | ) !DocData.Expr { | 3899 | ) !DocData.Expr { |
| 3767 | // TODO: compute the correct line offset | 3900 | // TODO: compute the correct line offset |
| 3768 | const wr = try self.walkInstruction(file, scope, parent_line, body_end, false); | 3901 | const wr = try self.walkInstruction(file, scope, parent_src, body_end, false); |
| 3769 | return wr.expr; | 3902 | return wr.expr; |
| 3770 | } | 3903 | } |
| 3771 | 3904 | ||
| ... | @@ -3773,7 +3906,7 @@ fn collectUnionFieldInfo( | ... | @@ -3773,7 +3906,7 @@ fn collectUnionFieldInfo( |
| 3773 | self: *Autodoc, | 3906 | self: *Autodoc, |
| 3774 | file: *File, | 3907 | file: *File, |
| 3775 | scope: *Scope, | 3908 | scope: *Scope, |
| 3776 | parent_line: usize, | 3909 | parent_src: SrcLocInfo, |
| 3777 | fields_len: usize, | 3910 | fields_len: usize, |
| 3778 | field_type_refs: *std.ArrayListUnmanaged(DocData.Expr), | 3911 | field_type_refs: *std.ArrayListUnmanaged(DocData.Expr), |
| 3779 | field_name_indexes: *std.ArrayListUnmanaged(usize), | 3912 | field_name_indexes: *std.ArrayListUnmanaged(usize), |
| ... | @@ -3820,7 +3953,7 @@ fn collectUnionFieldInfo( | ... | @@ -3820,7 +3953,7 @@ fn collectUnionFieldInfo( |
| 3820 | 3953 | ||
| 3821 | // type | 3954 | // type |
| 3822 | { | 3955 | { |
| 3823 | const walk_result = try self.walkRef(file, scope, parent_line, field_type, false); | 3956 | const walk_result = try self.walkRef(file, scope, parent_src, field_type, false); |
| 3824 | try field_type_refs.append(self.arena, walk_result.expr); | 3957 | try field_type_refs.append(self.arena, walk_result.expr); |
| 3825 | } | 3958 | } |
| 3826 | 3959 | ||
| ... | @@ -3843,7 +3976,7 @@ fn collectStructFieldInfo( | ... | @@ -3843,7 +3976,7 @@ fn collectStructFieldInfo( |
| 3843 | self: *Autodoc, | 3976 | self: *Autodoc, |
| 3844 | file: *File, | 3977 | file: *File, |
| 3845 | scope: *Scope, | 3978 | scope: *Scope, |
| 3846 | parent_line: usize, | 3979 | parent_src: SrcLocInfo, |
| 3847 | fields_len: usize, | 3980 | fields_len: usize, |
| 3848 | field_type_refs: *std.ArrayListUnmanaged(DocData.Expr), | 3981 | field_type_refs: *std.ArrayListUnmanaged(DocData.Expr), |
| 3849 | field_name_indexes: *std.ArrayListUnmanaged(usize), | 3982 | field_name_indexes: *std.ArrayListUnmanaged(usize), |
| ... | @@ -3917,7 +4050,7 @@ fn collectStructFieldInfo( | ... | @@ -3917,7 +4050,7 @@ fn collectStructFieldInfo( |
| 3917 | for (fields) |field| { | 4050 | for (fields) |field| { |
| 3918 | const type_expr = expr: { | 4051 | const type_expr = expr: { |
| 3919 | if (field.type_ref != .none) { | 4052 | if (field.type_ref != .none) { |
| 3920 | const walk_result = try self.walkRef(file, scope, parent_line, field.type_ref, false); | 4053 | const walk_result = try self.walkRef(file, scope, parent_src, field.type_ref, false); |
| 3921 | break :expr walk_result.expr; | 4054 | break :expr walk_result.expr; |
| 3922 | } | 4055 | } |
| 3923 | 4056 | ||
| ... | @@ -3927,7 +4060,7 @@ fn collectStructFieldInfo( | ... | @@ -3927,7 +4060,7 @@ fn collectStructFieldInfo( |
| 3927 | 4060 | ||
| 3928 | const break_inst = body[body.len - 1]; | 4061 | const break_inst = body[body.len - 1]; |
| 3929 | const operand = data[break_inst].@"break".operand; | 4062 | const operand = data[break_inst].@"break".operand; |
| 3930 | const walk_result = try self.walkRef(file, scope, parent_line, operand, false); | 4063 | const walk_result = try self.walkRef(file, scope, parent_src, operand, false); |
| 3931 | break :expr walk_result.expr; | 4064 | break :expr walk_result.expr; |
| 3932 | }; | 4065 | }; |
| 3933 | 4066 | ||
| ... | @@ -3957,7 +4090,7 @@ fn walkRef( | ... | @@ -3957,7 +4090,7 @@ fn walkRef( |
| 3957 | self: *Autodoc, | 4090 | self: *Autodoc, |
| 3958 | file: *File, | 4091 | file: *File, |
| 3959 | parent_scope: *Scope, | 4092 | parent_scope: *Scope, |
| 3960 | parent_line: usize, | 4093 | parent_src: SrcLocInfo, |
| 3961 | ref: Ref, | 4094 | ref: Ref, |
| 3962 | need_type: bool, // true when the caller needs also a typeRef for the return value | 4095 | need_type: bool, // true when the caller needs also a typeRef for the return value |
| 3963 | ) AutodocErrors!DocData.WalkResult { | 4096 | ) AutodocErrors!DocData.WalkResult { |
| ... | @@ -4069,7 +4202,7 @@ fn walkRef( | ... | @@ -4069,7 +4202,7 @@ fn walkRef( |
| 4069 | } | 4202 | } |
| 4070 | } else { | 4203 | } else { |
| 4071 | const zir_index = enum_value - Ref.typed_value_map.len; | 4204 | const zir_index = enum_value - Ref.typed_value_map.len; |
| 4072 | return self.walkInstruction(file, parent_scope, parent_line, zir_index, need_type); | 4205 | return self.walkInstruction(file, parent_scope, parent_src, zir_index, need_type); |
| 4073 | } | 4206 | } |
| 4074 | } | 4207 | } |
| 4075 | 4208 | ||
| ... | @@ -4122,3 +4255,24 @@ fn writePackageTableToJson( | ... | @@ -4122,3 +4255,24 @@ fn writePackageTableToJson( |
| 4122 | } | 4255 | } |
| 4123 | try jsw.endObject(); | 4256 | try jsw.endObject(); |
| 4124 | } | 4257 | } |
| 4258 | |||
| 4259 | fn srcLocInfo( | ||
| 4260 | self: Autodoc, | ||
| 4261 | file: *File, | ||
| 4262 | src_node: i32, | ||
| 4263 | parent_src: SrcLocInfo, | ||
| 4264 | ) !SrcLocInfo { | ||
| 4265 | const sn = @intCast(u32, @intCast(i32, parent_src.src_node) + src_node); | ||
| 4266 | const tree = try file.getTree(self.module.gpa); | ||
| 4267 | const node_idx = @bitCast(Ast.Node.Index, sn); | ||
| 4268 | const tokens = tree.nodes.items(.main_token); | ||
| 4269 | |||
| 4270 | const tok_idx = tokens[node_idx]; | ||
| 4271 | const start = tree.tokens.items(.start)[tok_idx]; | ||
| 4272 | const loc = tree.tokenLocation(parent_src.bytes, tok_idx); | ||
| 4273 | return SrcLocInfo{ | ||
| 4274 | .line = parent_src.line + loc.line, | ||
| 4275 | .bytes = start, | ||
| 4276 | .src_node = sn, | ||
| 4277 | }; | ||
| 4278 | } |
src/Module.zig+1-1| ... | @@ -4635,7 +4635,7 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !bool { | ... | @@ -4635,7 +4635,7 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !bool { |
| 4635 | decl.analysis = .complete; | 4635 | decl.analysis = .complete; |
| 4636 | decl.generation = mod.generation; | 4636 | decl.generation = mod.generation; |
| 4637 | 4637 | ||
| 4638 | const has_runtime_bits = try sema.fnHasRuntimeBits(&block_scope, ty_src, decl.ty); | 4638 | const has_runtime_bits = try sema.fnHasRuntimeBits(decl.ty); |
| 4639 | 4639 | ||
| 4640 | if (has_runtime_bits) { | 4640 | if (has_runtime_bits) { |
| 4641 | // We don't fully codegen the decl until later, but we do need to reserve a global | 4641 | // We don't fully codegen the decl until later, but we do need to reserve a global |
src/Sema.zig+128-63| ... | @@ -2565,7 +2565,7 @@ fn zirEnumDecl( | ... | @@ -2565,7 +2565,7 @@ fn zirEnumDecl( |
| 2565 | } | 2565 | } |
| 2566 | } | 2566 | } |
| 2567 | 2567 | ||
| 2568 | if (small.nonexhaustive) { | 2568 | if (small.nonexhaustive and enum_obj.tag_ty.zigTypeTag() != .ComptimeInt) { |
| 2569 | if (fields_len > 1 and std.math.log2_int(u64, fields_len) == enum_obj.tag_ty.bitSize(sema.mod.getTarget())) { | 2569 | if (fields_len > 1 and std.math.log2_int(u64, fields_len) == enum_obj.tag_ty.bitSize(sema.mod.getTarget())) { |
| 2570 | return sema.fail(block, src, "non-exhaustive enum specifies every value", .{}); | 2570 | return sema.fail(block, src, "non-exhaustive enum specifies every value", .{}); |
| 2571 | } | 2571 | } |
| ... | @@ -2586,6 +2586,7 @@ fn zirEnumDecl( | ... | @@ -2586,6 +2586,7 @@ fn zirEnumDecl( |
| 2586 | var cur_bit_bag: u32 = undefined; | 2586 | var cur_bit_bag: u32 = undefined; |
| 2587 | var field_i: u32 = 0; | 2587 | var field_i: u32 = 0; |
| 2588 | var last_tag_val: ?Value = null; | 2588 | var last_tag_val: ?Value = null; |
| 2589 | var tag_val_buf: Value.Payload.U64 = undefined; | ||
| 2589 | while (field_i < fields_len) : (field_i += 1) { | 2590 | while (field_i < fields_len) : (field_i += 1) { |
| 2590 | if (field_i % 32 == 0) { | 2591 | if (field_i % 32 == 0) { |
| 2591 | cur_bit_bag = sema.code.extra[bit_bag_index]; | 2592 | cur_bit_bag = sema.code.extra[bit_bag_index]; |
| ... | @@ -2641,6 +2642,21 @@ fn zirEnumDecl( | ... | @@ -2641,6 +2642,21 @@ fn zirEnumDecl( |
| 2641 | .ty = enum_obj.tag_ty, | 2642 | .ty = enum_obj.tag_ty, |
| 2642 | .mod = mod, | 2643 | .mod = mod, |
| 2643 | }); | 2644 | }); |
| 2645 | } else { | ||
| 2646 | tag_val_buf = .{ | ||
| 2647 | .base = .{ .tag = .int_u64 }, | ||
| 2648 | .data = field_i, | ||
| 2649 | }; | ||
| 2650 | last_tag_val = Value.initPayload(&tag_val_buf.base); | ||
| 2651 | } | ||
| 2652 | |||
| 2653 | if (!(try sema.intFitsInType(block, src, last_tag_val.?, enum_obj.tag_ty, null))) { | ||
| 2654 | const tree = try sema.getAstTree(block); | ||
| 2655 | const field_src = enumFieldSrcLoc(sema.mod.declPtr(block.src_decl), tree.*, src.node_offset.x, field_i); | ||
| 2656 | const msg = try sema.errMsg(block, field_src, "enumeration value '{}' too large for type '{}'", .{ | ||
| 2657 | last_tag_val.?.fmtValue(enum_obj.tag_ty, mod), enum_obj.tag_ty.fmt(mod), | ||
| 2658 | }); | ||
| 2659 | return sema.failWithOwnedErrorMsg(msg); | ||
| 2644 | } | 2660 | } |
| 2645 | } | 2661 | } |
| 2646 | return decl_val; | 2662 | return decl_val; |
| ... | @@ -2849,7 +2865,7 @@ fn zirRetPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air. | ... | @@ -2849,7 +2865,7 @@ fn zirRetPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air. |
| 2849 | const inst_data = sema.code.instructions.items(.data)[inst].node; | 2865 | const inst_data = sema.code.instructions.items(.data)[inst].node; |
| 2850 | const src = LazySrcLoc.nodeOffset(inst_data); | 2866 | const src = LazySrcLoc.nodeOffset(inst_data); |
| 2851 | 2867 | ||
| 2852 | if (block.is_comptime or try sema.typeRequiresComptime(block, src, sema.fn_ret_ty)) { | 2868 | if (block.is_comptime or try sema.typeRequiresComptime(sema.fn_ret_ty)) { |
| 2853 | const fn_ret_ty = try sema.resolveTypeFields(block, src, sema.fn_ret_ty); | 2869 | const fn_ret_ty = try sema.resolveTypeFields(block, src, sema.fn_ret_ty); |
| 2854 | return sema.analyzeComptimeAlloc(block, fn_ret_ty, 0, src); | 2870 | return sema.analyzeComptimeAlloc(block, fn_ret_ty, 0, src); |
| 2855 | } | 2871 | } |
| ... | @@ -5040,7 +5056,7 @@ pub fn analyzeExport( | ... | @@ -5040,7 +5056,7 @@ pub fn analyzeExport( |
| 5040 | try mod.ensureDeclAnalyzed(exported_decl_index); | 5056 | try mod.ensureDeclAnalyzed(exported_decl_index); |
| 5041 | const exported_decl = mod.declPtr(exported_decl_index); | 5057 | const exported_decl = mod.declPtr(exported_decl_index); |
| 5042 | 5058 | ||
| 5043 | if (!sema.validateExternType(exported_decl.ty, .other)) { | 5059 | if (!try sema.validateExternType(block, src, exported_decl.ty, .other)) { |
| 5044 | const msg = msg: { | 5060 | const msg = msg: { |
| 5045 | const msg = try sema.errMsg(block, src, "unable to export type '{}'", .{exported_decl.ty.fmt(sema.mod)}); | 5061 | const msg = try sema.errMsg(block, src, "unable to export type '{}'", .{exported_decl.ty.fmt(sema.mod)}); |
| 5046 | errdefer msg.destroy(sema.gpa); | 5062 | errdefer msg.destroy(sema.gpa); |
| ... | @@ -5569,7 +5585,11 @@ fn zirCall( | ... | @@ -5569,7 +5585,11 @@ fn zirCall( |
| 5569 | const param_ty_inst = try sema.addType(param_ty); | 5585 | const param_ty_inst = try sema.addType(param_ty); |
| 5570 | try sema.inst_map.put(sema.gpa, inst, param_ty_inst); | 5586 | try sema.inst_map.put(sema.gpa, inst, param_ty_inst); |
| 5571 | 5587 | ||
| 5572 | resolved_args[arg_index] = try sema.resolveBody(block, args_body[arg_start..arg_end], inst); | 5588 | const resolved = try sema.resolveBody(block, args_body[arg_start..arg_end], inst); |
| 5589 | if (sema.typeOf(resolved).zigTypeTag() == .NoReturn) { | ||
| 5590 | return resolved; | ||
| 5591 | } | ||
| 5592 | resolved_args[arg_index] = resolved; | ||
| 5573 | } | 5593 | } |
| 5574 | 5594 | ||
| 5575 | return sema.analyzeCall(block, func, func_src, call_src, modifier, ensure_result_used, resolved_args, bound_arg_src); | 5595 | return sema.analyzeCall(block, func, func_src, call_src, modifier, ensure_result_used, resolved_args, bound_arg_src); |
| ... | @@ -5768,7 +5788,7 @@ fn analyzeCall( | ... | @@ -5768,7 +5788,7 @@ fn analyzeCall( |
| 5768 | var is_comptime_call = block.is_comptime or modifier == .compile_time; | 5788 | var is_comptime_call = block.is_comptime or modifier == .compile_time; |
| 5769 | var comptime_only_ret_ty = false; | 5789 | var comptime_only_ret_ty = false; |
| 5770 | if (!is_comptime_call) { | 5790 | if (!is_comptime_call) { |
| 5771 | if (sema.typeRequiresComptime(block, func_src, func_ty_info.return_type)) |ct| { | 5791 | if (sema.typeRequiresComptime(func_ty_info.return_type)) |ct| { |
| 5772 | is_comptime_call = ct; | 5792 | is_comptime_call = ct; |
| 5773 | comptime_only_ret_ty = ct; | 5793 | comptime_only_ret_ty = ct; |
| 5774 | } else |err| switch (err) { | 5794 | } else |err| switch (err) { |
| ... | @@ -6047,7 +6067,7 @@ fn analyzeCall( | ... | @@ -6047,7 +6067,7 @@ fn analyzeCall( |
| 6047 | break :result try sema.analyzeBlockBody(block, call_src, &child_block, merges); | 6067 | break :result try sema.analyzeBlockBody(block, call_src, &child_block, merges); |
| 6048 | }; | 6068 | }; |
| 6049 | 6069 | ||
| 6050 | if (!is_comptime_call) { | 6070 | if (!is_comptime_call and sema.typeOf(result).zigTypeTag() != .NoReturn) { |
| 6051 | try sema.emitDbgInline( | 6071 | try sema.emitDbgInline( |
| 6052 | block, | 6072 | block, |
| 6053 | module_fn, | 6073 | module_fn, |
| ... | @@ -6206,7 +6226,7 @@ fn analyzeInlineCallArg( | ... | @@ -6206,7 +6226,7 @@ fn analyzeInlineCallArg( |
| 6206 | const param_ty = try sema.analyzeAsType(param_block, param_src, param_ty_inst); | 6226 | const param_ty = try sema.analyzeAsType(param_block, param_src, param_ty_inst); |
| 6207 | new_fn_info.param_types[arg_i.*] = param_ty; | 6227 | new_fn_info.param_types[arg_i.*] = param_ty; |
| 6208 | const uncasted_arg = uncasted_args[arg_i.*]; | 6228 | const uncasted_arg = uncasted_args[arg_i.*]; |
| 6209 | if (try sema.typeRequiresComptime(arg_block, arg_src, param_ty)) { | 6229 | if (try sema.typeRequiresComptime(param_ty)) { |
| 6210 | _ = sema.resolveConstMaybeUndefVal(arg_block, arg_src, uncasted_arg, "argument to parameter with comptime only type must be comptime known") catch |err| { | 6230 | _ = sema.resolveConstMaybeUndefVal(arg_block, arg_src, uncasted_arg, "argument to parameter with comptime only type must be comptime known") catch |err| { |
| 6211 | if (err == error.AnalysisFail and sema.err != null) { | 6231 | if (err == error.AnalysisFail and sema.err != null) { |
| 6212 | try sema.addComptimeReturnTypeNote(arg_block, func, func_src, ret_ty, sema.err.?, comptime_only_ret_ty); | 6232 | try sema.addComptimeReturnTypeNote(arg_block, func, func_src, ret_ty, sema.err.?, comptime_only_ret_ty); |
| ... | @@ -6308,7 +6328,7 @@ fn analyzeGenericCallArg( | ... | @@ -6308,7 +6328,7 @@ fn analyzeGenericCallArg( |
| 6308 | ) !void { | 6328 | ) !void { |
| 6309 | const is_runtime = comptime_arg.val.tag() == .generic_poison and | 6329 | const is_runtime = comptime_arg.val.tag() == .generic_poison and |
| 6310 | comptime_arg.ty.hasRuntimeBits() and | 6330 | comptime_arg.ty.hasRuntimeBits() and |
| 6311 | !(try sema.typeRequiresComptime(block, arg_src, comptime_arg.ty)); | 6331 | !(try sema.typeRequiresComptime(comptime_arg.ty)); |
| 6312 | if (is_runtime) { | 6332 | if (is_runtime) { |
| 6313 | const param_ty = new_fn_info.param_types[runtime_i.*]; | 6333 | const param_ty = new_fn_info.param_types[runtime_i.*]; |
| 6314 | const casted_arg = try sema.coerce(block, param_ty, uncasted_arg, arg_src); | 6334 | const casted_arg = try sema.coerce(block, param_ty, uncasted_arg, arg_src); |
| ... | @@ -6573,7 +6593,7 @@ fn instantiateGenericCall( | ... | @@ -6573,7 +6593,7 @@ fn instantiateGenericCall( |
| 6573 | } | 6593 | } |
| 6574 | } else if (is_anytype) { | 6594 | } else if (is_anytype) { |
| 6575 | const arg_ty = sema.typeOf(arg); | 6595 | const arg_ty = sema.typeOf(arg); |
| 6576 | if (try sema.typeRequiresComptime(block, .unneeded, arg_ty)) { | 6596 | if (try sema.typeRequiresComptime(arg_ty)) { |
| 6577 | const arg_val = try sema.resolveConstValue(block, .unneeded, arg, undefined); | 6597 | const arg_val = try sema.resolveConstValue(block, .unneeded, arg, undefined); |
| 6578 | const child_arg = try child_sema.addConstant(arg_ty, arg_val); | 6598 | const child_arg = try child_sema.addConstant(arg_ty, arg_val); |
| 6579 | child_sema.inst_map.putAssumeCapacityNoClobber(inst, child_arg); | 6599 | child_sema.inst_map.putAssumeCapacityNoClobber(inst, child_arg); |
| ... | @@ -6626,7 +6646,7 @@ fn instantiateGenericCall( | ... | @@ -6626,7 +6646,7 @@ fn instantiateGenericCall( |
| 6626 | const arg = child_sema.inst_map.get(inst).?; | 6646 | const arg = child_sema.inst_map.get(inst).?; |
| 6627 | const copied_arg_ty = try child_sema.typeOf(arg).copy(new_decl_arena_allocator); | 6647 | const copied_arg_ty = try child_sema.typeOf(arg).copy(new_decl_arena_allocator); |
| 6628 | 6648 | ||
| 6629 | if (try sema.typeRequiresComptime(block, .unneeded, copied_arg_ty)) { | 6649 | if (try sema.typeRequiresComptime(copied_arg_ty)) { |
| 6630 | is_comptime = true; | 6650 | is_comptime = true; |
| 6631 | } | 6651 | } |
| 6632 | 6652 | ||
| ... | @@ -6657,7 +6677,7 @@ fn instantiateGenericCall( | ... | @@ -6657,7 +6677,7 @@ fn instantiateGenericCall( |
| 6657 | // If the call evaluated to a return type that requires comptime, never mind | 6677 | // If the call evaluated to a return type that requires comptime, never mind |
| 6658 | // our generic instantiation. Instead we need to perform a comptime call. | 6678 | // our generic instantiation. Instead we need to perform a comptime call. |
| 6659 | const new_fn_info = new_decl.ty.fnInfo(); | 6679 | const new_fn_info = new_decl.ty.fnInfo(); |
| 6660 | if (try sema.typeRequiresComptime(block, call_src, new_fn_info.return_type)) { | 6680 | if (try sema.typeRequiresComptime(new_fn_info.return_type)) { |
| 6661 | return error.ComptimeReturn; | 6681 | return error.ComptimeReturn; |
| 6662 | } | 6682 | } |
| 6663 | // Similarly, if the call evaluated to a generic type we need to instead | 6683 | // Similarly, if the call evaluated to a generic type we need to instead |
| ... | @@ -7838,7 +7858,7 @@ fn funcCommon( | ... | @@ -7838,7 +7858,7 @@ fn funcCommon( |
| 7838 | } | 7858 | } |
| 7839 | 7859 | ||
| 7840 | var ret_ty_requires_comptime = false; | 7860 | var ret_ty_requires_comptime = false; |
| 7841 | const ret_poison = if (sema.typeRequiresComptime(block, ret_ty_src, bare_return_type)) |ret_comptime| rp: { | 7861 | const ret_poison = if (sema.typeRequiresComptime(bare_return_type)) |ret_comptime| rp: { |
| 7842 | ret_ty_requires_comptime = ret_comptime; | 7862 | ret_ty_requires_comptime = ret_comptime; |
| 7843 | break :rp bare_return_type.tag() == .generic_poison; | 7863 | break :rp bare_return_type.tag() == .generic_poison; |
| 7844 | } else |err| switch (err) { | 7864 | } else |err| switch (err) { |
| ... | @@ -7876,7 +7896,7 @@ fn funcCommon( | ... | @@ -7876,7 +7896,7 @@ fn funcCommon( |
| 7876 | }; | 7896 | }; |
| 7877 | return sema.failWithOwnedErrorMsg(msg); | 7897 | return sema.failWithOwnedErrorMsg(msg); |
| 7878 | } | 7898 | } |
| 7879 | if (!Type.fnCallingConventionAllowsZigTypes(cc_workaround) and !sema.validateExternType(return_type, .ret_ty)) { | 7899 | if (!Type.fnCallingConventionAllowsZigTypes(cc_workaround) and !try sema.validateExternType(block, ret_ty_src, return_type, .ret_ty)) { |
| 7880 | const msg = msg: { | 7900 | const msg = msg: { |
| 7881 | const msg = try sema.errMsg(block, ret_ty_src, "return type '{}' not allowed in function with calling convention '{s}'", .{ | 7901 | const msg = try sema.errMsg(block, ret_ty_src, "return type '{}' not allowed in function with calling convention '{s}'", .{ |
| 7882 | return_type.fmt(sema.mod), @tagName(cc_workaround), | 7902 | return_type.fmt(sema.mod), @tagName(cc_workaround), |
| ... | @@ -8072,7 +8092,7 @@ fn analyzeParameter( | ... | @@ -8072,7 +8092,7 @@ fn analyzeParameter( |
| 8072 | cc: std.builtin.CallingConvention, | 8092 | cc: std.builtin.CallingConvention, |
| 8073 | has_body: bool, | 8093 | has_body: bool, |
| 8074 | ) !void { | 8094 | ) !void { |
| 8075 | const requires_comptime = try sema.typeRequiresComptime(block, param_src, param.ty); | 8095 | const requires_comptime = try sema.typeRequiresComptime(param.ty); |
| 8076 | comptime_params[i] = param.is_comptime or requires_comptime; | 8096 | comptime_params[i] = param.is_comptime or requires_comptime; |
| 8077 | const this_generic = param.ty.tag() == .generic_poison; | 8097 | const this_generic = param.ty.tag() == .generic_poison; |
| 8078 | is_generic.* = is_generic.* or this_generic; | 8098 | is_generic.* = is_generic.* or this_generic; |
| ... | @@ -8095,7 +8115,7 @@ fn analyzeParameter( | ... | @@ -8095,7 +8115,7 @@ fn analyzeParameter( |
| 8095 | }; | 8115 | }; |
| 8096 | return sema.failWithOwnedErrorMsg(msg); | 8116 | return sema.failWithOwnedErrorMsg(msg); |
| 8097 | } | 8117 | } |
| 8098 | if (!Type.fnCallingConventionAllowsZigTypes(cc) and !sema.validateExternType(param.ty, .param_ty)) { | 8118 | if (!Type.fnCallingConventionAllowsZigTypes(cc) and !try sema.validateExternType(block, param_src, param.ty, .param_ty)) { |
| 8099 | const msg = msg: { | 8119 | const msg = msg: { |
| 8100 | const msg = try sema.errMsg(block, param_src, "parameter of type '{}' not allowed in function with calling convention '{s}'", .{ | 8120 | const msg = try sema.errMsg(block, param_src, "parameter of type '{}' not allowed in function with calling convention '{s}'", .{ |
| 8101 | param.ty.fmt(sema.mod), @tagName(cc), | 8121 | param.ty.fmt(sema.mod), @tagName(cc), |
| ... | @@ -8177,7 +8197,7 @@ fn zirParam( | ... | @@ -8177,7 +8197,7 @@ fn zirParam( |
| 8177 | } | 8197 | } |
| 8178 | }; | 8198 | }; |
| 8179 | const is_comptime = comptime_syntax or | 8199 | const is_comptime = comptime_syntax or |
| 8180 | try sema.typeRequiresComptime(block, src, param_ty); | 8200 | try sema.typeRequiresComptime(param_ty); |
| 8181 | if (sema.inst_map.get(inst)) |arg| { | 8201 | if (sema.inst_map.get(inst)) |arg| { |
| 8182 | if (is_comptime) { | 8202 | if (is_comptime) { |
| 8183 | // We have a comptime value for this parameter so it should be elided from the | 8203 | // We have a comptime value for this parameter so it should be elided from the |
| ... | @@ -8237,7 +8257,7 @@ fn zirParamAnytype( | ... | @@ -8237,7 +8257,7 @@ fn zirParamAnytype( |
| 8237 | 8257 | ||
| 8238 | if (sema.inst_map.get(inst)) |air_ref| { | 8258 | if (sema.inst_map.get(inst)) |air_ref| { |
| 8239 | const param_ty = sema.typeOf(air_ref); | 8259 | const param_ty = sema.typeOf(air_ref); |
| 8240 | if (comptime_syntax or try sema.typeRequiresComptime(block, src, param_ty)) { | 8260 | if (comptime_syntax or try sema.typeRequiresComptime(param_ty)) { |
| 8241 | // We have a comptime value for this parameter so it should be elided from the | 8261 | // We have a comptime value for this parameter so it should be elided from the |
| 8242 | // function type of the function instruction in this block. | 8262 | // function type of the function instruction in this block. |
| 8243 | return; | 8263 | return; |
| ... | @@ -10379,7 +10399,9 @@ fn zirImport(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air. | ... | @@ -10379,7 +10399,9 @@ fn zirImport(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air. |
| 10379 | } | 10399 | } |
| 10380 | } | 10400 | } |
| 10381 | unreachable; | 10401 | unreachable; |
| 10382 | } else unreachable; | 10402 | } else { |
| 10403 | return sema.fail(block, operand_src, "no package named '{s}' available", .{operand}); | ||
| 10404 | }; | ||
| 10383 | return sema.fail(block, operand_src, "no package named '{s}' available within package '{s}'", .{ operand, parent }); | 10405 | return sema.fail(block, operand_src, "no package named '{s}' available within package '{s}'", .{ operand, parent }); |
| 10384 | }, | 10406 | }, |
| 10385 | else => { | 10407 | else => { |
| ... | @@ -15563,7 +15585,7 @@ fn zirPtrType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air | ... | @@ -15563,7 +15585,7 @@ fn zirPtrType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air |
| 15563 | } else if (inst_data.size == .Many and elem_ty.zigTypeTag() == .Opaque) { | 15585 | } else if (inst_data.size == .Many and elem_ty.zigTypeTag() == .Opaque) { |
| 15564 | return sema.fail(block, elem_ty_src, "unknown-length pointer to opaque not allowed", .{}); | 15586 | return sema.fail(block, elem_ty_src, "unknown-length pointer to opaque not allowed", .{}); |
| 15565 | } else if (inst_data.size == .C) { | 15587 | } else if (inst_data.size == .C) { |
| 15566 | if (!sema.validateExternType(elem_ty, .other)) { | 15588 | if (!try sema.validateExternType(block, elem_ty_src, elem_ty, .other)) { |
| 15567 | const msg = msg: { | 15589 | const msg = msg: { |
| 15568 | const msg = try sema.errMsg(block, elem_ty_src, "C pointers cannot point to non-C-ABI-compatible type '{}'", .{elem_ty.fmt(sema.mod)}); | 15590 | const msg = try sema.errMsg(block, elem_ty_src, "C pointers cannot point to non-C-ABI-compatible type '{}'", .{elem_ty.fmt(sema.mod)}); |
| 15569 | errdefer msg.destroy(sema.gpa); | 15591 | errdefer msg.destroy(sema.gpa); |
| ... | @@ -16661,7 +16683,7 @@ fn zirReify(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData, in | ... | @@ -16661,7 +16683,7 @@ fn zirReify(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData, in |
| 16661 | } else if (ptr_size == .Many and elem_ty.zigTypeTag() == .Opaque) { | 16683 | } else if (ptr_size == .Many and elem_ty.zigTypeTag() == .Opaque) { |
| 16662 | return sema.fail(block, src, "unknown-length pointer to opaque not allowed", .{}); | 16684 | return sema.fail(block, src, "unknown-length pointer to opaque not allowed", .{}); |
| 16663 | } else if (ptr_size == .C) { | 16685 | } else if (ptr_size == .C) { |
| 16664 | if (!sema.validateExternType(elem_ty, .other)) { | 16686 | if (!try sema.validateExternType(block, src, elem_ty, .other)) { |
| 16665 | const msg = msg: { | 16687 | const msg = msg: { |
| 16666 | const msg = try sema.errMsg(block, src, "C pointers cannot point to non-C-ABI-compatible type '{}'", .{elem_ty.fmt(sema.mod)}); | 16688 | const msg = try sema.errMsg(block, src, "C pointers cannot point to non-C-ABI-compatible type '{}'", .{elem_ty.fmt(sema.mod)}); |
| 16667 | errdefer msg.destroy(sema.gpa); | 16689 | errdefer msg.destroy(sema.gpa); |
| ... | @@ -17499,7 +17521,7 @@ fn zirIntToFloat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError! | ... | @@ -17499,7 +17521,7 @@ fn zirIntToFloat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError! |
| 17499 | 17521 | ||
| 17500 | if (try sema.resolveMaybeUndefVal(block, operand_src, operand)) |val| { | 17522 | if (try sema.resolveMaybeUndefVal(block, operand_src, operand)) |val| { |
| 17501 | const target = sema.mod.getTarget(); | 17523 | const target = sema.mod.getTarget(); |
| 17502 | const result_val = try val.intToFloat(sema.arena, operand_ty, dest_ty, target); | 17524 | const result_val = try val.intToFloatAdvanced(sema.arena, operand_ty, dest_ty, target, sema.kit(block, operand_src)); |
| 17503 | return sema.addConstant(dest_ty, result_val); | 17525 | return sema.addConstant(dest_ty, result_val); |
| 17504 | } else if (dest_ty.zigTypeTag() == .ComptimeFloat) { | 17526 | } else if (dest_ty.zigTypeTag() == .ComptimeFloat) { |
| 17505 | return sema.failWithNeededComptime(block, operand_src, "value being casted to 'comptime_float' must be comptime known"); | 17527 | return sema.failWithNeededComptime(block, operand_src, "value being casted to 'comptime_float' must be comptime known"); |
| ... | @@ -20343,12 +20365,13 @@ fn validateRunTimeType( | ... | @@ -20343,12 +20365,13 @@ fn validateRunTimeType( |
| 20343 | .Int, | 20365 | .Int, |
| 20344 | .Float, | 20366 | .Float, |
| 20345 | .ErrorSet, | 20367 | .ErrorSet, |
| 20346 | .Enum, | ||
| 20347 | .Frame, | 20368 | .Frame, |
| 20348 | .AnyFrame, | 20369 | .AnyFrame, |
| 20349 | .Void, | 20370 | .Void, |
| 20350 | => return true, | 20371 | => return true, |
| 20351 | 20372 | ||
| 20373 | .Enum => return !(try sema.typeRequiresComptime(ty)), | ||
| 20374 | |||
| 20352 | .BoundFn, | 20375 | .BoundFn, |
| 20353 | .ComptimeFloat, | 20376 | .ComptimeFloat, |
| 20354 | .ComptimeInt, | 20377 | .ComptimeInt, |
| ... | @@ -20381,7 +20404,7 @@ fn validateRunTimeType( | ... | @@ -20381,7 +20404,7 @@ fn validateRunTimeType( |
| 20381 | 20404 | ||
| 20382 | .Struct, .Union => { | 20405 | .Struct, .Union => { |
| 20383 | const resolved_ty = try sema.resolveTypeFields(block, src, ty); | 20406 | const resolved_ty = try sema.resolveTypeFields(block, src, ty); |
| 20384 | const needs_comptime = try sema.typeRequiresComptime(block, src, resolved_ty); | 20407 | const needs_comptime = try sema.typeRequiresComptime(resolved_ty); |
| 20385 | return !needs_comptime; | 20408 | return !needs_comptime; |
| 20386 | }, | 20409 | }, |
| 20387 | }; | 20410 | }; |
| ... | @@ -20489,7 +20512,7 @@ fn explainWhyTypeIsComptimeInner( | ... | @@ -20489,7 +20512,7 @@ fn explainWhyTypeIsComptimeInner( |
| 20489 | .range = .type, | 20512 | .range = .type, |
| 20490 | }); | 20513 | }); |
| 20491 | 20514 | ||
| 20492 | if (try sema.typeRequiresComptime(block, src, field.ty)) { | 20515 | if (try sema.typeRequiresComptime(field.ty)) { |
| 20493 | try mod.errNoteNonLazy(field_src_loc, msg, "struct requires comptime because of this field", .{}); | 20516 | try mod.errNoteNonLazy(field_src_loc, msg, "struct requires comptime because of this field", .{}); |
| 20494 | try sema.explainWhyTypeIsComptimeInner(block, src, msg, field_src_loc, field.ty, type_set); | 20517 | try sema.explainWhyTypeIsComptimeInner(block, src, msg, field_src_loc, field.ty, type_set); |
| 20495 | } | 20518 | } |
| ... | @@ -20509,7 +20532,7 @@ fn explainWhyTypeIsComptimeInner( | ... | @@ -20509,7 +20532,7 @@ fn explainWhyTypeIsComptimeInner( |
| 20509 | .range = .type, | 20532 | .range = .type, |
| 20510 | }); | 20533 | }); |
| 20511 | 20534 | ||
| 20512 | if (try sema.typeRequiresComptime(block, src, field.ty)) { | 20535 | if (try sema.typeRequiresComptime(field.ty)) { |
| 20513 | try mod.errNoteNonLazy(field_src_loc, msg, "union requires comptime because of this field", .{}); | 20536 | try mod.errNoteNonLazy(field_src_loc, msg, "union requires comptime because of this field", .{}); |
| 20514 | try sema.explainWhyTypeIsComptimeInner(block, src, msg, field_src_loc, field.ty, type_set); | 20537 | try sema.explainWhyTypeIsComptimeInner(block, src, msg, field_src_loc, field.ty, type_set); |
| 20515 | } | 20538 | } |
| ... | @@ -20528,7 +20551,14 @@ const ExternPosition = enum { | ... | @@ -20528,7 +20551,14 @@ const ExternPosition = enum { |
| 20528 | 20551 | ||
| 20529 | /// Returns true if `ty` is allowed in extern types. | 20552 | /// Returns true if `ty` is allowed in extern types. |
| 20530 | /// Does *NOT* require `ty` to be resolved in any way. | 20553 | /// Does *NOT* require `ty` to be resolved in any way. |
| 20531 | fn validateExternType(sema: *Sema, ty: Type, position: ExternPosition) bool { | 20554 | /// Calls `resolveTypeLayout` for packed containers. |
| 20555 | fn validateExternType( | ||
| 20556 | sema: *Sema, | ||
| 20557 | block: *Block, | ||
| 20558 | src: LazySrcLoc, | ||
| 20559 | ty: Type, | ||
| 20560 | position: ExternPosition, | ||
| 20561 | ) !bool { | ||
| 20532 | switch (ty.zigTypeTag()) { | 20562 | switch (ty.zigTypeTag()) { |
| 20533 | .Type, | 20563 | .Type, |
| 20534 | .ComptimeFloat, | 20564 | .ComptimeFloat, |
| ... | @@ -20556,17 +20586,25 @@ fn validateExternType(sema: *Sema, ty: Type, position: ExternPosition) bool { | ... | @@ -20556,17 +20586,25 @@ fn validateExternType(sema: *Sema, ty: Type, position: ExternPosition) bool { |
| 20556 | .Fn => return !Type.fnCallingConventionAllowsZigTypes(ty.fnCallingConvention()), | 20586 | .Fn => return !Type.fnCallingConventionAllowsZigTypes(ty.fnCallingConvention()), |
| 20557 | .Enum => { | 20587 | .Enum => { |
| 20558 | var buf: Type.Payload.Bits = undefined; | 20588 | var buf: Type.Payload.Bits = undefined; |
| 20559 | return sema.validateExternType(ty.intTagType(&buf), position); | 20589 | return sema.validateExternType(block, src, ty.intTagType(&buf), position); |
| 20560 | }, | 20590 | }, |
| 20561 | .Struct, .Union => switch (ty.containerLayout()) { | 20591 | .Struct, .Union => switch (ty.containerLayout()) { |
| 20562 | .Extern, .Packed => return true, | 20592 | .Extern => return true, |
| 20563 | else => return false, | 20593 | .Packed => { |
| 20594 | const target = sema.mod.getTarget(); | ||
| 20595 | const bit_size = try ty.bitSizeAdvanced(target, sema.kit(block, src)); | ||
| 20596 | switch (bit_size) { | ||
| 20597 | 8, 16, 32, 64, 128 => return true, | ||
| 20598 | else => return false, | ||
| 20599 | } | ||
| 20600 | }, | ||
| 20601 | .Auto => return false, | ||
| 20564 | }, | 20602 | }, |
| 20565 | .Array => { | 20603 | .Array => { |
| 20566 | if (position == .ret_ty or position == .param_ty) return false; | 20604 | if (position == .ret_ty or position == .param_ty) return false; |
| 20567 | return sema.validateExternType(ty.elemType2(), .other); | 20605 | return sema.validateExternType(block, src, ty.elemType2(), .other); |
| 20568 | }, | 20606 | }, |
| 20569 | .Vector => return sema.validateExternType(ty.elemType2(), .other), | 20607 | .Vector => return sema.validateExternType(block, src, ty.elemType2(), .other), |
| 20570 | .Optional => return ty.isPtrLikeOptional(), | 20608 | .Optional => return ty.isPtrLikeOptional(), |
| 20571 | } | 20609 | } |
| 20572 | } | 20610 | } |
| ... | @@ -20618,8 +20656,8 @@ fn explainWhyTypeIsNotExtern( | ... | @@ -20618,8 +20656,8 @@ fn explainWhyTypeIsNotExtern( |
| 20618 | try mod.errNoteNonLazy(src_loc, msg, "enum tag type '{}' is not extern compatible", .{tag_ty.fmt(sema.mod)}); | 20656 | try mod.errNoteNonLazy(src_loc, msg, "enum tag type '{}' is not extern compatible", .{tag_ty.fmt(sema.mod)}); |
| 20619 | try sema.explainWhyTypeIsNotExtern(msg, src_loc, tag_ty, position); | 20657 | try sema.explainWhyTypeIsNotExtern(msg, src_loc, tag_ty, position); |
| 20620 | }, | 20658 | }, |
| 20621 | .Struct => try mod.errNoteNonLazy(src_loc, msg, "only structs with packed or extern layout are extern compatible", .{}), | 20659 | .Struct => try mod.errNoteNonLazy(src_loc, msg, "only extern structs and ABI sized packed structs are extern compatible", .{}), |
| 20622 | .Union => try mod.errNoteNonLazy(src_loc, msg, "only unions with packed or extern layout are extern compatible", .{}), | 20660 | .Union => try mod.errNoteNonLazy(src_loc, msg, "only extern unions and ABI sized packed unions are extern compatible", .{}), |
| 20623 | .Array => { | 20661 | .Array => { |
| 20624 | if (position == .ret_ty) { | 20662 | if (position == .ret_ty) { |
| 20625 | return mod.errNoteNonLazy(src_loc, msg, "arrays are not allowed as a return type", .{}); | 20663 | return mod.errNoteNonLazy(src_loc, msg, "arrays are not allowed as a return type", .{}); |
| ... | @@ -22998,7 +23036,7 @@ fn coerceExtra( | ... | @@ -22998,7 +23036,7 @@ fn coerceExtra( |
| 22998 | } | 23036 | } |
| 22999 | break :int; | 23037 | break :int; |
| 23000 | }; | 23038 | }; |
| 23001 | const result_val = try val.intToFloat(sema.arena, inst_ty, dest_ty, target); | 23039 | const result_val = try val.intToFloatAdvanced(sema.arena, inst_ty, dest_ty, target, sema.kit(block, inst_src)); |
| 23002 | // TODO implement this compile error | 23040 | // TODO implement this compile error |
| 23003 | //const int_again_val = try result_val.floatToInt(sema.arena, inst_ty); | 23041 | //const int_again_val = try result_val.floatToInt(sema.arena, inst_ty); |
| 23004 | //if (!int_again_val.eql(val, inst_ty, mod)) { | 23042 | //if (!int_again_val.eql(val, inst_ty, mod)) { |
| ... | @@ -23422,8 +23460,11 @@ const InMemoryCoercionResult = union(enum) { | ... | @@ -23422,8 +23460,11 @@ const InMemoryCoercionResult = union(enum) { |
| 23422 | var index: u6 = 0; | 23460 | var index: u6 = 0; |
| 23423 | var actual_noalias = false; | 23461 | var actual_noalias = false; |
| 23424 | while (true) : (index += 1) { | 23462 | while (true) : (index += 1) { |
| 23425 | if (param.actual << index != param.wanted << index) { | 23463 | const actual = @truncate(u1, param.actual >> index); |
| 23426 | actual_noalias = (param.actual << index) == (1 << 31); | 23464 | const wanted = @truncate(u1, param.wanted >> index); |
| 23465 | if (actual != wanted) { | ||
| 23466 | actual_noalias = actual == 1; | ||
| 23467 | break; | ||
| 23427 | } | 23468 | } |
| 23428 | } | 23469 | } |
| 23429 | if (!actual_noalias) { | 23470 | if (!actual_noalias) { |
| ... | @@ -23917,7 +23958,7 @@ fn coerceInMemoryAllowedFns( | ... | @@ -23917,7 +23958,7 @@ fn coerceInMemoryAllowedFns( |
| 23917 | 23958 | ||
| 23918 | if (dest_info.noalias_bits != src_info.noalias_bits) { | 23959 | if (dest_info.noalias_bits != src_info.noalias_bits) { |
| 23919 | return InMemoryCoercionResult{ .fn_param_noalias = .{ | 23960 | return InMemoryCoercionResult{ .fn_param_noalias = .{ |
| 23920 | .actual = dest_info.noalias_bits, | 23961 | .actual = src_info.noalias_bits, |
| 23921 | .wanted = dest_info.noalias_bits, | 23962 | .wanted = dest_info.noalias_bits, |
| 23922 | } }; | 23963 | } }; |
| 23923 | } | 23964 | } |
| ... | @@ -24075,16 +24116,40 @@ fn coerceVarArgParam( | ... | @@ -24075,16 +24116,40 @@ fn coerceVarArgParam( |
| 24075 | inst: Air.Inst.Ref, | 24116 | inst: Air.Inst.Ref, |
| 24076 | inst_src: LazySrcLoc, | 24117 | inst_src: LazySrcLoc, |
| 24077 | ) !Air.Inst.Ref { | 24118 | ) !Air.Inst.Ref { |
| 24078 | const inst_ty = sema.typeOf(inst); | ||
| 24079 | if (block.is_typeof) return inst; | 24119 | if (block.is_typeof) return inst; |
| 24080 | 24120 | ||
| 24081 | switch (inst_ty.zigTypeTag()) { | 24121 | const coerced = switch (sema.typeOf(inst).zigTypeTag()) { |
| 24082 | // TODO consider casting to c_int/f64 if they fit | 24122 | // TODO consider casting to c_int/f64 if they fit |
| 24083 | .ComptimeInt, .ComptimeFloat => return sema.fail(block, inst_src, "integer and float literals in var args function must be casted", .{}), | 24123 | .ComptimeInt, .ComptimeFloat => return sema.fail( |
| 24084 | else => {}, | 24124 | block, |
| 24125 | inst_src, | ||
| 24126 | "integer and float literals passed variadic function must be casted to a fixed-size number type", | ||
| 24127 | .{}, | ||
| 24128 | ), | ||
| 24129 | .Fn => blk: { | ||
| 24130 | const fn_val = try sema.resolveConstValue(block, .unneeded, inst, undefined); | ||
| 24131 | const fn_decl = fn_val.pointerDecl().?; | ||
| 24132 | break :blk try sema.analyzeDeclRef(fn_decl); | ||
| 24133 | }, | ||
| 24134 | .Array => return sema.fail(block, inst_src, "arrays must be passed by reference to variadic function", .{}), | ||
| 24135 | else => inst, | ||
| 24136 | }; | ||
| 24137 | |||
| 24138 | const coerced_ty = sema.typeOf(coerced); | ||
| 24139 | if (!try sema.validateExternType(block, inst_src, coerced_ty, .other)) { | ||
| 24140 | const msg = msg: { | ||
| 24141 | const msg = try sema.errMsg(block, inst_src, "cannot pass '{}' to variadic function", .{coerced_ty.fmt(sema.mod)}); | ||
| 24142 | errdefer msg.destroy(sema.gpa); | ||
| 24143 | |||
| 24144 | const src_decl = sema.mod.declPtr(block.src_decl); | ||
| 24145 | try sema.explainWhyTypeIsNotExtern(msg, inst_src.toSrcLoc(src_decl), coerced_ty, .other); | ||
| 24146 | |||
| 24147 | try sema.addDeclaredHereNote(msg, coerced_ty); | ||
| 24148 | break :msg msg; | ||
| 24149 | }; | ||
| 24150 | return sema.failWithOwnedErrorMsg(msg); | ||
| 24085 | } | 24151 | } |
| 24086 | // TODO implement more of this function. | 24152 | return coerced; |
| 24087 | return inst; | ||
| 24088 | } | 24153 | } |
| 24089 | 24154 | ||
| 24090 | // TODO migrate callsites to use storePtr2 instead. | 24155 | // TODO migrate callsites to use storePtr2 instead. |
| ... | @@ -27579,7 +27644,7 @@ pub fn resolveTypeLayout( | ... | @@ -27579,7 +27644,7 @@ pub fn resolveTypeLayout( |
| 27579 | // In case of querying the ABI alignment of this optional, we will ask | 27644 | // In case of querying the ABI alignment of this optional, we will ask |
| 27580 | // for hasRuntimeBits() of the payload type, so we need "requires comptime" | 27645 | // for hasRuntimeBits() of the payload type, so we need "requires comptime" |
| 27581 | // to be known already before this function returns. | 27646 | // to be known already before this function returns. |
| 27582 | _ = try sema.typeRequiresComptime(block, src, payload_ty); | 27647 | _ = try sema.typeRequiresComptime(payload_ty); |
| 27583 | return sema.resolveTypeLayout(block, src, payload_ty); | 27648 | return sema.resolveTypeLayout(block, src, payload_ty); |
| 27584 | }, | 27649 | }, |
| 27585 | .ErrorUnion => { | 27650 | .ErrorUnion => { |
| ... | @@ -27634,7 +27699,7 @@ fn resolveStructLayout( | ... | @@ -27634,7 +27699,7 @@ fn resolveStructLayout( |
| 27634 | // for hasRuntimeBits() of each field, so we need "requires comptime" | 27699 | // for hasRuntimeBits() of each field, so we need "requires comptime" |
| 27635 | // to be known already before this function returns. | 27700 | // to be known already before this function returns. |
| 27636 | for (struct_obj.fields.values()) |field, i| { | 27701 | for (struct_obj.fields.values()) |field, i| { |
| 27637 | _ = sema.typeRequiresComptime(block, src, field.ty) catch |err| switch (err) { | 27702 | _ = sema.typeRequiresComptime(field.ty) catch |err| switch (err) { |
| 27638 | error.AnalysisFail => { | 27703 | error.AnalysisFail => { |
| 27639 | const msg = sema.err orelse return err; | 27704 | const msg = sema.err orelse return err; |
| 27640 | try sema.addFieldErrNote(block, ty, i, msg, "while checking this field", .{}); | 27705 | try sema.addFieldErrNote(block, ty, i, msg, "while checking this field", .{}); |
| ... | @@ -27866,7 +27931,7 @@ fn resolveStructFully( | ... | @@ -27866,7 +27931,7 @@ fn resolveStructFully( |
| 27866 | } | 27931 | } |
| 27867 | 27932 | ||
| 27868 | // And let's not forget comptime-only status. | 27933 | // And let's not forget comptime-only status. |
| 27869 | _ = try sema.typeRequiresComptime(block, src, ty); | 27934 | _ = try sema.typeRequiresComptime(ty); |
| 27870 | } | 27935 | } |
| 27871 | 27936 | ||
| 27872 | fn resolveUnionFully( | 27937 | fn resolveUnionFully( |
| ... | @@ -27899,7 +27964,7 @@ fn resolveUnionFully( | ... | @@ -27899,7 +27964,7 @@ fn resolveUnionFully( |
| 27899 | } | 27964 | } |
| 27900 | 27965 | ||
| 27901 | // And let's not forget comptime-only status. | 27966 | // And let's not forget comptime-only status. |
| 27902 | _ = try sema.typeRequiresComptime(block, src, ty); | 27967 | _ = try sema.typeRequiresComptime(ty); |
| 27903 | } | 27968 | } |
| 27904 | 27969 | ||
| 27905 | pub fn resolveTypeFields(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) CompileError!Type { | 27970 | pub fn resolveTypeFields(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) CompileError!Type { |
| ... | @@ -28273,7 +28338,7 @@ fn semaStructFields(mod: *Module, struct_obj: *Module.Struct) CompileError!void | ... | @@ -28273,7 +28338,7 @@ fn semaStructFields(mod: *Module, struct_obj: *Module.Struct) CompileError!void |
| 28273 | }; | 28338 | }; |
| 28274 | return sema.failWithOwnedErrorMsg(msg); | 28339 | return sema.failWithOwnedErrorMsg(msg); |
| 28275 | } | 28340 | } |
| 28276 | if (struct_obj.layout == .Extern and !sema.validateExternType(field.ty, .other)) { | 28341 | if (struct_obj.layout == .Extern and !try sema.validateExternType(&block_scope, src, field.ty, .other)) { |
| 28277 | const msg = msg: { | 28342 | const msg = msg: { |
| 28278 | const tree = try sema.getAstTree(&block_scope); | 28343 | const tree = try sema.getAstTree(&block_scope); |
| 28279 | const fields_src = enumFieldSrcLoc(decl, tree.*, 0, i); | 28344 | const fields_src = enumFieldSrcLoc(decl, tree.*, 0, i); |
| ... | @@ -28610,7 +28675,7 @@ fn semaUnionFields(mod: *Module, union_obj: *Module.Union) CompileError!void { | ... | @@ -28610,7 +28675,7 @@ fn semaUnionFields(mod: *Module, union_obj: *Module.Union) CompileError!void { |
| 28610 | }; | 28675 | }; |
| 28611 | return sema.failWithOwnedErrorMsg(msg); | 28676 | return sema.failWithOwnedErrorMsg(msg); |
| 28612 | } | 28677 | } |
| 28613 | if (union_obj.layout == .Extern and !sema.validateExternType(field_ty, .union_field)) { | 28678 | if (union_obj.layout == .Extern and !try sema.validateExternType(&block_scope, src, field_ty, .union_field)) { |
| 28614 | const msg = msg: { | 28679 | const msg = msg: { |
| 28615 | const tree = try sema.getAstTree(&block_scope); | 28680 | const tree = try sema.getAstTree(&block_scope); |
| 28616 | const field_src = enumFieldSrcLoc(decl, tree.*, 0, field_i); | 28681 | const field_src = enumFieldSrcLoc(decl, tree.*, 0, field_i); |
| ... | @@ -29002,7 +29067,7 @@ pub fn typeHasOnePossibleValue( | ... | @@ -29002,7 +29067,7 @@ pub fn typeHasOnePossibleValue( |
| 29002 | }, | 29067 | }, |
| 29003 | .enum_nonexhaustive => { | 29068 | .enum_nonexhaustive => { |
| 29004 | const tag_ty = ty.castTag(.enum_nonexhaustive).?.data.tag_ty; | 29069 | const tag_ty = ty.castTag(.enum_nonexhaustive).?.data.tag_ty; |
| 29005 | if (!(try sema.typeHasRuntimeBits(block, src, tag_ty))) { | 29070 | if (tag_ty.zigTypeTag() != .ComptimeInt and !(try sema.typeHasRuntimeBits(block, src, tag_ty))) { |
| 29006 | return Value.zero; | 29071 | return Value.zero; |
| 29007 | } else { | 29072 | } else { |
| 29008 | return null; | 29073 | return null; |
| ... | @@ -29534,7 +29599,7 @@ fn typePtrOrOptionalPtrTy( | ... | @@ -29534,7 +29599,7 @@ fn typePtrOrOptionalPtrTy( |
| 29534 | /// TODO assert the return value matches `ty.comptimeOnly` | 29599 | /// TODO assert the return value matches `ty.comptimeOnly` |
| 29535 | /// TODO merge these implementations together with the "advanced"/sema_kit pattern seen | 29600 | /// TODO merge these implementations together with the "advanced"/sema_kit pattern seen |
| 29536 | /// elsewhere in value.zig | 29601 | /// elsewhere in value.zig |
| 29537 | pub fn typeRequiresComptime(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) CompileError!bool { | 29602 | pub fn typeRequiresComptime(sema: *Sema, ty: Type) CompileError!bool { |
| 29538 | return switch (ty.tag()) { | 29603 | return switch (ty.tag()) { |
| 29539 | .u1, | 29604 | .u1, |
| 29540 | .u8, | 29605 | .u8, |
| ... | @@ -29625,7 +29690,7 @@ pub fn typeRequiresComptime(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Typ | ... | @@ -29625,7 +29690,7 @@ pub fn typeRequiresComptime(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Typ |
| 29625 | .array, | 29690 | .array, |
| 29626 | .array_sentinel, | 29691 | .array_sentinel, |
| 29627 | .vector, | 29692 | .vector, |
| 29628 | => return sema.typeRequiresComptime(block, src, ty.childType()), | 29693 | => return sema.typeRequiresComptime(ty.childType()), |
| 29629 | 29694 | ||
| 29630 | .pointer, | 29695 | .pointer, |
| 29631 | .single_const_pointer, | 29696 | .single_const_pointer, |
| ... | @@ -29641,7 +29706,7 @@ pub fn typeRequiresComptime(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Typ | ... | @@ -29641,7 +29706,7 @@ pub fn typeRequiresComptime(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Typ |
| 29641 | if (child_ty.zigTypeTag() == .Fn) { | 29706 | if (child_ty.zigTypeTag() == .Fn) { |
| 29642 | return child_ty.fnInfo().is_generic; | 29707 | return child_ty.fnInfo().is_generic; |
| 29643 | } else { | 29708 | } else { |
| 29644 | return sema.typeRequiresComptime(block, src, child_ty); | 29709 | return sema.typeRequiresComptime(child_ty); |
| 29645 | } | 29710 | } |
| 29646 | }, | 29711 | }, |
| 29647 | 29712 | ||
| ... | @@ -29650,14 +29715,14 @@ pub fn typeRequiresComptime(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Typ | ... | @@ -29650,14 +29715,14 @@ pub fn typeRequiresComptime(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Typ |
| 29650 | .optional_single_const_pointer, | 29715 | .optional_single_const_pointer, |
| 29651 | => { | 29716 | => { |
| 29652 | var buf: Type.Payload.ElemType = undefined; | 29717 | var buf: Type.Payload.ElemType = undefined; |
| 29653 | return sema.typeRequiresComptime(block, src, ty.optionalChild(&buf)); | 29718 | return sema.typeRequiresComptime(ty.optionalChild(&buf)); |
| 29654 | }, | 29719 | }, |
| 29655 | 29720 | ||
| 29656 | .tuple, .anon_struct => { | 29721 | .tuple, .anon_struct => { |
| 29657 | const tuple = ty.tupleFields(); | 29722 | const tuple = ty.tupleFields(); |
| 29658 | for (tuple.types) |field_ty, i| { | 29723 | for (tuple.types) |field_ty, i| { |
| 29659 | const have_comptime_val = tuple.values[i].tag() != .unreachable_value; | 29724 | const have_comptime_val = tuple.values[i].tag() != .unreachable_value; |
| 29660 | if (!have_comptime_val and try sema.typeRequiresComptime(block, src, field_ty)) { | 29725 | if (!have_comptime_val and try sema.typeRequiresComptime(field_ty)) { |
| 29661 | return true; | 29726 | return true; |
| 29662 | } | 29727 | } |
| 29663 | } | 29728 | } |
| ... | @@ -29678,7 +29743,7 @@ pub fn typeRequiresComptime(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Typ | ... | @@ -29678,7 +29743,7 @@ pub fn typeRequiresComptime(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Typ |
| 29678 | struct_obj.requires_comptime = .wip; | 29743 | struct_obj.requires_comptime = .wip; |
| 29679 | for (struct_obj.fields.values()) |field| { | 29744 | for (struct_obj.fields.values()) |field| { |
| 29680 | if (field.is_comptime) continue; | 29745 | if (field.is_comptime) continue; |
| 29681 | if (try sema.typeRequiresComptime(block, src, field.ty)) { | 29746 | if (try sema.typeRequiresComptime(field.ty)) { |
| 29682 | struct_obj.requires_comptime = .yes; | 29747 | struct_obj.requires_comptime = .yes; |
| 29683 | return true; | 29748 | return true; |
| 29684 | } | 29749 | } |
| ... | @@ -29702,7 +29767,7 @@ pub fn typeRequiresComptime(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Typ | ... | @@ -29702,7 +29767,7 @@ pub fn typeRequiresComptime(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Typ |
| 29702 | 29767 | ||
| 29703 | union_obj.requires_comptime = .wip; | 29768 | union_obj.requires_comptime = .wip; |
| 29704 | for (union_obj.fields.values()) |field| { | 29769 | for (union_obj.fields.values()) |field| { |
| 29705 | if (try sema.typeRequiresComptime(block, src, field.ty)) { | 29770 | if (try sema.typeRequiresComptime(field.ty)) { |
| 29706 | union_obj.requires_comptime = .yes; | 29771 | union_obj.requires_comptime = .yes; |
| 29707 | return true; | 29772 | return true; |
| 29708 | } | 29773 | } |
| ... | @@ -29713,18 +29778,18 @@ pub fn typeRequiresComptime(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Typ | ... | @@ -29713,18 +29778,18 @@ pub fn typeRequiresComptime(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Typ |
| 29713 | } | 29778 | } |
| 29714 | }, | 29779 | }, |
| 29715 | 29780 | ||
| 29716 | .error_union => return sema.typeRequiresComptime(block, src, ty.errorUnionPayload()), | 29781 | .error_union => return sema.typeRequiresComptime(ty.errorUnionPayload()), |
| 29717 | .anyframe_T => { | 29782 | .anyframe_T => { |
| 29718 | const child_ty = ty.castTag(.anyframe_T).?.data; | 29783 | const child_ty = ty.castTag(.anyframe_T).?.data; |
| 29719 | return sema.typeRequiresComptime(block, src, child_ty); | 29784 | return sema.typeRequiresComptime(child_ty); |
| 29720 | }, | 29785 | }, |
| 29721 | .enum_numbered => { | 29786 | .enum_numbered => { |
| 29722 | const tag_ty = ty.castTag(.enum_numbered).?.data.tag_ty; | 29787 | const tag_ty = ty.castTag(.enum_numbered).?.data.tag_ty; |
| 29723 | return sema.typeRequiresComptime(block, src, tag_ty); | 29788 | return sema.typeRequiresComptime(tag_ty); |
| 29724 | }, | 29789 | }, |
| 29725 | .enum_full, .enum_nonexhaustive => { | 29790 | .enum_full, .enum_nonexhaustive => { |
| 29726 | const tag_ty = ty.cast(Type.Payload.EnumFull).?.data.tag_ty; | 29791 | const tag_ty = ty.cast(Type.Payload.EnumFull).?.data.tag_ty; |
| 29727 | return sema.typeRequiresComptime(block, src, tag_ty); | 29792 | return sema.typeRequiresComptime(tag_ty); |
| 29728 | }, | 29793 | }, |
| 29729 | }; | 29794 | }; |
| 29730 | } | 29795 | } |
| ... | @@ -29762,7 +29827,7 @@ fn unionFieldAlignment( | ... | @@ -29762,7 +29827,7 @@ fn unionFieldAlignment( |
| 29762 | } | 29827 | } |
| 29763 | 29828 | ||
| 29764 | /// Synchronize logic with `Type.isFnOrHasRuntimeBits`. | 29829 | /// Synchronize logic with `Type.isFnOrHasRuntimeBits`. |
| 29765 | pub fn fnHasRuntimeBits(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) CompileError!bool { | 29830 | pub fn fnHasRuntimeBits(sema: *Sema, ty: Type) CompileError!bool { |
| 29766 | const fn_info = ty.fnInfo(); | 29831 | const fn_info = ty.fnInfo(); |
| 29767 | if (fn_info.is_generic) return false; | 29832 | if (fn_info.is_generic) return false; |
| 29768 | if (fn_info.is_var_args) return true; | 29833 | if (fn_info.is_var_args) return true; |
| ... | @@ -29771,7 +29836,7 @@ pub fn fnHasRuntimeBits(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) C | ... | @@ -29771,7 +29836,7 @@ pub fn fnHasRuntimeBits(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) C |
| 29771 | .Inline => return false, | 29836 | .Inline => return false, |
| 29772 | else => {}, | 29837 | else => {}, |
| 29773 | } | 29838 | } |
| 29774 | if (try sema.typeRequiresComptime(block, src, fn_info.return_type)) { | 29839 | if (try sema.typeRequiresComptime(fn_info.return_type)) { |
| 29775 | return false; | 29840 | return false; |
| 29776 | } | 29841 | } |
| 29777 | return true; | 29842 | return true; |
src/arch/aarch64/abi.zig+63| ... | @@ -3,6 +3,69 @@ const builtin = @import("builtin"); | ... | @@ -3,6 +3,69 @@ const builtin = @import("builtin"); |
| 3 | const bits = @import("bits.zig"); | 3 | const bits = @import("bits.zig"); |
| 4 | const Register = bits.Register; | 4 | const Register = bits.Register; |
| 5 | const RegisterManagerFn = @import("../../register_manager.zig").RegisterManager; | 5 | const RegisterManagerFn = @import("../../register_manager.zig").RegisterManager; |
| 6 | const Type = @import("../../type.zig").Type; | ||
| 7 | |||
| 8 | pub const Class = enum { memory, integer, none, float_array }; | ||
| 9 | |||
| 10 | pub fn classifyType(ty: Type, target: std.Target) [2]Class { | ||
| 11 | if (!ty.hasRuntimeBitsIgnoreComptime()) return .{ .none, .none }; | ||
| 12 | switch (ty.zigTypeTag()) { | ||
| 13 | .Struct => { | ||
| 14 | if (ty.containerLayout() == .Packed) return .{ .integer, .none }; | ||
| 15 | |||
| 16 | if (ty.structFieldCount() <= 4) { | ||
| 17 | const fields = ty.structFields(); | ||
| 18 | var float_size: ?u64 = null; | ||
| 19 | for (fields.values()) |field| { | ||
| 20 | if (field.ty.zigTypeTag() != .Float) break; | ||
| 21 | const field_size = field.ty.bitSize(target); | ||
| 22 | const prev_size = float_size orelse { | ||
| 23 | float_size = field_size; | ||
| 24 | continue; | ||
| 25 | }; | ||
| 26 | if (field_size != prev_size) break; | ||
| 27 | } else { | ||
| 28 | return .{ .float_array, .none }; | ||
| 29 | } | ||
| 30 | } | ||
| 31 | const bit_size = ty.bitSize(target); | ||
| 32 | if (bit_size > 128) return .{ .memory, .none }; | ||
| 33 | if (bit_size > 64) return .{ .integer, .integer }; | ||
| 34 | return .{ .integer, .none }; | ||
| 35 | }, | ||
| 36 | .Union => { | ||
| 37 | const bit_size = ty.bitSize(target); | ||
| 38 | if (bit_size > 128) return .{ .memory, .none }; | ||
| 39 | if (bit_size > 64) return .{ .integer, .integer }; | ||
| 40 | return .{ .integer, .none }; | ||
| 41 | }, | ||
| 42 | .Int, .Enum, .ErrorSet, .Vector, .Float, .Bool => return .{ .integer, .none }, | ||
| 43 | .Array => return .{ .memory, .none }, | ||
| 44 | .Optional => { | ||
| 45 | std.debug.assert(ty.isPtrLikeOptional()); | ||
| 46 | return .{ .integer, .none }; | ||
| 47 | }, | ||
| 48 | .Pointer => { | ||
| 49 | std.debug.assert(!ty.isSlice()); | ||
| 50 | return .{ .integer, .none }; | ||
| 51 | }, | ||
| 52 | .ErrorUnion, | ||
| 53 | .Frame, | ||
| 54 | .AnyFrame, | ||
| 55 | .NoReturn, | ||
| 56 | .Void, | ||
| 57 | .Type, | ||
| 58 | .ComptimeFloat, | ||
| 59 | .ComptimeInt, | ||
| 60 | .Undefined, | ||
| 61 | .Null, | ||
| 62 | .BoundFn, | ||
| 63 | .Fn, | ||
| 64 | .Opaque, | ||
| 65 | .EnumLiteral, | ||
| 66 | => unreachable, | ||
| 67 | } | ||
| 68 | } | ||
| 6 | 69 | ||
| 7 | const callee_preserved_regs_impl = if (builtin.os.tag.isDarwin()) struct { | 70 | const callee_preserved_regs_impl = if (builtin.os.tag.isDarwin()) struct { |
| 8 | pub const callee_preserved_regs = [_]Register{ | 71 | pub const callee_preserved_regs = [_]Register{ |
src/arch/wasm/CodeGen.zig-2| ... | @@ -2394,9 +2394,7 @@ fn lowerConstant(self: *Self, val: Value, ty: Type) InnerError!WValue { | ... | @@ -2394,9 +2394,7 @@ fn lowerConstant(self: *Self, val: Value, ty: Type) InnerError!WValue { |
| 2394 | const decl_index = decl_ref_mut.data.decl_index; | 2394 | const decl_index = decl_ref_mut.data.decl_index; |
| 2395 | return self.lowerDeclRefValue(.{ .ty = ty, .val = val }, decl_index); | 2395 | return self.lowerDeclRefValue(.{ .ty = ty, .val = val }, decl_index); |
| 2396 | } | 2396 | } |
| 2397 | |||
| 2398 | const target = self.target; | 2397 | const target = self.target; |
| 2399 | |||
| 2400 | switch (ty.zigTypeTag()) { | 2398 | switch (ty.zigTypeTag()) { |
| 2401 | .Void => return WValue{ .none = {} }, | 2399 | .Void => return WValue{ .none = {} }, |
| 2402 | .Int => { | 2400 | .Int => { |
src/arch/wasm/abi.zig+8| ... | @@ -23,6 +23,10 @@ pub fn classifyType(ty: Type, target: Target) [2]Class { | ... | @@ -23,6 +23,10 @@ pub fn classifyType(ty: Type, target: Target) [2]Class { |
| 23 | if (!ty.hasRuntimeBitsIgnoreComptime()) return none; | 23 | if (!ty.hasRuntimeBitsIgnoreComptime()) return none; |
| 24 | switch (ty.zigTypeTag()) { | 24 | switch (ty.zigTypeTag()) { |
| 25 | .Struct => { | 25 | .Struct => { |
| 26 | if (ty.containerLayout() == .Packed) { | ||
| 27 | if (ty.bitSize(target) <= 64) return direct; | ||
| 28 | return .{ .direct, .direct }; | ||
| 29 | } | ||
| 26 | // When the struct type is non-scalar | 30 | // When the struct type is non-scalar |
| 27 | if (ty.structFieldCount() > 1) return memory; | 31 | if (ty.structFieldCount() > 1) return memory; |
| 28 | // When the struct's alignment is non-natural | 32 | // When the struct's alignment is non-natural |
| ... | @@ -57,6 +61,10 @@ pub fn classifyType(ty: Type, target: Target) [2]Class { | ... | @@ -57,6 +61,10 @@ pub fn classifyType(ty: Type, target: Target) [2]Class { |
| 57 | return direct; | 61 | return direct; |
| 58 | }, | 62 | }, |
| 59 | .Union => { | 63 | .Union => { |
| 64 | if (ty.containerLayout() == .Packed) { | ||
| 65 | if (ty.bitSize(target) <= 64) return direct; | ||
| 66 | return .{ .direct, .direct }; | ||
| 67 | } | ||
| 60 | const layout = ty.unionGetLayout(target); | 68 | const layout = ty.unionGetLayout(target); |
| 61 | std.debug.assert(layout.tag_size == 0); | 69 | std.debug.assert(layout.tag_size == 0); |
| 62 | if (ty.unionFields().count() > 1) return memory; | 70 | if (ty.unionFields().count() > 1) return memory; |
src/arch/x86_64/abi.zig+22-2| ... | @@ -5,7 +5,7 @@ const assert = std.debug.assert; | ... | @@ -5,7 +5,7 @@ const assert = std.debug.assert; |
| 5 | const Register = @import("bits.zig").Register; | 5 | const Register = @import("bits.zig").Register; |
| 6 | const RegisterManagerFn = @import("../../register_manager.zig").RegisterManager; | 6 | const RegisterManagerFn = @import("../../register_manager.zig").RegisterManager; |
| 7 | 7 | ||
| 8 | pub const Class = enum { integer, sse, sseup, x87, x87up, complex_x87, memory, none }; | 8 | pub const Class = enum { integer, sse, sseup, x87, x87up, complex_x87, memory, none, win_i128 }; |
| 9 | 9 | ||
| 10 | pub fn classifyWindows(ty: Type, target: Target) Class { | 10 | pub fn classifyWindows(ty: Type, target: Target) Class { |
| 11 | // https://docs.microsoft.com/en-gb/cpp/build/x64-calling-convention?view=vs-2017 | 11 | // https://docs.microsoft.com/en-gb/cpp/build/x64-calling-convention?view=vs-2017 |
| ... | @@ -34,7 +34,15 @@ pub fn classifyWindows(ty: Type, target: Target) Class { | ... | @@ -34,7 +34,15 @@ pub fn classifyWindows(ty: Type, target: Target) Class { |
| 34 | => switch (ty.abiSize(target)) { | 34 | => switch (ty.abiSize(target)) { |
| 35 | 0 => unreachable, | 35 | 0 => unreachable, |
| 36 | 1, 2, 4, 8 => return .integer, | 36 | 1, 2, 4, 8 => return .integer, |
| 37 | else => return .memory, | 37 | else => switch (ty.zigTypeTag()) { |
| 38 | .Int => return .win_i128, | ||
| 39 | .Struct, .Union => if (ty.containerLayout() == .Packed) { | ||
| 40 | return .win_i128; | ||
| 41 | } else { | ||
| 42 | return .memory; | ||
| 43 | }, | ||
| 44 | else => return .memory, | ||
| 45 | }, | ||
| 38 | }, | 46 | }, |
| 39 | 47 | ||
| 40 | .Float, .Vector => return .sse, | 48 | .Float, .Vector => return .sse, |
| ... | @@ -174,6 +182,12 @@ pub fn classifySystemV(ty: Type, target: Target) [8]Class { | ... | @@ -174,6 +182,12 @@ pub fn classifySystemV(ty: Type, target: Target) [8]Class { |
| 174 | // "If the size of the aggregate exceeds a single eightbyte, each is classified | 182 | // "If the size of the aggregate exceeds a single eightbyte, each is classified |
| 175 | // separately.". | 183 | // separately.". |
| 176 | const ty_size = ty.abiSize(target); | 184 | const ty_size = ty.abiSize(target); |
| 185 | if (ty.containerLayout() == .Packed) { | ||
| 186 | assert(ty_size <= 128); | ||
| 187 | result[0] = .integer; | ||
| 188 | if (ty_size > 64) result[1] = .integer; | ||
| 189 | return result; | ||
| 190 | } | ||
| 177 | if (ty_size > 64) | 191 | if (ty_size > 64) |
| 178 | return memory_class; | 192 | return memory_class; |
| 179 | 193 | ||
| ... | @@ -284,6 +298,12 @@ pub fn classifySystemV(ty: Type, target: Target) [8]Class { | ... | @@ -284,6 +298,12 @@ pub fn classifySystemV(ty: Type, target: Target) [8]Class { |
| 284 | // "If the size of the aggregate exceeds a single eightbyte, each is classified | 298 | // "If the size of the aggregate exceeds a single eightbyte, each is classified |
| 285 | // separately.". | 299 | // separately.". |
| 286 | const ty_size = ty.abiSize(target); | 300 | const ty_size = ty.abiSize(target); |
| 301 | if (ty.containerLayout() == .Packed) { | ||
| 302 | assert(ty_size <= 128); | ||
| 303 | result[0] = .integer; | ||
| 304 | if (ty_size > 64) result[1] = .integer; | ||
| 305 | return result; | ||
| 306 | } | ||
| 287 | if (ty_size > 64) | 307 | if (ty_size > 64) |
| 288 | return memory_class; | 308 | return memory_class; |
| 289 | 309 |
src/autodoc/render_source.zig+15| ... | @@ -79,6 +79,16 @@ pub fn genHtml( | ... | @@ -79,6 +79,16 @@ pub fn genHtml( |
| 79 | \\ text-align: right; | 79 | \\ text-align: right; |
| 80 | \\ color: #999; | 80 | \\ color: #999; |
| 81 | \\ } | 81 | \\ } |
| 82 | \\ | ||
| 83 | \\ .line { | ||
| 84 | \\ width: 100%; | ||
| 85 | \\ display: inline-block; | ||
| 86 | \\ } | ||
| 87 | \\ .line:target { | ||
| 88 | \\ border-top: 1px solid #ccc; | ||
| 89 | \\ border-bottom: 1px solid #ccc; | ||
| 90 | \\ background: #fafafa; | ||
| 91 | \\ } | ||
| 82 | \\ | 92 | \\ |
| 83 | \\ @media (prefers-color-scheme: dark) { | 93 | \\ @media (prefers-color-scheme: dark) { |
| 84 | \\ body{ | 94 | \\ body{ |
| ... | @@ -90,6 +100,11 @@ pub fn genHtml( | ... | @@ -90,6 +100,11 @@ pub fn genHtml( |
| 90 | \\ background: #222; | 100 | \\ background: #222; |
| 91 | \\ border: unset; | 101 | \\ border: unset; |
| 92 | \\ } | 102 | \\ } |
| 103 | \\ .line:target { | ||
| 104 | \\ border-top: 1px solid #444; | ||
| 105 | \\ border-bottom: 1px solid #444; | ||
| 106 | \\ background: #333; | ||
| 107 | \\ } | ||
| 93 | \\ .tok-kw { | 108 | \\ .tok-kw { |
| 94 | \\ color: #eee; | 109 | \\ color: #eee; |
| 95 | \\ } | 110 | \\ } |
src/codegen/llvm.zig+140-52| ... | @@ -23,6 +23,7 @@ const LazySrcLoc = Module.LazySrcLoc; | ... | @@ -23,6 +23,7 @@ const LazySrcLoc = Module.LazySrcLoc; |
| 23 | const CType = @import("../type.zig").CType; | 23 | const CType = @import("../type.zig").CType; |
| 24 | const x86_64_abi = @import("../arch/x86_64/abi.zig"); | 24 | const x86_64_abi = @import("../arch/x86_64/abi.zig"); |
| 25 | const wasm_c_abi = @import("../arch/wasm/abi.zig"); | 25 | const wasm_c_abi = @import("../arch/wasm/abi.zig"); |
| 26 | const aarch64_c_abi = @import("../arch/aarch64/abi.zig"); | ||
| 26 | 27 | ||
| 27 | const Error = error{ OutOfMemory, CodegenFail }; | 28 | const Error = error{ OutOfMemory, CodegenFail }; |
| 28 | 29 | ||
| ... | @@ -314,6 +315,15 @@ pub fn supportsTailCall(target: std.Target) bool { | ... | @@ -314,6 +315,15 @@ pub fn supportsTailCall(target: std.Target) bool { |
| 314 | } | 315 | } |
| 315 | } | 316 | } |
| 316 | 317 | ||
| 318 | /// TODO can this be done with simpler logic / different API binding? | ||
| 319 | fn deleteLlvmGlobal(llvm_global: *const llvm.Value) void { | ||
| 320 | if (llvm_global.globalGetValueType().getTypeKind() == .Function) { | ||
| 321 | llvm_global.deleteFunction(); | ||
| 322 | return; | ||
| 323 | } | ||
| 324 | return llvm_global.deleteGlobal(); | ||
| 325 | } | ||
| 326 | |||
| 317 | pub const Object = struct { | 327 | pub const Object = struct { |
| 318 | gpa: Allocator, | 328 | gpa: Allocator, |
| 319 | module: *Module, | 329 | module: *Module, |
| ... | @@ -667,7 +677,7 @@ pub const Object = struct { | ... | @@ -667,7 +677,7 @@ pub const Object = struct { |
| 667 | 677 | ||
| 668 | const new_global_ptr = other_global.constBitCast(llvm_global.typeOf()); | 678 | const new_global_ptr = other_global.constBitCast(llvm_global.typeOf()); |
| 669 | llvm_global.replaceAllUsesWith(new_global_ptr); | 679 | llvm_global.replaceAllUsesWith(new_global_ptr); |
| 670 | object.deleteLlvmGlobal(llvm_global); | 680 | deleteLlvmGlobal(llvm_global); |
| 671 | entry.value_ptr.* = new_global_ptr; | 681 | entry.value_ptr.* = new_global_ptr; |
| 672 | } | 682 | } |
| 673 | object.extern_collisions.clearRetainingCapacity(); | 683 | object.extern_collisions.clearRetainingCapacity(); |
| ... | @@ -693,7 +703,7 @@ pub const Object = struct { | ... | @@ -693,7 +703,7 @@ pub const Object = struct { |
| 693 | const new_global_ptr = llvm_global.constBitCast(other_global.typeOf()); | 703 | const new_global_ptr = llvm_global.constBitCast(other_global.typeOf()); |
| 694 | other_global.replaceAllUsesWith(new_global_ptr); | 704 | other_global.replaceAllUsesWith(new_global_ptr); |
| 695 | llvm_global.takeName(other_global); | 705 | llvm_global.takeName(other_global); |
| 696 | other_global.deleteGlobal(); | 706 | deleteLlvmGlobal(other_global); |
| 697 | // Problem: now we need to replace in the decl_map that | 707 | // Problem: now we need to replace in the decl_map that |
| 698 | // the extern decl index points to this new global. However we don't | 708 | // the extern decl index points to this new global. However we don't |
| 699 | // know the decl index. | 709 | // know the decl index. |
| ... | @@ -1084,6 +1094,26 @@ pub const Object = struct { | ... | @@ -1084,6 +1094,26 @@ pub const Object = struct { |
| 1084 | try args.ensureUnusedCapacity(1); | 1094 | try args.ensureUnusedCapacity(1); |
| 1085 | args.appendAssumeCapacity(casted); | 1095 | args.appendAssumeCapacity(casted); |
| 1086 | }, | 1096 | }, |
| 1097 | .float_array => { | ||
| 1098 | const param_ty = fn_info.param_types[it.zig_index - 1]; | ||
| 1099 | const param_llvm_ty = try dg.lowerType(param_ty); | ||
| 1100 | const param = llvm_func.getParam(llvm_arg_i); | ||
| 1101 | llvm_arg_i += 1; | ||
| 1102 | |||
| 1103 | const alignment = param_ty.abiAlignment(target); | ||
| 1104 | const arg_ptr = buildAllocaInner(builder, llvm_func, false, param_llvm_ty); | ||
| 1105 | arg_ptr.setAlignment(alignment); | ||
| 1106 | const casted_ptr = builder.buildBitCast(arg_ptr, param.typeOf().pointerType(0), ""); | ||
| 1107 | _ = builder.buildStore(param, casted_ptr); | ||
| 1108 | |||
| 1109 | if (isByRef(param_ty)) { | ||
| 1110 | try args.append(arg_ptr); | ||
| 1111 | } else { | ||
| 1112 | const load_inst = builder.buildLoad(param_llvm_ty, arg_ptr, ""); | ||
| 1113 | load_inst.setAlignment(alignment); | ||
| 1114 | try args.append(load_inst); | ||
| 1115 | } | ||
| 1116 | }, | ||
| 1087 | }; | 1117 | }; |
| 1088 | } | 1118 | } |
| 1089 | 1119 | ||
| ... | @@ -1191,15 +1221,6 @@ pub const Object = struct { | ... | @@ -1191,15 +1221,6 @@ pub const Object = struct { |
| 1191 | return null; | 1221 | return null; |
| 1192 | } | 1222 | } |
| 1193 | 1223 | ||
| 1194 | /// TODO can this be done with simpler logic / different API binding? | ||
| 1195 | fn deleteLlvmGlobal(o: Object, llvm_global: *const llvm.Value) void { | ||
| 1196 | if (o.llvm_module.getNamedFunction(llvm_global.getValueName()) != null) { | ||
| 1197 | llvm_global.deleteFunction(); | ||
| 1198 | return; | ||
| 1199 | } | ||
| 1200 | return llvm_global.deleteGlobal(); | ||
| 1201 | } | ||
| 1202 | |||
| 1203 | pub fn updateDeclExports( | 1224 | pub fn updateDeclExports( |
| 1204 | self: *Object, | 1225 | self: *Object, |
| 1205 | module: *Module, | 1226 | module: *Module, |
| ... | @@ -1294,7 +1315,7 @@ pub const Object = struct { | ... | @@ -1294,7 +1315,7 @@ pub const Object = struct { |
| 1294 | alias.setAliasee(llvm_global); | 1315 | alias.setAliasee(llvm_global); |
| 1295 | } else { | 1316 | } else { |
| 1296 | _ = self.llvm_module.addAlias( | 1317 | _ = self.llvm_module.addAlias( |
| 1297 | llvm_global.typeOf(), | 1318 | llvm_global.globalGetValueType(), |
| 1298 | 0, | 1319 | 0, |
| 1299 | llvm_global, | 1320 | llvm_global, |
| 1300 | exp_name_z, | 1321 | exp_name_z, |
| ... | @@ -2527,6 +2548,7 @@ pub const DeclGen = struct { | ... | @@ -2527,6 +2548,7 @@ pub const DeclGen = struct { |
| 2527 | .multiple_llvm_ints, | 2548 | .multiple_llvm_ints, |
| 2528 | .multiple_llvm_float, | 2549 | .multiple_llvm_float, |
| 2529 | .as_u16, | 2550 | .as_u16, |
| 2551 | .float_array, | ||
| 2530 | => continue, | 2552 | => continue, |
| 2531 | 2553 | ||
| 2532 | .slice => unreachable, // extern functions do not support slice types. | 2554 | .slice => unreachable, // extern functions do not support slice types. |
| ... | @@ -3093,6 +3115,13 @@ pub const DeclGen = struct { | ... | @@ -3093,6 +3115,13 @@ pub const DeclGen = struct { |
| 3093 | .as_u16 => { | 3115 | .as_u16 => { |
| 3094 | try llvm_params.append(dg.context.intType(16)); | 3116 | try llvm_params.append(dg.context.intType(16)); |
| 3095 | }, | 3117 | }, |
| 3118 | .float_array => { | ||
| 3119 | const param_ty = fn_info.param_types[it.zig_index - 1]; | ||
| 3120 | const float_ty = try dg.lowerType(param_ty.structFieldType(0)); | ||
| 3121 | const field_count = @intCast(c_uint, param_ty.structFieldCount()); | ||
| 3122 | const arr_ty = float_ty.arrayType(field_count); | ||
| 3123 | try llvm_params.append(arr_ty); | ||
| 3124 | }, | ||
| 3096 | }; | 3125 | }; |
| 3097 | 3126 | ||
| 3098 | return llvm.functionType( | 3127 | return llvm.functionType( |
| ... | @@ -4719,6 +4748,27 @@ pub const FuncGen = struct { | ... | @@ -4719,6 +4748,27 @@ pub const FuncGen = struct { |
| 4719 | const casted = self.builder.buildBitCast(llvm_arg, self.dg.context.intType(16), ""); | 4748 | const casted = self.builder.buildBitCast(llvm_arg, self.dg.context.intType(16), ""); |
| 4720 | try llvm_args.append(casted); | 4749 | try llvm_args.append(casted); |
| 4721 | }, | 4750 | }, |
| 4751 | .float_array => { | ||
| 4752 | const arg = args[it.zig_index - 1]; | ||
| 4753 | const arg_ty = self.air.typeOf(arg); | ||
| 4754 | var llvm_arg = try self.resolveInst(arg); | ||
| 4755 | if (!isByRef(arg_ty)) { | ||
| 4756 | const p = self.buildAlloca(llvm_arg.typeOf()); | ||
| 4757 | const store_inst = self.builder.buildStore(llvm_arg, p); | ||
| 4758 | store_inst.setAlignment(arg_ty.abiAlignment(target)); | ||
| 4759 | llvm_arg = store_inst; | ||
| 4760 | } | ||
| 4761 | |||
| 4762 | const float_ty = try self.dg.lowerType(arg_ty.structFieldType(0)); | ||
| 4763 | const field_count = @intCast(u32, arg_ty.structFieldCount()); | ||
| 4764 | const array_llvm_ty = float_ty.arrayType(field_count); | ||
| 4765 | |||
| 4766 | const casted = self.builder.buildBitCast(llvm_arg, array_llvm_ty.pointerType(0), ""); | ||
| 4767 | const alignment = arg_ty.abiAlignment(target); | ||
| 4768 | const load_inst = self.builder.buildLoad(array_llvm_ty, casted, ""); | ||
| 4769 | load_inst.setAlignment(alignment); | ||
| 4770 | try llvm_args.append(load_inst); | ||
| 4771 | }, | ||
| 4722 | }; | 4772 | }; |
| 4723 | 4773 | ||
| 4724 | const call = self.builder.buildCall( | 4774 | const call = self.builder.buildCall( |
| ... | @@ -9240,7 +9290,7 @@ pub const FuncGen = struct { | ... | @@ -9240,7 +9290,7 @@ pub const FuncGen = struct { |
| 9240 | } | 9290 | } |
| 9241 | }, | 9291 | }, |
| 9242 | }, | 9292 | }, |
| 9243 | .Union => return self.unionFieldPtr(inst, struct_ptr, struct_ty, field_index), | 9293 | .Union => return self.unionFieldPtr(inst, struct_ptr, struct_ty), |
| 9244 | else => unreachable, | 9294 | else => unreachable, |
| 9245 | } | 9295 | } |
| 9246 | } | 9296 | } |
| ... | @@ -9250,19 +9300,16 @@ pub const FuncGen = struct { | ... | @@ -9250,19 +9300,16 @@ pub const FuncGen = struct { |
| 9250 | inst: Air.Inst.Index, | 9300 | inst: Air.Inst.Index, |
| 9251 | union_ptr: *const llvm.Value, | 9301 | union_ptr: *const llvm.Value, |
| 9252 | union_ty: Type, | 9302 | union_ty: Type, |
| 9253 | field_index: c_uint, | ||
| 9254 | ) !?*const llvm.Value { | 9303 | ) !?*const llvm.Value { |
| 9255 | const union_obj = union_ty.cast(Type.Payload.Union).?.data; | ||
| 9256 | const field = &union_obj.fields.values()[field_index]; | ||
| 9257 | if (!field.ty.hasRuntimeBitsIgnoreComptime()) { | ||
| 9258 | return null; | ||
| 9259 | } | ||
| 9260 | const target = self.dg.module.getTarget(); | 9304 | const target = self.dg.module.getTarget(); |
| 9261 | const layout = union_ty.unionGetLayout(target); | 9305 | const layout = union_ty.unionGetLayout(target); |
| 9306 | const result_llvm_ty = try self.dg.lowerType(self.air.typeOfIndex(inst)); | ||
| 9307 | if (layout.payload_size == 0) { | ||
| 9308 | return self.builder.buildBitCast(union_ptr, result_llvm_ty, ""); | ||
| 9309 | } | ||
| 9262 | const payload_index = @boolToInt(layout.tag_align >= layout.payload_align); | 9310 | const payload_index = @boolToInt(layout.tag_align >= layout.payload_align); |
| 9263 | const union_llvm_ty = try self.dg.lowerType(union_ty); | 9311 | const union_llvm_ty = try self.dg.lowerType(union_ty); |
| 9264 | const union_field_ptr = self.builder.buildStructGEP(union_llvm_ty, union_ptr, payload_index, ""); | 9312 | const union_field_ptr = self.builder.buildStructGEP(union_llvm_ty, union_ptr, payload_index, ""); |
| 9265 | const result_llvm_ty = try self.dg.lowerType(self.air.typeOfIndex(inst)); | ||
| 9266 | return self.builder.buildBitCast(union_field_ptr, result_llvm_ty, ""); | 9313 | return self.builder.buildBitCast(union_field_ptr, result_llvm_ty, ""); |
| 9267 | } | 9314 | } |
| 9268 | 9315 | ||
| ... | @@ -9832,6 +9879,7 @@ fn firstParamSRet(fn_info: Type.Payload.Function.Data, target: std.Target) bool | ... | @@ -9832,6 +9879,7 @@ fn firstParamSRet(fn_info: Type.Payload.Function.Data, target: std.Target) bool |
| 9832 | else => return x86_64_abi.classifySystemV(fn_info.return_type, target)[0] == .memory, | 9879 | else => return x86_64_abi.classifySystemV(fn_info.return_type, target)[0] == .memory, |
| 9833 | }, | 9880 | }, |
| 9834 | .wasm32 => return wasm_c_abi.classifyType(fn_info.return_type, target)[0] == .indirect, | 9881 | .wasm32 => return wasm_c_abi.classifyType(fn_info.return_type, target)[0] == .indirect, |
| 9882 | .aarch64, .aarch64_be => return aarch64_c_abi.classifyType(fn_info.return_type, target)[0] == .memory, | ||
| 9835 | else => return false, // TODO investigate C ABI for other architectures | 9883 | else => return false, // TODO investigate C ABI for other architectures |
| 9836 | }, | 9884 | }, |
| 9837 | else => return false, | 9885 | else => return false, |
| ... | @@ -9862,22 +9910,7 @@ fn lowerFnRetTy(dg: *DeclGen, fn_info: Type.Payload.Function.Data) !*const llvm. | ... | @@ -9862,22 +9910,7 @@ fn lowerFnRetTy(dg: *DeclGen, fn_info: Type.Payload.Function.Data) !*const llvm. |
| 9862 | } | 9910 | } |
| 9863 | }, | 9911 | }, |
| 9864 | .C => { | 9912 | .C => { |
| 9865 | const is_scalar = switch (fn_info.return_type.zigTypeTag()) { | 9913 | const is_scalar = isScalar(fn_info.return_type); |
| 9866 | .Void, | ||
| 9867 | .Bool, | ||
| 9868 | .NoReturn, | ||
| 9869 | .Int, | ||
| 9870 | .Float, | ||
| 9871 | .Pointer, | ||
| 9872 | .Optional, | ||
| 9873 | .ErrorSet, | ||
| 9874 | .Enum, | ||
| 9875 | .AnyFrame, | ||
| 9876 | .Vector, | ||
| 9877 | => true, | ||
| 9878 | |||
| 9879 | else => false, | ||
| 9880 | }; | ||
| 9881 | switch (target.cpu.arch) { | 9914 | switch (target.cpu.arch) { |
| 9882 | .mips, .mipsel => return dg.lowerType(fn_info.return_type), | 9915 | .mips, .mipsel => return dg.lowerType(fn_info.return_type), |
| 9883 | .x86_64 => switch (target.os.tag) { | 9916 | .x86_64 => switch (target.os.tag) { |
| ... | @@ -9890,6 +9923,7 @@ fn lowerFnRetTy(dg: *DeclGen, fn_info: Type.Payload.Function.Data) !*const llvm. | ... | @@ -9890,6 +9923,7 @@ fn lowerFnRetTy(dg: *DeclGen, fn_info: Type.Payload.Function.Data) !*const llvm. |
| 9890 | return dg.context.intType(@intCast(c_uint, abi_size * 8)); | 9923 | return dg.context.intType(@intCast(c_uint, abi_size * 8)); |
| 9891 | } | 9924 | } |
| 9892 | }, | 9925 | }, |
| 9926 | .win_i128 => return dg.context.intType(64).vectorType(2), | ||
| 9893 | .memory => return dg.context.voidType(), | 9927 | .memory => return dg.context.voidType(), |
| 9894 | .sse => return dg.lowerType(fn_info.return_type), | 9928 | .sse => return dg.lowerType(fn_info.return_type), |
| 9895 | else => unreachable, | 9929 | else => unreachable, |
| ... | @@ -9930,6 +9964,7 @@ fn lowerFnRetTy(dg: *DeclGen, fn_info: Type.Payload.Function.Data) !*const llvm. | ... | @@ -9930,6 +9964,7 @@ fn lowerFnRetTy(dg: *DeclGen, fn_info: Type.Payload.Function.Data) !*const llvm. |
| 9930 | @panic("TODO"); | 9964 | @panic("TODO"); |
| 9931 | }, | 9965 | }, |
| 9932 | .memory => unreachable, // handled above | 9966 | .memory => unreachable, // handled above |
| 9967 | .win_i128 => unreachable, // windows only | ||
| 9933 | .none => break, | 9968 | .none => break, |
| 9934 | } | 9969 | } |
| 9935 | } | 9970 | } |
| ... | @@ -9954,6 +9989,24 @@ fn lowerFnRetTy(dg: *DeclGen, fn_info: Type.Payload.Function.Data) !*const llvm. | ... | @@ -9954,6 +9989,24 @@ fn lowerFnRetTy(dg: *DeclGen, fn_info: Type.Payload.Function.Data) !*const llvm. |
| 9954 | const abi_size = scalar_type.abiSize(target); | 9989 | const abi_size = scalar_type.abiSize(target); |
| 9955 | return dg.context.intType(@intCast(c_uint, abi_size * 8)); | 9990 | return dg.context.intType(@intCast(c_uint, abi_size * 8)); |
| 9956 | }, | 9991 | }, |
| 9992 | .aarch64, .aarch64_be => { | ||
| 9993 | if (is_scalar) { | ||
| 9994 | return dg.lowerType(fn_info.return_type); | ||
| 9995 | } | ||
| 9996 | const classes = aarch64_c_abi.classifyType(fn_info.return_type, target); | ||
| 9997 | if (classes[0] == .memory or classes[0] == .none) { | ||
| 9998 | return dg.context.voidType(); | ||
| 9999 | } | ||
| 10000 | if (classes[0] == .float_array) { | ||
| 10001 | return dg.lowerType(fn_info.return_type); | ||
| 10002 | } | ||
| 10003 | if (classes[1] == .none) { | ||
| 10004 | const bit_size = fn_info.return_type.bitSize(target); | ||
| 10005 | return dg.context.intType(@intCast(c_uint, bit_size)); | ||
| 10006 | } | ||
| 10007 | |||
| 10008 | return dg.context.intType(64).arrayType(2); | ||
| 10009 | }, | ||
| 9957 | // TODO investigate C ABI for other architectures | 10010 | // TODO investigate C ABI for other architectures |
| 9958 | else => return dg.lowerType(fn_info.return_type), | 10011 | else => return dg.lowerType(fn_info.return_type), |
| 9959 | } | 10012 | } |
| ... | @@ -9981,6 +10034,7 @@ const ParamTypeIterator = struct { | ... | @@ -9981,6 +10034,7 @@ const ParamTypeIterator = struct { |
| 9981 | multiple_llvm_float, | 10034 | multiple_llvm_float, |
| 9982 | slice, | 10035 | slice, |
| 9983 | as_u16, | 10036 | as_u16, |
| 10037 | float_array, | ||
| 9984 | }; | 10038 | }; |
| 9985 | 10039 | ||
| 9986 | pub fn next(it: *ParamTypeIterator) ?Lowering { | 10040 | pub fn next(it: *ParamTypeIterator) ?Lowering { |
| ... | @@ -10025,22 +10079,7 @@ const ParamTypeIterator = struct { | ... | @@ -10025,22 +10079,7 @@ const ParamTypeIterator = struct { |
| 10025 | @panic("TODO implement async function lowering in the LLVM backend"); | 10079 | @panic("TODO implement async function lowering in the LLVM backend"); |
| 10026 | }, | 10080 | }, |
| 10027 | .C => { | 10081 | .C => { |
| 10028 | const is_scalar = switch (ty.zigTypeTag()) { | 10082 | const is_scalar = isScalar(ty); |
| 10029 | .Void, | ||
| 10030 | .Bool, | ||
| 10031 | .NoReturn, | ||
| 10032 | .Int, | ||
| 10033 | .Float, | ||
| 10034 | .Pointer, | ||
| 10035 | .Optional, | ||
| 10036 | .ErrorSet, | ||
| 10037 | .Enum, | ||
| 10038 | .AnyFrame, | ||
| 10039 | .Vector, | ||
| 10040 | => true, | ||
| 10041 | |||
| 10042 | else => false, | ||
| 10043 | }; | ||
| 10044 | switch (it.target.cpu.arch) { | 10083 | switch (it.target.cpu.arch) { |
| 10045 | .riscv32, .riscv64 => { | 10084 | .riscv32, .riscv64 => { |
| 10046 | it.zig_index += 1; | 10085 | it.zig_index += 1; |
| ... | @@ -10069,6 +10108,11 @@ const ParamTypeIterator = struct { | ... | @@ -10069,6 +10108,11 @@ const ParamTypeIterator = struct { |
| 10069 | return .abi_sized_int; | 10108 | return .abi_sized_int; |
| 10070 | } | 10109 | } |
| 10071 | }, | 10110 | }, |
| 10111 | .win_i128 => { | ||
| 10112 | it.zig_index += 1; | ||
| 10113 | it.llvm_index += 1; | ||
| 10114 | return .byref; | ||
| 10115 | }, | ||
| 10072 | .memory => { | 10116 | .memory => { |
| 10073 | it.zig_index += 1; | 10117 | it.zig_index += 1; |
| 10074 | it.llvm_index += 1; | 10118 | it.llvm_index += 1; |
| ... | @@ -10123,6 +10167,7 @@ const ParamTypeIterator = struct { | ... | @@ -10123,6 +10167,7 @@ const ParamTypeIterator = struct { |
| 10123 | @panic("TODO"); | 10167 | @panic("TODO"); |
| 10124 | }, | 10168 | }, |
| 10125 | .memory => unreachable, // handled above | 10169 | .memory => unreachable, // handled above |
| 10170 | .win_i128 => unreachable, // windows only | ||
| 10126 | .none => break, | 10171 | .none => break, |
| 10127 | } | 10172 | } |
| 10128 | } | 10173 | } |
| ... | @@ -10155,6 +10200,28 @@ const ParamTypeIterator = struct { | ... | @@ -10155,6 +10200,28 @@ const ParamTypeIterator = struct { |
| 10155 | } | 10200 | } |
| 10156 | return .abi_sized_int; | 10201 | return .abi_sized_int; |
| 10157 | }, | 10202 | }, |
| 10203 | .aarch64, .aarch64_be => { | ||
| 10204 | it.zig_index += 1; | ||
| 10205 | it.llvm_index += 1; | ||
| 10206 | if (is_scalar) { | ||
| 10207 | return .byval; | ||
| 10208 | } | ||
| 10209 | const classes = aarch64_c_abi.classifyType(ty, it.target); | ||
| 10210 | if (classes[0] == .memory) { | ||
| 10211 | return .byref; | ||
| 10212 | } | ||
| 10213 | if (classes[0] == .float_array) { | ||
| 10214 | return .float_array; | ||
| 10215 | } | ||
| 10216 | if (classes[1] == .none) { | ||
| 10217 | it.llvm_types_len = 1; | ||
| 10218 | } else { | ||
| 10219 | it.llvm_types_len = 2; | ||
| 10220 | } | ||
| 10221 | it.llvm_types_buffer[0] = 64; | ||
| 10222 | it.llvm_types_buffer[1] = 64; | ||
| 10223 | return .multiple_llvm_ints; | ||
| 10224 | }, | ||
| 10158 | // TODO investigate C ABI for other architectures | 10225 | // TODO investigate C ABI for other architectures |
| 10159 | else => { | 10226 | else => { |
| 10160 | it.zig_index += 1; | 10227 | it.zig_index += 1; |
| ... | @@ -10294,6 +10361,27 @@ fn isByRef(ty: Type) bool { | ... | @@ -10294,6 +10361,27 @@ fn isByRef(ty: Type) bool { |
| 10294 | } | 10361 | } |
| 10295 | } | 10362 | } |
| 10296 | 10363 | ||
| 10364 | fn isScalar(ty: Type) bool { | ||
| 10365 | return switch (ty.zigTypeTag()) { | ||
| 10366 | .Void, | ||
| 10367 | .Bool, | ||
| 10368 | .NoReturn, | ||
| 10369 | .Int, | ||
| 10370 | .Float, | ||
| 10371 | .Pointer, | ||
| 10372 | .Optional, | ||
| 10373 | .ErrorSet, | ||
| 10374 | .Enum, | ||
| 10375 | .AnyFrame, | ||
| 10376 | .Vector, | ||
| 10377 | => true, | ||
| 10378 | |||
| 10379 | .Struct => ty.containerLayout() == .Packed, | ||
| 10380 | .Union => ty.containerLayout() == .Packed, | ||
| 10381 | else => false, | ||
| 10382 | }; | ||
| 10383 | } | ||
| 10384 | |||
| 10297 | /// This function returns true if we expect LLVM to lower x86_fp80 correctly | 10385 | /// This function returns true if we expect LLVM to lower x86_fp80 correctly |
| 10298 | /// and false if we expect LLVM to crash if it counters an x86_fp80 type. | 10386 | /// and false if we expect LLVM to crash if it counters an x86_fp80 type. |
| 10299 | fn backendSupportsF80(target: std.Target) bool { | 10387 | fn backendSupportsF80(target: std.Target) bool { |
src/link/Coff.zig+142-6| ... | @@ -50,6 +50,7 @@ text_section_index: ?u16 = null, | ... | @@ -50,6 +50,7 @@ text_section_index: ?u16 = null, |
| 50 | got_section_index: ?u16 = null, | 50 | got_section_index: ?u16 = null, |
| 51 | rdata_section_index: ?u16 = null, | 51 | rdata_section_index: ?u16 = null, |
| 52 | data_section_index: ?u16 = null, | 52 | data_section_index: ?u16 = null, |
| 53 | reloc_section_index: ?u16 = null, | ||
| 53 | 54 | ||
| 54 | locals: std.ArrayListUnmanaged(coff.Symbol) = .{}, | 55 | locals: std.ArrayListUnmanaged(coff.Symbol) = .{}, |
| 55 | globals: std.StringArrayHashMapUnmanaged(SymbolWithLoc) = .{}, | 56 | globals: std.StringArrayHashMapUnmanaged(SymbolWithLoc) = .{}, |
| ... | @@ -98,11 +99,16 @@ atom_by_index_table: std.AutoHashMapUnmanaged(u32, *Atom) = .{}, | ... | @@ -98,11 +99,16 @@ atom_by_index_table: std.AutoHashMapUnmanaged(u32, *Atom) = .{}, |
| 98 | /// with `Decl` `main`, and lives as long as that `Decl`. | 99 | /// with `Decl` `main`, and lives as long as that `Decl`. |
| 99 | unnamed_const_atoms: UnnamedConstTable = .{}, | 100 | unnamed_const_atoms: UnnamedConstTable = .{}, |
| 100 | 101 | ||
| 101 | /// A table of relocations indexed by the owning them `TextBlock`. | 102 | /// A table of relocations indexed by the owning them `Atom`. |
| 102 | /// Note that once we refactor `TextBlock`'s lifetime and ownership rules, | 103 | /// Note that once we refactor `Atom`'s lifetime and ownership rules, |
| 103 | /// this will be a table indexed by index into the list of Atoms. | 104 | /// this will be a table indexed by index into the list of Atoms. |
| 104 | relocs: RelocTable = .{}, | 105 | relocs: RelocTable = .{}, |
| 105 | 106 | ||
| 107 | /// A table of base relocations indexed by the owning them `Atom`. | ||
| 108 | /// Note that once we refactor `Atom`'s lifetime and ownership rules, | ||
| 109 | /// this will be a table indexed by index into the list of Atoms. | ||
| 110 | base_relocs: BaseRelocationTable = .{}, | ||
| 111 | |||
| 106 | pub const Reloc = struct { | 112 | pub const Reloc = struct { |
| 107 | @"type": enum { | 113 | @"type": enum { |
| 108 | got, | 114 | got, |
| ... | @@ -117,6 +123,7 @@ pub const Reloc = struct { | ... | @@ -117,6 +123,7 @@ pub const Reloc = struct { |
| 117 | }; | 123 | }; |
| 118 | 124 | ||
| 119 | const RelocTable = std.AutoHashMapUnmanaged(*Atom, std.ArrayListUnmanaged(Reloc)); | 125 | const RelocTable = std.AutoHashMapUnmanaged(*Atom, std.ArrayListUnmanaged(Reloc)); |
| 126 | const BaseRelocationTable = std.AutoHashMapUnmanaged(*Atom, std.ArrayListUnmanaged(u32)); | ||
| 120 | const UnnamedConstTable = std.AutoHashMapUnmanaged(Module.Decl.Index, std.ArrayListUnmanaged(*Atom)); | 127 | const UnnamedConstTable = std.AutoHashMapUnmanaged(Module.Decl.Index, std.ArrayListUnmanaged(*Atom)); |
| 121 | 128 | ||
| 122 | const default_file_alignment: u16 = 0x200; | 129 | const default_file_alignment: u16 = 0x200; |
| ... | @@ -150,7 +157,17 @@ const Section = struct { | ... | @@ -150,7 +157,17 @@ const Section = struct { |
| 150 | free_list: std.ArrayListUnmanaged(*Atom) = .{}, | 157 | free_list: std.ArrayListUnmanaged(*Atom) = .{}, |
| 151 | }; | 158 | }; |
| 152 | 159 | ||
| 153 | pub const PtrWidth = enum { p32, p64 }; | 160 | pub const PtrWidth = enum { |
| 161 | p32, | ||
| 162 | p64, | ||
| 163 | |||
| 164 | fn abiSize(pw: PtrWidth) u4 { | ||
| 165 | return switch (pw) { | ||
| 166 | .p32 => 4, | ||
| 167 | .p64 => 8, | ||
| 168 | }; | ||
| 169 | } | ||
| 170 | }; | ||
| 154 | pub const SrcFn = void; | 171 | pub const SrcFn = void; |
| 155 | 172 | ||
| 156 | pub const Export = struct { | 173 | pub const Export = struct { |
| ... | @@ -274,6 +291,14 @@ pub fn deinit(self: *Coff) void { | ... | @@ -274,6 +291,14 @@ pub fn deinit(self: *Coff) void { |
| 274 | } | 291 | } |
| 275 | self.relocs.deinit(gpa); | 292 | self.relocs.deinit(gpa); |
| 276 | } | 293 | } |
| 294 | |||
| 295 | { | ||
| 296 | var it = self.base_relocs.valueIterator(); | ||
| 297 | while (it.next()) |relocs| { | ||
| 298 | relocs.deinit(gpa); | ||
| 299 | } | ||
| 300 | self.base_relocs.deinit(gpa); | ||
| 301 | } | ||
| 277 | } | 302 | } |
| 278 | 303 | ||
| 279 | fn populateMissingMetadata(self: *Coff) !void { | 304 | fn populateMissingMetadata(self: *Coff) !void { |
| ... | @@ -307,7 +332,7 @@ fn populateMissingMetadata(self: *Coff) !void { | ... | @@ -307,7 +332,7 @@ fn populateMissingMetadata(self: *Coff) !void { |
| 307 | 332 | ||
| 308 | if (self.got_section_index == null) { | 333 | if (self.got_section_index == null) { |
| 309 | self.got_section_index = @intCast(u16, self.sections.slice().len); | 334 | self.got_section_index = @intCast(u16, self.sections.slice().len); |
| 310 | const file_size = @intCast(u32, self.base.options.symbol_count_hint); | 335 | const file_size = @intCast(u32, self.base.options.symbol_count_hint) * self.ptr_width.abiSize(); |
| 311 | const off = self.findFreeSpace(file_size, self.page_size); | 336 | const off = self.findFreeSpace(file_size, self.page_size); |
| 312 | log.debug("found .got free space 0x{x} to 0x{x}", .{ off, off + file_size }); | 337 | log.debug("found .got free space 0x{x} to 0x{x}", .{ off, off + file_size }); |
| 313 | var header = coff.SectionHeader{ | 338 | var header = coff.SectionHeader{ |
| ... | @@ -378,6 +403,31 @@ fn populateMissingMetadata(self: *Coff) !void { | ... | @@ -378,6 +403,31 @@ fn populateMissingMetadata(self: *Coff) !void { |
| 378 | try self.sections.append(gpa, .{ .header = header }); | 403 | try self.sections.append(gpa, .{ .header = header }); |
| 379 | } | 404 | } |
| 380 | 405 | ||
| 406 | if (self.reloc_section_index == null) { | ||
| 407 | self.reloc_section_index = @intCast(u16, self.sections.slice().len); | ||
| 408 | const file_size = @intCast(u32, self.base.options.symbol_count_hint) * @sizeOf(coff.BaseRelocation); | ||
| 409 | const off = self.findFreeSpace(file_size, self.page_size); | ||
| 410 | log.debug("found .reloc free space 0x{x} to 0x{x}", .{ off, off + file_size }); | ||
| 411 | var header = coff.SectionHeader{ | ||
| 412 | .name = undefined, | ||
| 413 | .virtual_size = file_size, | ||
| 414 | .virtual_address = off, | ||
| 415 | .size_of_raw_data = file_size, | ||
| 416 | .pointer_to_raw_data = off, | ||
| 417 | .pointer_to_relocations = 0, | ||
| 418 | .pointer_to_linenumbers = 0, | ||
| 419 | .number_of_relocations = 0, | ||
| 420 | .number_of_linenumbers = 0, | ||
| 421 | .flags = .{ | ||
| 422 | .CNT_INITIALIZED_DATA = 1, | ||
| 423 | .MEM_PURGEABLE = 1, | ||
| 424 | .MEM_READ = 1, | ||
| 425 | }, | ||
| 426 | }; | ||
| 427 | try self.setSectionName(&header, ".reloc"); | ||
| 428 | try self.sections.append(gpa, .{ .header = header }); | ||
| 429 | } | ||
| 430 | |||
| 381 | if (self.strtab_offset == null) { | 431 | if (self.strtab_offset == null) { |
| 382 | try self.strtab.buffer.append(gpa, 0); | 432 | try self.strtab.buffer.append(gpa, 0); |
| 383 | self.strtab_offset = self.findFreeSpace(@intCast(u32, self.strtab.len()), 1); | 433 | self.strtab_offset = self.findFreeSpace(@intCast(u32, self.strtab.len()), 1); |
| ... | @@ -605,6 +655,14 @@ fn createGotAtom(self: *Coff, target: SymbolWithLoc) !*Atom { | ... | @@ -605,6 +655,14 @@ fn createGotAtom(self: *Coff, target: SymbolWithLoc) !*Atom { |
| 605 | .prev_vaddr = sym.value, | 655 | .prev_vaddr = sym.value, |
| 606 | }); | 656 | }); |
| 607 | 657 | ||
| 658 | const target_sym = self.getSymbol(target); | ||
| 659 | switch (target_sym.section_number) { | ||
| 660 | .UNDEFINED => @panic("TODO generate a binding for undefined GOT target"), | ||
| 661 | .ABSOLUTE => {}, | ||
| 662 | .DEBUG => unreachable, // not possible | ||
| 663 | else => try atom.addBaseRelocation(self, 0), | ||
| 664 | } | ||
| 665 | |||
| 608 | return atom; | 666 | return atom; |
| 609 | } | 667 | } |
| 610 | 668 | ||
| ... | @@ -1179,6 +1237,7 @@ pub fn flushModule(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Nod | ... | @@ -1179,6 +1237,7 @@ pub fn flushModule(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Nod |
| 1179 | try self.resolveRelocs(atom.*); | 1237 | try self.resolveRelocs(atom.*); |
| 1180 | } | 1238 | } |
| 1181 | } | 1239 | } |
| 1240 | try self.writeBaseRelocations(); | ||
| 1182 | 1241 | ||
| 1183 | if (self.getEntryPoint()) |entry_sym_loc| { | 1242 | if (self.getEntryPoint()) |entry_sym_loc| { |
| 1184 | self.entry_addr = self.getSymbol(entry_sym_loc).value; | 1243 | self.entry_addr = self.getSymbol(entry_sym_loc).value; |
| ... | @@ -1216,6 +1275,83 @@ pub fn updateDeclLineNumber(self: *Coff, module: *Module, decl: *Module.Decl) !v | ... | @@ -1216,6 +1275,83 @@ pub fn updateDeclLineNumber(self: *Coff, module: *Module, decl: *Module.Decl) !v |
| 1216 | log.debug("TODO implement updateDeclLineNumber", .{}); | 1275 | log.debug("TODO implement updateDeclLineNumber", .{}); |
| 1217 | } | 1276 | } |
| 1218 | 1277 | ||
| 1278 | /// TODO: note if we need to rewrite base relocations by dirtying any of the entries in the global table | ||
| 1279 | /// TODO: note that .ABSOLUTE is used as padding within each block; we could use this fact to do | ||
| 1280 | /// incremental updates and writes into the table instead of doing it all at once | ||
| 1281 | fn writeBaseRelocations(self: *Coff) !void { | ||
| 1282 | const gpa = self.base.allocator; | ||
| 1283 | |||
| 1284 | var pages = std.AutoHashMap(u32, std.ArrayList(coff.BaseRelocation)).init(gpa); | ||
| 1285 | defer { | ||
| 1286 | var it = pages.valueIterator(); | ||
| 1287 | while (it.next()) |inner| { | ||
| 1288 | inner.deinit(); | ||
| 1289 | } | ||
| 1290 | pages.deinit(); | ||
| 1291 | } | ||
| 1292 | |||
| 1293 | var it = self.base_relocs.iterator(); | ||
| 1294 | while (it.next()) |entry| { | ||
| 1295 | const atom = entry.key_ptr.*; | ||
| 1296 | const offsets = entry.value_ptr.*; | ||
| 1297 | |||
| 1298 | for (offsets.items) |offset| { | ||
| 1299 | const sym = atom.getSymbol(self); | ||
| 1300 | const rva = sym.value + offset; | ||
| 1301 | const page = mem.alignBackwardGeneric(u32, rva, self.page_size); | ||
| 1302 | const gop = try pages.getOrPut(page); | ||
| 1303 | if (!gop.found_existing) { | ||
| 1304 | gop.value_ptr.* = std.ArrayList(coff.BaseRelocation).init(gpa); | ||
| 1305 | } | ||
| 1306 | try gop.value_ptr.append(.{ | ||
| 1307 | .offset = @intCast(u12, rva - page), | ||
| 1308 | .@"type" = .DIR64, | ||
| 1309 | }); | ||
| 1310 | } | ||
| 1311 | } | ||
| 1312 | |||
| 1313 | var buffer = std.ArrayList(u8).init(gpa); | ||
| 1314 | defer buffer.deinit(); | ||
| 1315 | |||
| 1316 | var pages_it = pages.iterator(); | ||
| 1317 | while (pages_it.next()) |entry| { | ||
| 1318 | // Pad to required 4byte alignment | ||
| 1319 | if (!mem.isAlignedGeneric( | ||
| 1320 | usize, | ||
| 1321 | entry.value_ptr.items.len * @sizeOf(coff.BaseRelocation), | ||
| 1322 | @sizeOf(u32), | ||
| 1323 | )) { | ||
| 1324 | try entry.value_ptr.append(.{ | ||
| 1325 | .offset = 0, | ||
| 1326 | .@"type" = .ABSOLUTE, | ||
| 1327 | }); | ||
| 1328 | } | ||
| 1329 | |||
| 1330 | const block_size = @intCast( | ||
| 1331 | u32, | ||
| 1332 | entry.value_ptr.items.len * @sizeOf(coff.BaseRelocation) + @sizeOf(coff.BaseRelocationDirectoryEntry), | ||
| 1333 | ); | ||
| 1334 | try buffer.ensureUnusedCapacity(block_size); | ||
| 1335 | buffer.appendSliceAssumeCapacity(mem.asBytes(&coff.BaseRelocationDirectoryEntry{ | ||
| 1336 | .page_rva = entry.key_ptr.*, | ||
| 1337 | .block_size = block_size, | ||
| 1338 | })); | ||
| 1339 | buffer.appendSliceAssumeCapacity(mem.sliceAsBytes(entry.value_ptr.items)); | ||
| 1340 | } | ||
| 1341 | |||
| 1342 | const header = &self.sections.items(.header)[self.reloc_section_index.?]; | ||
| 1343 | const sect_capacity = self.allocatedSize(header.pointer_to_raw_data); | ||
| 1344 | const needed_size = @intCast(u32, buffer.items.len); | ||
| 1345 | assert(needed_size < sect_capacity); // TODO expand .reloc section | ||
| 1346 | |||
| 1347 | try self.base.file.?.pwriteAll(buffer.items, header.pointer_to_raw_data); | ||
| 1348 | |||
| 1349 | self.data_directories[@enumToInt(coff.DirectoryEntry.BASERELOC)] = .{ | ||
| 1350 | .virtual_address = header.virtual_address, | ||
| 1351 | .size = needed_size, | ||
| 1352 | }; | ||
| 1353 | } | ||
| 1354 | |||
| 1219 | fn writeStrtab(self: *Coff) !void { | 1355 | fn writeStrtab(self: *Coff) !void { |
| 1220 | const allocated_size = self.allocatedSize(self.strtab_offset.?); | 1356 | const allocated_size = self.allocatedSize(self.strtab_offset.?); |
| 1221 | const needed_size = @intCast(u32, self.strtab.len()); | 1357 | const needed_size = @intCast(u32, self.strtab.len()); |
| ... | @@ -1277,8 +1413,8 @@ fn writeHeader(self: *Coff) !void { | ... | @@ -1277,8 +1413,8 @@ fn writeHeader(self: *Coff) !void { |
| 1277 | writer.writeAll(mem.asBytes(&coff_header)) catch unreachable; | 1413 | writer.writeAll(mem.asBytes(&coff_header)) catch unreachable; |
| 1278 | 1414 | ||
| 1279 | const dll_flags: coff.DllFlags = .{ | 1415 | const dll_flags: coff.DllFlags = .{ |
| 1280 | .HIGH_ENTROPY_VA = 0, //@boolToInt(self.base.options.pie), | 1416 | .HIGH_ENTROPY_VA = 1, // TODO do we want to permit non-PIE builds at all? |
| 1281 | .DYNAMIC_BASE = 0, | 1417 | .DYNAMIC_BASE = 1, |
| 1282 | .TERMINAL_SERVER_AWARE = 1, // We are not a legacy app | 1418 | .TERMINAL_SERVER_AWARE = 1, // We are not a legacy app |
| 1283 | .NX_COMPAT = 1, // We are compatible with Data Execution Prevention | 1419 | .NX_COMPAT = 1, // We are compatible with Data Execution Prevention |
| 1284 | }; | 1420 | }; |
src/link/Coff/Atom.zig+12-2| ... | @@ -2,6 +2,7 @@ const Atom = @This(); | ... | @@ -2,6 +2,7 @@ const Atom = @This(); |
| 2 | 2 | ||
| 3 | const std = @import("std"); | 3 | const std = @import("std"); |
| 4 | const coff = std.coff; | 4 | const coff = std.coff; |
| 5 | const log = std.log.scoped(.link); | ||
| 5 | 6 | ||
| 6 | const Allocator = std.mem.Allocator; | 7 | const Allocator = std.mem.Allocator; |
| 7 | 8 | ||
| ... | @@ -100,11 +101,20 @@ pub fn freeListEligible(self: Atom, coff_file: *const Coff) bool { | ... | @@ -100,11 +101,20 @@ pub fn freeListEligible(self: Atom, coff_file: *const Coff) bool { |
| 100 | 101 | ||
| 101 | pub fn addRelocation(self: *Atom, coff_file: *Coff, reloc: Reloc) !void { | 102 | pub fn addRelocation(self: *Atom, coff_file: *Coff, reloc: Reloc) !void { |
| 102 | const gpa = coff_file.base.allocator; | 103 | const gpa = coff_file.base.allocator; |
| 103 | // TODO causes a segfault on Windows | 104 | log.debug(" (adding reloc of type {s} to target %{d})", .{ @tagName(reloc.@"type"), reloc.target.sym_index }); |
| 104 | // log.debug("adding reloc of type {s} to target %{d}", .{ @tagName(reloc.@"type"), reloc.target.sym_index }); | ||
| 105 | const gop = try coff_file.relocs.getOrPut(gpa, self); | 105 | const gop = try coff_file.relocs.getOrPut(gpa, self); |
| 106 | if (!gop.found_existing) { | 106 | if (!gop.found_existing) { |
| 107 | gop.value_ptr.* = .{}; | 107 | gop.value_ptr.* = .{}; |
| 108 | } | 108 | } |
| 109 | try gop.value_ptr.append(gpa, reloc); | 109 | try gop.value_ptr.append(gpa, reloc); |
| 110 | } | 110 | } |
| 111 | |||
| 112 | pub fn addBaseRelocation(self: *Atom, coff_file: *Coff, offset: u32) !void { | ||
| 113 | const gpa = coff_file.base.allocator; | ||
| 114 | log.debug(" (adding base relocation at offset 0x{x} in %{d})", .{ offset, self.sym_index }); | ||
| 115 | const gop = try coff_file.base_relocs.getOrPut(gpa, self); | ||
| 116 | if (!gop.found_existing) { | ||
| 117 | gop.value_ptr.* = .{}; | ||
| 118 | } | ||
| 119 | try gop.value_ptr.append(gpa, offset); | ||
| 120 | } |
src/link/Wasm.zig+34-11| ... | @@ -607,6 +607,24 @@ fn resolveSymbolsInArchives(self: *Wasm) !void { | ... | @@ -607,6 +607,24 @@ fn resolveSymbolsInArchives(self: *Wasm) !void { |
| 607 | } | 607 | } |
| 608 | } | 608 | } |
| 609 | 609 | ||
| 610 | fn checkUndefinedSymbols(self: *const Wasm) !void { | ||
| 611 | var found_undefined_symbols = false; | ||
| 612 | for (self.undefs.values()) |undef| { | ||
| 613 | const symbol = undef.getSymbol(self); | ||
| 614 | if (symbol.tag == .data) { | ||
| 615 | found_undefined_symbols = true; | ||
| 616 | const file_name = if (undef.file) |file_index| name: { | ||
| 617 | break :name self.objects.items[file_index].name; | ||
| 618 | } else self.name; | ||
| 619 | log.err("could not resolve undefined symbol '{s}'", .{undef.getName(self)}); | ||
| 620 | log.err(" defined in '{s}'", .{file_name}); | ||
| 621 | } | ||
| 622 | } | ||
| 623 | if (found_undefined_symbols) { | ||
| 624 | return error.UndefinedSymbol; | ||
| 625 | } | ||
| 626 | } | ||
| 627 | |||
| 610 | pub fn deinit(self: *Wasm) void { | 628 | pub fn deinit(self: *Wasm) void { |
| 611 | const gpa = self.base.allocator; | 629 | const gpa = self.base.allocator; |
| 612 | if (build_options.have_llvm) { | 630 | if (build_options.have_llvm) { |
| ... | @@ -783,15 +801,17 @@ pub fn updateDecl(self: *Wasm, mod: *Module, decl_index: Module.Decl.Index) !voi | ... | @@ -783,15 +801,17 @@ pub fn updateDecl(self: *Wasm, mod: *Module, decl_index: Module.Decl.Index) !voi |
| 783 | 801 | ||
| 784 | decl.link.wasm.clear(); | 802 | decl.link.wasm.clear(); |
| 785 | 803 | ||
| 786 | if (decl.isExtern()) { | ||
| 787 | return; | ||
| 788 | } | ||
| 789 | |||
| 790 | if (decl.val.castTag(.function)) |_| { | 804 | if (decl.val.castTag(.function)) |_| { |
| 791 | return; | 805 | return; |
| 792 | } else if (decl.val.castTag(.extern_fn)) |_| { | 806 | } else if (decl.val.castTag(.extern_fn)) |_| { |
| 793 | return; | 807 | return; |
| 794 | } | 808 | } |
| 809 | |||
| 810 | if (decl.isExtern()) { | ||
| 811 | const variable = decl.getVariable().?; | ||
| 812 | const name = mem.sliceTo(decl.name, 0); | ||
| 813 | return self.addOrUpdateImport(name, decl.link.wasm.sym_index, variable.lib_name, null); | ||
| 814 | } | ||
| 795 | const val = if (decl.val.castTag(.variable)) |payload| payload.data.init else decl.val; | 815 | const val = if (decl.val.castTag(.variable)) |payload| payload.data.init else decl.val; |
| 796 | 816 | ||
| 797 | var code_writer = std.ArrayList(u8).init(self.base.allocator); | 817 | var code_writer = std.ArrayList(u8).init(self.base.allocator); |
| ... | @@ -834,19 +854,18 @@ pub fn updateDeclLineNumber(self: *Wasm, mod: *Module, decl: *const Module.Decl) | ... | @@ -834,19 +854,18 @@ pub fn updateDeclLineNumber(self: *Wasm, mod: *Module, decl: *const Module.Decl) |
| 834 | } | 854 | } |
| 835 | 855 | ||
| 836 | fn finishUpdateDecl(self: *Wasm, decl: *Module.Decl, code: []const u8) !void { | 856 | fn finishUpdateDecl(self: *Wasm, decl: *Module.Decl, code: []const u8) !void { |
| 837 | if (code.len == 0) return; | ||
| 838 | const mod = self.base.options.module.?; | 857 | const mod = self.base.options.module.?; |
| 839 | const atom: *Atom = &decl.link.wasm; | 858 | const atom: *Atom = &decl.link.wasm; |
| 840 | atom.size = @intCast(u32, code.len); | ||
| 841 | atom.alignment = decl.ty.abiAlignment(self.base.options.target); | ||
| 842 | const symbol = &self.symbols.items[atom.sym_index]; | 859 | const symbol = &self.symbols.items[atom.sym_index]; |
| 843 | |||
| 844 | const full_name = try decl.getFullyQualifiedName(mod); | 860 | const full_name = try decl.getFullyQualifiedName(mod); |
| 845 | defer self.base.allocator.free(full_name); | 861 | defer self.base.allocator.free(full_name); |
| 846 | symbol.name = try self.string_table.put(self.base.allocator, full_name); | 862 | symbol.name = try self.string_table.put(self.base.allocator, full_name); |
| 847 | try atom.code.appendSlice(self.base.allocator, code); | 863 | try atom.code.appendSlice(self.base.allocator, code); |
| 848 | |||
| 849 | try self.resolved_symbols.put(self.base.allocator, atom.symbolLoc(), {}); | 864 | try self.resolved_symbols.put(self.base.allocator, atom.symbolLoc(), {}); |
| 865 | |||
| 866 | if (code.len == 0) return; | ||
| 867 | atom.size = @intCast(u32, code.len); | ||
| 868 | atom.alignment = decl.ty.abiAlignment(self.base.options.target); | ||
| 850 | } | 869 | } |
| 851 | 870 | ||
| 852 | /// From a given symbol location, returns its `wasm.GlobalType`. | 871 | /// From a given symbol location, returns its `wasm.GlobalType`. |
| ... | @@ -1235,7 +1254,10 @@ pub fn addOrUpdateImport( | ... | @@ -1235,7 +1254,10 @@ pub fn addOrUpdateImport( |
| 1235 | .kind = .{ .function = ty_index }, | 1254 | .kind = .{ .function = ty_index }, |
| 1236 | }; | 1255 | }; |
| 1237 | } | 1256 | } |
| 1238 | } else @panic("TODO: Implement undefined symbols for non-function declarations"); | 1257 | } else { |
| 1258 | symbol.tag = .data; | ||
| 1259 | return; // non-functions will not be imported from the runtime, but only resolved during link-time | ||
| 1260 | } | ||
| 1239 | } | 1261 | } |
| 1240 | 1262 | ||
| 1241 | /// Kind represents the type of an Atom, which is only | 1263 | /// Kind represents the type of an Atom, which is only |
| ... | @@ -1438,7 +1460,7 @@ fn setupImports(self: *Wasm) !void { | ... | @@ -1438,7 +1460,7 @@ fn setupImports(self: *Wasm) !void { |
| 1438 | if (std.mem.eql(u8, symbol_loc.getName(self), "__indirect_function_table")) { | 1460 | if (std.mem.eql(u8, symbol_loc.getName(self), "__indirect_function_table")) { |
| 1439 | continue; | 1461 | continue; |
| 1440 | } | 1462 | } |
| 1441 | if (symbol.tag == .data or !symbol.requiresImport()) { | 1463 | if (!symbol.requiresImport()) { |
| 1442 | continue; | 1464 | continue; |
| 1443 | } | 1465 | } |
| 1444 | 1466 | ||
| ... | @@ -2007,6 +2029,7 @@ pub fn flushModule(self: *Wasm, comp: *Compilation, prog_node: *std.Progress.Nod | ... | @@ -2007,6 +2029,7 @@ pub fn flushModule(self: *Wasm, comp: *Compilation, prog_node: *std.Progress.Nod |
| 2007 | } | 2029 | } |
| 2008 | 2030 | ||
| 2009 | try self.resolveSymbolsInArchives(); | 2031 | try self.resolveSymbolsInArchives(); |
| 2032 | try self.checkUndefinedSymbols(); | ||
| 2010 | 2033 | ||
| 2011 | // When we finish/error we reset the state of the linker | 2034 | // When we finish/error we reset the state of the linker |
| 2012 | // So we can rebuild the binary file on each incremental update | 2035 | // So we can rebuild the binary file on each incremental update |
src/link/Wasm/Atom.zig+6-8| ... | @@ -172,18 +172,16 @@ fn relocationValue(self: Atom, relocation: types.Relocation, wasm_bin: *const Wa | ... | @@ -172,18 +172,16 @@ fn relocationValue(self: Atom, relocation: types.Relocation, wasm_bin: *const Wa |
| 172 | .R_WASM_MEMORY_ADDR_SLEB, | 172 | .R_WASM_MEMORY_ADDR_SLEB, |
| 173 | .R_WASM_MEMORY_ADDR_SLEB64, | 173 | .R_WASM_MEMORY_ADDR_SLEB64, |
| 174 | => { | 174 | => { |
| 175 | if (symbol.isUndefined() and symbol.isWeak()) { | 175 | std.debug.assert(symbol.tag == .data and !symbol.isUndefined()); |
| 176 | return 0; | ||
| 177 | } | ||
| 178 | std.debug.assert(symbol.tag == .data); | ||
| 179 | const merge_segment = wasm_bin.base.options.output_mode != .Obj; | 176 | const merge_segment = wasm_bin.base.options.output_mode != .Obj; |
| 180 | const segment_info = if (self.file) |object_index| blk: { | 177 | const target_atom_loc = wasm_bin.discarded.get(target_loc) orelse target_loc; |
| 178 | const target_atom = wasm_bin.symbol_atom.get(target_atom_loc).?; | ||
| 179 | const segment_info = if (target_atom.file) |object_index| blk: { | ||
| 181 | break :blk wasm_bin.objects.items[object_index].segment_info; | 180 | break :blk wasm_bin.objects.items[object_index].segment_info; |
| 182 | } else wasm_bin.segment_info.items; | 181 | } else wasm_bin.segment_info.items; |
| 183 | const segment_name = segment_info[symbol.index].outputName(merge_segment); | 182 | const segment_name = segment_info[symbol.index].outputName(merge_segment); |
| 184 | const atom_index = wasm_bin.data_segments.get(segment_name).?; | 183 | const segment_index = wasm_bin.data_segments.get(segment_name).?; |
| 185 | const target_atom = wasm_bin.symbol_atom.get(target_loc).?; | 184 | const segment = wasm_bin.segments.items[segment_index]; |
| 186 | const segment = wasm_bin.segments.items[atom_index]; | ||
| 187 | return target_atom.offset + segment.offset + (relocation.addend orelse 0); | 185 | return target_atom.offset + segment.offset + (relocation.addend orelse 0); |
| 188 | }, | 186 | }, |
| 189 | .R_WASM_EVENT_INDEX_LEB => return symbol.index, | 187 | .R_WASM_EVENT_INDEX_LEB => return symbol.index, |
src/link/Wasm/Symbol.zig+1-1| ... | @@ -79,9 +79,9 @@ pub const Flag = enum(u32) { | ... | @@ -79,9 +79,9 @@ pub const Flag = enum(u32) { |
| 79 | /// Verifies if the given symbol should be imported from the | 79 | /// Verifies if the given symbol should be imported from the |
| 80 | /// host environment or not | 80 | /// host environment or not |
| 81 | pub fn requiresImport(self: Symbol) bool { | 81 | pub fn requiresImport(self: Symbol) bool { |
| 82 | if (self.tag == .data) return false; | ||
| 82 | if (!self.isUndefined()) return false; | 83 | if (!self.isUndefined()) return false; |
| 83 | if (self.isWeak()) return false; | 84 | if (self.isWeak()) return false; |
| 84 | if (self.tag == .data) return false; | ||
| 85 | // if (self.isDefined() and self.isWeak()) return true; //TODO: Only when building shared lib | 85 | // if (self.isDefined() and self.isWeak()) return true; //TODO: Only when building shared lib |
| 86 | 86 | ||
| 87 | return true; | 87 | return true; |
src/main.zig+14| ... | @@ -2750,8 +2750,22 @@ fn buildOutputType( | ... | @@ -2750,8 +2750,22 @@ fn buildOutputType( |
| 2750 | 2750 | ||
| 2751 | // Transfer packages added with --pkg-begin/--pkg-end to the root package | 2751 | // Transfer packages added with --pkg-begin/--pkg-end to the root package |
| 2752 | if (main_pkg) |pkg| { | 2752 | if (main_pkg) |pkg| { |
| 2753 | var it = pkg_tree_root.table.valueIterator(); | ||
| 2754 | while (it.next()) |p| { | ||
| 2755 | if (p.*.parent == &pkg_tree_root) { | ||
| 2756 | p.*.parent = pkg; | ||
| 2757 | } | ||
| 2758 | } | ||
| 2753 | pkg.table = pkg_tree_root.table; | 2759 | pkg.table = pkg_tree_root.table; |
| 2754 | pkg_tree_root.table = .{}; | 2760 | pkg_tree_root.table = .{}; |
| 2761 | } else { | ||
| 2762 | // Remove any dangling pointers just in case. | ||
| 2763 | var it = pkg_tree_root.table.valueIterator(); | ||
| 2764 | while (it.next()) |p| { | ||
| 2765 | if (p.*.parent == &pkg_tree_root) { | ||
| 2766 | p.*.parent = null; | ||
| 2767 | } | ||
| 2768 | } | ||
| 2755 | } | 2769 | } |
| 2756 | 2770 | ||
| 2757 | const self_exe_path = try introspect.findZigExePath(arena); | 2771 | const self_exe_path = try introspect.findZigExePath(arena); |
src/translate_c.zig+4| ... | @@ -1166,6 +1166,10 @@ fn transRecordDecl(c: *Context, scope: *Scope, record_decl: *const clang.RecordD | ... | @@ -1166,6 +1166,10 @@ fn transRecordDecl(c: *Context, scope: *Scope, record_decl: *const clang.RecordD |
| 1166 | }); | 1166 | }); |
| 1167 | } | 1167 | } |
| 1168 | 1168 | ||
| 1169 | if (!c.zig_is_stage1 and is_packed) { | ||
| 1170 | return failDecl(c, record_loc, bare_name, "cannot translate packed record union", .{}); | ||
| 1171 | } | ||
| 1172 | |||
| 1169 | const record_payload = try c.arena.create(ast.Payload.Record); | 1173 | const record_payload = try c.arena.create(ast.Payload.Record); |
| 1170 | record_payload.* = .{ | 1174 | record_payload.* = .{ |
| 1171 | .base = .{ .tag = ([2]Tag{ .@"struct", .@"union" })[@boolToInt(is_union)] }, | 1175 | .base = .{ .tag = ([2]Tag{ .@"struct", .@"union" })[@boolToInt(is_union)] }, |
src/type.zig+5-2| ... | @@ -2042,6 +2042,9 @@ pub const Type = extern union { | ... | @@ -2042,6 +2042,9 @@ pub const Type = extern union { |
| 2042 | try writer.writeAll("fn("); | 2042 | try writer.writeAll("fn("); |
| 2043 | for (fn_info.param_types) |param_ty, i| { | 2043 | for (fn_info.param_types) |param_ty, i| { |
| 2044 | if (i != 0) try writer.writeAll(", "); | 2044 | if (i != 0) try writer.writeAll(", "); |
| 2045 | if (std.math.cast(u5, i)) |index| if (@truncate(u1, fn_info.noalias_bits >> index) != 0) { | ||
| 2046 | try writer.writeAll("noalias "); | ||
| 2047 | }; | ||
| 2045 | if (param_ty.tag() == .generic_poison) { | 2048 | if (param_ty.tag() == .generic_poison) { |
| 2046 | try writer.writeAll("anytype"); | 2049 | try writer.writeAll("anytype"); |
| 2047 | } else { | 2050 | } else { |
| ... | @@ -2398,7 +2401,7 @@ pub const Type = extern union { | ... | @@ -2398,7 +2401,7 @@ pub const Type = extern union { |
| 2398 | } else if (ty.childType().zigTypeTag() == .Fn) { | 2401 | } else if (ty.childType().zigTypeTag() == .Fn) { |
| 2399 | return !ty.childType().fnInfo().is_generic; | 2402 | return !ty.childType().fnInfo().is_generic; |
| 2400 | } else if (sema_kit) |sk| { | 2403 | } else if (sema_kit) |sk| { |
| 2401 | return !(try sk.sema.typeRequiresComptime(sk.block, sk.src, ty)); | 2404 | return !(try sk.sema.typeRequiresComptime(ty)); |
| 2402 | } else { | 2405 | } else { |
| 2403 | return !comptimeOnly(ty); | 2406 | return !comptimeOnly(ty); |
| 2404 | } | 2407 | } |
| ... | @@ -2437,7 +2440,7 @@ pub const Type = extern union { | ... | @@ -2437,7 +2440,7 @@ pub const Type = extern union { |
| 2437 | if (ignore_comptime_only) { | 2440 | if (ignore_comptime_only) { |
| 2438 | return true; | 2441 | return true; |
| 2439 | } else if (sema_kit) |sk| { | 2442 | } else if (sema_kit) |sk| { |
| 2440 | return !(try sk.sema.typeRequiresComptime(sk.block, sk.src, child_ty)); | 2443 | return !(try sk.sema.typeRequiresComptime(child_ty)); |
| 2441 | } else { | 2444 | } else { |
| 2442 | return !comptimeOnly(child_ty); | 2445 | return !comptimeOnly(child_ty); |
| 2443 | } | 2446 | } |
src/value.zig+26-3| ... | @@ -2940,17 +2940,24 @@ pub const Value = extern union { | ... | @@ -2940,17 +2940,24 @@ pub const Value = extern union { |
| 2940 | } | 2940 | } |
| 2941 | 2941 | ||
| 2942 | pub fn intToFloat(val: Value, arena: Allocator, int_ty: Type, float_ty: Type, target: Target) !Value { | 2942 | pub fn intToFloat(val: Value, arena: Allocator, int_ty: Type, float_ty: Type, target: Target) !Value { |
| 2943 | return intToFloatAdvanced(val, arena, int_ty, float_ty, target, null) catch |err| switch (err) { | ||
| 2944 | error.OutOfMemory => return error.OutOfMemory, | ||
| 2945 | else => unreachable, | ||
| 2946 | }; | ||
| 2947 | } | ||
| 2948 | |||
| 2949 | pub fn intToFloatAdvanced(val: Value, arena: Allocator, int_ty: Type, float_ty: Type, target: Target, sema_kit: ?Module.WipAnalysis) !Value { | ||
| 2943 | if (int_ty.zigTypeTag() == .Vector) { | 2950 | if (int_ty.zigTypeTag() == .Vector) { |
| 2944 | const result_data = try arena.alloc(Value, int_ty.vectorLen()); | 2951 | const result_data = try arena.alloc(Value, int_ty.vectorLen()); |
| 2945 | for (result_data) |*scalar, i| { | 2952 | for (result_data) |*scalar, i| { |
| 2946 | scalar.* = try intToFloatScalar(val.indexVectorlike(i), arena, float_ty.scalarType(), target); | 2953 | scalar.* = try intToFloatScalar(val.indexVectorlike(i), arena, float_ty.scalarType(), target, sema_kit); |
| 2947 | } | 2954 | } |
| 2948 | return Value.Tag.aggregate.create(arena, result_data); | 2955 | return Value.Tag.aggregate.create(arena, result_data); |
| 2949 | } | 2956 | } |
| 2950 | return intToFloatScalar(val, arena, float_ty, target); | 2957 | return intToFloatScalar(val, arena, float_ty, target, sema_kit); |
| 2951 | } | 2958 | } |
| 2952 | 2959 | ||
| 2953 | pub fn intToFloatScalar(val: Value, arena: Allocator, float_ty: Type, target: Target) !Value { | 2960 | pub fn intToFloatScalar(val: Value, arena: Allocator, float_ty: Type, target: Target, sema_kit: ?Module.WipAnalysis) !Value { |
| 2954 | switch (val.tag()) { | 2961 | switch (val.tag()) { |
| 2955 | .undef, .zero, .one => return val, | 2962 | .undef, .zero, .one => return val, |
| 2956 | .the_only_possible_value => return Value.initTag(.zero), // for i0, u0 | 2963 | .the_only_possible_value => return Value.initTag(.zero), // for i0, u0 |
| ... | @@ -2970,6 +2977,22 @@ pub const Value = extern union { | ... | @@ -2970,6 +2977,22 @@ pub const Value = extern union { |
| 2970 | const float = bigIntToFloat(limbs, false); | 2977 | const float = bigIntToFloat(limbs, false); |
| 2971 | return floatToValue(float, arena, float_ty, target); | 2978 | return floatToValue(float, arena, float_ty, target); |
| 2972 | }, | 2979 | }, |
| 2980 | .lazy_align => { | ||
| 2981 | const ty = val.castTag(.lazy_align).?.data; | ||
| 2982 | if (sema_kit) |sk| { | ||
| 2983 | return intToFloatInner((try ty.abiAlignmentAdvanced(target, .{ .sema_kit = sk })).scalar, arena, float_ty, target); | ||
| 2984 | } else { | ||
| 2985 | return intToFloatInner(ty.abiAlignment(target), arena, float_ty, target); | ||
| 2986 | } | ||
| 2987 | }, | ||
| 2988 | .lazy_size => { | ||
| 2989 | const ty = val.castTag(.lazy_size).?.data; | ||
| 2990 | if (sema_kit) |sk| { | ||
| 2991 | return intToFloatInner((try ty.abiSizeAdvanced(target, .{ .sema_kit = sk })).scalar, arena, float_ty, target); | ||
| 2992 | } else { | ||
| 2993 | return intToFloatInner(ty.abiSize(target), arena, float_ty, target); | ||
| 2994 | } | ||
| 2995 | }, | ||
| 2973 | else => unreachable, | 2996 | else => unreachable, |
| 2974 | } | 2997 | } |
| 2975 | } | 2998 | } |
test/behavior.zig+1| ... | @@ -85,6 +85,7 @@ test { | ... | @@ -85,6 +85,7 @@ test { |
| 85 | _ = @import("behavior/bugs/12033.zig"); | 85 | _ = @import("behavior/bugs/12033.zig"); |
| 86 | _ = @import("behavior/bugs/12430.zig"); | 86 | _ = @import("behavior/bugs/12430.zig"); |
| 87 | _ = @import("behavior/bugs/12486.zig"); | 87 | _ = @import("behavior/bugs/12486.zig"); |
| 88 | _ = @import("behavior/bugs/12680.zig"); | ||
| 88 | _ = @import("behavior/byteswap.zig"); | 89 | _ = @import("behavior/byteswap.zig"); |
| 89 | _ = @import("behavior/byval_arg_var.zig"); | 90 | _ = @import("behavior/byval_arg_var.zig"); |
| 90 | _ = @import("behavior/call.zig"); | 91 | _ = @import("behavior/call.zig"); |
test/behavior/bugs/12680.zig created+17| ... | @@ -0,0 +1,17 @@ | ||
| 1 | const std = @import("std"); | ||
| 2 | const expectEqual = std.testing.expectEqual; | ||
| 3 | const other_file = @import("12680_other_file.zig"); | ||
| 4 | const builtin = @import("builtin"); | ||
| 5 | |||
| 6 | extern fn test_func() callconv(.C) usize; | ||
| 7 | |||
| 8 | test "export a function twice" { | ||
| 9 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | ||
| 10 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; | ||
| 11 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; | ||
| 12 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; | ||
| 13 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; | ||
| 14 | |||
| 15 | // If it exports the function correctly, `test_func` and `testFunc` will points to the same address. | ||
| 16 | try expectEqual(test_func(), other_file.testFunc()); | ||
| 17 | } | ||
test/behavior/bugs/12680_other_file.zig created+8| ... | @@ -0,0 +1,8 @@ | ||
| 1 | // export this function twice | ||
| 2 | pub export fn testFunc() callconv(.C) usize { | ||
| 3 | return @ptrToInt(&testFunc); | ||
| 4 | } | ||
| 5 | |||
| 6 | comptime { | ||
| 7 | @export(testFunc, .{ .name = "test_func", .linkage = .Strong }); | ||
| 8 | } | ||
test/behavior/enum.zig+7| ... | @@ -1175,3 +1175,10 @@ test "Non-exhaustive enum with nonstandard int size behaves correctly" { | ... | @@ -1175,3 +1175,10 @@ test "Non-exhaustive enum with nonstandard int size behaves correctly" { |
| 1175 | const E = enum(u15) { _ }; | 1175 | const E = enum(u15) { _ }; |
| 1176 | try expect(@sizeOf(E) == @sizeOf(u15)); | 1176 | try expect(@sizeOf(E) == @sizeOf(u15)); |
| 1177 | } | 1177 | } |
| 1178 | |||
| 1179 | test "Non-exhaustive enum backed by comptime_int" { | ||
| 1180 | const E = enum(comptime_int) { a, b, c, _ }; | ||
| 1181 | comptime var e: E = .a; | ||
| 1182 | e = @intToEnum(E, 378089457309184723749); | ||
| 1183 | try expect(@enumToInt(e) == 378089457309184723749); | ||
| 1184 | } |
test/behavior/packed-struct.zig+26| ... | @@ -579,3 +579,29 @@ test "runtime init of unnamed packed struct type" { | ... | @@ -579,3 +579,29 @@ test "runtime init of unnamed packed struct type" { |
| 579 | } | 579 | } |
| 580 | }{ .x = z }).m(); | 580 | }{ .x = z }).m(); |
| 581 | } | 581 | } |
| 582 | |||
| 583 | test "packed struct passed to callconv(.C) function" { | ||
| 584 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | ||
| 585 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; | ||
| 586 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; | ||
| 587 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; | ||
| 588 | |||
| 589 | const S = struct { | ||
| 590 | const Packed = packed struct { | ||
| 591 | a: u16, | ||
| 592 | b: bool = true, | ||
| 593 | c: bool = true, | ||
| 594 | d: u46 = 0, | ||
| 595 | }; | ||
| 596 | |||
| 597 | fn foo(p: Packed, a1: u64, a2: u64, a3: u64, a4: u64, a5: u64) callconv(.C) bool { | ||
| 598 | return p.a == 12345 and p.b == true and p.c == true and p.d == 0 and a1 == 5 and a2 == 4 and a3 == 3 and a4 == 2 and a5 == 1; | ||
| 599 | } | ||
| 600 | }; | ||
| 601 | const result = S.foo(S.Packed{ | ||
| 602 | .a = 12345, | ||
| 603 | .b = true, | ||
| 604 | .c = true, | ||
| 605 | }, 5, 4, 3, 2, 1); | ||
| 606 | try expect(result); | ||
| 607 | } |
test/behavior/sizeof_and_typeof.zig+11| ... | @@ -301,3 +301,14 @@ test "array access of generic param in typeof expression" { | ... | @@ -301,3 +301,14 @@ test "array access of generic param in typeof expression" { |
| 301 | try expect(S.first("a") == 'a'); | 301 | try expect(S.first("a") == 'a'); |
| 302 | comptime try expect(S.first("a") == 'a'); | 302 | comptime try expect(S.first("a") == 'a'); |
| 303 | } | 303 | } |
| 304 | |||
| 305 | test "lazy size cast to float" { | ||
| 306 | { | ||
| 307 | const S = struct { a: u8 }; | ||
| 308 | try expect(@intToFloat(f32, @sizeOf(S)) == 1.0); | ||
| 309 | } | ||
| 310 | { | ||
| 311 | const S = struct { a: u8 }; | ||
| 312 | try expect(@as(f32, @sizeOf(S)) == 1.0); | ||
| 313 | } | ||
| 314 | } |
test/behavior/translate_c_macros.h+2| ... | @@ -48,3 +48,5 @@ typedef _Bool uintptr_t; | ... | @@ -48,3 +48,5 @@ typedef _Bool uintptr_t; |
| 48 | 48 | ||
| 49 | #define CAST_TO_BOOL(X) (_Bool)(X) | 49 | #define CAST_TO_BOOL(X) (_Bool)(X) |
| 50 | #define CAST_TO_UINTPTR(X) (uintptr_t)(X) | 50 | #define CAST_TO_UINTPTR(X) (uintptr_t)(X) |
| 51 | |||
| 52 | #define LARGE_INT 18446744073709550592 |
test/behavior/translate_c_macros.zig+10| ... | @@ -113,3 +113,13 @@ test "cast functions" { | ... | @@ -113,3 +113,13 @@ test "cast functions" { |
| 113 | try expectEqual(true, h.CAST_TO_BOOL(S.foo)); | 113 | try expectEqual(true, h.CAST_TO_BOOL(S.foo)); |
| 114 | try expect(h.CAST_TO_UINTPTR(S.foo) != 0); | 114 | try expect(h.CAST_TO_UINTPTR(S.foo) != 0); |
| 115 | } | 115 | } |
| 116 | |||
| 117 | test "large integer macro" { | ||
| 118 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO | ||
| 119 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO | ||
| 120 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO | ||
| 121 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | ||
| 122 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO | ||
| 123 | |||
| 124 | try expectEqual(@as(c_ulonglong, 18446744073709550592), h.LARGE_INT); | ||
| 125 | } |
test/behavior/union.zig+29-1| ... | @@ -690,7 +690,7 @@ test "union with only 1 field casted to its enum type which has enum value speci | ... | @@ -690,7 +690,7 @@ test "union with only 1 field casted to its enum type which has enum value speci |
| 690 | 690 | ||
| 691 | var e = Expr{ .Literal = Literal{ .Bool = true } }; | 691 | var e = Expr{ .Literal = Literal{ .Bool = true } }; |
| 692 | comptime try expect(Tag(ExprTag) == comptime_int); | 692 | comptime try expect(Tag(ExprTag) == comptime_int); |
| 693 | var t = @as(ExprTag, e); | 693 | comptime var t = @as(ExprTag, e); |
| 694 | try expect(t == Expr.Literal); | 694 | try expect(t == Expr.Literal); |
| 695 | try expect(@enumToInt(t) == 33); | 695 | try expect(@enumToInt(t) == 33); |
| 696 | comptime try expect(@enumToInt(t) == 33); | 696 | comptime try expect(@enumToInt(t) == 33); |
| ... | @@ -1352,3 +1352,31 @@ test "@unionInit uses tag value instead of field index" { | ... | @@ -1352,3 +1352,31 @@ test "@unionInit uses tag value instead of field index" { |
| 1352 | } | 1352 | } |
| 1353 | try expect(@enumToInt(u) == 255); | 1353 | try expect(@enumToInt(u) == 255); |
| 1354 | } | 1354 | } |
| 1355 | |||
| 1356 | test "union field ptr - zero sized payload" { | ||
| 1357 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO | ||
| 1358 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO | ||
| 1359 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | ||
| 1360 | |||
| 1361 | const U = union { | ||
| 1362 | foo: void, | ||
| 1363 | bar: void, | ||
| 1364 | fn bar(_: *void) void {} | ||
| 1365 | }; | ||
| 1366 | var u: U = .{ .foo = {} }; | ||
| 1367 | U.bar(&u.foo); | ||
| 1368 | } | ||
| 1369 | |||
| 1370 | test "union field ptr - zero sized field" { | ||
| 1371 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO | ||
| 1372 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO | ||
| 1373 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | ||
| 1374 | |||
| 1375 | const U = union { | ||
| 1376 | foo: void, | ||
| 1377 | bar: u32, | ||
| 1378 | fn bar(_: *void) void {} | ||
| 1379 | }; | ||
| 1380 | var u: U = .{ .foo = {} }; | ||
| 1381 | U.bar(&u.foo); | ||
| 1382 | } |
test/c_abi/cfuncs.c+29-49| ... | @@ -86,24 +86,8 @@ struct MedStructMixed { | ... | @@ -86,24 +86,8 @@ struct MedStructMixed { |
| 86 | void zig_med_struct_mixed(struct MedStructMixed); | 86 | void zig_med_struct_mixed(struct MedStructMixed); |
| 87 | struct MedStructMixed zig_ret_med_struct_mixed(); | 87 | struct MedStructMixed zig_ret_med_struct_mixed(); |
| 88 | 88 | ||
| 89 | struct SmallPackedStruct { | 89 | void zig_small_packed_struct(uint8_t); |
| 90 | uint8_t a: 2; | 90 | void zig_big_packed_struct(__int128); |
| 91 | uint8_t b: 2; | ||
| 92 | uint8_t c: 2; | ||
| 93 | uint8_t d: 2; | ||
| 94 | uint8_t e: 1; | ||
| 95 | }; | ||
| 96 | |||
| 97 | struct BigPackedStruct { | ||
| 98 | uint64_t a: 64; | ||
| 99 | uint64_t b: 64; | ||
| 100 | uint64_t c: 64; | ||
| 101 | uint64_t d: 64; | ||
| 102 | uint8_t e: 8; | ||
| 103 | }; | ||
| 104 | |||
| 105 | //void zig_small_packed_struct(struct SmallPackedStruct); // #1481 | ||
| 106 | void zig_big_packed_struct(struct BigPackedStruct); | ||
| 107 | 91 | ||
| 108 | struct SplitStructInts { | 92 | struct SplitStructInts { |
| 109 | uint64_t a; | 93 | uint64_t a; |
| ... | @@ -176,13 +160,19 @@ void run_c_tests(void) { | ... | @@ -176,13 +160,19 @@ void run_c_tests(void) { |
| 176 | } | 160 | } |
| 177 | 161 | ||
| 178 | { | 162 | { |
| 179 | struct BigPackedStruct s = {1, 2, 3, 4, 5}; | 163 | __int128 s = 0; |
| 164 | s |= 1 << 0; | ||
| 165 | s |= (__int128)2 << 64; | ||
| 180 | zig_big_packed_struct(s); | 166 | zig_big_packed_struct(s); |
| 181 | } | 167 | } |
| 182 | 168 | ||
| 183 | { | 169 | { |
| 184 | struct SmallPackedStruct s = {0, 1, 2, 3, 1}; | 170 | uint8_t s = 0; |
| 185 | //zig_small_packed_struct(s); | 171 | s |= 0 << 0; |
| 172 | s |= 1 << 2; | ||
| 173 | s |= 2 << 4; | ||
| 174 | s |= 3 << 6; | ||
| 175 | zig_small_packed_struct(s); | ||
| 186 | } | 176 | } |
| 187 | 177 | ||
| 188 | { | 178 | { |
| ... | @@ -378,42 +368,32 @@ void c_split_struct_mixed(struct SplitStructMixed x) { | ... | @@ -378,42 +368,32 @@ void c_split_struct_mixed(struct SplitStructMixed x) { |
| 378 | assert_or_panic(y.c == 1337.0f); | 368 | assert_or_panic(y.c == 1337.0f); |
| 379 | } | 369 | } |
| 380 | 370 | ||
| 381 | struct SmallPackedStruct c_ret_small_packed_struct() { | 371 | uint8_t c_ret_small_packed_struct() { |
| 382 | struct SmallPackedStruct s = { | 372 | uint8_t s = 0; |
| 383 | .a = 0, | 373 | s |= 0 << 0; |
| 384 | .b = 1, | 374 | s |= 1 << 2; |
| 385 | .c = 2, | 375 | s |= 2 << 4; |
| 386 | .d = 3, | 376 | s |= 3 << 6; |
| 387 | .e = 1, | ||
| 388 | }; | ||
| 389 | return s; | 377 | return s; |
| 390 | } | 378 | } |
| 391 | 379 | ||
| 392 | void c_small_packed_struct(struct SmallPackedStruct x) { | 380 | void c_small_packed_struct(uint8_t x) { |
| 393 | assert_or_panic(x.a == 0); | 381 | assert_or_panic(((x >> 0) & 0x3) == 0); |
| 394 | assert_or_panic(x.a == 1); | 382 | assert_or_panic(((x >> 2) & 0x3) == 1); |
| 395 | assert_or_panic(x.a == 2); | 383 | assert_or_panic(((x >> 4) & 0x3) == 2); |
| 396 | assert_or_panic(x.a == 3); | 384 | assert_or_panic(((x >> 6) & 0x3) == 3); |
| 397 | assert_or_panic(x.e == 1); | ||
| 398 | } | 385 | } |
| 399 | 386 | ||
| 400 | struct BigPackedStruct c_ret_big_packed_struct() { | 387 | __int128 c_ret_big_packed_struct() { |
| 401 | struct BigPackedStruct s = { | 388 | __int128 s = 0; |
| 402 | .a = 1, | 389 | s |= 1 << 0; |
| 403 | .b = 2, | 390 | s |= (__int128)2 << 64; |
| 404 | .c = 3, | ||
| 405 | .d = 4, | ||
| 406 | .e = 5, | ||
| 407 | }; | ||
| 408 | return s; | 391 | return s; |
| 409 | } | 392 | } |
| 410 | 393 | ||
| 411 | void c_big_packed_struct(struct BigPackedStruct x) { | 394 | void c_big_packed_struct(__int128 x) { |
| 412 | assert_or_panic(x.a == 1); | 395 | assert_or_panic(((x >> 0) & 0xFFFFFFFFFFFFFFFF) == 1); |
| 413 | assert_or_panic(x.b == 2); | 396 | assert_or_panic(((x >> 64) & 0xFFFFFFFFFFFFFFFF) == 2); |
| 414 | assert_or_panic(x.c == 3); | ||
| 415 | assert_or_panic(x.d == 4); | ||
| 416 | assert_or_panic(x.e == 5); | ||
| 417 | } | 397 | } |
| 418 | 398 | ||
| 419 | struct SplitStructMixed c_ret_split_struct_mixed() { | 399 | struct SplitStructMixed c_ret_split_struct_mixed() { |
test/c_abi/main.zig+11-24| ... | @@ -110,7 +110,7 @@ test "C ABI floats" { | ... | @@ -110,7 +110,7 @@ test "C ABI floats" { |
| 110 | } | 110 | } |
| 111 | 111 | ||
| 112 | test "C ABI long double" { | 112 | test "C ABI long double" { |
| 113 | if (!builtin.cpu.arch.isWasm()) return error.SkipZigTest; | 113 | if (!builtin.cpu.arch.isWasm() and !builtin.cpu.arch.isAARCH64()) return error.SkipZigTest; |
| 114 | c_long_double(12.34); | 114 | c_long_double(12.34); |
| 115 | } | 115 | } |
| 116 | 116 | ||
| ... | @@ -263,37 +263,30 @@ const SmallPackedStruct = packed struct { | ... | @@ -263,37 +263,30 @@ const SmallPackedStruct = packed struct { |
| 263 | b: u2, | 263 | b: u2, |
| 264 | c: u2, | 264 | c: u2, |
| 265 | d: u2, | 265 | d: u2, |
| 266 | e: bool, | ||
| 267 | }; | 266 | }; |
| 268 | const c_small_packed_struct: fn (SmallPackedStruct) callconv(.C) void = @compileError("TODO: #1481"); | 267 | extern fn c_small_packed_struct(SmallPackedStruct) void; |
| 269 | extern fn c_ret_small_packed_struct() SmallPackedStruct; | 268 | extern fn c_ret_small_packed_struct() SmallPackedStruct; |
| 270 | 269 | ||
| 271 | // waiting on #1481 | 270 | export fn zig_small_packed_struct(x: SmallPackedStruct) void { |
| 272 | //export fn zig_small_packed_struct(x: SmallPackedStruct) void { | 271 | expect(x.a == 0) catch @panic("test failure"); |
| 273 | // expect(x.a == 0) catch @panic("test failure"); | 272 | expect(x.b == 1) catch @panic("test failure"); |
| 274 | // expect(x.b == 1) catch @panic("test failure"); | 273 | expect(x.c == 2) catch @panic("test failure"); |
| 275 | // expect(x.c == 2) catch @panic("test failure"); | 274 | expect(x.d == 3) catch @panic("test failure"); |
| 276 | // expect(x.d == 3) catch @panic("test failure"); | 275 | } |
| 277 | // expect(x.e) catch @panic("test failure"); | ||
| 278 | //} | ||
| 279 | 276 | ||
| 280 | test "C ABI small packed struct" { | 277 | test "C ABI small packed struct" { |
| 281 | var s = SmallPackedStruct{ .a = 0, .b = 1, .c = 2, .d = 3, .e = true }; | 278 | var s = SmallPackedStruct{ .a = 0, .b = 1, .c = 2, .d = 3 }; |
| 282 | _ = s; //c_small_packed_struct(s); // waiting on #1481 | 279 | c_small_packed_struct(s); |
| 283 | var s2 = c_ret_small_packed_struct(); | 280 | var s2 = c_ret_small_packed_struct(); |
| 284 | try expect(s2.a == 0); | 281 | try expect(s2.a == 0); |
| 285 | try expect(s2.b == 1); | 282 | try expect(s2.b == 1); |
| 286 | try expect(s2.c == 2); | 283 | try expect(s2.c == 2); |
| 287 | try expect(s2.d == 3); | 284 | try expect(s2.d == 3); |
| 288 | try expect(s2.e); | ||
| 289 | } | 285 | } |
| 290 | 286 | ||
| 291 | const BigPackedStruct = packed struct { | 287 | const BigPackedStruct = packed struct { |
| 292 | a: u64, | 288 | a: u64, |
| 293 | b: u64, | 289 | b: u64, |
| 294 | c: u64, | ||
| 295 | d: u64, | ||
| 296 | e: u8, | ||
| 297 | }; | 290 | }; |
| 298 | extern fn c_big_packed_struct(BigPackedStruct) void; | 291 | extern fn c_big_packed_struct(BigPackedStruct) void; |
| 299 | extern fn c_ret_big_packed_struct() BigPackedStruct; | 292 | extern fn c_ret_big_packed_struct() BigPackedStruct; |
| ... | @@ -301,20 +294,14 @@ extern fn c_ret_big_packed_struct() BigPackedStruct; | ... | @@ -301,20 +294,14 @@ extern fn c_ret_big_packed_struct() BigPackedStruct; |
| 301 | export fn zig_big_packed_struct(x: BigPackedStruct) void { | 294 | export fn zig_big_packed_struct(x: BigPackedStruct) void { |
| 302 | expect(x.a == 1) catch @panic("test failure"); | 295 | expect(x.a == 1) catch @panic("test failure"); |
| 303 | expect(x.b == 2) catch @panic("test failure"); | 296 | expect(x.b == 2) catch @panic("test failure"); |
| 304 | expect(x.c == 3) catch @panic("test failure"); | ||
| 305 | expect(x.d == 4) catch @panic("test failure"); | ||
| 306 | expect(x.e == 5) catch @panic("test failure"); | ||
| 307 | } | 297 | } |
| 308 | 298 | ||
| 309 | test "C ABI big packed struct" { | 299 | test "C ABI big packed struct" { |
| 310 | var s = BigPackedStruct{ .a = 1, .b = 2, .c = 3, .d = 4, .e = 5 }; | 300 | var s = BigPackedStruct{ .a = 1, .b = 2 }; |
| 311 | c_big_packed_struct(s); | 301 | c_big_packed_struct(s); |
| 312 | var s2 = c_ret_big_packed_struct(); | 302 | var s2 = c_ret_big_packed_struct(); |
| 313 | try expect(s2.a == 1); | 303 | try expect(s2.a == 1); |
| 314 | try expect(s2.b == 2); | 304 | try expect(s2.b == 2); |
| 315 | try expect(s2.c == 3); | ||
| 316 | try expect(s2.d == 4); | ||
| 317 | try expect(s2.e == 5); | ||
| 318 | } | 305 | } |
| 319 | 306 | ||
| 320 | const SplitStructInt = extern struct { | 307 | const SplitStructInt = extern struct { |
test/cases/compile_errors/C_pointer_pointing_to_non_C_ABI_compatible_type_or_has_align_attr.zig+1-1| ... | @@ -10,5 +10,5 @@ export fn a() void { | ... | @@ -10,5 +10,5 @@ export fn a() void { |
| 10 | // target=native | 10 | // target=native |
| 11 | // | 11 | // |
| 12 | // :3:19: error: C pointers cannot point to non-C-ABI-compatible type 'tmp.Foo' | 12 | // :3:19: error: C pointers cannot point to non-C-ABI-compatible type 'tmp.Foo' |
| 13 | // :3:19: note: only structs with packed or extern layout are extern compatible | 13 | // :3:19: note: only extern structs and ABI sized packed structs are extern compatible |
| 14 | // :1:13: note: struct declared here | 14 | // :1:13: note: struct declared here |
test/cases/compile_errors/enum_backed_by_comptime_int_must_be_comptime.zig created+11| ... | @@ -0,0 +1,11 @@ | ||
| 1 | pub export fn entry() void { | ||
| 2 | const E = enum(comptime_int) { a, b, c, _ }; | ||
| 3 | var e: E = .a; | ||
| 4 | _ = e; | ||
| 5 | } | ||
| 6 | |||
| 7 | // error | ||
| 8 | // backend=stage2 | ||
| 9 | // target=native | ||
| 10 | // | ||
| 11 | // :3:12: error: variable of type 'tmp.entry.E' must be const or comptime | ||
test/cases/compile_errors/function_with_non-extern_non-packed_struct_parameter.zig+1-1| ... | @@ -10,5 +10,5 @@ export fn entry(foo: Foo) void { _ = foo; } | ... | @@ -10,5 +10,5 @@ export fn entry(foo: Foo) void { _ = foo; } |
| 10 | // target=native | 10 | // target=native |
| 11 | // | 11 | // |
| 12 | // :6:17: error: parameter of type 'tmp.Foo' not allowed in function with calling convention 'C' | 12 | // :6:17: error: parameter of type 'tmp.Foo' not allowed in function with calling convention 'C' |
| 13 | // :6:17: note: only structs with packed or extern layout are extern compatible | 13 | // :6:17: note: only extern structs and ABI sized packed structs are extern compatible |
| 14 | // :1:13: note: struct declared here | 14 | // :1:13: note: struct declared here |
test/cases/compile_errors/function_with_non-extern_non-packed_union_parameter.zig+1-1| ... | @@ -10,5 +10,5 @@ export fn entry(foo: Foo) void { _ = foo; } | ... | @@ -10,5 +10,5 @@ export fn entry(foo: Foo) void { _ = foo; } |
| 10 | // target=native | 10 | // target=native |
| 11 | // | 11 | // |
| 12 | // :6:17: error: parameter of type 'tmp.Foo' not allowed in function with calling convention 'C' | 12 | // :6:17: error: parameter of type 'tmp.Foo' not allowed in function with calling convention 'C' |
| 13 | // :6:17: note: only unions with packed or extern layout are extern compatible | 13 | // :6:17: note: only extern unions and ABI sized packed unions are extern compatible |
| 14 | // :1:13: note: union declared here | 14 | // :1:13: note: union declared here |
test/cases/compile_errors/int_literal_passed_as_variadic_arg.zig deleted-11| ... | @@ -1,11 +0,0 @@ | ||
| 1 | extern fn printf([*:0]const u8, ...) c_int; | ||
| 2 | |||
| 3 | pub export fn entry() void { | ||
| 4 | _ = printf("%d %d %d %d\n", 1, 2, 3, 4); | ||
| 5 | } | ||
| 6 | |||
| 7 | // error | ||
| 8 | // backend=stage2 | ||
| 9 | // target=native | ||
| 10 | // | ||
| 11 | // :4:33: error: integer and float literals in var args function must be casted | ||
test/cases/compile_errors/noalias_param_coersion.zig created+20| ... | @@ -0,0 +1,20 @@ | ||
| 1 | pub export fn entry() void { | ||
| 2 | comptime var x: fn (noalias *i32, noalias *i32) void = undefined; | ||
| 3 | x = bar; | ||
| 4 | } | ||
| 5 | pub export fn entry1() void { | ||
| 6 | comptime var x: fn (*i32, *i32) void = undefined; | ||
| 7 | x = foo; | ||
| 8 | } | ||
| 9 | |||
| 10 | fn foo(noalias _: *i32, noalias _: *i32) void {} | ||
| 11 | fn bar(noalias _: *i32, _: *i32) void {} | ||
| 12 | |||
| 13 | // error | ||
| 14 | // backend=stage2 | ||
| 15 | // target=native | ||
| 16 | // | ||
| 17 | // :3:9: error: expected type 'fn(noalias *i32, noalias *i32) void', found 'fn(noalias *i32, *i32) void' | ||
| 18 | // :3:9: note: regular parameter 1 cannot cast into a noalias parameter | ||
| 19 | // :7:9: error: expected type 'fn(*i32, *i32) void', found 'fn(noalias *i32, noalias *i32) void' | ||
| 20 | // :7:9: note: noalias parameter 0 cannot cast into a regular parameter | ||
test/cases/compile_errors/overflow_in_enum_value_allocation.zig created+14| ... | @@ -0,0 +1,14 @@ | ||
| 1 | const Moo = enum(u8) { | ||
| 2 | Last = 255, | ||
| 3 | Over, | ||
| 4 | }; | ||
| 5 | pub export fn entry() void { | ||
| 6 | var y = Moo.Last; | ||
| 7 | _ = y; | ||
| 8 | } | ||
| 9 | |||
| 10 | // error | ||
| 11 | // backend=stage2 | ||
| 12 | // target=native | ||
| 13 | // | ||
| 14 | // :3:5: error: enumeration value '256' too large for type 'u8' | ||
test/cases/compile_errors/specify_enum_tag_type_that_is_too_small.zig created+18| ... | @@ -0,0 +1,18 @@ | ||
| 1 | const Small = enum (u2) { | ||
| 2 | One, | ||
| 3 | Two, | ||
| 4 | Three, | ||
| 5 | Four, | ||
| 6 | Five, | ||
| 7 | }; | ||
| 8 | |||
| 9 | export fn entry() void { | ||
| 10 | var x = Small.One; | ||
| 11 | _ = x; | ||
| 12 | } | ||
| 13 | |||
| 14 | // error | ||
| 15 | // backend=stage2 | ||
| 16 | // target=native | ||
| 17 | // | ||
| 18 | // :6:5: error: enumeration value '4' too large for type 'u2' | ||
test/cases/compile_errors/stage1/obj/overflow_in_enum_value_allocation.zig deleted-14| ... | @@ -1,14 +0,0 @@ | ||
| 1 | const Moo = enum(u8) { | ||
| 2 | Last = 255, | ||
| 3 | Over, | ||
| 4 | }; | ||
| 5 | pub fn main() void { | ||
| 6 | var y = Moo.Last; | ||
| 7 | _ = y; | ||
| 8 | } | ||
| 9 | |||
| 10 | // error | ||
| 11 | // backend=stage1 | ||
| 12 | // target=native | ||
| 13 | // | ||
| 14 | // tmp.zig:3:5: error: enumeration value 256 too large for type 'u8' | ||
test/cases/compile_errors/stage1/obj/specify_enum_tag_type_that_is_too_small.zig deleted-18| ... | @@ -1,18 +0,0 @@ | ||
| 1 | const Small = enum (u2) { | ||
| 2 | One, | ||
| 3 | Two, | ||
| 4 | Three, | ||
| 5 | Four, | ||
| 6 | Five, | ||
| 7 | }; | ||
| 8 | |||
| 9 | export fn entry() void { | ||
| 10 | var x = Small.One; | ||
| 11 | _ = x; | ||
| 12 | } | ||
| 13 | |||
| 14 | // error | ||
| 15 | // backend=stage1 | ||
| 16 | // target=native | ||
| 17 | // | ||
| 18 | // tmp.zig:6:5: error: enumeration value 4 too large for type 'u2' | ||
test/cases/compile_errors/try_return.zig created+11| ... | @@ -0,0 +1,11 @@ | ||
| 1 | pub fn foo() !void { | ||
| 2 | try return bar(); | ||
| 3 | } | ||
| 4 | pub fn bar() !void {} | ||
| 5 | |||
| 6 | // error | ||
| 7 | // backend=stage2 | ||
| 8 | // target=native | ||
| 9 | // | ||
| 10 | // :2:5: error: unreachable code | ||
| 11 | // :2:9: note: control flow is diverted here | ||
test/cases/compile_errors/variadic_arg_validation.zig created+29| ... | @@ -0,0 +1,29 @@ | ||
| 1 | extern fn printf([*:0]const u8, ...) c_int; | ||
| 2 | |||
| 3 | pub export fn entry() void { | ||
| 4 | _ = printf("%d %d %d %d\n", 1, 2, 3, 4); | ||
| 5 | } | ||
| 6 | |||
| 7 | pub export fn entry1() void { | ||
| 8 | var arr: [2]u8 = undefined; | ||
| 9 | _ = printf("%d\n", arr); | ||
| 10 | } | ||
| 11 | |||
| 12 | pub export fn entry2() void { | ||
| 13 | _ = printf("%d\n", @as(u48, 2)); | ||
| 14 | } | ||
| 15 | |||
| 16 | pub export fn entry3() void { | ||
| 17 | _ = printf("%d\n", {}); | ||
| 18 | } | ||
| 19 | |||
| 20 | // error | ||
| 21 | // backend=stage2 | ||
| 22 | // target=native | ||
| 23 | // | ||
| 24 | // :4:33: error: integer and float literals passed variadic function must be casted to a fixed-size number type | ||
| 25 | // :9:24: error: arrays must be passed by reference to variadic function | ||
| 26 | // :13:24: error: cannot pass 'u48' to variadic function | ||
| 27 | // :13:24: note: only integers with power of two bits are extern compatible | ||
| 28 | // :17:24: error: cannot pass 'void' to variadic function | ||
| 29 | // :17:24: note: 'void' is a zero bit type; for C 'void' use 'anyopaque' | ||
test/link.zig+6| ... | @@ -52,6 +52,12 @@ fn addWasmCases(cases: *tests.StandaloneContext) void { | ... | @@ -52,6 +52,12 @@ fn addWasmCases(cases: *tests.StandaloneContext) void { |
| 52 | .build_modes = true, | 52 | .build_modes = true, |
| 53 | .requires_stage2 = true, | 53 | .requires_stage2 = true, |
| 54 | }); | 54 | }); |
| 55 | |||
| 56 | cases.addBuildFile("test/link/wasm/extern/build.zig", .{ | ||
| 57 | .build_modes = true, | ||
| 58 | .requires_stage2 = true, | ||
| 59 | .use_emulation = true, | ||
| 60 | }); | ||
| 55 | } | 61 | } |
| 56 | 62 | ||
| 57 | fn addMachOCases(cases: *tests.StandaloneContext) void { | 63 | fn addMachOCases(cases: *tests.StandaloneContext) void { |
test/link/wasm/extern/build.zig created+17| ... | @@ -0,0 +1,17 @@ | ||
| 1 | const std = @import("std"); | ||
| 2 | |||
| 3 | pub fn build(b: *std.build.Builder) void { | ||
| 4 | const mode = b.standardReleaseOptions(); | ||
| 5 | const exe = b.addExecutable("extern", "main.zig"); | ||
| 6 | exe.setTarget(.{ .cpu_arch = .wasm32, .os_tag = .wasi }); | ||
| 7 | exe.setBuildMode(mode); | ||
| 8 | exe.addCSourceFile("foo.c", &.{}); | ||
| 9 | exe.use_llvm = false; | ||
| 10 | exe.use_lld = false; | ||
| 11 | |||
| 12 | const run = exe.runEmulatable(); | ||
| 13 | run.expectStdOutEqual("Result: 30"); | ||
| 14 | |||
| 15 | const test_step = b.step("test", "Run linker test"); | ||
| 16 | test_step.dependOn(&run.step); | ||
| 17 | } | ||
test/link/wasm/extern/foo.c created+1| ... | @@ -0,0 +1 @@ | ||
| 1 | int foo = 30; | ||
test/link/wasm/extern/main.zig created+8| ... | @@ -0,0 +1,8 @@ | ||
| 1 | const std = @import("std"); | ||
| 2 | |||
| 3 | extern const foo: u32; | ||
| 4 | |||
| 5 | pub fn main() void { | ||
| 6 | const std_out = std.io.getStdOut(); | ||
| 7 | std_out.writer().print("Result: {d}", .{foo}) catch {}; | ||
| 8 | } | ||
test/run_translated_c.zig+14-12| ... | @@ -250,18 +250,20 @@ pub fn addCases(cases: *tests.RunTranslatedCContext) void { | ... | @@ -250,18 +250,20 @@ pub fn addCases(cases: *tests.RunTranslatedCContext) void { |
| 250 | \\} | 250 | \\} |
| 251 | , ""); | 251 | , ""); |
| 252 | 252 | ||
| 253 | cases.add("struct initializer - packed", | 253 | if (@import("builtin").zig_backend == .stage1) { |
| 254 | \\#define _NO_CRT_STDIO_INLINE 1 | 254 | cases.add("struct initializer - packed", |
| 255 | \\#include <stdint.h> | 255 | \\#define _NO_CRT_STDIO_INLINE 1 |
| 256 | \\#include <stdlib.h> | 256 | \\#include <stdint.h> |
| 257 | \\struct s {uint8_t x,y; | 257 | \\#include <stdlib.h> |
| 258 | \\ uint32_t z;} __attribute__((packed)) s0 = {1, 2}; | 258 | \\struct s {uint8_t x,y; |
| 259 | \\int main() { | 259 | \\ uint32_t z;} __attribute__((packed)) s0 = {1, 2}; |
| 260 | \\ /* sizeof nor offsetof currently supported */ | 260 | \\int main() { |
| 261 | \\ if (((intptr_t)&s0.z - (intptr_t)&s0.x) != 2) abort(); | 261 | \\ /* sizeof nor offsetof currently supported */ |
| 262 | \\ return 0; | 262 | \\ if (((intptr_t)&s0.z - (intptr_t)&s0.x) != 2) abort(); |
| 263 | \\} | 263 | \\ return 0; |
| 264 | , ""); | 264 | \\} |
| 265 | , ""); | ||
| 266 | } | ||
| 265 | 267 | ||
| 266 | cases.add("cast signed array index to unsigned", | 268 | cases.add("cast signed array index to unsigned", |
| 267 | \\#include <stdlib.h> | 269 | \\#include <stdlib.h> |
test/standalone.zig+6| ... | @@ -13,6 +13,8 @@ pub fn addCases(cases: *tests.StandaloneContext) void { | ... | @@ -13,6 +13,8 @@ pub fn addCases(cases: *tests.StandaloneContext) void { |
| 13 | cases.add("test/standalone/guess_number/main.zig"); | 13 | cases.add("test/standalone/guess_number/main.zig"); |
| 14 | cases.add("test/standalone/main_return_error/error_u8.zig"); | 14 | cases.add("test/standalone/main_return_error/error_u8.zig"); |
| 15 | cases.add("test/standalone/main_return_error/error_u8_non_zero.zig"); | 15 | cases.add("test/standalone/main_return_error/error_u8_non_zero.zig"); |
| 16 | cases.add("test/standalone/noreturn_call/inline.zig"); | ||
| 17 | cases.add("test/standalone/noreturn_call/as_arg.zig"); | ||
| 16 | cases.addBuildFile("test/standalone/main_pkg_path/build.zig", .{}); | 18 | cases.addBuildFile("test/standalone/main_pkg_path/build.zig", .{}); |
| 17 | cases.addBuildFile("test/standalone/shared_library/build.zig", .{}); | 19 | cases.addBuildFile("test/standalone/shared_library/build.zig", .{}); |
| 18 | cases.addBuildFile("test/standalone/mix_o_files/build.zig", .{}); | 20 | cases.addBuildFile("test/standalone/mix_o_files/build.zig", .{}); |
| ... | @@ -48,6 +50,9 @@ pub fn addCases(cases: *tests.StandaloneContext) void { | ... | @@ -48,6 +50,9 @@ pub fn addCases(cases: *tests.StandaloneContext) void { |
| 48 | cases.addBuildFile("test/c_abi/build.zig", .{}); | 50 | cases.addBuildFile("test/c_abi/build.zig", .{}); |
| 49 | } | 51 | } |
| 50 | } | 52 | } |
| 53 | if (builtin.cpu.arch.isAARCH64() and builtin.zig_backend == .stage2_llvm) { | ||
| 54 | cases.addBuildFile("test/c_abi/build.zig", .{}); | ||
| 55 | } | ||
| 51 | // C ABI tests only pass for the Wasm target when using stage2 | 56 | // C ABI tests only pass for the Wasm target when using stage2 |
| 52 | cases.addBuildFile("test/c_abi/build_wasm.zig", .{ | 57 | cases.addBuildFile("test/c_abi/build_wasm.zig", .{ |
| 53 | .requires_stage2 = true, | 58 | .requires_stage2 = true, |
| ... | @@ -66,6 +71,7 @@ pub fn addCases(cases: *tests.StandaloneContext) void { | ... | @@ -66,6 +71,7 @@ pub fn addCases(cases: *tests.StandaloneContext) void { |
| 66 | if (builtin.os.tag == .linux) { | 71 | if (builtin.os.tag == .linux) { |
| 67 | cases.addBuildFile("test/standalone/pie/build.zig", .{}); | 72 | cases.addBuildFile("test/standalone/pie/build.zig", .{}); |
| 68 | } | 73 | } |
| 74 | cases.addBuildFile("test/standalone/issue_12706/build.zig", .{}); | ||
| 69 | 75 | ||
| 70 | // Ensure the development tools are buildable. | 76 | // Ensure the development tools are buildable. |
| 71 | 77 |
test/standalone/issue_12706/build.zig created+39| ... | @@ -0,0 +1,39 @@ | ||
| 1 | const std = @import("std"); | ||
| 2 | const builtin = @import("builtin"); | ||
| 3 | const Builder = std.build.Builder; | ||
| 4 | const CrossTarget = std.zig.CrossTarget; | ||
| 5 | |||
| 6 | // TODO integrate this with the std.build executor API | ||
| 7 | fn isRunnableTarget(t: CrossTarget) bool { | ||
| 8 | if (t.isNative()) return true; | ||
| 9 | |||
| 10 | return (t.getOsTag() == builtin.os.tag and | ||
| 11 | t.getCpuArch() == builtin.cpu.arch); | ||
| 12 | } | ||
| 13 | |||
| 14 | pub fn build(b: *Builder) void { | ||
| 15 | const mode = b.standardReleaseOptions(); | ||
| 16 | const target = b.standardTargetOptions(.{}); | ||
| 17 | |||
| 18 | const exe = b.addExecutable("main", "main.zig"); | ||
| 19 | exe.setBuildMode(mode); | ||
| 20 | exe.install(); | ||
| 21 | |||
| 22 | const c_sources = [_][]const u8{ | ||
| 23 | "test.c", | ||
| 24 | }; | ||
| 25 | |||
| 26 | exe.addCSourceFiles(&c_sources, &.{}); | ||
| 27 | exe.linkLibC(); | ||
| 28 | |||
| 29 | exe.setTarget(target); | ||
| 30 | b.default_step.dependOn(&exe.step); | ||
| 31 | |||
| 32 | const test_step = b.step("test", "Test the program"); | ||
| 33 | if (isRunnableTarget(target)) { | ||
| 34 | const run_cmd = exe.run(); | ||
| 35 | test_step.dependOn(&run_cmd.step); | ||
| 36 | } else { | ||
| 37 | test_step.dependOn(&exe.step); | ||
| 38 | } | ||
| 39 | } | ||
test/standalone/issue_12706/main.zig created+12| ... | @@ -0,0 +1,12 @@ | ||
| 1 | const std = @import("std"); | ||
| 2 | extern fn testFnPtr(n: c_int, ...) void; | ||
| 3 | |||
| 4 | const val: c_int = 123; | ||
| 5 | |||
| 6 | fn func(a: c_int) callconv(.C) void { | ||
| 7 | std.debug.assert(a == val); | ||
| 8 | } | ||
| 9 | |||
| 10 | pub fn main() void { | ||
| 11 | testFnPtr(2, func, val); | ||
| 12 | } | ||
test/standalone/issue_12706/test.c created+11| ... | @@ -0,0 +1,11 @@ | ||
| 1 | #include <stdarg.h> | ||
| 2 | |||
| 3 | void testFnPtr(int n, ...) { | ||
| 4 | va_list ap; | ||
| 5 | va_start(ap, n); | ||
| 6 | |||
| 7 | void (*fnPtr)(int) = va_arg(ap, void (*)(int)); | ||
| 8 | int arg = va_arg(ap, int); | ||
| 9 | fnPtr(arg); | ||
| 10 | va_end(ap); | ||
| 11 | } | ||
| \ No newline at end of file | |||
test/standalone/noreturn_call/as_arg.zig created+8| ... | @@ -0,0 +1,8 @@ | ||
| 1 | const std = @import("std"); | ||
| 2 | fn foo() noreturn { | ||
| 3 | std.process.exit(0); | ||
| 4 | } | ||
| 5 | fn bar(_: u8, _: u8) void {} | ||
| 6 | pub fn main() void { | ||
| 7 | bar(foo(), @compileError("bad")); | ||
| 8 | } | ||
test/standalone/noreturn_call/inline.zig created+10| ... | @@ -0,0 +1,10 @@ | ||
| 1 | pub fn main() void { | ||
| 2 | _ = bar(); | ||
| 3 | } | ||
| 4 | inline fn bar() u8 { | ||
| 5 | noret(); | ||
| 6 | } | ||
| 7 | const std = @import("std"); | ||
| 8 | inline fn noret() noreturn { | ||
| 9 | std.process.exit(0); | ||
| 10 | } | ||
test/translate_c.zig+16-14| ... | @@ -728,20 +728,22 @@ pub fn addCases(cases: *tests.TranslateCContext) void { | ... | @@ -728,20 +728,22 @@ pub fn addCases(cases: *tests.TranslateCContext) void { |
| 728 | \\} | 728 | \\} |
| 729 | }); | 729 | }); |
| 730 | 730 | ||
| 731 | cases.add("struct initializer - packed", | 731 | if (builtin.zig_backend == .stage1) { |
| 732 | \\struct {int x,y,z;} __attribute__((packed)) s0 = {1, 2}; | 732 | cases.add("struct initializer - packed", |
| 733 | , &[_][]const u8{ | 733 | \\struct {int x,y,z;} __attribute__((packed)) s0 = {1, 2}; |
| 734 | \\const struct_unnamed_1 = packed struct { | 734 | , &[_][]const u8{ |
| 735 | \\ x: c_int, | 735 | \\const struct_unnamed_1 = packed struct { |
| 736 | \\ y: c_int, | 736 | \\ x: c_int, |
| 737 | \\ z: c_int, | 737 | \\ y: c_int, |
| 738 | \\}; | 738 | \\ z: c_int, |
| 739 | \\pub export var s0: struct_unnamed_1 = struct_unnamed_1{ | 739 | \\}; |
| 740 | \\ .x = @as(c_int, 1), | 740 | \\pub export var s0: struct_unnamed_1 = struct_unnamed_1{ |
| 741 | \\ .y = @as(c_int, 2), | 741 | \\ .x = @as(c_int, 1), |
| 742 | \\ .z = 0, | 742 | \\ .y = @as(c_int, 2), |
| 743 | \\}; | 743 | \\ .z = 0, |
| 744 | }); | 744 | \\}; |
| 745 | }); | ||
| 746 | } | ||
| 745 | 747 | ||
| 746 | // Test case temporarily disabled: | 748 | // Test case temporarily disabled: |
| 747 | // https://github.com/ziglang/zig/issues/12055 | 749 | // https://github.com/ziglang/zig/issues/12055 |