authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-09-06 19:06:09-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-09-06 19:45:02-07:00
logb7900de1684021ff86c67105e14e34968821ea02
treeb881a288071705ffb8cd65ede5f8e7a1452b6dce
parent20145016ac0d098e8e63d5107a05eca376d1e7bb
parente2bb92b2e27dc54852a0227345e294ae383358fd

Merge remote-tracking branch 'origin/master' into llvm15


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-it2/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"
5657
57if [ "${BUILD_REASON}" != "PullRequest" ]; then58if [ "${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 lib16$ZIG build test-stack-traces -Dskip-non-native --zig-lib-dir lib
17$ZIG build test-cli -Dskip-non-native --zig-lib-dir lib17$ZIG build test-cli -Dskip-non-native --zig-lib-dir lib
18$ZIG build test-asm-link -Dskip-non-native --zig-lib-dir lib18$ZIG build test-asm-link -Dskip-non-native --zig-lib-dir lib
19$ZIG build test-translate-c -Dskip-non-native --zig-lib-dir lib19# $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)"
101101
102cd "$HOME"102cd "$HOME"
103103
104# Upload new stdlib autodocs104# Update autodocs and langref directly to S3 in order to prevent the
105mkdir -p docs_to_upload/documentation/master/std/105# www.ziglang.org git repo from growing too big.
106gzip -c -9 "$ZIGDIR/docs/std/index.html" > docs_to_upload/documentation/master/std/index.html106
107gzip -c -9 "$ZIGDIR/docs/std/data.js" > docs_to_upload/documentation/master/std/data.js107# Please do not edit this script to pre-compress the artifacts before they hit
108gzip -c -9 "$ZIGDIR/docs/std/main.js" > docs_to_upload/documentation/master/std/main.js108# S3. This prevents the website from working on browsers that do not support gzip
109gzip -c -9 "$LANGREF" > docs_to_upload/documentation/master/index.html109# 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.
111111# The data.js file is currently 16 MiB. In order to fix this problem, we need to do
112mkdir -p docs_src_to_upload/documentation/master/std/112# one of the following things:
113cp -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
115115# 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.html118 --add-header="Cache-Control: max-age=0, must-revalidate" \
119# cp "$ZIGDIR/docs/std/data.js" docs_to_upload/documentation/master/std/data.js119 "$LANGREF" s3://ziglang.org/documentation/master/index.html
120# cp "$ZIGDIR/docs/std/main.js" docs_to_upload/documentation/master/std/main.js120
121# cp "$LANGREF" docs_to_upload/documentation/master/index.html121$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/
123141
124git clone --depth 1 git@github.com:ziglang/www.ziglang.org.git142git clone --depth 1 git@github.com:ziglang/www.ziglang.org.git
125cd www.ziglang.org143cd www.ziglang.org
126WWWDIR="$(pwd)"144WWWDIR="$(pwd)"
127145
128$S3CMD put -P --no-mime-magic --add-header="cache-control: public, max-age=31536000, immutable" "$HOME/$SRC_TARBALL" s3://ziglang.org/builds/
129
130cd "$WWWDIR"146cd "$WWWDIR"
131cp "$CIDIR/out/index.json" data/releases.json147cp "$CIDIR/out/index.json" data/releases.json
132git add data/releases.json148git 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_package76 - macos_package
77 - linux_package77 - linux_package
78 when:
79 branch:
80 - master
81 event:
82 - push
78 image: ci/debian-amd64:11.1-983 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"
29SHASUM=$(sha256sum $TARBALL | cut '-d ' -f1)29SHASUM=$(sha256sum $TARBALL | cut '-d ' -f1)
30BYTESIZE=$(wc -c < $TARBALL)30BYTESIZE=$(wc -c < $TARBALL)
3131
32MANIFEST="manifest.json"32MANIFEST="manifest-$TARGET.json"
33touch $MANIFEST33touch $MANIFEST
34echo "{\"tarball\": \"$TARBALL\"," >>$MANIFEST34echo "{\"tarball\": \"$TARBALL\"," >>$MANIFEST
35echo "\"shasum\": \"$SHASUM\"," >>$MANIFEST35echo "\"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"
33SHASUM=$(sha256sum $TARBALL | cut '-d ' -f1)33SHASUM=$(sha256sum $TARBALL | cut '-d ' -f1)
34BYTESIZE=$(wc -c < $TARBALL)34BYTESIZE=$(wc -c < $TARBALL)
3535
36MANIFEST="manifest.json"36MANIFEST="manifest-$TARGET.json"
37touch $MANIFEST37touch $MANIFEST
38echo "{\"tarball\": \"$TARBALL\"," >>$MANIFEST38echo "{\"tarball\": \"$TARBALL\"," >>$MANIFEST
39echo "\"shasum\": \"$SHASUM\"," >>$MANIFEST39echo "\"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 @@
359359
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.Enum246 typeKind === typeKinds.Enum ||
247 typeKind === typeKinds.Opaque
245 );248 );
246 }249 }
247250
...@@ -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 }
455463
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;
477485
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 }
481497
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 }
15571597
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;
15841628 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;
22852328
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 }
22902333
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 );
23982441
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];
24022445
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];
24052449
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);
24142459
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, %%rax771 \\ movq $11, %%rax
772 \\ movq %[ptr], %%rbx
773 \\ movq %[len], %%rcx
774 \\ syscall772 \\ syscall
775 \\ movq $60, %%rax773 \\ movq $60, %%rax
776 \\ movq $1, %%rdi774 \\ movq $1, %%rdi
777 \\ syscall775 \\ 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, #91781 \\ 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};
421421
422pub 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
444pub 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
469pub 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.
497pub 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
422pub const SectionHeader = extern struct {507pub 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 errors43//! // 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 a334 /// 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 }
339339
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 }
345345
346 // p/q > x/y iff p*y > x*q346 // 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}
706706
707test "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
707test "big.rational add single-limb" {719test "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,
34493449
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,
34523455
...@@ -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 returned3505 .BADF => unreachable, // always a race condition if this error is returned
3503 .INVAL => unreachable, // invalid parameters3506 .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` pointer3510 .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" {
268pub const CIntLiteralRadix = enum { decimal, octal, hexadecimal };268pub const CIntLiteralRadix = enum { decimal, octal, hexadecimal };
269269
270fn PromoteIntLiteralReturnType(comptime SuffixType: type, comptime number: comptime_int, comptime radix: CIntLiteralRadix) type {270fn 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 };
274274
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}
1818
19test "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
19test "zig fmt: respect line breaks in struct field value declaration" {41test "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}
50375059
5060test "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
5038test "zig fmt: make single-line if no trailing comma" {5075test "zig fmt: make single-line if no trailing comma" {
5039 try testCanonical(5076 try testCanonical(
5040 \\// Test trailing comma syntax5077 \\// 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 }
19351935
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 }
19401943
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}
23502363
2351/// Returns true if there exists a comment between any of the tokens from2364/// 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. a2365/// `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 if2366/// 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 @@
1const builtin = @import("builtin");1const builtin = @import("builtin");
2const std = @import("std");2const std = @import("std");
3const build_options = @import("build_options");3const build_options = @import("build_options");
4const Ast = std.zig.Ast;
4const Autodoc = @This();5const Autodoc = @This();
5const Compilation = @import("Compilation.zig");6const Compilation = @import("Compilation.zig");
6const Module = @import("Module.zig");7const 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};
4950
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.
58const SrcLocInfo = struct {
59 bytes: u32 = 0,
60 line: usize = 0,
61 src_node: u32 = 0,
62};
63
50var arena_allocator: std.heap.ArenaAllocator = undefined;64var arena_allocator: std.heap.ArenaAllocator = undefined;
51pub fn init(m: *Module, doc_location: Compilation.EmitLoc) Autodoc {65pub 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 {
202216
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);
206220
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 astNodes486 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 value649 value: []const u8, // string representation
629 negated: bool = false,650 negated: bool = false,
630 },651 },
631 float: f64, // direct value652 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 {
758const AutodocErrors = error{773const AutodocErrors = error{
759 OutOfMemory,774 OutOfMemory,
760 CurrentWorkingDirectoryUnlinked,775 CurrentWorkingDirectoryUnlinked,
761 Unexpected,776 UnexpectedEndOfFile,
762};777} || std.fs.File.OpenError || std.fs.File.ReadError;
763778
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 typeRef793 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 }
929944
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 }
933948
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 // @check1102 // @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 },
10971122
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 },
12811350
1282 // builtin functions1351 // 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);
13231392
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(
14551524
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 }
15351605
...@@ -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);
15641635
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);
15841655
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);
16031674
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);
16061677
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);
16241695
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);
16421713
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);
16451716
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);
16741745
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);
17861862
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(
18331909
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 // @check1949 // @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 }
20162094
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);
20202098
...@@ -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 );
20952178
2096 // On first iteration use field info to find out the struct type2179 // 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);
22372321
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);
22392323
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 provided2334 // to show discrepancies between the types of provided
2251 // arguments and the types declared in the function2335 // 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 }
22562340
...@@ -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(
23252409
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;
23662464
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
23732471 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
23762474 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;
24232566
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;
25452692
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;
26912842
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);
27972948
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(
28543006
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;
28863039
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);
28893043
2890 var is_test = false; // we discover if it's a test by lookin at its name3044 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 hack3053 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 decltest3055
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 this3059 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 function3062 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,
29113065 .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;
29153069 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,
29203074 .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 };
29233077 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 necessary3102 .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 all3107 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 else3109 else
3008 try self.walkInstruction(file, scope, line, value_index, true);3110 try self.walkInstruction(file, scope, decl_src, value_index, true);
30093111
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(
34663599
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);
34703603
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(
34753608
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;
34773610
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);
34803613
3481 var extra_index: usize = extra.end;3614 var extra_index: usize = extra.end;
34823615
...@@ -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(
36853818
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);
36893822
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 line3897 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 offset3900 // 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}
37713904
...@@ -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(
38203953
3821 // type3954 // 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 }
38263959
...@@ -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 }
39234056
...@@ -3927,7 +4060,7 @@ fn collectStructFieldInfo(...@@ -3927,7 +4060,7 @@ fn collectStructFieldInfo(
39274060
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 };
39334066
...@@ -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 value4095 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}
40754208
...@@ -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
4259fn 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;
46374637
4638 const has_runtime_bits = try sema.fnHasRuntimeBits(&block_scope, ty_src, decl.ty);4638 const has_runtime_bits = try sema.fnHasRuntimeBits(decl.ty);
46394639
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 global4641 // 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 }
25672567
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);
28512867
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);
50425058
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);
55715587
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 }
55745594
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 };
60496069
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 and6329 const is_runtime = comptime_arg.val.tag() == .generic_poison and
6310 comptime_arg.ty.hasRuntimeBits() and6330 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);
66286648
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 }
66326652
...@@ -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 mind6677 // 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 instead6683 // 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 }
78397859
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 or8199 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 the8203 // 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(
82378257
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 the8261 // 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!
1749917521
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,
2035120372
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(
2038120404
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 });
2049120514
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 });
2051120534
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 {
2052820551
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.
20531fn validateExternType(sema: *Sema, ty: Type, position: ExternPosition) bool {20554/// Calls `resolveTypeLayout` for packed containers.
20555fn 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 error23040 // 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(
2391723958
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;
2408024120
24081 switch (inst_ty.zigTypeTag()) {24121 const coerced = switch (sema.typeOf(inst).zigTypeTag()) {
24082 // TODO consider casting to c_int/f64 if they fit24122 // 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}
2408924154
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 ask27644 // 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 }
2786727932
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}
2787127936
27872fn resolveUnionFully(27937fn resolveUnionFully(
...@@ -27899,7 +27964,7 @@ fn resolveUnionFully(...@@ -27899,7 +27964,7 @@ fn resolveUnionFully(
27899 }27964 }
2790027965
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}
2790427969
27905pub fn resolveTypeFields(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) CompileError!Type {27970pub 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 seen29600/// TODO merge these implementations together with the "advanced"/sema_kit pattern seen
29536/// elsewhere in value.zig29601/// elsewhere in value.zig
29537pub fn typeRequiresComptime(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) CompileError!bool {29602pub 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()),
2962929694
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 },
2964729712
...@@ -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 },
2965529720
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
2970229767
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 },
2971529780
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}
2976329828
29764/// Synchronize logic with `Type.isFnOrHasRuntimeBits`.29829/// Synchronize logic with `Type.isFnOrHasRuntimeBits`.
29765pub fn fnHasRuntimeBits(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) CompileError!bool {29830pub 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");
3const bits = @import("bits.zig");3const bits = @import("bits.zig");
4const Register = bits.Register;4const Register = bits.Register;
5const RegisterManagerFn = @import("../../register_manager.zig").RegisterManager;5const RegisterManagerFn = @import("../../register_manager.zig").RegisterManager;
6const Type = @import("../../type.zig").Type;
7
8pub const Class = enum { memory, integer, none, float_array };
9
10pub 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}
669
7const callee_preserved_regs_impl = if (builtin.os.tag.isDarwin()) struct {70const 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-scalar30 // 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-natural32 // 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;
5const Register = @import("bits.zig").Register;5const Register = @import("bits.zig").Register;
6const RegisterManagerFn = @import("../../register_manager.zig").RegisterManager;6const RegisterManagerFn = @import("../../register_manager.zig").RegisterManager;
77
8pub const Class = enum { integer, sse, sseup, x87, x87up, complex_x87, memory, none };8pub const Class = enum { integer, sse, sseup, x87, x87up, complex_x87, memory, none, win_i128 };
99
10pub fn classifyWindows(ty: Type, target: Target) Class {10pub fn classifyWindows(ty: Type, target: Target) Class {
11 // https://docs.microsoft.com/en-gb/cpp/build/x64-calling-convention?view=vs-201711 // 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 },
3947
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 classified182 // "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;
179193
...@@ -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 classified298 // "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;
289309
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;
23const CType = @import("../type.zig").CType;23const CType = @import("../type.zig").CType;
24const x86_64_abi = @import("../arch/x86_64/abi.zig");24const x86_64_abi = @import("../arch/x86_64/abi.zig");
25const wasm_c_abi = @import("../arch/wasm/abi.zig");25const wasm_c_abi = @import("../arch/wasm/abi.zig");
26const aarch64_c_abi = @import("../arch/aarch64/abi.zig");
2627
27const Error = error{ OutOfMemory, CodegenFail };28const Error = error{ OutOfMemory, CodegenFail };
2829
...@@ -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}
316317
318/// TODO can this be done with simpler logic / different API binding?
319fn 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
317pub const Object = struct {327pub 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 {
667677
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 that707 // Problem: now we need to replace in the decl_map that
698 // the extern decl index points to this new global. However we don't708 // 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 }
10891119
...@@ -1191,15 +1221,6 @@ pub const Object = struct {...@@ -1191,15 +1221,6 @@ pub const Object = struct {
1191 return null;1221 return null;
1192 }1222 }
11931223
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,
25312553
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 };
30973126
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 };
47234773
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 }
92689315
...@@ -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 architectures9883 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 above9966 .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 architectures10010 // 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 };
998510039
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 above10169 .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 architectures10225 // 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}
1029610363
10364fn 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 correctly10385/// 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.
10299fn backendSupportsF80(target: std.Target) bool {10387fn 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,
50got_section_index: ?u16 = null,50got_section_index: ?u16 = null,
51rdata_section_index: ?u16 = null,51rdata_section_index: ?u16 = null,
52data_section_index: ?u16 = null,52data_section_index: ?u16 = null,
53reloc_section_index: ?u16 = null,
5354
54locals: std.ArrayListUnmanaged(coff.Symbol) = .{},55locals: std.ArrayListUnmanaged(coff.Symbol) = .{},
55globals: std.StringArrayHashMapUnmanaged(SymbolWithLoc) = .{},56globals: 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`.
99unnamed_const_atoms: UnnamedConstTable = .{},100unnamed_const_atoms: UnnamedConstTable = .{},
100101
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.
104relocs: RelocTable = .{},105relocs: RelocTable = .{},
105106
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.
110base_relocs: BaseRelocationTable = .{},
111
106pub const Reloc = struct {112pub 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};
118124
119const RelocTable = std.AutoHashMapUnmanaged(*Atom, std.ArrayListUnmanaged(Reloc));125const RelocTable = std.AutoHashMapUnmanaged(*Atom, std.ArrayListUnmanaged(Reloc));
126const BaseRelocationTable = std.AutoHashMapUnmanaged(*Atom, std.ArrayListUnmanaged(u32));
120const UnnamedConstTable = std.AutoHashMapUnmanaged(Module.Decl.Index, std.ArrayListUnmanaged(*Atom));127const UnnamedConstTable = std.AutoHashMapUnmanaged(Module.Decl.Index, std.ArrayListUnmanaged(*Atom));
121128
122const default_file_alignment: u16 = 0x200;129const 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};
152159
153pub const PtrWidth = enum { p32, p64 };160pub 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};
154pub const SrcFn = void;171pub const SrcFn = void;
155172
156pub const Export = struct {173pub 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}
278303
279fn populateMissingMetadata(self: *Coff) !void {304fn populateMissingMetadata(self: *Coff) !void {
...@@ -307,7 +332,7 @@ fn populateMissingMetadata(self: *Coff) !void {...@@ -307,7 +332,7 @@ fn populateMissingMetadata(self: *Coff) !void {
307332
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 }
380405
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 });
607657
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}
610668
...@@ -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();
11821241
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}
12181277
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
1281fn 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
1219fn writeStrtab(self: *Coff) !void {1355fn 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;
12781414
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 app1418 .TERMINAL_SERVER_AWARE = 1, // We are not a legacy app
1283 .NX_COMPAT = 1, // We are compatible with Data Execution Prevention1419 .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();
22
3const std = @import("std");3const std = @import("std");
4const coff = std.coff;4const coff = std.coff;
5const log = std.log.scoped(.link);
56
6const Allocator = std.mem.Allocator;7const Allocator = std.mem.Allocator;
78
...@@ -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 {
100101
101pub fn addRelocation(self: *Atom, coff_file: *Coff, reloc: Reloc) !void {102pub 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 Windows104 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
112pub 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}
609609
610fn 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
610pub fn deinit(self: *Wasm) void {628pub 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
783801
784 decl.link.wasm.clear();802 decl.link.wasm.clear();
785803
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;
796816
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}
835855
836fn finishUpdateDecl(self: *Wasm, decl: *Module.Decl, code: []const u8) !void {856fn 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}
851870
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}
12401262
1241/// Kind represents the type of an Atom, which is only1263/// 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 }
14441466
...@@ -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 }
20082030
2009 try self.resolveSymbolsInArchives();2031 try self.resolveSymbolsInArchives();
2032 try self.checkUndefinedSymbols();
20102033
2011 // When we finish/error we reset the state of the linker2034 // When we finish/error we reset the state of the linker
2012 // So we can rebuild the binary file on each incremental update2035 // 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 the79/// Verifies if the given symbol should be imported from the
80/// host environment or not80/// host environment or not
81pub fn requiresImport(self: Symbol) bool {81pub 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 lib85 // if (self.isDefined() and self.isWeak()) return true; //TODO: Only when building shared lib
8686
87 return true;87 return true;
src/main.zig+14
...@@ -2750,8 +2750,22 @@ fn buildOutputType(...@@ -2750,8 +2750,22 @@ fn buildOutputType(
27502750
2751 // Transfer packages added with --pkg-begin/--pkg-end to the root package2751 // 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 }
27562770
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 }
11681168
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 }
29412941
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 }
29522959
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, u02963 .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 @@
1const std = @import("std");
2const expectEqual = std.testing.expectEqual;
3const other_file = @import("12680_other_file.zig");
4const builtin = @import("builtin");
5
6extern fn test_func() callconv(.C) usize;
7
8test "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
2pub export fn testFunc() callconv(.C) usize {
3 return @ptrToInt(&testFunc);
4}
5
6comptime {
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
1179test "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
583test "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
305test "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;
4848
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
117test "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
690690
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
1356test "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
1370test "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 {
86void zig_med_struct_mixed(struct MedStructMixed);86void zig_med_struct_mixed(struct MedStructMixed);
87struct MedStructMixed zig_ret_med_struct_mixed();87struct MedStructMixed zig_ret_med_struct_mixed();
8888
89struct SmallPackedStruct {89void zig_small_packed_struct(uint8_t);
90 uint8_t a: 2;90void 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
97struct 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
106void zig_big_packed_struct(struct BigPackedStruct);
10791
108struct SplitStructInts {92struct 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 }
177161
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 }
182168
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 }
187177
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}
380370
381struct SmallPackedStruct c_ret_small_packed_struct() {371uint8_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}
391379
392void c_small_packed_struct(struct SmallPackedStruct x) {380void 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}
399386
400struct 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}
410393
411void c_big_packed_struct(struct BigPackedStruct x) {394void 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}
418398
419struct SplitStructMixed c_ret_split_struct_mixed() {399struct 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}
111111
112test "C ABI long double" {112test "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}
116116
...@@ -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};
268const c_small_packed_struct: fn (SmallPackedStruct) callconv(.C) void = @compileError("TODO: #1481");267extern fn c_small_packed_struct(SmallPackedStruct) void;
269extern fn c_ret_small_packed_struct() SmallPackedStruct;268extern fn c_ret_small_packed_struct() SmallPackedStruct;
270269
271// waiting on #1481270export 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//}
279276
280test "C ABI small packed struct" {277test "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 #1481279 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}
290286
291const BigPackedStruct = packed struct {287const 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};
298extern fn c_big_packed_struct(BigPackedStruct) void;291extern fn c_big_packed_struct(BigPackedStruct) void;
299extern fn c_ret_big_packed_struct() BigPackedStruct;292extern 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;
301export fn zig_big_packed_struct(x: BigPackedStruct) void {294export 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}
308298
309test "C ABI big packed struct" {299test "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}
319306
320const SplitStructInt = extern struct {307const 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=native10// 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 compatible13// :3:19: note: only extern structs and ABI sized packed structs are extern compatible
14// :1:13: note: struct declared here14// :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 @@
1pub 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=native10// 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 compatible13// :6:17: note: only extern structs and ABI sized packed structs are extern compatible
14// :1:13: note: struct declared here14// :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=native10// 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 compatible13// :6:17: note: only extern unions and ABI sized packed unions are extern compatible
14// :1:13: note: union declared here14// :1:13: note: union declared here
test/cases/compile_errors/int_literal_passed_as_variadic_arg.zig deleted-11
...@@ -1,11 +0,0 @@
1extern fn printf([*:0]const u8, ...) c_int;
2
3pub 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 @@
1pub export fn entry() void {
2 comptime var x: fn (noalias *i32, noalias *i32) void = undefined;
3 x = bar;
4}
5pub export fn entry1() void {
6 comptime var x: fn (*i32, *i32) void = undefined;
7 x = foo;
8}
9
10fn foo(noalias _: *i32, noalias _: *i32) void {}
11fn 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 @@
1const Moo = enum(u8) {
2 Last = 255,
3 Over,
4};
5pub 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 @@
1const Small = enum (u2) {
2 One,
3 Two,
4 Three,
5 Four,
6 Five,
7};
8
9export 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 @@
1const Moo = enum(u8) {
2 Last = 255,
3 Over,
4};
5pub 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 @@
1const Small = enum (u2) {
2 One,
3 Two,
4 Three,
5 Four,
6 Five,
7};
8
9export 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 @@
1pub fn foo() !void {
2 try return bar();
3}
4pub 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 @@
1extern fn printf([*:0]const u8, ...) c_int;
2
3pub export fn entry() void {
4 _ = printf("%d %d %d %d\n", 1, 2, 3, 4);
5}
6
7pub export fn entry1() void {
8 var arr: [2]u8 = undefined;
9 _ = printf("%d\n", arr);
10}
11
12pub export fn entry2() void {
13 _ = printf("%d\n", @as(u48, 2));
14}
15
16pub 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}
5662
57fn addMachOCases(cases: *tests.StandaloneContext) void {63fn addMachOCases(cases: *tests.StandaloneContext) void {
test/link/wasm/extern/build.zig created+17
...@@ -0,0 +1,17 @@
1const std = @import("std");
2
3pub 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 @@
1int foo = 30;
test/link/wasm/extern/main.zig created+8
...@@ -0,0 +1,8 @@
1const std = @import("std");
2
3extern const foo: u32;
4
5pub 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 , "");
252252
253 cases.add("struct initializer - packed",253 if (@import("builtin").zig_backend == .stage1) {
254 \\#define _NO_CRT_STDIO_INLINE 1254 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 }
265267
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 stage256 // 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", .{});
6975
70 // Ensure the development tools are buildable.76 // Ensure the development tools are buildable.
7177
test/standalone/issue_12706/build.zig created+39
...@@ -0,0 +1,39 @@
1const std = @import("std");
2const builtin = @import("builtin");
3const Builder = std.build.Builder;
4const CrossTarget = std.zig.CrossTarget;
5
6// TODO integrate this with the std.build executor API
7fn 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
14pub 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 @@
1const std = @import("std");
2extern fn testFnPtr(n: c_int, ...) void;
3
4const val: c_int = 123;
5
6fn func(a: c_int) callconv(.C) void {
7 std.debug.assert(a == val);
8}
9
10pub 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
3void 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 @@
1const std = @import("std");
2fn foo() noreturn {
3 std.process.exit(0);
4}
5fn bar(_: u8, _: u8) void {}
6pub fn main() void {
7 bar(foo(), @compileError("bad"));
8}
test/standalone/noreturn_call/inline.zig created+10
...@@ -0,0 +1,10 @@
1pub fn main() void {
2 _ = bar();
3}
4inline fn bar() u8 {
5 noret();
6}
7const std = @import("std");
8inline 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 });
730730
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 }
745747
746 // Test case temporarily disabled:748 // Test case temporarily disabled:
747 // https://github.com/ziglang/zig/issues/12055749 // https://github.com/ziglang/zig/issues/12055